diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0aeeff8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,12 @@ +*.o +.theos/* +debs/* +*.deb +*.dylib +**/.theos/* +*/.theos/* +*.psd +_/* +*/obj/* +obj/* +*.zip \ No newline at end of file diff --git a/LICENSE b/LICENSE deleted file mode 100644 index f288702..0000000 --- a/LICENSE +++ /dev/null @@ -1,674 +0,0 @@ - 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 index cda0273..728542b 100644 --- a/Makefile +++ b/Makefile @@ -1,15 +1,28 @@ -ARCHS = arm64 arm64e +GO_EASY_ON_ME = 1 +DEBUG = 0 +FINALPACKAGE = 1 + +THEOS_DEVICE_IP = 0.0.0.0 -p 2222 + +TARGET := iphone:clang:latest:12.0 +ARCHS = arm64 include $(THEOS)/makefiles/common.mk TOOL_NAME = vnodebypass -vnodebypass_FILES = main.m offsets.m +vnodebypass_FILES = main.m vnode.m libdimentio.c kernel.m vnodebypass_CFLAGS = -fobjc-arc +vnodebypass_CODESIGN_FLAGS = -Sent.plist +vnodebypass_INSTALL_PATH = /usr/bin +vnodebypass_FRAMEWORKS = IOKit include $(THEOS_MAKE_PATH)/tool.mk +SUBPROJECTS += app +SUBPROJECTS += debian-script +include $(THEOS_MAKE_PATH)/aggregate.mk -internal-stage:: - $(ECHO_NOTHING)ldid -S$(THEOS_STAGING_DIR)/../../tfp0.plist $(THEOS_STAGING_DIR)/usr/bin/vnodebypass$(ECHO_END) - $(ECHO_NOTHING)chown 0:0 $(THEOS_STAGING_DIR)/usr/bin/vnodebypass$(ECHO_END) - $(ECHO_NOTHING)chmod 6755 $(THEOS_STAGING_DIR)/usr/bin/vnodebypass$(ECHO_END) \ No newline at end of file +before-package:: + chmod -R 755 $(THEOS_STAGING_DIR) + chmod 6755 $(THEOS_STAGING_DIR)/usr/bin/vnodebypass + chmod 666 $(THEOS_STAGING_DIR)/DEBIAN/control diff --git a/README.md b/README.md index acc8251..2f5dfee 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# vnodebypass -vnodebypass using hidePath of jelbrekLib(Jakeashacks) and maphys (0x7ff) - - *Special Thanks to akusio. +vnodebypass +===================== + +### An expermental tool to hide jailbreak files for bypass detection. diff --git a/SVC_Caller.h b/SVC_Caller.h new file mode 100644 index 0000000..e85e231 --- /dev/null +++ b/SVC_Caller.h @@ -0,0 +1,22 @@ +#include +#include + +inline int SVC_Access(const char* detectionPath) { + +#if defined __arm64__ || defined __arm64e__ + int64_t flag = 0; + __asm __volatile("mov x0, %0" :: "r" (detectionPath)); //path + __asm __volatile("mov x1, #0"); //mode + __asm __volatile("mov x16, #0x21"); //access + __asm __volatile("svc #0x80"); //supervisor call + __asm __volatile("mov %0, x0" : "=r" (flag)); +#else + int flag = 0; + __asm __volatile("mov r0, %0" :: "r" (detectionPath)); //path + __asm __volatile("mov r1, #0"); //mode + __asm __volatile("mov r12, #0x21"); //access + __asm __volatile("svc #0x80"); //supervisor call + __asm __volatile("mov %0, r0" : "=r" (flag)); +#endif + return flag; +} \ No newline at end of file diff --git a/app/AppDelegate.h b/app/AppDelegate.h new file mode 100644 index 0000000..4938d6e --- /dev/null +++ b/app/AppDelegate.h @@ -0,0 +1,8 @@ +#import + +@interface AppDelegate : UIResponder + +@property(nonatomic, strong) UIWindow *window; +@property(nonatomic, strong) UIViewController *rootViewController; + +@end diff --git a/app/AppDelegate.m b/app/AppDelegate.m new file mode 100644 index 0000000..474c452 --- /dev/null +++ b/app/AppDelegate.m @@ -0,0 +1,13 @@ +#import "AppDelegate.h" +#import "RootViewController.h" + +@implementation AppDelegate + +- (void)applicationDidFinishLaunching:(UIApplication *)application { + _window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; + _rootViewController = [[RootViewController alloc] init]; + _window.rootViewController = _rootViewController; + [_window makeKeyAndVisible]; +} + +@end diff --git a/app/Makefile b/app/Makefile new file mode 100644 index 0000000..136649e --- /dev/null +++ b/app/Makefile @@ -0,0 +1,15 @@ +TARGET := iphone:clang:latest:7.0 +INSTALL_TARGET_PROCESSES = vnodebypass + +ARCHS = arm64 + +include $(THEOS)/makefiles/common.mk + +APPLICATION_NAME = vnodebypass + +vnodebypass_FILES = main.m AppDelegate.m RootViewController.m +vnodebypass_FRAMEWORKS = UIKit CoreGraphics +vnodebypass_CFLAGS = -fobjc-arc -I../include +vnodebypass_CODESIGN_FLAGS = -Sappent.xml + +include $(THEOS_MAKE_PATH)/application.mk diff --git a/app/Resources/AppIcon60x60@2x.png b/app/Resources/AppIcon60x60@2x.png new file mode 100644 index 0000000..59dd501 Binary files /dev/null and b/app/Resources/AppIcon60x60@2x.png differ diff --git a/app/Resources/AppIcon76x76@2x~ipad.png b/app/Resources/AppIcon76x76@2x~ipad.png new file mode 100644 index 0000000..0933520 Binary files /dev/null and b/app/Resources/AppIcon76x76@2x~ipad.png differ diff --git a/app/Resources/Info.plist b/app/Resources/Info.plist new file mode 100644 index 0000000..cd73321 --- /dev/null +++ b/app/Resources/Info.plist @@ -0,0 +1,79 @@ + + + + + BuildMachineOSBuild + 20D91 + CFBundleDevelopmentRegion + en + CFBundleExecutable + vnodebypass + CFBundleIconFiles + + AppIcon60x60@2x.png + AppIcon76x76@2x~ipad.png + + CFBundleIdentifier + kr.xsf1re.vnodebypass + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + vnodebypass + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSupportedPlatforms + + iPhoneOS + + CFBundleVersion + 1 + DTCompiler + com.apple.compilers.llvm.clang.1_0 + DTPlatformBuild + 18D46 + DTPlatformName + iphoneos + DTPlatformVersion + 14.4 + DTSDKBuild + 18D46 + DTSDKName + iphoneos14.4 + DTXcode + 1240 + DTXcodeBuild + 12D4e + LSRequiresIPhoneOS + + MinimumOSVersion + 12.0 + UIApplicationSupportsIndirectInputEvents + + UIDeviceFamily + + 1 + 2 + + UILaunchStoryboardName + LaunchScreen + UIRequiredDeviceCapabilities + + arm64 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/app/RootViewController.h b/app/RootViewController.h new file mode 100644 index 0000000..086df18 --- /dev/null +++ b/app/RootViewController.h @@ -0,0 +1,8 @@ +#import +#import + +@interface RootViewController : UIViewController +@property UILabel *titleLabel; +@property UILabel *subtitleLabel; +@property UIButton *button; +@end diff --git a/app/RootViewController.m b/app/RootViewController.m new file mode 100644 index 0000000..a44397d --- /dev/null +++ b/app/RootViewController.m @@ -0,0 +1,70 @@ +#import "RootViewController.h" + +@interface RootViewController () +@end + +@implementation RootViewController + +- (void)loadView { + [super loadView]; + + self.view.backgroundColor = UIColor.blackColor; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + + _titleLabel = + [[UILabel alloc] initWithFrame:CGRectMake(0, 50, UIScreen.mainScreen.bounds.size.width, 100)]; + _titleLabel.text = @"vnodebypass"; + _titleLabel.textAlignment = NSTextAlignmentCenter; + _titleLabel.textColor = UIColor.whiteColor; + _titleLabel.font = [UIFont systemFontOfSize:40]; + [self.view addSubview:_titleLabel]; + + _subtitleLabel = [[UILabel alloc] + initWithFrame:CGRectMake(0, 100, UIScreen.mainScreen.bounds.size.width, 100)]; + _subtitleLabel.text = @"USE IT AT YOUR OWN RISK!"; + _subtitleLabel.textAlignment = NSTextAlignmentCenter; + _subtitleLabel.textColor = UIColor.whiteColor; + _subtitleLabel.font = [UIFont systemFontOfSize:20]; + [self.view addSubview:_subtitleLabel]; + + _button = [UIButton buttonWithType:UIButtonTypeSystem]; + _button.frame = CGRectMake(UIScreen.mainScreen.bounds.size.width / 2 - 30, + UIScreen.mainScreen.bounds.size.height / 2 - 25, 60, 50); + [_button setTitle:access("/bin/bash", F_OK) == 0 ? @"Enable" : @"Disable" + forState:UIControlStateNormal]; + [_button addTarget:self + action:@selector(buttonPressed:) + forControlEvents:UIControlEventTouchUpInside]; + [self.view addSubview:_button]; +} + +- (void)buttonPressed:(UIButton *)sender { + BOOL disabled = access("/bin/bash", F_OK) == 0; + NSArray *opts; + if (disabled) { + opts = @[ @"-s", @"-h" ]; + } else { + opts = @[ @"-r", @"-R" ]; + } + + NSString *launchPath = + [NSString stringWithFormat:@"/usr/bin/%@", NSProcessInfo.processInfo.processName]; + NSTask *task = [NSTask launchedTaskWithLaunchPath:launchPath arguments:@[ opts[0] ]]; + [task waitUntilExit]; + task = [NSTask launchedTaskWithLaunchPath:launchPath arguments:@[ opts[1] ]]; + [task waitUntilExit]; + NSString *title = access("/bin/bash", F_OK) == 0 ? @"Enable" : @"Disable"; + NSString *successTitle = (access("/bin/bash", F_OK) == 0) == disabled ? @"Failed" : @"Success"; + [_button setTitle:successTitle forState:UIControlStateNormal]; + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + sleep(1); + dispatch_async(dispatch_get_main_queue(), ^{ + [_button setTitle:title forState:UIControlStateNormal]; + }); + }); +} + +@end diff --git a/app/appent.xml b/app/appent.xml new file mode 100644 index 0000000..a60b848 --- /dev/null +++ b/app/appent.xml @@ -0,0 +1,24 @@ + + + + + platform-application + + com.apple.private.security.container-required + + com.apple.springboard.debugapplicationsget-task-allow + + com.apple.private.skip-library-validation + + proc_info-allow + + get-task-allow + + task_for_pid-allow + + run-unsigned-code + + com.apple.private.security.no-container + + + diff --git a/app/main.m b/app/main.m new file mode 100644 index 0000000..de7c86e --- /dev/null +++ b/app/main.m @@ -0,0 +1,7 @@ +#import "AppDelegate.h" + +int main(int argc, char *argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass(AppDelegate.class)); + } +} diff --git a/control b/control index 9542a75..0a3adf0 100644 --- a/control +++ b/control @@ -1,9 +1,12 @@ -Package: kr.xsf1re.vnodebypass -Name: vnodeBypass -Version: 0.0.1 -Architecture: iphoneos-arm -Description: An awesome tool of some sort!! -Maintainer: XsF1re Author: XsF1re +Maintainer: ichitaso +Package: kr.xsf1re.vnodebypass +Name: vnodebypass +Depends: firmware (>= 12.0) Section: System -Tag: role::hacker +Version: 0.2.9 +Architecture: iphoneos-arm +Description: An expermental tool to hide jailbreak files for bypass detection. +Depiction: https://cydia.ichitaso.com/depiction/vnodebypass.html +Tag: role::hacker, compatible::ios12, compatible::ios13, compatible::ios14 +Icon: https://raw.githubusercontent.com/ichitaso/vnodebypass_theme/main/layout/Library/Themes/vnodebypass.theme/Icon.png diff --git a/debian-script/Makefile b/debian-script/Makefile new file mode 100644 index 0000000..6d411fe --- /dev/null +++ b/debian-script/Makefile @@ -0,0 +1,19 @@ +TARGET := iphone:clang:latest:12.0 + +ARCHS = arm64 + +include $(THEOS)/makefiles/common.mk + +TOOL_NAME = postinst prerm + +postinst_FILES = main.m +postinst_CFLAGS = -fobjc-arc -I../include +postinst_CODESIGN_FLAGS = -Sentitlements.plist +postinst_INSTALL_PATH = /DEBIAN + +prerm_FILES = main.m +prerm_CFLAGS = -fobjc-arc -I../include +prerm_CODESIGN_FLAGS = -Sentitlements.plist +prerm_INSTALL_PATH = /DEBIAN + +include $(THEOS_MAKE_PATH)/tool.mk diff --git a/debian-script/entitlements.plist b/debian-script/entitlements.plist new file mode 100644 index 0000000..0a48302 --- /dev/null +++ b/debian-script/entitlements.plist @@ -0,0 +1,9 @@ + + + + platform-application + + com.apple.private.security.container-required + + + diff --git a/debian-script/main.m b/debian-script/main.m new file mode 100644 index 0000000..2206c0b --- /dev/null +++ b/debian-script/main.m @@ -0,0 +1,73 @@ +#import +#import +#include + +int main(int argc, char *argv[], char *envp[]) { + @autoreleasepool { + NSTask *task = [NSTask new]; + task.launchPath = @"/usr/bin/uicache"; + + BOOL isRemoving = [NSProcessInfo.processInfo.processName containsString:@"prerm"]; + BOOL isUpgrading = strstr(argv[1], "upgrade"); + + if (isRemoving || isUpgrading) { + NSArray *fileList = + [[NSString stringWithContentsOfFile:@"/var/lib/dpkg/info/kr.xsf1re.vnodebypass.list" + encoding:NSUTF8StringEncoding + error:nil] componentsSeparatedByString:@"\n"]; + NSInteger appPathIndex = + [fileList indexOfObjectPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) { + return [obj hasSuffix:@".app"]; + }]; + if (appPathIndex != NSNotFound) { + task.arguments = @[ @"-u", fileList[appPathIndex] ]; + [task launch]; + [task waitUntilExit]; + } else { + printf("Could not find vnodebypass.app, skipping uicache\n"); + } + if (isRemoving) return 0; + } + + NSString *randomName = [[NSUUID UUID].UUIDString componentsSeparatedByString:@"-"].firstObject; + + NSMutableDictionary *appInfo = [NSMutableDictionary + dictionaryWithContentsOfFile:@"/Applications/vnodebypass.app/Info.plist"]; + appInfo[@"CFBundleExecutable"] = randomName; + [appInfo writeToFile:@"/Applications/vnodebypass.app/Info.plist" atomically:YES]; + + NSArray *renames = @[ + @[ @"/usr/bin/vnodebypass", @"/usr/bin/%@" ], + @[ @"/Applications/vnodebypass.app/vnodebypass", @"/Applications/vnodebypass.app/%@" ], + @[ @"/Applications/vnodebypass.app", @"/Applications/%@.app" ], + @[ @"/usr/share/vnodebypass", @"/usr/share/%@" ] + ]; + + for (NSArray *rename in renames) { + NSString *oldPath = rename[0]; + NSString *newPath = [NSString stringWithFormat:rename[1], randomName]; + NSError *error; + [[NSFileManager defaultManager] moveItemAtPath:oldPath toPath:newPath error:&error]; + if (error) { + printf("Failed to rename %s: %s\n", oldPath.UTF8String, + error.localizedDescription.UTF8String); + return 1; + } + } + + NSString *dpkgInfo = + [NSString stringWithContentsOfFile:@"/var/lib/dpkg/info/kr.xsf1re.vnodebypass.list" + encoding:NSUTF8StringEncoding + error:nil]; + dpkgInfo = [dpkgInfo stringByReplacingOccurrencesOfString:@"vnodebypass" withString:randomName]; + [dpkgInfo writeToFile:@"/var/lib/dpkg/info/kr.xsf1re.vnodebypass.list" + atomically:YES + encoding:NSUTF8StringEncoding + error:nil]; + + task.arguments = @[ @"-p", [NSString stringWithFormat:@"/Applications/%@.app", randomName] ]; + [task launch]; + [task waitUntilExit]; + return 0; + } +} diff --git a/tfp0.plist b/ent.plist similarity index 85% rename from tfp0.plist rename to ent.plist index bedde22..276df26 100644 --- a/tfp0.plist +++ b/ent.plist @@ -10,5 +10,7 @@ com.apple.private.security.no-container + com.apple.private.kernel.get-kext-info + diff --git a/include/NSTask.h b/include/NSTask.h new file mode 100644 index 0000000..03d3914 --- /dev/null +++ b/include/NSTask.h @@ -0,0 +1,76 @@ +// +// NSTask.h +// ipacracker +// +// Created by obaby on 14-2-10. +// +// +/* NSTask.h + Copyright (c) 1996-2007, Apple Inc. All rights reserved. + */ + +#import + +@class NSString, NSArray, NSDictionary; + +@interface NSTask : NSObject + +// Create an NSTask which can be run at a later time +// An NSTask can only be run once. Subsequent attempts to +// run an NSTask will raise. +// Upon task death a notification will be sent +// { Name = NSTaskDidTerminateNotification; object = task; } +// + +- (instancetype)init; + +// set parameters +// these methods can only be done before a launch +// if not set, use current +// if not set, use current + +// set standard I/O channels; may be either an NSFileHandle or an NSPipe +- (void)setStandardInput:(id)input; +- (void)setStandardOutput:(id)output; +- (void)setStandardError:(id)error; + +// get parameters +@property (NS_NONATOMIC_IOSONLY, copy) NSString *launchPath; +@property (NS_NONATOMIC_IOSONLY, copy) NSArray *arguments; +@property (NS_NONATOMIC_IOSONLY, copy) NSDictionary *environment; +@property (NS_NONATOMIC_IOSONLY, copy) NSString *currentDirectoryPath; + +// get standard I/O channels; could be either an NSFileHandle or an NSPipe +- (id)standardInput; +- (id)standardOutput; +- (id)standardError; + +// actions +- (void)launch; + +- (void)interrupt; // Not always possible. Sends SIGINT. +- (void)terminate; // Not always possible. Sends SIGTERM. + +@property (NS_NONATOMIC_IOSONLY, readonly) BOOL suspend; +@property (NS_NONATOMIC_IOSONLY, readonly) BOOL resume; + +// status +@property (NS_NONATOMIC_IOSONLY, readonly) int processIdentifier; +@property (NS_NONATOMIC_IOSONLY, getter=isRunning, readonly) BOOL running; + +@property (NS_NONATOMIC_IOSONLY, readonly) int terminationStatus; + +@end + +@interface NSTask (NSTaskConveniences) + ++ (NSTask *)launchedTaskWithLaunchPath:(NSString *)path arguments:(NSArray *)arguments; +// convenience; create and launch + +- (void)waitUntilExit; +// poll the runLoop in defaultMode until task completes + +@end + +FOUNDATION_EXPORT NSString * const NSTaskDidTerminateNotification; + diff --git a/kernel.h b/kernel.h new file mode 100644 index 0000000..e4368ee --- /dev/null +++ b/kernel.h @@ -0,0 +1,26 @@ +#import +#import +#include +#include +#include +#include "libdimentio.h" + +uint32_t off_p_pid; +uint32_t off_p_pfd; +uint32_t off_fd_ofiles; +uint32_t off_fp_fglob; +uint32_t off_fg_data; +uint32_t off_vnode_iocount; +uint32_t off_vnode_usecount; +uint32_t off_vnode_vflags; + +int offset_init(); + +//get vnode +uint64_t get_vnode_with_file_index(int, uint64_t); + +//hide and show file using vnode +void hide_path(uint64_t); +void show_path(uint64_t); + +int init_kernel(); diff --git a/kernel.m b/kernel.m new file mode 100644 index 0000000..c5b26c6 --- /dev/null +++ b/kernel.m @@ -0,0 +1,120 @@ +#include "kernel.h" + +//set offset +#define kCFCoreFoundationVersionNumber_iOS_12_0 (1535.12) +#define kCFCoreFoundationVersionNumber_iOS_13_0_b2 (1656) +#define kCFCoreFoundationVersionNumber_iOS_13_0_b1 (1652.20) +#define kCFCoreFoundationVersionNumber_iOS_14_0_b1 (1740) + +uint32_t off_p_pid = 0; +uint32_t off_p_pfd = 0; +uint32_t off_fd_ofiles = 0; +uint32_t off_fp_fglob = 0; +uint32_t off_fg_data = 0; +uint32_t off_vnode_iocount = 0; +uint32_t off_vnode_usecount = 0; +uint32_t off_vnode_vflags = 0; + +int offset_init() { + if(kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_14_0_b1) { + // ios 14 + printf("iOS 14.x offset selected!!!\n"); + off_p_pid = 0x68; + off_p_pfd = 0xf8; + off_fd_ofiles = 0x0; + off_fp_fglob = 0x10; + off_fg_data = 0x38; + off_vnode_iocount = 0x64; + off_vnode_usecount = 0x60; + off_vnode_vflags = 0x54; + return 0; + } + + if(kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_13_0_b2) { + // ios 13 + printf("iOS 13.x offset selected!!!\n"); + off_p_pid = 0x68; + off_p_pfd = 0x108; + off_fd_ofiles = 0x0; + off_fp_fglob = 0x10; + off_fg_data = 0x38; + off_vnode_iocount = 0x64; + off_vnode_usecount = 0x60; + off_vnode_vflags = 0x54; + return 0; + } + + if(kCFCoreFoundationVersionNumber <= kCFCoreFoundationVersionNumber_iOS_13_0_b1 + && kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_12_0) { + //ios 12 + printf("iOS 12.x offset selected!!!\n"); + off_p_pid = 0x60; + off_p_pfd = 0x100; + off_fd_ofiles = 0x0; + off_fp_fglob = 0x8; + off_fg_data = 0x38; + off_vnode_iocount = 0x64; + off_vnode_usecount = 0x60; + off_vnode_vflags = 0x54; + return 0; + } + + return -1; +} + +//get vnode +uint64_t get_vnode_with_file_index(int file_index, uint64_t proc) { + uint64_t filedesc = kernel_read64(proc + off_p_pfd); + uint64_t fileproc = kernel_read64(filedesc + off_fd_ofiles); + uint64_t openedfile = kernel_read64(fileproc + (sizeof(void*) * file_index)); + uint64_t fileglob = kernel_read64(openedfile + off_fp_fglob); + uint64_t vnode = kernel_read64(fileglob + off_fg_data); + + uint32_t usecount = kernel_read32(vnode + off_vnode_usecount); + uint32_t iocount = kernel_read32(vnode + off_vnode_iocount); + + kernel_write32(vnode + off_vnode_usecount, usecount + 1); + kernel_write32(vnode + off_vnode_iocount, iocount + 1); + + return vnode; +} + +//hide and show file using vnode +#define VISSHADOW 0x008000 +void hide_path(uint64_t vnode){ + uint32_t v_flags = kernel_read32(vnode + off_vnode_vflags); + kernel_write32(vnode + off_vnode_vflags, (v_flags | VISSHADOW)); +} + +void show_path(uint64_t vnode){ + uint32_t v_flags = kernel_read32(vnode + off_vnode_vflags); + kernel_write32(vnode + off_vnode_vflags, (v_flags &= ~VISSHADOW)); +} + +int init_kernel() { + + printf("======= init_kernel =======\n"); + + if(dimentio_init(0, NULL, NULL) != KERN_SUCCESS) { + printf("failed dimentio_init!\n"); + return 1; + } + +// if(init_tfp0() != KERN_SUCCESS) { +// printf("failed get_tfp0!\n"); +// return 1; +// } +// + if(kbase == 0) { + printf("failed get_kbase\n"); + return 1; + } + + kern_return_t err = offset_init(); + if (err) { + printf("offset init failed: %d\n", err); + return 1; + } + + return 0; +} diff --git a/layout/usr/share/vnodebypass/hidePathList.plist b/layout/usr/share/vnodebypass/hidePathList.plist new file mode 100644 index 0000000..5664c5a --- /dev/null +++ b/layout/usr/share/vnodebypass/hidePathList.plist @@ -0,0 +1,76 @@ + + + + + /.bootstrapped_electra + /Applications/Anemone.app + /Applications/Cydia.app + /Applications/SafeMode.app + /Applications/Sileo.app + /Applications/Zebra.app + /bin/bash + /bin/bunzip2 + /bin/bzip2 + /bin/cat + /bin/chgrp + /bin/chmod + /bin/chown + /bin/cp + /bin/grep + /bin/gzip + /bin/kill + /bin/ln + /bin/ls + /bin/mkdir + /bin/mv + /bin/sed + /bin/sh + /bin/su + /bin/tar + /binpack + /bootstrap + /chimera + /electra + /etc/apt + /etc/profile + /jb + /Library/dpkg/info/com.inoahdev.launchinsafemode.list + /Library/dpkg/info/com.inoahdev.launchinsafemode.md5sums + /Library/Frameworks/CydiaSubstrate.framework + /Library/MobileSubstrate/DynamicLibraries/FlyJB.dylb + /Library/MobileSubstrate/MobileSubstrate.dylib + /Library/PreferenceBundles/LaunchInSafeMode.bundle + /Library/PreferenceLoader/Preferences/LaunchInSafeMode.plist + /Library/Themes + /private/var/binpack + /private/var/checkra1n.dmg + /private/var/lib/apt + /usr/bin/diff + /usr/bin/hostinfo + /usr/bin/killall + /usr/bin/passwd + /usr/bin/recache + /usr/bin/tar + /usr/bin/which + /usr/bin/xargs + /usr/lib/libjailbreak.dylib + /usr/lib/libsubstitute.0.dylib + /usr/lib/libsubstitute.dylib + /usr/lib/libsubstrate.dylib + /usr/lib/substitute-loader.dylib + /usr/lib/SBInject + /usr/lib/SBInject.dylib + /usr/lib/TweakInject + /usr/lib/TweakInject.dylib + /usr/lib/TweakInjectMapsCheck.dylib + /usr/libexec/sftp-server + /usr/sbin/sshd + /usr/share/terminfo + /var/mobile/Library/.sbinjectSafeMode + /var/mobile/fakevar + /var/MobileSoftwareUpdate/mnt1/fakevar + /var/mobile/Library/Preferences/jp.akusio.kernbypass.plist + /var/mobile/Library/Preferences/jp.akusio.kernbypass-unofficial.plist + /var/mobile/Library/Preferences/jp.akusio.kernbypass2.plist + + diff --git a/libdimentio.c b/libdimentio.c new file mode 100644 index 0000000..f40af5a --- /dev/null +++ b/libdimentio.c @@ -0,0 +1,1065 @@ +/* Copyright 2020 0x7ff + * + * 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. + */ +#include "libdimentio.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#define LZSS_F (18) +#define LZSS_N (4096) +#define LZSS_THRESHOLD (2) +#define IPC_ENTRY_SZ (0x18) +#define OS_STRING_LEN_OFF (0xC) +#define KCOMP_HDR_PAD_SZ (0x16C) +#define OS_STRING_STRING_OFF (0x10) +#define IPC_SPACE_IS_TABLE_OFF (0x20) +#define IPC_ENTRY_IE_OBJECT_OFF (0x0) +#define PROC_P_LIST_LE_PREV_OFF (0x8) +#define OS_DICTIONARY_COUNT_OFF (0x14) +#define IPC_PORT_IP_KOBJECT_OFF (0x68) +#define PROC_P_LIST_LH_FIRST_OFF (0x0) +#define PREBOOT_PATH "/private/preboot/" +#define IPC_SPACE_IS_TABLE_SZ_OFF (0x14) +#define OS_DICTIONARY_DICT_ENTRY_OFF (0x20) +#define OS_STRING_LEN(a) extract32(a, 14, 18) +#define LOADED_KEXT_SUMMARY_HDR_NAME_OFF (0x10) +#define LOADED_KEXT_SUMMARY_HDR_ADDR_OFF (0x60) +#define APPLE_MOBILE_AP_NONCE_CLEAR_NONCE_SEL (0xC9) +#define APPLE_MOBILE_AP_NONCE_GENERATE_NONCE_SEL (0xC8) +#define kCFCoreFoundationVersionNumber_iOS_10_0_b5 (1348) +#define kCFCoreFoundationVersionNumber_iOS_13_0_b2 (1656) +#define kCFCoreFoundationVersionNumber_iOS_14_0_b1 (1740) +#define kCFCoreFoundationVersionNumber_iOS_11_0_b1 (1429.15) +#define kCFCoreFoundationVersionNumber_iOS_12_0_b1 (1535.13) +#define kCFCoreFoundationVersionNumber_iOS_13_0_b1 (1652.20) +#define kCFCoreFoundationVersionNumber_iOS_14_3_b1 (1770.300) +#define BOOT_PATH "/System/Library/Caches/com.apple.kernelcaches/kernelcache" + +#define DER_INT (0x2U) +#define DER_SEQ (0x30U) +#define DER_IA5_STR (0x16U) +#define DER_OCTET_STR (0x4U) +#define RD(a) extract32(a, 0, 5) +#define RN(a) extract32(a, 5, 5) +#define VM_KERN_MEMORY_OSKEXT (5) +#define KCOMP_HDR_MAGIC (0x636F6D70U) +#define ADRP_ADDR(a) ((a) & ~0xFFFULL) +#define ADRP_IMM(a) (ADR_IMM(a) << 12U) +#define IO_OBJECT_NULL ((io_object_t)0) +#define ADD_X_IMM(a) extract32(a, 10, 12) +#define kIODeviceTreePlane "IODeviceTree" +#define KCOMP_HDR_TYPE_LZSS (0x6C7A7373U) +#define LDR_X_IMM(a) (sextract64(a, 5, 19) << 2U) +#define kOSBundleLoadAddressKey "OSBundleLoadAddress" +#define IS_ADR(a) (((a) & 0x9F000000U) == 0x10000000U) +#define IS_ADRP(a) (((a) & 0x9F000000U) == 0x90000000U) +#define IS_LDR_X(a) (((a) & 0xFF000000U) == 0x58000000U) +#define IS_ADD_X(a) (((a) & 0xFFC00000U) == 0x91000000U) +#define LDR_W_UNSIGNED_IMM(a) (extract32(a, 10, 12) << 2U) +#define LDR_X_UNSIGNED_IMM(a) (extract32(a, 10, 12) << 3U) +#define kBootNoncePropertyKey "com.apple.System.boot-nonce" +#define kIONVRAMDeletePropertyKey "IONVRAM-DELETE-PROPERTY" +#define IS_LDR_W_UNSIGNED_IMM(a) (((a) & 0xFFC00000U) == 0xB9400000U) +#define IS_LDR_X_UNSIGNED_IMM(a) (((a) & 0xFFC00000U) == 0xF9400000U) +#define ADR_IMM(a) ((sextract64(a, 5, 19) << 2U) | extract32(a, 29, 2)) +#define kIONVRAMForceSyncNowPropertyKey "IONVRAM-FORCESYNCNOW-PROPERTY" + +#ifndef SECT_CSTRING +# define SECT_CSTRING "__cstring" +#endif + +#ifndef SEG_TEXT_EXEC +# define SEG_TEXT_EXEC "__TEXT_EXEC" +#endif + +typedef char io_string_t[512]; +typedef mach_port_t io_object_t; +typedef uint32_t IOOptionBits, ipc_entry_num_t; +typedef io_object_t io_service_t, io_connect_t, io_registry_entry_t; +typedef kern_return_t (*kernrw_0_kbase_func_t)(kaddr_t *), (*kernrw_0_kread_func_t)(kaddr_t, void *, size_t), (*kernrw_0_kwrite_func_t)(kaddr_t, const void *, size_t); +typedef int (*krw_0_kbase_func_t)(kaddr_t *), (*krw_0_kread_func_t)(kaddr_t, void *, size_t), (*krw_0_kwrite_func_t)(const void *, kaddr_t, size_t), (*kernrw_0_req_kernrw_func_t)(void); + +typedef struct { + struct section_64 s64; + const char *data; +} sec_64_t; + +typedef struct { + struct symtab_command cmd_symtab; + sec_64_t sec_text, sec_cstring; + kaddr_t base, kslide; + const char *kernel; + size_t kernel_sz; + char *data; +} pfinder_t; + +kern_return_t +IOServiceClose(io_connect_t); + +kern_return_t +IOObjectRelease(io_object_t); + +CFMutableDictionaryRef +IOServiceMatching(const char *); + +CFDictionaryRef +OSKextCopyLoadedKextInfo(CFArrayRef, CFArrayRef); + +io_registry_entry_t +IORegistryEntryFromPath(mach_port_t, const io_string_t); + +io_service_t +IOServiceGetMatchingService(mach_port_t, CFDictionaryRef); + +kern_return_t +IOServiceOpen(io_service_t, task_port_t, uint32_t, io_connect_t *); + +kern_return_t +IORegistryEntrySetCFProperty(io_registry_entry_t, CFStringRef, CFTypeRef); + +kern_return_t +mach_vm_write(vm_map_t, mach_vm_address_t, vm_offset_t, mach_msg_type_number_t); + +kern_return_t +IOConnectCallStructMethod(io_connect_t, uint32_t, const void *, size_t, void *, size_t *); + +CFTypeRef +IORegistryEntryCreateCFProperty(io_registry_entry_t, CFStringRef, CFAllocatorRef, IOOptionBits); + +kern_return_t +mach_vm_read_overwrite(vm_map_t, mach_vm_address_t, mach_vm_size_t, mach_vm_address_t, mach_vm_size_t *); + +kern_return_t +mach_vm_machine_attribute(vm_map_t, mach_vm_address_t, mach_vm_size_t, vm_machine_attribute_t, vm_machine_attribute_val_t *); + +kern_return_t +mach_vm_region(vm_map_t, mach_vm_address_t *, mach_vm_size_t *, vm_region_flavor_t, vm_region_info_t, mach_msg_type_number_t *, mach_port_t *); + +extern const mach_port_t kIOMasterPortDefault; +static void *krw_0, *kernrw_0; + +static kread_func_t kread_buf; +task_t tfp0 = TASK_NULL; +static kwrite_func_t kwrite_buf; +kaddr_t kbase, kslide, this_proc, our_task; +static kaddr_t kernproc; +static kernrw_0_kread_func_t kernrw_0_kread; +static kernrw_0_kwrite_func_t kernrw_0_kwrite; +static size_t proc_task_off, proc_p_pid_off, task_itk_space_off, io_dt_nvram_of_dict_off; + +static uint32_t +extract32(uint32_t val, unsigned start, unsigned len) { + return (val >> start) & (~0U >> (32U - len)); +} + +static uint64_t +sextract64(uint64_t val, unsigned start, unsigned len) { + return (uint64_t)((int64_t)(val << (64U - len - start)) >> (64U - len)); +} + +static size_t +decompress_lzss(const uint8_t *src, size_t src_len, uint8_t *dst, size_t dst_len) { + const uint8_t *src_end = src + src_len, *dst_start = dst, *dst_end = dst + dst_len; + uint16_t i, r = LZSS_N - LZSS_F, flags = 0; + uint8_t text_buf[LZSS_N + LZSS_F - 1], j; + + memset(text_buf, ' ', r); + while(src != src_end && dst != dst_end) { + if(((flags >>= 1U) & 0x100U) == 0) { + flags = *src++ | 0xFF00U; + if(src == src_end) { + break; + } + } + if((flags & 1U) != 0) { + text_buf[r++] = *dst++ = *src++; + r &= LZSS_N - 1U; + } else { + i = *src++; + if(src == src_end) { + break; + } + j = *src++; + i |= (j & 0xF0U) << 4U; + j = (j & 0xFU) + LZSS_THRESHOLD; + do { + *dst++ = text_buf[r++] = text_buf[i++ & (LZSS_N - 1U)]; + r &= LZSS_N - 1U; + } while(j-- != 0 && dst != dst_end); + } + } + return (size_t)(dst - dst_start); +} + +static const uint8_t * +der_decode(uint8_t tag, const uint8_t *der, const uint8_t *der_end, size_t *out_len) { + size_t der_len; + + if(der_end - der > 2 && tag == *der++) { + if(((der_len = *der++) & 0x80U) != 0) { + *out_len = 0; + if((der_len &= 0x7FU) <= sizeof(*out_len) && (size_t)(der_end - der) >= der_len) { + while(der_len-- != 0) { + *out_len = (*out_len << 8U) | *der++; + } + } + } else { + *out_len = der_len; + } + if(*out_len != 0 && (size_t)(der_end - der) >= *out_len) { + return der; + } + } + return NULL; +} + +static const uint8_t * +der_decode_seq(const uint8_t *der, const uint8_t *der_end, const uint8_t **seq_end) { + size_t der_len; + + if((der = der_decode(DER_SEQ, der, der_end, &der_len)) != NULL) { + *seq_end = der + der_len; + } + return der; +} + +static const uint8_t * +der_decode_uint64(const uint8_t *der, const uint8_t *der_end, uint64_t *r) { + size_t der_len; + + if((der = der_decode(DER_INT, der, der_end, &der_len)) != NULL && (*der & 0x80U) == 0 && (der_len <= sizeof(*r) || (--der_len == sizeof(*r) && *der++ == 0))) { + *r = 0; + while(der_len-- != 0) { + *r = (*r << 8U) | *der++; + } + return der; + } + return NULL; +} + +static void * +kdecompress(const void *src, size_t src_len, size_t *dst_len) { + const uint8_t *der, *octet, *der_end, *src_end = (const uint8_t *)src + src_len; + struct { + uint32_t magic, type, adler32, uncomp_sz, comp_sz; + uint8_t pad[KCOMP_HDR_PAD_SZ]; + } kcomp_hdr; + size_t der_len; + uint64_t r; + void *dst; + + if((der = der_decode_seq(src, src_end, &der_end)) != NULL && (der = der_decode(DER_IA5_STR, der, der_end, &der_len)) != NULL && der_len == 4 && (memcmp(der, "IMG4", der_len) != 0 || ((der = der_decode_seq(der + der_len, src_end, &der_end)) != NULL && (der = der_decode(DER_IA5_STR, der, der_end, &der_len)) != NULL && der_len == 4)) && memcmp(der, "IM4P", der_len) == 0 && (der = der_decode(DER_IA5_STR, der + der_len, der_end, &der_len)) != NULL && der_len == 4 && memcmp(der, "krnl", der_len) == 0 && (der = der_decode(DER_IA5_STR, der + der_len, der_end, &der_len)) != NULL && (der = der_decode(DER_OCTET_STR, der + der_len, der_end, &der_len)) != NULL && der_len > sizeof(kcomp_hdr)) { + octet = der; + memcpy(&kcomp_hdr, octet, sizeof(kcomp_hdr)); + if(kcomp_hdr.magic == __builtin_bswap32(KCOMP_HDR_MAGIC)) { + if(kcomp_hdr.type == __builtin_bswap32(KCOMP_HDR_TYPE_LZSS) && (kcomp_hdr.comp_sz = __builtin_bswap32(kcomp_hdr.comp_sz)) <= der_len - sizeof(kcomp_hdr) && (kcomp_hdr.uncomp_sz = __builtin_bswap32(kcomp_hdr.uncomp_sz)) != 0 && (dst = malloc(kcomp_hdr.uncomp_sz)) != NULL) { + if(decompress_lzss(octet + sizeof(kcomp_hdr), kcomp_hdr.comp_sz, dst, kcomp_hdr.uncomp_sz) == kcomp_hdr.uncomp_sz) { + *dst_len = kcomp_hdr.uncomp_sz; + return dst; + } + free(dst); + } + } else if((der = der_decode_seq(der + der_len, src_end, &der_end)) != NULL && (der = der_decode_uint64(der, der_end, &r)) != NULL && r == 1 && der_decode_uint64(der, der_end, &r) != NULL && r != 0 && (dst = malloc(r)) != NULL) { + if(compression_decode_buffer(dst, r, octet, der_len, NULL, COMPRESSION_LZFSE) == r) { + *dst_len = r; + return dst; + } + free(dst); + } + } + return NULL; +} + +static kern_return_t +kread_buf_krw_0(kaddr_t addr, void *buf, mach_vm_size_t sz) { + static krw_0_kread_func_t krw_0_kread; + + return (krw_0_kread != NULL || (krw_0_kread = (krw_0_kread_func_t)dlsym(krw_0, "kread")) != NULL) && krw_0_kread(addr, buf, sz) == 0 ? KERN_SUCCESS : KERN_FAILURE; +} + +static kern_return_t +kwrite_buf_krw_0(kaddr_t addr, const void *buf, mach_msg_type_number_t sz) { + static krw_0_kwrite_func_t krw_0_kwrite; + + return (krw_0_kwrite != NULL || (krw_0_kwrite = (krw_0_kwrite_func_t)dlsym(krw_0, "kwrite")) != NULL) && krw_0_kwrite(buf, addr, sz) == 0 ? KERN_SUCCESS : KERN_FAILURE; +} + +static kern_return_t +kread_buf_kernrw_0(kaddr_t addr, void *buf, mach_vm_size_t sz) { + return kernrw_0_kread(addr, buf, sz); +} + +static kern_return_t +kwrite_buf_kernrw_0(kaddr_t addr, const void *buf, mach_msg_type_number_t sz) { + return kernrw_0_kwrite(addr, buf, sz); +} + +kern_return_t +init_tfp0(void) { + kern_return_t ret = task_for_pid(mach_task_self(), 0, &tfp0); + mach_port_t host; + + if(ret != KERN_SUCCESS) { + host = mach_host_self(); + if(MACH_PORT_VALID(host)) { + printf("host: 0x%" PRIX32 "\n", host); + ret = host_get_special_port(host, HOST_LOCAL_NODE, 4, &tfp0); + mach_port_deallocate(mach_task_self(), host); + } + } + if(ret == KERN_SUCCESS && MACH_PORT_VALID(tfp0)) { + return ret; + } + return KERN_FAILURE; +} + +kern_return_t +kread_buf_tfp0(kaddr_t addr, void *buf, mach_vm_size_t sz) { + mach_vm_address_t p = (mach_vm_address_t)buf; + mach_vm_size_t read_sz, out_sz = 0; + + while(sz != 0) { + read_sz = MIN(sz, vm_kernel_page_size - (addr & vm_kernel_page_mask)); + if(mach_vm_read_overwrite(tfp0, addr, read_sz, p, &out_sz) != KERN_SUCCESS || out_sz != read_sz) { + return KERN_FAILURE; + } + p += read_sz; + sz -= read_sz; + addr += read_sz; + } + return KERN_SUCCESS; +} + +kern_return_t +kread_addr(kaddr_t addr, kaddr_t *val) { + return kread_buf(addr, val, sizeof(*val)); +} + +kern_return_t +kwrite_buf_tfp0(kaddr_t addr, const void *buf, mach_msg_type_number_t sz) { + vm_machine_attribute_val_t mattr_val = MATTR_VAL_CACHE_FLUSH; + mach_vm_address_t p = (mach_vm_address_t)buf; + mach_msg_type_number_t write_sz; + + while(sz != 0) { + write_sz = (mach_msg_type_number_t)MIN(sz, vm_kernel_page_size - (addr & vm_kernel_page_mask)); + if(mach_vm_write(tfp0, addr, p, write_sz) != KERN_SUCCESS || mach_vm_machine_attribute(tfp0, addr, write_sz, MATTR_CACHE, &mattr_val) != KERN_SUCCESS) { + return KERN_FAILURE; + } + p += write_sz; + sz -= write_sz; + addr += write_sz; + } + return KERN_SUCCESS; +} + +static kern_return_t +find_section(const char *p, struct segment_command_64 sg64, const char *sect_name, struct section_64 *sp) { + for(; sg64.nsects-- != 0; p += sizeof(*sp)) { + memcpy(sp, p, sizeof(*sp)); + if((sp->flags & SECTION_TYPE) != S_ZEROFILL) { + if(sp->offset < sg64.fileoff || sp->size > sg64.filesize || sp->offset - sg64.fileoff > sg64.filesize - sp->size) { + break; + } + if(sp->size != 0 && strncmp(sp->segname, sg64.segname, sizeof(sp->segname)) == 0 && strncmp(sp->sectname, sect_name, sizeof(sp->sectname)) == 0) { + return KERN_SUCCESS; + } + } + } + return KERN_FAILURE; +} + +static void +sec_reset(sec_64_t *sec) { + memset(&sec->s64, '\0', sizeof(sec->s64)); + sec->data = NULL; +} + +static kern_return_t +sec_read_buf(sec_64_t sec, kaddr_t addr, void *buf, size_t sz) { + size_t off; + + if(addr < sec.s64.addr || sz > sec.s64.size || (off = addr - sec.s64.addr) > sec.s64.size - sz) { + return KERN_FAILURE; + } + memcpy(buf, sec.data + off, sz); + return KERN_SUCCESS; +} + +static void +pfinder_reset(pfinder_t *pfinder) { + pfinder->base = 0; + pfinder->kslide = 0; + pfinder->data = NULL; + pfinder->kernel = NULL; + pfinder->kernel_sz = 0; + sec_reset(&pfinder->sec_text); + sec_reset(&pfinder->sec_cstring); + memset(&pfinder->cmd_symtab, '\0', sizeof(pfinder->cmd_symtab)); +} + +static void +pfinder_term(pfinder_t *pfinder) { + free(pfinder->data); + pfinder_reset(pfinder); +} + +static kern_return_t +pfinder_init_file(pfinder_t *pfinder, const char *filename) { + struct symtab_command cmd_symtab; + kern_return_t ret = KERN_FAILURE; + struct segment_command_64 sg64; + struct mach_header_64 mh64; + struct load_command lc; + struct section_64 s64; + struct fat_header fh; + struct stat stat_buf; + struct fat_arch fa; + const char *p, *e; + size_t len; + void *m; + int fd; + + pfinder_reset(pfinder); + if((fd = open(filename, O_RDONLY | O_CLOEXEC)) != -1) { + if(fstat(fd, &stat_buf) != -1 && S_ISREG(stat_buf.st_mode) && stat_buf.st_size > 0) { + len = (size_t)stat_buf.st_size; + if((m = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0)) != MAP_FAILED) { + if((pfinder->data = kdecompress(m, len, &pfinder->kernel_sz)) != NULL && pfinder->kernel_sz > sizeof(fh) + sizeof(mh64)) { + pfinder->kernel = pfinder->data; + memcpy(&fh, pfinder->kernel, sizeof(fh)); + if(fh.magic == __builtin_bswap32(FAT_MAGIC) && (fh.nfat_arch = __builtin_bswap32(fh.nfat_arch)) < (pfinder->kernel_sz - sizeof(fh)) / sizeof(fa)) { + for(p = pfinder->kernel + sizeof(fh); fh.nfat_arch-- != 0; p += sizeof(fa)) { + memcpy(&fa, p, sizeof(fa)); + if(fa.cputype == (cpu_type_t)__builtin_bswap32(CPU_TYPE_ARM64) && (fa.offset = __builtin_bswap32(fa.offset)) < pfinder->kernel_sz && (fa.size = __builtin_bswap32(fa.size)) <= pfinder->kernel_sz - fa.offset && fa.size > sizeof(mh64)) { + pfinder->kernel_sz = fa.size; + pfinder->kernel += fa.offset; + break; + } + } + } + memcpy(&mh64, pfinder->kernel, sizeof(mh64)); + if(mh64.magic == MH_MAGIC_64 && mh64.cputype == CPU_TYPE_ARM64 && mh64.filetype == MH_EXECUTE && mh64.sizeofcmds < pfinder->kernel_sz - sizeof(mh64)) { + for(p = pfinder->kernel + sizeof(mh64), e = p + mh64.sizeofcmds; mh64.ncmds-- != 0 && (size_t)(e - p) >= sizeof(lc); p += lc.cmdsize) { + memcpy(&lc, p, sizeof(lc)); + if(lc.cmdsize < sizeof(lc) || (size_t)(e - p) < lc.cmdsize) { + break; + } + if(lc.cmd == LC_SEGMENT_64) { + if(lc.cmdsize < sizeof(sg64)) { + break; + } + memcpy(&sg64, p, sizeof(sg64)); + if(sg64.vmsize == 0) { + continue; + } + if(sg64.nsects != (lc.cmdsize - sizeof(sg64)) / sizeof(s64) || sg64.fileoff > pfinder->kernel_sz || sg64.filesize > pfinder->kernel_sz - sg64.fileoff) { + break; + } + if(sg64.fileoff == 0 && sg64.filesize != 0) { + if(pfinder->base != 0) { + break; + } + pfinder->base = sg64.vmaddr; + printf("base: " KADDR_FMT "\n", sg64.vmaddr); + } + if(strncmp(sg64.segname, SEG_TEXT_EXEC, sizeof(sg64.segname)) == 0) { + if(find_section(p + sizeof(sg64), sg64, SECT_TEXT, &s64) != KERN_SUCCESS) { + break; + } + pfinder->sec_text.s64 = s64; + pfinder->sec_text.data = pfinder->kernel + s64.offset; + printf("sec_text_addr: " KADDR_FMT ", sec_text_off: 0x%" PRIX32 ", sec_text_sz: 0x%" PRIX64 "\n", s64.addr, s64.offset, s64.size); + } else if(strncmp(sg64.segname, SEG_TEXT, sizeof(sg64.segname)) == 0) { + if(find_section(p + sizeof(sg64), sg64, SECT_CSTRING, &s64) != KERN_SUCCESS || pfinder->kernel[s64.offset + s64.size - 1] != '\0') { + break; + } + pfinder->sec_cstring.s64 = s64; + pfinder->sec_cstring.data = pfinder->kernel + s64.offset; + printf("sec_cstring_addr: " KADDR_FMT ", sec_cstring_off: 0x%" PRIX32 ", sec_cstring_sz: 0x%" PRIX64 "\n", s64.addr, s64.offset, s64.size); + } + } else if(lc.cmd == LC_SYMTAB) { + if(lc.cmdsize != sizeof(cmd_symtab)) { + break; + } + memcpy(&cmd_symtab, p, sizeof(cmd_symtab)); + printf("cmd_symtab_symoff: 0x%" PRIX32 ", cmd_symtab_nsyms: 0x%" PRIX32 ", cmd_symtab_stroff: 0x%" PRIX32 "\n", cmd_symtab.symoff, cmd_symtab.nsyms, cmd_symtab.stroff); + if(cmd_symtab.nsyms != 0 && (cmd_symtab.symoff > pfinder->kernel_sz || cmd_symtab.nsyms > (pfinder->kernel_sz - cmd_symtab.symoff) / sizeof(struct nlist_64) || cmd_symtab.stroff > pfinder->kernel_sz || cmd_symtab.strsize > pfinder->kernel_sz - cmd_symtab.stroff || cmd_symtab.strsize == 0 || pfinder->kernel[cmd_symtab.stroff + cmd_symtab.strsize - 1] != '\0')) { + break; + } + pfinder->cmd_symtab = cmd_symtab; + } + if(pfinder->base != 0 && pfinder->sec_text.s64.size != 0 && pfinder->sec_cstring.s64.size != 0 && pfinder->cmd_symtab.cmdsize != 0) { + ret = KERN_SUCCESS; + break; + } + } + } + } + munmap(m, len); + } + } + close(fd); + } + if(ret != KERN_SUCCESS) { + pfinder_term(pfinder); + } + return ret; +} + +static kaddr_t +pfinder_xref_rd(pfinder_t pfinder, uint32_t rd, kaddr_t start, kaddr_t to) { + kaddr_t x[32] = { 0 }; + uint32_t insn; + + for(; sec_read_buf(pfinder.sec_text, start, &insn, sizeof(insn)) == KERN_SUCCESS; start += sizeof(insn)) { + if(IS_LDR_X(insn)) { + x[RD(insn)] = start + LDR_X_IMM(insn); + } else if(IS_ADR(insn)) { + x[RD(insn)] = start + ADR_IMM(insn); + } else if(IS_ADD_X(insn)) { + x[RD(insn)] = x[RN(insn)] + ADD_X_IMM(insn); + } else if(IS_LDR_W_UNSIGNED_IMM(insn)) { + x[RD(insn)] = x[RN(insn)] + LDR_W_UNSIGNED_IMM(insn); + } else if(IS_LDR_X_UNSIGNED_IMM(insn)) { + x[RD(insn)] = x[RN(insn)] + LDR_X_UNSIGNED_IMM(insn); + } else { + if(IS_ADRP(insn)) { + x[RD(insn)] = ADRP_ADDR(start) + ADRP_IMM(insn); + } + continue; + } + if(RD(insn) == rd) { + if(to == 0) { + if(x[rd] < pfinder.base) { + break; + } + return x[rd]; + } + if(x[rd] == to) { + return start; + } + } + } + return 0; +} + +static kaddr_t +pfinder_xref_str(pfinder_t pfinder, const char *str, uint32_t rd) { + const char *p, *e; + size_t len; + + for(p = pfinder.sec_cstring.data, e = p + pfinder.sec_cstring.s64.size; p != e; p += len) { + len = strlen(p) + 1; + if(strncmp(str, p, len) == 0) { + return pfinder_xref_rd(pfinder, rd, pfinder.sec_text.s64.addr, pfinder.sec_cstring.s64.addr + (kaddr_t)(p - pfinder.sec_cstring.data)); + } + } + return 0; +} + +static kaddr_t +pfinder_sym(pfinder_t pfinder, const char *sym) { + const char *p, *strtab = pfinder.kernel + pfinder.cmd_symtab.stroff; + struct nlist_64 nl64; + + for(p = pfinder.kernel + pfinder.cmd_symtab.symoff; pfinder.cmd_symtab.nsyms-- != 0; p += sizeof(nl64)) { + memcpy(&nl64, p, sizeof(nl64)); + if(nl64.n_un.n_strx != 0 && nl64.n_un.n_strx < pfinder.cmd_symtab.strsize && (nl64.n_type & (N_STAB | N_TYPE)) == N_SECT && nl64.n_value >= pfinder.base && strcmp(strtab + nl64.n_un.n_strx, sym) == 0) { + return nl64.n_value + pfinder.kslide; + } + } + return 0; +} + +static kaddr_t +pfinder_kernproc(pfinder_t pfinder) { + kaddr_t ref = pfinder_sym(pfinder, "_kernproc"); + uint32_t insns[2]; + + if(ref != 0) { + return ref; + } + for(ref = pfinder_xref_str(pfinder, "\"Should never have an EVFILT_READ except for reg or fifo.\"", 0); sec_read_buf(pfinder.sec_text, ref, insns, sizeof(insns)) == KERN_SUCCESS; ref -= sizeof(*insns)) { + if(IS_ADRP(insns[0]) && IS_LDR_X_UNSIGNED_IMM(insns[1]) && RD(insns[1]) == 3) { + return pfinder_xref_rd(pfinder, RD(insns[1]), ref, 0); + } + } + return 0; +} + +static kaddr_t +pfinder_init_kbase(pfinder_t *pfinder) { + mach_msg_type_number_t cnt = TASK_DYLD_INFO_COUNT; + kaddr_t kext_addr, kext_addr_slid; + CFDictionaryRef kexts_info, kext_info; + task_dyld_info_data_t dyld_info; + char kext_name[KMOD_MAX_NAME]; + struct mach_header_64 mh64; + CFStringRef kext_name_cf; + CFNumberRef kext_addr_cf; + CFArrayRef kext_names; + + struct { + uint32_t pri_prot, pri_max_prot, pri_inheritance, pri_flags; + uint64_t pri_offset; + uint32_t pri_behavior, pri_user_wired_cnt, pri_user_tag, pri_pages_resident, pri_pages_shared_now_private, pri_pages_swapped_out, pri_pages_dirtied, pri_ref_cnt, pri_shadow_depth, pri_share_mode, pri_private_pages_resident, pri_shared_pages_resident, pri_obj_id, pri_depth; + kaddr_t pri_addr; + uint64_t pri_sz; + } pri; + + if(pfinder->kslide == 0) { + if(task_info(tfp0, TASK_DYLD_INFO, (task_info_t)&dyld_info, &cnt) == KERN_SUCCESS) { + pfinder->kslide = dyld_info.all_image_info_size; + } + if(pfinder->kslide == 0) { + cnt = VM_REGION_EXTENDED_INFO_COUNT; + for(pri.pri_addr = 0; proc_pidinfo(0, PROC_PIDREGIONINFO, pri.pri_addr, &pri, sizeof(pri)) == sizeof(pri); pri.pri_addr += pri.pri_sz) { + if(pri.pri_prot == VM_PROT_READ && pri.pri_user_tag == VM_KERN_MEMORY_OSKEXT) { + if(kread_buf(pri.pri_addr + LOADED_KEXT_SUMMARY_HDR_NAME_OFF, kext_name, sizeof(kext_name)) == KERN_SUCCESS) { + printf("kext_name: %s\n", kext_name); + if(kread_addr(pri.pri_addr + LOADED_KEXT_SUMMARY_HDR_ADDR_OFF, &kext_addr_slid) == KERN_SUCCESS) { + printf("kext_addr_slid: " KADDR_FMT "\n", kext_addr_slid); + if((kext_name_cf = CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, kext_name, kCFStringEncodingUTF8, kCFAllocatorNull)) != NULL) { + if((kext_names = CFArrayCreate(kCFAllocatorDefault, (const void **)&kext_name_cf, 1, &kCFTypeArrayCallBacks)) != NULL) { + if((kexts_info = OSKextCopyLoadedKextInfo(kext_names, NULL)) != NULL) { + if(CFGetTypeID(kexts_info) == CFDictionaryGetTypeID() && CFDictionaryGetCount(kexts_info) == 1 && (kext_info = CFDictionaryGetValue(kexts_info, kext_name_cf)) != NULL && CFGetTypeID(kext_info) == CFDictionaryGetTypeID() && (kext_addr_cf = CFDictionaryGetValue(kext_info, CFSTR(kOSBundleLoadAddressKey))) != NULL && CFGetTypeID(kext_addr_cf) == CFNumberGetTypeID() && CFNumberGetValue(kext_addr_cf, kCFNumberSInt64Type, &kext_addr) && kext_addr_slid > kext_addr) { + pfinder->kslide = kext_addr_slid - kext_addr; + } + CFRelease(kexts_info); + } + CFRelease(kext_names); + } + CFRelease(kext_name_cf); + } + } + } + break; + } + } + } + } + if(pfinder->base + pfinder->kslide > pfinder->base && kread_buf(pfinder->base + pfinder->kslide, &mh64, sizeof(mh64)) == KERN_SUCCESS && mh64.magic == MH_MAGIC_64 && mh64.cputype == CPU_TYPE_ARM64 && mh64.filetype == MH_EXECUTE) { + pfinder->sec_text.s64.addr += pfinder->kslide; + pfinder->sec_cstring.s64.addr += pfinder->kslide; + printf("kbase: " KADDR_FMT ", kslide: " KADDR_FMT "\n", pfinder->base + pfinder->kslide, pfinder->kslide); + kbase = pfinder->base + pfinder->kslide; + kslide = pfinder->kslide; + return KERN_SUCCESS; + } + return KERN_FAILURE; +} + +static char * +get_boot_path(void) { + size_t hash_len, path_len = sizeof(BOOT_PATH); + io_registry_entry_t chosen; + struct stat stat_buf; + const uint8_t *hash; + CFDataRef hash_cf; + char *path = NULL; + + if(stat(PREBOOT_PATH, &stat_buf) != -1 && S_ISDIR(stat_buf.st_mode) && (chosen = IORegistryEntryFromPath(kIOMasterPortDefault, kIODeviceTreePlane ":/chosen")) != IO_OBJECT_NULL) { + if((hash_cf = IORegistryEntryCreateCFProperty(chosen, CFSTR("boot-manifest-hash"), kCFAllocatorDefault, kNilOptions)) != NULL) { + if(CFGetTypeID(hash_cf) == CFDataGetTypeID() && (hash_len = (size_t)CFDataGetLength(hash_cf) << 1U) != 0) { + path_len += strlen(PREBOOT_PATH) + hash_len; + if((path = malloc(path_len)) != NULL) { + memcpy(path, PREBOOT_PATH, strlen(PREBOOT_PATH)); + for(hash = CFDataGetBytePtr(hash_cf); hash_len-- != 0; ) { + path[strlen(PREBOOT_PATH) + hash_len] = "0123456789ABCDEF"[(hash[hash_len >> 1U] >> ((~hash_len & 1U) << 2U)) & 0xFU]; + } + } + } + CFRelease(hash_cf); + } + IOObjectRelease(chosen); + } + if(path == NULL) { + path_len = sizeof(BOOT_PATH); + path = malloc(path_len); + } + if(path != NULL) { + memcpy(path + (path_len - sizeof(BOOT_PATH)), BOOT_PATH, sizeof(BOOT_PATH)); + } + return path; +} + +kern_return_t +pfinder_init_offsets(void) { + kern_return_t ret = KERN_FAILURE; + pfinder_t pfinder; + char *boot_path; + + proc_task_off = 0x18; + proc_p_pid_off = 0x10; + task_itk_space_off = 0x290; + io_dt_nvram_of_dict_off = 0xC0; + if(kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_10_0_b5) { + task_itk_space_off = 0x300; + if(kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_11_0_b1) { + task_itk_space_off = 0x308; + if(kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_12_0_b1) { + proc_task_off = 0x10; + proc_p_pid_off = 0x60; + task_itk_space_off = 0x300; + if(kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_13_0_b1) { + task_itk_space_off = 0x320; + if(kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_13_0_b2) { + proc_p_pid_off = 0x68; + if(kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_14_0_b1) { + task_itk_space_off = 0x330; + io_dt_nvram_of_dict_off = 0xB8; + if(kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_14_3_b1) { + io_dt_nvram_of_dict_off = 0xC0; + } + } + } + } + } + } + } + if((boot_path = get_boot_path()) != NULL) { + printf("boot_path: %s\n", boot_path); + if(pfinder_init_file(&pfinder, boot_path) == KERN_SUCCESS) { + pfinder.kslide = kslide; + if(pfinder_init_kbase(&pfinder) == KERN_SUCCESS && (kernproc = pfinder_kernproc(pfinder)) != 0) { + printf("kernproc: " KADDR_FMT "\n", kernproc); + ret = KERN_SUCCESS; + } + pfinder_term(&pfinder); + } + free(boot_path); + } + return ret; +} + +kern_return_t +find_task(pid_t pid, kaddr_t *task) { + pid_t cur_pid; + kaddr_t proc; + + if(kread_addr(kernproc + PROC_P_LIST_LH_FIRST_OFF, &proc) == KERN_SUCCESS) { + while(proc != 0 && kread_buf(proc + proc_p_pid_off, &cur_pid, sizeof(cur_pid)) == KERN_SUCCESS) { + if(cur_pid == pid) { + this_proc = proc; + return kread_addr(proc + proc_task_off, task); + } + if(pid == 0 || kread_addr(proc + PROC_P_LIST_LE_PREV_OFF, &proc) != KERN_SUCCESS) { + break; + } + } + } + return KERN_FAILURE; +} + +static kern_return_t +lookup_ipc_port(mach_port_name_t port_name, kaddr_t *ipc_port) { + ipc_entry_num_t port_idx, is_table_sz; + kaddr_t itk_space, is_table; + + if(MACH_PORT_VALID(port_name) && kread_addr(our_task + task_itk_space_off, &itk_space) == KERN_SUCCESS) { + printf("itk_space: " KADDR_FMT "\n", itk_space); + if(kread_buf(itk_space + IPC_SPACE_IS_TABLE_SZ_OFF, &is_table_sz, sizeof(is_table_sz)) == KERN_SUCCESS) { + printf("is_table_sz: 0x%" PRIX32 "\n", is_table_sz); + if((port_idx = MACH_PORT_INDEX(port_name)) < is_table_sz && kread_addr(itk_space + IPC_SPACE_IS_TABLE_OFF, &is_table) == KERN_SUCCESS) { + printf("is_table: " KADDR_FMT "\n", is_table); + return kread_addr(is_table + port_idx * IPC_ENTRY_SZ + IPC_ENTRY_IE_OBJECT_OFF, ipc_port); + } + } + } + return KERN_FAILURE; +} + +static kern_return_t +lookup_io_object(io_object_t object, kaddr_t *ip_kobject) { + kaddr_t ipc_port; + + if(lookup_ipc_port(object, &ipc_port) == KERN_SUCCESS) { + printf("ipc_port: " KADDR_FMT "\n", ipc_port); + return kread_addr(ipc_port + IPC_PORT_IP_KOBJECT_OFF, ip_kobject); + } + return KERN_FAILURE; +} + +static kern_return_t +nonce_generate(io_service_t nonce_serv) { + uint8_t nonce_d[CC_SHA384_DIGEST_LENGTH]; + kern_return_t ret = KERN_FAILURE; + io_connect_t nonce_conn; + size_t nonce_d_sz; + + if(IOServiceOpen(nonce_serv, mach_task_self(), 0, &nonce_conn) == KERN_SUCCESS) { + printf("nonce_conn: 0x%" PRIX32 "\n", nonce_conn); + if(IOConnectCallStructMethod(nonce_conn, APPLE_MOBILE_AP_NONCE_CLEAR_NONCE_SEL, NULL, 0, NULL, NULL) == KERN_SUCCESS) { + nonce_d_sz = sizeof(nonce_d); + ret = IOConnectCallStructMethod(nonce_conn, APPLE_MOBILE_AP_NONCE_GENERATE_NONCE_SEL, NULL, 0, nonce_d, &nonce_d_sz); + } + IOServiceClose(nonce_conn); + } + return ret; +} + +static kern_return_t +get_of_dict(io_service_t nvram_serv, kaddr_t *of_dict) { + kaddr_t nvram_object; + + if(lookup_io_object(nvram_serv, &nvram_object) == KERN_SUCCESS) { + printf("nvram_object: " KADDR_FMT "\n", nvram_object); + return kread_addr(nvram_object + io_dt_nvram_of_dict_off, of_dict); + } + return KERN_FAILURE; +} + +static kaddr_t +lookup_key_in_os_dict(kaddr_t os_dict, const char *key) { + kaddr_t os_dict_entry_ptr, string_ptr, val = 0; + uint32_t os_dict_cnt, cur_key_len; + size_t key_len = strlen(key) + 1; + struct { + kaddr_t key, val; + } os_dict_entry; + char *cur_key; + + if((cur_key = malloc(key_len)) != NULL) { + if(kread_addr(os_dict + OS_DICTIONARY_DICT_ENTRY_OFF, &os_dict_entry_ptr) == KERN_SUCCESS && os_dict_entry_ptr != 0) { + printf("os_dict_entry_ptr: " KADDR_FMT "\n", os_dict_entry_ptr); + if(kread_buf(os_dict + OS_DICTIONARY_COUNT_OFF, &os_dict_cnt, sizeof(os_dict_cnt)) == KERN_SUCCESS) { + printf("os_dict_cnt: 0x%" PRIX32 "\n", os_dict_cnt); + while(os_dict_cnt-- != 0 && kread_buf(os_dict_entry_ptr + os_dict_cnt * sizeof(os_dict_entry), &os_dict_entry, sizeof(os_dict_entry)) == KERN_SUCCESS) { + printf("key: " KADDR_FMT ", val: " KADDR_FMT "\n", os_dict_entry.key, os_dict_entry.val); + if(kread_buf(os_dict_entry.key + OS_STRING_LEN_OFF, &cur_key_len, sizeof(cur_key_len)) != KERN_SUCCESS) { + break; + } + cur_key_len = OS_STRING_LEN(cur_key_len); + printf("cur_key_len: 0x%" PRIX32 "\n", cur_key_len); + if(cur_key_len == key_len) { + if(kread_addr(os_dict_entry.key + OS_STRING_STRING_OFF, &string_ptr) != KERN_SUCCESS || string_ptr == 0) { + break; + } + printf("string_ptr: " KADDR_FMT "\n", string_ptr); + if(kread_buf(string_ptr, cur_key, key_len) != KERN_SUCCESS) { + break; + } + if(memcmp(cur_key, key, key_len) == 0) { + val = os_dict_entry.val; + break; + } + } + } + } + } + free(cur_key); + } + return val; +} + +static kern_return_t +set_nvram_prop(io_service_t nvram_serv, const char *key, const char *val) { + CFStringRef cf_key = CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, key, kCFStringEncodingUTF8, kCFAllocatorNull), cf_val; + kern_return_t ret = KERN_FAILURE; + + if(cf_key != NULL) { + if((cf_val = CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, val, kCFStringEncodingUTF8, kCFAllocatorNull)) != NULL) { + ret = IORegistryEntrySetCFProperty(nvram_serv, cf_key, cf_val); + CFRelease(cf_val); + } + CFRelease(cf_key); + } + return ret; +} + +static kern_return_t +sync_nonce(io_service_t nvram_serv) { + if(set_nvram_prop(nvram_serv, "temp_key", "temp_val") == KERN_SUCCESS && set_nvram_prop(nvram_serv, kIONVRAMDeletePropertyKey, "temp_key") == KERN_SUCCESS) { + return set_nvram_prop(nvram_serv, kIONVRAMForceSyncNowPropertyKey, kBootNoncePropertyKey); + } + return KERN_FAILURE; +} + +static bool +entangle_nonce(uint64_t nonce, uint8_t entangled_nonce[CC_SHA384_DIGEST_LENGTH]) { + bool ret = false; +#ifdef __arm64e__ +# define IO_AES_ACCELERATOR_SPECIAL_KEYS_OFF (0xD0) +# define IO_AES_ACCELERATOR_SPECIAL_KEY_CNT_OFF (0xD8) + io_service_t aes_serv = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IOAESAccelerator")); + struct { + uint32_t generated, key_id, key_sz, val[4], key[4], zero, pad; + } key; + uint64_t buf[] = { 0, nonce }; + kaddr_t aes_object, keys_ptr; + uint32_t key_cnt; + size_t out_sz; + + if(aes_serv != IO_OBJECT_NULL) { + printf("aes_serv: 0x%" PRIX32 "\n", aes_serv); + if(lookup_io_object(aes_serv, &aes_object) == KERN_SUCCESS) { + printf("aes_object: " KADDR_FMT "\n", aes_object); + if(kread_addr(aes_object + IO_AES_ACCELERATOR_SPECIAL_KEYS_OFF, &keys_ptr) == KERN_SUCCESS) { + printf("keys_ptr: " KADDR_FMT "\n", keys_ptr); + if(kread_buf(aes_object + IO_AES_ACCELERATOR_SPECIAL_KEY_CNT_OFF, &key_cnt, sizeof(key_cnt)) == KERN_SUCCESS) { + printf("key_cnt: 0x%" PRIX32 "\n", key_cnt); + for(; key_cnt-- != 0 && kread_buf(keys_ptr, &key, sizeof(key)) == KERN_SUCCESS; keys_ptr += sizeof(key)) { + printf("generated: 0x%" PRIX32 ", key_id: 0x%" PRIX32 ", key_sz: 0x%" PRIX32 "\n", key.generated, key.key_id, key.key_sz); + if(key.generated == 1 && key.key_id == 0x8A3 && key.key_sz == 8 * kCCKeySizeAES128) { + if(CCCrypt(kCCEncrypt, kCCAlgorithmAES128, 0, key.val, kCCKeySizeAES128, NULL, buf, sizeof(buf), buf, sizeof(buf), &out_sz) == kCCSuccess && out_sz == sizeof(buf)) { + CC_SHA384(buf, sizeof(buf), entangled_nonce); + ret = true; + } + break; + } + } + } + } + } + IOObjectRelease(aes_serv); + } +#else + (void)nonce; + (void)entangled_nonce; +#endif + return ret; +} + +void +dimentio_term(void) { + if(tfp0 != TASK_NULL) { + mach_port_deallocate(mach_task_self(), tfp0); + } else if(krw_0 != NULL) { + dlclose(krw_0); + } + setpriority(PRIO_PROCESS, 0, 0); +} + +kern_return_t +dimentio_init(kaddr_t _kslide, kread_func_t _kread_buf, kwrite_func_t _kwrite_buf) { + kernrw_0_req_kernrw_func_t kernrw_0_req; + kslide = _kslide; + if(_kread_buf != NULL && _kwrite_buf != NULL) { + kread_buf = _kread_buf; + kwrite_buf = _kwrite_buf; + } else if(init_tfp0() == KERN_SUCCESS) { + printf("tfp0: 0x%" PRIX32 "\n", tfp0); + kread_buf = _kread_buf != NULL ? _kread_buf : kread_buf_tfp0; + kwrite_buf = _kwrite_buf != NULL ? _kwrite_buf : kwrite_buf_tfp0; + } else if((krw_0 = dlopen("/usr/lib/libkrw.0.dylib", RTLD_LAZY)) != NULL) { + printf("libkrw!\n"); + kread_buf = kread_buf_krw_0; + kwrite_buf = kwrite_buf_krw_0; + } else if((kernrw_0 = dlopen("/usr/lib/libkernrw.0.dylib", RTLD_LAZY)) != NULL && (kernrw_0_req = (kernrw_0_req_kernrw_func_t)dlsym(kernrw_0, "requestKernRw")) != NULL && kernrw_0_req() == 0 && (kernrw_0_kread = (kernrw_0_kread_func_t)dlsym(kernrw_0, "kernRW_readbuf")) != NULL && (kernrw_0_kwrite = (kernrw_0_kwrite_func_t)dlsym(kernrw_0, "kernRW_writebuf")) != NULL) { + printf("libkernrw!\n"); + kread_buf = kread_buf_kernrw_0; + kwrite_buf = kwrite_buf_kernrw_0; + } + if(setpriority(PRIO_PROCESS, 0, PRIO_MIN) != -1 && pfinder_init_offsets() == KERN_SUCCESS) { + return KERN_SUCCESS; + } + dimentio_term(); + return KERN_FAILURE; +} + +kern_return_t +dementia(uint64_t *nonce, uint8_t entangled_nonce[CC_SHA384_DIGEST_LENGTH], bool *entangled) { + io_service_t nvram_serv = IORegistryEntryFromPath(kIOMasterPortDefault, kIODeviceTreePlane ":/options"); + char nonce_hex[sizeof("0x") + 2 * sizeof(*nonce)]; + kaddr_t of_dict, os_string, string_ptr; + kern_return_t ret = KERN_FAILURE; + + if(nvram_serv != IO_OBJECT_NULL) { + printf("nvram_serv: 0x%" PRIX32 "\n", nvram_serv); + if(find_task(getpid(), &our_task) == KERN_SUCCESS) { + printf("our_task: " KADDR_FMT "\n", our_task); + if(get_of_dict(nvram_serv, &of_dict) == KERN_SUCCESS && of_dict != 0) { + printf("of_dict: " KADDR_FMT "\n", of_dict); + if((os_string = lookup_key_in_os_dict(of_dict, kBootNoncePropertyKey)) != 0) { + printf("os_string: " KADDR_FMT "\n", os_string); + if(kread_addr(os_string + OS_STRING_STRING_OFF, &string_ptr) == KERN_SUCCESS && string_ptr != 0) { + printf("string_ptr: " KADDR_FMT "\n", string_ptr); + if(kread_buf(string_ptr, nonce_hex, sizeof(nonce_hex)) == KERN_SUCCESS && sscanf(nonce_hex, "0x%016" PRIx64, nonce) == 1) { + ret = KERN_SUCCESS; + *entangled = entangle_nonce(*nonce, entangled_nonce); + } + } + } + } + } + IOObjectRelease(nvram_serv); + } + return ret; +} + +kern_return_t +dimentio(uint64_t nonce, uint8_t entangled_nonce[CC_SHA384_DIGEST_LENGTH], bool *entangled) { + io_service_t nonce_serv, nvram_serv = IORegistryEntryFromPath(kIOMasterPortDefault, kIODeviceTreePlane ":/options"); + char nonce_hex[sizeof("0x") + 2 * sizeof(nonce)]; + kaddr_t of_dict, os_string, string_ptr; + kern_return_t ret = KERN_FAILURE; + + if(nvram_serv != IO_OBJECT_NULL) { + printf("nvram_serv: 0x%" PRIX32 "\n", nvram_serv); + if(find_task(getpid(), &our_task) == KERN_SUCCESS) { + printf("our_task: " KADDR_FMT "\n", our_task); + if((nonce_serv = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("AppleMobileApNonce"))) != IO_OBJECT_NULL) { + printf("nonce_serv: 0x%" PRIX32 "\n", nonce_serv); + if(nonce_generate(nonce_serv) == KERN_SUCCESS && get_of_dict(nvram_serv, &of_dict) == KERN_SUCCESS && of_dict != 0) { + printf("of_dict: " KADDR_FMT "\n", of_dict); + if((os_string = lookup_key_in_os_dict(of_dict, kBootNoncePropertyKey)) != 0) { + printf("os_string: " KADDR_FMT "\n", os_string); + if(kread_addr(os_string + OS_STRING_STRING_OFF, &string_ptr) == KERN_SUCCESS && string_ptr != 0) { + printf("string_ptr: " KADDR_FMT "\n", string_ptr); + snprintf(nonce_hex, sizeof(nonce_hex), "0x%016" PRIx64, nonce); + if(kwrite_buf(string_ptr, nonce_hex, sizeof(nonce_hex)) == KERN_SUCCESS && sync_nonce(nvram_serv) == KERN_SUCCESS) { + ret = KERN_SUCCESS; + *entangled = entangle_nonce(nonce, entangled_nonce); + } + } + } + } + IOObjectRelease(nonce_serv); + } + } + IOObjectRelease(nvram_serv); + } + return ret; +} + +//read kernel +uint32_t kernel_read32(uint64_t where) { + uint32_t out; + kread_buf(where, &out, sizeof(uint32_t)); + return out; +} + +uint64_t kernel_read64(uint64_t where) { + uint64_t out; + kread_buf(where, &out, sizeof(uint64_t)); + return out; +} + +//write kernel +void kernel_write32(uint64_t where, uint32_t what) { + uint32_t _what = what; + kwrite_buf(where, &_what, sizeof(uint32_t)); +} + +void kernel_write64(uint64_t where, uint64_t what) { + uint64_t _what = what; + kwrite_buf(where, &_what, sizeof(uint64_t)); +} diff --git a/libdimentio.h b/libdimentio.h new file mode 100644 index 0000000..ff256b4 --- /dev/null +++ b/libdimentio.h @@ -0,0 +1,61 @@ +/* Copyright 2020 0x7ff + * + * 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 LIBDIMENTIO_H +# define LIBDIMENTIO_H +# include +# include +# include +# define KADDR_FMT "0x%" PRIX64 +typedef uint64_t kaddr_t; +typedef kern_return_t (*kread_func_t)(kaddr_t, void *, mach_vm_size_t), (*kwrite_func_t)(kaddr_t, const void *, mach_msg_type_number_t); +static kread_func_t kread_buf; +static kwrite_func_t kwrite_buf; +static size_t proc_p_pid_off; +static size_t proc_task_off; +task_t tfp0; +kaddr_t kbase, kslide, this_proc, our_task; + +void +dimentio_term(void); + +kern_return_t +dimentio_init(kaddr_t, kread_func_t, kwrite_func_t); + +kern_return_t +dimentio(uint64_t, uint8_t[CC_SHA384_DIGEST_LENGTH], bool *); + +kern_return_t +dementia(uint64_t *, uint8_t[CC_SHA384_DIGEST_LENGTH], bool *); + +kern_return_t +init_tfp0(void); + +kern_return_t +kread_addr(kaddr_t, kaddr_t *); + +kern_return_t +find_task(pid_t, kaddr_t *); + +kern_return_t +pfinder_init_offsets(void); + +//read kernel +uint32_t kernel_read32(uint64_t); +uint64_t kernel_read64(uint64_t); + +//write kernel +void kernel_write32(uint64_t, uint32_t); +void kernel_write64(uint64_t, uint64_t); +#endif diff --git a/main.m b/main.m index 3789744..c16ee88 100644 --- a/main.m +++ b/main.m @@ -1,649 +1,45 @@ -#include -#include -#include -#include -#import "offsets.h" #include +#import #include +#include "vnode.h" + +void showUsage() { + printf("Usage: vnodebypass [OPTION]...\n"); + printf("Hide jailbreak files using VNODE that provides an internal representation of a file or directory or defines an interface to a file.\n\n"); + printf("Option:\n"); + printf("-s, --save Get vnode with file index and save path to /tmp/vnodeMem.txt\n"); + printf("-h, --hide Hide jailbreak files\n"); + printf("-r, --revert Revert jailbreak files\n"); + printf("-R, --recovery To prevent kernel panic, vnode_usecount and vnode_iocount will be substracted 1 and remove /tmp/vnodeMem.txt\n"); + printf("-c, --check Check if jailbreak file exists using SVC #0x80 SYS_access.\n"); +} + +int main(int argc, char *argv[], char *envp[]) { + setuid(0); + setgid(0); + + if(getuid() != 0 && getgid() != 0) { + printf("Require vnodebypass to be run as root!\n"); + return -1; + } + + if (argc != 2) { + showUsage(); + return -1; + } + + if((strcmp(argv[1], "-s") == 0 || strcmp(argv[1], "--save") == 0)) + saveVnode(); + else if((strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--hide") == 0)) + hideVnode(); + else if((strcmp(argv[1], "-r") == 0 || strcmp(argv[1], "--revert") == 0)) + revertVnode(); + else if((strcmp(argv[1], "-R") == 0 || strcmp(argv[1], "--recovery") == 0)) + recoveryVnode(); + else if((strcmp(argv[1], "-c") == 0 || strcmp(argv[1], "--check") == 0)) + checkFile(); + else + showUsage(); -#define VISSHADOW 0x008000 -#ifdef __arm64e__ -# define CPU_DATA_RTCLOCK_DATAP_OFF (0x190) -#else -# define CPU_DATA_RTCLOCK_DATAP_OFF (0x198) -#endif -#define VM_KERNEL_LINK_ADDRESS (0xFFFFFFF007004000ULL) -#define kCFCoreFoundationVersionNumber_iOS_13_0_b2 (1656) -#define kCFCoreFoundationVersionNumber_iOS_13_0_b1 (1652.20) - -#define KADDR_FMT "0x%" PRIX64 -#define VM_KERN_MEMORY_CPU (9) -#define RD(a) extract32(a, 0, 5) -#define RN(a) extract32(a, 5, 5) -#define IS_RET(a) ((a) == 0xD65F03C0U) -#define ADRP_ADDR(a) ((a) & ~0xFFFULL) -#define ADRP_IMM(a) (ADR_IMM(a) << 12U) -#define IO_OBJECT_NULL ((io_object_t)0) -#define ADD_X_IMM(a) extract32(a, 10, 12) -#define LDR_X_IMM(a) (sextract64(a, 5, 19) << 2U) -#define IS_ADR(a) (((a) & 0x9F000000U) == 0x10000000U) -#define IS_ADRP(a) (((a) & 0x9F000000U) == 0x90000000U) -#define IS_ADD_X(a) (((a) & 0xFFC00000U) == 0x91000000U) -#define IS_LDR_X(a) (((a) & 0xFF000000U) == 0x58000000U) -#define LDR_X_UNSIGNED_IMM(a) (extract32(a, 10, 12) << 3U) -#define IS_LDR_X_UNSIGNED_IMM(a) (((a) & 0xFFC00000U) == 0xF9400000U) -#define ADR_IMM(a) ((sextract64(a, 5, 19) << 2U) | extract32(a, 29, 2)) - -#ifndef SEG_TEXT_EXEC -# define SEG_TEXT_EXEC "__TEXT_EXEC" -#endif - -#ifndef SECT_CSTRING -# define SECT_CSTRING "__cstring" -#endif - -#ifndef MIN -# define MIN(a, b) ((a) < (b) ? (a) : (b)) -#endif - -typedef uint64_t kaddr_t; -typedef mach_port_t io_object_t; -typedef io_object_t io_service_t; -typedef io_object_t io_connect_t; -typedef io_object_t io_registry_entry_t; - -typedef struct { - struct section_64 s64; - char *data; -} sec_64_t; - -typedef struct { - sec_64_t sec_text, sec_cstring; -} pfinder_t; - -typedef struct { - kaddr_t key, val; -} dict_entry_t; - - -kern_return_t - mach_vm_write(vm_map_t, mach_vm_address_t, vm_offset_t, mach_msg_type_number_t); - - -kern_return_t - mach_vm_read_overwrite(vm_map_t, mach_vm_address_t, mach_vm_size_t, mach_vm_address_t, mach_vm_size_t *); - -kern_return_t - mach_vm_machine_attribute(vm_map_t, mach_vm_address_t, mach_vm_size_t, vm_machine_attribute_t, vm_machine_attribute_val_t *); - -kern_return_t - mach_vm_region(vm_map_t, mach_vm_address_t *, mach_vm_size_t *, vm_region_flavor_t, vm_region_info_t, mach_msg_type_number_t *, mach_port_t *); - -extern const mach_port_t kIOMasterPortDefault; - -static kaddr_t allproc, our_task; -static kaddr_t proc; -static task_t tfp0 = MACH_PORT_NULL; - -static uint32_t -extract32(uint32_t val, unsigned start, unsigned len) { - return (val >> start) & (~0U >> (32U - len)); -} - -static uint64_t -sextract64(uint64_t val, unsigned start, unsigned len) { - return (uint64_t)((int64_t)(val << (64U - len - start)) >> (64U - len)); -} - -static kern_return_t -init_tfp0(void) { - kern_return_t ret = task_for_pid(mach_task_self(), 0, &tfp0); - mach_port_t host; - pid_t pid; - - if(ret != KERN_SUCCESS) { - host = mach_host_self(); - if(MACH_PORT_VALID(host)) { - printf("host: 0x%" PRIX32 "\n", host); - ret = host_get_special_port(host, HOST_LOCAL_NODE, 4, &tfp0); - printf("I think you're using unc0ver, But load it anyway.\n"); - return ret; //TO USE UNC0VER, TEMPORARY - } - mach_port_deallocate(mach_task_self(), host); - } - if(ret == KERN_SUCCESS && MACH_PORT_VALID(tfp0)) { - if(pid_for_task(tfp0, &pid) == KERN_SUCCESS && pid == 0) { - return ret; - } - mach_port_deallocate(mach_task_self(), tfp0); - } - printf("Failed to init tfp0.\n"); - return KERN_FAILURE; -} - -static kern_return_t -kread_buf(kaddr_t addr, void *buf, mach_vm_size_t sz) { - mach_vm_address_t p = (mach_vm_address_t)buf; - mach_vm_size_t read_sz, out_sz = 0; - - while(sz != 0) { - read_sz = MIN(sz, vm_kernel_page_size - (addr & vm_kernel_page_mask)); - if(mach_vm_read_overwrite(tfp0, addr, read_sz, p, &out_sz) != KERN_SUCCESS || out_sz != read_sz) { - return KERN_FAILURE; - } - p += read_sz; - sz -= read_sz; - addr += read_sz; - } - return KERN_SUCCESS; -} - - -static kern_return_t -kread_addr(kaddr_t addr, kaddr_t *val) { - return kread_buf(addr, val, sizeof(*val)); -} - -static kern_return_t -kwrite_buf(kaddr_t addr, const void *buf, mach_msg_type_number_t sz) { - vm_machine_attribute_val_t mattr_val = MATTR_VAL_CACHE_FLUSH; - mach_vm_address_t p = (mach_vm_address_t)buf; - mach_msg_type_number_t write_sz; - - while(sz != 0) { - write_sz = (mach_msg_type_number_t)MIN(sz, vm_kernel_page_size - (addr & vm_kernel_page_mask)); - if(mach_vm_write(tfp0, addr, p, write_sz) != KERN_SUCCESS || mach_vm_machine_attribute(tfp0, addr, write_sz, MATTR_CACHE, &mattr_val) != KERN_SUCCESS) { - return KERN_FAILURE; - } - p += write_sz; - sz -= write_sz; - addr += write_sz; - } - return KERN_SUCCESS; -} - -static kaddr_t -get_kbase(kaddr_t *kslide) { - mach_msg_type_number_t cnt = TASK_DYLD_INFO_COUNT; - vm_region_extended_info_data_t extended_info; - task_dyld_info_data_t dyld_info; - kaddr_t addr, rtclock_datap; - struct mach_header_64 mh64; - mach_port_t obj_nm; - mach_vm_size_t sz; - - if(task_info(tfp0, TASK_DYLD_INFO, (task_info_t)&dyld_info, &cnt) == KERN_SUCCESS && dyld_info.all_image_info_size != 0) { - *kslide = dyld_info.all_image_info_size; - return VM_KERNEL_LINK_ADDRESS + *kslide; - } - cnt = VM_REGION_EXTENDED_INFO_COUNT; - for(addr = 0; mach_vm_region(tfp0, &addr, &sz, VM_REGION_EXTENDED_INFO, (vm_region_info_t)&extended_info, &cnt, &obj_nm) == KERN_SUCCESS; addr += sz) { - mach_port_deallocate(mach_task_self(), obj_nm); - if(extended_info.user_tag == VM_KERN_MEMORY_CPU && extended_info.protection == VM_PROT_DEFAULT) { - if(kread_addr(addr + CPU_DATA_RTCLOCK_DATAP_OFF, &rtclock_datap) != KERN_SUCCESS) { - break; - } - printf("rtclock_datap: " KADDR_FMT "\n", rtclock_datap); - rtclock_datap = trunc_page_kernel(rtclock_datap); - do { - if(rtclock_datap <= VM_KERNEL_LINK_ADDRESS) { - return 0; - } - rtclock_datap -= vm_kernel_page_size; - if(kread_buf(rtclock_datap, &mh64, sizeof(mh64)) != KERN_SUCCESS) { - return 0; - } - } while(mh64.magic != MH_MAGIC_64 || mh64.cputype != CPU_TYPE_ARM64 || mh64.filetype != MH_EXECUTE); - *kslide = rtclock_datap - VM_KERNEL_LINK_ADDRESS; - return rtclock_datap; - } - } return 0; } - -static kern_return_t -find_section(kaddr_t sg64_addr, struct segment_command_64 sg64, const char *sect_name, struct section_64 *sp) { - kaddr_t s64_addr, s64_end; - - for(s64_addr = sg64_addr + sizeof(sg64), s64_end = s64_addr + (sg64.cmdsize - sizeof(*sp)); s64_addr < s64_end; s64_addr += sizeof(*sp)) { - if(kread_buf(s64_addr, sp, sizeof(*sp)) != KERN_SUCCESS) { - break; - } - if(strncmp(sp->segname, sg64.segname, sizeof(sp->segname)) == 0 && strncmp(sp->sectname, sect_name, sizeof(sp->sectname)) == 0) { - return KERN_SUCCESS; - } - } - return KERN_FAILURE; -} - -static void -sec_reset(sec_64_t *sec) { - memset(&sec->s64, '\0', sizeof(sec->s64)); - sec->data = NULL; -} - -static void -sec_term(sec_64_t *sec) { - free(sec->data); - sec_reset(sec); -} - -static kern_return_t -sec_init(sec_64_t *sec) { - if((sec->data = malloc(sec->s64.size)) != NULL) { - if(kread_buf(sec->s64.addr, sec->data, sec->s64.size) == KERN_SUCCESS) { - return KERN_SUCCESS; - } - sec_term(sec); - } - return KERN_FAILURE; -} - -static void -pfinder_reset(pfinder_t *pfinder) { - sec_reset(&pfinder->sec_text); - sec_reset(&pfinder->sec_cstring); -} - -static void -pfinder_term(pfinder_t *pfinder) { - sec_term(&pfinder->sec_text); - sec_term(&pfinder->sec_cstring); - pfinder_reset(pfinder); -} - -static kern_return_t -pfinder_init(pfinder_t *pfinder, kaddr_t kbase) { - kern_return_t ret = KERN_FAILURE; - struct segment_command_64 sg64; - kaddr_t sg64_addr, sg64_end; - struct mach_header_64 mh64; - struct section_64 s64; - - pfinder_reset(pfinder); - if(kread_buf(kbase, &mh64, sizeof(mh64)) == KERN_SUCCESS && mh64.magic == MH_MAGIC_64 && mh64.cputype == CPU_TYPE_ARM64 && mh64.filetype == MH_EXECUTE) { - for(sg64_addr = kbase + sizeof(mh64), sg64_end = sg64_addr + (mh64.sizeofcmds - sizeof(sg64)); sg64_addr < sg64_end; sg64_addr += sg64.cmdsize) { - if(kread_buf(sg64_addr, &sg64, sizeof(sg64)) != KERN_SUCCESS) { - break; - } - if(sg64.cmd == LC_SEGMENT_64) { - if(strncmp(sg64.segname, SEG_TEXT_EXEC, sizeof(sg64.segname)) == 0 && find_section(sg64_addr, sg64, SECT_TEXT, &s64) == KERN_SUCCESS) { - pfinder->sec_text.s64 = s64; - printf("sec_text_addr: " KADDR_FMT ", sec_text_sz: 0x%" PRIX64 "\n", s64.addr, s64.size); - } else if(strncmp(sg64.segname, SEG_TEXT, sizeof(sg64.segname)) == 0 && find_section(sg64_addr, sg64, SECT_CSTRING, &s64) == KERN_SUCCESS) { - pfinder->sec_cstring.s64 = s64; - printf("sec_cstring_addr: " KADDR_FMT ", sec_cstring_sz: 0x%" PRIX64 "\n", s64.addr, s64.size); - } - } - if(pfinder->sec_text.s64.size != 0 && pfinder->sec_cstring.s64.size != 0) { - if(sec_init(&pfinder->sec_text) == KERN_SUCCESS) { - ret = sec_init(&pfinder->sec_cstring); - } - break; - } - } - } - if(ret != KERN_SUCCESS) { - pfinder_term(pfinder); - } - return ret; -} - -static kaddr_t -pfinder_xref_rd(pfinder_t pfinder, uint32_t rd, kaddr_t start, kaddr_t to) { - uint64_t x[32] = { 0 }; - uint32_t insn; - - for(; start >= pfinder.sec_text.s64.addr && start < pfinder.sec_text.s64.addr + (pfinder.sec_text.s64.size - sizeof(insn)); start += sizeof(insn)) { - memcpy(&insn, pfinder.sec_text.data + (start - pfinder.sec_text.s64.addr), sizeof(insn)); - if(IS_LDR_X(insn)) { - x[RD(insn)] = start + LDR_X_IMM(insn); - } else if(IS_ADR(insn)) { - x[RD(insn)] = start + ADR_IMM(insn); - } else if(IS_ADRP(insn)) { - x[RD(insn)] = ADRP_ADDR(start) + ADRP_IMM(insn); - continue; - } else if(IS_ADD_X(insn)) { - x[RD(insn)] = x[RN(insn)] + ADD_X_IMM(insn); - } else if(IS_LDR_X_UNSIGNED_IMM(insn)) { - x[RD(insn)] = x[RN(insn)] + LDR_X_UNSIGNED_IMM(insn); - } else if(IS_RET(insn)) { - memset(x, '\0', sizeof(x)); - } - if(RD(insn) == rd) { - if(to == 0) { - return x[rd]; - } - if(x[rd] == to) { - return start; - } - } - } - return 0; -} - -static kaddr_t -pfinder_xref_str(pfinder_t pfinder, const char *str, uint32_t rd) { - const char *p, *e; - size_t len; - - for(p = pfinder.sec_cstring.data, e = p + pfinder.sec_cstring.s64.size; p < e; p += len) { - len = strlen(p) + 1; - if(strncmp(str, p, len) == 0) { - return pfinder_xref_rd(pfinder, rd, pfinder.sec_text.s64.addr, pfinder.sec_cstring.s64.addr + (kaddr_t)(p - pfinder.sec_cstring.data)); - } - } - return 0; -} - -static kaddr_t -pfinder_allproc(pfinder_t pfinder) { - kaddr_t ref = pfinder_xref_str(pfinder, "shutdownwait", 2); - - if(ref == 0) { - ref = pfinder_xref_str(pfinder, "shutdownwait", 3); /* msleep */ - } - return pfinder_xref_rd(pfinder, 8, ref, 0); -} - -static kern_return_t -pfinder_init_offsets(pfinder_t pfinder) { - if((allproc = pfinder_allproc(pfinder)) != 0) { - printf("allproc: " KADDR_FMT "\n", allproc); - return KERN_SUCCESS; - } - return KERN_FAILURE; -} - -static kern_return_t -find_task(pid_t pid, kaddr_t *task) { - proc = allproc; - pid_t cur_pid; - - while(kread_addr(proc, &proc) == KERN_SUCCESS && proc != 0) { - if(kread_buf(proc + koffset(KSTRUCT_OFFSET_PROC_PID), &cur_pid, sizeof(cur_pid)) == KERN_SUCCESS && cur_pid == pid) { - printf("proc: " KADDR_FMT "\n", proc); - return kread_addr(proc + koffset(KSTRUCT_OFFSET_PROC_TASK), task); - } - } - return KERN_FAILURE; -} - - - -////////aksuio code -static const uint32_t off_vnode_vflags = 0x54; -static const uint32_t off_vnode_iocount = 0x64; -static const uint32_t off_vnode_usecount = 0x60; - -uint32_t rk32(uint64_t where) { - uint32_t out; - kread_buf(where, &out, sizeof(uint32_t)); - return out; -} - -uint64_t rk64(uint64_t where) { - uint64_t out; - kread_buf(where, &out, sizeof(uint64_t)); - return out; -} - -void wk32(uint64_t where, uint32_t what) { - uint32_t _what = what; - kwrite_buf(where, &_what, sizeof(uint32_t)); -} - - -void wk64(uint64_t where, uint64_t what) { - uint64_t _what = what; - kwrite_buf(where, &_what, sizeof(uint64_t)); -} - -uint32_t savedVnodeOrig; - -uint64_t get_vnode_with_file_index(int file_index){ -//https://github.com/jakeajames/time_waste/blob/master/time_waste/offsets.m - - uint64_t filedesc = rk64(proc + koffset(KSTRUCT_OFFSET_PROC_P_FD)); - uint64_t fileproc = rk64(filedesc + koffset(KSTRUCT_OFFSET_FILEDESC_FD_OFILES)); - uint64_t openedfile = rk64(fileproc + (sizeof(void*) * file_index)); - uint64_t fileglob = rk64(openedfile + koffset(KSTRUCT_OFFSET_FILEPROC_F_FGLOB)); - uint64_t vnode = rk64(fileglob + koffset(KSTRUCT_OFFSET_FILEGLOB_FG_DATA)); - - uint32_t usecount = rk32(vnode + off_vnode_usecount); - uint32_t iocount = rk32(vnode + off_vnode_iocount); - - //? - wk32(vnode + off_vnode_usecount, usecount + 1); - wk32(vnode + off_vnode_iocount, iocount + 1); - - return vnode; -} - -uint64_t recovery_vnode_with_file_index(int file_index) { - uint64_t filedesc = rk64(proc + koffset(KSTRUCT_OFFSET_PROC_P_FD)); - uint64_t fileproc = rk64(filedesc + koffset(KSTRUCT_OFFSET_FILEDESC_FD_OFILES)); - uint64_t openedfile = rk64(fileproc + (sizeof(void*) * file_index)); - uint64_t fileglob = rk64(openedfile + koffset(KSTRUCT_OFFSET_FILEPROC_F_FGLOB)); - uint64_t vnode = rk64(fileglob + koffset(KSTRUCT_OFFSET_FILEGLOB_FG_DATA)); - - - wk32(vnode + off_vnode_usecount, 0x1); - wk32(vnode + off_vnode_iocount, 0x0); - - return vnode; -} - -void hide_path(uint64_t vnode){ - uint32_t v_flags = rk32(vnode + off_vnode_vflags); - wk32(vnode + off_vnode_vflags, (v_flags | VISSHADOW)); -} - -void show_path(uint64_t vnode){ - if(vnode == 0) { - printf("vnode is 0x0. Maybe No file? Skip show_path.\n"); - return; - } - - uint32_t v_flags = rk32(vnode + off_vnode_vflags); - wk32(vnode + off_vnode_vflags, (v_flags &= ~VISSHADOW)); -} - - -/////////// - -int -main(int argc, char **argv) { - - if(argc == 2 && (strcmp(argv[1], "-s") == 0 || strcmp(argv[1], "--save") == 0 || strcmp(argv[1], "--hide") == 0 || strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "-r") == 0 || strcmp(argv[1], "--revert") == 0 || strcmp(argv[1], "-R") == 0 || strcmp(argv[1], "--recovery") == 0)) { - - setuid(0); - setgid(0); - kaddr_t kbase, kslide; - pfinder_t pfinder; - - if(init_tfp0() == KERN_SUCCESS) { - printf("tfp0: 0x%" PRIX32 "\n", tfp0); - int checkDevice = init_offsets(); - if (checkDevice) { - printf("[-] iOS version not supported. but anyway working on it.\n"); - } - if((kbase = get_kbase(&kslide)) != 0) { - printf("kbase: " KADDR_FMT ", kslide: " KADDR_FMT "\n", kbase, kslide); - if(pfinder_init(&pfinder, kbase) == KERN_SUCCESS) { - if(pfinder_init_offsets(pfinder) == KERN_SUCCESS) { - if(find_task(getpid(), &our_task) == KERN_SUCCESS) { - printf("It works!\n"); - printf("allproc to patch: " KADDR_FMT "\n", allproc); - printf("proc to patch: " KADDR_FMT "\n", proc); - printf("===== Welcome to vnodeBypass =====\n"); - - NSArray* hidePathList = @[ - @"/bin/ls", - @"/Applications/SafeMode.app", - @"/.bootstrapped_electra", - @"/bin/sed", - @"/usr/lib/libsubstitute.0.dylib", - @"/bin/kill", - @"/bin/gzip", - @"/usr/bin/which", - @"/usr/bin/diff", - @"/jb", - @"/usr/lib/libjailbreak.dylib", - @"/bin/mkdir", - @"/Library/Frameworks/CydiaSubstrate.framework", - @"/bin/cp", - @"/bin/chgrp", - @"/usr/lib/SBInject", - @"/bin/cat", - @"/bin/tar", - @"/bin/chmod", - @"/usr/share/terminfo", - @"/bin/grep", - @"/usr/lib/SBInject.dylib", - @"/electra", - @"/bin/chown", - @"/usr/bin/tar", - @"/usr/bin/killall", - @"/Applications/Anemone.app", - @"/bin/ln", - @"/usr/bin/xargs", - @"/bin/su", - @"/usr/bin/recache", - @"/etc/profile", - @"/usr/lib/libsubstrate.dylib", - @"/bin/bunzip2", - @"/usr/bin/passwd", - @"/usr/lib/libsubstitute.dylib", - @"/etc/apt", - @"/usr/bin/hostinfo", - @"/bootstrap", - @"/Library/Themes", - @"/bin/bzip2", - @"/usr/libexec/sftp-server", - @"/Applications/Cydia.app", - @"/bin/bash", - @"/bin/sh", - @"/bin/mv", - ]; - NSUInteger arrayLength = [hidePathList count]; - int arrayLength_int = (int)arrayLength; - - if(strcmp(argv[1], "-s") == 0 || strcmp(argv[1], "--save") == 0) { - printf("Saving vnode now!\n"); - - FILE *fp = fopen("/var/mobile/Library/Preferences/vnodeMem.txt", "w"); - printf("hidePathList = %d\n", arrayLength_int); - uint64_t vnodeArray[arrayLength_int]; - int i; - for(i = 0; i < arrayLength_int; i++) { - NSString *path = [hidePathList objectAtIndex:i]; - const char *path_cs = [path cStringUsingEncoding:NSUTF8StringEncoding]; - int file_index = open([path UTF8String], O_RDONLY); - if(file_index == -1) { - printf("vnode[%d] => No such file or directory, path = %s\n", i, path_cs); - vnodeArray[i] = 0x0; - } - else { - vnodeArray[i] = get_vnode_with_file_index(file_index); - printf("vnode[%d] => 0x%" PRIX64 ", path = %s\n", i, vnodeArray[i], path_cs); - fprintf(fp, "0x%" PRIX64 "\n", vnodeArray[i]); - } - close(file_index); - - } - fclose(fp); - } - - if((strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--hide") == 0 || strcmp(argv[1], "-r") == 0 || strcmp(argv[1], "--revert") == 0)) { - if(access("/var/mobile/Library/Preferences/vnodeMem.txt", F_OK) == -1 ) { - printf("[-] vnodeMem.txt doesn't exist.\n"); - return -1; - } - FILE *fp = fopen("/var/mobile/Library/Preferences/vnodeMem.txt", "r"); - uint64_t savedVnode; - int i = 0; - while(!feof(fp)) - { - if ( fscanf(fp, "0x%" PRIX64 "\n", &savedVnode) == 1) - { - printf("Saved vnode[%d] = 0x%" PRIX64 "\n", i, savedVnode); - if(strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--hide") == 0) { - hide_path(savedVnode); - } - else if(strcmp(argv[1], "-r") == 0 || strcmp(argv[1], "--revert") == 0) { - show_path(savedVnode); - } - i++; - } - } - fclose(fp); - for(i = 0; i < arrayLength_int; i++) { - NSString *path = [hidePathList objectAtIndex:i]; - const char *path_cs = [path cStringUsingEncoding:NSUTF8StringEncoding]; - - int detectFlag = syscall(SYS_access, path_cs, F_OK); - - if(detectFlag == 0) { - printf("[Syscall Access] DETECTED %s path\n", path_cs); - } - else if(detectFlag == -1) { - printf("[Syscall Access] NOT DETECTED %s path\n", path_cs); - } - } - } - - if(strcmp(argv[1], "-R") == 0 || strcmp(argv[1], "--recovery") == 0) { - if(access("/var/mobile/Library/Preferences/vnodeMem.txt", F_OK) == -1 ) { - printf("[-] vnodeMem.txt doesn't exist.\n"); - return -1; - } - - printf("Recovering vnode now!\n"); - - printf("hidePathList = %d\n", arrayLength_int); - uint64_t vnodeArray[arrayLength_int]; - int i; - for(i = 0; i < arrayLength_int; i++) { - NSString *path = [hidePathList objectAtIndex:i]; - const char *path_cs = [path cStringUsingEncoding:NSUTF8StringEncoding]; - int file_index = open([path UTF8String], O_RDONLY); - if(file_index == -1) { - printf("vnode[%d] => No such file or directory, path = %s\n", i, path_cs); - vnodeArray[i] = 0x0; - } - else { - vnodeArray[i] = recovery_vnode_with_file_index(file_index); - printf("vnode[%d] => 0x%" PRIX64 ", path = %s\n", i, vnodeArray[i], path_cs); - } - close(file_index); - - } - - int chkRemove = remove("/var/mobile/Library/Preferences/vnodeMem.txt"); - if(chkRemove == 0) { - printf("Removed /var/mobile/Library/Preferences/vnodeMem.txt\n"); - } - else if(chkRemove == -1) { - printf("Failed to remove /var/mobile/Library/Preferences/vnodeMem.txt\n"); - } - } - - } - } - pfinder_term(&pfinder); - } - } - mach_port_deallocate(mach_task_self(), tfp0); - } - } - else { - printf("Usage: vnodebypass [OPTION]...\n"); - printf("Hide jailbreak files using VNODE that provides an internal representation of a file or directory or defines an interface to a file.\n\n"); - printf("Option:\n"); - printf("-s, --save Get vnode with file index and save path to /var/mobile/Library/Preferences/vnodeMem.txt\n"); - printf("-h, --hide Hide jailbreak files\n"); - printf("-r, --revert Revert jailbreak files\n"); - printf("-R, --recovery To prevent kernel panic, vnode_usecount and vnode_iocount will be back to 1, 0.\n"); - } -} diff --git a/offsets.h b/offsets.h deleted file mode 100644 index 7206374..0000000 --- a/offsets.h +++ /dev/null @@ -1,55 +0,0 @@ -enum kstruct_offset { - /* struct task */ - KSTRUCT_OFFSET_TASK_LCK_MTX_TYPE, - KSTRUCT_OFFSET_TASK_REF_COUNT, - KSTRUCT_OFFSET_TASK_ACTIVE, - KSTRUCT_OFFSET_TASK_VM_MAP, - KSTRUCT_OFFSET_TASK_NEXT, - KSTRUCT_OFFSET_TASK_PREV, - KSTRUCT_OFFSET_TASK_ITK_SELF, - KSTRUCT_OFFSET_TASK_ITK_SPACE, - KSTRUCT_OFFSET_TASK_BSD_INFO, - - /* struct ipc_port */ - KSTRUCT_OFFSET_IPC_PORT_IO_BITS, - KSTRUCT_OFFSET_IPC_PORT_IO_REFERENCES, - KSTRUCT_OFFSET_IPC_PORT_IKMQ_BASE, - KSTRUCT_OFFSET_IPC_PORT_MSG_COUNT, - KSTRUCT_OFFSET_IPC_PORT_IP_RECEIVER, - KSTRUCT_OFFSET_IPC_PORT_IP_KOBJECT, - KSTRUCT_OFFSET_IPC_PORT_IP_PREMSG, - KSTRUCT_OFFSET_IPC_PORT_IP_CONTEXT, - KSTRUCT_OFFSET_IPC_PORT_IP_SRIGHTS, - - /* struct proc */ - KSTRUCT_OFFSET_PROC_TASK, - KSTRUCT_OFFSET_PROC_PID, - KSTRUCT_OFFSET_PROC_P_FD, - - /* struct filedesc */ - KSTRUCT_OFFSET_FILEDESC_FD_OFILES, - - /* struct fileproc */ - KSTRUCT_OFFSET_FILEPROC_F_FGLOB, - - /* struct fileglob */ - KSTRUCT_OFFSET_FILEGLOB_FG_DATA, - - /* struct socket */ - KSTRUCT_OFFSET_SOCKET_SO_PCB, - - /* struct pipe */ - KSTRUCT_OFFSET_PIPE_BUFFER, - - /* struct ipc_space */ - KSTRUCT_OFFSET_IPC_SPACE_IS_TABLE_SIZE, - KSTRUCT_OFFSET_IPC_SPACE_IS_TABLE, - KSTRUCT_OFFSET_IPC_SPACE_IS_TASK, - - KFREE_ADDR_OFFSET, - - IOSURFACE_CREATE_OUTSIZE -}; - -int koffset(enum kstruct_offset offset); -int init_offsets(void); diff --git a/offsets.m b/offsets.m deleted file mode 100644 index f3cb0a3..0000000 --- a/offsets.m +++ /dev/null @@ -1,354 +0,0 @@ -#import -#import - -#import -#import -#import -#import -#import - -#import "offsets.h" - -#define SYSTEM_VERSION_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedSame) -#define SYSTEM_VERSION_GREATER_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending) -#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending) -#define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending) -#define SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedDescending) - -int* offsets = NULL; - -int kstruct_offsets_13_0[] = { - 0xb, // KSTRUCT_OFFSET_TASK_LCK_MTX_TYPE, - 0x10, // KSTRUCT_OFFSET_TASK_REF_COUNT, - 0x14, // KSTRUCT_OFFSET_TASK_ACTIVE, - 0x28, // KSTRUCT_OFFSET_TASK_VM_MAP, - 0x30, // KSTRUCT_OFFSET_TASK_NEXT, - 0x38, // KSTRUCT_OFFSET_TASK_PREV, - 0x108, // KSTRUCT_OFFSET_TASK_ITK_SELF, - 0x320, // KSTRUCT_OFFSET_TASK_ITK_SPACE, - -#if __arm64e__ - 0x388, // KSTRUCT_OFFSET_TASK_BSD_INFO, -#else - 0x380, // KSTRUCT_OFFSET_TASK_BSD_INFO, -#endif - 0x0, // KSTRUCT_OFFSET_IPC_PORT_IO_BITS, - 0x4, // KSTRUCT_OFFSET_IPC_PORT_IO_REFERENCES, - 0x40, // KSTRUCT_OFFSET_IPC_PORT_IKMQ_BASE, - 0x50, // KSTRUCT_OFFSET_IPC_PORT_MSG_COUNT, - 0x60, // KSTRUCT_OFFSET_IPC_PORT_IP_RECEIVER, - 0x68, // KSTRUCT_OFFSET_IPC_PORT_IP_KOBJECT, - 0x88, // KSTRUCT_OFFSET_IPC_PORT_IP_PREMSG, - 0x90, // KSTRUCT_OFFSET_IPC_PORT_IP_CONTEXT, - 0xa0, // KSTRUCT_OFFSET_IPC_PORT_IP_SRIGHTS, - - 0x10, // KSTRUCT_OFFSET_PROC_TASK, - 0x68, // KSTRUCT_OFFSET_PROC_PID, - 0x108, // KSTRUCT_OFFSET_PROC_P_FD - - 0x0, // KSTRUCT_OFFSET_FILEDESC_FD_OFILES - - 0x10, // KSTRUCT_OFFSET_FILEPROC_F_FGLOB - - 0x38, // KSTRUCT_OFFSET_FILEGLOB_FG_DATA - - 0x10, // KSTRUCT_OFFSET_SOCKET_SO_PCB - - 0x10, // KSTRUCT_OFFSET_PIPE_BUFFER - - 0x14, // KSTRUCT_OFFSET_IPC_SPACE_IS_TABLE_SIZE - 0x20, // KSTRUCT_OFFSET_IPC_SPACE_IS_TABLE - 0x28, // KSTRUCT_OFFSET_IPC_SPACE_IS_TASK - - 0x7c, // KFREE_ADDR_OFFSET - - 0xdd0, // IOSURFACE_CREATE_OUTSIZE -}; - -int kstruct_offsets_12_0[] = { - 0xb, // KSTRUCT_OFFSET_TASK_LCK_MTX_TYPE, - 0x10, // KSTRUCT_OFFSET_TASK_REF_COUNT, - 0x14, // KSTRUCT_OFFSET_TASK_ACTIVE, - 0x20, // KSTRUCT_OFFSET_TASK_VM_MAP, - 0x28, // KSTRUCT_OFFSET_TASK_NEXT, - 0x30, // KSTRUCT_OFFSET_TASK_PREV, - 0xd8, // KSTRUCT_OFFSET_TASK_ITK_SELF, - 0x300, // KSTRUCT_OFFSET_TASK_ITK_SPACE, - -#if __arm64e__ - 0x368, // KSTRUCT_OFFSET_TASK_BSD_INFO, -#else - 0x358, // KSTRUCT_OFFSET_TASK_BSD_INFO, -#endif - 0x0, // KSTRUCT_OFFSET_IPC_PORT_IO_BITS, - 0x4, // KSTRUCT_OFFSET_IPC_PORT_IO_REFERENCES, - 0x40, // KSTRUCT_OFFSET_IPC_PORT_IKMQ_BASE, - 0x50, // KSTRUCT_OFFSET_IPC_PORT_MSG_COUNT, - 0x60, // KSTRUCT_OFFSET_IPC_PORT_IP_RECEIVER, - 0x68, // KSTRUCT_OFFSET_IPC_PORT_IP_KOBJECT, - 0x88, // KSTRUCT_OFFSET_IPC_PORT_IP_PREMSG, - 0x90, // KSTRUCT_OFFSET_IPC_PORT_IP_CONTEXT, - 0xa0, // KSTRUCT_OFFSET_IPC_PORT_IP_SRIGHTS, - - 0x10, // KSTRUCT_OFFSET_PROC_TASK, - 0x60, // KSTRUCT_OFFSET_PROC_PID, - 0x100, // KSTRUCT_OFFSET_PROC_P_FD - - 0x0, // KSTRUCT_OFFSET_FILEDESC_FD_OFILES - - 0x10, // KSTRUCT_OFFSET_FILEPROC_F_FGLOB - - 0x38, // KSTRUCT_OFFSET_FILEGLOB_FG_DATA - - 0x10, // KSTRUCT_OFFSET_SOCKET_SO_PCB - - 0x10, // KSTRUCT_OFFSET_PIPE_BUFFER - - 0x14, // KSTRUCT_OFFSET_IPC_SPACE_IS_TABLE_SIZE - 0x20, // KSTRUCT_OFFSET_IPC_SPACE_IS_TABLE - 0x28, // KSTRUCT_OFFSET_IPC_SPACE_IS_TASK - - 0x7c, // KFREE_ADDR_OFFSET - - 0xdd0, // IOSURFACE_CREATE_OUTSIZE -}; - - -int kernel_offsets_11_3[] = { - 0xb, // KSTRUCT_OFFSET_TASK_LCK_MTX_TYPE - 0x10, // KSTRUCT_OFFSET_TASK_REF_COUNT - 0x14, // KSTRUCT_OFFSET_TASK_ACTIVE - 0x20, // KSTRUCT_OFFSET_TASK_VM_MAP - 0x28, // KSTRUCT_OFFSET_TASK_NEXT - 0x30, // KSTRUCT_OFFSET_TASK_PREV - 0x308, // KSTRUCT_OFFSET_TASK_ITK_SPACE - 0x368, // KSTRUCT_OFFSET_TASK_BSD_INFO - 0x3a8, // KSTRUCT_OFFSET_TASK_ALL_IMAGE_INFO_ADDR - 0x3b0, // KSTRUCT_OFFSET_TASK_ALL_IMAGE_INFO_SIZE - 0x3a0, // KSTRUCT_OFFSET_TASK_TFLAGS - 0x0, // KSTRUCT_OFFSET_TASK_LOCK - - 0x0, // KSTRUCT_OFFSET_IPC_PORT_IO_BITS - 0x4, // KSTRUCT_OFFSET_IPC_PORT_IO_REFERENCES - 0x40, // KSTRUCT_OFFSET_IPC_PORT_IKMQ_BASE - 0x50, // KSTRUCT_OFFSET_IPC_PORT_MSG_COUNT - 0x60, // KSTRUCT_OFFSET_IPC_PORT_IP_RECEIVER - 0x68, // KSTRUCT_OFFSET_IPC_PORT_IP_KOBJECT - 0x88, // KSTRUCT_OFFSET_IPC_PORT_IP_PREMSG - 0x90, // KSTRUCT_OFFSET_IPC_PORT_IP_CONTEXT - 0xa0, // KSTRUCT_OFFSET_IPC_PORT_IP_SRIGHTS - - 0x10, // KSTRUCT_OFFSET_PROC_PID - 0x108, // KSTRUCT_OFFSET_PROC_P_FD - 0x18, // KSTRUCT_OFFSET_PROC_TASK - 0x100, // KSTRUCT_OFFSET_PROC_UCRED - 0x0, // KSTRUCT_OFFSET_PROC_P_LIST - 0x2a8, // KSTRUCT_OFFSET_PROC_P_CSFLAGS - 0x410, // KSTRUCT_OFFSET_PROC_P_MEMSTAT_STATE - 0x58, // KSTRUCT_OFFSET_PROC_MLOCK - 0xf0, // KSTRUCT_OFFSET_PROC_UCRED_MLOCK - 0x40, // KSTRUCT_OFFSET_PROC_SVUID - 0x44, // KSTRUCT_OFFSET_PROC_SVGID - - 0x0, // KSTRUCT_OFFSET_FILEDESC_FD_OFILES - - 0x8, // KSTRUCT_OFFSET_FILEPROC_F_FGLOB - - 0x38, // KSTRUCT_OFFSET_FILEGLOB_FG_DATA - - 0x10, // KSTRUCT_OFFSET_SOCKET_SO_PCB - - 0x10, // KSTRUCT_OFFSET_PIPE_BUFFER - - 0x14, // KSTRUCT_OFFSET_IPC_SPACE_IS_TABLE_SIZE - 0x20, // KSTRUCT_OFFSET_IPC_SPACE_IS_TABLE - - 0xd8, // KSTRUCT_OFFSET_VNODE_V_MOUNT - 0x78, // KSTRUCT_OFFSET_VNODE_VU_SPECINFO - 0x0, // KSTRUCT_OFFSET_VNODE_V_LOCK - 0xe0, // KSTRUCT_OFFSET_VNODE_V_DATA - - 0x10, // KSTRUCT_OFFSET_SPECINFO_SI_FLAGS - - 0x70, // KSTRUCT_OFFSET_MOUNT_MNT_FLAG - 0x8f8, // KSTRUCT_OFFSET_MOUNT_MNT_DATA - 0x18, // KSTRUCT_OFFSET_MOUNT_MNT_MLOCK - - 0x10, // KSTRUCT_OFFSET_HOST_SPECIAL - - 0x10, // KSTRUCT_OFFSET_UCRED_CR_REF - 0x18, // KSTRUCT_OFFSET_UCRED_CR_UID - 0x1c, // KSTRUCT_OFFSET_UCRED_CR_RUID - 0x20, // KSTRUCT_OFFSET_UCRED_CR_SVUID - 0x24, // KSTRUCT_OFFSET_UCRED_CR_NGROUPS - 0x28, // KSTRUCT_OFFSET_UCRED_CR_GROUPS - 0x68, // KSTRUCT_OFFSET_UCRED_CR_RGID - 0x6c, // KSTRUCT_OFFSET_UCRED_CR_SVGID - 0x70, // KSTRUCT_OFFSET_UCRED_CR_GMUID - 0x74, // KSTRUCT_OFFSET_UCRED_CR_FLAGS - 0x78, // KSTRUCT_OFFSET_UCRED_CR_LABEL - - 0x0, // KSTRUCT_OFFSET_LABEL_L_FLAGS - 0x8, // KSTRUCT_OFFSET_LABEL_L_PERPOLICY - - 0x18, // KSTRUCT_SIZE_IPC_ENTRY - 0x8, // KSTRUCT_OFFSET_IPC_ENTRY_IE_BITS - - 0x54, // KSTRUCT_OFFSET_VNODE_V_FLAG - - 0x1F, // KVTABLE_OFFSET_OSDICTIONARY_SETOBJECTWITHCHARP - 0x26, // KVTABLE_OFFSET_OSDICTIONARY_GETOBJECTWITHCHARP - 0x23, // KVTABLE_OFFSET_OSDICTIONARY_MERGE - - 0x1E, // KVTABLE_OFFSET_OSARRAY_MERGE - 0x20, // KVTABLE_OFFSET_OSARRAY_REMOVEOBJECT - 0x22, // KVTABLE_OFFSET_OSARRAY_GETOBJECT - - 0x05, // KVTABLE_OFFSET_OSOBJECT_RELEASE - 0x03, // KVTABLE_OFFSET_OSOBJECT_GETRETAINCOUNT - 0x04, // KVTABLE_OFFSET_OSOBJECT_RETAIN - - 0x11, // KVTABLE_OFFSET_OSSTRING_GETLENGTH - - 0x6c, // KFREE_ADDR_OFFSET -}; - -int kernel_offsets_11_0[] = { - 0xb, // KSTRUCT_OFFSET_TASK_LCK_MTX_TYPE - 0x10, // KSTRUCT_OFFSET_TASK_REF_COUNT - 0x14, // KSTRUCT_OFFSET_TASK_ACTIVE - 0x20, // KSTRUCT_OFFSET_TASK_VM_MAP - 0x28, // KSTRUCT_OFFSET_TASK_NEXT - 0x30, // KSTRUCT_OFFSET_TASK_PREV - 0x308, // KSTRUCT_OFFSET_TASK_ITK_SPACE - 0x368, // KSTRUCT_OFFSET_TASK_BSD_INFO - 0x3a8, // KSTRUCT_OFFSET_TASK_ALL_IMAGE_INFO_ADDR - 0x3b0, // KSTRUCT_OFFSET_TASK_ALL_IMAGE_INFO_SIZE - 0x3a0, // KSTRUCT_OFFSET_TASK_TFLAGS - 0x0, // KSTRUCT_OFFSET_TASK_LOCK - - 0x0, // KSTRUCT_OFFSET_IPC_PORT_IO_BITS - 0x4, // KSTRUCT_OFFSET_IPC_PORT_IO_REFERENCES - 0x40, // KSTRUCT_OFFSET_IPC_PORT_IKMQ_BASE - 0x50, // KSTRUCT_OFFSET_IPC_PORT_MSG_COUNT - 0x60, // KSTRUCT_OFFSET_IPC_PORT_IP_RECEIVER - 0x68, // KSTRUCT_OFFSET_IPC_PORT_IP_KOBJECT - 0x88, // KSTRUCT_OFFSET_IPC_PORT_IP_PREMSG - 0x90, // KSTRUCT_OFFSET_IPC_PORT_IP_CONTEXT - 0xa0, // KSTRUCT_OFFSET_IPC_PORT_IP_SRIGHTS - - 0x10, // KSTRUCT_OFFSET_PROC_PID - 0x108, // KSTRUCT_OFFSET_PROC_P_FD - 0x18, // KSTRUCT_OFFSET_PROC_TASK - 0x100, // KSTRUCT_OFFSET_PROC_UCRED - 0x0, // KSTRUCT_OFFSET_PROC_P_LIST - 0x2a8, // KSTRUCT_OFFSET_PROC_P_CSFLAGS - 0x410, // KSTRUCT_OFFSET_PROC_P_MEMSTAT_STATE - 0x58, // KSTRUCT_OFFSET_PROC_MLOCK - 0xf0, // KSTRUCT_OFFSET_PROC_UCRED_MLOCK - 0x40, // KSTRUCT_OFFSET_PROC_SVUID - 0x44, // KSTRUCT_OFFSET_PROC_SVGID - - 0x0, // KSTRUCT_OFFSET_FILEDESC_FD_OFILES - - 0x8, // KSTRUCT_OFFSET_FILEPROC_F_FGLOB - - 0x38, // KSTRUCT_OFFSET_FILEGLOB_FG_DATA - - 0x10, // KSTRUCT_OFFSET_SOCKET_SO_PCB - - 0x10, // KSTRUCT_OFFSET_PIPE_BUFFER - - 0x14, // KSTRUCT_OFFSET_IPC_SPACE_IS_TABLE_SIZE - 0x20, // KSTRUCT_OFFSET_IPC_SPACE_IS_TABLE - - 0xd8, // KSTRUCT_OFFSET_VNODE_V_MOUNT - 0x78, // KSTRUCT_OFFSET_VNODE_VU_SPECINFO - 0x0, // KSTRUCT_OFFSET_VNODE_V_LOCK - 0xe0, // KSTRUCT_OFFSET_VNODE_V_DATA - - 0x10, // KSTRUCT_OFFSET_SPECINFO_SI_FLAGS - - 0x70, // KSTRUCT_OFFSET_MOUNT_MNT_FLAG - 0x8f8, // KSTRUCT_OFFSET_MOUNT_MNT_DATA - 0x18, // KSTRUCT_OFFSET_MOUNT_MNT_MLOCK - - 0x10, // KSTRUCT_OFFSET_HOST_SPECIAL - - 0x10, // KSTRUCT_OFFSET_UCRED_CR_REF - 0x18, // KSTRUCT_OFFSET_UCRED_CR_UID - 0x1c, // KSTRUCT_OFFSET_UCRED_CR_RUID - 0x20, // KSTRUCT_OFFSET_UCRED_CR_SVUID - 0x24, // KSTRUCT_OFFSET_UCRED_CR_NGROUPS - 0x28, // KSTRUCT_OFFSET_UCRED_CR_GROUPS - 0x68, // KSTRUCT_OFFSET_UCRED_CR_RGID - 0x6c, // KSTRUCT_OFFSET_UCRED_CR_SVGID - 0x70, // KSTRUCT_OFFSET_UCRED_CR_GMUID - 0x74, // KSTRUCT_OFFSET_UCRED_CR_FLAGS - 0x78, // KSTRUCT_OFFSET_UCRED_CR_LABEL - - 0x0, // KSTRUCT_OFFSET_LABEL_L_FLAGS - 0x8, // KSTRUCT_OFFSET_LABEL_L_PERPOLICY - - 0x18, // KSTRUCT_SIZE_IPC_ENTRY - 0x8, // KSTRUCT_OFFSET_IPC_ENTRY_IE_BITS - - 0x54, // KSTRUCT_OFFSET_VNODE_V_FLAG - - 0x1F, // KVTABLE_OFFSET_OSDICTIONARY_SETOBJECTWITHCHARP - 0x26, // KVTABLE_OFFSET_OSDICTIONARY_GETOBJECTWITHCHARP - 0x23, // KVTABLE_OFFSET_OSDICTIONARY_MERGE - - 0x1E, // KVTABLE_OFFSET_OSARRAY_MERGE - 0x20, // KVTABLE_OFFSET_OSARRAY_REMOVEOBJECT - 0x22, // KVTABLE_OFFSET_OSARRAY_GETOBJECT - - 0x05, // KVTABLE_OFFSET_OSOBJECT_RELEASE - 0x03, // KVTABLE_OFFSET_OSOBJECT_GETRETAINCOUNT - 0x04, // KVTABLE_OFFSET_OSOBJECT_RETAIN - - 0x11, // KVTABLE_OFFSET_OSSTRING_GETLENGTH - - 0x6c, // KFREE_ADDR_OFFSET -}; - -int koffset(enum kstruct_offset offset) { - if (offsets == NULL) { - printf("[-] Please call init_offsets() prior to querying offsets\n"); - return 0; - } - return offsets[offset]; -} - -uint32_t create_outsize; - -int init_offsets() { - if (SYSTEM_VERSION_GREATER_THAN(@"13.5")) { - printf("[-] iOS version too high, 13.4.x or lower required\n"); - return 1; - } - else if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"13.0")) { - printf("[i] Offsets selected for iOS 13.0 or above\n"); - offsets = kstruct_offsets_13_0; - return 0; - } - else if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"12.0")) { - printf("[i] Offsets selected for iOS 12.0 or above\n"); - offsets = kstruct_offsets_12_0; - return 0; - } - else if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"11.3")) { - printf("[i] Offsets selected for iOS 11.3 or above\n"); - offsets = kernel_offsets_11_3; - return 0; - } - else if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"11.0")) { - printf("[i] Offsets selected for iOS 11.0 or above\n"); - offsets = kernel_offsets_11_0; - return 0; - } - else { - printf("[-] iOS version too low, 11.0 or higher required\n"); - return 2; - } -} diff --git a/vnode.h b/vnode.h new file mode 100644 index 0000000..8e486e1 --- /dev/null +++ b/vnode.h @@ -0,0 +1,5 @@ +void saveVnode(); +void hideVnode(); +void revertVnode(); +void recoveryVnode(); +void checkFile(); diff --git a/vnode.m b/vnode.m new file mode 100644 index 0000000..e93d6b6 --- /dev/null +++ b/vnode.m @@ -0,0 +1,149 @@ +#include "vnode.h" +#import +#import +#include "SVC_Caller.h" +#include "kernel.h" +#include "libdimentio.h" + +const char *vnodeMemPath; +NSArray *hidePathList = nil; + +__attribute__((constructor)) void initVnodeMemPath() { + vnodeMemPath = + [NSString stringWithFormat:@"/tmp/%@.txt", NSProcessInfo.processInfo.processName].UTF8String; +} + +void initPath() { + hidePathList = [NSArray + arrayWithContentsOfFile:[NSString stringWithFormat:@"/usr/share/%@/hidePathList.plist", + NSProcessInfo.processInfo.processName]]; + if (hidePathList == nil) goto exit; + for (id path in hidePathList) { + if (![path isKindOfClass:[NSString class]]) goto exit; + } + return; +exit: + printf("hidePathList.plist is broken, please reinstall vnodebypass!\n"); + exit(1); +} + +void saveVnode() { + if (access(vnodeMemPath, F_OK) == 0) { + printf("Already exist /tmp/vnodeMem.txt, Please vnode recovery first!\n"); + return; + } + + initPath(); + if (init_kernel() == 1) { + printf("Failed init_kernel\n"); + return; + } + find_task(getpid(), &our_task); + if (!this_proc) return; + printf("this_proc: " KADDR_FMT "\n", this_proc); + + FILE *fp = fopen(vnodeMemPath, "w"); + + int hideCount = (int)[hidePathList count]; + uint64_t vnodeArray[hideCount]; + + for (int i = 0; i < hideCount; i++) { + const char *hidePath = [[hidePathList objectAtIndex:i] UTF8String]; + int file_index = open(hidePath, O_RDONLY); + + if (file_index == -1) continue; + + vnodeArray[i] = get_vnode_with_file_index(file_index, this_proc); + printf("hidePath: %s, vnode[%d]: 0x%" PRIX64 "\n", hidePath, i, vnodeArray[i]); + printf("vnode_usecount: 0x%" PRIX32 ", vnode_iocount: 0x%" PRIX32 "\n", + kernel_read32(vnodeArray[i] + off_vnode_usecount), + kernel_read32(vnodeArray[i] + off_vnode_iocount)); + fprintf(fp, "0x%" PRIX64 "\n", vnodeArray[i]); + close(file_index); + } + fclose(fp); + if (tfp0) mach_port_deallocate(mach_task_self(), tfp0); + printf("Saved vnode to /tmp/vnodeMem.txt\nMake sure vnode recovery to prevent kernel panic!\n"); +} + +void hideVnode() { + if (init_kernel() == 1) { + printf("Failed init_kernel\n"); + return; + } + if (access(vnodeMemPath, F_OK) == 0) { + FILE *fp = fopen(vnodeMemPath, "r"); + uint64_t savedVnode; + int i = 0; + while (!feof(fp)) { + if (fscanf(fp, "0x%" PRIX64 "\n", &savedVnode) == 1) { + printf("Saved vnode[%d] = 0x%" PRIX64 "\n", i, savedVnode); + hide_path(savedVnode); + } + i++; + } + } + if (tfp0) mach_port_deallocate(mach_task_self(), tfp0); + printf("Hide file!\n"); +} + +void revertVnode() { + if (init_kernel() == 1) { + printf("Failed init_kernel\n"); + return; + } + if (access(vnodeMemPath, F_OK) == 0) { + FILE *fp = fopen(vnodeMemPath, "r"); + uint64_t savedVnode; + int i = 0; + while (!feof(fp)) { + if (fscanf(fp, "0x%" PRIX64 "\n", &savedVnode) == 1) { + printf("Saved vnode[%d] = 0x%" PRIX64 "\n", i, savedVnode); + show_path(savedVnode); + } + i++; + } + } + if (tfp0) mach_port_deallocate(mach_task_self(), tfp0); + printf("Show file!\n"); +} + +void recoveryVnode() { + if (init_kernel() == 1) { + printf("Failed init_kernel\n"); + return; + } + if (access(vnodeMemPath, F_OK) == 0) { + FILE *fp = fopen(vnodeMemPath, "r"); + uint64_t savedVnode; + int i = 0; + while (!feof(fp)) { + if (fscanf(fp, "0x%" PRIX64 "\n", &savedVnode) == 1) { + kernel_write32(savedVnode + off_vnode_iocount, + kernel_read32(savedVnode + off_vnode_iocount) - 1); + kernel_write32(savedVnode + off_vnode_usecount, + kernel_read32(savedVnode + off_vnode_usecount) - 1); + printf("Saved vnode[%d] = 0x%" PRIX64 "\n", i, savedVnode); + printf("vnode_usecount: 0x%" PRIX32 ", vnode_iocount: 0x%" PRIX32 "\n", + kernel_read32(savedVnode + off_vnode_usecount), + kernel_read32(savedVnode + off_vnode_iocount)); + } + i++; + } + remove(vnodeMemPath); + } + if (tfp0) mach_port_deallocate(mach_task_self(), tfp0); + printf("Recovered vnode! No more kernel panic when you shutdown.\n"); +} + +void checkFile() { + initPath(); + int hideCount = (int)[hidePathList count]; + for (int i = 0; i < hideCount; i++) { + const char *hidePath = [[hidePathList objectAtIndex:i] UTF8String]; + int ret = 0; + ret = SVC_Access(hidePath); + printf("hidePath: %s, errno: %d\n", hidePath, ret); + } + printf("Done check file!\n"); +}