diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c921aec --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +logtbl.c diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/LICENSE.txt @@ -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/Makefile b/Makefile new file mode 100644 index 0000000..cbd63c7 --- /dev/null +++ b/Makefile @@ -0,0 +1,47 @@ +MAKEFLAGS = -j8 +CFLAGS = -Wall -std=c99 -s -O2 +DLL = -shared +DIRS = -Idistorm3.2-package/include -Ibson +LIBS = -lws2_32 -lshlwapi +OBJDIR = objects + +ifneq ($(OS),Windows_NT) + CC = mingw32-gcc +else + CC = gcc +endif + +DISTORM3 = $(wildcard distorm3.2-package/src/*.c) +DISTORM3OBJ = $(DISTORM3:distorm3.2-package/src/%.c=$(OBJDIR)/distorm3.2/%.o) + +CUCKOOSRC = $(wildcard *.c) +CUCKOOOBJ = $(CUCKOOSRC:%.c=$(OBJDIR)/%.o) + +LOGTBLSRC = logtbl.c +LOGTBLOBJ = $(LOGTBLSRC:%.c=$(OBJDIR)/%.o) + +BSONSRC = bson/bson.c bson/encoding.c bson/numbers.c +BSONOBJ = $(OBJDIR)/bson/bson.o $(OBJDIR)/bson/encoding.o $(OBJDIR)/bson/numbers.o + +default: $(OBJDIR) $(LOGTBLSRC) cuckoomon.dll + +$(OBJDIR): + mkdir $@ $@/bson $@/distorm3.2 + +$(LOGTBLSRC): netlog.py + python netlog.py c-header $@ + +$(OBJDIR)/distorm3.2/%.o: distorm3.2-package/src/%.c + $(CC) $(CFLAGS) $(DIRS) -c $^ -o $@ + +$(OBJDIR)/bson/%.o: bson/%.c + $(CC) $(CFLAGS) $(DIRS) -c $^ -o $@ + +$(OBJDIR)/%.o: %.c + $(CC) $(CFLAGS) $(DIRS) -c $^ -o $@ + +cuckoomon.dll: $(CUCKOOOBJ) $(DISTORM3OBJ) $(LOGTBLOBJ) $(BSONOBJ) + $(CC) $(CFLAGS) $(DLL) $(DIRS) -o $@ $^ $(LIBS) + +clean: + rm -rf $(OBJDIR) $(LOGTBLSRC) cuckoomon.dll diff --git a/bson/LICENSE b/bson/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/bson/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/bson/bson.c b/bson/bson.c new file mode 100644 index 0000000..11a88d7 --- /dev/null +++ b/bson/bson.c @@ -0,0 +1,1164 @@ +/* bson.c */ + +/* Copyright 2009, 2010 10gen Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if _MSC_VER && ! _CRT_SECURE_NO_WARNINGS + #define _CRT_SECURE_NO_WARNINGS +#endif + +#include +#include +#include +#include +#include + +#include "bson.h" +#include "encoding.h" + +const int initialBufferSize = 128; + +/* only need one of these */ +static const int zero = 0; + +/* Static data to use with bson_init_empty( ) and bson_shared_empty( ) */ +static char bson_shared_empty_data[] = {5,0,0,0,0}; + +/* Custom standard function pointers. */ +void *( *bson_malloc_func )( size_t ) = malloc; +void *( *bson_realloc_func )( void *, size_t ) = realloc; +void ( *bson_free_func )( void * ) = free; +#ifdef R_SAFETY_NET +bson_printf_func bson_printf; +#else +bson_printf_func bson_printf = printf; +#endif +bson_fprintf_func bson_fprintf = fprintf; +bson_sprintf_func bson_sprintf = sprintf; + +static int _bson_errprintf( const char *, ... ); +bson_printf_func bson_errprintf = _bson_errprintf; + +static void _bson_zero( bson *b ); +static size_t _bson_position( const bson *b ); + +/* ObjectId fuzz functions. */ +static int ( *oid_fuzz_func )( void ) = NULL; +static int ( *oid_inc_func )( void ) = NULL; + +/* ---------------------------- + READING + ------------------------------ */ + +MONGO_EXPORT void bson_init_zero(bson* b) { + memset(b, 0, sizeof(bson) - sizeof(b->stack)); +} + +MONGO_EXPORT bson* bson_alloc( void ) { + return ( bson* )bson_malloc( sizeof( bson ) ); +} + +MONGO_EXPORT void bson_dealloc( bson* b ) { + bson_free( b ); +} + +/* When passed a char * of a BSON data block, returns its reported size */ +static int bson_finished_data_size( const char *data ) { + int i; + bson_little_endian32( &i, data ); + return i; +} + +int bson_init_finished_data( bson *b, char *data, bson_bool_t ownsData ) { + _bson_zero( b ); + b->data = data; + b->dataSize = bson_finished_data_size( data ); + b->ownsData = ownsData; + b->finished = 1; + return BSON_OK; +} + +int bson_init_finished_data_with_copy( bson *b, const char *data ) { + int dataSize = bson_finished_data_size( data ); + if ( bson_init_size( b, dataSize ) == BSON_ERROR ) return BSON_ERROR; + memcpy( b->data, data, dataSize ); + b->finished = 1; + return BSON_OK; +} + +MONGO_EXPORT bson_bool_t bson_init_empty( bson *obj ) { + bson_init_finished_data( obj, bson_shared_empty_data, 0 ); + return BSON_OK; +} + +MONGO_EXPORT const bson *bson_shared_empty( void ) { + static const bson shared_empty = { bson_shared_empty_data, bson_shared_empty_data, 128, 1, 0 }; + return &shared_empty; +} + +MONGO_EXPORT int bson_copy( bson *out, const bson *in ) { + if ( !out || !in ) return BSON_ERROR; + if ( !in->finished ) return BSON_ERROR; + return bson_init_finished_data_with_copy( out, in->data ); +} + +MONGO_EXPORT int bson_size( const bson *b ) { + int i; + if ( ! b || ! b->data ) + return 0; + bson_little_endian32( &i, b->data ); + return i; +} + +static size_t _bson_position( const bson *b ) { + return b->cur - b->data; +} + +MONGO_EXPORT size_t bson_buffer_size( const bson *b ) { + return _bson_position(b) + 1; +} + + +MONGO_EXPORT const char *bson_data( const bson *b ) { + return (const char *)b->data; +} + +static char hexbyte( char hex ) { + if (hex >= '0' && hex <= '9') + return (hex - '0'); + else if (hex >= 'A' && hex <= 'F') + return (hex - 'A' + 10); + else if (hex >= 'a' && hex <= 'f') + return (hex - 'a' + 10); + else + return 0x0; +} + +MONGO_EXPORT void bson_oid_from_string( bson_oid_t *oid, const char *str ) { + int i; + for ( i=0; i<12; i++ ) { + oid->bytes[i] = ( hexbyte( str[2*i] ) << 4 ) | hexbyte( str[2*i + 1] ); + } +} + +MONGO_EXPORT void bson_oid_to_string( const bson_oid_t *oid, char *str ) { + static const char hex[16] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'}; + int i; + for ( i=0; i<12; i++ ) { + str[2*i] = hex[( oid->bytes[i] & 0xf0 ) >> 4]; + str[2*i + 1] = hex[ oid->bytes[i] & 0x0f ]; + } + str[24] = '\0'; +} + +MONGO_EXPORT void bson_set_oid_fuzz( int ( *func )( void ) ) { + oid_fuzz_func = func; +} + +MONGO_EXPORT void bson_set_oid_inc( int ( *func )( void ) ) { + oid_inc_func = func; +} + +MONGO_EXPORT void bson_oid_gen( bson_oid_t *oid ) { + static int incr = 0; + static int fuzz = 0; + int i; + time_t t = time( NULL ); + + if( oid_inc_func ) + i = oid_inc_func(); + else + i = incr++; + + if ( !fuzz ) { + if ( oid_fuzz_func ) + fuzz = oid_fuzz_func(); + else { + srand( ( int )t ); + fuzz = rand(); + } + } + + bson_big_endian32( &oid->ints[0], &t ); + oid->ints[1] = fuzz; + bson_big_endian32( &oid->ints[2], &i ); +} + +MONGO_EXPORT time_t bson_oid_generated_time( bson_oid_t *oid ) { + time_t out = 0; + bson_big_endian32( &out, &oid->ints[0] ); + + return out; +} + +MONGO_EXPORT void bson_print( const bson *b ) { + bson_print_raw( b->data , 0 ); +} + +MONGO_EXPORT void bson_print_raw( const char *data , int depth ) { + bson_iterator i; + const char *key; + int temp; + bson_timestamp_t ts; + char oidhex[25]; + bson scope; + bson_iterator_from_buffer( &i, data ); + + while ( bson_iterator_next( &i ) ) { + bson_type t = bson_iterator_type( &i ); + if ( t == 0 ) + break; + key = bson_iterator_key( &i ); + + for ( temp=0; temp<=depth; temp++ ) + bson_printf( "\t" ); + bson_printf( "%s : %d \t " , key , t ); + switch ( t ) { + case BSON_DOUBLE: + bson_printf( "%f" , bson_iterator_double( &i ) ); + break; + case BSON_STRING: + bson_printf( "%s" , bson_iterator_string( &i ) ); + break; + case BSON_SYMBOL: + bson_printf( "SYMBOL: %s" , bson_iterator_string( &i ) ); + break; + case BSON_OID: + bson_oid_to_string( bson_iterator_oid( &i ), oidhex ); + bson_printf( "%s" , oidhex ); + break; + case BSON_BOOL: + bson_printf( "%s" , bson_iterator_bool( &i ) ? "true" : "false" ); + break; + case BSON_DATE: + bson_printf( "%ld" , ( long int )bson_iterator_date( &i ) ); + break; + case BSON_BINDATA: + bson_printf( "BSON_BINDATA" ); + break; + case BSON_UNDEFINED: + bson_printf( "BSON_UNDEFINED" ); + break; + case BSON_NULL: + bson_printf( "BSON_NULL" ); + break; + case BSON_REGEX: + bson_printf( "BSON_REGEX: %s", bson_iterator_regex( &i ) ); + break; + case BSON_CODE: + bson_printf( "BSON_CODE: %s", bson_iterator_code( &i ) ); + break; + case BSON_CODEWSCOPE: + bson_printf( "BSON_CODE_W_SCOPE: %s", bson_iterator_code( &i ) ); + bson_iterator_code_scope_init( &i, &scope, 0 ); + bson_printf( "\n\t SCOPE: " ); + bson_print( &scope ); + bson_destroy( &scope ); + break; + case BSON_INT: + bson_printf( "%d" , bson_iterator_int( &i ) ); + break; + case BSON_LONG: + bson_printf( "%lld" , ( uint64_t )bson_iterator_long( &i ) ); + break; + case BSON_TIMESTAMP: + ts = bson_iterator_timestamp( &i ); + bson_printf( "i: %d, t: %d", ts.i, ts.t ); + break; + case BSON_OBJECT: + case BSON_ARRAY: + bson_printf( "\n" ); + bson_print_raw( bson_iterator_value( &i ) , depth + 1 ); + break; + default: + bson_errprintf( "can't print type : %d\n" , t ); + } + bson_printf( "\n" ); + } +} + +/* ---------------------------- + ITERATOR + ------------------------------ */ + +MONGO_EXPORT bson_iterator* bson_iterator_alloc( void ) { + return ( bson_iterator* )bson_malloc( sizeof( bson_iterator ) ); +} + +MONGO_EXPORT void bson_iterator_dealloc( bson_iterator* i ) { + bson_free( i ); +} + +MONGO_EXPORT void bson_iterator_init( bson_iterator *i, const bson *b ) { + i->cur = b->data + 4; + i->first = 1; +} + +MONGO_EXPORT void bson_iterator_from_buffer( bson_iterator *i, const char *buffer ) { + i->cur = buffer + 4; + i->first = 1; +} + +MONGO_EXPORT bson_type bson_find( bson_iterator *it, const bson *obj, const char *name ) { + bson_iterator_init( it, (bson *)obj ); + while( bson_iterator_next( it ) ) { + if ( strcmp( name, bson_iterator_key( it ) ) == 0 ) + break; + } + return bson_iterator_type( it ); +} + +MONGO_EXPORT bson_bool_t bson_iterator_more( const bson_iterator *i ) { + return *( i->cur ); +} + +MONGO_EXPORT bson_type bson_iterator_next( bson_iterator *i ) { + size_t ds; + + if ( i->first ) { + i->first = 0; + return ( bson_type )( *i->cur ); + } + + switch ( bson_iterator_type( i ) ) { + case BSON_EOO: + return BSON_EOO; /* don't advance */ + case BSON_UNDEFINED: + case BSON_NULL: + case BSON_MINKEY: + case BSON_MAXKEY: + ds = 0; + break; + case BSON_BOOL: + ds = 1; + break; + case BSON_INT: + ds = 4; + break; + case BSON_LONG: + case BSON_DOUBLE: + case BSON_TIMESTAMP: + case BSON_DATE: + ds = 8; + break; + case BSON_OID: + ds = 12; + break; + case BSON_STRING: + case BSON_SYMBOL: + case BSON_CODE: + ds = 4 + bson_iterator_int_raw( i ); + break; + case BSON_BINDATA: + ds = 5 + bson_iterator_int_raw( i ); + break; + case BSON_OBJECT: + case BSON_ARRAY: + case BSON_CODEWSCOPE: + ds = bson_iterator_int_raw( i ); + break; + case BSON_DBREF: + ds = 4+12 + bson_iterator_int_raw( i ); + break; + case BSON_REGEX: { + const char *s = bson_iterator_value( i ); + const char *p = s; + p += strlen( p )+1; + p += strlen( p )+1; + ds = p-s; + break; + } + + default: { + char msg[] = "unknown type: 000000000000"; + bson_numstr( msg+14, ( unsigned )( i->cur[0] ) ); + bson_fatal_msg( 0, msg ); + return 0; + } + } + + i->cur += 1 + strlen( i->cur + 1 ) + 1 + ds; + + return ( bson_type )( *i->cur ); +} + +MONGO_EXPORT bson_type bson_iterator_type( const bson_iterator *i ) { + // problem to convert 0xFF to 255 + return ( bson_type )( unsigned char )i->cur[0]; +} + +MONGO_EXPORT const char *bson_iterator_key( const bson_iterator *i ) { + return i->cur + 1; +} + +MONGO_EXPORT const char *bson_iterator_value( const bson_iterator *i ) { + const char *t = i->cur + 1; + t += strlen( t ) + 1; + return t; +} + +/* types */ + +int bson_iterator_int_raw( const bson_iterator *i ) { + int out; + bson_little_endian32( &out, bson_iterator_value( i ) ); + return out; +} + +double bson_iterator_double_raw( const bson_iterator *i ) { + double out; + bson_little_endian64( &out, bson_iterator_value( i ) ); + return out; +} + +int64_t bson_iterator_long_raw( const bson_iterator *i ) { + int64_t out; + bson_little_endian64( &out, bson_iterator_value( i ) ); + return out; +} + +bson_bool_t bson_iterator_bool_raw( const bson_iterator *i ) { + return bson_iterator_value( i )[0]; +} + +MONGO_EXPORT bson_oid_t *bson_iterator_oid( const bson_iterator *i ) { + return ( bson_oid_t * )bson_iterator_value( i ); +} + +MONGO_EXPORT int bson_iterator_int( const bson_iterator *i ) { + switch ( bson_iterator_type( i ) ) { + case BSON_INT: + return bson_iterator_int_raw( i ); + case BSON_LONG: + return ( int )bson_iterator_long_raw( i ); + case BSON_DOUBLE: + return ( int )bson_iterator_double_raw( i ); + default: + return 0; + } +} + +MONGO_EXPORT double bson_iterator_double( const bson_iterator *i ) { + switch ( bson_iterator_type( i ) ) { + case BSON_INT: + return bson_iterator_int_raw( i ); + case BSON_LONG: + return ( double )bson_iterator_long_raw( i ); + case BSON_DOUBLE: + return bson_iterator_double_raw( i ); + default: + return 0; + } +} + +MONGO_EXPORT int64_t bson_iterator_long( const bson_iterator *i ) { + switch ( bson_iterator_type( i ) ) { + case BSON_INT: + return bson_iterator_int_raw( i ); + case BSON_LONG: + return bson_iterator_long_raw( i ); + case BSON_DOUBLE: + return ( int64_t)bson_iterator_double_raw( i ); + default: + return 0; + } +} + +MONGO_EXPORT bson_timestamp_t bson_iterator_timestamp( const bson_iterator *i ) { + bson_timestamp_t ts; + bson_little_endian32( &( ts.i ), bson_iterator_value( i ) ); + bson_little_endian32( &( ts.t ), bson_iterator_value( i ) + 4 ); + return ts; +} + + +MONGO_EXPORT int bson_iterator_timestamp_time( const bson_iterator *i ) { + int time; + bson_little_endian32( &time, bson_iterator_value( i ) + 4 ); + return time; +} + + +MONGO_EXPORT int bson_iterator_timestamp_increment( const bson_iterator *i ) { + int increment; + bson_little_endian32( &increment, bson_iterator_value( i ) ); + return increment; +} + + +MONGO_EXPORT bson_bool_t bson_iterator_bool( const bson_iterator *i ) { + switch ( bson_iterator_type( i ) ) { + case BSON_BOOL: + return bson_iterator_bool_raw( i ); + case BSON_INT: + return bson_iterator_int_raw( i ) != 0; + case BSON_LONG: + return bson_iterator_long_raw( i ) != 0; + case BSON_DOUBLE: + return bson_iterator_double_raw( i ) != 0; + case BSON_EOO: + case BSON_NULL: + return 0; + default: + return 1; + } +} + +MONGO_EXPORT const char *bson_iterator_string( const bson_iterator *i ) { + switch ( bson_iterator_type( i ) ) { + case BSON_STRING: + case BSON_SYMBOL: + return bson_iterator_value( i ) + 4; + default: + return ""; + } +} + +int bson_iterator_string_len( const bson_iterator *i ) { + return bson_iterator_int_raw( i ); +} + +MONGO_EXPORT const char *bson_iterator_code( const bson_iterator *i ) { + switch ( bson_iterator_type( i ) ) { + case BSON_STRING: + case BSON_CODE: + return bson_iterator_value( i ) + 4; + case BSON_CODEWSCOPE: + return bson_iterator_value( i ) + 8; + default: + return NULL; + } +} + +MONGO_EXPORT void bson_iterator_code_scope_init( const bson_iterator *i, bson *scope, bson_bool_t copyData ) { + if ( bson_iterator_type( i ) == BSON_CODEWSCOPE ) { + int codeLen = bson_finished_data_size( bson_iterator_value( i )+4 ); + const char * scopeData = bson_iterator_value( i )+8+codeLen; + if( copyData ) + bson_init_finished_data_with_copy( scope, scopeData ); + else + bson_init_finished_data( scope, (char *)scopeData, 0 ); + } + else { + bson_init_empty( scope ); + } +} + +MONGO_EXPORT bson_date_t bson_iterator_date( const bson_iterator *i ) { + return bson_iterator_long_raw( i ); +} + +MONGO_EXPORT time_t bson_iterator_time_t( const bson_iterator *i ) { + return bson_iterator_date( i ) / 1000; +} + +MONGO_EXPORT int bson_iterator_bin_len( const bson_iterator *i ) { + return ( bson_iterator_bin_type( i ) == BSON_BIN_BINARY_OLD ) + ? bson_iterator_int_raw( i ) - 4 + : bson_iterator_int_raw( i ); +} + +MONGO_EXPORT char bson_iterator_bin_type( const bson_iterator *i ) { + return bson_iterator_value( i )[4]; +} + +MONGO_EXPORT const char *bson_iterator_bin_data( const bson_iterator *i ) { + return ( bson_iterator_bin_type( i ) == BSON_BIN_BINARY_OLD ) + ? bson_iterator_value( i ) + 9 + : bson_iterator_value( i ) + 5; +} + +MONGO_EXPORT const char *bson_iterator_regex( const bson_iterator *i ) { + return bson_iterator_value( i ); +} + +MONGO_EXPORT const char *bson_iterator_regex_opts( const bson_iterator *i ) { + const char *p = bson_iterator_value( i ); + return p + strlen( p ) + 1; + +} + +MONGO_EXPORT void bson_iterator_subobject_init( const bson_iterator *i, bson *sub, bson_bool_t copyData ) { + const char *data = bson_iterator_value( i ); + if( copyData ) + bson_init_finished_data_with_copy( sub, data ); + else + bson_init_finished_data( sub, (char *)data, 0 ); +} + +MONGO_EXPORT void bson_iterator_subiterator( const bson_iterator *i, bson_iterator *sub ) { + bson_iterator_from_buffer( sub, bson_iterator_value( i ) ); +} + +/* ---------------------------- + BUILDING + ------------------------------ */ + +static void _bson_zero( bson *b ) { + memset( b, 0, sizeof( bson ) ); +} + +MONGO_EXPORT int bson_init( bson *b ) { + return bson_init_size( b, initialBufferSize ); +} + +int bson_init_size( bson *b, int size ) { + _bson_zero( b ); + if( size != 0 ) + { + char * data = (char *) bson_malloc( size ); + if (data == NULL) return BSON_ERROR; + b->data = data; + b->dataSize = size; + } + b->ownsData = 1; + b->cur = b->data + 4; + return BSON_OK; +} + +int bson_init_unfinished_data( bson *b, char *data, int dataSize, bson_bool_t ownsData ) { + _bson_zero( b ); + b->data = data; + b->dataSize = dataSize; + b->ownsData = ownsData; + return BSON_OK; +} + +static int _bson_append_grow_stack( bson * b ) { + if ( !b->stackPtr ) { + // If this is an empty bson structure, initially use the struct-local (fixed-size) stack + b->stackPtr = b->stack; + b->stackSize = sizeof( b->stack ) / sizeof( size_t ); + } + else if ( b->stackPtr == b->stack ) { + // Once we require additional capacity, set up a dynamically resized stack + size_t *new_stack = ( size_t * ) bson_malloc( 2 * sizeof( b->stack ) ); + if ( new_stack ) { + b->stackPtr = new_stack; + b->stackSize = 2 * sizeof( b->stack ) / sizeof( size_t ); + memcpy( b->stackPtr, b->stack, sizeof( b->stack ) ); + } + else { + return BSON_ERROR; + } + } + else { + // Double the capacity of the dynamically-resized stack + size_t *new_stack = ( size_t * ) bson_realloc( b->stackPtr, ( b->stackSize * 2 ) * sizeof( size_t ) ); + if ( new_stack ) { + b->stackPtr = new_stack; + b->stackSize *= 2; + } + else { + return BSON_ERROR; + } + } + return BSON_OK; +} + +static void bson_append_byte( bson *b, char c ) { + b->cur[0] = c; + b->cur++; +} + +static void bson_append( bson *b, const void *data, size_t len ) { + memcpy( b->cur , data , len ); + b->cur += len; +} + +static void bson_append32( bson *b, const void *data ) { + bson_little_endian32( b->cur, data ); + b->cur += 4; +} + +static void bson_append32_as_int( bson *b, int data ) { + bson_little_endian32( b->cur, &data ); + b->cur += 4; +} + +static void bson_append64( bson *b, const void *data ) { + bson_little_endian64( b->cur, data ); + b->cur += 8; +} + +int bson_ensure_space( bson *b, const size_t bytesNeeded ) { + size_t pos = _bson_position(b); + char *orig = b->data; + int new_size; + + if ( pos + bytesNeeded <= (size_t) b->dataSize ) + return BSON_OK; + + new_size = (int) ( 1.5 * ( b->dataSize + bytesNeeded ) ); + + if( new_size < b->dataSize ) { + if( ( b->dataSize + bytesNeeded ) < INT_MAX ) + new_size = INT_MAX; + else { + b->err = BSON_SIZE_OVERFLOW; + return BSON_ERROR; + } + } + + if ( ! b->ownsData ) { + b->err = BSON_DOES_NOT_OWN_DATA; + return BSON_ERROR; + } + + b->data = bson_realloc( b->data, new_size ); + if ( !b->data ) + bson_fatal_msg( !!b->data, "realloc() failed" ); + + b->dataSize = new_size; + b->cur += b->data - orig; + + return BSON_OK; +} + +MONGO_EXPORT int bson_finish( bson *b ) { + int i; + + if( b->err & BSON_NOT_UTF8 ) + return BSON_ERROR; + + if ( ! b->finished ) { + bson_fatal_msg(!b->stackPos, "Subobject not finished before bson_finish()."); + if ( bson_ensure_space( b, 1 ) == BSON_ERROR ) return BSON_ERROR; + bson_append_byte( b, 0 ); + if ( _bson_position(b) >= INT32_MAX ) { + b->err = BSON_SIZE_OVERFLOW; + return BSON_ERROR; + } + i = ( int ) _bson_position(b); + bson_little_endian32( b->data, &i ); + b->finished = 1; + } + + return BSON_OK; +} + +MONGO_EXPORT void bson_destroy( bson *b ) { + if ( b ) { + if ( b->ownsData && b->data != NULL ) { + bson_free( b->data ); + } + b->data = NULL; + b->dataSize = 0; + b->ownsData = 0; + if ( b->stackPtr && b->stackPtr != b->stack ) { + bson_free( b->stackPtr ); + b->stackPtr = NULL; + } + b->stackSize = 0; + b->stackPos = 0; + b->err = 0; + b->cur = 0; + b->finished = 1; + } +} + +static int bson_append_estart( bson *b, int type, const char *name, const size_t dataSize ) { + const size_t len = strlen( name ) + 1; + + if ( b->finished ) { + b->err |= BSON_ALREADY_FINISHED; + return BSON_ERROR; + } + + if ( bson_ensure_space( b, 1 + len + dataSize ) == BSON_ERROR ) { + return BSON_ERROR; + } + + if( bson_check_field_name( b, ( const char * )name, len - 1 ) == BSON_ERROR ) { + bson_builder_error( b ); + return BSON_ERROR; + } + + bson_append_byte( b, ( char )type ); + bson_append( b, name, len ); + return BSON_OK; +} + +/* ---------------------------- + BUILDING TYPES + ------------------------------ */ + +MONGO_EXPORT int bson_append_int( bson *b, const char *name, const int i ) { + if ( bson_append_estart( b, BSON_INT, name, 4 ) == BSON_ERROR ) + return BSON_ERROR; + bson_append32( b , &i ); + return BSON_OK; +} + +MONGO_EXPORT int bson_append_long( bson *b, const char *name, const int64_t i ) { + if ( bson_append_estart( b , BSON_LONG, name, 8 ) == BSON_ERROR ) + return BSON_ERROR; + bson_append64( b , &i ); + return BSON_OK; +} + +MONGO_EXPORT int bson_append_double( bson *b, const char *name, const double d ) { + if ( bson_append_estart( b, BSON_DOUBLE, name, 8 ) == BSON_ERROR ) + return BSON_ERROR; + bson_append64( b , &d ); + return BSON_OK; +} + +MONGO_EXPORT int bson_append_bool( bson *b, const char *name, const bson_bool_t i ) { + if ( bson_append_estart( b, BSON_BOOL, name, 1 ) == BSON_ERROR ) + return BSON_ERROR; + bson_append_byte( b , i != 0 ); + return BSON_OK; +} + +MONGO_EXPORT int bson_append_null( bson *b, const char *name ) { + if ( bson_append_estart( b , BSON_NULL, name, 0 ) == BSON_ERROR ) + return BSON_ERROR; + return BSON_OK; +} + +MONGO_EXPORT int bson_append_undefined( bson *b, const char *name ) { + if ( bson_append_estart( b, BSON_UNDEFINED, name, 0 ) == BSON_ERROR ) + return BSON_ERROR; + return BSON_OK; +} + +MONGO_EXPORT int bson_append_maxkey( bson *b, const char *name ) { + if ( bson_append_estart( b, BSON_MAXKEY, name, 0 ) == BSON_ERROR ) + return BSON_ERROR; + return BSON_OK; +} + +MONGO_EXPORT int bson_append_minkey( bson *b, const char *name ) { + if ( bson_append_estart( b, BSON_MINKEY, name, 0 ) == BSON_ERROR ) + return BSON_ERROR; + return BSON_OK; +} + +static int bson_append_string_base( bson *b, const char *name, + const char *value, size_t len, bson_type type ) { + + size_t sl = len + 1; + if ( sl > INT32_MAX ) { + b->err = BSON_SIZE_OVERFLOW; + /* string too long */ + return BSON_ERROR; + } + if ( bson_check_string( b, ( const char * )value, sl - 1 ) == BSON_ERROR ) + return BSON_ERROR; + if ( bson_append_estart( b, type, name, 4 + sl ) == BSON_ERROR ) { + return BSON_ERROR; + } + bson_append32_as_int( b , ( int )sl ); + bson_append( b , value , sl - 1 ); + bson_append( b , "\0" , 1 ); + return BSON_OK; +} + +MONGO_EXPORT int bson_append_string( bson *b, const char *name, const char *value ) { + return bson_append_string_base( b, name, value, strlen ( value ), BSON_STRING ); +} + +MONGO_EXPORT int bson_append_symbol( bson *b, const char *name, const char *value ) { + return bson_append_string_base( b, name, value, strlen ( value ), BSON_SYMBOL ); +} + +MONGO_EXPORT int bson_append_code( bson *b, const char *name, const char *value ) { + return bson_append_string_base( b, name, value, strlen ( value ), BSON_CODE ); +} + +MONGO_EXPORT int bson_append_string_n( bson *b, const char *name, const char *value, size_t len ) { + return bson_append_string_base( b, name, value, len, BSON_STRING ); +} + +MONGO_EXPORT int bson_append_symbol_n( bson *b, const char *name, const char *value, size_t len ) { + return bson_append_string_base( b, name, value, len, BSON_SYMBOL ); +} + +MONGO_EXPORT int bson_append_code_n( bson *b, const char *name, const char *value, size_t len ) { + return bson_append_string_base( b, name, value, len, BSON_CODE ); +} + +MONGO_EXPORT int bson_append_code_w_scope_n( bson *b, const char *name, + const char *code, size_t len, const bson *scope ) { + + size_t sl, size; + if ( !scope ) return BSON_ERROR; + sl = len + 1; + size = 4 + 4 + sl + bson_size( scope ); + if ( size > (size_t)INT32_MAX ) { + b->err = BSON_SIZE_OVERFLOW; + return BSON_ERROR; + } + if ( bson_append_estart( b, BSON_CODEWSCOPE, name, size ) == BSON_ERROR ) + return BSON_ERROR; + bson_append32_as_int( b, ( int )size ); + bson_append32( b, &sl ); + bson_append( b, code, sl ); + bson_append( b, scope->data, bson_size( scope ) ); + return BSON_OK; +} + +MONGO_EXPORT int bson_append_code_w_scope( bson *b, const char *name, const char *code, const bson *scope ) { + return bson_append_code_w_scope_n( b, name, code, strlen ( code ), scope ); +} + +MONGO_EXPORT int bson_append_binary( bson *b, const char *name, char type, const char *str, size_t len ) { + if ( type == BSON_BIN_BINARY_OLD ) { + size_t subtwolen = len + 4; + if ( bson_append_estart( b, BSON_BINDATA, name, 4+1+4+len ) == BSON_ERROR ) + return BSON_ERROR; + bson_append32_as_int( b, ( int )subtwolen ); + bson_append_byte( b, type ); + bson_append32_as_int( b, ( int )len ); + bson_append( b, str, len ); + } + else { + if ( bson_append_estart( b, BSON_BINDATA, name, 4+1+len ) == BSON_ERROR ) + return BSON_ERROR; + bson_append32_as_int( b, ( int )len ); + bson_append_byte( b, type ); + bson_append( b, str, len ); + } + return BSON_OK; +} + +MONGO_EXPORT int bson_append_oid( bson *b, const char *name, const bson_oid_t *oid ) { + if ( bson_append_estart( b, BSON_OID, name, 12 ) == BSON_ERROR ) + return BSON_ERROR; + bson_append( b , oid , 12 ); + return BSON_OK; +} + +MONGO_EXPORT int bson_append_new_oid( bson *b, const char *name ) { + bson_oid_t oid; + bson_oid_gen( &oid ); + return bson_append_oid( b, name, &oid ); +} + +MONGO_EXPORT int bson_append_regex( bson *b, const char *name, const char *pattern, const char *opts ) { + const size_t plen = strlen( pattern )+1; + const size_t olen = strlen( opts )+1; + if ( bson_append_estart( b, BSON_REGEX, name, plen + olen ) == BSON_ERROR ) + return BSON_ERROR; + if ( bson_check_string( b, pattern, plen - 1 ) == BSON_ERROR ) + return BSON_ERROR; + bson_append( b , pattern , plen ); + bson_append( b , opts , olen ); + return BSON_OK; +} + +MONGO_EXPORT int bson_append_bson( bson *b, const char *name, const bson *bson ) { + if ( !bson ) return BSON_ERROR; + if ( bson_append_estart( b, BSON_OBJECT, name, bson_size( bson ) ) == BSON_ERROR ) + return BSON_ERROR; + bson_append( b , bson->data , bson_size( bson ) ); + return BSON_OK; +} + +MONGO_EXPORT int bson_append_element( bson *b, const char *name_or_null, const bson_iterator *elem ) { + bson_iterator next = *elem; + size_t size; + + bson_iterator_next( &next ); + size = next.cur - elem->cur; + + if ( name_or_null == NULL ) { + if( bson_ensure_space( b, size ) == BSON_ERROR ) + return BSON_ERROR; + bson_append( b, elem->cur, size ); + } + else { + size_t data_size = size - 2 - strlen( bson_iterator_key( elem ) ); + bson_append_estart( b, elem->cur[0], name_or_null, data_size ); + bson_append( b, bson_iterator_value( elem ), data_size ); + } + + return BSON_OK; +} + +MONGO_EXPORT int bson_append_timestamp( bson *b, const char *name, bson_timestamp_t *ts ) { + if ( bson_append_estart( b, BSON_TIMESTAMP, name, 8 ) == BSON_ERROR ) return BSON_ERROR; + + bson_append32( b , &( ts->i ) ); + bson_append32( b , &( ts->t ) ); + + return BSON_OK; +} + +MONGO_EXPORT int bson_append_timestamp2( bson *b, const char *name, int time, int increment ) { + if ( bson_append_estart( b, BSON_TIMESTAMP, name, 8 ) == BSON_ERROR ) return BSON_ERROR; + + bson_append32( b , &increment ); + bson_append32( b , &time ); + return BSON_OK; +} + +MONGO_EXPORT int bson_append_date( bson *b, const char *name, bson_date_t millis ) { + if ( bson_append_estart( b, BSON_DATE, name, 8 ) == BSON_ERROR ) return BSON_ERROR; + bson_append64( b , &millis ); + return BSON_OK; +} + +MONGO_EXPORT int bson_append_time_t( bson *b, const char *name, time_t secs ) { + return bson_append_date( b, name, ( bson_date_t )secs * 1000 ); +} + +MONGO_EXPORT int bson_append_start_object( bson *b, const char *name ) { + if ( bson_append_estart( b, BSON_OBJECT, name, 5 ) == BSON_ERROR ) return BSON_ERROR; + if ( b->stackPos >= b->stackSize && _bson_append_grow_stack( b ) == BSON_ERROR ) return BSON_ERROR; + b->stackPtr[ b->stackPos++ ] = _bson_position(b); + bson_append32( b , &zero ); + return BSON_OK; +} + +MONGO_EXPORT int bson_append_start_array( bson *b, const char *name ) { + if ( bson_append_estart( b, BSON_ARRAY, name, 5 ) == BSON_ERROR ) return BSON_ERROR; + if ( b->stackPos >= b->stackSize && _bson_append_grow_stack( b ) == BSON_ERROR ) return BSON_ERROR; + b->stackPtr[ b->stackPos++ ] = _bson_position(b); + bson_append32( b , &zero ); + return BSON_OK; +} + +MONGO_EXPORT int bson_append_finish_object( bson *b ) { + char *start; + int i; + if (!b) return BSON_ERROR; + if (!b->stackPos) { b->err = BSON_NOT_IN_SUBOBJECT; return BSON_ERROR; } + if ( bson_ensure_space( b, 1 ) == BSON_ERROR ) return BSON_ERROR; + bson_append_byte( b , 0 ); + + start = b->data + b->stackPtr[ --b->stackPos ]; + if ( b->cur - start >= INT32_MAX ) { + b->err = BSON_SIZE_OVERFLOW; + return BSON_ERROR; + } + i = ( int )( b->cur - start ); + bson_little_endian32( start, &i ); + + return BSON_OK; +} + +MONGO_EXPORT double bson_int64_to_double( int64_t i64 ) { + return (double)i64; +} + +MONGO_EXPORT int bson_append_finish_array( bson *b ) { + return bson_append_finish_object( b ); +} + +/* Error handling and allocators. */ + +static bson_err_handler err_handler = NULL; + +MONGO_EXPORT bson_err_handler set_bson_err_handler( bson_err_handler func ) { + bson_err_handler old = err_handler; + err_handler = func; + return old; +} + +MONGO_EXPORT void bson_free( void *ptr ) { + bson_free_func( ptr ); +} + +MONGO_EXPORT void *bson_malloc( size_t size ) { + void *p; + p = bson_malloc_func( size ); + bson_fatal_msg( !!p, "malloc() failed" ); + return p; +} + +void *bson_realloc( void *ptr, size_t size ) { + void *p; + p = bson_realloc_func( ptr, size ); + bson_fatal_msg( !!p, "realloc() failed" ); + return p; +} + +int _bson_errprintf( const char *format, ... ) { + va_list ap; + int ret = 0; + va_start( ap, format ); +#ifndef R_SAFETY_NET + ret = vfprintf( stderr, format, ap ); +#endif + va_end( ap ); + + return ret; +} + +/** + * This method is invoked when a non-fatal bson error is encountered. + * Calls the error handler if available. + * + * @param + */ +void bson_builder_error( bson *b ) { + if( err_handler ) + err_handler( "BSON error." ); +} + +void bson_fatal( int ok ) { + bson_fatal_msg( ok, "" ); +} + +void bson_fatal_msg( int ok , const char *msg ) { + if ( ok ) + return; + + if ( err_handler ) { + err_handler( msg ); + } +#ifndef R_SAFETY_NET + bson_errprintf( "error: %s\n" , msg ); + exit( -5 ); +#endif +} + + +/* Efficiently copy an integer to a string. */ +extern const char bson_numstrs[1000][4]; + +void bson_numstr( char *str, int i ) { + if( i < 1000 ) + memcpy( str, bson_numstrs[i], 4 ); + else + bson_sprintf( str,"%d", i ); +} + +MONGO_EXPORT void bson_swap_endian64( void *outp, const void *inp ) { + const char *in = ( const char * )inp; + char *out = ( char * )outp; + + out[0] = in[7]; + out[1] = in[6]; + out[2] = in[5]; + out[3] = in[4]; + out[4] = in[3]; + out[5] = in[2]; + out[6] = in[1]; + out[7] = in[0]; + +} + +MONGO_EXPORT void bson_swap_endian32( void *outp, const void *inp ) { + const char *in = ( const char * )inp; + char *out = ( char * )outp; + + out[0] = in[3]; + out[1] = in[2]; + out[2] = in[1]; + out[3] = in[0]; +} diff --git a/bson/bson.h b/bson/bson.h new file mode 100644 index 0000000..739b406 --- /dev/null +++ b/bson/bson.h @@ -0,0 +1,1180 @@ +/** + * @file bson.h + * @brief BSON Declarations + */ + +/* Copyright 2009-2012 10gen Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BSON_H_ +#define BSON_H_ + +#include +#include +#include +#include +#include + +#ifdef __GNUC__ +#define MONGO_INLINE static __inline__ +#define MONGO_EXPORT +#else +#define MONGO_INLINE static +#ifdef MONGO_STATIC_BUILD +#define MONGO_EXPORT +#elif defined(MONGO_DLL_BUILD) +#define MONGO_EXPORT __declspec(dllexport) +#else +#define MONGO_EXPORT __declspec(dllimport) +#endif +#endif + +#ifdef __cplusplus +#define MONGO_EXTERN_C_START extern "C" { +#define MONGO_EXTERN_C_END } +#else +#define MONGO_EXTERN_C_START +#define MONGO_EXTERN_C_END +#endif + +#if defined(MONGO_HAVE_STDINT) || __STDC_VERSION__ >= 199901L +#include +#elif defined(MONGO_HAVE_UNISTD) +#include +#elif defined(MONGO_USE__INT64) +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; +#define INT32_MAX 0x7fffffffL +#elif defined(MONGO_USE_LONG_LONG_INT) +typedef long long int int64_t; +typedef unsigned long long int uint64_t; +#else +#error Must compile with c99 or define MONGO_HAVE_STDINT, MONGO_HAVE_UNISTD, MONGO_USE__INT64, or MONGO_USE_LONG_LONG_INT. +#endif + +#ifdef MONGO_BIG_ENDIAN +#define bson_little_endian64(out, in) ( bson_swap_endian64(out, in) ) +#define bson_little_endian32(out, in) ( bson_swap_endian32(out, in) ) +#define bson_big_endian64(out, in) ( memcpy(out, in, 8) ) +#define bson_big_endian32(out, in) ( memcpy(out, in, 4) ) +#else +#define bson_little_endian64(out, in) ( memcpy(out, in, 8) ) +#define bson_little_endian32(out, in) ( memcpy(out, in, 4) ) +#define bson_big_endian64(out, in) ( bson_swap_endian64(out, in) ) +#define bson_big_endian32(out, in) ( bson_swap_endian32(out, in) ) +#endif + +MONGO_EXTERN_C_START + +#define BSON_OK 0 +#define BSON_ERROR -1 + +enum bson_error_t { + BSON_SIZE_OVERFLOW = (1 << 0), /**< Trying to create a BSON object larger than INT_MAX. */ + BSON_ALREADY_FINISHED = (1 << 4), /**< Trying to modify a finished BSON object. */ + BSON_NOT_IN_SUBOBJECT = (1 << 5), /**< Trying bson_append_finish_object() and not in sub */ + BSON_DOES_NOT_OWN_DATA = (1 << 6) /**< Trying to expand a BSON object which does not own its data block. */ +}; + +enum bson_validity_t { + BSON_VALID = 0, /**< BSON is valid and UTF-8 compliant. */ + BSON_NOT_UTF8 = (1 << 1), /**< A key or a string is not valid UTF-8. */ + BSON_FIELD_HAS_DOT = (1 << 2), /**< Warning: key contains '.' character. */ + BSON_FIELD_INIT_DOLLAR = (1 << 3) /**< Warning: key starts with '$' character. */ +}; + +enum bson_binary_subtype_t { + BSON_BIN_BINARY = 0, + BSON_BIN_FUNC = 1, + BSON_BIN_BINARY_OLD = 2, + BSON_BIN_UUID = 3, + BSON_BIN_MD5 = 5, + BSON_BIN_USER = 128 +}; + +typedef enum { + BSON_EOO = 0, + BSON_DOUBLE = 1, + BSON_STRING = 2, + BSON_OBJECT = 3, + BSON_ARRAY = 4, + BSON_BINDATA = 5, + BSON_UNDEFINED = 6, + BSON_OID = 7, + BSON_BOOL = 8, + BSON_DATE = 9, + BSON_NULL = 10, + BSON_REGEX = 11, + BSON_DBREF = 12, /**< Deprecated. */ + BSON_CODE = 13, + BSON_SYMBOL = 14, + BSON_CODEWSCOPE = 15, + BSON_INT = 16, + BSON_TIMESTAMP = 17, + BSON_LONG = 18, + BSON_MAXKEY = 127, + BSON_MINKEY = 255 +} bson_type; + +typedef int bson_bool_t; + +typedef struct { + const char *cur; + bson_bool_t first; +} bson_iterator; + +typedef struct { + char *data; /**< Pointer to a block of data in this BSON object. */ + char *cur; /**< Pointer to the current position. */ + int dataSize; /**< The number of bytes allocated to char *data. */ + bson_bool_t finished; /**< When finished, the BSON object can no longer be modified. */ + bson_bool_t ownsData; /**< Whether destroying this object will deallocate its data block */ + int err; /**< Bitfield representing errors or warnings on this buffer */ + int stackSize; /**< Number of elements in the current stack */ + int stackPos; /**< Index of current stack position. */ + size_t* stackPtr; /**< Pointer to the current stack */ + size_t stack[32]; /**< A stack used to keep track of nested BSON elements. + Must be at end of bson struct so _bson_zero does not clear. */ +} bson; + +#pragma pack(1) +typedef union { + char bytes[12]; + int ints[3]; +} bson_oid_t; +#pragma pack() + +typedef int64_t bson_date_t; /* milliseconds since epoch UTC */ + +typedef struct { + int i; /* increment */ + int t; /* time in seconds */ +} bson_timestamp_t; + +/* ---------------------------- + READING + ------------------------------ */ + +/** + * Zero a bson struct. All fields are set to zero except the stack. + * + * @note Mainly used internally, but can be called for safety + * purposes so that a later call to bson_destroy() doesn't flip out. + * It is safe to call this function on a NULL pointer in which case + * there is no effect. + * @param b the BSON object to zero. + * + */ +MONGO_EXPORT void bson_init_zero( bson *b ); + +/** + * Allocate memory for a new BSON object. + * + * @note After using this function, you must initialize the object + * using bson_init_finished_data( ), bson_init_empty( ), bson_init( ), + * or one of the other init functions. + * + * @return a new BSON object. + */ +MONGO_EXPORT bson* bson_alloc( void ); + +/** + * Deallocate a BSON object. + * + * @note You must call bson_destroy( ) before calling this function. + */ +MONGO_EXPORT void bson_dealloc( bson* b ); + +/** + * Initialize a BSON object for reading and set its data + * pointer to the provided char*. + * + * @note When done using the bson object, you must pass + * the object to bson_destroy( ). + * + * @param b the BSON object to initialize. + * @param data the finalized raw BSON data. + * @param ownsData when true, bson_destroy() will free the data block. + * + * @return BSON_OK or BSON_ERROR. + */ +MONGO_EXPORT int bson_init_finished_data( bson *b, char *data, bson_bool_t ownsData ); + +/** + * Initialize a BSON object for reading and copy finalized + * BSON data from the provided char*. + * + * @note When done using the bson object, you must pass + * the object to bson_destroy( ). + * + * @param b the BSON object to initialize. + * @param data the finalized raw BSON data to copy. + * + * @return BSON_OK or BSON_ERROR. + */ +MONGO_EXPORT int bson_init_finished_data_with_copy( bson *b, const char *data ); + +/** + * Size of a BSON object. + * + * @param b the BSON object. + * + * @return the size. + */ +MONGO_EXPORT int bson_size( const bson *b ); + +/** + * Minimum finished size of an unfinished BSON object given current contents. + * + * @param b the BSON object. + * + * @return the BSON object's minimum finished size + */ +MONGO_EXPORT size_t bson_buffer_size( const bson *b ); + +/** + * Print a string representation of a BSON object. + * + * @param b the BSON object to print. + */ +MONGO_EXPORT void bson_print( const bson *b ); + +/** + * Return a pointer to the raw buffer stored by this bson object. + * + * @param b a BSON object + */ +MONGO_EXPORT const char *bson_data( const bson *b ); + +/** + * Returns true if bson_data(b) {b->data} is not null; else, false. + * + * @note Convenience function for determining if bson data was returned by a function. + * Check required after calls to mongo_create_index(), mongo_create_simple_index(), + * mongo_cmd_get_last_error() and mongo_cmd_get_prev_error(). + * @param b the bson struct to inspect. + */ + +MONGO_EXPORT int bson_has_data( const bson *b ); + +/** + * Print a string representation of a BSON object. + * + * @param bson the raw data to print. + * @param depth the depth to recurse the object.x + */ +MONGO_EXPORT void bson_print_raw( const char *bson , int depth ); + +/** + * Advance a bson_iterator to the named field. + * + * @param it the bson_iterator to use. + * @param obj the BSON object to use. + * @param name the name of the field to find. + * + * @return the type of the found object or BSON_EOO if it is not found. + */ +MONGO_EXPORT bson_type bson_find( bson_iterator *it, const bson *obj, const char *name ); + + +MONGO_EXPORT bson_iterator* bson_iterator_alloc( void ); +MONGO_EXPORT void bson_iterator_dealloc(bson_iterator*); +/** + * Initialize a bson_iterator. + * + * @param i the bson_iterator to initialize. + * @param bson the BSON object to associate with the iterator. + */ +MONGO_EXPORT void bson_iterator_init( bson_iterator *i , const bson *b ); + +/** + * Initialize a bson iterator from a const char* buffer. Note + * that this is mostly used internally. + * + * @param i the bson_iterator to initialize. + * @param buffer the buffer to point to. + */ +MONGO_EXPORT void bson_iterator_from_buffer( bson_iterator *i, const char *buffer ); + +/* more returns true for eoo. best to loop with bson_iterator_next(&it) */ +/** + * Check to see if the bson_iterator has more data. + * + * @param i the iterator. + * + * @return returns true if there is more data. + */ +MONGO_EXPORT bson_bool_t bson_iterator_more( const bson_iterator *i ); + +/** + * Point the iterator at the next BSON object. + * + * @param i the bson_iterator. + * + * @return the type of the next BSON object. + */ +MONGO_EXPORT bson_type bson_iterator_next( bson_iterator *i ); + +/** + * Get the type of the BSON object currently pointed to by the iterator. + * + * @param i the bson_iterator + * + * @return the type of the current BSON object. + */ +MONGO_EXPORT bson_type bson_iterator_type( const bson_iterator *i ); + +/** + * Get the key of the BSON object currently pointed to by the iterator. + * + * @param i the bson_iterator + * + * @return the key of the current BSON object. + */ +MONGO_EXPORT const char *bson_iterator_key( const bson_iterator *i ); + +/** + * Get the value of the BSON object currently pointed to by the iterator. + * + * @param i the bson_iterator + * + * @return the value of the current BSON object. + */ +MONGO_EXPORT const char *bson_iterator_value( const bson_iterator *i ); + +/* these convert to the right type (return 0 if non-numeric) */ +/** + * Get the double value of the BSON object currently pointed to by the + * iterator. + * + * @param i the bson_iterator + * + * @return the value of the current BSON object. + */ +MONGO_EXPORT double bson_iterator_double( const bson_iterator *i ); + +/** + * Get the int value of the BSON object currently pointed to by the iterator. + * + * @param i the bson_iterator + * + * @return the value of the current BSON object. + */ +MONGO_EXPORT int bson_iterator_int( const bson_iterator *i ); + +/** + * Get the long value of the BSON object currently pointed to by the iterator. + * + * @param i the bson_iterator + * + * @return the value of the current BSON object. + */ +MONGO_EXPORT int64_t bson_iterator_long( const bson_iterator *i ); + +/* return the bson timestamp as a whole or in parts */ +/** + * Get the timestamp value of the BSON object currently pointed to by + * the iterator. + * + * @param i the bson_iterator + * + * @return the value of the current BSON object. + */ +MONGO_EXPORT bson_timestamp_t bson_iterator_timestamp( const bson_iterator *i ); +MONGO_EXPORT int bson_iterator_timestamp_time( const bson_iterator *i ); +MONGO_EXPORT int bson_iterator_timestamp_increment( const bson_iterator *i ); + +/** + * Get the boolean value of the BSON object currently pointed to by + * the iterator. + * + * @param i the bson_iterator + * + * @return the value of the current BSON object. + */ +/* false: boolean false, 0 in any type, or null */ +/* true: anything else (even empty strings and objects) */ +MONGO_EXPORT bson_bool_t bson_iterator_bool( const bson_iterator *i ); + +/** + * Get the double value of the BSON object currently pointed to by the + * iterator. Assumes the correct type is used. + * + * @param i the bson_iterator + * + * @return the value of the current BSON object. + */ +/* these assume you are using the right type */ +double bson_iterator_double_raw( const bson_iterator *i ); + +/** + * Get the int value of the BSON object currently pointed to by the + * iterator. Assumes the correct type is used. + * + * @param i the bson_iterator + * + * @return the value of the current BSON object. + */ +int bson_iterator_int_raw( const bson_iterator *i ); + +/** + * Get the long value of the BSON object currently pointed to by the + * iterator. Assumes the correct type is used. + * + * @param i the bson_iterator + * + * @return the value of the current BSON object. + */ +int64_t bson_iterator_long_raw( const bson_iterator *i ); + +/** + * Get the bson_bool_t value of the BSON object currently pointed to by the + * iterator. Assumes the correct type is used. + * + * @param i the bson_iterator + * + * @return the value of the current BSON object. + */ +bson_bool_t bson_iterator_bool_raw( const bson_iterator *i ); + +/** + * Get the bson_oid_t value of the BSON object currently pointed to by the + * iterator. + * + * @param i the bson_iterator + * + * @return the value of the current BSON object. + */ +MONGO_EXPORT bson_oid_t *bson_iterator_oid( const bson_iterator *i ); + +/** + * Get the string value of the BSON object currently pointed to by the + * iterator. + * + * @param i the bson_iterator + * + * @return the value of the current BSON object. + */ +/* these can also be used with bson_code and bson_symbol*/ +MONGO_EXPORT const char *bson_iterator_string( const bson_iterator *i ); + +/** + * Get the string length of the BSON object currently pointed to by the + * iterator. + * + * @param i the bson_iterator + * + * @return the length of the current BSON object. + */ +int bson_iterator_string_len( const bson_iterator *i ); + +/** + * Get the code value of the BSON object currently pointed to by the + * iterator. Works with bson_code, bson_codewscope, and BSON_STRING + * returns NULL for everything else. + * + * @param i the bson_iterator + * + * @return the code value of the current BSON object. + */ +/* works with bson_code, bson_codewscope, and BSON_STRING */ +/* returns NULL for everything else */ +MONGO_EXPORT const char *bson_iterator_code( const bson_iterator *i ); + +/** + * Get the code scope value of the BSON object currently pointed to + * by the iterator. Calls bson_init_empty on scope if current object is + * not BSON_CODEWSCOPE. + * + * @note When copyData is false, the scope becomes invalid when the + * iterator's data buffer is deallocated. For either value of + * copyData, you must pass the scope object to bson_destroy + * when you are done using it. + * + * @param i the bson_iterator. + * @param scope an uninitialized BSON object to receive the scope. + * @param copyData when true, makes a copy of the scope data which will remain + * valid when the iterator's data buffer is deallocated. + */ +MONGO_EXPORT void bson_iterator_code_scope_init( const bson_iterator *i, bson *scope, bson_bool_t copyData ); + +/** + * Get the date value of the BSON object currently pointed to by the + * iterator. + * + * @param i the bson_iterator + * + * @return the date value of the current BSON object. + */ +/* both of these only work with bson_date */ +MONGO_EXPORT bson_date_t bson_iterator_date( const bson_iterator *i ); + +/** + * Get the time value of the BSON object currently pointed to by the + * iterator. + * + * @param i the bson_iterator + * + * @return the time value of the current BSON object. + */ +MONGO_EXPORT time_t bson_iterator_time_t( const bson_iterator *i ); + +/** + * Get the length of the BSON binary object currently pointed to by the + * iterator. + * + * @param i the bson_iterator + * + * @return the length of the current BSON binary object. + */ +MONGO_EXPORT int bson_iterator_bin_len( const bson_iterator *i ); + +/** + * Get the type of the BSON binary object currently pointed to by the + * iterator. + * + * @param i the bson_iterator + * + * @return the type of the current BSON binary object. + */ +MONGO_EXPORT char bson_iterator_bin_type( const bson_iterator *i ); + +/** + * Get the value of the BSON binary object currently pointed to by the + * iterator. + * + * @param i the bson_iterator + * + * @return the value of the current BSON binary object. + */ +MONGO_EXPORT const char *bson_iterator_bin_data( const bson_iterator *i ); + +/** + * Get the value of the BSON regex object currently pointed to by the + * iterator. + * + * @param i the bson_iterator + * + * @return the value of the current BSON regex object. + */ +MONGO_EXPORT const char *bson_iterator_regex( const bson_iterator *i ); + +/** + * Get the options of the BSON regex object currently pointed to by the + * iterator. + * + * @param i the bson_iterator. + * + * @return the options of the current BSON regex object. + */ +MONGO_EXPORT const char *bson_iterator_regex_opts( const bson_iterator *i ); + +/* these work with BSON_OBJECT and BSON_ARRAY */ +/** + * Get the BSON subobject currently pointed to by the + * iterator. + * + * @note When copyData is 0, the subobject becomes invalid when its parent's + * data buffer is deallocated. For either value of copyData, you must + * pass the subobject to bson_destroy when you are done using it. + * + * @param i the bson_iterator. + * @param sub an unitialized BSON object which will become the new subobject. + */ +MONGO_EXPORT void bson_iterator_subobject_init( const bson_iterator *i, bson *sub, bson_bool_t copyData ); + +/** + * Get a bson_iterator that on the BSON subobject. + * + * @param i the bson_iterator. + * @param sub the iterator to point at the BSON subobject. + */ +MONGO_EXPORT void bson_iterator_subiterator( const bson_iterator *i, bson_iterator *sub ); + +/* str must be at least 24 hex chars + null byte */ +/** + * Create a bson_oid_t from a string. + * + * @param oid the bson_oid_t destination. + * @param str a null terminated string comprised of at least 24 hex chars. + */ +MONGO_EXPORT void bson_oid_from_string( bson_oid_t *oid, const char *str ); + +/** + * Create a string representation of the bson_oid_t. + * + * @param oid the bson_oid_t source. + * @param str the string representation destination. + */ +MONGO_EXPORT void bson_oid_to_string( const bson_oid_t *oid, char *str ); + +/** + * Create a bson_oid object. + * + * @param oid the destination for the newly created bson_oid_t. + */ +MONGO_EXPORT void bson_oid_gen( bson_oid_t *oid ); + +/** + * Set a function to be used to generate the second four bytes + * of an object id. + * + * @param func a pointer to a function that returns an int. + */ +MONGO_EXPORT void bson_set_oid_fuzz( int ( *func )( void ) ); + +/** + * Set a function to be used to generate the incrementing part + * of an object id (last four bytes). If you need thread-safety + * in generating object ids, you should set this function. + * + * @param func a pointer to a function that returns an int. + */ +MONGO_EXPORT void bson_set_oid_inc( int ( *func )( void ) ); + +/** + * Get the time a bson_oid_t was created. + * + * @param oid the bson_oid_t. + */ +MONGO_EXPORT time_t bson_oid_generated_time( bson_oid_t *oid ); /* Gives the time the OID was created */ + +/* ---------------------------- + BUILDING + ------------------------------ */ + +/** + * Initialize a BSON object for building and allocate a data buffer. + * + * @note You must initialize each new bson object using this, + * bson_init_finished_data( ), or one of the other init functions. + * When done using the BSON object, you must pass it to bson_destroy( ). + * + * @param b the BSON object to initialize. + * + * @return BSON_OK or BSON_ERROR. + */ +MONGO_EXPORT int bson_init( bson *b ); + +/** + * Initialize a BSON object for building and allocate a data buffer + * of a given size. + * + * @note When done using the bson object, you must pass it + * to bson_destroy( ). + * + * @param b the BSON object to initialize. + * @param size the initial size of the buffer. + * + * @return BSON_OK or BSON_ERROR. + */ +int bson_init_size( bson *b, int size ); + +/** + * Initialize a BSON object for building, using the provided char* + * of the given size. When ownsData is true, the BSON object may + * reallocate the data block as needed, and bson_destroy will free + * it. + * + * See also bson_init_finished_data( ) + * + * @note When done using the BSON object, you must pass + * it to bson_destroy( ). + * + * @param b the BSON object to initialize. + * @param data the raw BSON data. + * @param ownsData when true, bson_ensure_space() may reallocate the block and + * bson_destroy() will free it + * + * @return BSON_OK or BSON_ERROR. + */ +int bson_init_unfinished_data( bson *b, char *data, int dataSize, bson_bool_t ownsData ); + +/** + * Grow a bson object. + * + * @param b the bson to grow. + * @param bytesNeeded the additional number of bytes needed. + * + * @return BSON_OK or BSON_ERROR with the bson error object set. + * Exits if allocation fails. + */ +int bson_ensure_space( bson *b, const size_t bytesNeeded ); + +/** + * Finalize a bson object. + * + * @param b the bson object to finalize. + * + * @return the standard error code. To deallocate memory, + * call bson_destroy on the bson object. + */ +MONGO_EXPORT int bson_finish( bson *b ); + +/** + * Destroy a bson object and deallocate its data buffer. + * + * @param b the bson object to destroy. + * + */ +MONGO_EXPORT void bson_destroy( bson *b ); + +/** + * Initialize a BSON object to an emoty object with a shared, static data + * buffer. + * + * @note You must NOT modify this object's data. It is safe though not + * required to call bson_destroy( ) on this object. + * + * @param obj the BSON object to initialize. + * + * @return BSON_OK + */ +MONGO_EXPORT bson_bool_t bson_init_empty( bson *obj ); + +/** + * Return a pointer to an empty, shared, static BSON object. + * + * @note This object is owned by the driver. You must NOT modify it + * and must NOT call bson_destroy( ) on it. + * + * @return the shared initialized BSON object. + */ +MONGO_EXPORT const bson *bson_shared_empty( void ); + +/** + * Make a complete copy of the a BSON object. + * The source bson object must be in a finished + * state; otherwise, the copy will fail. + * + * @param out the copy destination BSON object. + * @param in the copy source BSON object. + */ +MONGO_EXPORT int bson_copy( bson *out, const bson *in ); /* puts data in new buffer. NOOP if out==NULL */ + +/** + * Append a previously created bson_oid_t to a bson object. + * + * @param b the bson to append to. + * @param name the key for the bson_oid_t. + * @param oid the bson_oid_t to append. + * + * @return BSON_OK or BSON_ERROR. + */ +MONGO_EXPORT int bson_append_oid( bson *b, const char *name, const bson_oid_t *oid ); + +/** + * Append a bson_oid_t to a bson. + * + * @param b the bson to append to. + * @param name the key for the bson_oid_t. + * + * @return BSON_OK or BSON_ERROR. + */ +MONGO_EXPORT int bson_append_new_oid( bson *b, const char *name ); + +/** + * Append an int to a bson. + * + * @param b the bson to append to. + * @param name the key for the int. + * @param i the int to append. + * + * @return BSON_OK or BSON_ERROR. + */ +MONGO_EXPORT int bson_append_int( bson *b, const char *name, const int i ); + +/** + * Append an long to a bson. + * + * @param b the bson to append to. + * @param name the key for the long. + * @param i the long to append. + * + * @return BSON_OK or BSON_ERROR. + */ +MONGO_EXPORT int bson_append_long( bson *b, const char *name, const int64_t i ); + +/** + * Append an double to a bson. + * + * @param b the bson to append to. + * @param name the key for the double. + * @param d the double to append. + * + * @return BSON_OK or BSON_ERROR. + */ +MONGO_EXPORT int bson_append_double( bson *b, const char *name, const double d ); + +/** + * Append a string to a bson. + * + * @param b the bson to append to. + * @param name the key for the string. + * @param str the string to append. + * + * @return BSON_OK or BSON_ERROR. +*/ +MONGO_EXPORT int bson_append_string( bson *b, const char *name, const char *str ); + +/** + * Append len bytes of a string to a bson. + * + * @param b the bson to append to. + * @param name the key for the string. + * @param str the string to append. + * @param len the number of bytes from str to append. + * + * @return BSON_OK or BSON_ERROR. + */ +MONGO_EXPORT int bson_append_string_n( bson *b, const char *name, const char *str, size_t len ); + +/** + * Append a symbol to a bson. + * + * @param b the bson to append to. + * @param name the key for the symbol. + * @param str the symbol to append. + * + * @return BSON_OK or BSON_ERROR. + */ +MONGO_EXPORT int bson_append_symbol( bson *b, const char *name, const char *str ); + +/** + * Append len bytes of a symbol to a bson. + * + * @param b the bson to append to. + * @param name the key for the symbol. + * @param str the symbol to append. + * @param len the number of bytes from str to append. + * + * @return BSON_OK or BSON_ERROR. + */ +MONGO_EXPORT int bson_append_symbol_n( bson *b, const char *name, const char *str, size_t len ); + +/** + * Append code to a bson. + * + * @param b the bson to append to. + * @param name the key for the code. + * @param str the code to append. + * @param len the number of bytes from str to append. + * + * @return BSON_OK or BSON_ERROR. + */ +MONGO_EXPORT int bson_append_code( bson *b, const char *name, const char *str ); + +/** + * Append len bytes of code to a bson. + * + * @param b the bson to append to. + * @param name the key for the code. + * @param str the code to append. + * @param len the number of bytes from str to append. + * + * @return BSON_OK or BSON_ERROR. + */ +MONGO_EXPORT int bson_append_code_n( bson *b, const char *name, const char *str, size_t len ); + +/** + * Append code to a bson with scope. + * + * @param b the bson to append to. + * @param name the key for the code. + * @param str the string to append. + * @param scope a BSON object containing the scope. + * + * @return BSON_OK or BSON_ERROR. + */ +MONGO_EXPORT int bson_append_code_w_scope( bson *b, const char *name, const char *code, const bson *scope ); + +/** + * Append len bytes of code to a bson with scope. + * + * @param b the bson to append to. + * @param name the key for the code. + * @param str the string to append. + * @param len the number of bytes from str to append. + * @param scope a BSON object containing the scope. + * + * @return BSON_OK or BSON_ERROR. + */ +MONGO_EXPORT int bson_append_code_w_scope_n( bson *b, const char *name, const char *code, size_t size, const bson *scope ); + +/** + * Append binary data to a bson. + * + * @param b the bson to append to. + * @param name the key for the data. + * @param type the binary data type. + * @param str the binary data. + * @param len the length of the data. + * + * @return BSON_OK or BSON_ERROR. + */ +MONGO_EXPORT int bson_append_binary( bson *b, const char *name, char type, const char *str, size_t len ); + +/** + * Append a bson_bool_t to a bson. + * + * @param b the bson to append to. + * @param name the key for the boolean value. + * @param v the bson_bool_t to append. + * + * @return BSON_OK or BSON_ERROR. + */ +MONGO_EXPORT int bson_append_bool( bson *b, const char *name, const bson_bool_t v ); + +/** + * Append a null value to a bson. + * + * @param b the bson to append to. + * @param name the key for the null value. + * + * @return BSON_OK or BSON_ERROR. + */ +MONGO_EXPORT int bson_append_null( bson *b, const char *name ); + +/** + * Append an undefined value to a bson. + * + * @param b the bson to append to. + * @param name the key for the undefined value. + * + * @return BSON_OK or BSON_ERROR. + */ +MONGO_EXPORT int bson_append_undefined( bson *b, const char *name ); + +/** + * Append a maxkey value to a bson. + * + * @param b the bson to append to. + * @param name the key for the maxkey value. + * + * @return BSON_OK or BSON_ERROR. + */ +MONGO_EXPORT int bson_append_maxkey( bson *b, const char *name ); + +/** + * Append a minkey value to a bson. + * + * @param b the bson to append to. + * @param name the key for the minkey value. + * + * @return BSON_OK or BSON_ERROR. + */ +MONGO_EXPORT int bson_append_minkey( bson *b, const char *name ); + +/** + * Append a regex value to a bson. + * + * @param b the bson to append to. + * @param name the key for the regex value. + * @param pattern the regex pattern to append. + * @param the regex options. + * + * @return BSON_OK or BSON_ERROR. + */ +MONGO_EXPORT int bson_append_regex( bson *b, const char *name, const char *pattern, const char *opts ); + +/** + * Append bson data to a bson. + * + * @param b the bson to append to. + * @param name the key for the bson data. + * @param bson the bson object to append. + * + * @return BSON_OK or BSON_ERROR. + */ +MONGO_EXPORT int bson_append_bson( bson *b, const char *name, const bson *bson ); + +/** + * Append a BSON element to a bson from the current point of an iterator. + * + * @param b the bson to append to. + * @param name_or_null the key for the BSON element, or NULL. + * @param elem the bson_iterator. + * + * @return BSON_OK or BSON_ERROR. + */ +MONGO_EXPORT int bson_append_element( bson *b, const char *name_or_null, const bson_iterator *elem ); + +/** + * Append a bson_timestamp_t value to a bson. + * + * @param b the bson to append to. + * @param name the key for the timestampe value. + * @param ts the bson_timestamp_t value to append. + * + * @return BSON_OK or BSON_ERROR. + */ +MONGO_EXPORT int bson_append_timestamp( bson *b, const char *name, bson_timestamp_t *ts ); +MONGO_EXPORT int bson_append_timestamp2( bson *b, const char *name, int time, int increment ); + +/* these both append a bson_date */ +/** + * Append a bson_date_t value to a bson. + * + * @param b the bson to append to. + * @param name the key for the date value. + * @param millis the bson_date_t to append. + * + * @return BSON_OK or BSON_ERROR. + */ +MONGO_EXPORT int bson_append_date( bson *b, const char *name, bson_date_t millis ); + +/** + * Append a time_t value to a bson. + * + * @param b the bson to append to. + * @param name the key for the date value. + * @param secs the time_t to append. + * + * @return BSON_OK or BSON_ERROR. + */ +MONGO_EXPORT int bson_append_time_t( bson *b, const char *name, time_t secs ); + +/** + * Start appending a new object to a bson. + * + * @param b the bson to append to. + * @param name the name of the new object. + * + * @return BSON_OK or BSON_ERROR. + */ +MONGO_EXPORT int bson_append_start_object( bson *b, const char *name ); + +/** + * Start appending a new array to a bson. + * + * @param b the bson to append to. + * @param name the name of the new array. + * + * @return BSON_OK or BSON_ERROR. + */ +MONGO_EXPORT int bson_append_start_array( bson *b, const char *name ); + +/** + * Finish appending a new object or array to a bson. + * + * @param b the bson to append to. + * + * @return BSON_OK or BSON_ERROR. + */ +MONGO_EXPORT int bson_append_finish_object( bson *b ); + +/** + * Finish appending a new object or array to a bson. This + * is simply an alias for bson_append_finish_object. + * + * @param b the bson to append to. + * + * @return BSON_OK or BSON_ERROR. + */ +MONGO_EXPORT int bson_append_finish_array( bson *b ); + +void bson_numstr( char *str, int i ); + +void bson_incnumstr( char *str ); + +/* Error handling and standard library function over-riding. */ +/* -------------------------------------------------------- */ + +/* bson_err_handlers shouldn't return!!! */ +typedef void( *bson_err_handler )( const char *errmsg ); + +typedef int (*bson_printf_func)( const char *, ... ); +typedef int (*bson_fprintf_func)( FILE *, const char *, ... ); +typedef int (*bson_sprintf_func)( char *, const char *, ... ); + +extern void *( *bson_malloc_func )( size_t ); +extern void *( *bson_realloc_func )( void *, size_t ); +extern void ( *bson_free_func )( void * ); + +extern bson_printf_func bson_printf; +extern bson_fprintf_func bson_fprintf; +extern bson_sprintf_func bson_sprintf; +extern bson_printf_func bson_errprintf; + +MONGO_EXPORT void bson_free( void *ptr ); + +/** + * Allocates memory and checks return value, exiting fatally if malloc() fails. + * + * @param size bytes to allocate. + * + * @return a pointer to the allocated memory. + * + * @sa malloc(3) + */ +MONGO_EXPORT void *bson_malloc( size_t size ); + +/** + * Changes the size of allocated memory and checks return value, + * exiting fatally if realloc() fails. + * + * @param ptr pointer to the space to reallocate. + * @param size bytes to allocate. + * + * @return a pointer to the allocated memory. + * + * @sa realloc() + */ +void *bson_realloc( void *ptr, size_t size ); + +/** + * Set a function for error handling. + * + * @param func a bson_err_handler function. + * + * @return the old error handling function, or NULL. + */ +MONGO_EXPORT bson_err_handler set_bson_err_handler( bson_err_handler func ); + +/* does nothing if ok != 0 */ +/** + * Exit fatally. + * + * @param ok exits if ok is equal to 0. + */ +void bson_fatal( int ok ); + +/** + * Exit fatally with an error message. + * + * @param ok exits if ok is equal to 0. + * @param msg prints to stderr before exiting. + */ +void bson_fatal_msg( int ok, const char *msg ); + +/** + * Invoke the error handler, but do not exit. + * + * @param b the buffer object. + */ +void bson_builder_error( bson *b ); + +/** + * Cast an int64_t to double. This is necessary for embedding in + * certain environments. + * + */ +MONGO_EXPORT double bson_int64_to_double( int64_t i64 ); + +MONGO_EXPORT void bson_swap_endian32( void *outp, const void *inp ); +MONGO_EXPORT void bson_swap_endian64( void *outp, const void *inp ); + +MONGO_EXTERN_C_END +#endif diff --git a/bson/encoding.c b/bson/encoding.c new file mode 100644 index 0000000..9a9017b --- /dev/null +++ b/bson/encoding.c @@ -0,0 +1,167 @@ +/* + * Copyright 2009-2012 10gen, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Portions Copyright 2001 Unicode, Inc. + * + * Disclaimer + * + * This source code is provided as is by Unicode, Inc. No claims are + * made as to fitness for any particular purpose. No warranties of any + * kind are expressed or implied. The recipient agrees to determine + * applicability of information provided. If this file has been + * purchased on magnetic or optical media from Unicode, Inc., the + * sole remedy for any claim will be exchange of defective media + * within 90 days of receipt. + * + * Limitations on Rights to Redistribute This Code + * + * Unicode, Inc. hereby grants the right to freely use the information + * supplied in this file in the creation of products supporting the + * Unicode Standard, and to make copies of this file in any form + * for internal or external distribution as long as this notice + * remains attached. + */ + + +#include "bson.h" +#include "encoding.h" + +/* + * Index into the table below with the first byte of a UTF-8 sequence to + * get the number of trailing bytes that are supposed to follow it. + */ +static const char trailingBytesForUTF8[256] = { + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 +}; + +/* --------------------------------------------------------------------- */ + +/* + * Utility routine to tell whether a sequence of bytes is legal UTF-8. + * This must be called with the length pre-determined by the first byte. + * The length can be set by: + * length = trailingBytesForUTF8[*source]+1; + * and the sequence is illegal right away if there aren't that many bytes + * available. + * If presented with a length > 4, this returns 0. The Unicode + * definition of UTF-8 goes up to 4-byte sequences. + */ +static int isLegalUTF8( const unsigned char *source, int length ) { + unsigned char a; + const unsigned char *srcptr = source + length; + switch ( length ) { + default: + return 0; + /* Everything else falls through when "true"... */ + case 4: + if ( ( a = ( *--srcptr ) ) < 0x80 || a > 0xBF ) return 0; + case 3: + if ( ( a = ( *--srcptr ) ) < 0x80 || a > 0xBF ) return 0; + case 2: + if ( ( a = ( *--srcptr ) ) > 0xBF ) return 0; + switch ( *source ) { + /* no fall-through in this inner switch */ + case 0xE0: + if ( a < 0xA0 ) return 0; + break; + case 0xF0: + if ( a < 0x90 ) return 0; + break; + case 0xF4: + if ( a > 0x8F ) return 0; + break; + default: + if ( a < 0x80 ) return 0; + } + case 1: + if ( *source >= 0x80 && *source < 0xC2 ) return 0; + if ( *source > 0xF4 ) return 0; + } + return 1; +} + +/* If the name is part of a db ref ($ref, $db, or $id), then return true. */ +static int bson_string_is_db_ref( const unsigned char *string, const size_t length ) { + int result = 0; + + if( length >= 4 ) { + if( string[1] == 'r' && string[2] == 'e' && string[3] == 'f' ) + result = 1; + } + else if( length >= 3 ) { + if( string[1] == 'i' && string[2] == 'd' ) + result = 1; + else if( string[1] == 'd' && string[2] == 'b' ) + result = 1; + } + + return result; +} + +static int bson_validate_string( bson *b, const unsigned char *string, + const size_t length, const char check_utf8, const char check_dot, + const char check_dollar ) { + + size_t position = 0; + int sequence_length = 1; + + if( check_dollar && string[0] == '$' ) { + if( !bson_string_is_db_ref( string, length ) ) + b->err |= BSON_FIELD_INIT_DOLLAR; + } + + while ( position < length ) { + if ( check_dot && *( string + position ) == '.' ) { + b->err |= BSON_FIELD_HAS_DOT; + } + + if ( check_utf8 ) { + sequence_length = trailingBytesForUTF8[*( string + position )] + 1; + if ( ( position + sequence_length ) > length ) { + b->err |= BSON_NOT_UTF8; + return BSON_ERROR; + } + if ( !isLegalUTF8( string + position, sequence_length ) ) { + b->err |= BSON_NOT_UTF8; + return BSON_ERROR; + } + } + position += sequence_length; + } + + return BSON_OK; +} + + +int bson_check_string( bson *b, const char *string, + const size_t length ) { + + return bson_validate_string( b, ( const unsigned char * )string, length, 1, 0, 0 ); +} + +int bson_check_field_name( bson *b, const char *string, + const size_t length ) { + + return bson_validate_string( b, ( const unsigned char * )string, length, 1, 1, 1 ); +} diff --git a/bson/encoding.h b/bson/encoding.h new file mode 100644 index 0000000..ec34c2e --- /dev/null +++ b/bson/encoding.h @@ -0,0 +1,54 @@ +/* + * Copyright 2009-2012 10gen, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BSON_ENCODING_H_ +#define BSON_ENCODING_H_ + +MONGO_EXTERN_C_START + +/** + * Check that a field name is valid UTF8, does not start with a '$', + * and contains no '.' characters. Set bson bit field appropriately. + * Note that we don't need to check for '\0' because we're using + * strlen(3), which stops at '\0'. + * + * @param b The bson object to which field name will be appended. + * @param string The field name as char*. + * @param length The length of the field name. + * + * @return BSON_OK if valid UTF8 and BSON_ERROR if not. All BSON strings must be + * valid UTF8. This function will also check whether the string + * contains '.' or starts with '$', since the validity of this depends on context. + * Set the value of b->err appropriately. + */ +int bson_check_field_name( bson *b, const char *string, + const size_t length ); + +/** + * Check that a string is valid UTF8. Sets the buffer bit field appropriately. + * + * @param b The bson object to which string will be appended. + * @param string The string to check. + * @param length The length of the string. + * + * @return BSON_OK if valid UTF-8; otherwise, BSON_ERROR. + * Sets b->err on error. + */ +bson_bool_t bson_check_string( bson *b, const char *string, + const size_t length ); + +MONGO_EXTERN_C_END +#endif diff --git a/bson/numbers.c b/bson/numbers.c new file mode 100644 index 0000000..b3032d5 --- /dev/null +++ b/bson/numbers.c @@ -0,0 +1,127 @@ +/* Copyright 2009-2012 10gen Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* all the numbers that fit in a 4 byte string */ +const char bson_numstrs[1000][4] = { + "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", + "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", + "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", + "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", + "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", + "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", + "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", + "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", + "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", + "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", + + "100", "101", "102", "103", "104", "105", "106", "107", "108", "109", + "110", "111", "112", "113", "114", "115", "116", "117", "118", "119", + "120", "121", "122", "123", "124", "125", "126", "127", "128", "129", + "130", "131", "132", "133", "134", "135", "136", "137", "138", "139", + "140", "141", "142", "143", "144", "145", "146", "147", "148", "149", + "150", "151", "152", "153", "154", "155", "156", "157", "158", "159", + "160", "161", "162", "163", "164", "165", "166", "167", "168", "169", + "170", "171", "172", "173", "174", "175", "176", "177", "178", "179", + "180", "181", "182", "183", "184", "185", "186", "187", "188", "189", + "190", "191", "192", "193", "194", "195", "196", "197", "198", "199", + + "200", "201", "202", "203", "204", "205", "206", "207", "208", "209", + "210", "211", "212", "213", "214", "215", "216", "217", "218", "219", + "220", "221", "222", "223", "224", "225", "226", "227", "228", "229", + "230", "231", "232", "233", "234", "235", "236", "237", "238", "239", + "240", "241", "242", "243", "244", "245", "246", "247", "248", "249", + "250", "251", "252", "253", "254", "255", "256", "257", "258", "259", + "260", "261", "262", "263", "264", "265", "266", "267", "268", "269", + "270", "271", "272", "273", "274", "275", "276", "277", "278", "279", + "280", "281", "282", "283", "284", "285", "286", "287", "288", "289", + "290", "291", "292", "293", "294", "295", "296", "297", "298", "299", + + "300", "301", "302", "303", "304", "305", "306", "307", "308", "309", + "310", "311", "312", "313", "314", "315", "316", "317", "318", "319", + "320", "321", "322", "323", "324", "325", "326", "327", "328", "329", + "330", "331", "332", "333", "334", "335", "336", "337", "338", "339", + "340", "341", "342", "343", "344", "345", "346", "347", "348", "349", + "350", "351", "352", "353", "354", "355", "356", "357", "358", "359", + "360", "361", "362", "363", "364", "365", "366", "367", "368", "369", + "370", "371", "372", "373", "374", "375", "376", "377", "378", "379", + "380", "381", "382", "383", "384", "385", "386", "387", "388", "389", + "390", "391", "392", "393", "394", "395", "396", "397", "398", "399", + + "400", "401", "402", "403", "404", "405", "406", "407", "408", "409", + "410", "411", "412", "413", "414", "415", "416", "417", "418", "419", + "420", "421", "422", "423", "424", "425", "426", "427", "428", "429", + "430", "431", "432", "433", "434", "435", "436", "437", "438", "439", + "440", "441", "442", "443", "444", "445", "446", "447", "448", "449", + "450", "451", "452", "453", "454", "455", "456", "457", "458", "459", + "460", "461", "462", "463", "464", "465", "466", "467", "468", "469", + "470", "471", "472", "473", "474", "475", "476", "477", "478", "479", + "480", "481", "482", "483", "484", "485", "486", "487", "488", "489", + "490", "491", "492", "493", "494", "495", "496", "497", "498", "499", + + "500", "501", "502", "503", "504", "505", "506", "507", "508", "509", + "510", "511", "512", "513", "514", "515", "516", "517", "518", "519", + "520", "521", "522", "523", "524", "525", "526", "527", "528", "529", + "530", "531", "532", "533", "534", "535", "536", "537", "538", "539", + "540", "541", "542", "543", "544", "545", "546", "547", "548", "549", + "550", "551", "552", "553", "554", "555", "556", "557", "558", "559", + "560", "561", "562", "563", "564", "565", "566", "567", "568", "569", + "570", "571", "572", "573", "574", "575", "576", "577", "578", "579", + "580", "581", "582", "583", "584", "585", "586", "587", "588", "589", + "590", "591", "592", "593", "594", "595", "596", "597", "598", "599", + + "600", "601", "602", "603", "604", "605", "606", "607", "608", "609", + "610", "611", "612", "613", "614", "615", "616", "617", "618", "619", + "620", "621", "622", "623", "624", "625", "626", "627", "628", "629", + "630", "631", "632", "633", "634", "635", "636", "637", "638", "639", + "640", "641", "642", "643", "644", "645", "646", "647", "648", "649", + "650", "651", "652", "653", "654", "655", "656", "657", "658", "659", + "660", "661", "662", "663", "664", "665", "666", "667", "668", "669", + "670", "671", "672", "673", "674", "675", "676", "677", "678", "679", + "680", "681", "682", "683", "684", "685", "686", "687", "688", "689", + "690", "691", "692", "693", "694", "695", "696", "697", "698", "699", + + "700", "701", "702", "703", "704", "705", "706", "707", "708", "709", + "710", "711", "712", "713", "714", "715", "716", "717", "718", "719", + "720", "721", "722", "723", "724", "725", "726", "727", "728", "729", + "730", "731", "732", "733", "734", "735", "736", "737", "738", "739", + "740", "741", "742", "743", "744", "745", "746", "747", "748", "749", + "750", "751", "752", "753", "754", "755", "756", "757", "758", "759", + "760", "761", "762", "763", "764", "765", "766", "767", "768", "769", + "770", "771", "772", "773", "774", "775", "776", "777", "778", "779", + "780", "781", "782", "783", "784", "785", "786", "787", "788", "789", + "790", "791", "792", "793", "794", "795", "796", "797", "798", "799", + + "800", "801", "802", "803", "804", "805", "806", "807", "808", "809", + "810", "811", "812", "813", "814", "815", "816", "817", "818", "819", + "820", "821", "822", "823", "824", "825", "826", "827", "828", "829", + "830", "831", "832", "833", "834", "835", "836", "837", "838", "839", + "840", "841", "842", "843", "844", "845", "846", "847", "848", "849", + "850", "851", "852", "853", "854", "855", "856", "857", "858", "859", + "860", "861", "862", "863", "864", "865", "866", "867", "868", "869", + "870", "871", "872", "873", "874", "875", "876", "877", "878", "879", + "880", "881", "882", "883", "884", "885", "886", "887", "888", "889", + "890", "891", "892", "893", "894", "895", "896", "897", "898", "899", + + "900", "901", "902", "903", "904", "905", "906", "907", "908", "909", + "910", "911", "912", "913", "914", "915", "916", "917", "918", "919", + "920", "921", "922", "923", "924", "925", "926", "927", "928", "929", + "930", "931", "932", "933", "934", "935", "936", "937", "938", "939", + "940", "941", "942", "943", "944", "945", "946", "947", "948", "949", + "950", "951", "952", "953", "954", "955", "956", "957", "958", "959", + "960", "961", "962", "963", "964", "965", "966", "967", "968", "969", + "970", "971", "972", "973", "974", "975", "976", "977", "978", "979", + "980", "981", "982", "983", "984", "985", "986", "987", "988", "989", + "990", "991", "992", "993", "994", "995", "996", "997", "998", "999", +}; diff --git a/config.c b/config.c new file mode 100644 index 0000000..655c3cf --- /dev/null +++ b/config.c @@ -0,0 +1,79 @@ +/* +Cuckoo Sandbox - Automated Malware Analysis +Copyright (C) 2010-2012 Cuckoo Sandbox Developers + +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 . +*/ + +#include +#include +#include "ntapi.h" +#include "config.h" + +void read_config() +{ + // TODO unicode support + char buf[512], config_fname[MAX_PATH]; + sprintf(config_fname, "%s\\%d.ini", + getenv("TEMP"), GetCurrentProcessId()); + + FILE *fp = fopen(config_fname, "r"); + if(fp != NULL) { + while (fgets(buf, sizeof(buf), fp) != NULL) { + // cut off the newline + char *p = strchr(buf, '\r'); + if(p != NULL) *p = 0; + p = strchr(buf, '\n'); + if(p != NULL) *p = 0; + + // split key=value + p = strchr(buf, '='); + if(p != NULL) { + *p = 0; + + const char *key = buf, *value = p + 1; + + if(!strcmp(key, "pipe")) { + strncpy(g_config.pipe_name, value, + ARRAYSIZE(g_config.pipe_name)); + } + else if(!strcmp(key, "results")) { + strncpy(g_config.results, value, + ARRAYSIZE(g_config.results)); + } + else if(!strcmp(key, "analyzer")) { + strncpy(g_config.analyzer, value, + ARRAYSIZE(g_config.analyzer)); + } + else if(!strcmp(key, "first-process")) { + g_config.first_process = value[0] == '1'; + } + else if(!strcmp(key, "startup-time")) { + g_config.startup_time = atoi(value); + } + else if(!strcmp(key, "retaddr-check")) { + g_config.retaddr_check = value[0] == '1'; + } + else if(!strcmp(key, "host-ip")) { + g_config.host_ip = inet_addr(value); + } + else if(!strcmp(key, "host-port")) { + g_config.host_port = atoi(value); + } + } + } + fclose(fp); + DeleteFile(config_fname); + } +} diff --git a/config.h b/config.h new file mode 100644 index 0000000..14a3b82 --- /dev/null +++ b/config.h @@ -0,0 +1,43 @@ +/* +Cuckoo Sandbox - Automated Malware Analysis +Copyright (C) 2010-2012 Cuckoo Sandbox Developers + +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 . +*/ + +struct { + // name of the pipe to communicate with cuckoo + char pipe_name[MAX_PATH]; + + // results directory, has to be hidden + char results[MAX_PATH]; + + // analyzer directory, has to be hidden + char analyzer[MAX_PATH]; + + // is this the first process or not? + int first_process; + + // how many milliseconds since startup + unsigned int startup_time; + + // do we want to enable the retaddr check? + int retaddr_check; + + // server ip and port + unsigned int host_ip; + unsigned short host_port; +} g_config; + +void read_config(); diff --git a/cuckoomon.c b/cuckoomon.c new file mode 100644 index 0000000..f3c422f --- /dev/null +++ b/cuckoomon.c @@ -0,0 +1,426 @@ +/* +Cuckoo Sandbox - Automated Malware Analysis +Copyright (C) 2010-2014 Cuckoo Sandbox Developers + +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 . +*/ + +#include +#include +#include "ntapi.h" +#include "misc.h" +#include "hooking.h" +#include "hooks.h" +#include "log.h" +#include "pipe.h" +#include "ignore.h" +#include "hook_file.h" +#include "hook_sleep.h" +#include "config.h" + +#define HOOK(library, funcname) {L###library, #funcname, NULL, \ + &New_##funcname, (void **) &Old_##funcname} + +#define HOOK2(library, funcname, recursion) {L###library, #funcname, NULL, \ + &New2_##funcname, (void **) &Old2_##funcname, recursion} + +static hook_t g_hooks[] = { + + // + // Special Hooks + // + // NOTE: due to the fact that the "special" hooks don't use a hook count + // (whereas the "normal" hooks, those with allow_hook_recursion set to + // zero, do) we have to hook the "special" hooks first. Otherwise the + // execution flow will end up in an infinite loop, because of hook count + // and whatnot. + // + // In other words, do *NOT* place "special" hooks behind "normal" hooks. + // + + HOOK2(ntdll, LdrLoadDll, TRUE), + HOOK2(kernel32, CreateProcessInternalW, TRUE), + + // + // File Hooks + // + + HOOK(ntdll, NtCreateFile), + HOOK(ntdll, NtOpenFile), + HOOK(ntdll, NtReadFile), + HOOK(ntdll, NtWriteFile), + HOOK(ntdll, NtDeleteFile), + HOOK(ntdll, NtDeviceIoControlFile), + HOOK(ntdll, NtQueryDirectoryFile), + HOOK(ntdll, NtQueryInformationFile), + HOOK(ntdll, NtSetInformationFile), + HOOK(ntdll, NtOpenDirectoryObject), + HOOK(ntdll, NtCreateDirectoryObject), + + // CreateDirectoryExA calls CreateDirectoryExW + // CreateDirectoryW does not call CreateDirectoryExW + HOOK(kernel32, CreateDirectoryW), + HOOK(kernel32, CreateDirectoryExW), + + HOOK(kernel32, RemoveDirectoryA), + HOOK(kernel32, RemoveDirectoryW), + + // lowest variant of MoveFile() + HOOK(kernel32, MoveFileWithProgressW), + + HOOK(kernel32, FindFirstFileExA), + HOOK(kernel32, FindFirstFileExW), + + // Covered by NtCreateFile() but still grap this information + HOOK(kernel32, CopyFileA), + HOOK(kernel32, CopyFileW), + HOOK(kernel32, CopyFileExW), + + // Covered by NtSetInformationFile() but still grap this information + HOOK(kernel32, DeleteFileA), + HOOK(kernel32, DeleteFileW), + + // + // Registry Hooks + // + // Note: Most, if not all, of the Registry API go natively from both the + // A as well as the W versions. In other words, we have to hook all the + // ascii *and* unicode APIs of those functions. + // + + HOOK(advapi32, RegOpenKeyExA), + HOOK(advapi32, RegOpenKeyExW), + + HOOK(advapi32, RegCreateKeyExA), + HOOK(advapi32, RegCreateKeyExW), + + // Note that RegDeleteKeyEx() is available for 64bit XP/Vista+ + HOOK(advapi32, RegDeleteKeyA), + HOOK(advapi32, RegDeleteKeyW), + + // RegEnumKeyA() calls RegEnumKeyExA(), but RegEnumKeyW() does *not* + // call RegEnumKeyExW() + HOOK(advapi32, RegEnumKeyW), + HOOK(advapi32, RegEnumKeyExA), + HOOK(advapi32, RegEnumKeyExW), + + HOOK(advapi32, RegEnumValueA), + HOOK(advapi32, RegEnumValueW), + + HOOK(advapi32, RegSetValueExA), + HOOK(advapi32, RegSetValueExW), + + HOOK(advapi32, RegQueryValueExA), + HOOK(advapi32, RegQueryValueExW), + + HOOK(advapi32, RegDeleteValueA), + HOOK(advapi32, RegDeleteValueW), + + HOOK(advapi32, RegQueryInfoKeyA), + HOOK(advapi32, RegQueryInfoKeyW), + + HOOK(advapi32, RegCloseKey), + + // + // Native Registry Hooks + // + + HOOK(ntdll, NtCreateKey), + HOOK(ntdll, NtOpenKey), + HOOK(ntdll, NtOpenKeyEx), + HOOK(ntdll, NtRenameKey), + HOOK(ntdll, NtReplaceKey), + HOOK(ntdll, NtEnumerateKey), + HOOK(ntdll, NtEnumerateValueKey), + HOOK(ntdll, NtSetValueKey), + HOOK(ntdll, NtQueryValueKey), + HOOK(ntdll, NtQueryMultipleValueKey), + HOOK(ntdll, NtDeleteKey), + HOOK(ntdll, NtDeleteValueKey), + HOOK(ntdll, NtLoadKey), + HOOK(ntdll, NtLoadKey2), + HOOK(ntdll, NtLoadKeyEx), + HOOK(ntdll, NtQueryKey), + HOOK(ntdll, NtSaveKey), + HOOK(ntdll, NtSaveKeyEx), + + // + // Window Hooks + // + + HOOK(user32, FindWindowA), + HOOK(user32, FindWindowW), + HOOK(user32, FindWindowExA), + HOOK(user32, FindWindowExW), + + // + // Sync Hooks + // + + HOOK(ntdll, NtCreateMutant), + HOOK(ntdll, NtOpenMutant), + HOOK(ntdll, NtCreateNamedPipeFile), + + // + // Process Hooks + // + + HOOK(ntdll, NtCreateProcess), + HOOK(ntdll, NtCreateProcessEx), + HOOK(ntdll, NtCreateUserProcess), + HOOK(ntdll, RtlCreateUserProcess), + //HOOK(ntdll, NtOpenProcess), + HOOK(ntdll, NtTerminateProcess), + HOOK(ntdll, NtCreateSection), + HOOK(ntdll, NtMakeTemporaryObject), + HOOK(ntdll, NtMakePermanentObject), + HOOK(ntdll, NtOpenSection), + //HOOK(kernel32, CreateProcessInternalW), + HOOK(ntdll, ZwMapViewOfSection), + HOOK(kernel32, ExitProcess), + + // all variants of ShellExecute end up in ShellExecuteExW + HOOK(shell32, ShellExecuteExW), + HOOK(ntdll, NtUnmapViewOfSection), + // HOOK(ntdll, NtAllocateVirtualMemory), + HOOK(ntdll, NtReadVirtualMemory), + HOOK(kernel32, ReadProcessMemory), + HOOK(ntdll, NtWriteVirtualMemory), + HOOK(kernel32, WriteProcessMemory), + HOOK(ntdll, NtProtectVirtualMemory), + HOOK(kernel32, VirtualProtectEx), + HOOK(ntdll, NtFreeVirtualMemory), + //HOOK(kernel32, VirtualFreeEx), + + HOOK(msvcrt, system), + + // + // Thread Hooks + // + + HOOK(ntdll, NtCreateThread), + HOOK(ntdll, NtCreateThreadEx), + HOOK(ntdll, NtOpenThread), + HOOK(ntdll, NtGetContextThread), + HOOK(ntdll, NtSetContextThread), + HOOK(ntdll, NtSuspendThread), + HOOK(ntdll, NtResumeThread), + HOOK(ntdll, NtTerminateThread), + HOOK(kernel32, CreateThread), + HOOK(kernel32, CreateRemoteThread), + HOOK(kernel32, ExitThread), + HOOK(ntdll, RtlCreateUserThread), + + // + // Misc Hooks + // + + HOOK(user32, SetWindowsHookExA), + HOOK(user32, SetWindowsHookExW), + HOOK(user32, UnhookWindowsHookEx), + //HOOK(ntdll, LdrLoadDll), + HOOK(ntdll, LdrGetDllHandle), + HOOK(ntdll, LdrGetProcedureAddress), + HOOK(kernel32, DeviceIoControl), + HOOK(user32, ExitWindowsEx), + HOOK(kernel32, IsDebuggerPresent), + HOOK(advapi32, LookupPrivilegeValueW), + //HOOK(ntdll, NtClose), + HOOK(kernel32, WriteConsoleA), + HOOK(kernel32, WriteConsoleW), + HOOK(user32, GetSystemMetrics), + HOOK(user32, GetCursorPos), + + // + // Network Hooks + // + + HOOK(urlmon, URLDownloadToFileW), + HOOK(wininet, InternetOpenA), + HOOK(wininet, InternetOpenW), + HOOK(wininet, InternetConnectA), + HOOK(wininet, InternetConnectW), + HOOK(wininet, InternetOpenUrlA), + HOOK(wininet, InternetOpenUrlW), + HOOK(wininet, HttpOpenRequestA), + HOOK(wininet, HttpOpenRequestW), + HOOK(wininet, HttpSendRequestA), + HOOK(wininet, HttpSendRequestW), + HOOK(wininet, InternetReadFile), + HOOK(wininet, InternetWriteFile), + HOOK(wininet, InternetCloseHandle), + + HOOK(dnsapi, DnsQuery_A), + HOOK(dnsapi, DnsQuery_UTF8), + HOOK(dnsapi, DnsQuery_W), + HOOK(ws2_32, getaddrinfo), + HOOK(ws2_32, GetAddrInfoW), + + // + // Service Hooks + // + + HOOK(advapi32, OpenSCManagerA), + HOOK(advapi32, OpenSCManagerW), + HOOK(advapi32, CreateServiceA), + HOOK(advapi32, CreateServiceW), + HOOK(advapi32, OpenServiceA), + HOOK(advapi32, OpenServiceW), + HOOK(advapi32, StartServiceA), + HOOK(advapi32, StartServiceW), + HOOK(advapi32, ControlService), + HOOK(advapi32, DeleteService), + + // + // Sleep Hooks + // + + HOOK(ntdll, NtDelayExecution), + HOOK(kernel32, GetLocalTime), + HOOK(kernel32, GetSystemTime), + HOOK(kernel32, GetTickCount), + HOOK(ntdll, NtQuerySystemTime), + + // + // Socket Hooks + // + + HOOK(ws2_32, WSAStartup), + HOOK(ws2_32, gethostbyname), + HOOK(ws2_32, socket), + HOOK(ws2_32, connect), + HOOK(ws2_32, send), + HOOK(ws2_32, sendto), + HOOK(ws2_32, recv), + HOOK(ws2_32, recvfrom), + HOOK(ws2_32, accept), + HOOK(ws2_32, bind), + HOOK(ws2_32, listen), + HOOK(ws2_32, select), + HOOK(ws2_32, setsockopt), + HOOK(ws2_32, ioctlsocket), + HOOK(ws2_32, closesocket), + HOOK(ws2_32, shutdown), + + HOOK(ws2_32, WSARecv), + HOOK(ws2_32, WSARecvFrom), + HOOK(ws2_32, WSASend), + HOOK(ws2_32, WSASendTo), + HOOK(ws2_32, WSASocketA), + HOOK(ws2_32, WSASocketW), + + // HOOK(wsock32, connect), + // HOOK(wsock32, send), + // HOOK(wsock32, recv), + + HOOK(mswsock, ConnectEx), + HOOK(mswsock, TransmitFile), +}; + +// get a random hooking method, except for hook_jmp_direct +//#define HOOKTYPE randint(HOOK_NOP_JMP_DIRECT, HOOK_MOV_EAX_INDIRECT_PUSH_RETN) +// error testing with hook_jmp_direct only +#define HOOKTYPE HOOK_JMP_DIRECT + +void set_hooks_dll(const wchar_t *library, int len) +{ + for (int i = 0; i < ARRAYSIZE(g_hooks); i++) { + if(!wcsnicmp(g_hooks[i].library, library, len)) { + hook_api(&g_hooks[i], HOOKTYPE); + } + } +} + +void set_hooks() +{ + // the hooks contain executable code as well, so they have to be RWX + DWORD old_protect; + VirtualProtect(g_hooks, sizeof(g_hooks), PAGE_EXECUTE_READWRITE, + &old_protect); + + hook_disable(); + + // now, hook each api :) + for (int i = 0; i < ARRAYSIZE(g_hooks); i++) { + if(g_hooks[i].allow_hook_recursion != FALSE) { + hook_api(&g_hooks[i], HOOKTYPE); + } + else { + hook_api(&g_hooks[i], HOOKTYPE); + } + } + + hook_enable(); +} + +BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved) +{ + if(dwReason == DLL_PROCESS_ATTACH) { + // make sure advapi32 is loaded + LoadLibrary("advapi32"); + + // there's a small list of processes which we don't want to inject + if(is_ignored_process()) { + return TRUE; + } + + // hide our module from peb + hide_module_from_peb(hModule); + + // obtain all protected pids + int pids[MAX_PROTECTED_PIDS], length = sizeof(pids); + pipe2(pids, &length, "GETPIDS"); + for (int i = 0; i < length / sizeof(pids[0]); i++) { + add_protected_pid(pids[i]); + } + + // initialize file stuff + file_init(); + + // read the config settings + read_config(); + g_pipe_name = g_config.pipe_name; + + // initialize the log file + log_init(g_config.host_ip, g_config.host_port, 0); + + // initialize the Sleep() skipping stuff + init_sleep_skip(g_config.first_process); + + // we skip a random given amount of milliseconds each run + init_startup_time(g_config.startup_time); + + // disable the retaddr check if the user wants so + if(g_config.retaddr_check == 0) { + hook_disable_retaddr_check(); + } + + // initialize all hooks + set_hooks(); + + // notify analyzer.py that we've loaded + char name[64]; + sprintf(name, "CuckooEvent%d", GetCurrentProcessId()); + HANDLE event_handle = OpenEvent(EVENT_ALL_ACCESS, FALSE, name); + if(event_handle != NULL) { + SetEvent(event_handle); + CloseHandle(event_handle); + } + } + else if(dwReason == DLL_PROCESS_DETACH) { + log_free(); + } + + return TRUE; +} diff --git a/distorm3.2-package/COPYING b/distorm3.2-package/COPYING new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/distorm3.2-package/COPYING @@ -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/distorm3.2-package/include/distorm.h b/distorm3.2-package/include/distorm.h new file mode 100644 index 0000000..ed073af --- /dev/null +++ b/distorm3.2-package/include/distorm.h @@ -0,0 +1,462 @@ +/* diStorm3 3.2 */ + +/* +distorm.h + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2012 Gil Dabah + +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 +*/ + + +#ifndef DISTORM_H +#define DISTORM_H + +/* + * 64 bit offsets support: + * If the diStorm library you use was compiled with 64 bits offsets, + * make sure you compile your own code with the following macro set: + * SUPPORT_64BIT_OFFSET + * Otherwise comment it out, or you will get a linker error of an unresolved symbol... + * Turned on by default! + */ + +#if !(defined(DISTORM_STATIC) || defined(DISTORM_DYNAMIC)) + /* Define this macro for outer projects by default. */ + #define SUPPORT_64BIT_OFFSET +#endif + +/* TINYC has a problem with some 64bits library functions, so ignore 64 bit offsets. */ +#ifdef __TINYC__ + #undef SUPPORT_64BIT_OFFSET +#endif + +/* If your compiler doesn't support stdint.h, define your own 64 bits type. */ +#ifdef SUPPORT_64BIT_OFFSET + #ifdef _MSC_VER + #define OFFSET_INTEGER unsigned __int64 + #else + #include + #define OFFSET_INTEGER uint64_t + #endif +#else + /* 32 bit offsets are used. */ + #define OFFSET_INTEGER unsigned long +#endif + +#ifdef _MSC_VER +/* Since MSVC isn't shipped with stdint.h, we will have our own: */ +typedef signed __int64 int64_t; +typedef unsigned __int64 uint64_t; +typedef signed __int32 int32_t; +typedef unsigned __int32 uint32_t; +typedef signed __int16 int16_t; +typedef unsigned __int16 uint16_t; +typedef signed __int8 int8_t; +typedef unsigned __int8 uint8_t; +#endif + +/* Support C++ compilers */ +#ifdef __cplusplus + extern "C" { +#endif + + +/* *** Helper Macros *** */ + +/* Get the ISC of the instruction, used with the definitions below. */ +#define META_GET_ISC(meta) (((meta) >> 3) & 0x1f) +#define META_SET_ISC(di, isc) (((di)->meta) |= ((isc) << 3)) +/* Get the flow control flags of the instruction, see 'features for decompose' below. */ +#define META_GET_FC(meta) ((meta) & 0x7) + +/* Get the target address of a branching instruction. O_PC operand type. */ +#define INSTRUCTION_GET_TARGET(di) ((_OffsetType)(((di)->addr + (di)->imm.addr + (di)->size))) +/* Get the target address of a RIP-relative memory indirection. */ +#define INSTRUCTION_GET_RIP_TARGET(di) ((_OffsetType)(((di)->addr + (di)->disp + (di)->size))) + +/* + * Operand Size or Adderss size are stored inside the flags: + * 0 - 16 bits + * 1 - 32 bits + * 2 - 64 bits + * 3 - reserved + * + * If you call these set-macros more than once, you will have to clean the bits before doing so. + */ +#define FLAG_SET_OPSIZE(di, size) ((di->flags) |= (((size) & 3) << 8)) +#define FLAG_SET_ADDRSIZE(di, size) ((di->flags) |= (((size) & 3) << 10)) +#define FLAG_GET_OPSIZE(flags) (((flags) >> 8) & 3) +#define FLAG_GET_ADDRSIZE(flags) (((flags) >> 10) & 3) +/* To get the LOCK/REPNZ/REP prefixes. */ +#define FLAG_GET_PREFIX(flags) ((flags) & 7) + +/* + * Macros to extract segment registers from 'segment': + */ +#define SEGMENT_DEFAULT 0x80 +#define SEGMENT_SET(di, seg) ((di->segment) |= seg) +#define SEGMENT_GET(segment) (((segment) == R_NONE) ? R_NONE : ((segment) & 0x7f)) +#define SEGMENT_IS_DEFAULT(segment) (((segment) & SEGMENT_DEFAULT) == SEGMENT_DEFAULT) + + +/* Decodes modes of the disassembler, 16 bits or 32 bits or 64 bits for AMD64, x86-64. */ +typedef enum { Decode16Bits = 0, Decode32Bits = 1, Decode64Bits = 2 } _DecodeType; + +typedef OFFSET_INTEGER _OffsetType; + +typedef struct { + _OffsetType codeOffset, nextOffset; /* nextOffset is OUT only. */ + const uint8_t* code; + int codeLen; /* Using signed integer makes it easier to detect an underflow. */ + _DecodeType dt; + unsigned int features; +} _CodeInfo; + +typedef enum { O_NONE, O_REG, O_IMM, O_IMM1, O_IMM2, O_DISP, O_SMEM, O_MEM, O_PC, O_PTR } _OperandType; + +typedef union { + /* Used by O_IMM: */ + int8_t sbyte; + uint8_t byte; + int16_t sword; + uint16_t word; + int32_t sdword; + uint32_t dword; + int64_t sqword; /* All immediates are SIGN-EXTENDED to 64 bits! */ + uint64_t qword; + + /* Used by O_PC: (Use GET_TARGET_ADDR).*/ + _OffsetType addr; /* It's a relative offset as for now. */ + + /* Used by O_PTR: */ + struct { + uint16_t seg; + /* Can be 16 or 32 bits, size is in ops[n].size. */ + uint32_t off; + } ptr; + + /* Used by O_IMM1 (i1) and O_IMM2 (i2). ENTER instruction only. */ + struct { + uint32_t i1; + uint32_t i2; + } ex; +} _Value; + +typedef struct { + /* Type of operand: + O_NONE: operand is to be ignored. + O_REG: index holds global register index. + O_IMM: instruction.imm. + O_IMM1: instruction.imm.ex.i1. + O_IMM2: instruction.imm.ex.i2. + O_DISP: memory dereference with displacement only, instruction.disp. + O_SMEM: simple memory dereference with optional displacement (a single register memory dereference). + O_MEM: complex memory dereference (optional fields: s/i/b/disp). + O_PC: the relative address of a branch instruction (instruction.imm.addr). + O_PTR: the absolute target address of a far branch instruction (instruction.imm.ptr.seg/off). + */ + uint8_t type; /* _OperandType */ + + /* Index of: + O_REG: holds global register index + O_SMEM: holds the 'base' register. E.G: [ECX], [EBX+0x1234] are both in operand.index. + O_MEM: holds the 'index' register. E.G: [EAX*4] is in operand.index. + */ + uint8_t index; + + /* Size of: + O_REG: register + O_IMM: instruction.imm + O_IMM1: instruction.imm.ex.i1 + O_IMM2: instruction.imm.ex.i2 + O_DISP: instruction.disp + O_SMEM: size of indirection. + O_MEM: size of indirection. + O_PC: size of the relative offset + O_PTR: size of instruction.imm.ptr.off (16 or 32) + */ + uint16_t size; +} _Operand; + +#define OPCODE_ID_NONE 0 +/* Instruction could not be disassembled. */ +#define FLAG_NOT_DECODABLE ((uint16_t)-1) +/* The instruction locks memory access. */ +#define FLAG_LOCK (1 << 0) +/* The instruction is prefixed with a REPNZ. */ +#define FLAG_REPNZ (1 << 1) +/* The instruction is prefixed with a REP, this can be a REPZ, it depends on the specific instruction. */ +#define FLAG_REP (1 << 2) +/* Indicates there is a hint taken for Jcc instructions only. */ +#define FLAG_HINT_TAKEN (1 << 3) +/* Indicates there is a hint non-taken for Jcc instructions only. */ +#define FLAG_HINT_NOT_TAKEN (1 << 4) +/* The Imm value is signed extended. */ +#define FLAG_IMM_SIGNED (1 << 5) +/* The destination operand is writable. */ +#define FLAG_DST_WR (1 << 6) +/* The instruction uses RIP-relative indirection. */ +#define FLAG_RIP_RELATIVE (1 << 7) + +/* No register was defined. */ +#define R_NONE ((uint8_t)-1) + +#define REGS64_BASE (0) +#define REGS32_BASE (16) +#define REGS16_BASE (32) +#define REGS8_BASE (48) +#define REGS8_REX_BASE (64) +#define SREGS_BASE (68) +/* #define RIP 74 */ +#define FPUREGS_BASE (75) +#define MMXREGS_BASE (83) +#define SSEREGS_BASE (91) +#define AVXREGS_BASE (107) +#define CREGS_BASE (123) +#define DREGS_BASE (132) + +#define OPERANDS_NO (4) + +typedef struct { + /* Used by ops[n].type == O_IMM/O_IMM1&O_IMM2/O_PTR/O_PC. Its size is ops[n].size. */ + _Value imm; + /* Used by ops[n].type == O_SMEM/O_MEM/O_DISP. Its size is dispSize. */ + uint64_t disp; + /* Virtual address of first byte of instruction. */ + _OffsetType addr; + /* General flags of instruction, holds prefixes and more, if FLAG_NOT_DECODABLE, instruction is invalid. */ + uint16_t flags; + /* Unused prefixes mask, for each bit that is set that prefix is not used (LSB is byte [addr + 0]). */ + uint16_t unusedPrefixesMask; + /* Mask of registers that were used in the operands, only used for quick look up, in order to know *some* operand uses that register class. */ + uint16_t usedRegistersMask; + /* ID of opcode in the global opcode table. Use for mnemonic look up. */ + uint16_t opcode; + /* Up to four operands per instruction, ignored if ops[n].type == O_NONE. */ + _Operand ops[OPERANDS_NO]; + /* Size of the whole instruction. */ + uint8_t size; + /* Segment information of memory indirection, default segment, or overriden one, can be -1. Use SEGMENT macros. */ + uint8_t segment; + /* Used by ops[n].type == O_MEM. Base global register index (might be R_NONE), scale size (2/4/8), ignored for 0 or 1. */ + uint8_t base, scale; + uint8_t dispSize; + /* Meta defines the instruction set class, and the flow control flags. Use META macros. */ + uint8_t meta; +} _DInst; + +#ifndef DISTORM_LIGHT + +/* Static size of strings. Do not change this value. Keep Python wrapper in sync. */ +#define MAX_TEXT_SIZE (48) +typedef struct { + unsigned int length; + unsigned char p[MAX_TEXT_SIZE]; /* p is a null terminated string. */ +} _WString; + +/* + * Old decoded instruction structure in text format. + * Used only for backward compatibility with diStorm64. + * This structure holds all information the disassembler generates per instruction. + */ +typedef struct { + _WString mnemonic; /* Mnemonic of decoded instruction, prefixed if required by REP, LOCK etc. */ + _WString operands; /* Operands of the decoded instruction, up to 3 operands, comma-seperated. */ + _WString instructionHex; /* Hex dump - little endian, including prefixes. */ + unsigned int size; /* Size of decoded instruction. */ + _OffsetType offset; /* Start offset of the decoded instruction. */ +} _DecodedInst; + +#endif /* DISTORM_LIGHT */ + +/* Register masks for quick look up, each mask indicates one of a register-class that is being used in some operand. */ +#define RM_AX 1 /* AL, AH, AX, EAX, RAX */ +#define RM_CX 2 /* CL, CH, CX, ECX, RCX */ +#define RM_DX 4 /* DL, DH, DX, EDX, RDX */ +#define RM_BX 8 /* BL, BH, BX, EBX, RBX */ +#define RM_SP 0x10 /* SPL, SP, ESP, RSP */ +#define RM_BP 0x20 /* BPL, BP, EBP, RBP */ +#define RM_SI 0x40 /* SIL, SI, ESI, RSI */ +#define RM_DI 0x80 /* DIL, DI, EDI, RDI */ +#define RM_FPU 0x100 /* ST(0) - ST(7) */ +#define RM_MMX 0x200 /* MM0 - MM7 */ +#define RM_SSE 0x400 /* XMM0 - XMM15 */ +#define RM_AVX 0x800 /* YMM0 - YMM15 */ +#define RM_CR 0x1000 /* CR0, CR2, CR3, CR4, CR8 */ +#define RM_DR 0x2000 /* DR0, DR1, DR2, DR3, DR6, DR7 */ +/* RIP should be checked using the 'flags' field and FLAG_RIP_RELATIVE. + * Segments should be checked using the segment macros. + * For now R8 - R15 are not supported and non general purpose registers map into same RM. + */ + +/* + * Instructions Set classes: + * if you want a better understanding of the available classes, look at disOps project, file: x86sets.py. + */ +/* Indicates the instruction belongs to the General Integer set. */ +#define ISC_INTEGER 1 +/* Indicates the instruction belongs to the 387 FPU set. */ +#define ISC_FPU 2 +/* Indicates the instruction belongs to the P6 set. */ +#define ISC_P6 3 +/* Indicates the instruction belongs to the MMX set. */ +#define ISC_MMX 4 +/* Indicates the instruction belongs to the SSE set. */ +#define ISC_SSE 5 +/* Indicates the instruction belongs to the SSE2 set. */ +#define ISC_SSE2 6 +/* Indicates the instruction belongs to the SSE3 set. */ +#define ISC_SSE3 7 +/* Indicates the instruction belongs to the SSSE3 set. */ +#define ISC_SSSE3 8 +/* Indicates the instruction belongs to the SSE4.1 set. */ +#define ISC_SSE4_1 9 +/* Indicates the instruction belongs to the SSE4.2 set. */ +#define ISC_SSE4_2 10 +/* Indicates the instruction belongs to the AMD's SSE4.A set. */ +#define ISC_SSE4_A 11 +/* Indicates the instruction belongs to the 3DNow! set. */ +#define ISC_3DNOW 12 +/* Indicates the instruction belongs to the 3DNow! Extensions set. */ +#define ISC_3DNOWEXT 13 +/* Indicates the instruction belongs to the VMX (Intel) set. */ +#define ISC_VMX 14 +/* Indicates the instruction belongs to the SVM (AMD) set. */ +#define ISC_SVM 15 +/* Indicates the instruction belongs to the AVX (Intel) set. */ +#define ISC_AVX 16 +/* Indicates the instruction belongs to the FMA (Intel) set. */ +#define ISC_FMA 17 +/* Indicates the instruction belongs to the AES/AVX (Intel) set. */ +#define ISC_AES 18 +/* Indicates the instruction belongs to the CLMUL (Intel) set. */ +#define ISC_CLMUL 19 + +/* Features for decompose: */ +#define DF_NONE 0 +/* The decoder will limit addresses to a maximum of 16 bits. */ +#define DF_MAXIMUM_ADDR16 1 +/* The decoder will limit addresses to a maximum of 32 bits. */ +#define DF_MAXIMUM_ADDR32 2 +/* The decoder will return only flow control instructions (and filter the others internally). */ +#define DF_RETURN_FC_ONLY 4 +/* The decoder will stop and return to the caller when the instruction 'CALL' (near and far) was decoded. */ +#define DF_STOP_ON_CALL 8 +/* The decoder will stop and return to the caller when the instruction 'RET' (near and far) was decoded. */ +#define DF_STOP_ON_RET 0x10 +/* The decoder will stop and return to the caller when the instruction system-call/ret was decoded. */ +#define DF_STOP_ON_SYS 0x20 +/* The decoder will stop and return to the caller when any of the branch 'JMP', (near and far) instructions were decoded. */ +#define DF_STOP_ON_UNC_BRANCH 0x40 +/* The decoder will stop and return to the caller when any of the conditional branch instruction were decoded. */ +#define DF_STOP_ON_CND_BRANCH 0x80 +/* The decoder will stop and return to the caller when the instruction 'INT' (INT, INT1, INTO, INT 3) was decoded. */ +#define DF_STOP_ON_INT 0x100 +/* The decoder will stop and return to the caller when any of the 'CMOVxx' instruction was decoded. */ +#define DF_STOP_ON_CMOV 0x200 +/* The decoder will stop and return to the caller when any flow control instruction was decoded. */ +#define DF_STOP_ON_FLOW_CONTROL (DF_STOP_ON_CALL | DF_STOP_ON_RET | DF_STOP_ON_SYS | DF_STOP_ON_UNC_BRANCH | DF_STOP_ON_CND_BRANCH | DF_STOP_ON_INT | DF_STOP_ON_CMOV) + +/* Indicates the instruction is not a flow-control instruction. */ +#define FC_NONE 0 +/* Indicates the instruction is one of: CALL, CALL FAR. */ +#define FC_CALL 1 +/* Indicates the instruction is one of: RET, IRET, RETF. */ +#define FC_RET 2 +/* Indicates the instruction is one of: SYSCALL, SYSRET, SYSENTER, SYSEXIT. */ +#define FC_SYS 3 +/* Indicates the instruction is one of: JMP, JMP FAR. */ +#define FC_UNC_BRANCH 4 +/* + * Indicates the instruction is one of: + * JCXZ, JO, JNO, JB, JAE, JZ, JNZ, JBE, JA, JS, JNS, JP, JNP, JL, JGE, JLE, JG, LOOP, LOOPZ, LOOPNZ. + */ +#define FC_CND_BRANCH 5 +/* Indiciates the instruction is one of: INT, INT1, INT 3, INTO, UD2. */ +#define FC_INT 6 +/* Indicates the instruction is one of: CMOVxx. */ +#define FC_CMOV 7 + +/* Return code of the decoding function. */ +typedef enum { DECRES_NONE, DECRES_SUCCESS, DECRES_MEMORYERR, DECRES_INPUTERR, DECRES_FILTERED } _DecodeResult; + +/* Define the following interface functions only for outer projects. */ +#if !(defined(DISTORM_STATIC) || defined(DISTORM_DYNAMIC)) + +/* distorm_decode + * Input: + * offset - Origin of the given code (virtual address that is), NOT an offset in code. + * code - Pointer to the code buffer to be disassembled. + * length - Amount of bytes that should be decoded from the code buffer. + * dt - Decoding mode, 16 bits (Decode16Bits), 32 bits (Decode32Bits) or AMD64 (Decode64Bits). + * result - Array of type _DecodeInst which will be used by this function in order to return the disassembled instructions. + * maxInstructions - The maximum number of entries in the result array that you pass to this function, so it won't exceed its bound. + * usedInstructionsCount - Number of the instruction that successfully were disassembled and written to the result array. + * Output: usedInstructionsCount will hold the number of entries used in the result array + * and the result array itself will be filled with the disassembled instructions. + * Return: DECRES_SUCCESS on success (no more to disassemble), DECRES_INPUTERR on input error (null code buffer, invalid decoding mode, etc...), + * DECRES_MEMORYERR when there are not enough entries to use in the result array, BUT YOU STILL have to check for usedInstructionsCount! + * Side-Effects: Even if the return code is DECRES_MEMORYERR, there might STILL be data in the + * array you passed, this function will try to use as much entries as possible! + * Notes: 1)The minimal size of maxInstructions is 15. + * 2)You will have to synchronize the offset,code and length by yourself if you pass code fragments and not a complete code block! + */ +#ifdef SUPPORT_64BIT_OFFSET + + _DecodeResult distorm_decompose64(_CodeInfo* ci, _DInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount); + #define distorm_decompose distorm_decompose64 + +#ifndef DISTORM_LIGHT + /* If distorm-light is defined, we won't export these text-formatting functionality. */ + _DecodeResult distorm_decode64(_OffsetType codeOffset, const unsigned char* code, int codeLen, _DecodeType dt, _DecodedInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount); + void distorm_format64(const _CodeInfo* ci, const _DInst* di, _DecodedInst* result); + #define distorm_decode distorm_decode64 + #define distorm_format distorm_format64 +#endif /*DISTORM_LIGHT*/ + +#else /*SUPPORT_64BIT_OFFSET*/ + + _DecodeResult distorm_decompose32(_CodeInfo* ci, _DInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount); + #define distorm_decompose distorm_decompose32 + +#ifndef DISTORM_LIGHT + /* If distorm-light is defined, we won't export these text-formatting functionality. */ + _DecodeResult distorm_decode32(_OffsetType codeOffset, const unsigned char* code, int codeLen, _DecodeType dt, _DecodedInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount); + void distorm_format32(const _CodeInfo* ci, const _DInst* di, _DecodedInst* result); + #define distorm_decode distorm_decode32 + #define distorm_format distorm_format32 +#endif /*DISTORM_LIGHT*/ + +#endif + +/* + * distorm_version + * Input: + * none + * + * Output: unsigned int - version of compiled library. + */ +unsigned int distorm_version(); + +#endif /* DISTORM_STATIC */ + +#ifdef __cplusplus +} /* End Of Extern */ +#endif + +#endif /* DISTORM_H */ diff --git a/distorm3.2-package/include/mnemonics.h b/distorm3.2-package/include/mnemonics.h new file mode 100644 index 0000000..652d64b --- /dev/null +++ b/distorm3.2-package/include/mnemonics.h @@ -0,0 +1,312 @@ +/* +mnemonics.h + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2012 Gil Dabah + +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 +*/ + + +#ifndef MNEMONICS_H +#define MNEMONICS_H + +#ifdef __cplusplus + extern "C" { +#endif + +#ifndef DISTORM_LIGHT + +typedef struct WMnemonic { + unsigned char length; + unsigned char p[1]; /* p is a null terminated string, which contains 'length' characters. */ +} _WMnemonic; + +typedef struct WRegister { + unsigned int length; + unsigned char p[6]; /* p is a null terminated string. */ +} _WRegister; + +extern const unsigned char _MNEMONICS[]; +extern const _WRegister _REGISTERS[]; + +#endif /* DISTORM_LIGHT */ + +#ifdef __cplusplus +} /* End Of Extern */ +#endif + +#define GET_REGISTER_NAME(r) (unsigned char*)_REGISTERS[(r)].p +#define GET_MNEMONIC_NAME(m) ((_WMnemonic*)&_MNEMONICS[(m)])->p + +typedef enum { + I_UNDEFINED = 0, I_AAA = 66, I_AAD = 389, I_AAM = 384, I_AAS = 76, I_ADC = 31, I_ADD = 11, I_ADDPD = 3110, + I_ADDPS = 3103, I_ADDSD = 3124, I_ADDSS = 3117, I_ADDSUBPD = 6394, I_ADDSUBPS = 6404, + I_AESDEC = 9209, I_AESDECLAST = 9226, I_AESENC = 9167, I_AESENCLAST = 9184, + I_AESIMC = 9150, I_AESKEYGENASSIST = 9795, I_AND = 41, I_ANDNPD = 3021, I_ANDNPS = 3013, + I_ANDPD = 2990, I_ANDPS = 2983, I_ARPL = 111, I_BLENDPD = 9372, I_BLENDPS = 9353, + I_BLENDVPD = 7619, I_BLENDVPS = 7609, I_BOUND = 104, I_BSF = 4346, I_BSR = 4358, + I_BSWAP = 960, I_BT = 872, I_BTC = 934, I_BTR = 912, I_BTS = 887, I_CALL = 456, + I_CALL_FAR = 260, I_CBW = 228, I_CDQ = 250, I_CDQE = 239, I_CLC = 492, I_CLD = 512, + I_CLFLUSH = 4329, I_CLGI = 1833, I_CLI = 502, I_CLTS = 541, I_CMC = 487, I_CMOVA = 694, + I_CMOVAE = 663, I_CMOVB = 656, I_CMOVBE = 686, I_CMOVG = 754, I_CMOVGE = 738, + I_CMOVL = 731, I_CMOVLE = 746, I_CMOVNO = 648, I_CMOVNP = 723, I_CMOVNS = 708, + I_CMOVNZ = 678, I_CMOVO = 641, I_CMOVP = 716, I_CMOVS = 701, I_CMOVZ = 671, + I_CMP = 71, I_CMPEQPD = 4449, I_CMPEQPS = 4370, I_CMPEQSD = 4607, I_CMPEQSS = 4528, + I_CMPLEPD = 4467, I_CMPLEPS = 4388, I_CMPLESD = 4625, I_CMPLESS = 4546, I_CMPLTPD = 4458, + I_CMPLTPS = 4379, I_CMPLTSD = 4616, I_CMPLTSS = 4537, I_CMPNEQPD = 4488, I_CMPNEQPS = 4409, + I_CMPNEQSD = 4646, I_CMPNEQSS = 4567, I_CMPNLEPD = 4508, I_CMPNLEPS = 4429, + I_CMPNLESD = 4666, I_CMPNLESS = 4587, I_CMPNLTPD = 4498, I_CMPNLTPS = 4419, + I_CMPNLTSD = 4656, I_CMPNLTSS = 4577, I_CMPORDPD = 4518, I_CMPORDPS = 4439, + I_CMPORDSD = 4676, I_CMPORDSS = 4597, I_CMPS = 301, I_CMPUNORDPD = 4476, I_CMPUNORDPS = 4397, + I_CMPUNORDSD = 4634, I_CMPUNORDSS = 4555, I_CMPXCHG = 898, I_CMPXCHG16B = 6373, + I_CMPXCHG8B = 6362, I_COMISD = 2779, I_COMISS = 2771, I_CPUID = 865, I_CQO = 255, + I_CRC32 = 9258, I_CVTDQ2PD = 6787, I_CVTDQ2PS = 3307, I_CVTPD2DQ = 6797, I_CVTPD2PI = 2681, + I_CVTPD2PS = 3233, I_CVTPH2PS = 4161, I_CVTPI2PD = 2495, I_CVTPI2PS = 2485, + I_CVTPS2DQ = 3317, I_CVTPS2PD = 3223, I_CVTPS2PH = 4171, I_CVTPS2PI = 2671, + I_CVTSD2SI = 2701, I_CVTSD2SS = 3253, I_CVTSI2SD = 2515, I_CVTSI2SS = 2505, + I_CVTSS2SD = 3243, I_CVTSS2SI = 2691, I_CVTTPD2DQ = 6776, I_CVTTPD2PI = 2614, + I_CVTTPS2DQ = 3327, I_CVTTPS2PI = 2603, I_CVTTSD2SI = 2636, I_CVTTSS2SI = 2625, + I_CWD = 245, I_CWDE = 233, I_DAA = 46, I_DAS = 56, I_DEC = 86, I_DIV = 1630, + I_DIVPD = 3499, I_DIVPS = 3492, I_DIVSD = 3513, I_DIVSS = 3506, I_DPPD = 9615, + I_DPPS = 9602, I_EMMS = 4100, I_ENTER = 340, I_EXTRACTPS = 9480, I_EXTRQ = 4136, + I_F2XM1 = 1176, I_FABS = 1107, I_FADD = 1007, I_FADDP = 1533, I_FBLD = 1585, + I_FBSTP = 1591, I_FCHS = 1101, I_FCLEX = 7289, I_FCMOVB = 1360, I_FCMOVBE = 1376, + I_FCMOVE = 1368, I_FCMOVNB = 1429, I_FCMOVNBE = 1447, I_FCMOVNE = 1438, I_FCMOVNU = 1457, + I_FCMOVU = 1385, I_FCOM = 1019, I_FCOMI = 1496, I_FCOMIP = 1607, I_FCOMP = 1025, + I_FCOMPP = 1547, I_FCOS = 1295, I_FDECSTP = 1222, I_FDIV = 1045, I_FDIVP = 1578, + I_FDIVR = 1051, I_FDIVRP = 1570, I_FEDISI = 1472, I_FEMMS = 574, I_FENI = 1466, + I_FFREE = 1511, I_FIADD = 1301, I_FICOM = 1315, I_FICOMP = 1322, I_FIDIV = 1345, + I_FIDIVR = 1352, I_FILD = 1402, I_FIMUL = 1308, I_FINCSTP = 1231, I_FINIT = 7304, + I_FIST = 1416, I_FISTP = 1422, I_FISTTP = 1408, I_FISUB = 1330, I_FISUBR = 1337, + I_FLD = 1058, I_FLD1 = 1125, I_FLDCW = 1082, I_FLDENV = 1074, I_FLDL2E = 1139, + I_FLDL2T = 1131, I_FLDLG2 = 1154, I_FLDLN2 = 1162, I_FLDPI = 1147, I_FLDZ = 1170, + I_FMUL = 1013, I_FMULP = 1540, I_FNCLEX = 7281, I_FNINIT = 7296, I_FNOP = 1095, + I_FNSAVE = 7311, I_FNSTCW = 7266, I_FNSTENV = 7249, I_FNSTSW = 7326, I_FPATAN = 1197, + I_FPREM = 1240, I_FPREM1 = 1214, I_FPTAN = 1190, I_FRNDINT = 1272, I_FRSTOR = 1503, + I_FSAVE = 7319, I_FSCALE = 1281, I_FSETPM = 1480, I_FSIN = 1289, I_FSINCOS = 1263, + I_FSQRT = 1256, I_FST = 1063, I_FSTCW = 7274, I_FSTENV = 7258, I_FSTP = 1068, + I_FSTSW = 7334, I_FSUB = 1032, I_FSUBP = 1563, I_FSUBR = 1038, I_FSUBRP = 1555, + I_FTST = 1113, I_FUCOM = 1518, I_FUCOMI = 1488, I_FUCOMIP = 1598, I_FUCOMP = 1525, + I_FUCOMPP = 1393, I_FXAM = 1119, I_FXCH = 1089, I_FXRSTOR = 9892, I_FXRSTOR64 = 9901, + I_FXSAVE = 9864, I_FXSAVE64 = 9872, I_FXTRACT = 1205, I_FYL2X = 1183, I_FYL2XP1 = 1247, + I_GETSEC = 633, I_HADDPD = 4181, I_HADDPS = 4189, I_HLT = 482, I_HSUBPD = 4215, + I_HSUBPS = 4223, I_IDIV = 1635, I_IMUL = 117, I_IN = 447, I_INC = 81, I_INS = 123, + I_INSERTPS = 9547, I_INSERTQ = 4143, I_INT = 367, I_INT_3 = 360, I_INT1 = 476, + I_INTO = 372, I_INVD = 555, I_INVEPT = 8284, I_INVLPG = 1711, I_INVLPGA = 1847, + I_INVPCID = 8301, I_INVVPID = 8292, I_IRET = 378, I_JA = 166, I_JAE = 147, + I_JB = 143, I_JBE = 161, I_JCXZ = 427, I_JECXZ = 433, I_JG = 202, I_JGE = 192, + I_JL = 188, I_JLE = 197, I_JMP = 462, I_JMP_FAR = 467, I_JNO = 138, I_JNP = 183, + I_JNS = 174, I_JNZ = 156, I_JO = 134, I_JP = 179, I_JRCXZ = 440, I_JS = 170, + I_JZ = 152, I_LAHF = 289, I_LAR = 522, I_LDDQU = 6994, I_LDMXCSR = 9922, I_LDS = 335, + I_LEA = 223, I_LEAVE = 347, I_LES = 330, I_LFENCE = 4265, I_LFS = 917, I_LGDT = 1687, + I_LGS = 922, I_LIDT = 1693, I_LLDT = 1652, I_LMSW = 1705, I_LODS = 313, I_LOOP = 421, + I_LOOPNZ = 406, I_LOOPZ = 414, I_LSL = 527, I_LSS = 907, I_LTR = 1658, I_LZCNT = 4363, + I_MASKMOVDQU = 7119, I_MASKMOVQ = 7109, I_MAXPD = 3559, I_MAXPS = 3552, I_MAXSD = 3573, + I_MAXSS = 3566, I_MFENCE = 4291, I_MINPD = 3439, I_MINPS = 3432, I_MINSD = 3453, + I_MINSS = 3446, I_MONITOR = 1755, I_MOV = 218, I_MOVAPD = 2459, I_MOVAPS = 2451, + I_MOVBE = 9251, I_MOVD = 3920, I_MOVDDUP = 2186, I_MOVDQ2Q = 6522, I_MOVDQA = 3946, + I_MOVDQU = 3954, I_MOVHLPS = 2151, I_MOVHPD = 2345, I_MOVHPS = 2337, I_MOVLHPS = 2328, + I_MOVLPD = 2168, I_MOVLPS = 2160, I_MOVMSKPD = 2815, I_MOVMSKPS = 2805, I_MOVNTDQ = 6849, + I_MOVNTDQA = 7895, I_MOVNTI = 952, I_MOVNTPD = 2556, I_MOVNTPS = 2547, I_MOVNTQ = 6841, + I_MOVNTSD = 2574, I_MOVNTSS = 2565, I_MOVQ = 3926, I_MOVQ2DQ = 6513, I_MOVS = 295, + I_MOVSD = 2110, I_MOVSHDUP = 2353, I_MOVSLDUP = 2176, I_MOVSS = 2103, I_MOVSX = 939, + I_MOVSXD = 10019, I_MOVUPD = 2095, I_MOVUPS = 2087, I_MOVZX = 927, I_MPSADBW = 9628, + I_MUL = 1625, I_MULPD = 3170, I_MULPS = 3163, I_MULSD = 3184, I_MULSS = 3177, + I_MWAIT = 1764, I_NEG = 1620, I_NOP = 581, I_NOT = 1615, I_OR = 27, I_ORPD = 3053, + I_ORPS = 3047, I_OUT = 451, I_OUTS = 128, I_PABSB = 7688, I_PABSD = 7718, I_PABSW = 7703, + I_PACKSSDW = 3849, I_PACKSSWB = 3681, I_PACKUSDW = 7916, I_PACKUSWB = 3759, + I_PADDB = 7204, I_PADDD = 7234, I_PADDQ = 6481, I_PADDSB = 6930, I_PADDSW = 6947, + I_PADDUSB = 6620, I_PADDUSW = 6639, I_PADDW = 7219, I_PALIGNR = 9410, I_PAND = 6607, + I_PANDN = 6665, I_PAUSE = 10027, I_PAVGB = 6680, I_PAVGUSB = 2078, I_PAVGW = 6725, + I_PBLENDVB = 7599, I_PBLENDW = 9391, I_PCLMULQDQ = 9647, I_PCMPEQB = 4043, + I_PCMPEQD = 4081, I_PCMPEQQ = 7876, I_PCMPEQW = 4062, I_PCMPESTRI = 9726, + I_PCMPESTRM = 9703, I_PCMPGTB = 3702, I_PCMPGTD = 3740, I_PCMPGTQ = 8087, + I_PCMPGTW = 3721, I_PCMPISTRI = 9772, I_PCMPISTRM = 9749, I_PEXTRB = 9429, + I_PEXTRD = 9446, I_PEXTRQ = 9454, I_PEXTRW = 6311, I_PF2ID = 1914, I_PF2IW = 1907, + I_PFACC = 2028, I_PFADD = 1977, I_PFCMPEQ = 2035, I_PFCMPGE = 1938, I_PFCMPGT = 1984, + I_PFMAX = 1993, I_PFMIN = 1947, I_PFMUL = 2044, I_PFNACC = 1921, I_PFPNACC = 1929, + I_PFRCP = 1954, I_PFRCPIT1 = 2000, I_PFRCPIT2 = 2051, I_PFRSQIT1 = 2010, I_PFRSQRT = 1961, + I_PFSUB = 1970, I_PFSUBR = 2020, I_PHADDD = 7375, I_PHADDSW = 7392, I_PHADDW = 7358, + I_PHMINPOSUW = 8259, I_PHSUBD = 7451, I_PHSUBSW = 7468, I_PHSUBW = 7434, I_PI2FD = 1900, + I_PI2FW = 1893, I_PINSRB = 9530, I_PINSRD = 9568, I_PINSRQ = 9576, I_PINSRW = 6294, + I_PMADDUBSW = 7411, I_PMADDWD = 7073, I_PMAXSB = 8174, I_PMAXSD = 8191, I_PMAXSW = 6964, + I_PMAXUB = 6648, I_PMAXUD = 8225, I_PMAXUW = 8208, I_PMINSB = 8106, I_PMINSD = 8123, + I_PMINSW = 6902, I_PMINUB = 6590, I_PMINUD = 8157, I_PMINUW = 8140, I_PMOVMSKB = 6531, + I_PMOVSXBD = 7754, I_PMOVSXBQ = 7775, I_PMOVSXBW = 7733, I_PMOVSXDQ = 7838, + I_PMOVSXWD = 7796, I_PMOVSXWQ = 7817, I_PMOVZXBD = 7982, I_PMOVZXBQ = 8003, + I_PMOVZXBW = 7961, I_PMOVZXDQ = 8066, I_PMOVZXWD = 8024, I_PMOVZXWQ = 8045, + I_PMULDQ = 7859, I_PMULHRSW = 7538, I_PMULHRW = 2061, I_PMULHUW = 6740, I_PMULHW = 6759, + I_PMULLD = 8242, I_PMULLW = 6496, I_PMULUDQ = 7054, I_POP = 22, I_POPA = 98, + I_POPCNT = 4338, I_POPF = 277, I_POR = 6919, I_PREFETCH = 1872, I_PREFETCHNTA = 2402, + I_PREFETCHT0 = 2415, I_PREFETCHT1 = 2427, I_PREFETCHT2 = 2439, I_PREFETCHW = 1882, + I_PSADBW = 7092, I_PSHUFB = 7341, I_PSHUFD = 3988, I_PSHUFHW = 3996, I_PSHUFLW = 4005, + I_PSHUFW = 3980, I_PSIGNB = 7487, I_PSIGND = 7521, I_PSIGNW = 7504, I_PSLLD = 7024, + I_PSLLDQ = 9847, I_PSLLQ = 7039, I_PSLLW = 7009, I_PSRAD = 6710, I_PSRAW = 6695, + I_PSRLD = 6451, I_PSRLDQ = 9830, I_PSRLQ = 6466, I_PSRLW = 6436, I_PSUBB = 7144, + I_PSUBD = 7174, I_PSUBQ = 7189, I_PSUBSB = 6868, I_PSUBSW = 6885, I_PSUBUSB = 6552, + I_PSUBUSW = 6571, I_PSUBW = 7159, I_PSWAPD = 2070, I_PTEST = 7629, I_PUNPCKHBW = 3780, + I_PUNPCKHDQ = 3826, I_PUNPCKHQDQ = 3895, I_PUNPCKHWD = 3803, I_PUNPCKLBW = 3612, + I_PUNPCKLDQ = 3658, I_PUNPCKLQDQ = 3870, I_PUNPCKLWD = 3635, I_PUSH = 16, + I_PUSHA = 91, I_PUSHF = 270, I_PXOR = 6981, I_RCL = 977, I_RCPPS = 2953, I_RCPSS = 2960, + I_RCR = 982, I_RDFSBASE = 9882, I_RDGSBASE = 9912, I_RDMSR = 600, I_RDPMC = 607, + I_RDRAND = 9980, I_RDTSC = 593, I_RDTSCP = 1864, I_RET = 325, I_RETF = 354, + I_ROL = 967, I_ROR = 972, I_ROUNDPD = 9296, I_ROUNDPS = 9277, I_ROUNDSD = 9334, + I_ROUNDSS = 9315, I_RSM = 882, I_RSQRTPS = 2915, I_RSQRTSS = 2924, I_SAHF = 283, + I_SAL = 997, I_SALC = 394, I_SAR = 1002, I_SBB = 36, I_SCAS = 319, I_SETA = 807, + I_SETAE = 780, I_SETB = 774, I_SETBE = 800, I_SETG = 859, I_SETGE = 845, I_SETL = 839, + I_SETLE = 852, I_SETNO = 767, I_SETNP = 832, I_SETNS = 819, I_SETNZ = 793, + I_SETO = 761, I_SETP = 826, I_SETS = 813, I_SETZ = 787, I_SFENCE = 4321, I_SGDT = 1675, + I_SHL = 987, I_SHLD = 876, I_SHR = 992, I_SHRD = 892, I_SHUFPD = 6336, I_SHUFPS = 6328, + I_SIDT = 1681, I_SKINIT = 1839, I_SLDT = 1641, I_SMSW = 1699, I_SQRTPD = 2855, + I_SQRTPS = 2847, I_SQRTSD = 2871, I_SQRTSS = 2863, I_STC = 497, I_STD = 517, + I_STGI = 1827, I_STI = 507, I_STMXCSR = 9951, I_STOS = 307, I_STR = 1647, I_SUB = 51, + I_SUBPD = 3379, I_SUBPS = 3372, I_SUBSD = 3393, I_SUBSS = 3386, I_SWAPGS = 1856, + I_SYSCALL = 532, I_SYSENTER = 614, I_SYSEXIT = 624, I_SYSRET = 547, I_TEST = 206, + I_TZCNT = 4351, I_UCOMISD = 2742, I_UCOMISS = 2733, I_UD2 = 569, I_UNPCKHPD = 2296, + I_UNPCKHPS = 2286, I_UNPCKLPD = 2254, I_UNPCKLPS = 2244, I_VADDPD = 3139, + I_VADDPS = 3131, I_VADDSD = 3155, I_VADDSS = 3147, I_VADDSUBPD = 6414, I_VADDSUBPS = 6425, + I_VAESDEC = 9217, I_VAESDECLAST = 9238, I_VAESENC = 9175, I_VAESENCLAST = 9196, + I_VAESIMC = 9158, I_VAESKEYGENASSIST = 9812, I_VANDNPD = 3038, I_VANDNPS = 3029, + I_VANDPD = 3005, I_VANDPS = 2997, I_VBLENDPD = 9381, I_VBLENDPS = 9362, I_VBLENDVPD = 9681, + I_VBLENDVPS = 9670, I_VBROADCASTF128 = 7672, I_VBROADCASTSD = 7658, I_VBROADCASTSS = 7644, + I_VCMPEQPD = 5088, I_VCMPEQPS = 4686, I_VCMPEQSD = 5892, I_VCMPEQSS = 5490, + I_VCMPEQ_OSPD = 5269, I_VCMPEQ_OSPS = 4867, I_VCMPEQ_OSSD = 6073, I_VCMPEQ_OSSS = 5671, + I_VCMPEQ_UQPD = 5175, I_VCMPEQ_UQPS = 4773, I_VCMPEQ_UQSD = 5979, I_VCMPEQ_UQSS = 5577, + I_VCMPEQ_USPD = 5378, I_VCMPEQ_USPS = 4976, I_VCMPEQ_USSD = 6182, I_VCMPEQ_USSS = 5780, + I_VCMPFALSEPD = 5210, I_VCMPFALSEPS = 4808, I_VCMPFALSESD = 6014, I_VCMPFALSESS = 5612, + I_VCMPFALSE_OSPD = 5419, I_VCMPFALSE_OSPS = 5017, I_VCMPFALSE_OSSD = 6223, + I_VCMPFALSE_OSSS = 5821, I_VCMPGEPD = 5237, I_VCMPGEPS = 4835, I_VCMPGESD = 6041, + I_VCMPGESS = 5639, I_VCMPGE_OQPD = 5449, I_VCMPGE_OQPS = 5047, I_VCMPGE_OQSD = 6253, + I_VCMPGE_OQSS = 5851, I_VCMPGTPD = 5247, I_VCMPGTPS = 4845, I_VCMPGTSD = 6051, + I_VCMPGTSS = 5649, I_VCMPGT_OQPD = 5462, I_VCMPGT_OQPS = 5060, I_VCMPGT_OQSD = 6266, + I_VCMPGT_OQSS = 5864, I_VCMPLEPD = 5108, I_VCMPLEPS = 4706, I_VCMPLESD = 5912, + I_VCMPLESS = 5510, I_VCMPLE_OQPD = 5295, I_VCMPLE_OQPS = 4893, I_VCMPLE_OQSD = 6099, + I_VCMPLE_OQSS = 5697, I_VCMPLTPD = 5098, I_VCMPLTPS = 4696, I_VCMPLTSD = 5902, + I_VCMPLTSS = 5500, I_VCMPLT_OQPD = 5282, I_VCMPLT_OQPS = 4880, I_VCMPLT_OQSD = 6086, + I_VCMPLT_OQSS = 5684, I_VCMPNEQPD = 5131, I_VCMPNEQPS = 4729, I_VCMPNEQSD = 5935, + I_VCMPNEQSS = 5533, I_VCMPNEQ_OQPD = 5223, I_VCMPNEQ_OQPS = 4821, I_VCMPNEQ_OQSD = 6027, + I_VCMPNEQ_OQSS = 5625, I_VCMPNEQ_OSPD = 5435, I_VCMPNEQ_OSPS = 5033, I_VCMPNEQ_OSSD = 6239, + I_VCMPNEQ_OSSS = 5837, I_VCMPNEQ_USPD = 5323, I_VCMPNEQ_USPS = 4921, I_VCMPNEQ_USSD = 6127, + I_VCMPNEQ_USSS = 5725, I_VCMPNGEPD = 5188, I_VCMPNGEPS = 4786, I_VCMPNGESD = 5992, + I_VCMPNGESS = 5590, I_VCMPNGE_UQPD = 5391, I_VCMPNGE_UQPS = 4989, I_VCMPNGE_UQSD = 6195, + I_VCMPNGE_UQSS = 5793, I_VCMPNGTPD = 5199, I_VCMPNGTPS = 4797, I_VCMPNGTSD = 6003, + I_VCMPNGTSS = 5601, I_VCMPNGT_UQPD = 5405, I_VCMPNGT_UQPS = 5003, I_VCMPNGT_UQSD = 6209, + I_VCMPNGT_UQSS = 5807, I_VCMPNLEPD = 5153, I_VCMPNLEPS = 4751, I_VCMPNLESD = 5957, + I_VCMPNLESS = 5555, I_VCMPNLE_UQPD = 5351, I_VCMPNLE_UQPS = 4949, I_VCMPNLE_UQSD = 6155, + I_VCMPNLE_UQSS = 5753, I_VCMPNLTPD = 5142, I_VCMPNLTPS = 4740, I_VCMPNLTSD = 5946, + I_VCMPNLTSS = 5544, I_VCMPNLT_UQPD = 5337, I_VCMPNLT_UQPS = 4935, I_VCMPNLT_UQSD = 6141, + I_VCMPNLT_UQSS = 5739, I_VCMPORDPD = 5164, I_VCMPORDPS = 4762, I_VCMPORDSD = 5968, + I_VCMPORDSS = 5566, I_VCMPORD_SPD = 5365, I_VCMPORD_SPS = 4963, I_VCMPORD_SSD = 6169, + I_VCMPORD_SSS = 5767, I_VCMPTRUEPD = 5257, I_VCMPTRUEPS = 4855, I_VCMPTRUESD = 6061, + I_VCMPTRUESS = 5659, I_VCMPTRUE_USPD = 5475, I_VCMPTRUE_USPS = 5073, I_VCMPTRUE_USSD = 6279, + I_VCMPTRUE_USSS = 5877, I_VCMPUNORDPD = 5118, I_VCMPUNORDPS = 4716, I_VCMPUNORDSD = 5922, + I_VCMPUNORDSS = 5520, I_VCMPUNORD_SPD = 5308, I_VCMPUNORD_SPS = 4906, I_VCMPUNORD_SSD = 6112, + I_VCMPUNORD_SSS = 5710, I_VCOMISD = 2796, I_VCOMISS = 2787, I_VCVTDQ2PD = 6819, + I_VCVTDQ2PS = 3338, I_VCVTPD2DQ = 6830, I_VCVTPD2PS = 3274, I_VCVTPS2DQ = 3349, + I_VCVTPS2PD = 3263, I_VCVTSD2SI = 2722, I_VCVTSD2SS = 3296, I_VCVTSI2SD = 2536, + I_VCVTSI2SS = 2525, I_VCVTSS2SD = 3285, I_VCVTSS2SI = 2711, I_VCVTTPD2DQ = 6807, + I_VCVTTPS2DQ = 3360, I_VCVTTSD2SI = 2659, I_VCVTTSS2SI = 2647, I_VDIVPD = 3528, + I_VDIVPS = 3520, I_VDIVSD = 3544, I_VDIVSS = 3536, I_VDPPD = 9621, I_VDPPS = 9608, + I_VERR = 1663, I_VERW = 1669, I_VEXTRACTF128 = 9516, I_VEXTRACTPS = 9491, + I_VFMADD132PD = 8387, I_VFMADD132PS = 8374, I_VFMADD132SD = 8413, I_VFMADD132SS = 8400, + I_VFMADD213PD = 8667, I_VFMADD213PS = 8654, I_VFMADD213SD = 8693, I_VFMADD213SS = 8680, + I_VFMADD231PD = 8947, I_VFMADD231PS = 8934, I_VFMADD231SD = 8973, I_VFMADD231SS = 8960, + I_VFMADDSUB132PD = 8326, I_VFMADDSUB132PS = 8310, I_VFMADDSUB213PD = 8606, + I_VFMADDSUB213PS = 8590, I_VFMADDSUB231PD = 8886, I_VFMADDSUB231PS = 8870, + I_VFMSUB132PD = 8439, I_VFMSUB132PS = 8426, I_VFMSUB132SD = 8465, I_VFMSUB132SS = 8452, + I_VFMSUB213PD = 8719, I_VFMSUB213PS = 8706, I_VFMSUB213SD = 8745, I_VFMSUB213SS = 8732, + I_VFMSUB231PD = 8999, I_VFMSUB231PS = 8986, I_VFMSUB231SD = 9025, I_VFMSUB231SS = 9012, + I_VFMSUBADD132PD = 8358, I_VFMSUBADD132PS = 8342, I_VFMSUBADD213PD = 8638, + I_VFMSUBADD213PS = 8622, I_VFMSUBADD231PD = 8918, I_VFMSUBADD231PS = 8902, + I_VFNMADD132PD = 8492, I_VFNMADD132PS = 8478, I_VFNMADD132SD = 8520, I_VFNMADD132SS = 8506, + I_VFNMADD213PD = 8772, I_VFNMADD213PS = 8758, I_VFNMADD213SD = 8800, I_VFNMADD213SS = 8786, + I_VFNMADD231PD = 9052, I_VFNMADD231PS = 9038, I_VFNMADD231SD = 9080, I_VFNMADD231SS = 9066, + I_VFNMSUB132PD = 8548, I_VFNMSUB132PS = 8534, I_VFNMSUB132SD = 8576, I_VFNMSUB132SS = 8562, + I_VFNMSUB213PD = 8828, I_VFNMSUB213PS = 8814, I_VFNMSUB213SD = 8856, I_VFNMSUB213SS = 8842, + I_VFNMSUB231PD = 9108, I_VFNMSUB231PS = 9094, I_VFNMSUB231SD = 9136, I_VFNMSUB231SS = 9122, + I_VHADDPD = 4197, I_VHADDPS = 4206, I_VHSUBPD = 4231, I_VHSUBPS = 4240, I_VINSERTF128 = 9503, + I_VINSERTPS = 9557, I_VLDDQU = 7001, I_VLDMXCSR = 9941, I_VMASKMOVDQU = 7131, + I_VMASKMOVPD = 7949, I_VMASKMOVPS = 7937, I_VMAXPD = 3588, I_VMAXPS = 3580, + I_VMAXSD = 3604, I_VMAXSS = 3596, I_VMCALL = 1719, I_VMCLEAR = 9997, I_VMFUNC = 1787, + I_VMINPD = 3468, I_VMINPS = 3460, I_VMINSD = 3484, I_VMINSS = 3476, I_VMLAUNCH = 1727, + I_VMLOAD = 1811, I_VMMCALL = 1802, I_VMOVAPD = 2476, I_VMOVAPS = 2467, I_VMOVD = 3932, + I_VMOVDDUP = 2234, I_VMOVDQA = 3962, I_VMOVDQU = 3971, I_VMOVHLPS = 2195, + I_VMOVHPD = 2382, I_VMOVHPS = 2373, I_VMOVLHPS = 2363, I_VMOVLPD = 2214, I_VMOVLPS = 2205, + I_VMOVMSKPD = 2836, I_VMOVMSKPS = 2825, I_VMOVNTDQ = 6858, I_VMOVNTDQA = 7905, + I_VMOVNTPD = 2593, I_VMOVNTPS = 2583, I_VMOVQ = 3939, I_VMOVSD = 2143, I_VMOVSHDUP = 2391, + I_VMOVSLDUP = 2223, I_VMOVSS = 2135, I_VMOVUPD = 2126, I_VMOVUPS = 2117, I_VMPSADBW = 9637, + I_VMPTRLD = 9988, I_VMPTRST = 6385, I_VMREAD = 4128, I_VMRESUME = 1737, I_VMRUN = 1795, + I_VMSAVE = 1819, I_VMULPD = 3199, I_VMULPS = 3191, I_VMULSD = 3215, I_VMULSS = 3207, + I_VMWRITE = 4152, I_VMXOFF = 1747, I_VMXON = 10006, I_VORPD = 3066, I_VORPS = 3059, + I_VPABSB = 7695, I_VPABSD = 7725, I_VPABSW = 7710, I_VPACKSSDW = 3859, I_VPACKSSWB = 3691, + I_VPACKUSDW = 7926, I_VPACKUSWB = 3769, I_VPADDB = 7211, I_VPADDD = 7241, + I_VPADDQ = 6488, I_VPADDSB = 6938, I_VPADDSW = 6955, I_VPADDUSW = 6629, I_VPADDW = 7226, + I_VPALIGNR = 9419, I_VPAND = 6613, I_VPANDN = 6672, I_VPAVGB = 6687, I_VPAVGW = 6732, + I_VPBLENDVB = 9692, I_VPBLENDW = 9400, I_VPCLMULQDQ = 9658, I_VPCMPEQB = 4052, + I_VPCMPEQD = 4090, I_VPCMPEQQ = 7885, I_VPCMPEQW = 4071, I_VPCMPESTRI = 9737, + I_VPCMPESTRM = 9714, I_VPCMPGTB = 3711, I_VPCMPGTD = 3749, I_VPCMPGTQ = 8096, + I_VPCMPGTW = 3730, I_VPCMPISTRI = 9783, I_VPCMPISTRM = 9760, I_VPERM2F128 = 9265, + I_VPERMILPD = 7570, I_VPERMILPS = 7559, I_VPEXTRB = 9437, I_VPEXTRD = 9462, + I_VPEXTRQ = 9471, I_VPEXTRW = 6319, I_VPHADDD = 7383, I_VPHADDSW = 7401, I_VPHADDW = 7366, + I_VPHMINPOSUW = 8271, I_VPHSUBD = 7459, I_VPHSUBSW = 7477, I_VPHSUBW = 7442, + I_VPINSRB = 9538, I_VPINSRD = 9584, I_VPINSRQ = 9593, I_VPINSRW = 6302, I_VPMADDUBSW = 7422, + I_VPMADDWD = 7082, I_VPMAXSB = 8182, I_VPMAXSD = 8199, I_VPMAXSW = 6972, I_VPMAXUB = 6656, + I_VPMAXUD = 8233, I_VPMAXUW = 8216, I_VPMINSB = 8114, I_VPMINSD = 8131, I_VPMINSW = 6910, + I_VPMINUB = 6598, I_VPMINUD = 8165, I_VPMINUW = 8148, I_VPMOVMSKB = 6541, + I_VPMOVSXBD = 7764, I_VPMOVSXBQ = 7785, I_VPMOVSXBW = 7743, I_VPMOVSXDQ = 7848, + I_VPMOVSXWD = 7806, I_VPMOVSXWQ = 7827, I_VPMOVZXBD = 7992, I_VPMOVZXBQ = 8013, + I_VPMOVZXBW = 7971, I_VPMOVZXDQ = 8076, I_VPMOVZXWD = 8034, I_VPMOVZXWQ = 8055, + I_VPMULDQ = 7867, I_VPMULHRSW = 7548, I_VPMULHUW = 6749, I_VPMULHW = 6767, + I_VPMULLD = 8250, I_VPMULLW = 6504, I_VPMULUDQ = 7063, I_VPOR = 6924, I_VPSADBW = 7100, + I_VPSHUFB = 7349, I_VPSHUFD = 4014, I_VPSHUFHW = 4023, I_VPSHUFLW = 4033, + I_VPSIGNB = 7495, I_VPSIGND = 7529, I_VPSIGNW = 7512, I_VPSLLD = 7031, I_VPSLLDQ = 9855, + I_VPSLLQ = 7046, I_VPSLLW = 7016, I_VPSRAD = 6717, I_VPSRAW = 6702, I_VPSRLD = 6458, + I_VPSRLDQ = 9838, I_VPSRLQ = 6473, I_VPSRLW = 6443, I_VPSUBB = 7151, I_VPSUBD = 7181, + I_VPSUBQ = 7196, I_VPSUBSB = 6876, I_VPSUBSW = 6893, I_VPSUBUSB = 6561, I_VPSUBUSW = 6580, + I_VPSUBW = 7166, I_VPTEST = 7636, I_VPUNPCKHBW = 3791, I_VPUNPCKHDQ = 3837, + I_VPUNPCKHQDQ = 3907, I_VPUNPCKHWD = 3814, I_VPUNPCKLBW = 3623, I_VPUNPCKLDQ = 3669, + I_VPUNPCKLQDQ = 3882, I_VPUNPCKLWD = 3646, I_VPXOR = 6987, I_VRCPPS = 2967, + I_VRCPSS = 2975, I_VROUNDPD = 9305, I_VROUNDPS = 9286, I_VROUNDSD = 9343, + I_VROUNDSS = 9324, I_VRSQRTPS = 2933, I_VRSQRTSS = 2943, I_VSHUFPD = 6353, + I_VSHUFPS = 6344, I_VSQRTPD = 2888, I_VSQRTPS = 2879, I_VSQRTSD = 2906, I_VSQRTSS = 2897, + I_VSTMXCSR = 9970, I_VSUBPD = 3408, I_VSUBPS = 3400, I_VSUBSD = 3424, I_VSUBSS = 3416, + I_VTESTPD = 7590, I_VTESTPS = 7581, I_VUCOMISD = 2761, I_VUCOMISS = 2751, + I_VUNPCKHPD = 2317, I_VUNPCKHPS = 2306, I_VUNPCKLPD = 2275, I_VUNPCKLPS = 2264, + I_VXORPD = 3095, I_VXORPS = 3087, I_VZEROALL = 4118, I_VZEROUPPER = 4106, + I_WAIT = 10013, I_WBINVD = 561, I_WRFSBASE = 9931, I_WRGSBASE = 9960, I_WRMSR = 586, + I_XADD = 946, I_XCHG = 212, I_XGETBV = 1771, I_XLAT = 400, I_XOR = 61, I_XORPD = 3080, + I_XORPS = 3073, I_XRSTOR = 4273, I_XRSTOR64 = 4281, I_XSAVE = 4249, I_XSAVE64 = 4256, + I_XSAVEOPT = 4299, I_XSAVEOPT64 = 4309, I_XSETBV = 1779 +} _InstructionType; + +typedef enum { + R_RAX, R_RCX, R_RDX, R_RBX, R_RSP, R_RBP, R_RSI, R_RDI, R_R8, R_R9, R_R10, R_R11, R_R12, R_R13, R_R14, R_R15, + R_EAX, R_ECX, R_EDX, R_EBX, R_ESP, R_EBP, R_ESI, R_EDI, R_R8D, R_R9D, R_R10D, R_R11D, R_R12D, R_R13D, R_R14D, R_R15D, + R_AX, R_CX, R_DX, R_BX, R_SP, R_BP, R_SI, R_DI, R_R8W, R_R9W, R_R10W, R_R11W, R_R12W, R_R13W, R_R14W, R_R15W, + R_AL, R_CL, R_DL, R_BL, R_AH, R_CH, R_DH, R_BH, R_R8B, R_R9B, R_R10B, R_R11B, R_R12B, R_R13B, R_R14B, R_R15B, + R_SPL, R_BPL, R_SIL, R_DIL, + R_ES, R_CS, R_SS, R_DS, R_FS, R_GS, + R_RIP, + R_ST0, R_ST1, R_ST2, R_ST3, R_ST4, R_ST5, R_ST6, R_ST7, + R_MM0, R_MM1, R_MM2, R_MM3, R_MM4, R_MM5, R_MM6, R_MM7, + R_XMM0, R_XMM1, R_XMM2, R_XMM3, R_XMM4, R_XMM5, R_XMM6, R_XMM7, R_XMM8, R_XMM9, R_XMM10, R_XMM11, R_XMM12, R_XMM13, R_XMM14, R_XMM15, + R_YMM0, R_YMM1, R_YMM2, R_YMM3, R_YMM4, R_YMM5, R_YMM6, R_YMM7, R_YMM8, R_YMM9, R_YMM10, R_YMM11, R_YMM12, R_YMM13, R_YMM14, R_YMM15, + R_CR0, R_UNUSED0, R_CR2, R_CR3, R_CR4, R_UNUSED1, R_UNUSED2, R_UNUSED3, R_CR8, + R_DR0, R_DR1, R_DR2, R_DR3, R_UNUSED4, R_UNUSED5, R_DR6, R_DR7 +} _RegisterType; + +#endif /* MNEMONICS_H */ diff --git a/distorm3.2-package/src/config.h b/distorm3.2-package/src/config.h new file mode 100644 index 0000000..30f7d39 --- /dev/null +++ b/distorm3.2-package/src/config.h @@ -0,0 +1,181 @@ +/* +config.h + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2012 Gil Dabah + +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 +*/ + + +#ifndef CONFIG_H +#define CONFIG_H + +/* diStorm version number. */ +#define __DISTORMV__ 0x030200 + +#include /* memset, memcpy - can be easily self implemented for libc independency. */ + +#include "../include/distorm.h" + + +/* + * 64 bit offsets support: + * This macro should be defined from compiler command line flags, e.g: -DSUPPORT_64BIT_OFFSET + * Note: make sure that the caller (library user) defines it too! + */ +/* #define SUPPORT_64BIT_OFFSET */ + +/* + * If you compile diStorm as a dynamic library (.dll or .so) file, make sure you uncomment the next line. + * So the interface functions will be exported, otherwise they are useable only for static library. + * For example, this macro is being set for compiling diStorm as a .dll for Python with CTypes. + */ +/* #define DISTORM_DYNAMIC */ + +/* + * If DISTORM_LIGHT is defined, everything involved in formatting the instructions + * as text will be excluded from compilation. + * distorm_decode(..) and distorm_format(..) will not be available. + * This will decrease the size of the executable and leave you with decomposition functionality only. + * + * Note: it should be either set in the preprocessor definitions manually or in command line -D switch. + * #define DISTORM_LIGHT + */ + +/* + * diStorm now supports little/big endian CPU's. + * It should detect the endianness according to predefined macro's of the compiler. + * If you don't use GCC/MSVC you will have to define it on your own. + */ + +/* These macros are used in order to make the code portable. */ +#ifdef __GNUC__ + +#include + +#define _DLLEXPORT_ +#define _FASTCALL_ +#define _INLINE_ static +/* GCC ignores this directive... */ +/*#define _FASTCALL_ __attribute__((__fastcall__))*/ + +/* Set endianity (supposed to be LE though): */ +#ifdef __BIG_ENDIAN__ + #define BE_SYSTEM +#endif + +/* End of __GCC__ */ + +#elif __WATCOMC__ + +#include + +#define _DLLEXPORT_ +#define _FASTCALL_ +#define _INLINE_ __inline + +/* End of __WATCOMC__ */ + +#elif __DMC__ + +#include + +#define _DLLEXPORT_ +#define _FASTCALL_ +#define _INLINE_ __inline + +/* End of __DMC__ */ + +#elif __TINYC__ + +#include + +#define _DLLEXPORT_ +#define _FASTCALL_ +#define _INLINE_ + +/* End of __TINYC__ */ + +#elif _MSC_VER + +/* stdint alternative is defined in distorm.h */ + +#define _DLLEXPORT_ __declspec(dllexport) +#define _FASTCALL_ __fastcall +#define _INLINE_ __inline + +/* Set endianity (supposed to be LE though): */ +#if !defined(_M_IX86) && !defined(_M_X64) + #define BE_SYSTEM +#endif + +#endif /* #elif _MSC_VER */ + +/* If the library isn't compiled as a dynamic library don't export any functions. */ +#ifndef DISTORM_DYNAMIC +#undef _DLLEXPORT_ +#define _DLLEXPORT_ +#endif + +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE 1 +#endif + +/* Define stream read functions for big endian systems. */ +#ifdef BE_SYSTEM +/* + * These functions can read from the stream safely! + * Swap endianity of input to little endian. + */ +static _INLINE_ int16_t RSHORT(const uint8_t *s) +{ + return s[0] | (s[1] << 8); +} +static _INLINE_ uint16_t RUSHORT(const uint8_t *s) +{ + return s[0] | (s[1] << 8); +} +static _INLINE_ int32_t RLONG(const uint8_t *s) +{ + return s[0] | (s[1] << 8) | (s[2] << 16) | (s[3] << 24); +} +static _INLINE_ uint32_t RULONG(const uint8_t *s) +{ + return s[0] | (s[1] << 8) | (s[2] << 16) | (s[3] << 24); +} +static _INLINE_ int64_t RLLONG(const uint8_t *s) +{ + return s[0] | (s[1] << 8) | (s[2] << 16) | (s[3] << 24) | ((uint64_t)s[4] << 32) | ((uint64_t)s[5] << 40) | ((uint64_t)s[6] << 48) | ((uint64_t)s[7] << 56); +} +static _INLINE_ uint64_t RULLONG(const uint8_t *s) +{ + return s[0] | (s[1] << 8) | (s[2] << 16) | (s[3] << 24) | ((uint64_t)s[4] << 32) | ((uint64_t)s[5] << 40) | ((uint64_t)s[6] << 48) | ((uint64_t)s[7] << 56); +} +#else +/* Little endian macro's will just make the cast. */ +#define RSHORT(x) *(int16_t *)x +#define RUSHORT(x) *(uint16_t *)x +#define RLONG(x) *(int32_t *)x +#define RULONG(x) *(uint32_t *)x +#define RLLONG(x) *(int64_t *)x +#define RULLONG(x) *(uint64_t *)x +#endif + +#endif /* CONFIG_H */ diff --git a/distorm3.2-package/src/decoder.c b/distorm3.2-package/src/decoder.c new file mode 100644 index 0000000..8123753 --- /dev/null +++ b/distorm3.2-package/src/decoder.c @@ -0,0 +1,606 @@ +/* +decoder.c + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2012 Gil Dabah + +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 +*/ + + +#include "decoder.h" +#include "instructions.h" +#include "insts.h" +#include "prefix.h" +#include "x86defs.h" +#include "operands.h" +#include "../include/mnemonics.h" + + +/* Instruction Prefixes - Opcode - ModR/M - SIB - Displacement - Immediate */ + +static _DecodeType decode_get_effective_addr_size(_DecodeType dt, _iflags decodedPrefixes) +{ + /* + * This table is to map from the current decoding mode to an effective address size: + * Decode16 -> Decode32 + * Decode32 -> Decode16 + * Decode64 -> Decode32 + */ + static _DecodeType AddrSizeTable[] = {Decode32Bits, Decode16Bits, Decode32Bits}; + + /* Switch to non default mode if prefix exists, only for ADDRESS SIZE. */ + if (decodedPrefixes & INST_PRE_ADDR_SIZE) dt = AddrSizeTable[dt]; + return dt; +} + +static _DecodeType decode_get_effective_op_size(_DecodeType dt, _iflags decodedPrefixes, unsigned int rex, _iflags instFlags) +{ + /* + * This table is to map from the current decoding mode to an effective operand size: + * Decode16 -> Decode32 + * Decode32 -> Decode16 + * Decode64 -> Decode16 + * Not that in 64bits it's a bit more complicated, because of REX and promoted instructions. + */ + static _DecodeType OpSizeTable[] = {Decode32Bits, Decode16Bits, Decode16Bits}; + + if (decodedPrefixes & INST_PRE_OP_SIZE) return OpSizeTable[dt]; + + if (dt == Decode64Bits) { + /* + * REX Prefix toggles data size to 64 bits. + * Operand size prefix toggles data size to 16. + * Default data size is 32 bits. + * Promoted instructions are 64 bits if they don't require a REX perfix. + * Non promoted instructions are 64 bits if the REX prefix exists. + */ + /* Automatically promoted instructions have only INST_64BITS SET! */ + if (((instFlags & (INST_64BITS | INST_PRE_REX)) == INST_64BITS) || + /* Other instructions in 64 bits can be promoted only with a REX prefix. */ + ((decodedPrefixes & INST_PRE_REX) && (rex & PREFIX_EX_W))) dt = Decode64Bits; + else dt = Decode32Bits; /* Default. */ + } + return dt; +} + +static _DecodeResult decode_inst(_CodeInfo* ci, _PrefixState* ps, _DInst* di) +{ + /* The ModR/M byte of the current instruction. */ + unsigned int modrm = 0; + + /* The REX/VEX prefix byte value. */ + unsigned int vrex = ps->vrex; + + /* + * Backup original input, so we can use it later if a problem occurs + * (like not enough data for decoding, invalid opcode, etc). + */ + const uint8_t* startCode = ci->code; + + /* Holds the info about the current found instruction. */ + _InstInfo* ii = NULL; + + /* Used only for special CMP instructions which have pseudo opcodes suffix. */ + unsigned char cmpType = 0; + + /* + * Indicates whether it is right to LOCK the instruction by decoding its first operand. + * Only then you know if it's ok to output the LOCK prefix's text... + * Used for first operand only. + */ + int lockable = FALSE; + + /* Calcualte (and cache) effective-operand-size and effective-address-size only once. */ + _DecodeType effOpSz, effAdrSz; + _iflags instFlags; + + ii = inst_lookup(ci, ps); + if (ii == NULL) goto _Undecodable; + instFlags = INST_INFO_FLAGS(ii); + + /* + * If both REX and OpSize are available we will have to disable the OpSize, because REX has precedence. + * However, only if REX.W is set ! + * We had to wait with this test, since the operand size may be a mandatory prefix, + * and we know it only after prefetching. + */ + if ((ps->prefixExtType == PET_REX) && + (ps->decodedPrefixes & INST_PRE_OP_SIZE) && + (!ps->isOpSizeMandatory) && + (vrex & PREFIX_EX_W)) { + ps->decodedPrefixes &= ~INST_PRE_OP_SIZE; + prefixes_ignore(ps, PFXIDX_OP_SIZE); + } + + /* + * In this point we know the instruction we are about to decode and its operands (unless, it's an invalid one!), + * so it makes it the right time for decoding-type suitability testing. + * Which practically means, don't allow 32 bits instructions in 16 bits decoding mode, but do allow + * 16 bits instructions in 32 bits decoding mode, of course... + + * NOTE: Make sure the instruction set for 32 bits has explicitly this specfic flag set. + * NOTE2: Make sure the instruction set for 64 bits has explicitly this specfic flag set. + + * If this is the case, drop what we've got and restart all over after DB'ing that byte. + + * Though, don't drop an instruction which is also supported in 16 and 32 bits. + */ + + /* ! ! ! DISABLED UNTIL FURTHER NOTICE ! ! ! Decode16Bits CAN NOW DECODE 32 BITS INSTRUCTIONS ! ! !*/ + /* if (ii && (dt == Decode16Bits) && (instFlags & INST_32BITS) && (~instFlags & INST_16BITS)) ii = NULL; */ + + /* Drop instructions which are invalid in 64 bits. */ + if ((ci->dt == Decode64Bits) && (instFlags & INST_INVALID_64BITS)) goto _Undecodable; + + /* If it's only a 64 bits instruction drop it in other decoding modes. */ + if ((ci->dt != Decode64Bits) && (instFlags & INST_64BITS_FETCH)) goto _Undecodable; + + if (instFlags & INST_MODRM_REQUIRED) { + /* If the ModRM byte is not part of the opcode, skip the last byte code, so code points now to ModRM. */ + if (~instFlags & INST_MODRM_INCLUDED) { + ci->code++; + if (--ci->codeLen < 0) goto _Undecodable; + } + modrm = *ci->code; + + /* Some instructions enforce that reg=000, so validate that. (Specifically EXTRQ). */ + if ((instFlags & INST_FORCE_REG0) && (((modrm >> 3) & 7) != 0)) goto _Undecodable; + /* Some instructions enforce that mod=11, so validate that. */ + if ((instFlags & INST_MODRR_REQUIRED) && (modrm < INST_DIVIDED_MODRM)) goto _Undecodable; + } + + ci->code++; /* Skip the last byte we just read (either last opcode's byte code or a ModRM). */ + + /* Cache the effective operand-size and address-size. */ + effOpSz = decode_get_effective_op_size(ci->dt, ps->decodedPrefixes, vrex, instFlags); + effAdrSz = decode_get_effective_addr_size(ci->dt, ps->decodedPrefixes); + + memset(di, 0, sizeof(_DInst)); + di->base = R_NONE; + + /* + * Try to extract the next operand only if the latter exists. + * For example, if there is not first operand, no reason to try to extract second operand... + * I decided that a for-break is better for readability in this specific case than goto. + * Note: do-while with a constant 0 makes the compiler warning about it. + */ + for (;;) { + if (ii->d != OT_NONE) { + if (!operands_extract(ci, di, ii, (_OpType)ii->d, ONT_1, modrm, ps, effOpSz, effAdrSz, &lockable)) goto _Undecodable; + } else break; + + if (ii->s != OT_NONE) { + if (!operands_extract(ci, di, ii, (_OpType)ii->s, ONT_2, modrm, ps, effOpSz, effAdrSz, NULL)) goto _Undecodable; + } else break; + + /* Use third operand, only if the flags says this InstInfo requires it. */ + if (instFlags & INST_USE_OP3) { + if (!operands_extract(ci, di, ii, (_OpType)((_InstInfoEx*)ii)->op3, ONT_3, modrm, ps, effOpSz, effAdrSz, NULL)) goto _Undecodable; + } else break; + + /* Support for a fourth operand is added for (i.e:) INSERTQ instruction. */ + if (instFlags & INST_USE_OP4) { + if (!operands_extract(ci, di, ii, (_OpType)((_InstInfoEx*)ii)->op4, ONT_4, modrm, ps, effOpSz, effAdrSz, NULL)) goto _Undecodable; + } + break; + } /* Continue here after all operands were extracted. */ + + /* If it were a 3DNow! instruction, we will have to find the instruction itself now that we got its operands extracted. */ + if (instFlags & INST_3DNOW_FETCH) { + ii = inst_lookup_3dnow(ci); + if (ii == NULL) goto _Undecodable; + instFlags = INST_INFO_FLAGS(ii); + } + + /* Check whether pseudo opcode is needed, only for CMP instructions: */ + if (instFlags & INST_PSEUDO_OPCODE) { + if (--ci->codeLen < 0) goto _Undecodable; + cmpType = *ci->code; + ci->code++; + if (instFlags & INST_PRE_VEX) { + /* AVX Comparison type must be between 0 to 32, otherwise Reserved. */ + if (cmpType >= INST_VCMP_MAX_RANGE) goto _Undecodable; + } else { + /* SSE Comparison type must be between 0 to 8, otherwise Reserved. */ + if (cmpType >= INST_CMP_MAX_RANGE) goto _Undecodable; + } + } + + /* + * There's a limit of 15 bytes on instruction length. The only way to violate + * this limit is by putting redundant prefixes before an instruction. + * start points to first prefix if any, otherwise it points to instruction first byte. + */ + if ((ci->code - ps->start) > INST_MAXIMUM_SIZE) goto _Undecodable; /* Drop instruction. */ + + /* + * If we reached here the instruction was fully decoded, we located the instruction in the DB and extracted operands. + * Use the correct mnemonic according to the DT. + * If we are in 32 bits decoding mode it doesn't necessarily mean we will choose mnemonic2, alas, + * it means that if there is a mnemonic2, it will be used. + */ + + /* Start with prefix LOCK. */ + if ((lockable == TRUE) && (instFlags & INST_PRE_LOCK)) { + ps->usedPrefixes |= INST_PRE_LOCK; + di->flags |= FLAG_LOCK; + } else if ((instFlags & INST_PRE_REPNZ) && (ps->decodedPrefixes & INST_PRE_REPNZ)) { + ps->usedPrefixes |= INST_PRE_REPNZ; + di->flags |= FLAG_REPNZ; + } else if ((instFlags & INST_PRE_REP) && (ps->decodedPrefixes & INST_PRE_REP)) { + ps->usedPrefixes |= INST_PRE_REP; + di->flags |= FLAG_REP; + } + + /* If it's JeCXZ the ADDR_SIZE prefix affects them. */ + if ((instFlags & (INST_PRE_ADDR_SIZE | INST_USE_EXMNEMONIC)) == (INST_PRE_ADDR_SIZE | INST_USE_EXMNEMONIC)) { + ps->usedPrefixes |= INST_PRE_ADDR_SIZE; + if (effAdrSz == Decode16Bits) di->opcode = ii->opcodeId; + else if (effAdrSz == Decode32Bits) di->opcode = ((_InstInfoEx*)ii)->opcodeId2; + /* Ignore REX.W in 64bits, JECXZ is promoted. */ + else /* Decode64Bits */ di->opcode = ((_InstInfoEx*)ii)->opcodeId3; + } + + /* LOOPxx instructions are also native instruction, but they are special case ones, ADDR_SIZE prefix affects them. */ + else if ((instFlags & (INST_PRE_ADDR_SIZE | INST_NATIVE)) == (INST_PRE_ADDR_SIZE | INST_NATIVE)) { + di->opcode = ii->opcodeId; + + /* If LOOPxx gets here from 64bits, it must be Decode32Bits because Address Size perfix is set. */ + ps->usedPrefixes |= INST_PRE_ADDR_SIZE; + } + /* + * Note: + * If the instruction is prefixed by operand size we will format it in the non-default decoding mode! + * So there might be a situation that an instruction of 32 bit gets formatted in 16 bits decoding mode. + * Both ways should end up with a correct and expected formatting of the text. + */ + else if (effOpSz == Decode16Bits) { /* Decode16Bits */ + + /* Set operand size. */ + FLAG_SET_OPSIZE(di, Decode16Bits); + + /* + * If it's a special instruction which has two mnemonics, then use the 16 bits one + update usedPrefixes. + * Note: use 16 bits mnemonic if that instruction supports 32 bit or 64 bit explicitly. + */ + if ((instFlags & INST_USE_EXMNEMONIC) && ((instFlags & (INST_32BITS | INST_64BITS)) == 0)) ps->usedPrefixes |= INST_PRE_OP_SIZE; + di->opcode = ii->opcodeId; + } else if (effOpSz == Decode32Bits) { /* Decode32Bits */ + + /* Set operand size. */ + FLAG_SET_OPSIZE(di, Decode32Bits); + + /* Give a chance for special mnemonic instruction in 32 bits decoding. */ + if (instFlags & INST_USE_EXMNEMONIC) { + ps->usedPrefixes |= INST_PRE_OP_SIZE; + /* Is it a special instruction which has another mnemonic for mod=11 ? */ + if (instFlags & INST_MNEMONIC_MODRM_BASED) { + if (modrm >= INST_DIVIDED_MODRM) di->opcode = ii->opcodeId; + else di->opcode = ((_InstInfoEx*)ii)->opcodeId2; + } else di->opcode = ((_InstInfoEx*)ii)->opcodeId2; + } else di->opcode = ii->opcodeId; + } else { /* Decode64Bits, note that some instructions might be decoded in Decode32Bits above. */ + + /* Set operand size. */ + FLAG_SET_OPSIZE(di, Decode64Bits); + + if (instFlags & (INST_USE_EXMNEMONIC | INST_USE_EXMNEMONIC2)) { + /* + * We shouldn't be here for MODRM based mnemonics with a MOD=11, + * because they must not use REX (otherwise it will get to the wrong instruction which share same opcode). + * See XRSTOR and XSAVEOPT. + */ + if ((instFlags & INST_MNEMONIC_MODRM_BASED) && (modrm >= INST_DIVIDED_MODRM)) goto _Undecodable; + + /* Use third mnemonic, for 64 bits. */ + if ((instFlags & INST_USE_EXMNEMONIC2) && (vrex & PREFIX_EX_W)) { + ps->usedPrefixes |= INST_PRE_REX; + di->opcode = ((_InstInfoEx*)ii)->opcodeId3; + } else di->opcode = ((_InstInfoEx*)ii)->opcodeId2; /* Use second mnemonic. */ + } else di->opcode = ii->opcodeId; + } + + /* If it's a native instruction use OpSize Prefix. */ + if ((instFlags & INST_NATIVE) && (ps->decodedPrefixes & INST_PRE_OP_SIZE)) ps->usedPrefixes |= INST_PRE_OP_SIZE; + + /* Check VEX mnemonics: */ + if ((instFlags & INST_PRE_VEX) && + (((((_InstInfoEx*)ii)->flagsEx & INST_MNEMONIC_VEXW_BASED) && (vrex & PREFIX_EX_W)) || + ((((_InstInfoEx*)ii)->flagsEx & INST_MNEMONIC_VEXL_BASED) && (vrex & PREFIX_EX_L)))) { + di->opcode = ((_InstInfoEx*)ii)->opcodeId2; + } + + /* Or is it a special CMP instruction which needs a pseudo opcode suffix ? */ + if (instFlags & INST_PSEUDO_OPCODE) { + /* + * The opcodeId is the offset to the FIRST pseudo compare mnemonic, + * we will have to fix it so it offsets into the corrected mnemonic. + * Therefore, we use another table to fix the offset. + */ + if (instFlags & INST_PRE_VEX) { + /* Use the AVX pesudo compare mnemonics table. */ + di->opcode = ii->opcodeId + VCmpMnemonicOffsets[cmpType]; + } else { + /* Use the SSE psuedo compare mnemonics table. */ + di->opcode = ii->opcodeId + CmpMnemonicOffsets[cmpType]; + } + } + + /* + * Store the address size inside the flags. + * This is necessary for the caller to know the size of rSP when using PUSHA for example. + */ + FLAG_SET_ADDRSIZE(di, effAdrSz); + + /* Copy DST_WR flag. */ + if (instFlags & INST_DST_WR) di->flags |= FLAG_DST_WR; + + /* Set the unused prefixes mask. */ + di->unusedPrefixesMask = prefixes_set_unused_mask(ps); + + /* Copy instruction meta. */ + di->meta = ii->meta; + if (di->segment == 0) di->segment = R_NONE; + + /* Take into account the O_MEM base register for the mask. */ + if (di->base != R_NONE) di->usedRegistersMask |= _REGISTERTORCLASS[di->base]; + + /* Calculate the size of the instruction we've just decoded. */ + di->size = (uint8_t)((ci->code - startCode) & 0xff); + return DECRES_SUCCESS; + +_Undecodable: /* If the instruction couldn't be decoded for some reason, drop the first byte. */ + memset(di, 0, sizeof(_DInst)); + di->base = R_NONE; + + di->size = 1; + /* Clean prefixes just in case... */ + ps->usedPrefixes = 0; + + /* Special case for WAIT instruction: If it's dropped, you have to return a valid instruction! */ + if (*startCode == INST_WAIT_INDEX) { + di->opcode = I_WAIT; + META_SET_ISC(di, ISC_INTEGER); + return DECRES_SUCCESS; + } + + /* Mark that we didn't manage to decode the instruction well, caller will drop it. */ + return DECRES_INPUTERR; +} + +/* + * decode_internal + * + * supportOldIntr - Since now we work with new structure instead of the old _DecodedInst, we are still interested in backward compatibility. + * So although, the array is now of type _DInst, we want to read it in jumps of the old array element's size. + * This is in order to save memory allocation for conversion between the new and the old structures. + * It really means we can do the conversion in-place now. + */ +_DecodeResult decode_internal(_CodeInfo* _ci, int supportOldIntr, _DInst result[], unsigned int maxResultCount, unsigned int* usedInstructionsCount) +{ + _PrefixState ps; + unsigned int prefixSize; + _CodeInfo ci; + + _OffsetType codeOffset = _ci->codeOffset; + const uint8_t* code = _ci->code; + int codeLen = _ci->codeLen; + + /* + * This is used for printing only, it is the real offset of where the whole instruction begins. + * We need this variable in addition to codeOffset, because prefixes might change the real offset an instruction begins at. + * So we keep track of both. + */ + _OffsetType startInstOffset = 0; + + const uint8_t* p; + + /* Current working decoded instruction in results. */ + unsigned int nextPos = 0; + _DInst *pdi = NULL; + + _OffsetType addrMask = (_OffsetType)-1; + + _DecodeResult decodeResult; + +#ifdef DISTORM_LIGHT + supportOldIntr; /* Unreferenced. */ +#endif + + if (_ci->features & DF_MAXIMUM_ADDR32) addrMask = 0xffffffff; + else if (_ci->features & DF_MAXIMUM_ADDR16) addrMask = 0xffff; + + /* No entries are used yet. */ + *usedInstructionsCount = 0; + ci.dt = _ci->dt; + _ci->nextOffset = codeOffset; + + /* Decode instructions as long as we have what to decode/enough room in entries. */ + while (codeLen > 0) { + + /* startInstOffset holds the displayed offset of current instruction. */ + startInstOffset = codeOffset; + + memset(&ps, 0, (size_t)((char*)&ps.pfxIndexer[0] - (char*)&ps)); + memset(ps.pfxIndexer, PFXIDX_NONE, sizeof(int) * PFXIDX_MAX); + ps.start = code; + ps.last = code; + prefixSize = 0; + + if (prefixes_is_valid(*code, ci.dt)) { + prefixes_decode(code, codeLen, &ps, ci.dt); + /* Count prefixes, start points to first prefix. */ + prefixSize = (unsigned int)(ps.last - ps.start); + /* + * It might be that we will just notice that we ran out of bytes, or only prefixes + * so we will have to drop everything and halt. + * Also take into consideration of flow control instruction filter. + */ + codeLen -= prefixSize; + if ((codeLen == 0) || (prefixSize == INST_MAXIMUM_SIZE)) { + if (~_ci->features & DF_RETURN_FC_ONLY) { + /* Make sure there is enough room. */ + if (nextPos + (ps.last - code) > maxResultCount) return DECRES_MEMORYERR; + + for (p = code; p < ps.last; p++, startInstOffset++) { + /* Use next entry. */ +#ifndef DISTORM_LIGHT + if (supportOldIntr) { + pdi = (_DInst*)((char*)result + nextPos * sizeof(_DecodedInst)); + } + else +#endif /* DISTORM_LIGHT */ + { + pdi = &result[nextPos]; + } + nextPos++; + memset(pdi, 0, sizeof(_DInst)); + + pdi->flags = FLAG_NOT_DECODABLE; + pdi->imm.byte = *p; + pdi->size = 1; + pdi->addr = startInstOffset & addrMask; + } + *usedInstructionsCount = nextPos; /* Include them all. */ + } + if (codeLen == 0) break; /* Bye bye, out of bytes. */ + } + code += prefixSize; + codeOffset += prefixSize; + + /* If we got only prefixes continue to next instruction. */ + if (prefixSize == INST_MAXIMUM_SIZE) continue; + } + + /* + * Now we decode the instruction and only then we do further prefixes handling. + * This is because the instruction could not be decoded at all, or an instruction requires + * a mandatory prefix, or some of the prefixes were useless, etc... + + * Even if there were a mandatory prefix, we already took into account its size as a normal prefix. + * so prefixSize includes that, and the returned size in pdi is simply the size of the real(=without prefixes) instruction. + */ + if (ci.dt == Decode64Bits) { + if (ps.decodedPrefixes & INST_PRE_REX) { + /* REX prefix must precede first byte of instruction. */ + if (ps.rexPos != (code - 1)) { + ps.decodedPrefixes &= ~INST_PRE_REX; + ps.prefixExtType = PET_NONE; + prefixes_ignore(&ps, PFXIDX_REX); + } + /* + * We will disable operand size prefix, + * if it exists only after decoding the instruction, since it might be a mandatory prefix. + * This will be done after calling inst_lookup in decode_inst. + */ + } + /* In 64 bits, segment overrides of CS, DS, ES and SS are ignored. So don't take'em into account. */ + if (ps.decodedPrefixes & INST_PRE_SEGOVRD_MASK32) { + ps.decodedPrefixes &= ~INST_PRE_SEGOVRD_MASK32; + prefixes_ignore(&ps, PFXIDX_SEG); + } + } + + /* Make sure there is at least one more entry to use, for the upcoming instruction. */ + if (nextPos + 1 > maxResultCount) return DECRES_MEMORYERR; +#ifndef DISTORM_LIGHT + if (supportOldIntr) { + pdi = (_DInst*)((char*)result + nextPos * sizeof(_DecodedInst)); + } + else +#endif /* DISTORM_LIGHT */ + { + pdi = &result[nextPos]; + } + nextPos++; + + /* + * The reason we copy these two again is because we have to keep track on the input ourselves. + * There might be a case when an instruction is invalid, and then it will be counted as one byte only. + * But that instruction already read a byte or two from the stream and only then returned the error. + * Thus, we end up unsynchronized on the stream. + * This way, we are totally safe, because we keep track after the call to decode_inst, using the returned size. + */ + ci.code = code; + ci.codeLen = codeLen; + /* Nobody uses codeOffset in the decoder itself, so spare it. */ + + decodeResult = decode_inst(&ci, &ps, pdi); + + /* See if we need to filter this instruction. */ + if ((_ci->features & DF_RETURN_FC_ONLY) && (META_GET_FC(pdi->meta) == FC_NONE)) decodeResult = DECRES_FILTERED; + + /* Set address to the beginning of the instruction. */ + pdi->addr = startInstOffset & addrMask; + /* pdi->disp &= addrMask; */ + + /* Advance to next instruction. */ + codeLen -= pdi->size; + codeOffset += pdi->size; + code += pdi->size; + + /* Instruction's size should include prefixes. */ + pdi->size += (uint8_t)prefixSize; + + /* Drop all prefixes and the instruction itself, because the instruction wasn't successfully decoded. */ + if ((decodeResult == DECRES_INPUTERR) && (~_ci->features & DF_RETURN_FC_ONLY)) { + nextPos--; /* Undo last result. */ + if ((prefixSize + 1) > 0) { /* 1 for the first instruction's byte. */ + if ((nextPos + prefixSize + 1) > maxResultCount) return DECRES_MEMORYERR; + + for (p = ps.start; p < ps.last + 1; p++, startInstOffset++) { + /* Use next entry. */ +#ifndef DISTORM_LIGHT + if (supportOldIntr) { + pdi = (_DInst*)((char*)result + nextPos * sizeof(_DecodedInst)); + } + else +#endif /* DISTORM_LIGHT */ + { + pdi = &result[nextPos]; + } + nextPos++; + + memset(pdi, 0, sizeof(_DInst)); + pdi->flags = FLAG_NOT_DECODABLE; + pdi->imm.byte = *p; + pdi->size = 1; + pdi->addr = startInstOffset & addrMask; + } + } + } else if (decodeResult == DECRES_FILTERED) nextPos--; /* Return it to pool, since it was filtered. */ + + /* Alright, the caller can read, at least, up to this one. */ + *usedInstructionsCount = nextPos; + /* Fix next offset. */ + _ci->nextOffset = codeOffset; + + /* Check whether we need to stop on any flow control instruction. */ + if ((decodeResult == DECRES_SUCCESS) && (_ci->features & DF_STOP_ON_FLOW_CONTROL)) { + if (((_ci->features & DF_STOP_ON_CALL) && (META_GET_FC(pdi->meta) == FC_CALL)) || + ((_ci->features & DF_STOP_ON_RET) && (META_GET_FC(pdi->meta) == FC_RET)) || + ((_ci->features & DF_STOP_ON_SYS) && (META_GET_FC(pdi->meta) == FC_SYS)) || + ((_ci->features & DF_STOP_ON_UNC_BRANCH) && (META_GET_FC(pdi->meta) == FC_UNC_BRANCH)) || + ((_ci->features & DF_STOP_ON_CND_BRANCH) && (META_GET_FC(pdi->meta) == FC_CND_BRANCH)) || + ((_ci->features & DF_STOP_ON_INT) && (META_GET_FC(pdi->meta) == FC_INT)) || + ((_ci->features & DF_STOP_ON_CMOV) && (META_GET_FC(pdi->meta) == FC_CMOV))) + return DECRES_SUCCESS; + } + } + + return DECRES_SUCCESS; +} diff --git a/distorm3.2-package/src/decoder.h b/distorm3.2-package/src/decoder.h new file mode 100644 index 0000000..2f9961a --- /dev/null +++ b/distorm3.2-package/src/decoder.h @@ -0,0 +1,33 @@ +/* +decoder.h + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2011 Gil Dabah + +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 +*/ + + +#ifndef DECODER_H +#define DECODER_H + +#include "config.h" + +typedef unsigned int _iflags; + +_DecodeResult decode_internal(_CodeInfo* ci, int supportOldIntr, _DInst result[], unsigned int maxResultCount, unsigned int* usedInstructionsCount); + +#endif /* DECODER_H */ diff --git a/distorm3.2-package/src/distorm.c b/distorm3.2-package/src/distorm.c new file mode 100644 index 0000000..2b865a6 --- /dev/null +++ b/distorm3.2-package/src/distorm.c @@ -0,0 +1,384 @@ +/* +distorm.c + +diStorm3 C Library Interface +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2012 Gil Dabah + +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 +*/ + + +#include "../include/distorm.h" +#include "config.h" +#include "decoder.h" +#include "x86defs.h" +#include "textdefs.h" +#include "wstring.h" +#include "../include/mnemonics.h" + +/* C DLL EXPORTS */ +#ifdef SUPPORT_64BIT_OFFSET + _DLLEXPORT_ _DecodeResult distorm_decompose64(_CodeInfo* ci, _DInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount) +#else + _DLLEXPORT_ _DecodeResult distorm_decompose32(_CodeInfo* ci, _DInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount) +#endif +{ + if (usedInstructionsCount == NULL) { + return DECRES_SUCCESS; + } + + /* DECRES_SUCCESS still may indicate we may have something in the result, so zero it first thing. */ + *usedInstructionsCount = 0; + + if ((ci == NULL) || + (ci->codeLen < 0) || + ((ci->dt != Decode16Bits) && (ci->dt != Decode32Bits) && (ci->dt != Decode64Bits)) || + (ci->code == NULL) || + (result == NULL) || + ((ci->features & (DF_MAXIMUM_ADDR16 | DF_MAXIMUM_ADDR32)) == (DF_MAXIMUM_ADDR16 | DF_MAXIMUM_ADDR32))) + { + return DECRES_INPUTERR; + } + + /* Assume length=0 is success. */ + if (ci->codeLen == 0) { + return DECRES_SUCCESS; + } + + return decode_internal(ci, FALSE, result, maxInstructions, usedInstructionsCount); +} + +#ifndef DISTORM_LIGHT + +/* Helper function to concat an explicit size when it's unknown from the operands. */ +static void distorm_format_size(_WString* str, const _DInst* di, int opNum) +{ + /* + * We only have to output the size explicitly if it's not clear from the operands. + * For example: + * mov al, [0x1234] -> The size is 8, we know it from the AL register operand. + * mov [0x1234], 0x11 -> Now we don't know the size. Pam pam pam + * + * If given operand number is higher than 2, then output the size anyways. + */ + if (((opNum >= 2) || ((di->ops[0].type != O_REG) && (di->ops[1].type != O_REG))) || + /* INS/OUTS are exception, because DX is a port specifier and not a real src/dst register. */ + ((di->opcode == I_INS) || (di->opcode == I_OUTS))) { + switch (di->ops[opNum].size) + { + case 0: break; /* OT_MEM's unknown size. */ + case 8: strcat_WSN(str, "BYTE "); break; + case 16: strcat_WSN(str, "WORD "); break; + case 32: strcat_WSN(str, "DWORD "); break; + case 64: strcat_WSN(str, "QWORD "); break; + case 80: strcat_WSN(str, "TBYTE "); break; + case 128: strcat_WSN(str, "DQWORD "); break; + case 256: strcat_WSN(str, "YWORD "); break; + default: /* Big oh uh if it gets here. */ break; + } + } +} + +static void distorm_format_signed_disp(_WString* str, const _DInst* di, uint64_t addrMask) +{ + int64_t tmpDisp64; + + if (di->dispSize) { + chrcat_WS(str, ((int64_t)di->disp < 0) ? MINUS_DISP_CHR : PLUS_DISP_CHR); + if ((int64_t)di->disp < 0) tmpDisp64 = -(int64_t)di->disp; + else tmpDisp64 = di->disp; + tmpDisp64 &= addrMask; + str_code_hqw(str, (uint8_t*)&tmpDisp64); + } +} + +#ifdef SUPPORT_64BIT_OFFSET + _DLLEXPORT_ void distorm_format64(const _CodeInfo* ci, const _DInst* di, _DecodedInst* result) +#else + _DLLEXPORT_ void distorm_format32(const _CodeInfo* ci, const _DInst* di, _DecodedInst* result) +#endif +{ + _WString* str; + unsigned int i, isDefault; + int64_t tmpDisp64; + uint64_t addrMask = (uint64_t)-1; + uint8_t segment; + const _WMnemonic* mnemonic; + + /* Set address mask, when default is for 64bits addresses. */ + if (ci->features & DF_MAXIMUM_ADDR32) addrMask = 0xffffffff; + else if (ci->features & DF_MAXIMUM_ADDR16) addrMask = 0xffff; + + /* Copy other fields. */ + result->size = di->size; + result->offset = di->addr & addrMask; + + if (di->flags == FLAG_NOT_DECODABLE) { + str = &result->mnemonic; + strclear_WS(&result->operands); + strcpy_WSN(str, "DB "); + str_code_hb(str, di->imm.byte); + strclear_WS(&result->instructionHex); + str_hex_b(&result->instructionHex, di->imm.byte); + return; /* Skip to next instruction. */ + } + + str = &result->instructionHex; + strclear_WS(str); + for (i = 0; i < di->size; i++) + str_hex_b(str, ci->code[(unsigned int)(di->addr - ci->codeOffset + i)]); + + str = &result->mnemonic; + switch (FLAG_GET_PREFIX(di->flags)) + { + case FLAG_LOCK: + strcpy_WSN(str, "LOCK "); + break; + case FLAG_REP: + strcpy_WSN(str, "REP "); + break; + case FLAG_REPNZ: + strcpy_WSN(str, "REPNZ "); + break; + default: + /* Init mnemonic string, cause next touch is concatenation. */ + strclear_WS(str); + break; + } + + mnemonic = (const _WMnemonic*)&_MNEMONICS[di->opcode]; + memcpy((int8_t*)&str->p[str->length], mnemonic->p, mnemonic->length + 1); + str->length += mnemonic->length; + + /* Format operands: */ + str = &result->operands; + strclear_WS(str); + + /* Special treatment for String instructions. */ + if ((META_GET_ISC(di->meta) == ISC_INTEGER) && + ((di->opcode == I_MOVS) || + (di->opcode == I_CMPS) || + (di->opcode == I_STOS) || + (di->opcode == I_LODS) || + (di->opcode == I_SCAS))) + { + /* + * No operands are needed if the address size is the default one, + * and no segment is overridden, so add the suffix letter, + * to indicate size of operation and continue to next instruction. + */ + if ((FLAG_GET_ADDRSIZE(di->flags) == ci->dt) && (SEGMENT_IS_DEFAULT(di->segment))) { + str = &result->mnemonic; + switch (di->ops[0].size) + { + case 8: chrcat_WS(str, 'B'); break; + case 16: chrcat_WS(str, 'W'); break; + case 32: chrcat_WS(str, 'D'); break; + case 64: chrcat_WS(str, 'Q'); break; + } + return; + } + } + + for (i = 0; ((i < OPERANDS_NO) && (di->ops[i].type != O_NONE)); i++) { + if (i > 0) strcat_WSN(str, ", "); + switch (di->ops[i].type) + { + case O_REG: + strcat_WS(str, (const _WString*)&_REGISTERS[di->ops[i].index]); + break; + case O_IMM: + /* If the instruction is 'push', show explicit size (except byte imm). */ + if (di->opcode == I_PUSH && di->ops[i].size != 8) distorm_format_size(str, di, i); + /* Special fix for negative sign extended immediates. */ + if ((di->flags & FLAG_IMM_SIGNED) && (di->ops[i].size == 8)) { + if (di->imm.sbyte < 0) { + chrcat_WS(str, MINUS_DISP_CHR); + str_code_hb(str, -di->imm.sbyte); + break; + } + } + if (di->ops[i].size == 64) str_code_hqw(str, (uint8_t*)&di->imm.qword); + else str_code_hdw(str, di->imm.dword); + break; + case O_IMM1: + str_code_hdw(str, di->imm.ex.i1); + break; + case O_IMM2: + str_code_hdw(str, di->imm.ex.i2); + break; + case O_DISP: + distorm_format_size(str, di, i); + chrcat_WS(str, OPEN_CHR); + if ((SEGMENT_GET(di->segment) != R_NONE) && !SEGMENT_IS_DEFAULT(di->segment)) { + strcat_WS(str, (const _WString*)&_REGISTERS[SEGMENT_GET(di->segment)]); + chrcat_WS(str, SEG_OFF_CHR); + } + tmpDisp64 = di->disp & addrMask; + str_code_hqw(str, (uint8_t*)&tmpDisp64); + chrcat_WS(str, CLOSE_CHR); + break; + case O_SMEM: + distorm_format_size(str, di, i); + chrcat_WS(str, OPEN_CHR); + + /* + * This is where we need to take special care for String instructions. + * If we got here, it means we need to explicitly show their operands. + * The problem with CMPS and MOVS is that they have two(!) memory operands. + * So we have to complete it ourselves, since the structure supplies only the segment that can be overridden. + * And make the rest of the String operations explicit. + */ + segment = SEGMENT_GET(di->segment); + isDefault = SEGMENT_IS_DEFAULT(di->segment); + switch (di->opcode) + { + case I_MOVS: + isDefault = FALSE; + if (i == 0) segment = R_ES; + break; + case I_CMPS: + isDefault = FALSE; + if (i == 1) segment = R_ES; + break; + case I_INS: + case I_LODS: + case I_STOS: + case I_SCAS: isDefault = FALSE; break; + } + if (!isDefault && (segment != R_NONE)) { + strcat_WS(str, (const _WString*)&_REGISTERS[segment]); + chrcat_WS(str, SEG_OFF_CHR); + } + + strcat_WS(str, (const _WString*)&_REGISTERS[di->ops[i].index]); + + distorm_format_signed_disp(str, di, addrMask); + chrcat_WS(str, CLOSE_CHR); + break; + case O_MEM: + distorm_format_size(str, di, i); + chrcat_WS(str, OPEN_CHR); + if ((SEGMENT_GET(di->segment) != R_NONE) && !SEGMENT_IS_DEFAULT(di->segment)) { + strcat_WS(str, (const _WString*)&_REGISTERS[SEGMENT_GET(di->segment)]); + chrcat_WS(str, SEG_OFF_CHR); + } + if (di->base != R_NONE) { + strcat_WS(str, (const _WString*)&_REGISTERS[di->base]); + chrcat_WS(str, PLUS_DISP_CHR); + } + strcat_WS(str, (const _WString*)&_REGISTERS[di->ops[i].index]); + if (di->scale != 0) { + chrcat_WS(str, '*'); + if (di->scale == 2) chrcat_WS(str, '2'); + else if (di->scale == 4) chrcat_WS(str, '4'); + else /* if (di->scale == 8) */ chrcat_WS(str, '8'); + } + + distorm_format_signed_disp(str, di, addrMask); + chrcat_WS(str, CLOSE_CHR); + break; + case O_PC: +#ifdef SUPPORT_64BIT_OFFSET + str_off64(str, (di->imm.sqword + di->addr + di->size) & addrMask); +#else + str_code_hdw(str, ((_OffsetType)di->imm.sdword + di->addr + di->size) & (uint32_t)addrMask); +#endif + break; + case O_PTR: + str_code_hdw(str, di->imm.ptr.seg); + chrcat_WS(str, SEG_OFF_CHR); + str_code_hdw(str, di->imm.ptr.off); + break; + } + } + + if (di->flags & FLAG_HINT_TAKEN) strcat_WSN(str, " ;TAKEN"); + else if (di->flags & FLAG_HINT_NOT_TAKEN) strcat_WSN(str, " ;NOT TAKEN"); +} + +#ifdef SUPPORT_64BIT_OFFSET + _DLLEXPORT_ _DecodeResult distorm_decode64(_OffsetType codeOffset, const unsigned char* code, int codeLen, _DecodeType dt, _DecodedInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount) +#else + _DLLEXPORT_ _DecodeResult distorm_decode32(_OffsetType codeOffset, const unsigned char* code, int codeLen, _DecodeType dt, _DecodedInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount) +#endif +{ + _DecodeResult res; + _DInst di; + _CodeInfo ci; + unsigned int instsCount = 0, i; + + *usedInstructionsCount = 0; + + /* I use codeLen as a signed variable in order to ease detection of underflow... and besides - */ + if (codeLen < 0) { + return DECRES_INPUTERR; + } + + if ((dt != Decode16Bits) && (dt != Decode32Bits) && (dt != Decode64Bits)) { + return DECRES_INPUTERR; + } + + if (code == NULL || result == NULL) { + return DECRES_INPUTERR; + } + + /* Assume length=0 is success. */ + if (codeLen == 0) { + return DECRES_SUCCESS; + } + + /* + * We have to format the result into text. But the interal decoder works with the new structure of _DInst. + * Therefore, we will pass the result array(!) from the caller and the interal decoder will fill it in with _DInst's. + * Then we will copy each result to a temporary structure, and use it to reformat that specific result. + * + * This is all done to save memory allocation and to work on the same result array in-place!!! + * It's a bit ugly, I have to admit, but worth it. + */ + + ci.codeOffset = codeOffset; + ci.code = code; + ci.codeLen = codeLen; + ci.dt = dt; + ci.features = DF_NONE; + if (dt == Decode16Bits) ci.features = DF_MAXIMUM_ADDR16; + else if (dt == Decode32Bits) ci.features = DF_MAXIMUM_ADDR32; + + res = decode_internal(&ci, TRUE, (_DInst*)result, maxInstructions, &instsCount); + for (i = 0; i < instsCount; i++) { + if ((*usedInstructionsCount + i) >= maxInstructions) return DECRES_MEMORYERR; + + /* Copy the current decomposed result to a temp structure, so we can override the result with text. */ + memcpy(&di, (char*)result + (i * sizeof(_DecodedInst)), sizeof(_DInst)); +#ifdef SUPPORT_64BIT_OFFSET + distorm_format64(&ci, &di, &result[i]); +#else + distorm_format32(&ci, &di, &result[i]); +#endif + } + + *usedInstructionsCount = instsCount; + return res; +} + +#endif /* DISTORM_LIGHT */ + +_DLLEXPORT_ unsigned int distorm_version() +{ + return __DISTORMV__; +} diff --git a/distorm3.2-package/src/instructions.c b/distorm3.2-package/src/instructions.c new file mode 100644 index 0000000..df122b9 --- /dev/null +++ b/distorm3.2-package/src/instructions.c @@ -0,0 +1,584 @@ +/* +instructions.c + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2012 Gil Dabah + +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 +*/ + + +#include "instructions.h" + +#include "insts.h" +#include "prefix.h" +#include "x86defs.h" +#include "../include/mnemonics.h" + + +/* Helper macros to extract the type or index from an inst-node value. */ +#define INST_NODE_INDEX(n) ((n) & 0x1fff) +#define INST_NODE_TYPE(n) ((n) >> 13) + +/* +I use the trie data structure as I found it most fitting to a disassembler mechanism. +When you read a byte and have to decide if it's enough or you should read more bytes, 'till you get to the instruction information. +It's really fast because you POP the instruction info in top 3 iterates on the DB, because an instruction can be formed from two bytes + 3 bits reg from the ModR/M byte. +For a simple explanation, check this out: +http://www.csse.monash.edu.au/~lloyd/tildeAlgDS/Tree/Trie/ +Futher reading: http://en.wikipedia.org/wiki/Trie + +The first GATE (array you read off a trie data structure), as I call them, is statically allocated by the compiler. +The second and third gates if used are being allocated dynamically by the instructions-insertion functionality. + +How would such a thing look in memory, say we support 4 instructions with 3 bytes top (means 2 dynamically allocated gates). + +-> +|-------| 0, +|0| -------------------------------> |-------| +|1|RET | 1, |0|AND | +|2| -----> |-------| |1|XOR | +|3|INT3 | |0|PUSH | |2|OR | 0,3, +|-------| |1|POP | |3| --------->|-------| + |2|PUSHF| |-------| |0|ROR | + |3|POPF | |1|ROL | + |-------| |2|SHR | + |3|SHL | + |-------| + +Of course, this is NOT how Intel instructions set looks!!! +but I just wanted to give a small demonstration. +Now the instructions you get from such a trie DB goes like this: + +0, 0 - AND +0, 1 - XOR +0, 2 - OR +0, 3, 0, ROR +0, 3, 1, ROL +0, 3, 2, SHR +0, 3, 3, SHL +1 - RET +2, 0 - PUSH +2, 1 - POP +2, 2 - PUSHF +2, 3 - POPF +3 - INT3 + +I guess it's clear by now. +So now, if you read 0, you know that you have to enter the second gate(list) with the second byte specifying the index. +But if you read 1, you know that you go to an instruction (in this case, a RET). +That's why there's an Instruction-Node structure, it tells you whether you got to an instruction or another list +so you should keep on reading byte). + +In Intel, you could go through 4 gates at top, because there're instructions which are built from 2 bytes and another smaller list +for the REG part, or newest SSE4 instructions which use 4 bytes for opcode. +Therefore, Intel's first gate is 256 long, and other gates are 256 (/72) or 8 long, yes, it costs pretty much alot of memory +for non-used defined instructions, but I think that it still rocks. +*/ + +/* + * A helper function to look up the correct inst-info structure. + * It does one fetch from the index-table, and then another to get the inst-info. + * Note that it takes care about basic inst-info or inst-info-ex. + * The caller should worry about boundary checks and whether it accesses a last-level table. + */ +static _InstInfo* inst_get_info(_InstNode in, int index) +{ + int instIndex = 0; + + in = InstructionsTree[INST_NODE_INDEX(in) + index]; + if (in == INT_NOTEXISTS) return NULL; + + instIndex = INST_NODE_INDEX(in); + return INST_NODE_TYPE(in) == INT_INFO ? &InstInfos[instIndex] : (_InstInfo*)&InstInfosEx[instIndex]; +} + +/* + * This function is responsible to return the instruction information of the first found in code. + * It returns the _InstInfo of the found instruction, otherwise NULL. + * code should point to the ModR/M byte upon exit (if used), or after the instruction binary code itself. + * This function is NOT decoding-type dependant, it is up to the caller to see whether the instruction is valid. + * Get the instruction info, using a Trie data structure. + * + * Sometimes normal prefixes become mandatory prefixes, which means they are now part of the instruction opcode bytes. + + * This is a bit tricky now, + * if the first byte is a REP (F3) prefix, we will have to give a chance to an SSE instruction. + * If an instruction doesn't exist, we will make it as a prefix and re-locateinst. + * A case such that a REP prefix is being changed into an instruction byte and also an SSE instruction will not be found can't happen, + * simply because there are no collisions between string instruction and SSE instructions (they are escaped). + + * As for S/SSE2/3, check for F2 and 66 as well. + + * In 64 bits, we have to make sure that we will skip the REX prefix, if it exists. + * There's a specific case, where a 66 is mandatory but it was dropped because REG.W was used, + * but it doesn't behave as an operand size prefix but as a mandatory, so we will have to take it into account. + + * For example (64 bits decoding mode): + * 66 98 CBW + * 48 98 CDQE + * 66 48 98: db 0x66; CDQE + * Shows that operand size is dropped. + + * Now, it's a mandatory prefix and NOT an operand size one. + * 66480f2dc0 db 0x48; CVTPD2PI XMM0, XMM0 + * Although this instruction doesn't require a REX.W, it just shows, that even if it did - it doesn't matter. + * REX.W is dropped because it's not requried, but the decode function disabled the operand size even so. + */ +static _InstInfo* inst_lookup_prefixed(_InstNode in, _PrefixState* ps) +{ + int checkOpSize = FALSE; + int index = 0; + _InstInfo* ii = NULL; + + /* Check prefixes of current decoded instruction (None, 0x66, 0xf3, 0xf2). */ + switch (ps->decodedPrefixes & (INST_PRE_OP_SIZE | INST_PRE_REPS)) + { + case 0: + /* Non-prefixed, index = 0. */ + index = 0; + break; + case INST_PRE_OP_SIZE: + /* 0x66, index = 1. */ + index = 1; + /* Mark that we used it as a mandatory prefix. */ + ps->isOpSizeMandatory = TRUE; + ps->decodedPrefixes &= ~INST_PRE_OP_SIZE; + break; + case INST_PRE_REP: + /* 0xf3, index = 2. */ + index = 2; + ps->decodedPrefixes &= ~INST_PRE_REP; + break; + case INST_PRE_REPNZ: + /* 0xf2, index = 3. */ + index = 3; + ps->decodedPrefixes &= ~INST_PRE_REPNZ; + break; + default: + /* + * Now we got a problem, since there are a few mandatory prefixes at once. + * There is only one case when it's ok, when the operand size prefix is for real (not mandatory). + * Otherwise we will have to return NULL, since the instruction is illegal. + * Therefore we will start with REPNZ and REP prefixes, + * try to get the instruction and only then check for the operand size prefix. + */ + + /* If both REPNZ and REP are together, it's illegal for sure. */ + if ((ps->decodedPrefixes & INST_PRE_REPS) == INST_PRE_REPS) return NULL; + + /* Now we know it's either REPNZ+OPSIZE or REP+OPSIZE, so examine the instruction. */ + if (ps->decodedPrefixes & INST_PRE_REPNZ) { + index = 3; + ps->decodedPrefixes &= ~INST_PRE_REPNZ; + } else if (ps->decodedPrefixes & INST_PRE_REP) { + index = 2; + ps->decodedPrefixes &= ~INST_PRE_REP; + } + /* Mark to verify the operand-size prefix of the fetched instruction below. */ + checkOpSize = TRUE; + break; + } + + /* Fetch the inst-info from the index. */ + ii = inst_get_info(in, index); + + if (checkOpSize) { + /* If the instruction doesn't support operand size prefix, then it's illegal. */ + if ((ii == NULL) || (~INST_INFO_FLAGS(ii) & INST_PRE_OP_SIZE)) return NULL; + } + + /* If there was a prefix, but the instruction wasn't found. Try to fall back to use the normal instruction. */ + if (ii == NULL) ii = inst_get_info(in, 0); + return ii; +} + +/* A helper function to look up special VEX instructions. + * See if it's a MOD based instruction and fix index if required. + * Only after a first lookup (that was done by caller), we can tell if we need to fix the index. + * Because these are coupled instructions + * (which means that the base instruction hints about the other instruction). + * Note that caller should check if it's a MOD dependent instruction before getting in here. + */ +static _InstInfo* inst_vex_mod_lookup(_CodeInfo* ci, _InstNode in, _InstInfo* ii, unsigned int index) +{ + /* Advance to read the MOD from ModRM byte. */ + ci->code += 1; + ci->codeLen -= 1; + if (ci->codeLen < 0) return NULL; + if (*ci->code < INST_DIVIDED_MODRM) { + /* MOD is not 11, therefore change the index to 8 - 12 range in the prefixed table. */ + index += 4; + /* Make a second lookup for this special instruction. */ + return inst_get_info(in, index); + } + /* Return the original one, in case we didn't find a stuited instruction. */ + return ii; +} + +static _InstInfo* inst_vex_lookup(_CodeInfo* ci, _PrefixState* ps) +{ + _InstNode in = 0; + unsigned int pp = 0, start = 0; + unsigned int index = 4; /* VEX instructions start at index 4 in the Prefixed table. */ + uint8_t vex = *ps->vexPos, vex2 = 0, v = 0; + int instType = 0, instIndex = 0; + + /* The VEX instruction will #ud if any of 66, f0, f2, f3, REX prefixes precede. */ + _iflags illegal = (INST_PRE_OP_SIZE | INST_PRE_LOCK | INST_PRE_REP | INST_PRE_REPNZ | INST_PRE_REX); + if ((ps->decodedPrefixes & illegal) != 0) return NULL; + + /* Read the some fields from the VEX prefix we need to extract the instruction. */ + if (ps->prefixExtType == PET_VEX2BYTES) { + ps->vexV = v = (~vex >> 3) & 0xf; + pp = vex & 3; + /* Implied leading 0x0f byte by default for 2 bytes VEX prefix. */ + start = 1; + } else { /* PET_VEX3BYTES */ + start = vex & 0x1f; + vex2 = *(ps->vexPos + 1); + ps->vexV = v = (~vex2 >> 3) & 0xf; + pp = vex2 & 3; + } + + /* start can be either 1 (0x0f), 2 (0x0f, 0x038) or 3 (0x0f, 0x3a), otherwise it's illegal. */ + switch (start) + { + case 1: in = Table_0F; break; + case 2: in = Table_0F_38; break; + case 3: in = Table_0F_3A; break; + default: return NULL; + } + + /* pp is actually the implied mandatory prefix, apply it to the index. */ + index += pp; /* (None, 0x66, 0xf3, 0xf2) */ + + /* Read a byte from the stream. */ + ci->codeLen -= 1; + if (ci->codeLen < 0) return NULL; + + in = InstructionsTree[INST_NODE_INDEX(in) + *ci->code]; + if (in == INT_NOTEXISTS) return NULL; + + instType = INST_NODE_TYPE(in); + instIndex = INST_NODE_INDEX(in); + + /* + * If we started with 0f38 or 0f3a so it's a prefixed table, + * therefore it's surely a VEXed instruction (because of a high index). + * However, starting with 0f, could also lead immediately to a prefixed table for some bytes. + * it might return NULL, if the index is invalid. + */ + if (instType == INT_LIST_PREFIXED) { + _InstInfo* ii = inst_get_info(in, index); + /* See if the instruction is dependent on MOD. */ + if ((ii != NULL) && (((_InstInfoEx*)ii)->flagsEx & INST_MODRR_BASED)) { + ii = inst_vex_mod_lookup(ci, in, ii, index); + } + return ii; + } + + /* + * If we reached here, obviously we started with 0f. VEXed instructions must be nodes of a prefixed table. + * But since we found an instruction (or divided one), just return NULL. + * They cannot lead to a VEXed instruction. + */ + if ((instType == INT_INFO) || (instType == INT_INFOEX) || (instType == INT_LIST_DIVIDED)) return NULL; + + /* Now we are left with handling either GROUP or FULL tables, therefore we will read another byte from the stream. */ + ci->code += 1; + ci->codeLen -= 1; + if (ci->codeLen < 0) return NULL; + + if (instType == INT_LIST_GROUP) { + in = InstructionsTree[instIndex + ((*ci->code >> 3) & 7)]; + /* Continue below to check prefixed table. */ + } else if (instType == INT_LIST_FULL) { + in = InstructionsTree[instIndex + *ci->code]; + /* Continue below to check prefixed table. */ + } + + /* Now that we got to the last table in the trie, check for a prefixed table. */ + if (INST_NODE_TYPE(in) == INT_LIST_PREFIXED) { + _InstInfo* ii = inst_get_info(in, index); + /* See if the instruction is dependent on MOD. */ + if ((ii != NULL) && (((_InstInfoEx*)ii)->flagsEx & INST_MODRR_BASED)) { + ii = inst_vex_mod_lookup(ci, in, ii, index); + } + return ii; + } + + /* No VEXed instruction was found. */ + return NULL; +} + +_InstInfo* inst_lookup(_CodeInfo* ci, _PrefixState* ps) +{ + unsigned int tmpIndex0 = 0, tmpIndex1 = 0, tmpIndex2 = 0, rex = ps->vrex; + int instType = 0; + _InstNode in = 0; + _InstInfo* ii = NULL; + int isWaitIncluded = FALSE; + + /* See whether we have to handle a VEX prefixed instruction. */ + if (ps->decodedPrefixes & INST_PRE_VEX) { + ii = inst_vex_lookup(ci, ps); + if (ii != NULL) { + /* Make sure that VEX.L exists when forced. */ + if ((((_InstInfoEx*)ii)->flagsEx & INST_FORCE_VEXL) && (~ps->vrex & PREFIX_EX_L)) return NULL; + /* If the instruction doesn't use VEX.vvvv it must be zero. */ + if ((((_InstInfoEx*)ii)->flagsEx & INST_VEX_V_UNUSED) && ps->vexV) return NULL; + } + return ii; + } + + /* Read first byte. */ + ci->codeLen -= 1; + if (ci->codeLen < 0) return NULL; + tmpIndex0 = *ci->code; + + /* Check for special 0x9b, WAIT instruction, which can be part of some instructions(x87). */ + if (tmpIndex0 == INST_WAIT_INDEX) { + /* Only OCST_1dBYTES get a chance to include this byte as part of the opcode. */ + isWaitIncluded = TRUE; + + /* Ignore all prefixes, since they are useless and operate on the WAIT instruction itself. */ + prefixes_ignore_all(ps); + + /* Move to next code byte as a new whole instruction. */ + ci->code += 1; + ci->codeLen -= 1; + if (ci->codeLen < 0) return NULL; /* Faster to return NULL, it will be detected as WAIT later anyway. */ + /* Since we got a WAIT prefix, we re-read the first byte. */ + tmpIndex0 = *ci->code; + } + + /* Walk first byte in InstructionsTree root. */ + in = InstructionsTree[tmpIndex0]; + if (in == INT_NOTEXISTS) return NULL; + instType = INST_NODE_TYPE(in); + + /* Single byte instruction (OCST_1BYTE). */ + if ((instType < INT_INFOS) && (!isWaitIncluded)) { + /* Some single byte instructions need extra treatment. */ + switch (tmpIndex0) + { + case INST_ARPL_INDEX: + /* + * ARPL/MOVSXD share the same opcode, and both have different operands and mnemonics, of course. + * Practically, I couldn't come up with a comfortable way to merge the operands' types of ARPL/MOVSXD. + * And since the DB can't be patched dynamically, because the DB has to be multi-threaded compliant, + * I have no choice but to check for ARPL/MOVSXD right here - "right about now, the funk soul brother, check it out now, the funk soul brother...", fatboy slim + */ + return ci->dt == Decode64Bits ? &II_movsxd : &II_arpl; + + case INST_NOP_INDEX: /* Nopnopnop */ + /* Check for Pause, since it's prefixed with 0xf3, which is not a real mandatory prefix. */ + if (ps->decodedPrefixes & INST_PRE_REP) { + /* Flag this prefix as used. */ + ps->usedPrefixes |= INST_PRE_REP; + return &II_pause; + } + + /* + * Treat NOP/XCHG specially. + * If we're not in 64bits restore XCHG to NOP, since in the DB it's XCHG. + * Else if we're in 64bits examine REX, if exists, and decide which instruction should go to output. + * 48 90 XCHG RAX, RAX is a true NOP (eat REX in this case because it's valid). + * 90 XCHG EAX, EAX is a true NOP (and not high dword of RAX = 0 although it should be a 32 bits operation). + * Note that if the REX.B is used, then the register is not RAX anymore but R8, which means it's not a NOP. + */ + if (rex & PREFIX_EX_W) ps->usedPrefixes |= INST_PRE_REX; + if ((ci->dt != Decode64Bits) || (~rex & PREFIX_EX_B)) return &II_nop; + break; + + case INST_LEA_INDEX: + /* Ignore segment override prefixes for LEA instruction. */ + ps->decodedPrefixes &= ~INST_PRE_SEGOVRD_MASK; + /* Update unused mask for ignoring segment prefix. */ + prefixes_ignore(ps, PFXIDX_SEG); + break; + } + + /* Return the 1 byte instruction we found. */ + return instType == INT_INFO ? &InstInfos[INST_NODE_INDEX(in)] : (_InstInfo*)&InstInfosEx[INST_NODE_INDEX(in)]; + } + + /* Read second byte, still doens't mean all of its bits are used (I.E: ModRM). */ + ci->code += 1; + ci->codeLen -= 1; + if (ci->codeLen < 0) return NULL; + tmpIndex1 = *ci->code; + + /* Try single byte instruction + reg bits (OCST_13BYTES). */ + if ((instType == INT_LIST_GROUP) && (!isWaitIncluded)) return inst_get_info(in, (tmpIndex1 >> 3) & 7); + + /* Try single byte instruction + reg byte OR one whole byte (OCST_1dBYTES). */ + if (instType == INT_LIST_DIVIDED) { + /* OCST_1dBYTES is relatively simple to OCST_2dBYTES, since it's really divided at 0xc0. */ + if (tmpIndex1 < INST_DIVIDED_MODRM) { + /* An instruction which requires a ModR/M byte. Thus it's 1.3 bytes long instruction. */ + tmpIndex1 = (tmpIndex1 >> 3) & 7; /* Isolate the 3 REG/OPCODE bits. */ + } else { /* Normal 2 bytes instruction. */ + /* + * Divided instructions can't be in the range of 0x8-0xc0. + * That's because 0-8 are used for 3 bits group. + * And 0xc0-0xff are used for not-divided instruction. + * So the inbetween range is omitted, thus saving some more place in the tables. + */ + tmpIndex1 -= INST_DIVIDED_MODRM - 8; + } + + in = InstructionsTree[INST_NODE_INDEX(in) + tmpIndex1]; + if (in == INT_NOTEXISTS) return NULL; + instType = INST_NODE_TYPE(in); + + if (instType < INT_INFOS) { + /* If the instruction doesn't support the wait (marked as opsize) as part of the opcode, it's illegal. */ + ii = instType == INT_INFO ? &InstInfos[INST_NODE_INDEX(in)] : (_InstInfo*)&InstInfosEx[INST_NODE_INDEX(in)]; + if ((~INST_INFO_FLAGS(ii) & INST_PRE_OP_SIZE) && (isWaitIncluded)) return NULL; + return ii; + } + /* + * If we got here the instruction can support the wait prefix, so see if it was part of the stream. + * Examine prefixed table, specially used for 0x9b, since it's optional. + * No Wait: index = 0. + * Wait Exists, index = 1. + */ + return inst_get_info(in, isWaitIncluded); + } + + /* Don't allow to continue if WAIT is part of the opcode, because there are no instructions that include it. */ + if (isWaitIncluded) return NULL; + + /* Try 2 bytes long instruction (doesn't include ModRM byte). */ + if (instType == INT_LIST_FULL) { + in = InstructionsTree[INST_NODE_INDEX(in) + tmpIndex1]; + if (in == INT_NOTEXISTS) return NULL; + instType = INST_NODE_TYPE(in); + + /* This is where we check if we just read two escape bytes in a row, which means it is a 3DNow! instruction. */ + if ((tmpIndex0 == _3DNOW_ESCAPE_BYTE) && (tmpIndex1 == _3DNOW_ESCAPE_BYTE)) return &II_3dnow; + + /* 2 bytes instruction (OCST_2BYTES). */ + if (instType < INT_INFOS) + return instType == INT_INFO ? &InstInfos[INST_NODE_INDEX(in)] : (_InstInfo*)&InstInfosEx[INST_NODE_INDEX(in)]; + + /* + * 2 bytes + mandatory perfix. + * Mandatory prefixes can be anywhere in the prefixes. + * There cannot be more than one mandatory prefix, unless it's a normal operand size prefix. + */ + if (instType == INT_LIST_PREFIXED) return inst_lookup_prefixed(in, ps); + } + + /* Read third byte, still doens't mean all of its bits are used (I.E: ModRM). */ + ci->code += 1; + ci->codeLen -= 1; + if (ci->codeLen < 0) return NULL; + tmpIndex2 = *ci->code; + + /* Try 2 bytes + reg instruction (OCST_23BYTES). */ + if (instType == INT_LIST_GROUP) { + in = InstructionsTree[INST_NODE_INDEX(in) + ((tmpIndex2 >> 3) & 7)]; + if (in == INT_NOTEXISTS) return NULL; + instType = INST_NODE_TYPE(in); + + if (instType < INT_INFOS) + return instType == INT_INFO ? &InstInfos[INST_NODE_INDEX(in)] : (_InstInfo*)&InstInfosEx[INST_NODE_INDEX(in)]; + + /* It has to be a prefixed table then. */ + return inst_lookup_prefixed(in, ps); + } + + /* Try 2 bytes + divided range (OCST_2dBYTES). */ + if (instType == INT_LIST_DIVIDED) { + _InstNode in2 = InstructionsTree[INST_NODE_INDEX(in) + ((tmpIndex2 >> 3) & 7)]; + /* + * Do NOT check for NULL here, since we do a bit of a guess work, + * hence we don't override 'in', cause we might still need it. + */ + instType = INST_NODE_TYPE(in2); + + if (instType == INT_INFO) ii = &InstInfos[INST_NODE_INDEX(in2)]; + else if (instType == INT_INFOEX) ii = (_InstInfo*)&InstInfosEx[INST_NODE_INDEX(in2)]; + + /* + * OCST_2dBYTES is complex, because there are a few instructions which are not divided in some special cases. + * If the instruction wasn't divided (but still it must be a 2.3 because we are in divided category) + * or it was an official 2.3 (because its index was less than 0xc0) - + * Then it means the instruction should be using the REG bits, otherwise give a chance to range 0xc0-0xff. + */ + /* If we found an instruction only by its REG bits, AND it is not divided, then return it. */ + if ((ii != NULL) && (INST_INFO_FLAGS(ii) & INST_NOT_DIVIDED)) return ii; + /* Otherwise, if the range is above 0xc0, try the special divided range (range 0x8-0xc0 is omitted). */ + if (tmpIndex2 >= INST_DIVIDED_MODRM) return inst_get_info(in, tmpIndex2 - INST_DIVIDED_MODRM + 8); + + /* It might be that we got here without touching ii in the above if statements, then it becomes an invalid instruction prolly. */ + return ii; + } + + /* Try 3 full bytes (OCST_3BYTES - no ModRM byte). */ + if (instType == INT_LIST_FULL) { + /* OCST_3BYTES. */ + in = InstructionsTree[INST_NODE_INDEX(in) + tmpIndex2]; + if (in == INT_NOTEXISTS) return NULL; + instType = INST_NODE_TYPE(in); + + if (instType < INT_INFOS) + return instType == INT_INFO ? &InstInfos[INST_NODE_INDEX(in)] : (_InstInfo*)&InstInfosEx[INST_NODE_INDEX(in)]; + + if (instType == INT_LIST_PREFIXED) return inst_lookup_prefixed(in, ps); + } + + /* Kahtchinggg, damn. */ + return NULL; +} + +/* +* 3DNow! instruction handling: + +* This is used when we encounter a 3DNow! instruction. +* We can't really locate a 3DNow! instruction before we see two escaped bytes, +* 0x0f, 0x0f. Then we have to extract operands which are, dest=mmx register, src=mmx register or quadword indirection. +* When we are finished with the extraction of operands we can resume to locate the instruction by reading another byte +* which tells us which 3DNow instruction we really tracked down... +* So in order to tell the extract operands function which operands the 3DNow! instruction require, we need to set up some +* generic instruction info for 3DNow! instructions. + +* In the inst_lookup itself, when we read an OCST_3BYTES which the two first bytes are 0x0f and 0x0f. +* we will return this special generic II for the specific operands we are interested in (MM, MM64). +* Then after extracting the operand, we'll call a completion routine for locating the instruction +* which will be called only for 3DNow! instructions, distinguished by a flag, and it will read the last byte of the 3 bytes. +* +* The id of this opcode should not be used, the following function should change it anyway. +*/ +_InstInfo* inst_lookup_3dnow(_CodeInfo* ci) +{ + /* Start off from the two escape bytes gates... which is 3DNow! table.*/ + _InstNode in = Table_0F_0F; + + int index; + + /* Make sure we can read a byte off the stream. */ + if (ci->codeLen < 1) return NULL; + + index = *ci->code; + + ci->codeLen -= 1; + ci->code += 1; + return inst_get_info(in, index); +} diff --git a/distorm3.2-package/src/instructions.h b/distorm3.2-package/src/instructions.h new file mode 100644 index 0000000..43be7d9 --- /dev/null +++ b/distorm3.2-package/src/instructions.h @@ -0,0 +1,444 @@ +/* +instructions.h + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2012 Gil Dabah + +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 +*/ + + +#ifndef INSTRUCTIONS_H +#define INSTRUCTIONS_H + +#include "config.h" +#include "prefix.h" + + +/* + * Operand type possibilities: + * Note "_FULL" suffix indicates to decode the operand as 16 bits or 32 bits depends on DecodeType - + * actually, it depends on the decoding mode, unless there's an operand/address size prefix. + * For example, the code: 33 c0 could be decoded/executed as XOR AX, AX or XOR EAX, EAX. + */ +typedef enum OpType { + /* No operand is set */ + OT_NONE = 0, + + /* Read a byte(8 bits) immediate */ + OT_IMM8, + /* Force a read of a word(16 bits) immediate, used by ret only */ + OT_IMM16, + /* Read a word/dword immediate */ + OT_IMM_FULL, + /* Read a double-word(32 bits) immediate */ + OT_IMM32, + + /* Read a signed extended byte(8 bits) immediate */ + OT_SEIMM8, + + /* + * Special immediates for instructions which have more than one immediate, + * which is an exception from standard instruction format. + * As to version v1.0: ENTER, INSERTQ, EXTRQ are the only problematic ones. + */ + /* 16 bits immediate using the first imm-slot */ + OT_IMM16_1, + /* 8 bits immediate using the first imm-slot */ + OT_IMM8_1, + /* 8 bits immediate using the second imm-slot */ + OT_IMM8_2, + + /* Use a 8bit register */ + OT_REG8, + /* Use a 16bit register */ + OT_REG16, + /* Use a 16/32/64bit register */ + OT_REG_FULL, + /* Use a 32bit register */ + OT_REG32, + /* + * If used with REX the reg operand size becomes 64 bits, otherwise 32 bits. + * VMX instructions are promoted automatically without a REX prefix. + */ + OT_REG32_64, + /* Used only by MOV CR/DR(n). Promoted with REX onlly. */ + OT_FREG32_64_RM, + + /* Use or read (indirection) a 8bit register or immediate byte */ + OT_RM8, + /* Some instructions force 16 bits (mov sreg, rm16) */ + OT_RM16, + /* Use or read a 16/32/64bit register or immediate word/dword/qword */ + OT_RM_FULL, + /* + * 32 or 64 bits (with REX) operand size indirection memory operand. + * Some instructions are promoted automatically without a REX prefix. + */ + OT_RM32_64, + /* 16 or 32 bits RM. This is used only with MOVZXD instruction in 64bits. */ + OT_RM16_32, + /* Same as OT_RMXX but POINTS to 16 bits [cannot use GENERAL-PURPOSE REG!] */ + OT_FPUM16, + /* Same as OT_RMXX but POINTS to 32 bits (single precision) [cannot use GENERAL-PURPOSE REG!] */ + OT_FPUM32, + /* Same as OT_RMXX but POINTS to 64 bits (double precision) [cannot use GENERAL-PURPOSE REG!] */ + OT_FPUM64, + /* Same as OT_RMXX but POINTS to 80 bits (extended precision) [cannot use GENERAL-PURPOSE REG!] */ + OT_FPUM80, + + /* + * Special operand type for SSE4 where the ModR/M might + * be a 32 bits register or 8 bits memory indirection operand. + */ + OT_R32_M8, + /* + * Special ModR/M for PINSRW, which need a 16 bits memory operand or 32 bits register. + * In 16 bits decoding mode R32 becomes R16, operand size cannot affect this. + */ + OT_R32_M16, + /* + * Special type for SSE4, ModR/M might be a 32 bits or 64 bits (with REX) register or + * a 8 bits memory indirection operand. + */ + OT_R32_64_M8, + /* + * Special type for SSE4, ModR/M might be a 32 bits or 64 bits (with REX) register or + * a 16 bits memory indirection operand. + */ + OT_R32_64_M16, + /* + * Special operand type for MOV reg16/32/64/mem16, segReg 8C /r. and SMSW. + * It supports all decoding modes, but if used as a memory indirection it's a 16 bit ModR/M indirection. + */ + OT_RFULL_M16, + + /* Use a control register */ + OT_CREG, + /* Use a debug register */ + OT_DREG, + /* Use a segment register */ + OT_SREG, + /* + * SEG is encoded in the flags of the opcode itself! + * This is used for specific "push SS" where SS is a segment where + * each "push SS" has an absolutely different opcode byte. + * We need this to detect whether an operand size prefix is used. + */ + OT_SEG, + + /* Use AL */ + OT_ACC8, + /* Use AX (FSTSW) */ + OT_ACC16, + /* Use AX/EAX/RAX */ + OT_ACC_FULL, + /* Use AX/EAX, no REX is possible for RAX, used only with IN/OUT which don't support 64 bit registers */ + OT_ACC_FULL_NOT64, + + /* + * Read one word (seg), and a word/dword/qword (depends on operand size) from memory. + * JMP FAR [EBX] means EBX point to 16:32 ptr. + */ + OT_MEM16_FULL, + /* Read one word (seg) and a word/dword/qword (depends on operand size), usually SEG:OFF, JMP 1234:1234 */ + OT_PTR16_FULL, + /* Read one word (limit) and a dword/qword (limit) (depends on operand size), used by SGDT, SIDT, LGDT, LIDT. */ + OT_MEM16_3264, + + /* Read a byte(8 bits) immediate and calculate it relatively to the current offset of the instruction being decoded */ + OT_RELCB, + /* Read a word/dword immediate and calculate it relatively to the current offset of the instruction being decoded */ + OT_RELC_FULL, + + /* Use general memory indirection, with varying sizes: */ + OT_MEM, + /* Used when a memory indirection is required, but if the mod field is 11, this operand will be ignored. */ + OT_MEM_OPT, + OT_MEM32, + /* Memory dereference for MOVNTI, either 32 or 64 bits (with REX). */ + OT_MEM32_64, + OT_MEM64, + OT_MEM128, + /* Used for cmpxchg8b/16b. */ + OT_MEM64_128, + + /* Read an immediate as an absolute address, size is known by instruction, used by MOV (memory offset) only */ + OT_MOFFS8, + OT_MOFFS_FULL, + /* Use an immediate of 1, as for SHR R/M, 1 */ + OT_CONST1, + /* Use CL, as for SHR R/M, CL */ + OT_REGCL, + + /* + * Instruction-Block for one byte long instructions, used by INC/DEC/PUSH/POP/XCHG, + * REG is extracted from the value of opcode + * Use a 8bit register + */ + OT_IB_RB, + /* Use a 16/32/64bit register */ + OT_IB_R_FULL, + + /* Use [(r)SI] as INDIRECTION, for repeatable instructions */ + OT_REGI_ESI, + /* Use [(r)DI] as INDIRECTION, for repeatable instructions */ + OT_REGI_EDI, + /* Use [(r)BX + AL] as INDIRECTIOM, used by XLAT only */ + OT_REGI_EBXAL, + /* Use [(r)AX] as INDIRECTION, used by AMD's SVM instructions */ + OT_REGI_EAX, + /* Use DX, as for OUTS DX, BYTE [SI] */ + OT_REGDX, + /* Use ECX in INVLPGA instruction */ + OT_REGECX, + + /* FPU registers: */ + OT_FPU_SI, /* ST(i) */ + OT_FPU_SSI, /* ST(0), ST(i) */ + OT_FPU_SIS, /* ST(i), ST(0) */ + + /* MMX registers: */ + OT_MM, + /* Extract the MMX register from the RM bits this time (used when the REG bits are used for opcode extension) */ + OT_MM_RM, + /* ModR/M points to 32 bits MMX variable */ + OT_MM32, + /* ModR/M points to 32 bits MMX variable */ + OT_MM64, + + /* SSE registers: */ + OT_XMM, + /* Extract the SSE register from the RM bits this time (used when the REG bits are used for opcode extension) */ + OT_XMM_RM, + /* ModR/M points to 16 bits SSE variable */ + OT_XMM16, + /* ModR/M points to 32 bits SSE variable */ + OT_XMM32, + /* ModR/M points to 64 bits SSE variable */ + OT_XMM64, + /* ModR/M points to 128 bits SSE variable */ + OT_XMM128, + /* Implied XMM0 register as operand, used in SSE4. */ + OT_REGXMM0, + + /* AVX operands: */ + + /* ModR/M for 32 bits. */ + OT_RM32, + /* Reg32/Reg64 (prefix width) or Mem8. */ + OT_REG32_64_M8, + /* Reg32/Reg64 (prefix width) or Mem16. */ + OT_REG32_64_M16, + /* Reg32/Reg 64 depends on prefix width only. */ + OT_WREG32_64, + /* RM32/RM64 depends on prefix width only. */ + OT_WRM32_64, + /* XMM or Mem32/Mem64 depends on perfix width only. */ + OT_WXMM32_64, + /* XMM is encoded in VEX.VVVV. */ + OT_VXMM, + /* XMM is encoded in the high nibble of an immediate byte. */ + OT_XMM_IMM, + /* YMM/XMM is dependent on VEX.L. */ + OT_YXMM, + /* YMM/XMM (depends on prefix length) is encoded in the high nibble of an immediate byte. */ + OT_YXMM_IMM, + /* YMM is encoded in reg. */ + OT_YMM, + /* YMM or Mem256. */ + OT_YMM256, + /* YMM is encoded in VEX.VVVV. */ + OT_VYMM, + /* YMM/XMM is dependent on VEX.L, and encoded in VEX.VVVV. */ + OT_VYXMM, + /* YMM/XMM or Mem64/Mem256 is dependent on VEX.L. */ + OT_YXMM64_256, + /* YMM/XMM or Mem128/Mem256 is dependent on VEX.L. */ + OT_YXMM128_256, + /* XMM or Mem64/Mem256 is dependent on VEX.L. */ + OT_LXMM64_128, + /* Mem128/Mem256 is dependent on VEX.L. */ + OT_LMEM128_256 +} _OpType; + +/* Flags for instruction: */ + +/* Empty flags indicator: */ +#define INST_FLAGS_NONE (0) +/* The instruction we are going to decode requires ModR/M encoding. */ +#define INST_MODRM_REQUIRED (1) +/* Special treatment for instructions which are in the divided-category but still needs the whole byte for ModR/M... */ +#define INST_NOT_DIVIDED (1 << 1) +/* + * Used explicitly in repeatable instructions, + * which needs a suffix letter in their mnemonic to specify operation-size (depend on operands). + */ +#define INST_16BITS (1 << 2) +/* If the opcode is supported by 80286 and upper models (16/32 bits). */ +#define INST_32BITS (1 << 3) +/* + * Prefix flags (6 types: lock/rep, seg override, addr-size, oper-size, REX, VEX) + * There are several specific instructions that can follow LOCK prefix, + * note that they must be using a memory operand form, otherwise they generate an exception. + */ +#define INST_PRE_LOCK (1 << 4) +/* REPNZ prefix for string instructions only - means an instruction can follow it. */ +#define INST_PRE_REPNZ (1 << 5) +/* REP prefix for string instructions only - means an instruction can follow it. */ +#define INST_PRE_REP (1 << 6) +/* CS override prefix. */ +#define INST_PRE_CS (1 << 7) +/* SS override prefix. */ +#define INST_PRE_SS (1 << 8) +/* DS override prefix. */ +#define INST_PRE_DS (1 << 9) +/* ES override prefix. */ +#define INST_PRE_ES (1 << 10) +/* FS override prefix. Funky Segment :) */ +#define INST_PRE_FS (1 << 11) +/* GS override prefix. Groovy Segment, of course not, duh ! */ +#define INST_PRE_GS (1 << 12) +/* Switch operand size from 32 to 16 and vice versa. */ +#define INST_PRE_OP_SIZE (1 << 13) +/* Switch address size from 32 to 16 and vice versa. */ +#define INST_PRE_ADDR_SIZE (1 << 14) +/* Native instructions which needs suffix letter to indicate their operation-size (and don't depend on operands). */ +#define INST_NATIVE (1 << 15) +/* Use extended mnemonic, means it's an _InstInfoEx structure, which contains another mnemonic for 32 bits specifically. */ +#define INST_USE_EXMNEMONIC (1 << 16) +/* Use third operand, means it's an _InstInfoEx structure, which contains another operand for special instructions. */ +#define INST_USE_OP3 (1 << 17) +/* Use fourth operand, means it's an _InstInfoEx structure, which contains another operand for special instructions. */ +#define INST_USE_OP4 (1 << 18) +/* The instruction's mnemonic depends on the mod value of the ModR/M byte (mod=11, mod!=11). */ +#define INST_MNEMONIC_MODRM_BASED (1 << 19) +/* The instruction uses a ModR/M byte which the MOD must be 11 (for registers operands only). */ +#define INST_MODRR_REQUIRED (1 << 20) +/* The way of 3DNow! instructions are built, we have to handle their locating specially. Suffix imm8 tells which instruction it is. */ +#define INST_3DNOW_FETCH (1 << 21) +/* The instruction needs two suffixes, one for the comparison type (imm8) and the second for its operation size indication (second mnemonic). */ +#define INST_PSEUDO_OPCODE (1 << 22) +/* Invalid instruction at 64 bits decoding mode. */ +#define INST_INVALID_64BITS (1 << 23) +/* Specific instruction can be promoted to 64 bits (without REX, it is promoted automatically). */ +#define INST_64BITS (1 << 24) +/* Indicates the instruction must be REX prefixed in order to use 64 bits operands. */ +#define INST_PRE_REX (1 << 25) +/* Third mnemonic is set. */ +#define INST_USE_EXMNEMONIC2 (1 << 26) +/* Instruction is only valid in 64 bits decoding mode. */ +#define INST_64BITS_FETCH (1 << 27) +/* Forces that the ModRM-REG/Opcode field will be 0. (For EXTRQ). */ +#define INST_FORCE_REG0 (1 << 28) +/* Indicates that instruction is encoded with a VEX prefix. */ +#define INST_PRE_VEX (1 << 29) +/* Indicates that the instruction is encoded with a ModRM byte (REG field specifically). */ +#define INST_MODRM_INCLUDED (1 << 30) +/* Indicates that the first (/destination) operand of the instruction is writable. */ +#define INST_DST_WR (1 << 31) + +#define INST_PRE_REPS (INST_PRE_REPNZ | INST_PRE_REP) +#define INST_PRE_LOKREP_MASK (INST_PRE_LOCK | INST_PRE_REPNZ | INST_PRE_REP) +#define INST_PRE_SEGOVRD_MASK32 (INST_PRE_CS | INST_PRE_SS | INST_PRE_DS | INST_PRE_ES) +#define INST_PRE_SEGOVRD_MASK64 (INST_PRE_FS | INST_PRE_GS) +#define INST_PRE_SEGOVRD_MASK (INST_PRE_SEGOVRD_MASK32 | INST_PRE_SEGOVRD_MASK64) + +/* Extended flags for VEX: */ +/* Indicates that the instruction might have VEX.L encoded. */ +#define INST_VEX_L (1) +/* Indicates that the instruction might have VEX.W encoded. */ +#define INST_VEX_W (1 << 1) +/* Indicates that the mnemonic of the instruction is based on the VEX.W bit. */ +#define INST_MNEMONIC_VEXW_BASED (1 << 2) +/* Indicates that the mnemonic of the instruction is based on the VEX.L bit. */ +#define INST_MNEMONIC_VEXL_BASED (1 << 3) +/* Forces the instruction to be encoded with VEX.L, otherwise it's undefined. */ +#define INST_FORCE_VEXL (1 << 4) +/* + * Indicates that the instruction is based on the MOD field of the ModRM byte. + * (MOD==11: got the right instruction, else skip +4 in prefixed table for the correct instruction). + */ +#define INST_MODRR_BASED (1 << 5) +/* Indicates that the instruction doesn't use the VVVV field of the VEX prefix, if it does then it's undecodable. */ +#define INST_VEX_V_UNUSED (1 << 6) + +/* + * Indicates which operand is being decoded. + * Destination (1st), Source (2nd), op3 (3rd), op4 (4th). + * Used to set the operands' fields in the _DInst structure! + */ +typedef enum {ONT_NONE = -1, ONT_1 = 0, ONT_2 = 1, ONT_3 = 2, ONT_4 = 3} _OperandNumberType; + +/* + * Info about the instruction, source/dest types, its name in text and flags. + * This structure is used for the instructions DB and NOT for the disassembled result code! + * This is the BASE structure, there are extentions to this structure below. + */ + +typedef struct { + uint8_t flagsIndex; /* An index into FlagsTables. */ + uint8_t s, d; /* OpType. */ + uint8_t meta; /* Hi 5 bits = Instruction set class | Lo 3 bits = flow control flags. */ + uint16_t opcodeId; /* The opcodeId is really a byte-offset into the mnemonics table. */ +} _InstInfo; + +/* + * There are merely few instructions which need a second mnemonic for 32 bits. + * Or a third for 64 bits. Therefore sometimes the second mnemonic is empty but not the third. + * In all decoding modes the first mnemonic is the default. + * A flag will indicate it uses another mnemonic. + * + * There are a couple of (SSE4) instructions in the whole DB which need both op3 and 3rd mnemonic for 64bits, + * therefore, I decided to make the extended structure contain all extra info in the same structure. + * There are a few instructions (SHLD/SHRD/IMUL and SSE too) which use third operand (or a fourth). + * A flag will indicate it uses a third/fourth operand. + * + */ +typedef struct { + /* Base structure (doesn't get accessed directly from code). */ + _InstInfo BASE; + + /* Extended starts here. */ + uint8_t flagsEx; /* 8 bits are enough, in the future we might make it a bigger integer. */ + uint8_t op3, op4; /* OpType. */ + uint16_t opcodeId2, opcodeId3; +} _InstInfoEx; + +/* Trie data structure node type: */ +typedef enum { + INT_NOTEXISTS = 0, /* Not exists. */ + INT_INFO = 1, /* It's an instruction info. */ + INT_INFOEX, + INT_LIST_GROUP, + INT_LIST_FULL, + INT_LIST_DIVIDED, + INT_LIST_PREFIXED +} _InstNodeType; + +/* Used to check instType < INT_INFOS, means we got an inst-info. Cause it has to be only one of them. */ +#define INT_INFOS (INT_LIST_GROUP) + +/* Instruction node is treated as { int index:13; int type:3; } */ +typedef uint16_t _InstNode; + +/* Helper macro to read the actual flags that are associated with an inst-info. */ +#define INST_INFO_FLAGS(ii) (FlagsTable[(ii)->flagsIndex]) + +_InstInfo* inst_lookup(_CodeInfo* ci, _PrefixState* ps); +_InstInfo* inst_lookup_3dnow(_CodeInfo* ci); + +#endif /* INSTRUCTIONS_H */ diff --git a/distorm3.2-package/src/insts.c b/distorm3.2-package/src/insts.c new file mode 100644 index 0000000..4c9179b --- /dev/null +++ b/distorm3.2-package/src/insts.c @@ -0,0 +1,7343 @@ +/* +insts.c + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2012 Gil Dabah + +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 +*/ + + +#include "config.h" +#include "insts.h" +#include "instructions.h" + + +/* + * GENERATED BY disOps at Mon May 07 05:39:59 2012 + */ + +/* See x86defs.c if you get an error here. */ +_iflags FlagsTable[97 + 5] = { +INST_MODRM_REQUIRED, +INST_MODRM_REQUIRED | INST_PRE_REX | INST_64BITS, +INST_FLAGS_NONE, +INST_FLAGS_NONE, +INST_32BITS | INST_MODRM_REQUIRED | INST_3DNOW_FETCH, +0x80000011, +0x80000000, +0x800400, +0x80800400, +0x800080, +0x800100, +0x80800100, +0x800200, +0x80800200, +0x800000, +0x1, +0x0, +0x80800000, +0x1000000, +0x81000000, +0x808000, +0x800001, +0x1000001, +0x80020001, +0x1002000, +0x60, +0x64, +0x80000001, +0x4010000, +0x1008000, +0x80000060, +0x83000064, +0x3000064, +0x83000000, +0x3008000, +0x200, +0xc000, +0x4014000, +0x8, +0x81000009, +0x9, +0x80000009, +0x1000808, +0x81000808, +0x80020009, +0x1001008, +0x81001008, +0x80000019, +0x3000009, +0x83000009, +0x83000008, +0xc0000011, +0x40000001, +0xc0800011, +0x40800001, +0xc0000019, +0xc1000001, +0xc0000001, +0x40000000, +0x40000008, +0x40000009, +0x41000001, +0x43000001, +0xc0000003, +0x40000003, +0x48000000, +0x200009, +0x20000009, +0x60020009, +0x60000009, +0x80090009, +0x200b0009, +0x20020009, +0x80100009, +0x21100009, +0x87000009, +0x20009, +0x20000008, +0x1000009, +0x10020009, +0x160009, +0x100009, +0x47000009, +0x47090009, +0x40090009, +0x80002009, +0xc0000009, +0x2001, +0x80002001, +0x410009, +0x20420009, +0x20060009, +0x120009, +0x21020009, +0xc7000019, +0x20100009, +0x40002009, +0x40002008, +0x4020009, +0x40100009, +0x60120009, +0x41000009 +}; + +_InstNode Table_0F = 256; +_InstNode Table_0F_0F = 1312; +_InstNode Table_0F_38 = 1768; +_InstNode Table_0F_3A = 2024; + +_InstInfo InstInfos[] = { + /*II_00*/ {0x5, 9, 15, 8, 11}, + /*II_01*/ {0x5, 11, 17, 8, 11}, + /*II_02*/ {0x5, 15, 9, 8, 11}, + /*II_03*/ {0x5, 17, 11, 8, 11}, + /*II_04*/ {0x6, 1, 33, 8, 11}, + /*II_05*/ {0x6, 3, 35, 8, 11}, + /*II_06*/ {0x7, 0, 32, 8, 16}, + /*II_07*/ {0x8, 0, 32, 8, 22}, + /*II_08*/ {0x5, 9, 15, 8, 27}, + /*II_09*/ {0x5, 11, 17, 8, 27}, + /*II_0A*/ {0x5, 15, 9, 8, 27}, + /*II_0B*/ {0x5, 17, 11, 8, 27}, + /*II_0C*/ {0x6, 1, 33, 8, 27}, + /*II_0D*/ {0x6, 3, 35, 8, 27}, + /*II_0E*/ {0x9, 0, 32, 8, 16}, + /*II_10*/ {0x5, 9, 15, 8, 31}, + /*II_11*/ {0x5, 11, 17, 8, 31}, + /*II_12*/ {0x5, 15, 9, 8, 31}, + /*II_13*/ {0x5, 17, 11, 8, 31}, + /*II_14*/ {0x6, 1, 33, 8, 31}, + /*II_15*/ {0x6, 3, 35, 8, 31}, + /*II_16*/ {0xa, 0, 32, 8, 16}, + /*II_17*/ {0xb, 0, 32, 8, 22}, + /*II_18*/ {0x5, 9, 15, 8, 36}, + /*II_19*/ {0x5, 11, 17, 8, 36}, + /*II_1A*/ {0x5, 15, 9, 8, 36}, + /*II_1B*/ {0x5, 17, 11, 8, 36}, + /*II_1C*/ {0x6, 1, 33, 8, 36}, + /*II_1D*/ {0x6, 3, 35, 8, 36}, + /*II_1E*/ {0xc, 0, 32, 8, 16}, + /*II_1F*/ {0xd, 0, 32, 8, 22}, + /*II_20*/ {0x5, 9, 15, 8, 41}, + /*II_21*/ {0x5, 11, 17, 8, 41}, + /*II_22*/ {0x5, 15, 9, 8, 41}, + /*II_23*/ {0x5, 17, 11, 8, 41}, + /*II_24*/ {0x6, 1, 33, 8, 41}, + /*II_25*/ {0x6, 3, 35, 8, 41}, + /*II_27*/ {0xe, 0, 0, 8, 46}, + /*II_28*/ {0x5, 9, 15, 8, 51}, + /*II_29*/ {0x5, 11, 17, 8, 51}, + /*II_2A*/ {0x5, 15, 9, 8, 51}, + /*II_2B*/ {0x5, 17, 11, 8, 51}, + /*II_2C*/ {0x6, 1, 33, 8, 51}, + /*II_2D*/ {0x6, 3, 35, 8, 51}, + /*II_2F*/ {0xe, 0, 0, 8, 56}, + /*II_30*/ {0x5, 9, 15, 8, 61}, + /*II_31*/ {0x5, 11, 17, 8, 61}, + /*II_32*/ {0x5, 15, 9, 8, 61}, + /*II_33*/ {0x5, 17, 11, 8, 61}, + /*II_34*/ {0x6, 1, 33, 8, 61}, + /*II_35*/ {0x6, 3, 35, 8, 61}, + /*II_37*/ {0xe, 0, 0, 8, 66}, + /*II_38*/ {0xf, 9, 15, 8, 71}, + /*II_39*/ {0xf, 11, 17, 8, 71}, + /*II_3A*/ {0xf, 15, 9, 8, 71}, + /*II_3B*/ {0xf, 17, 11, 8, 71}, + /*II_3C*/ {0x10, 1, 33, 8, 71}, + /*II_3D*/ {0x10, 3, 35, 8, 71}, + /*II_3F*/ {0xe, 0, 0, 8, 76}, + /*II_40*/ {0x11, 0, 54, 8, 81}, + /*II_40*/ {0x11, 0, 54, 8, 81}, + /*II_40*/ {0x11, 0, 54, 8, 81}, + /*II_40*/ {0x11, 0, 54, 8, 81}, + /*II_40*/ {0x11, 0, 54, 8, 81}, + /*II_40*/ {0x11, 0, 54, 8, 81}, + /*II_40*/ {0x11, 0, 54, 8, 81}, + /*II_40*/ {0x11, 0, 54, 8, 81}, + /*II_48*/ {0x11, 0, 54, 8, 86}, + /*II_48*/ {0x11, 0, 54, 8, 86}, + /*II_48*/ {0x11, 0, 54, 8, 86}, + /*II_48*/ {0x11, 0, 54, 8, 86}, + /*II_48*/ {0x11, 0, 54, 8, 86}, + /*II_48*/ {0x11, 0, 54, 8, 86}, + /*II_48*/ {0x11, 0, 54, 8, 86}, + /*II_48*/ {0x11, 0, 54, 8, 86}, + /*II_50*/ {0x12, 0, 54, 8, 16}, + /*II_50*/ {0x12, 0, 54, 8, 16}, + /*II_50*/ {0x12, 0, 54, 8, 16}, + /*II_50*/ {0x12, 0, 54, 8, 16}, + /*II_50*/ {0x12, 0, 54, 8, 16}, + /*II_50*/ {0x12, 0, 54, 8, 16}, + /*II_50*/ {0x12, 0, 54, 8, 16}, + /*II_50*/ {0x12, 0, 54, 8, 16}, + /*II_58*/ {0x13, 0, 54, 8, 22}, + /*II_58*/ {0x13, 0, 54, 8, 22}, + /*II_58*/ {0x13, 0, 54, 8, 22}, + /*II_58*/ {0x13, 0, 54, 8, 22}, + /*II_58*/ {0x13, 0, 54, 8, 22}, + /*II_58*/ {0x13, 0, 54, 8, 22}, + /*II_58*/ {0x13, 0, 54, 8, 22}, + /*II_58*/ {0x13, 0, 54, 8, 22}, + /*II_60*/ {0x14, 0, 0, 8, 91}, + /*II_61*/ {0x14, 0, 0, 8, 98}, + /*II_62*/ {0x15, 42, 11, 8, 104}, + /*II_63*/ {0x16, 10, 16, 8, 111}, + /*II_68*/ {0x12, 0, 3, 8, 16}, + /*II_6A*/ {0x18, 0, 5, 8, 16}, + /*II_6C*/ {0x19, 59, 56, 8, 123}, + /*II_6D*/ {0x1a, 59, 56, 8, 123}, + /*II_6E*/ {0x19, 55, 59, 8, 128}, + /*II_6F*/ {0x1a, 55, 59, 8, 128}, + /*II_70*/ {0x12, 0, 40, 13, 134}, + /*II_71*/ {0x12, 0, 40, 13, 138}, + /*II_72*/ {0x12, 0, 40, 13, 143}, + /*II_73*/ {0x12, 0, 40, 13, 147}, + /*II_74*/ {0x12, 0, 40, 13, 152}, + /*II_75*/ {0x12, 0, 40, 13, 156}, + /*II_76*/ {0x12, 0, 40, 13, 161}, + /*II_77*/ {0x12, 0, 40, 13, 166}, + /*II_78*/ {0x12, 0, 40, 13, 170}, + /*II_79*/ {0x12, 0, 40, 13, 174}, + /*II_7A*/ {0x12, 0, 40, 13, 179}, + /*II_7B*/ {0x12, 0, 40, 13, 183}, + /*II_7C*/ {0x12, 0, 40, 13, 188}, + /*II_7D*/ {0x12, 0, 40, 13, 192}, + /*II_7E*/ {0x12, 0, 40, 13, 197}, + /*II_7F*/ {0x12, 0, 40, 13, 202}, + /*II_84*/ {0xf, 9, 15, 8, 206}, + /*II_85*/ {0xf, 11, 17, 8, 206}, + /*II_86*/ {0x5, 9, 15, 8, 212}, + /*II_87*/ {0x5, 11, 17, 8, 212}, + /*II_88*/ {0x1b, 9, 15, 8, 218}, + /*II_89*/ {0x1b, 11, 17, 8, 218}, + /*II_8A*/ {0x1b, 15, 9, 8, 218}, + /*II_8B*/ {0x1b, 17, 11, 8, 218}, + /*II_8C*/ {0x1b, 31, 28, 8, 218}, + /*II_8D*/ {0x1b, 42, 11, 8, 223}, + /*II_8E*/ {0x1b, 28, 31, 8, 218}, + /*II_90*/ {0x6, 35, 54, 8, 212}, + /*II_91*/ {0x6, 35, 54, 8, 212}, + /*II_92*/ {0x6, 35, 54, 8, 212}, + /*II_93*/ {0x6, 35, 54, 8, 212}, + /*II_94*/ {0x6, 35, 54, 8, 212}, + /*II_95*/ {0x6, 35, 54, 8, 212}, + /*II_96*/ {0x6, 35, 54, 8, 212}, + /*II_97*/ {0x6, 35, 54, 8, 212}, + /*II_9A*/ {0xe, 0, 38, 9, 260}, + /*II_9C*/ {0x1d, 0, 0, 8, 270}, + /*II_9D*/ {0x1d, 0, 0, 8, 277}, + /*II_9E*/ {0x10, 0, 0, 8, 283}, + /*II_9F*/ {0x10, 0, 0, 8, 289}, + /*II_A0*/ {0x6, 49, 33, 8, 218}, + /*II_A1*/ {0x6, 50, 35, 8, 218}, + /*II_A2*/ {0x6, 33, 49, 8, 218}, + /*II_A3*/ {0x6, 35, 50, 8, 218}, + /*II_A4*/ {0x1e, 55, 56, 8, 295}, + /*II_A5*/ {0x1f, 55, 56, 8, 295}, + /*II_A6*/ {0x19, 56, 55, 8, 301}, + /*II_A7*/ {0x20, 56, 55, 8, 301}, + /*II_A8*/ {0x10, 1, 33, 8, 206}, + /*II_A9*/ {0x10, 3, 35, 8, 206}, + /*II_AA*/ {0x19, 33, 56, 8, 307}, + /*II_AB*/ {0x20, 35, 56, 8, 307}, + /*II_AC*/ {0x19, 55, 33, 8, 313}, + /*II_AD*/ {0x20, 55, 35, 8, 313}, + /*II_AE*/ {0x19, 33, 56, 8, 319}, + /*II_AF*/ {0x20, 35, 56, 8, 319}, + /*II_B0*/ {0x6, 1, 53, 8, 218}, + /*II_B0*/ {0x6, 1, 53, 8, 218}, + /*II_B0*/ {0x6, 1, 53, 8, 218}, + /*II_B0*/ {0x6, 1, 53, 8, 218}, + /*II_B0*/ {0x6, 1, 53, 8, 218}, + /*II_B0*/ {0x6, 1, 53, 8, 218}, + /*II_B0*/ {0x6, 1, 53, 8, 218}, + /*II_B0*/ {0x6, 1, 53, 8, 218}, + /*II_B8*/ {0x21, 3, 54, 8, 218}, + /*II_B8*/ {0x21, 3, 54, 8, 218}, + /*II_B8*/ {0x21, 3, 54, 8, 218}, + /*II_B8*/ {0x21, 3, 54, 8, 218}, + /*II_B8*/ {0x21, 3, 54, 8, 218}, + /*II_B8*/ {0x21, 3, 54, 8, 218}, + /*II_B8*/ {0x21, 3, 54, 8, 218}, + /*II_B8*/ {0x21, 3, 54, 8, 218}, + /*II_C2*/ {0x12, 0, 2, 10, 325}, + /*II_C3*/ {0x12, 0, 0, 10, 325}, + /*II_C4*/ {0x15, 37, 11, 8, 330}, + /*II_C5*/ {0x15, 37, 11, 8, 335}, + /*II_C8*/ {0x12, 8, 6, 8, 340}, + /*II_C9*/ {0x12, 0, 0, 8, 347}, + /*II_CA*/ {0x22, 0, 2, 10, 354}, + /*II_CB*/ {0x22, 0, 0, 10, 354}, + /*II_CC*/ {0x10, 0, 0, 14, 360}, + /*II_CD*/ {0x10, 0, 1, 14, 367}, + /*II_CE*/ {0xe, 0, 0, 14, 372}, + /*II_CF*/ {0x22, 0, 0, 10, 378}, + /*II_D4*/ {0xe, 0, 1, 8, 384}, + /*II_D5*/ {0xe, 0, 1, 8, 389}, + /*II_D6*/ {0xe, 0, 0, 8, 394}, + /*II_D7*/ {0x23, 0, 57, 8, 400}, + /*II_E0*/ {0x24, 0, 40, 13, 406}, + /*II_E1*/ {0x24, 0, 40, 13, 414}, + /*II_E2*/ {0x24, 0, 40, 13, 421}, + /*II_E4*/ {0x6, 1, 33, 8, 447}, + /*II_E5*/ {0x6, 1, 36, 8, 447}, + /*II_E6*/ {0x10, 33, 1, 8, 451}, + /*II_E7*/ {0x10, 36, 1, 8, 451}, + /*II_E8*/ {0x12, 0, 41, 9, 456}, + /*II_E9*/ {0x12, 0, 41, 12, 462}, + /*II_EA*/ {0xe, 0, 38, 12, 467}, + /*II_EB*/ {0x12, 0, 40, 12, 462}, + /*II_EC*/ {0x6, 59, 33, 8, 447}, + /*II_ED*/ {0x6, 59, 36, 8, 447}, + /*II_EE*/ {0x10, 33, 59, 8, 451}, + /*II_EF*/ {0x10, 36, 59, 8, 451}, + /*II_F1*/ {0x10, 0, 0, 14, 476}, + /*II_F4*/ {0x10, 0, 0, 8, 482}, + /*II_F5*/ {0x10, 0, 0, 8, 487}, + /*II_F8*/ {0x10, 0, 0, 8, 492}, + /*II_F9*/ {0x10, 0, 0, 8, 497}, + /*II_FA*/ {0x10, 0, 0, 8, 502}, + /*II_FB*/ {0x10, 0, 0, 8, 507}, + /*II_FC*/ {0x10, 0, 0, 8, 512}, + /*II_FD*/ {0x10, 0, 0, 8, 517}, + /*II_0F_02*/ {0xf, 16, 11, 8, 522}, + /*II_0F_03*/ {0xf, 16, 11, 8, 527}, + /*II_0F_05*/ {0x26, 0, 0, 27, 532}, + /*II_0F_06*/ {0x26, 0, 0, 8, 541}, + /*II_0F_07*/ {0x26, 0, 0, 27, 547}, + /*II_0F_08*/ {0x26, 0, 0, 8, 555}, + /*II_0F_09*/ {0x26, 0, 0, 8, 561}, + /*II_0F_0B*/ {0x26, 0, 0, 14, 569}, + /*II_0F_0E*/ {0x10, 0, 0, 96, 574}, + /*II_0F_1F*/ {0xf, 0, 17, 8, 581}, + /*II_0F_20*/ {0x27, 29, 14, 8, 218}, + /*II_0F_21*/ {0x27, 30, 14, 8, 218}, + /*II_0F_22*/ {0x27, 14, 29, 8, 218}, + /*II_0F_23*/ {0x27, 14, 30, 8, 218}, + /*II_0F_30*/ {0x26, 0, 0, 8, 586}, + /*II_0F_31*/ {0x26, 0, 0, 8, 593}, + /*II_0F_32*/ {0x26, 0, 0, 8, 600}, + /*II_0F_33*/ {0x26, 0, 0, 8, 607}, + /*II_0F_34*/ {0x26, 0, 0, 27, 614}, + /*II_0F_35*/ {0x26, 0, 0, 27, 624}, + /*II_0F_37*/ {0x28, 0, 0, 8, 633}, + /*II_0F_40*/ {0x29, 17, 11, 31, 641}, + /*II_0F_41*/ {0x29, 17, 11, 31, 648}, + /*II_0F_42*/ {0x29, 17, 11, 31, 656}, + /*II_0F_43*/ {0x29, 17, 11, 31, 663}, + /*II_0F_44*/ {0x29, 17, 11, 31, 671}, + /*II_0F_45*/ {0x29, 17, 11, 31, 678}, + /*II_0F_46*/ {0x29, 17, 11, 31, 686}, + /*II_0F_47*/ {0x29, 17, 11, 31, 694}, + /*II_0F_48*/ {0x29, 17, 11, 31, 701}, + /*II_0F_49*/ {0x29, 17, 11, 31, 708}, + /*II_0F_4A*/ {0x29, 17, 11, 31, 716}, + /*II_0F_4B*/ {0x29, 17, 11, 31, 723}, + /*II_0F_4C*/ {0x29, 17, 11, 31, 731}, + /*II_0F_4D*/ {0x29, 17, 11, 31, 738}, + /*II_0F_4E*/ {0x29, 17, 11, 31, 746}, + /*II_0F_4F*/ {0x29, 17, 11, 31, 754}, + /*II_0F_80*/ {0x26, 0, 41, 13, 134}, + /*II_0F_81*/ {0x26, 0, 41, 13, 138}, + /*II_0F_82*/ {0x26, 0, 41, 13, 143}, + /*II_0F_83*/ {0x26, 0, 41, 13, 147}, + /*II_0F_84*/ {0x26, 0, 41, 13, 152}, + /*II_0F_85*/ {0x26, 0, 41, 13, 156}, + /*II_0F_86*/ {0x26, 0, 41, 13, 161}, + /*II_0F_87*/ {0x26, 0, 41, 13, 166}, + /*II_0F_88*/ {0x26, 0, 41, 13, 170}, + /*II_0F_89*/ {0x26, 0, 41, 13, 174}, + /*II_0F_8A*/ {0x26, 0, 41, 13, 179}, + /*II_0F_8B*/ {0x26, 0, 41, 13, 183}, + /*II_0F_8C*/ {0x26, 0, 41, 13, 188}, + /*II_0F_8D*/ {0x26, 0, 41, 13, 192}, + /*II_0F_8E*/ {0x26, 0, 41, 13, 197}, + /*II_0F_8F*/ {0x26, 0, 41, 13, 202}, + /*II_0F_90*/ {0x29, 0, 15, 8, 761}, + /*II_0F_91*/ {0x29, 0, 15, 8, 767}, + /*II_0F_92*/ {0x29, 0, 15, 8, 774}, + /*II_0F_93*/ {0x29, 0, 15, 8, 780}, + /*II_0F_94*/ {0x29, 0, 15, 8, 787}, + /*II_0F_95*/ {0x29, 0, 15, 8, 793}, + /*II_0F_96*/ {0x29, 0, 15, 8, 800}, + /*II_0F_97*/ {0x29, 0, 15, 8, 807}, + /*II_0F_98*/ {0x29, 0, 15, 8, 813}, + /*II_0F_99*/ {0x29, 0, 15, 8, 819}, + /*II_0F_9A*/ {0x29, 0, 15, 8, 826}, + /*II_0F_9B*/ {0x29, 0, 15, 8, 832}, + /*II_0F_9C*/ {0x29, 0, 15, 8, 839}, + /*II_0F_9D*/ {0x29, 0, 15, 8, 845}, + /*II_0F_9E*/ {0x29, 0, 15, 8, 852}, + /*II_0F_9F*/ {0x29, 0, 15, 8, 859}, + /*II_0F_A0*/ {0x2a, 0, 32, 8, 16}, + /*II_0F_A1*/ {0x2b, 0, 32, 8, 22}, + /*II_0F_A2*/ {0x26, 0, 0, 8, 865}, + /*II_0F_A3*/ {0x29, 11, 17, 8, 872}, + /*II_0F_A8*/ {0x2d, 0, 32, 8, 16}, + /*II_0F_A9*/ {0x2e, 0, 32, 8, 22}, + /*II_0F_AA*/ {0x26, 0, 0, 8, 882}, + /*II_0F_AB*/ {0x2f, 11, 17, 8, 887}, + /*II_0F_AF*/ {0x29, 17, 11, 8, 117}, + /*II_0F_B0*/ {0x2f, 9, 15, 8, 898}, + /*II_0F_B1*/ {0x2f, 11, 17, 8, 898}, + /*II_0F_B2*/ {0x30, 37, 11, 8, 907}, + /*II_0F_B3*/ {0x2f, 11, 17, 8, 912}, + /*II_0F_B4*/ {0x30, 37, 11, 8, 917}, + /*II_0F_B5*/ {0x30, 37, 11, 8, 922}, + /*II_0F_B6*/ {0x29, 15, 11, 8, 927}, + /*II_0F_B7*/ {0x31, 16, 11, 8, 927}, + /*II_0F_B9*/ {0x26, 0, 0, 14, 569}, + /*II_0F_BB*/ {0x2f, 11, 17, 8, 934}, + /*II_0F_BE*/ {0x29, 15, 11, 8, 939}, + /*II_0F_BF*/ {0x31, 16, 11, 8, 939}, + /*II_0F_C0*/ {0x2f, 9, 15, 8, 946}, + /*II_0F_C1*/ {0x2f, 11, 17, 8, 946}, + /*II_0F_C3*/ {0x31, 13, 45, 48, 952}, + /*II_0F_C8*/ {0x32, 0, 54, 8, 960}, + /*II_0F_C8*/ {0x32, 0, 54, 8, 960}, + /*II_0F_C8*/ {0x32, 0, 54, 8, 960}, + /*II_0F_C8*/ {0x32, 0, 54, 8, 960}, + /*II_0F_C8*/ {0x32, 0, 54, 8, 960}, + /*II_0F_C8*/ {0x32, 0, 54, 8, 960}, + /*II_0F_C8*/ {0x32, 0, 54, 8, 960}, + /*II_0F_C8*/ {0x32, 0, 54, 8, 960}, + /*II_80_00*/ {0x33, 1, 15, 8, 11}, + /*II_80_01*/ {0x33, 1, 15, 8, 27}, + /*II_80_02*/ {0x33, 1, 15, 8, 31}, + /*II_80_03*/ {0x33, 1, 15, 8, 36}, + /*II_80_04*/ {0x33, 1, 15, 8, 41}, + /*II_80_05*/ {0x33, 1, 15, 8, 51}, + /*II_80_06*/ {0x33, 1, 15, 8, 61}, + /*II_80_07*/ {0x34, 1, 15, 8, 71}, + /*II_81_00*/ {0x33, 3, 17, 8, 11}, + /*II_81_01*/ {0x33, 3, 17, 8, 27}, + /*II_81_02*/ {0x33, 3, 17, 8, 31}, + /*II_81_03*/ {0x33, 3, 17, 8, 36}, + /*II_81_04*/ {0x33, 3, 17, 8, 41}, + /*II_81_05*/ {0x33, 3, 17, 8, 51}, + /*II_81_06*/ {0x33, 3, 17, 8, 61}, + /*II_81_07*/ {0x34, 3, 17, 8, 71}, + /*II_82_00*/ {0x35, 1, 15, 8, 11}, + /*II_82_01*/ {0x35, 1, 15, 8, 27}, + /*II_82_02*/ {0x35, 1, 15, 8, 31}, + /*II_82_03*/ {0x35, 1, 15, 8, 36}, + /*II_82_04*/ {0x35, 1, 15, 8, 41}, + /*II_82_05*/ {0x35, 1, 15, 8, 51}, + /*II_82_06*/ {0x35, 1, 15, 8, 61}, + /*II_82_07*/ {0x36, 1, 15, 8, 71}, + /*II_83_00*/ {0x33, 5, 17, 8, 11}, + /*II_83_01*/ {0x37, 5, 17, 8, 27}, + /*II_83_02*/ {0x33, 5, 17, 8, 31}, + /*II_83_03*/ {0x33, 5, 17, 8, 36}, + /*II_83_04*/ {0x37, 5, 17, 8, 41}, + /*II_83_05*/ {0x33, 5, 17, 8, 51}, + /*II_83_06*/ {0x37, 5, 17, 8, 61}, + /*II_83_07*/ {0x34, 5, 17, 8, 71}, + /*II_8F_00*/ {0x38, 0, 17, 8, 22}, + /*II_C0_00*/ {0x39, 1, 15, 8, 967}, + /*II_C0_01*/ {0x39, 1, 15, 8, 972}, + /*II_C0_02*/ {0x39, 1, 15, 8, 977}, + /*II_C0_03*/ {0x39, 1, 15, 8, 982}, + /*II_C0_04*/ {0x39, 1, 15, 8, 987}, + /*II_C0_05*/ {0x39, 1, 15, 8, 992}, + /*II_C0_06*/ {0x39, 1, 15, 8, 997}, + /*II_C0_07*/ {0x39, 1, 15, 8, 1002}, + /*II_C1_00*/ {0x39, 1, 17, 8, 967}, + /*II_C1_01*/ {0x39, 1, 17, 8, 972}, + /*II_C1_02*/ {0x39, 1, 17, 8, 977}, + /*II_C1_03*/ {0x39, 1, 17, 8, 982}, + /*II_C1_04*/ {0x39, 1, 17, 8, 987}, + /*II_C1_05*/ {0x39, 1, 17, 8, 992}, + /*II_C1_06*/ {0x39, 1, 17, 8, 997}, + /*II_C1_07*/ {0x39, 1, 17, 8, 1002}, + /*II_C6_00*/ {0x39, 1, 15, 8, 218}, + /*II_C7_00*/ {0x39, 3, 17, 8, 218}, + /*II_D0_00*/ {0x39, 51, 15, 8, 967}, + /*II_D0_01*/ {0x39, 51, 15, 8, 972}, + /*II_D0_02*/ {0x39, 51, 15, 8, 977}, + /*II_D0_03*/ {0x39, 51, 15, 8, 982}, + /*II_D0_04*/ {0x39, 51, 15, 8, 987}, + /*II_D0_05*/ {0x39, 51, 15, 8, 992}, + /*II_D0_06*/ {0x39, 51, 15, 8, 997}, + /*II_D0_07*/ {0x39, 51, 15, 8, 1002}, + /*II_D1_00*/ {0x39, 51, 17, 8, 967}, + /*II_D1_01*/ {0x39, 51, 17, 8, 972}, + /*II_D1_02*/ {0x39, 51, 17, 8, 977}, + /*II_D1_03*/ {0x39, 51, 17, 8, 982}, + /*II_D1_04*/ {0x39, 51, 17, 8, 987}, + /*II_D1_05*/ {0x39, 51, 17, 8, 992}, + /*II_D1_06*/ {0x39, 51, 17, 8, 997}, + /*II_D1_07*/ {0x39, 51, 17, 8, 1002}, + /*II_D2_00*/ {0x39, 52, 15, 8, 967}, + /*II_D2_01*/ {0x39, 52, 15, 8, 972}, + /*II_D2_02*/ {0x39, 52, 15, 8, 977}, + /*II_D2_03*/ {0x39, 52, 15, 8, 982}, + /*II_D2_04*/ {0x39, 52, 15, 8, 987}, + /*II_D2_05*/ {0x39, 52, 15, 8, 992}, + /*II_D2_06*/ {0x39, 52, 15, 8, 997}, + /*II_D2_07*/ {0x39, 52, 15, 8, 1002}, + /*II_D3_00*/ {0x39, 52, 17, 8, 967}, + /*II_D3_01*/ {0x39, 52, 17, 8, 972}, + /*II_D3_02*/ {0x39, 52, 17, 8, 977}, + /*II_D3_03*/ {0x39, 52, 17, 8, 982}, + /*II_D3_04*/ {0x39, 52, 17, 8, 987}, + /*II_D3_05*/ {0x39, 52, 17, 8, 992}, + /*II_D3_06*/ {0x39, 52, 17, 8, 997}, + /*II_D3_07*/ {0x39, 52, 17, 8, 1002}, + /*II_D8_00*/ {0x34, 0, 21, 16, 1007}, + /*II_D8_01*/ {0x34, 0, 21, 16, 1013}, + /*II_D8_02*/ {0x34, 0, 21, 16, 1019}, + /*II_D8_03*/ {0x34, 0, 21, 16, 1025}, + /*II_D8_04*/ {0x34, 0, 21, 16, 1032}, + /*II_D8_05*/ {0x34, 0, 21, 16, 1038}, + /*II_D8_06*/ {0x34, 0, 21, 16, 1045}, + /*II_D8_07*/ {0x34, 0, 21, 16, 1051}, + /*II_D8_C0*/ {0x3a, 0, 62, 16, 1007}, + /*II_D8_C0*/ {0x3a, 0, 62, 16, 1007}, + /*II_D8_C0*/ {0x3a, 0, 62, 16, 1007}, + /*II_D8_C0*/ {0x3a, 0, 62, 16, 1007}, + /*II_D8_C0*/ {0x3a, 0, 62, 16, 1007}, + /*II_D8_C0*/ {0x3a, 0, 62, 16, 1007}, + /*II_D8_C0*/ {0x3a, 0, 62, 16, 1007}, + /*II_D8_C0*/ {0x3a, 0, 62, 16, 1007}, + /*II_D8_C8*/ {0x3a, 0, 62, 16, 1013}, + /*II_D8_C8*/ {0x3a, 0, 62, 16, 1013}, + /*II_D8_C8*/ {0x3a, 0, 62, 16, 1013}, + /*II_D8_C8*/ {0x3a, 0, 62, 16, 1013}, + /*II_D8_C8*/ {0x3a, 0, 62, 16, 1013}, + /*II_D8_C8*/ {0x3a, 0, 62, 16, 1013}, + /*II_D8_C8*/ {0x3a, 0, 62, 16, 1013}, + /*II_D8_C8*/ {0x3a, 0, 62, 16, 1013}, + /*II_D8_D0*/ {0x3a, 0, 61, 16, 1019}, + /*II_D8_D0*/ {0x3a, 0, 61, 16, 1019}, + /*II_D8_D0*/ {0x3a, 0, 61, 16, 1019}, + /*II_D8_D0*/ {0x3a, 0, 61, 16, 1019}, + /*II_D8_D0*/ {0x3a, 0, 61, 16, 1019}, + /*II_D8_D0*/ {0x3a, 0, 61, 16, 1019}, + /*II_D8_D0*/ {0x3a, 0, 61, 16, 1019}, + /*II_D8_D0*/ {0x3a, 0, 61, 16, 1019}, + /*II_D8_D8*/ {0x3a, 0, 61, 16, 1025}, + /*II_D8_D9*/ {0x3a, 0, 0, 16, 1025}, + /*II_D8_D8*/ {0x3a, 0, 61, 16, 1025}, + /*II_D8_D8*/ {0x3a, 0, 61, 16, 1025}, + /*II_D8_D8*/ {0x3a, 0, 61, 16, 1025}, + /*II_D8_D8*/ {0x3a, 0, 61, 16, 1025}, + /*II_D8_D8*/ {0x3a, 0, 61, 16, 1025}, + /*II_D8_D8*/ {0x3a, 0, 61, 16, 1025}, + /*II_D8_E0*/ {0x3a, 0, 62, 16, 1032}, + /*II_D8_E0*/ {0x3a, 0, 62, 16, 1032}, + /*II_D8_E0*/ {0x3a, 0, 62, 16, 1032}, + /*II_D8_E0*/ {0x3a, 0, 62, 16, 1032}, + /*II_D8_E0*/ {0x3a, 0, 62, 16, 1032}, + /*II_D8_E0*/ {0x3a, 0, 62, 16, 1032}, + /*II_D8_E0*/ {0x3a, 0, 62, 16, 1032}, + /*II_D8_E0*/ {0x3a, 0, 62, 16, 1032}, + /*II_D8_E8*/ {0x3a, 0, 62, 16, 1038}, + /*II_D8_E8*/ {0x3a, 0, 62, 16, 1038}, + /*II_D8_E8*/ {0x3a, 0, 62, 16, 1038}, + /*II_D8_E8*/ {0x3a, 0, 62, 16, 1038}, + /*II_D8_E8*/ {0x3a, 0, 62, 16, 1038}, + /*II_D8_E8*/ {0x3a, 0, 62, 16, 1038}, + /*II_D8_E8*/ {0x3a, 0, 62, 16, 1038}, + /*II_D8_E8*/ {0x3a, 0, 62, 16, 1038}, + /*II_D8_F0*/ {0x3a, 0, 62, 16, 1045}, + /*II_D8_F0*/ {0x3a, 0, 62, 16, 1045}, + /*II_D8_F0*/ {0x3a, 0, 62, 16, 1045}, + /*II_D8_F0*/ {0x3a, 0, 62, 16, 1045}, + /*II_D8_F0*/ {0x3a, 0, 62, 16, 1045}, + /*II_D8_F0*/ {0x3a, 0, 62, 16, 1045}, + /*II_D8_F0*/ {0x3a, 0, 62, 16, 1045}, + /*II_D8_F0*/ {0x3a, 0, 62, 16, 1045}, + /*II_D8_F8*/ {0x3a, 0, 62, 16, 1051}, + /*II_D8_F8*/ {0x3a, 0, 62, 16, 1051}, + /*II_D8_F8*/ {0x3a, 0, 62, 16, 1051}, + /*II_D8_F8*/ {0x3a, 0, 62, 16, 1051}, + /*II_D8_F8*/ {0x3a, 0, 62, 16, 1051}, + /*II_D8_F8*/ {0x3a, 0, 62, 16, 1051}, + /*II_D8_F8*/ {0x3a, 0, 62, 16, 1051}, + /*II_D8_F8*/ {0x3a, 0, 62, 16, 1051}, + /*II_D9_00*/ {0x34, 0, 21, 16, 1058}, + /*II_D9_02*/ {0x34, 0, 21, 16, 1063}, + /*II_D9_03*/ {0x34, 0, 21, 16, 1068}, + /*II_D9_04*/ {0x34, 0, 42, 16, 1074}, + /*II_D9_05*/ {0x34, 0, 42, 16, 1082}, + /*II_D9_C0*/ {0x3a, 0, 61, 16, 1058}, + /*II_D9_C0*/ {0x3a, 0, 61, 16, 1058}, + /*II_D9_C0*/ {0x3a, 0, 61, 16, 1058}, + /*II_D9_C0*/ {0x3a, 0, 61, 16, 1058}, + /*II_D9_C0*/ {0x3a, 0, 61, 16, 1058}, + /*II_D9_C0*/ {0x3a, 0, 61, 16, 1058}, + /*II_D9_C0*/ {0x3a, 0, 61, 16, 1058}, + /*II_D9_C0*/ {0x3a, 0, 61, 16, 1058}, + /*II_D9_C8*/ {0x3a, 0, 61, 16, 1089}, + /*II_D9_C9*/ {0x3a, 0, 0, 16, 1089}, + /*II_D9_C8*/ {0x3a, 0, 61, 16, 1089}, + /*II_D9_C8*/ {0x3a, 0, 61, 16, 1089}, + /*II_D9_C8*/ {0x3a, 0, 61, 16, 1089}, + /*II_D9_C8*/ {0x3a, 0, 61, 16, 1089}, + /*II_D9_C8*/ {0x3a, 0, 61, 16, 1089}, + /*II_D9_C8*/ {0x3a, 0, 61, 16, 1089}, + /*II_D9_D0*/ {0x3a, 0, 0, 16, 1095}, + /*II_D9_E0*/ {0x3a, 0, 0, 16, 1101}, + /*II_D9_E1*/ {0x3a, 0, 0, 16, 1107}, + /*II_D9_E4*/ {0x3a, 0, 0, 16, 1113}, + /*II_D9_E5*/ {0x3a, 0, 0, 16, 1119}, + /*II_D9_E8*/ {0x3a, 0, 0, 16, 1125}, + /*II_D9_E9*/ {0x3a, 0, 0, 16, 1131}, + /*II_D9_EA*/ {0x3a, 0, 0, 16, 1139}, + /*II_D9_EB*/ {0x3a, 0, 0, 16, 1147}, + /*II_D9_EC*/ {0x3a, 0, 0, 16, 1154}, + /*II_D9_ED*/ {0x3a, 0, 0, 16, 1162}, + /*II_D9_EE*/ {0x3a, 0, 0, 16, 1170}, + /*II_D9_F0*/ {0x3a, 0, 0, 16, 1176}, + /*II_D9_F1*/ {0x3a, 0, 0, 16, 1183}, + /*II_D9_F2*/ {0x3a, 0, 0, 16, 1190}, + /*II_D9_F3*/ {0x3a, 0, 0, 16, 1197}, + /*II_D9_F4*/ {0x3a, 0, 0, 16, 1205}, + /*II_D9_F5*/ {0x3a, 0, 0, 16, 1214}, + /*II_D9_F6*/ {0x3a, 0, 0, 16, 1222}, + /*II_D9_F7*/ {0x3a, 0, 0, 16, 1231}, + /*II_D9_F8*/ {0x3a, 0, 0, 16, 1240}, + /*II_D9_F9*/ {0x3a, 0, 0, 16, 1247}, + /*II_D9_FA*/ {0x3a, 0, 0, 16, 1256}, + /*II_D9_FB*/ {0x3a, 0, 0, 16, 1263}, + /*II_D9_FC*/ {0x3a, 0, 0, 16, 1272}, + /*II_D9_FD*/ {0x3a, 0, 0, 16, 1281}, + /*II_D9_FE*/ {0x3a, 0, 0, 16, 1289}, + /*II_D9_FF*/ {0x3a, 0, 0, 16, 1295}, + /*II_DA_00*/ {0x34, 0, 21, 16, 1301}, + /*II_DA_01*/ {0x34, 0, 21, 16, 1308}, + /*II_DA_02*/ {0x34, 0, 21, 16, 1315}, + /*II_DA_03*/ {0x34, 0, 21, 16, 1322}, + /*II_DA_04*/ {0x34, 0, 21, 16, 1330}, + /*II_DA_05*/ {0x34, 0, 21, 16, 1337}, + /*II_DA_06*/ {0x34, 0, 21, 16, 1345}, + /*II_DA_07*/ {0x34, 0, 21, 16, 1352}, + /*II_DA_C0*/ {0x3b, 0, 62, 24, 1360}, + /*II_DA_C0*/ {0x3b, 0, 62, 24, 1360}, + /*II_DA_C0*/ {0x3b, 0, 62, 24, 1360}, + /*II_DA_C0*/ {0x3b, 0, 62, 24, 1360}, + /*II_DA_C0*/ {0x3b, 0, 62, 24, 1360}, + /*II_DA_C0*/ {0x3b, 0, 62, 24, 1360}, + /*II_DA_C0*/ {0x3b, 0, 62, 24, 1360}, + /*II_DA_C0*/ {0x3b, 0, 62, 24, 1360}, + /*II_DA_C8*/ {0x3b, 0, 62, 24, 1368}, + /*II_DA_C8*/ {0x3b, 0, 62, 24, 1368}, + /*II_DA_C8*/ {0x3b, 0, 62, 24, 1368}, + /*II_DA_C8*/ {0x3b, 0, 62, 24, 1368}, + /*II_DA_C8*/ {0x3b, 0, 62, 24, 1368}, + /*II_DA_C8*/ {0x3b, 0, 62, 24, 1368}, + /*II_DA_C8*/ {0x3b, 0, 62, 24, 1368}, + /*II_DA_C8*/ {0x3b, 0, 62, 24, 1368}, + /*II_DA_D0*/ {0x3b, 0, 62, 24, 1376}, + /*II_DA_D0*/ {0x3b, 0, 62, 24, 1376}, + /*II_DA_D0*/ {0x3b, 0, 62, 24, 1376}, + /*II_DA_D0*/ {0x3b, 0, 62, 24, 1376}, + /*II_DA_D0*/ {0x3b, 0, 62, 24, 1376}, + /*II_DA_D0*/ {0x3b, 0, 62, 24, 1376}, + /*II_DA_D0*/ {0x3b, 0, 62, 24, 1376}, + /*II_DA_D0*/ {0x3b, 0, 62, 24, 1376}, + /*II_DA_D8*/ {0x3b, 0, 62, 24, 1385}, + /*II_DA_D8*/ {0x3b, 0, 62, 24, 1385}, + /*II_DA_D8*/ {0x3b, 0, 62, 24, 1385}, + /*II_DA_D8*/ {0x3b, 0, 62, 24, 1385}, + /*II_DA_D8*/ {0x3b, 0, 62, 24, 1385}, + /*II_DA_D8*/ {0x3b, 0, 62, 24, 1385}, + /*II_DA_D8*/ {0x3b, 0, 62, 24, 1385}, + /*II_DA_D8*/ {0x3b, 0, 62, 24, 1385}, + /*II_DA_E9*/ {0x3a, 0, 0, 16, 1393}, + /*II_DB_00*/ {0x34, 0, 21, 16, 1402}, + /*II_DB_01*/ {0x3c, 0, 21, 56, 1408}, + /*II_DB_02*/ {0x34, 0, 21, 16, 1416}, + /*II_DB_03*/ {0x34, 0, 21, 16, 1422}, + /*II_DB_05*/ {0x34, 0, 23, 16, 1058}, + /*II_DB_07*/ {0x34, 0, 23, 16, 1068}, + /*II_DB_C0*/ {0x3b, 0, 62, 24, 1429}, + /*II_DB_C0*/ {0x3b, 0, 62, 24, 1429}, + /*II_DB_C0*/ {0x3b, 0, 62, 24, 1429}, + /*II_DB_C0*/ {0x3b, 0, 62, 24, 1429}, + /*II_DB_C0*/ {0x3b, 0, 62, 24, 1429}, + /*II_DB_C0*/ {0x3b, 0, 62, 24, 1429}, + /*II_DB_C0*/ {0x3b, 0, 62, 24, 1429}, + /*II_DB_C0*/ {0x3b, 0, 62, 24, 1429}, + /*II_DB_C8*/ {0x3b, 0, 62, 24, 1438}, + /*II_DB_C8*/ {0x3b, 0, 62, 24, 1438}, + /*II_DB_C8*/ {0x3b, 0, 62, 24, 1438}, + /*II_DB_C8*/ {0x3b, 0, 62, 24, 1438}, + /*II_DB_C8*/ {0x3b, 0, 62, 24, 1438}, + /*II_DB_C8*/ {0x3b, 0, 62, 24, 1438}, + /*II_DB_C8*/ {0x3b, 0, 62, 24, 1438}, + /*II_DB_C8*/ {0x3b, 0, 62, 24, 1438}, + /*II_DB_D0*/ {0x3b, 0, 62, 24, 1447}, + /*II_DB_D0*/ {0x3b, 0, 62, 24, 1447}, + /*II_DB_D0*/ {0x3b, 0, 62, 24, 1447}, + /*II_DB_D0*/ {0x3b, 0, 62, 24, 1447}, + /*II_DB_D0*/ {0x3b, 0, 62, 24, 1447}, + /*II_DB_D0*/ {0x3b, 0, 62, 24, 1447}, + /*II_DB_D0*/ {0x3b, 0, 62, 24, 1447}, + /*II_DB_D0*/ {0x3b, 0, 62, 24, 1447}, + /*II_DB_D8*/ {0x3b, 0, 62, 24, 1457}, + /*II_DB_D8*/ {0x3b, 0, 62, 24, 1457}, + /*II_DB_D8*/ {0x3b, 0, 62, 24, 1457}, + /*II_DB_D8*/ {0x3b, 0, 62, 24, 1457}, + /*II_DB_D8*/ {0x3b, 0, 62, 24, 1457}, + /*II_DB_D8*/ {0x3b, 0, 62, 24, 1457}, + /*II_DB_D8*/ {0x3b, 0, 62, 24, 1457}, + /*II_DB_D8*/ {0x3b, 0, 62, 24, 1457}, + /*II_DB_E0*/ {0x3a, 0, 0, 16, 1466}, + /*II_DB_E1*/ {0x3a, 0, 0, 16, 1472}, + /*II_DB_E4*/ {0x3a, 0, 0, 16, 1480}, + /*II_DB_E8*/ {0x3b, 0, 62, 16, 1488}, + /*II_DB_E8*/ {0x3b, 0, 62, 16, 1488}, + /*II_DB_E8*/ {0x3b, 0, 62, 16, 1488}, + /*II_DB_E8*/ {0x3b, 0, 62, 16, 1488}, + /*II_DB_E8*/ {0x3b, 0, 62, 16, 1488}, + /*II_DB_E8*/ {0x3b, 0, 62, 16, 1488}, + /*II_DB_E8*/ {0x3b, 0, 62, 16, 1488}, + /*II_DB_E8*/ {0x3b, 0, 62, 16, 1488}, + /*II_DB_F0*/ {0x3b, 0, 62, 24, 1496}, + /*II_DB_F0*/ {0x3b, 0, 62, 24, 1496}, + /*II_DB_F0*/ {0x3b, 0, 62, 24, 1496}, + /*II_DB_F0*/ {0x3b, 0, 62, 24, 1496}, + /*II_DB_F0*/ {0x3b, 0, 62, 24, 1496}, + /*II_DB_F0*/ {0x3b, 0, 62, 24, 1496}, + /*II_DB_F0*/ {0x3b, 0, 62, 24, 1496}, + /*II_DB_F0*/ {0x3b, 0, 62, 24, 1496}, + /*II_DC_00*/ {0x34, 0, 22, 16, 1007}, + /*II_DC_01*/ {0x34, 0, 22, 16, 1013}, + /*II_DC_02*/ {0x34, 0, 22, 16, 1019}, + /*II_DC_03*/ {0x34, 0, 22, 16, 1025}, + /*II_DC_04*/ {0x34, 0, 22, 16, 1032}, + /*II_DC_05*/ {0x34, 0, 22, 16, 1038}, + /*II_DC_06*/ {0x34, 0, 22, 16, 1045}, + /*II_DC_07*/ {0x34, 0, 22, 16, 1051}, + /*II_DC_C0*/ {0x3a, 0, 63, 16, 1007}, + /*II_DC_C0*/ {0x3a, 0, 63, 16, 1007}, + /*II_DC_C0*/ {0x3a, 0, 63, 16, 1007}, + /*II_DC_C0*/ {0x3a, 0, 63, 16, 1007}, + /*II_DC_C0*/ {0x3a, 0, 63, 16, 1007}, + /*II_DC_C0*/ {0x3a, 0, 63, 16, 1007}, + /*II_DC_C0*/ {0x3a, 0, 63, 16, 1007}, + /*II_DC_C0*/ {0x3a, 0, 63, 16, 1007}, + /*II_DC_C8*/ {0x3a, 0, 63, 16, 1013}, + /*II_DC_C8*/ {0x3a, 0, 63, 16, 1013}, + /*II_DC_C8*/ {0x3a, 0, 63, 16, 1013}, + /*II_DC_C8*/ {0x3a, 0, 63, 16, 1013}, + /*II_DC_C8*/ {0x3a, 0, 63, 16, 1013}, + /*II_DC_C8*/ {0x3a, 0, 63, 16, 1013}, + /*II_DC_C8*/ {0x3a, 0, 63, 16, 1013}, + /*II_DC_C8*/ {0x3a, 0, 63, 16, 1013}, + /*II_DC_E0*/ {0x3a, 0, 63, 16, 1038}, + /*II_DC_E0*/ {0x3a, 0, 63, 16, 1038}, + /*II_DC_E0*/ {0x3a, 0, 63, 16, 1038}, + /*II_DC_E0*/ {0x3a, 0, 63, 16, 1038}, + /*II_DC_E0*/ {0x3a, 0, 63, 16, 1038}, + /*II_DC_E0*/ {0x3a, 0, 63, 16, 1038}, + /*II_DC_E0*/ {0x3a, 0, 63, 16, 1038}, + /*II_DC_E0*/ {0x3a, 0, 63, 16, 1038}, + /*II_DC_E8*/ {0x3a, 0, 63, 16, 1032}, + /*II_DC_E8*/ {0x3a, 0, 63, 16, 1032}, + /*II_DC_E8*/ {0x3a, 0, 63, 16, 1032}, + /*II_DC_E8*/ {0x3a, 0, 63, 16, 1032}, + /*II_DC_E8*/ {0x3a, 0, 63, 16, 1032}, + /*II_DC_E8*/ {0x3a, 0, 63, 16, 1032}, + /*II_DC_E8*/ {0x3a, 0, 63, 16, 1032}, + /*II_DC_E8*/ {0x3a, 0, 63, 16, 1032}, + /*II_DC_F0*/ {0x3a, 0, 63, 16, 1051}, + /*II_DC_F0*/ {0x3a, 0, 63, 16, 1051}, + /*II_DC_F0*/ {0x3a, 0, 63, 16, 1051}, + /*II_DC_F0*/ {0x3a, 0, 63, 16, 1051}, + /*II_DC_F0*/ {0x3a, 0, 63, 16, 1051}, + /*II_DC_F0*/ {0x3a, 0, 63, 16, 1051}, + /*II_DC_F0*/ {0x3a, 0, 63, 16, 1051}, + /*II_DC_F0*/ {0x3a, 0, 63, 16, 1051}, + /*II_DC_F8*/ {0x3a, 0, 63, 16, 1045}, + /*II_DC_F8*/ {0x3a, 0, 63, 16, 1045}, + /*II_DC_F8*/ {0x3a, 0, 63, 16, 1045}, + /*II_DC_F8*/ {0x3a, 0, 63, 16, 1045}, + /*II_DC_F8*/ {0x3a, 0, 63, 16, 1045}, + /*II_DC_F8*/ {0x3a, 0, 63, 16, 1045}, + /*II_DC_F8*/ {0x3a, 0, 63, 16, 1045}, + /*II_DC_F8*/ {0x3a, 0, 63, 16, 1045}, + /*II_DD_00*/ {0x34, 0, 22, 16, 1058}, + /*II_DD_01*/ {0x3c, 0, 22, 56, 1408}, + /*II_DD_02*/ {0x34, 0, 22, 16, 1063}, + /*II_DD_03*/ {0x34, 0, 22, 16, 1068}, + /*II_DD_04*/ {0x34, 0, 42, 16, 1503}, + /*II_DD_C0*/ {0x3a, 0, 61, 16, 1511}, + /*II_DD_C0*/ {0x3a, 0, 61, 16, 1511}, + /*II_DD_C0*/ {0x3a, 0, 61, 16, 1511}, + /*II_DD_C0*/ {0x3a, 0, 61, 16, 1511}, + /*II_DD_C0*/ {0x3a, 0, 61, 16, 1511}, + /*II_DD_C0*/ {0x3a, 0, 61, 16, 1511}, + /*II_DD_C0*/ {0x3a, 0, 61, 16, 1511}, + /*II_DD_C0*/ {0x3a, 0, 61, 16, 1511}, + /*II_DD_D0*/ {0x3a, 0, 61, 16, 1063}, + /*II_DD_D0*/ {0x3a, 0, 61, 16, 1063}, + /*II_DD_D0*/ {0x3a, 0, 61, 16, 1063}, + /*II_DD_D0*/ {0x3a, 0, 61, 16, 1063}, + /*II_DD_D0*/ {0x3a, 0, 61, 16, 1063}, + /*II_DD_D0*/ {0x3a, 0, 61, 16, 1063}, + /*II_DD_D0*/ {0x3a, 0, 61, 16, 1063}, + /*II_DD_D0*/ {0x3a, 0, 61, 16, 1063}, + /*II_DD_D8*/ {0x3a, 0, 61, 16, 1068}, + /*II_DD_D8*/ {0x3a, 0, 61, 16, 1068}, + /*II_DD_D8*/ {0x3a, 0, 61, 16, 1068}, + /*II_DD_D8*/ {0x3a, 0, 61, 16, 1068}, + /*II_DD_D8*/ {0x3a, 0, 61, 16, 1068}, + /*II_DD_D8*/ {0x3a, 0, 61, 16, 1068}, + /*II_DD_D8*/ {0x3a, 0, 61, 16, 1068}, + /*II_DD_D8*/ {0x3a, 0, 61, 16, 1068}, + /*II_DD_E0*/ {0x3a, 0, 63, 16, 1518}, + /*II_DD_E1*/ {0x3a, 0, 0, 16, 1518}, + /*II_DD_E0*/ {0x3a, 0, 63, 16, 1518}, + /*II_DD_E0*/ {0x3a, 0, 63, 16, 1518}, + /*II_DD_E0*/ {0x3a, 0, 63, 16, 1518}, + /*II_DD_E0*/ {0x3a, 0, 63, 16, 1518}, + /*II_DD_E0*/ {0x3a, 0, 63, 16, 1518}, + /*II_DD_E0*/ {0x3a, 0, 63, 16, 1518}, + /*II_DD_E8*/ {0x3a, 0, 61, 16, 1525}, + /*II_DD_E9*/ {0x3a, 0, 0, 16, 1525}, + /*II_DD_E8*/ {0x3a, 0, 61, 16, 1525}, + /*II_DD_E8*/ {0x3a, 0, 61, 16, 1525}, + /*II_DD_E8*/ {0x3a, 0, 61, 16, 1525}, + /*II_DD_E8*/ {0x3a, 0, 61, 16, 1525}, + /*II_DD_E8*/ {0x3a, 0, 61, 16, 1525}, + /*II_DD_E8*/ {0x3a, 0, 61, 16, 1525}, + /*II_DE_00*/ {0x34, 0, 20, 16, 1301}, + /*II_DE_01*/ {0x34, 0, 20, 16, 1308}, + /*II_DE_02*/ {0x34, 0, 20, 16, 1315}, + /*II_DE_03*/ {0x34, 0, 20, 16, 1322}, + /*II_DE_04*/ {0x34, 0, 20, 16, 1330}, + /*II_DE_05*/ {0x34, 0, 20, 16, 1337}, + /*II_DE_06*/ {0x34, 0, 20, 16, 1345}, + /*II_DE_07*/ {0x34, 0, 20, 16, 1352}, + /*II_DE_C0*/ {0x3a, 0, 63, 16, 1533}, + /*II_DE_C1*/ {0x3a, 0, 0, 16, 1533}, + /*II_DE_C0*/ {0x3a, 0, 63, 16, 1533}, + /*II_DE_C0*/ {0x3a, 0, 63, 16, 1533}, + /*II_DE_C0*/ {0x3a, 0, 63, 16, 1533}, + /*II_DE_C0*/ {0x3a, 0, 63, 16, 1533}, + /*II_DE_C0*/ {0x3a, 0, 63, 16, 1533}, + /*II_DE_C0*/ {0x3a, 0, 63, 16, 1533}, + /*II_DE_C8*/ {0x3a, 0, 63, 16, 1540}, + /*II_DE_C9*/ {0x3a, 0, 0, 16, 1540}, + /*II_DE_C8*/ {0x3a, 0, 63, 16, 1540}, + /*II_DE_C8*/ {0x3a, 0, 63, 16, 1540}, + /*II_DE_C8*/ {0x3a, 0, 63, 16, 1540}, + /*II_DE_C8*/ {0x3a, 0, 63, 16, 1540}, + /*II_DE_C8*/ {0x3a, 0, 63, 16, 1540}, + /*II_DE_C8*/ {0x3a, 0, 63, 16, 1540}, + /*II_DE_D9*/ {0x3a, 0, 0, 16, 1547}, + /*II_DE_E0*/ {0x3a, 0, 63, 16, 1555}, + /*II_DE_E1*/ {0x3a, 0, 0, 16, 1555}, + /*II_DE_E0*/ {0x3a, 0, 63, 16, 1555}, + /*II_DE_E0*/ {0x3a, 0, 63, 16, 1555}, + /*II_DE_E0*/ {0x3a, 0, 63, 16, 1555}, + /*II_DE_E0*/ {0x3a, 0, 63, 16, 1555}, + /*II_DE_E0*/ {0x3a, 0, 63, 16, 1555}, + /*II_DE_E0*/ {0x3a, 0, 63, 16, 1555}, + /*II_DE_E8*/ {0x3a, 0, 63, 16, 1563}, + /*II_DE_E9*/ {0x3a, 0, 0, 16, 1563}, + /*II_DE_E8*/ {0x3a, 0, 63, 16, 1563}, + /*II_DE_E8*/ {0x3a, 0, 63, 16, 1563}, + /*II_DE_E8*/ {0x3a, 0, 63, 16, 1563}, + /*II_DE_E8*/ {0x3a, 0, 63, 16, 1563}, + /*II_DE_E8*/ {0x3a, 0, 63, 16, 1563}, + /*II_DE_E8*/ {0x3a, 0, 63, 16, 1563}, + /*II_DE_F0*/ {0x3a, 0, 63, 16, 1570}, + /*II_DE_F1*/ {0x3a, 0, 0, 16, 1570}, + /*II_DE_F0*/ {0x3a, 0, 63, 16, 1570}, + /*II_DE_F0*/ {0x3a, 0, 63, 16, 1570}, + /*II_DE_F0*/ {0x3a, 0, 63, 16, 1570}, + /*II_DE_F0*/ {0x3a, 0, 63, 16, 1570}, + /*II_DE_F0*/ {0x3a, 0, 63, 16, 1570}, + /*II_DE_F0*/ {0x3a, 0, 63, 16, 1570}, + /*II_DE_F8*/ {0x3a, 0, 63, 16, 1578}, + /*II_DE_F9*/ {0x3a, 0, 0, 16, 1578}, + /*II_DE_F8*/ {0x3a, 0, 63, 16, 1578}, + /*II_DE_F8*/ {0x3a, 0, 63, 16, 1578}, + /*II_DE_F8*/ {0x3a, 0, 63, 16, 1578}, + /*II_DE_F8*/ {0x3a, 0, 63, 16, 1578}, + /*II_DE_F8*/ {0x3a, 0, 63, 16, 1578}, + /*II_DE_F8*/ {0x3a, 0, 63, 16, 1578}, + /*II_DF_00*/ {0x34, 0, 20, 16, 1402}, + /*II_DF_01*/ {0x3c, 0, 20, 56, 1408}, + /*II_DF_02*/ {0x34, 0, 20, 16, 1416}, + /*II_DF_03*/ {0x34, 0, 20, 16, 1422}, + /*II_DF_04*/ {0x34, 0, 23, 16, 1585}, + /*II_DF_05*/ {0x34, 0, 22, 16, 1402}, + /*II_DF_06*/ {0x34, 0, 23, 16, 1591}, + /*II_DF_07*/ {0x34, 0, 22, 16, 1422}, + /*II_DF_E8*/ {0x3b, 0, 62, 16, 1598}, + /*II_DF_E8*/ {0x3b, 0, 62, 16, 1598}, + /*II_DF_E8*/ {0x3b, 0, 62, 16, 1598}, + /*II_DF_E8*/ {0x3b, 0, 62, 16, 1598}, + /*II_DF_E8*/ {0x3b, 0, 62, 16, 1598}, + /*II_DF_E8*/ {0x3b, 0, 62, 16, 1598}, + /*II_DF_E8*/ {0x3b, 0, 62, 16, 1598}, + /*II_DF_E8*/ {0x3b, 0, 62, 16, 1598}, + /*II_DF_F0*/ {0x3b, 0, 62, 16, 1607}, + /*II_DF_F0*/ {0x3b, 0, 62, 16, 1607}, + /*II_DF_F0*/ {0x3b, 0, 62, 16, 1607}, + /*II_DF_F0*/ {0x3b, 0, 62, 16, 1607}, + /*II_DF_F0*/ {0x3b, 0, 62, 16, 1607}, + /*II_DF_F0*/ {0x3b, 0, 62, 16, 1607}, + /*II_DF_F0*/ {0x3b, 0, 62, 16, 1607}, + /*II_DF_F0*/ {0x3b, 0, 62, 16, 1607}, + /*II_F6_00*/ {0x34, 1, 15, 8, 206}, + /*II_F6_02*/ {0x33, 0, 15, 8, 1615}, + /*II_F6_03*/ {0x33, 0, 15, 8, 1620}, + /*II_F6_04*/ {0x39, 0, 15, 8, 1625}, + /*II_F6_05*/ {0x39, 0, 15, 8, 117}, + /*II_F6_06*/ {0x39, 0, 15, 8, 1630}, + /*II_F6_07*/ {0x39, 0, 15, 8, 1635}, + /*II_F7_00*/ {0x34, 3, 17, 8, 206}, + /*II_F7_02*/ {0x33, 0, 17, 8, 1615}, + /*II_F7_03*/ {0x33, 0, 17, 8, 1620}, + /*II_F7_04*/ {0x39, 0, 17, 8, 1625}, + /*II_F7_05*/ {0x39, 0, 17, 8, 117}, + /*II_F7_06*/ {0x39, 0, 17, 8, 1630}, + /*II_F7_07*/ {0x39, 0, 17, 8, 1635}, + /*II_FE_00*/ {0x33, 0, 15, 8, 81}, + /*II_FE_01*/ {0x33, 0, 15, 8, 86}, + /*II_FF_00*/ {0x33, 0, 17, 8, 81}, + /*II_FF_01*/ {0x33, 0, 17, 8, 86}, + /*II_FF_02*/ {0x3d, 0, 17, 9, 456}, + /*II_FF_03*/ {0x3e, 0, 37, 9, 260}, + /*II_FF_04*/ {0x3d, 0, 17, 12, 462}, + /*II_FF_05*/ {0x3e, 0, 37, 12, 467}, + /*II_FF_06*/ {0x3d, 0, 17, 8, 16}, + /*II_0F_00_00*/ {0x34, 0, 17, 8, 1641}, + /*II_0F_00_01*/ {0x34, 0, 16, 8, 1647}, + /*II_0F_00_02*/ {0x34, 0, 16, 8, 1652}, + /*II_0F_00_03*/ {0x3c, 0, 16, 8, 1658}, + /*II_0F_00_04*/ {0x34, 0, 16, 8, 1663}, + /*II_0F_00_05*/ {0x34, 0, 16, 8, 1669}, + /*II_0F_01_00*/ {0x3d, 0, 39, 8, 1675}, + /*II_0F_01_01*/ {0x3d, 0, 39, 8, 1681}, + /*II_0F_01_02*/ {0x3d, 0, 39, 8, 1687}, + /*II_0F_01_03*/ {0x3d, 0, 39, 8, 1693}, + /*II_0F_01_04*/ {0x3f, 0, 28, 8, 1699}, + /*II_0F_01_06*/ {0x40, 0, 16, 8, 1705}, + /*II_0F_01_07*/ {0x3c, 0, 42, 8, 1711}, + /*II_0F_01_C1*/ {0x3b, 0, 0, 112, 1719}, + /*II_0F_01_C2*/ {0x3b, 0, 0, 112, 1727}, + /*II_0F_01_C3*/ {0x3b, 0, 0, 112, 1737}, + /*II_0F_01_C4*/ {0x3b, 0, 0, 112, 1747}, + /*II_0F_01_C8*/ {0x3b, 0, 0, 8, 1755}, + /*II_0F_01_C9*/ {0x3b, 0, 0, 8, 1764}, + /*II_0F_01_D0*/ {0x26, 0, 0, 8, 1771}, + /*II_0F_01_D1*/ {0x26, 0, 0, 8, 1779}, + /*II_0F_01_D4*/ {0x3b, 0, 0, 112, 1787}, + /*II_0F_01_D8*/ {0x3c, 0, 58, 120, 1795}, + /*II_0F_01_D9*/ {0x3b, 0, 0, 120, 1802}, + /*II_0F_01_DA*/ {0x3b, 0, 58, 120, 1811}, + /*II_0F_01_DB*/ {0x3b, 0, 58, 120, 1819}, + /*II_0F_01_DC*/ {0x3b, 0, 0, 120, 1827}, + /*II_0F_01_DD*/ {0x3b, 0, 0, 120, 1833}, + /*II_0F_01_DE*/ {0x3b, 0, 58, 120, 1839}, + /*II_0F_01_DF*/ {0x3b, 60, 58, 120, 1847}, + /*II_0F_01_F8*/ {0x41, 0, 0, 8, 1856}, + /*II_0F_01_F9*/ {0x41, 0, 0, 8, 1864}, + /*II_0F_0D_00*/ {0x3c, 0, 42, 96, 1872}, + /*II_0F_0D_01*/ {0x3c, 0, 42, 96, 1882}, + /*II_0F_0F_0C*/ {0x42, 67, 64, 104, 1893}, + /*II_0F_0F_0D*/ {0x42, 67, 64, 96, 1900}, + /*II_0F_0F_1C*/ {0x42, 67, 64, 104, 1907}, + /*II_0F_0F_1D*/ {0x42, 67, 64, 96, 1914}, + /*II_0F_0F_8A*/ {0x42, 67, 64, 104, 1921}, + /*II_0F_0F_8E*/ {0x42, 67, 64, 104, 1929}, + /*II_0F_0F_90*/ {0x42, 67, 64, 96, 1938}, + /*II_0F_0F_94*/ {0x42, 67, 64, 96, 1947}, + /*II_0F_0F_96*/ {0x42, 67, 64, 96, 1954}, + /*II_0F_0F_97*/ {0x42, 67, 64, 96, 1961}, + /*II_0F_0F_9A*/ {0x42, 67, 64, 96, 1970}, + /*II_0F_0F_9E*/ {0x42, 67, 64, 96, 1977}, + /*II_0F_0F_A0*/ {0x42, 67, 64, 96, 1984}, + /*II_0F_0F_A4*/ {0x42, 67, 64, 96, 1993}, + /*II_0F_0F_A6*/ {0x42, 67, 64, 96, 2000}, + /*II_0F_0F_A7*/ {0x42, 67, 64, 96, 2010}, + /*II_0F_0F_AA*/ {0x42, 67, 64, 96, 2020}, + /*II_0F_0F_AE*/ {0x42, 67, 64, 96, 2028}, + /*II_0F_0F_B0*/ {0x42, 67, 64, 96, 2035}, + /*II_0F_0F_B4*/ {0x42, 67, 64, 96, 2044}, + /*II_0F_0F_B6*/ {0x42, 67, 64, 96, 2051}, + /*II_0F_0F_B7*/ {0x42, 67, 64, 96, 2061}, + /*II_0F_0F_BB*/ {0x42, 67, 64, 104, 2070}, + /*II_0F_0F_BF*/ {0x42, 67, 64, 96, 2078}, + /*II_0F_10*/ {0x29, 73, 68, 40, 2087}, + /*II_66_0F_10*/ {0x29, 73, 68, 48, 2095}, + /*II_F3_0F_10*/ {0x29, 71, 68, 40, 2103}, + /*II_F2_0F_10*/ {0x29, 72, 68, 48, 2110}, + /*II_0F_11*/ {0x29, 68, 73, 40, 2087}, + /*II_66_0F_11*/ {0x29, 68, 73, 48, 2095}, + /*II_F3_0F_11*/ {0x29, 68, 71, 40, 2103}, + /*II_F2_0F_11*/ {0x29, 68, 72, 48, 2110}, + /*II_66_0F_12*/ {0x29, 46, 68, 48, 2168}, + /*II_F3_0F_12*/ {0x29, 72, 68, 56, 2176}, + /*II_F2_0F_12*/ {0x29, 72, 68, 56, 2186}, + /*II_0F_13*/ {0x29, 68, 46, 40, 2160}, + /*II_66_0F_13*/ {0x29, 68, 46, 48, 2168}, + /*II_0F_14*/ {0x28, 73, 68, 40, 2244}, + /*II_66_0F_14*/ {0x28, 73, 68, 48, 2254}, + /*II_0F_15*/ {0x28, 73, 68, 40, 2286}, + /*II_66_0F_15*/ {0x28, 73, 68, 48, 2296}, + /*II_66_0F_16*/ {0x29, 46, 68, 48, 2345}, + /*II_F3_0F_16*/ {0x29, 73, 68, 56, 2353}, + /*II_0F_17*/ {0x29, 68, 46, 40, 2337}, + /*II_66_0F_17*/ {0x29, 68, 46, 48, 2345}, + /*II_0F_18_00*/ {0x3c, 0, 42, 40, 2402}, + /*II_0F_18_01*/ {0x3c, 0, 42, 40, 2415}, + /*II_0F_18_02*/ {0x3c, 0, 42, 40, 2427}, + /*II_0F_18_03*/ {0x3c, 0, 42, 40, 2439}, + /*II_0F_28*/ {0x29, 73, 68, 40, 2451}, + /*II_66_0F_28*/ {0x29, 73, 68, 48, 2459}, + /*II_0F_29*/ {0x29, 68, 73, 40, 2451}, + /*II_66_0F_29*/ {0x29, 68, 73, 48, 2459}, + /*II_0F_2A*/ {0x28, 67, 68, 40, 2485}, + /*II_66_0F_2A*/ {0x28, 67, 68, 48, 2495}, + /*II_F3_0F_2A*/ {0x30, 18, 68, 40, 2505}, + /*II_F2_0F_2A*/ {0x30, 18, 68, 48, 2515}, + /*II_0F_2B*/ {0x29, 68, 47, 40, 2547}, + /*II_66_0F_2B*/ {0x29, 68, 47, 48, 2556}, + /*II_F3_0F_2B*/ {0x29, 68, 44, 88, 2565}, + /*II_F2_0F_2B*/ {0x29, 68, 46, 88, 2574}, + /*II_0F_2C*/ {0x28, 72, 64, 40, 2603}, + /*II_66_0F_2C*/ {0x28, 73, 64, 48, 2614}, + /*II_F3_0F_2C*/ {0x30, 71, 13, 40, 2625}, + /*II_F2_0F_2C*/ {0x30, 72, 13, 48, 2636}, + /*II_0F_2D*/ {0x28, 72, 64, 40, 2671}, + /*II_66_0F_2D*/ {0x28, 73, 68, 48, 2681}, + /*II_F3_0F_2D*/ {0x30, 71, 13, 40, 2691}, + /*II_F2_0F_2D*/ {0x30, 72, 13, 48, 2701}, + /*II_0F_2E*/ {0x28, 71, 68, 40, 2733}, + /*II_66_0F_2E*/ {0x28, 72, 68, 48, 2742}, + /*II_0F_2F*/ {0x28, 71, 68, 40, 2771}, + /*II_66_0F_2F*/ {0x28, 72, 68, 48, 2779}, + /*II_0F_50*/ {0x49, 69, 12, 40, 2805}, + /*II_66_0F_50*/ {0x49, 69, 12, 48, 2815}, + /*II_0F_51*/ {0x28, 73, 68, 40, 2847}, + /*II_66_0F_51*/ {0x28, 73, 68, 48, 2855}, + /*II_F3_0F_51*/ {0x28, 71, 68, 40, 2863}, + /*II_F2_0F_51*/ {0x28, 72, 68, 48, 2871}, + /*II_0F_52*/ {0x28, 73, 68, 40, 2915}, + /*II_F3_0F_52*/ {0x28, 71, 68, 40, 2924}, + /*II_0F_53*/ {0x28, 73, 68, 40, 2953}, + /*II_F3_0F_53*/ {0x28, 71, 68, 40, 2960}, + /*II_0F_54*/ {0x28, 73, 68, 40, 2983}, + /*II_66_0F_54*/ {0x28, 73, 68, 48, 2990}, + /*II_0F_55*/ {0x28, 73, 68, 40, 3013}, + /*II_66_0F_55*/ {0x28, 73, 68, 48, 3021}, + /*II_0F_56*/ {0x28, 73, 68, 40, 3047}, + /*II_66_0F_56*/ {0x28, 73, 68, 48, 3053}, + /*II_0F_57*/ {0x28, 73, 68, 40, 3073}, + /*II_66_0F_57*/ {0x28, 73, 68, 48, 3080}, + /*II_0F_58*/ {0x28, 73, 68, 40, 3103}, + /*II_66_0F_58*/ {0x28, 73, 68, 48, 3110}, + /*II_F3_0F_58*/ {0x28, 71, 68, 40, 3117}, + /*II_F2_0F_58*/ {0x28, 72, 68, 48, 3124}, + /*II_0F_59*/ {0x28, 73, 68, 40, 3163}, + /*II_66_0F_59*/ {0x28, 73, 68, 48, 3170}, + /*II_F3_0F_59*/ {0x28, 71, 68, 40, 3177}, + /*II_F2_0F_59*/ {0x28, 72, 68, 48, 3184}, + /*II_0F_5A*/ {0x28, 72, 68, 48, 3223}, + /*II_66_0F_5A*/ {0x28, 73, 68, 48, 3233}, + /*II_F3_0F_5A*/ {0x28, 71, 68, 48, 3243}, + /*II_F2_0F_5A*/ {0x28, 72, 68, 48, 3253}, + /*II_0F_5B*/ {0x28, 73, 68, 48, 3307}, + /*II_66_0F_5B*/ {0x28, 73, 68, 48, 3317}, + /*II_F3_0F_5B*/ {0x28, 73, 68, 48, 3327}, + /*II_0F_5C*/ {0x28, 73, 68, 40, 3372}, + /*II_66_0F_5C*/ {0x28, 73, 68, 48, 3379}, + /*II_F3_0F_5C*/ {0x28, 71, 68, 40, 3386}, + /*II_F2_0F_5C*/ {0x28, 72, 68, 48, 3393}, + /*II_0F_5D*/ {0x28, 73, 68, 40, 3432}, + /*II_66_0F_5D*/ {0x28, 73, 68, 48, 3439}, + /*II_F3_0F_5D*/ {0x28, 71, 68, 40, 3446}, + /*II_F2_0F_5D*/ {0x28, 72, 68, 48, 3453}, + /*II_0F_5E*/ {0x28, 73, 68, 40, 3492}, + /*II_66_0F_5E*/ {0x28, 73, 68, 48, 3499}, + /*II_F3_0F_5E*/ {0x28, 71, 68, 40, 3506}, + /*II_F2_0F_5E*/ {0x28, 72, 68, 48, 3513}, + /*II_0F_5F*/ {0x28, 73, 68, 40, 3552}, + /*II_66_0F_5F*/ {0x28, 73, 68, 48, 3559}, + /*II_F3_0F_5F*/ {0x28, 71, 68, 40, 3566}, + /*II_F2_0F_5F*/ {0x28, 72, 68, 48, 3573}, + /*II_0F_60*/ {0x28, 66, 64, 32, 3612}, + /*II_66_0F_60*/ {0x28, 73, 68, 48, 3612}, + /*II_0F_61*/ {0x28, 66, 64, 32, 3635}, + /*II_66_0F_61*/ {0x28, 73, 68, 48, 3635}, + /*II_0F_62*/ {0x28, 66, 64, 32, 3658}, + /*II_66_0F_62*/ {0x28, 73, 68, 48, 3658}, + /*II_0F_63*/ {0x28, 67, 64, 32, 3681}, + /*II_66_0F_63*/ {0x28, 73, 68, 48, 3681}, + /*II_0F_64*/ {0x28, 67, 64, 32, 3702}, + /*II_66_0F_64*/ {0x28, 73, 68, 48, 3702}, + /*II_0F_65*/ {0x28, 67, 64, 32, 3721}, + /*II_66_0F_65*/ {0x28, 73, 68, 48, 3721}, + /*II_0F_66*/ {0x28, 67, 64, 32, 3740}, + /*II_66_0F_66*/ {0x28, 73, 68, 48, 3740}, + /*II_0F_67*/ {0x28, 67, 64, 32, 3759}, + /*II_66_0F_67*/ {0x28, 73, 68, 48, 3759}, + /*II_0F_68*/ {0x28, 67, 64, 32, 3780}, + /*II_66_0F_68*/ {0x28, 73, 68, 48, 3780}, + /*II_0F_69*/ {0x28, 67, 64, 32, 3803}, + /*II_66_0F_69*/ {0x28, 73, 68, 48, 3803}, + /*II_0F_6A*/ {0x28, 67, 64, 32, 3826}, + /*II_66_0F_6A*/ {0x28, 73, 68, 48, 3826}, + /*II_0F_6B*/ {0x28, 67, 64, 32, 3849}, + /*II_66_0F_6B*/ {0x28, 73, 68, 48, 3849}, + /*II_66_0F_6C*/ {0x28, 73, 68, 48, 3870}, + /*II_66_0F_6D*/ {0x28, 73, 68, 48, 3895}, + /*II_0F_6F*/ {0x29, 67, 64, 32, 3926}, + /*II_66_0F_6F*/ {0x29, 73, 68, 48, 3946}, + /*II_F3_0F_6F*/ {0x29, 73, 68, 48, 3954}, + /*II_0F_74*/ {0x28, 67, 64, 32, 4043}, + /*II_66_0F_74*/ {0x28, 73, 68, 48, 4043}, + /*II_0F_75*/ {0x28, 67, 64, 32, 4062}, + /*II_66_0F_75*/ {0x28, 73, 68, 48, 4062}, + /*II_0F_76*/ {0x28, 67, 64, 32, 4081}, + /*II_66_0F_76*/ {0x28, 73, 68, 48, 4081}, + /*II_0F_77*/ {0x26, 0, 0, 32, 4100}, + /*II_0F_78*/ {0x4e, 13, 18, 112, 4128}, + /*II_0F_79*/ {0x4e, 18, 13, 112, 4152}, + /*II_66_0F_79*/ {0x28, 69, 68, 88, 4136}, + /*II_F2_0F_79*/ {0x51, 69, 68, 88, 4143}, + /*II_0F_7A_30*/ {0x26, 72, 68, 112, 4161}, + /*II_0F_7A_31*/ {0x26, 68, 72, 112, 4171}, + /*II_66_0F_7C*/ {0x28, 73, 68, 56, 4181}, + /*II_F2_0F_7C*/ {0x28, 73, 68, 56, 4189}, + /*II_66_0F_7D*/ {0x28, 73, 68, 56, 4215}, + /*II_F2_0F_7D*/ {0x28, 73, 68, 56, 4223}, + /*II_F3_0F_7E*/ {0x29, 72, 68, 48, 3926}, + /*II_0F_7F*/ {0x29, 64, 67, 32, 3926}, + /*II_66_0F_7F*/ {0x29, 68, 73, 48, 3946}, + /*II_F3_0F_7F*/ {0x29, 68, 73, 48, 3954}, + /*II_F3_0F_B8*/ {0x55, 17, 11, 80, 4338}, + /*II_0F_BA_04*/ {0x56, 1, 17, 8, 872}, + /*II_0F_BA_05*/ {0x37, 1, 17, 8, 887}, + /*II_0F_BA_06*/ {0x37, 1, 17, 8, 912}, + /*II_0F_BA_07*/ {0x37, 1, 17, 8, 934}, + /*II_0F_BC*/ {0x28, 17, 11, 8, 4346}, + /*II_F3_0F_BC*/ {0x57, 17, 11, 112, 4351}, + /*II_0F_BD*/ {0x28, 17, 11, 8, 4358}, + /*II_F3_0F_BD*/ {0x58, 17, 11, 8, 4363}, + /*II_0F_C7_07*/ {0x3c, 0, 46, 112, 6385}, + /*II_66_0F_D0*/ {0x28, 73, 68, 56, 6394}, + /*II_F2_0F_D0*/ {0x28, 73, 68, 56, 6404}, + /*II_0F_D1*/ {0x28, 67, 64, 32, 6436}, + /*II_66_0F_D1*/ {0x28, 73, 68, 48, 6436}, + /*II_0F_D2*/ {0x28, 67, 64, 32, 6451}, + /*II_66_0F_D2*/ {0x28, 73, 68, 48, 6451}, + /*II_0F_D3*/ {0x28, 67, 64, 32, 6466}, + /*II_66_0F_D3*/ {0x28, 73, 68, 48, 6466}, + /*II_0F_D4*/ {0x28, 72, 68, 48, 6481}, + /*II_66_0F_D4*/ {0x28, 73, 68, 48, 6481}, + /*II_0F_D5*/ {0x28, 67, 64, 32, 6496}, + /*II_66_0F_D5*/ {0x28, 73, 68, 48, 6496}, + /*II_66_0F_D6*/ {0x29, 68, 72, 48, 3926}, + /*II_F3_0F_D6*/ {0x49, 65, 68, 48, 6513}, + /*II_F2_0F_D6*/ {0x49, 69, 64, 48, 6522}, + /*II_0F_D7*/ {0x51, 65, 12, 40, 6531}, + /*II_66_0F_D7*/ {0x51, 69, 12, 48, 6531}, + /*II_0F_D8*/ {0x28, 67, 64, 32, 6552}, + /*II_66_0F_D8*/ {0x28, 73, 68, 48, 6552}, + /*II_0F_D9*/ {0x28, 67, 64, 32, 6571}, + /*II_66_0F_D9*/ {0x28, 73, 68, 48, 6571}, + /*II_0F_DA*/ {0x28, 67, 64, 40, 6590}, + /*II_66_0F_DA*/ {0x28, 73, 68, 48, 6590}, + /*II_0F_DB*/ {0x28, 67, 64, 32, 6607}, + /*II_66_0F_DB*/ {0x28, 73, 68, 48, 6607}, + /*II_0F_DC*/ {0x28, 67, 64, 32, 6620}, + /*II_66_0F_DC*/ {0x28, 73, 68, 48, 6620}, + /*II_0F_DD*/ {0x28, 67, 64, 32, 6639}, + /*II_66_0F_DD*/ {0x28, 73, 68, 48, 6639}, + /*II_0F_DE*/ {0x28, 67, 64, 40, 6648}, + /*II_66_0F_DE*/ {0x28, 73, 68, 48, 6648}, + /*II_0F_DF*/ {0x28, 67, 64, 32, 6665}, + /*II_66_0F_DF*/ {0x28, 73, 68, 48, 6665}, + /*II_0F_E0*/ {0x28, 67, 64, 40, 6680}, + /*II_66_0F_E0*/ {0x28, 73, 68, 48, 6680}, + /*II_0F_E1*/ {0x28, 67, 64, 32, 6695}, + /*II_66_0F_E1*/ {0x28, 73, 68, 48, 6695}, + /*II_0F_E2*/ {0x28, 67, 64, 32, 6710}, + /*II_66_0F_E2*/ {0x28, 73, 68, 48, 6710}, + /*II_0F_E3*/ {0x28, 67, 64, 40, 6725}, + /*II_66_0F_E3*/ {0x28, 73, 68, 48, 6725}, + /*II_0F_E4*/ {0x28, 67, 64, 40, 6740}, + /*II_66_0F_E4*/ {0x28, 73, 68, 48, 6740}, + /*II_0F_E5*/ {0x28, 67, 64, 32, 6759}, + /*II_66_0F_E5*/ {0x28, 73, 68, 48, 6759}, + /*II_66_0F_E6*/ {0x28, 73, 68, 48, 6776}, + /*II_F3_0F_E6*/ {0x28, 72, 68, 48, 6787}, + /*II_F2_0F_E6*/ {0x28, 73, 68, 48, 6797}, + /*II_0F_E7*/ {0x29, 64, 46, 40, 6841}, + /*II_66_0F_E7*/ {0x29, 68, 47, 48, 6849}, + /*II_0F_E8*/ {0x28, 67, 64, 32, 6868}, + /*II_66_0F_E8*/ {0x28, 73, 68, 48, 6868}, + /*II_0F_E9*/ {0x28, 67, 64, 32, 6885}, + /*II_66_0F_E9*/ {0x28, 73, 68, 48, 6885}, + /*II_0F_EA*/ {0x28, 67, 64, 40, 6902}, + /*II_66_0F_EA*/ {0x28, 73, 68, 48, 6902}, + /*II_0F_EB*/ {0x28, 67, 64, 32, 6919}, + /*II_66_0F_EB*/ {0x28, 73, 68, 48, 6919}, + /*II_0F_EC*/ {0x28, 67, 64, 32, 6930}, + /*II_66_0F_EC*/ {0x28, 73, 68, 48, 6930}, + /*II_0F_ED*/ {0x28, 67, 64, 32, 6947}, + /*II_66_0F_ED*/ {0x28, 73, 68, 48, 6947}, + /*II_0F_EE*/ {0x28, 67, 64, 40, 6964}, + /*II_66_0F_EE*/ {0x28, 73, 68, 48, 6964}, + /*II_0F_EF*/ {0x28, 67, 64, 32, 6981}, + /*II_66_0F_EF*/ {0x28, 73, 68, 48, 6981}, + /*II_F2_0F_F0*/ {0x28, 42, 68, 56, 6994}, + /*II_0F_F1*/ {0x28, 67, 64, 32, 7009}, + /*II_66_0F_F1*/ {0x28, 73, 68, 48, 7009}, + /*II_0F_F2*/ {0x28, 67, 64, 32, 7024}, + /*II_66_0F_F2*/ {0x28, 73, 68, 48, 7024}, + /*II_0F_F3*/ {0x28, 67, 64, 32, 7039}, + /*II_66_0F_F3*/ {0x28, 73, 68, 48, 7039}, + /*II_0F_F4*/ {0x28, 67, 64, 48, 7054}, + /*II_66_0F_F4*/ {0x28, 73, 68, 48, 7054}, + /*II_0F_F5*/ {0x28, 67, 64, 32, 7073}, + /*II_66_0F_F5*/ {0x28, 73, 68, 48, 7073}, + /*II_0F_F6*/ {0x28, 67, 64, 40, 7092}, + /*II_66_0F_F6*/ {0x28, 73, 68, 48, 7092}, + /*II_0F_F7*/ {0x51, 65, 64, 40, 7109}, + /*II_66_0F_F7*/ {0x51, 69, 68, 48, 7119}, + /*II_0F_F8*/ {0x28, 67, 64, 32, 7144}, + /*II_66_0F_F8*/ {0x28, 73, 68, 48, 7144}, + /*II_0F_F9*/ {0x28, 67, 64, 32, 7159}, + /*II_66_0F_F9*/ {0x28, 73, 68, 48, 7159}, + /*II_0F_FA*/ {0x28, 67, 64, 32, 7174}, + /*II_66_0F_FA*/ {0x28, 73, 68, 48, 7174}, + /*II_0F_FB*/ {0x28, 67, 64, 48, 7189}, + /*II_66_0F_FB*/ {0x28, 73, 68, 48, 7189}, + /*II_0F_FC*/ {0x28, 67, 64, 32, 7204}, + /*II_66_0F_FC*/ {0x28, 73, 68, 48, 7204}, + /*II_0F_FD*/ {0x28, 67, 64, 32, 7219}, + /*II_66_0F_FD*/ {0x28, 73, 68, 48, 7219}, + /*II_0F_FE*/ {0x28, 67, 64, 32, 7234}, + /*II_66_0F_FE*/ {0x28, 73, 68, 48, 7234}, + /*II_D9_06*/ {0x34, 0, 42, 16, 7249}, + /*II_9B_D9_06*/ {0x60, 0, 42, 16, 7258}, + /*II_D9_07*/ {0x34, 0, 42, 16, 7266}, + /*II_9B_D9_07*/ {0x60, 0, 42, 16, 7274}, + /*II_DB_E2*/ {0x3a, 0, 0, 16, 7281}, + /*II_9B_DB_E2*/ {0x61, 0, 0, 16, 7289}, + /*II_DB_E3*/ {0x3a, 0, 0, 16, 7296}, + /*II_9B_DB_E3*/ {0x61, 0, 0, 16, 7304}, + /*II_DD_06*/ {0x34, 0, 42, 16, 7311}, + /*II_9B_DD_06*/ {0x60, 0, 42, 16, 7319}, + /*II_DD_07*/ {0x34, 0, 42, 16, 7326}, + /*II_9B_DD_07*/ {0x60, 0, 42, 16, 7334}, + /*II_DF_E0*/ {0x3a, 0, 34, 16, 7326}, + /*II_9B_DF_E0*/ {0x61, 0, 34, 16, 7334}, + /*II_0F_38_00*/ {0x28, 67, 64, 64, 7341}, + /*II_66_0F_38_00*/ {0x28, 73, 68, 64, 7341}, + /*II_0F_38_01*/ {0x28, 67, 64, 64, 7358}, + /*II_66_0F_38_01*/ {0x28, 73, 68, 64, 7358}, + /*II_0F_38_02*/ {0x28, 67, 64, 64, 7375}, + /*II_66_0F_38_02*/ {0x28, 73, 68, 64, 7375}, + /*II_0F_38_03*/ {0x28, 67, 64, 64, 7392}, + /*II_66_0F_38_03*/ {0x28, 73, 68, 64, 7392}, + /*II_0F_38_04*/ {0x28, 67, 64, 64, 7411}, + /*II_66_0F_38_04*/ {0x28, 73, 68, 64, 7411}, + /*II_0F_38_05*/ {0x28, 67, 64, 64, 7434}, + /*II_66_0F_38_05*/ {0x28, 73, 68, 64, 7434}, + /*II_0F_38_06*/ {0x28, 67, 64, 64, 7451}, + /*II_66_0F_38_06*/ {0x28, 73, 68, 64, 7451}, + /*II_0F_38_07*/ {0x28, 67, 64, 64, 7468}, + /*II_66_0F_38_07*/ {0x28, 73, 68, 64, 7468}, + /*II_0F_38_08*/ {0x28, 67, 64, 64, 7487}, + /*II_66_0F_38_08*/ {0x28, 73, 68, 64, 7487}, + /*II_0F_38_09*/ {0x28, 67, 64, 64, 7504}, + /*II_66_0F_38_09*/ {0x28, 73, 68, 64, 7504}, + /*II_0F_38_0A*/ {0x28, 67, 64, 64, 7521}, + /*II_66_0F_38_0A*/ {0x28, 73, 68, 64, 7521}, + /*II_0F_38_0B*/ {0x28, 67, 64, 64, 7538}, + /*II_66_0F_38_0B*/ {0x28, 73, 68, 64, 7538}, + /*II_66_0F_38_17*/ {0x28, 73, 68, 80, 7629}, + /*II_0F_38_1C*/ {0x28, 67, 64, 64, 7688}, + /*II_66_0F_38_1C*/ {0x28, 73, 68, 64, 7688}, + /*II_0F_38_1D*/ {0x28, 67, 64, 64, 7703}, + /*II_66_0F_38_1D*/ {0x28, 73, 68, 64, 7703}, + /*II_0F_38_1E*/ {0x28, 67, 64, 64, 7718}, + /*II_66_0F_38_1E*/ {0x28, 73, 68, 64, 7718}, + /*II_66_0F_38_20*/ {0x28, 72, 68, 72, 7733}, + /*II_66_0F_38_21*/ {0x28, 71, 68, 72, 7754}, + /*II_66_0F_38_22*/ {0x28, 70, 68, 72, 7775}, + /*II_66_0F_38_23*/ {0x28, 72, 68, 72, 7796}, + /*II_66_0F_38_24*/ {0x28, 71, 68, 72, 7817}, + /*II_66_0F_38_25*/ {0x28, 72, 68, 72, 7838}, + /*II_66_0F_38_28*/ {0x28, 73, 68, 72, 7859}, + /*II_66_0F_38_29*/ {0x28, 73, 68, 72, 7876}, + /*II_66_0F_38_2A*/ {0x29, 47, 68, 72, 7895}, + /*II_66_0F_38_2B*/ {0x28, 73, 68, 72, 7916}, + /*II_66_0F_38_30*/ {0x28, 72, 68, 72, 7961}, + /*II_66_0F_38_31*/ {0x28, 71, 68, 72, 7982}, + /*II_66_0F_38_32*/ {0x28, 70, 68, 72, 8003}, + /*II_66_0F_38_33*/ {0x28, 72, 68, 72, 8024}, + /*II_66_0F_38_34*/ {0x28, 71, 68, 72, 8045}, + /*II_66_0F_38_35*/ {0x28, 72, 68, 72, 8066}, + /*II_66_0F_38_37*/ {0x28, 73, 68, 80, 8087}, + /*II_66_0F_38_38*/ {0x28, 73, 68, 72, 8106}, + /*II_66_0F_38_39*/ {0x28, 73, 68, 72, 8123}, + /*II_66_0F_38_3A*/ {0x28, 73, 68, 72, 8140}, + /*II_66_0F_38_3B*/ {0x28, 73, 68, 72, 8157}, + /*II_66_0F_38_3C*/ {0x28, 73, 68, 72, 8174}, + /*II_66_0F_38_3D*/ {0x28, 73, 68, 72, 8191}, + /*II_66_0F_38_3E*/ {0x28, 73, 68, 72, 8208}, + /*II_66_0F_38_3F*/ {0x28, 73, 68, 72, 8225}, + /*II_66_0F_38_40*/ {0x28, 73, 68, 72, 8242}, + /*II_66_0F_38_41*/ {0x28, 73, 68, 72, 8259}, + /*II_66_0F_38_80*/ {0x4e, 47, 13, 112, 8284}, + /*II_66_0F_38_81*/ {0x4e, 47, 13, 112, 8292}, + /*II_66_0F_38_82*/ {0x4e, 47, 13, 112, 8301}, + /*II_66_0F_38_DB*/ {0x28, 73, 68, 152, 9150}, + /*II_66_0F_38_DC*/ {0x28, 73, 68, 152, 9167}, + /*II_66_0F_38_DD*/ {0x28, 73, 68, 152, 9184}, + /*II_66_0F_38_DE*/ {0x28, 73, 68, 152, 9209}, + /*II_66_0F_38_DF*/ {0x28, 73, 68, 152, 9226}, + /*II_0F_38_F0*/ {0x29, 17, 11, 8, 9251}, + /*II_F2_0F_38_F0*/ {0x29, 15, 13, 80, 9258}, + /*II_0F_38_F1*/ {0x29, 11, 17, 8, 9251}, + /*II_F2_0F_38_F1*/ {0x29, 17, 13, 80, 9258}, + /*II_0F_71_02*/ {0x63, 1, 65, 32, 6436}, + /*II_66_0F_71_02*/ {0x3c, 1, 69, 48, 6436}, + /*II_0F_71_04*/ {0x63, 1, 65, 32, 6695}, + /*II_66_0F_71_04*/ {0x3c, 1, 69, 48, 6695}, + /*II_0F_71_06*/ {0x63, 1, 65, 32, 7009}, + /*II_66_0F_71_06*/ {0x3c, 1, 69, 48, 7009}, + /*II_0F_72_02*/ {0x63, 1, 65, 32, 6451}, + /*II_66_0F_72_02*/ {0x3c, 1, 69, 48, 6451}, + /*II_0F_72_04*/ {0x63, 1, 65, 32, 6710}, + /*II_66_0F_72_04*/ {0x3c, 1, 69, 48, 6710}, + /*II_0F_72_06*/ {0x63, 1, 65, 32, 7024}, + /*II_66_0F_72_06*/ {0x3c, 1, 69, 48, 7024}, + /*II_0F_73_02*/ {0x63, 1, 65, 32, 6466}, + /*II_66_0F_73_02*/ {0x3c, 1, 69, 48, 6466}, + /*II_66_0F_73_03*/ {0x3c, 1, 69, 48, 9830}, + /*II_0F_73_06*/ {0x63, 1, 65, 32, 7039}, + /*II_66_0F_73_06*/ {0x3c, 1, 69, 48, 7039}, + /*II_66_0F_73_07*/ {0x3c, 1, 69, 48, 9847}, + /*II_F3_0F_AE_00*/ {0x65, 0, 13, 112, 9882}, + /*II_F3_0F_AE_01*/ {0x65, 0, 13, 112, 9912}, + /*II_0F_AE_02*/ {0x3c, 0, 42, 8, 9922}, + /*II_F3_0F_AE_02*/ {0x65, 0, 13, 112, 9931}, + /*II_0F_AE_03*/ {0x3c, 0, 42, 8, 9951}, + /*II_F3_0F_AE_03*/ {0x65, 0, 13, 112, 9960}, + /*II_66_0F_C7_06*/ {0x3c, 0, 46, 112, 9997}, + /*II_F3_0F_C7_06*/ {0x3c, 0, 46, 112, 10006} +}; + +_InstInfoEx InstInfosEx[] = { + /*II_69*/ {{0x17, 17, 11, 8, 117}, 0x0, 3, 0, 0, 0}, + /*II_6B*/ {{0x17, 17, 11, 8, 117}, 0x0, 5, 0, 0, 0}, + /*II_98*/ {{0x1c, 0, 0, 8, 228}, 0x0, 0, 0, 233, 239}, + /*II_99*/ {{0x1c, 0, 0, 8, 245}, 0x0, 0, 0, 250, 255}, + /*II_E3*/ {{0x25, 0, 40, 13, 427}, 0x0, 0, 0, 433, 440}, + /*II_0F_A4*/ {{0x2c, 11, 17, 8, 876}, 0x0, 1, 0, 0, 0}, + /*II_0F_A5*/ {{0x2c, 11, 17, 8, 876}, 0x0, 52, 0, 0, 0}, + /*II_0F_AC*/ {{0x2c, 11, 17, 8, 892}, 0x0, 1, 0, 0, 0}, + /*II_0F_AD*/ {{0x2c, 11, 17, 8, 892}, 0x0, 52, 0, 0, 0}, + /*II_V_0F_10*/ {{0x43, 90, 83, 128, 2117}, 0x41, 0, 0, 0, 0}, + /*II_V_66_0F_10*/ {{0x43, 90, 83, 128, 2126}, 0x41, 0, 0, 0, 0}, + /*II_V_F3_0F_10*/ {{0x44, 81, 68, 128, 2135}, 0x20, 69, 0, 0, 0}, + /*II_V_F2_0F_10*/ {{0x44, 81, 68, 128, 2143}, 0x20, 69, 0, 0, 0}, + /*II_VRR_F3_0F_10*/ {{0x45, 44, 68, 128, 2135}, 0x60, 0, 0, 0, 0}, + /*II_VRR_F2_0F_10*/ {{0x45, 46, 68, 128, 2143}, 0x60, 0, 0, 0, 0}, + /*II_V_0F_11*/ {{0x43, 83, 90, 128, 2117}, 0x41, 0, 0, 0, 0}, + /*II_V_66_0F_11*/ {{0x43, 83, 90, 128, 2126}, 0x41, 0, 0, 0, 0}, + /*II_V_F3_0F_11*/ {{0x44, 81, 68, 128, 2135}, 0x20, 69, 0, 0, 0}, + /*II_V_F2_0F_11*/ {{0x44, 81, 68, 128, 2143}, 0x20, 69, 0, 0, 0}, + /*II_VRR_F3_0F_11*/ {{0x45, 68, 44, 128, 2135}, 0x60, 0, 0, 0, 0}, + /*II_VRR_F2_0F_11*/ {{0x45, 68, 46, 128, 2143}, 0x60, 0, 0, 0, 0}, + /*II_0F_12*/ {{0x46, 72, 68, 40, 2151}, 0x0, 0, 0, 2160, 0}, + /*II_V_0F_12*/ {{0x47, 81, 68, 128, 2195}, 0x0, 72, 0, 2205, 0}, + /*II_V_66_0F_12*/ {{0x48, 81, 68, 128, 2214}, 0x0, 46, 0, 0, 0}, + /*II_V_F3_0F_12*/ {{0x43, 90, 83, 128, 2223}, 0x41, 0, 0, 0, 0}, + /*II_V_F2_0F_12*/ {{0x43, 89, 83, 128, 2234}, 0x41, 0, 0, 0, 0}, + /*II_V_0F_13*/ {{0x43, 68, 46, 128, 2205}, 0x40, 0, 0, 0, 0}, + /*II_V_66_0F_13*/ {{0x43, 68, 46, 128, 2214}, 0x40, 0, 0, 0, 0}, + /*II_V_0F_14*/ {{0x48, 88, 83, 128, 2264}, 0x1, 90, 0, 0, 0}, + /*II_V_66_0F_14*/ {{0x48, 88, 83, 128, 2275}, 0x1, 90, 0, 0, 0}, + /*II_V_0F_15*/ {{0x48, 88, 83, 128, 2306}, 0x1, 90, 0, 0, 0}, + /*II_V_66_0F_15*/ {{0x48, 88, 83, 128, 2317}, 0x1, 90, 0, 0, 0}, + /*II_0F_16*/ {{0x46, 72, 68, 40, 2328}, 0x0, 0, 0, 2337, 0}, + /*II_V_0F_16*/ {{0x47, 81, 68, 128, 2363}, 0x0, 72, 0, 2373, 0}, + /*II_V_66_0F_16*/ {{0x48, 81, 68, 128, 2382}, 0x0, 46, 0, 0, 0}, + /*II_V_F3_0F_16*/ {{0x43, 90, 83, 128, 2391}, 0x41, 0, 0, 0, 0}, + /*II_V_0F_17*/ {{0x43, 68, 46, 128, 2373}, 0x40, 0, 0, 0, 0}, + /*II_V_66_0F_17*/ {{0x43, 68, 46, 128, 2382}, 0x40, 0, 0, 0, 0}, + /*II_V_0F_28*/ {{0x43, 90, 83, 128, 2467}, 0x41, 0, 0, 0, 0}, + /*II_V_66_0F_28*/ {{0x43, 90, 83, 128, 2476}, 0x41, 0, 0, 0, 0}, + /*II_V_0F_29*/ {{0x43, 83, 90, 128, 2467}, 0x41, 0, 0, 0, 0}, + /*II_V_66_0F_29*/ {{0x43, 83, 90, 128, 2476}, 0x41, 0, 0, 0, 0}, + /*II_V_F3_0F_2A*/ {{0x48, 81, 68, 128, 2525}, 0x2, 79, 0, 0, 0}, + /*II_V_F2_0F_2A*/ {{0x48, 81, 68, 128, 2536}, 0x2, 79, 0, 0, 0}, + /*II_V_0F_2B*/ {{0x43, 83, 92, 128, 2583}, 0x41, 0, 0, 0, 0}, + /*II_V_66_0F_2B*/ {{0x43, 83, 92, 128, 2593}, 0x41, 0, 0, 0, 0}, + /*II_V_F3_0F_2C*/ {{0x43, 80, 78, 128, 2647}, 0x42, 0, 0, 0, 0}, + /*II_V_F2_0F_2C*/ {{0x43, 80, 78, 128, 2659}, 0x42, 0, 0, 0, 0}, + /*II_V_F3_0F_2D*/ {{0x43, 80, 78, 128, 2711}, 0x42, 0, 0, 0, 0}, + /*II_V_F2_0F_2D*/ {{0x43, 80, 78, 128, 2722}, 0x42, 0, 0, 0, 0}, + /*II_V_0F_2E*/ {{0x43, 71, 68, 128, 2751}, 0x40, 0, 0, 0, 0}, + /*II_V_66_0F_2E*/ {{0x43, 72, 68, 128, 2761}, 0x40, 0, 0, 0, 0}, + /*II_V_0F_2F*/ {{0x43, 71, 68, 128, 2787}, 0x40, 0, 0, 0, 0}, + /*II_V_66_0F_2F*/ {{0x43, 72, 68, 128, 2796}, 0x40, 0, 0, 0, 0}, + /*II_V_0F_50*/ {{0x4a, 83, 13, 128, 2825}, 0x41, 0, 0, 0, 0}, + /*II_V_66_0F_50*/ {{0x4a, 83, 13, 128, 2836}, 0x41, 0, 0, 0, 0}, + /*II_V_0F_51*/ {{0x43, 90, 83, 128, 2879}, 0x41, 0, 0, 0, 0}, + /*II_V_66_0F_51*/ {{0x43, 90, 83, 128, 2888}, 0x41, 0, 0, 0, 0}, + /*II_V_F3_0F_51*/ {{0x48, 81, 68, 128, 2897}, 0x0, 71, 0, 0, 0}, + /*II_V_F2_0F_51*/ {{0x48, 81, 68, 128, 2906}, 0x0, 72, 0, 0, 0}, + /*II_V_0F_52*/ {{0x43, 90, 83, 128, 2933}, 0x41, 0, 0, 0, 0}, + /*II_V_F3_0F_52*/ {{0x48, 81, 68, 128, 2943}, 0x0, 71, 0, 0, 0}, + /*II_V_0F_53*/ {{0x43, 90, 83, 128, 2967}, 0x41, 0, 0, 0, 0}, + /*II_V_F3_0F_53*/ {{0x48, 81, 68, 128, 2975}, 0x0, 71, 0, 0, 0}, + /*II_V_0F_54*/ {{0x48, 88, 83, 128, 2997}, 0x1, 90, 0, 0, 0}, + /*II_V_66_0F_54*/ {{0x48, 88, 83, 128, 3005}, 0x1, 90, 0, 0, 0}, + /*II_V_0F_55*/ {{0x48, 88, 83, 128, 3029}, 0x1, 90, 0, 0, 0}, + /*II_V_66_0F_55*/ {{0x48, 88, 83, 128, 3038}, 0x1, 90, 0, 0, 0}, + /*II_V_0F_56*/ {{0x48, 88, 83, 128, 3059}, 0x1, 90, 0, 0, 0}, + /*II_V_66_0F_56*/ {{0x48, 88, 83, 128, 3066}, 0x1, 90, 0, 0, 0}, + /*II_V_0F_57*/ {{0x48, 88, 83, 128, 3087}, 0x1, 90, 0, 0, 0}, + /*II_V_66_0F_57*/ {{0x48, 88, 83, 128, 3095}, 0x1, 90, 0, 0, 0}, + /*II_V_0F_58*/ {{0x48, 88, 83, 128, 3131}, 0x1, 90, 0, 0, 0}, + /*II_V_66_0F_58*/ {{0x48, 88, 83, 128, 3139}, 0x1, 90, 0, 0, 0}, + /*II_V_F3_0F_58*/ {{0x48, 81, 68, 128, 3147}, 0x0, 71, 0, 0, 0}, + /*II_V_F2_0F_58*/ {{0x48, 81, 68, 128, 3155}, 0x0, 72, 0, 0, 0}, + /*II_V_0F_59*/ {{0x48, 88, 83, 128, 3191}, 0x1, 90, 0, 0, 0}, + /*II_V_66_0F_59*/ {{0x48, 88, 83, 128, 3199}, 0x1, 90, 0, 0, 0}, + /*II_V_F3_0F_59*/ {{0x48, 81, 68, 128, 3207}, 0x0, 71, 0, 0, 0}, + /*II_V_F2_0F_59*/ {{0x48, 81, 68, 128, 3215}, 0x0, 72, 0, 0, 0}, + /*II_V_0F_5A*/ {{0x43, 91, 83, 128, 3263}, 0x41, 0, 0, 0, 0}, + /*II_V_66_0F_5A*/ {{0x43, 90, 68, 128, 3274}, 0x41, 0, 0, 0, 0}, + /*II_V_F3_0F_5A*/ {{0x48, 81, 68, 128, 3285}, 0x0, 71, 0, 0, 0}, + /*II_V_F2_0F_5A*/ {{0x48, 81, 68, 128, 3296}, 0x0, 72, 0, 0, 0}, + /*II_V_0F_5B*/ {{0x43, 90, 83, 128, 3338}, 0x41, 0, 0, 0, 0}, + /*II_V_66_0F_5B*/ {{0x43, 90, 83, 128, 3349}, 0x41, 0, 0, 0, 0}, + /*II_V_F3_0F_5B*/ {{0x43, 90, 83, 128, 3360}, 0x41, 0, 0, 0, 0}, + /*II_V_0F_5C*/ {{0x48, 88, 83, 128, 3400}, 0x1, 90, 0, 0, 0}, + /*II_V_66_0F_5C*/ {{0x48, 88, 83, 128, 3408}, 0x1, 90, 0, 0, 0}, + /*II_V_F3_0F_5C*/ {{0x48, 81, 68, 128, 3416}, 0x0, 71, 0, 0, 0}, + /*II_V_F2_0F_5C*/ {{0x48, 81, 68, 128, 3424}, 0x0, 72, 0, 0, 0}, + /*II_V_0F_5D*/ {{0x48, 88, 83, 128, 3460}, 0x1, 90, 0, 0, 0}, + /*II_V_66_0F_5D*/ {{0x48, 88, 83, 128, 3468}, 0x1, 90, 0, 0, 0}, + /*II_V_F3_0F_5D*/ {{0x48, 81, 68, 128, 3476}, 0x0, 71, 0, 0, 0}, + /*II_V_F2_0F_5D*/ {{0x48, 81, 68, 128, 3484}, 0x0, 72, 0, 0, 0}, + /*II_V_0F_5E*/ {{0x48, 88, 83, 128, 3520}, 0x1, 90, 0, 0, 0}, + /*II_V_66_0F_5E*/ {{0x48, 88, 83, 128, 3528}, 0x1, 90, 0, 0, 0}, + /*II_V_F3_0F_5E*/ {{0x48, 81, 68, 128, 3536}, 0x0, 71, 0, 0, 0}, + /*II_V_F2_0F_5E*/ {{0x48, 81, 68, 128, 3544}, 0x0, 72, 0, 0, 0}, + /*II_V_0F_5F*/ {{0x48, 88, 83, 128, 3580}, 0x1, 90, 0, 0, 0}, + /*II_V_66_0F_5F*/ {{0x48, 88, 83, 128, 3588}, 0x1, 90, 0, 0, 0}, + /*II_V_F3_0F_5F*/ {{0x48, 81, 68, 128, 3596}, 0x0, 71, 0, 0, 0}, + /*II_V_F2_0F_5F*/ {{0x48, 81, 68, 128, 3604}, 0x0, 72, 0, 0, 0}, + /*II_V_66_0F_60*/ {{0x48, 81, 68, 128, 3623}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_61*/ {{0x48, 81, 68, 128, 3646}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_62*/ {{0x48, 81, 68, 128, 3669}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_63*/ {{0x48, 81, 68, 128, 3691}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_64*/ {{0x48, 81, 68, 128, 3711}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_65*/ {{0x48, 81, 68, 128, 3730}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_66*/ {{0x48, 81, 68, 128, 3749}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_67*/ {{0x48, 81, 68, 128, 3769}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_68*/ {{0x48, 81, 68, 128, 3791}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_69*/ {{0x48, 81, 68, 128, 3814}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_6A*/ {{0x48, 81, 68, 128, 3837}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_6B*/ {{0x48, 81, 68, 128, 3859}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_6C*/ {{0x48, 81, 68, 128, 3882}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_6D*/ {{0x48, 81, 68, 128, 3907}, 0x0, 73, 0, 0, 0}, + /*II_0F_6E*/ {{0x4b, 18, 64, 32, 3920}, 0x0, 0, 0, 0, 3926}, + /*II_66_0F_6E*/ {{0x4b, 18, 68, 48, 3920}, 0x0, 0, 0, 0, 3926}, + /*II_V_66_0F_6E*/ {{0x43, 79, 68, 128, 3932}, 0x46, 0, 0, 3939, 0}, + /*II_V_66_0F_6F*/ {{0x43, 90, 83, 128, 3962}, 0x41, 0, 0, 0, 0}, + /*II_V_F3_0F_6F*/ {{0x43, 90, 83, 128, 3971}, 0x41, 0, 0, 0, 0}, + /*II_0F_70*/ {{0x4c, 67, 64, 40, 3980}, 0x0, 1, 0, 0, 0}, + /*II_66_0F_70*/ {{0x4c, 73, 68, 48, 3988}, 0x0, 1, 0, 0, 0}, + /*II_F3_0F_70*/ {{0x4c, 73, 68, 48, 3996}, 0x0, 1, 0, 0, 0}, + /*II_F2_0F_70*/ {{0x4c, 73, 68, 48, 4005}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_70*/ {{0x48, 73, 68, 128, 4014}, 0x40, 1, 0, 0, 0}, + /*II_V_F3_0F_70*/ {{0x48, 73, 68, 128, 4023}, 0x40, 1, 0, 0, 0}, + /*II_V_F2_0F_70*/ {{0x48, 73, 68, 128, 4033}, 0x40, 1, 0, 0, 0}, + /*II_V_66_0F_74*/ {{0x48, 81, 68, 128, 4052}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_75*/ {{0x48, 81, 68, 128, 4071}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_76*/ {{0x48, 81, 68, 128, 4090}, 0x0, 73, 0, 0, 0}, + /*II_V_0F_77*/ {{0x4d, 0, 0, 128, 4106}, 0x49, 0, 0, 4118, 0}, + /*II_66_0F_78*/ {{0x4f, 7, 69, 88, 4136}, 0x0, 8, 0, 0, 0}, + /*II_F2_0F_78*/ {{0x50, 69, 68, 88, 4143}, 0x0, 7, 8, 0, 0}, + /*II_V_66_0F_7C*/ {{0x48, 88, 83, 128, 4197}, 0x1, 90, 0, 0, 0}, + /*II_V_F2_0F_7C*/ {{0x48, 88, 83, 128, 4206}, 0x1, 90, 0, 0, 0}, + /*II_V_66_0F_7D*/ {{0x48, 88, 83, 128, 4231}, 0x1, 90, 0, 0, 0}, + /*II_V_F2_0F_7D*/ {{0x48, 88, 83, 128, 4240}, 0x1, 90, 0, 0, 0}, + /*II_0F_7E*/ {{0x4b, 64, 18, 32, 3920}, 0x0, 0, 0, 0, 3926}, + /*II_66_0F_7E*/ {{0x4b, 68, 18, 48, 3920}, 0x0, 0, 0, 0, 3926}, + /*II_V_66_0F_7E*/ {{0x43, 68, 79, 128, 3932}, 0x46, 0, 0, 3939, 0}, + /*II_V_F3_0F_7E*/ {{0x43, 72, 68, 128, 3939}, 0x40, 0, 0, 0, 0}, + /*II_V_66_0F_7F*/ {{0x43, 83, 90, 128, 3962}, 0x41, 0, 0, 0, 0}, + /*II_V_F3_0F_7F*/ {{0x43, 83, 90, 128, 3971}, 0x41, 0, 0, 0, 0}, + /*II_0F_AE_04*/ {{0x52, 0, 42, 8, 4249}, 0x0, 0, 0, 0, 4256}, + /*II_0F_AE_05*/ {{0x53, 0, 43, 8, 4265}, 0x0, 0, 0, 4273, 4281}, + /*II_0F_AE_06*/ {{0x53, 0, 43, 8, 4291}, 0x0, 0, 0, 4299, 4309}, + /*II_0F_AE_07*/ {{0x54, 0, 43, 8, 4321}, 0x0, 0, 0, 4329, 0}, + /*II_0F_C2*/ {{0x59, 73, 68, 40, 4370}, 0x0, 0, 0, 4379, 4388}, + /*II_66_0F_C2*/ {{0x59, 73, 68, 48, 4449}, 0x0, 0, 0, 4458, 4467}, + /*II_F3_0F_C2*/ {{0x59, 71, 68, 40, 4528}, 0x0, 0, 0, 4537, 4546}, + /*II_F2_0F_C2*/ {{0x59, 72, 68, 48, 4607}, 0x0, 0, 0, 4616, 4625}, + /*II_V_0F_C2*/ {{0x5a, 88, 83, 128, 4686}, 0x1, 90, 0, 4696, 4706}, + /*II_V_66_0F_C2*/ {{0x5a, 88, 83, 128, 5088}, 0x1, 90, 0, 5098, 5108}, + /*II_V_F3_0F_C2*/ {{0x5a, 81, 68, 128, 5490}, 0x0, 71, 0, 5500, 5510}, + /*II_V_F2_0F_C2*/ {{0x5a, 81, 68, 128, 5892}, 0x0, 72, 0, 5902, 5912}, + /*II_0F_C4*/ {{0x4c, 25, 64, 40, 6294}, 0x0, 1, 0, 0, 0}, + /*II_66_0F_C4*/ {{0x4c, 25, 68, 48, 6294}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_C4*/ {{0x5b, 81, 68, 128, 6302}, 0x0, 25, 1, 0, 0}, + /*II_0F_C5*/ {{0x5c, 65, 12, 40, 6311}, 0x0, 1, 0, 0, 0}, + /*II_66_0F_C5*/ {{0x4c, 69, 12, 48, 6311}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_C5*/ {{0x5d, 68, 13, 128, 6319}, 0x40, 1, 0, 0, 0}, + /*II_0F_C6*/ {{0x4c, 73, 68, 40, 6328}, 0x0, 1, 0, 0, 0}, + /*II_66_0F_C6*/ {{0x4c, 73, 68, 48, 6336}, 0x0, 1, 0, 0, 0}, + /*II_V_0F_C6*/ {{0x5b, 88, 83, 128, 6344}, 0x1, 90, 1, 0, 0}, + /*II_V_66_0F_C6*/ {{0x5b, 88, 83, 128, 6353}, 0x1, 90, 1, 0, 0}, + /*II_0F_C7_01*/ {{0x5e, 0, 48, 8, 6362}, 0x0, 0, 0, 0, 6373}, + /*II_V_66_0F_D0*/ {{0x48, 88, 83, 128, 6414}, 0x1, 90, 0, 0, 0}, + /*II_V_F2_0F_D0*/ {{0x48, 88, 83, 128, 6425}, 0x1, 90, 0, 0, 0}, + /*II_V_66_0F_D1*/ {{0x48, 81, 68, 128, 6443}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_D2*/ {{0x48, 81, 68, 128, 6458}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_D3*/ {{0x48, 81, 68, 128, 6473}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_D4*/ {{0x48, 81, 68, 128, 6488}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_D5*/ {{0x48, 81, 68, 128, 6504}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_D6*/ {{0x43, 68, 72, 128, 3939}, 0x40, 0, 0, 0, 0}, + /*II_V_66_0F_D7*/ {{0x4a, 68, 13, 128, 6541}, 0x40, 0, 0, 0, 0}, + /*II_V_66_0F_D8*/ {{0x48, 81, 68, 128, 6561}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_D9*/ {{0x48, 81, 68, 128, 6580}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_DA*/ {{0x48, 81, 68, 128, 6598}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_DB*/ {{0x48, 81, 68, 128, 6613}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_DC*/ {{0x48, 81, 68, 128, 6629}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_DD*/ {{0x48, 81, 68, 128, 6629}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_DE*/ {{0x48, 81, 68, 128, 6656}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_DF*/ {{0x48, 81, 68, 128, 6672}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_E0*/ {{0x48, 81, 68, 128, 6687}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_E1*/ {{0x48, 81, 68, 128, 6702}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_E2*/ {{0x48, 81, 68, 128, 6717}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_E3*/ {{0x48, 81, 68, 128, 6732}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_E4*/ {{0x48, 81, 68, 128, 6749}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_E5*/ {{0x48, 81, 68, 128, 6767}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_E6*/ {{0x43, 90, 68, 128, 6807}, 0x41, 0, 0, 0, 0}, + /*II_V_F3_0F_E6*/ {{0x43, 91, 83, 128, 6819}, 0x41, 0, 0, 0, 0}, + /*II_V_F2_0F_E6*/ {{0x43, 90, 68, 128, 6830}, 0x41, 0, 0, 0, 0}, + /*II_V_66_0F_E7*/ {{0x43, 83, 92, 128, 6858}, 0x41, 0, 0, 0, 0}, + /*II_V_66_0F_E8*/ {{0x48, 81, 68, 128, 6876}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_E9*/ {{0x48, 81, 68, 128, 6893}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_EA*/ {{0x48, 81, 68, 128, 6910}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_EB*/ {{0x48, 81, 68, 128, 6924}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_EC*/ {{0x48, 81, 68, 128, 6938}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_ED*/ {{0x48, 81, 68, 128, 6955}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_EE*/ {{0x48, 81, 68, 128, 6972}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_EF*/ {{0x48, 81, 68, 128, 6987}, 0x0, 73, 0, 0, 0}, + /*II_V_F2_0F_F0*/ {{0x43, 92, 83, 128, 7001}, 0x41, 0, 0, 0, 0}, + /*II_V_66_0F_F1*/ {{0x48, 81, 68, 128, 7016}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_F2*/ {{0x48, 81, 68, 128, 7031}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_F3*/ {{0x48, 81, 68, 128, 7046}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_F4*/ {{0x48, 81, 68, 128, 7063}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_F5*/ {{0x48, 81, 68, 128, 7082}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_F6*/ {{0x48, 81, 68, 128, 7100}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_F7*/ {{0x5f, 69, 68, 128, 7131}, 0x40, 0, 0, 0, 0}, + /*II_V_66_0F_F8*/ {{0x48, 81, 68, 128, 7151}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_F9*/ {{0x48, 81, 68, 128, 7166}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_FA*/ {{0x48, 81, 68, 128, 7181}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_FB*/ {{0x48, 81, 68, 128, 7196}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_FC*/ {{0x48, 81, 68, 128, 7211}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_FD*/ {{0x48, 81, 68, 128, 7226}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_FE*/ {{0x48, 81, 68, 128, 7241}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_38_00*/ {{0x48, 81, 68, 128, 7349}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_38_01*/ {{0x48, 81, 68, 128, 7366}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_38_02*/ {{0x48, 81, 68, 128, 7383}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_38_03*/ {{0x48, 81, 68, 128, 7401}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_38_04*/ {{0x48, 81, 68, 128, 7422}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_38_05*/ {{0x48, 81, 68, 128, 7442}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_38_06*/ {{0x48, 81, 68, 128, 7459}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_38_07*/ {{0x48, 81, 68, 128, 7477}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_38_08*/ {{0x48, 81, 68, 128, 7495}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_38_09*/ {{0x48, 81, 68, 128, 7512}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_38_0A*/ {{0x48, 81, 68, 128, 7529}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_38_0B*/ {{0x48, 81, 68, 128, 7548}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_38_0C*/ {{0x48, 88, 83, 128, 7559}, 0x1, 90, 0, 0, 0}, + /*II_V_66_0F_38_0D*/ {{0x48, 88, 83, 128, 7570}, 0x1, 90, 0, 0, 0}, + /*II_V_66_0F_38_0E*/ {{0x43, 90, 83, 128, 7581}, 0x41, 0, 0, 0, 0}, + /*II_V_66_0F_38_0F*/ {{0x43, 90, 83, 128, 7590}, 0x41, 0, 0, 0, 0}, + /*II_66_0F_38_10*/ {{0x4c, 73, 68, 72, 7599}, 0x0, 74, 0, 0, 0}, + /*II_66_0F_38_14*/ {{0x4c, 73, 68, 72, 7609}, 0x0, 74, 0, 0, 0}, + /*II_66_0F_38_15*/ {{0x4c, 73, 68, 72, 7619}, 0x0, 74, 0, 0, 0}, + /*II_V_66_0F_38_17*/ {{0x43, 90, 83, 128, 7636}, 0x41, 0, 0, 0, 0}, + /*II_V_66_0F_38_18*/ {{0x43, 44, 83, 128, 7644}, 0x41, 0, 0, 0, 0}, + /*II_V_66_0F_38_19*/ {{0x43, 46, 85, 128, 7658}, 0x50, 0, 0, 0, 0}, + /*II_V_66_0F_38_1A*/ {{0x43, 47, 85, 128, 7672}, 0x50, 0, 0, 0, 0}, + /*II_V_66_0F_38_1C*/ {{0x43, 73, 68, 128, 7695}, 0x40, 0, 0, 0, 0}, + /*II_V_66_0F_38_1D*/ {{0x43, 73, 68, 128, 7710}, 0x40, 0, 0, 0, 0}, + /*II_V_66_0F_38_1E*/ {{0x43, 73, 68, 128, 7725}, 0x40, 0, 0, 0, 0}, + /*II_V_66_0F_38_20*/ {{0x43, 72, 68, 128, 7743}, 0x40, 0, 0, 0, 0}, + /*II_V_66_0F_38_21*/ {{0x43, 71, 68, 128, 7764}, 0x40, 0, 0, 0, 0}, + /*II_V_66_0F_38_22*/ {{0x43, 70, 68, 128, 7785}, 0x40, 0, 0, 0, 0}, + /*II_V_66_0F_38_23*/ {{0x43, 72, 68, 128, 7806}, 0x40, 0, 0, 0, 0}, + /*II_V_66_0F_38_24*/ {{0x43, 71, 68, 128, 7827}, 0x40, 0, 0, 0, 0}, + /*II_V_66_0F_38_25*/ {{0x43, 72, 68, 128, 7848}, 0x40, 0, 0, 0, 0}, + /*II_V_66_0F_38_28*/ {{0x48, 81, 68, 128, 7867}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_38_29*/ {{0x48, 81, 68, 128, 7885}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_38_2A*/ {{0x43, 47, 68, 128, 7905}, 0x40, 0, 0, 0, 0}, + /*II_V_66_0F_38_2B*/ {{0x48, 81, 68, 128, 7926}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_38_2C*/ {{0x48, 88, 83, 128, 7937}, 0x1, 92, 0, 0, 0}, + /*II_V_66_0F_38_2D*/ {{0x48, 88, 83, 128, 7949}, 0x1, 92, 0, 0, 0}, + /*II_V_66_0F_38_2E*/ {{0x48, 88, 92, 128, 7937}, 0x1, 83, 0, 0, 0}, + /*II_V_66_0F_38_2F*/ {{0x48, 88, 92, 128, 7949}, 0x1, 83, 0, 0, 0}, + /*II_V_66_0F_38_30*/ {{0x43, 72, 68, 128, 7971}, 0x40, 0, 0, 0, 0}, + /*II_V_66_0F_38_31*/ {{0x43, 71, 68, 128, 7992}, 0x40, 0, 0, 0, 0}, + /*II_V_66_0F_38_32*/ {{0x43, 70, 68, 128, 8013}, 0x40, 0, 0, 0, 0}, + /*II_V_66_0F_38_33*/ {{0x43, 72, 68, 128, 8034}, 0x40, 0, 0, 0, 0}, + /*II_V_66_0F_38_34*/ {{0x43, 71, 68, 128, 8055}, 0x40, 0, 0, 0, 0}, + /*II_V_66_0F_38_35*/ {{0x43, 72, 68, 128, 8076}, 0x40, 0, 0, 0, 0}, + /*II_V_66_0F_38_37*/ {{0x48, 81, 68, 128, 8096}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_38_38*/ {{0x48, 81, 68, 128, 8114}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_38_39*/ {{0x48, 81, 68, 128, 8131}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_38_3A*/ {{0x48, 81, 68, 128, 8148}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_38_3B*/ {{0x48, 81, 68, 128, 8165}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_38_3C*/ {{0x48, 81, 68, 128, 8182}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_38_3D*/ {{0x48, 81, 68, 128, 8199}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_38_3E*/ {{0x48, 81, 68, 128, 8216}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_38_3F*/ {{0x48, 81, 68, 128, 8233}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_38_40*/ {{0x48, 81, 68, 128, 8250}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_38_41*/ {{0x43, 73, 68, 128, 8271}, 0x40, 0, 0, 0, 0}, + /*II_V_66_0F_38_96*/ {{0x48, 88, 83, 136, 8310}, 0x7, 90, 0, 8326, 0}, + /*II_V_66_0F_38_97*/ {{0x48, 88, 83, 136, 8342}, 0x7, 90, 0, 8358, 0}, + /*II_V_66_0F_38_98*/ {{0x48, 88, 83, 136, 8374}, 0x7, 90, 0, 8387, 0}, + /*II_V_66_0F_38_99*/ {{0x48, 81, 68, 136, 8400}, 0x6, 80, 0, 8413, 0}, + /*II_V_66_0F_38_9A*/ {{0x48, 88, 83, 136, 8426}, 0x7, 90, 0, 8439, 0}, + /*II_V_66_0F_38_9B*/ {{0x48, 81, 68, 136, 8452}, 0x6, 80, 0, 8465, 0}, + /*II_V_66_0F_38_9C*/ {{0x48, 88, 83, 136, 8478}, 0x7, 90, 0, 8492, 0}, + /*II_V_66_0F_38_9D*/ {{0x48, 81, 68, 136, 8506}, 0x6, 80, 0, 8520, 0}, + /*II_V_66_0F_38_9E*/ {{0x48, 88, 83, 136, 8534}, 0x7, 90, 0, 8548, 0}, + /*II_V_66_0F_38_9F*/ {{0x48, 81, 68, 136, 8562}, 0x6, 80, 0, 8576, 0}, + /*II_V_66_0F_38_A6*/ {{0x48, 88, 83, 136, 8590}, 0x7, 90, 0, 8606, 0}, + /*II_V_66_0F_38_A7*/ {{0x48, 88, 83, 136, 8622}, 0x7, 90, 0, 8638, 0}, + /*II_V_66_0F_38_A8*/ {{0x48, 88, 83, 136, 8654}, 0x7, 90, 0, 8667, 0}, + /*II_V_66_0F_38_A9*/ {{0x48, 81, 68, 136, 8680}, 0x6, 80, 0, 8693, 0}, + /*II_V_66_0F_38_AA*/ {{0x48, 88, 83, 136, 8706}, 0x7, 90, 0, 8719, 0}, + /*II_V_66_0F_38_AB*/ {{0x48, 81, 68, 136, 8732}, 0x6, 80, 0, 8745, 0}, + /*II_V_66_0F_38_AC*/ {{0x48, 88, 83, 136, 8758}, 0x7, 90, 0, 8772, 0}, + /*II_V_66_0F_38_AD*/ {{0x48, 81, 68, 136, 8786}, 0x6, 80, 0, 8800, 0}, + /*II_V_66_0F_38_AE*/ {{0x48, 88, 83, 136, 8814}, 0x7, 90, 0, 8828, 0}, + /*II_V_66_0F_38_AF*/ {{0x48, 81, 68, 136, 8842}, 0x6, 80, 0, 8856, 0}, + /*II_V_66_0F_38_B6*/ {{0x48, 88, 83, 136, 8870}, 0x7, 90, 0, 8886, 0}, + /*II_V_66_0F_38_B7*/ {{0x48, 88, 83, 136, 8902}, 0x7, 90, 0, 8918, 0}, + /*II_V_66_0F_38_B8*/ {{0x48, 88, 83, 136, 8934}, 0x7, 90, 0, 8947, 0}, + /*II_V_66_0F_38_B9*/ {{0x48, 81, 68, 136, 8960}, 0x6, 80, 0, 8973, 0}, + /*II_V_66_0F_38_BA*/ {{0x48, 88, 83, 136, 8986}, 0x7, 90, 0, 8999, 0}, + /*II_V_66_0F_38_BB*/ {{0x48, 81, 68, 136, 9012}, 0x6, 80, 0, 9025, 0}, + /*II_V_66_0F_38_BC*/ {{0x48, 88, 83, 136, 9038}, 0x7, 90, 0, 9052, 0}, + /*II_V_66_0F_38_BD*/ {{0x48, 81, 68, 136, 9066}, 0x6, 80, 0, 9080, 0}, + /*II_V_66_0F_38_BE*/ {{0x48, 88, 83, 136, 9094}, 0x7, 90, 0, 9108, 0}, + /*II_V_66_0F_38_BF*/ {{0x48, 81, 68, 136, 9122}, 0x6, 80, 0, 9136, 0}, + /*II_V_66_0F_38_DB*/ {{0x43, 73, 68, 152, 9158}, 0x40, 0, 0, 0, 0}, + /*II_V_66_0F_38_DC*/ {{0x48, 81, 68, 152, 9175}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_38_DD*/ {{0x48, 81, 68, 152, 9196}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_38_DE*/ {{0x48, 81, 68, 152, 9217}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_38_DF*/ {{0x48, 81, 68, 152, 9238}, 0x0, 73, 0, 0, 0}, + /*II_V_66_0F_3A_04*/ {{0x48, 90, 83, 128, 7559}, 0x41, 1, 0, 0, 0}, + /*II_V_66_0F_3A_05*/ {{0x48, 90, 83, 128, 7570}, 0x41, 1, 0, 0, 0}, + /*II_V_66_0F_3A_06*/ {{0x5b, 87, 85, 128, 9265}, 0x10, 86, 1, 0, 0}, + /*II_66_0F_3A_08*/ {{0x4c, 73, 68, 72, 9277}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_3A_08*/ {{0x48, 90, 83, 128, 9286}, 0x41, 1, 0, 0, 0}, + /*II_66_0F_3A_09*/ {{0x4c, 73, 68, 72, 9296}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_3A_09*/ {{0x48, 90, 83, 128, 9305}, 0x41, 1, 0, 0, 0}, + /*II_66_0F_3A_0A*/ {{0x4c, 71, 68, 72, 9315}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_3A_0A*/ {{0x5b, 81, 68, 128, 9324}, 0x0, 71, 1, 0, 0}, + /*II_66_0F_3A_0B*/ {{0x4c, 72, 68, 72, 9334}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_3A_0B*/ {{0x5b, 81, 68, 128, 9343}, 0x0, 72, 1, 0, 0}, + /*II_66_0F_3A_0C*/ {{0x4c, 73, 68, 72, 9353}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_3A_0C*/ {{0x5b, 88, 83, 128, 9362}, 0x1, 90, 1, 0, 0}, + /*II_66_0F_3A_0D*/ {{0x4c, 73, 68, 72, 9372}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_3A_0D*/ {{0x5b, 88, 83, 128, 9381}, 0x1, 90, 1, 0, 0}, + /*II_66_0F_3A_0E*/ {{0x4c, 73, 68, 72, 9391}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_3A_0E*/ {{0x5b, 81, 68, 128, 9400}, 0x0, 73, 1, 0, 0}, + /*II_0F_3A_0F*/ {{0x4c, 67, 64, 64, 9410}, 0x0, 1, 0, 0, 0}, + /*II_66_0F_3A_0F*/ {{0x4c, 73, 68, 64, 9410}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_3A_0F*/ {{0x5b, 81, 68, 128, 9419}, 0x0, 73, 1, 0, 0}, + /*II_66_0F_3A_14*/ {{0x4c, 68, 26, 72, 9429}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_3A_14*/ {{0x5d, 68, 76, 128, 9437}, 0x40, 1, 0, 0, 0}, + /*II_66_0F_3A_15*/ {{0x4c, 68, 27, 72, 6311}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_3A_15*/ {{0x5d, 68, 77, 128, 6319}, 0x40, 1, 0, 0, 0}, + /*II_66_0F_3A_16*/ {{0x62, 68, 18, 72, 9446}, 0x0, 1, 0, 0, 9454}, + /*II_V_66_0F_3A_16*/ {{0x48, 68, 79, 128, 9462}, 0x46, 1, 0, 9471, 0}, + /*II_66_0F_3A_17*/ {{0x4c, 68, 18, 72, 9480}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_3A_17*/ {{0x48, 68, 75, 128, 9491}, 0x40, 1, 0, 0, 0}, + /*II_V_66_0F_3A_18*/ {{0x5b, 87, 85, 128, 9503}, 0x10, 73, 1, 0, 0}, + /*II_V_66_0F_3A_19*/ {{0x48, 85, 73, 128, 9516}, 0x50, 1, 0, 0, 0}, + /*II_66_0F_3A_20*/ {{0x4c, 24, 68, 72, 9530}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_3A_20*/ {{0x5b, 81, 68, 128, 9538}, 0x0, 76, 1, 0, 0}, + /*II_66_0F_3A_21*/ {{0x4c, 71, 68, 72, 9547}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_3A_21*/ {{0x5b, 81, 68, 128, 9557}, 0x0, 71, 1, 0, 0}, + /*II_66_0F_3A_22*/ {{0x62, 18, 68, 72, 9568}, 0x0, 1, 0, 0, 9576}, + /*II_V_66_0F_3A_22*/ {{0x5b, 81, 68, 128, 9584}, 0x6, 79, 1, 9593, 0}, + /*II_66_0F_3A_40*/ {{0x4c, 73, 68, 72, 9602}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_3A_40*/ {{0x5b, 88, 83, 128, 9608}, 0x1, 90, 1, 0, 0}, + /*II_66_0F_3A_41*/ {{0x4c, 73, 68, 72, 9615}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_3A_41*/ {{0x5b, 81, 68, 128, 9621}, 0x0, 73, 1, 0, 0}, + /*II_66_0F_3A_42*/ {{0x4c, 73, 68, 72, 9628}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_3A_42*/ {{0x5b, 81, 68, 128, 9637}, 0x0, 73, 1, 0, 0}, + /*II_66_0F_3A_44*/ {{0x4c, 73, 68, 144, 9647}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_3A_44*/ {{0x5b, 81, 68, 144, 9658}, 0x0, 73, 1, 0, 0}, + /*II_V_66_0F_3A_4A*/ {{0x5b, 88, 83, 128, 9670}, 0x1, 90, 84, 0, 0}, + /*II_V_66_0F_3A_4B*/ {{0x5b, 88, 83, 128, 9681}, 0x1, 90, 84, 0, 0}, + /*II_V_66_0F_3A_4C*/ {{0x5b, 81, 68, 128, 9692}, 0x0, 73, 82, 0, 0}, + /*II_66_0F_3A_60*/ {{0x4c, 73, 68, 80, 9703}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_3A_60*/ {{0x48, 73, 68, 128, 9714}, 0x40, 1, 0, 0, 0}, + /*II_66_0F_3A_61*/ {{0x4c, 73, 68, 80, 9726}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_3A_61*/ {{0x48, 73, 68, 128, 9737}, 0x40, 1, 0, 0, 0}, + /*II_66_0F_3A_62*/ {{0x4c, 73, 68, 80, 9749}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_3A_62*/ {{0x48, 73, 68, 128, 9760}, 0x40, 1, 0, 0, 0}, + /*II_66_0F_3A_63*/ {{0x4c, 73, 68, 80, 9772}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_3A_63*/ {{0x48, 73, 68, 128, 9783}, 0x40, 1, 0, 0, 0}, + /*II_66_0F_3A_DF*/ {{0x4c, 73, 68, 152, 9795}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_3A_DF*/ {{0x48, 73, 68, 152, 9812}, 0x40, 1, 0, 0, 0}, + /*II_V_66_0F_71_02*/ {{0x64, 69, 81, 128, 6443}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_71_04*/ {{0x64, 69, 81, 128, 6702}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_71_06*/ {{0x64, 69, 81, 128, 7016}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_72_02*/ {{0x64, 69, 81, 128, 6458}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_72_04*/ {{0x64, 69, 81, 128, 6717}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_72_06*/ {{0x64, 69, 81, 128, 7031}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_73_02*/ {{0x64, 69, 81, 128, 6473}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_73_03*/ {{0x64, 69, 81, 128, 9838}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_73_06*/ {{0x64, 69, 81, 128, 7046}, 0x0, 1, 0, 0, 0}, + /*II_V_66_0F_73_07*/ {{0x64, 69, 81, 128, 9855}, 0x0, 1, 0, 0, 0}, + /*II_0F_AE_00*/ {{0x52, 0, 42, 8, 9864}, 0x0, 0, 0, 0, 9872}, + /*II_0F_AE_01*/ {{0x52, 0, 42, 8, 9892}, 0x0, 0, 0, 0, 9901}, + /*II_V_0F_AE_02*/ {{0x45, 0, 44, 128, 9941}, 0x40, 0, 0, 0, 0}, + /*II_V_0F_AE_03*/ {{0x45, 0, 44, 128, 9970}, 0x40, 0, 0, 0, 0}, + /*II_0F_C7_06*/ {{0x54, 0, 43, 112, 9980}, 0x0, 0, 0, 9988, 0} +}; + +_InstNode InstructionsTree[] = { +/* 0 - _00 */ 0x2000, +/* 1 - _01 */ 0x2001, +/* 2 - _02 */ 0x2002, +/* 3 - _03 */ 0x2003, +/* 4 - _04 */ 0x2004, +/* 5 - _05 */ 0x2005, +/* 6 - _06 */ 0x2006, +/* 7 - _07 */ 0x2007, +/* 8 - _08 */ 0x2008, +/* 9 - _09 */ 0x2009, +/* a - _0A */ 0x200a, +/* b - _0B */ 0x200b, +/* c - _0C */ 0x200c, +/* d - _0D */ 0x200d, +/* e - _0E */ 0x200e, +/* f - _0F */ 0x8100, +/* 10 - _10 */ 0x200f, +/* 11 - _11 */ 0x2010, +/* 12 - _12 */ 0x2011, +/* 13 - _13 */ 0x2012, +/* 14 - _14 */ 0x2013, +/* 15 - _15 */ 0x2014, +/* 16 - _16 */ 0x2015, +/* 17 - _17 */ 0x2016, +/* 18 - _18 */ 0x2017, +/* 19 - _19 */ 0x2018, +/* 1a - _1A */ 0x2019, +/* 1b - _1B */ 0x201a, +/* 1c - _1C */ 0x201b, +/* 1d - _1D */ 0x201c, +/* 1e - _1E */ 0x201d, +/* 1f - _1F */ 0x201e, +/* 20 - _20 */ 0x201f, +/* 21 - _21 */ 0x2020, +/* 22 - _22 */ 0x2021, +/* 23 - _23 */ 0x2022, +/* 24 - _24 */ 0x2023, +/* 25 - _25 */ 0x2024, +/* 26 - */ 0, +/* 27 - _27 */ 0x2025, +/* 28 - _28 */ 0x2026, +/* 29 - _29 */ 0x2027, +/* 2a - _2A */ 0x2028, +/* 2b - _2B */ 0x2029, +/* 2c - _2C */ 0x202a, +/* 2d - _2D */ 0x202b, +/* 2e - */ 0, +/* 2f - _2F */ 0x202c, +/* 30 - _30 */ 0x202d, +/* 31 - _31 */ 0x202e, +/* 32 - _32 */ 0x202f, +/* 33 - _33 */ 0x2030, +/* 34 - _34 */ 0x2031, +/* 35 - _35 */ 0x2032, +/* 36 - */ 0, +/* 37 - _37 */ 0x2033, +/* 38 - _38 */ 0x2034, +/* 39 - _39 */ 0x2035, +/* 3a - _3A */ 0x2036, +/* 3b - _3B */ 0x2037, +/* 3c - _3C */ 0x2038, +/* 3d - _3D */ 0x2039, +/* 3e - */ 0, +/* 3f - _3F */ 0x203a, +/* 40 - _40 */ 0x203b, +/* 41 - _40 */ 0x203c, +/* 42 - _40 */ 0x203d, +/* 43 - _40 */ 0x203e, +/* 44 - _40 */ 0x203f, +/* 45 - _40 */ 0x2040, +/* 46 - _40 */ 0x2041, +/* 47 - _40 */ 0x2042, +/* 48 - _48 */ 0x2043, +/* 49 - _48 */ 0x2044, +/* 4a - _48 */ 0x2045, +/* 4b - _48 */ 0x2046, +/* 4c - _48 */ 0x2047, +/* 4d - _48 */ 0x2048, +/* 4e - _48 */ 0x2049, +/* 4f - _48 */ 0x204a, +/* 50 - _50 */ 0x204b, +/* 51 - _50 */ 0x204c, +/* 52 - _50 */ 0x204d, +/* 53 - _50 */ 0x204e, +/* 54 - _50 */ 0x204f, +/* 55 - _50 */ 0x2050, +/* 56 - _50 */ 0x2051, +/* 57 - _50 */ 0x2052, +/* 58 - _58 */ 0x2053, +/* 59 - _58 */ 0x2054, +/* 5a - _58 */ 0x2055, +/* 5b - _58 */ 0x2056, +/* 5c - _58 */ 0x2057, +/* 5d - _58 */ 0x2058, +/* 5e - _58 */ 0x2059, +/* 5f - _58 */ 0x205a, +/* 60 - _60 */ 0x205b, +/* 61 - _61 */ 0x205c, +/* 62 - _62 */ 0x205d, +/* 63 - _63 */ 0x205e, +/* 64 - */ 0, +/* 65 - */ 0, +/* 66 - */ 0, +/* 67 - */ 0, +/* 68 - _68 */ 0x205f, +/* 69 - _69 */ 0x4000, +/* 6a - _6A */ 0x2060, +/* 6b - _6B */ 0x4001, +/* 6c - _6C */ 0x2061, +/* 6d - _6D */ 0x2062, +/* 6e - _6E */ 0x2063, +/* 6f - _6F */ 0x2064, +/* 70 - _70 */ 0x2065, +/* 71 - _71 */ 0x2066, +/* 72 - _72 */ 0x2067, +/* 73 - _73 */ 0x2068, +/* 74 - _74 */ 0x2069, +/* 75 - _75 */ 0x206a, +/* 76 - _76 */ 0x206b, +/* 77 - _77 */ 0x206c, +/* 78 - _78 */ 0x206d, +/* 79 - _79 */ 0x206e, +/* 7a - _7A */ 0x206f, +/* 7b - _7B */ 0x2070, +/* 7c - _7C */ 0x2071, +/* 7d - _7D */ 0x2072, +/* 7e - _7E */ 0x2073, +/* 7f - _7F */ 0x2074, +/* 80 - _80 */ 0x6200, +/* 81 - _81 */ 0x6208, +/* 82 - _82 */ 0x6210, +/* 83 - _83 */ 0x6218, +/* 84 - _84 */ 0x2075, +/* 85 - _85 */ 0x2076, +/* 86 - _86 */ 0x2077, +/* 87 - _87 */ 0x2078, +/* 88 - _88 */ 0x2079, +/* 89 - _89 */ 0x207a, +/* 8a - _8A */ 0x207b, +/* 8b - _8B */ 0x207c, +/* 8c - _8C */ 0x207d, +/* 8d - _8D */ 0x207e, +/* 8e - _8E */ 0x207f, +/* 8f - _8F */ 0x6220, +/* 90 - _90 */ 0x2080, +/* 91 - _91 */ 0x2081, +/* 92 - _92 */ 0x2082, +/* 93 - _93 */ 0x2083, +/* 94 - _94 */ 0x2084, +/* 95 - _95 */ 0x2085, +/* 96 - _96 */ 0x2086, +/* 97 - _97 */ 0x2087, +/* 98 - _98 */ 0x4002, +/* 99 - _99 */ 0x4003, +/* 9a - _9A */ 0x2088, +/* 9b - */ 0, +/* 9c - _9C */ 0x2089, +/* 9d - _9D */ 0x208a, +/* 9e - _9E */ 0x208b, +/* 9f - _9F */ 0x208c, +/* a0 - _A0 */ 0x208d, +/* a1 - _A1 */ 0x208e, +/* a2 - _A2 */ 0x208f, +/* a3 - _A3 */ 0x2090, +/* a4 - _A4 */ 0x2091, +/* a5 - _A5 */ 0x2092, +/* a6 - _A6 */ 0x2093, +/* a7 - _A7 */ 0x2094, +/* a8 - _A8 */ 0x2095, +/* a9 - _A9 */ 0x2096, +/* aa - _AA */ 0x2097, +/* ab - _AB */ 0x2098, +/* ac - _AC */ 0x2099, +/* ad - _AD */ 0x209a, +/* ae - _AE */ 0x209b, +/* af - _AF */ 0x209c, +/* b0 - _B0 */ 0x209d, +/* b1 - _B0 */ 0x209e, +/* b2 - _B0 */ 0x209f, +/* b3 - _B0 */ 0x20a0, +/* b4 - _B0 */ 0x20a1, +/* b5 - _B0 */ 0x20a2, +/* b6 - _B0 */ 0x20a3, +/* b7 - _B0 */ 0x20a4, +/* b8 - _B8 */ 0x20a5, +/* b9 - _B8 */ 0x20a6, +/* ba - _B8 */ 0x20a7, +/* bb - _B8 */ 0x20a8, +/* bc - _B8 */ 0x20a9, +/* bd - _B8 */ 0x20aa, +/* be - _B8 */ 0x20ab, +/* bf - _B8 */ 0x20ac, +/* c0 - _C0 */ 0x6228, +/* c1 - _C1 */ 0x6230, +/* c2 - _C2 */ 0x20ad, +/* c3 - _C3 */ 0x20ae, +/* c4 - _C4 */ 0x20af, +/* c5 - _C5 */ 0x20b0, +/* c6 - _C6 */ 0x6238, +/* c7 - _C7 */ 0x6240, +/* c8 - _C8 */ 0x20b1, +/* c9 - _C9 */ 0x20b2, +/* ca - _CA */ 0x20b3, +/* cb - _CB */ 0x20b4, +/* cc - _CC */ 0x20b5, +/* cd - _CD */ 0x20b6, +/* ce - _CE */ 0x20b7, +/* cf - _CF */ 0x20b8, +/* d0 - _D0 */ 0x6248, +/* d1 - _D1 */ 0x6250, +/* d2 - _D2 */ 0x6258, +/* d3 - _D3 */ 0x6260, +/* d4 - _D4 */ 0x20b9, +/* d5 - _D5 */ 0x20ba, +/* d6 - _D6 */ 0x20bb, +/* d7 - _D7 */ 0x20bc, +/* d8 - _D8 */ 0xa268, +/* d9 - _D9 */ 0xa2b0, +/* da - _DA */ 0xa2f8, +/* db - _DB */ 0xa340, +/* dc - _DC */ 0xa388, +/* dd - _DD */ 0xa3d0, +/* de - _DE */ 0xa418, +/* df - _DF */ 0xa460, +/* e0 - _E0 */ 0x20bd, +/* e1 - _E1 */ 0x20be, +/* e2 - _E2 */ 0x20bf, +/* e3 - _E3 */ 0x4004, +/* e4 - _E4 */ 0x20c0, +/* e5 - _E5 */ 0x20c1, +/* e6 - _E6 */ 0x20c2, +/* e7 - _E7 */ 0x20c3, +/* e8 - _E8 */ 0x20c4, +/* e9 - _E9 */ 0x20c5, +/* ea - _EA */ 0x20c6, +/* eb - _EB */ 0x20c7, +/* ec - _EC */ 0x20c8, +/* ed - _ED */ 0x20c9, +/* ee - _EE */ 0x20ca, +/* ef - _EF */ 0x20cb, +/* f0 - */ 0, +/* f1 - _F1 */ 0x20cc, +/* f2 - */ 0, +/* f3 - */ 0, +/* f4 - _F4 */ 0x20cd, +/* f5 - _F5 */ 0x20ce, +/* f6 - _F6 */ 0x64a8, +/* f7 - _F7 */ 0x64b0, +/* f8 - _F8 */ 0x20cf, +/* f9 - _F9 */ 0x20d0, +/* fa - _FA */ 0x20d1, +/* fb - _FB */ 0x20d2, +/* fc - _FC */ 0x20d3, +/* fd - _FD */ 0x20d4, +/* fe - _FE */ 0x64b8, +/* ff - _FF */ 0x64c0, +/* 100 - _0F_00 */ 0x64c8, +/* 101 - _0F_01 */ 0xa4d0, +/* 102 - _0F_02 */ 0x20d5, +/* 103 - _0F_03 */ 0x20d6, +/* 104 - */ 0, +/* 105 - _0F_05 */ 0x20d7, +/* 106 - _0F_06 */ 0x20d8, +/* 107 - _0F_07 */ 0x20d9, +/* 108 - _0F_08 */ 0x20da, +/* 109 - _0F_09 */ 0x20db, +/* 10a - */ 0, +/* 10b - _0F_0B */ 0x20dc, +/* 10c - */ 0, +/* 10d - _0F_0D */ 0x6518, +/* 10e - _0F_0E */ 0x20dd, +/* 10f - _0F_0F */ 0x8520, +/* 110 - _0F_10 */ 0xc620, +/* 111 - _0F_11 */ 0xc62c, +/* 112 - _0F_12 */ 0xc638, +/* 113 - _0F_13 */ 0xc644, +/* 114 - _0F_14 */ 0xc650, +/* 115 - _0F_15 */ 0xc65c, +/* 116 - _0F_16 */ 0xc668, +/* 117 - _0F_17 */ 0xc674, +/* 118 - _0F_18 */ 0x6680, +/* 119 - */ 0, +/* 11a - */ 0, +/* 11b - */ 0, +/* 11c - */ 0, +/* 11d - */ 0, +/* 11e - */ 0, +/* 11f - _0F_1F */ 0x20de, +/* 120 - _0F_20 */ 0x20df, +/* 121 - _0F_21 */ 0x20e0, +/* 122 - _0F_22 */ 0x20e1, +/* 123 - _0F_23 */ 0x20e2, +/* 124 - */ 0, +/* 125 - */ 0, +/* 126 - */ 0, +/* 127 - */ 0, +/* 128 - _0F_28 */ 0xc688, +/* 129 - _0F_29 */ 0xc694, +/* 12a - _0F_2A */ 0xc6a0, +/* 12b - _0F_2B */ 0xc6ac, +/* 12c - _0F_2C */ 0xc6b8, +/* 12d - _0F_2D */ 0xc6c4, +/* 12e - _0F_2E */ 0xc6d0, +/* 12f - _0F_2F */ 0xc6dc, +/* 130 - _0F_30 */ 0x20e3, +/* 131 - _0F_31 */ 0x20e4, +/* 132 - _0F_32 */ 0x20e5, +/* 133 - _0F_33 */ 0x20e6, +/* 134 - _0F_34 */ 0x20e7, +/* 135 - _0F_35 */ 0x20e8, +/* 136 - */ 0, +/* 137 - _0F_37 */ 0x20e9, +/* 138 - _0F_38 */ 0x86e8, +/* 139 - */ 0, +/* 13a - _0F_3A */ 0x87e8, +/* 13b - */ 0, +/* 13c - */ 0, +/* 13d - */ 0, +/* 13e - */ 0, +/* 13f - */ 0, +/* 140 - _0F_40 */ 0x20ea, +/* 141 - _0F_41 */ 0x20eb, +/* 142 - _0F_42 */ 0x20ec, +/* 143 - _0F_43 */ 0x20ed, +/* 144 - _0F_44 */ 0x20ee, +/* 145 - _0F_45 */ 0x20ef, +/* 146 - _0F_46 */ 0x20f0, +/* 147 - _0F_47 */ 0x20f1, +/* 148 - _0F_48 */ 0x20f2, +/* 149 - _0F_49 */ 0x20f3, +/* 14a - _0F_4A */ 0x20f4, +/* 14b - _0F_4B */ 0x20f5, +/* 14c - _0F_4C */ 0x20f6, +/* 14d - _0F_4D */ 0x20f7, +/* 14e - _0F_4E */ 0x20f8, +/* 14f - _0F_4F */ 0x20f9, +/* 150 - _0F_50 */ 0xc8e8, +/* 151 - _0F_51 */ 0xc8f4, +/* 152 - _0F_52 */ 0xc900, +/* 153 - _0F_53 */ 0xc90c, +/* 154 - _0F_54 */ 0xc918, +/* 155 - _0F_55 */ 0xc924, +/* 156 - _0F_56 */ 0xc930, +/* 157 - _0F_57 */ 0xc93c, +/* 158 - _0F_58 */ 0xc948, +/* 159 - _0F_59 */ 0xc954, +/* 15a - _0F_5A */ 0xc960, +/* 15b - _0F_5B */ 0xc96c, +/* 15c - _0F_5C */ 0xc978, +/* 15d - _0F_5D */ 0xc984, +/* 15e - _0F_5E */ 0xc990, +/* 15f - _0F_5F */ 0xc99c, +/* 160 - _0F_60 */ 0xc9a8, +/* 161 - _0F_61 */ 0xc9b4, +/* 162 - _0F_62 */ 0xc9c0, +/* 163 - _0F_63 */ 0xc9cc, +/* 164 - _0F_64 */ 0xc9d8, +/* 165 - _0F_65 */ 0xc9e4, +/* 166 - _0F_66 */ 0xc9f0, +/* 167 - _0F_67 */ 0xc9fc, +/* 168 - _0F_68 */ 0xca08, +/* 169 - _0F_69 */ 0xca14, +/* 16a - _0F_6A */ 0xca20, +/* 16b - _0F_6B */ 0xca2c, +/* 16c - _0F_6C */ 0xca38, +/* 16d - _0F_6D */ 0xca44, +/* 16e - _0F_6E */ 0xca50, +/* 16f - _0F_6F */ 0xca5c, +/* 170 - _0F_70 */ 0xca68, +/* 171 - _0F_71 */ 0x6a74, +/* 172 - _0F_72 */ 0x6a7c, +/* 173 - _0F_73 */ 0x6a84, +/* 174 - _0F_74 */ 0xca8c, +/* 175 - _0F_75 */ 0xca98, +/* 176 - _0F_76 */ 0xcaa4, +/* 177 - _0F_77 */ 0xcab0, +/* 178 - _0F_78 */ 0xcabc, +/* 179 - _0F_79 */ 0xcac8, +/* 17a - _0F_7A */ 0x8ad4, +/* 17b - */ 0, +/* 17c - _0F_7C */ 0xcbd4, +/* 17d - _0F_7D */ 0xcbe0, +/* 17e - _0F_7E */ 0xcbec, +/* 17f - _0F_7F */ 0xcbf8, +/* 180 - _0F_80 */ 0x20fa, +/* 181 - _0F_81 */ 0x20fb, +/* 182 - _0F_82 */ 0x20fc, +/* 183 - _0F_83 */ 0x20fd, +/* 184 - _0F_84 */ 0x20fe, +/* 185 - _0F_85 */ 0x20ff, +/* 186 - _0F_86 */ 0x2100, +/* 187 - _0F_87 */ 0x2101, +/* 188 - _0F_88 */ 0x2102, +/* 189 - _0F_89 */ 0x2103, +/* 18a - _0F_8A */ 0x2104, +/* 18b - _0F_8B */ 0x2105, +/* 18c - _0F_8C */ 0x2106, +/* 18d - _0F_8D */ 0x2107, +/* 18e - _0F_8E */ 0x2108, +/* 18f - _0F_8F */ 0x2109, +/* 190 - _0F_90 */ 0x210a, +/* 191 - _0F_91 */ 0x210b, +/* 192 - _0F_92 */ 0x210c, +/* 193 - _0F_93 */ 0x210d, +/* 194 - _0F_94 */ 0x210e, +/* 195 - _0F_95 */ 0x210f, +/* 196 - _0F_96 */ 0x2110, +/* 197 - _0F_97 */ 0x2111, +/* 198 - _0F_98 */ 0x2112, +/* 199 - _0F_99 */ 0x2113, +/* 19a - _0F_9A */ 0x2114, +/* 19b - _0F_9B */ 0x2115, +/* 19c - _0F_9C */ 0x2116, +/* 19d - _0F_9D */ 0x2117, +/* 19e - _0F_9E */ 0x2118, +/* 19f - _0F_9F */ 0x2119, +/* 1a0 - _0F_A0 */ 0x211a, +/* 1a1 - _0F_A1 */ 0x211b, +/* 1a2 - _0F_A2 */ 0x211c, +/* 1a3 - _0F_A3 */ 0x211d, +/* 1a4 - _0F_A4 */ 0x4005, +/* 1a5 - _0F_A5 */ 0x4006, +/* 1a6 - */ 0, +/* 1a7 - */ 0, +/* 1a8 - _0F_A8 */ 0x211e, +/* 1a9 - _0F_A9 */ 0x211f, +/* 1aa - _0F_AA */ 0x2120, +/* 1ab - _0F_AB */ 0x2121, +/* 1ac - _0F_AC */ 0x4007, +/* 1ad - _0F_AD */ 0x4008, +/* 1ae - _0F_AE */ 0x6c04, +/* 1af - _0F_AF */ 0x2122, +/* 1b0 - _0F_B0 */ 0x2123, +/* 1b1 - _0F_B1 */ 0x2124, +/* 1b2 - _0F_B2 */ 0x2125, +/* 1b3 - _0F_B3 */ 0x2126, +/* 1b4 - _0F_B4 */ 0x2127, +/* 1b5 - _0F_B5 */ 0x2128, +/* 1b6 - _0F_B6 */ 0x2129, +/* 1b7 - _0F_B7 */ 0x212a, +/* 1b8 - _0F_B8 */ 0xcc0c, +/* 1b9 - _0F_B9 */ 0x212b, +/* 1ba - _0F_BA */ 0x6c18, +/* 1bb - _0F_BB */ 0x212c, +/* 1bc - _0F_BC */ 0xcc20, +/* 1bd - _0F_BD */ 0xcc2c, +/* 1be - _0F_BE */ 0x212d, +/* 1bf - _0F_BF */ 0x212e, +/* 1c0 - _0F_C0 */ 0x212f, +/* 1c1 - _0F_C1 */ 0x2130, +/* 1c2 - _0F_C2 */ 0xcc38, +/* 1c3 - _0F_C3 */ 0x2131, +/* 1c4 - _0F_C4 */ 0xcc44, +/* 1c5 - _0F_C5 */ 0xcc50, +/* 1c6 - _0F_C6 */ 0xcc5c, +/* 1c7 - _0F_C7 */ 0x6c68, +/* 1c8 - _0F_C8 */ 0x2132, +/* 1c9 - _0F_C8 */ 0x2133, +/* 1ca - _0F_C8 */ 0x2134, +/* 1cb - _0F_C8 */ 0x2135, +/* 1cc - _0F_C8 */ 0x2136, +/* 1cd - _0F_C8 */ 0x2137, +/* 1ce - _0F_C8 */ 0x2138, +/* 1cf - _0F_C8 */ 0x2139, +/* 1d0 - _0F_D0 */ 0xcc70, +/* 1d1 - _0F_D1 */ 0xcc7c, +/* 1d2 - _0F_D2 */ 0xcc88, +/* 1d3 - _0F_D3 */ 0xcc94, +/* 1d4 - _0F_D4 */ 0xcca0, +/* 1d5 - _0F_D5 */ 0xccac, +/* 1d6 - _0F_D6 */ 0xccb8, +/* 1d7 - _0F_D7 */ 0xccc4, +/* 1d8 - _0F_D8 */ 0xccd0, +/* 1d9 - _0F_D9 */ 0xccdc, +/* 1da - _0F_DA */ 0xcce8, +/* 1db - _0F_DB */ 0xccf4, +/* 1dc - _0F_DC */ 0xcd00, +/* 1dd - _0F_DD */ 0xcd0c, +/* 1de - _0F_DE */ 0xcd18, +/* 1df - _0F_DF */ 0xcd24, +/* 1e0 - _0F_E0 */ 0xcd30, +/* 1e1 - _0F_E1 */ 0xcd3c, +/* 1e2 - _0F_E2 */ 0xcd48, +/* 1e3 - _0F_E3 */ 0xcd54, +/* 1e4 - _0F_E4 */ 0xcd60, +/* 1e5 - _0F_E5 */ 0xcd6c, +/* 1e6 - _0F_E6 */ 0xcd78, +/* 1e7 - _0F_E7 */ 0xcd84, +/* 1e8 - _0F_E8 */ 0xcd90, +/* 1e9 - _0F_E9 */ 0xcd9c, +/* 1ea - _0F_EA */ 0xcda8, +/* 1eb - _0F_EB */ 0xcdb4, +/* 1ec - _0F_EC */ 0xcdc0, +/* 1ed - _0F_ED */ 0xcdcc, +/* 1ee - _0F_EE */ 0xcdd8, +/* 1ef - _0F_EF */ 0xcde4, +/* 1f0 - _0F_F0 */ 0xcdf0, +/* 1f1 - _0F_F1 */ 0xcdfc, +/* 1f2 - _0F_F2 */ 0xce08, +/* 1f3 - _0F_F3 */ 0xce14, +/* 1f4 - _0F_F4 */ 0xce20, +/* 1f5 - _0F_F5 */ 0xce2c, +/* 1f6 - _0F_F6 */ 0xce38, +/* 1f7 - _0F_F7 */ 0xce44, +/* 1f8 - _0F_F8 */ 0xce50, +/* 1f9 - _0F_F9 */ 0xce5c, +/* 1fa - _0F_FA */ 0xce68, +/* 1fb - _0F_FB */ 0xce74, +/* 1fc - _0F_FC */ 0xce80, +/* 1fd - _0F_FD */ 0xce8c, +/* 1fe - _0F_FE */ 0xce98, +/* 1ff - */ 0, +/* 200 - _80_00 */ 0x213a, +/* 201 - _80_01 */ 0x213b, +/* 202 - _80_02 */ 0x213c, +/* 203 - _80_03 */ 0x213d, +/* 204 - _80_04 */ 0x213e, +/* 205 - _80_05 */ 0x213f, +/* 206 - _80_06 */ 0x2140, +/* 207 - _80_07 */ 0x2141, +/* 208 - _81_00 */ 0x2142, +/* 209 - _81_01 */ 0x2143, +/* 20a - _81_02 */ 0x2144, +/* 20b - _81_03 */ 0x2145, +/* 20c - _81_04 */ 0x2146, +/* 20d - _81_05 */ 0x2147, +/* 20e - _81_06 */ 0x2148, +/* 20f - _81_07 */ 0x2149, +/* 210 - _82_00 */ 0x214a, +/* 211 - _82_01 */ 0x214b, +/* 212 - _82_02 */ 0x214c, +/* 213 - _82_03 */ 0x214d, +/* 214 - _82_04 */ 0x214e, +/* 215 - _82_05 */ 0x214f, +/* 216 - _82_06 */ 0x2150, +/* 217 - _82_07 */ 0x2151, +/* 218 - _83_00 */ 0x2152, +/* 219 - _83_01 */ 0x2153, +/* 21a - _83_02 */ 0x2154, +/* 21b - _83_03 */ 0x2155, +/* 21c - _83_04 */ 0x2156, +/* 21d - _83_05 */ 0x2157, +/* 21e - _83_06 */ 0x2158, +/* 21f - _83_07 */ 0x2159, +/* 220 - _8F_00 */ 0x215a, +/* 221 - */ 0, +/* 222 - */ 0, +/* 223 - */ 0, +/* 224 - */ 0, +/* 225 - */ 0, +/* 226 - */ 0, +/* 227 - */ 0, +/* 228 - _C0_00 */ 0x215b, +/* 229 - _C0_01 */ 0x215c, +/* 22a - _C0_02 */ 0x215d, +/* 22b - _C0_03 */ 0x215e, +/* 22c - _C0_04 */ 0x215f, +/* 22d - _C0_05 */ 0x2160, +/* 22e - _C0_06 */ 0x2161, +/* 22f - _C0_07 */ 0x2162, +/* 230 - _C1_00 */ 0x2163, +/* 231 - _C1_01 */ 0x2164, +/* 232 - _C1_02 */ 0x2165, +/* 233 - _C1_03 */ 0x2166, +/* 234 - _C1_04 */ 0x2167, +/* 235 - _C1_05 */ 0x2168, +/* 236 - _C1_06 */ 0x2169, +/* 237 - _C1_07 */ 0x216a, +/* 238 - _C6_00 */ 0x216b, +/* 239 - */ 0, +/* 23a - */ 0, +/* 23b - */ 0, +/* 23c - */ 0, +/* 23d - */ 0, +/* 23e - */ 0, +/* 23f - */ 0, +/* 240 - _C7_00 */ 0x216c, +/* 241 - */ 0, +/* 242 - */ 0, +/* 243 - */ 0, +/* 244 - */ 0, +/* 245 - */ 0, +/* 246 - */ 0, +/* 247 - */ 0, +/* 248 - _D0_00 */ 0x216d, +/* 249 - _D0_01 */ 0x216e, +/* 24a - _D0_02 */ 0x216f, +/* 24b - _D0_03 */ 0x2170, +/* 24c - _D0_04 */ 0x2171, +/* 24d - _D0_05 */ 0x2172, +/* 24e - _D0_06 */ 0x2173, +/* 24f - _D0_07 */ 0x2174, +/* 250 - _D1_00 */ 0x2175, +/* 251 - _D1_01 */ 0x2176, +/* 252 - _D1_02 */ 0x2177, +/* 253 - _D1_03 */ 0x2178, +/* 254 - _D1_04 */ 0x2179, +/* 255 - _D1_05 */ 0x217a, +/* 256 - _D1_06 */ 0x217b, +/* 257 - _D1_07 */ 0x217c, +/* 258 - _D2_00 */ 0x217d, +/* 259 - _D2_01 */ 0x217e, +/* 25a - _D2_02 */ 0x217f, +/* 25b - _D2_03 */ 0x2180, +/* 25c - _D2_04 */ 0x2181, +/* 25d - _D2_05 */ 0x2182, +/* 25e - _D2_06 */ 0x2183, +/* 25f - _D2_07 */ 0x2184, +/* 260 - _D3_00 */ 0x2185, +/* 261 - _D3_01 */ 0x2186, +/* 262 - _D3_02 */ 0x2187, +/* 263 - _D3_03 */ 0x2188, +/* 264 - _D3_04 */ 0x2189, +/* 265 - _D3_05 */ 0x218a, +/* 266 - _D3_06 */ 0x218b, +/* 267 - _D3_07 */ 0x218c, +/* 268 - _D8_00 */ 0x218d, +/* 269 - _D8_01 */ 0x218e, +/* 26a - _D8_02 */ 0x218f, +/* 26b - _D8_03 */ 0x2190, +/* 26c - _D8_04 */ 0x2191, +/* 26d - _D8_05 */ 0x2192, +/* 26e - _D8_06 */ 0x2193, +/* 26f - _D8_07 */ 0x2194, +/* 270 - _D8_C0 */ 0x2195, +/* 271 - _D8_C0 */ 0x2196, +/* 272 - _D8_C0 */ 0x2197, +/* 273 - _D8_C0 */ 0x2198, +/* 274 - _D8_C0 */ 0x2199, +/* 275 - _D8_C0 */ 0x219a, +/* 276 - _D8_C0 */ 0x219b, +/* 277 - _D8_C0 */ 0x219c, +/* 278 - _D8_C8 */ 0x219d, +/* 279 - _D8_C8 */ 0x219e, +/* 27a - _D8_C8 */ 0x219f, +/* 27b - _D8_C8 */ 0x21a0, +/* 27c - _D8_C8 */ 0x21a1, +/* 27d - _D8_C8 */ 0x21a2, +/* 27e - _D8_C8 */ 0x21a3, +/* 27f - _D8_C8 */ 0x21a4, +/* 280 - _D8_D0 */ 0x21a5, +/* 281 - _D8_D0 */ 0x21a6, +/* 282 - _D8_D0 */ 0x21a7, +/* 283 - _D8_D0 */ 0x21a8, +/* 284 - _D8_D0 */ 0x21a9, +/* 285 - _D8_D0 */ 0x21aa, +/* 286 - _D8_D0 */ 0x21ab, +/* 287 - _D8_D0 */ 0x21ac, +/* 288 - _D8_D8 */ 0x21ad, +/* 289 - _D8_D9 */ 0x21ae, +/* 28a - _D8_D8 */ 0x21af, +/* 28b - _D8_D8 */ 0x21b0, +/* 28c - _D8_D8 */ 0x21b1, +/* 28d - _D8_D8 */ 0x21b2, +/* 28e - _D8_D8 */ 0x21b3, +/* 28f - _D8_D8 */ 0x21b4, +/* 290 - _D8_E0 */ 0x21b5, +/* 291 - _D8_E0 */ 0x21b6, +/* 292 - _D8_E0 */ 0x21b7, +/* 293 - _D8_E0 */ 0x21b8, +/* 294 - _D8_E0 */ 0x21b9, +/* 295 - _D8_E0 */ 0x21ba, +/* 296 - _D8_E0 */ 0x21bb, +/* 297 - _D8_E0 */ 0x21bc, +/* 298 - _D8_E8 */ 0x21bd, +/* 299 - _D8_E8 */ 0x21be, +/* 29a - _D8_E8 */ 0x21bf, +/* 29b - _D8_E8 */ 0x21c0, +/* 29c - _D8_E8 */ 0x21c1, +/* 29d - _D8_E8 */ 0x21c2, +/* 29e - _D8_E8 */ 0x21c3, +/* 29f - _D8_E8 */ 0x21c4, +/* 2a0 - _D8_F0 */ 0x21c5, +/* 2a1 - _D8_F0 */ 0x21c6, +/* 2a2 - _D8_F0 */ 0x21c7, +/* 2a3 - _D8_F0 */ 0x21c8, +/* 2a4 - _D8_F0 */ 0x21c9, +/* 2a5 - _D8_F0 */ 0x21ca, +/* 2a6 - _D8_F0 */ 0x21cb, +/* 2a7 - _D8_F0 */ 0x21cc, +/* 2a8 - _D8_F8 */ 0x21cd, +/* 2a9 - _D8_F8 */ 0x21ce, +/* 2aa - _D8_F8 */ 0x21cf, +/* 2ab - _D8_F8 */ 0x21d0, +/* 2ac - _D8_F8 */ 0x21d1, +/* 2ad - _D8_F8 */ 0x21d2, +/* 2ae - _D8_F8 */ 0x21d3, +/* 2af - _D8_F8 */ 0x21d4, +/* 2b0 - _D9_00 */ 0x21d5, +/* 2b1 - */ 0, +/* 2b2 - _D9_02 */ 0x21d6, +/* 2b3 - _D9_03 */ 0x21d7, +/* 2b4 - _D9_04 */ 0x21d8, +/* 2b5 - _D9_05 */ 0x21d9, +/* 2b6 - _D9_06 */ 0xcea4, +/* 2b7 - _D9_07 */ 0xceb0, +/* 2b8 - _D9_C0 */ 0x21da, +/* 2b9 - _D9_C0 */ 0x21db, +/* 2ba - _D9_C0 */ 0x21dc, +/* 2bb - _D9_C0 */ 0x21dd, +/* 2bc - _D9_C0 */ 0x21de, +/* 2bd - _D9_C0 */ 0x21df, +/* 2be - _D9_C0 */ 0x21e0, +/* 2bf - _D9_C0 */ 0x21e1, +/* 2c0 - _D9_C8 */ 0x21e2, +/* 2c1 - _D9_C9 */ 0x21e3, +/* 2c2 - _D9_C8 */ 0x21e4, +/* 2c3 - _D9_C8 */ 0x21e5, +/* 2c4 - _D9_C8 */ 0x21e6, +/* 2c5 - _D9_C8 */ 0x21e7, +/* 2c6 - _D9_C8 */ 0x21e8, +/* 2c7 - _D9_C8 */ 0x21e9, +/* 2c8 - _D9_D0 */ 0x21ea, +/* 2c9 - */ 0, +/* 2ca - */ 0, +/* 2cb - */ 0, +/* 2cc - */ 0, +/* 2cd - */ 0, +/* 2ce - */ 0, +/* 2cf - */ 0, +/* 2d0 - */ 0, +/* 2d1 - */ 0, +/* 2d2 - */ 0, +/* 2d3 - */ 0, +/* 2d4 - */ 0, +/* 2d5 - */ 0, +/* 2d6 - */ 0, +/* 2d7 - */ 0, +/* 2d8 - _D9_E0 */ 0x21eb, +/* 2d9 - _D9_E1 */ 0x21ec, +/* 2da - */ 0, +/* 2db - */ 0, +/* 2dc - _D9_E4 */ 0x21ed, +/* 2dd - _D9_E5 */ 0x21ee, +/* 2de - */ 0, +/* 2df - */ 0, +/* 2e0 - _D9_E8 */ 0x21ef, +/* 2e1 - _D9_E9 */ 0x21f0, +/* 2e2 - _D9_EA */ 0x21f1, +/* 2e3 - _D9_EB */ 0x21f2, +/* 2e4 - _D9_EC */ 0x21f3, +/* 2e5 - _D9_ED */ 0x21f4, +/* 2e6 - _D9_EE */ 0x21f5, +/* 2e7 - */ 0, +/* 2e8 - _D9_F0 */ 0x21f6, +/* 2e9 - _D9_F1 */ 0x21f7, +/* 2ea - _D9_F2 */ 0x21f8, +/* 2eb - _D9_F3 */ 0x21f9, +/* 2ec - _D9_F4 */ 0x21fa, +/* 2ed - _D9_F5 */ 0x21fb, +/* 2ee - _D9_F6 */ 0x21fc, +/* 2ef - _D9_F7 */ 0x21fd, +/* 2f0 - _D9_F8 */ 0x21fe, +/* 2f1 - _D9_F9 */ 0x21ff, +/* 2f2 - _D9_FA */ 0x2200, +/* 2f3 - _D9_FB */ 0x2201, +/* 2f4 - _D9_FC */ 0x2202, +/* 2f5 - _D9_FD */ 0x2203, +/* 2f6 - _D9_FE */ 0x2204, +/* 2f7 - _D9_FF */ 0x2205, +/* 2f8 - _DA_00 */ 0x2206, +/* 2f9 - _DA_01 */ 0x2207, +/* 2fa - _DA_02 */ 0x2208, +/* 2fb - _DA_03 */ 0x2209, +/* 2fc - _DA_04 */ 0x220a, +/* 2fd - _DA_05 */ 0x220b, +/* 2fe - _DA_06 */ 0x220c, +/* 2ff - _DA_07 */ 0x220d, +/* 300 - _DA_C0 */ 0x220e, +/* 301 - _DA_C0 */ 0x220f, +/* 302 - _DA_C0 */ 0x2210, +/* 303 - _DA_C0 */ 0x2211, +/* 304 - _DA_C0 */ 0x2212, +/* 305 - _DA_C0 */ 0x2213, +/* 306 - _DA_C0 */ 0x2214, +/* 307 - _DA_C0 */ 0x2215, +/* 308 - _DA_C8 */ 0x2216, +/* 309 - _DA_C8 */ 0x2217, +/* 30a - _DA_C8 */ 0x2218, +/* 30b - _DA_C8 */ 0x2219, +/* 30c - _DA_C8 */ 0x221a, +/* 30d - _DA_C8 */ 0x221b, +/* 30e - _DA_C8 */ 0x221c, +/* 30f - _DA_C8 */ 0x221d, +/* 310 - _DA_D0 */ 0x221e, +/* 311 - _DA_D0 */ 0x221f, +/* 312 - _DA_D0 */ 0x2220, +/* 313 - _DA_D0 */ 0x2221, +/* 314 - _DA_D0 */ 0x2222, +/* 315 - _DA_D0 */ 0x2223, +/* 316 - _DA_D0 */ 0x2224, +/* 317 - _DA_D0 */ 0x2225, +/* 318 - _DA_D8 */ 0x2226, +/* 319 - _DA_D8 */ 0x2227, +/* 31a - _DA_D8 */ 0x2228, +/* 31b - _DA_D8 */ 0x2229, +/* 31c - _DA_D8 */ 0x222a, +/* 31d - _DA_D8 */ 0x222b, +/* 31e - _DA_D8 */ 0x222c, +/* 31f - _DA_D8 */ 0x222d, +/* 320 - */ 0, +/* 321 - */ 0, +/* 322 - */ 0, +/* 323 - */ 0, +/* 324 - */ 0, +/* 325 - */ 0, +/* 326 - */ 0, +/* 327 - */ 0, +/* 328 - */ 0, +/* 329 - _DA_E9 */ 0x222e, +/* 32a - */ 0, +/* 32b - */ 0, +/* 32c - */ 0, +/* 32d - */ 0, +/* 32e - */ 0, +/* 32f - */ 0, +/* 330 - */ 0, +/* 331 - */ 0, +/* 332 - */ 0, +/* 333 - */ 0, +/* 334 - */ 0, +/* 335 - */ 0, +/* 336 - */ 0, +/* 337 - */ 0, +/* 338 - */ 0, +/* 339 - */ 0, +/* 33a - */ 0, +/* 33b - */ 0, +/* 33c - */ 0, +/* 33d - */ 0, +/* 33e - */ 0, +/* 33f - */ 0, +/* 340 - _DB_00 */ 0x222f, +/* 341 - _DB_01 */ 0x2230, +/* 342 - _DB_02 */ 0x2231, +/* 343 - _DB_03 */ 0x2232, +/* 344 - */ 0, +/* 345 - _DB_05 */ 0x2233, +/* 346 - */ 0, +/* 347 - _DB_07 */ 0x2234, +/* 348 - _DB_C0 */ 0x2235, +/* 349 - _DB_C0 */ 0x2236, +/* 34a - _DB_C0 */ 0x2237, +/* 34b - _DB_C0 */ 0x2238, +/* 34c - _DB_C0 */ 0x2239, +/* 34d - _DB_C0 */ 0x223a, +/* 34e - _DB_C0 */ 0x223b, +/* 34f - _DB_C0 */ 0x223c, +/* 350 - _DB_C8 */ 0x223d, +/* 351 - _DB_C8 */ 0x223e, +/* 352 - _DB_C8 */ 0x223f, +/* 353 - _DB_C8 */ 0x2240, +/* 354 - _DB_C8 */ 0x2241, +/* 355 - _DB_C8 */ 0x2242, +/* 356 - _DB_C8 */ 0x2243, +/* 357 - _DB_C8 */ 0x2244, +/* 358 - _DB_D0 */ 0x2245, +/* 359 - _DB_D0 */ 0x2246, +/* 35a - _DB_D0 */ 0x2247, +/* 35b - _DB_D0 */ 0x2248, +/* 35c - _DB_D0 */ 0x2249, +/* 35d - _DB_D0 */ 0x224a, +/* 35e - _DB_D0 */ 0x224b, +/* 35f - _DB_D0 */ 0x224c, +/* 360 - _DB_D8 */ 0x224d, +/* 361 - _DB_D8 */ 0x224e, +/* 362 - _DB_D8 */ 0x224f, +/* 363 - _DB_D8 */ 0x2250, +/* 364 - _DB_D8 */ 0x2251, +/* 365 - _DB_D8 */ 0x2252, +/* 366 - _DB_D8 */ 0x2253, +/* 367 - _DB_D8 */ 0x2254, +/* 368 - _DB_E0 */ 0x2255, +/* 369 - _DB_E1 */ 0x2256, +/* 36a - _DB_E2 */ 0xcebc, +/* 36b - _DB_E3 */ 0xcec8, +/* 36c - _DB_E4 */ 0x2257, +/* 36d - */ 0, +/* 36e - */ 0, +/* 36f - */ 0, +/* 370 - _DB_E8 */ 0x2258, +/* 371 - _DB_E8 */ 0x2259, +/* 372 - _DB_E8 */ 0x225a, +/* 373 - _DB_E8 */ 0x225b, +/* 374 - _DB_E8 */ 0x225c, +/* 375 - _DB_E8 */ 0x225d, +/* 376 - _DB_E8 */ 0x225e, +/* 377 - _DB_E8 */ 0x225f, +/* 378 - _DB_F0 */ 0x2260, +/* 379 - _DB_F0 */ 0x2261, +/* 37a - _DB_F0 */ 0x2262, +/* 37b - _DB_F0 */ 0x2263, +/* 37c - _DB_F0 */ 0x2264, +/* 37d - _DB_F0 */ 0x2265, +/* 37e - _DB_F0 */ 0x2266, +/* 37f - _DB_F0 */ 0x2267, +/* 380 - */ 0, +/* 381 - */ 0, +/* 382 - */ 0, +/* 383 - */ 0, +/* 384 - */ 0, +/* 385 - */ 0, +/* 386 - */ 0, +/* 387 - */ 0, +/* 388 - _DC_00 */ 0x2268, +/* 389 - _DC_01 */ 0x2269, +/* 38a - _DC_02 */ 0x226a, +/* 38b - _DC_03 */ 0x226b, +/* 38c - _DC_04 */ 0x226c, +/* 38d - _DC_05 */ 0x226d, +/* 38e - _DC_06 */ 0x226e, +/* 38f - _DC_07 */ 0x226f, +/* 390 - _DC_C0 */ 0x2270, +/* 391 - _DC_C0 */ 0x2271, +/* 392 - _DC_C0 */ 0x2272, +/* 393 - _DC_C0 */ 0x2273, +/* 394 - _DC_C0 */ 0x2274, +/* 395 - _DC_C0 */ 0x2275, +/* 396 - _DC_C0 */ 0x2276, +/* 397 - _DC_C0 */ 0x2277, +/* 398 - _DC_C8 */ 0x2278, +/* 399 - _DC_C8 */ 0x2279, +/* 39a - _DC_C8 */ 0x227a, +/* 39b - _DC_C8 */ 0x227b, +/* 39c - _DC_C8 */ 0x227c, +/* 39d - _DC_C8 */ 0x227d, +/* 39e - _DC_C8 */ 0x227e, +/* 39f - _DC_C8 */ 0x227f, +/* 3a0 - */ 0, +/* 3a1 - */ 0, +/* 3a2 - */ 0, +/* 3a3 - */ 0, +/* 3a4 - */ 0, +/* 3a5 - */ 0, +/* 3a6 - */ 0, +/* 3a7 - */ 0, +/* 3a8 - */ 0, +/* 3a9 - */ 0, +/* 3aa - */ 0, +/* 3ab - */ 0, +/* 3ac - */ 0, +/* 3ad - */ 0, +/* 3ae - */ 0, +/* 3af - */ 0, +/* 3b0 - _DC_E0 */ 0x2280, +/* 3b1 - _DC_E0 */ 0x2281, +/* 3b2 - _DC_E0 */ 0x2282, +/* 3b3 - _DC_E0 */ 0x2283, +/* 3b4 - _DC_E0 */ 0x2284, +/* 3b5 - _DC_E0 */ 0x2285, +/* 3b6 - _DC_E0 */ 0x2286, +/* 3b7 - _DC_E0 */ 0x2287, +/* 3b8 - _DC_E8 */ 0x2288, +/* 3b9 - _DC_E8 */ 0x2289, +/* 3ba - _DC_E8 */ 0x228a, +/* 3bb - _DC_E8 */ 0x228b, +/* 3bc - _DC_E8 */ 0x228c, +/* 3bd - _DC_E8 */ 0x228d, +/* 3be - _DC_E8 */ 0x228e, +/* 3bf - _DC_E8 */ 0x228f, +/* 3c0 - _DC_F0 */ 0x2290, +/* 3c1 - _DC_F0 */ 0x2291, +/* 3c2 - _DC_F0 */ 0x2292, +/* 3c3 - _DC_F0 */ 0x2293, +/* 3c4 - _DC_F0 */ 0x2294, +/* 3c5 - _DC_F0 */ 0x2295, +/* 3c6 - _DC_F0 */ 0x2296, +/* 3c7 - _DC_F0 */ 0x2297, +/* 3c8 - _DC_F8 */ 0x2298, +/* 3c9 - _DC_F8 */ 0x2299, +/* 3ca - _DC_F8 */ 0x229a, +/* 3cb - _DC_F8 */ 0x229b, +/* 3cc - _DC_F8 */ 0x229c, +/* 3cd - _DC_F8 */ 0x229d, +/* 3ce - _DC_F8 */ 0x229e, +/* 3cf - _DC_F8 */ 0x229f, +/* 3d0 - _DD_00 */ 0x22a0, +/* 3d1 - _DD_01 */ 0x22a1, +/* 3d2 - _DD_02 */ 0x22a2, +/* 3d3 - _DD_03 */ 0x22a3, +/* 3d4 - _DD_04 */ 0x22a4, +/* 3d5 - */ 0, +/* 3d6 - _DD_06 */ 0xced4, +/* 3d7 - _DD_07 */ 0xcee0, +/* 3d8 - _DD_C0 */ 0x22a5, +/* 3d9 - _DD_C0 */ 0x22a6, +/* 3da - _DD_C0 */ 0x22a7, +/* 3db - _DD_C0 */ 0x22a8, +/* 3dc - _DD_C0 */ 0x22a9, +/* 3dd - _DD_C0 */ 0x22aa, +/* 3de - _DD_C0 */ 0x22ab, +/* 3df - _DD_C0 */ 0x22ac, +/* 3e0 - */ 0, +/* 3e1 - */ 0, +/* 3e2 - */ 0, +/* 3e3 - */ 0, +/* 3e4 - */ 0, +/* 3e5 - */ 0, +/* 3e6 - */ 0, +/* 3e7 - */ 0, +/* 3e8 - _DD_D0 */ 0x22ad, +/* 3e9 - _DD_D0 */ 0x22ae, +/* 3ea - _DD_D0 */ 0x22af, +/* 3eb - _DD_D0 */ 0x22b0, +/* 3ec - _DD_D0 */ 0x22b1, +/* 3ed - _DD_D0 */ 0x22b2, +/* 3ee - _DD_D0 */ 0x22b3, +/* 3ef - _DD_D0 */ 0x22b4, +/* 3f0 - _DD_D8 */ 0x22b5, +/* 3f1 - _DD_D8 */ 0x22b6, +/* 3f2 - _DD_D8 */ 0x22b7, +/* 3f3 - _DD_D8 */ 0x22b8, +/* 3f4 - _DD_D8 */ 0x22b9, +/* 3f5 - _DD_D8 */ 0x22ba, +/* 3f6 - _DD_D8 */ 0x22bb, +/* 3f7 - _DD_D8 */ 0x22bc, +/* 3f8 - _DD_E0 */ 0x22bd, +/* 3f9 - _DD_E1 */ 0x22be, +/* 3fa - _DD_E0 */ 0x22bf, +/* 3fb - _DD_E0 */ 0x22c0, +/* 3fc - _DD_E0 */ 0x22c1, +/* 3fd - _DD_E0 */ 0x22c2, +/* 3fe - _DD_E0 */ 0x22c3, +/* 3ff - _DD_E0 */ 0x22c4, +/* 400 - _DD_E8 */ 0x22c5, +/* 401 - _DD_E9 */ 0x22c6, +/* 402 - _DD_E8 */ 0x22c7, +/* 403 - _DD_E8 */ 0x22c8, +/* 404 - _DD_E8 */ 0x22c9, +/* 405 - _DD_E8 */ 0x22ca, +/* 406 - _DD_E8 */ 0x22cb, +/* 407 - _DD_E8 */ 0x22cc, +/* 408 - */ 0, +/* 409 - */ 0, +/* 40a - */ 0, +/* 40b - */ 0, +/* 40c - */ 0, +/* 40d - */ 0, +/* 40e - */ 0, +/* 40f - */ 0, +/* 410 - */ 0, +/* 411 - */ 0, +/* 412 - */ 0, +/* 413 - */ 0, +/* 414 - */ 0, +/* 415 - */ 0, +/* 416 - */ 0, +/* 417 - */ 0, +/* 418 - _DE_00 */ 0x22cd, +/* 419 - _DE_01 */ 0x22ce, +/* 41a - _DE_02 */ 0x22cf, +/* 41b - _DE_03 */ 0x22d0, +/* 41c - _DE_04 */ 0x22d1, +/* 41d - _DE_05 */ 0x22d2, +/* 41e - _DE_06 */ 0x22d3, +/* 41f - _DE_07 */ 0x22d4, +/* 420 - _DE_C0 */ 0x22d5, +/* 421 - _DE_C1 */ 0x22d6, +/* 422 - _DE_C0 */ 0x22d7, +/* 423 - _DE_C0 */ 0x22d8, +/* 424 - _DE_C0 */ 0x22d9, +/* 425 - _DE_C0 */ 0x22da, +/* 426 - _DE_C0 */ 0x22db, +/* 427 - _DE_C0 */ 0x22dc, +/* 428 - _DE_C8 */ 0x22dd, +/* 429 - _DE_C9 */ 0x22de, +/* 42a - _DE_C8 */ 0x22df, +/* 42b - _DE_C8 */ 0x22e0, +/* 42c - _DE_C8 */ 0x22e1, +/* 42d - _DE_C8 */ 0x22e2, +/* 42e - _DE_C8 */ 0x22e3, +/* 42f - _DE_C8 */ 0x22e4, +/* 430 - */ 0, +/* 431 - */ 0, +/* 432 - */ 0, +/* 433 - */ 0, +/* 434 - */ 0, +/* 435 - */ 0, +/* 436 - */ 0, +/* 437 - */ 0, +/* 438 - */ 0, +/* 439 - _DE_D9 */ 0x22e5, +/* 43a - */ 0, +/* 43b - */ 0, +/* 43c - */ 0, +/* 43d - */ 0, +/* 43e - */ 0, +/* 43f - */ 0, +/* 440 - _DE_E0 */ 0x22e6, +/* 441 - _DE_E1 */ 0x22e7, +/* 442 - _DE_E0 */ 0x22e8, +/* 443 - _DE_E0 */ 0x22e9, +/* 444 - _DE_E0 */ 0x22ea, +/* 445 - _DE_E0 */ 0x22eb, +/* 446 - _DE_E0 */ 0x22ec, +/* 447 - _DE_E0 */ 0x22ed, +/* 448 - _DE_E8 */ 0x22ee, +/* 449 - _DE_E9 */ 0x22ef, +/* 44a - _DE_E8 */ 0x22f0, +/* 44b - _DE_E8 */ 0x22f1, +/* 44c - _DE_E8 */ 0x22f2, +/* 44d - _DE_E8 */ 0x22f3, +/* 44e - _DE_E8 */ 0x22f4, +/* 44f - _DE_E8 */ 0x22f5, +/* 450 - _DE_F0 */ 0x22f6, +/* 451 - _DE_F1 */ 0x22f7, +/* 452 - _DE_F0 */ 0x22f8, +/* 453 - _DE_F0 */ 0x22f9, +/* 454 - _DE_F0 */ 0x22fa, +/* 455 - _DE_F0 */ 0x22fb, +/* 456 - _DE_F0 */ 0x22fc, +/* 457 - _DE_F0 */ 0x22fd, +/* 458 - _DE_F8 */ 0x22fe, +/* 459 - _DE_F9 */ 0x22ff, +/* 45a - _DE_F8 */ 0x2300, +/* 45b - _DE_F8 */ 0x2301, +/* 45c - _DE_F8 */ 0x2302, +/* 45d - _DE_F8 */ 0x2303, +/* 45e - _DE_F8 */ 0x2304, +/* 45f - _DE_F8 */ 0x2305, +/* 460 - _DF_00 */ 0x2306, +/* 461 - _DF_01 */ 0x2307, +/* 462 - _DF_02 */ 0x2308, +/* 463 - _DF_03 */ 0x2309, +/* 464 - _DF_04 */ 0x230a, +/* 465 - _DF_05 */ 0x230b, +/* 466 - _DF_06 */ 0x230c, +/* 467 - _DF_07 */ 0x230d, +/* 468 - */ 0, +/* 469 - */ 0, +/* 46a - */ 0, +/* 46b - */ 0, +/* 46c - */ 0, +/* 46d - */ 0, +/* 46e - */ 0, +/* 46f - */ 0, +/* 470 - */ 0, +/* 471 - */ 0, +/* 472 - */ 0, +/* 473 - */ 0, +/* 474 - */ 0, +/* 475 - */ 0, +/* 476 - */ 0, +/* 477 - */ 0, +/* 478 - */ 0, +/* 479 - */ 0, +/* 47a - */ 0, +/* 47b - */ 0, +/* 47c - */ 0, +/* 47d - */ 0, +/* 47e - */ 0, +/* 47f - */ 0, +/* 480 - */ 0, +/* 481 - */ 0, +/* 482 - */ 0, +/* 483 - */ 0, +/* 484 - */ 0, +/* 485 - */ 0, +/* 486 - */ 0, +/* 487 - */ 0, +/* 488 - _DF_E0 */ 0xceec, +/* 489 - */ 0, +/* 48a - */ 0, +/* 48b - */ 0, +/* 48c - */ 0, +/* 48d - */ 0, +/* 48e - */ 0, +/* 48f - */ 0, +/* 490 - _DF_E8 */ 0x230e, +/* 491 - _DF_E8 */ 0x230f, +/* 492 - _DF_E8 */ 0x2310, +/* 493 - _DF_E8 */ 0x2311, +/* 494 - _DF_E8 */ 0x2312, +/* 495 - _DF_E8 */ 0x2313, +/* 496 - _DF_E8 */ 0x2314, +/* 497 - _DF_E8 */ 0x2315, +/* 498 - _DF_F0 */ 0x2316, +/* 499 - _DF_F0 */ 0x2317, +/* 49a - _DF_F0 */ 0x2318, +/* 49b - _DF_F0 */ 0x2319, +/* 49c - _DF_F0 */ 0x231a, +/* 49d - _DF_F0 */ 0x231b, +/* 49e - _DF_F0 */ 0x231c, +/* 49f - _DF_F0 */ 0x231d, +/* 4a0 - */ 0, +/* 4a1 - */ 0, +/* 4a2 - */ 0, +/* 4a3 - */ 0, +/* 4a4 - */ 0, +/* 4a5 - */ 0, +/* 4a6 - */ 0, +/* 4a7 - */ 0, +/* 4a8 - _F6_00 */ 0x231e, +/* 4a9 - */ 0, +/* 4aa - _F6_02 */ 0x231f, +/* 4ab - _F6_03 */ 0x2320, +/* 4ac - _F6_04 */ 0x2321, +/* 4ad - _F6_05 */ 0x2322, +/* 4ae - _F6_06 */ 0x2323, +/* 4af - _F6_07 */ 0x2324, +/* 4b0 - _F7_00 */ 0x2325, +/* 4b1 - */ 0, +/* 4b2 - _F7_02 */ 0x2326, +/* 4b3 - _F7_03 */ 0x2327, +/* 4b4 - _F7_04 */ 0x2328, +/* 4b5 - _F7_05 */ 0x2329, +/* 4b6 - _F7_06 */ 0x232a, +/* 4b7 - _F7_07 */ 0x232b, +/* 4b8 - _FE_00 */ 0x232c, +/* 4b9 - _FE_01 */ 0x232d, +/* 4ba - */ 0, +/* 4bb - */ 0, +/* 4bc - */ 0, +/* 4bd - */ 0, +/* 4be - */ 0, +/* 4bf - */ 0, +/* 4c0 - _FF_00 */ 0x232e, +/* 4c1 - _FF_01 */ 0x232f, +/* 4c2 - _FF_02 */ 0x2330, +/* 4c3 - _FF_03 */ 0x2331, +/* 4c4 - _FF_04 */ 0x2332, +/* 4c5 - _FF_05 */ 0x2333, +/* 4c6 - _FF_06 */ 0x2334, +/* 4c7 - */ 0, +/* 4c8 - _0F_00_00 */ 0x2335, +/* 4c9 - _0F_00_01 */ 0x2336, +/* 4ca - _0F_00_02 */ 0x2337, +/* 4cb - _0F_00_03 */ 0x2338, +/* 4cc - _0F_00_04 */ 0x2339, +/* 4cd - _0F_00_05 */ 0x233a, +/* 4ce - */ 0, +/* 4cf - */ 0, +/* 4d0 - _0F_01_00 */ 0x233b, +/* 4d1 - _0F_01_01 */ 0x233c, +/* 4d2 - _0F_01_02 */ 0x233d, +/* 4d3 - _0F_01_03 */ 0x233e, +/* 4d4 - _0F_01_04 */ 0x233f, +/* 4d5 - */ 0, +/* 4d6 - _0F_01_06 */ 0x2340, +/* 4d7 - _0F_01_07 */ 0x2341, +/* 4d8 - */ 0, +/* 4d9 - _0F_01_C1 */ 0x2342, +/* 4da - _0F_01_C2 */ 0x2343, +/* 4db - _0F_01_C3 */ 0x2344, +/* 4dc - _0F_01_C4 */ 0x2345, +/* 4dd - */ 0, +/* 4de - */ 0, +/* 4df - */ 0, +/* 4e0 - _0F_01_C8 */ 0x2346, +/* 4e1 - _0F_01_C9 */ 0x2347, +/* 4e2 - */ 0, +/* 4e3 - */ 0, +/* 4e4 - */ 0, +/* 4e5 - */ 0, +/* 4e6 - */ 0, +/* 4e7 - */ 0, +/* 4e8 - _0F_01_D0 */ 0x2348, +/* 4e9 - _0F_01_D1 */ 0x2349, +/* 4ea - */ 0, +/* 4eb - */ 0, +/* 4ec - _0F_01_D4 */ 0x234a, +/* 4ed - */ 0, +/* 4ee - */ 0, +/* 4ef - */ 0, +/* 4f0 - _0F_01_D8 */ 0x234b, +/* 4f1 - _0F_01_D9 */ 0x234c, +/* 4f2 - _0F_01_DA */ 0x234d, +/* 4f3 - _0F_01_DB */ 0x234e, +/* 4f4 - _0F_01_DC */ 0x234f, +/* 4f5 - _0F_01_DD */ 0x2350, +/* 4f6 - _0F_01_DE */ 0x2351, +/* 4f7 - _0F_01_DF */ 0x2352, +/* 4f8 - */ 0, +/* 4f9 - */ 0, +/* 4fa - */ 0, +/* 4fb - */ 0, +/* 4fc - */ 0, +/* 4fd - */ 0, +/* 4fe - */ 0, +/* 4ff - */ 0, +/* 500 - */ 0, +/* 501 - */ 0, +/* 502 - */ 0, +/* 503 - */ 0, +/* 504 - */ 0, +/* 505 - */ 0, +/* 506 - */ 0, +/* 507 - */ 0, +/* 508 - */ 0, +/* 509 - */ 0, +/* 50a - */ 0, +/* 50b - */ 0, +/* 50c - */ 0, +/* 50d - */ 0, +/* 50e - */ 0, +/* 50f - */ 0, +/* 510 - _0F_01_F8 */ 0x2353, +/* 511 - _0F_01_F9 */ 0x2354, +/* 512 - */ 0, +/* 513 - */ 0, +/* 514 - */ 0, +/* 515 - */ 0, +/* 516 - */ 0, +/* 517 - */ 0, +/* 518 - _0F_0D_00 */ 0x2355, +/* 519 - _0F_0D_01 */ 0x2356, +/* 51a - */ 0, +/* 51b - */ 0, +/* 51c - */ 0, +/* 51d - */ 0, +/* 51e - */ 0, +/* 51f - */ 0, +/* 520 - */ 0, +/* 521 - */ 0, +/* 522 - */ 0, +/* 523 - */ 0, +/* 524 - */ 0, +/* 525 - */ 0, +/* 526 - */ 0, +/* 527 - */ 0, +/* 528 - */ 0, +/* 529 - */ 0, +/* 52a - */ 0, +/* 52b - */ 0, +/* 52c - _0F_0F_0C */ 0x2357, +/* 52d - _0F_0F_0D */ 0x2358, +/* 52e - */ 0, +/* 52f - */ 0, +/* 530 - */ 0, +/* 531 - */ 0, +/* 532 - */ 0, +/* 533 - */ 0, +/* 534 - */ 0, +/* 535 - */ 0, +/* 536 - */ 0, +/* 537 - */ 0, +/* 538 - */ 0, +/* 539 - */ 0, +/* 53a - */ 0, +/* 53b - */ 0, +/* 53c - _0F_0F_1C */ 0x2359, +/* 53d - _0F_0F_1D */ 0x235a, +/* 53e - */ 0, +/* 53f - */ 0, +/* 540 - */ 0, +/* 541 - */ 0, +/* 542 - */ 0, +/* 543 - */ 0, +/* 544 - */ 0, +/* 545 - */ 0, +/* 546 - */ 0, +/* 547 - */ 0, +/* 548 - */ 0, +/* 549 - */ 0, +/* 54a - */ 0, +/* 54b - */ 0, +/* 54c - */ 0, +/* 54d - */ 0, +/* 54e - */ 0, +/* 54f - */ 0, +/* 550 - */ 0, +/* 551 - */ 0, +/* 552 - */ 0, +/* 553 - */ 0, +/* 554 - */ 0, +/* 555 - */ 0, +/* 556 - */ 0, +/* 557 - */ 0, +/* 558 - */ 0, +/* 559 - */ 0, +/* 55a - */ 0, +/* 55b - */ 0, +/* 55c - */ 0, +/* 55d - */ 0, +/* 55e - */ 0, +/* 55f - */ 0, +/* 560 - */ 0, +/* 561 - */ 0, +/* 562 - */ 0, +/* 563 - */ 0, +/* 564 - */ 0, +/* 565 - */ 0, +/* 566 - */ 0, +/* 567 - */ 0, +/* 568 - */ 0, +/* 569 - */ 0, +/* 56a - */ 0, +/* 56b - */ 0, +/* 56c - */ 0, +/* 56d - */ 0, +/* 56e - */ 0, +/* 56f - */ 0, +/* 570 - */ 0, +/* 571 - */ 0, +/* 572 - */ 0, +/* 573 - */ 0, +/* 574 - */ 0, +/* 575 - */ 0, +/* 576 - */ 0, +/* 577 - */ 0, +/* 578 - */ 0, +/* 579 - */ 0, +/* 57a - */ 0, +/* 57b - */ 0, +/* 57c - */ 0, +/* 57d - */ 0, +/* 57e - */ 0, +/* 57f - */ 0, +/* 580 - */ 0, +/* 581 - */ 0, +/* 582 - */ 0, +/* 583 - */ 0, +/* 584 - */ 0, +/* 585 - */ 0, +/* 586 - */ 0, +/* 587 - */ 0, +/* 588 - */ 0, +/* 589 - */ 0, +/* 58a - */ 0, +/* 58b - */ 0, +/* 58c - */ 0, +/* 58d - */ 0, +/* 58e - */ 0, +/* 58f - */ 0, +/* 590 - */ 0, +/* 591 - */ 0, +/* 592 - */ 0, +/* 593 - */ 0, +/* 594 - */ 0, +/* 595 - */ 0, +/* 596 - */ 0, +/* 597 - */ 0, +/* 598 - */ 0, +/* 599 - */ 0, +/* 59a - */ 0, +/* 59b - */ 0, +/* 59c - */ 0, +/* 59d - */ 0, +/* 59e - */ 0, +/* 59f - */ 0, +/* 5a0 - */ 0, +/* 5a1 - */ 0, +/* 5a2 - */ 0, +/* 5a3 - */ 0, +/* 5a4 - */ 0, +/* 5a5 - */ 0, +/* 5a6 - */ 0, +/* 5a7 - */ 0, +/* 5a8 - */ 0, +/* 5a9 - */ 0, +/* 5aa - _0F_0F_8A */ 0x235b, +/* 5ab - */ 0, +/* 5ac - */ 0, +/* 5ad - */ 0, +/* 5ae - _0F_0F_8E */ 0x235c, +/* 5af - */ 0, +/* 5b0 - _0F_0F_90 */ 0x235d, +/* 5b1 - */ 0, +/* 5b2 - */ 0, +/* 5b3 - */ 0, +/* 5b4 - _0F_0F_94 */ 0x235e, +/* 5b5 - */ 0, +/* 5b6 - _0F_0F_96 */ 0x235f, +/* 5b7 - _0F_0F_97 */ 0x2360, +/* 5b8 - */ 0, +/* 5b9 - */ 0, +/* 5ba - _0F_0F_9A */ 0x2361, +/* 5bb - */ 0, +/* 5bc - */ 0, +/* 5bd - */ 0, +/* 5be - _0F_0F_9E */ 0x2362, +/* 5bf - */ 0, +/* 5c0 - _0F_0F_A0 */ 0x2363, +/* 5c1 - */ 0, +/* 5c2 - */ 0, +/* 5c3 - */ 0, +/* 5c4 - _0F_0F_A4 */ 0x2364, +/* 5c5 - */ 0, +/* 5c6 - _0F_0F_A6 */ 0x2365, +/* 5c7 - _0F_0F_A7 */ 0x2366, +/* 5c8 - */ 0, +/* 5c9 - */ 0, +/* 5ca - _0F_0F_AA */ 0x2367, +/* 5cb - */ 0, +/* 5cc - */ 0, +/* 5cd - */ 0, +/* 5ce - _0F_0F_AE */ 0x2368, +/* 5cf - */ 0, +/* 5d0 - _0F_0F_B0 */ 0x2369, +/* 5d1 - */ 0, +/* 5d2 - */ 0, +/* 5d3 - */ 0, +/* 5d4 - _0F_0F_B4 */ 0x236a, +/* 5d5 - */ 0, +/* 5d6 - _0F_0F_B6 */ 0x236b, +/* 5d7 - _0F_0F_B7 */ 0x236c, +/* 5d8 - */ 0, +/* 5d9 - */ 0, +/* 5da - */ 0, +/* 5db - _0F_0F_BB */ 0x236d, +/* 5dc - */ 0, +/* 5dd - */ 0, +/* 5de - */ 0, +/* 5df - _0F_0F_BF */ 0x236e, +/* 5e0 - */ 0, +/* 5e1 - */ 0, +/* 5e2 - */ 0, +/* 5e3 - */ 0, +/* 5e4 - */ 0, +/* 5e5 - */ 0, +/* 5e6 - */ 0, +/* 5e7 - */ 0, +/* 5e8 - */ 0, +/* 5e9 - */ 0, +/* 5ea - */ 0, +/* 5eb - */ 0, +/* 5ec - */ 0, +/* 5ed - */ 0, +/* 5ee - */ 0, +/* 5ef - */ 0, +/* 5f0 - */ 0, +/* 5f1 - */ 0, +/* 5f2 - */ 0, +/* 5f3 - */ 0, +/* 5f4 - */ 0, +/* 5f5 - */ 0, +/* 5f6 - */ 0, +/* 5f7 - */ 0, +/* 5f8 - */ 0, +/* 5f9 - */ 0, +/* 5fa - */ 0, +/* 5fb - */ 0, +/* 5fc - */ 0, +/* 5fd - */ 0, +/* 5fe - */ 0, +/* 5ff - */ 0, +/* 600 - */ 0, +/* 601 - */ 0, +/* 602 - */ 0, +/* 603 - */ 0, +/* 604 - */ 0, +/* 605 - */ 0, +/* 606 - */ 0, +/* 607 - */ 0, +/* 608 - */ 0, +/* 609 - */ 0, +/* 60a - */ 0, +/* 60b - */ 0, +/* 60c - */ 0, +/* 60d - */ 0, +/* 60e - */ 0, +/* 60f - */ 0, +/* 610 - */ 0, +/* 611 - */ 0, +/* 612 - */ 0, +/* 613 - */ 0, +/* 614 - */ 0, +/* 615 - */ 0, +/* 616 - */ 0, +/* 617 - */ 0, +/* 618 - */ 0, +/* 619 - */ 0, +/* 61a - */ 0, +/* 61b - */ 0, +/* 61c - */ 0, +/* 61d - */ 0, +/* 61e - */ 0, +/* 61f - */ 0, +/* 620 - _0F_10 */ 0x236f, +/* 621 - _66_0F_10 */ 0x2370, +/* 622 - _F3_0F_10 */ 0x2371, +/* 623 - _F2_0F_10 */ 0x2372, +/* 624 - _V_0F_10 */ 0x4009, +/* 625 - _V_66_0F_10 */ 0x400a, +/* 626 - _V_F3_0F_10 */ 0x400b, +/* 627 - _V_F2_0F_10 */ 0x400c, +/* 628 - */ 0, +/* 629 - */ 0, +/* 62a - _VRR_F3_0F_10 */ 0x400d, +/* 62b - _VRR_F2_0F_10 */ 0x400e, +/* 62c - _0F_11 */ 0x2373, +/* 62d - _66_0F_11 */ 0x2374, +/* 62e - _F3_0F_11 */ 0x2375, +/* 62f - _F2_0F_11 */ 0x2376, +/* 630 - _V_0F_11 */ 0x400f, +/* 631 - _V_66_0F_11 */ 0x4010, +/* 632 - _V_F3_0F_11 */ 0x4011, +/* 633 - _V_F2_0F_11 */ 0x4012, +/* 634 - */ 0, +/* 635 - */ 0, +/* 636 - _VRR_F3_0F_11 */ 0x4013, +/* 637 - _VRR_F2_0F_11 */ 0x4014, +/* 638 - _0F_12 */ 0x4015, +/* 639 - _66_0F_12 */ 0x2377, +/* 63a - _F3_0F_12 */ 0x2378, +/* 63b - _F2_0F_12 */ 0x2379, +/* 63c - _V_0F_12 */ 0x4016, +/* 63d - _V_66_0F_12 */ 0x4017, +/* 63e - _V_F3_0F_12 */ 0x4018, +/* 63f - _V_F2_0F_12 */ 0x4019, +/* 640 - */ 0, +/* 641 - */ 0, +/* 642 - */ 0, +/* 643 - */ 0, +/* 644 - _0F_13 */ 0x237a, +/* 645 - _66_0F_13 */ 0x237b, +/* 646 - */ 0, +/* 647 - */ 0, +/* 648 - _V_0F_13 */ 0x401a, +/* 649 - _V_66_0F_13 */ 0x401b, +/* 64a - */ 0, +/* 64b - */ 0, +/* 64c - */ 0, +/* 64d - */ 0, +/* 64e - */ 0, +/* 64f - */ 0, +/* 650 - _0F_14 */ 0x237c, +/* 651 - _66_0F_14 */ 0x237d, +/* 652 - */ 0, +/* 653 - */ 0, +/* 654 - _V_0F_14 */ 0x401c, +/* 655 - _V_66_0F_14 */ 0x401d, +/* 656 - */ 0, +/* 657 - */ 0, +/* 658 - */ 0, +/* 659 - */ 0, +/* 65a - */ 0, +/* 65b - */ 0, +/* 65c - _0F_15 */ 0x237e, +/* 65d - _66_0F_15 */ 0x237f, +/* 65e - */ 0, +/* 65f - */ 0, +/* 660 - _V_0F_15 */ 0x401e, +/* 661 - _V_66_0F_15 */ 0x401f, +/* 662 - */ 0, +/* 663 - */ 0, +/* 664 - */ 0, +/* 665 - */ 0, +/* 666 - */ 0, +/* 667 - */ 0, +/* 668 - _0F_16 */ 0x4020, +/* 669 - _66_0F_16 */ 0x2380, +/* 66a - _F3_0F_16 */ 0x2381, +/* 66b - */ 0, +/* 66c - _V_0F_16 */ 0x4021, +/* 66d - _V_66_0F_16 */ 0x4022, +/* 66e - _V_F3_0F_16 */ 0x4023, +/* 66f - */ 0, +/* 670 - */ 0, +/* 671 - */ 0, +/* 672 - */ 0, +/* 673 - */ 0, +/* 674 - _0F_17 */ 0x2382, +/* 675 - _66_0F_17 */ 0x2383, +/* 676 - */ 0, +/* 677 - */ 0, +/* 678 - _V_0F_17 */ 0x4024, +/* 679 - _V_66_0F_17 */ 0x4025, +/* 67a - */ 0, +/* 67b - */ 0, +/* 67c - */ 0, +/* 67d - */ 0, +/* 67e - */ 0, +/* 67f - */ 0, +/* 680 - _0F_18_00 */ 0x2384, +/* 681 - _0F_18_01 */ 0x2385, +/* 682 - _0F_18_02 */ 0x2386, +/* 683 - _0F_18_03 */ 0x2387, +/* 684 - */ 0, +/* 685 - */ 0, +/* 686 - */ 0, +/* 687 - */ 0, +/* 688 - _0F_28 */ 0x2388, +/* 689 - _66_0F_28 */ 0x2389, +/* 68a - */ 0, +/* 68b - */ 0, +/* 68c - _V_0F_28 */ 0x4026, +/* 68d - _V_66_0F_28 */ 0x4027, +/* 68e - */ 0, +/* 68f - */ 0, +/* 690 - */ 0, +/* 691 - */ 0, +/* 692 - */ 0, +/* 693 - */ 0, +/* 694 - _0F_29 */ 0x238a, +/* 695 - _66_0F_29 */ 0x238b, +/* 696 - */ 0, +/* 697 - */ 0, +/* 698 - _V_0F_29 */ 0x4028, +/* 699 - _V_66_0F_29 */ 0x4029, +/* 69a - */ 0, +/* 69b - */ 0, +/* 69c - */ 0, +/* 69d - */ 0, +/* 69e - */ 0, +/* 69f - */ 0, +/* 6a0 - _0F_2A */ 0x238c, +/* 6a1 - _66_0F_2A */ 0x238d, +/* 6a2 - _F3_0F_2A */ 0x238e, +/* 6a3 - _F2_0F_2A */ 0x238f, +/* 6a4 - */ 0, +/* 6a5 - */ 0, +/* 6a6 - _V_F3_0F_2A */ 0x402a, +/* 6a7 - _V_F2_0F_2A */ 0x402b, +/* 6a8 - */ 0, +/* 6a9 - */ 0, +/* 6aa - */ 0, +/* 6ab - */ 0, +/* 6ac - _0F_2B */ 0x2390, +/* 6ad - _66_0F_2B */ 0x2391, +/* 6ae - _F3_0F_2B */ 0x2392, +/* 6af - _F2_0F_2B */ 0x2393, +/* 6b0 - _V_0F_2B */ 0x402c, +/* 6b1 - _V_66_0F_2B */ 0x402d, +/* 6b2 - */ 0, +/* 6b3 - */ 0, +/* 6b4 - */ 0, +/* 6b5 - */ 0, +/* 6b6 - */ 0, +/* 6b7 - */ 0, +/* 6b8 - _0F_2C */ 0x2394, +/* 6b9 - _66_0F_2C */ 0x2395, +/* 6ba - _F3_0F_2C */ 0x2396, +/* 6bb - _F2_0F_2C */ 0x2397, +/* 6bc - */ 0, +/* 6bd - */ 0, +/* 6be - _V_F3_0F_2C */ 0x402e, +/* 6bf - _V_F2_0F_2C */ 0x402f, +/* 6c0 - */ 0, +/* 6c1 - */ 0, +/* 6c2 - */ 0, +/* 6c3 - */ 0, +/* 6c4 - _0F_2D */ 0x2398, +/* 6c5 - _66_0F_2D */ 0x2399, +/* 6c6 - _F3_0F_2D */ 0x239a, +/* 6c7 - _F2_0F_2D */ 0x239b, +/* 6c8 - */ 0, +/* 6c9 - */ 0, +/* 6ca - _V_F3_0F_2D */ 0x4030, +/* 6cb - _V_F2_0F_2D */ 0x4031, +/* 6cc - */ 0, +/* 6cd - */ 0, +/* 6ce - */ 0, +/* 6cf - */ 0, +/* 6d0 - _0F_2E */ 0x239c, +/* 6d1 - _66_0F_2E */ 0x239d, +/* 6d2 - */ 0, +/* 6d3 - */ 0, +/* 6d4 - _V_0F_2E */ 0x4032, +/* 6d5 - _V_66_0F_2E */ 0x4033, +/* 6d6 - */ 0, +/* 6d7 - */ 0, +/* 6d8 - */ 0, +/* 6d9 - */ 0, +/* 6da - */ 0, +/* 6db - */ 0, +/* 6dc - _0F_2F */ 0x239e, +/* 6dd - _66_0F_2F */ 0x239f, +/* 6de - */ 0, +/* 6df - */ 0, +/* 6e0 - _V_0F_2F */ 0x4034, +/* 6e1 - _V_66_0F_2F */ 0x4035, +/* 6e2 - */ 0, +/* 6e3 - */ 0, +/* 6e4 - */ 0, +/* 6e5 - */ 0, +/* 6e6 - */ 0, +/* 6e7 - */ 0, +/* 6e8 - _0F_38_00 */ 0xcef8, +/* 6e9 - _0F_38_01 */ 0xcf04, +/* 6ea - _0F_38_02 */ 0xcf10, +/* 6eb - _0F_38_03 */ 0xcf1c, +/* 6ec - _0F_38_04 */ 0xcf28, +/* 6ed - _0F_38_05 */ 0xcf34, +/* 6ee - _0F_38_06 */ 0xcf40, +/* 6ef - _0F_38_07 */ 0xcf4c, +/* 6f0 - _0F_38_08 */ 0xcf58, +/* 6f1 - _0F_38_09 */ 0xcf64, +/* 6f2 - _0F_38_0A */ 0xcf70, +/* 6f3 - _0F_38_0B */ 0xcf7c, +/* 6f4 - _0F_38_0C */ 0xcf88, +/* 6f5 - _0F_38_0D */ 0xcf94, +/* 6f6 - _0F_38_0E */ 0xcfa0, +/* 6f7 - _0F_38_0F */ 0xcfac, +/* 6f8 - _0F_38_10 */ 0xcfb8, +/* 6f9 - */ 0, +/* 6fa - */ 0, +/* 6fb - */ 0, +/* 6fc - _0F_38_14 */ 0xcfc4, +/* 6fd - _0F_38_15 */ 0xcfd0, +/* 6fe - */ 0, +/* 6ff - _0F_38_17 */ 0xcfdc, +/* 700 - _0F_38_18 */ 0xcfe8, +/* 701 - _0F_38_19 */ 0xcff4, +/* 702 - _0F_38_1A */ 0xd000, +/* 703 - */ 0, +/* 704 - _0F_38_1C */ 0xd00c, +/* 705 - _0F_38_1D */ 0xd018, +/* 706 - _0F_38_1E */ 0xd024, +/* 707 - */ 0, +/* 708 - _0F_38_20 */ 0xd030, +/* 709 - _0F_38_21 */ 0xd03c, +/* 70a - _0F_38_22 */ 0xd048, +/* 70b - _0F_38_23 */ 0xd054, +/* 70c - _0F_38_24 */ 0xd060, +/* 70d - _0F_38_25 */ 0xd06c, +/* 70e - */ 0, +/* 70f - */ 0, +/* 710 - _0F_38_28 */ 0xd078, +/* 711 - _0F_38_29 */ 0xd084, +/* 712 - _0F_38_2A */ 0xd090, +/* 713 - _0F_38_2B */ 0xd09c, +/* 714 - _0F_38_2C */ 0xd0a8, +/* 715 - _0F_38_2D */ 0xd0b4, +/* 716 - _0F_38_2E */ 0xd0c0, +/* 717 - _0F_38_2F */ 0xd0cc, +/* 718 - _0F_38_30 */ 0xd0d8, +/* 719 - _0F_38_31 */ 0xd0e4, +/* 71a - _0F_38_32 */ 0xd0f0, +/* 71b - _0F_38_33 */ 0xd0fc, +/* 71c - _0F_38_34 */ 0xd108, +/* 71d - _0F_38_35 */ 0xd114, +/* 71e - */ 0, +/* 71f - _0F_38_37 */ 0xd120, +/* 720 - _0F_38_38 */ 0xd12c, +/* 721 - _0F_38_39 */ 0xd138, +/* 722 - _0F_38_3A */ 0xd144, +/* 723 - _0F_38_3B */ 0xd150, +/* 724 - _0F_38_3C */ 0xd15c, +/* 725 - _0F_38_3D */ 0xd168, +/* 726 - _0F_38_3E */ 0xd174, +/* 727 - _0F_38_3F */ 0xd180, +/* 728 - _0F_38_40 */ 0xd18c, +/* 729 - _0F_38_41 */ 0xd198, +/* 72a - */ 0, +/* 72b - */ 0, +/* 72c - */ 0, +/* 72d - */ 0, +/* 72e - */ 0, +/* 72f - */ 0, +/* 730 - */ 0, +/* 731 - */ 0, +/* 732 - */ 0, +/* 733 - */ 0, +/* 734 - */ 0, +/* 735 - */ 0, +/* 736 - */ 0, +/* 737 - */ 0, +/* 738 - */ 0, +/* 739 - */ 0, +/* 73a - */ 0, +/* 73b - */ 0, +/* 73c - */ 0, +/* 73d - */ 0, +/* 73e - */ 0, +/* 73f - */ 0, +/* 740 - */ 0, +/* 741 - */ 0, +/* 742 - */ 0, +/* 743 - */ 0, +/* 744 - */ 0, +/* 745 - */ 0, +/* 746 - */ 0, +/* 747 - */ 0, +/* 748 - */ 0, +/* 749 - */ 0, +/* 74a - */ 0, +/* 74b - */ 0, +/* 74c - */ 0, +/* 74d - */ 0, +/* 74e - */ 0, +/* 74f - */ 0, +/* 750 - */ 0, +/* 751 - */ 0, +/* 752 - */ 0, +/* 753 - */ 0, +/* 754 - */ 0, +/* 755 - */ 0, +/* 756 - */ 0, +/* 757 - */ 0, +/* 758 - */ 0, +/* 759 - */ 0, +/* 75a - */ 0, +/* 75b - */ 0, +/* 75c - */ 0, +/* 75d - */ 0, +/* 75e - */ 0, +/* 75f - */ 0, +/* 760 - */ 0, +/* 761 - */ 0, +/* 762 - */ 0, +/* 763 - */ 0, +/* 764 - */ 0, +/* 765 - */ 0, +/* 766 - */ 0, +/* 767 - */ 0, +/* 768 - _0F_38_80 */ 0xd1a4, +/* 769 - _0F_38_81 */ 0xd1b0, +/* 76a - _0F_38_82 */ 0xd1bc, +/* 76b - */ 0, +/* 76c - */ 0, +/* 76d - */ 0, +/* 76e - */ 0, +/* 76f - */ 0, +/* 770 - */ 0, +/* 771 - */ 0, +/* 772 - */ 0, +/* 773 - */ 0, +/* 774 - */ 0, +/* 775 - */ 0, +/* 776 - */ 0, +/* 777 - */ 0, +/* 778 - */ 0, +/* 779 - */ 0, +/* 77a - */ 0, +/* 77b - */ 0, +/* 77c - */ 0, +/* 77d - */ 0, +/* 77e - _0F_38_96 */ 0xd1c8, +/* 77f - _0F_38_97 */ 0xd1d4, +/* 780 - _0F_38_98 */ 0xd1e0, +/* 781 - _0F_38_99 */ 0xd1ec, +/* 782 - _0F_38_9A */ 0xd1f8, +/* 783 - _0F_38_9B */ 0xd204, +/* 784 - _0F_38_9C */ 0xd210, +/* 785 - _0F_38_9D */ 0xd21c, +/* 786 - _0F_38_9E */ 0xd228, +/* 787 - _0F_38_9F */ 0xd234, +/* 788 - */ 0, +/* 789 - */ 0, +/* 78a - */ 0, +/* 78b - */ 0, +/* 78c - */ 0, +/* 78d - */ 0, +/* 78e - _0F_38_A6 */ 0xd240, +/* 78f - _0F_38_A7 */ 0xd24c, +/* 790 - _0F_38_A8 */ 0xd258, +/* 791 - _0F_38_A9 */ 0xd264, +/* 792 - _0F_38_AA */ 0xd270, +/* 793 - _0F_38_AB */ 0xd27c, +/* 794 - _0F_38_AC */ 0xd288, +/* 795 - _0F_38_AD */ 0xd294, +/* 796 - _0F_38_AE */ 0xd2a0, +/* 797 - _0F_38_AF */ 0xd2ac, +/* 798 - */ 0, +/* 799 - */ 0, +/* 79a - */ 0, +/* 79b - */ 0, +/* 79c - */ 0, +/* 79d - */ 0, +/* 79e - _0F_38_B6 */ 0xd2b8, +/* 79f - _0F_38_B7 */ 0xd2c4, +/* 7a0 - _0F_38_B8 */ 0xd2d0, +/* 7a1 - _0F_38_B9 */ 0xd2dc, +/* 7a2 - _0F_38_BA */ 0xd2e8, +/* 7a3 - _0F_38_BB */ 0xd2f4, +/* 7a4 - _0F_38_BC */ 0xd300, +/* 7a5 - _0F_38_BD */ 0xd30c, +/* 7a6 - _0F_38_BE */ 0xd318, +/* 7a7 - _0F_38_BF */ 0xd324, +/* 7a8 - */ 0, +/* 7a9 - */ 0, +/* 7aa - */ 0, +/* 7ab - */ 0, +/* 7ac - */ 0, +/* 7ad - */ 0, +/* 7ae - */ 0, +/* 7af - */ 0, +/* 7b0 - */ 0, +/* 7b1 - */ 0, +/* 7b2 - */ 0, +/* 7b3 - */ 0, +/* 7b4 - */ 0, +/* 7b5 - */ 0, +/* 7b6 - */ 0, +/* 7b7 - */ 0, +/* 7b8 - */ 0, +/* 7b9 - */ 0, +/* 7ba - */ 0, +/* 7bb - */ 0, +/* 7bc - */ 0, +/* 7bd - */ 0, +/* 7be - */ 0, +/* 7bf - */ 0, +/* 7c0 - */ 0, +/* 7c1 - */ 0, +/* 7c2 - */ 0, +/* 7c3 - _0F_38_DB */ 0xd330, +/* 7c4 - _0F_38_DC */ 0xd33c, +/* 7c5 - _0F_38_DD */ 0xd348, +/* 7c6 - _0F_38_DE */ 0xd354, +/* 7c7 - _0F_38_DF */ 0xd360, +/* 7c8 - */ 0, +/* 7c9 - */ 0, +/* 7ca - */ 0, +/* 7cb - */ 0, +/* 7cc - */ 0, +/* 7cd - */ 0, +/* 7ce - */ 0, +/* 7cf - */ 0, +/* 7d0 - */ 0, +/* 7d1 - */ 0, +/* 7d2 - */ 0, +/* 7d3 - */ 0, +/* 7d4 - */ 0, +/* 7d5 - */ 0, +/* 7d6 - */ 0, +/* 7d7 - */ 0, +/* 7d8 - _0F_38_F0 */ 0xd36c, +/* 7d9 - _0F_38_F1 */ 0xd378, +/* 7da - */ 0, +/* 7db - */ 0, +/* 7dc - */ 0, +/* 7dd - */ 0, +/* 7de - */ 0, +/* 7df - */ 0, +/* 7e0 - */ 0, +/* 7e1 - */ 0, +/* 7e2 - */ 0, +/* 7e3 - */ 0, +/* 7e4 - */ 0, +/* 7e5 - */ 0, +/* 7e6 - */ 0, +/* 7e7 - */ 0, +/* 7e8 - */ 0, +/* 7e9 - */ 0, +/* 7ea - */ 0, +/* 7eb - */ 0, +/* 7ec - _0F_3A_04 */ 0xd384, +/* 7ed - _0F_3A_05 */ 0xd390, +/* 7ee - _0F_3A_06 */ 0xd39c, +/* 7ef - */ 0, +/* 7f0 - _0F_3A_08 */ 0xd3a8, +/* 7f1 - _0F_3A_09 */ 0xd3b4, +/* 7f2 - _0F_3A_0A */ 0xd3c0, +/* 7f3 - _0F_3A_0B */ 0xd3cc, +/* 7f4 - _0F_3A_0C */ 0xd3d8, +/* 7f5 - _0F_3A_0D */ 0xd3e4, +/* 7f6 - _0F_3A_0E */ 0xd3f0, +/* 7f7 - _0F_3A_0F */ 0xd3fc, +/* 7f8 - */ 0, +/* 7f9 - */ 0, +/* 7fa - */ 0, +/* 7fb - */ 0, +/* 7fc - _0F_3A_14 */ 0xd408, +/* 7fd - _0F_3A_15 */ 0xd414, +/* 7fe - _0F_3A_16 */ 0xd420, +/* 7ff - _0F_3A_17 */ 0xd42c, +/* 800 - _0F_3A_18 */ 0xd438, +/* 801 - _0F_3A_19 */ 0xd444, +/* 802 - */ 0, +/* 803 - */ 0, +/* 804 - */ 0, +/* 805 - */ 0, +/* 806 - */ 0, +/* 807 - */ 0, +/* 808 - _0F_3A_20 */ 0xd450, +/* 809 - _0F_3A_21 */ 0xd45c, +/* 80a - _0F_3A_22 */ 0xd468, +/* 80b - */ 0, +/* 80c - */ 0, +/* 80d - */ 0, +/* 80e - */ 0, +/* 80f - */ 0, +/* 810 - */ 0, +/* 811 - */ 0, +/* 812 - */ 0, +/* 813 - */ 0, +/* 814 - */ 0, +/* 815 - */ 0, +/* 816 - */ 0, +/* 817 - */ 0, +/* 818 - */ 0, +/* 819 - */ 0, +/* 81a - */ 0, +/* 81b - */ 0, +/* 81c - */ 0, +/* 81d - */ 0, +/* 81e - */ 0, +/* 81f - */ 0, +/* 820 - */ 0, +/* 821 - */ 0, +/* 822 - */ 0, +/* 823 - */ 0, +/* 824 - */ 0, +/* 825 - */ 0, +/* 826 - */ 0, +/* 827 - */ 0, +/* 828 - _0F_3A_40 */ 0xd474, +/* 829 - _0F_3A_41 */ 0xd480, +/* 82a - _0F_3A_42 */ 0xd48c, +/* 82b - */ 0, +/* 82c - _0F_3A_44 */ 0xd498, +/* 82d - */ 0, +/* 82e - */ 0, +/* 82f - */ 0, +/* 830 - */ 0, +/* 831 - */ 0, +/* 832 - _0F_3A_4A */ 0xd4a4, +/* 833 - _0F_3A_4B */ 0xd4b0, +/* 834 - _0F_3A_4C */ 0xd4bc, +/* 835 - */ 0, +/* 836 - */ 0, +/* 837 - */ 0, +/* 838 - */ 0, +/* 839 - */ 0, +/* 83a - */ 0, +/* 83b - */ 0, +/* 83c - */ 0, +/* 83d - */ 0, +/* 83e - */ 0, +/* 83f - */ 0, +/* 840 - */ 0, +/* 841 - */ 0, +/* 842 - */ 0, +/* 843 - */ 0, +/* 844 - */ 0, +/* 845 - */ 0, +/* 846 - */ 0, +/* 847 - */ 0, +/* 848 - _0F_3A_60 */ 0xd4c8, +/* 849 - _0F_3A_61 */ 0xd4d4, +/* 84a - _0F_3A_62 */ 0xd4e0, +/* 84b - _0F_3A_63 */ 0xd4ec, +/* 84c - */ 0, +/* 84d - */ 0, +/* 84e - */ 0, +/* 84f - */ 0, +/* 850 - */ 0, +/* 851 - */ 0, +/* 852 - */ 0, +/* 853 - */ 0, +/* 854 - */ 0, +/* 855 - */ 0, +/* 856 - */ 0, +/* 857 - */ 0, +/* 858 - */ 0, +/* 859 - */ 0, +/* 85a - */ 0, +/* 85b - */ 0, +/* 85c - */ 0, +/* 85d - */ 0, +/* 85e - */ 0, +/* 85f - */ 0, +/* 860 - */ 0, +/* 861 - */ 0, +/* 862 - */ 0, +/* 863 - */ 0, +/* 864 - */ 0, +/* 865 - */ 0, +/* 866 - */ 0, +/* 867 - */ 0, +/* 868 - */ 0, +/* 869 - */ 0, +/* 86a - */ 0, +/* 86b - */ 0, +/* 86c - */ 0, +/* 86d - */ 0, +/* 86e - */ 0, +/* 86f - */ 0, +/* 870 - */ 0, +/* 871 - */ 0, +/* 872 - */ 0, +/* 873 - */ 0, +/* 874 - */ 0, +/* 875 - */ 0, +/* 876 - */ 0, +/* 877 - */ 0, +/* 878 - */ 0, +/* 879 - */ 0, +/* 87a - */ 0, +/* 87b - */ 0, +/* 87c - */ 0, +/* 87d - */ 0, +/* 87e - */ 0, +/* 87f - */ 0, +/* 880 - */ 0, +/* 881 - */ 0, +/* 882 - */ 0, +/* 883 - */ 0, +/* 884 - */ 0, +/* 885 - */ 0, +/* 886 - */ 0, +/* 887 - */ 0, +/* 888 - */ 0, +/* 889 - */ 0, +/* 88a - */ 0, +/* 88b - */ 0, +/* 88c - */ 0, +/* 88d - */ 0, +/* 88e - */ 0, +/* 88f - */ 0, +/* 890 - */ 0, +/* 891 - */ 0, +/* 892 - */ 0, +/* 893 - */ 0, +/* 894 - */ 0, +/* 895 - */ 0, +/* 896 - */ 0, +/* 897 - */ 0, +/* 898 - */ 0, +/* 899 - */ 0, +/* 89a - */ 0, +/* 89b - */ 0, +/* 89c - */ 0, +/* 89d - */ 0, +/* 89e - */ 0, +/* 89f - */ 0, +/* 8a0 - */ 0, +/* 8a1 - */ 0, +/* 8a2 - */ 0, +/* 8a3 - */ 0, +/* 8a4 - */ 0, +/* 8a5 - */ 0, +/* 8a6 - */ 0, +/* 8a7 - */ 0, +/* 8a8 - */ 0, +/* 8a9 - */ 0, +/* 8aa - */ 0, +/* 8ab - */ 0, +/* 8ac - */ 0, +/* 8ad - */ 0, +/* 8ae - */ 0, +/* 8af - */ 0, +/* 8b0 - */ 0, +/* 8b1 - */ 0, +/* 8b2 - */ 0, +/* 8b3 - */ 0, +/* 8b4 - */ 0, +/* 8b5 - */ 0, +/* 8b6 - */ 0, +/* 8b7 - */ 0, +/* 8b8 - */ 0, +/* 8b9 - */ 0, +/* 8ba - */ 0, +/* 8bb - */ 0, +/* 8bc - */ 0, +/* 8bd - */ 0, +/* 8be - */ 0, +/* 8bf - */ 0, +/* 8c0 - */ 0, +/* 8c1 - */ 0, +/* 8c2 - */ 0, +/* 8c3 - */ 0, +/* 8c4 - */ 0, +/* 8c5 - */ 0, +/* 8c6 - */ 0, +/* 8c7 - _0F_3A_DF */ 0xd4f8, +/* 8c8 - */ 0, +/* 8c9 - */ 0, +/* 8ca - */ 0, +/* 8cb - */ 0, +/* 8cc - */ 0, +/* 8cd - */ 0, +/* 8ce - */ 0, +/* 8cf - */ 0, +/* 8d0 - */ 0, +/* 8d1 - */ 0, +/* 8d2 - */ 0, +/* 8d3 - */ 0, +/* 8d4 - */ 0, +/* 8d5 - */ 0, +/* 8d6 - */ 0, +/* 8d7 - */ 0, +/* 8d8 - */ 0, +/* 8d9 - */ 0, +/* 8da - */ 0, +/* 8db - */ 0, +/* 8dc - */ 0, +/* 8dd - */ 0, +/* 8de - */ 0, +/* 8df - */ 0, +/* 8e0 - */ 0, +/* 8e1 - */ 0, +/* 8e2 - */ 0, +/* 8e3 - */ 0, +/* 8e4 - */ 0, +/* 8e5 - */ 0, +/* 8e6 - */ 0, +/* 8e7 - */ 0, +/* 8e8 - _0F_50 */ 0x23a0, +/* 8e9 - _66_0F_50 */ 0x23a1, +/* 8ea - */ 0, +/* 8eb - */ 0, +/* 8ec - _V_0F_50 */ 0x4036, +/* 8ed - _V_66_0F_50 */ 0x4037, +/* 8ee - */ 0, +/* 8ef - */ 0, +/* 8f0 - */ 0, +/* 8f1 - */ 0, +/* 8f2 - */ 0, +/* 8f3 - */ 0, +/* 8f4 - _0F_51 */ 0x23a2, +/* 8f5 - _66_0F_51 */ 0x23a3, +/* 8f6 - _F3_0F_51 */ 0x23a4, +/* 8f7 - _F2_0F_51 */ 0x23a5, +/* 8f8 - _V_0F_51 */ 0x4038, +/* 8f9 - _V_66_0F_51 */ 0x4039, +/* 8fa - _V_F3_0F_51 */ 0x403a, +/* 8fb - _V_F2_0F_51 */ 0x403b, +/* 8fc - */ 0, +/* 8fd - */ 0, +/* 8fe - */ 0, +/* 8ff - */ 0, +/* 900 - _0F_52 */ 0x23a6, +/* 901 - */ 0, +/* 902 - _F3_0F_52 */ 0x23a7, +/* 903 - */ 0, +/* 904 - _V_0F_52 */ 0x403c, +/* 905 - */ 0, +/* 906 - _V_F3_0F_52 */ 0x403d, +/* 907 - */ 0, +/* 908 - */ 0, +/* 909 - */ 0, +/* 90a - */ 0, +/* 90b - */ 0, +/* 90c - _0F_53 */ 0x23a8, +/* 90d - */ 0, +/* 90e - _F3_0F_53 */ 0x23a9, +/* 90f - */ 0, +/* 910 - _V_0F_53 */ 0x403e, +/* 911 - */ 0, +/* 912 - _V_F3_0F_53 */ 0x403f, +/* 913 - */ 0, +/* 914 - */ 0, +/* 915 - */ 0, +/* 916 - */ 0, +/* 917 - */ 0, +/* 918 - _0F_54 */ 0x23aa, +/* 919 - _66_0F_54 */ 0x23ab, +/* 91a - */ 0, +/* 91b - */ 0, +/* 91c - _V_0F_54 */ 0x4040, +/* 91d - _V_66_0F_54 */ 0x4041, +/* 91e - */ 0, +/* 91f - */ 0, +/* 920 - */ 0, +/* 921 - */ 0, +/* 922 - */ 0, +/* 923 - */ 0, +/* 924 - _0F_55 */ 0x23ac, +/* 925 - _66_0F_55 */ 0x23ad, +/* 926 - */ 0, +/* 927 - */ 0, +/* 928 - _V_0F_55 */ 0x4042, +/* 929 - _V_66_0F_55 */ 0x4043, +/* 92a - */ 0, +/* 92b - */ 0, +/* 92c - */ 0, +/* 92d - */ 0, +/* 92e - */ 0, +/* 92f - */ 0, +/* 930 - _0F_56 */ 0x23ae, +/* 931 - _66_0F_56 */ 0x23af, +/* 932 - */ 0, +/* 933 - */ 0, +/* 934 - _V_0F_56 */ 0x4044, +/* 935 - _V_66_0F_56 */ 0x4045, +/* 936 - */ 0, +/* 937 - */ 0, +/* 938 - */ 0, +/* 939 - */ 0, +/* 93a - */ 0, +/* 93b - */ 0, +/* 93c - _0F_57 */ 0x23b0, +/* 93d - _66_0F_57 */ 0x23b1, +/* 93e - */ 0, +/* 93f - */ 0, +/* 940 - _V_0F_57 */ 0x4046, +/* 941 - _V_66_0F_57 */ 0x4047, +/* 942 - */ 0, +/* 943 - */ 0, +/* 944 - */ 0, +/* 945 - */ 0, +/* 946 - */ 0, +/* 947 - */ 0, +/* 948 - _0F_58 */ 0x23b2, +/* 949 - _66_0F_58 */ 0x23b3, +/* 94a - _F3_0F_58 */ 0x23b4, +/* 94b - _F2_0F_58 */ 0x23b5, +/* 94c - _V_0F_58 */ 0x4048, +/* 94d - _V_66_0F_58 */ 0x4049, +/* 94e - _V_F3_0F_58 */ 0x404a, +/* 94f - _V_F2_0F_58 */ 0x404b, +/* 950 - */ 0, +/* 951 - */ 0, +/* 952 - */ 0, +/* 953 - */ 0, +/* 954 - _0F_59 */ 0x23b6, +/* 955 - _66_0F_59 */ 0x23b7, +/* 956 - _F3_0F_59 */ 0x23b8, +/* 957 - _F2_0F_59 */ 0x23b9, +/* 958 - _V_0F_59 */ 0x404c, +/* 959 - _V_66_0F_59 */ 0x404d, +/* 95a - _V_F3_0F_59 */ 0x404e, +/* 95b - _V_F2_0F_59 */ 0x404f, +/* 95c - */ 0, +/* 95d - */ 0, +/* 95e - */ 0, +/* 95f - */ 0, +/* 960 - _0F_5A */ 0x23ba, +/* 961 - _66_0F_5A */ 0x23bb, +/* 962 - _F3_0F_5A */ 0x23bc, +/* 963 - _F2_0F_5A */ 0x23bd, +/* 964 - _V_0F_5A */ 0x4050, +/* 965 - _V_66_0F_5A */ 0x4051, +/* 966 - _V_F3_0F_5A */ 0x4052, +/* 967 - _V_F2_0F_5A */ 0x4053, +/* 968 - */ 0, +/* 969 - */ 0, +/* 96a - */ 0, +/* 96b - */ 0, +/* 96c - _0F_5B */ 0x23be, +/* 96d - _66_0F_5B */ 0x23bf, +/* 96e - _F3_0F_5B */ 0x23c0, +/* 96f - */ 0, +/* 970 - _V_0F_5B */ 0x4054, +/* 971 - _V_66_0F_5B */ 0x4055, +/* 972 - _V_F3_0F_5B */ 0x4056, +/* 973 - */ 0, +/* 974 - */ 0, +/* 975 - */ 0, +/* 976 - */ 0, +/* 977 - */ 0, +/* 978 - _0F_5C */ 0x23c1, +/* 979 - _66_0F_5C */ 0x23c2, +/* 97a - _F3_0F_5C */ 0x23c3, +/* 97b - _F2_0F_5C */ 0x23c4, +/* 97c - _V_0F_5C */ 0x4057, +/* 97d - _V_66_0F_5C */ 0x4058, +/* 97e - _V_F3_0F_5C */ 0x4059, +/* 97f - _V_F2_0F_5C */ 0x405a, +/* 980 - */ 0, +/* 981 - */ 0, +/* 982 - */ 0, +/* 983 - */ 0, +/* 984 - _0F_5D */ 0x23c5, +/* 985 - _66_0F_5D */ 0x23c6, +/* 986 - _F3_0F_5D */ 0x23c7, +/* 987 - _F2_0F_5D */ 0x23c8, +/* 988 - _V_0F_5D */ 0x405b, +/* 989 - _V_66_0F_5D */ 0x405c, +/* 98a - _V_F3_0F_5D */ 0x405d, +/* 98b - _V_F2_0F_5D */ 0x405e, +/* 98c - */ 0, +/* 98d - */ 0, +/* 98e - */ 0, +/* 98f - */ 0, +/* 990 - _0F_5E */ 0x23c9, +/* 991 - _66_0F_5E */ 0x23ca, +/* 992 - _F3_0F_5E */ 0x23cb, +/* 993 - _F2_0F_5E */ 0x23cc, +/* 994 - _V_0F_5E */ 0x405f, +/* 995 - _V_66_0F_5E */ 0x4060, +/* 996 - _V_F3_0F_5E */ 0x4061, +/* 997 - _V_F2_0F_5E */ 0x4062, +/* 998 - */ 0, +/* 999 - */ 0, +/* 99a - */ 0, +/* 99b - */ 0, +/* 99c - _0F_5F */ 0x23cd, +/* 99d - _66_0F_5F */ 0x23ce, +/* 99e - _F3_0F_5F */ 0x23cf, +/* 99f - _F2_0F_5F */ 0x23d0, +/* 9a0 - _V_0F_5F */ 0x4063, +/* 9a1 - _V_66_0F_5F */ 0x4064, +/* 9a2 - _V_F3_0F_5F */ 0x4065, +/* 9a3 - _V_F2_0F_5F */ 0x4066, +/* 9a4 - */ 0, +/* 9a5 - */ 0, +/* 9a6 - */ 0, +/* 9a7 - */ 0, +/* 9a8 - _0F_60 */ 0x23d1, +/* 9a9 - _66_0F_60 */ 0x23d2, +/* 9aa - */ 0, +/* 9ab - */ 0, +/* 9ac - */ 0, +/* 9ad - _V_66_0F_60 */ 0x4067, +/* 9ae - */ 0, +/* 9af - */ 0, +/* 9b0 - */ 0, +/* 9b1 - */ 0, +/* 9b2 - */ 0, +/* 9b3 - */ 0, +/* 9b4 - _0F_61 */ 0x23d3, +/* 9b5 - _66_0F_61 */ 0x23d4, +/* 9b6 - */ 0, +/* 9b7 - */ 0, +/* 9b8 - */ 0, +/* 9b9 - _V_66_0F_61 */ 0x4068, +/* 9ba - */ 0, +/* 9bb - */ 0, +/* 9bc - */ 0, +/* 9bd - */ 0, +/* 9be - */ 0, +/* 9bf - */ 0, +/* 9c0 - _0F_62 */ 0x23d5, +/* 9c1 - _66_0F_62 */ 0x23d6, +/* 9c2 - */ 0, +/* 9c3 - */ 0, +/* 9c4 - */ 0, +/* 9c5 - _V_66_0F_62 */ 0x4069, +/* 9c6 - */ 0, +/* 9c7 - */ 0, +/* 9c8 - */ 0, +/* 9c9 - */ 0, +/* 9ca - */ 0, +/* 9cb - */ 0, +/* 9cc - _0F_63 */ 0x23d7, +/* 9cd - _66_0F_63 */ 0x23d8, +/* 9ce - */ 0, +/* 9cf - */ 0, +/* 9d0 - */ 0, +/* 9d1 - _V_66_0F_63 */ 0x406a, +/* 9d2 - */ 0, +/* 9d3 - */ 0, +/* 9d4 - */ 0, +/* 9d5 - */ 0, +/* 9d6 - */ 0, +/* 9d7 - */ 0, +/* 9d8 - _0F_64 */ 0x23d9, +/* 9d9 - _66_0F_64 */ 0x23da, +/* 9da - */ 0, +/* 9db - */ 0, +/* 9dc - */ 0, +/* 9dd - _V_66_0F_64 */ 0x406b, +/* 9de - */ 0, +/* 9df - */ 0, +/* 9e0 - */ 0, +/* 9e1 - */ 0, +/* 9e2 - */ 0, +/* 9e3 - */ 0, +/* 9e4 - _0F_65 */ 0x23db, +/* 9e5 - _66_0F_65 */ 0x23dc, +/* 9e6 - */ 0, +/* 9e7 - */ 0, +/* 9e8 - */ 0, +/* 9e9 - _V_66_0F_65 */ 0x406c, +/* 9ea - */ 0, +/* 9eb - */ 0, +/* 9ec - */ 0, +/* 9ed - */ 0, +/* 9ee - */ 0, +/* 9ef - */ 0, +/* 9f0 - _0F_66 */ 0x23dd, +/* 9f1 - _66_0F_66 */ 0x23de, +/* 9f2 - */ 0, +/* 9f3 - */ 0, +/* 9f4 - */ 0, +/* 9f5 - _V_66_0F_66 */ 0x406d, +/* 9f6 - */ 0, +/* 9f7 - */ 0, +/* 9f8 - */ 0, +/* 9f9 - */ 0, +/* 9fa - */ 0, +/* 9fb - */ 0, +/* 9fc - _0F_67 */ 0x23df, +/* 9fd - _66_0F_67 */ 0x23e0, +/* 9fe - */ 0, +/* 9ff - */ 0, +/* a00 - */ 0, +/* a01 - _V_66_0F_67 */ 0x406e, +/* a02 - */ 0, +/* a03 - */ 0, +/* a04 - */ 0, +/* a05 - */ 0, +/* a06 - */ 0, +/* a07 - */ 0, +/* a08 - _0F_68 */ 0x23e1, +/* a09 - _66_0F_68 */ 0x23e2, +/* a0a - */ 0, +/* a0b - */ 0, +/* a0c - */ 0, +/* a0d - _V_66_0F_68 */ 0x406f, +/* a0e - */ 0, +/* a0f - */ 0, +/* a10 - */ 0, +/* a11 - */ 0, +/* a12 - */ 0, +/* a13 - */ 0, +/* a14 - _0F_69 */ 0x23e3, +/* a15 - _66_0F_69 */ 0x23e4, +/* a16 - */ 0, +/* a17 - */ 0, +/* a18 - */ 0, +/* a19 - _V_66_0F_69 */ 0x4070, +/* a1a - */ 0, +/* a1b - */ 0, +/* a1c - */ 0, +/* a1d - */ 0, +/* a1e - */ 0, +/* a1f - */ 0, +/* a20 - _0F_6A */ 0x23e5, +/* a21 - _66_0F_6A */ 0x23e6, +/* a22 - */ 0, +/* a23 - */ 0, +/* a24 - */ 0, +/* a25 - _V_66_0F_6A */ 0x4071, +/* a26 - */ 0, +/* a27 - */ 0, +/* a28 - */ 0, +/* a29 - */ 0, +/* a2a - */ 0, +/* a2b - */ 0, +/* a2c - _0F_6B */ 0x23e7, +/* a2d - _66_0F_6B */ 0x23e8, +/* a2e - */ 0, +/* a2f - */ 0, +/* a30 - */ 0, +/* a31 - _V_66_0F_6B */ 0x4072, +/* a32 - */ 0, +/* a33 - */ 0, +/* a34 - */ 0, +/* a35 - */ 0, +/* a36 - */ 0, +/* a37 - */ 0, +/* a38 - */ 0, +/* a39 - _66_0F_6C */ 0x23e9, +/* a3a - */ 0, +/* a3b - */ 0, +/* a3c - */ 0, +/* a3d - _V_66_0F_6C */ 0x4073, +/* a3e - */ 0, +/* a3f - */ 0, +/* a40 - */ 0, +/* a41 - */ 0, +/* a42 - */ 0, +/* a43 - */ 0, +/* a44 - */ 0, +/* a45 - _66_0F_6D */ 0x23ea, +/* a46 - */ 0, +/* a47 - */ 0, +/* a48 - */ 0, +/* a49 - _V_66_0F_6D */ 0x4074, +/* a4a - */ 0, +/* a4b - */ 0, +/* a4c - */ 0, +/* a4d - */ 0, +/* a4e - */ 0, +/* a4f - */ 0, +/* a50 - _0F_6E */ 0x4075, +/* a51 - _66_0F_6E */ 0x4076, +/* a52 - */ 0, +/* a53 - */ 0, +/* a54 - */ 0, +/* a55 - _V_66_0F_6E */ 0x4077, +/* a56 - */ 0, +/* a57 - */ 0, +/* a58 - */ 0, +/* a59 - */ 0, +/* a5a - */ 0, +/* a5b - */ 0, +/* a5c - _0F_6F */ 0x23eb, +/* a5d - _66_0F_6F */ 0x23ec, +/* a5e - _F3_0F_6F */ 0x23ed, +/* a5f - */ 0, +/* a60 - */ 0, +/* a61 - _V_66_0F_6F */ 0x4078, +/* a62 - _V_F3_0F_6F */ 0x4079, +/* a63 - */ 0, +/* a64 - */ 0, +/* a65 - */ 0, +/* a66 - */ 0, +/* a67 - */ 0, +/* a68 - _0F_70 */ 0x407a, +/* a69 - _66_0F_70 */ 0x407b, +/* a6a - _F3_0F_70 */ 0x407c, +/* a6b - _F2_0F_70 */ 0x407d, +/* a6c - */ 0, +/* a6d - _V_66_0F_70 */ 0x407e, +/* a6e - _V_F3_0F_70 */ 0x407f, +/* a6f - _V_F2_0F_70 */ 0x4080, +/* a70 - */ 0, +/* a71 - */ 0, +/* a72 - */ 0, +/* a73 - */ 0, +/* a74 - */ 0, +/* a75 - */ 0, +/* a76 - _0F_71_02 */ 0xd504, +/* a77 - */ 0, +/* a78 - _0F_71_04 */ 0xd510, +/* a79 - */ 0, +/* a7a - _0F_71_06 */ 0xd51c, +/* a7b - */ 0, +/* a7c - */ 0, +/* a7d - */ 0, +/* a7e - _0F_72_02 */ 0xd528, +/* a7f - */ 0, +/* a80 - _0F_72_04 */ 0xd534, +/* a81 - */ 0, +/* a82 - _0F_72_06 */ 0xd540, +/* a83 - */ 0, +/* a84 - */ 0, +/* a85 - */ 0, +/* a86 - _0F_73_02 */ 0xd54c, +/* a87 - _0F_73_03 */ 0xd558, +/* a88 - */ 0, +/* a89 - */ 0, +/* a8a - _0F_73_06 */ 0xd564, +/* a8b - _0F_73_07 */ 0xd570, +/* a8c - _0F_74 */ 0x23ee, +/* a8d - _66_0F_74 */ 0x23ef, +/* a8e - */ 0, +/* a8f - */ 0, +/* a90 - */ 0, +/* a91 - _V_66_0F_74 */ 0x4081, +/* a92 - */ 0, +/* a93 - */ 0, +/* a94 - */ 0, +/* a95 - */ 0, +/* a96 - */ 0, +/* a97 - */ 0, +/* a98 - _0F_75 */ 0x23f0, +/* a99 - _66_0F_75 */ 0x23f1, +/* a9a - */ 0, +/* a9b - */ 0, +/* a9c - */ 0, +/* a9d - _V_66_0F_75 */ 0x4082, +/* a9e - */ 0, +/* a9f - */ 0, +/* aa0 - */ 0, +/* aa1 - */ 0, +/* aa2 - */ 0, +/* aa3 - */ 0, +/* aa4 - _0F_76 */ 0x23f2, +/* aa5 - _66_0F_76 */ 0x23f3, +/* aa6 - */ 0, +/* aa7 - */ 0, +/* aa8 - */ 0, +/* aa9 - _V_66_0F_76 */ 0x4083, +/* aaa - */ 0, +/* aab - */ 0, +/* aac - */ 0, +/* aad - */ 0, +/* aae - */ 0, +/* aaf - */ 0, +/* ab0 - _0F_77 */ 0x23f4, +/* ab1 - */ 0, +/* ab2 - */ 0, +/* ab3 - */ 0, +/* ab4 - _V_0F_77 */ 0x4084, +/* ab5 - */ 0, +/* ab6 - */ 0, +/* ab7 - */ 0, +/* ab8 - */ 0, +/* ab9 - */ 0, +/* aba - */ 0, +/* abb - */ 0, +/* abc - _0F_78 */ 0x23f5, +/* abd - _66_0F_78 */ 0x4085, +/* abe - */ 0, +/* abf - _F2_0F_78 */ 0x4086, +/* ac0 - */ 0, +/* ac1 - */ 0, +/* ac2 - */ 0, +/* ac3 - */ 0, +/* ac4 - */ 0, +/* ac5 - */ 0, +/* ac6 - */ 0, +/* ac7 - */ 0, +/* ac8 - _0F_79 */ 0x23f6, +/* ac9 - _66_0F_79 */ 0x23f7, +/* aca - */ 0, +/* acb - _F2_0F_79 */ 0x23f8, +/* acc - */ 0, +/* acd - */ 0, +/* ace - */ 0, +/* acf - */ 0, +/* ad0 - */ 0, +/* ad1 - */ 0, +/* ad2 - */ 0, +/* ad3 - */ 0, +/* ad4 - */ 0, +/* ad5 - */ 0, +/* ad6 - */ 0, +/* ad7 - */ 0, +/* ad8 - */ 0, +/* ad9 - */ 0, +/* ada - */ 0, +/* adb - */ 0, +/* adc - */ 0, +/* add - */ 0, +/* ade - */ 0, +/* adf - */ 0, +/* ae0 - */ 0, +/* ae1 - */ 0, +/* ae2 - */ 0, +/* ae3 - */ 0, +/* ae4 - */ 0, +/* ae5 - */ 0, +/* ae6 - */ 0, +/* ae7 - */ 0, +/* ae8 - */ 0, +/* ae9 - */ 0, +/* aea - */ 0, +/* aeb - */ 0, +/* aec - */ 0, +/* aed - */ 0, +/* aee - */ 0, +/* aef - */ 0, +/* af0 - */ 0, +/* af1 - */ 0, +/* af2 - */ 0, +/* af3 - */ 0, +/* af4 - */ 0, +/* af5 - */ 0, +/* af6 - */ 0, +/* af7 - */ 0, +/* af8 - */ 0, +/* af9 - */ 0, +/* afa - */ 0, +/* afb - */ 0, +/* afc - */ 0, +/* afd - */ 0, +/* afe - */ 0, +/* aff - */ 0, +/* b00 - */ 0, +/* b01 - */ 0, +/* b02 - */ 0, +/* b03 - */ 0, +/* b04 - _0F_7A_30 */ 0x23f9, +/* b05 - _0F_7A_31 */ 0x23fa, +/* b06 - */ 0, +/* b07 - */ 0, +/* b08 - */ 0, +/* b09 - */ 0, +/* b0a - */ 0, +/* b0b - */ 0, +/* b0c - */ 0, +/* b0d - */ 0, +/* b0e - */ 0, +/* b0f - */ 0, +/* b10 - */ 0, +/* b11 - */ 0, +/* b12 - */ 0, +/* b13 - */ 0, +/* b14 - */ 0, +/* b15 - */ 0, +/* b16 - */ 0, +/* b17 - */ 0, +/* b18 - */ 0, +/* b19 - */ 0, +/* b1a - */ 0, +/* b1b - */ 0, +/* b1c - */ 0, +/* b1d - */ 0, +/* b1e - */ 0, +/* b1f - */ 0, +/* b20 - */ 0, +/* b21 - */ 0, +/* b22 - */ 0, +/* b23 - */ 0, +/* b24 - */ 0, +/* b25 - */ 0, +/* b26 - */ 0, +/* b27 - */ 0, +/* b28 - */ 0, +/* b29 - */ 0, +/* b2a - */ 0, +/* b2b - */ 0, +/* b2c - */ 0, +/* b2d - */ 0, +/* b2e - */ 0, +/* b2f - */ 0, +/* b30 - */ 0, +/* b31 - */ 0, +/* b32 - */ 0, +/* b33 - */ 0, +/* b34 - */ 0, +/* b35 - */ 0, +/* b36 - */ 0, +/* b37 - */ 0, +/* b38 - */ 0, +/* b39 - */ 0, +/* b3a - */ 0, +/* b3b - */ 0, +/* b3c - */ 0, +/* b3d - */ 0, +/* b3e - */ 0, +/* b3f - */ 0, +/* b40 - */ 0, +/* b41 - */ 0, +/* b42 - */ 0, +/* b43 - */ 0, +/* b44 - */ 0, +/* b45 - */ 0, +/* b46 - */ 0, +/* b47 - */ 0, +/* b48 - */ 0, +/* b49 - */ 0, +/* b4a - */ 0, +/* b4b - */ 0, +/* b4c - */ 0, +/* b4d - */ 0, +/* b4e - */ 0, +/* b4f - */ 0, +/* b50 - */ 0, +/* b51 - */ 0, +/* b52 - */ 0, +/* b53 - */ 0, +/* b54 - */ 0, +/* b55 - */ 0, +/* b56 - */ 0, +/* b57 - */ 0, +/* b58 - */ 0, +/* b59 - */ 0, +/* b5a - */ 0, +/* b5b - */ 0, +/* b5c - */ 0, +/* b5d - */ 0, +/* b5e - */ 0, +/* b5f - */ 0, +/* b60 - */ 0, +/* b61 - */ 0, +/* b62 - */ 0, +/* b63 - */ 0, +/* b64 - */ 0, +/* b65 - */ 0, +/* b66 - */ 0, +/* b67 - */ 0, +/* b68 - */ 0, +/* b69 - */ 0, +/* b6a - */ 0, +/* b6b - */ 0, +/* b6c - */ 0, +/* b6d - */ 0, +/* b6e - */ 0, +/* b6f - */ 0, +/* b70 - */ 0, +/* b71 - */ 0, +/* b72 - */ 0, +/* b73 - */ 0, +/* b74 - */ 0, +/* b75 - */ 0, +/* b76 - */ 0, +/* b77 - */ 0, +/* b78 - */ 0, +/* b79 - */ 0, +/* b7a - */ 0, +/* b7b - */ 0, +/* b7c - */ 0, +/* b7d - */ 0, +/* b7e - */ 0, +/* b7f - */ 0, +/* b80 - */ 0, +/* b81 - */ 0, +/* b82 - */ 0, +/* b83 - */ 0, +/* b84 - */ 0, +/* b85 - */ 0, +/* b86 - */ 0, +/* b87 - */ 0, +/* b88 - */ 0, +/* b89 - */ 0, +/* b8a - */ 0, +/* b8b - */ 0, +/* b8c - */ 0, +/* b8d - */ 0, +/* b8e - */ 0, +/* b8f - */ 0, +/* b90 - */ 0, +/* b91 - */ 0, +/* b92 - */ 0, +/* b93 - */ 0, +/* b94 - */ 0, +/* b95 - */ 0, +/* b96 - */ 0, +/* b97 - */ 0, +/* b98 - */ 0, +/* b99 - */ 0, +/* b9a - */ 0, +/* b9b - */ 0, +/* b9c - */ 0, +/* b9d - */ 0, +/* b9e - */ 0, +/* b9f - */ 0, +/* ba0 - */ 0, +/* ba1 - */ 0, +/* ba2 - */ 0, +/* ba3 - */ 0, +/* ba4 - */ 0, +/* ba5 - */ 0, +/* ba6 - */ 0, +/* ba7 - */ 0, +/* ba8 - */ 0, +/* ba9 - */ 0, +/* baa - */ 0, +/* bab - */ 0, +/* bac - */ 0, +/* bad - */ 0, +/* bae - */ 0, +/* baf - */ 0, +/* bb0 - */ 0, +/* bb1 - */ 0, +/* bb2 - */ 0, +/* bb3 - */ 0, +/* bb4 - */ 0, +/* bb5 - */ 0, +/* bb6 - */ 0, +/* bb7 - */ 0, +/* bb8 - */ 0, +/* bb9 - */ 0, +/* bba - */ 0, +/* bbb - */ 0, +/* bbc - */ 0, +/* bbd - */ 0, +/* bbe - */ 0, +/* bbf - */ 0, +/* bc0 - */ 0, +/* bc1 - */ 0, +/* bc2 - */ 0, +/* bc3 - */ 0, +/* bc4 - */ 0, +/* bc5 - */ 0, +/* bc6 - */ 0, +/* bc7 - */ 0, +/* bc8 - */ 0, +/* bc9 - */ 0, +/* bca - */ 0, +/* bcb - */ 0, +/* bcc - */ 0, +/* bcd - */ 0, +/* bce - */ 0, +/* bcf - */ 0, +/* bd0 - */ 0, +/* bd1 - */ 0, +/* bd2 - */ 0, +/* bd3 - */ 0, +/* bd4 - */ 0, +/* bd5 - _66_0F_7C */ 0x23fb, +/* bd6 - */ 0, +/* bd7 - _F2_0F_7C */ 0x23fc, +/* bd8 - */ 0, +/* bd9 - _V_66_0F_7C */ 0x4087, +/* bda - */ 0, +/* bdb - _V_F2_0F_7C */ 0x4088, +/* bdc - */ 0, +/* bdd - */ 0, +/* bde - */ 0, +/* bdf - */ 0, +/* be0 - */ 0, +/* be1 - _66_0F_7D */ 0x23fd, +/* be2 - */ 0, +/* be3 - _F2_0F_7D */ 0x23fe, +/* be4 - */ 0, +/* be5 - _V_66_0F_7D */ 0x4089, +/* be6 - */ 0, +/* be7 - _V_F2_0F_7D */ 0x408a, +/* be8 - */ 0, +/* be9 - */ 0, +/* bea - */ 0, +/* beb - */ 0, +/* bec - _0F_7E */ 0x408b, +/* bed - _66_0F_7E */ 0x408c, +/* bee - _F3_0F_7E */ 0x23ff, +/* bef - */ 0, +/* bf0 - */ 0, +/* bf1 - _V_66_0F_7E */ 0x408d, +/* bf2 - _V_F3_0F_7E */ 0x408e, +/* bf3 - */ 0, +/* bf4 - */ 0, +/* bf5 - */ 0, +/* bf6 - */ 0, +/* bf7 - */ 0, +/* bf8 - _0F_7F */ 0x2400, +/* bf9 - _66_0F_7F */ 0x2401, +/* bfa - _F3_0F_7F */ 0x2402, +/* bfb - */ 0, +/* bfc - */ 0, +/* bfd - _V_66_0F_7F */ 0x408f, +/* bfe - _V_F3_0F_7F */ 0x4090, +/* bff - */ 0, +/* c00 - */ 0, +/* c01 - */ 0, +/* c02 - */ 0, +/* c03 - */ 0, +/* c04 - _0F_AE_00 */ 0xd57c, +/* c05 - _0F_AE_01 */ 0xd588, +/* c06 - _0F_AE_02 */ 0xd594, +/* c07 - _0F_AE_03 */ 0xd5a0, +/* c08 - _0F_AE_04 */ 0x4091, +/* c09 - _0F_AE_05 */ 0x4092, +/* c0a - _0F_AE_06 */ 0x4093, +/* c0b - _0F_AE_07 */ 0x4094, +/* c0c - */ 0, +/* c0d - */ 0, +/* c0e - _F3_0F_B8 */ 0x2403, +/* c0f - */ 0, +/* c10 - */ 0, +/* c11 - */ 0, +/* c12 - */ 0, +/* c13 - */ 0, +/* c14 - */ 0, +/* c15 - */ 0, +/* c16 - */ 0, +/* c17 - */ 0, +/* c18 - */ 0, +/* c19 - */ 0, +/* c1a - */ 0, +/* c1b - */ 0, +/* c1c - _0F_BA_04 */ 0x2404, +/* c1d - _0F_BA_05 */ 0x2405, +/* c1e - _0F_BA_06 */ 0x2406, +/* c1f - _0F_BA_07 */ 0x2407, +/* c20 - _0F_BC */ 0x2408, +/* c21 - */ 0, +/* c22 - _F3_0F_BC */ 0x2409, +/* c23 - */ 0, +/* c24 - */ 0, +/* c25 - */ 0, +/* c26 - */ 0, +/* c27 - */ 0, +/* c28 - */ 0, +/* c29 - */ 0, +/* c2a - */ 0, +/* c2b - */ 0, +/* c2c - _0F_BD */ 0x240a, +/* c2d - */ 0, +/* c2e - _F3_0F_BD */ 0x240b, +/* c2f - */ 0, +/* c30 - */ 0, +/* c31 - */ 0, +/* c32 - */ 0, +/* c33 - */ 0, +/* c34 - */ 0, +/* c35 - */ 0, +/* c36 - */ 0, +/* c37 - */ 0, +/* c38 - _0F_C2 */ 0x4095, +/* c39 - _66_0F_C2 */ 0x4096, +/* c3a - _F3_0F_C2 */ 0x4097, +/* c3b - _F2_0F_C2 */ 0x4098, +/* c3c - _V_0F_C2 */ 0x4099, +/* c3d - _V_66_0F_C2 */ 0x409a, +/* c3e - _V_F3_0F_C2 */ 0x409b, +/* c3f - _V_F2_0F_C2 */ 0x409c, +/* c40 - */ 0, +/* c41 - */ 0, +/* c42 - */ 0, +/* c43 - */ 0, +/* c44 - _0F_C4 */ 0x409d, +/* c45 - _66_0F_C4 */ 0x409e, +/* c46 - */ 0, +/* c47 - */ 0, +/* c48 - */ 0, +/* c49 - _V_66_0F_C4 */ 0x409f, +/* c4a - */ 0, +/* c4b - */ 0, +/* c4c - */ 0, +/* c4d - */ 0, +/* c4e - */ 0, +/* c4f - */ 0, +/* c50 - _0F_C5 */ 0x40a0, +/* c51 - _66_0F_C5 */ 0x40a1, +/* c52 - */ 0, +/* c53 - */ 0, +/* c54 - */ 0, +/* c55 - _V_66_0F_C5 */ 0x40a2, +/* c56 - */ 0, +/* c57 - */ 0, +/* c58 - */ 0, +/* c59 - */ 0, +/* c5a - */ 0, +/* c5b - */ 0, +/* c5c - _0F_C6 */ 0x40a3, +/* c5d - _66_0F_C6 */ 0x40a4, +/* c5e - */ 0, +/* c5f - */ 0, +/* c60 - _V_0F_C6 */ 0x40a5, +/* c61 - _V_66_0F_C6 */ 0x40a6, +/* c62 - */ 0, +/* c63 - */ 0, +/* c64 - */ 0, +/* c65 - */ 0, +/* c66 - */ 0, +/* c67 - */ 0, +/* c68 - */ 0, +/* c69 - _0F_C7_01 */ 0x40a7, +/* c6a - */ 0, +/* c6b - */ 0, +/* c6c - */ 0, +/* c6d - */ 0, +/* c6e - _0F_C7_06 */ 0xd5ac, +/* c6f - _0F_C7_07 */ 0x240c, +/* c70 - */ 0, +/* c71 - _66_0F_D0 */ 0x240d, +/* c72 - */ 0, +/* c73 - _F2_0F_D0 */ 0x240e, +/* c74 - */ 0, +/* c75 - _V_66_0F_D0 */ 0x40a8, +/* c76 - */ 0, +/* c77 - _V_F2_0F_D0 */ 0x40a9, +/* c78 - */ 0, +/* c79 - */ 0, +/* c7a - */ 0, +/* c7b - */ 0, +/* c7c - _0F_D1 */ 0x240f, +/* c7d - _66_0F_D1 */ 0x2410, +/* c7e - */ 0, +/* c7f - */ 0, +/* c80 - */ 0, +/* c81 - _V_66_0F_D1 */ 0x40aa, +/* c82 - */ 0, +/* c83 - */ 0, +/* c84 - */ 0, +/* c85 - */ 0, +/* c86 - */ 0, +/* c87 - */ 0, +/* c88 - _0F_D2 */ 0x2411, +/* c89 - _66_0F_D2 */ 0x2412, +/* c8a - */ 0, +/* c8b - */ 0, +/* c8c - */ 0, +/* c8d - _V_66_0F_D2 */ 0x40ab, +/* c8e - */ 0, +/* c8f - */ 0, +/* c90 - */ 0, +/* c91 - */ 0, +/* c92 - */ 0, +/* c93 - */ 0, +/* c94 - _0F_D3 */ 0x2413, +/* c95 - _66_0F_D3 */ 0x2414, +/* c96 - */ 0, +/* c97 - */ 0, +/* c98 - */ 0, +/* c99 - _V_66_0F_D3 */ 0x40ac, +/* c9a - */ 0, +/* c9b - */ 0, +/* c9c - */ 0, +/* c9d - */ 0, +/* c9e - */ 0, +/* c9f - */ 0, +/* ca0 - _0F_D4 */ 0x2415, +/* ca1 - _66_0F_D4 */ 0x2416, +/* ca2 - */ 0, +/* ca3 - */ 0, +/* ca4 - */ 0, +/* ca5 - _V_66_0F_D4 */ 0x40ad, +/* ca6 - */ 0, +/* ca7 - */ 0, +/* ca8 - */ 0, +/* ca9 - */ 0, +/* caa - */ 0, +/* cab - */ 0, +/* cac - _0F_D5 */ 0x2417, +/* cad - _66_0F_D5 */ 0x2418, +/* cae - */ 0, +/* caf - */ 0, +/* cb0 - */ 0, +/* cb1 - _V_66_0F_D5 */ 0x40ae, +/* cb2 - */ 0, +/* cb3 - */ 0, +/* cb4 - */ 0, +/* cb5 - */ 0, +/* cb6 - */ 0, +/* cb7 - */ 0, +/* cb8 - */ 0, +/* cb9 - _66_0F_D6 */ 0x2419, +/* cba - _F3_0F_D6 */ 0x241a, +/* cbb - _F2_0F_D6 */ 0x241b, +/* cbc - */ 0, +/* cbd - _V_66_0F_D6 */ 0x40af, +/* cbe - */ 0, +/* cbf - */ 0, +/* cc0 - */ 0, +/* cc1 - */ 0, +/* cc2 - */ 0, +/* cc3 - */ 0, +/* cc4 - _0F_D7 */ 0x241c, +/* cc5 - _66_0F_D7 */ 0x241d, +/* cc6 - */ 0, +/* cc7 - */ 0, +/* cc8 - */ 0, +/* cc9 - _V_66_0F_D7 */ 0x40b0, +/* cca - */ 0, +/* ccb - */ 0, +/* ccc - */ 0, +/* ccd - */ 0, +/* cce - */ 0, +/* ccf - */ 0, +/* cd0 - _0F_D8 */ 0x241e, +/* cd1 - _66_0F_D8 */ 0x241f, +/* cd2 - */ 0, +/* cd3 - */ 0, +/* cd4 - */ 0, +/* cd5 - _V_66_0F_D8 */ 0x40b1, +/* cd6 - */ 0, +/* cd7 - */ 0, +/* cd8 - */ 0, +/* cd9 - */ 0, +/* cda - */ 0, +/* cdb - */ 0, +/* cdc - _0F_D9 */ 0x2420, +/* cdd - _66_0F_D9 */ 0x2421, +/* cde - */ 0, +/* cdf - */ 0, +/* ce0 - */ 0, +/* ce1 - _V_66_0F_D9 */ 0x40b2, +/* ce2 - */ 0, +/* ce3 - */ 0, +/* ce4 - */ 0, +/* ce5 - */ 0, +/* ce6 - */ 0, +/* ce7 - */ 0, +/* ce8 - _0F_DA */ 0x2422, +/* ce9 - _66_0F_DA */ 0x2423, +/* cea - */ 0, +/* ceb - */ 0, +/* cec - */ 0, +/* ced - _V_66_0F_DA */ 0x40b3, +/* cee - */ 0, +/* cef - */ 0, +/* cf0 - */ 0, +/* cf1 - */ 0, +/* cf2 - */ 0, +/* cf3 - */ 0, +/* cf4 - _0F_DB */ 0x2424, +/* cf5 - _66_0F_DB */ 0x2425, +/* cf6 - */ 0, +/* cf7 - */ 0, +/* cf8 - */ 0, +/* cf9 - _V_66_0F_DB */ 0x40b4, +/* cfa - */ 0, +/* cfb - */ 0, +/* cfc - */ 0, +/* cfd - */ 0, +/* cfe - */ 0, +/* cff - */ 0, +/* d00 - _0F_DC */ 0x2426, +/* d01 - _66_0F_DC */ 0x2427, +/* d02 - */ 0, +/* d03 - */ 0, +/* d04 - */ 0, +/* d05 - _V_66_0F_DC */ 0x40b5, +/* d06 - */ 0, +/* d07 - */ 0, +/* d08 - */ 0, +/* d09 - */ 0, +/* d0a - */ 0, +/* d0b - */ 0, +/* d0c - _0F_DD */ 0x2428, +/* d0d - _66_0F_DD */ 0x2429, +/* d0e - */ 0, +/* d0f - */ 0, +/* d10 - */ 0, +/* d11 - _V_66_0F_DD */ 0x40b6, +/* d12 - */ 0, +/* d13 - */ 0, +/* d14 - */ 0, +/* d15 - */ 0, +/* d16 - */ 0, +/* d17 - */ 0, +/* d18 - _0F_DE */ 0x242a, +/* d19 - _66_0F_DE */ 0x242b, +/* d1a - */ 0, +/* d1b - */ 0, +/* d1c - */ 0, +/* d1d - _V_66_0F_DE */ 0x40b7, +/* d1e - */ 0, +/* d1f - */ 0, +/* d20 - */ 0, +/* d21 - */ 0, +/* d22 - */ 0, +/* d23 - */ 0, +/* d24 - _0F_DF */ 0x242c, +/* d25 - _66_0F_DF */ 0x242d, +/* d26 - */ 0, +/* d27 - */ 0, +/* d28 - */ 0, +/* d29 - _V_66_0F_DF */ 0x40b8, +/* d2a - */ 0, +/* d2b - */ 0, +/* d2c - */ 0, +/* d2d - */ 0, +/* d2e - */ 0, +/* d2f - */ 0, +/* d30 - _0F_E0 */ 0x242e, +/* d31 - _66_0F_E0 */ 0x242f, +/* d32 - */ 0, +/* d33 - */ 0, +/* d34 - */ 0, +/* d35 - _V_66_0F_E0 */ 0x40b9, +/* d36 - */ 0, +/* d37 - */ 0, +/* d38 - */ 0, +/* d39 - */ 0, +/* d3a - */ 0, +/* d3b - */ 0, +/* d3c - _0F_E1 */ 0x2430, +/* d3d - _66_0F_E1 */ 0x2431, +/* d3e - */ 0, +/* d3f - */ 0, +/* d40 - */ 0, +/* d41 - _V_66_0F_E1 */ 0x40ba, +/* d42 - */ 0, +/* d43 - */ 0, +/* d44 - */ 0, +/* d45 - */ 0, +/* d46 - */ 0, +/* d47 - */ 0, +/* d48 - _0F_E2 */ 0x2432, +/* d49 - _66_0F_E2 */ 0x2433, +/* d4a - */ 0, +/* d4b - */ 0, +/* d4c - */ 0, +/* d4d - _V_66_0F_E2 */ 0x40bb, +/* d4e - */ 0, +/* d4f - */ 0, +/* d50 - */ 0, +/* d51 - */ 0, +/* d52 - */ 0, +/* d53 - */ 0, +/* d54 - _0F_E3 */ 0x2434, +/* d55 - _66_0F_E3 */ 0x2435, +/* d56 - */ 0, +/* d57 - */ 0, +/* d58 - */ 0, +/* d59 - _V_66_0F_E3 */ 0x40bc, +/* d5a - */ 0, +/* d5b - */ 0, +/* d5c - */ 0, +/* d5d - */ 0, +/* d5e - */ 0, +/* d5f - */ 0, +/* d60 - _0F_E4 */ 0x2436, +/* d61 - _66_0F_E4 */ 0x2437, +/* d62 - */ 0, +/* d63 - */ 0, +/* d64 - */ 0, +/* d65 - _V_66_0F_E4 */ 0x40bd, +/* d66 - */ 0, +/* d67 - */ 0, +/* d68 - */ 0, +/* d69 - */ 0, +/* d6a - */ 0, +/* d6b - */ 0, +/* d6c - _0F_E5 */ 0x2438, +/* d6d - _66_0F_E5 */ 0x2439, +/* d6e - */ 0, +/* d6f - */ 0, +/* d70 - */ 0, +/* d71 - _V_66_0F_E5 */ 0x40be, +/* d72 - */ 0, +/* d73 - */ 0, +/* d74 - */ 0, +/* d75 - */ 0, +/* d76 - */ 0, +/* d77 - */ 0, +/* d78 - */ 0, +/* d79 - _66_0F_E6 */ 0x243a, +/* d7a - _F3_0F_E6 */ 0x243b, +/* d7b - _F2_0F_E6 */ 0x243c, +/* d7c - */ 0, +/* d7d - _V_66_0F_E6 */ 0x40bf, +/* d7e - _V_F3_0F_E6 */ 0x40c0, +/* d7f - _V_F2_0F_E6 */ 0x40c1, +/* d80 - */ 0, +/* d81 - */ 0, +/* d82 - */ 0, +/* d83 - */ 0, +/* d84 - _0F_E7 */ 0x243d, +/* d85 - _66_0F_E7 */ 0x243e, +/* d86 - */ 0, +/* d87 - */ 0, +/* d88 - */ 0, +/* d89 - _V_66_0F_E7 */ 0x40c2, +/* d8a - */ 0, +/* d8b - */ 0, +/* d8c - */ 0, +/* d8d - */ 0, +/* d8e - */ 0, +/* d8f - */ 0, +/* d90 - _0F_E8 */ 0x243f, +/* d91 - _66_0F_E8 */ 0x2440, +/* d92 - */ 0, +/* d93 - */ 0, +/* d94 - */ 0, +/* d95 - _V_66_0F_E8 */ 0x40c3, +/* d96 - */ 0, +/* d97 - */ 0, +/* d98 - */ 0, +/* d99 - */ 0, +/* d9a - */ 0, +/* d9b - */ 0, +/* d9c - _0F_E9 */ 0x2441, +/* d9d - _66_0F_E9 */ 0x2442, +/* d9e - */ 0, +/* d9f - */ 0, +/* da0 - */ 0, +/* da1 - _V_66_0F_E9 */ 0x40c4, +/* da2 - */ 0, +/* da3 - */ 0, +/* da4 - */ 0, +/* da5 - */ 0, +/* da6 - */ 0, +/* da7 - */ 0, +/* da8 - _0F_EA */ 0x2443, +/* da9 - _66_0F_EA */ 0x2444, +/* daa - */ 0, +/* dab - */ 0, +/* dac - */ 0, +/* dad - _V_66_0F_EA */ 0x40c5, +/* dae - */ 0, +/* daf - */ 0, +/* db0 - */ 0, +/* db1 - */ 0, +/* db2 - */ 0, +/* db3 - */ 0, +/* db4 - _0F_EB */ 0x2445, +/* db5 - _66_0F_EB */ 0x2446, +/* db6 - */ 0, +/* db7 - */ 0, +/* db8 - */ 0, +/* db9 - _V_66_0F_EB */ 0x40c6, +/* dba - */ 0, +/* dbb - */ 0, +/* dbc - */ 0, +/* dbd - */ 0, +/* dbe - */ 0, +/* dbf - */ 0, +/* dc0 - _0F_EC */ 0x2447, +/* dc1 - _66_0F_EC */ 0x2448, +/* dc2 - */ 0, +/* dc3 - */ 0, +/* dc4 - */ 0, +/* dc5 - _V_66_0F_EC */ 0x40c7, +/* dc6 - */ 0, +/* dc7 - */ 0, +/* dc8 - */ 0, +/* dc9 - */ 0, +/* dca - */ 0, +/* dcb - */ 0, +/* dcc - _0F_ED */ 0x2449, +/* dcd - _66_0F_ED */ 0x244a, +/* dce - */ 0, +/* dcf - */ 0, +/* dd0 - */ 0, +/* dd1 - _V_66_0F_ED */ 0x40c8, +/* dd2 - */ 0, +/* dd3 - */ 0, +/* dd4 - */ 0, +/* dd5 - */ 0, +/* dd6 - */ 0, +/* dd7 - */ 0, +/* dd8 - _0F_EE */ 0x244b, +/* dd9 - _66_0F_EE */ 0x244c, +/* dda - */ 0, +/* ddb - */ 0, +/* ddc - */ 0, +/* ddd - _V_66_0F_EE */ 0x40c9, +/* dde - */ 0, +/* ddf - */ 0, +/* de0 - */ 0, +/* de1 - */ 0, +/* de2 - */ 0, +/* de3 - */ 0, +/* de4 - _0F_EF */ 0x244d, +/* de5 - _66_0F_EF */ 0x244e, +/* de6 - */ 0, +/* de7 - */ 0, +/* de8 - */ 0, +/* de9 - _V_66_0F_EF */ 0x40ca, +/* dea - */ 0, +/* deb - */ 0, +/* dec - */ 0, +/* ded - */ 0, +/* dee - */ 0, +/* def - */ 0, +/* df0 - */ 0, +/* df1 - */ 0, +/* df2 - */ 0, +/* df3 - _F2_0F_F0 */ 0x244f, +/* df4 - */ 0, +/* df5 - */ 0, +/* df6 - */ 0, +/* df7 - _V_F2_0F_F0 */ 0x40cb, +/* df8 - */ 0, +/* df9 - */ 0, +/* dfa - */ 0, +/* dfb - */ 0, +/* dfc - _0F_F1 */ 0x2450, +/* dfd - _66_0F_F1 */ 0x2451, +/* dfe - */ 0, +/* dff - */ 0, +/* e00 - */ 0, +/* e01 - _V_66_0F_F1 */ 0x40cc, +/* e02 - */ 0, +/* e03 - */ 0, +/* e04 - */ 0, +/* e05 - */ 0, +/* e06 - */ 0, +/* e07 - */ 0, +/* e08 - _0F_F2 */ 0x2452, +/* e09 - _66_0F_F2 */ 0x2453, +/* e0a - */ 0, +/* e0b - */ 0, +/* e0c - */ 0, +/* e0d - _V_66_0F_F2 */ 0x40cd, +/* e0e - */ 0, +/* e0f - */ 0, +/* e10 - */ 0, +/* e11 - */ 0, +/* e12 - */ 0, +/* e13 - */ 0, +/* e14 - _0F_F3 */ 0x2454, +/* e15 - _66_0F_F3 */ 0x2455, +/* e16 - */ 0, +/* e17 - */ 0, +/* e18 - */ 0, +/* e19 - _V_66_0F_F3 */ 0x40ce, +/* e1a - */ 0, +/* e1b - */ 0, +/* e1c - */ 0, +/* e1d - */ 0, +/* e1e - */ 0, +/* e1f - */ 0, +/* e20 - _0F_F4 */ 0x2456, +/* e21 - _66_0F_F4 */ 0x2457, +/* e22 - */ 0, +/* e23 - */ 0, +/* e24 - */ 0, +/* e25 - _V_66_0F_F4 */ 0x40cf, +/* e26 - */ 0, +/* e27 - */ 0, +/* e28 - */ 0, +/* e29 - */ 0, +/* e2a - */ 0, +/* e2b - */ 0, +/* e2c - _0F_F5 */ 0x2458, +/* e2d - _66_0F_F5 */ 0x2459, +/* e2e - */ 0, +/* e2f - */ 0, +/* e30 - */ 0, +/* e31 - _V_66_0F_F5 */ 0x40d0, +/* e32 - */ 0, +/* e33 - */ 0, +/* e34 - */ 0, +/* e35 - */ 0, +/* e36 - */ 0, +/* e37 - */ 0, +/* e38 - _0F_F6 */ 0x245a, +/* e39 - _66_0F_F6 */ 0x245b, +/* e3a - */ 0, +/* e3b - */ 0, +/* e3c - */ 0, +/* e3d - _V_66_0F_F6 */ 0x40d1, +/* e3e - */ 0, +/* e3f - */ 0, +/* e40 - */ 0, +/* e41 - */ 0, +/* e42 - */ 0, +/* e43 - */ 0, +/* e44 - _0F_F7 */ 0x245c, +/* e45 - _66_0F_F7 */ 0x245d, +/* e46 - */ 0, +/* e47 - */ 0, +/* e48 - */ 0, +/* e49 - _V_66_0F_F7 */ 0x40d2, +/* e4a - */ 0, +/* e4b - */ 0, +/* e4c - */ 0, +/* e4d - */ 0, +/* e4e - */ 0, +/* e4f - */ 0, +/* e50 - _0F_F8 */ 0x245e, +/* e51 - _66_0F_F8 */ 0x245f, +/* e52 - */ 0, +/* e53 - */ 0, +/* e54 - */ 0, +/* e55 - _V_66_0F_F8 */ 0x40d3, +/* e56 - */ 0, +/* e57 - */ 0, +/* e58 - */ 0, +/* e59 - */ 0, +/* e5a - */ 0, +/* e5b - */ 0, +/* e5c - _0F_F9 */ 0x2460, +/* e5d - _66_0F_F9 */ 0x2461, +/* e5e - */ 0, +/* e5f - */ 0, +/* e60 - */ 0, +/* e61 - _V_66_0F_F9 */ 0x40d4, +/* e62 - */ 0, +/* e63 - */ 0, +/* e64 - */ 0, +/* e65 - */ 0, +/* e66 - */ 0, +/* e67 - */ 0, +/* e68 - _0F_FA */ 0x2462, +/* e69 - _66_0F_FA */ 0x2463, +/* e6a - */ 0, +/* e6b - */ 0, +/* e6c - */ 0, +/* e6d - _V_66_0F_FA */ 0x40d5, +/* e6e - */ 0, +/* e6f - */ 0, +/* e70 - */ 0, +/* e71 - */ 0, +/* e72 - */ 0, +/* e73 - */ 0, +/* e74 - _0F_FB */ 0x2464, +/* e75 - _66_0F_FB */ 0x2465, +/* e76 - */ 0, +/* e77 - */ 0, +/* e78 - */ 0, +/* e79 - _V_66_0F_FB */ 0x40d6, +/* e7a - */ 0, +/* e7b - */ 0, +/* e7c - */ 0, +/* e7d - */ 0, +/* e7e - */ 0, +/* e7f - */ 0, +/* e80 - _0F_FC */ 0x2466, +/* e81 - _66_0F_FC */ 0x2467, +/* e82 - */ 0, +/* e83 - */ 0, +/* e84 - */ 0, +/* e85 - _V_66_0F_FC */ 0x40d7, +/* e86 - */ 0, +/* e87 - */ 0, +/* e88 - */ 0, +/* e89 - */ 0, +/* e8a - */ 0, +/* e8b - */ 0, +/* e8c - _0F_FD */ 0x2468, +/* e8d - _66_0F_FD */ 0x2469, +/* e8e - */ 0, +/* e8f - */ 0, +/* e90 - */ 0, +/* e91 - _V_66_0F_FD */ 0x40d8, +/* e92 - */ 0, +/* e93 - */ 0, +/* e94 - */ 0, +/* e95 - */ 0, +/* e96 - */ 0, +/* e97 - */ 0, +/* e98 - _0F_FE */ 0x246a, +/* e99 - _66_0F_FE */ 0x246b, +/* e9a - */ 0, +/* e9b - */ 0, +/* e9c - */ 0, +/* e9d - _V_66_0F_FE */ 0x40d9, +/* e9e - */ 0, +/* e9f - */ 0, +/* ea0 - */ 0, +/* ea1 - */ 0, +/* ea2 - */ 0, +/* ea3 - */ 0, +/* ea4 - _D9_06 */ 0x246c, +/* ea5 - _9B_D9_06 */ 0x246d, +/* ea6 - */ 0, +/* ea7 - */ 0, +/* ea8 - */ 0, +/* ea9 - */ 0, +/* eaa - */ 0, +/* eab - */ 0, +/* eac - */ 0, +/* ead - */ 0, +/* eae - */ 0, +/* eaf - */ 0, +/* eb0 - _D9_07 */ 0x246e, +/* eb1 - _9B_D9_07 */ 0x246f, +/* eb2 - */ 0, +/* eb3 - */ 0, +/* eb4 - */ 0, +/* eb5 - */ 0, +/* eb6 - */ 0, +/* eb7 - */ 0, +/* eb8 - */ 0, +/* eb9 - */ 0, +/* eba - */ 0, +/* ebb - */ 0, +/* ebc - _DB_E2 */ 0x2470, +/* ebd - _9B_DB_E2 */ 0x2471, +/* ebe - */ 0, +/* ebf - */ 0, +/* ec0 - */ 0, +/* ec1 - */ 0, +/* ec2 - */ 0, +/* ec3 - */ 0, +/* ec4 - */ 0, +/* ec5 - */ 0, +/* ec6 - */ 0, +/* ec7 - */ 0, +/* ec8 - _DB_E3 */ 0x2472, +/* ec9 - _9B_DB_E3 */ 0x2473, +/* eca - */ 0, +/* ecb - */ 0, +/* ecc - */ 0, +/* ecd - */ 0, +/* ece - */ 0, +/* ecf - */ 0, +/* ed0 - */ 0, +/* ed1 - */ 0, +/* ed2 - */ 0, +/* ed3 - */ 0, +/* ed4 - _DD_06 */ 0x2474, +/* ed5 - _9B_DD_06 */ 0x2475, +/* ed6 - */ 0, +/* ed7 - */ 0, +/* ed8 - */ 0, +/* ed9 - */ 0, +/* eda - */ 0, +/* edb - */ 0, +/* edc - */ 0, +/* edd - */ 0, +/* ede - */ 0, +/* edf - */ 0, +/* ee0 - _DD_07 */ 0x2476, +/* ee1 - _9B_DD_07 */ 0x2477, +/* ee2 - */ 0, +/* ee3 - */ 0, +/* ee4 - */ 0, +/* ee5 - */ 0, +/* ee6 - */ 0, +/* ee7 - */ 0, +/* ee8 - */ 0, +/* ee9 - */ 0, +/* eea - */ 0, +/* eeb - */ 0, +/* eec - _DF_E0 */ 0x2478, +/* eed - _9B_DF_E0 */ 0x2479, +/* eee - */ 0, +/* eef - */ 0, +/* ef0 - */ 0, +/* ef1 - */ 0, +/* ef2 - */ 0, +/* ef3 - */ 0, +/* ef4 - */ 0, +/* ef5 - */ 0, +/* ef6 - */ 0, +/* ef7 - */ 0, +/* ef8 - _0F_38_00 */ 0x247a, +/* ef9 - _66_0F_38_00 */ 0x247b, +/* efa - */ 0, +/* efb - */ 0, +/* efc - */ 0, +/* efd - _V_66_0F_38_00 */ 0x40da, +/* efe - */ 0, +/* eff - */ 0, +/* f00 - */ 0, +/* f01 - */ 0, +/* f02 - */ 0, +/* f03 - */ 0, +/* f04 - _0F_38_01 */ 0x247c, +/* f05 - _66_0F_38_01 */ 0x247d, +/* f06 - */ 0, +/* f07 - */ 0, +/* f08 - */ 0, +/* f09 - _V_66_0F_38_01 */ 0x40db, +/* f0a - */ 0, +/* f0b - */ 0, +/* f0c - */ 0, +/* f0d - */ 0, +/* f0e - */ 0, +/* f0f - */ 0, +/* f10 - _0F_38_02 */ 0x247e, +/* f11 - _66_0F_38_02 */ 0x247f, +/* f12 - */ 0, +/* f13 - */ 0, +/* f14 - */ 0, +/* f15 - _V_66_0F_38_02 */ 0x40dc, +/* f16 - */ 0, +/* f17 - */ 0, +/* f18 - */ 0, +/* f19 - */ 0, +/* f1a - */ 0, +/* f1b - */ 0, +/* f1c - _0F_38_03 */ 0x2480, +/* f1d - _66_0F_38_03 */ 0x2481, +/* f1e - */ 0, +/* f1f - */ 0, +/* f20 - */ 0, +/* f21 - _V_66_0F_38_03 */ 0x40dd, +/* f22 - */ 0, +/* f23 - */ 0, +/* f24 - */ 0, +/* f25 - */ 0, +/* f26 - */ 0, +/* f27 - */ 0, +/* f28 - _0F_38_04 */ 0x2482, +/* f29 - _66_0F_38_04 */ 0x2483, +/* f2a - */ 0, +/* f2b - */ 0, +/* f2c - */ 0, +/* f2d - _V_66_0F_38_04 */ 0x40de, +/* f2e - */ 0, +/* f2f - */ 0, +/* f30 - */ 0, +/* f31 - */ 0, +/* f32 - */ 0, +/* f33 - */ 0, +/* f34 - _0F_38_05 */ 0x2484, +/* f35 - _66_0F_38_05 */ 0x2485, +/* f36 - */ 0, +/* f37 - */ 0, +/* f38 - */ 0, +/* f39 - _V_66_0F_38_05 */ 0x40df, +/* f3a - */ 0, +/* f3b - */ 0, +/* f3c - */ 0, +/* f3d - */ 0, +/* f3e - */ 0, +/* f3f - */ 0, +/* f40 - _0F_38_06 */ 0x2486, +/* f41 - _66_0F_38_06 */ 0x2487, +/* f42 - */ 0, +/* f43 - */ 0, +/* f44 - */ 0, +/* f45 - _V_66_0F_38_06 */ 0x40e0, +/* f46 - */ 0, +/* f47 - */ 0, +/* f48 - */ 0, +/* f49 - */ 0, +/* f4a - */ 0, +/* f4b - */ 0, +/* f4c - _0F_38_07 */ 0x2488, +/* f4d - _66_0F_38_07 */ 0x2489, +/* f4e - */ 0, +/* f4f - */ 0, +/* f50 - */ 0, +/* f51 - _V_66_0F_38_07 */ 0x40e1, +/* f52 - */ 0, +/* f53 - */ 0, +/* f54 - */ 0, +/* f55 - */ 0, +/* f56 - */ 0, +/* f57 - */ 0, +/* f58 - _0F_38_08 */ 0x248a, +/* f59 - _66_0F_38_08 */ 0x248b, +/* f5a - */ 0, +/* f5b - */ 0, +/* f5c - */ 0, +/* f5d - _V_66_0F_38_08 */ 0x40e2, +/* f5e - */ 0, +/* f5f - */ 0, +/* f60 - */ 0, +/* f61 - */ 0, +/* f62 - */ 0, +/* f63 - */ 0, +/* f64 - _0F_38_09 */ 0x248c, +/* f65 - _66_0F_38_09 */ 0x248d, +/* f66 - */ 0, +/* f67 - */ 0, +/* f68 - */ 0, +/* f69 - _V_66_0F_38_09 */ 0x40e3, +/* f6a - */ 0, +/* f6b - */ 0, +/* f6c - */ 0, +/* f6d - */ 0, +/* f6e - */ 0, +/* f6f - */ 0, +/* f70 - _0F_38_0A */ 0x248e, +/* f71 - _66_0F_38_0A */ 0x248f, +/* f72 - */ 0, +/* f73 - */ 0, +/* f74 - */ 0, +/* f75 - _V_66_0F_38_0A */ 0x40e4, +/* f76 - */ 0, +/* f77 - */ 0, +/* f78 - */ 0, +/* f79 - */ 0, +/* f7a - */ 0, +/* f7b - */ 0, +/* f7c - _0F_38_0B */ 0x2490, +/* f7d - _66_0F_38_0B */ 0x2491, +/* f7e - */ 0, +/* f7f - */ 0, +/* f80 - */ 0, +/* f81 - _V_66_0F_38_0B */ 0x40e5, +/* f82 - */ 0, +/* f83 - */ 0, +/* f84 - */ 0, +/* f85 - */ 0, +/* f86 - */ 0, +/* f87 - */ 0, +/* f88 - */ 0, +/* f89 - */ 0, +/* f8a - */ 0, +/* f8b - */ 0, +/* f8c - */ 0, +/* f8d - _V_66_0F_38_0C */ 0x40e6, +/* f8e - */ 0, +/* f8f - */ 0, +/* f90 - */ 0, +/* f91 - */ 0, +/* f92 - */ 0, +/* f93 - */ 0, +/* f94 - */ 0, +/* f95 - */ 0, +/* f96 - */ 0, +/* f97 - */ 0, +/* f98 - */ 0, +/* f99 - _V_66_0F_38_0D */ 0x40e7, +/* f9a - */ 0, +/* f9b - */ 0, +/* f9c - */ 0, +/* f9d - */ 0, +/* f9e - */ 0, +/* f9f - */ 0, +/* fa0 - */ 0, +/* fa1 - */ 0, +/* fa2 - */ 0, +/* fa3 - */ 0, +/* fa4 - */ 0, +/* fa5 - _V_66_0F_38_0E */ 0x40e8, +/* fa6 - */ 0, +/* fa7 - */ 0, +/* fa8 - */ 0, +/* fa9 - */ 0, +/* faa - */ 0, +/* fab - */ 0, +/* fac - */ 0, +/* fad - */ 0, +/* fae - */ 0, +/* faf - */ 0, +/* fb0 - */ 0, +/* fb1 - _V_66_0F_38_0F */ 0x40e9, +/* fb2 - */ 0, +/* fb3 - */ 0, +/* fb4 - */ 0, +/* fb5 - */ 0, +/* fb6 - */ 0, +/* fb7 - */ 0, +/* fb8 - */ 0, +/* fb9 - _66_0F_38_10 */ 0x40ea, +/* fba - */ 0, +/* fbb - */ 0, +/* fbc - */ 0, +/* fbd - */ 0, +/* fbe - */ 0, +/* fbf - */ 0, +/* fc0 - */ 0, +/* fc1 - */ 0, +/* fc2 - */ 0, +/* fc3 - */ 0, +/* fc4 - */ 0, +/* fc5 - _66_0F_38_14 */ 0x40eb, +/* fc6 - */ 0, +/* fc7 - */ 0, +/* fc8 - */ 0, +/* fc9 - */ 0, +/* fca - */ 0, +/* fcb - */ 0, +/* fcc - */ 0, +/* fcd - */ 0, +/* fce - */ 0, +/* fcf - */ 0, +/* fd0 - */ 0, +/* fd1 - _66_0F_38_15 */ 0x40ec, +/* fd2 - */ 0, +/* fd3 - */ 0, +/* fd4 - */ 0, +/* fd5 - */ 0, +/* fd6 - */ 0, +/* fd7 - */ 0, +/* fd8 - */ 0, +/* fd9 - */ 0, +/* fda - */ 0, +/* fdb - */ 0, +/* fdc - */ 0, +/* fdd - _66_0F_38_17 */ 0x2492, +/* fde - */ 0, +/* fdf - */ 0, +/* fe0 - */ 0, +/* fe1 - _V_66_0F_38_17 */ 0x40ed, +/* fe2 - */ 0, +/* fe3 - */ 0, +/* fe4 - */ 0, +/* fe5 - */ 0, +/* fe6 - */ 0, +/* fe7 - */ 0, +/* fe8 - */ 0, +/* fe9 - */ 0, +/* fea - */ 0, +/* feb - */ 0, +/* fec - */ 0, +/* fed - _V_66_0F_38_18 */ 0x40ee, +/* fee - */ 0, +/* fef - */ 0, +/* ff0 - */ 0, +/* ff1 - */ 0, +/* ff2 - */ 0, +/* ff3 - */ 0, +/* ff4 - */ 0, +/* ff5 - */ 0, +/* ff6 - */ 0, +/* ff7 - */ 0, +/* ff8 - */ 0, +/* ff9 - _V_66_0F_38_19 */ 0x40ef, +/* ffa - */ 0, +/* ffb - */ 0, +/* ffc - */ 0, +/* ffd - */ 0, +/* ffe - */ 0, +/* fff - */ 0, +/* 1000 - */ 0, +/* 1001 - */ 0, +/* 1002 - */ 0, +/* 1003 - */ 0, +/* 1004 - */ 0, +/* 1005 - _V_66_0F_38_1A */ 0x40f0, +/* 1006 - */ 0, +/* 1007 - */ 0, +/* 1008 - */ 0, +/* 1009 - */ 0, +/* 100a - */ 0, +/* 100b - */ 0, +/* 100c - _0F_38_1C */ 0x2493, +/* 100d - _66_0F_38_1C */ 0x2494, +/* 100e - */ 0, +/* 100f - */ 0, +/* 1010 - */ 0, +/* 1011 - _V_66_0F_38_1C */ 0x40f1, +/* 1012 - */ 0, +/* 1013 - */ 0, +/* 1014 - */ 0, +/* 1015 - */ 0, +/* 1016 - */ 0, +/* 1017 - */ 0, +/* 1018 - _0F_38_1D */ 0x2495, +/* 1019 - _66_0F_38_1D */ 0x2496, +/* 101a - */ 0, +/* 101b - */ 0, +/* 101c - */ 0, +/* 101d - _V_66_0F_38_1D */ 0x40f2, +/* 101e - */ 0, +/* 101f - */ 0, +/* 1020 - */ 0, +/* 1021 - */ 0, +/* 1022 - */ 0, +/* 1023 - */ 0, +/* 1024 - _0F_38_1E */ 0x2497, +/* 1025 - _66_0F_38_1E */ 0x2498, +/* 1026 - */ 0, +/* 1027 - */ 0, +/* 1028 - */ 0, +/* 1029 - _V_66_0F_38_1E */ 0x40f3, +/* 102a - */ 0, +/* 102b - */ 0, +/* 102c - */ 0, +/* 102d - */ 0, +/* 102e - */ 0, +/* 102f - */ 0, +/* 1030 - */ 0, +/* 1031 - _66_0F_38_20 */ 0x2499, +/* 1032 - */ 0, +/* 1033 - */ 0, +/* 1034 - */ 0, +/* 1035 - _V_66_0F_38_20 */ 0x40f4, +/* 1036 - */ 0, +/* 1037 - */ 0, +/* 1038 - */ 0, +/* 1039 - */ 0, +/* 103a - */ 0, +/* 103b - */ 0, +/* 103c - */ 0, +/* 103d - _66_0F_38_21 */ 0x249a, +/* 103e - */ 0, +/* 103f - */ 0, +/* 1040 - */ 0, +/* 1041 - _V_66_0F_38_21 */ 0x40f5, +/* 1042 - */ 0, +/* 1043 - */ 0, +/* 1044 - */ 0, +/* 1045 - */ 0, +/* 1046 - */ 0, +/* 1047 - */ 0, +/* 1048 - */ 0, +/* 1049 - _66_0F_38_22 */ 0x249b, +/* 104a - */ 0, +/* 104b - */ 0, +/* 104c - */ 0, +/* 104d - _V_66_0F_38_22 */ 0x40f6, +/* 104e - */ 0, +/* 104f - */ 0, +/* 1050 - */ 0, +/* 1051 - */ 0, +/* 1052 - */ 0, +/* 1053 - */ 0, +/* 1054 - */ 0, +/* 1055 - _66_0F_38_23 */ 0x249c, +/* 1056 - */ 0, +/* 1057 - */ 0, +/* 1058 - */ 0, +/* 1059 - _V_66_0F_38_23 */ 0x40f7, +/* 105a - */ 0, +/* 105b - */ 0, +/* 105c - */ 0, +/* 105d - */ 0, +/* 105e - */ 0, +/* 105f - */ 0, +/* 1060 - */ 0, +/* 1061 - _66_0F_38_24 */ 0x249d, +/* 1062 - */ 0, +/* 1063 - */ 0, +/* 1064 - */ 0, +/* 1065 - _V_66_0F_38_24 */ 0x40f8, +/* 1066 - */ 0, +/* 1067 - */ 0, +/* 1068 - */ 0, +/* 1069 - */ 0, +/* 106a - */ 0, +/* 106b - */ 0, +/* 106c - */ 0, +/* 106d - _66_0F_38_25 */ 0x249e, +/* 106e - */ 0, +/* 106f - */ 0, +/* 1070 - */ 0, +/* 1071 - _V_66_0F_38_25 */ 0x40f9, +/* 1072 - */ 0, +/* 1073 - */ 0, +/* 1074 - */ 0, +/* 1075 - */ 0, +/* 1076 - */ 0, +/* 1077 - */ 0, +/* 1078 - */ 0, +/* 1079 - _66_0F_38_28 */ 0x249f, +/* 107a - */ 0, +/* 107b - */ 0, +/* 107c - */ 0, +/* 107d - _V_66_0F_38_28 */ 0x40fa, +/* 107e - */ 0, +/* 107f - */ 0, +/* 1080 - */ 0, +/* 1081 - */ 0, +/* 1082 - */ 0, +/* 1083 - */ 0, +/* 1084 - */ 0, +/* 1085 - _66_0F_38_29 */ 0x24a0, +/* 1086 - */ 0, +/* 1087 - */ 0, +/* 1088 - */ 0, +/* 1089 - _V_66_0F_38_29 */ 0x40fb, +/* 108a - */ 0, +/* 108b - */ 0, +/* 108c - */ 0, +/* 108d - */ 0, +/* 108e - */ 0, +/* 108f - */ 0, +/* 1090 - */ 0, +/* 1091 - _66_0F_38_2A */ 0x24a1, +/* 1092 - */ 0, +/* 1093 - */ 0, +/* 1094 - */ 0, +/* 1095 - _V_66_0F_38_2A */ 0x40fc, +/* 1096 - */ 0, +/* 1097 - */ 0, +/* 1098 - */ 0, +/* 1099 - */ 0, +/* 109a - */ 0, +/* 109b - */ 0, +/* 109c - */ 0, +/* 109d - _66_0F_38_2B */ 0x24a2, +/* 109e - */ 0, +/* 109f - */ 0, +/* 10a0 - */ 0, +/* 10a1 - _V_66_0F_38_2B */ 0x40fd, +/* 10a2 - */ 0, +/* 10a3 - */ 0, +/* 10a4 - */ 0, +/* 10a5 - */ 0, +/* 10a6 - */ 0, +/* 10a7 - */ 0, +/* 10a8 - */ 0, +/* 10a9 - */ 0, +/* 10aa - */ 0, +/* 10ab - */ 0, +/* 10ac - */ 0, +/* 10ad - _V_66_0F_38_2C */ 0x40fe, +/* 10ae - */ 0, +/* 10af - */ 0, +/* 10b0 - */ 0, +/* 10b1 - */ 0, +/* 10b2 - */ 0, +/* 10b3 - */ 0, +/* 10b4 - */ 0, +/* 10b5 - */ 0, +/* 10b6 - */ 0, +/* 10b7 - */ 0, +/* 10b8 - */ 0, +/* 10b9 - _V_66_0F_38_2D */ 0x40ff, +/* 10ba - */ 0, +/* 10bb - */ 0, +/* 10bc - */ 0, +/* 10bd - */ 0, +/* 10be - */ 0, +/* 10bf - */ 0, +/* 10c0 - */ 0, +/* 10c1 - */ 0, +/* 10c2 - */ 0, +/* 10c3 - */ 0, +/* 10c4 - */ 0, +/* 10c5 - _V_66_0F_38_2E */ 0x4100, +/* 10c6 - */ 0, +/* 10c7 - */ 0, +/* 10c8 - */ 0, +/* 10c9 - */ 0, +/* 10ca - */ 0, +/* 10cb - */ 0, +/* 10cc - */ 0, +/* 10cd - */ 0, +/* 10ce - */ 0, +/* 10cf - */ 0, +/* 10d0 - */ 0, +/* 10d1 - _V_66_0F_38_2F */ 0x4101, +/* 10d2 - */ 0, +/* 10d3 - */ 0, +/* 10d4 - */ 0, +/* 10d5 - */ 0, +/* 10d6 - */ 0, +/* 10d7 - */ 0, +/* 10d8 - */ 0, +/* 10d9 - _66_0F_38_30 */ 0x24a3, +/* 10da - */ 0, +/* 10db - */ 0, +/* 10dc - */ 0, +/* 10dd - _V_66_0F_38_30 */ 0x4102, +/* 10de - */ 0, +/* 10df - */ 0, +/* 10e0 - */ 0, +/* 10e1 - */ 0, +/* 10e2 - */ 0, +/* 10e3 - */ 0, +/* 10e4 - */ 0, +/* 10e5 - _66_0F_38_31 */ 0x24a4, +/* 10e6 - */ 0, +/* 10e7 - */ 0, +/* 10e8 - */ 0, +/* 10e9 - _V_66_0F_38_31 */ 0x4103, +/* 10ea - */ 0, +/* 10eb - */ 0, +/* 10ec - */ 0, +/* 10ed - */ 0, +/* 10ee - */ 0, +/* 10ef - */ 0, +/* 10f0 - */ 0, +/* 10f1 - _66_0F_38_32 */ 0x24a5, +/* 10f2 - */ 0, +/* 10f3 - */ 0, +/* 10f4 - */ 0, +/* 10f5 - _V_66_0F_38_32 */ 0x4104, +/* 10f6 - */ 0, +/* 10f7 - */ 0, +/* 10f8 - */ 0, +/* 10f9 - */ 0, +/* 10fa - */ 0, +/* 10fb - */ 0, +/* 10fc - */ 0, +/* 10fd - _66_0F_38_33 */ 0x24a6, +/* 10fe - */ 0, +/* 10ff - */ 0, +/* 1100 - */ 0, +/* 1101 - _V_66_0F_38_33 */ 0x4105, +/* 1102 - */ 0, +/* 1103 - */ 0, +/* 1104 - */ 0, +/* 1105 - */ 0, +/* 1106 - */ 0, +/* 1107 - */ 0, +/* 1108 - */ 0, +/* 1109 - _66_0F_38_34 */ 0x24a7, +/* 110a - */ 0, +/* 110b - */ 0, +/* 110c - */ 0, +/* 110d - _V_66_0F_38_34 */ 0x4106, +/* 110e - */ 0, +/* 110f - */ 0, +/* 1110 - */ 0, +/* 1111 - */ 0, +/* 1112 - */ 0, +/* 1113 - */ 0, +/* 1114 - */ 0, +/* 1115 - _66_0F_38_35 */ 0x24a8, +/* 1116 - */ 0, +/* 1117 - */ 0, +/* 1118 - */ 0, +/* 1119 - _V_66_0F_38_35 */ 0x4107, +/* 111a - */ 0, +/* 111b - */ 0, +/* 111c - */ 0, +/* 111d - */ 0, +/* 111e - */ 0, +/* 111f - */ 0, +/* 1120 - */ 0, +/* 1121 - _66_0F_38_37 */ 0x24a9, +/* 1122 - */ 0, +/* 1123 - */ 0, +/* 1124 - */ 0, +/* 1125 - _V_66_0F_38_37 */ 0x4108, +/* 1126 - */ 0, +/* 1127 - */ 0, +/* 1128 - */ 0, +/* 1129 - */ 0, +/* 112a - */ 0, +/* 112b - */ 0, +/* 112c - */ 0, +/* 112d - _66_0F_38_38 */ 0x24aa, +/* 112e - */ 0, +/* 112f - */ 0, +/* 1130 - */ 0, +/* 1131 - _V_66_0F_38_38 */ 0x4109, +/* 1132 - */ 0, +/* 1133 - */ 0, +/* 1134 - */ 0, +/* 1135 - */ 0, +/* 1136 - */ 0, +/* 1137 - */ 0, +/* 1138 - */ 0, +/* 1139 - _66_0F_38_39 */ 0x24ab, +/* 113a - */ 0, +/* 113b - */ 0, +/* 113c - */ 0, +/* 113d - _V_66_0F_38_39 */ 0x410a, +/* 113e - */ 0, +/* 113f - */ 0, +/* 1140 - */ 0, +/* 1141 - */ 0, +/* 1142 - */ 0, +/* 1143 - */ 0, +/* 1144 - */ 0, +/* 1145 - _66_0F_38_3A */ 0x24ac, +/* 1146 - */ 0, +/* 1147 - */ 0, +/* 1148 - */ 0, +/* 1149 - _V_66_0F_38_3A */ 0x410b, +/* 114a - */ 0, +/* 114b - */ 0, +/* 114c - */ 0, +/* 114d - */ 0, +/* 114e - */ 0, +/* 114f - */ 0, +/* 1150 - */ 0, +/* 1151 - _66_0F_38_3B */ 0x24ad, +/* 1152 - */ 0, +/* 1153 - */ 0, +/* 1154 - */ 0, +/* 1155 - _V_66_0F_38_3B */ 0x410c, +/* 1156 - */ 0, +/* 1157 - */ 0, +/* 1158 - */ 0, +/* 1159 - */ 0, +/* 115a - */ 0, +/* 115b - */ 0, +/* 115c - */ 0, +/* 115d - _66_0F_38_3C */ 0x24ae, +/* 115e - */ 0, +/* 115f - */ 0, +/* 1160 - */ 0, +/* 1161 - _V_66_0F_38_3C */ 0x410d, +/* 1162 - */ 0, +/* 1163 - */ 0, +/* 1164 - */ 0, +/* 1165 - */ 0, +/* 1166 - */ 0, +/* 1167 - */ 0, +/* 1168 - */ 0, +/* 1169 - _66_0F_38_3D */ 0x24af, +/* 116a - */ 0, +/* 116b - */ 0, +/* 116c - */ 0, +/* 116d - _V_66_0F_38_3D */ 0x410e, +/* 116e - */ 0, +/* 116f - */ 0, +/* 1170 - */ 0, +/* 1171 - */ 0, +/* 1172 - */ 0, +/* 1173 - */ 0, +/* 1174 - */ 0, +/* 1175 - _66_0F_38_3E */ 0x24b0, +/* 1176 - */ 0, +/* 1177 - */ 0, +/* 1178 - */ 0, +/* 1179 - _V_66_0F_38_3E */ 0x410f, +/* 117a - */ 0, +/* 117b - */ 0, +/* 117c - */ 0, +/* 117d - */ 0, +/* 117e - */ 0, +/* 117f - */ 0, +/* 1180 - */ 0, +/* 1181 - _66_0F_38_3F */ 0x24b1, +/* 1182 - */ 0, +/* 1183 - */ 0, +/* 1184 - */ 0, +/* 1185 - _V_66_0F_38_3F */ 0x4110, +/* 1186 - */ 0, +/* 1187 - */ 0, +/* 1188 - */ 0, +/* 1189 - */ 0, +/* 118a - */ 0, +/* 118b - */ 0, +/* 118c - */ 0, +/* 118d - _66_0F_38_40 */ 0x24b2, +/* 118e - */ 0, +/* 118f - */ 0, +/* 1190 - */ 0, +/* 1191 - _V_66_0F_38_40 */ 0x4111, +/* 1192 - */ 0, +/* 1193 - */ 0, +/* 1194 - */ 0, +/* 1195 - */ 0, +/* 1196 - */ 0, +/* 1197 - */ 0, +/* 1198 - */ 0, +/* 1199 - _66_0F_38_41 */ 0x24b3, +/* 119a - */ 0, +/* 119b - */ 0, +/* 119c - */ 0, +/* 119d - _V_66_0F_38_41 */ 0x4112, +/* 119e - */ 0, +/* 119f - */ 0, +/* 11a0 - */ 0, +/* 11a1 - */ 0, +/* 11a2 - */ 0, +/* 11a3 - */ 0, +/* 11a4 - */ 0, +/* 11a5 - _66_0F_38_80 */ 0x24b4, +/* 11a6 - */ 0, +/* 11a7 - */ 0, +/* 11a8 - */ 0, +/* 11a9 - */ 0, +/* 11aa - */ 0, +/* 11ab - */ 0, +/* 11ac - */ 0, +/* 11ad - */ 0, +/* 11ae - */ 0, +/* 11af - */ 0, +/* 11b0 - */ 0, +/* 11b1 - _66_0F_38_81 */ 0x24b5, +/* 11b2 - */ 0, +/* 11b3 - */ 0, +/* 11b4 - */ 0, +/* 11b5 - */ 0, +/* 11b6 - */ 0, +/* 11b7 - */ 0, +/* 11b8 - */ 0, +/* 11b9 - */ 0, +/* 11ba - */ 0, +/* 11bb - */ 0, +/* 11bc - */ 0, +/* 11bd - _66_0F_38_82 */ 0x24b6, +/* 11be - */ 0, +/* 11bf - */ 0, +/* 11c0 - */ 0, +/* 11c1 - */ 0, +/* 11c2 - */ 0, +/* 11c3 - */ 0, +/* 11c4 - */ 0, +/* 11c5 - */ 0, +/* 11c6 - */ 0, +/* 11c7 - */ 0, +/* 11c8 - */ 0, +/* 11c9 - */ 0, +/* 11ca - */ 0, +/* 11cb - */ 0, +/* 11cc - */ 0, +/* 11cd - _V_66_0F_38_96 */ 0x4113, +/* 11ce - */ 0, +/* 11cf - */ 0, +/* 11d0 - */ 0, +/* 11d1 - */ 0, +/* 11d2 - */ 0, +/* 11d3 - */ 0, +/* 11d4 - */ 0, +/* 11d5 - */ 0, +/* 11d6 - */ 0, +/* 11d7 - */ 0, +/* 11d8 - */ 0, +/* 11d9 - _V_66_0F_38_97 */ 0x4114, +/* 11da - */ 0, +/* 11db - */ 0, +/* 11dc - */ 0, +/* 11dd - */ 0, +/* 11de - */ 0, +/* 11df - */ 0, +/* 11e0 - */ 0, +/* 11e1 - */ 0, +/* 11e2 - */ 0, +/* 11e3 - */ 0, +/* 11e4 - */ 0, +/* 11e5 - _V_66_0F_38_98 */ 0x4115, +/* 11e6 - */ 0, +/* 11e7 - */ 0, +/* 11e8 - */ 0, +/* 11e9 - */ 0, +/* 11ea - */ 0, +/* 11eb - */ 0, +/* 11ec - */ 0, +/* 11ed - */ 0, +/* 11ee - */ 0, +/* 11ef - */ 0, +/* 11f0 - */ 0, +/* 11f1 - _V_66_0F_38_99 */ 0x4116, +/* 11f2 - */ 0, +/* 11f3 - */ 0, +/* 11f4 - */ 0, +/* 11f5 - */ 0, +/* 11f6 - */ 0, +/* 11f7 - */ 0, +/* 11f8 - */ 0, +/* 11f9 - */ 0, +/* 11fa - */ 0, +/* 11fb - */ 0, +/* 11fc - */ 0, +/* 11fd - _V_66_0F_38_9A */ 0x4117, +/* 11fe - */ 0, +/* 11ff - */ 0, +/* 1200 - */ 0, +/* 1201 - */ 0, +/* 1202 - */ 0, +/* 1203 - */ 0, +/* 1204 - */ 0, +/* 1205 - */ 0, +/* 1206 - */ 0, +/* 1207 - */ 0, +/* 1208 - */ 0, +/* 1209 - _V_66_0F_38_9B */ 0x4118, +/* 120a - */ 0, +/* 120b - */ 0, +/* 120c - */ 0, +/* 120d - */ 0, +/* 120e - */ 0, +/* 120f - */ 0, +/* 1210 - */ 0, +/* 1211 - */ 0, +/* 1212 - */ 0, +/* 1213 - */ 0, +/* 1214 - */ 0, +/* 1215 - _V_66_0F_38_9C */ 0x4119, +/* 1216 - */ 0, +/* 1217 - */ 0, +/* 1218 - */ 0, +/* 1219 - */ 0, +/* 121a - */ 0, +/* 121b - */ 0, +/* 121c - */ 0, +/* 121d - */ 0, +/* 121e - */ 0, +/* 121f - */ 0, +/* 1220 - */ 0, +/* 1221 - _V_66_0F_38_9D */ 0x411a, +/* 1222 - */ 0, +/* 1223 - */ 0, +/* 1224 - */ 0, +/* 1225 - */ 0, +/* 1226 - */ 0, +/* 1227 - */ 0, +/* 1228 - */ 0, +/* 1229 - */ 0, +/* 122a - */ 0, +/* 122b - */ 0, +/* 122c - */ 0, +/* 122d - _V_66_0F_38_9E */ 0x411b, +/* 122e - */ 0, +/* 122f - */ 0, +/* 1230 - */ 0, +/* 1231 - */ 0, +/* 1232 - */ 0, +/* 1233 - */ 0, +/* 1234 - */ 0, +/* 1235 - */ 0, +/* 1236 - */ 0, +/* 1237 - */ 0, +/* 1238 - */ 0, +/* 1239 - _V_66_0F_38_9F */ 0x411c, +/* 123a - */ 0, +/* 123b - */ 0, +/* 123c - */ 0, +/* 123d - */ 0, +/* 123e - */ 0, +/* 123f - */ 0, +/* 1240 - */ 0, +/* 1241 - */ 0, +/* 1242 - */ 0, +/* 1243 - */ 0, +/* 1244 - */ 0, +/* 1245 - _V_66_0F_38_A6 */ 0x411d, +/* 1246 - */ 0, +/* 1247 - */ 0, +/* 1248 - */ 0, +/* 1249 - */ 0, +/* 124a - */ 0, +/* 124b - */ 0, +/* 124c - */ 0, +/* 124d - */ 0, +/* 124e - */ 0, +/* 124f - */ 0, +/* 1250 - */ 0, +/* 1251 - _V_66_0F_38_A7 */ 0x411e, +/* 1252 - */ 0, +/* 1253 - */ 0, +/* 1254 - */ 0, +/* 1255 - */ 0, +/* 1256 - */ 0, +/* 1257 - */ 0, +/* 1258 - */ 0, +/* 1259 - */ 0, +/* 125a - */ 0, +/* 125b - */ 0, +/* 125c - */ 0, +/* 125d - _V_66_0F_38_A8 */ 0x411f, +/* 125e - */ 0, +/* 125f - */ 0, +/* 1260 - */ 0, +/* 1261 - */ 0, +/* 1262 - */ 0, +/* 1263 - */ 0, +/* 1264 - */ 0, +/* 1265 - */ 0, +/* 1266 - */ 0, +/* 1267 - */ 0, +/* 1268 - */ 0, +/* 1269 - _V_66_0F_38_A9 */ 0x4120, +/* 126a - */ 0, +/* 126b - */ 0, +/* 126c - */ 0, +/* 126d - */ 0, +/* 126e - */ 0, +/* 126f - */ 0, +/* 1270 - */ 0, +/* 1271 - */ 0, +/* 1272 - */ 0, +/* 1273 - */ 0, +/* 1274 - */ 0, +/* 1275 - _V_66_0F_38_AA */ 0x4121, +/* 1276 - */ 0, +/* 1277 - */ 0, +/* 1278 - */ 0, +/* 1279 - */ 0, +/* 127a - */ 0, +/* 127b - */ 0, +/* 127c - */ 0, +/* 127d - */ 0, +/* 127e - */ 0, +/* 127f - */ 0, +/* 1280 - */ 0, +/* 1281 - _V_66_0F_38_AB */ 0x4122, +/* 1282 - */ 0, +/* 1283 - */ 0, +/* 1284 - */ 0, +/* 1285 - */ 0, +/* 1286 - */ 0, +/* 1287 - */ 0, +/* 1288 - */ 0, +/* 1289 - */ 0, +/* 128a - */ 0, +/* 128b - */ 0, +/* 128c - */ 0, +/* 128d - _V_66_0F_38_AC */ 0x4123, +/* 128e - */ 0, +/* 128f - */ 0, +/* 1290 - */ 0, +/* 1291 - */ 0, +/* 1292 - */ 0, +/* 1293 - */ 0, +/* 1294 - */ 0, +/* 1295 - */ 0, +/* 1296 - */ 0, +/* 1297 - */ 0, +/* 1298 - */ 0, +/* 1299 - _V_66_0F_38_AD */ 0x4124, +/* 129a - */ 0, +/* 129b - */ 0, +/* 129c - */ 0, +/* 129d - */ 0, +/* 129e - */ 0, +/* 129f - */ 0, +/* 12a0 - */ 0, +/* 12a1 - */ 0, +/* 12a2 - */ 0, +/* 12a3 - */ 0, +/* 12a4 - */ 0, +/* 12a5 - _V_66_0F_38_AE */ 0x4125, +/* 12a6 - */ 0, +/* 12a7 - */ 0, +/* 12a8 - */ 0, +/* 12a9 - */ 0, +/* 12aa - */ 0, +/* 12ab - */ 0, +/* 12ac - */ 0, +/* 12ad - */ 0, +/* 12ae - */ 0, +/* 12af - */ 0, +/* 12b0 - */ 0, +/* 12b1 - _V_66_0F_38_AF */ 0x4126, +/* 12b2 - */ 0, +/* 12b3 - */ 0, +/* 12b4 - */ 0, +/* 12b5 - */ 0, +/* 12b6 - */ 0, +/* 12b7 - */ 0, +/* 12b8 - */ 0, +/* 12b9 - */ 0, +/* 12ba - */ 0, +/* 12bb - */ 0, +/* 12bc - */ 0, +/* 12bd - _V_66_0F_38_B6 */ 0x4127, +/* 12be - */ 0, +/* 12bf - */ 0, +/* 12c0 - */ 0, +/* 12c1 - */ 0, +/* 12c2 - */ 0, +/* 12c3 - */ 0, +/* 12c4 - */ 0, +/* 12c5 - */ 0, +/* 12c6 - */ 0, +/* 12c7 - */ 0, +/* 12c8 - */ 0, +/* 12c9 - _V_66_0F_38_B7 */ 0x4128, +/* 12ca - */ 0, +/* 12cb - */ 0, +/* 12cc - */ 0, +/* 12cd - */ 0, +/* 12ce - */ 0, +/* 12cf - */ 0, +/* 12d0 - */ 0, +/* 12d1 - */ 0, +/* 12d2 - */ 0, +/* 12d3 - */ 0, +/* 12d4 - */ 0, +/* 12d5 - _V_66_0F_38_B8 */ 0x4129, +/* 12d6 - */ 0, +/* 12d7 - */ 0, +/* 12d8 - */ 0, +/* 12d9 - */ 0, +/* 12da - */ 0, +/* 12db - */ 0, +/* 12dc - */ 0, +/* 12dd - */ 0, +/* 12de - */ 0, +/* 12df - */ 0, +/* 12e0 - */ 0, +/* 12e1 - _V_66_0F_38_B9 */ 0x412a, +/* 12e2 - */ 0, +/* 12e3 - */ 0, +/* 12e4 - */ 0, +/* 12e5 - */ 0, +/* 12e6 - */ 0, +/* 12e7 - */ 0, +/* 12e8 - */ 0, +/* 12e9 - */ 0, +/* 12ea - */ 0, +/* 12eb - */ 0, +/* 12ec - */ 0, +/* 12ed - _V_66_0F_38_BA */ 0x412b, +/* 12ee - */ 0, +/* 12ef - */ 0, +/* 12f0 - */ 0, +/* 12f1 - */ 0, +/* 12f2 - */ 0, +/* 12f3 - */ 0, +/* 12f4 - */ 0, +/* 12f5 - */ 0, +/* 12f6 - */ 0, +/* 12f7 - */ 0, +/* 12f8 - */ 0, +/* 12f9 - _V_66_0F_38_BB */ 0x412c, +/* 12fa - */ 0, +/* 12fb - */ 0, +/* 12fc - */ 0, +/* 12fd - */ 0, +/* 12fe - */ 0, +/* 12ff - */ 0, +/* 1300 - */ 0, +/* 1301 - */ 0, +/* 1302 - */ 0, +/* 1303 - */ 0, +/* 1304 - */ 0, +/* 1305 - _V_66_0F_38_BC */ 0x412d, +/* 1306 - */ 0, +/* 1307 - */ 0, +/* 1308 - */ 0, +/* 1309 - */ 0, +/* 130a - */ 0, +/* 130b - */ 0, +/* 130c - */ 0, +/* 130d - */ 0, +/* 130e - */ 0, +/* 130f - */ 0, +/* 1310 - */ 0, +/* 1311 - _V_66_0F_38_BD */ 0x412e, +/* 1312 - */ 0, +/* 1313 - */ 0, +/* 1314 - */ 0, +/* 1315 - */ 0, +/* 1316 - */ 0, +/* 1317 - */ 0, +/* 1318 - */ 0, +/* 1319 - */ 0, +/* 131a - */ 0, +/* 131b - */ 0, +/* 131c - */ 0, +/* 131d - _V_66_0F_38_BE */ 0x412f, +/* 131e - */ 0, +/* 131f - */ 0, +/* 1320 - */ 0, +/* 1321 - */ 0, +/* 1322 - */ 0, +/* 1323 - */ 0, +/* 1324 - */ 0, +/* 1325 - */ 0, +/* 1326 - */ 0, +/* 1327 - */ 0, +/* 1328 - */ 0, +/* 1329 - _V_66_0F_38_BF */ 0x4130, +/* 132a - */ 0, +/* 132b - */ 0, +/* 132c - */ 0, +/* 132d - */ 0, +/* 132e - */ 0, +/* 132f - */ 0, +/* 1330 - */ 0, +/* 1331 - _66_0F_38_DB */ 0x24b7, +/* 1332 - */ 0, +/* 1333 - */ 0, +/* 1334 - */ 0, +/* 1335 - _V_66_0F_38_DB */ 0x4131, +/* 1336 - */ 0, +/* 1337 - */ 0, +/* 1338 - */ 0, +/* 1339 - */ 0, +/* 133a - */ 0, +/* 133b - */ 0, +/* 133c - */ 0, +/* 133d - _66_0F_38_DC */ 0x24b8, +/* 133e - */ 0, +/* 133f - */ 0, +/* 1340 - */ 0, +/* 1341 - _V_66_0F_38_DC */ 0x4132, +/* 1342 - */ 0, +/* 1343 - */ 0, +/* 1344 - */ 0, +/* 1345 - */ 0, +/* 1346 - */ 0, +/* 1347 - */ 0, +/* 1348 - */ 0, +/* 1349 - _66_0F_38_DD */ 0x24b9, +/* 134a - */ 0, +/* 134b - */ 0, +/* 134c - */ 0, +/* 134d - _V_66_0F_38_DD */ 0x4133, +/* 134e - */ 0, +/* 134f - */ 0, +/* 1350 - */ 0, +/* 1351 - */ 0, +/* 1352 - */ 0, +/* 1353 - */ 0, +/* 1354 - */ 0, +/* 1355 - _66_0F_38_DE */ 0x24ba, +/* 1356 - */ 0, +/* 1357 - */ 0, +/* 1358 - */ 0, +/* 1359 - _V_66_0F_38_DE */ 0x4134, +/* 135a - */ 0, +/* 135b - */ 0, +/* 135c - */ 0, +/* 135d - */ 0, +/* 135e - */ 0, +/* 135f - */ 0, +/* 1360 - */ 0, +/* 1361 - _66_0F_38_DF */ 0x24bb, +/* 1362 - */ 0, +/* 1363 - */ 0, +/* 1364 - */ 0, +/* 1365 - _V_66_0F_38_DF */ 0x4135, +/* 1366 - */ 0, +/* 1367 - */ 0, +/* 1368 - */ 0, +/* 1369 - */ 0, +/* 136a - */ 0, +/* 136b - */ 0, +/* 136c - _0F_38_F0 */ 0x24bc, +/* 136d - */ 0, +/* 136e - */ 0, +/* 136f - _F2_0F_38_F0 */ 0x24bd, +/* 1370 - */ 0, +/* 1371 - */ 0, +/* 1372 - */ 0, +/* 1373 - */ 0, +/* 1374 - */ 0, +/* 1375 - */ 0, +/* 1376 - */ 0, +/* 1377 - */ 0, +/* 1378 - _0F_38_F1 */ 0x24be, +/* 1379 - */ 0, +/* 137a - */ 0, +/* 137b - _F2_0F_38_F1 */ 0x24bf, +/* 137c - */ 0, +/* 137d - */ 0, +/* 137e - */ 0, +/* 137f - */ 0, +/* 1380 - */ 0, +/* 1381 - */ 0, +/* 1382 - */ 0, +/* 1383 - */ 0, +/* 1384 - */ 0, +/* 1385 - */ 0, +/* 1386 - */ 0, +/* 1387 - */ 0, +/* 1388 - */ 0, +/* 1389 - _V_66_0F_3A_04 */ 0x4136, +/* 138a - */ 0, +/* 138b - */ 0, +/* 138c - */ 0, +/* 138d - */ 0, +/* 138e - */ 0, +/* 138f - */ 0, +/* 1390 - */ 0, +/* 1391 - */ 0, +/* 1392 - */ 0, +/* 1393 - */ 0, +/* 1394 - */ 0, +/* 1395 - _V_66_0F_3A_05 */ 0x4137, +/* 1396 - */ 0, +/* 1397 - */ 0, +/* 1398 - */ 0, +/* 1399 - */ 0, +/* 139a - */ 0, +/* 139b - */ 0, +/* 139c - */ 0, +/* 139d - */ 0, +/* 139e - */ 0, +/* 139f - */ 0, +/* 13a0 - */ 0, +/* 13a1 - _V_66_0F_3A_06 */ 0x4138, +/* 13a2 - */ 0, +/* 13a3 - */ 0, +/* 13a4 - */ 0, +/* 13a5 - */ 0, +/* 13a6 - */ 0, +/* 13a7 - */ 0, +/* 13a8 - */ 0, +/* 13a9 - _66_0F_3A_08 */ 0x4139, +/* 13aa - */ 0, +/* 13ab - */ 0, +/* 13ac - */ 0, +/* 13ad - _V_66_0F_3A_08 */ 0x413a, +/* 13ae - */ 0, +/* 13af - */ 0, +/* 13b0 - */ 0, +/* 13b1 - */ 0, +/* 13b2 - */ 0, +/* 13b3 - */ 0, +/* 13b4 - */ 0, +/* 13b5 - _66_0F_3A_09 */ 0x413b, +/* 13b6 - */ 0, +/* 13b7 - */ 0, +/* 13b8 - */ 0, +/* 13b9 - _V_66_0F_3A_09 */ 0x413c, +/* 13ba - */ 0, +/* 13bb - */ 0, +/* 13bc - */ 0, +/* 13bd - */ 0, +/* 13be - */ 0, +/* 13bf - */ 0, +/* 13c0 - */ 0, +/* 13c1 - _66_0F_3A_0A */ 0x413d, +/* 13c2 - */ 0, +/* 13c3 - */ 0, +/* 13c4 - */ 0, +/* 13c5 - _V_66_0F_3A_0A */ 0x413e, +/* 13c6 - */ 0, +/* 13c7 - */ 0, +/* 13c8 - */ 0, +/* 13c9 - */ 0, +/* 13ca - */ 0, +/* 13cb - */ 0, +/* 13cc - */ 0, +/* 13cd - _66_0F_3A_0B */ 0x413f, +/* 13ce - */ 0, +/* 13cf - */ 0, +/* 13d0 - */ 0, +/* 13d1 - _V_66_0F_3A_0B */ 0x4140, +/* 13d2 - */ 0, +/* 13d3 - */ 0, +/* 13d4 - */ 0, +/* 13d5 - */ 0, +/* 13d6 - */ 0, +/* 13d7 - */ 0, +/* 13d8 - */ 0, +/* 13d9 - _66_0F_3A_0C */ 0x4141, +/* 13da - */ 0, +/* 13db - */ 0, +/* 13dc - */ 0, +/* 13dd - _V_66_0F_3A_0C */ 0x4142, +/* 13de - */ 0, +/* 13df - */ 0, +/* 13e0 - */ 0, +/* 13e1 - */ 0, +/* 13e2 - */ 0, +/* 13e3 - */ 0, +/* 13e4 - */ 0, +/* 13e5 - _66_0F_3A_0D */ 0x4143, +/* 13e6 - */ 0, +/* 13e7 - */ 0, +/* 13e8 - */ 0, +/* 13e9 - _V_66_0F_3A_0D */ 0x4144, +/* 13ea - */ 0, +/* 13eb - */ 0, +/* 13ec - */ 0, +/* 13ed - */ 0, +/* 13ee - */ 0, +/* 13ef - */ 0, +/* 13f0 - */ 0, +/* 13f1 - _66_0F_3A_0E */ 0x4145, +/* 13f2 - */ 0, +/* 13f3 - */ 0, +/* 13f4 - */ 0, +/* 13f5 - _V_66_0F_3A_0E */ 0x4146, +/* 13f6 - */ 0, +/* 13f7 - */ 0, +/* 13f8 - */ 0, +/* 13f9 - */ 0, +/* 13fa - */ 0, +/* 13fb - */ 0, +/* 13fc - _0F_3A_0F */ 0x4147, +/* 13fd - _66_0F_3A_0F */ 0x4148, +/* 13fe - */ 0, +/* 13ff - */ 0, +/* 1400 - */ 0, +/* 1401 - _V_66_0F_3A_0F */ 0x4149, +/* 1402 - */ 0, +/* 1403 - */ 0, +/* 1404 - */ 0, +/* 1405 - */ 0, +/* 1406 - */ 0, +/* 1407 - */ 0, +/* 1408 - */ 0, +/* 1409 - _66_0F_3A_14 */ 0x414a, +/* 140a - */ 0, +/* 140b - */ 0, +/* 140c - */ 0, +/* 140d - _V_66_0F_3A_14 */ 0x414b, +/* 140e - */ 0, +/* 140f - */ 0, +/* 1410 - */ 0, +/* 1411 - */ 0, +/* 1412 - */ 0, +/* 1413 - */ 0, +/* 1414 - */ 0, +/* 1415 - _66_0F_3A_15 */ 0x414c, +/* 1416 - */ 0, +/* 1417 - */ 0, +/* 1418 - */ 0, +/* 1419 - _V_66_0F_3A_15 */ 0x414d, +/* 141a - */ 0, +/* 141b - */ 0, +/* 141c - */ 0, +/* 141d - */ 0, +/* 141e - */ 0, +/* 141f - */ 0, +/* 1420 - */ 0, +/* 1421 - _66_0F_3A_16 */ 0x414e, +/* 1422 - */ 0, +/* 1423 - */ 0, +/* 1424 - */ 0, +/* 1425 - _V_66_0F_3A_16 */ 0x414f, +/* 1426 - */ 0, +/* 1427 - */ 0, +/* 1428 - */ 0, +/* 1429 - */ 0, +/* 142a - */ 0, +/* 142b - */ 0, +/* 142c - */ 0, +/* 142d - _66_0F_3A_17 */ 0x4150, +/* 142e - */ 0, +/* 142f - */ 0, +/* 1430 - */ 0, +/* 1431 - _V_66_0F_3A_17 */ 0x4151, +/* 1432 - */ 0, +/* 1433 - */ 0, +/* 1434 - */ 0, +/* 1435 - */ 0, +/* 1436 - */ 0, +/* 1437 - */ 0, +/* 1438 - */ 0, +/* 1439 - */ 0, +/* 143a - */ 0, +/* 143b - */ 0, +/* 143c - */ 0, +/* 143d - _V_66_0F_3A_18 */ 0x4152, +/* 143e - */ 0, +/* 143f - */ 0, +/* 1440 - */ 0, +/* 1441 - */ 0, +/* 1442 - */ 0, +/* 1443 - */ 0, +/* 1444 - */ 0, +/* 1445 - */ 0, +/* 1446 - */ 0, +/* 1447 - */ 0, +/* 1448 - */ 0, +/* 1449 - _V_66_0F_3A_19 */ 0x4153, +/* 144a - */ 0, +/* 144b - */ 0, +/* 144c - */ 0, +/* 144d - */ 0, +/* 144e - */ 0, +/* 144f - */ 0, +/* 1450 - */ 0, +/* 1451 - _66_0F_3A_20 */ 0x4154, +/* 1452 - */ 0, +/* 1453 - */ 0, +/* 1454 - */ 0, +/* 1455 - _V_66_0F_3A_20 */ 0x4155, +/* 1456 - */ 0, +/* 1457 - */ 0, +/* 1458 - */ 0, +/* 1459 - */ 0, +/* 145a - */ 0, +/* 145b - */ 0, +/* 145c - */ 0, +/* 145d - _66_0F_3A_21 */ 0x4156, +/* 145e - */ 0, +/* 145f - */ 0, +/* 1460 - */ 0, +/* 1461 - _V_66_0F_3A_21 */ 0x4157, +/* 1462 - */ 0, +/* 1463 - */ 0, +/* 1464 - */ 0, +/* 1465 - */ 0, +/* 1466 - */ 0, +/* 1467 - */ 0, +/* 1468 - */ 0, +/* 1469 - _66_0F_3A_22 */ 0x4158, +/* 146a - */ 0, +/* 146b - */ 0, +/* 146c - */ 0, +/* 146d - _V_66_0F_3A_22 */ 0x4159, +/* 146e - */ 0, +/* 146f - */ 0, +/* 1470 - */ 0, +/* 1471 - */ 0, +/* 1472 - */ 0, +/* 1473 - */ 0, +/* 1474 - */ 0, +/* 1475 - _66_0F_3A_40 */ 0x415a, +/* 1476 - */ 0, +/* 1477 - */ 0, +/* 1478 - */ 0, +/* 1479 - _V_66_0F_3A_40 */ 0x415b, +/* 147a - */ 0, +/* 147b - */ 0, +/* 147c - */ 0, +/* 147d - */ 0, +/* 147e - */ 0, +/* 147f - */ 0, +/* 1480 - */ 0, +/* 1481 - _66_0F_3A_41 */ 0x415c, +/* 1482 - */ 0, +/* 1483 - */ 0, +/* 1484 - */ 0, +/* 1485 - _V_66_0F_3A_41 */ 0x415d, +/* 1486 - */ 0, +/* 1487 - */ 0, +/* 1488 - */ 0, +/* 1489 - */ 0, +/* 148a - */ 0, +/* 148b - */ 0, +/* 148c - */ 0, +/* 148d - _66_0F_3A_42 */ 0x415e, +/* 148e - */ 0, +/* 148f - */ 0, +/* 1490 - */ 0, +/* 1491 - _V_66_0F_3A_42 */ 0x415f, +/* 1492 - */ 0, +/* 1493 - */ 0, +/* 1494 - */ 0, +/* 1495 - */ 0, +/* 1496 - */ 0, +/* 1497 - */ 0, +/* 1498 - */ 0, +/* 1499 - _66_0F_3A_44 */ 0x4160, +/* 149a - */ 0, +/* 149b - */ 0, +/* 149c - */ 0, +/* 149d - _V_66_0F_3A_44 */ 0x4161, +/* 149e - */ 0, +/* 149f - */ 0, +/* 14a0 - */ 0, +/* 14a1 - */ 0, +/* 14a2 - */ 0, +/* 14a3 - */ 0, +/* 14a4 - */ 0, +/* 14a5 - */ 0, +/* 14a6 - */ 0, +/* 14a7 - */ 0, +/* 14a8 - */ 0, +/* 14a9 - _V_66_0F_3A_4A */ 0x4162, +/* 14aa - */ 0, +/* 14ab - */ 0, +/* 14ac - */ 0, +/* 14ad - */ 0, +/* 14ae - */ 0, +/* 14af - */ 0, +/* 14b0 - */ 0, +/* 14b1 - */ 0, +/* 14b2 - */ 0, +/* 14b3 - */ 0, +/* 14b4 - */ 0, +/* 14b5 - _V_66_0F_3A_4B */ 0x4163, +/* 14b6 - */ 0, +/* 14b7 - */ 0, +/* 14b8 - */ 0, +/* 14b9 - */ 0, +/* 14ba - */ 0, +/* 14bb - */ 0, +/* 14bc - */ 0, +/* 14bd - */ 0, +/* 14be - */ 0, +/* 14bf - */ 0, +/* 14c0 - */ 0, +/* 14c1 - _V_66_0F_3A_4C */ 0x4164, +/* 14c2 - */ 0, +/* 14c3 - */ 0, +/* 14c4 - */ 0, +/* 14c5 - */ 0, +/* 14c6 - */ 0, +/* 14c7 - */ 0, +/* 14c8 - */ 0, +/* 14c9 - _66_0F_3A_60 */ 0x4165, +/* 14ca - */ 0, +/* 14cb - */ 0, +/* 14cc - */ 0, +/* 14cd - _V_66_0F_3A_60 */ 0x4166, +/* 14ce - */ 0, +/* 14cf - */ 0, +/* 14d0 - */ 0, +/* 14d1 - */ 0, +/* 14d2 - */ 0, +/* 14d3 - */ 0, +/* 14d4 - */ 0, +/* 14d5 - _66_0F_3A_61 */ 0x4167, +/* 14d6 - */ 0, +/* 14d7 - */ 0, +/* 14d8 - */ 0, +/* 14d9 - _V_66_0F_3A_61 */ 0x4168, +/* 14da - */ 0, +/* 14db - */ 0, +/* 14dc - */ 0, +/* 14dd - */ 0, +/* 14de - */ 0, +/* 14df - */ 0, +/* 14e0 - */ 0, +/* 14e1 - _66_0F_3A_62 */ 0x4169, +/* 14e2 - */ 0, +/* 14e3 - */ 0, +/* 14e4 - */ 0, +/* 14e5 - _V_66_0F_3A_62 */ 0x416a, +/* 14e6 - */ 0, +/* 14e7 - */ 0, +/* 14e8 - */ 0, +/* 14e9 - */ 0, +/* 14ea - */ 0, +/* 14eb - */ 0, +/* 14ec - */ 0, +/* 14ed - _66_0F_3A_63 */ 0x416b, +/* 14ee - */ 0, +/* 14ef - */ 0, +/* 14f0 - */ 0, +/* 14f1 - _V_66_0F_3A_63 */ 0x416c, +/* 14f2 - */ 0, +/* 14f3 - */ 0, +/* 14f4 - */ 0, +/* 14f5 - */ 0, +/* 14f6 - */ 0, +/* 14f7 - */ 0, +/* 14f8 - */ 0, +/* 14f9 - _66_0F_3A_DF */ 0x416d, +/* 14fa - */ 0, +/* 14fb - */ 0, +/* 14fc - */ 0, +/* 14fd - _V_66_0F_3A_DF */ 0x416e, +/* 14fe - */ 0, +/* 14ff - */ 0, +/* 1500 - */ 0, +/* 1501 - */ 0, +/* 1502 - */ 0, +/* 1503 - */ 0, +/* 1504 - _0F_71_02 */ 0x24c0, +/* 1505 - _66_0F_71_02 */ 0x24c1, +/* 1506 - */ 0, +/* 1507 - */ 0, +/* 1508 - */ 0, +/* 1509 - _V_66_0F_71_02 */ 0x416f, +/* 150a - */ 0, +/* 150b - */ 0, +/* 150c - */ 0, +/* 150d - */ 0, +/* 150e - */ 0, +/* 150f - */ 0, +/* 1510 - _0F_71_04 */ 0x24c2, +/* 1511 - _66_0F_71_04 */ 0x24c3, +/* 1512 - */ 0, +/* 1513 - */ 0, +/* 1514 - */ 0, +/* 1515 - _V_66_0F_71_04 */ 0x4170, +/* 1516 - */ 0, +/* 1517 - */ 0, +/* 1518 - */ 0, +/* 1519 - */ 0, +/* 151a - */ 0, +/* 151b - */ 0, +/* 151c - _0F_71_06 */ 0x24c4, +/* 151d - _66_0F_71_06 */ 0x24c5, +/* 151e - */ 0, +/* 151f - */ 0, +/* 1520 - */ 0, +/* 1521 - _V_66_0F_71_06 */ 0x4171, +/* 1522 - */ 0, +/* 1523 - */ 0, +/* 1524 - */ 0, +/* 1525 - */ 0, +/* 1526 - */ 0, +/* 1527 - */ 0, +/* 1528 - _0F_72_02 */ 0x24c6, +/* 1529 - _66_0F_72_02 */ 0x24c7, +/* 152a - */ 0, +/* 152b - */ 0, +/* 152c - */ 0, +/* 152d - _V_66_0F_72_02 */ 0x4172, +/* 152e - */ 0, +/* 152f - */ 0, +/* 1530 - */ 0, +/* 1531 - */ 0, +/* 1532 - */ 0, +/* 1533 - */ 0, +/* 1534 - _0F_72_04 */ 0x24c8, +/* 1535 - _66_0F_72_04 */ 0x24c9, +/* 1536 - */ 0, +/* 1537 - */ 0, +/* 1538 - */ 0, +/* 1539 - _V_66_0F_72_04 */ 0x4173, +/* 153a - */ 0, +/* 153b - */ 0, +/* 153c - */ 0, +/* 153d - */ 0, +/* 153e - */ 0, +/* 153f - */ 0, +/* 1540 - _0F_72_06 */ 0x24ca, +/* 1541 - _66_0F_72_06 */ 0x24cb, +/* 1542 - */ 0, +/* 1543 - */ 0, +/* 1544 - */ 0, +/* 1545 - _V_66_0F_72_06 */ 0x4174, +/* 1546 - */ 0, +/* 1547 - */ 0, +/* 1548 - */ 0, +/* 1549 - */ 0, +/* 154a - */ 0, +/* 154b - */ 0, +/* 154c - _0F_73_02 */ 0x24cc, +/* 154d - _66_0F_73_02 */ 0x24cd, +/* 154e - */ 0, +/* 154f - */ 0, +/* 1550 - */ 0, +/* 1551 - _V_66_0F_73_02 */ 0x4175, +/* 1552 - */ 0, +/* 1553 - */ 0, +/* 1554 - */ 0, +/* 1555 - */ 0, +/* 1556 - */ 0, +/* 1557 - */ 0, +/* 1558 - */ 0, +/* 1559 - _66_0F_73_03 */ 0x24ce, +/* 155a - */ 0, +/* 155b - */ 0, +/* 155c - */ 0, +/* 155d - _V_66_0F_73_03 */ 0x4176, +/* 155e - */ 0, +/* 155f - */ 0, +/* 1560 - */ 0, +/* 1561 - */ 0, +/* 1562 - */ 0, +/* 1563 - */ 0, +/* 1564 - _0F_73_06 */ 0x24cf, +/* 1565 - _66_0F_73_06 */ 0x24d0, +/* 1566 - */ 0, +/* 1567 - */ 0, +/* 1568 - */ 0, +/* 1569 - _V_66_0F_73_06 */ 0x4177, +/* 156a - */ 0, +/* 156b - */ 0, +/* 156c - */ 0, +/* 156d - */ 0, +/* 156e - */ 0, +/* 156f - */ 0, +/* 1570 - */ 0, +/* 1571 - _66_0F_73_07 */ 0x24d1, +/* 1572 - */ 0, +/* 1573 - */ 0, +/* 1574 - */ 0, +/* 1575 - _V_66_0F_73_07 */ 0x4178, +/* 1576 - */ 0, +/* 1577 - */ 0, +/* 1578 - */ 0, +/* 1579 - */ 0, +/* 157a - */ 0, +/* 157b - */ 0, +/* 157c - _0F_AE_00 */ 0x4179, +/* 157d - */ 0, +/* 157e - _F3_0F_AE_00 */ 0x24d2, +/* 157f - */ 0, +/* 1580 - */ 0, +/* 1581 - */ 0, +/* 1582 - */ 0, +/* 1583 - */ 0, +/* 1584 - */ 0, +/* 1585 - */ 0, +/* 1586 - */ 0, +/* 1587 - */ 0, +/* 1588 - _0F_AE_01 */ 0x417a, +/* 1589 - */ 0, +/* 158a - _F3_0F_AE_01 */ 0x24d3, +/* 158b - */ 0, +/* 158c - */ 0, +/* 158d - */ 0, +/* 158e - */ 0, +/* 158f - */ 0, +/* 1590 - */ 0, +/* 1591 - */ 0, +/* 1592 - */ 0, +/* 1593 - */ 0, +/* 1594 - _0F_AE_02 */ 0x24d4, +/* 1595 - */ 0, +/* 1596 - _F3_0F_AE_02 */ 0x24d5, +/* 1597 - */ 0, +/* 1598 - _V_0F_AE_02 */ 0x417b, +/* 1599 - */ 0, +/* 159a - */ 0, +/* 159b - */ 0, +/* 159c - */ 0, +/* 159d - */ 0, +/* 159e - */ 0, +/* 159f - */ 0, +/* 15a0 - _0F_AE_03 */ 0x24d6, +/* 15a1 - */ 0, +/* 15a2 - _F3_0F_AE_03 */ 0x24d7, +/* 15a3 - */ 0, +/* 15a4 - _V_0F_AE_03 */ 0x417c, +/* 15a5 - */ 0, +/* 15a6 - */ 0, +/* 15a7 - */ 0, +/* 15a8 - */ 0, +/* 15a9 - */ 0, +/* 15aa - */ 0, +/* 15ab - */ 0, +/* 15ac - _0F_C7_06 */ 0x417d, +/* 15ad - _66_0F_C7_06 */ 0x24d8, +/* 15ae - _F3_0F_C7_06 */ 0x24d9, +/* 15af - */ 0, +/* 15b0 - */ 0, +/* 15b1 - */ 0, +/* 15b2 - */ 0, +/* 15b3 - */ 0, +/* 15b4 - */ 0, +/* 15b5 - */ 0, +/* 15b6 - */ 0, +/* 15b7 - */ 0 +}; + +uint16_t CmpMnemonicOffsets[8] = { +0, 9, 18, 27, 39, 49, 59, 69 +}; +uint16_t VCmpMnemonicOffsets[32] = { +0, 10, 20, 30, 43, 54, 65, 76, 87, 100, 111, 122, 135, 149, 159, 169, 181, +194, 207, 220, 235, 249, 263, 277, 290, 303, 317, 331, 347, 361, 374, 387 +}; diff --git a/distorm3.2-package/src/insts.h b/distorm3.2-package/src/insts.h new file mode 100644 index 0000000..0cdf2ef --- /dev/null +++ b/distorm3.2-package/src/insts.h @@ -0,0 +1,47 @@ +/* +insts.h + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2012 Gil Dabah + +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 +*/ + + +#ifndef INSTS_H +#define INSTS_H + +#include "instructions.h" + + +/* Flags Table */ +extern _iflags FlagsTable[]; + +/* Root Trie DB */ +extern _InstInfo InstInfos[]; +extern _InstInfoEx InstInfosEx[]; +extern _InstNode InstructionsTree[]; + +/* 3DNow! Trie DB */ +extern _InstNode Table_0F_0F; +/* AVX related: */ +extern _InstNode Table_0F, Table_0F_38, Table_0F_3A; + +/* Helper tables for pesudo compare mnemonics. */ +extern uint16_t CmpMnemonicOffsets[8]; /* SSE */ +extern uint16_t VCmpMnemonicOffsets[32]; /* AVX */ + +#endif /* INSTS_H */ diff --git a/distorm3.2-package/src/mnemonics.c b/distorm3.2-package/src/mnemonics.c new file mode 100644 index 0000000..0c39a21 --- /dev/null +++ b/distorm3.2-package/src/mnemonics.c @@ -0,0 +1,294 @@ +/* +mnemonics.c + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2012 Gil Dabah + +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 +*/ + + +#include "../include/mnemonics.h" + +#ifndef DISTORM_LIGHT + +const unsigned char _MNEMONICS[] = +"\x09" "UNDEFINED\0" "\x03" "ADD\0" "\x04" "PUSH\0" "\x03" "POP\0" "\x02" "OR\0" \ +"\x03" "ADC\0" "\x03" "SBB\0" "\x03" "AND\0" "\x03" "DAA\0" "\x03" "SUB\0" \ +"\x03" "DAS\0" "\x03" "XOR\0" "\x03" "AAA\0" "\x03" "CMP\0" "\x03" "AAS\0" \ +"\x03" "INC\0" "\x03" "DEC\0" "\x05" "PUSHA\0" "\x04" "POPA\0" "\x05" "BOUND\0" \ +"\x04" "ARPL\0" "\x04" "IMUL\0" "\x03" "INS\0" "\x04" "OUTS\0" "\x02" "JO\0" \ +"\x03" "JNO\0" "\x02" "JB\0" "\x03" "JAE\0" "\x02" "JZ\0" "\x03" "JNZ\0" "\x03" "JBE\0" \ +"\x02" "JA\0" "\x02" "JS\0" "\x03" "JNS\0" "\x02" "JP\0" "\x03" "JNP\0" "\x02" "JL\0" \ +"\x03" "JGE\0" "\x03" "JLE\0" "\x02" "JG\0" "\x04" "TEST\0" "\x04" "XCHG\0" \ +"\x03" "MOV\0" "\x03" "LEA\0" "\x03" "CBW\0" "\x04" "CWDE\0" "\x04" "CDQE\0" \ +"\x03" "CWD\0" "\x03" "CDQ\0" "\x03" "CQO\0" "\x08" "CALL FAR\0" "\x05" "PUSHF\0" \ +"\x04" "POPF\0" "\x04" "SAHF\0" "\x04" "LAHF\0" "\x04" "MOVS\0" "\x04" "CMPS\0" \ +"\x04" "STOS\0" "\x04" "LODS\0" "\x04" "SCAS\0" "\x03" "RET\0" "\x03" "LES\0" \ +"\x03" "LDS\0" "\x05" "ENTER\0" "\x05" "LEAVE\0" "\x04" "RETF\0" "\x05" "INT 3\0" \ +"\x03" "INT\0" "\x04" "INTO\0" "\x04" "IRET\0" "\x03" "AAM\0" "\x03" "AAD\0" \ +"\x04" "SALC\0" "\x04" "XLAT\0" "\x06" "LOOPNZ\0" "\x05" "LOOPZ\0" "\x04" "LOOP\0" \ +"\x04" "JCXZ\0" "\x05" "JECXZ\0" "\x05" "JRCXZ\0" "\x02" "IN\0" "\x03" "OUT\0" \ +"\x04" "CALL\0" "\x03" "JMP\0" "\x07" "JMP FAR\0" "\x04" "INT1\0" "\x03" "HLT\0" \ +"\x03" "CMC\0" "\x03" "CLC\0" "\x03" "STC\0" "\x03" "CLI\0" "\x03" "STI\0" \ +"\x03" "CLD\0" "\x03" "STD\0" "\x03" "LAR\0" "\x03" "LSL\0" "\x07" "SYSCALL\0" \ +"\x04" "CLTS\0" "\x06" "SYSRET\0" "\x04" "INVD\0" "\x06" "WBINVD\0" "\x03" "UD2\0" \ +"\x05" "FEMMS\0" "\x03" "NOP\0" "\x05" "WRMSR\0" "\x05" "RDTSC\0" "\x05" "RDMSR\0" \ +"\x05" "RDPMC\0" "\x08" "SYSENTER\0" "\x07" "SYSEXIT\0" "\x06" "GETSEC\0" "\x05" "CMOVO\0" \ +"\x06" "CMOVNO\0" "\x05" "CMOVB\0" "\x06" "CMOVAE\0" "\x05" "CMOVZ\0" "\x06" "CMOVNZ\0" \ +"\x06" "CMOVBE\0" "\x05" "CMOVA\0" "\x05" "CMOVS\0" "\x06" "CMOVNS\0" "\x05" "CMOVP\0" \ +"\x06" "CMOVNP\0" "\x05" "CMOVL\0" "\x06" "CMOVGE\0" "\x06" "CMOVLE\0" "\x05" "CMOVG\0" \ +"\x04" "SETO\0" "\x05" "SETNO\0" "\x04" "SETB\0" "\x05" "SETAE\0" "\x04" "SETZ\0" \ +"\x05" "SETNZ\0" "\x05" "SETBE\0" "\x04" "SETA\0" "\x04" "SETS\0" "\x05" "SETNS\0" \ +"\x04" "SETP\0" "\x05" "SETNP\0" "\x04" "SETL\0" "\x05" "SETGE\0" "\x05" "SETLE\0" \ +"\x04" "SETG\0" "\x05" "CPUID\0" "\x02" "BT\0" "\x04" "SHLD\0" "\x03" "RSM\0" \ +"\x03" "BTS\0" "\x04" "SHRD\0" "\x07" "CMPXCHG\0" "\x03" "LSS\0" "\x03" "BTR\0" \ +"\x03" "LFS\0" "\x03" "LGS\0" "\x05" "MOVZX\0" "\x03" "BTC\0" "\x05" "MOVSX\0" \ +"\x04" "XADD\0" "\x06" "MOVNTI\0" "\x05" "BSWAP\0" "\x03" "ROL\0" "\x03" "ROR\0" \ +"\x03" "RCL\0" "\x03" "RCR\0" "\x03" "SHL\0" "\x03" "SHR\0" "\x03" "SAL\0" \ +"\x03" "SAR\0" "\x04" "FADD\0" "\x04" "FMUL\0" "\x04" "FCOM\0" "\x05" "FCOMP\0" \ +"\x04" "FSUB\0" "\x05" "FSUBR\0" "\x04" "FDIV\0" "\x05" "FDIVR\0" "\x03" "FLD\0" \ +"\x03" "FST\0" "\x04" "FSTP\0" "\x06" "FLDENV\0" "\x05" "FLDCW\0" "\x04" "FXCH\0" \ +"\x04" "FNOP\0" "\x04" "FCHS\0" "\x04" "FABS\0" "\x04" "FTST\0" "\x04" "FXAM\0" \ +"\x04" "FLD1\0" "\x06" "FLDL2T\0" "\x06" "FLDL2E\0" "\x05" "FLDPI\0" "\x06" "FLDLG2\0" \ +"\x06" "FLDLN2\0" "\x04" "FLDZ\0" "\x05" "F2XM1\0" "\x05" "FYL2X\0" "\x05" "FPTAN\0" \ +"\x06" "FPATAN\0" "\x07" "FXTRACT\0" "\x06" "FPREM1\0" "\x07" "FDECSTP\0" "\x07" "FINCSTP\0" \ +"\x05" "FPREM\0" "\x07" "FYL2XP1\0" "\x05" "FSQRT\0" "\x07" "FSINCOS\0" "\x07" "FRNDINT\0" \ +"\x06" "FSCALE\0" "\x04" "FSIN\0" "\x04" "FCOS\0" "\x05" "FIADD\0" "\x05" "FIMUL\0" \ +"\x05" "FICOM\0" "\x06" "FICOMP\0" "\x05" "FISUB\0" "\x06" "FISUBR\0" "\x05" "FIDIV\0" \ +"\x06" "FIDIVR\0" "\x06" "FCMOVB\0" "\x06" "FCMOVE\0" "\x07" "FCMOVBE\0" "\x06" "FCMOVU\0" \ +"\x07" "FUCOMPP\0" "\x04" "FILD\0" "\x06" "FISTTP\0" "\x04" "FIST\0" "\x05" "FISTP\0" \ +"\x07" "FCMOVNB\0" "\x07" "FCMOVNE\0" "\x08" "FCMOVNBE\0" "\x07" "FCMOVNU\0" \ +"\x04" "FENI\0" "\x06" "FEDISI\0" "\x06" "FSETPM\0" "\x06" "FUCOMI\0" "\x05" "FCOMI\0" \ +"\x06" "FRSTOR\0" "\x05" "FFREE\0" "\x05" "FUCOM\0" "\x06" "FUCOMP\0" "\x05" "FADDP\0" \ +"\x05" "FMULP\0" "\x06" "FCOMPP\0" "\x06" "FSUBRP\0" "\x05" "FSUBP\0" "\x06" "FDIVRP\0" \ +"\x05" "FDIVP\0" "\x04" "FBLD\0" "\x05" "FBSTP\0" "\x07" "FUCOMIP\0" "\x06" "FCOMIP\0" \ +"\x03" "NOT\0" "\x03" "NEG\0" "\x03" "MUL\0" "\x03" "DIV\0" "\x04" "IDIV\0" \ +"\x04" "SLDT\0" "\x03" "STR\0" "\x04" "LLDT\0" "\x03" "LTR\0" "\x04" "VERR\0" \ +"\x04" "VERW\0" "\x04" "SGDT\0" "\x04" "SIDT\0" "\x04" "LGDT\0" "\x04" "LIDT\0" \ +"\x04" "SMSW\0" "\x04" "LMSW\0" "\x06" "INVLPG\0" "\x06" "VMCALL\0" "\x08" "VMLAUNCH\0" \ +"\x08" "VMRESUME\0" "\x06" "VMXOFF\0" "\x07" "MONITOR\0" "\x05" "MWAIT\0" "\x06" "XGETBV\0" \ +"\x06" "XSETBV\0" "\x06" "VMFUNC\0" "\x05" "VMRUN\0" "\x07" "VMMCALL\0" "\x06" "VMLOAD\0" \ +"\x06" "VMSAVE\0" "\x04" "STGI\0" "\x04" "CLGI\0" "\x06" "SKINIT\0" "\x07" "INVLPGA\0" \ +"\x06" "SWAPGS\0" "\x06" "RDTSCP\0" "\x08" "PREFETCH\0" "\x09" "PREFETCHW\0" \ +"\x05" "PI2FW\0" "\x05" "PI2FD\0" "\x05" "PF2IW\0" "\x05" "PF2ID\0" "\x06" "PFNACC\0" \ +"\x07" "PFPNACC\0" "\x07" "PFCMPGE\0" "\x05" "PFMIN\0" "\x05" "PFRCP\0" "\x07" "PFRSQRT\0" \ +"\x05" "PFSUB\0" "\x05" "PFADD\0" "\x07" "PFCMPGT\0" "\x05" "PFMAX\0" "\x08" "PFRCPIT1\0" \ +"\x08" "PFRSQIT1\0" "\x06" "PFSUBR\0" "\x05" "PFACC\0" "\x07" "PFCMPEQ\0" "\x05" "PFMUL\0" \ +"\x08" "PFRCPIT2\0" "\x07" "PMULHRW\0" "\x06" "PSWAPD\0" "\x07" "PAVGUSB\0" \ +"\x06" "MOVUPS\0" "\x06" "MOVUPD\0" "\x05" "MOVSS\0" "\x05" "MOVSD\0" "\x07" "VMOVUPS\0" \ +"\x07" "VMOVUPD\0" "\x06" "VMOVSS\0" "\x06" "VMOVSD\0" "\x07" "MOVHLPS\0" "\x06" "MOVLPS\0" \ +"\x06" "MOVLPD\0" "\x08" "MOVSLDUP\0" "\x07" "MOVDDUP\0" "\x08" "VMOVHLPS\0" \ +"\x07" "VMOVLPS\0" "\x07" "VMOVLPD\0" "\x09" "VMOVSLDUP\0" "\x08" "VMOVDDUP\0" \ +"\x08" "UNPCKLPS\0" "\x08" "UNPCKLPD\0" "\x09" "VUNPCKLPS\0" "\x09" "VUNPCKLPD\0" \ +"\x08" "UNPCKHPS\0" "\x08" "UNPCKHPD\0" "\x09" "VUNPCKHPS\0" "\x09" "VUNPCKHPD\0" \ +"\x07" "MOVLHPS\0" "\x06" "MOVHPS\0" "\x06" "MOVHPD\0" "\x08" "MOVSHDUP\0" \ +"\x08" "VMOVLHPS\0" "\x07" "VMOVHPS\0" "\x07" "VMOVHPD\0" "\x09" "VMOVSHDUP\0" \ +"\x0b" "PREFETCHNTA\0" "\x0a" "PREFETCHT0\0" "\x0a" "PREFETCHT1\0" "\x0a" "PREFETCHT2\0" \ +"\x06" "MOVAPS\0" "\x06" "MOVAPD\0" "\x07" "VMOVAPS\0" "\x07" "VMOVAPD\0" "\x08" "CVTPI2PS\0" \ +"\x08" "CVTPI2PD\0" "\x08" "CVTSI2SS\0" "\x08" "CVTSI2SD\0" "\x09" "VCVTSI2SS\0" \ +"\x09" "VCVTSI2SD\0" "\x07" "MOVNTPS\0" "\x07" "MOVNTPD\0" "\x07" "MOVNTSS\0" \ +"\x07" "MOVNTSD\0" "\x08" "VMOVNTPS\0" "\x08" "VMOVNTPD\0" "\x09" "CVTTPS2PI\0" \ +"\x09" "CVTTPD2PI\0" "\x09" "CVTTSS2SI\0" "\x09" "CVTTSD2SI\0" "\x0a" "VCVTTSS2SI\0" \ +"\x0a" "VCVTTSD2SI\0" "\x08" "CVTPS2PI\0" "\x08" "CVTPD2PI\0" "\x08" "CVTSS2SI\0" \ +"\x08" "CVTSD2SI\0" "\x09" "VCVTSS2SI\0" "\x09" "VCVTSD2SI\0" "\x07" "UCOMISS\0" \ +"\x07" "UCOMISD\0" "\x08" "VUCOMISS\0" "\x08" "VUCOMISD\0" "\x06" "COMISS\0" \ +"\x06" "COMISD\0" "\x07" "VCOMISS\0" "\x07" "VCOMISD\0" "\x08" "MOVMSKPS\0" \ +"\x08" "MOVMSKPD\0" "\x09" "VMOVMSKPS\0" "\x09" "VMOVMSKPD\0" "\x06" "SQRTPS\0" \ +"\x06" "SQRTPD\0" "\x06" "SQRTSS\0" "\x06" "SQRTSD\0" "\x07" "VSQRTPS\0" "\x07" "VSQRTPD\0" \ +"\x07" "VSQRTSS\0" "\x07" "VSQRTSD\0" "\x07" "RSQRTPS\0" "\x07" "RSQRTSS\0" \ +"\x08" "VRSQRTPS\0" "\x08" "VRSQRTSS\0" "\x05" "RCPPS\0" "\x05" "RCPSS\0" "\x06" "VRCPPS\0" \ +"\x06" "VRCPSS\0" "\x05" "ANDPS\0" "\x05" "ANDPD\0" "\x06" "VANDPS\0" "\x06" "VANDPD\0" \ +"\x06" "ANDNPS\0" "\x06" "ANDNPD\0" "\x07" "VANDNPS\0" "\x07" "VANDNPD\0" "\x04" "ORPS\0" \ +"\x04" "ORPD\0" "\x05" "VORPS\0" "\x05" "VORPD\0" "\x05" "XORPS\0" "\x05" "XORPD\0" \ +"\x06" "VXORPS\0" "\x06" "VXORPD\0" "\x05" "ADDPS\0" "\x05" "ADDPD\0" "\x05" "ADDSS\0" \ +"\x05" "ADDSD\0" "\x06" "VADDPS\0" "\x06" "VADDPD\0" "\x06" "VADDSS\0" "\x06" "VADDSD\0" \ +"\x05" "MULPS\0" "\x05" "MULPD\0" "\x05" "MULSS\0" "\x05" "MULSD\0" "\x06" "VMULPS\0" \ +"\x06" "VMULPD\0" "\x06" "VMULSS\0" "\x06" "VMULSD\0" "\x08" "CVTPS2PD\0" "\x08" "CVTPD2PS\0" \ +"\x08" "CVTSS2SD\0" "\x08" "CVTSD2SS\0" "\x09" "VCVTPS2PD\0" "\x09" "VCVTPD2PS\0" \ +"\x09" "VCVTSS2SD\0" "\x09" "VCVTSD2SS\0" "\x08" "CVTDQ2PS\0" "\x08" "CVTPS2DQ\0" \ +"\x09" "CVTTPS2DQ\0" "\x09" "VCVTDQ2PS\0" "\x09" "VCVTPS2DQ\0" "\x0a" "VCVTTPS2DQ\0" \ +"\x05" "SUBPS\0" "\x05" "SUBPD\0" "\x05" "SUBSS\0" "\x05" "SUBSD\0" "\x06" "VSUBPS\0" \ +"\x06" "VSUBPD\0" "\x06" "VSUBSS\0" "\x06" "VSUBSD\0" "\x05" "MINPS\0" "\x05" "MINPD\0" \ +"\x05" "MINSS\0" "\x05" "MINSD\0" "\x06" "VMINPS\0" "\x06" "VMINPD\0" "\x06" "VMINSS\0" \ +"\x06" "VMINSD\0" "\x05" "DIVPS\0" "\x05" "DIVPD\0" "\x05" "DIVSS\0" "\x05" "DIVSD\0" \ +"\x06" "VDIVPS\0" "\x06" "VDIVPD\0" "\x06" "VDIVSS\0" "\x06" "VDIVSD\0" "\x05" "MAXPS\0" \ +"\x05" "MAXPD\0" "\x05" "MAXSS\0" "\x05" "MAXSD\0" "\x06" "VMAXPS\0" "\x06" "VMAXPD\0" \ +"\x06" "VMAXSS\0" "\x06" "VMAXSD\0" "\x09" "PUNPCKLBW\0" "\x0a" "VPUNPCKLBW\0" \ +"\x09" "PUNPCKLWD\0" "\x0a" "VPUNPCKLWD\0" "\x09" "PUNPCKLDQ\0" "\x0a" "VPUNPCKLDQ\0" \ +"\x08" "PACKSSWB\0" "\x09" "VPACKSSWB\0" "\x07" "PCMPGTB\0" "\x08" "VPCMPGTB\0" \ +"\x07" "PCMPGTW\0" "\x08" "VPCMPGTW\0" "\x07" "PCMPGTD\0" "\x08" "VPCMPGTD\0" \ +"\x08" "PACKUSWB\0" "\x09" "VPACKUSWB\0" "\x09" "PUNPCKHBW\0" "\x0a" "VPUNPCKHBW\0" \ +"\x09" "PUNPCKHWD\0" "\x0a" "VPUNPCKHWD\0" "\x09" "PUNPCKHDQ\0" "\x0a" "VPUNPCKHDQ\0" \ +"\x08" "PACKSSDW\0" "\x09" "VPACKSSDW\0" "\x0a" "PUNPCKLQDQ\0" "\x0b" "VPUNPCKLQDQ\0" \ +"\x0a" "PUNPCKHQDQ\0" "\x0b" "VPUNPCKHQDQ\0" "\x04" "MOVD\0" "\x04" "MOVQ\0" \ +"\x05" "VMOVD\0" "\x05" "VMOVQ\0" "\x06" "MOVDQA\0" "\x06" "MOVDQU\0" "\x07" "VMOVDQA\0" \ +"\x07" "VMOVDQU\0" "\x06" "PSHUFW\0" "\x06" "PSHUFD\0" "\x07" "PSHUFHW\0" "\x07" "PSHUFLW\0" \ +"\x07" "VPSHUFD\0" "\x08" "VPSHUFHW\0" "\x08" "VPSHUFLW\0" "\x07" "PCMPEQB\0" \ +"\x08" "VPCMPEQB\0" "\x07" "PCMPEQW\0" "\x08" "VPCMPEQW\0" "\x07" "PCMPEQD\0" \ +"\x08" "VPCMPEQD\0" "\x04" "EMMS\0" "\x0a" "VZEROUPPER\0" "\x08" "VZEROALL\0" \ +"\x06" "VMREAD\0" "\x05" "EXTRQ\0" "\x07" "INSERTQ\0" "\x07" "VMWRITE\0" "\x08" "CVTPH2PS\0" \ +"\x08" "CVTPS2PH\0" "\x06" "HADDPD\0" "\x06" "HADDPS\0" "\x07" "VHADDPD\0" \ +"\x07" "VHADDPS\0" "\x06" "HSUBPD\0" "\x06" "HSUBPS\0" "\x07" "VHSUBPD\0" "\x07" "VHSUBPS\0" \ +"\x05" "XSAVE\0" "\x07" "XSAVE64\0" "\x06" "LFENCE\0" "\x06" "XRSTOR\0" "\x08" "XRSTOR64\0" \ +"\x06" "MFENCE\0" "\x08" "XSAVEOPT\0" "\x0a" "XSAVEOPT64\0" "\x06" "SFENCE\0" \ +"\x07" "CLFLUSH\0" "\x06" "POPCNT\0" "\x03" "BSF\0" "\x05" "TZCNT\0" "\x03" "BSR\0" \ +"\x05" "LZCNT\0" "\x07" "CMPEQPS\0" "\x07" "CMPLTPS\0" "\x07" "CMPLEPS\0" "\x0a" "CMPUNORDPS\0" \ +"\x08" "CMPNEQPS\0" "\x08" "CMPNLTPS\0" "\x08" "CMPNLEPS\0" "\x08" "CMPORDPS\0" \ +"\x07" "CMPEQPD\0" "\x07" "CMPLTPD\0" "\x07" "CMPLEPD\0" "\x0a" "CMPUNORDPD\0" \ +"\x08" "CMPNEQPD\0" "\x08" "CMPNLTPD\0" "\x08" "CMPNLEPD\0" "\x08" "CMPORDPD\0" \ +"\x07" "CMPEQSS\0" "\x07" "CMPLTSS\0" "\x07" "CMPLESS\0" "\x0a" "CMPUNORDSS\0" \ +"\x08" "CMPNEQSS\0" "\x08" "CMPNLTSS\0" "\x08" "CMPNLESS\0" "\x08" "CMPORDSS\0" \ +"\x07" "CMPEQSD\0" "\x07" "CMPLTSD\0" "\x07" "CMPLESD\0" "\x0a" "CMPUNORDSD\0" \ +"\x08" "CMPNEQSD\0" "\x08" "CMPNLTSD\0" "\x08" "CMPNLESD\0" "\x08" "CMPORDSD\0" \ +"\x08" "VCMPEQPS\0" "\x08" "VCMPLTPS\0" "\x08" "VCMPLEPS\0" "\x0b" "VCMPUNORDPS\0" \ +"\x09" "VCMPNEQPS\0" "\x09" "VCMPNLTPS\0" "\x09" "VCMPNLEPS\0" "\x09" "VCMPORDPS\0" \ +"\x0b" "VCMPEQ_UQPS\0" "\x09" "VCMPNGEPS\0" "\x09" "VCMPNGTPS\0" "\x0b" "VCMPFALSEPS\0" \ +"\x0c" "VCMPNEQ_OQPS\0" "\x08" "VCMPGEPS\0" "\x08" "VCMPGTPS\0" "\x0a" "VCMPTRUEPS\0" \ +"\x0b" "VCMPEQ_OSPS\0" "\x0b" "VCMPLT_OQPS\0" "\x0b" "VCMPLE_OQPS\0" "\x0d" "VCMPUNORD_SPS\0" \ +"\x0c" "VCMPNEQ_USPS\0" "\x0c" "VCMPNLT_UQPS\0" "\x0c" "VCMPNLE_UQPS\0" "\x0b" "VCMPORD_SPS\0" \ +"\x0b" "VCMPEQ_USPS\0" "\x0c" "VCMPNGE_UQPS\0" "\x0c" "VCMPNGT_UQPS\0" "\x0e" "VCMPFALSE_OSPS\0" \ +"\x0c" "VCMPNEQ_OSPS\0" "\x0b" "VCMPGE_OQPS\0" "\x0b" "VCMPGT_OQPS\0" "\x0d" "VCMPTRUE_USPS\0" \ +"\x08" "VCMPEQPD\0" "\x08" "VCMPLTPD\0" "\x08" "VCMPLEPD\0" "\x0b" "VCMPUNORDPD\0" \ +"\x09" "VCMPNEQPD\0" "\x09" "VCMPNLTPD\0" "\x09" "VCMPNLEPD\0" "\x09" "VCMPORDPD\0" \ +"\x0b" "VCMPEQ_UQPD\0" "\x09" "VCMPNGEPD\0" "\x09" "VCMPNGTPD\0" "\x0b" "VCMPFALSEPD\0" \ +"\x0c" "VCMPNEQ_OQPD\0" "\x08" "VCMPGEPD\0" "\x08" "VCMPGTPD\0" "\x0a" "VCMPTRUEPD\0" \ +"\x0b" "VCMPEQ_OSPD\0" "\x0b" "VCMPLT_OQPD\0" "\x0b" "VCMPLE_OQPD\0" "\x0d" "VCMPUNORD_SPD\0" \ +"\x0c" "VCMPNEQ_USPD\0" "\x0c" "VCMPNLT_UQPD\0" "\x0c" "VCMPNLE_UQPD\0" "\x0b" "VCMPORD_SPD\0" \ +"\x0b" "VCMPEQ_USPD\0" "\x0c" "VCMPNGE_UQPD\0" "\x0c" "VCMPNGT_UQPD\0" "\x0e" "VCMPFALSE_OSPD\0" \ +"\x0c" "VCMPNEQ_OSPD\0" "\x0b" "VCMPGE_OQPD\0" "\x0b" "VCMPGT_OQPD\0" "\x0d" "VCMPTRUE_USPD\0" \ +"\x08" "VCMPEQSS\0" "\x08" "VCMPLTSS\0" "\x08" "VCMPLESS\0" "\x0b" "VCMPUNORDSS\0" \ +"\x09" "VCMPNEQSS\0" "\x09" "VCMPNLTSS\0" "\x09" "VCMPNLESS\0" "\x09" "VCMPORDSS\0" \ +"\x0b" "VCMPEQ_UQSS\0" "\x09" "VCMPNGESS\0" "\x09" "VCMPNGTSS\0" "\x0b" "VCMPFALSESS\0" \ +"\x0c" "VCMPNEQ_OQSS\0" "\x08" "VCMPGESS\0" "\x08" "VCMPGTSS\0" "\x0a" "VCMPTRUESS\0" \ +"\x0b" "VCMPEQ_OSSS\0" "\x0b" "VCMPLT_OQSS\0" "\x0b" "VCMPLE_OQSS\0" "\x0d" "VCMPUNORD_SSS\0" \ +"\x0c" "VCMPNEQ_USSS\0" "\x0c" "VCMPNLT_UQSS\0" "\x0c" "VCMPNLE_UQSS\0" "\x0b" "VCMPORD_SSS\0" \ +"\x0b" "VCMPEQ_USSS\0" "\x0c" "VCMPNGE_UQSS\0" "\x0c" "VCMPNGT_UQSS\0" "\x0e" "VCMPFALSE_OSSS\0" \ +"\x0c" "VCMPNEQ_OSSS\0" "\x0b" "VCMPGE_OQSS\0" "\x0b" "VCMPGT_OQSS\0" "\x0d" "VCMPTRUE_USSS\0" \ +"\x08" "VCMPEQSD\0" "\x08" "VCMPLTSD\0" "\x08" "VCMPLESD\0" "\x0b" "VCMPUNORDSD\0" \ +"\x09" "VCMPNEQSD\0" "\x09" "VCMPNLTSD\0" "\x09" "VCMPNLESD\0" "\x09" "VCMPORDSD\0" \ +"\x0b" "VCMPEQ_UQSD\0" "\x09" "VCMPNGESD\0" "\x09" "VCMPNGTSD\0" "\x0b" "VCMPFALSESD\0" \ +"\x0c" "VCMPNEQ_OQSD\0" "\x08" "VCMPGESD\0" "\x08" "VCMPGTSD\0" "\x0a" "VCMPTRUESD\0" \ +"\x0b" "VCMPEQ_OSSD\0" "\x0b" "VCMPLT_OQSD\0" "\x0b" "VCMPLE_OQSD\0" "\x0d" "VCMPUNORD_SSD\0" \ +"\x0c" "VCMPNEQ_USSD\0" "\x0c" "VCMPNLT_UQSD\0" "\x0c" "VCMPNLE_UQSD\0" "\x0b" "VCMPORD_SSD\0" \ +"\x0b" "VCMPEQ_USSD\0" "\x0c" "VCMPNGE_UQSD\0" "\x0c" "VCMPNGT_UQSD\0" "\x0e" "VCMPFALSE_OSSD\0" \ +"\x0c" "VCMPNEQ_OSSD\0" "\x0b" "VCMPGE_OQSD\0" "\x0b" "VCMPGT_OQSD\0" "\x0d" "VCMPTRUE_USSD\0" \ +"\x06" "PINSRW\0" "\x07" "VPINSRW\0" "\x06" "PEXTRW\0" "\x07" "VPEXTRW\0" "\x06" "SHUFPS\0" \ +"\x06" "SHUFPD\0" "\x07" "VSHUFPS\0" "\x07" "VSHUFPD\0" "\x09" "CMPXCHG8B\0" \ +"\x0a" "CMPXCHG16B\0" "\x07" "VMPTRST\0" "\x08" "ADDSUBPD\0" "\x08" "ADDSUBPS\0" \ +"\x09" "VADDSUBPD\0" "\x09" "VADDSUBPS\0" "\x05" "PSRLW\0" "\x06" "VPSRLW\0" \ +"\x05" "PSRLD\0" "\x06" "VPSRLD\0" "\x05" "PSRLQ\0" "\x06" "VPSRLQ\0" "\x05" "PADDQ\0" \ +"\x06" "VPADDQ\0" "\x06" "PMULLW\0" "\x07" "VPMULLW\0" "\x07" "MOVQ2DQ\0" "\x07" "MOVDQ2Q\0" \ +"\x08" "PMOVMSKB\0" "\x09" "VPMOVMSKB\0" "\x07" "PSUBUSB\0" "\x08" "VPSUBUSB\0" \ +"\x07" "PSUBUSW\0" "\x08" "VPSUBUSW\0" "\x06" "PMINUB\0" "\x07" "VPMINUB\0" \ +"\x04" "PAND\0" "\x05" "VPAND\0" "\x07" "PADDUSB\0" "\x08" "VPADDUSW\0" "\x07" "PADDUSW\0" \ +"\x06" "PMAXUB\0" "\x07" "VPMAXUB\0" "\x05" "PANDN\0" "\x06" "VPANDN\0" "\x05" "PAVGB\0" \ +"\x06" "VPAVGB\0" "\x05" "PSRAW\0" "\x06" "VPSRAW\0" "\x05" "PSRAD\0" "\x06" "VPSRAD\0" \ +"\x05" "PAVGW\0" "\x06" "VPAVGW\0" "\x07" "PMULHUW\0" "\x08" "VPMULHUW\0" "\x06" "PMULHW\0" \ +"\x07" "VPMULHW\0" "\x09" "CVTTPD2DQ\0" "\x08" "CVTDQ2PD\0" "\x08" "CVTPD2DQ\0" \ +"\x0a" "VCVTTPD2DQ\0" "\x09" "VCVTDQ2PD\0" "\x09" "VCVTPD2DQ\0" "\x06" "MOVNTQ\0" \ +"\x07" "MOVNTDQ\0" "\x08" "VMOVNTDQ\0" "\x06" "PSUBSB\0" "\x07" "VPSUBSB\0" \ +"\x06" "PSUBSW\0" "\x07" "VPSUBSW\0" "\x06" "PMINSW\0" "\x07" "VPMINSW\0" "\x03" "POR\0" \ +"\x04" "VPOR\0" "\x06" "PADDSB\0" "\x07" "VPADDSB\0" "\x06" "PADDSW\0" "\x07" "VPADDSW\0" \ +"\x06" "PMAXSW\0" "\x07" "VPMAXSW\0" "\x04" "PXOR\0" "\x05" "VPXOR\0" "\x05" "LDDQU\0" \ +"\x06" "VLDDQU\0" "\x05" "PSLLW\0" "\x06" "VPSLLW\0" "\x05" "PSLLD\0" "\x06" "VPSLLD\0" \ +"\x05" "PSLLQ\0" "\x06" "VPSLLQ\0" "\x07" "PMULUDQ\0" "\x08" "VPMULUDQ\0" "\x07" "PMADDWD\0" \ +"\x08" "VPMADDWD\0" "\x06" "PSADBW\0" "\x07" "VPSADBW\0" "\x08" "MASKMOVQ\0" \ +"\x0a" "MASKMOVDQU\0" "\x0b" "VMASKMOVDQU\0" "\x05" "PSUBB\0" "\x06" "VPSUBB\0" \ +"\x05" "PSUBW\0" "\x06" "VPSUBW\0" "\x05" "PSUBD\0" "\x06" "VPSUBD\0" "\x05" "PSUBQ\0" \ +"\x06" "VPSUBQ\0" "\x05" "PADDB\0" "\x06" "VPADDB\0" "\x05" "PADDW\0" "\x06" "VPADDW\0" \ +"\x05" "PADDD\0" "\x06" "VPADDD\0" "\x07" "FNSTENV\0" "\x06" "FSTENV\0" "\x06" "FNSTCW\0" \ +"\x05" "FSTCW\0" "\x06" "FNCLEX\0" "\x05" "FCLEX\0" "\x06" "FNINIT\0" "\x05" "FINIT\0" \ +"\x06" "FNSAVE\0" "\x05" "FSAVE\0" "\x06" "FNSTSW\0" "\x05" "FSTSW\0" "\x06" "PSHUFB\0" \ +"\x07" "VPSHUFB\0" "\x06" "PHADDW\0" "\x07" "VPHADDW\0" "\x06" "PHADDD\0" "\x07" "VPHADDD\0" \ +"\x07" "PHADDSW\0" "\x08" "VPHADDSW\0" "\x09" "PMADDUBSW\0" "\x0a" "VPMADDUBSW\0" \ +"\x06" "PHSUBW\0" "\x07" "VPHSUBW\0" "\x06" "PHSUBD\0" "\x07" "VPHSUBD\0" "\x07" "PHSUBSW\0" \ +"\x08" "VPHSUBSW\0" "\x06" "PSIGNB\0" "\x07" "VPSIGNB\0" "\x06" "PSIGNW\0" \ +"\x07" "VPSIGNW\0" "\x06" "PSIGND\0" "\x07" "VPSIGND\0" "\x08" "PMULHRSW\0" \ +"\x09" "VPMULHRSW\0" "\x09" "VPERMILPS\0" "\x09" "VPERMILPD\0" "\x07" "VTESTPS\0" \ +"\x07" "VTESTPD\0" "\x08" "PBLENDVB\0" "\x08" "BLENDVPS\0" "\x08" "BLENDVPD\0" \ +"\x05" "PTEST\0" "\x06" "VPTEST\0" "\x0c" "VBROADCASTSS\0" "\x0c" "VBROADCASTSD\0" \ +"\x0e" "VBROADCASTF128\0" "\x05" "PABSB\0" "\x06" "VPABSB\0" "\x05" "PABSW\0" \ +"\x06" "VPABSW\0" "\x05" "PABSD\0" "\x06" "VPABSD\0" "\x08" "PMOVSXBW\0" "\x09" "VPMOVSXBW\0" \ +"\x08" "PMOVSXBD\0" "\x09" "VPMOVSXBD\0" "\x08" "PMOVSXBQ\0" "\x09" "VPMOVSXBQ\0" \ +"\x08" "PMOVSXWD\0" "\x09" "VPMOVSXWD\0" "\x08" "PMOVSXWQ\0" "\x09" "VPMOVSXWQ\0" \ +"\x08" "PMOVSXDQ\0" "\x09" "VPMOVSXDQ\0" "\x06" "PMULDQ\0" "\x07" "VPMULDQ\0" \ +"\x07" "PCMPEQQ\0" "\x08" "VPCMPEQQ\0" "\x08" "MOVNTDQA\0" "\x09" "VMOVNTDQA\0" \ +"\x08" "PACKUSDW\0" "\x09" "VPACKUSDW\0" "\x0a" "VMASKMOVPS\0" "\x0a" "VMASKMOVPD\0" \ +"\x08" "PMOVZXBW\0" "\x09" "VPMOVZXBW\0" "\x08" "PMOVZXBD\0" "\x09" "VPMOVZXBD\0" \ +"\x08" "PMOVZXBQ\0" "\x09" "VPMOVZXBQ\0" "\x08" "PMOVZXWD\0" "\x09" "VPMOVZXWD\0" \ +"\x08" "PMOVZXWQ\0" "\x09" "VPMOVZXWQ\0" "\x08" "PMOVZXDQ\0" "\x09" "VPMOVZXDQ\0" \ +"\x07" "PCMPGTQ\0" "\x08" "VPCMPGTQ\0" "\x06" "PMINSB\0" "\x07" "VPMINSB\0" \ +"\x06" "PMINSD\0" "\x07" "VPMINSD\0" "\x06" "PMINUW\0" "\x07" "VPMINUW\0" "\x06" "PMINUD\0" \ +"\x07" "VPMINUD\0" "\x06" "PMAXSB\0" "\x07" "VPMAXSB\0" "\x06" "PMAXSD\0" "\x07" "VPMAXSD\0" \ +"\x06" "PMAXUW\0" "\x07" "VPMAXUW\0" "\x06" "PMAXUD\0" "\x07" "VPMAXUD\0" "\x06" "PMULLD\0" \ +"\x07" "VPMULLD\0" "\x0a" "PHMINPOSUW\0" "\x0b" "VPHMINPOSUW\0" "\x06" "INVEPT\0" \ +"\x07" "INVVPID\0" "\x07" "INVPCID\0" "\x0e" "VFMADDSUB132PS\0" "\x0e" "VFMADDSUB132PD\0" \ +"\x0e" "VFMSUBADD132PS\0" "\x0e" "VFMSUBADD132PD\0" "\x0b" "VFMADD132PS\0" \ +"\x0b" "VFMADD132PD\0" "\x0b" "VFMADD132SS\0" "\x0b" "VFMADD132SD\0" "\x0b" "VFMSUB132PS\0" \ +"\x0b" "VFMSUB132PD\0" "\x0b" "VFMSUB132SS\0" "\x0b" "VFMSUB132SD\0" "\x0c" "VFNMADD132PS\0" \ +"\x0c" "VFNMADD132PD\0" "\x0c" "VFNMADD132SS\0" "\x0c" "VFNMADD132SD\0" "\x0c" "VFNMSUB132PS\0" \ +"\x0c" "VFNMSUB132PD\0" "\x0c" "VFNMSUB132SS\0" "\x0c" "VFNMSUB132SD\0" "\x0e" "VFMADDSUB213PS\0" \ +"\x0e" "VFMADDSUB213PD\0" "\x0e" "VFMSUBADD213PS\0" "\x0e" "VFMSUBADD213PD\0" \ +"\x0b" "VFMADD213PS\0" "\x0b" "VFMADD213PD\0" "\x0b" "VFMADD213SS\0" "\x0b" "VFMADD213SD\0" \ +"\x0b" "VFMSUB213PS\0" "\x0b" "VFMSUB213PD\0" "\x0b" "VFMSUB213SS\0" "\x0b" "VFMSUB213SD\0" \ +"\x0c" "VFNMADD213PS\0" "\x0c" "VFNMADD213PD\0" "\x0c" "VFNMADD213SS\0" "\x0c" "VFNMADD213SD\0" \ +"\x0c" "VFNMSUB213PS\0" "\x0c" "VFNMSUB213PD\0" "\x0c" "VFNMSUB213SS\0" "\x0c" "VFNMSUB213SD\0" \ +"\x0e" "VFMADDSUB231PS\0" "\x0e" "VFMADDSUB231PD\0" "\x0e" "VFMSUBADD231PS\0" \ +"\x0e" "VFMSUBADD231PD\0" "\x0b" "VFMADD231PS\0" "\x0b" "VFMADD231PD\0" "\x0b" "VFMADD231SS\0" \ +"\x0b" "VFMADD231SD\0" "\x0b" "VFMSUB231PS\0" "\x0b" "VFMSUB231PD\0" "\x0b" "VFMSUB231SS\0" \ +"\x0b" "VFMSUB231SD\0" "\x0c" "VFNMADD231PS\0" "\x0c" "VFNMADD231PD\0" "\x0c" "VFNMADD231SS\0" \ +"\x0c" "VFNMADD231SD\0" "\x0c" "VFNMSUB231PS\0" "\x0c" "VFNMSUB231PD\0" "\x0c" "VFNMSUB231SS\0" \ +"\x0c" "VFNMSUB231SD\0" "\x06" "AESIMC\0" "\x07" "VAESIMC\0" "\x06" "AESENC\0" \ +"\x07" "VAESENC\0" "\x0a" "AESENCLAST\0" "\x0b" "VAESENCLAST\0" "\x06" "AESDEC\0" \ +"\x07" "VAESDEC\0" "\x0a" "AESDECLAST\0" "\x0b" "VAESDECLAST\0" "\x05" "MOVBE\0" \ +"\x05" "CRC32\0" "\x0a" "VPERM2F128\0" "\x07" "ROUNDPS\0" "\x08" "VROUNDPS\0" \ +"\x07" "ROUNDPD\0" "\x08" "VROUNDPD\0" "\x07" "ROUNDSS\0" "\x08" "VROUNDSS\0" \ +"\x07" "ROUNDSD\0" "\x08" "VROUNDSD\0" "\x07" "BLENDPS\0" "\x08" "VBLENDPS\0" \ +"\x07" "BLENDPD\0" "\x08" "VBLENDPD\0" "\x07" "PBLENDW\0" "\x08" "VPBLENDW\0" \ +"\x07" "PALIGNR\0" "\x08" "VPALIGNR\0" "\x06" "PEXTRB\0" "\x07" "VPEXTRB\0" \ +"\x06" "PEXTRD\0" "\x06" "PEXTRQ\0" "\x07" "VPEXTRD\0" "\x07" "VPEXTRQ\0" "\x09" "EXTRACTPS\0" \ +"\x0a" "VEXTRACTPS\0" "\x0b" "VINSERTF128\0" "\x0c" "VEXTRACTF128\0" "\x06" "PINSRB\0" \ +"\x07" "VPINSRB\0" "\x08" "INSERTPS\0" "\x09" "VINSERTPS\0" "\x06" "PINSRD\0" \ +"\x06" "PINSRQ\0" "\x07" "VPINSRD\0" "\x07" "VPINSRQ\0" "\x04" "DPPS\0" "\x05" "VDPPS\0" \ +"\x04" "DPPD\0" "\x05" "VDPPD\0" "\x07" "MPSADBW\0" "\x08" "VMPSADBW\0" "\x09" "PCLMULQDQ\0" \ +"\x0a" "VPCLMULQDQ\0" "\x09" "VBLENDVPS\0" "\x09" "VBLENDVPD\0" "\x09" "VPBLENDVB\0" \ +"\x09" "PCMPESTRM\0" "\x0a" "VPCMPESTRM\0" "\x09" "PCMPESTRI\0" "\x0a" "VPCMPESTRI\0" \ +"\x09" "PCMPISTRM\0" "\x0a" "VPCMPISTRM\0" "\x09" "PCMPISTRI\0" "\x0a" "VPCMPISTRI\0" \ +"\x0f" "AESKEYGENASSIST\0" "\x10" "VAESKEYGENASSIST\0" "\x06" "PSRLDQ\0" "\x07" "VPSRLDQ\0" \ +"\x06" "PSLLDQ\0" "\x07" "VPSLLDQ\0" "\x06" "FXSAVE\0" "\x08" "FXSAVE64\0" \ +"\x08" "RDFSBASE\0" "\x07" "FXRSTOR\0" "\x09" "FXRSTOR64\0" "\x08" "RDGSBASE\0" \ +"\x07" "LDMXCSR\0" "\x08" "WRFSBASE\0" "\x08" "VLDMXCSR\0" "\x07" "STMXCSR\0" \ +"\x08" "WRGSBASE\0" "\x08" "VSTMXCSR\0" "\x06" "RDRAND\0" "\x07" "VMPTRLD\0" \ +"\x07" "VMCLEAR\0" "\x05" "VMXON\0" "\x04" "WAIT\0" "\x06" "MOVSXD\0" "\x05" "PAUSE\0"; + +const _WRegister _REGISTERS[] = { + {3, "RAX"}, {3, "RCX"}, {3, "RDX"}, {3, "RBX"}, {3, "RSP"}, {3, "RBP"}, {3, "RSI"}, {3, "RDI"}, {2, "R8"}, {2, "R9"}, {3, "R10"}, {3, "R11"}, {3, "R12"}, {3, "R13"}, {3, "R14"}, {3, "R15"}, + {3, "EAX"}, {3, "ECX"}, {3, "EDX"}, {3, "EBX"}, {3, "ESP"}, {3, "EBP"}, {3, "ESI"}, {3, "EDI"}, {3, "R8D"}, {3, "R9D"}, {4, "R10D"}, {4, "R11D"}, {4, "R12D"}, {4, "R13D"}, {4, "R14D"}, {4, "R15D"}, + {2, "AX"}, {2, "CX"}, {2, "DX"}, {2, "BX"}, {2, "SP"}, {2, "BP"}, {2, "SI"}, {2, "DI"}, {3, "R8W"}, {3, "R9W"}, {4, "R10W"}, {4, "R11W"}, {4, "R12W"}, {4, "R13W"}, {4, "R14W"}, {4, "R15W"}, + {2, "AL"}, {2, "CL"}, {2, "DL"}, {2, "BL"}, {2, "AH"}, {2, "CH"}, {2, "DH"}, {2, "BH"}, {3, "R8B"}, {3, "R9B"}, {4, "R10B"}, {4, "R11B"}, {4, "R12B"}, {4, "R13B"}, {4, "R14B"}, {4, "R15B"}, + {3, "SPL"}, {3, "BPL"}, {3, "SIL"}, {3, "DIL"}, + {2, "ES"}, {2, "CS"}, {2, "SS"}, {2, "DS"}, {2, "FS"}, {2, "GS"}, + {3, "RIP"}, + {3, "ST0"}, {3, "ST1"}, {3, "ST2"}, {3, "ST3"}, {3, "ST4"}, {3, "ST5"}, {3, "ST6"}, {3, "ST7"}, + {3, "MM0"}, {3, "MM1"}, {3, "MM2"}, {3, "MM3"}, {3, "MM4"}, {3, "MM5"}, {3, "MM6"}, {3, "MM7"}, + {4, "XMM0"}, {4, "XMM1"}, {4, "XMM2"}, {4, "XMM3"}, {4, "XMM4"}, {4, "XMM5"}, {4, "XMM6"}, {4, "XMM7"}, {4, "XMM8"}, {4, "XMM9"}, {5, "XMM10"}, {5, "XMM11"}, {5, "XMM12"}, {5, "XMM13"}, {5, "XMM14"}, {5, "XMM15"}, + {4, "YMM0"}, {4, "YMM1"}, {4, "YMM2"}, {4, "YMM3"}, {4, "YMM4"}, {4, "YMM5"}, {4, "YMM6"}, {4, "YMM7"}, {4, "YMM8"}, {4, "YMM9"}, {5, "YMM10"}, {5, "YMM11"}, {5, "YMM12"}, {5, "YMM13"}, {5, "YMM14"}, {5, "YMM15"}, + {3, "CR0"}, {0, ""}, {3, "CR2"}, {3, "CR3"}, {3, "CR4"}, {0, ""}, {0, ""}, {0, ""}, {3, "CR8"}, + {3, "DR0"}, {3, "DR1"}, {3, "DR2"}, {3, "DR3"}, {0, ""}, {0, ""}, {3, "DR6"}, {3, "DR7"} +}; + +#endif /* DISTORM_LIGHT */ diff --git a/distorm3.2-package/src/operands.c b/distorm3.2-package/src/operands.c new file mode 100644 index 0000000..7260623 --- /dev/null +++ b/distorm3.2-package/src/operands.c @@ -0,0 +1,1299 @@ +/* +operands.c + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2012 Gil Dabah + +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 +*/ + + +#include "config.h" +#include "operands.h" +#include "x86defs.h" +#include "insts.h" +#include "../include/mnemonics.h" + + +/* Maps a register to its register-class mask. */ +uint16_t _REGISTERTORCLASS[] = /* Based on _RegisterType enumeration! */ +{RM_AX, RM_CX, RM_DX, RM_BX, RM_SP, RM_BP, RM_SI, RM_DI, 0, 0, 0, 0, 0, 0, 0, 0, + RM_AX, RM_CX, RM_DX, RM_BX, RM_SP, RM_BP, RM_SI, RM_DI, 0, 0, 0, 0, 0, 0, 0, 0, + RM_AX, RM_CX, RM_DX, RM_BX, RM_SP, RM_BP, RM_SI, RM_DI, 0, 0, 0, 0, 0, 0, 0, 0, + RM_AX, RM_CX, RM_DX, RM_BX, RM_AX, RM_CX, RM_DX, RM_BX, 0, 0, 0, 0, 0, 0, 0, 0, + RM_SP, RM_BP, RM_SI, RM_DI, + 0, 0, 0, 0, 0, 0, + 0, + RM_FPU, RM_FPU, RM_FPU, RM_FPU, RM_FPU, RM_FPU, RM_FPU, RM_FPU, + RM_MMX, RM_MMX, RM_MMX, RM_MMX, RM_MMX, RM_MMX, RM_MMX, RM_MMX, + RM_SSE, RM_SSE, RM_SSE, RM_SSE, RM_SSE, RM_SSE, RM_SSE, RM_SSE, RM_SSE, RM_SSE, RM_SSE, RM_SSE, RM_SSE, RM_SSE, RM_SSE, RM_SSE, + RM_AVX, RM_AVX, RM_AVX, RM_AVX, RM_AVX, RM_AVX, RM_AVX, RM_AVX, RM_AVX, RM_AVX, RM_AVX, RM_AVX, RM_AVX, RM_AVX, RM_AVX, RM_AVX, + RM_CR, 0, RM_CR, RM_CR, RM_CR, 0, 0, 0, RM_CR, + RM_DR, RM_DR, RM_DR, RM_DR, 0, 0, RM_DR, RM_DR +}; + +typedef enum {OPERAND_SIZE_NONE = 0, OPERAND_SIZE8, OPERAND_SIZE16, OPERAND_SIZE32, OPERAND_SIZE64, OPERAND_SIZE80, OPERAND_SIZE128, OPERAND_SIZE256} _OperandSizeType; +static uint16_t _OPSIZETOINT[] = {0, 8, 16, 32, 64, 80, 128, 256}; + +/* A helper function to fix the 8 bits register if REX is used (to support SIL, DIL, etc). */ +static unsigned int _FASTCALL_ operands_fix_8bit_rex_base(unsigned int reg) +{ + if ((reg >= 4) && (reg < 8)) return reg + REGS8_REX_BASE - 4; + return reg + REGS8_BASE; +} + +/* A helper function to set operand's type and size. */ +static void _FASTCALL_ operands_set_ts(_Operand* op, _OperandType type, uint16_t size) +{ + op->type = type; + op->size = size; +} + +/* A helper function to set operand's type, size and index. */ +static void _FASTCALL_ operands_set_tsi(_Operand* op, _OperandType type, uint16_t size, unsigned int index) +{ + op->type = type; + op->index = (uint8_t)index; + op->size = size; +} + +/* A helper function to read an unsigned integer from the stream safely. */ +static int _FASTCALL_ read_stream_safe_uint(_CodeInfo* ci, void* result, unsigned int size) +{ + ci->codeLen -= size; + if (ci->codeLen < 0) return FALSE; + switch (size) + { + case 1: *(uint8_t*)result = *(uint8_t*)ci->code; break; + case 2: *(uint16_t*)result = RUSHORT(ci->code); break; + case 4: *(uint32_t*)result = RULONG(ci->code); break; + case 8: *(uint64_t*)result = RULLONG(ci->code); break; + } + ci->code += size; + return TRUE; +} + +/* A helper function to read a signed integer from the stream safely. */ +static int _FASTCALL_ read_stream_safe_sint(_CodeInfo* ci, int64_t* result, unsigned int size) +{ + ci->codeLen -= size; + if (ci->codeLen < 0) return FALSE; + switch (size) + { + case 1: *result = *(int8_t*)ci->code; break; + case 2: *result = RSHORT(ci->code); break; + case 4: *result = RLONG(ci->code); break; + case 8: *result = RLLONG(ci->code); break; + } + ci->code += size; + return TRUE; +} + +/* + * SIB decoding is the most confusing part when decoding IA-32 instructions. + * This explanation should clear up some stuff. + * + * ! When base == 5, use EBP as the base register ! + * if (rm == 4) { + * if mod == 01, decode SIB byte and ALSO read a 8 bits displacement. + * if mod == 10, decode SIB byte and ALSO read a 32 bits displacement. + * if mod == 11 <-- EXCEPTION, this is a general-purpose register and mustn't lead to SIB decoding! + * ; So far so good, now the confusing part comes in with mod == 0 and base=5, but no worry. + * if (mod == 00) { + * decode SIB byte WITHOUT any displacement. + * EXCEPTION!!! when base == 5, read a 32 bits displacement, but this time DO NOT use (EBP) BASE at all! + * } + * + * NOTE: base could specify None (no base register) if base==5 and mod==0, but then you also need DISP32. + * } + */ +static void operands_extract_sib(_DInst* di, _OperandNumberType opNum, + _PrefixState* ps, _DecodeType effAdrSz, + unsigned int sib, unsigned int mod) +{ + unsigned int scale = 0, index = 0, base = 0; + unsigned int vrex = ps->vrex; + uint8_t* pIndex = NULL; + + _Operand* op = &di->ops[opNum]; + + /* + * SIB bits: + * |7---6-5----3-2---0| + * |SCALE| INDEX| BASE| + * |------------------| + */ + scale = (sib >> 6) & 3; + index = (sib >> 3) & 7; + base = sib & 7; + + /* + * The following fields: base/index/scale/disp8/32 are ALL optional by specific rules! + * The idea here is to keep the indirection as a simple-memory type. + * Because the base is optional, and we might be left with only one index. + * So even if there's a base but no index, or vice versa, we end up with one index register. + */ + + /* In 64 bits the REX prefix might affect the index of the SIB byte. */ + if (vrex & PREFIX_EX_X) { + ps->usedPrefixes |= INST_PRE_REX; + index += EX_GPR_BASE; + } + + if (index == 4) { /* No index is used. Use SMEM. */ + op->type = O_SMEM; + pIndex = &op->index; + } else { + op->type = O_MEM; + pIndex = &di->base; + /* No base, unless it is updated below. E.G: [EAX*4] has no base reg. */ + } + + if (base != 5) { + if (vrex & PREFIX_EX_B) ps->usedPrefixes |= INST_PRE_REX; + *pIndex = effAdrSz == Decode64Bits ? REGS64_BASE : REGS32_BASE; + *pIndex += (uint8_t)(base + ((vrex & PREFIX_EX_B) ? EX_GPR_BASE : 0)); + } else if (mod != 0) { + /* + * if base == 5 then you have to decode according to MOD. + * mod(00) - disp32. + * mod(01) - disp8 + rBP + * mod(10) - disp32 + rBP + * mod(11) - not possible, it's a general-purpose register. + */ + + if (vrex & PREFIX_EX_B) ps->usedPrefixes |= INST_PRE_REX; + if (effAdrSz == Decode64Bits) *pIndex = REGS64_BASE + 5 + ((vrex & PREFIX_EX_B) ? EX_GPR_BASE : 0); + else *pIndex = REGS32_BASE + 5 + ((vrex & PREFIX_EX_B) ? EX_GPR_BASE : 0); + } else if (index == 4) { + /* 32bits displacement only. */ + op->type = O_DISP; + return; + } + + if (index != 4) { /* In 64 bits decoding mode, if index == R12, it's valid! */ + if (effAdrSz == Decode64Bits) op->index = (uint8_t)(REGS64_BASE + index); + else op->index = (uint8_t)(REGS32_BASE + index); + di->scale = scale != 0 ? (1 << scale) : 0; + } +} + +/* + * This seems to be the hardest part in decoding the operands. + * If you take a look carefully at Table 2-2. 32-Bit Addressing Forms with the ModR/M Byte, + * you will understand it's easy to decode the operands. + + * First we check the DT, so we can decide according to which Table in the documentation we are supposed to decode. + * Then we follow the specific table whether it's 16 bits or 32/64 bits. + + * Don't forget that Operand Size AND Address Size prefixes may change the decoding! + + * Some instructions force the use of RM16 or other specific types, so take it into account. + */ +static int operands_extract_modrm(_CodeInfo* ci, + _DInst* di, _OpType type, + _OperandNumberType opNum, _PrefixState* ps, + _DecodeType effOpSz, _DecodeType effAdrSz, + int* lockableInstruction, unsigned int mod, unsigned int rm, + _iflags instFlags) +{ + unsigned int vrex = ps->vrex, sib = 0, base = 0; + _Operand* op = &di->ops[opNum]; + uint16_t size = 0; + + if (mod == 3) { + /* + * General-purpose register is handled the same way in 16/32/64 bits decoding modes. + * NOTE!! that we have to override the size of the register, since it was set earlier as Memory and not Register! + */ + op->type = O_REG; + /* Start with original size which was set earlier, some registers have same size of memory and depend on it. */ + size = op->size; + switch(type) + { + case OT_RFULL_M16: + case OT_RM_FULL: + switch (effOpSz) + { + case Decode16Bits: + ps->usedPrefixes |= INST_PRE_OP_SIZE; + if (vrex & PREFIX_EX_B) { + ps->usedPrefixes |= INST_PRE_REX; + rm += EX_GPR_BASE; + } + size = 16; + rm += REGS16_BASE; + break; + case Decode32Bits: + ps->usedPrefixes |= INST_PRE_OP_SIZE; + if (vrex & PREFIX_EX_B) { + ps->usedPrefixes |= INST_PRE_REX; + rm += EX_GPR_BASE; + } + size = 32; + rm += REGS32_BASE; + break; + case Decode64Bits: + /* A fix for SMSW RAX which use the REX prefix. */ + if (type == OT_RFULL_M16) ps->usedPrefixes |= INST_PRE_REX; + /* CALL NEAR/PUSH/POP defaults to 64 bits. --> INST_64BITS, REX isn't required, thus ignored anyways. */ + if (instFlags & INST_PRE_REX) ps->usedPrefixes |= INST_PRE_REX; + /* Include REX if used for REX.B. */ + if (vrex & PREFIX_EX_B) { + ps->usedPrefixes |= INST_PRE_REX; + rm += EX_GPR_BASE; + } + size = 64; + rm += REGS64_BASE; + break; + } + break; + case OT_R32_64_M8: + /* FALL THROUGH, decode 32 or 64 bits register. */ + case OT_R32_64_M16: + /* FALL THROUGH, decode 32 or 64 bits register. */ + case OT_RM32_64: /* Take care specifically in MOVNTI/MOVD/CVT's instructions, making it _REG64 with REX or if they are promoted. */ + if (vrex & PREFIX_EX_B) { + ps->usedPrefixes |= INST_PRE_REX; + rm += EX_GPR_BASE; + } + /* Is it a promoted instruction? (only INST_64BITS is set and REX isn't required.) */ + if ((ci->dt == Decode64Bits) && ((instFlags & (INST_64BITS | INST_PRE_REX)) == INST_64BITS)) { + size = 64; + rm += REGS64_BASE; + break; + } + /* Give a chance to REX.W. Because if it was a promoted instruction we don't care about REX.W anyways. */ + if (vrex & PREFIX_EX_W) { + ps->usedPrefixes |= INST_PRE_REX; + size = 64; + rm += REGS64_BASE; + } else { + size = 32; + rm += REGS32_BASE; + } + break; + case OT_RM16_32: /* Used only with MOVZXD instruction to support 16 bits operand. */ + if (vrex & PREFIX_EX_B) { + ps->usedPrefixes |= INST_PRE_REX; + rm += EX_GPR_BASE; + } + /* Is it 16 bits operand size? */ + if (ps->decodedPrefixes & INST_PRE_OP_SIZE) { + ps->usedPrefixes |= INST_PRE_OP_SIZE; + size = 16; + rm += REGS16_BASE; + } else { + size = 32; + rm += REGS32_BASE; + } + break; + case OT_RM16: + if (vrex & PREFIX_EX_B) { + ps->usedPrefixes |= INST_PRE_REX; + rm += EX_GPR_BASE; + } + rm += REGS16_BASE; + break; + case OT_RM8: + if (ps->prefixExtType == PET_REX) { + ps->usedPrefixes |= INST_PRE_REX; + rm = operands_fix_8bit_rex_base(rm + ((vrex & PREFIX_EX_B) ? EX_GPR_BASE : 0)); + } else rm += REGS8_BASE; + break; + case OT_MM32: + case OT_MM64: + /* MMX doesn't support extended registers. */ + size = 64; + rm += MMXREGS_BASE; + break; + + case OT_XMM16: + case OT_XMM32: + case OT_XMM64: + case OT_XMM128: + if (vrex & PREFIX_EX_B) { + ps->usedPrefixes |= INST_PRE_REX; + rm += EX_GPR_BASE; + } + size = 128; + rm += SSEREGS_BASE; + break; + + case OT_RM32: + case OT_R32_M8: + case OT_R32_M16: + if (vrex & PREFIX_EX_B) { + ps->usedPrefixes |= INST_PRE_REX; + rm += EX_GPR_BASE; + } + size = 32; + rm += REGS32_BASE; + break; + + case OT_YMM256: + if (vrex & PREFIX_EX_B) rm += EX_GPR_BASE; + rm += AVXREGS_BASE; + break; + case OT_YXMM64_256: + case OT_YXMM128_256: + if (vrex & PREFIX_EX_B) rm += EX_GPR_BASE; + if (vrex & PREFIX_EX_L) { + size = 256; + rm += AVXREGS_BASE; + } else { + size = 128; + rm += SSEREGS_BASE; + } + break; + case OT_WXMM32_64: + case OT_LXMM64_128: + if (vrex & PREFIX_EX_B) rm += EX_GPR_BASE; + size = 128; + rm += SSEREGS_BASE; + break; + + case OT_WRM32_64: + case OT_REG32_64_M8: + case OT_REG32_64_M16: + if (vrex & PREFIX_EX_B) rm += EX_GPR_BASE; + if (vrex & PREFIX_EX_W) { + size = 64; + rm += REGS64_BASE; + } else { + size = 32; + rm += REGS32_BASE; + } + break; + + default: return FALSE; + } + op->size = size; + op->index = (uint8_t)rm; + return TRUE; + } + + /* Memory indirection decoding ahead:) */ + + ps->usedPrefixes |= INST_PRE_ADDR_SIZE; + if (lockableInstruction && (ps->decodedPrefixes & INST_PRE_LOCK)) *lockableInstruction = TRUE; + + if (effAdrSz == Decode16Bits) { + /* Decoding according to Table 2-1. (16 bits) */ + if ((mod == 0) && (rm == 6)) { + /* 6 is a special case - only 16 bits displacement. */ + op->type = O_DISP; + di->dispSize = 16; + if (!read_stream_safe_sint(ci, (int64_t*)&di->disp, sizeof(int16_t))) return FALSE; + } else { + /* + * Create the O_MEM for 16 bits indirection that requires 2 registers, E.G: [BS+SI]. + * or create O_SMEM for a single register indirection, E.G: [BP]. + */ + static uint8_t MODS[] = {R_BX, R_BX, R_BP, R_BP, R_SI, R_DI, R_BP, R_BX}; + static uint8_t MODS2[] = {R_SI, R_DI, R_SI, R_DI}; + if (rm < 4) { + op->type = O_MEM; + di->base = MODS[rm]; + op->index = MODS2[rm]; + } else { + op->type = O_SMEM; + op->index = MODS[rm]; + } + + if (mod == 1) { /* 8 bits displacement + indirection */ + di->dispSize = 8; + if (!read_stream_safe_sint(ci, (int64_t*)&di->disp, sizeof(int8_t))) return FALSE; + } else if (mod == 2) { /* 16 bits displacement + indirection */ + di->dispSize = 16; + if (!read_stream_safe_sint(ci, (int64_t*)&di->disp, sizeof(int16_t))) return FALSE; + } + } + + if ((rm == 2) || (rm == 3) || ((rm == 6) && (mod != 0))) { + /* BP's default segment is SS, so ignore it. */ + prefixes_use_segment(INST_PRE_SS, ps, ci->dt, di); + } else { + /* Ignore default DS segment. */ + prefixes_use_segment(INST_PRE_DS, ps, ci->dt, di); + } + } else { /* Decode32Bits or Decode64Bits! */ + /* Remember that from a 32/64 bits ModR/M byte a SIB byte could follow! */ + if ((mod == 0) && (rm == 5)) { + + /* 5 is a special case - only 32 bits displacement, or RIP relative. */ + di->dispSize = 32; + if (!read_stream_safe_sint(ci, (int64_t*)&di->disp, sizeof(int32_t))) return FALSE; + + if (ci->dt == Decode64Bits) { + /* In 64 bits decoding mode depsite of the address size, a RIP-relative address it is. */ + op->type = O_SMEM; + op->index = R_RIP; + di->flags |= FLAG_RIP_RELATIVE; + } else { + /* Absolute address: */ + op->type = O_DISP; + } + } else { + if (rm == 4) { + /* 4 is a special case - SIB byte + disp8/32 follows! */ + /* Read SIB byte. */ + if (!read_stream_safe_uint(ci, &sib, sizeof(int8_t))) return FALSE; + operands_extract_sib(di, opNum, ps, effAdrSz, sib, mod); + } else { + op->type = O_SMEM; + if (vrex & PREFIX_EX_B) { + ps->usedPrefixes |= INST_PRE_REX; + rm += EX_GPR_BASE; + } + + if (effAdrSz == Decode64Bits) op->index = (uint8_t)(REGS64_BASE + rm); + else op->index = (uint8_t)(REGS32_BASE + rm); + } + + if (mod == 1) { + di->dispSize = 8; + if (!read_stream_safe_sint(ci, (int64_t*)&di->disp, sizeof(int8_t))) return FALSE; + } else if ((mod == 2) || ((sib & 7) == 5)) { /* If there is no BASE, read DISP32! */ + di->dispSize = 32; + if (!read_stream_safe_sint(ci, (int64_t*)&di->disp, sizeof(int32_t))) return FALSE; + } + } + + /* Get the base register. */ + base = op->index; + if (di->base != R_NONE) base = di->base; + else if (di->scale >= 2) base = 0; /* If it's only an index but got scale, it's still DS. */ + /* Default for EBP/ESP is SS segment. 64 bits mode ignores DS anyway. */ + if ((base == R_EBP) || (base == R_ESP)) prefixes_use_segment(INST_PRE_SS, ps, ci->dt, di); + else prefixes_use_segment(INST_PRE_DS, ps, ci->dt, di); + } + + return TRUE; +} + + +/* + * This function is reponsible to textually format a required operand according to its type. + * It is vital to understand that there are other operands than what the ModR/M byte specifies. + + * Only by decoding the operands of an instruction which got a LOCK prefix, we could tell whether it may use the LOCK prefix. + * According to Intel, LOCK prefix must precede some specific instructions AND in their memory destination operand form (which means first operand). + * LOCK INC EAX, would generate an exception, but LOCK INC [EAX] is alright. + * Also LOCK ADD BX, [BP] would generate an exception. + + * Return code: + * TRUE - continue parsing the instruction and its operands, everything went right 'till now. + * FALSE - not enough bytes, or invalid operands. + */ + +int operands_extract(_CodeInfo* ci, _DInst* di, _InstInfo* ii, + _OpType type, _OperandNumberType opNum, + unsigned int modrm, _PrefixState* ps, _DecodeType effOpSz, + _DecodeType effAdrSz, int* lockableInstruction) +{ + int ret = 0; + unsigned int mod = 0, reg = 0, rm = 0, vexV = ps->vexV; + unsigned int vrex = ps->vrex, typeHandled = TRUE; + _iflags instFlags = INST_INFO_FLAGS(ii); + _Operand* op = &di->ops[opNum]; + + /* Used to indicate the size of the MEMORY INDIRECTION only. */ + _OperandSizeType opSize = OPERAND_SIZE_NONE; + + /* + * ModRM bits: + * |7-6-5--------3-2-0| + * |MOD|REG/OPCODE|RM | + * |------------------| + */ + mod = (modrm >> 6) & 3; /* Mode(register-indirection, disp8+reg+indirection, disp16+reg+indirection, general-purpose register) */ + reg = (modrm >> 3) & 7; /* Register(could be part of the opcode itself or general-purpose register) */ + rm = modrm & 7; /* Specifies which general-purpose register or disp+reg to use. */ + + /* -- Memory Indirection Operands (that cannot be a general purpose register) -- */ + switch (type) + { + case OT_MEM64_128: /* Used only by CMPXCHG8/16B. */ + /* Make a specific check when the type is OT_MEM64_128 since the lockable CMPXCHG8B uses this one... */ + if (lockableInstruction && (ps->decodedPrefixes & INST_PRE_LOCK)) *lockableInstruction = TRUE; + if (effOpSz == Decode64Bits) { + ps->usedPrefixes |= INST_PRE_REX; + opSize = OPERAND_SIZE128; + } else opSize = OPERAND_SIZE64; + break; + case OT_MEM32: opSize = OPERAND_SIZE32; break; + case OT_MEM32_64: + /* Used by MOVNTI. Default size is 32bits, 64bits with REX. */ + if (effOpSz == Decode64Bits) { + ps->usedPrefixes |= INST_PRE_REX; + opSize = OPERAND_SIZE64; + } else opSize = OPERAND_SIZE32; + break; + case OT_MEM64: opSize = OPERAND_SIZE64; break; + case OT_MEM128: opSize = OPERAND_SIZE128; break; + case OT_MEM16_FULL: /* The size indicates about the second item of the pair. */ + switch (effOpSz) + { + case Decode16Bits: + ps->usedPrefixes |= INST_PRE_OP_SIZE; + opSize = OPERAND_SIZE16; + break; + case Decode32Bits: + ps->usedPrefixes |= INST_PRE_OP_SIZE; + opSize = OPERAND_SIZE32; + break; + case Decode64Bits: + /* Mark usage of REX only if it was required. */ + if ((instFlags & (INST_64BITS | INST_PRE_REX)) == (INST_64BITS | INST_PRE_REX)) ps->usedPrefixes |= INST_PRE_REX; + opSize = OPERAND_SIZE64; + break; + } + break; + case OT_MEM16_3264: /* The size indicates about the second item of the pair. */ + if (ci->dt == Decode64Bits) opSize = OPERAND_SIZE64; + else opSize = OPERAND_SIZE32; + break; + case OT_MEM_OPT: + /* Since the MEM is optional, only when mod != 3, then return true as if the operand was alright. */ + if (mod == 0x3) return TRUE; + break; + case OT_FPUM16: opSize = OPERAND_SIZE16; break; + case OT_FPUM32: opSize = OPERAND_SIZE32; break; + case OT_FPUM64: opSize = OPERAND_SIZE64; break; + case OT_FPUM80: opSize = OPERAND_SIZE80; break; + case OT_LMEM128_256: + if (vrex & PREFIX_EX_L) opSize = OPERAND_SIZE256; + else opSize = OPERAND_SIZE128; + break; + case OT_MEM: /* Size is unknown, but still handled. */ break; + default: typeHandled = FALSE; break; + } + if (typeHandled) { + /* All of the above types can't use a general-purpose register (a MOD of 3)!. */ + if (mod == 0x3) { + if (lockableInstruction) *lockableInstruction = FALSE; + return FALSE; + } + op->size = _OPSIZETOINT[opSize]; + ret = operands_extract_modrm(ci, di, type, opNum, ps, effOpSz, effAdrSz, lockableInstruction, mod, rm, instFlags); + if ((op->type == O_REG) || (op->type == O_SMEM) || (op->type == O_MEM)) { + di->usedRegistersMask |= _REGISTERTORCLASS[op->index]; + } + return ret; + } + + /* -- Memory Indirection Operands (that can be a register) -- */ + typeHandled = TRUE; + switch (type) + { + case OT_RM_FULL: + ps->usedPrefixes |= INST_PRE_OP_SIZE; + /* PUSH/JMP/CALL are automatically promoted to 64 bits! */ + if (effOpSz == Decode32Bits) { + opSize = OPERAND_SIZE32; + break; + } else if (effOpSz == Decode64Bits) { + /* Mark usage of REX only if it was required. */ + if ((instFlags & INST_64BITS) == 0) ps->usedPrefixes |= INST_PRE_REX; + opSize = OPERAND_SIZE64; + break; + } + /* FALL THROUGH BECAUSE dt==Decoded16Bits @-<----*/ + case OT_RM16: + /* If we got here not from OT_RM16, then the prefix was used. */ + if (type != OT_RM16) ps->usedPrefixes |= INST_PRE_OP_SIZE; + opSize = OPERAND_SIZE16; + break; + case OT_RM32_64: + /* The default size is 32, which can be 64 with a REX only. */ + if (effOpSz == Decode64Bits) { + opSize = OPERAND_SIZE64; + /* Mark REX prefix as used if non-promoted instruction. */ + if ((instFlags & (INST_64BITS | INST_PRE_REX)) == (INST_64BITS | INST_PRE_REX)) { + ps->usedPrefixes |= INST_PRE_REX; + } + } else opSize = OPERAND_SIZE32; + break; + case OT_RM16_32: + /* Ignore REX, it's either 32 or 16 bits RM. */ + if (ps->decodedPrefixes & INST_PRE_OP_SIZE) { + ps->usedPrefixes |= INST_PRE_OP_SIZE; + /* Assume: We are in 64bits when we have this operand used. */ + opSize = OPERAND_SIZE16; + } else opSize = OPERAND_SIZE32; + break; + case OT_WXMM32_64: + case OT_WRM32_64: + if (vrex & PREFIX_EX_W) opSize = OPERAND_SIZE64; + else opSize = OPERAND_SIZE32; + break; + case OT_YXMM64_256: + if (vrex & PREFIX_EX_L) opSize = OPERAND_SIZE256; + else opSize = OPERAND_SIZE64; + break; + case OT_YXMM128_256: + if (vrex & PREFIX_EX_L) opSize = OPERAND_SIZE256; + else opSize = OPERAND_SIZE128; + break; + case OT_LXMM64_128: + if (vrex & PREFIX_EX_L) opSize = OPERAND_SIZE128; + else opSize = OPERAND_SIZE64; + break; + case OT_RFULL_M16: + ps->usedPrefixes |= INST_PRE_OP_SIZE; + opSize = OPERAND_SIZE16; + break; + + case OT_RM8: + case OT_R32_M8: + case OT_R32_64_M8: + case OT_REG32_64_M8: + opSize = OPERAND_SIZE8; + break; + + case OT_XMM16: + case OT_R32_M16: + case OT_R32_64_M16: + case OT_REG32_64_M16: + opSize = OPERAND_SIZE16; + break; + + case OT_RM32: + case OT_MM32: + case OT_XMM32: + opSize = OPERAND_SIZE32; + break; + + case OT_MM64: + case OT_XMM64: + opSize = OPERAND_SIZE64; + break; + + case OT_XMM128: opSize = OPERAND_SIZE128; break; + case OT_YMM256: opSize = OPERAND_SIZE256; break; + default: typeHandled = FALSE; break; + } + if (typeHandled) { + /* Fill size of memory dereference for operand. */ + op->size = _OPSIZETOINT[opSize]; + ret = operands_extract_modrm(ci, di, type, opNum, ps, effOpSz, effAdrSz, lockableInstruction, mod, rm, instFlags); + if ((op->type == O_REG) || (op->type == O_SMEM) || (op->type == O_MEM)) { + di->usedRegistersMask |= _REGISTERTORCLASS[op->index]; + } + return ret; + } + + /* Simple operand type (no ModRM byte). */ + switch (type) + { + case OT_IMM8: + operands_set_ts(op, O_IMM, 8); + if (!read_stream_safe_uint(ci, &di->imm.byte, sizeof(int8_t))) return FALSE; + break; + case OT_IMM_FULL: /* 16, 32 or 64, depends on prefixes. */ + if (effOpSz == Decode16Bits) { + ps->usedPrefixes |= INST_PRE_OP_SIZE; + /* FALL THROUGH */ + case OT_IMM16: /* Force 16 bits imm. */ + operands_set_ts(op, O_IMM, 16); + if (!read_stream_safe_uint(ci, &di->imm.word, sizeof(int16_t))) return FALSE; + break; + /* + * Extension: MOV imm64, requires REX. + * Make sure it needs the REX. + * REX must be present because op size function takes it into consideration. + */ + } else if ((effOpSz == Decode64Bits) && + ((instFlags & (INST_64BITS | INST_PRE_REX)) == (INST_64BITS | INST_PRE_REX))) { + ps->usedPrefixes |= INST_PRE_REX; + + operands_set_ts(op, O_IMM, 64); + if (!read_stream_safe_uint(ci, &di->imm.qword, sizeof(int64_t))) return FALSE; + break; + } else ps->usedPrefixes |= INST_PRE_OP_SIZE; + /* FALL THROUGH BECAUSE dt==Decoded32Bits @-<----*/ + case OT_IMM32: + op->type = O_IMM; + if (ci->dt == Decode64Bits) { + /* Imm32 is sign extended to 64 bits! */ + op->size = 64; + di->flags |= FLAG_IMM_SIGNED; + if (!read_stream_safe_sint(ci, &di->imm.sqword, sizeof(int32_t))) return FALSE; + } else { + op->size = 32; + if (!read_stream_safe_uint(ci, &di->imm.dword, sizeof(int32_t))) return FALSE; + } + break; + case OT_SEIMM8: /* Sign extended immediate. */ + /* + * PUSH SEIMM8 can be prefixed by operand size: + * Input stream: 66, 6a, 55 + * 64bits DT: push small 55 + * 32bits DT: push small 55 + * 16bits DT: push large 55 + * small/large indicates the size of the eSP pointer advancement. + * Check the instFlags (ii->flags) if it can be operand-size-prefixed and if the prefix exists. + */ + op->type = O_IMM; + if ((instFlags & INST_PRE_OP_SIZE) && (ps->decodedPrefixes & INST_PRE_OP_SIZE)) { + ps->usedPrefixes |= INST_PRE_OP_SIZE; + switch (ci->dt) + { + case Decode16Bits: op->size = 32; break; + case Decode32Bits: + case Decode64Bits: + op->size = 16; + break; + } + } else op->size = 8; + di->flags |= FLAG_IMM_SIGNED; + if (!read_stream_safe_sint(ci, &di->imm.sqword, sizeof(int8_t))) return FALSE; + break; + case OT_IMM16_1: + operands_set_ts(op, O_IMM1, 16); + if (!read_stream_safe_uint(ci, &di->imm.ex.i1, sizeof(int16_t))) return FALSE; + break; + case OT_IMM8_1: + operands_set_ts(op, O_IMM1, 8); + if (!read_stream_safe_uint(ci, &di->imm.ex.i1, sizeof(int8_t))) return FALSE; + break; + case OT_IMM8_2: + operands_set_ts(op, O_IMM2, 8); + if (!read_stream_safe_uint(ci, &di->imm.ex.i2, sizeof(int8_t))) return FALSE; + break; + case OT_REG8: + operands_set_ts(op, O_REG, 8); + if (ps->prefixExtType) { + /* + * If REX prefix is valid then we will have to use low bytes. + * This is a PASSIVE behaviour changer of REX prefix, it affects operands even if its value is 0x40 ! + */ + ps->usedPrefixes |= INST_PRE_REX; + op->index = (uint8_t)operands_fix_8bit_rex_base(reg + ((vrex & PREFIX_EX_R) ? EX_GPR_BASE : 0)); + } else op->index = (uint8_t)(REGS8_BASE + reg); + break; + case OT_REG16: + operands_set_tsi(op, O_REG, 16, REGS16_BASE + reg); + break; + case OT_REG_FULL: + switch (effOpSz) + { + case Decode16Bits: + ps->usedPrefixes |= INST_PRE_OP_SIZE; + if (vrex & PREFIX_EX_R) { + ps->usedPrefixes |= INST_PRE_REX; + reg += EX_GPR_BASE; + } + operands_set_tsi(op, O_REG, 16, REGS16_BASE + reg); + break; + case Decode32Bits: + if (vrex & PREFIX_EX_R) { + ps->usedPrefixes |= INST_PRE_REX; + reg += EX_GPR_BASE; + } else ps->usedPrefixes |= INST_PRE_OP_SIZE; + operands_set_tsi(op, O_REG, 32, REGS32_BASE + reg); + break; + case Decode64Bits: /* rex must be presented. */ + ps->usedPrefixes |= INST_PRE_REX; + operands_set_tsi(op, O_REG, 64, REGS64_BASE + reg + ((vrex & PREFIX_EX_R) ? EX_GPR_BASE : 0)); + break; + } + break; + case OT_REG32: + if (vrex & PREFIX_EX_R) { + ps->usedPrefixes |= INST_PRE_REX; + reg += EX_GPR_BASE; + } + operands_set_tsi(op, O_REG, 32, REGS32_BASE + reg); + break; + case OT_REG32_64: /* Handle CVT's, MOVxX and MOVNTI instructions which could be extended to 64 bits registers with REX. */ + if (vrex & PREFIX_EX_R) { + ps->usedPrefixes |= INST_PRE_REX; + reg += EX_GPR_BASE; + } + + /* Is it a promoted instruction? (only INST_64BITS is set and REX isn't required.) */ + if ((ci->dt == Decode64Bits) && ((instFlags & (INST_64BITS | INST_PRE_REX)) == INST_64BITS)) { + operands_set_tsi(op, O_REG, 64, REGS64_BASE + reg); + break; + } + /* Give a chance to REX.W. Because if it was a promoted instruction we don't care about REX.W anyways. */ + if (vrex & PREFIX_EX_W) { + ps->usedPrefixes |= INST_PRE_REX; + operands_set_tsi(op, O_REG, 64, REGS64_BASE + reg); + } else operands_set_tsi(op, O_REG, 32, REGS32_BASE + reg); + break; + case OT_FREG32_64_RM: /* Force decoding mode. Used for MOV CR(n)/DR(n) which defaults to 64 bits operand size in 64 bits. */ + if (vrex & PREFIX_EX_B) { + ps->usedPrefixes |= INST_PRE_REX; + rm += EX_GPR_BASE; + } + + if (ci->dt == Decode64Bits) operands_set_tsi(op, O_REG, 64, REGS64_BASE + rm); + else operands_set_tsi(op, O_REG, 32, REGS32_BASE + rm); + break; + case OT_MM: /* MMX register */ + operands_set_tsi(op, O_REG, 64, MMXREGS_BASE + reg); + break; + case OT_MM_RM: /* MMX register, this time from the RM field */ + operands_set_tsi(op, O_REG, 64, MMXREGS_BASE + rm); + break; + case OT_REGXMM0: /* Implicit XMM0 operand. */ + reg = 0; + vrex = 0; + /* FALL THROUGH */ + case OT_XMM: /* SSE register */ + if (vrex & PREFIX_EX_R) { + ps->usedPrefixes |= INST_PRE_REX; + reg += EX_GPR_BASE; + } + operands_set_tsi(op, O_REG, 128, SSEREGS_BASE + reg); + break; + case OT_XMM_RM: /* SSE register, this time from the RM field */ + if (vrex & PREFIX_EX_B) { + ps->usedPrefixes |= INST_PRE_REX; + rm += EX_GPR_BASE; + } + operands_set_tsi(op, O_REG, 128, SSEREGS_BASE + rm); + break; + case OT_CREG: + /* + * Don't parse if the reg exceeds the bounds of the array. + * Most of the CR's are not implemented, so if there's no matching string, the operand is invalid. + */ + if (vrex & PREFIX_EX_R) { + ps->usedPrefixes |= INST_PRE_REX; + reg += EX_GPR_BASE; + } else if ((ci->dt == Decode32Bits) && (ps->decodedPrefixes & INST_PRE_LOCK)) { + /* + * NOTE: In 32 bits decoding mode, + * if the lock prefix is set before MOV CR(n) it will become the 4th bit of the REG field like REX.R in 64 bits. + */ + reg += EX_GPR_BASE; + ps->usedPrefixes |= INST_PRE_LOCK; + } + /* Ignore some registers which do not exist. */ + if ((reg >= CREGS_MAX) || (reg == 1) || ((reg >= 5) && (reg <= 7))) return FALSE; + + op->type = O_REG; + if (ci->dt == Decode64Bits) op->size = 64; + else op->size = 32; + op->index = (uint8_t)(CREGS_BASE + reg); + break; + case OT_DREG: + /* + * In 64 bits there are 16 debug registers. + * but accessing any of dr8-15 which aren't implemented will cause an #ud. + */ + if ((reg == 4) || (reg == 5) || (vrex & PREFIX_EX_R)) return FALSE; + + op->type = O_REG; + if (ci->dt == Decode64Bits) op->size = 64; + else op->size = 32; + op->index = (uint8_t)(DREGS_BASE + reg); + break; + case OT_SREG: /* Works with REG16 only! */ + /* If lockableInstruction pointer is non-null we know it's the first operand. */ + if (lockableInstruction && (reg == 1)) return FALSE; /* Can't MOV CS, . */ + /*Don't parse if the reg exceeds the bounds of the array. */ + if (reg <= SEG_REGS_MAX - 1) operands_set_tsi(op, O_REG, 16, SREGS_BASE + reg); + else return FALSE; + break; + case OT_SEG: + op->type = O_REG; + /* Size of reg is always 16, it's up to caller to zero extend it to operand size. */ + op->size = 16; + ps->usedPrefixes |= INST_PRE_OP_SIZE; + /* + * Extract the SEG from ii->flags this time!!! + * Check whether an operand size prefix is used. + */ + switch (instFlags & INST_PRE_SEGOVRD_MASK) + { + case INST_PRE_ES: op->index = R_ES; break; + case INST_PRE_CS: op->index = R_CS; break; + case INST_PRE_SS: op->index = R_SS; break; + case INST_PRE_DS: op->index = R_DS; break; + case INST_PRE_FS: op->index = R_FS; break; + case INST_PRE_GS: op->index = R_GS; break; + } + break; + case OT_ACC8: + operands_set_tsi(op, O_REG, 8, R_AL); + break; + case OT_ACC16: + operands_set_tsi(op, O_REG, 16, R_AX); + break; + case OT_ACC_FULL_NOT64: /* No REX.W support for IN/OUT. */ + vrex &= ~PREFIX_EX_W; + case OT_ACC_FULL: + if (effOpSz == Decode16Bits) { + ps->usedPrefixes |= INST_PRE_OP_SIZE; + operands_set_tsi(op, O_REG, 16, R_AX); + } else if (effOpSz == Decode32Bits) { + ps->usedPrefixes |= INST_PRE_OP_SIZE; + operands_set_tsi(op, O_REG, 32, R_EAX); + } else { /* Decode64Bits */ + /* Only non-promoted instructions need REX in order to decode in 64 bits. */ + /* MEM-OFFSET MOV's are NOT automatically promoted to 64 bits. */ + if (~instFlags & INST_64BITS) { + ps->usedPrefixes |= INST_PRE_REX; + } + operands_set_tsi(op, O_REG, 64, R_RAX); + } + break; + case OT_PTR16_FULL: + /* ptr16:full - full is size of operand size to read, therefore Operand Size Prefix affects this. So we need to handle it. */ + if (effOpSz == Decode16Bits) { + ps->usedPrefixes |= INST_PRE_OP_SIZE; + ci->codeLen -= sizeof(int16_t)*2; + if (ci->codeLen < 0) return FALSE; + + operands_set_ts(op, O_PTR, 16); + di->imm.ptr.off = RUSHORT(ci->code); /* Read offset first. */ + di->imm.ptr.seg = RUSHORT((ci->code + sizeof(int16_t))); /* And read segment. */ + + ci->code += sizeof(int16_t)*2; + } else { /* Decode32Bits, for Decode64Bits this instruction is invalid. */ + ps->usedPrefixes |= INST_PRE_OP_SIZE; + ci->codeLen -= sizeof(int32_t) + sizeof(int16_t); + if (ci->codeLen < 0) return FALSE; + + operands_set_ts(op, O_PTR, 32); + di->imm.ptr.off = RULONG(ci->code); /* Read 32bits offset this time. */ + di->imm.ptr.seg = RUSHORT((ci->code + sizeof(int32_t))); /* And read segment, 16 bits. */ + + ci->code += sizeof(int32_t) + sizeof(int16_t); + } + break; + case OT_RELCB: + case OT_RELC_FULL: + + if (type == OT_RELCB) { + operands_set_ts(op, O_PC, 8); + if (!read_stream_safe_sint(ci, &di->imm.sqword, sizeof(int8_t))) return FALSE; + } else { /* OT_RELC_FULL */ + + /* Yep, operand size prefix affects relc also. */ + ps->usedPrefixes |= INST_PRE_OP_SIZE; + if (effOpSz == Decode16Bits) { + operands_set_ts(op, O_PC, 16); + if (!read_stream_safe_sint(ci, &di->imm.sqword, sizeof(int16_t))) return FALSE; + } else { /* Decode32Bits or Decode64Bits = for now they are the same */ + operands_set_ts(op, O_PC, 32); + if (!read_stream_safe_sint(ci, &di->imm.sqword, sizeof(int32_t))) return FALSE; + } + } + + /* Support for hint, see if there's a segment override. */ + if ((ii->opcodeId >= I_JO) && (ii->opcodeId <= I_JG)) { + if (ps->decodedPrefixes & INST_PRE_CS) { + ps->usedPrefixes |= INST_PRE_CS; + di->flags |= FLAG_HINT_NOT_TAKEN; + } else if (ps->decodedPrefixes & INST_PRE_DS) { + ps->usedPrefixes |= INST_PRE_DS; + di->flags |= FLAG_HINT_TAKEN; + } + } + break; + case OT_MOFFS8: + op->size = 8; + /* FALL THROUGH, size won't be changed. */ + case OT_MOFFS_FULL: + op->type = O_DISP; + if (op->size == 0) { + /* Calculate size of operand (same as ACC size). */ + switch (effOpSz) + { + case Decode16Bits: op->size = 16; break; + case Decode32Bits: op->size = 32; break; + case Decode64Bits: op->size = 64; break; + } + } + + prefixes_use_segment(INST_PRE_DS, ps, ci->dt, di); + + /* + * Just a pointer to a BYTE, WORD, DWORD, QWORD. Works only with ACC8/16/32/64 respectively. + * MOV [0x1234], AL ; MOV AX, [0x1234] ; MOV EAX, [0x1234], note that R/E/AX will be chosen by OT_ACC_FULL. + */ + if (effAdrSz == Decode16Bits) { + ps->usedPrefixes |= INST_PRE_ADDR_SIZE; + + di->dispSize = 16; + if (!read_stream_safe_uint(ci, &di->disp, sizeof(int16_t))) return FALSE; + } else if (effAdrSz == Decode32Bits) { + ps->usedPrefixes |= INST_PRE_ADDR_SIZE; + + di->dispSize = 32; + if (!read_stream_safe_uint(ci, &di->disp, sizeof(int32_t))) return FALSE; + } else { /* Decode64Bits */ + di->dispSize = 64; + if (!read_stream_safe_uint(ci, &di->disp, sizeof(int64_t))) return FALSE; + } + break; + case OT_CONST1: + operands_set_ts(op, O_IMM, 8); + di->imm.byte = 1; + break; + case OT_REGCL: + operands_set_tsi(op, O_REG, 8, R_CL); + break; + + case OT_FPU_SI: + /* Low 3 bits specify the REG, similar to the MODR/M byte reg. */ + operands_set_tsi(op, O_REG, 32, FPUREGS_BASE + (*(ci->code-1) & 7)); + break; + case OT_FPU_SSI: + operands_set_tsi(op, O_REG, 32, R_ST0); + operands_set_tsi(op + 1, O_REG, 32, FPUREGS_BASE + (*(ci->code-1) & 7)); + break; + case OT_FPU_SIS: + operands_set_tsi(op, O_REG, 32, FPUREGS_BASE + (*(ci->code-1) & 7)); + operands_set_tsi(op + 1, O_REG, 32, R_ST0); + break; + + /* + * Special treatment for Instructions-Block: + * INC/DEC (only 16/32 bits) /PUSH/POP/XCHG instructions, which get their REG from their own binary code. + + * Notice these instructions are 1 or 2 byte long, + * code points after the byte which represents the instruction itself, + * thus, even if the instructions are 2 bytes long it will read its last byte which contains the REG info. + */ + case OT_IB_RB: + /* Low 3 bits specify the REG, similar to the MODR/M byte reg. */ + operands_set_ts(op, O_REG, 8); + reg = *(ci->code-1) & 7; + if (vrex & PREFIX_EX_B) { + ps->usedPrefixes |= INST_PRE_REX; + op->index = (uint8_t)operands_fix_8bit_rex_base(reg + EX_GPR_BASE); + } else if (ps->prefixExtType == PET_REX) { + ps->usedPrefixes |= INST_PRE_REX; + op->index = (uint8_t)operands_fix_8bit_rex_base(reg); + } else op->index = (uint8_t)(REGS8_BASE + reg); + break; + case OT_IB_R_FULL: + reg = *(ci->code-1) & 7; + switch (effOpSz) + { + case Decode16Bits: + ps->usedPrefixes |= INST_PRE_OP_SIZE; + if (vrex & PREFIX_EX_B) { + ps->usedPrefixes |= INST_PRE_REX; + reg += EX_GPR_BASE; + } + operands_set_tsi(op, O_REG, 16, REGS16_BASE + reg); + break; + case Decode32Bits: + if (vrex & PREFIX_EX_B) { + ps->usedPrefixes |= INST_PRE_REX; + reg += EX_GPR_BASE; + } else ps->usedPrefixes |= INST_PRE_OP_SIZE; + operands_set_tsi(op, O_REG, 32, REGS32_BASE + reg); + break; + case Decode64Bits: + /* + * Automatically promoted instruction can drop REX prefix if not required. + * PUSH/POP defaults to 64 bits. --> INST_64BITS + * MOV imm64 / BSWAP requires REX.W to be 64 bits --> INST_64BITS | INST_PRE_REX + */ + if ((instFlags & INST_64BITS) && ((instFlags & INST_PRE_REX) == 0)) { + if (vrex & PREFIX_EX_B) { + ps->usedPrefixes |= INST_PRE_REX; + reg += EX_GPR_BASE; + } + } else { + ps->usedPrefixes |= INST_PRE_REX; + reg += (vrex & PREFIX_EX_B) ? EX_GPR_BASE : 0; + } + operands_set_tsi(op, O_REG, 64, REGS64_BASE + reg); + break; + } + break; + + /* + * Special treatment for repeatable instructions. + + * We want the following output: + * If there's only the REP/NZ prefix, we won't output anything (All operands are implicit). + * If there's an operand size prefix, we will change the suffix letter of the mnemonic, which specifies the size of operand to the required one. + * If there's a segment override prefix, we will output the segment and the used index register (EDI/ESI). + * If there's an address size prefix, we will output the (segment if needed and) the used and inverted index register (DI/SI). + + * Example: + * :: Decoding in 16 bits mode! :: + * AD ~ LODSW + * 66 AD ~ LODSD + * F3 AC ~ REP LODSB + * F3 66 AD ~ REP LODSD + * F3 3E AC ~ REP LODS BYTE DS:[SI] + * F3 67 AD ~ REP LODS WORD [ESI] + + * The basic form of a repeatable instruction has its operands hidden and has a suffix letter + * which implies on the size of operation being done. + * Therefore, we cannot change the mnemonic here when we encounter another prefix and its not the decoder's responsibility to do so. + * That's why the caller is responsible to add the suffix letter if no other prefixes are used. + * And all we are doing here is formatting the operand correctly. + */ + case OT_REGI_ESI: + ps->usedPrefixes |= INST_PRE_ADDR_SIZE; + + op->type = O_SMEM; + + /* This might be a 16, 32 or 64 bits instruction, depends on the decoding mode. */ + if (instFlags & INST_16BITS) { + ps->usedPrefixes |= INST_PRE_OP_SIZE; + + if (effOpSz == Decode16Bits) op->size = 16; + else if ((effOpSz == Decode64Bits) && (instFlags & INST_64BITS)) { + ps->usedPrefixes |= INST_PRE_REX; + op->size = 64; + } else op->size = 32; + } else op->size = 8; + + /* + * Clear segment in case OT_REGI_EDI was parsed earlier, + * DS can be overridden and therefore has precedence. + */ + di->segment = 0; + prefixes_use_segment(INST_PRE_DS, ps, ci->dt, di); + + if (effAdrSz == Decode16Bits) op->index = R_SI; + else if (effAdrSz == Decode32Bits) op->index = R_ESI; + else op->index = R_RSI; + break; + case OT_REGI_EDI: + ps->usedPrefixes |= INST_PRE_ADDR_SIZE; + + op->type = O_SMEM; + + /* This might be a 16 or 32 bits instruction, depends on the decoding mode. */ + if (instFlags & INST_16BITS) { + ps->usedPrefixes |= INST_PRE_OP_SIZE; + + if (effOpSz == Decode16Bits) op->size = 16; + else if ((effOpSz == Decode64Bits) && (instFlags & INST_64BITS)) { + ps->usedPrefixes |= INST_PRE_REX; + op->size = 64; + } else op->size = 32; + } else op->size = 8; + + /* Note: The [rDI] operand can't be prefixed by a segment override, therefore we don't set usedPrefixes. */ + if ((opNum == ONT_1) && (ci->dt != Decode64Bits)) di->segment = R_ES | SEGMENT_DEFAULT; /* No ES in 64 bits mode. */ + + if (effAdrSz == Decode16Bits) op->index = R_DI; + else if (effAdrSz == Decode32Bits) op->index = R_EDI; + else op->index = R_RDI; + break; + + /* Used for In/Out instructions varying forms. */ + case OT_REGDX: + /* Simple single IN/OUT instruction. */ + operands_set_tsi(op, O_REG, 16, R_DX); + break; + + /* Used for INVLPGA instruction. */ + case OT_REGECX: + operands_set_tsi(op, O_REG, 32, R_ECX); + break; + case OT_REGI_EBXAL: + /* XLAT BYTE [rBX + AL] */ + ps->usedPrefixes |= INST_PRE_ADDR_SIZE; + + prefixes_use_segment(INST_PRE_DS, ps, ci->dt, di); + + /* Size of deref is always 8 for xlat. */ + operands_set_tsi(op, O_MEM, 8, R_AL); + + if (effAdrSz == Decode16Bits) di->base = R_BX; + else if (effAdrSz == Decode32Bits) di->base = R_EBX; + else { + ps->usedPrefixes |= INST_PRE_REX; + di->base = R_RBX; + } + break; + case OT_REGI_EAX: + /* + * Implicit rAX as memory indirection operand. Used by AMD's SVM instructions. + * Since this is a memory indirection, the default address size in 64bits decoding mode is 64. + */ + + if (effAdrSz == Decode64Bits) operands_set_tsi(op, O_SMEM, 64, R_RAX); + else if (effAdrSz == Decode32Bits) { + ps->usedPrefixes |= INST_PRE_ADDR_SIZE; + operands_set_tsi(op, O_SMEM, 32, R_EAX); + } else { + ps->usedPrefixes |= INST_PRE_ADDR_SIZE; + operands_set_tsi(op, O_SMEM, 16, R_AX); + } + break; + case OT_VXMM: + operands_set_tsi(op, O_REG, 128, SSEREGS_BASE + vexV); + break; + case OT_XMM_IMM: + ci->codeLen -= sizeof(int8_t); + if (ci->codeLen < 0) return FALSE; + + if (ci->dt == Decode32Bits) reg = (*ci->code >> 4) & 0x7; + else reg = (*ci->code >> 4) & 0xf; + operands_set_tsi(op, O_REG, 128, SSEREGS_BASE + reg); + + ci->code += sizeof(int8_t); + break; + case OT_YXMM: + if (vrex & PREFIX_EX_R) reg += EX_GPR_BASE; + if (ps->vrex & PREFIX_EX_L) operands_set_tsi(op, O_REG, 256, AVXREGS_BASE + reg); + else operands_set_tsi(op, O_REG, 128, SSEREGS_BASE + reg); + break; + case OT_YXMM_IMM: + ci->codeLen -= sizeof(int8_t); + if (ci->codeLen < 0) return FALSE; + + if (ci->dt == Decode32Bits) reg = (*ci->code >> 4) & 0x7; + else reg = (*ci->code >> 4) & 0xf; + + if (ps->vrex & PREFIX_EX_L) operands_set_tsi(op, O_REG, 256, AVXREGS_BASE + reg); + else operands_set_tsi(op, O_REG, 128, SSEREGS_BASE + reg); + + ci->code += sizeof(int8_t); + break; + case OT_YMM: + if (vrex & PREFIX_EX_R) reg += EX_GPR_BASE; + operands_set_tsi(op, O_REG, 256, AVXREGS_BASE + reg); + break; + case OT_VYMM: + operands_set_tsi(op, O_REG, 256, AVXREGS_BASE + vexV); + break; + case OT_VYXMM: + if (ps->vrex & PREFIX_EX_L) operands_set_tsi(op, O_REG, 256, AVXREGS_BASE + vexV); + else operands_set_tsi(op, O_REG, 128, SSEREGS_BASE + vexV); + break; + case OT_WREG32_64: + if (vrex & PREFIX_EX_R) reg += EX_GPR_BASE; + if (ps->vrex & PREFIX_EX_W) operands_set_tsi(op, O_REG, 64, REGS64_BASE + reg); + else operands_set_tsi(op, O_REG, 32, REGS32_BASE + reg); + break; + default: return FALSE; + } + + if ((op->type == O_REG) || (op->type == O_SMEM) || (op->type == O_MEM)) { + di->usedRegistersMask |= _REGISTERTORCLASS[op->index]; + } + + return TRUE; +} diff --git a/distorm3.2-package/src/operands.h b/distorm3.2-package/src/operands.h new file mode 100644 index 0000000..e1beb6f --- /dev/null +++ b/distorm3.2-package/src/operands.h @@ -0,0 +1,40 @@ +/* +operands.h + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2012 Gil Dabah + +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 +*/ + + +#ifndef OPERANDS_H +#define OPERANDS_H + +#include "config.h" +#include "decoder.h" +#include "prefix.h" +#include "instructions.h" + + +extern uint16_t _REGISTERTORCLASS[]; + +int operands_extract(_CodeInfo* ci, _DInst* di, _InstInfo* ii, + _OpType type, _OperandNumberType opNum, + unsigned int modrm, _PrefixState* ps, _DecodeType effOpSz, + _DecodeType effAdrSz, int* lockableInstruction); + +#endif /* OPERANDS_H */ diff --git a/distorm3.2-package/src/prefix.c b/distorm3.2-package/src/prefix.c new file mode 100644 index 0000000..53f09b6 --- /dev/null +++ b/distorm3.2-package/src/prefix.c @@ -0,0 +1,380 @@ +/* +prefix.c + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2012 Gil Dabah + +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 +*/ + + +#include "prefix.h" + +#include "x86defs.h" +#include "instructions.h" +#include "../include/mnemonics.h" + + +/* + * The main purpose of this module is to keep track of all kind of prefixes a single instruction may have. + * The problem is that a single instruction may have up to six different prefix-types. + * That's why I have to detect such cases and drop those excess prefixes. + */ + +int prefixes_is_valid(unsigned int ch, _DecodeType dt) +{ + switch (ch) { + /* for i in xrange(0x40, 0x50): print "case 0x%2x:" % i */ + case 0x40: /* REX: */ + case 0x41: + case 0x42: + case 0x43: + case 0x44: + case 0x45: + case 0x46: + case 0x47: + case 0x48: + case 0x49: + case 0x4a: + case 0x4b: + case 0x4c: + case 0x4d: + case 0x4e: + case 0x4f: return (dt == Decode64Bits); + case PREFIX_LOCK: return TRUE; + case PREFIX_REPNZ: return TRUE; + case PREFIX_REP: return TRUE; + case PREFIX_CS: return TRUE; + case PREFIX_SS: return TRUE; + case PREFIX_DS: return TRUE; + case PREFIX_ES: return TRUE; + case PREFIX_FS: return TRUE; + case PREFIX_GS: return TRUE; + case PREFIX_OP_SIZE: return TRUE; + case PREFIX_ADDR_SIZE: return TRUE; + /* The VEXs might be false positives, the decode_perfixes will determine for sure. */ + case PREFIX_VEX2b: /* VEX is supported for all modes, because 16 bits Pmode is included. */ + case PREFIX_VEX3b: return TRUE; + } + return FALSE; +} + +/* Ignore a specific prefix type. */ +void prefixes_ignore(_PrefixState* ps, _PrefixIndexer pi) +{ + /* + * If that type of prefix appeared already, set the bit of that *former* prefix. + * Anyway, set the new index of that prefix type to the current index, so next time we know its position. + */ + if (ps->pfxIndexer[pi] != PFXIDX_NONE) ps->unusedPrefixesMask |= (1 << ps->pfxIndexer[pi]); +} + +/* Ignore all prefix. */ +void prefixes_ignore_all(_PrefixState* ps) +{ + int i; + for (i = 0; i < PFXIDX_MAX; i++) + prefixes_ignore(ps, i); +} + +/* Calculates which prefixes weren't used and accordingly sets the bits in the unusedPrefixesMask. */ +uint16_t prefixes_set_unused_mask(_PrefixState* ps) +{ + /* + * The decodedPrefixes represents the prefixes that were *read* from the binary stream for the instruction. + * The usedPrefixes represents the prefixes that were actually used by the instruction in the *decode* phase. + * Xoring between the two will result in a 'diff' which returns the prefixes that were read + * from the stream *and* that were never used in the actual decoding. + * + * Only one prefix per type can be set in decodedPrefixes from the stream. + * Therefore it's enough to check each type once and set the flag accordingly. + * That's why we had to book-keep each prefix type and its position. + * So now we know which bits we need to set exactly in the mask. + */ + _iflags unusedPrefixesDiff = ps->decodedPrefixes ^ ps->usedPrefixes; + + /* Examine unused prefixes by type: */ + /* + * About REX: it might be set in the diff although it was never in the stream itself. + * This is because the vrex is shared between VEX and REX and some places flag it as REX usage, while + * we were really decoding an AVX instruction. + * It's not a big problem, because the prefixes_ignore func will ignore it anyway, + * since it wasn't seen earlier. But it's important to know this. + */ + if (unusedPrefixesDiff & INST_PRE_REX) prefixes_ignore(ps, PFXIDX_REX); + if (unusedPrefixesDiff & INST_PRE_SEGOVRD_MASK) prefixes_ignore(ps, PFXIDX_SEG); + if (unusedPrefixesDiff & INST_PRE_LOKREP_MASK) prefixes_ignore(ps, PFXIDX_LOREP); + if (unusedPrefixesDiff & INST_PRE_OP_SIZE) prefixes_ignore(ps, PFXIDX_OP_SIZE); + if (unusedPrefixesDiff & INST_PRE_ADDR_SIZE) prefixes_ignore(ps, PFXIDX_ADRS); + /* If a VEX instruction was found, its prefix is considered as used, therefore no point for checking for it. */ + + return ps->unusedPrefixesMask; +} + +/* + * Mark a prefix as unused, and bookkeep where we last saw this same type, + * because in the future we might want to disable it too. + */ +_INLINE_ void prefixes_track_unused(_PrefixState* ps, int index, _PrefixIndexer pi) +{ + prefixes_ignore(ps, pi); + /* Book-keep the current index for this type. */ + ps->pfxIndexer[pi] = index; +} + +/* + * Read as many prefixes as possible, up to 15 bytes, and halt when we encounter non-prefix byte. + * This algorithm tries to imitate a real processor, where the same prefix can appear a few times, etc. + * The tiny complexity is that we want to know when a prefix was superfluous and mark any copy of it as unused. + * Note that the last prefix of its type will be considered as used, and all the others (of same type) before it as unused. + */ +void prefixes_decode(const uint8_t* code, int codeLen, _PrefixState* ps, _DecodeType dt) +{ + int index, done; + uint8_t vex; + + /* + * First thing to do, scan for prefixes, there are six types of prefixes. + * There may be up to six prefixes before a single instruction, not the same type, no special order, + * except REX/VEX must precede immediately the first opcode byte. + * BTW - This is the reason why I didn't make the REP prefixes part of the instructions (STOS/SCAS/etc). + * + * Another thing, the instruction maximum size is 15 bytes, thus if we read more than 15 bytes, we will halt. + * + * We attach all prefixes to the next instruction, there might be two or more occurrences from the same prefix. + * Also, since VEX can be allowed only once we will test it separately. + */ + for (index = 0, done = FALSE; + (codeLen > 0) && (code - ps->start < INST_MAXIMUM_SIZE); + code++, codeLen--, index++) { + /* + NOTE: AMD treat lock/rep as two different groups... But I am based on Intel. + + - Lock and Repeat: + - 0xF0 — LOCK + - 0xF2 — REPNE/REPNZ + - 0xF3 - REP/REPE/REPZ + - Segment Override: + - 0x2E - CS + - 0x36 - SS + - 0x3E - DS + - 0x26 - ES + - 0x64 - FS + - 0x65 - GS + - Operand-Size Override: 0x66, switching default size. + - Address-Size Override: 0x67, switching default size. + + 64 Bits: + - REX: 0x40 - 0x4f, extends register access. + - 2 Bytes VEX: 0xc4 + - 3 Bytes VEX: 0xc5 + 32 Bits: + - 2 Bytes VEX: 0xc4 11xx-xxxx + - 3 Bytes VEX: 0xc5 11xx-xxxx + */ + + /* Examine what type of prefix we got. */ + switch (*code) + { + /* REX type, 64 bits decoding mode only: */ + case 0x40: + case 0x41: + case 0x42: + case 0x43: + case 0x44: + case 0x45: + case 0x46: + case 0x47: + case 0x48: + case 0x49: + case 0x4a: + case 0x4b: + case 0x4c: + case 0x4d: + case 0x4e: + case 0x4f: + if (dt == Decode64Bits) { + ps->decodedPrefixes |= INST_PRE_REX; + ps->vrex = *code & 0xf; /* Keep only BXRW. */ + ps->rexPos = code; + ps->prefixExtType = PET_REX; + prefixes_track_unused(ps, index, PFXIDX_REX); + } else done = TRUE; /* If we are not in 64 bits mode, it's an instruction, then halt. */ + break; + + /* LOCK and REPx type: */ + case PREFIX_LOCK: + ps->decodedPrefixes |= INST_PRE_LOCK; + prefixes_track_unused(ps, index, PFXIDX_LOREP); + break; + case PREFIX_REPNZ: + ps->decodedPrefixes |= INST_PRE_REPNZ; + prefixes_track_unused(ps, index, PFXIDX_LOREP); + break; + case PREFIX_REP: + ps->decodedPrefixes |= INST_PRE_REP; + prefixes_track_unused(ps, index, PFXIDX_LOREP); + break; + + /* Seg Overide type: */ + case PREFIX_CS: + ps->decodedPrefixes |= INST_PRE_CS; + prefixes_track_unused(ps, index, PFXIDX_SEG); + break; + case PREFIX_SS: + ps->decodedPrefixes |= INST_PRE_SS; + prefixes_track_unused(ps, index, PFXIDX_SEG); + break; + case PREFIX_DS: + ps->decodedPrefixes |= INST_PRE_DS; + prefixes_track_unused(ps, index, PFXIDX_SEG); + break; + case PREFIX_ES: + ps->decodedPrefixes |= INST_PRE_ES; + prefixes_track_unused(ps, index, PFXIDX_SEG); + break; + case PREFIX_FS: + ps->decodedPrefixes |= INST_PRE_FS; + prefixes_track_unused(ps, index, PFXIDX_SEG); + break; + case PREFIX_GS: + ps->decodedPrefixes |= INST_PRE_GS; + prefixes_track_unused(ps, index, PFXIDX_SEG); + break; + + /* Op Size type: */ + case PREFIX_OP_SIZE: + ps->decodedPrefixes |= INST_PRE_OP_SIZE; + prefixes_track_unused(ps, index, PFXIDX_OP_SIZE); + break; + + /* Addr Size type: */ + case PREFIX_ADDR_SIZE: + ps->decodedPrefixes |= INST_PRE_ADDR_SIZE; + prefixes_track_unused(ps, index, PFXIDX_ADRS); + break; + + /* Non-prefix byte now, so break 2. */ + default: done = TRUE; break; + } + if (done) break; + } + + /* 2 Bytes VEX: */ + if ((codeLen >= 2) && + (*code == PREFIX_VEX2b) && + ((code - ps->start) <= INST_MAXIMUM_SIZE - 2)) { + /* + * In 32 bits the second byte has to be in the special range of Mod=11. + * Otherwise it might be a normal LDS instruction. + */ + if ((dt == Decode64Bits) || (*(code + 1) >= INST_DIVIDED_MODRM)) { + ps->vexPos = code + 1; + ps->decodedPrefixes |= INST_PRE_VEX; + ps->prefixExtType = PET_VEX2BYTES; + + /* + * VEX 1 byte bits: + * |7-6--3-2-10| + * |R|vvvv|L|pp| + * |-----------| + */ + + /* -- Convert from VEX prefix to VREX flags -- */ + vex = *ps->vexPos; + if (~vex & 0x80 && dt == Decode64Bits) ps->vrex |= PREFIX_EX_R; /* Convert VEX.R. */ + if (vex & 4) ps->vrex |= PREFIX_EX_L; /* Convert VEX.L. */ + + code += 2; + } + } + + /* 3 Bytes VEX: */ + if ((codeLen >= 3) && + (*code == PREFIX_VEX3b) && + ((code - ps->start) <= INST_MAXIMUM_SIZE - 3) && + (~ps->decodedPrefixes & INST_PRE_VEX)) { + /* + * In 32 bits the second byte has to be in the special range of Mod=11. + * Otherwise it might be a normal LES instruction. + * And we don't care now about the 3rd byte. + */ + if ((dt == Decode64Bits) || (*(code + 1) >= INST_DIVIDED_MODRM)) { + ps->vexPos = code + 1; + ps->decodedPrefixes |= INST_PRE_VEX; + ps->prefixExtType = PET_VEX3BYTES; + + /* + * VEX first and second bytes: + * |7-6-5-4----0| |7-6--3-2-10| + * |R|X|B|m-mmmm| |W|vvvv|L|pp| + * |------------| |-----------| + */ + + /* -- Convert from VEX prefix to VREX flags -- */ + vex = *ps->vexPos; + ps->vrex |= ((~vex >> 5) & 0x7); /* Shift and invert VEX.R/X/B to their place */ + vex = *(ps->vexPos + 1); + if (vex & 4) ps->vrex |= PREFIX_EX_L; /* Convert VEX.L. */ + if (vex & 0x80) ps->vrex |= PREFIX_EX_W; /* Convert VEX.W. */ + + /* Clear some flags if the mode isn't 64 bits. */ + if (dt != Decode64Bits) ps->vrex &= ~(PREFIX_EX_B | PREFIX_EX_X | PREFIX_EX_R | PREFIX_EX_W); + + code += 3; + } + } + + /* + * Save last byte scanned address, so the decoder could keep on scanning from this point and on and on and on. + * In addition the decoder is able to know that the last byte could lead to MMX/SSE instructions (preceding REX if exists). + */ + ps->last = code; /* ps->last points to an opcode byte. */ +} + +/* + * For every memory-indirection operand we want to set its corresponding default segment. + * If the segment is being overrided, we need to see whether we use it or not. + * We will use it only if it's not the default one already. + */ +void prefixes_use_segment(_iflags defaultSeg, _PrefixState* ps, _DecodeType dt, _DInst* di) +{ + _iflags flags = 0; + if (dt == Decode64Bits) flags = ps->decodedPrefixes & INST_PRE_SEGOVRD_MASK64; + else flags = ps->decodedPrefixes & INST_PRE_SEGOVRD_MASK; + + if ((flags == 0) || (flags == defaultSeg)) { + flags = defaultSeg; + di->segment |= SEGMENT_DEFAULT; + } else if (flags != defaultSeg) { + /* Use it only if it's non-default segment. */ + ps->usedPrefixes |= flags; + } + + /* ASSERT: R_XX must be below 128. */ + switch (flags) + { + case INST_PRE_ES: di->segment |= R_ES; break; + case INST_PRE_CS: di->segment |= R_CS; break; + case INST_PRE_SS: di->segment |= R_SS; break; + case INST_PRE_DS: di->segment |= R_DS; break; + case INST_PRE_FS: di->segment |= R_FS; break; + case INST_PRE_GS: di->segment |= R_GS; break; + } + + /* If it's one of the CS,SS,DS,ES and the mode is 64 bits, set segment it to none, since it's ignored. */ + if ((dt == Decode64Bits) && (flags & INST_PRE_SEGOVRD_MASK32)) di->segment = R_NONE; +} diff --git a/distorm3.2-package/src/prefix.h b/distorm3.2-package/src/prefix.h new file mode 100644 index 0000000..673aa50 --- /dev/null +++ b/distorm3.2-package/src/prefix.h @@ -0,0 +1,76 @@ +/* +prefix.h + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2012 Gil Dabah + +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 +*/ + + +#ifndef PREFIX_H +#define PREFIX_H + +#include "config.h" +#include "decoder.h" + + +/* Specifies the type of the extension prefix, such as: REX, 2 bytes VEX, 3 bytes VEX. */ +typedef enum {PET_NONE = 0, PET_REX, PET_VEX2BYTES, PET_VEX3BYTES} _PrefixExtType; + +/* Specifies an index into a table of prefixes by their type. */ +typedef enum {PFXIDX_NONE = -1, PFXIDX_REX, PFXIDX_LOREP, PFXIDX_SEG, PFXIDX_OP_SIZE, PFXIDX_ADRS, PFXIDX_MAX} _PrefixIndexer; + +/* +* This holds the prefixes state for the current instruction we decode. +* decodedPrefixes includes all specific prefixes that the instruction got. +* start is a pointer to the first prefix to take into account. +* last is a pointer to the last byte we scanned. +* Other pointers are used to keep track of prefixes positions and help us know if they appeared already and where. +*/ +typedef struct { + _iflags decodedPrefixes, usedPrefixes; + const uint8_t *start, *last, *vexPos, *rexPos; + _PrefixExtType prefixExtType; + uint16_t unusedPrefixesMask; + /* Indicates whether the operand size prefix (0x66) was used as a mandatory prefix. */ + int isOpSizeMandatory; + /* If VEX prefix is used, store the VEX.vvvv field. */ + unsigned int vexV; + /* The fields B/X/R/W/L of REX and VEX are stored together in this byte. */ + unsigned int vrex; + + /* !! Make sure pfxIndexer is LAST! Otherwise memset won't work well with it. !! */ + + /* Holds the offset to the prefix byte by its type. */ + int pfxIndexer[PFXIDX_MAX]; +} _PrefixState; + +/* +* Intel supports 6 types of prefixes, whereas AMD supports 5 types (lock is seperated from rep/nz). +* REX is the fifth prefix type, this time I'm based on AMD64. +* VEX is the 6th, though it can't be repeated. +*/ +#define MAX_PREFIXES (5) + +int prefixes_is_valid(unsigned int ch, _DecodeType dt); +void prefixes_ignore(_PrefixState* ps, _PrefixIndexer pi); +void prefixes_ignore_all(_PrefixState* ps); +uint16_t prefixes_set_unused_mask(_PrefixState* ps); +void prefixes_decode(const uint8_t* code, int codeLen, _PrefixState* ps, _DecodeType dt); +void prefixes_use_segment(_iflags defaultSeg, _PrefixState* ps, _DecodeType dt, _DInst* di); + +#endif /* PREFIX_H */ diff --git a/distorm3.2-package/src/textdefs.c b/distorm3.2-package/src/textdefs.c new file mode 100644 index 0000000..eec26f1 --- /dev/null +++ b/distorm3.2-package/src/textdefs.c @@ -0,0 +1,184 @@ +/* +textdefs.c + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2012 Gil Dabah + +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 +*/ + + +#include "textdefs.h" + +#ifndef DISTORM_LIGHT + +static uint8_t Nibble2ChrTable[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; +#define NIBBLE_TO_CHR Nibble2ChrTable[t] + +void _FASTCALL_ str_hex_b(_WString* s, unsigned int x) +{ + /* + * def prebuilt(): + * s = "" + * for i in xrange(256): + * if ((i % 0x10) == 0): + * s += "\r\n" + * s += "\"%02x\", " % (i) + * return s + */ + static int8_t TextBTable[256][3] = { + "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0a", "0b", "0c", "0d", "0e", "0f", + "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1a", "1b", "1c", "1d", "1e", "1f", + "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2a", "2b", "2c", "2d", "2e", "2f", + "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3a", "3b", "3c", "3d", "3e", "3f", + "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4a", "4b", "4c", "4d", "4e", "4f", + "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5a", "5b", "5c", "5d", "5e", "5f", + "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6a", "6b", "6c", "6d", "6e", "6f", + "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7a", "7b", "7c", "7d", "7e", "7f", + "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8a", "8b", "8c", "8d", "8e", "8f", + "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9a", "9b", "9c", "9d", "9e", "9f", + "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "aa", "ab", "ac", "ad", "ae", "af", + "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8", "b9", "ba", "bb", "bc", "bd", "be", "bf", + "c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9", "ca", "cb", "cc", "cd", "ce", "cf", + "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "da", "db", "dc", "dd", "de", "df", + "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9", "ea", "eb", "ec", "ed", "ee", "ef", + "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "fa", "fb", "fc", "fd", "fe", "ff" + }; + + /* + * Fixed length of 3 including null terminate character. + */ + memcpy(&s->p[s->length], TextBTable[x & 255], 3); + s->length += 2; +} + +void _FASTCALL_ str_code_hb(_WString* s, unsigned int x) +{ + static int8_t TextHBTable[256][5] = { + /* + * def prebuilt(): + * s = "" + * for i in xrange(256): + * if ((i % 0x10) == 0): + * s += "\r\n" + * s += "\"0x%x\", " % (i) + * return s + */ + "0x0", "0x1", "0x2", "0x3", "0x4", "0x5", "0x6", "0x7", "0x8", "0x9", "0xa", "0xb", "0xc", "0xd", "0xe", "0xf", + "0x10", "0x11", "0x12", "0x13", "0x14", "0x15", "0x16", "0x17", "0x18", "0x19", "0x1a", "0x1b", "0x1c", "0x1d", "0x1e", "0x1f", + "0x20", "0x21", "0x22", "0x23", "0x24", "0x25", "0x26", "0x27", "0x28", "0x29", "0x2a", "0x2b", "0x2c", "0x2d", "0x2e", "0x2f", + "0x30", "0x31", "0x32", "0x33", "0x34", "0x35", "0x36", "0x37", "0x38", "0x39", "0x3a", "0x3b", "0x3c", "0x3d", "0x3e", "0x3f", + "0x40", "0x41", "0x42", "0x43", "0x44", "0x45", "0x46", "0x47", "0x48", "0x49", "0x4a", "0x4b", "0x4c", "0x4d", "0x4e", "0x4f", + "0x50", "0x51", "0x52", "0x53", "0x54", "0x55", "0x56", "0x57", "0x58", "0x59", "0x5a", "0x5b", "0x5c", "0x5d", "0x5e", "0x5f", + "0x60", "0x61", "0x62", "0x63", "0x64", "0x65", "0x66", "0x67", "0x68", "0x69", "0x6a", "0x6b", "0x6c", "0x6d", "0x6e", "0x6f", + "0x70", "0x71", "0x72", "0x73", "0x74", "0x75", "0x76", "0x77", "0x78", "0x79", "0x7a", "0x7b", "0x7c", "0x7d", "0x7e", "0x7f", + "0x80", "0x81", "0x82", "0x83", "0x84", "0x85", "0x86", "0x87", "0x88", "0x89", "0x8a", "0x8b", "0x8c", "0x8d", "0x8e", "0x8f", + "0x90", "0x91", "0x92", "0x93", "0x94", "0x95", "0x96", "0x97", "0x98", "0x99", "0x9a", "0x9b", "0x9c", "0x9d", "0x9e", "0x9f", + "0xa0", "0xa1", "0xa2", "0xa3", "0xa4", "0xa5", "0xa6", "0xa7", "0xa8", "0xa9", "0xaa", "0xab", "0xac", "0xad", "0xae", "0xaf", + "0xb0", "0xb1", "0xb2", "0xb3", "0xb4", "0xb5", "0xb6", "0xb7", "0xb8", "0xb9", "0xba", "0xbb", "0xbc", "0xbd", "0xbe", "0xbf", + "0xc0", "0xc1", "0xc2", "0xc3", "0xc4", "0xc5", "0xc6", "0xc7", "0xc8", "0xc9", "0xca", "0xcb", "0xcc", "0xcd", "0xce", "0xcf", + "0xd0", "0xd1", "0xd2", "0xd3", "0xd4", "0xd5", "0xd6", "0xd7", "0xd8", "0xd9", "0xda", "0xdb", "0xdc", "0xdd", "0xde", "0xdf", + "0xe0", "0xe1", "0xe2", "0xe3", "0xe4", "0xe5", "0xe6", "0xe7", "0xe8", "0xe9", "0xea", "0xeb", "0xec", "0xed", "0xee", "0xef", + "0xf0", "0xf1", "0xf2", "0xf3", "0xf4", "0xf5", "0xf6", "0xf7", "0xf8", "0xf9", "0xfa", "0xfb", "0xfc", "0xfd", "0xfe", "0xff" + }; + + if (x < 0x10) { /* < 0x10 has a fixed length of 4 including null terminate. */ + memcpy(&s->p[s->length], TextHBTable[x & 255], 4); + s->length += 3; + } else { /* >= 0x10 has a fixed length of 5 including null terminate. */ + memcpy(&s->p[s->length], TextHBTable[x & 255], 5); + s->length += 4; + } +} + +void _FASTCALL_ str_code_hdw(_WString* s, uint32_t x) +{ + int8_t* buf; + int i = 0, shift = 0; + unsigned int t = 0; + + buf = (int8_t*)&s->p[s->length]; + + buf[0] = '0'; + buf[1] = 'x'; + buf += 2; + + for (shift = 28; shift != 0; shift -= 4) { + t = (x >> shift) & 0xf; + if (i | t) buf[i++] = NIBBLE_TO_CHR; + } + t = x & 0xf; + buf[i++] = NIBBLE_TO_CHR; + + s->length += i + 2; + buf[i] = '\0'; +} + +void _FASTCALL_ str_code_hqw(_WString* s, uint8_t src[8]) +{ + int8_t* buf; + int i = 0, shift = 0; + uint32_t x = RULONG(&src[sizeof(int32_t)]); + int t; + + buf = (int8_t*)&s->p[s->length]; + buf[0] = '0'; + buf[1] = 'x'; + buf += 2; + + for (shift = 28; shift != -4; shift -= 4) { + t = (x >> shift) & 0xf; + if (i | t) buf[i++] = NIBBLE_TO_CHR; + } + + x = RULONG(src); + for (shift = 28; shift != 0; shift -= 4) { + t = (x >> shift) & 0xf; + if (i | t) buf[i++] = NIBBLE_TO_CHR; + } + t = x & 0xf; + buf[i++] = NIBBLE_TO_CHR; + + s->length += i + 2; + buf[i] = '\0'; +} + +#ifdef SUPPORT_64BIT_OFFSET +void _FASTCALL_ str_off64(_WString* s, OFFSET_INTEGER x) +{ + int8_t* buf; + int i = 0, shift = 0; + OFFSET_INTEGER t = 0; + + buf = (int8_t*)&s->p[s->length]; + + buf[0] = '0'; + buf[1] = 'x'; + buf += 2; + + for (shift = 60; shift != 0; shift -= 4) { + t = (x >> shift) & 0xf; + if (i | t) buf[i++] = NIBBLE_TO_CHR; + } + t = x & 0xf; + buf[i++] = NIBBLE_TO_CHR; + + s->length += i + 2; + buf[i] = '\0'; +} +#endif /* SUPPORT_64BIT_OFFSET */ + +#endif /* DISTORM_LIGHT */ diff --git a/distorm3.2-package/src/textdefs.h b/distorm3.2-package/src/textdefs.h new file mode 100644 index 0000000..275cf88 --- /dev/null +++ b/distorm3.2-package/src/textdefs.h @@ -0,0 +1,71 @@ +/* +textdefs.h + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2012 Gil Dabah + +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 +*/ + + +#ifndef TEXTDEFS_H +#define TEXTDEFS_H + +#include "config.h" +#include "wstring.h" + +#ifndef DISTORM_LIGHT + +#define PLUS_DISP_CHR '+' +#define MINUS_DISP_CHR '-' +#define OPEN_CHR '[' +#define CLOSE_CHR ']' +#define SP_CHR ' ' +#define SEG_OFF_CHR ':' + +/* +Naming Convention: + +* get - returns a pointer to a string. +* str - concatenates to string. + +* hex - means the function is used for hex dump (number is padded to required size) - Little Endian output. +* code - means the function is used for disassembled instruction - Big Endian output. +* off - means the function is used for 64bit offset - Big Endian output. + +* h - '0x' in front of the string. + +* b - byte +* dw - double word (can be used for word also) +* qw - quad word + +* all numbers are in HEX. +*/ + +extern int8_t TextBTable[256][4]; + +void _FASTCALL_ str_hex_b(_WString* s, unsigned int x); +void _FASTCALL_ str_code_hb(_WString* s, unsigned int x); +void _FASTCALL_ str_code_hdw(_WString* s, uint32_t x); +void _FASTCALL_ str_code_hqw(_WString* s, uint8_t src[8]); + +#ifdef SUPPORT_64BIT_OFFSET +void _FASTCALL_ str_off64(_WString* s, OFFSET_INTEGER x); +#endif + +#endif /* DISTORM_LIGHT */ + +#endif /* TEXTDEFS_H */ diff --git a/distorm3.2-package/src/wstring.c b/distorm3.2-package/src/wstring.c new file mode 100644 index 0000000..26b2260 --- /dev/null +++ b/distorm3.2-package/src/wstring.c @@ -0,0 +1,59 @@ +/* +wstring.c + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2012 Gil Dabah + +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 +*/ + + +#include "wstring.h" + +#ifndef DISTORM_LIGHT + +void strclear_WS(_WString* s) +{ + s->p[0] = '\0'; + s->length = 0; +} + +void chrcat_WS(_WString* s, uint8_t ch) +{ + s->p[s->length] = ch; + s->p[s->length + 1] = '\0'; + s->length += 1; +} + +void strcpylen_WS(_WString* s, const int8_t* buf, unsigned int len) +{ + s->length = len; + memcpy((int8_t*)s->p, buf, len + 1); +} + +void strcatlen_WS(_WString* s, const int8_t* buf, unsigned int len) +{ + memcpy((int8_t*)&s->p[s->length], buf, len + 1); + s->length += len; +} + +void strcat_WS(_WString* s, const _WString* s2) +{ + memcpy((int8_t*)&s->p[s->length], s2->p, s2->length + 1); + s->length += s2->length; +} + +#endif /* DISTORM_LIGHT */ diff --git a/distorm3.2-package/src/wstring.h b/distorm3.2-package/src/wstring.h new file mode 100644 index 0000000..6ff9ccf --- /dev/null +++ b/distorm3.2-package/src/wstring.h @@ -0,0 +1,47 @@ +/* +wstring.h + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2012 Gil Dabah + +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 +*/ + + +#ifndef WSTRING_H +#define WSTRING_H + +#include "config.h" + +#ifndef DISTORM_LIGHT + +void strclear_WS(_WString* s); +void chrcat_WS(_WString* s, uint8_t ch); +void strcpylen_WS(_WString* s, const int8_t* buf, unsigned int len); +void strcatlen_WS(_WString* s, const int8_t* buf, unsigned int len); +void strcat_WS(_WString* s, const _WString* s2); + +/* +* Warning, this macro should be used only when the compiler knows the size of string in advance! +* This macro is used in order to spare the call to strlen when the strings are known already. +* Note: sizeof includes NULL terminated character. +*/ +#define strcat_WSN(s, t) strcatlen_WS((s), ((const int8_t*)t), sizeof((t))-1) +#define strcpy_WSN(s, t) strcpylen_WS((s), ((const int8_t*)t), sizeof((t))-1) + +#endif /* DISTORM_LIGHT */ + +#endif /* WSTRING_H */ diff --git a/distorm3.2-package/src/x86defs.c b/distorm3.2-package/src/x86defs.c new file mode 100644 index 0000000..4ee7e42 --- /dev/null +++ b/distorm3.2-package/src/x86defs.c @@ -0,0 +1,50 @@ +/* +x86defs.c + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2012 Gil Dabah + +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 +*/ + + +#include "x86defs.h" +#include "instructions.h" +#include "../include/mnemonics.h" + + +/* + * The first field of an _InstInfo is the flagsInex, which goes into FlagsTable in insts.c + * Since this table is auto generated in disOps, we have to make sure that the first 5 entries + * are reserved for our use here. + * The following defined inst-infos have to be synced manually every time you change insts.c. + */ + +_InstInfo II_arpl = {0 /* INST_MODRM_REQUIRED */, OT_REG16, OT_RM16, ISC_INTEGER << 3, I_ARPL}; +/* + * MOVSXD: + * This is the worst defined instruction ever. It has so many variations. + * I decided after a third review, to make it like MOVSXD RAX, EAX when there IS a REX.W. + * Otherwise it will be MOVSXD EAX, EAX, which really zero extends to RAX. + * Completely ignoring DB 0x66, which is possible by the docs, BTW. + */ +_InstInfo II_movsxd = {1 /* INST_MODRM_REQUIRED | INST_PRE_REX | INST_64BITS */, OT_RM32, OT_REG32_64, ISC_INTEGER << 3, I_MOVSXD}; + +_InstInfo II_nop = {2 /* INST_FLAGS_NONE */, OT_NONE, OT_NONE, ISC_INTEGER << 3, I_NOP}; + +_InstInfo II_pause = {3 /* INST_FLAGS_NONE */, OT_NONE, OT_NONE, ISC_INTEGER << 3, I_PAUSE}; + +_InstInfo II_3dnow = {4 /* INST_32BITS | INST_MODRM_REQUIRED | INST_3DNOW_FETCH */, OT_MM64, OT_MM, ISC_3DNOW << 3, I_UNDEFINED}; diff --git a/distorm3.2-package/src/x86defs.h b/distorm3.2-package/src/x86defs.h new file mode 100644 index 0000000..f35ff42 --- /dev/null +++ b/distorm3.2-package/src/x86defs.h @@ -0,0 +1,115 @@ +/* +x86defs.h + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2012 Gil Dabah + +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 +*/ + + +#ifndef X86DEFS_H +#define X86DEFS_H + +#include "config.h" +#include "instructions.h" + + +#define SEG_REGS_MAX (6) +#define CREGS_MAX (9) +#define DREGS_MAX (8) + +/* Maximum instruction size, including prefixes */ +#define INST_MAXIMUM_SIZE (15) + +/* Maximum range of imm8 (comparison type) of special SSE CMP instructions. */ +#define INST_CMP_MAX_RANGE (8) + +/* Maximum range of imm8 (comparison type) of special AVX VCMP instructions. */ +#define INST_VCMP_MAX_RANGE (32) + +/* Wait instruction byte code. */ +#define INST_WAIT_INDEX (0x9b) + +/* Lea instruction byte code. */ +#define INST_LEA_INDEX (0x8d) + +/* + * Minimal MODR/M value of divided instructions. + * It's 0xc0, two MSBs set, which indicates a general purpose register is used too. + */ +#define INST_DIVIDED_MODRM (0xc0) + +/* This is the escape byte value used for 3DNow! instructions. */ +#define _3DNOW_ESCAPE_BYTE (0x0f) + +#define PREFIX_LOCK (0xf0) +#define PREFIX_REPNZ (0xf2) +#define PREFIX_REP (0xf3) +#define PREFIX_CS (0x2e) +#define PREFIX_SS (0x36) +#define PREFIX_DS (0x3e) +#define PREFIX_ES (0x26) +#define PREFIX_FS (0x64) +#define PREFIX_GS (0x65) +#define PREFIX_OP_SIZE (0x66) +#define PREFIX_ADDR_SIZE (0x67) +#define PREFIX_VEX2b (0xc5) +#define PREFIX_VEX3b (0xc4) + +/* REX prefix value range, 64 bits mode decoding only. */ +#define PREFIX_REX_LOW (0x40) +#define PREFIX_REX_HI (0x4f) +/* In order to use the extended GPR's we have to add 8 to the Modr/M info values. */ +#define EX_GPR_BASE (8) + +/* Mask for REX and VEX features: */ +/* Base */ +#define PREFIX_EX_B (1) +/* Index */ +#define PREFIX_EX_X (2) +/* Register */ +#define PREFIX_EX_R (4) +/* Operand Width */ +#define PREFIX_EX_W (8) +/* Vector Lengh */ +#define PREFIX_EX_L (0x10) + +/* + * The inst_lookup will return on of these two instructions according to the specified decoding mode. + * ARPL or MOVSXD on 64 bits is one byte instruction at index 0x63. + */ +#define INST_ARPL_INDEX (0x63) +extern _InstInfo II_arpl; +extern _InstInfo II_movsxd; + +/* + * The NOP instruction can be prefixed by REX in 64bits, therefore we have to decide in runtime whether it's an XCHG or NOP instruction. + * If 0x90 is prefixed by a useable REX it will become XCHG, otherwise it will become a NOP. + * Also note that if it's prefixed by 0xf3, it becomes a Pause. + */ +#define INST_NOP_INDEX (0x90) +extern _InstInfo II_nop; +extern _InstInfo II_pause; + +/* + * Used for letting the extract operand know the type of operands without knowing the + * instruction itself yet, because of the way those instructions work. + * See function instructions.c!inst_lookup_3dnow. + */ +extern _InstInfo II_3dnow; + +#endif /* X86DEFS_H */ diff --git a/hook_file.c b/hook_file.c new file mode 100644 index 0000000..94bb075 --- /dev/null +++ b/hook_file.c @@ -0,0 +1,505 @@ +/* +Cuckoo Sandbox - Automated Malware Analysis +Copyright (C) 2010-2014 Cuckoo Sandbox Developers + +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 . +*/ + +#include +#include +#include +#include +#include "hooking.h" +#include "ntapi.h" +#include "log.h" +#include "pipe.h" +#include "misc.h" +#include "ignore.h" +#include "lookup.h" + +static IS_SUCCESS_NTSTATUS(); + +#define DUMP_FILE_MASK (GENERIC_WRITE | FILE_GENERIC_WRITE | \ + FILE_WRITE_DATA | FILE_APPEND_DATA | STANDARD_RIGHTS_WRITE | \ + STANDARD_RIGHTS_ALL) + +#define HDDVOL1 L"\\Device\\HarddiskVolume1" + +// length of a hardcoded unicode string +#define UNILEN(x) (sizeof(x) / sizeof(wchar_t) - 1) + +typedef struct _file_record_t { + unsigned int attributes; + size_t length; + wchar_t filename[0]; +} file_record_t; + +static lookup_t g_files; + +void file_init() +{ + lookup_init(&g_files); +} + +static void new_file(const UNICODE_STRING *obj) +{ + const wchar_t *str = obj->Buffer; + unsigned int len = obj->Length / sizeof(wchar_t); + + // if it's a path including \??\ then we can send it straight away, + // but we strip the \??\ part + if(len > 4 && !wcsncmp(str, L"\\??\\", 4)) { + pipe("FILE_NEW:%S", len - 4, str + 4); + } + // maybe it's an absolute path (or a relative path with a harddisk, + // such as C:abc.txt) + else if(isalpha(str[0]) != 0 && str[1] == ':') { + pipe("FILE_NEW:%S", len, str); + } + // the filename starts with \Device\HarddiskVolume1, which is + // basically just C: + else if(!wcsnicmp(str, HDDVOL1, UNILEN(HDDVOL1))) { + str += UNILEN(HDDVOL1), len -= UNILEN(HDDVOL1); + pipe("FILE_NEW:C:%S", len, str); + } +} + +static void cache_file(HANDLE file_handle, const wchar_t *path, + unsigned int length, unsigned int attributes) +{ + file_record_t *r = lookup_add(&g_files, (unsigned int) file_handle, + sizeof(file_record_t) + length * sizeof(wchar_t) + sizeof(wchar_t)); + + *r = (file_record_t) { + .attributes = attributes, + .length = length, + }; + + wcsncpy(r->filename, path, r->length + 1); +} + +static void file_write(HANDLE file_handle) +{ + file_record_t *r = lookup_get(&g_files, (unsigned int) file_handle, NULL); + if(r != NULL) { + UNICODE_STRING str = { + // microsoft actually meant "size" + .Length = r->length * sizeof(wchar_t), + .MaximumLength = (r->length + 1) * sizeof(wchar_t) , + .Buffer = r->filename, + }; + + // we do in fact want to dump this file because it was written to + new_file(&str); + + // delete the file record from the list + lookup_del(&g_files, (unsigned int) file_handle); + } +} + +static void handle_new_file(HANDLE file_handle, const OBJECT_ATTRIBUTES *obj) +{ + if(is_directory_objattr(obj) == 0 && is_ignored_file_objattr(obj) == 0) { + + wchar_t fname[MAX_PATH_PLUS_TOLERANCE]; uint32_t length; + + length = path_from_object_attributes(obj, + fname, MAX_PATH_PLUS_TOLERANCE); + + length = ensure_absolute_path(fname, fname, length); + + // cache this file + cache_file(file_handle, fname, length, obj->Attributes); + } +} + +void file_close(HANDLE file_handle) +{ + lookup_del(&g_files, (unsigned int) file_handle); +} + +HOOKDEF(NTSTATUS, WINAPI, NtCreateFile, + __out PHANDLE FileHandle, + __in ACCESS_MASK DesiredAccess, + __in POBJECT_ATTRIBUTES ObjectAttributes, + __out PIO_STATUS_BLOCK IoStatusBlock, + __in_opt PLARGE_INTEGER AllocationSize, + __in ULONG FileAttributes, + __in ULONG ShareAccess, + __in ULONG CreateDisposition, + __in ULONG CreateOptions, + __in PVOID EaBuffer, + __in ULONG EaLength +) { + NTSTATUS ret = Old_NtCreateFile(FileHandle, DesiredAccess, + ObjectAttributes, IoStatusBlock, AllocationSize, FileAttributes, + ShareAccess, CreateDisposition, CreateOptions, EaBuffer, EaLength); + LOQ("PpOll", "FileHandle", FileHandle, "DesiredAccess", DesiredAccess, + "FileName", ObjectAttributes, "CreateDisposition", CreateDisposition, + "ShareAccess", ShareAccess); + if(NT_SUCCESS(ret) && DesiredAccess & DUMP_FILE_MASK) { + handle_new_file(*FileHandle, ObjectAttributes); + } + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, NtOpenFile, + __out PHANDLE FileHandle, + __in ACCESS_MASK DesiredAccess, + __in POBJECT_ATTRIBUTES ObjectAttributes, + __out PIO_STATUS_BLOCK IoStatusBlock, + __in ULONG ShareAccess, + __in ULONG OpenOptions +) { + NTSTATUS ret = Old_NtOpenFile(FileHandle, DesiredAccess, ObjectAttributes, + IoStatusBlock, ShareAccess, OpenOptions); + LOQ("PpOl", "FileHandle", FileHandle, "DesiredAccess", DesiredAccess, + "FileName", ObjectAttributes, "ShareAccess", ShareAccess); + if(NT_SUCCESS(ret) && DesiredAccess & DUMP_FILE_MASK) { + handle_new_file(*FileHandle, ObjectAttributes); + } + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, NtReadFile, + __in HANDLE FileHandle, + __in_opt HANDLE Event, + __in_opt PIO_APC_ROUTINE ApcRoutine, + __in_opt PVOID ApcContext, + __out PIO_STATUS_BLOCK IoStatusBlock, + __out PVOID Buffer, + __in ULONG Length, + __in_opt PLARGE_INTEGER ByteOffset, + __in_opt PULONG Key +) { + NTSTATUS ret = Old_NtReadFile(FileHandle, Event, ApcRoutine, ApcContext, + IoStatusBlock, Buffer, Length, ByteOffset, Key); + LOQ("pb", "FileHandle", FileHandle, + "Buffer", IoStatusBlock->Information, Buffer); + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, NtWriteFile, + __in HANDLE FileHandle, + __in_opt HANDLE Event, + __in_opt PIO_APC_ROUTINE ApcRoutine, + __in_opt PVOID ApcContext, + __out PIO_STATUS_BLOCK IoStatusBlock, + __in PVOID Buffer, + __in ULONG Length, + __in_opt PLARGE_INTEGER ByteOffset, + __in_opt PULONG Key +) { + NTSTATUS ret = Old_NtWriteFile(FileHandle, Event, ApcRoutine, ApcContext, + IoStatusBlock, Buffer, Length, ByteOffset, Key); + LOQ("pb", "FileHandle", FileHandle, + "Buffer", IoStatusBlock->Information, Buffer); + if(NT_SUCCESS(ret)) { + file_write(FileHandle); + } + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, NtDeleteFile, + __in POBJECT_ATTRIBUTES ObjectAttributes +) { + pipe("FILE_DEL:%O", ObjectAttributes); + + NTSTATUS ret = Old_NtDeleteFile(ObjectAttributes); + LOQ("O", "FileName", ObjectAttributes); + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, NtDeviceIoControlFile, + __in HANDLE FileHandle, + __in HANDLE Event, + __in PIO_APC_ROUTINE ApcRoutine, + __in PVOID ApcContext, + __out PIO_STATUS_BLOCK IoStatusBlock, + __in ULONG IoControlCode, + __in PVOID InputBuffer, + __in ULONG InputBufferLength, + __out PVOID OutputBuffer, + __in ULONG OutputBufferLength +) { + NTSTATUS ret = Old_NtDeviceIoControlFile(FileHandle, Event, + ApcRoutine, ApcContext, IoStatusBlock, IoControlCode, + InputBuffer, InputBufferLength, OutputBuffer, + OutputBufferLength); + LOQ("pbb", "FileHandle", FileHandle, + "InputBuffer", InputBufferLength, InputBuffer, + "OutputBuffer", IoStatusBlock->Information, OutputBuffer); + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, NtQueryDirectoryFile, + __in HANDLE FileHandle, + __in_opt HANDLE Event, + __in_opt PIO_APC_ROUTINE ApcRoutine, + __in_opt PVOID ApcContext, + __out PIO_STATUS_BLOCK IoStatusBlock, + __out PVOID FileInformation, + __in ULONG Length, + __in FILE_INFORMATION_CLASS FileInformationClass, + __in BOOLEAN ReturnSingleEntry, + __in_opt PUNICODE_STRING FileName, + __in BOOLEAN RestartScan +) { + NTSTATUS ret = Old_NtQueryDirectoryFile(FileHandle, Event, + ApcRoutine, ApcContext, IoStatusBlock, FileInformation, + Length, FileInformationClass, ReturnSingleEntry, + FileName, RestartScan); + LOQ("pbo", "FileHandle", FileHandle, + "FileInformation", IoStatusBlock->Information, FileInformation, + "FileName", FileName); + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, NtQueryInformationFile, + __in HANDLE FileHandle, + __out PIO_STATUS_BLOCK IoStatusBlock, + __out PVOID FileInformation, + __in ULONG Length, + __in FILE_INFORMATION_CLASS FileInformationClass +) { + NTSTATUS ret = Old_NtQueryInformationFile(FileHandle, IoStatusBlock, + FileInformation, Length, FileInformationClass); + LOQ("pb", "FileHandle", FileHandle, + "FileInformation", IoStatusBlock->Information, FileInformation); + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, NtSetInformationFile, + __in HANDLE FileHandle, + __out PIO_STATUS_BLOCK IoStatusBlock, + __in PVOID FileInformation, + __in ULONG Length, + __in FILE_INFORMATION_CLASS FileInformationClass +) { + if(FileInformation != NULL && Length == sizeof(BOOLEAN) && + FileInformationClass == FileDispositionInformation && + *(BOOLEAN *) FileInformation != FALSE) { + + wchar_t path[MAX_PATH_PLUS_TOLERANCE]; + path_from_handle(FileHandle, path, (unsigned int) MAX_PATH_PLUS_TOLERANCE); + pipe("FILE_DEL:%Z", path); + } + + NTSTATUS ret = Old_NtSetInformationFile(FileHandle, IoStatusBlock, + FileInformation, Length, FileInformationClass); + LOQ("pb", "FileHandle", FileHandle, + "FileInformation", IoStatusBlock->Information, FileInformation); + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, NtOpenDirectoryObject, + __out PHANDLE DirectoryHandle, + __in ACCESS_MASK DesiredAccess, + __in POBJECT_ATTRIBUTES ObjectAttributes +) { + NTSTATUS ret = Old_NtOpenDirectoryObject(DirectoryHandle, DesiredAccess, + ObjectAttributes); + LOQ("PlO", "DirectoryHandle", DirectoryHandle, + "DesiredAccess", DesiredAccess, "ObjectAttributes", ObjectAttributes); + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, NtCreateDirectoryObject, + __out PHANDLE DirectoryHandle, + __in ACCESS_MASK DesiredAccess, + __in POBJECT_ATTRIBUTES ObjectAttributes +) { + NTSTATUS ret = Old_NtCreateDirectoryObject(DirectoryHandle, DesiredAccess, + ObjectAttributes); + LOQ("PlO", "DirectoryHandle", DirectoryHandle, + "DesiredAccess", DesiredAccess, "ObjectAttributes", ObjectAttributes); + return ret; +} + +HOOKDEF(BOOL, WINAPI, CreateDirectoryW, + __in LPWSTR lpPathName, + __in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes +) { + IS_SUCCESS_BOOL(); + + BOOL ret = Old_CreateDirectoryW(lpPathName, lpSecurityAttributes); + LOQ("u", "DirectoryName", lpPathName); + return ret; +} + +HOOKDEF(BOOL, WINAPI, CreateDirectoryExW, + __in LPWSTR lpTemplateDirectory, + __in LPWSTR lpNewDirectory, + __in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes +) { + IS_SUCCESS_BOOL(); + + BOOL ret = Old_CreateDirectoryExW(lpTemplateDirectory, lpNewDirectory, + lpSecurityAttributes); + LOQ("u", "DirectoryName", lpNewDirectory); + return ret; +} + +HOOKDEF(BOOL, WINAPI, RemoveDirectoryA, + __in LPCTSTR lpPathName +) { + IS_SUCCESS_BOOL(); + + BOOL ret = Old_RemoveDirectoryA(lpPathName); + LOQ("s", "DirectoryName", lpPathName); + return ret; +} + +HOOKDEF(BOOL, WINAPI, RemoveDirectoryW, + __in LPWSTR lpPathName +) { + IS_SUCCESS_BOOL(); + + BOOL ret = Old_RemoveDirectoryW(lpPathName); + LOQ("u", "DirectoryName", lpPathName); + return ret; +} + +HOOKDEF(BOOL, WINAPI, MoveFileWithProgressW, + __in LPWSTR lpExistingFileName, + __in_opt LPWSTR lpNewFileName, + __in_opt LPPROGRESS_ROUTINE lpProgressRoutine, + __in_opt LPVOID lpData, + __in DWORD dwFlags +) { + IS_SUCCESS_BOOL(); + + BOOL ret = Old_MoveFileWithProgressW(lpExistingFileName, lpNewFileName, + lpProgressRoutine, lpData, dwFlags); + LOQ("uu", "ExistingFileName", lpExistingFileName, + "NewFileName", lpNewFileName); + if(ret != FALSE) { + pipe("FILE_MOVE:%Z::%Z", lpExistingFileName, lpNewFileName); + } + return ret; +} + +HOOKDEF(HANDLE, WINAPI, FindFirstFileExA, + __in LPCTSTR lpFileName, + __in FINDEX_INFO_LEVELS fInfoLevelId, + __out LPVOID lpFindFileData, + __in FINDEX_SEARCH_OPS fSearchOp, + __reserved LPVOID lpSearchFilter, + __in DWORD dwAdditionalFlags +) { + IS_SUCCESS_HANDLE(); + + HANDLE ret = Old_FindFirstFileExA(lpFileName, fInfoLevelId, + lpFindFileData, fSearchOp, lpSearchFilter, dwAdditionalFlags); + LOQ("s", "FileName", lpFileName); + return ret; +} + +HOOKDEF(HANDLE, WINAPI, FindFirstFileExW, + __in LPWSTR lpFileName, + __in FINDEX_INFO_LEVELS fInfoLevelId, + __out LPVOID lpFindFileData, + __in FINDEX_SEARCH_OPS fSearchOp, + __reserved LPVOID lpSearchFilter, + __in DWORD dwAdditionalFlags +) { + IS_SUCCESS_HANDLE(); + + HANDLE ret = Old_FindFirstFileExW(lpFileName, fInfoLevelId, + lpFindFileData, fSearchOp, lpSearchFilter, dwAdditionalFlags); + LOQ("u", "FileName", lpFileName); + return ret; +} + +HOOKDEF(BOOL, WINAPI, CopyFileA, + __in LPCTSTR lpExistingFileName, + __in LPCTSTR lpNewFileName, + __in BOOL bFailIfExists +) { + IS_SUCCESS_BOOL(); + + BOOL ret = Old_CopyFileA(lpExistingFileName, lpNewFileName, + bFailIfExists); + LOQ("ss", "ExistingFileName", lpExistingFileName, + "NewFileName", lpNewFileName); + return ret; +} + +HOOKDEF(BOOL, WINAPI, CopyFileW, + __in LPWSTR lpExistingFileName, + __in LPWSTR lpNewFileName, + __in BOOL bFailIfExists +) { + IS_SUCCESS_BOOL(); + + BOOL ret = Old_CopyFileW(lpExistingFileName, lpNewFileName, + bFailIfExists); + LOQ("uu", "ExistingFileName", lpExistingFileName, + "NewFileName", lpNewFileName); + return ret; +} + +HOOKDEF(BOOL, WINAPI, CopyFileExW, + _In_ LPWSTR lpExistingFileName, + _In_ LPWSTR lpNewFileName, + _In_opt_ LPPROGRESS_ROUTINE lpProgressRoutine, + _In_opt_ LPVOID lpData, + _In_opt_ LPBOOL pbCancel, + _In_ DWORD dwCopyFlags +) { + IS_SUCCESS_BOOL(); + + BOOL ret = Old_CopyFileExW(lpExistingFileName, lpNewFileName, + lpProgressRoutine, lpData, pbCancel, dwCopyFlags); + LOQ("uul", "ExistingFileName", lpExistingFileName, + "NewFileName", lpNewFileName, "CopyFlags", dwCopyFlags); + return ret; +} + +HOOKDEF(BOOL, WINAPI, DeleteFileA, + __in LPCSTR lpFileName +) { + IS_SUCCESS_BOOL(); + + wchar_t path[MAX_PATH]; + + // copy ascii to unicode string + for (int i = 0; lpFileName[i] != 0 && i < MAX_PATH; i++) { + path[i] = lpFileName[i]; + } + + ensure_absolute_path(path, path, strlen(lpFileName)); + + pipe("FILE_DEL:%Z", path); + + BOOL ret = Old_DeleteFileA(lpFileName); + LOQ("s", "FileName", lpFileName); + return ret; +} + +HOOKDEF(BOOL, WINAPI, DeleteFileW, + __in LPWSTR lpFileName +) { + IS_SUCCESS_BOOL(); + + wchar_t path[MAX_PATH]; + + ensure_absolute_path(path, lpFileName, lstrlenW(lpFileName)); + + pipe("FILE_DEL:%Z", path); + + BOOL ret = Old_DeleteFileW(lpFileName); + LOQ("u", "FileName", lpFileName); + return ret; +} diff --git a/hook_file.h b/hook_file.h new file mode 100644 index 0000000..1307e99 --- /dev/null +++ b/hook_file.h @@ -0,0 +1,20 @@ +/* +Cuckoo Sandbox - Automated Malware Analysis +Copyright (C) 2010-2014 Cuckoo Sandbox Developers + +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 . +*/ + +void file_init(); +void file_close(HANDLE file_handle); diff --git a/hook_misc.c b/hook_misc.c new file mode 100644 index 0000000..02d0884 --- /dev/null +++ b/hook_misc.c @@ -0,0 +1,246 @@ +/* +Cuckoo Sandbox - Automated Malware Analysis +Copyright (C) 2010-2014 Cuckoo Sandbox Developers + +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 . +*/ + +#include +#include +#include "hooking.h" +#include "ntapi.h" +#include "log.h" +#include "pipe.h" +#include "misc.h" +#include "hook_file.h" +#include "hook_sleep.h" + +static IS_SUCCESS_NTSTATUS(); + +HOOKDEF(HHOOK, WINAPI, SetWindowsHookExA, + __in int idHook, + __in HOOKPROC lpfn, + __in HINSTANCE hMod, + __in DWORD dwThreadId +) { + IS_SUCCESS_HHOOK(); + + HHOOK ret = Old_SetWindowsHookExA(idHook, lpfn, hMod, dwThreadId); + LOQ("lppl", "HookIdentifier", idHook, "ProcedureAddress", lpfn, + "ModuleAddress", hMod, "ThreadId", dwThreadId); + return ret; +} + +HOOKDEF(HHOOK, WINAPI, SetWindowsHookExW, + __in int idHook, + __in HOOKPROC lpfn, + __in HINSTANCE hMod, + __in DWORD dwThreadId +) { + IS_SUCCESS_HHOOK(); + + HHOOK ret = Old_SetWindowsHookExW(idHook, lpfn, hMod, dwThreadId); + LOQ("lppl", "HookIdentifier", idHook, "ProcedureAddress", lpfn, + "ModuleAddress", hMod, "ThreadId", dwThreadId); + return ret; +} + +HOOKDEF(BOOL, WINAPI, UnhookWindowsHookEx, + __in HHOOK hhk +) { + IS_SUCCESS_BOOL(); + + BOOL ret = Old_UnhookWindowsHookEx(hhk); + LOQ("p", "HookHandle", hhk); + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, LdrLoadDll, + __in_opt PWCHAR PathToFile, + __in_opt ULONG Flags, + __in PUNICODE_STRING ModuleFileName, + __out PHANDLE ModuleHandle +) { + COPY_UNICODE_STRING(library, ModuleFileName); + + NTSTATUS ret = Old_LdrLoadDll(PathToFile, Flags, ModuleFileName, + ModuleHandle); + LOQ("loP", "Flags", Flags, "FileName", &library, + "BaseAddress", ModuleHandle); + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, LdrGetDllHandle, + __in_opt PWORD pwPath, + __in_opt PVOID Unused, + __in PUNICODE_STRING ModuleFileName, + __out PHANDLE pHModule +) { + NTSTATUS ret = Old_LdrGetDllHandle(pwPath, Unused, ModuleFileName, + pHModule); + LOQ("oP", "FileName", ModuleFileName, "ModuleHandle", pHModule); + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, LdrGetProcedureAddress, + __in HMODULE ModuleHandle, + __in_opt PANSI_STRING FunctionName, + __in_opt WORD Ordinal, + __out PVOID *FunctionAddress +) { + NTSTATUS ret = Old_LdrGetProcedureAddress(ModuleHandle, FunctionName, + Ordinal, FunctionAddress); + LOQ("pSlP", "ModuleHandle", ModuleHandle, + "FunctionName", FunctionName != NULL ? FunctionName->Length : 0, + FunctionName != NULL ? FunctionName->Buffer : NULL, + "Ordinal", Ordinal, "FunctionAddress", FunctionAddress); + return ret; +} + +HOOKDEF(BOOL, WINAPI, DeviceIoControl, + __in HANDLE hDevice, + __in DWORD dwIoControlCode, + __in_opt LPVOID lpInBuffer, + __in DWORD nInBufferSize, + __out_opt LPVOID lpOutBuffer, + __in DWORD nOutBufferSize, + __out_opt LPDWORD lpBytesReturned, + __inout_opt LPOVERLAPPED lpOverlapped +) { + IS_SUCCESS_BOOL(); + + BOOL ret = Old_DeviceIoControl(hDevice, dwIoControlCode, lpInBuffer, + nInBufferSize, lpOutBuffer, nOutBufferSize, lpBytesReturned, + lpOverlapped); + LOQ("plbb", "DeviceHandle", hDevice, "IoControlCode", dwIoControlCode, + "InBuffer", nInBufferSize, lpInBuffer, + "OutBuffer", lpBytesReturned ? *lpBytesReturned : nOutBufferSize, + lpOutBuffer); + return ret; +} + +HOOKDEF(BOOL, WINAPI, ExitWindowsEx, + __in UINT uFlags, + __in DWORD dwReason +) { + IS_SUCCESS_BOOL(); + + int ret = 0; + LOQ("ll", "Flags", uFlags, "Reason", dwReason); + return Old_ExitWindowsEx(uFlags, dwReason); +} + +HOOKDEF(BOOL, WINAPI, IsDebuggerPresent, + void +) { + IS_SUCCESS_BOOL(); + + BOOL ret = Old_IsDebuggerPresent(); + LOQ(""); + return ret; +} + +HOOKDEF(BOOL, WINAPI, LookupPrivilegeValueW, + __in_opt LPWSTR lpSystemName, + __in LPWSTR lpName, + __out PLUID lpLuid +) { + IS_SUCCESS_BOOL(); + + BOOL ret = Old_LookupPrivilegeValueW(lpSystemName, lpName, lpLuid); + LOQ("uu", "SystemName", lpSystemName, "PrivilegeName", lpName); + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, NtClose, + __in HANDLE Handle +) { + NTSTATUS ret = Old_NtClose(Handle); + LOQ("p", "Handle", Handle); + if(NT_SUCCESS(ret)) { + file_close(Handle); + } + return ret; +} + +HOOKDEF(BOOL, WINAPI, WriteConsoleA, + _In_ HANDLE hConsoleOutput, + _In_ const VOID *lpBuffer, + _In_ DWORD nNumberOfCharsToWrite, + _Out_ LPDWORD lpNumberOfCharsWritten, + _Reserved_ LPVOID lpReseverd +) { + BOOL ret = Old_WriteConsoleA(hConsoleOutput, lpBuffer, + nNumberOfCharsToWrite, lpNumberOfCharsWritten, lpReseverd); + LOQ("pS", "ConsoleHandle", hConsoleOutput, + "Buffer", nNumberOfCharsToWrite, lpBuffer); + return ret; +} + +HOOKDEF(BOOL, WINAPI, WriteConsoleW, + _In_ HANDLE hConsoleOutput, + _In_ const VOID *lpBuffer, + _In_ DWORD nNumberOfCharsToWrite, + _Out_ LPDWORD lpNumberOfCharsWritten, + _Reserved_ LPVOID lpReseverd +) { + BOOL ret = Old_WriteConsoleW(hConsoleOutput, lpBuffer, + nNumberOfCharsToWrite, lpNumberOfCharsWritten, lpReseverd); + LOQ("pU", "ConsoleHandle", hConsoleOutput, + "Buffer", nNumberOfCharsToWrite, lpBuffer); + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, ZwMapViewOfSection, + _In_ HANDLE SectionHandle, + _In_ HANDLE ProcessHandle, + __inout PVOID *BaseAddress, + _In_ ULONG_PTR ZeroBits, + _In_ SIZE_T CommitSize, + __inout PLARGE_INTEGER SectionOffset, + __inout PSIZE_T ViewSize, + __in UINT InheritDisposition, + __in ULONG AllocationType, + __in ULONG Win32Protect +) { + NTSTATUS ret = Old_ZwMapViewOfSection(SectionHandle, ProcessHandle, + BaseAddress, ZeroBits, CommitSize, SectionOffset, ViewSize, + InheritDisposition, AllocationType, Win32Protect); + LOQ("ppPp", "SectionHandle", SectionHandle, + "ProcessHandle", ProcessHandle, "BaseAddress", BaseAddress, + "SectionOffset", SectionOffset); + + if(NT_SUCCESS(ret)) { + pipe("PROCESS:%d", pid_from_process_handle(ProcessHandle)); + disable_sleep_skip(); + } + return ret; +} + +HOOKDEF(int, WINAPI, GetSystemMetrics, + _In_ int nIndex +) { + int ret = Old_GetSystemMetrics(nIndex); + LOQ("l", "SystemMetricIndex", nIndex); + return ret; +} + +HOOKDEF(BOOL, WINAPI, GetCursorPos, + _Out_ LPPOINT lpPoint +) { + BOOL ret = Old_GetCursorPos(lpPoint); + LOQ("ll", "x", lpPoint != NULL ? lpPoint->x : 0, + "y", lpPoint != NULL ? lpPoint->y : 0); + return ret; +} diff --git a/hook_network.c b/hook_network.c new file mode 100644 index 0000000..94e9fe9 --- /dev/null +++ b/hook_network.c @@ -0,0 +1,328 @@ +/* +Cuckoo Sandbox - Automated Malware Analysis +Copyright (C) 2010-2014 Cuckoo Sandbox Developers + +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 . +*/ + +#include +#include +#include +#include +#include "hooking.h" +#include "ntapi.h" +#include "log.h" +#include "pipe.h" + +static IS_SUCCESS_HINTERNET(); + +HOOKDEF(HRESULT, WINAPI, URLDownloadToFileW, + LPUNKNOWN pCaller, + LPWSTR szURL, + LPWSTR szFileName, + DWORD dwReserved, + LPVOID lpfnCB +) { + IS_SUCCESS_HRESULT(); + + HRESULT ret = Old_URLDownloadToFileW(pCaller, szURL, szFileName, + dwReserved, lpfnCB); + LOQ("uu", "URL", szURL, "FileName", szFileName); + if(ret == S_OK) { + pipe("FILE_NEW:%S", szFileName); + } + return ret; +} + +HOOKDEF(HINTERNET, WINAPI, InternetOpenA, + _In_ LPCTSTR lpszAgent, + _In_ DWORD dwAccessType, + _In_ LPCTSTR lpszProxyName, + _In_ LPCTSTR lpszProxyBypass, + _In_ DWORD dwFlags +) { + HINTERNET ret = Old_InternetOpenA(lpszAgent, dwAccessType, lpszProxyName, + lpszProxyBypass, dwFlags); + LOQ("spssp", "Agent", lpszAgent, "AccessType", dwAccessType, + "ProxyName", lpszProxyName, "ProxyBypass", lpszProxyBypass, + "Flags", dwFlags); + return ret; +} + +HOOKDEF(HINTERNET, WINAPI, InternetOpenW, + _In_ LPWSTR lpszAgent, + _In_ DWORD dwAccessType, + _In_ LPWSTR lpszProxyName, + _In_ LPWSTR lpszProxyBypass, + _In_ DWORD dwFlags +) { + HINTERNET ret = Old_InternetOpenW(lpszAgent, dwAccessType, lpszProxyName, + lpszProxyBypass, dwFlags); + LOQ("upuup", "Agent", lpszAgent, "AccessType", dwAccessType, + "ProxyName", lpszProxyName, "ProxyBypass", lpszProxyBypass, + "Flags", dwFlags); + return ret; +} + +HOOKDEF(HINTERNET, WINAPI, InternetConnectA, + _In_ HINTERNET hInternet, + _In_ LPCTSTR lpszServerName, + _In_ INTERNET_PORT nServerPort, + _In_ LPCTSTR lpszUsername, + _In_ LPCTSTR lpszPassword, + _In_ DWORD dwService, + _In_ DWORD dwFlags, + _In_ DWORD_PTR dwContext +) { + HINTERNET ret = Old_InternetConnectA(hInternet, lpszServerName, + nServerPort, lpszUsername, lpszPassword, dwService, dwFlags, + dwContext); + LOQ("pslsslp", "InternetHandle", hInternet, "ServerName", lpszServerName, + "ServerPort", nServerPort, "Username", lpszUsername, + "Password", lpszPassword, "Service", dwService, "Flags", dwFlags); + return ret; +} + +HOOKDEF(HINTERNET, WINAPI, InternetConnectW, + _In_ HINTERNET hInternet, + _In_ LPWSTR lpszServerName, + _In_ INTERNET_PORT nServerPort, + _In_ LPWSTR lpszUsername, + _In_ LPWSTR lpszPassword, + _In_ DWORD dwService, + _In_ DWORD dwFlags, + _In_ DWORD_PTR dwContext +) { + HINTERNET ret = Old_InternetConnectW(hInternet, lpszServerName, + nServerPort, lpszUsername, lpszPassword, dwService, dwFlags, + dwContext); + LOQ("puluulp", "InternetHandle", hInternet, "ServerName", lpszServerName, + "ServerPort", nServerPort, "Username", lpszUsername, + "Password", lpszPassword, "Service", dwService, "Flags", dwFlags); + return ret; +} + +HOOKDEF(HINTERNET, WINAPI, InternetOpenUrlA, + __in HINTERNET hInternet, + __in LPCTSTR lpszUrl, + __in LPCTSTR lpszHeaders, + __in DWORD dwHeadersLength, + __in DWORD dwFlags, + __in DWORD_PTR dwContext +) { + HINTERNET ret = Old_InternetOpenUrlA(hInternet, lpszUrl, lpszHeaders, + dwHeadersLength, dwFlags, dwContext); + if(dwHeadersLength == (DWORD) -1) dwHeadersLength = strlen(lpszHeaders); + LOQ("psSp", "ConnectionHandle", hInternet, "URL", lpszUrl, + "Headers", dwHeadersLength, lpszHeaders, "Flags", dwFlags); + return ret; +} + +HOOKDEF(HINTERNET, WINAPI, InternetOpenUrlW, + __in HINTERNET hInternet, + __in LPWSTR lpszUrl, + __in LPWSTR lpszHeaders, + __in DWORD dwHeadersLength, + __in DWORD dwFlags, + __in DWORD_PTR dwContext +) { + HINTERNET ret = Old_InternetOpenUrlW(hInternet, lpszUrl, lpszHeaders, + dwHeadersLength, dwFlags, dwContext); + LOQ("puUp", "ConnectionHandle", hInternet, "URL", lpszUrl, + "Headers", dwHeadersLength, lpszHeaders, "Flags", dwFlags); + return ret; +} + +HOOKDEF(HINTERNET, WINAPI, HttpOpenRequestA, + __in HINTERNET hConnect, + __in LPCTSTR lpszVerb, + __in LPCTSTR lpszObjectName, + __in LPCTSTR lpszVersion, + __in LPCTSTR lpszReferer, + __in LPCTSTR *lplpszAcceptTypes, + __in DWORD dwFlags, + __in DWORD_PTR dwContext +) { + HINTERNET ret = Old_HttpOpenRequestA(hConnect, lpszVerb, lpszObjectName, + lpszVersion, lpszReferer, lplpszAcceptTypes, dwFlags, dwContext); + LOQ("psl", "InternetHandle", hConnect, "Path", lpszObjectName, + "Flags", dwFlags); + return ret; +} + +HOOKDEF(HINTERNET, WINAPI, HttpOpenRequestW, + __in HINTERNET hConnect, + __in LPWSTR lpszVerb, + __in LPWSTR lpszObjectName, + __in LPWSTR lpszVersion, + __in LPWSTR lpszReferer, + __in LPWSTR *lplpszAcceptTypes, + __in DWORD dwFlags, + __in DWORD_PTR dwContext +) { + HINTERNET ret = Old_HttpOpenRequestW(hConnect, lpszVerb, lpszObjectName, + lpszVersion, lpszReferer, lplpszAcceptTypes, dwFlags, dwContext); + LOQ("pul", "InternetHandle", hConnect, "Path", lpszObjectName, + "Flags", dwFlags); + return ret; +} + +HOOKDEF(BOOL, WINAPI, HttpSendRequestA, + __in HINTERNET hRequest, + __in LPCTSTR lpszHeaders, + __in DWORD dwHeadersLength, + __in LPVOID lpOptional, + __in DWORD dwOptionalLength +) { + IS_SUCCESS_BOOL(); + + BOOL ret = Old_HttpSendRequestA(hRequest, lpszHeaders, dwHeadersLength, + lpOptional, dwOptionalLength); + if(dwHeadersLength == (DWORD) -1) dwHeadersLength = strlen(lpszHeaders); + LOQ("pSb", "RequestHandle", hRequest, + "Headers", dwHeadersLength, lpszHeaders, + "PostData", dwOptionalLength, lpOptional); + return ret; +} + +HOOKDEF(BOOL, WINAPI, HttpSendRequestW, + __in HINTERNET hRequest, + __in LPWSTR lpszHeaders, + __in DWORD dwHeadersLength, + __in LPVOID lpOptional, + __in DWORD dwOptionalLength +) { + IS_SUCCESS_BOOL(); + + BOOL ret = Old_HttpSendRequestW(hRequest, lpszHeaders, dwHeadersLength, + lpOptional, dwOptionalLength); + LOQ("pUb", "RequestHandle", hRequest, + "Headers", dwHeadersLength, lpszHeaders, + "PostData", dwOptionalLength, lpOptional); + return ret; +} + +HOOKDEF(BOOL, WINAPI, InternetReadFile, + _In_ HINTERNET hFile, + _Out_ LPVOID lpBuffer, + _In_ DWORD dwNumberOfBytesToRead, + _Out_ LPDWORD lpdwNumberOfBytesRead +) { + IS_SUCCESS_BOOL(); + + BOOL ret = Old_InternetReadFile(hFile, lpBuffer, dwNumberOfBytesToRead, + lpdwNumberOfBytesRead); + LOQ("pB", "InternetHandle", hFile, + "Buffer", lpdwNumberOfBytesRead, lpBuffer); + return ret; +} + +HOOKDEF(BOOL, WINAPI, InternetWriteFile, + _In_ HINTERNET hFile, + _In_ LPCVOID lpBuffer, + _In_ DWORD dwNumberOfBytesToWrite, + _Out_ LPDWORD lpdwNumberOfBytesWritten +) { + IS_SUCCESS_BOOL(); + + BOOL ret = Old_InternetWriteFile(hFile, lpBuffer, dwNumberOfBytesToWrite, + lpdwNumberOfBytesWritten); + LOQ("pB", "InternetHandle", hFile, + "Buffer", lpdwNumberOfBytesWritten, lpBuffer); + return ret; +} + +HOOKDEF(BOOL, WINAPI, InternetCloseHandle, + _In_ HINTERNET hInternet +) { + IS_SUCCESS_BOOL(); + + BOOL ret = Old_InternetCloseHandle(hInternet); + LOQ("p", "InternetHandle", hInternet); + return ret; +} + +HOOKDEF(DNS_STATUS, WINAPI, DnsQuery_A, + __in PCSTR lpstrName, + __in WORD wType, + __in DWORD Options, + __inout_opt PVOID pExtra, + __out_opt PDNS_RECORD *ppQueryResultsSet, + __out_opt PVOID *pReserved +) { + IS_SUCCESS_ZERO(); + + DNS_STATUS ret = Old_DnsQuery_A(lpstrName, wType, Options, pExtra, + ppQueryResultsSet, pReserved); + LOQ("sil", "Name", lpstrName, "Type", wType, "Options", Options); + return ret; +} + +HOOKDEF(DNS_STATUS, WINAPI, DnsQuery_UTF8, + __in LPBYTE lpstrName, + __in WORD wType, + __in DWORD Options, + __inout_opt PVOID pExtra, + __out_opt PDNS_RECORD *ppQueryResultsSet, + __out_opt PVOID *pReserved +) { + IS_SUCCESS_ZERO(); + + DNS_STATUS ret = Old_DnsQuery_UTF8(lpstrName, wType, Options, pExtra, + ppQueryResultsSet, pReserved); + LOQ("sil", "Name", lpstrName, "Type", wType, "Options", Options); + return ret; +} + +HOOKDEF(DNS_STATUS, WINAPI, DnsQuery_W, + __in PWSTR lpstrName, + __in WORD wType, + __in DWORD Options, + __inout_opt PVOID pExtra, + __out_opt PDNS_RECORD *ppQueryResultsSet, + __out_opt PVOID *pReserved +) { + IS_SUCCESS_ZERO(); + + DNS_STATUS ret = Old_DnsQuery_W(lpstrName, wType, Options, pExtra, + ppQueryResultsSet, pReserved); + LOQ("uil", "Name", lpstrName, "Type", wType, "Options", Options); + return ret; +} + +HOOKDEF(int, WSAAPI, getaddrinfo, + _In_opt_ PCSTR pNodeName, + _In_opt_ PCSTR pServiceName, + _In_opt_ const ADDRINFOA *pHints, + _Out_ PADDRINFOA *ppResult +) { + IS_SUCCESS_ZERO(); + + BOOL ret = Old_getaddrinfo(pNodeName, pServiceName, pHints, ppResult); + LOQ("ss", "NodeName", pNodeName, "ServiceName", pServiceName); + return ret; +} + +HOOKDEF(int, WSAAPI, GetAddrInfoW, + _In_opt_ PCWSTR pNodeName, + _In_opt_ PCWSTR pServiceName, + _In_opt_ const ADDRINFOW *pHints, + _Out_ PADDRINFOW *ppResult +) { + IS_SUCCESS_ZERO(); + + BOOL ret = Old_GetAddrInfoW(pNodeName, pServiceName, pHints, ppResult); + LOQ("uu", "NodeName", pNodeName, "ServiceName", pServiceName); + return ret; +} diff --git a/hook_process.c b/hook_process.c new file mode 100644 index 0000000..cc2d485 --- /dev/null +++ b/hook_process.c @@ -0,0 +1,456 @@ +/* +Cuckoo Sandbox - Automated Malware Analysis +Copyright (C) 2010-2014 Cuckoo Sandbox Developers + +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 . +*/ + +#include +#include +#include "hooking.h" +#include "ntapi.h" +#include "log.h" +#include "pipe.h" +#include "misc.h" +#include "ignore.h" +#include "hook_sleep.h" + +static IS_SUCCESS_NTSTATUS(); + +HOOKDEF(NTSTATUS, WINAPI, NtCreateProcess, + __out PHANDLE ProcessHandle, + __in ACCESS_MASK DesiredAccess, + __in_opt POBJECT_ATTRIBUTES ObjectAttributes, + __in HANDLE ParentProcess, + __in BOOLEAN InheritObjectTable, + __in_opt HANDLE SectionHandle, + __in_opt HANDLE DebugPort, + __in_opt HANDLE ExceptionPort +) { + NTSTATUS ret = Old_NtCreateProcess(ProcessHandle, DesiredAccess, + ObjectAttributes, ParentProcess, InheritObjectTable, SectionHandle, + DebugPort, ExceptionPort); + LOQ("PpO", "ProcessHandle", ProcessHandle, "DesiredAccess", DesiredAccess, + "FileName", ObjectAttributes); + if(NT_SUCCESS(ret)) { + pipe("PROCESS:%d", pid_from_process_handle(*ProcessHandle)); + disable_sleep_skip(); + } + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, NtCreateProcessEx, + __out PHANDLE ProcessHandle, + __in ACCESS_MASK DesiredAccess, + __in_opt POBJECT_ATTRIBUTES ObjectAttributes, + __in HANDLE ParentProcess, + __in ULONG Flags, + __in_opt HANDLE SectionHandle, + __in_opt HANDLE DebugPort, + __in_opt HANDLE ExceptionPort, + __in BOOLEAN InJob +) { + NTSTATUS ret = Old_NtCreateProcessEx(ProcessHandle, DesiredAccess, + ObjectAttributes, ParentProcess, Flags, SectionHandle, DebugPort, + ExceptionPort, InJob); + LOQ("PpO", "ProcessHandle", ProcessHandle, "DesiredAccess", DesiredAccess, + "FileName", ObjectAttributes); + if(NT_SUCCESS(ret)) { + pipe("PROCESS:%d", pid_from_process_handle(*ProcessHandle)); + disable_sleep_skip(); + } + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, NtCreateUserProcess, + __out PHANDLE ProcessHandle, + __out PHANDLE ThreadHandle, + __in ACCESS_MASK ProcessDesiredAccess, + __in ACCESS_MASK ThreadDesiredAccess, + __in_opt POBJECT_ATTRIBUTES ProcessObjectAttributes, + __in_opt POBJECT_ATTRIBUTES ThreadObjectAttributes, + __in ULONG ProcessFlags, + __in ULONG ThreadFlags, + __in_opt PRTL_USER_PROCESS_PARAMETERS ProcessParameters, + __inout PPS_CREATE_INFO CreateInfo, + __in_opt PPS_ATTRIBUTE_LIST AttributeList +) { + RTL_USER_PROCESS_PARAMETERS _ProcessParameters = {}; + if(ProcessParameters == NULL) ProcessParameters = &_ProcessParameters; + + NTSTATUS ret = Old_NtCreateUserProcess(ProcessHandle, ThreadHandle, + ProcessDesiredAccess, ThreadDesiredAccess, + ProcessObjectAttributes, ThreadObjectAttributes, + ProcessFlags, ThreadFlags, ProcessParameters, + CreateInfo, AttributeList); + LOQ("PPppOOoo", "ProcessHandle", ProcessHandle, + "ThreadHandle", ThreadHandle, + "ProcessDesiredAccess", ProcessDesiredAccess, + "ThreadDesiredAccess", ThreadDesiredAccess, + "ProcessFileName", ProcessObjectAttributes, + "ThreadName", ThreadObjectAttributes, + "ImagePathName", &ProcessParameters->ImagePathName, + "CommandLine", &ProcessParameters->CommandLine); + if(NT_SUCCESS(ret)) { + pipe("PROCESS:%d,%d", pid_from_process_handle(*ProcessHandle), + pid_from_thread_handle(*ThreadHandle)); + disable_sleep_skip(); + } + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, RtlCreateUserProcess, + IN PUNICODE_STRING ImagePath, + IN ULONG ObjectAttributes, + IN OUT PRTL_USER_PROCESS_PARAMETERS ProcessParameters, + IN PSECURITY_DESCRIPTOR ProcessSecurityDescriptor OPTIONAL, + IN PSECURITY_DESCRIPTOR ThreadSecurityDescriptor OPTIONAL, + IN HANDLE ParentProcess, + IN BOOLEAN InheritHandles, + IN HANDLE DebugPort OPTIONAL, + IN HANDLE ExceptionPort OPTIONAL, + OUT PRTL_USER_PROCESS_INFORMATION ProcessInformation +) { + NTSTATUS ret = Old_RtlCreateUserProcess(ImagePath, ObjectAttributes, + ProcessParameters, ProcessSecurityDescriptor, + ThreadSecurityDescriptor, ParentProcess, InheritHandles, DebugPort, + ExceptionPort, ProcessInformation); + LOQ("opp", "ImagePath", ImagePath, "ObjectAttributes", ObjectAttributes, + "ParentProcess", ParentProcess); + if(NT_SUCCESS(ret)) { + pipe("PROCESS:%d,%d", + pid_from_process_handle(ProcessInformation->ProcessHandle), + pid_from_thread_handle(ProcessInformation->ThreadHandle)); + disable_sleep_skip(); + } + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, NtOpenProcess, + __out PHANDLE ProcessHandle, + __in ACCESS_MASK DesiredAccess, + __in POBJECT_ATTRIBUTES ObjectAttributes, + __in_opt PCLIENT_ID ClientId +) { + // although the documentation on msdn is a bit vague, this seems correct + // for both XP and Vista (the ClientId->UniqueProcess part, that is) + + int pid = 0; + if(ClientId != NULL) { + pid = (int) ClientId->UniqueProcess; + } + + if(is_protected_pid(pid)) { + NTSTATUS ret = STATUS_ACCESS_DENIED; + LOQ("ppp", "ProcessHandle", NULL, "DesiredAccess", DesiredAccess, + "ProcessIdentifier", &pid); + return STATUS_ACCESS_DENIED; + } + + NTSTATUS ret = Old_NtOpenProcess(ProcessHandle, DesiredAccess, + ObjectAttributes, ClientId); + LOQ2("PpP", "ProcessHandle", ProcessHandle, + "DesiredAccess", DesiredAccess, + "ProcessIdentifier", &pid); + /* + if(NT_SUCCESS(ret)) { + // let's do an extra check here, because the msdn documentation is + // so vague.. + unsigned long pid = pid_from_process_handle(*ProcessHandle); + // check if this pid is protected + if(is_protected_pid(pid)) { + CloseHandle(*ProcessHandle); + return STATUS_ACCESS_DENIED; + } + pipe("PROCESS:%d", pid); + } + */ + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, NtTerminateProcess, + __in_opt HANDLE ProcessHandle, + __in NTSTATUS ExitStatus +) { + NTSTATUS ret = Old_NtTerminateProcess(ProcessHandle, ExitStatus); + LOQ("pl", "ProcessHandle", ProcessHandle, "ExitCode", ExitStatus); + log_flush(); + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, NtCreateSection, + __out PHANDLE SectionHandle, + __in ACCESS_MASK DesiredAccess, + __in_opt POBJECT_ATTRIBUTES ObjectAttributes, + __in_opt PLARGE_INTEGER MaximumSize, + __in ULONG SectionPageProtection, + __in ULONG AllocationAttributes, + __in_opt HANDLE FileHandle +) { + NTSTATUS ret = Old_NtCreateSection(SectionHandle, DesiredAccess, + ObjectAttributes, MaximumSize, SectionPageProtection, + AllocationAttributes, FileHandle); + LOQ("PpOp", "SectionHandle", SectionHandle, + "DesiredAccess", DesiredAccess, "ObjectAttributes", ObjectAttributes, + "FileHandle", FileHandle); + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, NtMakeTemporaryObject, + __in HANDLE ObjectHandle +) { + NTSTATUS ret = Old_NtMakeTemporaryObject(ObjectHandle); + LOQ("p", "ObjectHandle", ObjectHandle); + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, NtMakePermanentObject, + __in HANDLE ObjectHandle +) { + NTSTATUS ret = Old_NtMakePermanentObject(ObjectHandle); + LOQ("p", "ObjectHandle", ObjectHandle); + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, NtOpenSection, + __out PHANDLE SectionHandle, + __in ACCESS_MASK DesiredAccess, + __in POBJECT_ATTRIBUTES ObjectAttributes +) { + NTSTATUS ret = Old_NtOpenSection(SectionHandle, DesiredAccess, + ObjectAttributes); + LOQ("PpO", "SectionHandle", SectionHandle, "DesiredAccess", DesiredAccess, + "ObjectAttributes", ObjectAttributes); + return ret; +} + +HOOKDEF(BOOL, WINAPI, CreateProcessInternalW, + __in_opt LPVOID lpUnknown1, + __in_opt LPWSTR lpApplicationName, + __inout_opt LPWSTR lpCommandLine, + __in_opt LPSECURITY_ATTRIBUTES lpProcessAttributes, + __in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes, + __in BOOL bInheritHandles, + __in DWORD dwCreationFlags, + __in_opt LPVOID lpEnvironment, + __in_opt LPWSTR lpCurrentDirectory, + __in LPSTARTUPINFO lpStartupInfo, + __out LPPROCESS_INFORMATION lpProcessInformation, + __in_opt LPVOID lpUnknown2 +) { + BOOL ret = Old_CreateProcessInternalW(lpUnknown1, lpApplicationName, + lpCommandLine, lpProcessAttributes, lpThreadAttributes, + bInheritHandles, dwCreationFlags, lpEnvironment, + lpCurrentDirectory, lpStartupInfo, lpProcessInformation, lpUnknown2); + LOQ("uupllpp", "ApplicationName", lpApplicationName, + "CommandLine", lpCommandLine, "CreationFlags", dwCreationFlags, + "ProcessId", lpProcessInformation->dwProcessId, + "ThreadId", lpProcessInformation->dwThreadId, + "ProcessHandle", lpProcessInformation->hProcess, + "ThreadHandle", lpProcessInformation->hThread); + return ret; +} + +HOOKDEF(VOID, WINAPI, ExitProcess, + __in UINT uExitCode +) { + IS_SUCCESS_VOID(); + + int ret = 0; + LOQ("l", "ExitCode", uExitCode); + log_free(); + Old_ExitProcess(uExitCode); +} + +HOOKDEF(BOOL, WINAPI, ShellExecuteExW, + __inout SHELLEXECUTEINFOW *pExecInfo +) { + IS_SUCCESS_BOOL(); + + BOOL ret = Old_ShellExecuteExW(pExecInfo); + LOQ("2ul", "FilePath", pExecInfo->lpFile, + "Parameters", pExecInfo->lpParameters, "Show", pExecInfo->nShow); + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, NtUnmapViewOfSection, + _In_ HANDLE ProcessHandle, + _In_opt_ PVOID BaseAddress +) { + unsigned int map_size = 0; MEMORY_BASIC_INFORMATION mbi; + if(VirtualQueryEx(ProcessHandle, BaseAddress, &mbi, + sizeof(mbi)) == sizeof(mbi)) { + map_size = mbi.RegionSize; + } + NTSTATUS ret = Old_NtUnmapViewOfSection(ProcessHandle, BaseAddress); + if(NT_SUCCESS(ret)) { + pipe("UNMAP:%d,%x,%x", pid_from_process_handle(ProcessHandle), + BaseAddress, map_size); + } + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, NtAllocateVirtualMemory, + __in HANDLE ProcessHandle, + __inout PVOID *BaseAddress, + __in ULONG_PTR ZeroBits, + __inout PSIZE_T RegionSize, + __in ULONG AllocationType, + __in ULONG Protect +) { + NTSTATUS ret = Old_NtAllocateVirtualMemory(ProcessHandle, BaseAddress, + ZeroBits, RegionSize, AllocationType, Protect); + LOQ("pPPp", "ProcessHandle", ProcessHandle, "BaseAddress", BaseAddress, + "RegionSize", RegionSize, "Protection", Protect); + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, NtReadVirtualMemory, + __in HANDLE ProcessHandle, + __in LPCVOID BaseAddress, + __out LPVOID Buffer, + __in ULONG NumberOfBytesToRead, + __out_opt PULONG NumberOfBytesReaded +) { + ENSURE_ULONG(NumberOfBytesReaded); + + BOOL ret = Old_NtReadVirtualMemory(ProcessHandle, BaseAddress, Buffer, + NumberOfBytesToRead, NumberOfBytesReaded); + + LOQ("2pB", "ProcessHandle", ProcessHandle, "BaseAddress", BaseAddress, + "Buffer", NumberOfBytesReaded, Buffer); + return ret; +} + +HOOKDEF(BOOL, WINAPI, ReadProcessMemory, + _In_ HANDLE hProcess, + _In_ LPCVOID lpBaseAddress, + _Out_ LPVOID lpBuffer, + _In_ SIZE_T nSize, + _Out_ SIZE_T *lpNumberOfBytesRead +) { + IS_SUCCESS_BOOL(); + ENSURE_SIZET(lpNumberOfBytesRead); + + BOOL ret = Old_ReadProcessMemory(hProcess, lpBaseAddress, lpBuffer, + nSize, lpNumberOfBytesRead); + + LOQ("ppB", "ProcessHandle", hProcess, "BaseAddress", lpBaseAddress, + "Buffer", lpNumberOfBytesRead, lpBuffer); + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, NtWriteVirtualMemory, + __in HANDLE ProcessHandle, + __in LPVOID BaseAddress, + __in LPCVOID Buffer, + __in ULONG NumberOfBytesToWrite, + __out_opt ULONG *NumberOfBytesWritten +) { + ENSURE_ULONG(NumberOfBytesWritten); + + BOOL ret = Old_NtWriteVirtualMemory(ProcessHandle, BaseAddress, Buffer, + NumberOfBytesToWrite, NumberOfBytesWritten); + + LOQ("2pB", "ProcessHandle", ProcessHandle, "BaseAddress", BaseAddress, + "Buffer", NumberOfBytesWritten, Buffer); + return ret; +} + +HOOKDEF(BOOL, WINAPI, WriteProcessMemory, + _In_ HANDLE hProcess, + _In_ LPVOID lpBaseAddress, + _In_ LPCVOID lpBuffer, + _In_ SIZE_T nSize, + _Out_ SIZE_T *lpNumberOfBytesWritten +) { + IS_SUCCESS_BOOL(); + ENSURE_SIZET(lpNumberOfBytesWritten); + + BOOL ret = Old_WriteProcessMemory(hProcess, lpBaseAddress, lpBuffer, + nSize, lpNumberOfBytesWritten); + + LOQ("ppB", "ProcessHandle", hProcess, "BaseAddress", lpBaseAddress, + "Buffer", lpNumberOfBytesWritten, lpBuffer); + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, NtProtectVirtualMemory, + IN HANDLE ProcessHandle, + IN OUT PVOID *BaseAddress, + IN OUT PULONG NumberOfBytesToProtect, + IN ULONG NewAccessProtection, + OUT PULONG OldAccessProtection +) { + NTSTATUS ret = Old_NtProtectVirtualMemory(ProcessHandle, BaseAddress, + NumberOfBytesToProtect, NewAccessProtection, OldAccessProtection); + LOQ("pPPpP", "ProcessHandle", ProcessHandle, "BaseAddress", BaseAddress, + "NumberOfBytesProtected", NumberOfBytesToProtect, + "NewAccessProtection", NewAccessProtection, + "OldAccessProtection", OldAccessProtection); + return ret; +} + +HOOKDEF(BOOL, WINAPI, VirtualProtectEx, + __in HANDLE hProcess, + __in LPVOID lpAddress, + __in SIZE_T dwSize, + __in DWORD flNewProtect, + __out PDWORD lpflOldProtect +) { + IS_SUCCESS_BOOL(); + + BOOL ret = Old_VirtualProtectEx(hProcess, lpAddress, dwSize, flNewProtect, + lpflOldProtect); + LOQ("pppp", "ProcessHandle", hProcess, "Address", lpAddress, + "Size", dwSize, "Protection", flNewProtect); + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, NtFreeVirtualMemory, + IN HANDLE ProcessHandle, + IN PVOID *BaseAddress, + IN OUT PULONG RegionSize, + IN ULONG FreeType +) { + NTSTATUS ret = Old_NtFreeVirtualMemory(ProcessHandle, BaseAddress, + RegionSize, FreeType); + LOQ("pPPp", "ProcessHandle", ProcessHandle, "BaseAddress", BaseAddress, + "RegionSize", RegionSize, "FreeType", FreeType); + return ret; +} + +HOOKDEF(BOOL, WINAPI, VirtualFreeEx, + __in HANDLE hProcess, + __in LPVOID lpAddress, + __in SIZE_T dwSize, + __in DWORD dwFreeType +) { + IS_SUCCESS_BOOL(); + + BOOL ret = Old_VirtualFreeEx(hProcess, lpAddress, dwSize, dwFreeType); + LOQ("pppl", "ProcessHandle", hProcess, "Address", lpAddress, + "Size", dwSize, "FreeType", dwFreeType); + return ret; +} + +HOOKDEF(int, CDECL, system, + const char *command +) { + IS_SUCCESS_INTM1(); + + int ret = Old_system(command); + LOQ("s", "Command", command); + return ret; +} diff --git a/hook_reg.c b/hook_reg.c new file mode 100644 index 0000000..6d226bb --- /dev/null +++ b/hook_reg.c @@ -0,0 +1,370 @@ +/* +Cuckoo Sandbox - Automated Malware Analysis +Copyright (C) 2010-2014 Cuckoo Sandbox Developers + +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 . +*/ + +#include +#include +#include "hooking.h" +#include "ntapi.h" +#include "log.h" + +static IS_SUCCESS_LONGREG(); + +HOOKDEF(LONG, WINAPI, RegOpenKeyExA, + __in HKEY hKey, + __in_opt LPCTSTR lpSubKey, + __reserved DWORD ulOptions, + __in REGSAM samDesired, + __out PHKEY phkResult +) { + LONG ret = Old_RegOpenKeyExA(hKey, lpSubKey, ulOptions, samDesired, + phkResult); + LOQ("psP", "Registry", hKey, "SubKey", lpSubKey, "Handle", phkResult); + return ret; +} + +HOOKDEF(LONG, WINAPI, RegOpenKeyExW, + __in HKEY hKey, + __in_opt LPWSTR lpSubKey, + __reserved DWORD ulOptions, + __in REGSAM samDesired, + __out PHKEY phkResult +) { + LONG ret = Old_RegOpenKeyExW(hKey, lpSubKey, ulOptions, samDesired, + phkResult); + LOQ("puP", "Registry", hKey, "SubKey", lpSubKey, "Handle", phkResult); + return ret; +} + +HOOKDEF(LONG, WINAPI, RegCreateKeyExA, + __in HKEY hKey, + __in LPCTSTR lpSubKey, + __reserved DWORD Reserved, + __in_opt LPTSTR lpClass, + __in DWORD dwOptions, + __in REGSAM samDesired, + __in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes, + __out PHKEY phkResult, + __out_opt LPDWORD lpdwDisposition +) { + LONG ret = Old_RegCreateKeyExA(hKey, lpSubKey, Reserved, lpClass, + dwOptions, samDesired, lpSecurityAttributes, phkResult, + lpdwDisposition); + LOQ("psslP", "Registry", hKey, "SubKey", lpSubKey, "Class", lpClass, + "Access", samDesired, "Handle", phkResult); + return ret; +} + +HOOKDEF(LONG, WINAPI, RegCreateKeyExW, + __in HKEY hKey, + __in LPWSTR lpSubKey, + __reserved DWORD Reserved, + __in_opt LPWSTR lpClass, + __in DWORD dwOptions, + __in REGSAM samDesired, + __in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes, + __out PHKEY phkResult, + __out_opt LPDWORD lpdwDisposition +) { + LONG ret = Old_RegCreateKeyExW(hKey, lpSubKey, Reserved, lpClass, + dwOptions, samDesired, lpSecurityAttributes, phkResult, + lpdwDisposition); + LOQ("puulP", "Registry", hKey, "SubKey", lpSubKey, "Class", lpClass, + "Access", samDesired, "Handle", phkResult); + return ret; +} + +HOOKDEF(LONG, WINAPI, RegDeleteKeyA, + __in HKEY hKey, + __in LPCTSTR lpSubKey +) { + LONG ret = Old_RegDeleteKeyA(hKey, lpSubKey); + LOQ("ps", "Handle", hKey, "SubKey", lpSubKey); + return ret; +} + +HOOKDEF(LONG, WINAPI, RegDeleteKeyW, + __in HKEY hKey, + __in LPWSTR lpSubKey +) { + LONG ret = Old_RegDeleteKeyW(hKey, lpSubKey); + LOQ("pu", "Handle", hKey, "SubKey", lpSubKey); + return ret; +} + +HOOKDEF(LONG, WINAPI, RegEnumKeyW, + __in HKEY hKey, + __in DWORD dwIndex, + __out LPWSTR lpName, + __in DWORD cchName +) { + LONG ret = Old_RegEnumKeyW(hKey, dwIndex, lpName, cchName); + LOQ("plu", "Handle", hKey, "Index", dwIndex, "Name", lpName); + return ret; +} + +HOOKDEF(LONG, WINAPI, RegEnumKeyExA, + __in HKEY hKey, + __in DWORD dwIndex, + __out LPTSTR lpName, + __inout LPDWORD lpcName, + __reserved LPDWORD lpReserved, + __inout LPTSTR lpClass, + __inout_opt LPDWORD lpcClass, + __out_opt PFILETIME lpftLastWriteTime +) { + LONG ret = Old_RegEnumKeyExA(hKey, dwIndex, lpName, lpcName, lpReserved, + lpClass, lpcClass, lpftLastWriteTime); + LOQ("plss", "Handle", hKey, "Index", dwIndex, "Name", lpName, + "Class", lpClass); + return ret; +} + +HOOKDEF(LONG, WINAPI, RegEnumKeyExW, + __in HKEY hKey, + __in DWORD dwIndex, + __out LPWSTR lpName, + __inout LPDWORD lpcName, + __reserved LPDWORD lpReserved, + __inout LPWSTR lpClass, + __inout_opt LPDWORD lpcClass, + __out_opt PFILETIME lpftLastWriteTime +) { + LONG ret = Old_RegEnumKeyExW(hKey, dwIndex, lpName, lpcName, lpReserved, + lpClass, lpcClass, lpftLastWriteTime); + LOQ("pluu", "Handle", hKey, "Index", dwIndex, "Name", lpName, + "Class", lpClass); + return ret; +} + +HOOKDEF(LONG, WINAPI, RegEnumValueA, + __in HKEY hKey, + __in DWORD dwIndex, + __out LPTSTR lpValueName, + __inout LPDWORD lpcchValueName, + __reserved LPDWORD lpReserved, + __out_opt LPDWORD lpType, + __out_opt LPBYTE lpData, + __inout_opt LPDWORD lpcbData +) { + ENSURE_DWORD(lpType); + LONG ret = Old_RegEnumValueA(hKey, dwIndex, lpValueName, lpcchValueName, + lpReserved, lpType, lpData, lpcbData); + if(ret == ERROR_SUCCESS && lpType != NULL && lpData != NULL && + lpcbData != NULL) { + LOQ("plsr", "Handle", hKey, "Index", dwIndex, + "ValueName", lpValueName, "Data", *lpType, *lpcbData, lpData); + } + else { + LOQ2("plsLL", "Handle", hKey, "Index", dwIndex, + "ValueName", lpValueName, "Type", lpType, "DataLength", lpcbData); + } + return ret; +} + +HOOKDEF(LONG, WINAPI, RegEnumValueW, + __in HKEY hKey, + __in DWORD dwIndex, + __out LPWSTR lpValueName, + __inout LPDWORD lpcchValueName, + __reserved LPDWORD lpReserved, + __out_opt LPDWORD lpType, + __out_opt LPBYTE lpData, + __inout_opt LPDWORD lpcbData +) { + ENSURE_DWORD(lpType); + LONG ret = Old_RegEnumValueW(hKey, dwIndex, lpValueName, lpcchValueName, + lpReserved, lpType, lpData, lpcbData); + if(ret == ERROR_SUCCESS && lpType != NULL && lpData != NULL && + lpcbData != NULL) { + LOQ("pluR", "Handle", hKey, "Index", dwIndex, + "ValueName", lpValueName, "Data", *lpType, *lpcbData, lpData); + } + else { + LOQ2("pluLL", "Handle", hKey, "Index", dwIndex, + "ValueName", lpValueName, "Type", lpType, "DataLength", lpcbData); + } + return ret; +} + +HOOKDEF(LONG, WINAPI, RegSetValueExA, + __in HKEY hKey, + __in_opt LPCTSTR lpValueName, + __reserved DWORD Reserved, + __in DWORD dwType, + __in const BYTE *lpData, + __in DWORD cbData +) { + LONG ret = Old_RegSetValueExA(hKey, lpValueName, Reserved, dwType, lpData, + cbData); + if(ret == ERROR_SUCCESS) { + LOQ("pslr", "Handle", hKey, "ValueName", lpValueName, "Type", dwType, + "Buffer", dwType, cbData, lpData); + } + else { + LOQ2("psl", "Handle", hKey, "ValueName", lpValueName, "Type", dwType); + } + return ret; +} + +HOOKDEF(LONG, WINAPI, RegSetValueExW, + __in HKEY hKey, + __in_opt LPWSTR lpValueName, + __reserved DWORD Reserved, + __in DWORD dwType, + __in const BYTE *lpData, + __in DWORD cbData +) { + LONG ret = Old_RegSetValueExW(hKey, lpValueName, Reserved, dwType, lpData, + cbData); + if(ret == ERROR_SUCCESS) { + LOQ("pulR", "Handle", hKey, "ValueName", lpValueName, "Type", dwType, + "Buffer", dwType, cbData, lpData); + } + else { + LOQ2("pul", "Handle", hKey, "ValueName", lpValueName, "Type", dwType); + } + return ret; +} + +HOOKDEF(LONG, WINAPI, RegQueryValueExA, + __in HKEY hKey, + __in_opt LPCTSTR lpValueName, + __reserved LPDWORD lpReserved, + __out_opt LPDWORD lpType, + __out_opt LPBYTE lpData, + __inout_opt LPDWORD lpcbData +) { + ENSURE_DWORD(lpType); + LONG ret = Old_RegQueryValueExA(hKey, lpValueName, lpReserved, lpType, + lpData, lpcbData); + if(ret == ERROR_SUCCESS && lpType != NULL && lpData != NULL && + lpcbData != NULL) { + LOQ("psr", "Handle", hKey, "ValueName", lpValueName, + "Data", *lpType, *lpcbData, lpData); + } + else { + LOQ2("psLL", "Handle", hKey, "ValueName", lpValueName, + "Type", lpType, "DataLength", lpcbData); + } + return ret; +} + +HOOKDEF(LONG, WINAPI, RegQueryValueExW, + __in HKEY hKey, + __in_opt LPWSTR lpValueName, + __reserved LPDWORD lpReserved, + __out_opt LPDWORD lpType, + __out_opt LPBYTE lpData, + __inout_opt LPDWORD lpcbData +) { + ENSURE_DWORD(lpType); + LONG ret = Old_RegQueryValueExW(hKey, lpValueName, lpReserved, lpType, + lpData, lpcbData); + if(ret == ERROR_SUCCESS && lpType != NULL && lpData != NULL && + lpcbData != NULL) { + LOQ("puR", "Handle", hKey, "ValueName", lpValueName, + "Data", *lpType, *lpcbData, lpData); + } + else { + LOQ2("puLL", "Handle", hKey, "ValueName", lpValueName, + "Type", lpType, "DataLength", lpcbData); + } + return ret; +} + +HOOKDEF(LONG, WINAPI, RegDeleteValueA, + __in HKEY hKey, + __in_opt LPCTSTR lpValueName +) { + LONG ret = Old_RegDeleteValueA(hKey, lpValueName); + LOQ("ps", "Handle", hKey, "ValueName", lpValueName); + return ret; +} + +HOOKDEF(LONG, WINAPI, RegDeleteValueW, + __in HKEY hKey, + __in_opt LPWSTR lpValueName +) { + LONG ret = Old_RegDeleteValueW(hKey, lpValueName); + LOQ("pu", "Handle", hKey, "ValueName", lpValueName); + return ret; +} + +HOOKDEF(LONG, WINAPI, RegQueryInfoKeyA, + _In_ HKEY hKey, + _Out_opt_ LPTSTR lpClass, + _Inout_opt_ LPDWORD lpcClass, + _Reserved_ LPDWORD lpReserved, + _Out_opt_ LPDWORD lpcSubKeys, + _Out_opt_ LPDWORD lpcMaxSubKeyLen, + _Out_opt_ LPDWORD lpcMaxClassLen, + _Out_opt_ LPDWORD lpcValues, + _Out_opt_ LPDWORD lpcMaxValueNameLen, + _Out_opt_ LPDWORD lpcMaxValueLen, + _Out_opt_ LPDWORD lpcbSecurityDescriptor, + _Out_opt_ PFILETIME lpftLastWriteTime +) { + IS_SUCCESS_LONGREG(); + + LONG ret = Old_RegQueryInfoKeyA(hKey, lpClass, lpcClass, lpReserved, + lpcSubKeys, lpcMaxSubKeyLen, lpcMaxClassLen, lpcValues, + lpcMaxValueNameLen, lpcMaxValueLen, lpcbSecurityDescriptor, + lpftLastWriteTime); + LOQ("pS6L", "KeyHandle", hKey, "Class", lpcClass ? *lpcClass : 0, lpClass, + "SubKeyCount", lpcSubKeys, "MaxSubKeyLength", lpcMaxSubKeyLen, + "MaxClassLength", lpcMaxClassLen, "ValueCount", lpcValues, + "MaxValueNameLength", lpcMaxValueNameLen, + "MaxValueLength", lpcMaxValueLen); + return ret; +} + +HOOKDEF(LONG, WINAPI, RegQueryInfoKeyW, + _In_ HKEY hKey, + _Out_opt_ LPWSTR lpClass, + _Inout_opt_ LPDWORD lpcClass, + _Reserved_ LPDWORD lpReserved, + _Out_opt_ LPDWORD lpcSubKeys, + _Out_opt_ LPDWORD lpcMaxSubKeyLen, + _Out_opt_ LPDWORD lpcMaxClassLen, + _Out_opt_ LPDWORD lpcValues, + _Out_opt_ LPDWORD lpcMaxValueNameLen, + _Out_opt_ LPDWORD lpcMaxValueLen, + _Out_opt_ LPDWORD lpcbSecurityDescriptor, + _Out_opt_ PFILETIME lpftLastWriteTime +) { + IS_SUCCESS_LONGREG(); + + LONG ret = Old_RegQueryInfoKeyW(hKey, lpClass, lpcClass, lpReserved, + lpcSubKeys, lpcMaxSubKeyLen, lpcMaxClassLen, lpcValues, + lpcMaxValueNameLen, lpcMaxValueLen, lpcbSecurityDescriptor, + lpftLastWriteTime); + LOQ("pU6L", "KeyHandle", hKey, "Class", lpcClass ? *lpcClass : 0, lpClass, + "SubKeyCount", lpcSubKeys, "MaxSubKeyLength", lpcMaxSubKeyLen, + "MaxClassLength", lpcMaxClassLen, "ValueCount", lpcValues, + "MaxValueNameLength", lpcMaxValueNameLen, + "MaxValueLength", lpcMaxValueLen); + return ret; +} + +HOOKDEF(LONG, WINAPI, RegCloseKey, + __in HKEY hKey +) { + LONG ret = Old_RegCloseKey(hKey); + LOQ("p", "Handle", hKey); + return ret; +} diff --git a/hook_reg_native.c b/hook_reg_native.c new file mode 100644 index 0000000..436e321 --- /dev/null +++ b/hook_reg_native.c @@ -0,0 +1,283 @@ +/* +Cuckoo Sandbox - Automated Malware Analysis +Copyright (C) 2010-2014 Cuckoo Sandbox Developers + +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 . +*/ + +#include +#include +#include "hooking.h" +#include "ntapi.h" +#include "log.h" +#include "pipe.h" + +static IS_SUCCESS_LONGREG(); + +HOOKDEF(NTSTATUS, WINAPI, NtCreateKey, + __out PHANDLE KeyHandle, + __in ACCESS_MASK DesiredAccess, + __in POBJECT_ATTRIBUTES ObjectAttributes, + __reserved ULONG TitleIndex, + __in_opt PUNICODE_STRING Class, + __in ULONG CreateOptions, + __out_opt PULONG Disposition +) { + NTSTATUS ret = Old_NtCreateKey(KeyHandle, DesiredAccess, ObjectAttributes, + TitleIndex, Class, CreateOptions, Disposition); + LOQ("Ploo", "KeyHandle", KeyHandle, "DesiredAccess", DesiredAccess, + "ObjectAttributes", unistr_from_objattr(ObjectAttributes), + "Class", Class); + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, NtOpenKey, + __out PHANDLE KeyHandle, + __in ACCESS_MASK DesiredAccess, + __in POBJECT_ATTRIBUTES ObjectAttributes +) { + NTSTATUS ret = Old_NtOpenKey(KeyHandle, DesiredAccess, ObjectAttributes); + LOQ("Plo", "KeyHandle", KeyHandle, "DesiredAccess", DesiredAccess, + "ObjectAttributes", unistr_from_objattr(ObjectAttributes)); + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, NtOpenKeyEx, + __out PHANDLE KeyHandle, + __in ACCESS_MASK DesiredAccess, + __in POBJECT_ATTRIBUTES ObjectAttributes, + __in ULONG OpenOptions +) { + NTSTATUS ret = Old_NtOpenKeyEx(KeyHandle, DesiredAccess, ObjectAttributes, + OpenOptions); + LOQ("Plo", "KeyHandle", KeyHandle, "DesiredAccess", DesiredAccess, + "ObjectAttributes", unistr_from_objattr(ObjectAttributes)); + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, NtRenameKey, + __in HANDLE KeyHandle, + __in PUNICODE_STRING NewName +) { + NTSTATUS ret = Old_NtRenameKey(KeyHandle, NewName); + LOQ("po", "KeyHandle", KeyHandle, "NewName", NewName); + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, NtReplaceKey, + __in POBJECT_ATTRIBUTES NewHiveFileName, + __in HANDLE KeyHandle, + __in POBJECT_ATTRIBUTES BackupHiveFileName +) { + NTSTATUS ret = Old_NtReplaceKey(NewHiveFileName, KeyHandle, + BackupHiveFileName); + LOQ("poo", "KeyHandle", KeyHandle, + "NewHiveFileName", unistr_from_objattr(NewHiveFileName), + "BackupHiveFileName", unistr_from_objattr(BackupHiveFileName)); + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, NtEnumerateKey, + __in HANDLE KeyHandle, + __in ULONG Index, + __in KEY_INFORMATION_CLASS KeyInformationClass, + __out_opt PVOID KeyInformation, + __in ULONG Length, + __out PULONG ResultLength +) { + NTSTATUS ret = Old_NtEnumerateKey(KeyHandle, Index, KeyInformationClass, + KeyInformation, Length, ResultLength); + LOQ("pl", "KeyHandle", KeyHandle, "Index", Index); + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, NtEnumerateValueKey, + __in HANDLE KeyHandle, + __in ULONG Index, + __in KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, + __out_opt PVOID KeyValueInformation, + __in ULONG Length, + __out PULONG ResultLength +) { + NTSTATUS ret = Old_NtEnumerateValueKey(KeyHandle, Index, + KeyValueInformationClass, KeyValueInformation, Length, ResultLength); + LOQ("pll", "KeyHandle", KeyHandle, "Index", Index, + "KeyValueInformationClass", KeyValueInformationClass); + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, NtSetValueKey, + __in HANDLE KeyHandle, + __in PUNICODE_STRING ValueName, + __in_opt ULONG TitleIndex, + __in ULONG Type, + __in_opt PVOID Data, + __in ULONG DataSize +) { + NTSTATUS ret = Old_NtSetValueKey(KeyHandle, ValueName, TitleIndex, + Type, Data, DataSize); + if(NT_SUCCESS(ret)) { + LOQ("polR", "KeyHandle", KeyHandle, "ValueName", ValueName, + "Type", Type, "Buffer", Type, DataSize, Data); + } + else { + LOQ2("pol", "KeyHandle", KeyHandle, "ValueName", ValueName, + "Type", Type); + } + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, NtQueryValueKey, + __in HANDLE KeyHandle, + __in PUNICODE_STRING ValueName, + __in KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, + __out_opt PVOID KeyValueInformation, + __in ULONG Length, + __out PULONG ResultLength +) { + ENSURE_ULONG_ZERO(ResultLength); + + NTSTATUS ret = Old_NtQueryValueKey(KeyHandle, ValueName, + KeyValueInformationClass, KeyValueInformation, Length, ResultLength); + if(NT_SUCCESS(ret) && + *ResultLength >= sizeof(ULONG) * 3) { + ULONG Type, DataLength = 0; UCHAR *Data = NULL; + + // someday add support for Name and NameLength, if there's use for it + + Type = ((KEY_VALUE_PARTIAL_INFORMATION *) KeyValueInformation)->Type; + if(KeyValueInformationClass == KeyValueFullInformation) { + KEY_VALUE_FULL_INFORMATION *p = + (KEY_VALUE_FULL_INFORMATION *) KeyValueInformation; + DataLength = p->DataLength; + Data = (UCHAR *) KeyValueInformation + p->DataOffset; + } + else if(KeyValueInformationClass == KeyValuePartialInformation) { + KEY_VALUE_PARTIAL_INFORMATION *p = + (KEY_VALUE_PARTIAL_INFORMATION *) KeyValueInformation; + DataLength = p->DataLength; + Data = p->Data; + } + + LOQ("polR", "KeyHandle", KeyHandle, "ValueName", ValueName, + "Type", Type, "Information", Type, DataLength, Data); + } + else { + LOQ2("po", "KeyHandle", KeyHandle, "ValueName", ValueName); + } + + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, NtQueryMultipleValueKey, + __in HANDLE KeyHandle, + __inout PKEY_VALUE_ENTRY ValueEntries, + __in ULONG EntryCount, + __out PVOID ValueBuffer, + __inout PULONG BufferLength, + __out_opt PULONG RequiredBufferLength +) { + NTSTATUS ret = Old_NtQueryMultipleValueKey(KeyHandle, ValueEntries, + EntryCount, ValueBuffer, BufferLength, RequiredBufferLength); + LOQ("poS", "KeyHandle", KeyHandle, "ValueName", ValueEntries->ValueName, + "ValueBuffer", *BufferLength, ValueBuffer); + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, NtDeleteKey, + __in HANDLE KeyHandle +) { + NTSTATUS ret = Old_NtDeleteKey(KeyHandle); + LOQ("p", "KeyHandle", KeyHandle); + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, NtDeleteValueKey, + __in HANDLE KeyHandle, + __in PUNICODE_STRING ValueName +) { + NTSTATUS ret = Old_NtDeleteValueKey(KeyHandle, ValueName); + LOQ("po", "KeyHandle", KeyHandle, "ValueName", ValueName); + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, NtLoadKey, + __in POBJECT_ATTRIBUTES TargetKey, + __in POBJECT_ATTRIBUTES SourceFile +) { + NTSTATUS ret = Old_NtLoadKey(TargetKey, SourceFile); + LOQ("oo", "TargetKey", unistr_from_objattr(TargetKey), + "SourceFile", unistr_from_objattr(SourceFile)); + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, NtLoadKey2, + __in POBJECT_ATTRIBUTES TargetKey, + __in POBJECT_ATTRIBUTES SourceFile, + __in ULONG Flags +) { + NTSTATUS ret = Old_NtLoadKey2(TargetKey, SourceFile, Flags); + LOQ("ool", "TargetKey", unistr_from_objattr(TargetKey), + "SourceFile", unistr_from_objattr(SourceFile), "Flags", Flags); + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, NtLoadKeyEx, + __in POBJECT_ATTRIBUTES TargetKey, + __in POBJECT_ATTRIBUTES SourceFile, + __in ULONG Flags, + __in_opt HANDLE TrustClassKey +) { + NTSTATUS ret = Old_NtLoadKeyEx(TargetKey, SourceFile, Flags, + TrustClassKey); + LOQ("pool", "TrustClassKey", TrustClassKey, + "TargetKey", unistr_from_objattr(TargetKey), + "SourceFile", unistr_from_objattr(SourceFile), "Flags", Flags); + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, NtQueryKey, + __in HANDLE KeyHandle, + __in KEY_INFORMATION_CLASS KeyInformationClass, + __out_opt PVOID KeyInformation, + __in ULONG Length, + __out PULONG ResultLength +) { + NTSTATUS ret = Old_NtQueryKey(KeyHandle, KeyInformationClass, + KeyInformation, Length, ResultLength); + LOQ("pSl", "KeyHandle", KeyHandle, + "KeyInformation", Length, KeyInformation, + "KeyInformationClass", KeyInformationClass); + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, NtSaveKey, + __in HANDLE KeyHandle, + __in HANDLE FileHandle +) { + NTSTATUS ret = Old_NtSaveKey(KeyHandle, FileHandle); + LOQ("pp", "KeyHandle", KeyHandle, "FileHandle", FileHandle); + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, NtSaveKeyEx, + __in HANDLE KeyHandle, + __in HANDLE FileHandle, + __in ULONG Format +) { + NTSTATUS ret = Old_NtSaveKeyEx(KeyHandle, FileHandle, Format); + LOQ("ppl", "KeyHandle", KeyHandle, "FileHandle", FileHandle, + "Format", Format); + return ret; +} diff --git a/hook_services.c b/hook_services.c new file mode 100644 index 0000000..10a77f8 --- /dev/null +++ b/hook_services.c @@ -0,0 +1,181 @@ +/* +Cuckoo Sandbox - Automated Malware Analysis +Copyright (C) 2010-2014 Cuckoo Sandbox Developers + +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 . +*/ + +#include +#include +#include "hooking.h" +#include "ntapi.h" +#include "log.h" + +static IS_SUCCESS_SCHANDLE(); + +HOOKDEF(SC_HANDLE, WINAPI, OpenSCManagerA, + __in_opt LPCTSTR lpMachineName, + __in_opt LPCTSTR lpDatabaseName, + __in DWORD dwDesiredAccess +) { + SC_HANDLE ret = Old_OpenSCManagerA(lpMachineName, lpDatabaseName, + dwDesiredAccess); + LOQ("ssl", "MachineName", lpMachineName, "DatabaseName", lpDatabaseName, + "DesiredAccess", dwDesiredAccess); + return ret; +} + +HOOKDEF(SC_HANDLE, WINAPI, OpenSCManagerW, + __in_opt LPWSTR lpMachineName, + __in_opt LPWSTR lpDatabaseName, + __in DWORD dwDesiredAccess +) { + SC_HANDLE ret = Old_OpenSCManagerW(lpMachineName, lpDatabaseName, + dwDesiredAccess); + LOQ("uul", "MachineName", lpMachineName, "DatabaseName", lpDatabaseName, + "DesiredAccess", dwDesiredAccess); + return ret; +} + +HOOKDEF(SC_HANDLE, WINAPI, CreateServiceA, + __in SC_HANDLE hSCManager, + __in LPCTSTR lpServiceName, + __in_opt LPCTSTR lpDisplayName, + __in DWORD dwDesiredAccess, + __in DWORD dwServiceType, + __in DWORD dwStartType, + __in DWORD dwErrorControl, + __in_opt LPCTSTR lpBinaryPathName, + __in_opt LPCTSTR lpLoadOrderGroup, + __out_opt LPDWORD lpdwTagId, + __in_opt LPCTSTR lpDependencies, + __in_opt LPCTSTR lpServiceStartName, + __in_opt LPCTSTR lpPassword +) { + SC_HANDLE ret = Old_CreateServiceA(hSCManager, lpServiceName, + lpDisplayName, dwDesiredAccess, dwServiceType, dwStartType, + dwErrorControl, lpBinaryPathName, lpLoadOrderGroup, lpdwTagId, + lpDependencies, lpServiceStartName, lpPassword); + LOQ("pss4l3s", "ServiceControlHandle", hSCManager, + "ServiceName", lpServiceName, "DisplayName", lpDisplayName, + "DesiredAccess", dwDesiredAccess, "ServiceType", dwServiceType, + "StartType", dwStartType, "ErrorControl", dwErrorControl, + "BinaryPathName", lpBinaryPathName, + "ServiceStartName", lpServiceStartName, + "Password", lpPassword); + return ret; +} + +HOOKDEF(SC_HANDLE, WINAPI, CreateServiceW, + __in SC_HANDLE hSCManager, + __in LPWSTR lpServiceName, + __in_opt LPWSTR lpDisplayName, + __in DWORD dwDesiredAccess, + __in DWORD dwServiceType, + __in DWORD dwStartType, + __in DWORD dwErrorControl, + __in_opt LPWSTR lpBinaryPathName, + __in_opt LPWSTR lpLoadOrderGroup, + __out_opt LPDWORD lpdwTagId, + __in_opt LPWSTR lpDependencies, + __in_opt LPWSTR lpServiceStartName, + __in_opt LPWSTR lpPassword +) { + SC_HANDLE ret = Old_CreateServiceW(hSCManager, lpServiceName, + lpDisplayName, dwDesiredAccess, dwServiceType, dwStartType, + dwErrorControl, lpBinaryPathName, lpLoadOrderGroup, lpdwTagId, + lpDependencies, lpServiceStartName, lpPassword); + LOQ("puu4l3u", "ServiceControlHandle", hSCManager, + "ServiceName", lpServiceName, "DisplayName", lpDisplayName, + "DesiredAccess", dwDesiredAccess, "ServiceType", dwServiceType, + "StartType", dwStartType, "ErrorControl", dwErrorControl, + "BinaryPathName", lpBinaryPathName, + "ServiceStartName", lpServiceStartName, + "Password", lpPassword); + return ret; +} + +HOOKDEF(SC_HANDLE, WINAPI, OpenServiceA, + __in SC_HANDLE hSCManager, + __in LPCTSTR lpServiceName, + __in DWORD dwDesiredAccess +) { + SC_HANDLE ret = Old_OpenServiceA(hSCManager, lpServiceName, + dwDesiredAccess); + LOQ("psl", "ServiceControlManager", hSCManager, + "ServiceName", lpServiceName, "DesiredAccess", dwDesiredAccess); + return ret; +} + +HOOKDEF(SC_HANDLE, WINAPI, OpenServiceW, + __in SC_HANDLE hSCManager, + __in LPWSTR lpServiceName, + __in DWORD dwDesiredAccess +) { + SC_HANDLE ret = Old_OpenServiceW(hSCManager, lpServiceName, + dwDesiredAccess); + LOQ("pul", "ServiceControlManager", hSCManager, + "ServiceName", lpServiceName, "DesiredAccess", dwDesiredAccess); + return ret; +} + +HOOKDEF(BOOL, WINAPI, StartServiceA, + __in SC_HANDLE hService, + __in DWORD dwNumServiceArgs, + __in_opt LPCTSTR *lpServiceArgVectors +) { + IS_SUCCESS_BOOL(); + + BOOL ret = Old_StartServiceA(hService, dwNumServiceArgs, + lpServiceArgVectors); + LOQ("pa", "ServiceHandle", hService, "Arguments", dwNumServiceArgs, + lpServiceArgVectors); + return ret; +} + +HOOKDEF(BOOL, WINAPI, StartServiceW, + __in SC_HANDLE hService, + __in DWORD dwNumServiceArgs, + __in_opt LPWSTR *lpServiceArgVectors +) { + IS_SUCCESS_BOOL(); + + BOOL ret = Old_StartServiceW(hService, dwNumServiceArgs, + lpServiceArgVectors); + LOQ("pA", "ServiceHandle", hService, "Arguments", dwNumServiceArgs, + lpServiceArgVectors); + return ret; +} + +HOOKDEF(BOOL, WINAPI, ControlService, + __in SC_HANDLE hService, + __in DWORD dwControl, + __out LPSERVICE_STATUS lpServiceStatus +) { + IS_SUCCESS_BOOL(); + + BOOL ret = Old_ControlService(hService, dwControl, lpServiceStatus); + LOQ("pl", "ServiceHandle", hService, "ControlCode", dwControl); + return ret; +} + +HOOKDEF(BOOL, WINAPI, DeleteService, + __in SC_HANDLE hService +) { + IS_SUCCESS_BOOL(); + + BOOL ret = Old_DeleteService(hService); + LOQ("p", "ServiceHandle", hService); + return ret; +} diff --git a/hook_sleep.c b/hook_sleep.c new file mode 100644 index 0000000..207e3d5 --- /dev/null +++ b/hook_sleep.c @@ -0,0 +1,141 @@ +/* +Cuckoo Sandbox - Automated Malware Analysis +Copyright (C) 2010-2014 Cuckoo Sandbox Developers + +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 . +*/ + +#include +#include +#include "hooking.h" +#include "ntapi.h" +#include "log.h" +#include "pipe.h" + +// only skip Sleep()'s the first five seconds +#define MAX_SLEEP_SKIP_DIFF 5000 + +static IS_SUCCESS_NTSTATUS(); + +// skipping sleep calls is done while this variable is set to true +static int sleep_skip_active = 1; + +// the amount of time skipped, in 100-nanosecond +static LARGE_INTEGER time_skipped; +static LARGE_INTEGER time_start; + +HOOKDEF(NTSTATUS, WINAPI, NtDelayExecution, + __in BOOLEAN Alertable, + __in PLARGE_INTEGER DelayInterval +) { + NTSTATUS ret = 0; + + // do we want to skip this sleep? + if(sleep_skip_active != 0) { + FILETIME ft; LARGE_INTEGER li; + GetSystemTimeAsFileTime(&ft); + li.HighPart = ft.dwHighDateTime; + li.LowPart = ft.dwLowDateTime; + + // check if we're still within the hardcoded limit + if(li.QuadPart < time_start.QuadPart + MAX_SLEEP_SKIP_DIFF * 10000) { + time_skipped.QuadPart += -DelayInterval->QuadPart; + + // notify how much we've skipped + unsigned long milli = -DelayInterval->QuadPart / 10000; + LOQ("ls", "Milliseconds", milli, "Status", "Skipped"); + return ret; + } + else { + sleep_skip_active = 0; + } + } + unsigned long milli = -DelayInterval->QuadPart / 10000; + LOQ2("l", "Milliseconds", milli); + return Old_NtDelayExecution(Alertable, DelayInterval); +} + +HOOKDEF(void, WINAPI, GetLocalTime, + __out LPSYSTEMTIME lpSystemTime +) { + Old_GetLocalTime(lpSystemTime); + + LARGE_INTEGER li; FILETIME ft; + SystemTimeToFileTime(lpSystemTime, &ft); + li.HighPart = ft.dwHighDateTime; + li.LowPart = ft.dwLowDateTime; + li.QuadPart += time_skipped.QuadPart; + ft.dwHighDateTime = li.HighPart; + ft.dwLowDateTime = li.LowPart; + FileTimeToSystemTime(&ft, lpSystemTime); +} + +HOOKDEF(void, WINAPI, GetSystemTime, + __out LPSYSTEMTIME lpSystemTime +) { + Old_GetSystemTime(lpSystemTime); + + LARGE_INTEGER li; FILETIME ft; + SystemTimeToFileTime(lpSystemTime, &ft); + li.HighPart = ft.dwHighDateTime; + li.LowPart = ft.dwLowDateTime; + li.QuadPart += time_skipped.QuadPart; + ft.dwHighDateTime = li.HighPart; + ft.dwLowDateTime = li.LowPart; + FileTimeToSystemTime(&ft, lpSystemTime); +} + +HOOKDEF(DWORD, WINAPI, GetTickCount, + void +) { + DWORD ret = Old_GetTickCount(); + + // add the time we've skipped + ret += time_skipped.QuadPart / 10000; + + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, NtQuerySystemTime, + _Out_ PLARGE_INTEGER SystemTime +) { + NTSTATUS ret = Old_NtQuerySystemTime(SystemTime); + if(NT_SUCCESS(ret)) { + SystemTime->QuadPart += time_skipped.QuadPart; + } + return 0; +} + +void disable_sleep_skip() +{ + sleep_skip_active = 0; +} + +void init_sleep_skip(int first_process) +{ + FILETIME ft; + GetSystemTimeAsFileTime(&ft); + time_start.HighPart = ft.dwHighDateTime; + time_start.LowPart = ft.dwLowDateTime; + + // we don't want to skip sleep calls in child processes + if(first_process == 0) { + disable_sleep_skip(); + } +} + +void init_startup_time(unsigned int startup_time) +{ + time_skipped.QuadPart += (unsigned __int64) startup_time * 10000; +} diff --git a/hook_sleep.h b/hook_sleep.h new file mode 100644 index 0000000..ea13fd5 --- /dev/null +++ b/hook_sleep.h @@ -0,0 +1,21 @@ +/* +Cuckoo Sandbox - Automated Malware Analysis +Copyright (C) 2010-2014 Cuckoo Sandbox Developers + +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 . +*/ + +void disable_sleep_skip(); +void init_sleep_skip(int first_process); +void init_startup_time(unsigned int startup_time); diff --git a/hook_socket.c b/hook_socket.c new file mode 100644 index 0000000..2f3d0cf --- /dev/null +++ b/hook_socket.c @@ -0,0 +1,337 @@ +/* +Cuckoo Sandbox - Automated Malware Analysis +Copyright (C) 2010-2014 Cuckoo Sandbox Developers + +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 . +*/ + +#include +#include +#include +#include +#include "hooking.h" +#include "ntapi.h" +#include "log.h" + +static IS_SUCCESS_INTM1(); + +HOOKDEF(int, WINAPI, WSAStartup, + _In_ WORD wVersionRequested, + _Out_ LPWSADATA lpWSAData +) { + IS_SUCCESS_ZERO(); + + int ret = Old_WSAStartup(wVersionRequested, lpWSAData); + LOQ("p", "VersionRequested", wVersionRequested); + return ret; +} + +HOOKDEF(struct hostent *, WSAAPI, gethostbyname, + __in const char *name +) { + IS_SUCCESS_HANDLE(); + + struct hostent *ret = Old_gethostbyname(name); + LOQ("s", "Name", name); + return ret; +} + +HOOKDEF(SOCKET, WSAAPI, socket, + __in int af, + __in int type, + __in int protocol +) { + SOCKET ret = Old_socket(af, type, protocol); + LOQ("lll", "af", af, "type", type, "protocol", protocol); + return ret; +} + +HOOKDEF(int, WSAAPI, connect, + __in SOCKET s, + __in const struct sockaddr *name, + __in int namelen +) { + int ret = Old_connect(s, name, namelen); + LOQ("p", "socket", s); + return ret; +} + +HOOKDEF(int, WSAAPI, send, + __in SOCKET s, + __in const char *buf, + __in int len, + __in int flags +) { + int ret = Old_send(s, buf, len, flags); + LOQ("pb", "socket", s, "buffer", ret < 1 ? 0 : ret, buf); + return ret; +} + +HOOKDEF(int, WSAAPI, sendto, + __in SOCKET s, + __in const char *buf, + __in int len, + __in int flags, + __in const struct sockaddr *to, + __in int tolen +) { + int ret = Old_sendto(s, buf, len, flags, to, tolen); + LOQ("pb", "socket", s, "buffer", ret < 1 ? 0 : ret, buf); + return ret; +} + +HOOKDEF(int, WSAAPI, recv, + __in SOCKET s, + __out char *buf, + __in int len, + __in int flags +) { + int ret = Old_recv(s, buf, len, flags); + LOQ("pb", "socket", s, "buffer", ret < 1 ? 0 : len, buf); + return ret; +} + +HOOKDEF(int, WSAAPI, recvfrom, + __in SOCKET s, + __out char *buf, + __in int len, + __in int flags, + __out struct sockaddr *from, + __inout_opt int *fromlen +) { + int ret = Old_recvfrom(s, buf, len, flags, from, fromlen); + LOQ("pb", "socket", s, "buffer", ret < 1 ? 0 : ret, buf); + return ret; +} + +HOOKDEF(SOCKET, WSAAPI, accept, + __in SOCKET s, + __out struct sockaddr *addr, + __inout int *addrlen +) { + SOCKET ret = Old_accept(s, addr, addrlen); + LOQ("pp", "socket", s, "ClientSocket", ret); + return ret; +} + +HOOKDEF(int, WSAAPI, bind, + __in SOCKET s, + __in const struct sockaddr *name, + __in int namelen +) { + int ret = Old_bind(s, name, namelen); + if(ret == 0) { + LOQ("psl", "socket", s, + "ip", inet_ntoa(((struct sockaddr_in *) name)->sin_addr), + "port", htons(((struct sockaddr_in *) name)->sin_port)); + } + else { + LOQ2("p", "socket", s); + } + return ret; +} + +HOOKDEF(int, WSAAPI, listen, + __in SOCKET s, + __in int backlog +) { + int ret = Old_listen(s, backlog); + LOQ("p", "socket", s); + return ret; +} + +HOOKDEF(int, WSAAPI, select, + __in SOCKET s, + __inout fd_set *readfds, + __inout fd_set *writefds, + __inout fd_set *exceptfds, + __in const struct timeval *timeout +) { + int ret = Old_select(s, readfds, writefds, exceptfds, timeout); + LOQ("p", "socket", s); + return ret; +} + +HOOKDEF(int, WSAAPI, setsockopt, + __in SOCKET s, + __in int level, + __in int optname, + __in const char *optval, + __in int optlen +) { + int ret = Old_setsockopt(s, level, optname, optval, optlen); + LOQ("pllb", "socket", s, "level", level, "optname", optname, + "optval", optlen, optval); + return ret; +} + +HOOKDEF(int, WSAAPI, ioctlsocket, + __in SOCKET s, + __in long cmd, + __inout u_long *argp +) { + int ret = Old_ioctlsocket(s, cmd, argp); + LOQ("pl", "socket", s, "command", cmd); + return ret; +} + +HOOKDEF(int, WSAAPI, closesocket, + __in SOCKET s +) { + int ret = Old_closesocket(s); + LOQ("p", "socket", s); + return ret; +} + +HOOKDEF(int, WSAAPI, shutdown, + __in SOCKET s, + __in int how +) { + int ret = Old_shutdown(s, how); + LOQ("pl", "socket", s, "how", how); + return ret; +} + +HOOKDEF(int, WSAAPI, WSARecv, + __in SOCKET s, + __inout LPWSABUF lpBuffers, + __in DWORD dwBufferCount, + __out LPDWORD lpNumberOfBytesRecvd, + __inout LPDWORD lpFlags, + __in LPWSAOVERLAPPED lpOverlapped, + __in LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine +) { + BOOL ret = Old_WSARecv(s, lpBuffers, dwBufferCount, lpNumberOfBytesRecvd, + lpFlags, lpOverlapped, lpCompletionRoutine); + // TODO dump buffers + LOQ("p", "socket", s); + return ret; +} + +HOOKDEF(int, WSAAPI, WSARecvFrom, + __in SOCKET s, + __inout LPWSABUF lpBuffers, + __in DWORD dwBufferCount, + __out LPDWORD lpNumberOfBytesRecvd, + __inout LPDWORD lpFlags, + __out struct sockaddr *lpFrom, + __inout LPINT lpFromlen, + __in LPWSAOVERLAPPED lpOverlapped, + __in LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine +) { + BOOL ret = Old_WSARecvFrom(s, lpBuffers, dwBufferCount, + lpNumberOfBytesRecvd, lpFlags, lpFrom, lpFromlen, lpOverlapped, + lpCompletionRoutine); + // TODO dump buffer + LOQ("p", "socket", s); + return ret; +} + +HOOKDEF(int, WSAAPI, WSASend, + __in SOCKET s, + __in LPWSABUF lpBuffers, + __in DWORD dwBufferCount, + __out LPDWORD lpNumberOfBytesSent, + __in DWORD dwFlags, + __in LPWSAOVERLAPPED lpOverlapped, + __in LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine +) { + BOOL ret = Old_WSASend(s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, + dwFlags, lpOverlapped, lpCompletionRoutine); + // TODO dump buffers + LOQ("p", "Socket", s); + return ret; +} + +HOOKDEF(int, WSAAPI, WSASendTo, + __in SOCKET s, + __in LPWSABUF lpBuffers, + __in DWORD dwBufferCount, + __out LPDWORD lpNumberOfBytesSent, + __in DWORD dwFlags, + __in const struct sockaddr *lpTo, + __in int iToLen, + __in LPWSAOVERLAPPED lpOverlapped, + __in LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine +) { + BOOL ret = Old_WSASendTo(s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, + dwFlags, lpTo, iToLen, lpOverlapped, lpCompletionRoutine); + // TODO dump buffers + LOQ("p", "Socket", s); + return ret; +} + +HOOKDEF(SOCKET, WSAAPI, WSASocketA, + __in int af, + __in int type, + __in int protocol, + __in LPWSAPROTOCOL_INFO lpProtocolInfo, + __in GROUP g, + __in DWORD dwFlags +) { + SOCKET ret = Old_WSASocketA(af, type, protocol, lpProtocolInfo, + g, dwFlags); + LOQ("lll", "af", af, "type", type, "protocol", protocol); + return ret; +} + +HOOKDEF(SOCKET, WSAAPI, WSASocketW, + __in int af, + __in int type, + __in int protocol, + __in LPWSAPROTOCOL_INFO lpProtocolInfo, + __in GROUP g, + __in DWORD dwFlags +) { + SOCKET ret = Old_WSASocketW(af, type, protocol, lpProtocolInfo, + g, dwFlags); + LOQ("lll", "af", af, "type", type, "protocol", protocol); + return ret; +} + +HOOKDEF(BOOL, PASCAL, ConnectEx, + _In_ SOCKET s, + _In_ const struct sockaddr *name, + _In_ int namelen, + _In_opt_ PVOID lpSendBuffer, + _In_ DWORD dwSendDataLength, + _Out_ LPDWORD lpdwBytesSent, + _In_ LPOVERLAPPED lpOverlapped +) { + IS_SUCCESS_BOOL(); + + BOOL ret = Old_ConnectEx(s, name, namelen, lpSendBuffer, dwSendDataLength, + lpdwBytesSent, lpOverlapped); + LOQ("pB", "socket", s, "SendBuffer", lpdwBytesSent, lpSendBuffer); + return ret; +} + +HOOKDEF(BOOL, PASCAL, TransmitFile, + SOCKET hSocket, + HANDLE hFile, + DWORD nNumberOfBytesToWrite, + DWORD nNumberOfBytesPerSend, + LPOVERLAPPED lpOverlapped, + LPTRANSMIT_FILE_BUFFERS lpTransmitBuffers, + DWORD dwFlags +) { + IS_SUCCESS_BOOL(); + + BOOL ret = Old_TransmitFile(hSocket, hFile, nNumberOfBytesToWrite, + nNumberOfBytesPerSend, lpOverlapped, lpTransmitBuffers, dwFlags); + LOQ("ppll", "socket", hSocket, "FileHandle", hFile, + "NumberOfBytesToWrite", nNumberOfBytesToWrite, + "NumberOfBytesPerSend", nNumberOfBytesPerSend); + return ret; +} diff --git a/hook_special.c b/hook_special.c new file mode 100644 index 0000000..694d52d --- /dev/null +++ b/hook_special.c @@ -0,0 +1,109 @@ +/* +Cuckoo Sandbox - Automated Malware Analysis +Copyright (C) 2010-2014 Cuckoo Sandbox Developers + +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 . +*/ + +#include +#include +#include "hooking.h" +#include "ntapi.h" +#include "log.h" +#include "pipe.h" +#include "hook_sleep.h" + +static IS_SUCCESS_NTSTATUS(); + +void set_hooks_dll(const wchar_t *library, int len); + +HOOKDEF2(NTSTATUS, WINAPI, LdrLoadDll, + __in_opt PWCHAR PathToFile, + __in_opt ULONG Flags, + __in PUNICODE_STRING ModuleFileName, + __out PHANDLE ModuleHandle +) { + // + // In the event that loading this dll results in loading another dll as + // well, then the unicode string (which is located in the TEB) will be + // overwritten, therefore we make a copy of it for our own use. + // + + COPY_UNICODE_STRING(library, ModuleFileName); + + NTSTATUS ret = Old2_LdrLoadDll(PathToFile, Flags, ModuleFileName, + ModuleHandle); + + if (hook_info()->depth_count == 1) { + LOQspecial("loP", "Flags", Flags, "FileName", &library, + "BaseAddress", ModuleHandle); + } + + // + // Check this DLL against our table of hooks, because we might have to + // place some new hooks. + // + + if(NT_SUCCESS(ret)) { + set_hooks_dll(library.Buffer, library.Length >> 1); + } + + return ret; +} + +HOOKDEF2(BOOL, WINAPI, CreateProcessInternalW, + __in_opt LPVOID lpUnknown1, + __in_opt LPWSTR lpApplicationName, + __inout_opt LPWSTR lpCommandLine, + __in_opt LPSECURITY_ATTRIBUTES lpProcessAttributes, + __in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes, + __in BOOL bInheritHandles, + __in DWORD dwCreationFlags, + __in_opt LPVOID lpEnvironment, + __in_opt LPWSTR lpCurrentDirectory, + __in LPSTARTUPINFO lpStartupInfo, + __out LPPROCESS_INFORMATION lpProcessInformation, + __in_opt LPVOID lpUnknown2 +) { + IS_SUCCESS_BOOL(); + + BOOL ret = Old2_CreateProcessInternalW(lpUnknown1, lpApplicationName, + lpCommandLine, lpProcessAttributes, lpThreadAttributes, + bInheritHandles, dwCreationFlags | CREATE_SUSPENDED, lpEnvironment, + lpCurrentDirectory, lpStartupInfo, lpProcessInformation, lpUnknown2); + + if(ret != FALSE) { + pipe("PROCESS:%d,%d", lpProcessInformation->dwProcessId, + lpProcessInformation->dwThreadId); + + // if the CREATE_SUSPENDED flag was not set, then we have to resume + // the main thread ourself + if((dwCreationFlags & CREATE_SUSPENDED) == 0) { + ResumeThread(lpProcessInformation->hThread); + } + + disable_sleep_skip(); + } + + if (hook_info()->depth_count == 1) { + LOQspecial("uupllpp", "ApplicationName", lpApplicationName, + "CommandLine", lpCommandLine, "CreationFlags", dwCreationFlags, + "ProcessId", lpProcessInformation->dwProcessId, + "ThreadId", lpProcessInformation->dwThreadId, + "ProcessHandle", lpProcessInformation->hProcess, + "ThreadHandle", lpProcessInformation->hThread); + } + + return ret; +} diff --git a/hook_sync.c b/hook_sync.c new file mode 100644 index 0000000..afc8b3f --- /dev/null +++ b/hook_sync.c @@ -0,0 +1,78 @@ +/* +Cuckoo Sandbox - Automated Malware Analysis +Copyright (C) 2010-2014 Cuckoo Sandbox Developers + +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 . +*/ + +#include +#include +#include "hooking.h" +#include "ntapi.h" +#include "log.h" + +static IS_SUCCESS_NTSTATUS(); + +HOOKDEF(NTSTATUS, WINAPI, NtCreateMutant, + __out PHANDLE MutantHandle, + __in ACCESS_MASK DesiredAccess, + __in_opt POBJECT_ATTRIBUTES ObjectAttributes, + __in BOOLEAN InitialOwner +) { + NTSTATUS ret = Old_NtCreateMutant(MutantHandle, DesiredAccess, + ObjectAttributes, InitialOwner); + LOQ("Pol", "Handle", MutantHandle, + "MutexName", unistr_from_objattr(ObjectAttributes), + "InitialOwner", InitialOwner); + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, NtOpenMutant, + __out PHANDLE MutantHandle, + __in ACCESS_MASK DesiredAccess, + __in POBJECT_ATTRIBUTES ObjectAttributes +) { + NTSTATUS ret = Old_NtOpenMutant(MutantHandle, DesiredAccess, + ObjectAttributes); + LOQ("Po", "Handle", MutantHandle, + "MutexName", unistr_from_objattr(ObjectAttributes)); + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, NtCreateNamedPipeFile, + OUT PHANDLE NamedPipeFileHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN ULONG ShareAccess, + IN ULONG CreateDisposition, + IN ULONG CreateOptions, + IN BOOLEAN WriteModeMessage, + IN BOOLEAN ReadModeMessage, + IN BOOLEAN NonBlocking, + IN ULONG MaxInstances, + IN ULONG InBufferSize, + IN ULONG OutBufferSize, + IN PLARGE_INTEGER DefaultTimeOut +) { + NTSTATUS ret = Old_NtCreateNamedPipeFile(NamedPipeFileHandle, + DesiredAccess, ObjectAttributes, IoStatusBlock, ShareAccess, + CreateDisposition, CreateOptions, WriteModeMessage, ReadModeMessage, + NonBlocking, MaxInstances, InBufferSize, OutBufferSize, + DefaultTimeOut); + LOQ("PpOl", "NamedPipeHandle", NamedPipeFileHandle, + "DesiredAccess", DesiredAccess, "PipeName", ObjectAttributes, + "ShareAccess", ShareAccess); + return ret; +} diff --git a/hook_thread.c b/hook_thread.c new file mode 100644 index 0000000..06f85c7 --- /dev/null +++ b/hook_thread.c @@ -0,0 +1,225 @@ +/* +Cuckoo Sandbox - Automated Malware Analysis +Copyright (C) 2010-2014 Cuckoo Sandbox Developers + +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 . +*/ + +#include +#include +#include "hooking.h" +#include "ntapi.h" +#include "log.h" +#include "pipe.h" +#include "misc.h" +#include "hook_sleep.h" + +static IS_SUCCESS_NTSTATUS(); + +HOOKDEF(NTSTATUS, WINAPI, NtCreateThread, + __out PHANDLE ThreadHandle, + __in ACCESS_MASK DesiredAccess, + __in_opt POBJECT_ATTRIBUTES ObjectAttributes, + __in HANDLE ProcessHandle, + __out PCLIENT_ID ClientId, + __in PCONTEXT ThreadContext, + __in PINITIAL_TEB InitialTeb, + __in BOOLEAN CreateSuspended +) { + pipe("PROCESS:%d", pid_from_process_handle(ProcessHandle)); + + NTSTATUS ret = Old_NtCreateThread(ThreadHandle, DesiredAccess, + ObjectAttributes, ProcessHandle, ClientId, ThreadContext, + InitialTeb, CreateSuspended); + LOQ("PpO", "ThreadHandle", ThreadHandle, "ProcessHandle", ProcessHandle, + "ObjectAttributes", ObjectAttributes); + if(NT_SUCCESS(ret)) { + disable_sleep_skip(); + } + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, NtCreateThreadEx, + OUT PHANDLE hThread, + IN ACCESS_MASK DesiredAccess, + IN PVOID ObjectAttributes, + IN HANDLE ProcessHandle, + IN LPTHREAD_START_ROUTINE lpStartAddress, + IN PVOID lpParameter, + IN BOOL CreateSuspended, + IN LONG StackZeroBits, + IN LONG SizeOfStackCommit, + IN LONG SizeOfStackReserve, + OUT PVOID lpBytesBuffer +) { + NTSTATUS ret = Old_NtCreateThreadEx(hThread, DesiredAccess, + ObjectAttributes, ProcessHandle, lpStartAddress, lpParameter, + CreateSuspended, StackZeroBits, SizeOfStackCommit, SizeOfStackReserve, + lpBytesBuffer); + LOQ("Pppl", "ThreadHandle", hThread, "ProcessHandle", ProcessHandle, + "StartAddress", lpStartAddress, "CreateSuspended", CreateSuspended); + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, NtOpenThread, + __out PHANDLE ThreadHandle, + __in ACCESS_MASK DesiredAccess, + __in POBJECT_ATTRIBUTES ObjectAttributes, + __in PCLIENT_ID ClientId +) { + NTSTATUS ret = Old_NtOpenThread(ThreadHandle, DesiredAccess, + ObjectAttributes, ClientId); + LOQ("PlO", "ThreadHandle", ThreadHandle, "DesiredAccess", DesiredAccess, + "ObjectAttributes", ObjectAttributes); + if(NT_SUCCESS(ret)) { + // TODO: are we sure that OpenThread specifies the PID? + pipe("PROCESS:%d", ClientId->UniqueProcess); + } + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, NtGetContextThread, + __in HANDLE ThreadHandle, + __inout LPCONTEXT Context +) { + NTSTATUS ret = Old_NtGetContextThread(ThreadHandle, Context); + LOQ("p", "ThreadHandle", ThreadHandle); + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, NtSetContextThread, + __in HANDLE ThreadHandle, + __in const CONTEXT *Context +) { + NTSTATUS ret = Old_NtSetContextThread(ThreadHandle, Context); + LOQ("p", "ThreadHandle", ThreadHandle); + + pipe("PROCESS:%d", pid_from_thread_handle(ThreadHandle)); + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, NtSuspendThread, + __in HANDLE ThreadHandle, + __out_opt ULONG *PreviousSuspendCount +) { + ENSURE_ULONG(PreviousSuspendCount); + + NTSTATUS ret = Old_NtSuspendThread(ThreadHandle, PreviousSuspendCount); + LOQ("pL", "ThreadHandle", ThreadHandle, + "SuspendCount", PreviousSuspendCount); + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, NtResumeThread, + __in HANDLE ThreadHandle, + __out_opt ULONG *SuspendCount +) { + ENSURE_ULONG(SuspendCount); + + NTSTATUS ret = Old_NtResumeThread(ThreadHandle, SuspendCount); + LOQ("pL", "ThreadHandle", ThreadHandle, "SuspendCount", SuspendCount); + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, NtTerminateThread, + __in HANDLE ThreadHandle, + __in NTSTATUS ExitStatus +) { + NTSTATUS ret = Old_NtTerminateThread(ThreadHandle, ExitStatus); + LOQ("pl", "ThreadHandle", ThreadHandle, "ExitStatus", ExitStatus); + return ret; +} + +HOOKDEF(HANDLE, WINAPI, CreateThread, + __in LPSECURITY_ATTRIBUTES lpThreadAttributes, + __in SIZE_T dwStackSize, + __in LPTHREAD_START_ROUTINE lpStartAddress, + __in LPVOID lpParameter, + __in DWORD dwCreationFlags, + __out LPDWORD lpThreadId +) { + IS_SUCCESS_HANDLE(); + + HANDLE ret = Old_CreateThread(lpThreadAttributes, dwStackSize, + lpStartAddress, lpParameter, dwCreationFlags, lpThreadId); + LOQ("pplL", "StartRoutine", lpStartAddress, "Parameter", lpParameter, + "CreationFlags", dwCreationFlags, "ThreadId", lpThreadId); + if(NT_SUCCESS(ret)) { + disable_sleep_skip(); + } + return ret; +} + +HOOKDEF(HANDLE, WINAPI, CreateRemoteThread, + __in HANDLE hProcess, + __in LPSECURITY_ATTRIBUTES lpThreadAttributes, + __in SIZE_T dwStackSize, + __in LPTHREAD_START_ROUTINE lpStartAddress, + __in LPVOID lpParameter, + __in DWORD dwCreationFlags, + __out LPDWORD lpThreadId +) { + IS_SUCCESS_HANDLE(); + + pipe("PROCESS:%d", pid_from_process_handle(hProcess)); + + HANDLE ret = Old_CreateRemoteThread(hProcess, lpThreadAttributes, + dwStackSize, lpStartAddress, lpParameter, dwCreationFlags, + lpThreadId); + LOQ("3plL", "ProcessHandle", hProcess, "StartRoutine", lpStartAddress, + "Parameter", lpParameter, "CreationFlags", dwCreationFlags, + "ThreadId", lpThreadId); + if(NT_SUCCESS(ret)) { + disable_sleep_skip(); + } + return ret; +} + +HOOKDEF(VOID, WINAPI, ExitThread, + __in DWORD dwExitCode +) { + IS_SUCCESS_VOID(); + + int ret = 0; + LOQ("l", "ExitCode", dwExitCode); + Old_ExitThread(dwExitCode); +} + +HOOKDEF(NTSTATUS, WINAPI, RtlCreateUserThread, + IN HANDLE ProcessHandle, + IN PSECURITY_DESCRIPTOR SecurityDescriptor OPTIONAL, + IN BOOLEAN CreateSuspended, + IN ULONG StackZeroBits, + IN OUT PULONG StackReserved, + IN OUT PULONG StackCommit, + IN PVOID StartAddress, + IN PVOID StartParameter OPTIONAL, + OUT PHANDLE ThreadHandle, + OUT PCLIENT_ID ClientId +) { + ENSURE_CLIENT_ID(ClientId); + + NTSTATUS ret = Old_RtlCreateUserThread(ProcessHandle, SecurityDescriptor, + CreateSuspended, StackZeroBits, StackReserved, StackCommit, + StartAddress, StartParameter, ThreadHandle, ClientId); + LOQ("plppPl", "ProcessHandle", ProcessHandle, + "CreateSuspended", CreateSuspended, "StartAddress", StartAddress, + "StartParameter", StartParameter, "ThreadHandle", ThreadHandle, + "ThreadIdentifier", ClientId->UniqueThread); + if(NT_SUCCESS(ret)) { + pipe("PROCESS:0,%d", ClientId->UniqueThread); + disable_sleep_skip(); + } + return ret; +} diff --git a/hook_window.c b/hook_window.c new file mode 100644 index 0000000..f9b63a8 --- /dev/null +++ b/hook_window.c @@ -0,0 +1,94 @@ +/* +Cuckoo Sandbox - Automated Malware Analysis +Copyright (C) 2010-2014 Cuckoo Sandbox Developers + +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 . +*/ + +#include +#include +#include "hooking.h" +#include "ntapi.h" +#include "log.h" + +static IS_SUCCESS_HWND(); + +HOOKDEF(HWND, WINAPI, FindWindowA, + __in_opt LPCTSTR lpClassName, + __in_opt LPCTSTR lpWindowName +) { + // The atom must be in the low-order word of lpClassName; + // the high-order word must be zero (from MSDN documentation.) + HWND ret = Old_FindWindowA(lpClassName, lpWindowName); + if(((DWORD_PTR) lpClassName & 0xffff) == (DWORD_PTR) lpClassName) { + LOQ("ls", "ClassName", lpClassName, "WindowName", lpWindowName); + } + else { + LOQ("ss", "ClassName", lpClassName, "WindowName", lpWindowName); + } + return ret; +} + +HOOKDEF(HWND, WINAPI, FindWindowW, + __in_opt LPWSTR lpClassName, + __in_opt LPWSTR lpWindowName +) { + HWND ret = Old_FindWindowW(lpClassName, lpWindowName); + if(((DWORD_PTR) lpClassName & 0xffff) == (DWORD_PTR) lpClassName) { + LOQ("lu", "ClassName", lpClassName, "WindowName", lpWindowName); + } + else { + LOQ("uu", "ClassName", lpClassName, "WindowName", lpWindowName); + } + return ret; +} + +HOOKDEF(HWND, WINAPI, FindWindowExA, + __in_opt HWND hwndParent, + __in_opt HWND hwndChildAfter, + __in_opt LPCTSTR lpszClass, + __in_opt LPCTSTR lpszWindow +) { + HWND ret = Old_FindWindowExA(hwndParent, hwndChildAfter, lpszClass, + lpszWindow); + + // lpszClass can be one of the predefined window controls.. which lay in + // the 0..ffff range + if(((DWORD_PTR) lpszClass & 0xffff) == (DWORD_PTR) lpszClass) { + LOQ("ls", "ClassName", lpszClass, "WindowName", lpszWindow); + } + else { + LOQ2("ss", "ClassName", lpszClass, "WindowName", lpszWindow); + } + return ret; +} + +HOOKDEF(HWND, WINAPI, FindWindowExW, + __in_opt HWND hwndParent, + __in_opt HWND hwndChildAfter, + __in_opt LPWSTR lpszClass, + __in_opt LPWSTR lpszWindow +) { + HWND ret = Old_FindWindowExW(hwndParent, hwndChildAfter, lpszClass, + lpszWindow); + // lpszClass can be one of the predefined window controls.. which lay in + // the 0..ffff range + if(((DWORD_PTR) lpszClass & 0xffff) == (DWORD_PTR) lpszClass) { + LOQ("lu", "ClassName", lpszClass, "WindowName", lpszWindow); + } + else { + LOQ2("uu", "ClassName", lpszClass, "WindowName", lpszWindow); + } + return ret; +} diff --git a/hooking.c b/hooking.c new file mode 100644 index 0000000..7bf1f7c --- /dev/null +++ b/hooking.c @@ -0,0 +1,815 @@ +/* +Cuckoo Sandbox - Automated Malware Analysis +Copyright (C) 2010-2014 Cuckoo Sandbox Developers + +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 . +*/ + +#include +#include +#include +#include "hooking.h" +#include "distorm.h" +#include "mnemonics.h" +#include "ntapi.h" +#include "ignore.h" + +// this number can be changed if required to do so +#define TLS_HOOK_INFO 0x44 + +// do not change this number +#define TLS_LAST_ERROR 0x34 + +// hook return address stack space +#define TLS_HOOK_INFO_RETADDR_SPACE 0x100 + +static void ensure_valid_hook_info(); + +// by default we enable the retaddr check +static int g_enable_retaddr_check = 1; + +// length disassembler engine +int lde(void *addr) +{ + // the length of an instruction is 16 bytes max, but there can also be + // 16 instructions of length one, so.. we support "decomposing" 16 + // instructions at once, max + unsigned int used_instruction_count; _DInst instructions[16]; + _CodeInfo code_info = {0, 0, addr, 16, Decode32Bits}; + _DecodeResult ret = distorm_decompose(&code_info, instructions, 16, + &used_instruction_count); + + return ret == DECRES_SUCCESS ? instructions[0].size : 0; +} + +static int is_interesting_backtrace(unsigned int ebp) +{ + // only perform this function when the retaddr-check is enabled, otherwise + // return true in all cases (if retaddr-check is disabled, then every + // backtrace is interesting) + if(g_enable_retaddr_check == 0) { + return 1; + } + + // http://en.wikipedia.org/wiki/Win32_Thread_Information_Block + unsigned int top = __readfsdword(0x04); + unsigned int bottom = __readfsdword(0x08); + + unsigned int count = HOOK_BACKTRACE_DEPTH; + while (ebp >= bottom && ebp < top && count-- != 0) { + + // obtain the return address and the next value of ebp + unsigned int addr = *(unsigned int *)(ebp + 4); + ebp = *(unsigned int *) ebp; + + // if this return address is *not* to be ignored, then it's + // interesting + if(is_ignored_retaddr(addr) == 0) { + return 1; + } + } + return 0; +} + +// create a trampoline at the given address, that is, we are going to replace +// the original instructions at this particular address. So, in order to +// call the original function from our hook, we have to execute the original +// instructions *before* jumping into addr+offset, where offset is the length +// which totals the size of the instructions which we place in the `tramp'. +// returns 0 on failure, or a positive integer defining the size of the tramp +// NOTE: tramp represents the memory address where the trampoline will be +// placed, copying it to another memory address will result into failure +static int hook_create_trampoline(unsigned char *addr, int len, + unsigned char *tramp) +{ + const unsigned char *base = tramp; + + // after the original function has returned, we have to make a backup of + // the Last Error Code, so what we do is the following (we use the same + // method below in the pre-tramp.) We store the current return address in + // info->ret_last_error, then we overwrite the return address with a + // return address in our trampoline. When we reach the trampoline, we make + // a backup of the Last Error Code and jmp to the real return address. + + unsigned char pre_backup[] = { + // push eax + 0x50, + + // mov eax, fs:[TLS_HOOK_INFO] + 0x64, 0xa1, TLS_HOOK_INFO, 0x00, 0x00, 0x00, + // test eax, eax + 0x85, 0xc0, + // jnz $+0d + 0x75, 0x0d, + // pushad + 0x60, + // call ensure_valid_hook_info + 0xe8, 0x00, 0x00, 0x00, 0x00, + // popad + 0x61, + // mov eax, fs:[TLS_HOOK_INFO] + 0x64, 0xa1, TLS_HOOK_INFO, 0x00, 0x00, 0x00, + + // cmp dword [eax+hook_info_t.hook_count], 0 + 0x83, 0x78, offsetof(hook_info_t, hook_count), 0x00, + // jg $+12 + 0x7f, 0x12, + // inc dword [eax+hook_info_t.hook_count] + 0xff, 0x40, offsetof(hook_info_t, hook_count), + // push dword [esp+4] + 0xff, 0x74, 0xe4, 0x04, + // pop dword [eax+hook_info_t.ret_last_error] + 0x8f, 0x40, offsetof(hook_info_t, ret_last_error), + // mov dword [esp+4], new_return_address + 0xc7, 0x44, 0xe4, 0x04, 0x00, 0x00, 0x00, 0x00, + + // pop eax + 0x58, + }; + + // the function returns here after executing, backup the Last Error Code + unsigned char post_backup[] = { + // push eax + 0x50, + // mov eax, fs:[TLS_HOOK_INFO] + 0x64, 0xa1, TLS_HOOK_INFO, 0x00, 0x00, 0x00, + // dec dword [eax+hook_info_t.hook_count] + 0xff, 0x48, offsetof(hook_info_t, hook_count), + // cmp dword [eax+hook_info_t.depth_count], 1 + 0x83, 0x78, offsetof(hook_info_t, depth_count), 0x01, + // jg $+0a + 0x7f, 0x0a, + // push dword fs:[TLS_LAST_ERROR] + 0x64, 0xff, 0x35, TLS_LAST_ERROR, 0x00, 0x00, 0x00, + // pop dword [eax+hook_info_t.last_error] + 0x8f, 0x40, offsetof(hook_info_t, last_error), + // mov eax, dword [eax+hook_info_t.ret_last_error] + 0x8b, 0x40, offsetof(hook_info_t, ret_last_error), + // xchg eax, dword [esp] + 0x87, 0x04, 0xe4, + // retn + 0xc3, + }; + + *(unsigned int *)(pre_backup + 13) = + (unsigned char *) &ensure_valid_hook_info - tramp - 12 - 5; + + memcpy(tramp, pre_backup, sizeof(pre_backup)); + tramp += sizeof(pre_backup); + + unsigned char **pre_backup_addr = (unsigned char **)(tramp - 5); + + // our trampoline should contain at least enough bytes to fit the given + // length + while (len > 0) { + + // obtain the length of this instruction + int length = lde(addr); + + // error? + if(length == 0) { + return 0; + } + + // how many bytes left? + len -= length; + + // check the type of instruction at this particular address, if it's + // a jump or a call instruction, then we have to calculate some fancy + // addresses, otherwise we can simply copy the instruction to our + // trampoline + + // it's a (conditional) jump or call with 32bit relative offset + if(*addr == 0xe9 || *addr == 0xe8 || (*addr == 0x0f && + addr[1] >= 0x80 && addr[1] < 0x90)) { + + // copy the jmp or call instruction (conditional jumps are two + // bytes, the rest is one byte) + *tramp++ += *addr++; + if(addr[-1] != 0xe9 && addr[-1] != 0xe8) { + *tramp++ += *addr++; + } + + // when a jmp/call is performed, then the relative offset + + // the instruction pointer + the size of the instruction is the + // calculated address, so that's our target address as well. + // (note that `addr' is already increased by one or two, so the + // 4 represents the 32bit offset of this particular instruction) + unsigned long jmp_addr = *(unsigned long *) addr + 4 + + (unsigned long) addr; + addr += 4; + + // trampoline is already filled with the opcode itself (the jump + // instruction), now we will actually jump to the location by + // calculating the relative offset which points to the real + // address (this is the reverse operation of the one to calculate + // the absolute address of a jump) + *(unsigned long *) tramp = jmp_addr - (unsigned long) tramp - 4; + tramp += 4; + + // because an unconditional jump denotes the end of a basic block + // we will return failure if we have not yet processed enough room + // to store our hook code + if(tramp[-5] == 0xe9 && len > 0) return 0; + } + // (conditional) jump with 8bit relative offset + else if(*addr == 0xeb || (*addr >= 0x70 && *addr < 0x80)) { + + // same rules apply as with the 32bit relative offsets, except + // for the fact that both conditional and unconditional 8bit + // relative jumps take only one byte for the opcode + + // 8bit relative offset, we have to sign-extend it (by casting it + // as signed char) in order to calculate the correct address + unsigned long jmp_addr = (unsigned long) addr + 2 + + *(signed char *)(addr + 1); + + // the chance is *fairly* high that we will not be able to perform + // a jump from the trampoline to the original function, so instead + // we will use 32bit relative offset jumps + if(*addr == 0xeb) { + *tramp++ = 0xe9; + } + else { + // hex representation of the two types of 32bit jumps + // 8bit relative conditional jumps: 70..80 + // 32bit relative conditional jumps: 0f 80..90 + // so we will simply add 0x10 to the opcode of 8bit relative + // offset jump to obtain the 32bit relative offset jump opcode + *tramp++ = 0x0f; + *tramp++ = *addr + 0x10; + } + + // calculate the correct relative offset address + *(unsigned long *) tramp = jmp_addr - (unsigned long) tramp - 4; + tramp += 4; + + // again, end of basic block, check for length + if(*addr == 0xeb && len > 0) { + return 0; + } + + // add the instruction length + addr += 2; + } + // return instruction, indicates end of basic block as well, so we + // have to check if we already have enough space for our hook.. + else if((*addr == 0xc3 || *addr == 0xc2) && len > 0) { + return 0; + } + else { + // copy the instruction directly to the trampoline + while (length-- != 0) { + *tramp++ = *addr++; + } + } + } + + // append a jump from the trampoline to the original function + *tramp++ = 0xe9; + *(unsigned int *) tramp = + (unsigned int) addr - (unsigned int) tramp - 4; + tramp += 4; + + // return address is the next instruction after the jmp + *pre_backup_addr = tramp; + + memcpy(tramp, post_backup, sizeof(post_backup)); + tramp += sizeof(post_backup); + + // return the length of this trampoline + return tramp - base; +} + +// this function constructs the so-called pre-trampoline, this pre-trampoline +// determines if a hook should really be executed. An example will be the +// easiest; imagine we have a hook on CreateProcessInternalW() and on +// NtCreateProcessEx() (this is actually the case currently), now, if all goes +// well, a call to CreateProcess() will call CreateProcessInternalW() followed +// by a call to NtCreateProcessEx(). Because we already hook the higher-level +// API CreateProcessInternalW() it is not really useful to us to log the +// information retrieved in the NtCreateProcessEx() function as well, +// therefore, because one is called by the other, we can tell the hooking +// engine "once inside a hook, don't hook further API calls" by setting the +// allow_hook_recursion flag to false. The example above is what happens when +// the hook recursion is not allowed. +static void hook_create_pre_tramp(hook_t *h, uint8_t is_special_hook) +{ + unsigned char pre_tramp[] = { + // push ebx + 0x53, + // push eax + 0x50, + + // mov eax, fs:[TLS_HOOK_INFO] + 0x64, 0xa1, TLS_HOOK_INFO, 0x00, 0x00, 0x00, + // test eax, eax + 0x85, 0xc0, + // jnz $+0d + 0x75, 0x0d, + // pushad + 0x60, + // call ensure_valid_hook_info + 0xe8, 0x00, 0x00, 0x00, 0x00, + // popad + 0x61, + // mov eax, fs:[TLS_HOOK_INFO] + 0x64, 0xa1, TLS_HOOK_INFO, 0x00, 0x00, 0x00, + + // inc dword [eax+hook_info_t.depth_count] + 0xff, 0x40, offsetof(hook_info_t, depth_count), + + // mov ebx, [esp+8] + 0x8b, 0x5c, 0xe4, 0x08, + // xchg esp, [eax+hook_info_t.retaddr_esp] + 0x87, 0x60, offsetof(hook_info_t, retaddr_esp), + // push ebx + 0x53, + // xchg esp, [eax+hook_info_t.retaddr_esp] + 0x87, 0x60, offsetof(hook_info_t, retaddr_esp), + // mov dword [esp+8], new_return_address + 0xc7, 0x44, 0xe4, 0x08, 0x00, 0x00, 0x00, 0x00, + + // special hook support + // mov ebx, 1 + 0xbb, 0x01, 0x00, 0x00, 0x00, + // cmp ebx, is_special_hook + 0x83, 0xfb, is_special_hook, + // jnz $+7 + 0x75, 0x07, + // pop eax; pop ebx + 0x58, 0x5b, + // jmp h->store_exc + 0xe9, 0x00, 0x00, 0x00, 0x00, + + // cmp dword [eax+hook_info_t.depth_count], 1 + 0x83, 0x78, offsetof(hook_info_t, depth_count), 0x01, + // jle $+7 + 0x7e, 0x07, + // pop eax; pop ebx + 0x58, 0x5b, + // jmp h->tramp + 0xe9, 0x00, 0x00, 0x00, 0x00, + + // pushad + 0x60, + // push ebp + 0x55, + // call is_interesting_backtrace + 0xe8, 0x00, 0x00, 0x00, 0x00, + // test eax, eax + 0x85, 0xc0, + // pop eax + 0x58, + // popad + 0x61, + // jnz $+7 + 0x75, 0x07, + // pop eax; pop ebx + 0x58, 0x5b, + // jmp h->tramp + 0xe9, 0x00, 0x00, 0x00, 0x00, + + // pop eax; pop ebx + 0x58, 0x5b, + // jmp h->store_exc + 0xe9, 0x00, 0x00, 0x00, 0x00, + + + // push ebx; push eax + 0x53, 0x50, + // mov eax, fs:[TLS_HOOK_INFO] + 0x64, 0xa1, TLS_HOOK_INFO, 0x00, 0x00, 0x00, + // dec dword [eax+hook_info_t.depth_count] + 0xff, 0x48, offsetof(hook_info_t, depth_count), + // push dword [eax+hook_info_t.last_error] + 0xff, 0x70, offsetof(hook_info_t, last_error), + // pop dword fs:[0x34] + 0x64, 0x8f, 0x05, 0x34, 0x00, 0x00, 0x00, + + // xchg esp, [eax+hook_info_t.retaddr_esp] + 0x87, 0x60, offsetof(hook_info_t, retaddr_esp), + // pop ebx + 0x5b, + // xchg esp, [eax+hook_info_t.retaddr_esp] + 0x87, 0x60, offsetof(hook_info_t, retaddr_esp), + // pop eax + 0x58, + // xchg ebx, dword [esp] + 0x87, 0x1c, 0xe4, + // retn + 0xc3, + + }; + + *(unsigned int *)(pre_tramp + 14) = + (unsigned char *) &ensure_valid_hook_info - h->pre_tramp - 13 - 5; + *(unsigned int *)(pre_tramp + 43) = (unsigned int) h->pre_tramp + 104; + + *(unsigned int *)(pre_tramp + 60) = + (unsigned char *) h->store_exc - h->pre_tramp - 59 - 5; + + *(unsigned int *)(pre_tramp + 73) = h->tramp - h->pre_tramp - 72 - 5; + *(unsigned int *)(pre_tramp + 80) = + (unsigned char *) &is_interesting_backtrace - h->pre_tramp - 79 - 5; + *(unsigned int *)(pre_tramp + 93) = h->tramp - h->pre_tramp - 92 - 5; + *(unsigned int *)(pre_tramp + 100) = + (unsigned char *) h->store_exc - h->pre_tramp - 99 - 5; + + memcpy(h->pre_tramp, pre_tramp, sizeof(pre_tramp)); +} + +static void hook_store_exception_info(hook_t *h) +{ + unsigned char store_exception[] = { + // push eax + 0x50, + // mov eax, fs:[TLS_HOOK_INFO] + 0x64, 0xa1, TLS_HOOK_INFO, 0x00, 0x00, 0x00, + // xchg ebx, dword [esp] + 0x87, 0x1c, 0xe4, + // mov dword [eax+hook_info_t.eax], ebx + 0x89, 0x58, offsetof(hook_info_t, eax), + // xchg ebx, dword [esp] + 0x87, 0x1c, 0xe4, + // mov dword [eax+hook_info_t.ecx], ecx + 0x89, 0x48, offsetof(hook_info_t, ecx), + // mov dword [eax+hook_info_t.edx], edx + 0x89, 0x50, offsetof(hook_info_t, edx), + // mov dword [eax+hook_info_t.ebx], ebx + 0x89, 0x58, offsetof(hook_info_t, ebx), + // mov dword [eax+hook_info_t.esp], esp + 0x89, 0x60, offsetof(hook_info_t, esp), + // mov dword [eax+hook_info_t.ebp], ebp + 0x89, 0x68, offsetof(hook_info_t, ebp), + // mov dword [eax+hook_info_t.esi], esi + 0x89, 0x70, offsetof(hook_info_t, esi), + // mov dword [eax+hook_info_t.edi], edi + 0x89, 0x78, offsetof(hook_info_t, edi), + // pop eax + 0x58, + // jmp h->new_func + 0xe9, 0x00, 0x00, 0x00, 0x00, + }; + + unsigned int offset = sizeof(store_exception) - 5; + *(unsigned int *)(store_exception + offset + 1) = + (unsigned char *) h->new_func - h->store_exc - offset - 5; + memcpy(h->store_exc, store_exception, sizeof(store_exception)); +} + +static int hook_api_jmp_direct(hook_t *h, unsigned char *from, + unsigned char *to) +{ + // unconditional jump opcode + *from = 0xe9; + + // store the relative address from this opcode to our hook function + *(unsigned long *)(from + 1) = (unsigned char *) to - from - 5; + return 0; +} + +static int hook_api_nop_jmp_direct(hook_t *h, unsigned char *from, + unsigned char *to) +{ + // nop + *from++ = 0x90; + + return hook_api_jmp_direct(h, from, to); +} + +static int hook_api_hotpatch_jmp_direct(hook_t *h, unsigned char *from, + unsigned char *to) +{ + // mov edi, edi + *from++ = 0x8b; + *from++ = 0xff; + + return hook_api_jmp_direct(h, from, to); +} + +static int hook_api_push_retn(hook_t *h, unsigned char *from, + unsigned char *to) +{ + // push addr + *from++ = 0x68; + *(unsigned char **) from = to; + + // retn + from[4] = 0xc3; + + return 0; +} + +static int hook_api_nop_push_retn(hook_t *h, unsigned char *from, + unsigned char *to) +{ + // nop + *from++ = 0x90; + + return hook_api_push_retn(h, from, to); +} + +static int hook_api_jmp_indirect(hook_t *h, unsigned char *from, + unsigned char *to) +{ + // jmp dword [hook_data] + *from++ = 0xff; + *from++ = 0x25; + + *(unsigned char **) from = h->hook_data; + + // the real address is stored in hook_data + memcpy(h->hook_data, &to, sizeof(to)); + return 0; +} + +static int hook_api_mov_eax_jmp_eax(hook_t *h, unsigned char *from, + unsigned char *to) +{ + // mov eax, address + *from++ = 0xb8; + *(unsigned char **) from = to; + from += 4; + + // jmp eax + *from++ = 0xff; + *from++ = 0xe0; + return 0; +} + +static int hook_api_mov_eax_push_retn(hook_t *h, unsigned char *from, + unsigned char *to) +{ + // mov eax, address + *from++ = 0xb8; + *(unsigned char **) from = to; + from += 4; + + // push eax + *from++ = 0x50; + + // retn + *from++ = 0xc3; + return 0; +} + +static int hook_api_mov_eax_indirect_jmp_eax(hook_t *h, unsigned char *from, + unsigned char *to) +{ + // mov eax, [hook_data] + *from++ = 0xa1; + *(unsigned char **) from = h->hook_data; + from += 4; + + // store the address at hook_data + memcpy(h->hook_data, &to, sizeof(to)); + + // jmp eax + *from++ = 0xff; + *from++ = 0xe0; + return 0; +} + +static int hook_api_mov_eax_indirect_push_retn(hook_t *h, unsigned char *from, + unsigned char *to) +{ + // mov eax, [hook_data] + *from++ = 0xa1; + *(unsigned char **) from = h->hook_data; + from += 4; + + // store the address at hook_data + memcpy(h->hook_data, &to, sizeof(to)); + + // push eax + *from++ = 0x50; + + // retn + *from++ = 0xc3; + return 0; +} + +#if HOOK_ENABLE_FPU +static int hook_api_push_fpu_retn(hook_t *h, unsigned char *from, + unsigned char *to) +{ + // push ebp + *from++ = 0x55; + + // fld qword [hook_data] + *from++ = 0xdd; + *from++ = 0x05; + + *(unsigned char **) from = h->hook_data; + from += 4; + + // fistp dword [esp] + *from++ = 0xdb; + *from++ = 0x1c; + *from++ = 0xe4; + + // retn + *from++ = 0xc3; + + // store the address as double + double addr = (double) (unsigned long) to; + memcpy(h->hook_data, &addr, sizeof(addr)); + return 0; +} +#endif + +static int hook_api_special_jmp(hook_t *h, unsigned char *from, + unsigned char *to) +{ + // our largest hook in use is currently 7 bytes. so we have to make sure + // that this special hook (a hook that will be patched over again later) + // is atleast seven bytes. + *from++ = 0x90; + *from++ = 0x90; + return hook_api_jmp_direct(h, from, to); +} + +int hook_api(hook_t *h, int type) +{ + // table with all possible hooking types + static struct { + int(*hook)(hook_t *h, unsigned char *from, unsigned char *to); + int len; + } hook_types[] = { + /* HOOK_JMP_DIRECT */ {&hook_api_jmp_direct, 5}, + /* HOOK_NOP_JMP_DIRECT */ {&hook_api_nop_jmp_direct, 6}, + /* HOOK_HOTPATCH_JMP_DIRECT */ {&hook_api_hotpatch_jmp_direct, 7}, + /* HOOK_PUSH_RETN */ {&hook_api_push_retn, 6}, + /* HOOK_NOP_PUSH_RETN */ {&hook_api_nop_push_retn, 7}, + /* HOOK_JMP_INDIRECT */ {&hook_api_jmp_indirect, 6}, + /* HOOK_MOV_EAX_JMP_EAX */ {&hook_api_mov_eax_jmp_eax, 7}, + /* HOOK_MOV_EAX_PUSH_RETN */ {&hook_api_mov_eax_push_retn, 7}, + /* HOOK_MOV_EAX_INDIRECT_JMP_EAX */ + {&hook_api_mov_eax_indirect_jmp_eax, 7}, + /* HOOK_MOV_EAX_INDIRECT_PUSH_RETN */ + {&hook_api_mov_eax_indirect_push_retn, 7}, +#if HOOK_ENABLE_FPU + /* HOOK_PUSH_FPU_RETN */ {&hook_api_push_fpu_retn, 11}, +#endif + /* HOOK_SPECIAL_JMP */ {&hook_api_special_jmp, 7}, + }; + + // is this address already hooked? + if(h->is_hooked != 0) { + return 0; + } + + // resolve the address to hook + unsigned char *addr = h->addr; + + if(addr == NULL && h->library != NULL && h->funcname != NULL) { + addr = (unsigned char *) GetProcAddress(GetModuleHandleW(h->library), + h->funcname); + } + if(addr == NULL) { + return -1; + } + + int ret = -1; + + // check if this is a valid hook type + if(type >= 0 && type < ARRAYSIZE(hook_types)) { + + // determine whether we're running under win7, if so, we might have to + // follow a short relative jmp and an indirect jump before reaching + // the real address + OSVERSIONINFO os_info = {sizeof(OSVERSIONINFO)}; + if(GetVersionEx(&os_info) && os_info.dwMajorVersion == 6 && + os_info.dwMinorVersion == 1) { + // windows 7 has a DLL called kernelbase.dll which basically acts + // as a layer between the program and kernel32 (and related?) it + // allows easy hotpatching of a set of functions which is why + // there's a short relative jump and an indirect jump. we want to + // resolve the address of the real function, so we follow these + // two jumps. + if(!memcmp(addr, "\xeb\x05", 2) && + !memcmp(addr + 7, "\xff\x25", 2)) { + addr = **(unsigned char ***)(addr + 9); + } + + // Some functions don't just have the short jump and indirect + // jump, but also an empty function prolog + // ("mov edi, edi ; push ebp ; mov ebp, esp ; pop ebp"). Other + // than that, this edge case is equivalent to the case above. + else if(!memcmp(addr, "\x8b\xff\x55\x8b\xec\x5d\xeb\x05", 8) && + !memcmp(addr + 13, "\xff\x25", 2)) { + addr = **(unsigned char ***)(addr + 15); + } + + // the following applies for "inlined" functions on windows 7, + // some functions are inlined into kernelbase.dll, rather than + // kernelbase.dll jumping to e.g. kernel32.dll. for these + // functions there is a short relative jump, followed by the + // inlined function. + if(!memcmp(addr, "\xeb\x02", 2) && + !memcmp(addr - 5, "\xcc\xcc\xcc\xcc\xcc", 5)) { + // step over the short jump and the relative offset + addr += 4; + } + } + + DWORD old_protect; + + // make the address writable + if(VirtualProtect(addr, hook_types[type].len, PAGE_EXECUTE_READWRITE, + &old_protect)) { + + if(hook_create_trampoline(addr, hook_types[type].len, h->tramp)) { + + hook_store_exception_info(h); + + uint8_t special = 0; + + if(h->allow_hook_recursion == 1) { + special = 1; + } + + hook_create_pre_tramp(h, special); + + // insert the hook (jump from the api to the + // pre-trampoline) + ret = hook_types[type].hook(h, addr, h->pre_tramp); + + // if successful, assign the trampoline address to *old_func + if(ret == 0) { + *h->old_func = h->tramp; + + // successful hook is successful + h->is_hooked = 1; + } + } + + // restore the old protection + VirtualProtect(addr, hook_types[type].len, old_protect, + &old_protect); + } + } + + return ret; +} + +hook_info_t *hook_info() +{ + return (hook_info_t *) __readfsdword(TLS_HOOK_INFO); +} + +static void ensure_valid_hook_info() +{ + if(hook_info() == NULL) { + hook_info_t *info = (hook_info_t *) calloc(1, sizeof(hook_info_t)+TLS_HOOK_INFO_RETADDR_SPACE); + info->retaddr_esp = (unsigned int) info + sizeof(hook_info_t) + TLS_HOOK_INFO_RETADDR_SPACE; + __writefsdword(TLS_HOOK_INFO, (unsigned int) info); + } +} + +void hook_enable() +{ + ensure_valid_hook_info(); + hook_info()->depth_count--; +} + +void hook_disable() +{ + ensure_valid_hook_info(); + hook_info()->depth_count++; +} + +int hook_is_inside() +{ + ensure_valid_hook_info(); + return hook_info()->depth_count || hook_info()->hook_count; +} + +unsigned int hook_get_last_error() +{ + ensure_valid_hook_info(); + return hook_info()->last_error; +} + +void hook_set_last_error(unsigned int errcode) +{ + ensure_valid_hook_info(); + hook_info()->last_error = errcode; +} + +void hook_disable_retaddr_check() +{ + g_enable_retaddr_check = 0; +} diff --git a/hooking.h b/hooking.h new file mode 100644 index 0000000..572b352 --- /dev/null +++ b/hooking.h @@ -0,0 +1,125 @@ +/* +Cuckoo Sandbox - Automated Malware Analysis +Copyright (C) 2010-2014 Cuckoo Sandbox Developers + +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 . +*/ + +typedef struct _hook_info_t { + unsigned int depth_count; + + unsigned int hook_count; + unsigned int retaddr_esp; + + unsigned int last_error; + unsigned int ret_last_error; + + // in case of an exception, this is the state of all registers upon + // execution of our hook + unsigned int eax; + unsigned int ecx; + unsigned int edx; + unsigned int ebx; + unsigned int esp; + unsigned int ebp; + unsigned int esi; + unsigned int edi; +} hook_info_t; + +typedef struct _hook_t { + const wchar_t *library; + const char *funcname; + + // instead of a library/funcname combination, an address can be given + // as well (this address has more priority than library/funcname) + void *addr; + + // pointer to the new function + void *new_func; + + // "function" which jumps over the trampoline and executes the original + // function call + void **old_func; + + // allow hook recursion on this hook? + // (see comments @ hook_create_pre_trampoline) + int allow_hook_recursion; + + // this hook has been performed + int is_hooked; + + unsigned char tramp[128]; + unsigned char pre_tramp[150]; + unsigned char store_exc[128]; + unsigned char hook_data[32]; +} hook_t; + +int lde(void *addr); + +int hook_api(hook_t *h, int type); + +hook_info_t* hook_info(); +void hook_enable(); +void hook_disable(); + +int hook_is_inside(); + +unsigned int hook_get_last_error(); +void hook_set_last_error(unsigned int errcode); + +void hook_disable_retaddr_check(); + +#define HOOK_BACKTRACE_DEPTH 20 + +#define HOOK_ENABLE_FPU 0 + +enum { + HOOK_JMP_DIRECT, + HOOK_NOP_JMP_DIRECT, + HOOK_HOTPATCH_JMP_DIRECT, + HOOK_PUSH_RETN, + HOOK_NOP_PUSH_RETN, + HOOK_JMP_INDIRECT, + HOOK_MOV_EAX_JMP_EAX, + HOOK_MOV_EAX_PUSH_RETN, + HOOK_MOV_EAX_INDIRECT_JMP_EAX, + HOOK_MOV_EAX_INDIRECT_PUSH_RETN, +#if HOOK_ENABLE_FPU + HOOK_PUSH_FPU_RETN, +#endif + HOOK_SPECIAL_JMP, + HOOK_TECHNIQUE_MAXTYPE, +}; + +#define HOOKDEF(return_value, calling_convention, apiname, ...) \ + return_value (calling_convention *Old_##apiname)(__VA_ARGS__); \ + return_value calling_convention New_##apiname(__VA_ARGS__) + +#define HOOKDEF2(return_value, calling_convention, apiname, ...) \ + return_value (calling_convention *Old2_##apiname)(__VA_ARGS__); \ + return_value calling_convention New2_##apiname(__VA_ARGS__) + +// each thread has a special 260-wchar counting unicode_string buffer in its +// thread information block, this is likely to be overwritten in certain +// functions, therefore we have this macro which copies it to the stack. +// (so we can use the unicode_string after executing the original function) +#define COPY_UNICODE_STRING(local_name, param_name) \ + UNICODE_STRING local_name = {0}; wchar_t local_name##_buf[260]; \ + local_name.Buffer = local_name##_buf; \ + if(param_name != NULL && param_name->MaximumLength < 520) { \ + local_name.Length = param_name->Length; \ + local_name.MaximumLength = param_name->MaximumLength; \ + memcpy(local_name.Buffer, param_name->Buffer, \ + local_name.MaximumLength); \ + } diff --git a/hooks.h b/hooks.h new file mode 100644 index 0000000..9e8f038 --- /dev/null +++ b/hooks.h @@ -0,0 +1,1486 @@ +/* +Cuckoo Sandbox - Automated Malware Analysis +Copyright (C) 2010-2014 Cuckoo Sandbox Developers + +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 . +*/ + +#include +#include +#include +#include "ntapi.h" + +// +// File Hooks +// + +extern HOOKDEF(NTSTATUS, WINAPI, NtCreateFile, + __out PHANDLE FileHandle, + __in ACCESS_MASK DesiredAccess, + __in POBJECT_ATTRIBUTES ObjectAttributes, + __out PIO_STATUS_BLOCK IoStatusBlock, + __in_opt PLARGE_INTEGER AllocationSize, + __in ULONG FileAttributes, + __in ULONG ShareAccess, + __in ULONG CreateDisposition, + __in ULONG CreateOptions, + __in PVOID EaBuffer, + __in ULONG EaLength +); + +extern HOOKDEF(NTSTATUS, WINAPI, NtOpenFile, + __out PHANDLE FileHandle, + __in ACCESS_MASK DesiredAccess, + __in POBJECT_ATTRIBUTES ObjectAttributes, + __out PIO_STATUS_BLOCK IoStatusBlock, + __in ULONG ShareAccess, + __in ULONG OpenOptions +); + +extern HOOKDEF(NTSTATUS, WINAPI, NtReadFile, + __in HANDLE FileHandle, + __in_opt HANDLE Event, + __in_opt PIO_APC_ROUTINE ApcRoutine, + __in_opt PVOID ApcContext, + __out PIO_STATUS_BLOCK IoStatusBlock, + __out PVOID Buffer, + __in ULONG Length, + __in_opt PLARGE_INTEGER ByteOffset, + __in_opt PULONG Key +); + +extern HOOKDEF(NTSTATUS, WINAPI, NtWriteFile, + __in HANDLE FileHandle, + __in_opt HANDLE Event, + __in_opt PIO_APC_ROUTINE ApcRoutine, + __in_opt PVOID ApcContext, + __out PIO_STATUS_BLOCK IoStatusBlock, + __in PVOID Buffer, + __in ULONG Length, + __in_opt PLARGE_INTEGER ByteOffset, + __in_opt PULONG Key +); + +extern HOOKDEF(NTSTATUS, WINAPI, NtDeleteFile, + __in POBJECT_ATTRIBUTES ObjectAttributes +); + +extern HOOKDEF(NTSTATUS, WINAPI, NtDeviceIoControlFile, + __in HANDLE FileHandle, + __in HANDLE Event, + __in PIO_APC_ROUTINE ApcRoutine, + __in PVOID ApcContext, + __out PIO_STATUS_BLOCK IoStatusBlock, + __in ULONG IoControlCode, + __in PVOID InputBuffer, + __in ULONG InputBufferLength, + __out PVOID OutputBuffer, + __in ULONG OutputBufferLength +); + +extern HOOKDEF(NTSTATUS, WINAPI, NtQueryDirectoryFile, + __in HANDLE FileHandle, + __in_opt HANDLE Event, + __in_opt PIO_APC_ROUTINE ApcRoutine, + __in_opt PVOID ApcContext, + __out PIO_STATUS_BLOCK IoStatusBlock, + __out PVOID FileInformation, + __in ULONG Length, + __in FILE_INFORMATION_CLASS FileInformationClass, + __in BOOLEAN ReturnSingleEntry, + __in_opt PUNICODE_STRING FileName, + __in BOOLEAN RestartScan +); + +extern HOOKDEF(NTSTATUS, WINAPI, NtQueryInformationFile, + __in HANDLE FileHandle, + __out PIO_STATUS_BLOCK IoStatusBlock, + __out PVOID FileInformation, + __in ULONG Length, + __in FILE_INFORMATION_CLASS FileInformationClass +); + +extern HOOKDEF(NTSTATUS, WINAPI, NtSetInformationFile, + __in HANDLE FileHandle, + __out PIO_STATUS_BLOCK IoStatusBlock, + __in PVOID FileInformation, + __in ULONG Length, + __in FILE_INFORMATION_CLASS FileInformationClass +); + +extern HOOKDEF(NTSTATUS, WINAPI, NtOpenDirectoryObject, + __out PHANDLE DirectoryHandle, + __in ACCESS_MASK DesiredAccess, + __in POBJECT_ATTRIBUTES ObjectAttributes +); + +extern HOOKDEF(NTSTATUS, WINAPI, NtCreateDirectoryObject, + __out PHANDLE DirectoryHandle, + __in ACCESS_MASK DesiredAccess, + __in POBJECT_ATTRIBUTES ObjectAttributes +); + +extern HOOKDEF(BOOL, WINAPI, MoveFileWithProgressW, + __in LPWSTR lpExistingFileName, + __in_opt LPWSTR lpNewFileName, + __in_opt LPPROGRESS_ROUTINE lpProgressRoutine, + __in_opt LPVOID lpData, + __in DWORD dwFlags +); + +extern HOOKDEF(BOOL, WINAPI, CreateDirectoryW, + __in LPCTSTR lpPathName, + __in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes +); + +extern HOOKDEF(BOOL, WINAPI, CreateDirectoryExW, + __in LPWSTR lpTemplateDirectory, + __in LPWSTR lpNewDirectory, + __in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes +); + +extern HOOKDEF(BOOL, WINAPI, RemoveDirectoryA, + __in LPCTSTR lpPathName +); + +extern HOOKDEF(BOOL, WINAPI, RemoveDirectoryW, + __in LPWSTR lpPathName +); + +extern HOOKDEF(BOOL, WINAPI, MoveFileWithProgressW, + __in LPWSTR lpExistingFileName, + __in_opt LPWSTR lpNewFileName, + __in_opt LPPROGRESS_ROUTINE lpProgressRoutine, + __in_opt LPVOID lpData, + __in DWORD dwFlags +); + +extern HOOKDEF(HANDLE, WINAPI, FindFirstFileExA, + __in LPCTSTR lpFileName, + __in FINDEX_INFO_LEVELS fInfoLevelId, + __out LPVOID lpFindFileData, + __in FINDEX_SEARCH_OPS fSearchOp, + __reserved LPVOID lpSearchFilter, + __in DWORD dwAdditionalFlags +); + +extern HOOKDEF(HANDLE, WINAPI, FindFirstFileExW, + __in LPWSTR lpFileName, + __in FINDEX_INFO_LEVELS fInfoLevelId, + __out LPVOID lpFindFileData, + __in FINDEX_SEARCH_OPS fSearchOp, + __reserved LPVOID lpSearchFilter, + __in DWORD dwAdditionalFlags +); + +extern HOOKDEF(BOOL, WINAPI, CopyFileA, + __in LPCTSTR lpExistingFileName, + __in LPCTSTR lpNewFileName, + __in BOOL bFailIfExists +); + +extern HOOKDEF(BOOL, WINAPI, CopyFileW, + __in LPWSTR lpExistingFileName, + __in LPWSTR lpNewFileName, + __in BOOL bFailIfExists +); + +extern HOOKDEF(BOOL, WINAPI, CopyFileExW, + _In_ LPWSTR lpExistingFileName, + _In_ LPWSTR lpNewFileName, + _In_opt_ LPPROGRESS_ROUTINE lpProgressRoutine, + _In_opt_ LPVOID lpData, + _In_opt_ LPBOOL pbCancel, + _In_ DWORD dwCopyFlags +); + +extern HOOKDEF(BOOL, WINAPI, DeleteFileA, + __in LPCSTR lpFileName +); + +extern HOOKDEF(BOOL, WINAPI, DeleteFileW, + __in LPWSTR lpFileName +); + +// +// Registry Hooks +// + +extern HOOKDEF(LONG, WINAPI, RegOpenKeyExA, + __in HKEY hKey, + __in_opt LPCTSTR lpSubKey, + __reserved DWORD ulOptions, + __in REGSAM samDesired, + __out PHKEY phkResult +); + +extern HOOKDEF(LONG, WINAPI, RegOpenKeyExW, + __in HKEY hKey, + __in_opt LPWSTR lpSubKey, + __reserved DWORD ulOptions, + __in REGSAM samDesired, + __out PHKEY phkResult +); + +extern HOOKDEF(LONG, WINAPI, RegCreateKeyExA, + __in HKEY hKey, + __in LPCTSTR lpSubKey, + __reserved DWORD Reserved, + __in_opt LPTSTR lpClass, + __in DWORD dwOptions, + __in REGSAM samDesired, + __in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes, + __out PHKEY phkResult, + __out_opt LPDWORD lpdwDisposition +); + +extern HOOKDEF(LONG, WINAPI, RegCreateKeyExW, + __in HKEY hKey, + __in LPWSTR lpSubKey, + __reserved DWORD Reserved, + __in_opt LPWSTR lpClass, + __in DWORD dwOptions, + __in REGSAM samDesired, + __in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes, + __out PHKEY phkResult, + __out_opt LPDWORD lpdwDisposition +); + +extern HOOKDEF(LONG, WINAPI, RegDeleteKeyA, + __in HKEY hKey, + __in LPCTSTR lpSubKey +); + +extern HOOKDEF(LONG, WINAPI, RegDeleteKeyW, + __in HKEY hKey, + __in LPWSTR lpSubKey +); + +extern HOOKDEF(LONG, WINAPI, RegEnumKeyW, + __in HKEY hKey, + __in DWORD dwIndex, + __out LPWSTR lpName, + __in DWORD cchName +); + +extern HOOKDEF(LONG, WINAPI, RegEnumKeyExA, + __in HKEY hKey, + __in DWORD dwIndex, + __out LPTSTR lpName, + __inout LPDWORD lpcName, + __reserved LPDWORD lpReserved, + __inout LPTSTR lpClass, + __inout_opt LPDWORD lpcClass, + __out_opt PFILETIME lpftLastWriteTime +); + +extern HOOKDEF(LONG, WINAPI, RegEnumKeyExW, + __in HKEY hKey, + __in DWORD dwIndex, + __out LPWSTR lpName, + __inout LPDWORD lpcName, + __reserved LPDWORD lpReserved, + __inout LPWSTR lpClass, + __inout_opt LPDWORD lpcClass, + __out_opt PFILETIME lpftLastWriteTime +); + +extern HOOKDEF(LONG, WINAPI, RegEnumValueA, + __in HKEY hKey, + __in DWORD dwIndex, + __out LPTSTR lpValueName, + __inout LPDWORD lpcchValueName, + __reserved LPDWORD lpReserved, + __out_opt LPDWORD lpType, + __out_opt LPBYTE lpData, + __inout_opt LPDWORD lpcbData +); + +extern HOOKDEF(LONG, WINAPI, RegEnumValueW, + __in HKEY hKey, + __in DWORD dwIndex, + __out LPWSTR lpValueName, + __inout LPDWORD lpcchValueName, + __reserved LPDWORD lpReserved, + __out_opt LPDWORD lpType, + __out_opt LPBYTE lpData, + __inout_opt LPDWORD lpcbData +); + +extern HOOKDEF(LONG, WINAPI, RegSetValueExA, + __in HKEY hKey, + __in_opt LPCTSTR lpValueName, + __reserved DWORD Reserved, + __in DWORD dwType, + __in const BYTE *lpData, + __in DWORD cbData +); + +extern HOOKDEF(LONG, WINAPI, RegSetValueExW, + __in HKEY hKey, + __in_opt LPWSTR lpValueName, + __reserved DWORD Reserved, + __in DWORD dwType, + __in const BYTE *lpData, + __in DWORD cbData +); + +extern HOOKDEF(LONG, WINAPI, RegQueryValueExA, + __in HKEY hKey, + __in_opt LPCTSTR lpValueName, + __reserved LPDWORD lpReserved, + __out_opt LPDWORD lpType, + __out_opt LPBYTE lpData, + __inout_opt LPDWORD lpcbData +); + +extern HOOKDEF(LONG, WINAPI, RegQueryValueExW, + __in HKEY hKey, + __in_opt LPWSTR lpValueName, + __reserved LPDWORD lpReserved, + __out_opt LPDWORD lpType, + __out_opt LPBYTE lpData, + __inout_opt LPDWORD lpcbData +); + +extern HOOKDEF(LONG, WINAPI, RegDeleteValueA, + __in HKEY hKey, + __in_opt LPCTSTR lpValueName +); + +extern HOOKDEF(LONG, WINAPI, RegDeleteValueW, + __in HKEY hKey, + __in_opt LPWSTR lpValueName +); + +extern HOOKDEF(LONG, WINAPI, RegQueryInfoKeyA, + _In_ HKEY hKey, + _Out_opt_ LPTSTR lpClass, + _Inout_opt_ LPDWORD lpcClass, + _Reserved_ LPDWORD lpReserved, + _Out_opt_ LPDWORD lpcSubKeys, + _Out_opt_ LPDWORD lpcMaxSubKeyLen, + _Out_opt_ LPDWORD lpcMaxClassLen, + _Out_opt_ LPDWORD lpcValues, + _Out_opt_ LPDWORD lpcMaxValueNameLen, + _Out_opt_ LPDWORD lpcMaxValueLen, + _Out_opt_ LPDWORD lpcbSecurityDescriptor, + _Out_opt_ PFILETIME lpftLastWriteTime +); + +extern HOOKDEF(LONG, WINAPI, RegQueryInfoKeyW, + _In_ HKEY hKey, + _Out_opt_ LPWSTR lpClass, + _Inout_opt_ LPDWORD lpcClass, + _Reserved_ LPDWORD lpReserved, + _Out_opt_ LPDWORD lpcSubKeys, + _Out_opt_ LPDWORD lpcMaxSubKeyLen, + _Out_opt_ LPDWORD lpcMaxClassLen, + _Out_opt_ LPDWORD lpcValues, + _Out_opt_ LPDWORD lpcMaxValueNameLen, + _Out_opt_ LPDWORD lpcMaxValueLen, + _Out_opt_ LPDWORD lpcbSecurityDescriptor, + _Out_opt_ PFILETIME lpftLastWriteTime +); + +extern HOOKDEF(LONG, WINAPI, RegCloseKey, + __in HKEY hKey +); + +// +// Native Registry Hooks +// + +extern HOOKDEF(NTSTATUS, WINAPI, NtCreateKey, + __out PHANDLE KeyHandle, + __in ACCESS_MASK DesiredAccess, + __in POBJECT_ATTRIBUTES ObjectAttributes, + __reserved ULONG TitleIndex, + __in_opt PUNICODE_STRING Class, + __in ULONG CreateOptions, + __out_opt PULONG Disposition +); + +extern HOOKDEF(NTSTATUS, WINAPI, NtOpenKey, + __out PHANDLE KeyHandle, + __in ACCESS_MASK DesiredAccess, + __in POBJECT_ATTRIBUTES ObjectAttributes +); + +extern HOOKDEF(NTSTATUS, WINAPI, NtOpenKeyEx, + __out PHANDLE KeyHandle, + __in ACCESS_MASK DesiredAccess, + __in POBJECT_ATTRIBUTES ObjectAttributes, + __in ULONG OpenOptions +); + +extern HOOKDEF(NTSTATUS, WINAPI, NtRenameKey, + __in HANDLE KeyHandle, + __in PUNICODE_STRING NewName +); + +extern HOOKDEF(NTSTATUS, WINAPI, NtReplaceKey, + __in POBJECT_ATTRIBUTES NewHiveFileName, + __in HANDLE KeyHandle, + __in POBJECT_ATTRIBUTES BackupHiveFileName +); + +extern HOOKDEF(NTSTATUS, WINAPI, NtEnumerateKey, + __in HANDLE KeyHandle, + __in ULONG Index, + __in KEY_INFORMATION_CLASS KeyInformationClass, + __out_opt PVOID KeyInformation, + __in ULONG Length, + __out PULONG ResultLength +); + +extern HOOKDEF(NTSTATUS, WINAPI, NtEnumerateValueKey, + __in HANDLE KeyHandle, + __in ULONG Index, + __in KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, + __out_opt PVOID KeyValueInformation, + __in ULONG Length, + __out PULONG ResultLength +); + +extern HOOKDEF(NTSTATUS, WINAPI, NtSetValueKey, + __in HANDLE KeyHandle, + __in PUNICODE_STRING ValueName, + __in_opt ULONG TitleIndex, + __in ULONG Type, + __in_opt PVOID Data, + __in ULONG DataSize +); + +extern HOOKDEF(NTSTATUS, WINAPI, NtQueryValueKey, + __in HANDLE KeyHandle, + __in PUNICODE_STRING ValueName, + __in KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, + __out_opt PVOID KeyValueInformation, + __in ULONG Length, + __out PULONG ResultLength +); + +extern HOOKDEF(NTSTATUS, WINAPI, NtQueryMultipleValueKey, + __in HANDLE KeyHandle, + __inout PKEY_VALUE_ENTRY ValueEntries, + __in ULONG EntryCount, + __out PVOID ValueBuffer, + __inout PULONG BufferLength, + __out_opt PULONG RequiredBufferLength +); + +extern HOOKDEF(NTSTATUS, WINAPI, NtDeleteKey, + __in HANDLE KeyHandle +); + +extern HOOKDEF(NTSTATUS, WINAPI, NtDeleteValueKey, + __in HANDLE KeyHandle, + __in PUNICODE_STRING ValueName +); + +extern HOOKDEF(NTSTATUS, WINAPI, NtLoadKey, + __in POBJECT_ATTRIBUTES TargetKey, + __in POBJECT_ATTRIBUTES SourceFile +); + +extern HOOKDEF(NTSTATUS, WINAPI, NtLoadKey2, + __in POBJECT_ATTRIBUTES TargetKey, + __in POBJECT_ATTRIBUTES SourceFile, + __in ULONG Flags +); + +extern HOOKDEF(NTSTATUS, WINAPI, NtLoadKeyEx, + __in POBJECT_ATTRIBUTES TargetKey, + __in POBJECT_ATTRIBUTES SourceFile, + __in ULONG Flags, + __in_opt HANDLE TrustClassKey +); + +extern HOOKDEF(NTSTATUS, WINAPI, NtQueryKey, + __in HANDLE KeyHandle, + __in KEY_INFORMATION_CLASS KeyInformationClass, + __out_opt PVOID KeyInformation, + __in ULONG Length, + __out PULONG ResultLength +); + +extern HOOKDEF(NTSTATUS, WINAPI, NtSaveKey, + __in HANDLE KeyHandle, + __in HANDLE FileHandle +); + +extern HOOKDEF(NTSTATUS, WINAPI, NtSaveKeyEx, + __in HANDLE KeyHandle, + __in HANDLE FileHandle, + __in ULONG Format +); + +// +// Window Hooks +// + +extern HOOKDEF(HWND, WINAPI, FindWindowA, + __in_opt LPCTSTR lpClassName, + __in_opt LPCTSTR lpWindowName +); + +extern HOOKDEF(HWND, WINAPI, FindWindowW, + __in_opt LPWSTR lpClassName, + __in_opt LPWSTR lpWindowName +); + +extern HOOKDEF(HWND, WINAPI, FindWindowExA, + __in_opt HWND hwndParent, + __in_opt HWND hwndChildAfter, + __in_opt LPCTSTR lpszClass, + __in_opt LPCTSTR lpszWindow +); + +extern HOOKDEF(HWND, WINAPI, FindWindowExW, + __in_opt HWND hwndParent, + __in_opt HWND hwndChildAfter, + __in_opt LPWSTR lpszClass, + __in_opt LPWSTR lpszWindow +); + +// +// Sync Hooks +// + +extern HOOKDEF(NTSTATUS, WINAPI, NtCreateMutant, + __out PHANDLE MutantHandle, + __in ACCESS_MASK DesiredAccess, + __in_opt POBJECT_ATTRIBUTES ObjectAttributes, + __in BOOLEAN InitialOwner +); + +extern HOOKDEF(NTSTATUS, WINAPI, NtOpenMutant, + __out PHANDLE MutantHandle, + __in ACCESS_MASK DesiredAccess, + __in POBJECT_ATTRIBUTES ObjectAttributes +); + +extern HOOKDEF(NTSTATUS, WINAPI, NtCreateNamedPipeFile, + OUT PHANDLE NamedPipeFileHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN ULONG ShareAccess, + IN ULONG CreateDisposition, + IN ULONG CreateOptions, + IN BOOLEAN WriteModeMessage, + IN BOOLEAN ReadModeMessage, + IN BOOLEAN NonBlocking, + IN ULONG MaxInstances, + IN ULONG InBufferSize, + IN ULONG OutBufferSize, + IN PLARGE_INTEGER DefaultTimeOut +); + +// +// Process Hooks +// + +extern HOOKDEF(NTSTATUS, WINAPI, NtCreateProcess, + __out PHANDLE ProcessHandle, + __in ACCESS_MASK DesiredAccess, + __in_opt POBJECT_ATTRIBUTES ObjectAttributes, + __in HANDLE ParentProcess, + __in BOOLEAN InheritObjectTable, + __in_opt HANDLE SectionHandle, + __in_opt HANDLE DebugPort, + __in_opt HANDLE ExceptionPort +); + +extern HOOKDEF(NTSTATUS, WINAPI, NtCreateProcessEx, + __out PHANDLE ProcessHandle, + __in ACCESS_MASK DesiredAccess, + __in_opt POBJECT_ATTRIBUTES ObjectAttributes, + __in HANDLE ParentProcess, + __in ULONG Flags, + __in_opt HANDLE SectionHandle, + __in_opt HANDLE DebugPort, + __in_opt HANDLE ExceptionPort, + __in BOOLEAN InJob +); + +extern HOOKDEF(NTSTATUS, WINAPI, NtCreateUserProcess, + __out PHANDLE ProcessHandle, + __out PHANDLE ThreadHandle, + __in ACCESS_MASK ProcessDesiredAccess, + __in ACCESS_MASK ThreadDesiredAccess, + __in_opt POBJECT_ATTRIBUTES ProcessObjectAttributes, + __in_opt POBJECT_ATTRIBUTES ThreadObjectAttributes, + __in ULONG ProcessFlags, + __in ULONG ThreadFlags, + __in_opt PRTL_USER_PROCESS_PARAMETERS ProcessParameters, + __inout PPS_CREATE_INFO CreateInfo, + __in_opt PPS_ATTRIBUTE_LIST AttributeList +); + +extern HOOKDEF(NTSTATUS, WINAPI, RtlCreateUserProcess, + IN PUNICODE_STRING ImagePath, + IN ULONG ObjectAttributes, + IN OUT PRTL_USER_PROCESS_PARAMETERS ProcessParameters, + IN PSECURITY_DESCRIPTOR ProcessSecurityDescriptor OPTIONAL, + IN PSECURITY_DESCRIPTOR ThreadSecurityDescriptor OPTIONAL, + IN HANDLE ParentProcess, + IN BOOLEAN InheritHandles, + IN HANDLE DebugPort OPTIONAL, + IN HANDLE ExceptionPort OPTIONAL, + OUT PRTL_USER_PROCESS_INFORMATION ProcessInformation +); + +extern HOOKDEF(NTSTATUS, WINAPI, NtOpenProcess, + __out PHANDLE ProcessHandle, + __in ACCESS_MASK DesiredAccess, + __in POBJECT_ATTRIBUTES ObjectAttributes, + __in_opt PCLIENT_ID ClientId +); + +extern HOOKDEF(NTSTATUS, WINAPI, NtTerminateProcess, + __in_opt HANDLE ProcessHandle, + __in NTSTATUS ExitStatus +); + +extern HOOKDEF(NTSTATUS, WINAPI, NtCreateSection, + __out PHANDLE SectionHandle, + __in ACCESS_MASK DesiredAccess, + __in_opt POBJECT_ATTRIBUTES ObjectAttributes, + __in_opt PLARGE_INTEGER MaximumSize, + __in ULONG SectionPageProtection, + __in ULONG AllocationAttributes, + __in_opt HANDLE FileHandle +); + +extern HOOKDEF(NTSTATUS, WINAPI, NtMakeTemporaryObject, + __in HANDLE ObjectHandle +); + +extern HOOKDEF(NTSTATUS, WINAPI, NtMakePermanentObject, + __in HANDLE ObjectHandle +); + +extern HOOKDEF(NTSTATUS, WINAPI, NtOpenSection, + __out PHANDLE SectionHandle, + __in ACCESS_MASK DesiredAccess, + __in POBJECT_ATTRIBUTES ObjectAttributes +); + +extern HOOKDEF(BOOL, WINAPI, CreateProcessInternalW, + __in_opt LPVOID lpUnknown1, + __in_opt LPWSTR lpApplicationName, + __inout_opt LPWSTR lpCommandLine, + __in_opt LPSECURITY_ATTRIBUTES lpProcessAttributes, + __in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes, + __in BOOL bInheritHandles, + __in DWORD dwCreationFlags, + __in_opt LPVOID lpEnvironment, + __in_opt LPWSTR lpCurrentDirectory, + __in LPSTARTUPINFO lpStartupInfo, + __out LPPROCESS_INFORMATION lpProcessInformation, + __in_opt LPVOID lpUnknown2 +); + +extern HOOKDEF2(BOOL, WINAPI, CreateProcessInternalW, + __in_opt LPVOID lpUnknown1, + __in_opt LPWSTR lpApplicationName, + __inout_opt LPWSTR lpCommandLine, + __in_opt LPSECURITY_ATTRIBUTES lpProcessAttributes, + __in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes, + __in BOOL bInheritHandles, + __in DWORD dwCreationFlags, + __in_opt LPVOID lpEnvironment, + __in_opt LPWSTR lpCurrentDirectory, + __in LPSTARTUPINFO lpStartupInfo, + __out LPPROCESS_INFORMATION lpProcessInformation, + __in_opt LPVOID lpUnknown2 +); + +extern HOOKDEF(VOID, WINAPI, ExitProcess, + __in UINT uExitCode +); + +extern HOOKDEF(BOOL, WINAPI, ShellExecuteExW, + __inout SHELLEXECUTEINFOW *pExecInfo +); + +extern HOOKDEF(NTSTATUS, WINAPI, NtUnmapViewOfSection, + _In_ HANDLE ProcessHandle, + _In_opt_ PVOID BaseAddress +); + +extern HOOKDEF(NTSTATUS, WINAPI, NtAllocateVirtualMemory, + __in HANDLE ProcessHandle, + __inout PVOID *BaseAddress, + __in ULONG_PTR ZeroBits, + __inout PSIZE_T RegionSize, + __in ULONG AllocationType, + __in ULONG Protect +); + +extern HOOKDEF(NTSTATUS, WINAPI, NtReadVirtualMemory, + __in HANDLE ProcessHandle, + __in LPCVOID BaseAddress, + __out LPVOID Buffer, + __in ULONG NumberOfBytesToRead, + __out_opt PULONG NumberOfBytesReaded +); + +extern HOOKDEF(BOOL, WINAPI, ReadProcessMemory, + _In_ HANDLE hProcess, + _In_ LPCVOID lpBaseAddress, + _Out_ LPVOID lpBuffer, + _In_ SIZE_T nSize, + _Out_ SIZE_T *lpNumberOfBytesRead +); + +extern HOOKDEF(NTSTATUS, WINAPI, NtWriteVirtualMemory, + __in HANDLE ProcessHandle, + __in LPVOID BaseAddress, + __in LPCVOID Buffer, + __in ULONG NumberOfBytesToWrite, + __out_opt ULONG *NumberOfBytesWritten +); + +extern HOOKDEF(BOOL, WINAPI, WriteProcessMemory, + _In_ HANDLE hProcess, + _In_ LPVOID lpBaseAddress, + _In_ LPCVOID lpBuffer, + _In_ SIZE_T nSize, + _Out_ SIZE_T *lpNumberOfBytesWritten +); + +extern HOOKDEF(NTSTATUS, WINAPI, NtProtectVirtualMemory, + IN HANDLE ProcessHandle, + IN OUT PVOID *BaseAddress, + IN OUT PULONG NumberOfBytesToProtect, + IN ULONG NewAccessProtection, + OUT PULONG OldAccessProtection +); + +extern HOOKDEF(BOOL, WINAPI, VirtualProtectEx, + __in HANDLE hProcess, + __in LPVOID lpAddress, + __in SIZE_T dwSize, + __in DWORD flNewProtect, + __out PDWORD lpflOldProtect +); + +extern HOOKDEF(NTSTATUS, WINAPI, NtFreeVirtualMemory, + IN HANDLE ProcessHandle, + IN PVOID *BaseAddress, + IN OUT PULONG RegionSize, + IN ULONG FreeType +); + +extern HOOKDEF(BOOL, WINAPI, VirtualFreeEx, + __in HANDLE hProcess, + __in LPVOID lpAddress, + __in SIZE_T dwSize, + __in DWORD dwFreeType +); + +extern HOOKDEF(int, CDECL, system, + const char *command +); + +// +// Thread Hooks +// + +extern HOOKDEF(NTSTATUS, WINAPI, NtCreateThread, + __out PHANDLE ThreadHandle, + __in ACCESS_MASK DesiredAccess, + __in_opt POBJECT_ATTRIBUTES ObjectAttributes, + __in HANDLE ProcessHandle, + __out PCLIENT_ID ClientId, + __in PCONTEXT ThreadContext, + __in PINITIAL_TEB InitialTeb, + __in BOOLEAN CreateSuspended +); + +extern HOOKDEF(NTSTATUS, WINAPI, NtCreateThreadEx, + OUT PHANDLE hThread, + IN ACCESS_MASK DesiredAccess, + IN PVOID ObjectAttributes, + IN HANDLE ProcessHandle, + IN LPTHREAD_START_ROUTINE lpStartAddress, + IN PVOID lpParameter, + IN BOOL CreateSuspended, + IN LONG StackZeroBits, + IN LONG SizeOfStackCommit, + IN LONG SizeOfStackReserve, + OUT PVOID lpBytesBuffer +); + +extern HOOKDEF(NTSTATUS, WINAPI, NtOpenThread, + __out PHANDLE ThreadHandle, + __in ACCESS_MASK DesiredAccess, + __in POBJECT_ATTRIBUTES ObjectAttributes, + __in PCLIENT_ID ClientId +); + +extern HOOKDEF(NTSTATUS, WINAPI, NtGetContextThread, + __in HANDLE ThreadHandle, + __inout LPCONTEXT Context +); + +extern HOOKDEF(NTSTATUS, WINAPI, NtSetContextThread, + __in HANDLE ThreadHandle, + __in const CONTEXT *Context +); + +extern HOOKDEF(NTSTATUS, WINAPI, NtSuspendThread, + __in HANDLE ThreadHandle, + __out_opt ULONG *PreviousSuspendCount +); + +extern HOOKDEF(NTSTATUS, WINAPI, NtResumeThread, + __in HANDLE ThreadHandle, + __out_opt ULONG *SuspendCount +); + +extern HOOKDEF(NTSTATUS, WINAPI, NtTerminateThread, + __in HANDLE ThreadHandle, + __in NTSTATUS ExitStatus +); + +extern HOOKDEF(HANDLE, WINAPI, CreateThread, + __in LPSECURITY_ATTRIBUTES lpThreadAttributes, + __in SIZE_T dwStackSize, + __in LPTHREAD_START_ROUTINE lpStartAddress, + __in LPVOID lpParameter, + __in DWORD dwCreationFlags, + __out LPDWORD lpThreadId +); + +extern HOOKDEF(HANDLE, WINAPI, CreateRemoteThread, + __in HANDLE hProcess, + __in LPSECURITY_ATTRIBUTES lpThreadAttributes, + __in SIZE_T dwStackSize, + __in LPTHREAD_START_ROUTINE lpStartAddress, + __in LPVOID lpParameter, + __in DWORD dwCreationFlags, + __out LPDWORD lpThreadId +); + +extern HOOKDEF(BOOL, WINAPI, TerminateThread, + __inout HANDLE hThread, + __in DWORD dwExitCode +); + +extern HOOKDEF(VOID, WINAPI, ExitThread, + __in DWORD dwExitCode +); + +extern HOOKDEF(NTSTATUS, WINAPI, RtlCreateUserThread, + IN HANDLE ProcessHandle, + IN PSECURITY_DESCRIPTOR SecurityDescriptor OPTIONAL, + IN BOOLEAN CreateSuspended, + IN ULONG StackZeroBits, + IN OUT PULONG StackReserved, + IN OUT PULONG StackCommit, + IN PVOID StartAddress, + IN PVOID StartParameter OPTIONAL, + OUT PHANDLE ThreadHandle, + OUT PCLIENT_ID ClientId +); + +// +// Misc Hooks +// + +extern HOOKDEF(HHOOK, WINAPI, SetWindowsHookExA, + __in int idHook, + __in HOOKPROC lpfn, + __in HINSTANCE hMod, + __in DWORD dwThreadId +); + +extern HOOKDEF(HHOOK, WINAPI, SetWindowsHookExW, + __in int idHook, + __in HOOKPROC lpfn, + __in HINSTANCE hMod, + __in DWORD dwThreadId +); + +extern HOOKDEF(BOOL, WINAPI, UnhookWindowsHookEx, + __in HHOOK hhk +); + +extern HOOKDEF(NTSTATUS, WINAPI, LdrLoadDll, + __in_opt PWCHAR PathToFile, + __in_opt ULONG Flags, + __in PUNICODE_STRING ModuleFileName, + __out PHANDLE ModuleHandle +); + +extern HOOKDEF(NTSTATUS, WINAPI, LdrGetDllHandle, + __in_opt PWORD pwPath, + __in_opt PVOID Unused, + __in PUNICODE_STRING ModuleFileName, + __out PHANDLE pHModule +); + +extern HOOKDEF(NTSTATUS, WINAPI, LdrGetProcedureAddress, + __in HMODULE ModuleHandle, + __in_opt PANSI_STRING FunctionName, + __in_opt WORD Ordinal, + __out PVOID *FunctionAddress +); + +extern HOOKDEF(BOOL, WINAPI, DeviceIoControl, + __in HANDLE hDevice, + __in DWORD dwIoControlCode, + __in_opt LPVOID lpInBuffer, + __in DWORD nInBufferSize, + __out_opt LPVOID lpOutBuffer, + __in DWORD nOutBufferSize, + __out_opt LPDWORD lpBytesReturned, + __inout_opt LPOVERLAPPED lpOverlapped +); + +extern HOOKDEF(NTSTATUS, WINAPI, NtDelayExecution, + __in BOOLEAN Alertable, + __in PLARGE_INTEGER DelayInterval +); + +extern HOOKDEF(BOOL, WINAPI, ExitWindowsEx, + __in UINT uFlags, + __in DWORD dwReason +); + +extern HOOKDEF(BOOL, WINAPI, IsDebuggerPresent, + void +); + +extern HOOKDEF(BOOL, WINAPI, LookupPrivilegeValueW, + __in_opt LPWSTR lpSystemName, + __in LPWSTR lpName, + __out PLUID lpLuid +); + +extern HOOKDEF(NTSTATUS, WINAPI, NtClose, + __in HANDLE Handle +); + +extern HOOKDEF(BOOL, WINAPI, WriteConsoleA, + _In_ HANDLE hConsoleOutput, + _In_ const VOID *lpBuffer, + _In_ DWORD nNumberOfCharsToWrite, + _Out_ LPDWORD lpNumberOfCharsWritten, + _Reserved_ LPVOID lpReseverd +); + +extern HOOKDEF(BOOL, WINAPI, WriteConsoleW, + _In_ HANDLE hConsoleOutput, + _In_ const VOID *lpBuffer, + _In_ DWORD nNumberOfCharsToWrite, + _Out_ LPDWORD lpNumberOfCharsWritten, + _Reserved_ LPVOID lpReseverd +); + +extern HOOKDEF(int, WINAPI, GetSystemMetrics, + _In_ int nIndex +); + +extern HOOKDEF(BOOL, WINAPI, GetCursorPos, + _Out_ LPPOINT lpPoint +); + +// +// Network Hooks +// + +extern HOOKDEF(HRESULT, WINAPI, URLDownloadToFileW, + LPUNKNOWN pCaller, + LPWSTR szURL, + LPWSTR szFileName, + DWORD dwReserved, + LPVOID lpfnCB +); + +extern HOOKDEF(HINTERNET, WINAPI, InternetOpenA, + _In_ LPCTSTR lpszAgent, + _In_ DWORD dwAccessType, + _In_ LPCTSTR lpszProxyName, + _In_ LPCTSTR lpszProxyBypass, + _In_ DWORD dwFlags +); + +extern HOOKDEF(HINTERNET, WINAPI, InternetOpenW, + _In_ LPWSTR lpszAgent, + _In_ DWORD dwAccessType, + _In_ LPWSTR lpszProxyName, + _In_ LPWSTR lpszProxyBypass, + _In_ DWORD dwFlags +); + +extern HOOKDEF(HINTERNET, WINAPI, InternetConnectA, + _In_ HINTERNET hInternet, + _In_ LPCTSTR lpszServerName, + _In_ INTERNET_PORT nServerPort, + _In_ LPCTSTR lpszUsername, + _In_ LPCTSTR lpszPassword, + _In_ DWORD dwService, + _In_ DWORD dwFlags, + _In_ DWORD_PTR dwContext +); + +extern HOOKDEF(HINTERNET, WINAPI, InternetConnectW, + _In_ HINTERNET hInternet, + _In_ LPWSTR lpszServerName, + _In_ INTERNET_PORT nServerPort, + _In_ LPWSTR lpszUsername, + _In_ LPWSTR lpszPassword, + _In_ DWORD dwService, + _In_ DWORD dwFlags, + _In_ DWORD_PTR dwContext +); + +extern HOOKDEF(HINTERNET, WINAPI, InternetOpenUrlA, + __in HINTERNET hInternet, + __in LPCTSTR lpszUrl, + __in LPCTSTR lpszHeaders, + __in DWORD dwHeadersLength, + __in DWORD dwFlags, + __in DWORD_PTR dwContext +); + +extern HOOKDEF(HINTERNET, WINAPI, InternetOpenUrlW, + __in HINTERNET hInternet, + __in LPWSTR lpszUrl, + __in LPWSTR lpszHeaders, + __in DWORD dwHeadersLength, + __in DWORD dwFlags, + __in DWORD_PTR dwContext +); + +extern HOOKDEF(HINTERNET, WINAPI, HttpOpenRequestA, + __in HINTERNET hConnect, + __in LPCTSTR lpszVerb, + __in LPCTSTR lpszObjectName, + __in LPCTSTR lpszVersion, + __in LPCTSTR lpszReferer, + __in LPCTSTR *lplpszAcceptTypes, + __in DWORD dwFlags, + __in DWORD_PTR dwContext +); + +extern HOOKDEF(HINTERNET, WINAPI, HttpOpenRequestW, + __in HINTERNET hConnect, + __in LPWSTR lpszVerb, + __in LPWSTR lpszObjectName, + __in LPWSTR lpszVersion, + __in LPWSTR lpszReferer, + __in LPWSTR *lplpszAcceptTypes, + __in DWORD dwFlags, + __in DWORD_PTR dwContext +); + +extern HOOKDEF(BOOL, WINAPI, HttpSendRequestA, + __in HINTERNET hRequest, + __in LPCTSTR lpszHeaders, + __in DWORD dwHeadersLength, + __in LPVOID lpOptional, + __in DWORD dwOptionalLength +); + +extern HOOKDEF(BOOL, WINAPI, HttpSendRequestW, + __in HINTERNET hRequest, + __in LPWSTR lpszHeaders, + __in DWORD dwHeadersLength, + __in LPVOID lpOptional, + __in DWORD dwOptionalLength +); + +extern HOOKDEF(BOOL, WINAPI, InternetReadFile, + _In_ HINTERNET hFile, + _Out_ LPVOID lpBuffer, + _In_ DWORD dwNumberOfBytesToRead, + _Out_ LPDWORD lpdwNumberOfBytesRead +); + +extern HOOKDEF(BOOL, WINAPI, InternetWriteFile, + _In_ HINTERNET hFile, + _In_ LPCVOID lpBuffer, + _In_ DWORD dwNumberOfBytesToWrite, + _Out_ LPDWORD lpdwNumberOfBytesWritten +); + +extern HOOKDEF(BOOL, WINAPI, InternetCloseHandle, + _In_ HINTERNET hInternet +); + +extern HOOKDEF(DNS_STATUS, WINAPI, DnsQuery_A, + __in PCSTR lpstrName, + __in WORD wType, + __in DWORD Options, + __inout_opt PVOID pExtra, + __out_opt PDNS_RECORD *ppQueryResultsSet, + __out_opt PVOID *pReserved +); + +extern HOOKDEF(DNS_STATUS, WINAPI, DnsQuery_UTF8, + __in LPBYTE lpstrName, + __in WORD wType, + __in DWORD Options, + __inout_opt PVOID pExtra, + __out_opt PDNS_RECORD *ppQueryResultsSet, + __out_opt PVOID *pReserved +); + +extern HOOKDEF(DNS_STATUS, WINAPI, DnsQuery_W, + __in PWSTR lpstrName, + __in WORD wType, + __in DWORD Options, + __inout_opt PVOID pExtra, + __out_opt PDNS_RECORD *ppQueryResultsSet, + __out_opt PVOID *pReserved +); + +extern HOOKDEF(int, WSAAPI, getaddrinfo, + _In_opt_ PCSTR pNodeName, + _In_opt_ PCSTR pServiceName, + _In_opt_ const ADDRINFOA *pHints, + _Out_ PADDRINFOA *ppResult +); + +extern HOOKDEF(int, WSAAPI, GetAddrInfoW, + _In_opt_ PCWSTR pNodeName, + _In_opt_ PCWSTR pServiceName, + _In_opt_ const ADDRINFOW *pHints, + _Out_ PADDRINFOW *ppResult +); + +// +// Service Hooks +// + +extern HOOKDEF(SC_HANDLE, WINAPI, OpenSCManagerA, + __in_opt LPCTSTR lpMachineName, + __in_opt LPCTSTR lpDatabaseName, + __in DWORD dwDesiredAccess +); + +extern HOOKDEF(SC_HANDLE, WINAPI, OpenSCManagerW, + __in_opt LPWSTR lpMachineName, + __in_opt LPWSTR lpDatabaseName, + __in DWORD dwDesiredAccess +); + +extern HOOKDEF(SC_HANDLE, WINAPI, CreateServiceA, + __in SC_HANDLE hSCManager, + __in LPCTSTR lpServiceName, + __in_opt LPCTSTR lpDisplayName, + __in DWORD dwDesiredAccess, + __in DWORD dwServiceType, + __in DWORD dwStartType, + __in DWORD dwErrorControl, + __in_opt LPCTSTR lpBinaryPathName, + __in_opt LPCTSTR lpLoadOrderGroup, + __out_opt LPDWORD lpdwTagId, + __in_opt LPCTSTR lpDependencies, + __in_opt LPCTSTR lpServiceStartName, + __in_opt LPCTSTR lpPassword +); + +extern HOOKDEF(SC_HANDLE, WINAPI, CreateServiceW, + __in SC_HANDLE hSCManager, + __in LPWSTR lpServiceName, + __in_opt LPWSTR lpDisplayName, + __in DWORD dwDesiredAccess, + __in DWORD dwServiceType, + __in DWORD dwStartType, + __in DWORD dwErrorControl, + __in_opt LPWSTR lpBinaryPathName, + __in_opt LPWSTR lpLoadOrderGroup, + __out_opt LPDWORD lpdwTagId, + __in_opt LPWSTR lpDependencies, + __in_opt LPWSTR lpServiceStartName, + __in_opt LPWSTR lpPassword +); + +extern HOOKDEF(SC_HANDLE, WINAPI, OpenServiceA, + __in SC_HANDLE hSCManager, + __in LPCTSTR lpServiceName, + __in DWORD dwDesiredAccess +); + +extern HOOKDEF(SC_HANDLE, WINAPI, OpenServiceW, + __in SC_HANDLE hSCManager, + __in LPWSTR lpServiceName, + __in DWORD dwDesiredAccess +); + +extern HOOKDEF(BOOL, WINAPI, StartServiceA, + __in SC_HANDLE hService, + __in DWORD dwNumServiceArgs, + __in_opt LPCTSTR *lpServiceArgVectors +); + +extern HOOKDEF(BOOL, WINAPI, StartServiceW, + __in SC_HANDLE hService, + __in DWORD dwNumServiceArgs, + __in_opt LPWSTR *lpServiceArgVectors +); + +extern HOOKDEF(BOOL, WINAPI, ControlService, + __in SC_HANDLE hService, + __in DWORD dwControl, + __out LPSERVICE_STATUS lpServiceStatus +); + +extern HOOKDEF(BOOL, WINAPI, DeleteService, + __in SC_HANDLE hService +); + +// +// Sleep Hooks +// + +extern HOOKDEF(NTSTATUS, WINAPI, NtDelayExecution, + __in BOOLEAN Alertable, + __in PLARGE_INTEGER DelayInterval +); + +extern HOOKDEF(void, WINAPI, GetLocalTime, + __out LPSYSTEMTIME lpSystemTime +); + +extern HOOKDEF(void, WINAPI, GetSystemTime, + __out LPSYSTEMTIME lpSystemTime +); + +extern HOOKDEF(DWORD, WINAPI, GetTickCount, + void +); + +extern HOOKDEF(NTSTATUS, WINAPI, NtQuerySystemTime, + _Out_ PLARGE_INTEGER SystemTime +); + +// +// Socket Hooks +// + +extern HOOKDEF(int, WINAPI, WSAStartup, + _In_ WORD wVersionRequested, + _Out_ LPWSADATA lpWSAData +); + +extern HOOKDEF(struct hostent *, WSAAPI, gethostbyname, + __in const char *name +); + +extern HOOKDEF(SOCKET, WSAAPI, socket, + __in int af, + __in int type, + __in int protocol +); + +extern HOOKDEF(int, WSAAPI, connect, + __in SOCKET s, + __in const struct sockaddr *name, + __in int namelen +); + +extern HOOKDEF(int, WSAAPI, send, + __in SOCKET s, + __in const char *buf, + __in int len, + __in int flags +); + +extern HOOKDEF(int, WSAAPI, sendto, + __in SOCKET s, + __in const char *buf, + __in int len, + __in int flags, + __in const struct sockaddr *to, + __in int tolen +); + +extern HOOKDEF(int, WSAAPI, recv, + __in SOCKET s, + __out char *buf, + __in int len, + __in int flags +); + +extern HOOKDEF(int, WSAAPI, recvfrom, + __in SOCKET s, + __out char *buf, + __in int len, + __in int flags, + __out struct sockaddr *from, + __inout_opt int *fromlen +); + +extern HOOKDEF(SOCKET, WSAAPI, accept, + __in SOCKET s, + __out struct sockaddr *addr, + __inout int *addrlen +); + +extern HOOKDEF(int, WSAAPI, bind, + __in SOCKET s, + __in const struct sockaddr *name, + __in int namelen +); + +extern HOOKDEF(int, WSAAPI, listen, + __in SOCKET s, + __in int backlog +); + +extern HOOKDEF(int, WSAAPI, select, + __in SOCKET s, + __inout fd_set *readfds, + __inout fd_set *writefds, + __inout fd_set *exceptfds, + __in const struct timeval *timeout +); + +extern HOOKDEF(int, WSAAPI, setsockopt, + __in SOCKET s, + __in int level, + __in int optname, + __in const char *optval, + __in int optlen +); + +extern HOOKDEF(int, WSAAPI, ioctlsocket, + __in SOCKET s, + __in long cmd, + __inout u_long *argp +); + +extern HOOKDEF(int, WSAAPI, closesocket, + __in SOCKET s +); + +extern HOOKDEF(int, WSAAPI, shutdown, + __in SOCKET s, + __in int how +); + +extern HOOKDEF(int, WSAAPI, WSARecv, + __in SOCKET s, + __inout LPWSABUF lpBuffers, + __in DWORD dwBufferCount, + __out LPDWORD lpNumberOfBytesRecvd, + __inout LPDWORD lpFlags, + __in LPWSAOVERLAPPED lpOverlapped, + __in LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine +); + +extern HOOKDEF(int, WSAAPI, WSARecvFrom, + __in SOCKET s, + __inout LPWSABUF lpBuffers, + __in DWORD dwBufferCount, + __out LPDWORD lpNumberOfBytesRecvd, + __inout LPDWORD lpFlags, + __out struct sockaddr *lpFrom, + __inout LPINT lpFromlen, + __in LPWSAOVERLAPPED lpOverlapped, + __in LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine +); + +extern HOOKDEF(int, WSAAPI, WSASend, + __in SOCKET s, + __in LPWSABUF lpBuffers, + __in DWORD dwBufferCount, + __out LPDWORD lpNumberOfBytesSent, + __in DWORD dwFlags, + __in LPWSAOVERLAPPED lpOverlapped, + __in LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine +); + +extern HOOKDEF(int, WSAAPI, WSASendTo, + __in SOCKET s, + __in LPWSABUF lpBuffers, + __in DWORD dwBufferCount, + __out LPDWORD lpNumberOfBytesSent, + __in DWORD dwFlags, + __in const struct sockaddr *lpTo, + __in int iToLen, + __in LPWSAOVERLAPPED lpOverlapped, + __in LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine +); + +extern HOOKDEF(SOCKET, WSAAPI, WSASocketA, + __in int af, + __in int type, + __in int protocol, + __in LPWSAPROTOCOL_INFO lpProtocolInfo, + __in GROUP g, + __in DWORD dwFlags +); + +extern HOOKDEF(SOCKET, WSAAPI, WSASocketW, + __in int af, + __in int type, + __in int protocol, + __in LPWSAPROTOCOL_INFO lpProtocolInfo, + __in GROUP g, + __in DWORD dwFlags +); + + +extern HOOKDEF(BOOL, PASCAL, ConnectEx, + _In_ SOCKET s, + _In_ const struct sockaddr *name, + _In_ int namelen, + _In_opt_ PVOID lpSendBuffer, + _In_ DWORD dwSendDataLength, + _Out_ LPDWORD lpdwBytesSent, + _In_ LPOVERLAPPED lpOverlapped +); + +extern HOOKDEF(BOOL, PASCAL, TransmitFile, + SOCKET hSocket, + HANDLE hFile, + DWORD nNumberOfBytesToWrite, + DWORD nNumberOfBytesPerSend, + LPOVERLAPPED lpOverlapped, + LPTRANSMIT_FILE_BUFFERS lpTransmitBuffers, + DWORD dwFlags +); + +// +// Special Hooks +// + +extern HOOKDEF2(NTSTATUS, WINAPI, LdrLoadDll, + __in_opt PWCHAR PathToFile, + __in_opt ULONG Flags, + __in PUNICODE_STRING ModuleFileName, + __out PHANDLE ModuleHandle +); + +extern HOOKDEF(NTSTATUS, WINAPI, ZwMapViewOfSection, + _In_ HANDLE SectionHandle, + _In_ HANDLE ProcessHandle, + __inout PVOID *BaseAddress, + _In_ ULONG_PTR ZeroBits, + _In_ SIZE_T CommitSize, + __inout PLARGE_INTEGER SectionOffset, + __inout PSIZE_T ViewSize, + __in UINT InheritDisposition, + __in ULONG AllocationType, + __in ULONG Win32Protect +); diff --git a/ignore.c b/ignore.c new file mode 100644 index 0000000..3e9e45a --- /dev/null +++ b/ignore.c @@ -0,0 +1,151 @@ +/* +Cuckoo Sandbox - Automated Malware Analysis +Copyright (C) 2010-2014 Cuckoo Sandbox Developers + +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 . +*/ + +#include +#include +#include "ntapi.h" +#include "ignore.h" +#include "misc.h" +#include "pipe.h" + +// +// Protected Processes +// + +static unsigned long g_pids[MAX_PROTECTED_PIDS]; +static unsigned long g_pid_count; + +void add_protected_pid(unsigned long pid) +{ + g_pids[g_pid_count++] = pid; +} + +int is_protected_pid(unsigned long pid) +{ + for (unsigned long i = 0; i < g_pid_count; i++) { + if(pid == g_pids[i]) { + return 1; + } + } + return 0; +} + +// +// Blacklist for Dumping Files +// + +#define S(s, f) {L##s, sizeof(s)-1, f} + +#define FLAG_NONE 0 +#define FLAG_BEGINS_WITH 1 + +static struct _ignored_file_t { + const wchar_t *unicode; + unsigned int length; + unsigned int flags; +} g_ignored_files[] = { + S("\\??\\PIPE\\lsarpc", FLAG_NONE), + S("\\??\\IDE#", FLAG_BEGINS_WITH), + S("\\??\\STORAGE#", FLAG_BEGINS_WITH), + S("\\??\\MountPointManager", FLAG_NONE), + S("\\??\\root#", FLAG_BEGINS_WITH), + S("\\Device\\", FLAG_BEGINS_WITH), +}; + +int is_ignored_file_unicode(const wchar_t *fname, int length) +{ + struct _ignored_file_t *f = g_ignored_files; + for (unsigned int i = 0; i < ARRAYSIZE(g_ignored_files); i++, f++) { + if(f->flags == FLAG_NONE && length == f->length && + !wcsnicmp(fname, f->unicode, length)) { + return 1; + } + else if(f->flags == FLAG_BEGINS_WITH && length >= f->length && + !wcsnicmp(fname, f->unicode, f->length)) { + return 1; + } + } + return 0; +} + +int is_ignored_file_objattr(const OBJECT_ATTRIBUTES *obj) +{ + return is_ignored_file_unicode(obj->ObjectName->Buffer, + obj->ObjectName->Length / sizeof(wchar_t)); +} + +static wchar_t *g_ignored_processpaths[] = { + L"C:\\WINDOWS\\system32\\dwwin.exe", + L"C:\\WINDOWS\\system32\\dumprep.exe", + L"C:\\WINDOWS\\system32\\drwtsn32.exe", +}; + +int is_ignored_process() +{ + wchar_t process_path[MAX_PATH]; + GetModuleFileNameW(NULL, process_path, ARRAYSIZE(process_path)); + + for (int i = 0; i < ARRAYSIZE(g_ignored_processpaths); i++) { + if(!wcsicmp(g_ignored_processpaths[i], process_path)) { + return 1; + } + } + return 0; +} + +// +// Whitelist for Return Addresses +// + +// for each high 20-bits of an address, there are two bits: +// - is this address ignored +// - is the ignored bit initialized yet? +static unsigned char retaddr[0x40000]; + +void init_ignored_retaddr() +{ + // send the address of the retaddr buffer to analyzer.py + pipe("RET_INIT:%d,%x", GetCurrentProcessId(), retaddr); +} + +/* +static void ret_get_flags(unsigned int addr, unsigned int *ignored, + unsigned int *initialized) +{ + unsigned int index = addr / 0x1000; + unsigned char info = retaddr[index / 4] >> ((index % 4) << 1); + // first bit defines whether the address is ignored + *ignored = info & 1; + // second bit defines whether the ignored bit has been initialized yet + *initialized = (info >> 1) & 1; +} + +static void ret_set_flags(unsigned int addr, unsigned int ignored) +{ + unsigned int index = addr / 0x1000; + // reset the original flags + retaddr[index / 4] &= ~(3 << (index % 4) << 1); + // set the new flags + retaddr[index / 4] |= (!!ignored + 2) << (index % 4) << 1; +} +*/ + +int is_ignored_retaddr(unsigned int addr) +{ + return 0; +} diff --git a/ignore.h b/ignore.h new file mode 100644 index 0000000..b2f6575 --- /dev/null +++ b/ignore.h @@ -0,0 +1,35 @@ +/* +Cuckoo Sandbox - Automated Malware Analysis +Copyright (C) 2010-2014 Cuckoo Sandbox Developers + +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 . +*/ + +#define MAX_PROTECTED_PIDS 32 + +#include "ntapi.h" + +void add_protected_pid(unsigned long pid); +int is_protected_pid(unsigned long pid); + +int is_ignored_file_ascii(const char *fname, int length); +int is_ignored_file_unicode(const wchar_t *fname, int length); +int is_ignored_file_objattr(const OBJECT_ATTRIBUTES *obj); + +void ignore_file_prepend_stuff(const OBJECT_ATTRIBUTES *obj, + wchar_t **str, unsigned int *length); + +int is_ignored_process(); + +int is_ignored_retaddr(unsigned int addr); diff --git a/install.sh b/install.sh new file mode 100644 index 0000000..ab1c0c9 --- /dev/null +++ b/install.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +# directory in which the main repository of Cuckoo Sandbox can be found +if [ -z "$CUCKOODIR" ]; then + CUCKOODIR=../cuckoo +fi + +# target filename - in case of testing with custom dll's one may wish to +# use a different filename, such as "cuckoomon_bson.dll" +if [ -z "$CUCKOOMON" ]; then + CUCKOOMON=cuckoomon.dll +fi + +make && cp cuckoomon.dll "$CUCKOODIR/analyzer/windows/dll/$CUCKOOMON" diff --git a/log.c b/log.c new file mode 100644 index 0000000..fe06332 --- /dev/null +++ b/log.c @@ -0,0 +1,563 @@ +/* +Cuckoo Sandbox - Automated Malware Analysis +Copyright (C) 2010-2014 Cuckoo Sandbox Developers + +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 . +*/ + +#include +#include +#include +#include +#include +#include +#include "ntapi.h" +#include "misc.h" +#include "utf8.h" +#include "log.h" +#include "bson.h" + +// the size of the logging buffer +#define BUFFERSIZE 1024 * 1024 +#define BUFFER_LOG_MAX 256 + +static CRITICAL_SECTION g_mutex; +static int g_sock; +static unsigned int g_starttick; + +static char g_buffer[BUFFERSIZE]; +static int g_idx; + +// current to-be-logged API call +static bson g_bson[1]; +static char g_istr[4]; + +static char logtbl_explained[256] = {0}; + +// +// Log API +// + +void log_flush() +{ + if(g_idx != 0) { + int written; + if(g_sock == INVALID_SOCKET) { + written = fwrite(g_buffer, 1, g_idx, stderr); + } + else { + written = send(g_sock, g_buffer, g_idx, 0); + } + + // TODO add more error checking + + // if this call didn't write the entire buffer, then we have to move + // around some stuff in the buffer + if(written < g_idx) { + memcpy(g_buffer, g_buffer + written, g_idx - written); + } + + // subtract the amount of written bytes from the index + g_idx -= written; + } +} + +/* +static void log_raw(const char *buf, size_t length) { + for (int i=0; i= BUFFERSIZE -1) { + log_flush(); + } + } +} +*/ + +static void log_raw_direct(const char *buf, size_t length) { + int sent = 0; + int r; + while (sent < length) { + r = send(g_sock, buf+sent, length-sent, 0); + if (r == -1) { + fprintf(stderr, "send returned -1.\n"); + return; + } + sent += r; + } +} + +static void debug_message(const char *msg) { + bson b[1]; + bson_init( b ); + bson_append_string( b, "type", "debug" ); + bson_append_string( b, "msg", msg ); + bson_finish( b ); + log_raw_direct(bson_data( b ), bson_size( b )); + bson_destroy( b ); + // log_flush(); +} + +/* +static void log_int8(char value) +{ + bson_append_int( g_bson, g_istr, value ); +} + +static void log_int16(short value) +{ + bson_append_int( g_bson, g_istr, value ); +} +*/ + +static void log_int32(int value) +{ + bson_append_int( g_bson, g_istr, value ); +} + +static void log_string(const char *str, int length) +{ + if (str == NULL) { + bson_append_string_n( g_bson, g_istr, "", 0 ); + return; + } + int ret; + char * utf8s = utf8_string(str, length); + int utf8len = * (int *) utf8s; + ret = bson_append_binary( g_bson, g_istr, BSON_BIN_BINARY, utf8s+4, utf8len ); + if (ret == BSON_ERROR) { + char tmp[64]; + snprintf(tmp, 64, "dbg bson err string %x utf8len %d", g_bson->err, utf8len); + debug_message(tmp); + } + free(utf8s); +} + +static void log_wstring(const wchar_t *str, int length) +{ + if (str == NULL) { + bson_append_string_n( g_bson, g_istr, "", 0 ); + return; + } + int ret; + char * utf8s = utf8_wstring(str, length); + int utf8len = * (int *) utf8s; + ret = bson_append_binary( g_bson, g_istr, BSON_BIN_BINARY, utf8s+4, utf8len ); + if (ret == BSON_ERROR) { + char tmp[64]; + snprintf(tmp, 64, "dbg bson err wstring %x utf8len %d", g_bson->err, utf8len); + debug_message(tmp); + } + free(utf8s); +} + +static void log_argv(int argc, const char ** argv) { + bson_append_start_array( g_bson, g_istr ); + + for (int i=0; i= '2' && *fmt <= '9' ? *fmt++ - '0' : 1; + + // the next format specifier + key = *fmt++; + } + + pname = va_arg(args, const char *); + snprintf(g_istr, 4, "%u", argnum); + argnum++; + + //on certain formats, we need to tell cuckoo about them for nicer display / matching + if (key == 'p' || key == 'P') { + bson_append_start_array( b, g_istr ); + bson_append_string( b, "0", pname ); + bson_append_string( b, "1", "p" ); + bson_append_finish_array( b ); + } else { + bson_append_string( b, g_istr, pname ); + } + + //now ignore the values + if(key == 's') { + (void) va_arg(args, const char *); + } + else if(key == 'S') { + (void) va_arg(args, int); + (void) va_arg(args, const char *); + } + else if(key == 'u') { + (void) va_arg(args, const wchar_t *); + } + else if(key == 'U') { + (void) va_arg(args, int); + (void) va_arg(args, const wchar_t *); + } + else if(key == 'b') { + (void) va_arg(args, size_t); + (void) va_arg(args, const char *); + } + else if(key == 'B') { + (void) va_arg(args, size_t *); + (void) va_arg(args, const char *); + } + else if(key == 'i') { + (void) va_arg(args, int); + } + else if(key == 'l' || key == 'p') { + (void) va_arg(args, long); + } + else if(key == 'L' || key == 'P') { + (void) va_arg(args, long *); + } + else if(key == 'o') { + (void) va_arg(args, UNICODE_STRING *); + } + else if(key == 'O') { + (void) va_arg(args, OBJECT_ATTRIBUTES *); + } + else if(key == 'a') { + (void) va_arg(args, int); + (void) va_arg(args, const char **); + } + else if(key == 'A') { + (void) va_arg(args, int); + (void) va_arg(args, const wchar_t **); + } + else if(key == 'r' || key == 'R') { + (void) va_arg(args, unsigned long); + (void) va_arg(args, unsigned long); + (void) va_arg(args, unsigned char *); + } + + } + bson_append_finish_array( b ); + bson_finish( b ); + log_raw_direct(bson_data( b ), bson_size( b )); + bson_destroy( b ); + // log_flush(); + } + + va_end(args); + fmt = fmtbak; + va_start(args, fmt); + count = 1; key = 0; argnum = 2; + + bson_init( g_bson ); + bson_append_int( g_bson, "I", index ); + bson_append_int( g_bson, "T", GetCurrentThreadId() ); + bson_append_int( g_bson, "t", GetTickCount() - g_starttick ); + bson_append_start_array( g_bson, "args" ); + bson_append_int( g_bson, "0", is_success ); + bson_append_int( g_bson, "1", return_value ); + + while (--count != 0 || *fmt != 0) { + + // we have to find the next format specifier + if(count == 0) { + // end of format + if(*fmt == 0) break; + + // set the count, possibly with a repeated format specifier + count = *fmt >= '2' && *fmt <= '9' ? *fmt++ - '0' : 1; + + // the next format specifier + key = *fmt++; + } + + // pop the key and omit it + (void) va_arg(args, const char *); + snprintf(g_istr, 4, "%u", argnum); + argnum++; + + // log the value + if(key == 's') { + const char *s = va_arg(args, const char *); + if(s == NULL) s = ""; + log_string(s, -1); + } + else if(key == 'S') { + int len = va_arg(args, int); + const char *s = va_arg(args, const char *); + if(s == NULL) { s = ""; len = 0; } + log_string(s, len); + } + else if(key == 'u') { + const wchar_t *s = va_arg(args, const wchar_t *); + if(s == NULL) s = L""; + log_wstring(s, -1); + } + else if(key == 'U') { + int len = va_arg(args, int); + const wchar_t *s = va_arg(args, const wchar_t *); + if(s == NULL) { s = L""; len = 0; } + log_wstring(s, len); + } + else if(key == 'b') { + size_t len = va_arg(args, size_t); + const char *s = va_arg(args, const char *); + log_buffer(s, len); + } + else if(key == 'B') { + size_t *len = va_arg(args, size_t *); + const char *s = va_arg(args, const char *); + log_buffer(s, *len); + } + else if(key == 'i') { + int value = va_arg(args, int); + log_int32(value); + } + else if(key == 'l' || key == 'p') { + long value = va_arg(args, long); + log_int32(value); + } + else if(key == 'L' || key == 'P') { + long *ptr = va_arg(args, long *); + log_int32(ptr != NULL ? *ptr : 0); + } + else if(key == 'o') { + UNICODE_STRING *str = va_arg(args, UNICODE_STRING *); + if(str == NULL) { + log_string("", 0); + } + else { + log_wstring(str->Buffer, str->Length / sizeof(wchar_t)); + } + } + else if(key == 'O') { + OBJECT_ATTRIBUTES *obj = va_arg(args, OBJECT_ATTRIBUTES *); + if(obj == NULL || obj->ObjectName == NULL) { + log_string("", 0); + } + else { + wchar_t path[MAX_PATH_PLUS_TOLERANCE]; int length; + + length = path_from_object_attributes( + obj, path, MAX_PATH_PLUS_TOLERANCE); + + length = ensure_absolute_path(path, path, length); + + log_wstring(path, length); + } + } + else if(key == 'a') { + int argc = va_arg(args, int); + const char **argv = va_arg(args, const char **); + log_argv(argc, argv); + } + else if(key == 'A') { + int argc = va_arg(args, int); + const wchar_t **argv = va_arg(args, const wchar_t **); + log_wargv(argc, argv); + } + else if(key == 'r' || key == 'R') { + unsigned long type = va_arg(args, unsigned long); + unsigned long size = va_arg(args, unsigned long); + unsigned char *data = va_arg(args, unsigned char *); + + // bson_append_start_object( g_bson, g_istr ); + // bson_append_int( g_bson, "type", type ); + + // strncpy(g_istr, "val", 4); + if(type == REG_NONE) { + log_string("", 0); + } + else if(type == REG_DWORD || type == REG_DWORD_LITTLE_ENDIAN) { + unsigned int value = *(unsigned int *) data; + log_int32(value); + } + else if(type == REG_DWORD_BIG_ENDIAN) { + unsigned int value = *(unsigned int *) data; + log_int32(htonl(value)); + } + else if(type == REG_EXPAND_SZ || type == REG_SZ) { + + if(data == NULL) { + bson_append_binary(g_bson, g_istr, BSON_BIN_BINARY, + (const char *) data, 0); + } + // ascii strings + else if(key == 'r') { + bson_append_binary(g_bson, g_istr, BSON_BIN_BINARY, + (const char *) data, size); + } + // unicode strings + else { + bson_append_binary(g_bson, g_istr, BSON_BIN_BINARY, + (const char *) data, size); + } + } else { + bson_append_binary(g_bson, g_istr, BSON_BIN_BINARY, + (const char *) data, 0); + } + + // bson_append_finish_object( g_bson ); + } + } + + va_end(args); + + bson_append_finish_array( g_bson ); + bson_finish( g_bson ); + // if (bson_size( g_bson ) > BUFFERSIZE) { + // //DBGWARN, ignoring bson obj + // } else { + log_raw_direct(bson_data( g_bson ), bson_size( g_bson )); + // } + + bson_destroy( g_bson ); + // log_flush(); + LeaveCriticalSection(&g_mutex); +} + +void announce_netlog() +{ + char protoname[32]; + strcpy(protoname, "BSON\n"); + //sprintf(protoname+5, "logs/%lu.bson\n", GetCurrentProcessId()); + log_raw_direct(protoname, strlen(protoname)); +} + +void log_new_process() +{ + wchar_t module_path[MAX_PATH]; + GetModuleFileNameW(NULL, module_path, ARRAYSIZE(module_path)); + + g_starttick = GetTickCount(); + + FILETIME st; + GetSystemTimeAsFileTime(&st); + + loq(0, "__process__", 1, 0, "llllu", "TimeLow", st.dwLowDateTime, + "TimeHigh", st.dwHighDateTime, + "ProcessIdentifier", GetCurrentProcessId(), + "ParentProcessIdentifier", parent_process_id(), + "ModulePath", module_path); +} + +void log_new_thread() +{ + loq(1, "__thread__", 1, 0, "l", "ProcessIdentifier", GetCurrentProcessId()); +} + +void log_init(unsigned int ip, unsigned short port, int debug) +{ + InitializeCriticalSection(&g_mutex); + + if(debug != 0) { + g_sock = INVALID_SOCKET; + } + else { + WSADATA wsa; + WSAStartup(MAKEWORD(2, 2), &wsa); + + g_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + + struct sockaddr_in addr = { + .sin_family = AF_INET, + .sin_addr.s_addr = ip, + .sin_port = htons(port), + }; + + connect(g_sock, (struct sockaddr *) &addr, sizeof(addr)); + } + + announce_netlog(); + log_new_process(); + log_new_thread(); + // flushing here so host can create files / keep timestamps + // log_flush(); +} + +void log_free() +{ + DeleteCriticalSection(&g_mutex); + log_flush(); + if(g_sock != INVALID_SOCKET) { + closesocket(g_sock); + } +} + +int log_resolve_index(const char *funcname, int index) +{ + for (int i = 0; logtbl[i][0] != NULL; i++) { + if(!strcmp(funcname, logtbl[i][0])) { + if(index != 0) { + index--; + } + else { + return i; + } + } + } + return -1; +} diff --git a/log.h b/log.h new file mode 100644 index 0000000..df320b1 --- /dev/null +++ b/log.h @@ -0,0 +1,125 @@ +/* +Cuckoo Sandbox - Automated Malware Analysis +Copyright (C) 2010-2014 Cuckoo Sandbox Developers + +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 . +*/ + +// +// Log API +// +// The Log takes a format string and parses the extra arguments accordingly +// +// The following Format Specifiers are available: +// s -> (char *) -> zero-terminated string +// S -> (int, char *) -> string with length +// u -> (wchar_t *) -> zero-terminated unicode string +// U -> (int, wchar_t *) -> unicode string with length +// b -> (int, void *) -> memory with a given size (alias for S) +// B -> (int *, void *) -> memory with a given size (value at integer) +// i -> (int) -> integer +// l -> (long) -> long integer +// L -> (long *) -> pointer to a long integer +// p -> (void *) -> pointer (alias for l) +// P -> (void **) -> pointer to a handle (alias for L) +// o -> (UNICODE_STRING *) -> unicode string +// O -> (OBJECT_ATTRIBUTES *) -> wrapper around a unicode string +// a -> (int, char **) -> array of string +// A -> (int, wchar_t **) -> array of unicode strings +// r -> (Type, int, char *) type as defined for Registry operations +// R -> (Type, int, wchar_t *) type as defined for Registry operations +// type r is for ascii functions, R for unicode (Nt* are unicode) +// +// Each of these format specifiers are prefixed with a zero-terminated key +// value, e.g. +// +// log("s", "key", "value"); +// +// A format specifier can also be repeated for n times (with n in the range +// 2..9), e.g. +// +// loq("sss", "key1", "value", "key2", "value2", "key3", "value3"); +// loq("3s", "key1", "value", "key2", "value2", "key3", "value3"); +// + +void loq(int index, const char *name, int is_success, int return_value, const char *fmt, ...); +void log_new_process(); +void log_new_thread(); + +void log_init(unsigned int ip, unsigned short port, int debug); +void log_flush(); +void log_free(); + +int log_resolve_index(const char *funcname, int index); +extern const char *logtbl[][2]; + +#define LOQ(fmt, ...) { static int _index; if(_index == 0) \ + _index = log_resolve_index(&__FUNCTION__[4], 0); loq(_index, \ + &__FUNCTION__[4], is_success(ret), (int) ret, fmt, ##__VA_ARGS__); } + +#define LOQ2(fmt, ...) { static int _index; if(_index == 0) \ + _index = log_resolve_index(&__FUNCTION__[4], 1); loq(_index, \ + &__FUNCTION__[4], is_success(ret), (int) ret, fmt, ##__VA_ARGS__); } + +#define LOQ3(fmt, ...) { static int _index; if(_index == 0) \ + _index = log_resolve_index(&__FUNCTION__[4], 2); loq(_index, \ + &__FUNCTION__[4], is_success(ret), (int) ret, fmt, ##__VA_ARGS__); } + +#define LOQspecial(fmt, ...) { static int _index; if(_index == 0) \ + _index = log_resolve_index(&__FUNCTION__[5], 0); loq(_index, \ + &__FUNCTION__[5], is_success(ret), (int) ret, fmt, ##__VA_ARGS__); } + +#define IS_SUCCESS_NTSTATUS() int is_success(NTSTATUS ret) { \ + return NT_SUCCESS(ret); } +#define IS_SUCCESS_BOOL() int is_success(BOOL ret) { \ + return ret != FALSE; } +#define IS_SUCCESS_HHOOK() int is_success(HHOOK ret) { \ + return ret != NULL; } +#define IS_SUCCESS_HINTERNET() int is_success(HINTERNET ret) { \ + return ret != NULL; } +#define IS_SUCCESS_HRESULT() int is_success(HRESULT ret) { \ + return ret == S_OK; } +#define IS_SUCCESS_HANDLE() int is_success(HANDLE ret) { \ + return ret != NULL; } +#define IS_SUCCESS_HANDLE2() int is_success(HANDLE ret) { \ + return ret != NULL && ret != INVALID_HANDLE_VALUE; } +#define IS_SUCCESS_VOID() int is_success(int ret) { return TRUE; } +#define IS_SUCCESS_LONGREG() int is_success(LONG ret) { \ + return ret == ERROR_SUCCESS; } +#define IS_SUCCESS_SCHANDLE() int is_success(SC_HANDLE ret) { \ + return ret != NULL; } +#define IS_SUCCESS_DWORDTHREAD() int is_success(DWORD ret) { \ + return ret != (DWORD) -1; } +#define IS_SUCCESS_HWND() int is_success(HWND ret) { \ + return ret != NULL; } +#define IS_SUCCESS_ZERO() int is_success(int ret) { \ + return ret == 0; } +#define IS_SUCCESS_INTM1() int is_success(int ret) { \ + return ret != -1; } + +#define ENSURE_DWORD(param) \ + DWORD _##param = 0; if(param == NULL) param = &_##param + +#define ENSURE_ULONG(param) \ + ULONG _##param = 0; if(param == NULL) param = &_##param +#define ENSURE_ULONG_ZERO(param) \ + ENSURE_ULONG(param); else *param = 0 + +#define ENSURE_SIZET(param) \ + ULONG _##param = 0; if(param == NULL) param = &_##param +#define ENSURE_SIZET_ZERO(param) \ + ENSURE_ULONG(param); else *param = 0 + +#define ENSURE_CLIENT_ID(param) \ + CLIENT_ID _##param = {}; if(param == NULL) param = &_##param diff --git a/logtbl.py b/logtbl.py new file mode 100644 index 0000000..076553d --- /dev/null +++ b/logtbl.py @@ -0,0 +1,200 @@ +# Copyright (C) 2010-2014 Cuckoo Sandbox Developers. +# This file is part of Cuckoo Sandbox - http://www.cuckoosandbox.org +# See the file 'docs/LICENSE' for copying permission. + +"""Table for all hook logging statements. + +This table is not automatically generated at the moment, but kept up-to-date +by hand. + +""" +table = [ + ("__process__", "__init__", ("",)), + ("__thread__", "__init__", ("",)), + ("NtDeleteFile", "filesystem", ("O", "FileName")), + ("CreateDirectoryW", "filesystem", ("u", "DirectoryName")), + ("CreateDirectoryExW", "filesystem", ("u", "DirectoryName")), + ("RemoveDirectoryA", "filesystem", ("s", "DirectoryName")), + ("RemoveDirectoryW", "filesystem", ("u", "DirectoryName")), + ("FindFirstFileExA", "filesystem", ("s", "FileName")), + ("FindFirstFileExW", "filesystem", ("u", "FileName")), + ("DeleteFileA", "filesystem", ("s", "FileName")), + ("DeleteFileW", "filesystem", ("u", "FileName")), + ("UnhookWindowsHookEx", "hooking", ("p", "HookHandle")), + ("LdrGetDllHandle", "system", ("oP", "FileName", "ModuleHandle")), + ("ExitWindowsEx", "system", ("ll", "Flags", "Reason")), + ("IsDebuggerPresent", "system", ("",)), + ("LookupPrivilegeValueW", "system", ("uu", "SystemName", "PrivilegeName")), + ("NtClose", "system", ("p", "Handle")), + ("URLDownloadToFileW", "network", ("uu", "URL", "FileName")), + ("InternetReadFile", "network", ("pB", "InternetHandle", "Buffer")), + ("InternetWriteFile", "network", ("pB", "InternetHandle", "Buffer")), + ("InternetCloseHandle", "network", ("p", "InternetHandle")), + ("DnsQuery_A", "network", ("sil", "Name", "Type", "Options")), + ("DnsQuery_UTF8", "network", ("sil", "Name", "Type", "Options")), + ("DnsQuery_W", "network", ("uil", "Name", "Type", "Options")), + ("getaddrinfo", "network", ("ss", "NodeName", "ServiceName")), + ("GetAddrInfoW", "network", ("uu", "NodeName", "ServiceName")), + ("NtTerminateProcess", "process", ("pl", "ProcessHandle", "ExitCode")), + ("ExitProcess", "process", ("l", "ExitCode")), + ("system", "process", ("s", "Command")), + ("RegOpenKeyExA", "registry", ("psP", "Registry", "SubKey", "Handle")), + ("RegOpenKeyExW", "registry", ("puP", "Registry", "SubKey", "Handle")), + ("RegDeleteKeyA", "registry", ("ps", "Handle", "SubKey")), + ("RegDeleteKeyW", "registry", ("pu", "Handle", "SubKey")), + ("RegEnumKeyW", "registry", ("plu", "Handle", "Index", "Name")), + ("RegDeleteValueA", "registry", ("ps", "Handle", "ValueName")), + ("RegDeleteValueW", "registry", ("pu", "Handle", "ValueName")), + ("RegCloseKey", "registry", ("p", "Handle")), + ("NtRenameKey", "registry", ("po", "KeyHandle", "NewName")), + ("NtEnumerateKey", "registry", ("pl", "KeyHandle", "Index")), + ("NtDeleteKey", "registry", ("p", "KeyHandle")), + ("NtDeleteValueKey", "registry", ("po", "KeyHandle", "ValueName")), + ("NtLoadKey", "registry", ("OO", "TargetKey", "SourceFile")), + ("NtSaveKey", "registry", ("pp", "KeyHandle", "FileHandle")), + ("ControlService", "services", ("pl", "ServiceHandle", "ControlCode")), + ("DeleteService", "services", ("p", "ServiceHandle")), + ("NtDelayExecution", "system", ("ls", "Milliseconds", "Status")), + ("NtDelayExecution", "system", ("l", "Milliseconds")), + ("WSAStartup", "socket", ("p", "VersionRequested")), + ("gethostbyname", "socket", ("s", "Name")), + ("socket", "socket", ("lll", "af", "type", "protocol")), + ("connect", "socket", ("p", "socket")), + ("send", "socket", ("pb", "socket", "buffer")), + ("sendto", "socket", ("pb", "socket", "buffer")), + ("recv", "socket", ("pb", "socket", "buffer")), + ("recvfrom", "socket", ("pb", "socket", "buffer")), + ("accept", "socket", ("pp", "socket", "ClientSocket")), + ("bind", "socket", ("psl", "socket", "ip", "port")), + ("bind", "socket", ("p", "socket")), + ("setsockopt", "socket", ("pllb", "socket", "level", "optname", "optval")), + ("listen", "socket", ("p", "socket")), + ("select", "socket", ("p", "socket")), + ("ioctlsocket", "socket", ("pl", "socket", "command")), + ("closesocket", "socket", ("p", "socket")), + ("shutdown", "socket", ("pl", "socket", "how")), + ("WSARecv", "socket", ("p", "socket")), + ("WSARecvFrom", "socket", ("p", "socket")), + ("WSASend", "socket", ("p", "Socket")), + ("WSASendTo", "socket", ("p", "Socket")), + ("WSASocketA", "socket", ("lll", "af", "type", "protocol")), + ("WSASocketW", "socket", ("lll", "af", "type", "protocol")), + ("ConnectEx", "socket", ("pB", "socket", "SendBuffer")), + ("NtOpenMutant", "synchronization", ("PO", "Handle", "MutexName")), + ("NtGetContextThread", "threading", ("p", "ThreadHandle")), + ("NtSetContextThread", "threading", ("p", "ThreadHandle")), + ("NtResumeThread", "threading", ("pL", "ThreadHandle", "SuspendCount")), + ("NtTerminateThread", "threading", ("pl", "ThreadHandle", "ExitStatus")), + ("ExitThread", "threading", ("l", "ExitCode")), + ("FindWindowA", "windows", ("ss", "ClassName", "WindowName")), + ("FindWindowW", "windows", ("uu", "ClassName", "WindowName")), + ("FindWindowExA", "windows", ("ls", "ClassName", "WindowName")), + ("FindWindowExA", "windows", ("ss", "ClassName", "WindowName")), + ("FindWindowExW", "windows", ("lu", "ClassName", "WindowName")), + ("FindWindowExW", "windows", ("uu", "ClassName", "WindowName")), + ("NtCreateFile", "filesystem", ("PpOll", "FileHandle", "DesiredAccess", "FileName", "CreateDisposition", "ShareAccess")), + ("NtOpenFile", "filesystem", ("PpOl", "FileHandle", "DesiredAccess", "FileName", "ShareAccess")), + ("NtReadFile", "filesystem", ("pb", "FileHandle", "Buffer")), + ("NtWriteFile", "filesystem", ("pb", "FileHandle", "Buffer")), + ("NtDeviceIoControlFile", "filesystem", ("pbb", "FileHandle", "InputBuffer", "OutputBuffer")), + ("NtQueryDirectoryFile", "filesystem", ("pbo", "FileHandle", "FileInformation", "FileName")), + ("NtQueryInformationFile", "filesystem", ("pb", "FileHandle", "FileInformation")), + ("NtSetInformationFile", "filesystem", ("pb", "FileHandle", "FileInformation")), + ("NtOpenDirectoryObject", "filesystem", ("PlO", "DirectoryHandle", "DesiredAccess", "ObjectAttributes")), + ("NtCreateDirectoryObject", "filesystem", ("PlO", "DirectoryHandle", "DesiredAccess", "ObjectAttributes")), + ("MoveFileWithProgressW", "filesystem", ("uu", "ExistingFileName", "NewFileName")), + ("CopyFileA", "filesystem", ("ss", "ExistingFileName", "NewFileName")), + ("CopyFileW", "filesystem", ("uu", "ExistingFileName", "NewFileName")), + ("CopyFileExW", "filesystem", ("uul", "ExistingFileName", "NewFileName", "CopyFlags")), + ("SetWindowsHookExA", "system", ("lppl", "HookIdentifier", "ProcedureAddress", "ModuleAddress", "ThreadId")), + ("SetWindowsHookExW", "system", ("lppl", "HookIdentifier", "ProcedureAddress", "ModuleAddress", "ThreadId")), + ("LdrLoadDll", "system", ("loP", "Flags", "FileName", "BaseAddress")), + ("LdrGetProcedureAddress", "system", ("pSlP", "ModuleHandle", "FunctionName", "Ordinal", "FunctionAddress")), + ("DeviceIoControl", "device", ("plbb", "DeviceHandle", "IoControlCode", "InBuffer", "OutBuffer")), + ("WriteConsoleA", "system", ("pS", "ConsoleHandle", "Buffer")), + ("WriteConsoleW", "system", ("pU", "ConsoleHandle", "Buffer")), + ("InternetOpenA", "network", ("spssp", "Agent", "AccessType", "ProxyName", "ProxyBypass", "Flags")), + ("InternetOpenW", "network", ("upuup", "Agent", "AccessType", "ProxyName", "ProxyBypass", "Flags")), + ("InternetConnectA", "network", ("pslsslp", "InternetHandle", "ServerName", "ServerPort", "Username", "Password", "Service", "Flags")), + ("InternetConnectW", "network", ("puluulp", "InternetHandle", "ServerName", "ServerPort", "Username", "Password", "Service", "Flags")), + ("InternetOpenUrlA", "network", ("psSp", "ConnectionHandle", "URL", "Headers", "Flags")), + ("InternetOpenUrlW", "network", ("puUp", "ConnectionHandle", "URL", "Headers", "Flags")), + ("HttpOpenRequestA", "network", ("psl", "InternetHandle", "Path", "Flags")), + ("HttpOpenRequestW", "network", ("pul", "InternetHandle", "Path", "Flags")), + ("HttpSendRequestA", "network", ("pSb", "RequestHandle", "Headers", "PostData")), + ("HttpSendRequestW", "network", ("pUb", "RequestHandle", "Headers", "PostData")), + ("NtCreateProcess", "process", ("PpO", "ProcessHandle", "DesiredAccess", "FileName")), + ("NtCreateProcessEx", "process", ("PpO", "ProcessHandle", "DesiredAccess", "FileName")), + ("NtCreateUserProcess", "process", ("PPppOOoo", "ProcessHandle", "ThreadHandle", "ProcessDesiredAccess", "ThreadDesiredAccess", "ProcessFileName", "ThreadName", "ImagePathName", "CommandLine")), + ("NtOpenProcess", "process", ("ppp", "ProcessHandle", "DesiredAccess", "ProcessIdentifier")), + ("NtOpenProcess", "process", ("PpP", "ProcessHandle", "DesiredAccess", "ProcessIdentifier")), + ("NtCreateSection", "process", ("PpOp", "SectionHandle", "DesiredAccess", "ObjectAttributes", "FileHandle")), + ("NtMakeTemporaryObject", "process", ("p", "ObjectHandle")), + ("NtMakePermanentObject", "process", ("p", "ObjectHandle")), + ("NtOpenSection", "process", ("PpO", "SectionHandle", "DesiredAccess", "ObjectAttributes")), + ("CreateProcessInternalW", "process", ("uupllpp", "ApplicationName", "CommandLine", "CreationFlags", "ProcessId", "ThreadId", "ProcessHandle", "ThreadHandle")), + ("ShellExecuteExW", "process", ("2ul", "FilePath", "Parameters", "Show")), + ("NtAllocateVirtualMemory", "process", ("pPPp", "ProcessHandle", "BaseAddress", "RegionSize", "Protection")), + ("NtReadVirtualMemory", "process", ("2pB", "ProcessHandle", "BaseAddress", "Buffer")), + ("ReadProcessMemory", "process", ("ppB", "ProcessHandle", "BaseAddress", "Buffer")), + ("NtWriteVirtualMemory", "process", ("2pB", "ProcessHandle", "BaseAddress", "Buffer")), + ("WriteProcessMemory", "process", ("ppB", "ProcessHandle", "BaseAddress", "Buffer")), + ("NtProtectVirtualMemory", "process", ("pPPpP", "ProcessHandle", "BaseAddress", "NumberOfBytesProtected", "NewAccessProtection", "OldAccessProtection")), + ("VirtualProtectEx", "process", ("pppp", "ProcessHandle", "Address", "Size", "Protection")), + ("NtFreeVirtualMemory", "process", ("pPPp", "ProcessHandle", "BaseAddress", "RegionSize", "FreeType")), + ("VirtualFreeEx", "process", ("pppl", "ProcessHandle", "Address", "Size", "FreeType")), + ("RegCreateKeyExA", "registry", ("psslP", "Registry", "SubKey", "Class", "Access", "Handle")), + ("RegCreateKeyExW", "registry", ("puulP", "Registry", "SubKey", "Class", "Access", "Handle")), + ("RegEnumKeyExA", "registry", ("plss", "Handle", "Index", "Name", "Class")), + ("RegEnumKeyExW", "registry", ("pluu", "Handle", "Index", "Name", "Class")), + ("RegEnumValueA", "registry", ("plsr", "Handle", "Index", "ValueName", "Data")), + ("RegEnumValueA", "registry", ("plsLL", "Handle", "Index", "ValueName", "Type", "DataLength")), + ("RegEnumValueW", "registry", ("pluR", "Handle", "Index", "ValueName", "Data")), + ("RegEnumValueW", "registry", ("pluLL", "Handle", "Index", "ValueName", "Type", "DataLength")), + ("RegSetValueExA", "registry", ("pslr", "Handle", "ValueName", "Type", "Buffer")), + ("RegSetValueExA", "registry", ("psl", "Handle", "ValueName", "Type")), + ("RegSetValueExW", "registry", ("pulR", "Handle", "ValueName", "Type", "Buffer")), + ("RegSetValueExW", "registry", ("pul", "Handle", "ValueName", "Type")), + ("RegQueryValueExA", "registry", ("psr", "Handle", "ValueName", "Data")), + ("RegQueryValueExA", "registry", ("psLL", "Handle", "ValueName", "Type", "DataLength")), + ("RegQueryValueExW", "registry", ("puR", "Handle", "ValueName", "Data")), + ("RegQueryValueExW", "registry", ("puLL", "Handle", "ValueName", "Type", "DataLength")), + ("RegQueryInfoKeyA", "registry", ("pS6L", "KeyHandle", "Class", "SubKeyCount", "MaxSubKeyLength", "MaxClassLength", "ValueCount", "MaxValueNameLength", "MaxValueLength")), + ("RegQueryInfoKeyW", "registry", ("pU6L", "KeyHandle", "Class", "SubKeyCount", "MaxSubKeyLength", "MaxClassLength", "ValueCount", "MaxValueNameLength", "MaxValueLength")), + ("NtCreateKey", "registry", ("PlOo", "KeyHandle", "DesiredAccess", "ObjectAttributes", "Class")), + ("NtOpenKey", "registry", ("PlO", "KeyHandle", "DesiredAccess", "ObjectAttributes")), + ("NtOpenKeyEx", "registry", ("PlO", "KeyHandle", "DesiredAccess", "ObjectAttributes")), + ("NtReplaceKey", "registry", ("pOO", "KeyHandle", "NewHiveFileName", "BackupHiveFileName")), + ("NtEnumerateValueKey", "registry", ("pll", "KeyHandle", "Index", "KeyValueInformationClass")), + ("NtSetValueKey", "registry", ("polR", "KeyHandle", "ValueName", "Type", "Buffer")), + ("NtSetValueKey", "registry", ("pol", "KeyHandle", "ValueName", "Type")), + ("NtQueryValueKey", "registry", ("polR", "KeyHandle", "ValueName", "Type", "Information")), + ("NtQueryValueKey", "registry", ("po", "KeyHandle", "ValueName")), + ("NtQueryMultipleValueKey", "registry", ("poS", "KeyHandle", "ValueName", "ValueBuffer")), + ("NtLoadKey2", "registry", ("OOl", "TargetKey", "SourceFile", "Flags")), + ("NtLoadKeyEx", "registry", ("pOOl", "TrustClassKey", "TargetKey", "SourceFile", "Flags")), + ("NtQueryKey", "registry", ("pSl", "KeyHandle", "KeyInformation", "KeyInformationClass")), + ("NtSaveKeyEx", "registry", ("ppl", "KeyHandle", "FileHandle", "Format")), + ("OpenSCManagerA", "services", ("ssl", "MachineName", "DatabaseName", "DesiredAccess")), + ("OpenSCManagerW", "services", ("uul", "MachineName", "DatabaseName", "DesiredAccess")), + ("CreateServiceA", "services", ("pss4l3s", "ServiceControlHandle", "ServiceName", "DisplayName", "DesiredAccess", "ServiceType", "StartType", "ErrorControl", "BinaryPathName", "ServiceStartName", "Password")), + ("CreateServiceW", "services", ("puu4l3u", "ServiceControlHandle", "ServiceName", "DisplayName", "DesiredAccess", "ServiceType", "StartType", "ErrorControl", "BinaryPathName", "ServiceStartName", "Password")), + ("OpenServiceA", "services", ("psl", "ServiceControlManager", "ServiceName", "DesiredAccess")), + ("OpenServiceW", "services", ("pul", "ServiceControlManager", "ServiceName", "DesiredAccess")), + ("StartServiceA", "services", ("pa", "ServiceHandle", "Arguments")), + ("StartServiceW", "services", ("pA", "ServiceHandle", "Arguments")), + ("TransmitFile", "socket", ("ppll", "socket", "FileHandle", "NumberOfBytesToWrite", "NumberOfBytesPerSend")), + ("NtCreateMutant", "synchronization", ("POl", "Handle", "MutexName", "InitialOwner")), + ("NtCreateNamedPipeFile", "synchronization", ("PpOl", "NamedPipeHandle", "DesiredAccess", "PipeName", "ShareAccess")), + ("NtCreateThread", "threading", ("PpO", "ThreadHandle", "ProcessHandle", "ObjectAttributes")), + ("NtOpenThread", "threading", ("PlO", "ThreadHandle", "DesiredAccess", "ObjectAttributes")), + ("NtSuspendThread", "threading", ("pL", "ThreadHandle", "SuspendCount")), + ("CreateThread", "threading", ("pplL", "StartRoutine", "Parameter", "CreationFlags", "ThreadId")), + ("CreateRemoteThread", "threading", ("3plL", "ProcessHandle", "StartRoutine", "Parameter", "CreationFlags", "ThreadId")), + ("RtlCreateUserThread", "threading", ("plppPl", "ProcessHandle", "CreateSuspended", "StartAddress", "StartParameter", "ThreadHandle", "ThreadIdentifier")), + ("ZwMapViewOfSection", "process", ("ppPp", "SectionHandle", "ProcessHandle", "BaseAddress", "SectionOffset")), + ("GetSystemMetrics", "misc", ("l", "SystemMetricIndex")), + ("GetCursorPos", "misc", ("ll", "x", "y")), + ("RtlCreateUserProcess", "process", ("opp", "ImagePath", "ObjectAttributes", "ParentProcess")), + ("NtCreateThreadEx", "threading", ("Pppl", "ThreadHandle", "ProcessHandle", "StartAddress", "CreateSuspended")), +] diff --git a/lookup.c b/lookup.c new file mode 100644 index 0000000..9264ea7 --- /dev/null +++ b/lookup.c @@ -0,0 +1,97 @@ +/* +Cuckoo Sandbox - Automated Malware Analysis +Copyright (C) 2010-2014 Cuckoo Sandbox Developers + +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 . +*/ + +#include +#include +#include +#include +#include "lookup.h" + +#define ENTER() EnterCriticalSection(&d->cs) +#define LEAVE() LeaveCriticalSection(&d->cs) + +typedef struct _entry_t { + struct _entry_t *next; + unsigned int id; + unsigned int size; + unsigned char data[0]; +} entry_t; + +void lookup_init(lookup_t *d) +{ + d->root = NULL; + InitializeCriticalSection(&d->cs); +} + +void lookup_free(lookup_t *d) +{ + // TODO +} + +void *lookup_add(lookup_t *d, unsigned int id, unsigned int size) +{ + entry_t *t = (entry_t *) malloc(sizeof(entry_t) + size); + ENTER(); + *t = (entry_t) { + .next = d->root, + .id = id, + .size = size, + }; + d->root = t; + LEAVE(); + return t->data; +} + +void *lookup_get(lookup_t *d, unsigned int id, unsigned int *size) +{ + ENTER(); + for (entry_t *p = d->root; p != NULL; p = p->next) { + if(p->id == id) { + if(size != NULL) { + *size = p->size; + } + void *data = p->data; + LEAVE(); + return data; + } + } + LEAVE(); + return NULL; +} + +void lookup_del(lookup_t *d, unsigned int id) +{ + ENTER(); + entry_t *p = d->root; + // edge case; we want to delete the first entry + if(p != NULL && p->id == id) { + entry_t *t = p->next; + free(d->root); + d->root = t; + LEAVE(); + return; + } + for (entry_t *last = NULL; p != NULL; last = p, p = p->next) { + if(p->id == id) { + last->next = p->next; + free(p); + break; + } + } + LEAVE(); +} diff --git a/lookup.h b/lookup.h new file mode 100644 index 0000000..9581145 --- /dev/null +++ b/lookup.h @@ -0,0 +1,29 @@ +/* +Cuckoo Sandbox - Automated Malware Analysis +Copyright (C) 2010-2014 Cuckoo Sandbox Developers + +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 . +*/ + +#include + +typedef struct _lookup_internal_t { + CRITICAL_SECTION cs; + void *root; +} lookup_t; + +void lookup_init(lookup_t *d); +void *lookup_add(lookup_t *d, unsigned int id, unsigned int size); +void *lookup_get(lookup_t *d, unsigned int id, unsigned int *size); +void lookup_del(lookup_t *d, unsigned int id); diff --git a/misc.c b/misc.c new file mode 100644 index 0000000..37dff1f --- /dev/null +++ b/misc.c @@ -0,0 +1,269 @@ +/* +Cuckoo Sandbox - Automated Malware Analysis +Copyright (C) 2010-2014 Cuckoo Sandbox Developers + +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 . +*/ + +#include +#include +#include +#include +#include "ntapi.h" +#include "misc.h" + +ULONG_PTR parent_process_id() // By Napalm @ NetCore2K (rohitab.com) +{ + ULONG_PTR pbi[6]; ULONG ulSize = 0; + LONG (WINAPI *NtQueryInformationProcess)(HANDLE ProcessHandle, + ULONG ProcessInformationClass, PVOID ProcessInformation, + ULONG ProcessInformationLength, PULONG ReturnLength); + + *(FARPROC *) &NtQueryInformationProcess = GetProcAddress( + GetModuleHandle("ntdll"), "NtQueryInformationProcess"); + + if(NtQueryInformationProcess != NULL && NtQueryInformationProcess( + GetCurrentProcess(), 0, &pbi, sizeof(pbi), &ulSize) >= 0 && + ulSize == sizeof(pbi)) { + return pbi[5]; + } + return 0; +} + +DWORD pid_from_process_handle(HANDLE process_handle) +{ + PROCESS_BASIC_INFORMATION pbi = {}; ULONG ulSize; + LONG (WINAPI *NtQueryInformationProcess)(HANDLE ProcessHandle, + ULONG ProcessInformationClass, PVOID ProcessInformation, + ULONG ProcessInformationLength, PULONG ReturnLength); + + *(FARPROC *) &NtQueryInformationProcess = GetProcAddress( + GetModuleHandle("ntdll"), "NtQueryInformationProcess"); + + if(NtQueryInformationProcess != NULL && NtQueryInformationProcess( + process_handle, 0, &pbi, sizeof(pbi), &ulSize) >= 0 && + ulSize == sizeof(pbi)) { + return pbi.UniqueProcessId; + } + return 0; +} + +DWORD pid_from_thread_handle(HANDLE thread_handle) +{ + THREAD_BASIC_INFORMATION tbi = {}; ULONG ulSize; + LONG (WINAPI *NtQueryInformationThread)(HANDLE ThreadHandle, + ULONG ThreadInformationClass, PVOID ThreadInformation, + ULONG ThreadInformationLength, PULONG ReturnLength); + + *(FARPROC *) &NtQueryInformationThread = GetProcAddress( + GetModuleHandle("ntdll"), "NtQueryInformationThread"); + + if(NtQueryInformationThread != NULL && NtQueryInformationThread( + thread_handle, 0, &tbi, sizeof(tbi), &ulSize) >= 0 && + ulSize == sizeof(tbi)) { + return (DWORD) tbi.ClientId.UniqueProcess; + } + return 0; +} + +DWORD random() +{ + static BOOLEAN (WINAPI *pRtlGenRandom)(PVOID RandomBuffer, + ULONG RandomBufferLength); + + if(pRtlGenRandom == NULL) { + *(FARPROC *) &pRtlGenRandom = GetProcAddress( + GetModuleHandle("advapi32"), "SystemFunction036"); + } + + DWORD ret; + return pRtlGenRandom(&ret, sizeof(ret)) ? ret : rand(); +} + +DWORD randint(DWORD min, DWORD max) +{ + return min + (random() % (max - min + 1)); +} + +BOOL is_directory_objattr(const OBJECT_ATTRIBUTES *obj) +{ + static NTSTATUS (WINAPI *pNtQueryAttributesFile)( + _In_ const OBJECT_ATTRIBUTES *ObjectAttributes, + _Out_ PFILE_BASIC_INFORMATION FileInformation + ); + + if(pNtQueryAttributesFile == NULL) { + *(FARPROC *) &pNtQueryAttributesFile = GetProcAddress( + GetModuleHandle("ntdll"), "NtQueryAttributesFile"); + } + + FILE_BASIC_INFORMATION basic_information; + if(NT_SUCCESS(pNtQueryAttributesFile(obj, &basic_information))) { + return basic_information.FileAttributes & FILE_ATTRIBUTE_DIRECTORY; + } + return FALSE; +} + +// hide our module from PEB +// http://www.openrce.org/blog/view/844/How_to_hide_dll + +#define CUT_LIST(item) \ + item.Blink->Flink = item.Flink; \ + item.Flink->Blink = item.Blink + +void hide_module_from_peb(HMODULE module_handle) +{ + LDR_MODULE *mod; PEB *peb = (PEB *) __readfsdword(0x30); + + for (mod = (LDR_MODULE *) peb->LoaderData->InLoadOrderModuleList.Flink; + mod->BaseAddress != NULL; + mod = (LDR_MODULE *) mod->InLoadOrderModuleList.Flink) { + + if(mod->BaseAddress == module_handle) { + CUT_LIST(mod->InLoadOrderModuleList); + CUT_LIST(mod->InInitializationOrderModuleList); + CUT_LIST(mod->InMemoryOrderModuleList); + + // TODO test whether this list is really used as a linked list + // like InLoadOrderModuleList etc + CUT_LIST(mod->HashTableEntry); + + memset(mod, 0, sizeof(LDR_MODULE)); + break; + } + } +} + +uint32_t path_from_handle(HANDLE handle, + wchar_t *path, uint32_t path_buffer_len) +{ + static NTSTATUS (WINAPI *pNtQueryVolumeInformationFile)( + _In_ HANDLE FileHandle, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _Out_ PVOID FsInformation, + _In_ ULONG Length, + _In_ FS_INFORMATION_CLASS FsInformationClass + ); + + if(pNtQueryVolumeInformationFile == NULL) { + *(FARPROC *) &pNtQueryVolumeInformationFile = GetProcAddress( + GetModuleHandle("ntdll"), "NtQueryVolumeInformationFile"); + } + + static NTSTATUS (WINAPI *pNtQueryInformationFile)( + _In_ HANDLE FileHandle, + _Out_ PIO_STATUS_BLOCK IoStatusBlock, + _Out_ PVOID FileInformation, + _In_ ULONG Length, + _In_ FILE_INFORMATION_CLASS FileInformationClass + ); + + if(pNtQueryInformationFile == NULL) { + *(FARPROC *) &pNtQueryInformationFile = GetProcAddress( + GetModuleHandle("ntdll"), "NtQueryInformationFile"); + } + + IO_STATUS_BLOCK status = {}; + FILE_FS_VOLUME_INFORMATION volume_information; + + unsigned char buf[FILE_NAME_INFORMATION_REQUIRED_SIZE]; + FILE_NAME_INFORMATION *name_information = (FILE_NAME_INFORMATION *) buf; + + // get the volume serial number of the directory handle + if(NT_SUCCESS(pNtQueryVolumeInformationFile(handle, &status, + &volume_information, sizeof(volume_information), + FileFsVolumeInformation)) == 0) { + return 0; + } + + unsigned long serial_number; + + // enumerate all harddisks in order to find the + // corresponding serial number + wcscpy(path, L"?:\\"); + for (path[0] = 'A'; path[0] <= 'Z'; path[0]++) { + if(GetVolumeInformationW(path, NULL, 0, &serial_number, NULL, + NULL, NULL, 0) == 0 || + serial_number != volume_information.VolumeSerialNumber) { + continue; + } + + // obtain the relative path for this filename on the given harddisk + if(NT_SUCCESS(pNtQueryInformationFile(handle, &status, + name_information, FILE_NAME_INFORMATION_REQUIRED_SIZE, + FileNameInformation))) { + + uint32_t length = + name_information->FileNameLength / sizeof(wchar_t); + + // NtQueryInformationFile omits the "C:" part in a + // filename, apparently + wcsncpy(path + 2, name_information->FileName, + path_buffer_len - 2); + + return length + 2 < path_buffer_len ? + length + 2 : path_buffer_len - 1; + } + } + return 0; +} + +uint32_t path_from_object_attributes(const OBJECT_ATTRIBUTES *obj, + wchar_t *path, uint32_t buffer_length) +{ + if(obj->ObjectName == NULL || obj->ObjectName->Buffer == NULL) { + return 0; + } + + // ObjectName->Length is actually the size in bytes. + uint32_t obj_length = obj->ObjectName->Length / sizeof(wchar_t); + + if(obj->RootDirectory == NULL) { + wcsncpy(path, obj->ObjectName->Buffer, buffer_length); + return obj_length > buffer_length ? buffer_length : obj_length; + } + + uint32_t length = path_from_handle(obj->RootDirectory, + path, buffer_length); + + path[length++] = L'\\'; + wcsncpy(&path[length], obj->ObjectName->Buffer, buffer_length - length); + + length += obj_length; + return length > buffer_length ? buffer_length : length; +} + +int ensure_absolute_path(wchar_t *out, const wchar_t *in, int length) +{ + if(!wcsncmp(in, L"\\??\\", 4)) { + length -= 4, in += 4; + wcsncpy(out, in, length < MAX_PATH ? length : MAX_PATH); + return out[length] = 0, length; + } + else if(in[1] != ':' || (in[2] != '\\' && in[2] != '/')) { + wchar_t cur_dir[MAX_PATH], fname[MAX_PATH]; + GetCurrentDirectoryW(ARRAYSIZE(cur_dir), cur_dir); + + // ensure the filename is zero-terminated + wcsncpy(fname, in, length < MAX_PATH ? length : MAX_PATH); + fname[length] = 0; + + PathCombineW(out, cur_dir, fname); + return lstrlenW(out); + } + else { + wcsncpy(out, in, length < MAX_PATH ? length : MAX_PATH); + return out[length] = 0, length; + } +} diff --git a/misc.h b/misc.h new file mode 100644 index 0000000..aa6f8dd --- /dev/null +++ b/misc.h @@ -0,0 +1,40 @@ +/* +Cuckoo Sandbox - Automated Malware Analysis +Copyright (C) 2010-2014 Cuckoo Sandbox Developers + +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 . +*/ + +ULONG_PTR parent_process_id(); // By Napalm @ NetCore2K (rohitab.com) +DWORD pid_from_process_handle(HANDLE process_handle); +DWORD pid_from_thread_handle(HANDLE thread_handle); +DWORD random(); +DWORD randint(DWORD min, DWORD max); +BOOL is_directory_objattr(const OBJECT_ATTRIBUTES *obj); +void hide_module_from_peb(HMODULE module_handle); + +uint32_t path_from_handle(HANDLE handle, + wchar_t *path, uint32_t path_buffer_len); + +uint32_t path_from_object_attributes(const OBJECT_ATTRIBUTES *obj, + wchar_t *path, uint32_t buffer_length); + +int ensure_absolute_path(wchar_t *out, const wchar_t *in, int length); + +// imported but for some doesn't show up when #including string.h etc +int wcsnicmp(const wchar_t *a, const wchar_t *b, int len); +int wcsicmp(const wchar_t *a, const wchar_t *b); + +// Define MAX_PATH plus tolerance for windows "tolerance" +#define MAX_PATH_PLUS_TOLERANCE MAX_PATH + 64 diff --git a/netlog.py b/netlog.py new file mode 100644 index 0000000..5ba65a1 --- /dev/null +++ b/netlog.py @@ -0,0 +1,87 @@ +"""Simple utility to generate code to communicate between C and Python. + +This utility generates C definitions and Python definitions in order to +send integers, strings, lists, and other custom types over a socket. + +""" +import logtbl +import sys +from struct import unpack + + +def read_int32(buf, offset): + """Reads a 32bit integer from the buffer.""" + return 4, unpack('I', buf[offset:offset+4])[0] + + +def read_ptr(buf, offset): + """Read a pointer from the buffer.""" + length, value = read_int32(buf, offset) + return length, '0x%08x' % value + + +def read_string(buf, offset): + """Reads an utf8 string from the buffer.""" + length, maxlength = unpack('HH', buf[offset:offset+8]) + return length+4, (length, maxlength, buf[offset+4:offset+4+length]) + + +def read_buffer(buf, offset): + """Reads a memory buffer from the buffer.""" + length, maxlength = unpack('HH', buf[offset:offset+8]) + # only return the maxlength, as we don't log the actual buffer right now + return 4, maxlength + + +def read_registry(buf, offset): + """Read logged registry data from the buffer.""" + typ = unpack('H', buf[offset:offset+2])[0] + # do something depending on type + return + + +def read_list(buf, offset, fn): + """Reads a list of _fn_ from the buffer.""" + count = unpack('H', buf[offset:offset+2])[0] + ret, length = [], 0 + for x in xrange(count): + item_length, item = fn(buf, offset+length) + length += item_length + ret.append(item) + return item_length+2, ret + + +def parse_fmt(funcname, fmt, *args): + typ = { + 's': read_string, + 'S': read_string, + 'u': read_string, + 'U': read_string, + 'b': read_buffer, + 'B': read_buffer, + 'i': read_int32, + 'l': read_int32, + 'L': read_int32, + 'p': read_ptr, + 'P': read_ptr, + 'o': read_string, + 'O': read_string, + 'a': None, + 'A': None, + 'r': read_registry, + 'R': read_registry, + } + + +def generate_c_code(fname): + lines = ['#include ', '', 'const char *logtbl[][2] = {'] + for index, (funcname, module, args) in enumerate(logtbl.table): + lines.append(' {"%s", "%s"},' % (funcname, module)) + lines.append(' {NULL, NULL},') + lines.append('};') + lines.append('char logtbl_explained[sizeof(logtbl)/sizeof(char *)] = {0};') + open(fname, 'w').write('\n'.join(lines) + '\n') + +if __name__ == '__main__': + if sys.argv[1] == 'c-header': + generate_c_code(sys.argv[2]) diff --git a/ntapi.h b/ntapi.h new file mode 100644 index 0000000..6e42f4a --- /dev/null +++ b/ntapi.h @@ -0,0 +1,470 @@ +/* +Cuckoo Sandbox - Automated Malware Analysis +Copyright (C) 2010-2014 Cuckoo Sandbox Developers + +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 . +*/ + +#include +#include + +#ifndef __NTAPI_H__ +#define __NTAPI_H__ + +typedef LONG NTSTATUS; + +#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0) + +#define __out +#define __in +#define __in_opt +#define __reserved +#define __out_opt +#define __inout +#define __inout_opt +#define _In_ +#define _In_opt_ +#define _Out_ +#define _Out_opt_ +#define _Inout_opt_ +#define _Reserved_ + +typedef struct _STRING { + USHORT Length; + USHORT MaximumLength; + PCHAR Buffer; +} ANSI_STRING, *PANSI_STRING; + +typedef struct _LSA_UNICODE_STRING { + USHORT Length; + USHORT MaximumLength; + PWSTR Buffer; +} LSA_UNICODE_STRING, *PLSA_UNICODE_STRING, UNICODE_STRING, *PUNICODE_STRING; + +typedef struct _IO_STATUS_BLOCK { + union { + NTSTATUS Status; + PVOID Pointer; + }; + ULONG_PTR Information; +} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK; + +typedef struct _OBJECT_ATTRIBUTES { + ULONG Length; + HANDLE RootDirectory; + PUNICODE_STRING ObjectName; + ULONG Attributes; + PVOID SecurityDescriptor; + PVOID SecurityQualityOfService; +} OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES; + +// for now.. +typedef void *PIO_APC_ROUTINE; + +#ifndef ARRAYSIZE +#define ARRAYSIZE(a) (sizeof(a) / sizeof(*(a))) +#endif + +typedef void *HINTERNET; + +typedef struct addrinfo { + int ai_flags; + int ai_family; + int ai_socktype; + int ai_protocol; + size_t ai_addrlen; + char *ai_canonname; + struct sockaddr *ai_addr; + struct addrinfo *ai_next; +} ADDRINFOA, *PADDRINFOA; + +typedef struct addrinfoW { + int ai_flags; + int ai_family; + int ai_socktype; + int ai_protocol; + size_t ai_addrlen; + PWSTR ai_canonname; + struct sockaddr *ai_addr; + struct addrinfoW *ai_next; +} ADDRINFOW, *PADDRINFOW; + +typedef enum _KEY_INFORMATION_CLASS { + KeyBasicInformation = 0, + KeyNodeInformation = 1, + KeyFullInformation = 2, + KeyNameInformation = 3, + KeyCachedInformation = 4, + KeyFlagsInformation = 5, + KeyVirtualizationInformation = 6, + KeyHandleTagsInformation = 7, + MaxKeyInfoClass = 8 +} KEY_INFORMATION_CLASS; + +typedef enum _KEY_VALUE_INFORMATION_CLASS { + KeyValueBasicInformation = 0, + KeyValueFullInformation = 1, + KeyValuePartialInformation = 2, + KeyValueFullInformationAlign64 = 3, + KeyValuePartialInformationAlign64 = 4, + MaxKeyValueInfoClass = 5 +} KEY_VALUE_INFORMATION_CLASS; + +typedef struct _KEY_VALUE_BASIC_INFORMATION { + ULONG TitleIndex; + ULONG Type; + ULONG NameLength; + WCHAR Name[1]; +} KEY_VALUE_BASIC_INFORMATION, *PKEY_VALUE_BASIC_INFORMATION; + +typedef struct _KEY_VALUE_FULL_INFORMATION { + ULONG TitleIndex; + ULONG Type; + ULONG DataOffset; + ULONG DataLength; + ULONG NameLength; + WCHAR Name[1]; +} KEY_VALUE_FULL_INFORMATION, *PKEY_VALUE_FULL_INFORMATION; + +typedef struct _KEY_VALUE_PARTIAL_INFORMATION { + ULONG TitleIndex; + ULONG Type; + ULONG DataLength; + UCHAR Data[1]; +} KEY_VALUE_PARTIAL_INFORMATION, *PKEY_VALUE_PARTIAL_INFORMATION; + +typedef struct _KEY_VALUE_ENTRY { + PUNICODE_STRING ValueName; + ULONG DataLength; + ULONG DataOffset; + ULONG Type; +} KEY_VALUE_ENTRY, *PKEY_VALUE_ENTRY; + +typedef struct _PROCESS_BASIC_INFORMATION { + PVOID Reserved1; + void *PebBaseAddress; + PVOID Reserved2[2]; + ULONG_PTR UniqueProcessId; + PVOID Reserved3; +} PROCESS_BASIC_INFORMATION; + +typedef struct _CLIENT_ID { + PVOID UniqueProcess; + PVOID UniqueThread; +} CLIENT_ID, *PCLIENT_ID; + +typedef ULONG_PTR KAFFINITY; +typedef LONG KPRIORITY; + +typedef struct _THREAD_BASIC_INFORMATION { + NTSTATUS ExitStatus; + PVOID TebBaseAddress; + CLIENT_ID ClientId; + KAFFINITY AffinityMask; + KPRIORITY Priority; + KPRIORITY BasePriority; +} THREAD_BASIC_INFORMATION, *PTHREAD_BASIC_INFORMATION; + +typedef struct _INITIAL_TEB { + PVOID StackBase; + PVOID StackLimit; + PVOID StackCommit; + PVOID StackCommitMax; + PVOID StackReserved; +} INITIAL_TEB, *PINITIAL_TEB; + +typedef enum _FILE_INFORMATION_CLASS { + FileDirectoryInformation = 1, + FileFullDirectoryInformation, + FileBothDirectoryInformation, + FileBasicInformation, + FileStandardInformation, + FileInternalInformation, + FileEaInformation, + FileAccessInformation, + FileNameInformation, + FileRenameInformation, + FileLinkInformation, + FileNamesInformation, + FileDispositionInformation, + FilePositionInformation, + FileFullEaInformation, + FileModeInformation, + FileAlignmentInformation, + FileAllInformation, + FileAllocationInformation, + FileEndOfFileInformation, + FileAlternateNameInformation, + FileStreamInformation, + FilePipeInformation, + FilePipeLocalInformation, + FilePipeRemoteInformation, + FileMailslotQueryInformation, + FileMailslotSetInformation, + FileCompressionInformation, + FileObjectIdInformation, + FileCompletionInformation, + FileMoveClusterInformation, + FileQuotaInformation, + FileReparsePointInformation, + FileNetworkOpenInformation, + FileAttributeTagInformation, + FileTrackingInformation, + FileIdBothDirectoryInformation, + FileIdFullDirectoryInformation, + FileValidDataLengthInformation, + FileShortNameInformation, + FileIoCompletionNotificationInformation, + FileIoStatusBlockRangeInformation, + FileIoPriorityHintInformation, + FileSfioReserveInformation, + FileSfioVolumeInformation, + FileHardLinkInformation, + FileProcessIdsUsingFileInformation, + FileNormalizedNameInformation, + FileNetworkPhysicalNameInformation, + FileIdGlobalTxDirectoryInformation, + FileIsRemoteDeviceInformation, + FileAttributeCacheInformation, + FileNumaNodeInformation, + FileStandardLinkInformation, + FileRemoteProtocolInformation, + FileMaximumInformation +} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS; + +#define STATUS_ACCESS_DENIED ((NTSTATUS) 0xc0000022) + +typedef struct _FILE_BASIC_INFORMATION { + LARGE_INTEGER CreationTime; + LARGE_INTEGER LastAccessTime; + LARGE_INTEGER LastWriteTime; + LARGE_INTEGER ChangeTime; + ULONG FileAttributes; +} FILE_BASIC_INFORMATION, *PFILE_BASIC_INFORMATION; + +typedef struct _RTL_DRIVE_LETTER_CURDIR { + USHORT Flags; + USHORT Length; + ULONG TimeStamp; + UNICODE_STRING DosPath; +} RTL_DRIVE_LETTER_CURDIR, *PRTL_DRIVE_LETTER_CURDIR; + +typedef struct _RTL_USER_PROCESS_PARAMETERS { + ULONG MaximumLength; + ULONG Length; + ULONG Flags; + ULONG DebugFlags; + PVOID ConsoleHandle; + ULONG ConsoleFlags; + HANDLE StdInputHandle; + HANDLE StdOutputHandle; + HANDLE StdErrorHandle; + UNICODE_STRING CurrentDirectoryPath; + HANDLE CurrentDirectoryHandle; + UNICODE_STRING DllPath; + UNICODE_STRING ImagePathName; + UNICODE_STRING CommandLine; + PVOID Environment; + ULONG StartingPositionLeft; + ULONG StartingPositionTop; + ULONG Width; + ULONG Height; + ULONG CharWidth; + ULONG CharHeight; + ULONG ConsoleTextAttributes; + ULONG WindowFlags; + ULONG ShowWindowFlags; + UNICODE_STRING WindowTitle; + UNICODE_STRING DesktopName; + UNICODE_STRING ShellInfo; + UNICODE_STRING RuntimeData; + RTL_DRIVE_LETTER_CURDIR DLCurrentDirectory[0x20]; +} RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS; + +typedef void *PPS_CREATE_INFO, *PPS_ATTRIBUTE_LIST; + +typedef void *PVOID, **PPVOID; + +typedef struct _PEB_LDR_DATA { + ULONG Length; + BOOLEAN Initialized; + PVOID SsHandle; + LIST_ENTRY InLoadOrderModuleList; + LIST_ENTRY InMemoryOrderModuleList; + LIST_ENTRY InInitializationOrderModuleList; +} PEB_LDR_DATA, *PPEB_LDR_DATA; + +typedef struct _LDR_MODULE { + LIST_ENTRY InLoadOrderModuleList; + LIST_ENTRY InMemoryOrderModuleList; + LIST_ENTRY InInitializationOrderModuleList; + PVOID BaseAddress; + PVOID EntryPoint; + ULONG SizeOfImage; + UNICODE_STRING FullDllName; + UNICODE_STRING BaseDllName; + ULONG Flags; + SHORT LoadCount; + SHORT TlsIndex; + LIST_ENTRY HashTableEntry; + ULONG TimeDateStamp; +} LDR_MODULE, *PLDR_MODULE; + +typedef struct _PEB { + BOOLEAN InheritedAddressSpace; + BOOLEAN ReadImageFileExecOptions; + BOOLEAN BeingDebugged; + BOOLEAN Spare; + HANDLE Mutant; + PVOID ImageBaseAddress; + PPEB_LDR_DATA LoaderData; + PRTL_USER_PROCESS_PARAMETERS ProcessParameters; + PVOID SubSystemData; + PVOID ProcessHeap; + PVOID FastPebLock; + void *FastPebLockRoutine; + void *FastPebUnlockRoutine; + ULONG EnvironmentUpdateCount; + PPVOID KernelCallbackTable; + PVOID EventLogSection; + PVOID EventLog; + void *FreeList; + ULONG TlsExpansionCounter; + PVOID TlsBitmap; + ULONG TlsBitmapBits[0x2]; + PVOID ReadOnlySharedMemoryBase; + PVOID ReadOnlySharedMemoryHeap; + PPVOID ReadOnlyStaticServerData; + PVOID AnsiCodePageData; + PVOID OemCodePageData; + PVOID UnicodeCaseTableData; + ULONG NumberOfProcessors; + ULONG NtGlobalFlag; + BYTE Spare2[0x4]; + LARGE_INTEGER CriticalSectionTimeout; + ULONG HeapSegmentReserve; + ULONG HeapSegmentCommit; + ULONG HeapDeCommitTotalFreeThreshold; + ULONG HeapDeCommitFreeBlockThreshold; + ULONG NumberOfHeaps; + ULONG MaximumNumberOfHeaps; + PPVOID *ProcessHeaps; + PVOID GdiSharedHandleTable; + PVOID ProcessStarterHelper; + PVOID GdiDCAttributeList; + PVOID LoaderLock; + ULONG OSMajorVersion; + ULONG OSMinorVersion; + ULONG OSBuildNumber; + ULONG OSPlatformId; + ULONG ImageSubSystem; + ULONG ImageSubSystemMajorVersion; + ULONG ImageSubSystemMinorVersion; + ULONG GdiHandleBuffer[0x22]; + ULONG PostProcessInitRoutine; + ULONG TlsExpansionBitmap; + BYTE TlsExpansionBitmapBits[0x80]; + ULONG SessionId; +} PEB, *PPEB; + +static inline unsigned int __readfsdword(unsigned int index) +{ + unsigned int ret; + __asm__("movl %%fs:(%1), %0" : "=r" (ret) : "r" (index)); + return ret; +} + +static inline void __writefsdword(unsigned int index, unsigned int value) +{ + __asm__("movl %0, %%fs:(%1)" :: "r" (value), "r" (index)); +} + +typedef struct _SECTION_IMAGE_INFORMATION { + VOID* TransferAddress; + uint32_t ZeroBits; + uint8_t _PADDING0_[0x4]; + uint64_t MaximumStackSize; + uint64_t CommittedStackSize; + uint32_t SubSystemType; + union { + struct { + uint16_t SubSystemMinorVersion; + uint16_t SubSystemMajorVersion; + }; + uint32_t SubSystemVersion; + }; + uint32_t GpValue; + uint16_t ImageCharacteristics; + uint16_t DllCharacteristics; + uint16_t Machine; + uint8_t ImageContainsCode; + union { + uint8_t ImageFlags; + struct { + uint8_t ComPlusNativeReady : 1; + uint8_t ComPlusILOnly : 1; + uint8_t ImageDynamicallyRelocated : 1; + uint8_t ImageMappedFlat : 1; + uint8_t Reserved : 4; + }; + }; + uint32_t LoaderFlags; + uint32_t ImageFileSize; + uint32_t CheckSum; +} SECTION_IMAGE_INFORMATION, *PSECTION_IMAGE_INFORMATION; + +typedef struct _RTL_USER_PROCESS_INFORMATION { + ULONG Size; + HANDLE ProcessHandle; + HANDLE ThreadHandle; + CLIENT_ID ClientId; + SECTION_IMAGE_INFORMATION ImageInformation; +} RTL_USER_PROCESS_INFORMATION, *PRTL_USER_PROCESS_INFORMATION; + +#define FILE_NAME_INFORMATION_REQUIRED_SIZE \ + sizeof(FILE_NAME_INFORMATION) + sizeof(wchar_t) * MAX_PATH + +typedef struct _FILE_NAME_INFORMATION { + ULONG FileNameLength; + WCHAR FileName[1]; +} FILE_NAME_INFORMATION, *PFILE_NAME_INFORMATION; + +typedef enum { + FileFsVolumeInformation = 1, + FileFsLabelInformation = 2, + FileFsSizeInformation = 3, + FileFsDeviceInformation = 4, + FileFsAttributeInformation = 5, + FileFsControlInformation = 6, + FileFsFullSizeInformation = 7, + FileFsObjectIdInformation = 8, + FileFsDriverPathInformation = 9, + FileFsVolumeFlagsInformation = 10, + FileFsSectorSizeInformation = 11 +} FS_INFORMATION_CLASS; + +typedef struct _FILE_FS_VOLUME_INFORMATION { + LARGE_INTEGER VolumeCreationTime; + ULONG VolumeSerialNumber; + ULONG VolumeLabelLength; + BOOLEAN SupportsObjects; + WCHAR VolumeLabel[1]; +} FILE_FS_VOLUME_INFORMATION, *PFILE_FS_VOLUME_INFORMATION; + +static inline UNICODE_STRING *unistr_from_objattr(OBJECT_ATTRIBUTES *obj) +{ + return obj != NULL ? obj->ObjectName : NULL; +} + +#endif diff --git a/pipe.c b/pipe.c new file mode 100644 index 0000000..86fe2ea --- /dev/null +++ b/pipe.c @@ -0,0 +1,154 @@ +/* +Cuckoo Sandbox - Automated Malware Analysis +Copyright (C) 2010-2014 Cuckoo Sandbox Developers + +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 . +*/ + +#include +#include +#include "ntapi.h" +#include "pipe.h" +#include "utf8.h" +#include "misc.h" + +const char *g_pipe_name; + +static int _pipe_utf8x(char **out, unsigned short x) +{ + unsigned char buf[3]; + int len = utf8_encode(x, buf); + if(*out != NULL) { + memcpy(*out, buf, len); + *out += len; + } + return len; +} + +static int _pipe_ascii(char **out, const char *s, int len) +{ + int ret = 0; + while (len-- != 0) { + ret += _pipe_utf8x(out, *(unsigned char *) s++); + } + return ret; +} + +static int _pipe_unicode(char **out, const wchar_t *s, int len) +{ + int ret = 0; + while (len-- != 0) { + ret += _pipe_utf8x(out, *(unsigned short *) s++); + } + return ret; +} + +static int _pipe_sprintf(char *out, const char *fmt, va_list args) +{ + int ret = 0; + while (*fmt != 0) { + if(*fmt != '%') { + ret += _pipe_utf8x(&out, *fmt++); + continue; + } + if(*++fmt == 'z') { + const char *s = va_arg(args, const char *); + if(s == NULL) return -1; + + ret += _pipe_ascii(&out, s, strlen(s)); + } + else if(*fmt == 'Z') { + const wchar_t *s = va_arg(args, const wchar_t *); + if(s == NULL) return -1; + + ret += _pipe_unicode(&out, s, lstrlenW(s)); + } + else if(*fmt == 's') { + int len = va_arg(args, int); + const char *s = va_arg(args, const char *); + if(s == NULL) return -1; + + ret += _pipe_ascii(&out, s, len < 0 ? strlen(s) : len); + } + else if(*fmt == 'S') { + int len = va_arg(args, int); + const wchar_t *s = va_arg(args, const wchar_t *); + if(s == NULL) return -1; + + ret += _pipe_unicode(&out, s, len < 0 ? lstrlenW(s) : len); + } + else if(*fmt == 'o') { + UNICODE_STRING *str = va_arg(args, UNICODE_STRING *); + if(str == NULL) return -1; + + ret += _pipe_unicode(&out, str->Buffer, + str->Length / sizeof(wchar_t)); + } + else if(*fmt == 'O') { + OBJECT_ATTRIBUTES *obj = va_arg(args, OBJECT_ATTRIBUTES *); + if(obj == NULL || obj->ObjectName == NULL) return -1; + + wchar_t path[MAX_PATH_PLUS_TOLERANCE]; int length; + length = path_from_object_attributes(obj, path, (unsigned int) MAX_PATH_PLUS_TOLERANCE); + + length = ensure_absolute_path(path, path, length); + + ret += _pipe_unicode(&out, path, length); + } + else if(*fmt == 'd') { + char s[32]; + sprintf(s, "%d", va_arg(args, int)); + ret += _pipe_ascii(&out, s, strlen(s)); + } + else if(*fmt == 'x') { + char s[16]; + sprintf(s, "%x", va_arg(args, int)); + ret += _pipe_ascii(&out, s, strlen(s)); + } + fmt++; + } + return ret; +} + +int pipe(const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + int len = _pipe_sprintf(NULL, fmt, args); + if(len > 0) { + char buf[len + 1]; + _pipe_sprintf(buf, fmt, args); + va_end(args); + + return CallNamedPipe(g_pipe_name, buf, len, buf, len, + (unsigned long *) &len, NMPWAIT_WAIT_FOREVER); + } + return -1; +} + +int pipe2(void *out, int *outlen, const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + int len = _pipe_sprintf(NULL, fmt, args); + if(len > 0) { + char buf[len + 1]; + _pipe_sprintf(buf, fmt, args); + va_end(args); + + return CallNamedPipe(g_pipe_name, buf, len, out, *outlen, + (DWORD *) outlen, NMPWAIT_WAIT_FOREVER); + } + return -1; +} diff --git a/pipe.h b/pipe.h new file mode 100644 index 0000000..d4282d3 --- /dev/null +++ b/pipe.h @@ -0,0 +1,38 @@ +/* +Cuckoo Sandbox - Automated Malware Analysis +Copyright (C) 2010-2014 Cuckoo Sandbox Developers + +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 . +*/ + +// +// Pipe API +// +// The following Format Specifiers are available: +// z -> (char *) -> zero-terminated ascii string +// Z -> (wchar_t *) -> zero-terminated unicode string +// s -> (int, char *) -> ascii string with length +// S -> (int, wchar_t *) -> unicode string with length +// o -> (UNICODE_STRING *) -> unicode string +// O -> (OBJECT_ATTRIBUTES *) -> wrapper around unicode string +// d -> (int) -> integer +// x -> (int) -> hexadecimal integer +// + +int pipe(const char *fmt, ...); +int pipe2(void *out, int *outlen, const char *fmt, ...); + +#define PIPE_MAX_TIMEOUT 10000 + +extern const char *g_pipe_name; diff --git a/tests/Makefile b/tests/Makefile new file mode 100644 index 0000000..201f863 --- /dev/null +++ b/tests/Makefile @@ -0,0 +1,26 @@ +MAKEFLAGS = -j8 +CFLAGS = -Wall -std=c99 -s -O2 +LIBS = -ldnsapi -lws2_32 -lwininet -lshlwapi + +ifneq ($(OS),Windows_NT) + CC = i586-mingw32msvc-cc +else + CC = gcc +endif + +TESTS = $(wildcard *.c) +TESTSEXE = $(TESTS:.c=.exe) + +# please build all the object files using the main Makefile (in the parent +# directory) +CUCKOOOBJ := $(wildcard ../objects/*.o) +CUCKOOOBJ += $(wildcard ../objects/bson/*.o) +CUCKOOOBJ += $(wildcard ../objects/distorm3.2/*.o) + +all: $(TESTSEXE) + +%.exe: %.c $(CUCKOOOBJ) $(DISTORM3OBJ) + $(CC) $(CFLAGS) -I../distorm3.2-package/include -I.. -o $@ $^ $(LIBS) + +clean: + rm -f $(TESTSEXE) diff --git a/tests/apc-inject.c b/tests/apc-inject.c new file mode 100644 index 0000000..50e95c1 --- /dev/null +++ b/tests/apc-inject.c @@ -0,0 +1,39 @@ +/* +Cuckoo Sandbox - Automated Malware Analysis +Copyright (C) 2010-2014 Cuckoo Sandbox Developers + +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 . +*/ + +#define _WIN32_WINNT 0x0500 +#include +#include +#include + +int main() +{ + LoadLibrary("../cuckoomon.dll"); + + FARPROC sleep = GetProcAddress(GetModuleHandle("kernel32"), "Sleep"); + + for (uint32_t tid = 2000; ; tid += 4) { + HANDLE thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE, tid); + if(thread_handle != NULL) { + printf("tid %d .. :)\n", tid); + QueueUserAPC((PAPCFUNC) sleep, thread_handle, 1337); + CloseHandle(thread_handle); + break; + } + } +} diff --git a/tests/apihooks.c b/tests/apihooks.c new file mode 100644 index 0000000..61ac3b0 --- /dev/null +++ b/tests/apihooks.c @@ -0,0 +1,64 @@ +#include +#include +#include + +DWORD WINAPI dummy(LPVOID lpValue) +{ + printf("dummy here!\n"); + return 0; +} + +int main() +{ + // there we go + LoadLibrary("../cuckoomon.dll"); + + FILE *fp = fopen("test-hello", "r"); + if(fp != NULL) fclose(fp); + + fp = fopen("test-hello", "wb"); + fwrite("whatsup", 1, 6, fp); + fclose(fp); + + fp = fopen("test-hello", "rb"); + char buf[6]; + fread(buf, 1, 6, fp); + fclose(fp); + + _mkdir("abc"); + + DeleteFile("test-hello"); + + HKEY hKey; + if(RegCreateKeyEx(HKEY_CURRENT_USER, + "Software\\Microsoft\\Windows\\CurrentVersion\\Run", 0, NULL, 0, + KEY_ALL_ACCESS, NULL, &hKey, NULL) == ERROR_SUCCESS) { + RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL); + RegSetValueEx(hKey, "TestApiHooks", 0, REG_SZ, (BYTE *) "Hoi", 3); + RegDeleteValue(hKey, "TestApiHooks"); + RegCloseKey(hKey); + } + + system("echo hai"); + + WinExec("echo hi there", SW_SHOW); + + CreateMutex(NULL, FALSE, "MutexNam3"); + OpenMutex(MUTEX_ALL_ACCESS, FALSE, "OpenMutexName"); + + // just some random dll + LoadLibrary("urlmon.dll"); + + FARPROC sleep = GetProcAddress(GetModuleHandle("kernel32"), "Sleep"); + sleep(1000); + + printf("debugger: %d\n", IsDebuggerPresent()); + + CloseHandle(CreateThread(NULL, 0, &dummy, NULL, 0, NULL)); + + HANDLE thread_handle = CreateRemoteThread(GetCurrentProcess(), NULL, 0, + &dummy, NULL, 0, NULL); + WaitForSingleObject(thread_handle, INFINITE); + CloseHandle(thread_handle); +} diff --git a/tests/bind-port.c b/tests/bind-port.c new file mode 100644 index 0000000..16d461d --- /dev/null +++ b/tests/bind-port.c @@ -0,0 +1,17 @@ +#include +#include + +int main() +{ + WSADATA wsa; + WSAStartup(MAKEWORD(2, 2), &wsa); + + SOCKET s = socket(AF_INET, SOCK_STREAM, 0); + + struct sockaddr_in addr = {}; + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = 0; + addr.sin_port = htons(0x29a); + + bind(s, (struct sockaddr *) &addr, sizeof(addr)); +} diff --git a/tests/blacklist.c b/tests/blacklist.c new file mode 100644 index 0000000..ee4530a --- /dev/null +++ b/tests/blacklist.c @@ -0,0 +1,18 @@ +#include +#include +#include +#include "ignore.h" +#include "ntapi.h" + +int main() +{ + const wchar_t *unicode[] = { + L"abcd", + L"\\??\\IDE#what's up bro?", + }; + for (int i = 0; i < ARRAYSIZE(unicode); i++) { + printf("%d <= %S\n", + is_ignored_file_unicode(unicode[i], wcslen(unicode[i])), + unicode[i]); + } +} diff --git a/tests/child-sleep.c b/tests/child-sleep.c new file mode 100644 index 0000000..40206d3 --- /dev/null +++ b/tests/child-sleep.c @@ -0,0 +1,16 @@ +#include +#include + +int main(int argc, char *argv[]) +{ + if(argc == 4) { + Sleep(5000); + return 0; + } + + Sleep(10000); + + char buf[256]; + sprintf(buf, "%s a b c", argv[0]); + system(buf); +} diff --git a/tests/crash.c b/tests/crash.c new file mode 100644 index 0000000..4e8baeb --- /dev/null +++ b/tests/crash.c @@ -0,0 +1,7 @@ +#include + +int main() +{ + char *p = NULL; + *p = 0; +} diff --git a/tests/create-file.c b/tests/create-file.c new file mode 100644 index 0000000..257af06 --- /dev/null +++ b/tests/create-file.c @@ -0,0 +1,24 @@ +#include +#include + +int main() +{ + const char *modes[] = {"r", "r+", "w", "w+", "a", "a+"}; + const char *fname = "abc"; + + for (int i = 0; i < sizeof(modes)/sizeof(char *); i++) { + DeleteFile(fname); + FILE *fp = fopen(fname, modes[i]); + if(fp != NULL) { + fclose(fp); + } + } + + fclose(fopen(fname, "w")); + for (int i = 0; i < sizeof(modes)/sizeof(char *); i++) { + FILE *fp = fopen(fname, modes[i]); + if(fp != NULL) { + fclose(fp); + } + } +} diff --git a/tests/delete-file.c b/tests/delete-file.c new file mode 100644 index 0000000..3d7627d --- /dev/null +++ b/tests/delete-file.c @@ -0,0 +1,150 @@ +#include +#include +#include "../ntapi.h" + +#define OBJ_CASE_INSENSITIVE 0x00000040 +#define OBJ_KERNEL_HANDLE 0x00000200 + +#define InitializeObjectAttributes(p, n, a, r, s) { \ + (p)->Length = sizeof(OBJECT_ATTRIBUTES); \ + (p)->RootDirectory = r; \ + (p)->Attributes = a; \ + (p)->ObjectName = n; \ + (p)->SecurityDescriptor = s; \ + (p)->SecurityQualityOfService = NULL; \ + } + +VOID (WINAPI *pRtlInitUnicodeString)(PUNICODE_STRING DestinationString, + PCWSTR SourceString); + +NTSTATUS (WINAPI *pZwDeleteFile)(POBJECT_ATTRIBUTES ObjectAttributes); + +NTSTATUS (WINAPI *pZwCreateFile)(PHANDLE FileHandle, + ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, + PIO_STATUS_BLOCK IoStatusBlock, PVOID AllocationSize, + ULONG FileAttributes, ULONG ShareAccess, ULONG CreateDisposition, + ULONG CreateOptions, PVOID EaBuffer, ULONG EaLength); + +NTSTATUS (WINAPI *pZwSetInformationFile)(HANDLE FileHandle, + PIO_STATUS_BLOCK IoStatusBlock, PVOID FileInformation, ULONG Length, + FILE_INFORMATION_CLASS FileInformationClass); + +void write_file(const char *fname, const char *s) +{ + FILE *fp = fopen(fname, "wb"); + if(fp != NULL) { + fputs(s, fp); + fclose(fp); + } +} + +int main() +{ + printf( + "Going to try to delete files using various techiques.\n" + "Note that the MoveFileEx method will fail (see source why)\n" + ); + + write_file("abc.txt", "DeleteFile"); + + // + // delete the file using the well-known DeleteFile function + // + + printf("DeleteFile: %s (0x%08x)\n", DeleteFile("abc.txt") ? + "SUCCESS" : "FAILURE", GetLastError()); + + write_file("abc.txt", "MoveFileEx"); + + // + // delete the file using MoveFileEx, note that a NULL destination filename + // is only supported when the MOVEFILE_DELAY_UNTIL_REBOOT flag is set. + // (so this call will actually fail..) + // + + printf("MoveFileEx: %s (0x%08x)\n", MoveFileEx("abc.txt", NULL, 0) ? + "SUCCESS" : "FAILURE", GetLastError()); + + write_file("abc.txt", "ZwDeleteFile"); + + // + // delete the file using ZwDeleteFile + // + + UNICODE_STRING dir_fname, file_fname; + OBJECT_ATTRIBUTES obj_dir, obj_file; + IO_STATUS_BLOCK io_dir; + HANDLE dir_handle; + + *(FARPROC *) &pRtlInitUnicodeString = GetProcAddress( + GetModuleHandle("ntdll"), "RtlInitUnicodeString"); + *(FARPROC *) &pZwDeleteFile = GetProcAddress( + GetModuleHandle("ntdll"), "ZwDeleteFile"); + *(FARPROC *) &pZwCreateFile = GetProcAddress( + GetModuleHandle("ntdll"), "ZwCreateFile"); + *(FARPROC *) &pZwSetInformationFile = GetProcAddress( + GetModuleHandle("ntdll"), "ZwSetInformationFile"); + + // prepend the path with "\\??\\" + wchar_t cur_dir[MAX_PATH] = L"\\??\\"; + GetCurrentDirectoryW(MAX_PATH-4, cur_dir+4); + + pRtlInitUnicodeString(&dir_fname, cur_dir); + pRtlInitUnicodeString(&file_fname, L"abc.txt"); + + InitializeObjectAttributes(&obj_dir, &dir_fname, + OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); + + // open the directory + NTSTATUS ret = pZwCreateFile(&dir_handle, FILE_TRAVERSE, &obj_dir, + &io_dir, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN, + FILE_DIRECTORY_FILE, NULL, 0); + + if(NT_SUCCESS(ret)) { + InitializeObjectAttributes(&obj_file, &file_fname, + OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, dir_handle, NULL); + + // delete the file + ret = pZwDeleteFile(&obj_file); + printf("ZwDeleteFile: %s (0x%08x)\n", NT_SUCCESS(ret) ? + "SUCCESS" : "FAILURE", ret); + CloseHandle(dir_handle); + } + else { + printf("ZwDeleteFile: FAILURE (0x%08x)\n", ret); + } + + write_file("abc.txt", "ZwSetInformationFile"); + + // + // delete the file using ZwSetInformationFile + // + + IO_STATUS_BLOCK io_file; + HANDLE file_handle; + + // prepend the path with "\\??\\" and append "abc.txt" + wchar_t file_name[MAX_PATH] = L"\\??\\"; + GetCurrentDirectoryW(MAX_PATH-4, file_name+4); + lstrcatW(file_name, L"\\abc.txt"); + + pRtlInitUnicodeString(&file_fname, file_name); + InitializeObjectAttributes(&obj_file, &file_fname, + OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); + + // open the file with DELETE access rights + ret = pZwCreateFile(&file_handle, DELETE, &obj_file, &io_file, NULL, + FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN, 0, NULL, 0); + if(NT_SUCCESS(ret)) { + BOOLEAN disp_info = TRUE; + ret = pZwSetInformationFile(file_handle, &io_file, &disp_info, + sizeof(disp_info), FileDispositionInformation); + CloseHandle(file_handle); + + printf("ZwSetInformationFile: %s (0x%08x)\n", NT_SUCCESS(ret) ? + "SUCCESS" : "FAILURE", ret); + } + else { + printf("ZwSetInformationFile: FAILURE (0x%08x)\n", ret); + } +} diff --git a/tests/getcursorpos.c b/tests/getcursorpos.c new file mode 100644 index 0000000..2773b7e --- /dev/null +++ b/tests/getcursorpos.c @@ -0,0 +1,29 @@ +/* +Cuckoo Sandbox - Automated Malware Analysis +Copyright (C) 2010-2014 Cuckoo Sandbox Developers + +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 . +*/ + +#include +#include + +int main() +{ + for (int i = 0; i < 10; i++) { + POINT p = {}; GetCursorPos(&p); + printf("{x: %ld, y: %ld}\n", p.x, p.y); + Sleep(100); + } +} diff --git a/tests/logging.c b/tests/logging.c new file mode 100644 index 0000000..9244248 --- /dev/null +++ b/tests/logging.c @@ -0,0 +1,33 @@ +#include +#include +#include "../log.h" + +const char *module_name = "logging"; + +int main() +{ + int is_success(int ret) { return 1; } + int ret = 0; + + log_init(0, 0, 1); + + LOQ("2s", "a", "b", "c", "d"); + LOQ("S", "a", 4, "hello"); + LOQ("U", "b", 4, L"ab\u1337c"); + LOQ("s", "c", NULL); + LOQ("lUl", "a", 32, "b", 6, L"HelloWorld", "c", 32); + + // utf8 encoding examples from wikipedia, should result in the following: + // "\x24\xc2\xa2\xe2\x82\xac" + LOQ("u", "a", L"\u0024\u00a2\u20ac"); + + int argc = 4; + char *argv[] = {"a", "b", "c", "d"}; + LOQ("a", "a", argc, argv); + + // registry stuff + LOQ("r", "a", REG_SZ, 0, "lolz"); + LOQ("r", "a", REG_DWORD, 4, "\x10\x00\x00\x00"); + LOQ("R", "a", REG_SZ, 1337, L"omgz0r"); + LOQ("R", "a", REG_BINARY, 8, "Hello World"); +} diff --git a/tests/lookup.c b/tests/lookup.c new file mode 100644 index 0000000..cbd43e9 --- /dev/null +++ b/tests/lookup.c @@ -0,0 +1,31 @@ +#include +#include +#include "lookup.h" + +typedef struct _entry_t { + struct _entry_t *next; + unsigned int id; + unsigned int size; + unsigned char data[0]; +} entry_t; + +int main() +{ + lookup_t a; + + lookup_init(&a); + strcpy((char *) lookup_add(&a, 1, 10), "abc"); + strcpy((char *) lookup_add(&a, 2, 20), "def"); + lookup_del(&a, 1); + strcpy((char *) lookup_add(&a, 3, 30), "ghi"); + strcpy((char *) lookup_add(&a, 4, 40), "jkl"); + lookup_del(&a, 4); + + for (int i = 0; i < 5; i++) { + printf("%d -> %p\n", i, lookup_get(&a, i, NULL)); + } + + for (entry_t *p = a.root; p != NULL; p = p->next) { + printf("%p %d %d\n", p, p->id, p->size); + } +} diff --git a/tests/migrate-process.c b/tests/migrate-process.c new file mode 100644 index 0000000..9734fe4 --- /dev/null +++ b/tests/migrate-process.c @@ -0,0 +1,8 @@ +#include +#include + +int main() +{ + // process identifier of explorer.exe on my VM + CloseHandle(OpenProcess(PROCESS_ALL_ACCESS, FALSE, 468)); +} diff --git a/tests/mitigate-process.c b/tests/mitigate-process.c new file mode 100644 index 0000000..5336c06 --- /dev/null +++ b/tests/mitigate-process.c @@ -0,0 +1,32 @@ +#include +#include + +/* multiple ways to inject into another process */ + +int main(int argc, char *argv[]) +{ + if(argc == 2) { + printf("Child process %s.. exiting..\n", argv[1]); + ExitProcess(0); + } + + char buf[256]; + + // WinExec + sprintf(buf, "\"%s\" a", argv[0]); + WinExec(buf, SW_SHOW); + + // ShellExecute + ShellExecute(NULL, NULL, argv[0], "b", NULL, SW_SHOW); + + // CreateProcess + sprintf(buf, "\"%s\" c", argv[0]); + STARTUPINFO si = {sizeof(si)}; PROCESS_INFORMATION pi = {}; + CreateProcess(NULL, buf, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); + + // system + sprintf(buf, "\"%s\" d", argv[0]); + system(buf); + + return 0; +} diff --git a/tests/mousebutton-count.c b/tests/mousebutton-count.c new file mode 100644 index 0000000..32d7311 --- /dev/null +++ b/tests/mousebutton-count.c @@ -0,0 +1,25 @@ +/* +Cuckoo Sandbox - Automated Malware Analysis +Copyright (C) 2010-2014 Cuckoo Sandbox Developers + +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 . +*/ + +#include +#include + +int main() +{ + printf("count: %d\n", GetSystemMetrics(SM_CMOUSEBUTTONS)); +} diff --git a/tests/open-protected-pid.c b/tests/open-protected-pid.c new file mode 100644 index 0000000..25f4115 --- /dev/null +++ b/tests/open-protected-pid.c @@ -0,0 +1,10 @@ +#include +#include + +int main() +{ + // this is the process identifier of agent.py on my VM + HANDLE process_handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, 1576); + printf("process-handle: %p -> %d\n", process_handle, GetLastError()); + return 0; +} diff --git a/tests/peb-check.c b/tests/peb-check.c new file mode 100644 index 0000000..2b01a4d --- /dev/null +++ b/tests/peb-check.c @@ -0,0 +1,29 @@ +/* +Cuckoo Sandbox - Automated Malware Analysis +Copyright (C) 2010-2014 Cuckoo Sandbox Developers + +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 . +*/ + +#include +#include + +int main() +{ + LoadLibrary("../cuckoomon.dll"); + + HMODULE cuckoomon_handle = GetModuleHandle("cuckoomon.dll"); + printf("cuckoomon -> 0x%08x\n", cuckoomon_handle); + return 0; +} diff --git a/tests/sleep.c b/tests/sleep.c new file mode 100644 index 0000000..3e5066e --- /dev/null +++ b/tests/sleep.c @@ -0,0 +1,30 @@ +#include +#include + +DWORD WINAPI thread(LPVOID lpNothing) +{ + return 0; +} + +int main() +{ + LoadLibrary("../cuckoomon.dll"); + + // sleep for five seconds (skipped) + for (int i = 0; i < 100; i++) { + Sleep(50); + + printf("tick: %ld\n", GetTickCount()); + } + + // sleep for 10 seconds (skipped) + Sleep(10000); + + printf("tick: %ld\n", GetTickCount()); + + printf("starting second thread\n"); + CloseHandle(CreateThread(NULL, 0, &thread, NULL, 0, NULL)); + + // sleep for 5 seconds (not skipped) + Sleep(5000); +} diff --git a/tests/sleep2.c b/tests/sleep2.c new file mode 100644 index 0000000..605941b --- /dev/null +++ b/tests/sleep2.c @@ -0,0 +1,24 @@ +#include +#include + +int main() +{ + LoadLibrary("../cuckoomon.dll"); + + unsigned int start = GetTickCount(); + printf("%d\n", start); + + Sleep(1000); + + printf("%d -> %d\n", GetTickCount(), GetTickCount() - start); + + for (int i = 0; i < 10; i++) { + for (int j = 0; j < 0xfffffff; j++); + } + + printf("%d -> %d\n", GetTickCount(), GetTickCount() - start); + + Sleep(1000); + + printf("%d -> %d\n", GetTickCount(), GetTickCount() - start); +} diff --git a/tests/startup-time.c b/tests/startup-time.c new file mode 100644 index 0000000..abf33c3 --- /dev/null +++ b/tests/startup-time.c @@ -0,0 +1,16 @@ +#include +#include +#include + +// Idea originally taken from the following article +// http://spth.virii.lu/v4/articles/m0sa/evade.html + +int main() +{ + if(GetTickCount() < 10 * 60 * 1000) { + printf("Running under a VM!\n"); + } + else { + printf("This computer is ok! Uptime: %d\n", GetTickCount()); + } +} diff --git a/tests/suspended-process.c b/tests/suspended-process.c new file mode 100644 index 0000000..c4b883a --- /dev/null +++ b/tests/suspended-process.c @@ -0,0 +1,30 @@ +#include +#include + +int main(int argc, char *argv[]) +{ + if(argc != 1) { + printf("arg: %s\n", argv[1]); + fflush(stdout); + return 1337; + } + + STARTUPINFO si = {sizeof(si)}; PROCESS_INFORMATION pi; char buf[256]; + + sprintf(buf, "\"%s\" a", argv[0]); + + BOOL ret = CreateProcess(argv[0], buf, NULL, NULL, FALSE, + CREATE_SUSPENDED, NULL, NULL, &si, &pi); + + printf("ret: %d\n", ret); + fflush(stdout); + + ResumeThread(pi.hThread); + WaitForSingleObject(pi.hThread, INFINITE); + WaitForSingleObject(pi.hProcess, INFINITE); + + DWORD exit_code; + GetExitCodeProcess(pi.hProcess, &exit_code); + printf("ret: %d\n", exit_code); + fflush(stdout); +} diff --git a/tests/test-dns.c b/tests/test-dns.c new file mode 100644 index 0000000..58783cf --- /dev/null +++ b/tests/test-dns.c @@ -0,0 +1,19 @@ +#define _WIN32_WINNT 0x0501 +#include +#include +#include +#include + +int main() +{ + LoadLibrary("../cuckoomon.dll"); + + printf("DnsQuery -> %d\n", DnsQuery("jbremer.org", DNS_TYPE_A, + DNS_QUERY_STANDARD, NULL, NULL, NULL)); + + struct addrinfo *info = NULL; + printf("getaddrinfo -> %d\n", getaddrinfo("jbremer.org", NULL, NULL, + &info)); + + printf("gethostbyname -> %p\n", gethostbyname("jbremer.org")); +} diff --git a/tests/test-lasterr.c b/tests/test-lasterr.c new file mode 100644 index 0000000..dc25663 --- /dev/null +++ b/tests/test-lasterr.c @@ -0,0 +1,60 @@ +#include +#include +#include "hooking.h" +#include "ntapi.h" + +#define HOOK(library, funcname) {L###library, #funcname, NULL, \ + &New_##funcname##0, (void **) &Old_##funcname##0} + +HOOKDEF(BOOL, WINAPI, DeleteFileW0, + __in LPWSTR lpFileName +) { + BOOL ret = Old_DeleteFileW0(lpFileName); + + printf("ret: %d, lasterr: %d, %d\n", ret, GetLastError(), + hook_get_last_error()); + + SetLastError(0x1337); + + printf("ret: %d, lasterr: %d, %d\n", ret, GetLastError(), + hook_get_last_error()); + + hook_set_last_error(0xb00b); + + printf("ret: %d, lasterr: %d, %d\n", ret, GetLastError(), + hook_get_last_error()); + + return ret; +} + +HOOKDEF(NTSTATUS, WINAPI, NtOpenFile0, + __out PHANDLE FileHandle, + __in ACCESS_MASK DesiredAccess, + __in POBJECT_ATTRIBUTES ObjectAttributes, + __out PIO_STATUS_BLOCK IoStatusBlock, + __in ULONG ShareAccess, + __in ULONG OpenOptions +) { + NTSTATUS ret = Old_NtOpenFile0(FileHandle, DesiredAccess, ObjectAttributes, + IoStatusBlock, ShareAccess, OpenOptions); + SetLastError(0x1338); + printf("OMG!!! %d\n", GetLastError()); + return ret; +} + +int main() +{ + static hook_t hook[] = { + HOOK(kernel32, DeleteFileW), + HOOK(ntdll, NtOpenFile), + }; + + DWORD old_protect; + VirtualProtect(hook, sizeof(hook), PAGE_EXECUTE_READWRITE, &old_protect); + + hook_api(&hook[0], HOOK_JMP_DIRECT); + hook_api(&hook[1], HOOK_JMP_DIRECT); + + DeleteFile("hoi"); + printf("lasterr: %d\n", GetLastError()); +} diff --git a/tests/test-lde.c b/tests/test-lde.c new file mode 100644 index 0000000..48bc1d0 --- /dev/null +++ b/tests/test-lde.c @@ -0,0 +1,15 @@ +#include +#include "../hooking.h" + +int main() +{ + unsigned char b[][8] = { + {0x55}, + {0x89, 0xe5}, + {0x83, 0xec, 0x18}, + }; + + for (int i = 0; i < sizeof(b)/sizeof(b[0]); i++) { + printf("%d\n", lde(b[i])); + } +} diff --git a/tests/wininet.c b/tests/wininet.c new file mode 100644 index 0000000..754c611 --- /dev/null +++ b/tests/wininet.c @@ -0,0 +1,33 @@ +#include +#include +#include + +int print_url_contents(const char *url) +{ + HINTERNET internet_handle, request_handle; + char buffer[1024]; unsigned long bytes_read; + + internet_handle = InternetOpen(NULL, INTERNET_OPEN_TYPE_DIRECT, NULL, + NULL, 0); + if(internet_handle == NULL) return FALSE; + + request_handle = InternetOpenUrl(internet_handle, url, NULL, 0, 0, 0); + if(request_handle == NULL) { + InternetCloseHandle(internet_handle); + return FALSE; + } + + while (InternetReadFile(request_handle, buffer, sizeof(buffer), + &bytes_read) != FALSE && bytes_read != 0) { + fwrite(buffer, bytes_read, 1, stderr); + } + + InternetCloseHandle(internet_handle); + InternetCloseHandle(request_handle); + return TRUE; +} + +int main() +{ + print_url_contents("http://jbremer.org/"); +} diff --git a/tests/write-file.c b/tests/write-file.c new file mode 100644 index 0000000..9c7d279 --- /dev/null +++ b/tests/write-file.c @@ -0,0 +1,30 @@ +#include +#include + +int main() +{ + const char *fnames[] = { + "C:\\a.txt", + "C:\\b.txt", + "C:\\c.txt", + "C:\\d.txt", + "C:\\e.txt", + }; + + FILE *fp[3]; + for (int i = 0; i < 5; i++) { + fp[i] = fopen(fnames[i], "w"); + } + + for (int i = 0; i < 20; i++) { + fprintf(fp[rand() % 5], "Hello %d\n", i); + } + + for (int i = 0; i < 20; i++) { + int idx = rand() % 5; + if(fp[idx] != NULL) { + fclose(fp[idx]); + fp[idx] = NULL; + } + } +} diff --git a/utf8.c b/utf8.c new file mode 100644 index 0000000..7193787 --- /dev/null +++ b/utf8.c @@ -0,0 +1,98 @@ +/* +Cuckoo Sandbox - Automated Malware Analysis +Copyright (C) 2010-2014 Cuckoo Sandbox Developers + +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 . +*/ + +#include +#include +#include "utf8.h" + +int utf8_encode(unsigned short c, unsigned char *out) +{ + if(c < 0x80) { + *out = c & 0x7f; + return 1; + } + else if(c < 0x800) { + *out = 0xc0 + ((c >> 8) << 2) + (c >> 6); + out[1] = 0x80 + (c & 0x3f); + return 2; + } + else { + *out = 0xe0 + (c >> 12); + out[1] = 0x80 + (((c >> 8) & 0x1f) << 2) + ((c >> 6) & 0x3); + out[2] = 0x80 + (c & 0x3f); + return 3; + } +} + +int utf8_length(unsigned short x) +{ + unsigned char buf[3]; + return utf8_encode(x, buf); +} + +int utf8_strlen_ascii(const char *s, int len) +{ + if(len < 0) len = strlen(s); + + int ret = 0; + while (len-- != 0) { + ret += utf8_length(*s++); + } + return ret; +} + +int utf8_strlen_unicode(const wchar_t *s, int len) +{ + if(len < 0) len = lstrlenW(s); + + int ret = 0; + while (len-- != 0) { + ret += utf8_length(*s++); + } + return ret; +} + +char * utf8_string(const char *str, int length) +{ + if (length == -1) length = strlen(str); + + int encoded_length = utf8_strlen_ascii(str, length); + char * utf8string = (char *) malloc(encoded_length+4); + *((int *) utf8string) = encoded_length; + int pos = 4; + + while (length-- != 0) { + pos += utf8_encode(*str++, (unsigned char *) &utf8string[pos]); + } + return utf8string; +} + +char * utf8_wstring(const wchar_t *str, int length) +{ + if (length == -1) length = lstrlenW(str); + + int encoded_length = utf8_strlen_unicode(str, length); + char * utf8string = (char *) malloc(encoded_length+4); + *((int *) utf8string) = encoded_length; + int pos = 4; + + while (length-- != 0) { + pos += utf8_encode(*str++, (unsigned char *) &utf8string[pos]); + } + return utf8string; +} \ No newline at end of file diff --git a/utf8.h b/utf8.h new file mode 100644 index 0000000..30dff04 --- /dev/null +++ b/utf8.h @@ -0,0 +1,28 @@ +/* +Cuckoo Sandbox - Automated Malware Analysis +Copyright (C) 2010-2014 Cuckoo Sandbox Developers + +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 . +*/ + +int utf8_encode(unsigned short x, unsigned char *out); +int utf8_length(unsigned short x); + +// name is a bit weird.. but it calculates the length of the utf8 encoded +// ascii/unicode string "s" in bytes +int utf8_strlen_ascii(const char *s, int len); +int utf8_strlen_unicode(const wchar_t *s, int len); + +char * utf8_string(const char *str, int length); +char * utf8_wstring(const wchar_t *str, int length);