https://iphonedev.wiki/api.php?action=feedcontributions&user=PoomSmart&feedformat=atomiPhone Development Wiki - User contributions [en]2024-03-19T14:05:34ZUser contributionsMediaWiki 1.39.5https://iphonedev.wiki/index.php?title=Updating_extensions_for_iOS_15/16&diff=5961Updating extensions for iOS 15/162022-12-27T02:43:36Z<p>PoomSmart: /* Low Power Mode */ Name the params</p>
<hr />
<div>Let's collect knowledge like we did with [[Updating extensions for iOS 14|iOS 14]], [[Updating extensions for iOS 13|iOS 13]], [[Updating extensions for iOS 12|iOS 12]], [[Updating extensions for iOS 11|iOS 11]], [[Updating extensions for iOS 10|iOS 10]], [[Updating extensions for iOS 9|iOS 9]], [[Updating extensions for iOS 8|iOS 8]] and [[Updating extensions for iOS 7|iOS 7]] – paste in your notes and share what you've learned, and somebody else will organize it later. :) If you want to ask questions and share tips over chat with other developers, see [[How to use IRC]] for how to connect to #theos and #iphonedev.<br />
<br />
'''Hey developer, you can add your knowledge here! Yes, you! [http://iphonedevwiki.net/index.php?title=Special:UserLogin&returnto=Updating+extensions+for+iOS+14&type=signup Make an account and edit this page!]'''<br />
<br />
If you want to see what's been recently updated on this page, you can use the wiki's [http://iphonedevwiki.net/index.php?title=Updating_extensions_for_iOS_15&action=history history feature] to compare the revisions (to look at the diff) since the last time you visited this page.<br />
<br />
== Developing tweaks for the palera1n tethered iOS 15.x JB ==<br />
<br />
This jailbreak is primarily a developer jailbreak and has certain restrictions.<br />
<br />
=== Procursus: New Signing Requirements ===<br />
<br />
iOS 15.0+ requires DER encoding of the entitlements, as such it is required that all tweaks are signed with an updated <code>ldid</code>. iOS 15.1+ adds a requirement on hash agility, added in <code>ldid</code> version <code>2.1.5-procursus3</code> which can be found [https://github.com/ProcursusTeam/ldid here].<br />
<br />
=== Low Power Mode ===<br />
<br />
iOS 15.0+ introduced a new framework for handling Low Power Mode called LowPowerMode.framework. Toggling Low Power Mode can be done via the <code>_PMLowPowerMode</code> class.<br />
<br />
<syntaxhighlight lang="objc"><br />
@interface _PMLowPowerMode : NSObject<br />
+ (instancetype)sharedInstance;<br />
- (NSInteger)getPowerMode; // 1 == Low Power Mode active<br />
- (void)setPowerMode:(NSInteger)powerMode fromSource:(id)source; // Source == @"SpringBoard"<br />
@end<br />
<br />
%hook ClassName<br />
- (void)toggleLowPower {<br />
_PMLowPowerMode *lowPowerMode = [%c(_PMLowPowerMode) sharedInstance];<br />
BOOL active = [lowPowerMode getPowerMode] == 1;<br />
// BOOL active == [NSProcessInfo processInfo].lowPowerModeEnabled; // alternatively<br />
[lowPowerMode setPowerMode:!active fromSource:@"SpringBoard"];<br />
}<br />
%end<br />
</syntaxhighlight><br />
<br />
== Framework Changes ==<br />
<br />
=== SpringBoardHome ===<br />
<br />
==== SBHIconGridSizeClassSizes ====<br />
<br />
This class is responsible for icon grid constraints.<br />
<br />
<code>SBHIconGridSizeClassSizes</code> in all arguments of methods and functions is now passed via pointer, instead of being passed as a raw struct.<br />
<br />
You can write code that supports both versions like so:<br />
<br />
<syntaxhighlight lang="objc"><br />
<br />
@interface SBIconListGridLayoutConfiguration : NSObject<br />
-(void)setIconGridSizeClassSizes:(SBHIconGridSizeClassSizes)sizes;<br />
@end<br />
<br />
@interface i15SBIconListGridLayoutConfiguration : NSObject<br />
-(void)setIconGridSizeClassSizes:(SBHIconGridSizeClassSizes *)sizes;<br />
@end<br />
<br />
...<br />
<br />
SBHIconGridSizeClassSizes sizes = { .small = { .columns = (short)widgetWidth(2, loadoutValueColumns), .rows = 2 },<br />
.medium = { .columns = (short)widgetWidth(4, loadoutValueColumns), .rows = 2 },<br />
.large = { .columns = (short)widgetWidth(4, loadoutValueColumns), .rows = 6 },<br />
.extralarge = { .columns = (short)widgetWidth(4, loadoutValueColumns), .rows = 6 } };<br />
<br />
if (@available(iOS 15, *))<br />
// Cast to the iOS 15 Interface so ARC allows us to compile this<br />
// I need to double-check whether this actually needs to be allocated or whether passing it a stack pointer works fine.<br />
[(i15SBIconListGridLayoutConfiguration *)config setIconGridSizeClassSizes:&sizes];<br />
else<br />
[config setIconGridSizeClassSizes:sizes];<br />
</syntaxhighlight></div>PoomSmarthttps://iphonedev.wiki/index.php?title=Updating_extensions_for_iOS_15/16&diff=5960Updating extensions for iOS 15/162022-12-27T02:09:52Z<p>PoomSmart: /* Low Power Mode */ Improved example</p>
<hr />
<div>Let's collect knowledge like we did with [[Updating extensions for iOS 14|iOS 14]], [[Updating extensions for iOS 13|iOS 13]], [[Updating extensions for iOS 12|iOS 12]], [[Updating extensions for iOS 11|iOS 11]], [[Updating extensions for iOS 10|iOS 10]], [[Updating extensions for iOS 9|iOS 9]], [[Updating extensions for iOS 8|iOS 8]] and [[Updating extensions for iOS 7|iOS 7]] – paste in your notes and share what you've learned, and somebody else will organize it later. :) If you want to ask questions and share tips over chat with other developers, see [[How to use IRC]] for how to connect to #theos and #iphonedev.<br />
<br />
'''Hey developer, you can add your knowledge here! Yes, you! [http://iphonedevwiki.net/index.php?title=Special:UserLogin&returnto=Updating+extensions+for+iOS+14&type=signup Make an account and edit this page!]'''<br />
<br />
If you want to see what's been recently updated on this page, you can use the wiki's [http://iphonedevwiki.net/index.php?title=Updating_extensions_for_iOS_15&action=history history feature] to compare the revisions (to look at the diff) since the last time you visited this page.<br />
<br />
== Developing tweaks for the palera1n tethered iOS 15.x JB ==<br />
<br />
This jailbreak is primarily a developer jailbreak and has certain restrictions.<br />
<br />
=== Procursus: New Signing Requirements ===<br />
<br />
iOS 15.0+ requires DER encoding of the entitlements, as such it is required that all tweaks are signed with an updated <code>ldid</code>. iOS 15.1+ adds a requirement on hash agility, added in <code>ldid</code> version <code>2.1.5-procursus3</code> which can be found [https://github.com/ProcursusTeam/ldid here].<br />
<br />
=== Low Power Mode ===<br />
<br />
iOS 15.0+ introduced a new framework for handling Low Power Mode called LowPowerMode.framework. Toggling Low Power Mode can be done via the <code>_PMLowPowerMode</code> class.<br />
<br />
<syntaxhighlight lang="objc"><br />
@interface _PMLowPowerMode : NSObject<br />
+ (instancetype)sharedInstance;<br />
- (NSInteger)getPowerMode; // 1 == Low Power Mode active<br />
- (void)setPowerMode:(NSInteger)arg0 fromSource:(id)arg1; // Source == @"SpringBoard"<br />
@end<br />
<br />
%hook ClassName<br />
- (void)toggleLowPower {<br />
_PMLowPowerMode *lowPowerMode = [%c(_PMLowPowerMode) sharedInstance];<br />
BOOL active = [lowPowerMode getPowerMode] == 1;<br />
// BOOL active == [NSProcessInfo processInfo].lowPowerModeEnabled; // alternatively<br />
[lowPowerMode setPowerMode:!active fromSource:@"SpringBoard"];<br />
}<br />
%end<br />
</syntaxhighlight><br />
<br />
== Framework Changes ==<br />
<br />
=== SpringBoardHome ===<br />
<br />
==== SBHIconGridSizeClassSizes ====<br />
<br />
This class is responsible for icon grid constraints.<br />
<br />
<code>SBHIconGridSizeClassSizes</code> in all arguments of methods and functions is now passed via pointer, instead of being passed as a raw struct.<br />
<br />
You can write code that supports both versions like so:<br />
<br />
<syntaxhighlight lang="objc"><br />
<br />
@interface SBIconListGridLayoutConfiguration : NSObject<br />
-(void)setIconGridSizeClassSizes:(SBHIconGridSizeClassSizes)sizes;<br />
@end<br />
<br />
@interface i15SBIconListGridLayoutConfiguration : NSObject<br />
-(void)setIconGridSizeClassSizes:(SBHIconGridSizeClassSizes *)sizes;<br />
@end<br />
<br />
...<br />
<br />
SBHIconGridSizeClassSizes sizes = { .small = { .columns = (short)widgetWidth(2, loadoutValueColumns), .rows = 2 },<br />
.medium = { .columns = (short)widgetWidth(4, loadoutValueColumns), .rows = 2 },<br />
.large = { .columns = (short)widgetWidth(4, loadoutValueColumns), .rows = 6 },<br />
.extralarge = { .columns = (short)widgetWidth(4, loadoutValueColumns), .rows = 6 } };<br />
<br />
if (@available(iOS 15, *))<br />
// Cast to the iOS 15 Interface so ARC allows us to compile this<br />
// I need to double-check whether this actually needs to be allocated or whether passing it a stack pointer works fine.<br />
[(i15SBIconListGridLayoutConfiguration *)config setIconGridSizeClassSizes:&sizes];<br />
else<br />
[config setIconGridSizeClassSizes:sizes];<br />
</syntaxhighlight></div>PoomSmarthttps://iphonedev.wiki/index.php?title=SSH_Over_USB&diff=5908SSH Over USB2022-08-30T07:39:10Z<p>PoomSmart: </p>
<hr />
<div><small>'''Languages: English &bull; [[SSH Over USB/fr|français]] &bull; [[SSH Over USB/th|ไทย]]'''</small><br />
<br />
== SSH over USB using usbmuxd ==<br />
<br />
You can either download a binary and run that or use a python script. The python script is a lot slower than the binary version. On Linux the python method is mostly deprecated, use the binary version provided by libimobiledevice. There is also a newer solution called gandalf. <br />
<br />
=== Using binary ===<br />
<br />
On Windows, ensure iTunes is installed, then download itunnel_mux_rev71.zip from [https://code.google.com/archive/p/iphonetunnel-usbmuxconnectbyport/downloads Google Code]. Unzip to a directory of choice.<br />
<br />
On OS X and Linux, install [https://github.com/libimobiledevice/usbmuxd usbmuxd] from your package manager.<br />
<br />
Then:<br />
<br />
* Windows: Run <code>path/to/itunnel_mux.exe --iport 22 --lport 2222</code><br />
* OS X/Linux: <code>iproxy 2222 22</code><br />
<br />
Connect to <code>localhost -p 2222</code> as you would over wifi.<br />
<br />
If you have multiple devices connected, it may be useful to run multiple instances, specifying UDIDs and ports like so:<br />
<br />
<source lang="bash"><br />
iproxy 2222 22 abcdef0123456789abcdef1234567890abcdef12 & \<br />
iproxy 2223 22 9876543210fedcba9876543210fedcba98765432<br />
</source><br />
<br />
==== Making iproxy run automatically in the background on OS X ====<br />
<br />
* Install it with Homebrew (<code>brew install libimobiledevice</code>).<br />
* Create the file <code>~/Library/LaunchAgents/com.usbmux.iproxy.plist</code> with the contents:<br />
<source lang="xml"><br />
<?xml version="1.0" encoding="UTF-8"?><br />
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><br />
<plist version="1.0"><br />
<dict><br />
<key>Label</key><br />
<string>com.usbmux.iproxy</string><br />
<key>ProgramArguments</key><br />
<array><br />
<string>/usr/local/bin/iproxy</string><br />
<string>2222</string><br />
<string>22</string><br />
</array><br />
<key>RunAtLoad</key><br />
<true/><br />
<key>KeepAlive</key><br />
<true/><br />
</dict><br />
</plist><br />
</source><br />
<br />
* Run <code>launchctl load ~/Library/LaunchAgents/com.usbmux.iproxy.plist</code>.<br />
* You now don't have to run the iproxy binary every time you want to SSH over USB as the iproxy software is always running in the background.<br />
<br />
If you have several devices you can create a daemon with a specific port for each one.<br />
* Create a file in <code>~/Library/LaunchAgents/</code> but name it using the device UDID, name or an identifier of your choice (like <code>com.usbmux.iproxy.iPhone7,2.plist</code>).<br />
* Replace <tt>UDID_HERE</tt> in the following snippet with the device UDID. The label should be unique and is best to match the filename you used.<br />
<br />
<source lang="xml"><br />
<?xml version="1.0" encoding="UTF-8"?><br />
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><br />
<plist version="1.0"><br />
<dict><br />
<key>Label</key><br />
<string>com.usbmux.iproxy.iPhone7,2</string><br />
<key>ProgramArguments</key><br />
<array><br />
<string>/usr/local/bin/iproxy</string><br />
<string>2222</string><br />
<string>22</string><br />
<string>UDID_HERE</string><br />
</array><br />
<key>RunAtLoad</key><br />
<true/><br />
<key>KeepAlive</key><br />
<true/><br />
</dict><br />
</plist><br />
</source><br />
* Run <code>launchctl load ~/Library/LaunchAgents/FILE_NAME_OF_YOUR_CHOICE</code>.<br />
* You now don't have to run the iproxy binary every time you want to SSH over USB as the iproxy software is always running in the background.<br />
<br />
=== Using Python ===<br />
<br />
Tested on OS X and Windows.<br />
<br />
You will need to have Python installed on your system.<br />
<br />
* Get [http://marcansoft.com/blog/iphonelinux/usbmuxd/ usbmuxd] source package and unpack. (Or if the linked usbmuxd package doesn't work, try [http://cgit.sukimashita.com/libusbmuxd.git/ libusbmuxd].)<br />
* Go into folder python-client<br />
* <code>chmod +x tcprelay.py</code><br />
* Run <code>./tcprelay.py -t 22:2222</code><br />
<br />
Now you can log into your device via <code>ssh mobile@localhost -p 2222</code><br />
<br />
The -t switch tells tcprelay to run threaded and allow more than one ssh over the same port.<br />
<br />
See ./tcprelay.py --help for further options.<br />
<br />
=== Using gandalf ===<br />
<br />
Tested on OS X and Linux, each with up to 29 devices connected at the same time. The advantage of using <br />
gandalf is that it is written in a functional programming language, which practically means that it won't <br />
give you seg faults and it is actively maintained https://github.com/onlinemediagroup/ocaml-usbmux<br />
<br />
* Installation<br />
You need to have opam installed, it is OCaml's package manager.<br />
<br />
On OS X you can do:<br />
<br />
<pre><br />
$ brew install opam<br />
</pre><br />
<br />
(If on Linux, then get opam via your package manager, details available https://opam.ocaml.org/doc/Install.html, <br />
Ubuntu users please pay attention, need to use a ppa for opam). <br />
It is important that your compiler is up to date, you can<br />
check with opam switch, make sure its at least >= 4.02.0<br />
<br />
then<br />
<br />
<pre><br />
$ opam install usbmux<br />
</pre><br />
<br />
This will install the command line tool gandalf and an OCaml<br />
library.<br />
<br />
* gandalf usage.<br />
<br />
The following are a series of usages of gandalf, all short form<br />
arguments have long-forms as well and -v can be added at any time.<br />
<br />
1) See with realtime updates what devices are connected <br />
<br />
<pre><br />
$ gandalf<br />
</pre><br />
This will start up gandalf in listen mode, that is it will print<br />
out whenever a device connects or disconnects and more crucially <br />
it will print out the UDID of each device. <br />
<br />
2) Start with a mapping file which is of the form<br />
<udid>:<local_port>:<device_port>. The # character starts comments<br />
So an example mapping file would be: <br />
<br />
<pre><br />
# the phone1 udid, local port 2000, phone's port 22 aka ssh<br />
123456dfg213423453456123dfg:2000:22<br />
# phone 2, same deal but note different local port <br />
frgfg2345345123jifgidfug123:2001:22<br />
</pre><br />
<br />
and the gandalf invocation is: <br />
<br />
<pre><br />
$ gandalf -m mapping<br />
</pre><br />
<br />
2.1) You can also daemonize gandalf with the -d flag. *NOTE*: You might need to end up doing that under sudo as gandalf needs to<br />
make a pid file under /var/run.<br />
<br />
3) To see a pretty JSON representation of devices and their ports that are currently connected, do:<br />
<br />
<pre><br />
$ gandalf -s<br />
</pre><br />
<br />
4) To reload gandalf with a new set of mappings, do:<br />
<br />
<pre><br />
$ gandalf -r<br />
</pre><br />
<br />
This will cancel all running threads and reload from the original<br />
mappings file, so make your changes there.<br />
<br />
5) To cleanly exit gandalf, do: *NOTE* This might require super user permissions.<br />
<pre><br />
$ gandalf -e<br />
</pre><br />
<br />
Check out the man page, accessible with:<br />
<pre><br />
$ gandalf --help<br />
</pre><br />
<br />
or <br />
<br />
<pre><br />
$ man gandalf<br />
</pre><br />
<br />
Simple invocation:<br />
<br />
<pre><br />
$ sudo `which gandalf` --mappings etc/mapping --daemonize --verbose<br />
</pre><br />
<br />
* Important Notes and Catches<br />
<br />
1) If you are running this on Linux, then you might get issues with<br />
usbmuxd having issues when more than around 7 devices are plugged<br />
in. This is because multiple threads are trying to call various<br />
libxml2 freeing functions. I have a forked version of libplist<br />
that usbmuxd uses, sans the memory freeing calls. Its available<br />
[https://github.com/onlinemediagroup/libplist here]. Compile and install that, then compile and install usbmuxd<br />
from source. This will leak memory but its not that much at all and<br />
I believe it to be a fixed amount.<br />
<br />
2) Another issue you might have is USB3.0. The Linux kernel might crap<br />
out on you after 13 devices. This is a combination of the kernel<br />
not giving enough resources and the host controller on your<br />
motherboard being crappy. The solution to this problem is to<br />
disable USB3.0 in your BIOS. To verify that USB3.0 isn't working<br />
check with lsusb<br />
<br />
== SSH over USB using the iFunBox GUI (Windows only) ==<br />
<br />
This feature only exists in the '''Windows build''' of iFunBox.<br />
<br />
* Get the latest Windows build of [http://dl.i-funbox.com/ iFunBox] and install it.<br />
* Click on "Quick Toolbox," then "USB Tunnel."<br />
* Assign ports as you see fit.<br />
<br />
== SSH over USB using iPhoneTunnel Menu Bar Application (macOS Intel only) ==<br />
<br />
[https://code.google.com/archive/p/iphonetunnel-mac/downloads Google Code Archive]<br />
<br />
[https://www.dropbox.com/s/mz4asmq8zc87hvh/iPhoneTunnel.app.zip?dl=0 DropBox Mirror]<br />
<br />
# Turn Tunnel On<br />
# Tools -> SSH<br />
<br />
== Theos usage ==<br />
Export the following variables in your shell in order to deploy builds to the connected device:<br />
<br />
<code>export THEOS_DEVICE_IP=localhost<br />
<br />
export THEOS_DEVICE_PORT=2222<br />
</code><br />
<br />
== SSH without password ==<br />
Run the following commands one time and you will not be asked to type your password again.<br />
<br />
You must create an SSH key with <code>ssh-keygen</code> if you have not created one. A passphrase isn’t required but still recommended. You can use <code>ssh-agent</code> [https://help.github.com/articles/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent/ as described here] to keep the passphrase in memory and not be prompted for it constantly.<br />
<br />
Then run the following command:<br />
<code>ssh-copy-id root@DEVICE_IP</code><br />
<br />
On OS X, ssh-copy-id will need to be installed with <code>brew install ssh-copy-id</code>.</div>PoomSmarthttps://iphonedev.wiki/index.php?title=User:PoomSmart/vector.css&diff=5900User:PoomSmart/vector.css2022-07-28T12:38:16Z<p>PoomSmart: Created page with "h1,h2,h3,h4,h5,h6{color:#c1c1c1 !important}hr{color:#222 !important}.editOptions{background-color:#333 !important;border-color:#4c4c4c !important}input,textarea{background-col..."</p>
<hr />
<div>h1,h2,h3,h4,h5,h6{color:#c1c1c1 !important}hr{color:#222 !important}.editOptions{background-color:#333 !important;border-color:#4c4c4c !important}input,textarea{background-color:#4c4c4c !important;border-color:#4c4c4c !important;color:#c1c1c1 !important}a,.mw-body a.external,.mw-body a.extiw{color:#7d9ed4 !important}a:visited,.mw-body a.external:visited,.mw-body a.extiw:visited{color:#8a7f6c !important}a.new,#p-personal a.new{color:#d44 !important}ul{list-style-image:none !important}div.thumbinner,.catlinks{background-color:#4c4c4c !important;border-color:#666 !important}#toc,div.toc,ul#filetoc,li.gallerybox div.thumb{background-color:#4c4c4c !important;border-color:#666 !important}code{border:none !important;background-color:inherit !important;color:inherit !important}table.mw_metadata td,table.mw_metadata th,table.wikitable,table.wikitable>*>tr>th,table.wikitable>*>tr>td,pre{color:#c1c1c1 !important;background-color:#4c4c4c !important;border-color:#666 !important}table.mw_metadata th,table.wikitable>*>tr>th{background-color:#595959 !important}table.diff{background-color:#4c4c4c !important}td .diffchange{color:#4c4c4c !important}#pagehistory li.selected,td.diff-context{background-color:inherit !important;color:inherit !important}#pagehistory li{border:0 !important}ul.mw-gallery-packed-hover li.gallerybox:hover div.gallerytextwrapper,ul.mw-gallery-packed-overlay li.gallerybox div.gallerytextwrapper,ul.mw-gallery-packed-hover li.gallerybox.mw-gallery-focused div.gallerytextwrapper{background-color:rgba(0,0,0,0.8) !important}#left-navigation div.vectorTabs,#right-navigation div.vectorTabs{background-image:inherit !important;background-color:#250b2d !important}#left-navigation div.vectorTabs ul,#right-navigation div.vectorTabs ul{background-color:#250b2d !important}#left-navigation div.vectorTabs ul li,#right-navigation div.vectorTabs ul li{background-color:#222 !important;background-image:-moz-linear-gradient(top, #2e2e2e 20%, #222 100%) !important;background-image:-webkit-gradient(linear, left top, left bottom, color-stop(20%, #2e2e2e), color-stop(100%, #222)) !important;background-image:-webkit-linear-gradient(top, #2e2e2e 20%, #222 100%) !important;background-image:linear-gradient(#2e2e2e 20%, #222 100%) !important}#left-navigation div.vectorTabs li.new a,#right-navigation div.vectorTabs li.new a,#left-navigation div.vectorTabs li.new a:visited,#right-navigation div.vectorTabs li.new a:visited{color:#d44 !important}#left-navigation div.vectorTabs li.selected,#right-navigation div.vectorTabs li.selected{background-color:#333 !important;background-image:-moz-linear-gradient(top, #7d9ed4 0, #333 10%) !important;background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0, #7d9ed4), color-stop(10%, #333)) !important;background-image:-webkit-linear-gradient(top, #7d9ed4 0, #333 10%) !important;background-image:linear-gradient(#7d9ed4 0, #333 10%) !important}#left-navigation div.vectorTabs li.selected a,#right-navigation div.vectorTabs li.selected a,#left-navigation div.vectorTabs li.selected a:visited,#right-navigation div.vectorTabs li.selected a:visited{color:#8a7f6c !important}#left-navigation div.vectorTabs li a,#right-navigation div.vectorTabs li a{color:#7d9ed4 !important}#left-navigation div.vectorTabs span,#right-navigation div.vectorTabs span{background:transparent !important}div#mw-head #right-navigation div.vectorMenu h3{background:inherit !important}div#mw-head div.vectorMenu h3 span{color:#7d9ed4 !important}div.vectorMenu h3 a{background:inherit !important}div.vectorMenu ul{background-color:black !important;border:solid 1px #0c0c0c !important}div.vectorMenu li a{color:#7d9ed4 !important}div.vectorMenu li.selected a,div.vectorMenu li.selected a:visited{color:#8a7f6c !important;text-decoration:none !important}div.vectorMenu#p-cactions div.menu{border-color:#666 !important}div.vectorMenu#p-cactions ul{border:0 !important;background-color:#4c4c4c !important}#mw-navigation div#mw-panel div.portal{background-image:none !important;border-top:1px solid #4c4c4c !important}#mw-navigation div#mw-panel div.portal#p-logo,#mw-navigation div#mw-panel div.portal#p-navigation{border-top:none !important}html{font-size:100% !important}html,body{height:100% !important;margin:0 !important;padding:0 !important;font-family:sans-serif !important}body{background-color:#2a2a2a !important}.mw-body{margin-left:10em !important;padding:1em !important;border:1px solid #250b2d !important;border-right-width:0 !important;margin-top:-1px !important;background-color:#333 !important;color:#c1c1c1 !important;direction:ltr !important}.mw-body .mw-editsection,.mw-body .mw-editsection-like{font-family:sans-serif !important}.mw-body p{line-height:inherit !important;margin:.5em 0 !important}.mw-body h1,.mw-body h2,.mw-body #firstHeading{font-family:"Linux Libertine",Georgia,Times,serif !important;line-height:1.3 !important;margin-bottom:.25em !important;padding:0 !important}.mw-body h1,.mw-body #firstHeading{font-size:1.8em !important}.mw-body h2{font-size:1.5em !important;margin-top:1em !important}.mw-body h3,.mw-body h4,.mw-body h5,.mw-body h6{line-height:1.6 !important;margin-top:.3em !important;margin-bottom:0 !important;padding-bottom:0 !important}.mw-body h3{font-size:1.17em !important}.mw-body h3,.mw-body h4{font-weight:bold !important}.mw-body h4,.mw-body h5,.mw-body h6{font-size:100% !important}.mw-body #toc h2,.mw-body .toc h2{font-size:100% !important;font-family:sans-serif !important}div.emptyPortlet{display:none !important}ul{list-style-type:disc !important;list-style-image:/* @embed */ url('skins/Vector/images/bullet-icon.png') !important}pre,.mw-code{line-height:1.3em !important}#siteNotice{font-size:.8em !important}.redirectText{font-size:140% !important}.redirectMsg img{vertical-align:text-bottom !important}.mw-body-content{position:relative !important;line-height:1.6 !important;font-size:.875em !important}body.vector-animateLayout .mw-body,body.vector-animateLayout div#footer,body.vector-animateLayout #left-navigation{-webkit-transition:margin-left 250ms,padding 250ms !important;-moz-transition:margin-left 250ms,padding 250ms !important;-o-transition:margin-left 250ms,padding 250ms !important;transition:margin-left 250ms,padding 250ms !important}body.vector-animateLayout #p-logo{-webkit-transition:left 250ms !important;-moz-transition:left 250ms !important;-o-transition:left 250ms !important;transition:left 250ms !important}body.vector-animateLayout #mw-panel{-webkit-transition:padding-right 250ms !important;-moz-transition:padding-right 250ms !important;-o-transition:padding-right 250ms !important;transition:padding-right 250ms !important}body.vector-animateLayout #p-search{-webkit-transition:margin-right 250ms !important;-moz-transition:margin-right 250ms !important;-o-transition:margin-right 250ms !important;transition:margin-right 250ms !important}body.vector-animateLayout #p-personal{-webkit-transition:right 250ms !important;-moz-transition:right 250ms !important;-o-transition:right 250ms !important;transition:right 250ms !important}body.vector-animateLayout #mw-head-base{-webkit-transition:margin-left 250ms !important;-moz-transition:margin-left 250ms !important;-o-transition:margin-left 250ms !important;transition:margin-left 250ms !important}#p-personal{position:absolute !important;top:.33em !important;right:.75em !important;z-index:100 !important}#p-personal h3{display:none !important}#p-personal ul{list-style-type:none !important;list-style-image:none !important;margin:0 !important;padding-left:10em !important}#p-personal li{line-height:1.125em !important;float:left !important;margin-left:.75em !important;margin-top:.5em !important;font-size:.75em !important;white-space:nowrap !important}#pt-userpage,#pt-anonuserpage{background-position:left top !important;background-repeat:no-repeat !important;background-image:url('skins/Vector/images/user-icon.png') !important;background-image:-webkit-linear-gradient(transparent, transparent),/* @embed */ url('skins/Vector/images/user-icon.svg') !important;background-image:linear-gradient(transparent, transparent),/* @embed */ url('skins/Vector/images/user-icon.svg') !important;padding-left:15px !important !important}#p-search{float:left !important;margin-right:.5em !important;margin-left:.5em !important}#p-search h3{display:none !important}#p-search form,#p-search input{margin:0 !important;margin-top:.4em !important}div#simpleSearch{display:block !important;width:12.6em !important;padding-right:1.4em !important;height:1.4em !important;margin-top:.65em !important;position:relative !important;min-height:1px !important;border:solid 1px #aaa !important;color:black !important;background-color:white !important;background-image:/* @embed */ url('skins/Vector/images/search-fade.png') !important;background-position:top left !important;background-repeat:repeat-x !important}div#simpleSearch input{margin:0 !important;padding:0 !important;border:0 !important;background-color:transparent !important;color:black !important}div#simpleSearch #searchInput{width:100% !important;padding:.2em 0 .2em .2em !important;font-size:13px !important;direction:ltr !important;-webkit-appearance:textfield !important}div#simpleSearch #searchInput:focus{outline:none !important}div#simpleSearch #searchInput.placeholder{color:#999 !important}div#simpleSearch #searchInput:-ms-input-placeholder{color:#999 !important}div#simpleSearch #searchInput:-moz-placeholder{color:#999 !important}div#simpleSearch #searchInput::-webkit-search-decoration,div#simpleSearch #searchInput::-webkit-search-cancel-button,div#simpleSearch #searchInput::-webkit-search-results-button,div#simpleSearch #searchInput::-webkit-search-results-decoration{-webkit-appearance:textfield !important}div#simpleSearch #searchButton,div#simpleSearch #mw-searchButton{position:absolute !important;top:0 !important;right:0 !important;width:1.65em !important;height:100% !important;cursor:pointer !important;text-indent:-99999px !important;line-height:1 !important;direction:ltr !important;white-space:nowrap !important;overflow:hidden !important;background-image:url('skins/Vector/images/search-ltr.png') !important;background-image:-webkit-linear-gradient(transparent, transparent),/* @embed */ url('skins/Vector/images/search-ltr.svg') !important;background-image:linear-gradient(transparent, transparent),/* @embed */ url('skins/Vector/images/search-ltr.svg') !important;background-position:center center !important;background-repeat:no-repeat !important}div#simpleSearch #mw-searchButton{z-index:1 !important}div.vectorTabs h3{display:none !important}div.vectorTabs{float:left !important;height:2.5em !important;background-image:/* @embed */ url('skins/Vector/images/tab-break.png') !important;background-position:bottom left !important;background-repeat:no-repeat !important;padding-left:1px !important}div.vectorTabs ul{float:left !important;height:100% !important;list-style-type:none !important;list-style-image:none !important;margin:0 !important;padding:0 !important;background-image:/* @embed */ url('skins/Vector/images/tab-break.png') !important;background-position:right bottom !important;background-repeat:no-repeat !important}div.vectorTabs ul li{float:left !important;line-height:1.125em !important;display:inline-block !important;height:100% !important;margin:0 !important;padding:0 !important;background-color:#f3f3f3 !important;background-image:/* @embed */ url('skins/Vector/images/tab-normal-fade.png') !important;background-position:bottom left !important;background-repeat:repeat-x !important;white-space:nowrap !important}div.vectorTabs ul>li{display:block !important}div.vectorTabs li.new a,div.vectorTabs li.new a:visited{color:#a55858 !important}div.vectorTabs li.selected{background-image:/* @embed */ url('skins/Vector/images/tab-current-fade.png') !important}div.vectorTabs li.selected a,div.vectorTabs li.selected a:visited{color:#333 !important;text-decoration:none !important}div.vectorTabs li.icon a{background-position:bottom right !important;background-repeat:no-repeat !important}div.vectorTabs li a{display:inline-block !important;height:1.9em !important;padding-left:.5em !important;padding-right:.5em !important;color:#7d9ed4 !important;cursor:pointer !important;font-size:.8em !important}div.vectorTabs li>a{display:block !important}div.vectorTabs span{display:inline-block !important;background-image:/* @embed */ url('skins/Vector/images/tab-break.png') !important;background-position:bottom right !important;background-repeat:no-repeat !important}div.vectorTabs span a{display:inline-block !important;padding-top:1.25em !important}div.vectorTabs span>a{float:left !important;display:block !important}div.vectorMenu{direction:ltr !important;float:left !important;cursor:pointer !important;position:relative !important}body.rtl div.vectorMenu{direction:rtl !important}div#mw-head div.vectorMenu h3{float:left !important;background-image:/* @embed */ url('skins/Vector/images/tab-break.png') !important;background-repeat:no-repeat !important;background-position:bottom right !important;margin-left:-1px !important;font-size:1em !important;height:2.5em !important;padding-right:1px !important;margin-right:-1px !important}div.vectorMenu h3 span{display:block !important;font-size:.8em !important;padding-left:.7em !important;padding-top:1.375em !important;margin-right:20px !important;font-weight:normal !important;color:#4d4d4d !important}div.vectorMenu h3 a{position:absolute !important;top:0 !important;right:0 !important;width:20px !important;height:2.5em !important;background-image:url('skins/Vector/images/arrow-down-icon.png') !important;background-image:-webkit-linear-gradient(transparent, transparent),/* @embed */ url('skins/Vector/images/arrow-down-icon.svg') !important;background-image:linear-gradient(transparent, transparent),/* @embed */ url('skins/Vector/images/arrow-down-icon.svg') !important;background-position:100% 70% !important;background-repeat:no-repeat !important;-webkit-transition:background-position 250ms !important;-moz-transition:background-position 250ms !important;-o-transition:background-position 250ms !important;transition:background-position 250ms !important}div.vectorMenu.menuForceShow h3 a{background-position:100% 100% !important}div.vectorMenuFocus h3 a{background-image:url('skins/Vector/images/arrow-down-focus-icon.png') !important;background-image:-webkit-linear-gradient(transparent, transparent),/* @embed */ url('skins/Vector/images/arrow-down-focus-icon.svg') !important;background-image:linear-gradient(transparent, transparent),/* @embed */ url('skins/Vector/images/arrow-down-focus-icon.svg') !important}div.vectorMenu div.menu{min-width:100% !important;position:absolute !important;top:2.5em !important;left:-1px !important;background-color:white !important;border:solid 1px silver !important;border-top-width:0 !important;clear:both !important;text-align:left !important;display:none !important}div.vectorMenu:hover div.menu,div.vectorMenu.menuForceShow div.menu{display:block !important}div.vectorMenu ul{list-style-type:none !important;list-style-image:none !important;padding:0 !important;margin:0 !important;text-align:left !important}div.vectorMenu ul,x:-moz-any-link{min-width:5em !important}div.vectorMenu ul,x:-moz-any-link,x:default{min-width:0 !important}div.vectorMenu li{padding:0 !important;margin:0 !important;text-align:left !important;line-height:1em !important}div.vectorMenu li a{display:inline-block !important;padding:.5em !important;white-space:nowrap !important;color:#7d9ed4 !important;cursor:pointer !important;font-size:.8em !important}div.vectorMenu li>a{display:block !important}div.vectorMenu li.selected a,div.vectorMenu li.selected a:visited{color:#333 !important;text-decoration:none !important}@-webkit-keyframes rotate{from{-webkit-transform:rotate(0deg) !important;-moz-transform:rotate(0deg) !important;transform:rotate(0deg) !important}to{-webkit-transform:rotate(360deg) !important;-moz-transform:rotate(360deg) !important;transform:rotate(360deg) !important} !important}@-moz-keyframes rotate{from{-webkit-transform:rotate(0deg) !important;-moz-transform:rotate(0deg) !important;transform:rotate(0deg) !important}to{-webkit-transform:rotate(360deg) !important;-moz-transform:rotate(360deg) !important;transform:rotate(360deg) !important} !important}@-o-keyframes rotate{from{-webkit-transform:rotate(0deg) !important;-moz-transform:rotate(0deg) !important;transform:rotate(0deg) !important}to{-webkit-transform:rotate(360deg) !important;-moz-transform:rotate(360deg) !important;transform:rotate(360deg) !important} !important}@keyframes rotate{from{-webkit-transform:rotate(0deg) !important;-moz-transform:rotate(0deg) !important;transform:rotate(0deg) !important}to{-webkit-transform:rotate(360deg) !important;-moz-transform:rotate(360deg) !important;transform:rotate(360deg) !important} !important}#ca-unwatch.icon a,#ca-watch.icon a{margin:0 !important;padding:0 !important;display:block !important;width:26px !important;padding-top:3.1em !important;margin-top:0 !important;height:0 !important;overflow:hidden !important;background-position:5px 60% !important}#ca-unwatch.icon a{background-image:url('skins/Vector/images/unwatch-icon.png') !important;background-image:-webkit-linear-gradient(transparent, transparent),/* @embed */ url('skins/Vector/images/unwatch-icon.svg') !important;background-image:linear-gradient(transparent, transparent),/* @embed */ url('skins/Vector/images/unwatch-icon.svg') !important}#ca-watch.icon a{background-image:url('skins/Vector/images/watch-icon.png') !important;background-image:-webkit-linear-gradient(transparent, transparent),/* @embed */ url('skins/Vector/images/watch-icon.svg') !important;background-image:linear-gradient(transparent, transparent),/* @embed */ url('skins/Vector/images/watch-icon.svg') !important}#ca-unwatch.icon a:hover,#ca-unwatch.icon a:focus{background-image:url('skins/Vector/images/unwatch-icon-hl.png') !important;background-image:-webkit-linear-gradient(transparent, transparent),/* @embed */ url('skins/Vector/images/unwatch-icon-hl.svg') !important;background-image:linear-gradient(transparent, transparent),/* @embed */ url('skins/Vector/images/unwatch-icon-hl.svg') !important}#ca-watch.icon a:hover,#ca-watch.icon a:focus{background-image:url('skins/Vector/images/watch-icon-hl.png') !important;background-image:-webkit-linear-gradient(transparent, transparent),/* @embed */ url('skins/Vector/images/watch-icon-hl.svg') !important;background-image:linear-gradient(transparent, transparent),/* @embed */ url('skins/Vector/images/watch-icon-hl.svg') !important}#ca-unwatch.icon a.loading,#ca-watch.icon a.loading{background-image:url('skins/Vector/images/watch-icon-loading.png') !important;background-image:-webkit-linear-gradient(transparent, transparent),/* @embed */ url('skins/Vector/images/watch-icon-loading.svg') !important;background-image:linear-gradient(transparent, transparent),/* @embed */ url('skins/Vector/images/watch-icon-loading.svg') !important;-webkit-animation:rotate 700ms infinite linear !important;-moz-animation:rotate 700ms infinite linear !important;-o-animation:rotate 700ms infinite linear !important;animation:rotate 700ms infinite linear !important;outline:none !important;cursor:default !important;pointer-events:none !important;background-position:50% 60% !important;-webkit-transform-origin:50% 57% !important;transform-origin:50% 57% !important}#ca-unwatch.icon a span,#ca-watch.icon a span{display:none !important}#mw-navigation h2{position:absolute !important;top:-9999px !important}#mw-page-base{height:5em !important;background-position:bottom left !important;background-repeat:repeat-x !important;background-image:url('skins/Vector/images/page-fade.png') !important;background-color:#2a2a2a !important;background-image:-moz-linear-gradient(top, #333 50%, #2a2a2a 100%) !important;background-image:-webkit-gradient(linear, left top, left bottom, color-stop(50%, #333), color-stop(100%, #2a2a2a)) !important;background-image:-webkit-linear-gradient(top, #333 50%, #2a2a2a 100%) !important;background-image:linear-gradient(#333 50%, #2a2a2a 100%) !important;background-color:#333 !important}#mw-head-base{margin-top:-5em !important;margin-left:10em !important;height:5em !important}div#mw-head{position:absolute !important;top:0 !important;right:0 !important;width:100% !important}div#mw-head h3{margin:0 !important;padding:0 !important}#left-navigation{float:left !important;margin-left:10em !important;margin-top:2.5em !important;margin-bottom:-2.5em !important;display:inline !important}#right-navigation{float:right !important;margin-top:2.5em !important}#p-logo{position:absolute !important;top:-160px !important;left:0 !important;width:10em !important;height:160px !important}#p-logo a{display:block !important;width:10em !important;height:160px !important;background-repeat:no-repeat !important;background-position:center center !important;text-decoration:none !important}div#mw-panel{font-size:inherit !important;position:absolute !important;top:160px !important;padding-top:1em !important;width:10em !important;left:0 !important}div#mw-panel div.portal{margin:0 .6em 0 .7em !important;padding:.25em 0 !important;direction:ltr !important;background-position:top left !important;background-repeat:no-repeat !important;background-image:/* @embed */ url('skins/Vector/images/portal-break.png') !important}div#mw-panel div.portal h3{font-size:.75em !important;color:#4d4d4d !important;font-weight:normal !important;margin:0 !important;padding:.25em 0 .25em .25em !important;cursor:default !important;border:none !important}div#mw-panel div.portal div.body{margin:0 0 0 1.25em !important;padding-top:0 !important}div#mw-panel div.portal div.body ul{list-style-type:none !important;list-style-image:none !important;margin:0 !important;padding:0 !important}div#mw-panel div.portal div.body ul li{line-height:1.125em !important;margin:0 !important;padding:.25em 0 !important;font-size:.75em !important;word-wrap:break-word !important}div#mw-panel div.portal div.body ul li a{color:#7d9ed4 !important}div#mw-panel div.portal div.body ul li a:visited{color:#8a7f6c !important}div#mw-panel div.portal.first{background-image:none !important;margin-top:0 !important}div#mw-panel div.portal.first h3{display:none !important}div#mw-panel div.portal.first div.body{margin-left:.5em !important}div#footer{margin-left:10em !important;margin-top:0 !important;padding:.75em !important;direction:ltr !important}div#footer ul{list-style-type:none !important;list-style-image:none !important;margin:0 !important;padding:0 !important}div#footer ul li{margin:0 !important;padding:0 !important;padding-top:.5em !important;padding-bottom:.5em !important;color:#333 !important;font-size:.7em !important}div#footer #footer-icons{float:right !important}div#footer #footer-icons li{float:left !important;margin-left:.5em !important;line-height:2em !important;text-align:right !important}div#footer #footer-info li{line-height:1.4em !important}div#footer #footer-places li{float:left !important;margin-right:1em !important;line-height:2em !important}body.ltr div#footer #footer-places{float:left !important}.mw-body .external{background-position:center right !important;background-repeat:no-repeat !important;background-image:url('skins/Vector/images/external-link-ltr-icon.png') !important;background-image:-webkit-linear-gradient(transparent, transparent),/* @embed */ url('skins/Vector/images/external-link-ltr-icon.svg') !important;background-image:linear-gradient(transparent, transparent),/* @embed */ url('skins/Vector/images/external-link-ltr-icon.svg') !important;padding-right:13px !important}</div>PoomSmarthttps://iphonedev.wiki/index.php?title=Welcome&diff=5899Welcome2022-07-28T12:37:33Z<p>PoomSmart: Removed dead page</p>
<hr />
<div>__NOTOC__<br />
{{DISPLAYTITLE:<span style="position: absolute; clip: rect(1px 1px 1px 1px); clip: rect(1px, 1px, 1px, 1px);">{{FULLPAGENAME}}</span>}}<br />
<br />
<div><br />
<div style="margin-top: 2em;"><br />
<h1 style="position: absolute;top: -17px;"><span class="mw-headline" id="Welcome_to_the_iPhoneDevWiki">Welcome to the iPhoneDevWiki</span></h1><br />
Our goal is to share the sum of all human<ref> We'll make an exception for lawyers; they may submit too. Cf. http://wiki.creativecommons.org/Frequently_Asked_Questions#How_does_a_Creative_Commons_license_operate.3F: "Creative Commons licenses are expressed in three different formats: the Commons Deed (human-readable code), the Legal Code (lawyer-readable code); and the metadata (machine readable code)."</ref> knowledge about jailbroken iOS development. In other words, this is a collection of documentation written by developers to help each other write extensions (tweaks) for jailbroken iOS, and you're invited to learn from it and contribute to it too.<br />
<br />
What is this wiki for?<br />
<br />
* Information about using iOS frameworks, system daemons (for hooking and hacking), and other iOS internals.<br />
* Information about third-party libraries and extensions for developers.<br />
* Useful information for reverse engineers and tweak developers.<br />
* Documentation about making [http://iphonedevwiki.net/index.php/Category:Preferences preferences] for tweaks.<br />
* Anything else about development for jailbroken iOS devices. <br />
<br />
For other technical information about iOS, see [http://theiphonewiki.com The iPhone Wiki], which covers topics including jailbreak exploits, internal iOS systems, and iOS hardware details. [http://theiphonewiki.com/wiki/Up_to_Speed "Up to Speed"] is its getting-started page about learning about security research on iOS.<br />
<br />
Doing some late-night hacking / tired of the eye strain? 2-step instructions on how to turn on dark mode are over at [[Dark Mode]].<br />
<br />
</div><br />
<div><br />
<br />
== Getting started ==<br />
<br />
New to developing for jailbroken devices? Welcome, it's fun and challenging! Hopefully you already have some experience with Objective-C. You will want to get familiar with [[MobileSubstrate|Cydia Substrate (formerly called MobileSubstrate)]] and [[Theos]], and you can study some [[Open Source Projects]] to see how existing tweaks work. See '''[[Getting Started]]''' and also take a look at [[Best Practices]] and [[MobileSubstrate Pitfalls]]. If you're looking for a more thorough and sequential tutorial, take a look at the book ''[http://iosre.com/t/ios-app-reverse-engineering-the-worlds-1st-book-of-very-detailed-ios-app-reverse-engineering-skills/1117 iOS App Reverse Engineering]'' and its forum [http://bbs.iosre.com iOSRE].<br />
<br />
'''[[Getting Help | How to ask for help]]:''' There are tags for [http://stackoverflow.com/questions/tagged/jailbreak "jailbreak"], [http://stackoverflow.com/questions/tagged/cydia "Cydia"], and [http://stackoverflow.com/questions/tagged/theos "Theos"] on Stack Overflow, a site for programming questions in general; feel free to ask there as well. On reddit, there's [http://www.reddit.com/r/jailbreakdevelopers/ /r/jailbreakdevelopers]. For non-development-related troubleshooting questions, try [http://www.reddit.com/r/jailbreak/ /r/jailbreak].<br />
<br />
</div><br />
</div><br />
<br />
== Overview of contents ==<br />
<br />
<div class="flex"><br />
<div><br />
=== Frameworks: ===<br />
* {{fwlink|UIKit}}<br />
* {{fwlink|GraphicsServices}} <br />
* {{fwlink|AppSupport}} <br />
* {{fwlink|BiometricKit}} <br />
* {{fwlink|ChatKit}} <br />
* {{fwlink|MobileWiFi}} <br />
* '''''[[Template:Navbox Frameworks|more »]]'''''<br />
<br />
=== Applications: ===<br />
* {{applink|SpringBoard}} <br />
* {{applink|Preferences}} <br />
* {{applink|MobileSafari}} <br />
* '''''[[Template:Navbox Applications|more »]]'''''<br />
<br />
=== System directories: ===<br />
* [[Frameworks]] <br />
* [[Internet Plug-Ins]] <br />
* [[PreferenceBundles]] <br />
* [[PrivateFrameworks]] <br />
* '''''[[Template:Navbox_Library|more »]]'''''<br />
<br />
=== Other parts of iOS: ===<br />
* [[dyld_shared_cache]]<br />
* [[Bluetooth]] <br />
* [[CgBI file format]] <br />
* [[Coprocessors]] <br />
* [[Daemons]]<br />
* [[Entitlements]] <br />
* [[iOS Keyboard]] <br />
* [[launchd]] <br />
* [[NFC]] <br />
* [[Notifications]]<br />
* [[Seatbelt]]<br />
<br />
=== By iOS Version ===<br />
<br />
* '''New in iOS 15:''' [[Updating extensions for iOS 15/16]]<br />
* '''New in iOS 14:''' [[Updating extensions for iOS 14]]<br />
* '''New in iOS 13:''' [[Updating extensions for iOS 13]]<br />
* '''New in iOS 12:''' [[Updating extensions for iOS 12]]<br />
* '''New in iOS 11:''' [[Updating extensions for iOS 11]]<br />
* '''New in iOS 10:''' [[Updating extensions for iOS 10]], [[ControlCenterUI.framework]], [[UserNotificationsUIKit.framework]].<br />
* '''New in iOS 9:''' [[Updating extensions for iOS 9]], [[Updating extensions for iOS 9.3.3]], [[Breadcrumbs]].<br />
* '''New in iOS 8:''' [[Updating extensions for iOS 8]], [[AssertionServices.framework]], [[SBSRestartRenderServerAction]], [[FBSSystemService]], [[UIAlertController]].<br />
* '''New in iOS 7:''' [[Updating extensions for iOS 7]], [[Debugging on iOS 7]], [[Downgrading iPhone 4 from iOS 7]], [[BiometricKit.framework]], [[TouchID]], [[UIBackdropView]], [[AVFlashlight]], [[SBAppSliderController]].<br />
* '''New in iOS 6:''' [[BackBoardServices.framework]], [[backboardd]], [[ChatKit.framework]], [[BKSProcessAssertion]].<br />
* '''New in iOS 5:''' [[SBIconView]], [[CKMadridService]], [[SBAppContextHostManager]].<br />
* '''New in iOS 4:''' [[SBAppSwitcherModel]].<br />
<br />
</div><br />
<div><br />
<br />
=== Development tools: ===<br />
* [[Theos]], [[Logos]], [[NIC]], [[Logify]] <br />
* [[Reverse Engineering Tools]] <br />
* [[Jailbreak Development Tools]] <br />
* [[Preferences specifier plist]]<br />
* [[SSH Over USB]]<br />
* [[MobileSubstrate|Cydia Substrate (MobileSubstrate)]] <br />
* [[debugserver|debugserver (remote debugging)]] <br />
* [[ldid]] <br />
* [[On-device toolchains]] <br />
* [[Retrieving SDKs]] <br />
* [[Xcode|Xcode &ndash; Bypass Provisioning Profile]]<br />
<br />
=== Extensions: ===<br />
* [[ActionMenu]]<br />
* [[AppList]] <br />
* [[Cydget]] <br />
* [[Flipswitch]] <br />
* [[IconSupport]] <br />
* [[LayerSnapshotter]] <br />
* [[libactivator]] <br />
* [[libhide]] <br />
* [[libobjcipc]] <br />
* [[libstatusbar]] <br />
* [[PreferenceLoader]] <br />
* [[RocketBootstrap]] <br />
* [[WinterBoard]] <br />
* [[libPassword]]<br />
* '''''[[:Category:Cydia_packages|more »]]'''''<br />
<br />
=== Other articles about development: ===<br />
* [[Getting Started]] <br />
* [[Best Practices]] <br />
* [[MobileSubstrate Pitfalls]] <br />
* [[Open Source Projects]] <br />
* [[Advice for new developers]] <br />
* [[Cydia Store Integration]]<br />
* [[Tweak DRM]] <br />
* [[Code Signing]] <br />
* [[Repository Management]] <br />
* [[Packaging]] <br />
* [[Crack prevention]] <br />
* [[List of development blogs]] <br />
* [[Using ARC in tweaks]] <br />
* [[Career advice]]<br />
<br />
</div><br />
</div><br />
<br />
<br />
<br />
Translated articles: <br />
<br />
* '''Français''': [[Main page/fr]] &bull; [[MobileSubstrate/fr]] &bull; [[SSH Over USB/fr]] &bull; [[UIFont/fr]] &bull; [[UIColor/fr]] &bull; [[ActorKit.framework/fr]] &bull; [[IOSOpenDev/fr]]<br />
* '''ไทย''': [[SSH Over USB/th]] &bull; [[SpringBoard.app/th]] &bull; [[UIColor/th]]<br />
* '''Deutsch''': [[Theos/de]]<br />
<br />
<!-- {{Navbox Frameworks}}<br />
{{Navbox Applications}} --><br />
<br />
<br />
<div class="flex"><br />
<div><br />
<br />
== Editing this wiki ==<br />
<br />
* If you have anything at all to contribute, feel free to do so!<br />
<br />
Some ideas for information to contribute:<br />
<br />
* Add more projects to the list of [[Open Source Projects]], or fill out details on that page.<br />
* Expand [[Getting Started]] for new developers - what do they need to know before beginning? How do they set up a development environment on OS X, Windows, and Linux? What are common beginner's mistakes that they should watch out for? How to reverse-engineer parts of iOS for writing tweaks? How to debug with GDB and learn about memory management?<br />
* Update articles that haven't been significantly edited in a few years, such as [[Seatbelt]] and [[Crack prevention]]. See [[Special:AncientPages]] for a list of articles that haven't been updated recently.<br />
* Help [[Cycript]] explain why Cycript is fun - syntax highlighting, injection, auto-completion, generally exploring around.<br />
* Make a page that documents a class or framework you're familiar with.<br />
* If you've developed a library that other developers can use or write addons/plugins/extensions for, make a page that documents your project.<br />
* Update [[Xcode]] with better information about how to build apps for jailbroken devices.<br />
* Make the homepage more useful! For example, add links to good pages that are hidden/buried deep within the wiki.<br />
* The following articles are linked from nowhere in the wiki: [[Special:LonelyPages]] - you can fix that by linking them somewhere.<br />
* Check out the most popular pages and see if they need updating: [[Special:PopularPages]].<br />
* Write an article that is in demand: [[Special:WantedPages]].<br />
* Translate an existing article into a non-English language. Check out the list at [[Special:PopularPages]] for ideas about high-priority articles to translate, and then make a new page with this name format: <code>Article name/[language code]</code>. [http://svn.wikimedia.org/svnroot/mediawiki/trunk/phase3/languages/Names.php Here's the list of language codes.] For example: [[PreferenceLoader/de]] or [[Libactivator/sv]].<br />
<br />
</div><br />
<div><br />
<br />
== Good Edit Candidates == <br />
<br />
If you're looking for some articles to work on that dont require a ton of in-depth RE, or are important yet woefully outdated, the following articles are good candidates:<br />
<br />
* [[Jailbreak detection]]<br />
* [[CATransition]]<br />
* [[Code Signing]] - Not bad info, needs updated primary instructions for current year<br />
* [[Notifications]] - Update with info about MuireyIPC, new pages, etc. <br />
* [[Best_Practices]]<br />
* [[IOS Keyboard]] - Woefully outdated + no useful info<br />
* [[IWidgets]] - Conglomerate and link to modern replacements.<br />
<br />
</div><br />
</div><br />
----<br />
<br />
<references /></div>PoomSmarthttps://iphonedev.wiki/index.php?title=Libundirect&diff=5898Libundirect2022-07-28T12:36:04Z<p>PoomSmart: Updated latest version</p>
<hr />
<div>{{DISPLAYTITLE:libundirect}}<br />
{{Infobox Package<br />
|developer=[https://twitter.com/opa334dev Lars Fröder (opa334)]<br />
|version=1.1.3<br />
|package=com.opa334.libundirect<br />
}}<br />
<br />
'''libundirect''' is a patchfinding and rebinding 64-bit library that provides directives to hook Objective-C direct methods. With the feature called <code>objc_direct</code> introduced in Xcode 12 and iOS 14.0, these direct methods are stripped when compiled - being unexported C functions and thus their signature and name are missing.<br />
<br />
As a patchfinder, <code>libundirect_find()</code> can find the address of the function to hook by providing unique bytes within the function and the name of the binary or library that the function resides. You need to perform reverse engineering on the binary that you are working with in order to determine the bytes to use. See [https://github.com/opa334/libundirect/blob/main/README.md#patchfinder libundirect's note on patchfinding] or [https://gist.github.com/johnzaro/fdffd93c2ee0bc7db56d7959a67b4235 johnzaro's guide to using libundirect] for more details.<br />
<br />
As a rebinder, <code>libundirect_rebind()</code> can re-add Objective-C method signature to the function that you hook. This provides backward compatibility for earlier iOS versions that the signature is still intact - and that you have to import <code><libundirect/libundirect_hookoverwrite.h></code> to make <code>MSHookMessageEx()</code> aware of direct methods and turn itself into <code>MSHookFunction</code> (because it is just a C-like function now).<br />
<br />
== How to use this library ==<br />
<br />
Headers are available from [https://github.com/opa334/libundirect libundirect's GitHub project] (the latest one) or from [https://github.com/theos/headers Theos' headers project]. The library from opa334's repository can be installed to <code>$THEOS/vendor/lib</code> by running <code>install_to_theos.sh</code> script inside libundirect repository.<br />
<br />
=== Include directive(s) ===<br />
<br />
<source lang="objc"><br />
#import <libundirect/libundirect.h><br />
#import <libundirect/libundirect_dynamic.h> // if you don't want to link directly against libundirect, import this one instead<br />
#import <libundirect/libundirect_hookoverwrite.h> // if you want backward compatibility<br />
</source><br />
<br />
=== Makefile ===<br />
<br />
Add to your Makefile:<br />
<br />
* <code>XXX_LIBRARIES = undirect</code><br />
<br />
=== Packaging ===<br />
<br />
Add to your package's control file:<br />
<br />
* <code>com.opa334.libundirect (>= 1.1.1)</code> to the <code>Depends</code> field.<br />
<br />
== Examples ==<br />
<br />
=== Hooking (and rebinding) a direct Objective-C method (MobileSafari) ===<br />
<br />
We will use the code in SafariPlus by opa334 as an example.<br />
<br />
<source lang="objc"><br />
#import <libundirect/libundirect.h><br />
#import <libundirect/libundirect_hookoverwrite.h><br />
#import <version.h><br />
<br />
%hook BrowserController<br />
<br />
- (void)tabControllerDocumentCountDidChange:(TabController *)tabController {<br />
%orig;<br />
...<br />
}<br />
<br />
%end<br />
<br />
...<br />
<br />
// In your constructor:<br />
<br />
if (IS_IOS_OR_NEWER(iOS_14_0)) {<br />
Class class_browserController = NSClassFromString(@"BrowserController");<br />
<br />
// -[BrowserController tabControllerDocumentCountDidChange:]<br />
// arm64 memory of function: [600100B4 F44FBEA9]<br />
// arm64e memory of function: [A00100B4 7F2303D5 F44FBEA9]<br />
// criteria: called by -[BrowserController _updateSceneTitle] (14.2: sub_100041e5c, references string @"Private Browsing")<br />
// 14.2: sub_10005bef8, arm64e: sub_10005E824<br />
<br />
#if __arm64e__<br />
void* tabControllerDocumentCountDidChange = libundirect_find(@"MobileSafari", (unsigned char[]){0xA0, 0x01, 0x00, 0xB4, 0x7F, 0x23, 0x03, 0xD5, 0xF4, 0x4F, 0xBE, 0xA9}, 12, 0);<br />
#else<br />
void* tabControllerDocumentCountDidChange = libundirect_find(@"MobileSafari", (unsigned char[]){0x60, 0x01, 0x00, 0xB4, 0xF4, 0x4F, 0xBE, 0xA9}, 8, 0);<br />
#endif<br />
<br />
libundirect_rebind(tabControllerDocumentCountDidChange, class_browserController, @selector(tabControllerDocumentCountDidChange:), "v@:@");<br />
}<br />
<br />
%init;<br />
</source><br />
<br />
=== Hooking an unnamed C function (libicucore) ===<br />
<br />
We will use the code in EmojiAttributes by PoomSmart as an example.<br />
<br />
<source lang="objc"><br />
#import <libundirect/libundirect.h><br />
<br />
...<br />
<br />
%group getUnicodeProperties<br />
<br />
%hookf(uint32_t, u_getUnicodeProperties, UChar32 c, int32_t column) {<br />
if (column >= propsVectorsColumns)<br />
return 0;<br />
uint16_t vecIndex = UTRIE2_GET16(&propsVectorsTrie, c);<br />
return propsVectors[vecIndex + column];<br />
}<br />
<br />
%end<br />
<br />
// In your constructor:<br />
<br />
#if TARGET_OS_SIMULATOR<br />
// Memory of function (iOS 13.5): 31C083FE 020F8F8D 00000055 4889E581 FFFFD700 00770789 F8C1E805 EB4A81FF FFFF0000 771731C0 81FF00DC 0000B940 0100000F 4DC889F8 C1E805EB 29B8D813 000081FF FFFF1000 773289F8 C1E80B48 8D0D30CC 1B000FB7 8C414010 000089F8 C1E80583 E03F01C8 89C0488D 0D15CC1B 000FB704 4183E71F 488D0487 488D0D03 CC1B000F B7044148 63CE4801 C1488D05 D2B11A00 8B04885D C3<br />
// Memory of function (iOS 12.4): 554889E5 31C083FE 020F8F8A 00000081 FFFFD700 00770789 F8C1E805 EB4C81FF FFFF0000 771731C0 81FF00DC 0000B940 0100000F 4DC889F8 C1E805EB 2B81FFFF FF100076 07B8D413 0000EB32 89F8C1E8 0B488D0D CFE61B00 0FB78C41 40100000 89F8C1E8 0583E03F 01C889C0 488D0DB4 E61B000F B7044183 E71F488D 0487488D 0DA2E61B 000FB704 414863CE 4801C148 8D0571D3 1A008B04 885DC3<br />
// Unique bytes (iOS 13.5): E03F01C8 89C0488D 0D15CC1B (offset: 100)<br />
// Unique bytes (iOS 12.4): 0583E03F 01C889C0 488D0DB4 (offset: 100)<br />
// Starting byte (iOS 13.5): 0x31<br />
// Starting byte (iOS 12.4): 0x55<br />
void *rp = libundirect_find(@"libicucore.A.dylib", (unsigned char[]){0xE0, 0x3F, 0x01, 0xC8, 0x89, 0xC0, 0x48, 0x8D, 0x0D, 0x15, 0xCC, 0x1B}, 12, 0x31);<br />
if (rp == NULL)<br />
rp = libundirect_find(@"libicucore.A.dylib", (unsigned char[]){0x05, 0x83, 0xE0, 0x3F, 0x01, 0xC8, 0x89, 0xC0, 0x48, 0x8D, 0x0D, 0xB4}, 12, 0x55);<br />
#else<br />
// Memory of function: 3F080071 6D000054 00008052 C0035FD6 087C0B53 1F690071 68000054 087C0513 08000014 087C1053 68020035 08809B52 1F00086B 08288052 08B19F1A 0815800B 090D00B0 29110F91 28D96878 09100012 2809080B 090D00B0 29110F91 28D96878 0801010B 890C00B0 29A12791 20D968B8 C0035FD6 1F410071 69000054 08548252 F5FFFF17 087C0B13 090D00B0 29110F91 28C5288B 08816079 0A280553 08412A8B 28796878 EAFFFF17<br />
// Unique bytes: 3F080071 6D000054 00008052 C0035FD6 (offset: 0)<br />
// Starting byte: 0x3F<br />
void *rp = libundirect_find(@"libicucore.A.dylib", (unsigned char[]){0x3F, 0x08, 0x00, 0x71, 0x6D, 0x00, 0x00, 0x54, 0x00, 0x00, 0x80, 0x52, 0xC0, 0x03, 0x5F, 0xD6}, 16, 0x3F);<br />
#endif<br />
<br />
%init(getUnicodeProperties, u_getUnicodeProperties = (void *)rp);<br />
</source><br />
<br />
== Project Examples ==<br />
<br />
{| class="wikitable"<br />
|-<br />
! Project<br />
! Author<br />
|-<br />
| [https://github.com/opa334/SafariPlus SafariPlus]<br />
| [https://github.com/opa334 opa334]<br />
|-<br />
| [https://github.com/udevsharold/safaritabs14 SafariTabs14]<br />
| [https://github.com/udevsharold udevsharold]<br />
|-<br />
| [https://github.com/p2kdev/SafariBlocker SafariBlocker]<br />
| [https://github.com/p2kdev p2kdev]<br />
|-<br />
| [https://github.com/PoomSmart/EmojiAttributes EmojiAttributes]<br />
| [https://github.com/PoomSmart PoomSmart]<br />
|}<br />
<br />
== External Links ==<br />
<br />
* [https://github.com/opa334/libundirect/blob/main/README.md libundirect's detailed usages]<br />
* [https://gist.github.com/johnzaro/fdffd93c2ee0bc7db56d7959a67b4235 Using disassembler to find unique bytes for libundirect]<br />
* [https://nshipster.com/direct/ Objective-C Direct Methods]<br />
<br />
{{Navbox Library}}<br />
<br />
[[Category:Cydia packages]]<br />
<br />
[[Category:Directories in /Library]]</div>PoomSmarthttps://iphonedev.wiki/index.php?title=SSH_Over_USB&diff=5897SSH Over USB2022-07-28T12:33:30Z<p>PoomSmart: Fixed syntax and small things</p>
<hr />
<div><small>'''Languages: English &bull; [[SSH Over USB/fr|français]] &bull; [[SSH Over USB/th|ไทย]]'''</small><br />
<br />
== SSH over USB using usbmuxd ==<br />
<br />
You can either download a binary and run that or use a python script. The python script is a lot slower than the binary version. On Linux the python method is mostly deprecated, use the binary version provided by libimobiledevice. There is also a newer solution called gandalf. <br />
<br />
=== Using binary ===<br />
<br />
On Windows, ensure iTunes is installed, then download itunnel_mux_rev71.zip from [https://code.google.com/archive/p/iphonetunnel-usbmuxconnectbyport/downloads Google Code]. Unzip to a directory of choice.<br />
<br />
On OS X and Linux, install [https://github.com/libimobiledevice/usbmuxd usbmuxd] from your package manager.<br />
<br />
Then:<br />
<br />
* Windows: Run <code>path/to/itunnel_mux.exe --iport 22 --lport 2222</code><br />
* OS X/Linux: <code>iproxy 2222 22</code><br />
<br />
Connect to <code>localhost -p 2222</code> as you would over wifi.<br />
<br />
If you have multiple devices connected, it may be useful to run multiple instances, specifying UDIDs and ports like so:<br />
<br />
<source lang="bash"><br />
iproxy 2222 22 abcdef0123456789abcdef1234567890abcdef12 & \<br />
iproxy 2223 22 9876543210fedcba9876543210fedcba98765432<br />
</source><br />
<br />
==== Making iproxy run automatically in the background on OS X ====<br />
<br />
* Install it with Homebrew (<code>brew install libimobiledevice</code>).<br />
* Create the file <code>~/Library/LaunchAgents/com.usbmux.iproxy.plist</code> with the contents:<br />
<source lang="xml"><br />
<?xml version="1.0" encoding="UTF-8"?><br />
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><br />
<plist version="1.0"><br />
<dict><br />
<key>Label</key><br />
<string>com.usbmux.iproxy</string><br />
<key>ProgramArguments</key><br />
<array><br />
<string>/usr/local/bin/iproxy</string><br />
<string>2222</string><br />
<string>22</string><br />
</array><br />
<key>RunAtLoad</key><br />
<true/><br />
<key>KeepAlive</key><br />
<true/><br />
</dict><br />
</plist><br />
</source><br />
<br />
* Run <code>launchctl load ~/Library/LaunchAgents/com.usbmux.iproxy.plist</code>.<br />
* You now don't have to run the iproxy binary every time you want to SSH over USB as the iproxy software is always running in the background.<br />
<br />
If you have several devices you can create a daemon with a specific port for each one.<br />
* Create a file in <code>~/Library/LaunchAgents/</code> but name it using the device UDID, name or an identifier of your choice (like <code>com.usbmux.iproxy.iPhone7,2.plist</code>).<br />
* Replace <tt>UDID_HERE</tt> in the following snippet with the device UDID. The label should be unique and is best to match the filename you used.<br />
<br />
<source lang="xml"><br />
<?xml version="1.0" encoding="UTF-8"?><br />
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><br />
<plist version="1.0"><br />
<dict><br />
<key>Label</key><br />
<string>com.usbmux.iproxy.iPhone7,2</string><br />
<key>ProgramArguments</key><br />
<array><br />
<string>/usr/local/bin/iproxy</string><br />
<string>2222</string><br />
<string>22</string><br />
<string>UDID_HERE</string><br />
</array><br />
<key>RunAtLoad</key><br />
<true/><br />
<key>KeepAlive</key><br />
<true/><br />
</dict><br />
</plist><br />
</source><br />
* Run <code>launchctl load ~/Library/LaunchAgents/FILE_NAME_OF_YOUR_CHOICE</code>.<br />
* You now don't have to run the iproxy binary every time you want to SSH over USB as the iproxy software is always running in the background.<br />
<br />
=== Using Python ===<br />
<br />
Tested on OS X and Windows.<br />
<br />
You will need to have Python installed on your system.<br />
<br />
* Get [http://marcansoft.com/blog/iphonelinux/usbmuxd/ usbmuxd] source package and unpack. (Or if the linked usbmuxd package doesn't work, try [http://cgit.sukimashita.com/libusbmuxd.git/ libusbmuxd].)<br />
* Go into folder python-client<br />
* <code>chmod +x tcprelay.py</code><br />
* Run <code>./tcprelay.py -t 22:2222</code><br />
<br />
Now you can log into your device via ssh mobile@localhost -p 2222<br />
<br />
The -t switch tells tcprelay to run threaded and allow more than one ssh over the same port.<br />
<br />
See ./tcprelay.py --help for further options.<br />
<br />
=== Using gandalf ===<br />
<br />
Tested on OS X and Linux, each with up to 29 devices connected at the same time. The advantage of using <br />
gandalf is that it is written in a functional programming language, which practically means that it won't <br />
give you seg faults and it is actively maintained https://github.com/onlinemediagroup/ocaml-usbmux<br />
<br />
* Installation<br />
You need to have opam installed, it is OCaml's package manager.<br />
<br />
On OS X you can do:<br />
<br />
<pre><br />
$ brew install opam<br />
</pre><br />
<br />
(If on Linux, then get opam via your package manager, details available https://opam.ocaml.org/doc/Install.html, <br />
Ubuntu users please pay attention, need to use a ppa for opam). <br />
It is important that your compiler is up to date, you can<br />
check with opam switch, make sure its at least >= 4.02.0<br />
<br />
then<br />
<br />
<pre><br />
$ opam install usbmux<br />
</pre><br />
<br />
This will install the command line tool gandalf and an OCaml<br />
library.<br />
<br />
* gandalf usage.<br />
<br />
The following are a series of usages of gandalf, all short form<br />
arguments have long-forms as well and -v can be added at any time.<br />
<br />
1) See with realtime updates what devices are connected <br />
<br />
<pre><br />
$ gandalf<br />
</pre><br />
This will start up gandalf in listen mode, that is it will print<br />
out whenever a device connects or disconnects and more crucially <br />
it will print out the UDID of each device. <br />
<br />
2) Start with a mapping file which is of the form<br />
<udid>:<local_port>:<device_port>. The # character starts comments<br />
So an example mapping file would be: <br />
<br />
<pre><br />
# the phone1 udid, local port 2000, phone's port 22 aka ssh<br />
123456dfg213423453456123dfg:2000:22<br />
# phone 2, same deal but note different local port <br />
frgfg2345345123jifgidfug123:2001:22<br />
</pre><br />
<br />
and the gandalf invocation is: <br />
<br />
<pre><br />
$ gandalf -m mapping<br />
</pre><br />
<br />
2.1) You can also daemonize gandalf with the -d flag. *NOTE*: You might need to end up doing that under sudo as gandalf needs to<br />
make a pid file under /var/run.<br />
<br />
3) To see a pretty JSON representation of devices and their ports that are currently connected, do:<br />
<br />
<pre><br />
$ gandalf -s<br />
</pre><br />
<br />
4) To reload gandalf with a new set of mappings, do:<br />
<br />
<pre><br />
$ gandalf -r<br />
</pre><br />
<br />
This will cancel all running threads and reload from the original<br />
mappings file, so make your changes there.<br />
<br />
5) To cleanly exit gandalf, do: *NOTE* This might require super user permissions.<br />
<pre><br />
$ gandalf -e<br />
</pre><br />
<br />
Check out the man page, accessible with:<br />
<pre><br />
$ gandalf --help<br />
</pre><br />
<br />
or <br />
<br />
<pre><br />
$ man gandalf<br />
</pre><br />
<br />
Simple invocation:<br />
<br />
<pre><br />
$ sudo `which gandalf` --mappings etc/mapping --daemonize --verbose<br />
</pre><br />
<br />
* Important Notes and Catches<br />
<br />
1) If you are running this on Linux, then you might get issues with<br />
usbmuxd having issues when more than around 7 devices are plugged<br />
in. This is because multiple threads are trying to call various<br />
libxml2 freeing functions. I have a forked version of libplist<br />
that usbmuxd uses, sans the memory freeing calls. Its available<br />
[https://github.com/onlinemediagroup/libplist here]. Compile and install that, then compile and install usbmuxd<br />
from source. This will leak memory but its not that much at all and<br />
I believe it to be a fixed amount.<br />
<br />
2) Another issue you might have is USB3.0. The Linux kernel might crap<br />
out on you after 13 devices. This is a combination of the kernel<br />
not giving enough resources and the host controller on your<br />
motherboard being crappy. The solution to this problem is to<br />
disable USB3.0 in your BIOS. To verify that USB3.0 isn't working<br />
check with lsusb<br />
<br />
== SSH over USB using the iFunBox GUI (Windows only) ==<br />
<br />
This feature only exists in the '''Windows build''' of iFunBox.<br />
<br />
* Get the latest Windows build of [http://dl.i-funbox.com/ iFunBox] and install it.<br />
* Click on "Quick Toolbox," then "USB Tunnel."<br />
* Assign ports as you see fit.<br />
<br />
== SSH over USB using iPhoneTunnel Menu Bar Application (macOS only) ==<br />
<br />
[https://code.google.com/archive/p/iphonetunnel-mac/downloads Google Code Archive]<br />
<br />
[https://www.dropbox.com/s/mz4asmq8zc87hvh/iPhoneTunnel.app.zip?dl=0 DropBox Mirror]<br />
<br />
# Turn Tunnel On<br />
# Tools -> SSH<br />
<br />
== Theos usage ==<br />
Export the following variables in your shell in order to deploy builds to the connected device:<br />
<br />
<code>export THEOS_DEVICE_IP=localhost<br />
<br />
export THEOS_DEVICE_PORT=2222<br />
</code><br />
<br />
== SSH without password ==<br />
Run the following commands one time and you will not be asked to type your password again.<br />
<br />
You must create an SSH key with <code>ssh-keygen</code> if you have not created one. A passphrase isn’t required but still recommended. You can use <code>ssh-agent</code> [https://help.github.com/articles/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent/ as described here] to keep the passphrase in memory and not be prompted for it constantly.<br />
<br />
Then run the following command:<br />
<code>ssh-copy-id root@DEVICE_IP</code><br />
<br />
On OS X, ssh-copy-id will need to be installed with <code>brew install ssh-copy-id</code>.</div>PoomSmarthttps://iphonedev.wiki/index.php?title=LSApplicationProxy&diff=5803LSApplicationProxy2022-04-27T15:31:54Z<p>PoomSmart: /* Using LSApplicationProxy in your project */ Correction</p>
<hr />
<div>'''LSApplicationProxy''' is an object that provides information about App Store applications via a proxy.<br />
<br />
== Using LSApplicationProxy in your project ==<br />
<br />
Add MobileCoreServices to your Makefile<br />
<br />
<source><br />
Tweak_PRIVATE_FRAMEWORKS = MobileCoreServices<br />
</source><br />
<br />
Header:<br />
<source lang=objc><br />
@interface LSApplicationProxy : NSObject<br />
+ (id)applicationProxyForIdentifier:(id)arg1;<br />
- (NSString *)localizedNameForContext:(id)arg1; // iOS 11+<br />
- (NSString *)localizedName; // iOS 5-10<br />
- (NSURL *)bundleURL;<br />
- (NSURL *)containerURL;<br />
- (NSString *)bundleExecutable;<br />
- (NSString *)bundleIdentifier;<br />
- (NSString *)vendorName;<br />
- (NSString *)teamID;<br />
- (NSString *)applicationType;<br />
- (NSSet *)claimedURLSchemes;<br />
- (BOOL)isDeletable;<br />
@end<br />
</source><br />
<br />
== Creating an application proxy ==<br />
<br />
<source lang=objc><br />
LSApplicationProxy *proxy = [LSApplicationProxy applicationProxyForIdentifier:bundleIdentifier];<br />
NSString *genre = [proxy genre];<br />
</source><br />
<br />
== Getting display name for an application proxy ==<br />
<br />
<source lang=objc><br />
// iOS 11+<br />
NSString *name = [proxy localizedNameForContext:nil];<br />
<br />
// iOS 5-10<br />
NSString *name = [proxy localizedName];<br />
</source></div>PoomSmarthttps://iphonedev.wiki/index.php?title=Template:CoreFoundation_Version_Table&diff=5788Template:CoreFoundation Version Table2022-03-15T05:36:12Z<p>PoomSmart: Added CF ver for iOS 15.4</p>
<hr />
<div>{| class="wikitable sortable"<br />
|-<br />
! Firmware !! CoreFoundation version<br />
|-<br />
| 2.0 || 478.23<br />
|-<br />
| 2.1 || 478.26.1<br />
|-<br />
| 2.2 || 478.29<br />
|-<br />
| 3.0 || 478.47.7<br />
|-<br />
| 3.1 || 478.52<br />
|-<br />
| 3.2 || 478.61<br />
|-<br />
| 4.0 || 550.32<br />
|-<br />
| 4.1 || 550.38.1<br />
|-<br />
| 4.2 || 550.52 <br />
|-<br />
| 4.3 || 550.58.1<br />
|-<br />
| 5.0 || 675.00 <br />
|-<br />
| 5.1 || 690.10<br />
|-<br />
| 6.0 || 793.00<br />
|-<br />
| 6.1 || 793.00<br />
|-<br />
| 7.0 || 847.20<br />
|-<br />
| 7.1 || 847.24<br />
|-<br />
| 8.0 || 1140.10<br />
|-<br />
| 8.1 || 1141.14<br />
|-<br />
| 8.2 || 1142.16<br />
|-<br />
| 8.3 || 1144.17<br />
|-<br />
| 8.4 || 1145.15<br />
|-<br />
| 9.0 || 1240.10<br />
|-<br />
| 9.1 || 1241.11<br />
|-<br />
| 9.2 || 1242.13<br />
|-<br />
| 9.3 || 1280.38<br />
|-<br />
| 10.0 || 1348.00<br />
|-<br />
| 10.1 || 1348.00<br />
|-<br />
| 10.2 || 1348.22<br />
|-<br />
| 10.3 || 1349.56 <br />
|-<br />
| 11.0 || 1443.00 <br />
|-<br />
| 11.1 || 1445.32 <br />
|-<br />
| 11.2 || 1450.14<br />
|-<br />
| 11.3 || 1452.23<br />
|-<br />
| 11.4 || 1452.23<br />
|-<br />
| 12.0 || 1556.00<br />
|-<br />
| 12.1 || 1560.10<br />
|-<br />
| 12.2 || 1570.15<br />
|-<br />
| 12.3 || 1575.13<br />
|-<br />
| 12.4 || 1575.17<br />
|-<br />
| 12.5 || 1575.23<br />
|-<br />
| 13.0 || 1665.15<br />
|-<br />
| 13.1 || 1671.101<br />
|-<br />
| 13.2 || 1673.126<br />
|-<br />
| 13.3 || 1674.102<br />
|-<br />
| 13.4 || 1675.129<br />
|-<br />
| 13.5 || 1676.104<br />
|-<br />
| 13.6 || 1677.104<br />
|-<br />
| 13.7 || 1677.104<br />
|-<br />
| 14.0 || 1751.108<br />
|-<br />
| 14.1 || 1751.108<br />
|-<br />
| 14.2 || 1770.106<br />
|-<br />
| 14.3 || 1770.300<br />
|-<br />
| 14.4 || 1774.101<br />
|-<br />
| 14.5 || 1775.118<br />
|-<br />
| 14.6 || 1776.103<br />
|-<br />
| 14.7 || 1777.103<br />
|-<br />
| 14.8 || 1778.101<br />
|-<br />
| 15.0 || 1854<br />
|-<br />
| 15.1 || 1855.105<br />
|-<br />
| 15.2 || 1856.105<br />
|-<br />
| 15.3 || 1856.105<br />
|-<br />
| 15.4 || 1858.112<br />
|-<br />
|}</div>PoomSmarthttps://iphonedev.wiki/index.php?title=Template:CoreFoundation_Version_Table&diff=5782Template:CoreFoundation Version Table2022-03-06T04:12:45Z<p>PoomSmart: Oopsie</p>
<hr />
<div>{| class="wikitable sortable"<br />
|-<br />
! Firmware !! CoreFoundation version<br />
|-<br />
| 2.0 || 478.23<br />
|-<br />
| 2.1 || 478.26.1<br />
|-<br />
| 2.2 || 478.29<br />
|-<br />
| 3.0 || 478.47.7<br />
|-<br />
| 3.1 || 478.52<br />
|-<br />
| 3.2 || 478.61<br />
|-<br />
| 4.0 || 550.32<br />
|-<br />
| 4.1 || 550.38.1<br />
|-<br />
| 4.2 || 550.52 <br />
|-<br />
| 4.3 || 550.58.1<br />
|-<br />
| 5.0 || 675.00 <br />
|-<br />
| 5.1 || 690.10<br />
|-<br />
| 6.0 || 793.00<br />
|-<br />
| 6.1 || 793.00<br />
|-<br />
| 7.0 || 847.20<br />
|-<br />
| 7.1 || 847.24<br />
|-<br />
| 8.0 || 1140.10<br />
|-<br />
| 8.1 || 1141.14<br />
|-<br />
| 8.2 || 1142.16<br />
|-<br />
| 8.3 || 1144.17<br />
|-<br />
| 8.4 || 1145.15<br />
|-<br />
| 9.0 || 1240.10<br />
|-<br />
| 9.1 || 1241.11<br />
|-<br />
| 9.2 || 1242.13<br />
|-<br />
| 9.3 || 1280.38<br />
|-<br />
| 10.0 || 1348.00<br />
|-<br />
| 10.1 || 1348.00<br />
|-<br />
| 10.2 || 1348.22<br />
|-<br />
| 10.3 || 1349.56 <br />
|-<br />
| 11.0 || 1443.00 <br />
|-<br />
| 11.1 || 1445.32 <br />
|-<br />
| 11.2 || 1450.14<br />
|-<br />
| 11.3 || 1452.23<br />
|-<br />
| 11.4 || 1452.23<br />
|-<br />
| 12.0 || 1556.00<br />
|-<br />
| 12.1 || 1560.10<br />
|-<br />
| 12.2 || 1570.15<br />
|-<br />
| 12.3 || 1575.13<br />
|-<br />
| 12.4 || 1575.17<br />
|-<br />
| 12.5 || 1575.23<br />
|-<br />
| 13.0 || 1665.15<br />
|-<br />
| 13.1 || 1671.101<br />
|-<br />
| 13.2 || 1673.126<br />
|-<br />
| 13.3 || 1674.102<br />
|-<br />
| 13.4 || 1675.129<br />
|-<br />
| 13.5 || 1676.104<br />
|-<br />
| 13.6 || 1677.104<br />
|-<br />
| 13.7 || 1677.104<br />
|-<br />
| 14.0 || 1751.108<br />
|-<br />
| 14.1 || 1751.108<br />
|-<br />
| 14.2 || 1770.106<br />
|-<br />
| 14.3 || 1770.300<br />
|-<br />
| 14.4 || 1774.101<br />
|-<br />
| 14.5 || 1775.118<br />
|-<br />
| 14.6 || 1776.103<br />
|-<br />
| 14.7 || 1777.103<br />
|-<br />
| 14.8 || 1778.101<br />
|-<br />
| 15.0 || 1854<br />
|-<br />
| 15.1 || 1855.105<br />
|-<br />
| 15.2 || 1856.105<br />
|-<br />
| 15.3 || 1856.105<br />
|-<br />
|}</div>PoomSmarthttps://iphonedev.wiki/index.php?title=Template:CoreFoundation_Version_Table&diff=5781Template:CoreFoundation Version Table2022-03-06T04:12:02Z<p>PoomSmart: Added versions for iOS 14.6 - 15.3</p>
<hr />
<div>{| class="wikitable sortable"<br />
|-<br />
! Firmware !! CoreFoundation version<br />
|-<br />
| 2.0 || 478.23<br />
|-<br />
| 2.1 || 478.26.1<br />
|-<br />
| 2.2 || 478.29<br />
|-<br />
| 3.0 || 478.47.7<br />
|-<br />
| 3.1 || 478.52<br />
|-<br />
| 3.2 || 478.61<br />
|-<br />
| 4.0 || 550.32<br />
|-<br />
| 4.1 || 550.38.1<br />
|-<br />
| 4.2 || 550.52 <br />
|-<br />
| 4.3 || 550.58.1<br />
|-<br />
| 5.0 || 675.00 <br />
|-<br />
| 5.1 || 690.10<br />
|-<br />
| 6.0 || 793.00<br />
|-<br />
| 6.1 || 793.00<br />
|-<br />
| 7.0 || 847.20<br />
|-<br />
| 7.1 || 847.24<br />
|-<br />
| 8.0 || 1140.10<br />
|-<br />
| 8.1 || 1141.14<br />
|-<br />
| 8.2 || 1142.16<br />
|-<br />
| 8.3 || 1144.17<br />
|-<br />
| 8.4 || 1145.15<br />
|-<br />
| 9.0 || 1240.10<br />
|-<br />
| 9.1 || 1241.11<br />
|-<br />
| 9.2 || 1242.13<br />
|-<br />
| 9.3 || 1280.38<br />
|-<br />
| 10.0 || 1348.00<br />
|-<br />
| 10.1 || 1348.00<br />
|-<br />
| 10.2 || 1348.22<br />
|-<br />
| 10.3 || 1349.56 <br />
|-<br />
| 11.0 || 1443.00 <br />
|-<br />
| 11.1 || 1445.32 <br />
|-<br />
| 11.2 || 1450.14<br />
|-<br />
| 11.3 || 1452.23<br />
|-<br />
| 11.4 || 1452.23<br />
|-<br />
| 12.0 || 1556.00<br />
|-<br />
| 12.1 || 1560.10<br />
|-<br />
| 12.2 || 1570.15<br />
|-<br />
| 12.3 || 1575.13<br />
|-<br />
| 12.4 || 1575.17<br />
|-<br />
| 12.5 || 1575.23<br />
|-<br />
| 13.0 || 1665.15<br />
|-<br />
| 13.1 || 1671.101<br />
|-<br />
| 13.2 || 1673.126<br />
|-<br />
| 13.3 || 1674.102<br />
|-<br />
| 13.4 || 1675.129<br />
|-<br />
| 13.5 || 1676.104<br />
|-<br />
| 13.6 || 1677.104<br />
|-<br />
| 13.7 || 1677.104<br />
|-<br />
| 14.0 || 1751.108<br />
|-<br />
| 14.1 || 1751.108<br />
|-<br />
| 14.2 || 1770.106<br />
|-<br />
| 14.3 || 1770.300<br />
|-<br />
| 14.4 || 1774.101<br />
|-<br />
| 14.5 || 1775.118<br />
|-<br />
| 14.6 || 1776.103<br />
|-<br />
| 14.7 || 1777.103<br />
|-<br />
| 14.8 || 1778.101<br />
|-<br />
| 15.0 || 1854<br />
|-<br />
| 15.1 || 1855.105<br />
|-<br />
| 15.2 || 1855.105<br />
|-<br />
| 15.3 || 1856.105<br />
|-<br />
|}</div>PoomSmarthttps://iphonedev.wiki/index.php?title=IconSupport&diff=5767IconSupport2022-01-15T10:54:25Z<p>PoomSmart: </p>
<hr />
<div>{{Infobox Package<br />
|developer=Sakurina, chpwn, ashikase<br />
|version=1.8.1-1<br />
|package=com.chpwn.iconsupport<br />
}}<br />
'''IconSupport''' is a library that helps icon-layout-modifying tweaks play nicely together.<br />
<br />
This library supports up to iOS 11 and is no longer maintained.<br />
<br />
Quoted from its depiction:<br />
<br />
<blockquote><br />
<p>IconSupport is a package for use by extensions that modify how SpringBoard lays-out icons (such as extensions that change the number of icons shown per row/column).</p><br />
<p>Normally, syncing with iTunes or booting into Mobile Substrate's Safe Mode would cause these modified layouts to be reset; IconSupport prevents this.</p><br />
<p>IconSupport also handles repairing layouts when installing and uninstalling IconSupport-enabled extensions.</p><br />
</blockquote><br />
<br />
Quoted from the README of its [https://github.com/Xuzz/IconSupport source on GitHub]:<br />
<br />
<blockquote><br />
<p>Uses a unique ID for each combination of packages, so icon state is never lost via respring or uninstalling a new package.</p><br />
</blockquote><br />
<br />
== How to use this library ==<br />
<br />
Headers are available from [https://github.com/grp/IconSupport/blob/master/Extension/4.0/ISIconSupport.h IconSupport's GitHub project]. If using Theos, place the headers in <code>$THEOS/include/IconSupport</code>.<br />
<br />
=== Include directive ===<br />
<br />
<source lang="objc"><br />
#import <IconSupport/ISIconSupport.h><br />
</source><br />
<br />
=== Packaging ===<br />
<br />
Add to your package's control file:<br />
<br />
* <code>, com.chpwn.iconsupport</code> to the <code>Depends</code> field.<br />
<br />
== Usage ==<br />
<br />
<source lang="logos"><br />
%ctor {<br />
dlopen("/Library/MobileSubstrate/DynamicLibraries/IconSupport.dylib", RTLD_NOW);<br />
[[%c("ISIconSupport") sharedInstance] addExtension:@"theNameOfMyExtension"];<br />
}<br />
</source><br />
<br />
== External links ==<br />
<br />
* [https://github.com/Xuzz/IconSupport source on GitHub].<br />
<br />
{{Navbox Library}}<br />
<br />
[[Category:Cydia packages]]<br />
<br />
[[Category:Directories in /Library]]</div>PoomSmarthttps://iphonedev.wiki/index.php?title=Frameworks&diff=5766Frameworks2022-01-15T10:49:11Z<p>PoomSmart: </p>
<hr />
<div>[[Frameworks]] are bundles that contain a linkable library (usually a dylib) and the associated resources and headers for development. <br />
<br />
There are “public” and [[PrivateFrameworks|“private”]] frameworks. The former are usually well documented and prepared for use by general developers, while the latter are (supposed to be) restricted for internal use only. Public frameworks can be found in <tt>/System/Library/Frameworks</tt>, and private ones in <tt>/System/Library/PrivateFrameworks</tt>. Other than this artificial division, there are no differences between public and private frameworks.<br />
<br />
Since iOS 3.1, all default (public and private) libraries have been combined into a big cache file in <tt>/System/Library/Caches/com.apple.dyld/dyld_shared_cache_armvX</tt> (where X can be <tt>6</tt>, <tt>7</tt>, <tt>7s</tt>, <tt>64</tt> or <tt>64e</tt>) to improve performance. See [[dyld_shared_cache]]. The original libraries are no longer useful for non-on-device-developers, so they are eliminated from the system. The framework folders still contain other resources, such as localization strings.<br />
<br />
Frameworks have an extension of <tt>.framework</tt>. Headers, if any, are stored in a subdirectory called <tt>Headers</tt>. <br />
<br />
== References ==<br />
* [http://developer.apple.com/iphone/library/documentation/General/Conceptual/DevPedia-CocoaCore/Framework.html Apple's definition of frameworks].<br />
<br />
== List of frameworks ==<br />
<br />
See [http://theiphonewiki.com/wiki//System/Library/Frameworks /System/Library/Frameworks on TheiPhoneWiki] for another list.<br />
<br />
The following list reflects the state of public frameworks as of iOS 15.0:<br />
<br />
* [[ARKit.framework]] <br />
* [[AVFAudio.framework]]<br />
* [[AVFoundation.framework]] (com.apple.avfoundation)<br />
* [[AVKit.framework]]<br />
* [[Accelerate.framework]] (com.apple.Accelerate)<br />
* [[Accounts.framework]] <br />
* [[AdServices.framework]]<br />
* [[AdSupport.framework]]<br />
* [[AddressBook.framework]] (com.apple.AddressBook)<br />
* [[AddressBookUI.framework]] (com.apple.AddressBookUI)<br />
* [[AppClip.framework]]<br />
* [[AppTrackingTransparency.framework]]<br />
* [[AssetsLibrary.framework]] (com.yourcompany.AssetsLibrary)<br />
* [[AudioToolbox.framework]] (com.apple.audio.toolbox.AudioToolbox)<br />
* [[AudioUnit.framework]] (com.apple.audio.units.AudioUnit)<br />
* [[AuthenticationServices.framework]]<br />
* [[AutomaticAssessmentConfiguration.framework]]<br />
* [[BackgroundTasks.framework]]<br />
* [[BusinessChat.framework]]<br />
* [[CFNetwork.framework]] (com.apple.CFNetwork)<br />
* [[CHIP.framework]]<br />
* [[Callkit.framework]]<br />
* [[CarPlay.framework]]<br />
* [[ClassKit.framework]]<br />
* [[ClockKit.framework]]<br />
* [[CloudKit.framework]]<br />
* [[Combine.framework]]<br />
* [[Contacts.framework]]<br />
* [[ContactsUI.framework]]<br />
* [[CoreAudio.framework]] (com.apple.audio.CoreAudio)<br />
* [[CoreAudioKit.framework]]<br />
* [[CoreBluetooth.framework]]<br />
* [[CoreData.framework]] (com.apple.CoreData)<br />
* [[CoreFoundation.framework]] (com.apple.CoreFoundation)<br />
* [[CoreGraphics.framework]]<br />
* [[CoreHaptics.framework]]<br />
* [[CoreImage.framework]]<br />
* [[CoreLocation.framework]] (com.apple.corelocation)<br />
* [[CoreLocationUI.framework]]<br />
* [[CoreMIDI.framework]]<br />
* [[CoreML.framework]]<br />
* [[CoreMedia.framework]] (com.apple.CoreMedia)<br />
* [[CoreMotion.framework]] (com.apple.coremotion)<br />
* [[CoreNFC.framework]]<br />
* [[CorePDF.framework]] (com.apple.CorePDF)<br />
* [[CoreServices.framework]]<br />
* [[CoreSpotlight.framework]]<br />
* [[CoreTelephony.framework]] (com.apple.coretelephony)<br />
* [[CoreText.framework]] (com.apple.CoreText)<br />
* [[CoreVideo.framework]] (com.apple.CoreVideo)<br />
* [[CreateML.framework]]<br />
* [[CryptoKit.framework]]<br />
* [[CryptoTokenKit.framework]]<br />
* [[DataDetection.framework]]<br />
* [[DeveloperToolsSupport.framework]]<br />
* [[DeviceActivity.framework]]<br />
* [[DeviceCheck.framework]]<br />
* [[EventKit.framework]] (com.apple.eventkit)<br />
* [[EventKitUI.framework]] (com.apple.eventkitui)<br />
* [[ExposureNotification.framework]]<br />
* [[ExternalAccessory.framework]] (com.apple.ExternalAccessory)<br />
* [[FamilyControls.framework]]<br />
* [[FileProvider.framework]]<br />
* [[FileProviderUI.framework]]<br />
* [[Foundation.framework]] (com.apple.Foundation)<br />
* [[GLKit.framework]]<br />
* [[GSS.framework]]<br />
* [[GameController.framework]]<br />
* [[GameKit.framework]] (com.apple.GameKit)<br />
* [[GameplayKit.framework]]<br />
* [[GroupActivities.framework]]<br />
* [[HealthKit.framework]]<br />
* [[HealthKitUI.framework]]<br />
* [[HomeKit.framework]]<br />
* [[IOSurface.framework]]<br />
* [[IOKit.framework]]<br />
* [[IdentityLookup.framework]]<br />
* [[IdentityLookupUI.framework]]<br />
* [[ImageCaptureCore.framework]]<br />
* [[ImageIO.framework]] (com.apple.ImageIO.framework)<br />
* [[Intents.framework]]<br />
* [[IntentsUI.framework]]<br />
* [[JavaScriptCore.framework]]<br />
* [[LinkPresentation.framework]]<br />
* [[LocalAuthentication.framework]]<br />
* [[MLCompute.framework]]<br />
* [[ManagedSettings.framework]]<br />
* [[ManagedSettingsUI.framework]]<br />
* [[MapKit.framework]] (com.apple.MapKit)<br />
* [[MediaAccessibility.framework]]<br />
* [[MediaPlayer.framework]] (com.apple.MediaPlayer)<br />
* [[MediaSetup.framework]]<br />
* [[MediaToolbox.framework]]<br />
* [[MessageUI.framework]] (com.apple.messageui)<br />
* [[Messages.framework]]<br />
* [[Metal.framework]]<br />
* [[MetalKit.framework]]<br />
* [[MetalPerformanceShaders.framework]]<br />
* [[MetalPerformanceShadersGraph.framework]]<br />
* [[MetricKit.framework]]<br />
* [[MobileCoreServices.framework]] (com.apple.MobileCoreServices)<br />
* [[ModelIO.framework]]<br />
* [[MultipeerConnectivity.framework]]<br />
* [[MusicKit.framework]]<br />
* [[NaturalLanguage.framework]]<br />
* [[NearbyInteraction.framework]]<br />
* [[Network.framework]]<br />
* [[NetworkExtension.framework]]<br />
* [[NewsstandKit.framework]]<br />
* [[NotificationCenter.framework]]<br />
* [[OSLog.framework]]<br />
* [[OpenAL.framework]] (com.apple.audio.OpenAL)<br />
* [[OpenGLES.framework]] (com.apple.opengles)<br />
* [[PDFKit.framework]]<br />
* [[PHASE.framework]]<br />
* [[PassKit.framework]]<br />
* [[PencilKit.framework]]<br />
* [[Photos.framework]]<br />
* [[PhotosUI.framework]]<br />
* [[PushKit.framework]]<br />
* [[QuartzCore.framework]] (com.apple.QuartzCore)<br />
* [[QuickLook.framework]] (com.apple.QuickLook)<br />
* [[QuickLookThumbnailing.framework]]<br />
* [[RealityFoundation.framework]]<br />
* [[RealityKit.framework]]<br />
* [[ReplayKit.framework]]<br />
* [[SafariServices.framework]]<br />
* [[SceneKit.framework]]<br />
* [[ScreenTime.framework]]<br />
* [[Security.framework]] (com.apple.Security)<br />
* [[SensorKit.framework]]<br />
* [[ShazamKit.framework]]<br />
* [[Social.framework]]<br />
* [[SoundAnalysis.framework]]<br />
* [[Speech.framework]]<br />
* [[SpriteKit.framework]]<br />
* [[StoreKit.framework]] (com.apple.StoreKit)<br />
* [[SwiftUI.framework]]<br />
* [[System.framework]]<br />
* [[SystemConfiguration.framework]] (com.apple.SystemConfiguration)<br />
* [[TabularData.framework]]<br />
* [[ThreadNetwork.framework]]<br />
* [[Twitter.framework]]<br />
* [[UIKit.framework]] (com.apple.UIKit)<br />
* [[UniformTypeIdentifiers.framework]]<br />
* [[UserNotifications.framework]]<br />
* [[UserNotificationsUI.framework]]<br />
* [[VideoSubscriberAccount.framework]]<br />
* [[VideoToolbox.framework]]<br />
* [[Vision.framework]]<br />
* [[WatchConnectivity.framework]]<br />
* [[WatchKit.framework]]<br />
* [[WebKit.framework]]<br />
* [[WidgetKit.framework]]<br />
* [[iAd.framework]] (com.apple.iAd)<br />
<br />
{{Navbox Frameworks}}<br />
{{Navbox Library}}<br />
[[Category:Directories in /System/Library]]</div>PoomSmarthttps://iphonedev.wiki/index.php?title=Preferences&diff=5716Preferences2021-08-20T23:50:21Z<p>PoomSmart: /* Tweak part */</p>
<hr />
<div>:''This article is about reading and writing preferences. For the Preferences user interface framework, see [[Preferences.framework]].''<br />
<br />
Tweaks typically have preferences that can be set by the user from the Settings app. The [[Preferences.framework|Preferences framework]] uses the [https://developer.apple.com/library/ios/documentation/CoreFoundation/Reference/CFPreferencesUtils/ CFPreferences] family of functions to read and write preferences. Before OS X 10.8 and iOS 8, these functions would directly read and write a plist with the name of the application identifier in <code>~/Library/Preferences</code>. (Note that when an app is sandboxed in a container, the home directory is the path to the container, not the user's home directory.) Nowadays, preferences are managed by a daemon called cfprefsd.<br />
<br />
The Foundation class [https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSUserDefaults_Class/ NSUserDefaults] provides a subset of features over the CFPreferences functions. It appears to be intended more as a simple-to-use class that handles calling CFPreferences functions for you, as opposed to being feature-by-feature compatible with CFPreferences.<br />
<br />
CFPreferences functions can take and return CFStringRefs and [https://developer.apple.com/library/ios/documentation/CoreFoundation/Reference/CFPropertyListRef/ CFPropertyListRefs]. As such, you can [https://developer.apple.com/library/ios/documentation/CoreFoundation/Conceptual/CFDesignConcepts/Articles/tollFreeBridgedTypes.html toll-free bridge] these from or to their matching Foundation classes.<br />
<br />
== cfprefsd ==<br />
<br />
'''cfprefsd''' is the daemon that handles reading and writing preference values. It also caches values in memory so that they can be returned faster. Its goal is to avoid disk reads/writes as much as is possible. This has caused some confusion among tweak developers who have for the most part simply been reading their preference plist directly from the disk, which isn't written to until cfprefsd decides to flush its in-memory cache, or it's sent a SIGTERM (<code>killall cfprefsd</code>). It was introduced to OS X with 10.8, and to iOS with 8.0.<br />
<br />
Due to cfprefsd not working as desired in processes that live in an app container and having no documentation other than a vague [https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man8/cfprefsd.8.html man page], various developers have created different solutions to read and write preference values. These are outlined at [[PreferenceBundles#Loading Preferences|PreferenceBundles &sect; Loading Preferences]].<br />
<br />
The signal SIGUSR1 can be sent to cfprefsd to make it write a file to <code>/tmp</code>. It provides data about each preference domain read or written to using CFPreferences APIs since the daemon started, in the following form:<br />
<br />
<source lang="bash"><br />
$ killall -USR1 cfprefsd<br />
$ head -24 '/tmp/cfprefsddump(166:460692319.078117).txt'<br />
<br />
*****************************************************<br />
Domain: fud<br />
User: root<br />
Container: (null)<br />
Path: /Library/Managed Preferences/root/fud.plist<br />
plist data:(null)<br />
shmem index:2017<br />
dirty:0<br />
byHost:1<br />
mode:600<br />
isMultiProcess:1<br />
<br />
*****************************************************<br />
Domain: com.apple.WebKit.Networking<br />
User: mobile<br />
Container: (null)<br />
Path: /var/mobile/Library/Preferences/com.apple.WebKit.Networking.plist<br />
plist data:(null)<br />
shmem index:1145<br />
dirty:0<br />
byHost:0<br />
mode:600<br />
isMultiProcess:1<br />
</source><br />
<br />
== Examples ==<br />
<br />
''To do: read [http://oleb.net/blog/2014/02/nsuserdefaults-handling-default-values/ this] carefully and move all information regarding preferences to a more appropriate place. Bring the following contents:''<br />
<br />
* http://iphonedevwiki.net/index.php/PreferenceBundles#Loading_Preferences<br />
* http://iphonedevwiki.net/index.php/Updating_extensions_for_iOS_8#Preference_saving<br />
<br />
=== Tweak part ===<br />
<br />
As opposed to using NSDictionaries and <code>[NSHomeDirectory() stringByAppendingFormat:@"/Library/Preferences/%s.plist", "com.your.tweak"]</code>, the following implementation uses NSUserDefaults, which works properly for unsandboxed processes, so read the previous links to handle preferences on sandboxed processes until an implementation is added here.<br />
<br />
{{Collapse|1=<source lang="objc"><br />
#import <Foundation/NSUserDefaults+Private.h><br />
<br />
static NSString *nsDomainString = @"com.your.tweak";<br />
static NSString *nsNotificationString = @"com.your.tweak/preferences.changed";<br />
static BOOL enabled;<br />
<br />
static void notificationCallback(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) {<br />
NSNumber *n = (NSNumber *)[[NSUserDefaults standardUserDefaults] objectForKey:@"enabled" inDomain:nsDomainString];<br />
enabled = (n) ? [n boolValue] : YES;<br />
}<br />
<br />
%ctor {<br />
// Set variables on start up<br />
notificationCallback(NULL, NULL, NULL, NULL, NULL);<br />
<br />
// Register for 'PostNotification' notifications<br />
CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(),<br />
NULL,<br />
notificationCallback,<br />
(CFStringRef)nsNotificationString,<br />
NULL,<br />
CFNotificationSuspensionBehaviorCoalesce);<br />
<br />
// Add any personal initializations<br />
}<br />
<br />
/*<br />
* From here onward, write your tweak.<br />
* To make your tweak actually do stuff when enabled:<br />
if (!enabled) {<br />
// Do the original algorithm by calling:<br />
// %orig();<br />
} else {<br />
...<br />
// Optionally, do the original algorithm<br />
}<br />
*/<br />
<br />
</source>|2=Tweak.xm}}<br />
<br />
=== Preference plist ===<br />
<br />
{{main|PreferenceLoader}}<br />
<br />
Choose any of the following styles, see [[preferences specifier plist]] for all available specifier types and how to use them.<br />
<br />
==== Reduced style ====<br />
<br />
Provides a switch on the root section of the preferences (like Airplane Mode). Recommended for configuration-less tweaks.<br />
<br />
Saved in your tweak's folder as <code>layout/Library/PreferenceLoader/Preferences/com.your.tweak/entry.plist</code><br />
<br />
{|<br />
|+ style="text-align:left;"| entry.plist<br />
|- valign="top"<br />
|<br />
{{Collapse|1=<source lang="javascript">{<br />
entry = {<br />
cell = PSSwitchCell;<br />
defaults = "com.your.tweak";<br />
label = "Your Tweak";<br />
key = enabled;<br />
default = 1;<br />
icon = "/Applications/Preferences.app/icon-table@2x.png";<br />
PostNotification = "com.your.tweak/preferences.changed";<br />
};<br />
}<br />
</source>|2=NeXTSTEP style}}<br />
||<br />
{{Collapse|1=<source lang="xml"><br />
<?xml version="1.0" encoding="UTF-8"?><br />
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><br />
<plist version="1.0"><br />
<dict><br />
<key>entry</key><br />
<dict><br />
<key>cell</key><br />
<string>PSSwitchCell</string><br />
<key>defaults</key><br />
<string>com.your.tweak</string><br />
<key>label</key><br />
<string>Your Tweak</string><br />
<key>key</key><br />
<string>enabled</string><br />
<key>default</key><br />
<true/><br />
<key>icon</key><br />
<string>/Applications/Preferences.app/icon-table@2x.png</string><br />
<key>PostNotification</key><br />
<string>com.your.tweak/preferences.changed</string><br />
</dict><br />
</dict><br />
</plist><br />
</source>|2=XML style}}<br />
|}<br />
<br />
==== Extended Style ====<br />
<br />
Provides a pane where other cells can appear (like Wi-Fi). Recommended for configuration-friendly tweaks.<br />
<br />
Saved in your tweak's folder as <code>layout/Library/PreferenceLoader/Preferences/com.your.tweak/entry.plist</code><br />
<br />
{|<br />
|+ style="text-align:left;"| entry.plist<br />
|- valign="top"<br />
|<br />
{{Collapse|1=<source lang="javascript">{<br />
title = "Your Tweak";<br />
entry = {<br />
cell = PSLinkCell;<br />
label = "Your Tweak";<br />
icon = "/Applications/Preferences.app/icon-table@2x.png";<br />
};<br />
items = (<br />
{<br />
cell = PSSwitchCell;<br />
defaults = "com.your.tweak";<br />
label = Enabled;<br />
key = enabled;<br />
default = 1;<br />
PostNotification = "com.your.tweak/preferences.changed";<br />
}<br />
// add more cells (dictionaries) here<br />
);<br />
}<br />
</source>|2=NeXTSTEP style}}<br />
||<br />
{{Collapse|1=<source lang="xml"><br />
<?xml version="1.0" encoding="UTF-8"?><br />
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><br />
<plist version="1.0"><br />
<dict><br />
<key>title</key><br />
<string>Your Tweak</string><br />
<key>entry</key><br />
<dict><br />
<key>cell</key><br />
<string>PSSwitchCell</string><br />
<key>label</key><br />
<string>Your Tweak</string><br />
<key>icon</key><br />
<string>/Applications/Preferences.app/icon-table@2x.png</string><br />
</dict><br />
<key>items</key><br />
<array><br />
<dict><br />
<key>cell</key><br />
<string>PSSwitchCell</string><br />
<key>defaults</key><br />
<string>com.your.tweak</string><br />
<key>label</key><br />
<string>Enabled</string><br />
<key>key</key><br />
<string>enabled</string><br />
<key>default</key><br />
<true/><br />
<key>PostNotification</key><br />
<string>com.your.tweak/preferences.changed</string><br />
</dict><br />
// add more cells (dictionaries) here<br />
</array><br />
</dict><br />
</plist><br />
</source>|2=XML style}}<br />
|}<br />
<br />
==== Inside PreferenceBundles ====<br />
<br />
{{main|PreferenceBundles}}<br />
<br />
Provides a static list of cells. Recommended for Preference Bundles of tweaks.<br />
<br />
Saved in your tweak's Preference Bundle subproject folder as <code>Resources/com.your.tweak.plist</code><br />
<br />
{|<br />
|+ style="text-align:left;"| com.your.tweak.plist<br />
|- valign="top"<br />
|<br />
{{Collapse|1=<source lang="javascript">{<br />
items = (<br />
{<br />
cell = PSSwitchCell;<br />
defaults = "com.your.tweak";<br />
label = Enabled;<br />
key = enabled;<br />
default = 1;<br />
PostNotification = "com.your.tweak/preferences.changed";<br />
}<br />
// add more cells (dictionaries) here<br />
);<br />
}<br />
</source>|2=NeXTSTEP style}}<br />
||<br />
{{Collapse|1=<source lang="xml"><br />
<?xml version="1.0" encoding="UTF-8"?><br />
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><br />
<plist version="1.0"><br />
<dict><br />
<key>items</key><br />
<array><br />
<dict><br />
<key>cell</key><br />
<string>PSSwitchCell</string><br />
<key>defaults</key><br />
<string>com.your.tweak</string><br />
<key>label</key><br />
<string>Enabled</string><br />
<key>key</key><br />
<string>enabled</string><br />
<key>default</key><br />
<true/><br />
<key>PostNotification</key><br />
<string>com.your.tweak/preferences.changed</string><br />
</dict><br />
// add more cells (dictionaries) here<br />
</array><br />
</dict><br />
</plist><br />
</source>|2=XML style}}<br />
|}<br />
<br />
=== Flipswitches ===<br />
<br />
{{main|Flipswitch}}<br />
<br />
After using the Flipswitch NIC template, modify accordingly<br />
<br />
{{Collapse|1=<source lang="objc"><br />
#import "FSSwitchDataSource.h"<br />
#import "FSSwitchPanel.h"<br />
<br />
@interface NSUserDefaults (Tweak_Category)<br />
- (id)objectForKey:(NSString *)key inDomain:(NSString *)domain;<br />
- (void)setObject:(id)value forKey:(NSString *)key inDomain:(NSString *)domain;<br />
@end<br />
<br />
static NSString *nsDomainString = @"com.your.tweak";<br />
static NSString *nsNotificationString = @"com.your.tweak/preferences.changed";<br />
<br />
@interface YourTweakFlipswitchSwitch : NSObject <FSSwitchDataSource><br />
@end<br />
<br />
@implementation YourTweakFlipswitchSwitch<br />
<br />
- (NSString *)titleForSwitchIdentifier:(NSString *)switchIdentifier {<br />
return @"Your Tweak";<br />
}<br />
<br />
- (FSSwitchState)stateForSwitchIdentifier:(NSString *)switchIdentifier {<br />
NSNumber *n = (NSNumber *)[[NSUserDefaults standardUserDefaults] objectForKey:@"enabled" inDomain:nsDomainString];<br />
BOOL enabled = (n)? [n boolValue]:YES;<br />
return (enabled) ? FSSwitchStateOn : FSSwitchStateOff;<br />
}<br />
<br />
- (void)applyState:(FSSwitchState)newState forSwitchIdentifier:(NSString *)switchIdentifier {<br />
switch (newState) {<br />
case FSSwitchStateIndeterminate:<br />
break;<br />
case FSSwitchStateOn:<br />
[[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithBool:YES] forKey:@"enabled" inDomain:nsDomainString];<br />
CFNotificationCenterPostNotification(CFNotificationCenterGetDarwinNotifyCenter(), (CFStringRef)nsNotificationString, NULL, NULL, YES);<br />
break;<br />
case FSSwitchStateOff:<br />
[[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithBool:NO] forKey:@"enabled" inDomain:nsDomainString];<br />
CFNotificationCenterPostNotification(CFNotificationCenterGetDarwinNotifyCenter(), (CFStringRef)nsNotificationString, NULL, NULL, YES);<br />
break;<br />
}<br />
return;<br />
}<br />
<br />
@end<br />
<br />
</source>|2=Switch.x}}<br />
<br />
[[Category:Preferences]]</div>PoomSmarthttps://iphonedev.wiki/index.php?title=Developer_Directory&diff=5715Developer Directory2021-08-19T04:47:35Z<p>PoomSmart: </p>
<hr />
<div>This is a table showing a directory of tweak developers. This will include their handle, twitter account, github profile, email address, repository, and projects where applicable. If you would not like some of the information to be displayed under your name, feel free to make an edit or notify a contributor to do it for you.<br />
<br />
This list was first made with tweak developers who have created a tweak of their own, and updated or released a tweak since evasi0n7 (7.0).<br />
<br />
''This list is incomplete; you can help by expanding it.''<br />
<br />
{| class="wikitable"<br />
! name / handle !! Twitter handle !! GitHub profile !! <!-- Repository !! email !! --> Recent tweaks<br />
|-<br />
| _kritanta || [https://twitter.com/arm64e @arm64e] || https://github.com/KritantaDev || - <br />
|-<br />
| _Matchstic (Matt Clarke) || [https://twitter.com/_Matchstic @_Matchstic] || - || Convergance<br />
|-<br />
| _mxms (Maximus) || - || - || -<br />
|-<br />
| aarzee (Carlos Liam) || [https://twitter.com/carlosaarzee @carlosaarzee] || https://github.com/aarzee || Contractor<br />
|-<br />
| ac3xx (James Long) || [https://twitter.com/ac3xx @ac3xx] || https://github.com/ac3xx || -<br />
|-<br />
| Adolfoi_ || - || - || -<br />
|-<br />
| Adrian Granados || - || - || -<br />
|-<br />
| Aehmlo (Aehmlo Lxaitn) || [https://twitter.com/aehmlo @Aehmlo] || https://github.com/Aehmlo || Badger 7, PowerDown Enhancer 2<br />
|-<br />
| alexzielenski (Alex Zielenski) || [https://twitter.com/alexzielenski @alexzielenski] || https://github.com/alexzielenski || Zeppelin, ThemeEngine, Mousecape, artFileTool, sartFileTool, TinyBar<br />
|-<br />
| Alltim3h4ckers || - || - || -<br />
|-<br />
| ashikase (Lance Fetters) || [https://twitter.com/ashikase @ashikase] || https://github.com/ashikase || CrashReporter<br />
|-<br />
| b3ll (Adam Bell) || [https://twitter.com/b3ll @b3ll] || https://github.com/b3ll || -<br />
|-<br />
| Bailey Seymour || [http://twitter.com/baileyseymour_ @baileyseymour_] || https://github.com/s0ulp1xel || AppDye, UIColors<br />
|-<br />
| bd452 (Bryce Dougherty) || [https://twitter.com/bd452 @bd452] || https://github.com/bd452 || -<br />
|-<br />
| ben_gerard (Ben Gerard) || - || - || -<br />
|-<br />
| bensge (Benno Kraus) || [https://twitter.com/bensge @bensge] || https://github.com/bensge || -<br />
|-<br />
| Brogan Miner || [https://twitter.com/BroganMinerDev @BroganMinerDev] || https://github.com/broha22 || -<br />
|-<br />
| Callum Ryan || - || - || -<br />
|-<br />
| Friggog (Charlie Hewitt) || [https://twitter.com/Friggog @Friggog] || https://github.com/Friggog || -<br />
|-<br />
| Cornelius Koetting || [https://twitter.com/C0rne1ius4 @C0rne1ius4] || https://github.com/Bananastudios/ || Wolfram, Rhodium, Tatton, WhoPaysForLenses?, Palin, NoEmergency<br />
|-<br />
| CoolStar || [https://twitter.com/coolstarorg @coolstarorg] || https://github.com/coolstar || -<br />
|-<br />
| Cykey (David Murray) || [http://twitter.com/icykey @iCykey] || https://github.com/cykey || Smart Search<br />
|-<br />
| Daniel Turner || - || - || -<br />
|-<br />
| DoK (Salvatore Ansani) || [https://twitter.com/DoK @DoK] || https://github.com/ansani || KiK Camera Sender / Shot From Camera<br />
|-<br />
| Elias Limneos || [https://twitter.com/limneos @limneos] || https://github.com/limneos || -<br />
|-<br />
| Evan Swick || [http://twitter.com/e_swick @e_swick] || https://github.com/eswick || OS Experience, Harbor<br />
|-<br />
| evilgoldfish (Evan) || [https://twitter.com/evilgoldfish01 @evilgoldfish01] || https://github.com/evilgoldfish || -<br />
|-<br />
| EvilPenguin (James Emrich) || [https://twitter.com/EvilPenguin_ @EvilPenguin_] || https://github.com/EvilPenguin || -<br />
|-<br />
| expr (Fionn Kelleher) || - || - || -<br />
|-<br />
| F0u4d || - || - || -<br />
|-<br />
| FilippoBiga (Filippo Bigarella) || - || - || -<br />
|-<br />
| Finn Gaida || [https://twitter.com/fga @fga] || https://github.com/finngaida || TwitterNotificationAnimation, Keyhook, Breadcrumb10<br />
|-<br />
| flux (Aditya K.) || - || - || -<br />
|-<br />
| Guillermo Morán || [https://twitter.com/fr0st @fr0st] || https://github.com/fr0stdev || Eclipse (1-4), AppDrawer<br />
|-<br />
| freemanrepo (Majd Alfhaily) || - || - || -<br />
|-<br />
| iKyle (Kyle Howells) || [http://twitter.com/freerunnering @freerunnering] || https://github.com/freerunnering || Alympus, SwipeSelection<br />
|-<br />
| Frostbitee08 (Rocco Del Priore) || - || - || -<br />
|-<br />
| Gabriele Filipponi || - || - || -<br />
|-<br />
| gertab || - || - || CallShortcut<br />
|-<br />
| GreenPaperClip (jonathan yazinski) || - || - || -<br />
|-<br />
| Haifisch (Dylan Laws) || [http://twitter.com/0x8badfl00d @0x8badfl00d] || https://github.com/Haifisch || RePower, SnowBoard<br />
|-<br />
| Hiraku || [http://twitter.com/hiraku_dev @hiraku_dev] || https://github.com/hirakujira || iKeywi, Pasithea, Apple File Conduit "2" (iOS 11+, arm64)<br />
|-<br />
| iakd || - || - || -<br />
|-<br />
| IAmOrion || - || - || -<br />
|-<br />
| Ian Burns (ianb821) || [https://twitter.com/ianb821 @ianb821] || https://github.com/ianb821 || QRConversation, AlternateControls, MessageHeads, Vertex, GuestMode<br />
|-<br />
| ichitaso || [https://twitter.com/ichitaso @ichitaso] || https://github.com/ichitaso || NotifyWiFiX, IconTweak, Pasithea, PrimalFolder<br />
|-<br />
| ilendemli (Muhammet Ilendemli) || - || - || -<br />
|-<br />
| iKilledAppl3 (J.K Hayslip) || [http://twitter.com/iKilledAppl3 @iKilledAppl3] || https://github.com/iKilledAppl3 || CCWallCustomizer, NCWallCustomizer, StyloPowerDown<br />
|-<br />
| iMokhles (Mokhlas Hussein) || [http://twitter.com/imokhles @iMokhles] || https://github.com/iMokhles || WAEnhancer, Rendarya, VBEnhancer, PHEnhancer<br />
|-<br />
| iNasser (Nasser Aldeen) || [http://twitter.com/v000000000 @v000000000] || https://github.com/iNasser0 || Predix, DockColor, iDevice Wise, Instant Compose<br />
|-<br />
| iNeal || - || - || -<br />
|-<br />
| insanj (Julian Weiss) || - || - || -<br />
|-<br />
| iOSMarvin || - || - || -<br />
|-<br />
| its_not_herpes (Ethan Arbuckle) || - || - || -<br />
|-<br />
| Ivano Bilenchi (Exile.90) || [https://twitter.com/ivanobilenchi @IvanoBilenchi] || https://github.com/IvanoBilenchi || iCleaner, iCleaner Pro<br />
|-<br />
| J_W97 (Jack Willis) || - || - || -<br />
|-<br />
| Jailpod || - || - || -<br />
|-<br />
| Jeepston || - || - || -<br />
|-<br />
| Jerry En || - || - || -<br />
|-<br />
| Jontelang (Jonathan Winger-Lang) || - || - || -<br />
|-<br />
| jzplusplus (Jay Zuerndorfer) || - || - || -<br />
|-<br />
| Karen Tsai (angelXwind) || [https://twitter.com/angelXwind @angelXwind] || https://github.com/angelXwind || mikoto, Forecast, JellyLock Unified, AirSpeaker, IneffectivePower, PreferenceOrganizer 2<br />
|-<br />
| Kinan Saeb || [https://twitter.com/Kinan_iOS @Kinan_iOS] || - || Youtube Essentials<br />
|-<br />
| kirb (Adam Demasi) || [https://twitter.com/hbkirb @hbkirb] || https://github.com/kirb || TypeStatus, Cephei, Opener<br />
|-<br />
| LacertosusDeus || [https://twitter.com/LacertosusDeus @LacertosusDeus] || https://github.com/LacertosusRepo || Libellum, NowPlayingIcon<br />
|-<br />
| Majd Alfhaily || - || - || -<br />
|-<br />
| Marvin Schwalzik || - || - || -<br />
|-<br />
| max_katzmann (Max Katzmann) || - || - || -<br />
|-<br />
| merdok || [https://twitter.com/merdok_dev @merdok_dev] || - || UnlockSound, Appcon, Iconizer, Speak Notification, HUD Customizer, Badgomizer, Wake Info 2<br />
|-<br />
| MichaelSP1991 (Michael Poole) || [https://twitter.com/MichaelSP1991 @MichaelSP1991] || - || SubtleLock, WebShare, Ringdom<br />
|-<br />
| ming9010 || - || - || -<br />
|-<br />
| MPow (ManzoPower) || - || - || -<br />
|-<br />
| MTAC || [https://twitter.com/mtac8 @MTAC8] || https://github.com/MTACS || Lynx, FingerLock, MagSafe, N95, DopeConvos<br />
|-<br />
| NoahDev || [https://twitter.com/NoahDev @NoahDev] || https://github.com/NoahDev || NoSpotlightBlur<br />
|-<br />
| Noeliel ||[https://twitter.com/NoelielDev @NoelielDev] || - || Centered, QuickPass, StatusPeek, vHome<br />
|-<br />
| NoInfo07(Nathan Parker) ||[https://twitter.com/Nathan_Parker_ @Nathan_Parker_] || - || CustomMessages<br />
|-<br />
| nullpixel (Jamie Bishop) ||[https://twitter.com/nullriver @nullriver] || https://github.com/nullpixel1 || NoBTCC, NoLowPowerLock, contribute to Limitless<br />
|-<br />
| openmind (Dimitar Marinov) || - || - || -<br />
|-<br />
| Optimo || - || - || -<br />
|-<br />
| phillipten (Phillip Tennen) || [https://twitter.com/phillipten @phillipten] || https://github.com/Codyd51 || Acute, Hermes, CamText<br />
|-<br />
| pimskeks (Nikias Bassen) || - || - || -<br />
|-<br />
| pod2g || - || - || -<br />
|-<br />
| PoomSmart || [https://twitter.com/PoomSmart @PoomSmart] || https://github.com/PoomSmart || EmojiPort, YouPiP<br />
|-<br />
| pull3rb0y (Julian Rehorn) || [https://twitter.com/pull3rb0y @pull3rb0y] || https://github.com/pull3rb0y || pullbre4k<br />
|-<br />
| qwertyoruiop (Luca Todesco) || - || - || -<br />
|-<br />
| r333d || [https://twitter.com/rweichler @rweichler] || https://github.com/rweichler || Cylinder, [https://eqe.fm/about EQE], jjjj<br />
|-<br />
| r_idn (RiDan) || - || - || -<br />
|-<br />
| r0r0 (Rohit M.) || [https://twitter.com/r0r0m0ney @r0r0m0ney] || https://github.com/r0r0 || Twitter Essentials, Mega Runner, iMessage7<br />
|- <br />
| rdrnt || [https://twitter.com/_rdrnt @_rdrnt] || https://github.com/rdrnt || Superslam, Trudeau<br />
|- <br />
| rabih96 (Rabih M.) || [https://twitter.com/rabih96 @rabih96] || https://github.com/rabih96 || MyBatteryAlerts, CCScale, VolumeStatus<br />
|-<br />
| Razzile || [https://twitter.com/Razzilient @Razzilient] || https://github.com/Razzile || Candy Crusher, EasyRespring, KillSwitcher<br />
|-<br />
| rob311 || [https://twitter.com/rob311apps @rob311apps] || - || OneThumb, ListeningLauncher, StopCCinApp<br />
|-<br />
| robottomdev || - || - || -<br />
|-<br />
| Ron Thakrar || [https://twitter.com/ronthakrar @ronthakrar] || - || ChangeAwake, AboutUDID, Controls for Spotify<br />
|-<br />
| RTech || - || - || -<br />
|-<br />
| rpetrich (Ryan Petrich) || [https://twitter.com/rpetrich @rpetrich] || https://github.com/rpetrich || <!-- [http://rpetri.ch/repo/ link] || [mailto:rpetrich@gmail.com] || --> -<br />
|-<br />
| rud0lf77 || - || - || -<br />
|-<br />
| Ruslan Ardashev || [https://twitter.com/ruse_Ardashev @ruse_Ardashev] || https://github.com/ruslan120101 || panicLock (free), panicLock Pro [iOS 7, iOS 8], nupsidedown, reachabilityToggles<br />
|-<br />
| ryebread761 || - || - || -<br />
|-<br />
| rviraj (Raviraj Minawala) || [https://twitter.com/rv1raj @rv1raj] || https://github.com/ravirajm || -<br />
|-<br />
| Sassoty (Noah Saso) || [https://twitter.com/Sassoty @Sassoty] || https://github.com/Sassoty || ConvoProtect, GlowBadge, PulltoRespring, TypeRead, ScreenPainter, CamText<br />
|-<br />
| saurik (Jay Freeman) || [https://twitter.com/saurik @saurik] || https://github.com/saurik || -<br />
|-<br />
| sharedRoutine (Janosch H&uuml;bner) || [https://twitter.com/sharedRoutine @sharedRoutine] || https://github.com/sharedRoutine || AppHeads, MSGAutosave8<br />
|-<br />
| Shrugs (Matt Condon) || - || - || -<br />
|-<br />
| Simon Selg || [https://twitter.com/accuratweaks @AccuraTweaks] || https://github.com/Cr4zyS1m0n/ || BetterWiFi7, QRMode, Call Enhancer, AutoRotateVideos (beta)<br />
|-<br />
| SkittyBlock || [https://twitter.com/skittyblock @Skittyblock] || https://github.com/skittyblock/ || -<br />
|-<br />
| Skylerk99 || - || - || -<br />
|-<br />
| SpiritOfLogic || - || - || -<br />
|-<br />
| Sticktron || - || - || -<br />
|-<br />
| Suhaib Alfaqeeh || - || - || -<br />
|-<br />
| switchpwn (Mustafa Gezen) || - || - || -<br />
|-<br />
| termus1997 || [https://twitter.com/termus1997 @termus1997] || - || AutoLoadTweets, NoNotificationCenterBlur<br />
|-<br />
| theiostream || - || - || -<br />
|-<br />
| TheJailPad || [https://twitter.com/TheJailPadApple @TheJailPadApple] || - || BatterySafe, CCBackground, PlayTask<br />
|-<br />
| TheNinjaprawn (George Dan) || [http://twitter.com/theninjaprawn @TheNinjaprawn] || https://github.com/ninjaprawn || ColorBar, FolderSwipe7, Voltage<br />
|-<br />
| tomf64 (Thomas Finch) || [https://twitter.com/tomf64 @tomf64] || https://github.com/thomasfinch || Priority Hub, Dim<br />
|-<br />
| tweakcc (Alan Yip) || [https://twitter.com/tweakcc @tweakcc] || https://github.com/a1anyip || ProWidgets, StatusHUD 2<br />
|-<br />
| twodayslate || [https://twitter.com/twodayslate @twodayslate] || https://github.com/twodayslate || -<br />
|-<br />
| unlimapps || [https://twitter.com/unlimapps @unlimapps] || https://github.com/eni9889 || -<br />
|-<br />
| uroboro || [https://twitter.com/uroboro845 @uroboro845] || https://github.com/uroboro || FlipNC, 2048oard<br />
|-<br />
| vmanot (Vatsal Manot) || [https://twitter.com/vatsal_manot @vatsal_manot] || https://github.com/vmanot || Athena 2, Disable Parallax Effect, Menu Button Emulator, Power Button Emulator, Verbal<br />
|-<br />
| VedBoon (Javier Brito) || - || - || -<br />
|-<br />
| VladMax Soft || - || - || -<br />
|-<br />
| winocm || [https://twitter.com/winocm @winocm] || https://github.com/winocm || -<br />
|-<br />
| xTM3x (Wilson) || [https://twitter.com/xtm3x @xTM3x] || https://github.com/xthemaster3x || NoBlur, Dye, BIM, PAG<br />
|-<br />
| Dave van Wijk || [https://twitter.com/DaveWijk @DaveWijk] || https://github.com/vanwijkdave || QuickLS, QuitAll, Ainsworth<br />
|-<br />
| Zanif || - || - || -<br />
|-<br />
|-<br />
|}<br />
<br />
= External links =<br />
<br />
* A [http://www.reddit.com/r/jailbreak/wiki/twitter list] on the [http://www.reddit.com/r/jailbreak /r/jailbreak] wiki</div>PoomSmarthttps://iphonedev.wiki/index.php?title=Retrieving_SDKs&diff=5713Retrieving SDKs2021-07-06T13:46:54Z<p>PoomSmart: /* Retrieving without a Mac */ Removed dead link</p>
<hr />
<div>'''SDKs''' (Software Development Kits) are bundles that contain headers, binaries, and other tools needed to build for a specific version of iOS. These can be found within Xcode at <code>Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs</code>.<br />
<br />
== Retrieving without a Mac ==<br />
The legal way to download an SDK without access to a Mac is to download a copy of Xcode from Apple. These are available at [https://developer.apple.com/downloads/index.action developer.apple.com] (free developer registration required). Usually the latest SDK is best, but if you want an older version, find the Xcode version containing it from [https://xcodereleases.com/ this table]. <br />
<br />
A shareware program, [http://www.acutesystems.com/scrtm.htm TransMac], can extract Xcode DMGs on Windows. Open the DMG in the program, then use the left directory tree to navigate to <code>xcode.dmg/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs</code>. Right-click the SDK directory and choose "Copy To".<br />
<br />
Alternatively, grab a copy from [http://resources.airnativeextensions.com/ios/ here].<br />
<br />
''Expansion needed: How can modern Xcode .xip releases be extracted on Windows/Linux?''<br />
<br />
=== Troubleshooting ===<br />
<br />
As of iOS 8, some people found that those instructions didn't work with the latest version of TransMac (version 11), but version 10.6 may work.</div>PoomSmarthttps://iphonedev.wiki/index.php?title=Libundirect&diff=5709Libundirect2021-06-11T03:28:13Z<p>PoomSmart: /* How to use this library */</p>
<hr />
<div>{{DISPLAYTITLE:libundirect}}<br />
{{Infobox Package<br />
|developer=[https://twitter.com/opa334dev Lars Fröder (opa334)]<br />
|version=1.1.2<br />
|package=com.opa334.libundirect<br />
}}<br />
<br />
'''libundirect''' is a patchfinding and rebinding 64-bit library that provides directives to hook Objective-C direct methods. With the feature called <code>objc_direct</code> introduced in Xcode 12 and iOS 14.0, these direct methods are stripped when compiled - being unexported C functions and thus their signature and name are missing.<br />
<br />
As a patchfinder, <code>libundirect_find()</code> can find the address of the function to hook by providing unique bytes within the function and the name of the binary or library that the function resides. You need to perform reverse engineering on the binary that you are working with in order to determine the bytes to use. See [https://github.com/opa334/libundirect/blob/main/README.md#patchfinder libundirect's note on patchfinding] or [https://gist.github.com/johnzaro/fdffd93c2ee0bc7db56d7959a67b4235 johnzaro's guide to using libundirect] for more details.<br />
<br />
As a rebinder, <code>libundirect_rebind()</code> can re-add Objective-C method signature to the function that you hook. This provides backward compatibility for earlier iOS versions that the signature is still intact - and that you have to import <code><libundirect/libundirect_hookoverwrite.h></code> to make <code>MSHookMessageEx()</code> aware of direct methods and turn itself into <code>MSHookFunction</code> (because it is just a C-like function now).<br />
<br />
== How to use this library ==<br />
<br />
Headers are available from [https://github.com/opa334/libundirect libundirect's GitHub project] (the latest one) or from [https://github.com/theos/headers Theos' headers project]. The library from opa334's repository can be installed to <code>$THEOS/vendor/lib</code> by running <code>install_to_theos.sh</code> script inside libundirect repository.<br />
<br />
=== Include directive(s) ===<br />
<br />
<source lang="objc"><br />
#import <libundirect/libundirect.h><br />
#import <libundirect/libundirect_dynamic.h> // if you don't want to link directly against libundirect, import this one instead<br />
#import <libundirect/libundirect_hookoverwrite.h> // if you want backward compatibility<br />
</source><br />
<br />
=== Makefile ===<br />
<br />
Add to your Makefile:<br />
<br />
* <code>XXX_LIBRARIES = undirect</code><br />
<br />
=== Packaging ===<br />
<br />
Add to your package's control file:<br />
<br />
* <code>com.opa334.libundirect (>= 1.1.1)</code> to the <code>Depends</code> field.<br />
<br />
== Examples ==<br />
<br />
=== Hooking (and rebinding) a direct Objective-C method (MobileSafari) ===<br />
<br />
We will use the code in SafariPlus by opa334 as an example.<br />
<br />
<source lang="objc"><br />
#import <libundirect/libundirect.h><br />
#import <libundirect/libundirect_hookoverwrite.h><br />
#import <version.h><br />
<br />
%hook BrowserController<br />
<br />
- (void)tabControllerDocumentCountDidChange:(TabController *)tabController {<br />
%orig;<br />
...<br />
}<br />
<br />
%end<br />
<br />
...<br />
<br />
// In your constructor:<br />
<br />
if (IS_IOS_OR_NEWER(iOS_14_0)) {<br />
Class class_browserController = NSClassFromString(@"BrowserController");<br />
<br />
// -[BrowserController tabControllerDocumentCountDidChange:]<br />
// arm64 memory of function: [600100B4 F44FBEA9]<br />
// arm64e memory of function: [A00100B4 7F2303D5 F44FBEA9]<br />
// criteria: called by -[BrowserController _updateSceneTitle] (14.2: sub_100041e5c, references string @"Private Browsing")<br />
// 14.2: sub_10005bef8, arm64e: sub_10005E824<br />
<br />
#if __arm64e__<br />
void* tabControllerDocumentCountDidChange = libundirect_find(@"MobileSafari", (unsigned char[]){0xA0, 0x01, 0x00, 0xB4, 0x7F, 0x23, 0x03, 0xD5, 0xF4, 0x4F, 0xBE, 0xA9}, 12, 0);<br />
#else<br />
void* tabControllerDocumentCountDidChange = libundirect_find(@"MobileSafari", (unsigned char[]){0x60, 0x01, 0x00, 0xB4, 0xF4, 0x4F, 0xBE, 0xA9}, 8, 0);<br />
#endif<br />
<br />
libundirect_rebind(tabControllerDocumentCountDidChange, class_browserController, @selector(tabControllerDocumentCountDidChange:), "v@:@");<br />
}<br />
<br />
%init;<br />
</source><br />
<br />
=== Hooking an unnamed C function (libicucore) ===<br />
<br />
We will use the code in EmojiAttributes by PoomSmart as an example.<br />
<br />
<source lang="objc"><br />
#import <libundirect/libundirect.h><br />
<br />
...<br />
<br />
%group getUnicodeProperties<br />
<br />
%hookf(uint32_t, u_getUnicodeProperties, UChar32 c, int32_t column) {<br />
if (column >= propsVectorsColumns)<br />
return 0;<br />
uint16_t vecIndex = UTRIE2_GET16(&propsVectorsTrie, c);<br />
return propsVectors[vecIndex + column];<br />
}<br />
<br />
%end<br />
<br />
// In your constructor:<br />
<br />
#if TARGET_OS_SIMULATOR<br />
// Memory of function (iOS 13.5): 31C083FE 020F8F8D 00000055 4889E581 FFFFD700 00770789 F8C1E805 EB4A81FF FFFF0000 771731C0 81FF00DC 0000B940 0100000F 4DC889F8 C1E805EB 29B8D813 000081FF FFFF1000 773289F8 C1E80B48 8D0D30CC 1B000FB7 8C414010 000089F8 C1E80583 E03F01C8 89C0488D 0D15CC1B 000FB704 4183E71F 488D0487 488D0D03 CC1B000F B7044148 63CE4801 C1488D05 D2B11A00 8B04885D C3<br />
// Memory of function (iOS 12.4): 554889E5 31C083FE 020F8F8A 00000081 FFFFD700 00770789 F8C1E805 EB4C81FF FFFF0000 771731C0 81FF00DC 0000B940 0100000F 4DC889F8 C1E805EB 2B81FFFF FF100076 07B8D413 0000EB32 89F8C1E8 0B488D0D CFE61B00 0FB78C41 40100000 89F8C1E8 0583E03F 01C889C0 488D0DB4 E61B000F B7044183 E71F488D 0487488D 0DA2E61B 000FB704 414863CE 4801C148 8D0571D3 1A008B04 885DC3<br />
// Unique bytes (iOS 13.5): E03F01C8 89C0488D 0D15CC1B (offset: 100)<br />
// Unique bytes (iOS 12.4): 0583E03F 01C889C0 488D0DB4 (offset: 100)<br />
// Starting byte (iOS 13.5): 0x31<br />
// Starting byte (iOS 12.4): 0x55<br />
void *rp = libundirect_find(@"libicucore.A.dylib", (unsigned char[]){0xE0, 0x3F, 0x01, 0xC8, 0x89, 0xC0, 0x48, 0x8D, 0x0D, 0x15, 0xCC, 0x1B}, 12, 0x31);<br />
if (rp == NULL)<br />
rp = libundirect_find(@"libicucore.A.dylib", (unsigned char[]){0x05, 0x83, 0xE0, 0x3F, 0x01, 0xC8, 0x89, 0xC0, 0x48, 0x8D, 0x0D, 0xB4}, 12, 0x55);<br />
#else<br />
// Memory of function: 3F080071 6D000054 00008052 C0035FD6 087C0B53 1F690071 68000054 087C0513 08000014 087C1053 68020035 08809B52 1F00086B 08288052 08B19F1A 0815800B 090D00B0 29110F91 28D96878 09100012 2809080B 090D00B0 29110F91 28D96878 0801010B 890C00B0 29A12791 20D968B8 C0035FD6 1F410071 69000054 08548252 F5FFFF17 087C0B13 090D00B0 29110F91 28C5288B 08816079 0A280553 08412A8B 28796878 EAFFFF17<br />
// Unique bytes: 3F080071 6D000054 00008052 C0035FD6 (offset: 0)<br />
// Starting byte: 0x3F<br />
void *rp = libundirect_find(@"libicucore.A.dylib", (unsigned char[]){0x3F, 0x08, 0x00, 0x71, 0x6D, 0x00, 0x00, 0x54, 0x00, 0x00, 0x80, 0x52, 0xC0, 0x03, 0x5F, 0xD6}, 16, 0x3F);<br />
#endif<br />
<br />
%init(getUnicodeProperties, u_getUnicodeProperties = (void *)rp);<br />
</source><br />
<br />
== Project Examples ==<br />
<br />
{| class="wikitable"<br />
|-<br />
! Project<br />
! Author<br />
|-<br />
| [https://github.com/opa334/SafariPlus SafariPlus]<br />
| [https://github.com/opa334 opa334]<br />
|-<br />
| [https://github.com/udevsharold/safaritabs14 SafariTabs14]<br />
| [https://github.com/udevsharold udevsharold]<br />
|-<br />
| [https://github.com/p2kdev/SafariBlocker SafariBlocker]<br />
| [https://github.com/p2kdev p2kdev]<br />
|-<br />
| [https://github.com/PoomSmart/EmojiAttributes EmojiAttributes]<br />
| [https://github.com/PoomSmart PoomSmart]<br />
|}<br />
<br />
== External Links ==<br />
<br />
* [https://github.com/opa334/libundirect/blob/main/README.md libundirect's detailed usages]<br />
* [https://gist.github.com/johnzaro/fdffd93c2ee0bc7db56d7959a67b4235 Using disassembler to find unique bytes for libundirect]<br />
* [https://nshipster.com/direct/ Objective-C Direct Methods]<br />
<br />
{{Navbox Library}}<br />
<br />
[[Category:Cydia packages]]<br />
<br />
[[Category:Directories in /Library]]</div>PoomSmarthttps://iphonedev.wiki/index.php?title=Libundirect&diff=5708Libundirect2021-06-11T03:26:55Z<p>PoomSmart: </p>
<hr />
<div>{{DISPLAYTITLE:libundirect}}<br />
{{Infobox Package<br />
|developer=[https://twitter.com/opa334dev Lars Fröder (opa334)]<br />
|version=1.1.2<br />
|package=com.opa334.libundirect<br />
}}<br />
<br />
'''libundirect''' is a patchfinding and rebinding 64-bit library that provides directives to hook Objective-C direct methods. With the feature called <code>objc_direct</code> introduced in Xcode 12 and iOS 14.0, these direct methods are stripped when compiled - being unexported C functions and thus their signature and name are missing.<br />
<br />
As a patchfinder, <code>libundirect_find()</code> can find the address of the function to hook by providing unique bytes within the function and the name of the binary or library that the function resides. You need to perform reverse engineering on the binary that you are working with in order to determine the bytes to use. See [https://github.com/opa334/libundirect/blob/main/README.md#patchfinder libundirect's note on patchfinding] or [https://gist.github.com/johnzaro/fdffd93c2ee0bc7db56d7959a67b4235 johnzaro's guide to using libundirect] for more details.<br />
<br />
As a rebinder, <code>libundirect_rebind()</code> can re-add Objective-C method signature to the function that you hook. This provides backward compatibility for earlier iOS versions that the signature is still intact - and that you have to import <code><libundirect/libundirect_hookoverwrite.h></code> to make <code>MSHookMessageEx()</code> aware of direct methods and turn itself into <code>MSHookFunction</code> (because it is just a C-like function now).<br />
<br />
== How to use this library ==<br />
<br />
Headers are available from [https://github.com/opa334/libundirect libundirect's GitHub project] or from [https://github.com/theos/headers Theos' headers project]. The library can be installed to <code>$THEOS/vendor/lib</code> by running <code>install_to_theos.sh</code> script inside libundirect repository.<br />
<br />
=== Include directive(s) ===<br />
<br />
<source lang="objc"><br />
#import <libundirect/libundirect.h><br />
#import <libundirect/libundirect_dynamic.h> // if you don't want to link directly against libundirect, import this one instead<br />
#import <libundirect/libundirect_hookoverwrite.h> // if you want backward compatibility<br />
</source><br />
<br />
=== Makefile ===<br />
<br />
Add to your Makefile:<br />
<br />
* <code>XXX_LIBRARIES = undirect</code><br />
<br />
=== Packaging ===<br />
<br />
Add to your package's control file:<br />
<br />
* <code>com.opa334.libundirect (>= 1.1.1)</code> to the <code>Depends</code> field.<br />
<br />
== Examples ==<br />
<br />
=== Hooking (and rebinding) a direct Objective-C method (MobileSafari) ===<br />
<br />
We will use the code in SafariPlus by opa334 as an example.<br />
<br />
<source lang="objc"><br />
#import <libundirect/libundirect.h><br />
#import <libundirect/libundirect_hookoverwrite.h><br />
#import <version.h><br />
<br />
%hook BrowserController<br />
<br />
- (void)tabControllerDocumentCountDidChange:(TabController *)tabController {<br />
%orig;<br />
...<br />
}<br />
<br />
%end<br />
<br />
...<br />
<br />
// In your constructor:<br />
<br />
if (IS_IOS_OR_NEWER(iOS_14_0)) {<br />
Class class_browserController = NSClassFromString(@"BrowserController");<br />
<br />
// -[BrowserController tabControllerDocumentCountDidChange:]<br />
// arm64 memory of function: [600100B4 F44FBEA9]<br />
// arm64e memory of function: [A00100B4 7F2303D5 F44FBEA9]<br />
// criteria: called by -[BrowserController _updateSceneTitle] (14.2: sub_100041e5c, references string @"Private Browsing")<br />
// 14.2: sub_10005bef8, arm64e: sub_10005E824<br />
<br />
#if __arm64e__<br />
void* tabControllerDocumentCountDidChange = libundirect_find(@"MobileSafari", (unsigned char[]){0xA0, 0x01, 0x00, 0xB4, 0x7F, 0x23, 0x03, 0xD5, 0xF4, 0x4F, 0xBE, 0xA9}, 12, 0);<br />
#else<br />
void* tabControllerDocumentCountDidChange = libundirect_find(@"MobileSafari", (unsigned char[]){0x60, 0x01, 0x00, 0xB4, 0xF4, 0x4F, 0xBE, 0xA9}, 8, 0);<br />
#endif<br />
<br />
libundirect_rebind(tabControllerDocumentCountDidChange, class_browserController, @selector(tabControllerDocumentCountDidChange:), "v@:@");<br />
}<br />
<br />
%init;<br />
</source><br />
<br />
=== Hooking an unnamed C function (libicucore) ===<br />
<br />
We will use the code in EmojiAttributes by PoomSmart as an example.<br />
<br />
<source lang="objc"><br />
#import <libundirect/libundirect.h><br />
<br />
...<br />
<br />
%group getUnicodeProperties<br />
<br />
%hookf(uint32_t, u_getUnicodeProperties, UChar32 c, int32_t column) {<br />
if (column >= propsVectorsColumns)<br />
return 0;<br />
uint16_t vecIndex = UTRIE2_GET16(&propsVectorsTrie, c);<br />
return propsVectors[vecIndex + column];<br />
}<br />
<br />
%end<br />
<br />
// In your constructor:<br />
<br />
#if TARGET_OS_SIMULATOR<br />
// Memory of function (iOS 13.5): 31C083FE 020F8F8D 00000055 4889E581 FFFFD700 00770789 F8C1E805 EB4A81FF FFFF0000 771731C0 81FF00DC 0000B940 0100000F 4DC889F8 C1E805EB 29B8D813 000081FF FFFF1000 773289F8 C1E80B48 8D0D30CC 1B000FB7 8C414010 000089F8 C1E80583 E03F01C8 89C0488D 0D15CC1B 000FB704 4183E71F 488D0487 488D0D03 CC1B000F B7044148 63CE4801 C1488D05 D2B11A00 8B04885D C3<br />
// Memory of function (iOS 12.4): 554889E5 31C083FE 020F8F8A 00000081 FFFFD700 00770789 F8C1E805 EB4C81FF FFFF0000 771731C0 81FF00DC 0000B940 0100000F 4DC889F8 C1E805EB 2B81FFFF FF100076 07B8D413 0000EB32 89F8C1E8 0B488D0D CFE61B00 0FB78C41 40100000 89F8C1E8 0583E03F 01C889C0 488D0DB4 E61B000F B7044183 E71F488D 0487488D 0DA2E61B 000FB704 414863CE 4801C148 8D0571D3 1A008B04 885DC3<br />
// Unique bytes (iOS 13.5): E03F01C8 89C0488D 0D15CC1B (offset: 100)<br />
// Unique bytes (iOS 12.4): 0583E03F 01C889C0 488D0DB4 (offset: 100)<br />
// Starting byte (iOS 13.5): 0x31<br />
// Starting byte (iOS 12.4): 0x55<br />
void *rp = libundirect_find(@"libicucore.A.dylib", (unsigned char[]){0xE0, 0x3F, 0x01, 0xC8, 0x89, 0xC0, 0x48, 0x8D, 0x0D, 0x15, 0xCC, 0x1B}, 12, 0x31);<br />
if (rp == NULL)<br />
rp = libundirect_find(@"libicucore.A.dylib", (unsigned char[]){0x05, 0x83, 0xE0, 0x3F, 0x01, 0xC8, 0x89, 0xC0, 0x48, 0x8D, 0x0D, 0xB4}, 12, 0x55);<br />
#else<br />
// Memory of function: 3F080071 6D000054 00008052 C0035FD6 087C0B53 1F690071 68000054 087C0513 08000014 087C1053 68020035 08809B52 1F00086B 08288052 08B19F1A 0815800B 090D00B0 29110F91 28D96878 09100012 2809080B 090D00B0 29110F91 28D96878 0801010B 890C00B0 29A12791 20D968B8 C0035FD6 1F410071 69000054 08548252 F5FFFF17 087C0B13 090D00B0 29110F91 28C5288B 08816079 0A280553 08412A8B 28796878 EAFFFF17<br />
// Unique bytes: 3F080071 6D000054 00008052 C0035FD6 (offset: 0)<br />
// Starting byte: 0x3F<br />
void *rp = libundirect_find(@"libicucore.A.dylib", (unsigned char[]){0x3F, 0x08, 0x00, 0x71, 0x6D, 0x00, 0x00, 0x54, 0x00, 0x00, 0x80, 0x52, 0xC0, 0x03, 0x5F, 0xD6}, 16, 0x3F);<br />
#endif<br />
<br />
%init(getUnicodeProperties, u_getUnicodeProperties = (void *)rp);<br />
</source><br />
<br />
== Project Examples ==<br />
<br />
{| class="wikitable"<br />
|-<br />
! Project<br />
! Author<br />
|-<br />
| [https://github.com/opa334/SafariPlus SafariPlus]<br />
| [https://github.com/opa334 opa334]<br />
|-<br />
| [https://github.com/udevsharold/safaritabs14 SafariTabs14]<br />
| [https://github.com/udevsharold udevsharold]<br />
|-<br />
| [https://github.com/p2kdev/SafariBlocker SafariBlocker]<br />
| [https://github.com/p2kdev p2kdev]<br />
|-<br />
| [https://github.com/PoomSmart/EmojiAttributes EmojiAttributes]<br />
| [https://github.com/PoomSmart PoomSmart]<br />
|}<br />
<br />
== External Links ==<br />
<br />
* [https://github.com/opa334/libundirect/blob/main/README.md libundirect's detailed usages]<br />
* [https://gist.github.com/johnzaro/fdffd93c2ee0bc7db56d7959a67b4235 Using disassembler to find unique bytes for libundirect]<br />
* [https://nshipster.com/direct/ Objective-C Direct Methods]<br />
<br />
{{Navbox Library}}<br />
<br />
[[Category:Cydia packages]]<br />
<br />
[[Category:Directories in /Library]]</div>PoomSmarthttps://iphonedev.wiki/index.php?title=SBApplication&diff=5704SBApplication2021-06-06T08:10:40Z<p>PoomSmart: /* Classic Mode */</p>
<hr />
<div>[[SBApplication]] is a class that represents individual applications. It contains anything you could possibly want to know about the application it represents. <br />
<br />
== Fetching SBApplications ==<br />
[[SBApplicationController]] holds all known instances of SBApplication. There will usually just be a single instance per currently-running application. An instance can be retrieved using the wanted-application's bundle identifier.<br />
<source lang="objc"><br />
//iOS 7-<br />
SBApplication* app = [[SBApplicationController sharedInstance] applicationWithDisplayIdentifier:@"com.yourcompany.appname"];<br />
<br />
// iOS 8+<br />
SBApplication* app = [[SBApplicationController sharedInstance] applicationWithBundleIdentifier:@"com.yourcompany.appname"];<br />
</source><br />
<br />
== Fetching Frontmost App's SBApplication Instance ==<br />
This method will return the frontmost application's SBApplication instance. If no app is currently running <code>nil</code> will be returned. Internally it queries [[SBSceneManagerCoordinator]] to retrieve the application (if any) that is fulfilling the primary layout role.<br />
<source lang="objc"><br />
[[SpringBoard sharedApplication] _accessibilityFrontMostApplication];<br />
</source><br />
<br />
== Fetching All Instances ==<br />
[[SBApplicationController]] can provide an array containing all known instances of SBApplication. <br />
<source lang="objc"><br />
[[SBApplicationController sharedInstanceIfExists] runningApplications];<br />
</source><br />
<br />
== Fetch "Now Playing" App ==<br />
<source lang="objc"><br />
SBApplication *nowPlayingApp = [[SBMediaController sharedInstance] nowPlayingApplication];<br />
</source><br />
<br />
== Launching an SBApplication ==<br />
[[SBUIController]] can be used to launch an SBApplication.<br />
<source lang="objc"><br />
SBApplication *appToLaunch = [[SBApplicationController sharedInstanceIfExists] runningApplications][0];<br />
[[SBUIController sharedInstanceIfExists] activateApplication:appToLaunch];<br />
</source><br />
<br />
== Classic Mode ==<br />
<br />
Here are the constants that represent application classic mode depending on the screen type, retrieved from reversing <code>SBApplicationClassicModeDescription(NSInteger)</code> or <code>SBApplicationClassicModeForString(NSString *)</code> from [[SpringBoard.framework]].<br />
<br />
<source lang="objc"><br />
<br />
// The number suffix, if present, represents the diagonal size of the screen, in inches<br />
typedef NS_ENUM(NSInteger, SBApplicationClassicMode) {<br />
SBApplicationClassicModeNone = 0,<br />
SBApplicationClassicModePhone = 1,<br />
SBApplicationClassicModePhone4 = 2,<br />
SBApplicationClassicModePhone4_7 = 3,<br />
SBApplicationClassicModePhone5_5 = 4,<br />
SBApplicationClassicModePhone5_8_Zoomed = 5, // rounded<br />
SBApplicationClassicModePhone5_8 = 6, // rounded<br />
SBApplicationClassicModePhone6_1 = 7, // rounded<br />
SBApplicationClassicModePhone6_5 = 8, // rounded<br />
SBApplicationClassicModePhone6_7 = 9, // rounded<br />
SBApplicationClassicModePad = 10,<br />
SBApplicationClassicModePad_10_5 = 11,<br />
SBApplicationClassicModePad_12_9 = 12,<br />
SBApplicationClassicModePad_11 = 13 // rounded<br />
};<br />
<br />
</source><br />
<br />
To disable launch animations simply apply the correct activation setting before calling <code>-activateApplication:</code>.<br />
<source lang="objc"><br />
[appToLaunch setFlag:1 forActivationSetting:1]; // flag 1 = ON, Activation Setting 1 = @"noAnimate"<br />
</source><br />
<br />
'''Notes:'''<br />
* This method will not respect parental control. However, you can determine if an SBApplication is restricted (parental locked) by using [[SBApplicationRestrictionController]], which [[SBApplicationController]] holds an instance of. <br />
<source lang="objc"><br />
SBApplication *appToCheck = [[SBApplicationController sharedInstanceIfExists] runningApplications][0];<br />
BOOL appIsRestricted = [[[SBApplicationController sharedInstanceIfExists] restrictionController] isApplicationIdentifierRestricted:[appToCheck bundleIdentifier]];<br />
</source><br />
<br />
'''Other Known Activation Flags'''<br />
<br />
{| class="activationflags"<br />
|-<br />
! Flag || Setting<br />
|-<br />
| 1 || Launch without animations. <br />
|-<br />
| 8 || Force launch animation to use app's context view instead of a snapshot. <br />
|-<br />
| 11 || Delay launch animation.<br />
|-<br />
| 43 || Set the app as the "Now Playing" application. <br />
|}<br />
<br />
== Useful Methods == <br />
These are a few of the useful items in SBApplication. <br />
<source lang="objc"><br />
<br />
//the apps bundle id<br />
- (NSString *)bundleIdentifier; <br />
<br />
//is it SpringBoard's instance<br />
- (BOOL)isSpringBoard; <br />
<br />
//app location info<br />
- (NSString *)path;<br />
- (NSString *)dataContainerPath;<br />
- (NSString *)bundleContainerPath;<br />
- (NSString *)bundleVersion;<br />
- (NSString *)sandboxPath; <br />
<br />
//general info<br />
- (BOOL)isSetup;<br />
- (BOOL)isMobilePhone;<br />
- (BOOL)isFaceTime;<br />
- (BOOL)behavesLikePhone;<br />
- (BOOL)isWebApplication;<br />
- (BOOL)isWatchApplication;<br />
- (BOOL)isNowPlayingApplication;<br />
- (BOOL)isNowRecordingApplication;<br />
- (BOOL)showsProgress;<br />
- (BOOL)isRecordingAudio;<br />
- (BOOL)isRunning;<br />
- (BOOL)hasStartedLaunching;<br />
<br />
//the string displayed under the icon<br />
- (NSString *)displayName;<br />
<br />
//has it been launched at some point in SpringBoard's life<br />
- (BOOL)hasBeenFrontmost;<br />
<br />
//badge number<br />
- (id)badgeNumberOrString;<br />
<br />
//returns the app's FBScene instance, useful for doing context host view stuff<br />
- (FBScene *)mainScene;<br />
<br />
</source><br />
<br />
== Application Info.plist ==<br />
<br />
SpringBoard will recognize the following Info.plist keys:<br />
<br />
* UISystemProvisioning<br />
* SBDemoRole<ref name="hunt">http://blogs.oreilly.com/iphone/2008/11/hunting-down-infoplist-prefere.html</ref><br />
* SBIsRevealable<ref name="hunt"/><ref>http://www.tuaw.com/2007/11/29/enable-app-hiding-on-your-iphone/</ref><br />
* SBUsesNetwork<ref>http://stackoverflow.com/questions/596589/iphone-sdk-internet-connection-detection</ref><br />
* UIJetsamPriority<br />
* SBIconClass<br />
* SBSpotlightIcons<br />
* UIRoles<br />
* SBMachServices<br />
* disabled<br />
* CFBundleIconFile<br />
* SPSearchDomainLaunchInfo<br />
* SBAppTags<ref>http://www.ifans.com/forums/threads/what-keeps-these-hidden.331215/#post-2552445</ref><ref>http://www.ifans.com/forums/threads/hide-applications.76176/#post-717439</ref><br />
* Other UIKit keys described in http://developer.apple.com/IPhone/library/documentation/General/Reference/InfoPlistKeyReference/Articles/iPhoneOSKeys.html<br />
<br />
Starting from 3.2 these ''documented'' keys are also recognized:<br />
<br />
* ProductType, UIDeviceFamily, DeviceFamily<ref>The keys ProductType and DeviceFamily are private but equivalent to UIDeviceFamily.</ref><br />
* UIAppFonts<br />
* UIFileSharingEnabled<br />
* UISupportedInterfaceOrientations<br />
<br />
As of iOS 8, the following undocumented key is also recognized:<br />
<br />
* _UILaunchAlwaysFullScreen<ref>http://pastebin.com/XmRqevnD</ref><br />
<br />
== References ==<br />
<references /><br />
* Header: https://github.com/theos/headers/blob/master/SpringBoard/SBApplication.h<br />
<br />
{{occlass|library=SpringBoard.app|navbox=1}}</div>PoomSmarthttps://iphonedev.wiki/index.php?title=IDA_Pro&diff=5703IDA Pro2021-06-05T14:02:11Z<p>PoomSmart: /* Types and Functions Definitions */</p>
<hr />
<div>Notes: <br />
* All discussion of resources that can be obtained from InternalUI builds should be regarded as hypothetical and purely educational. Obtaining these builds without the express permission of Apple is illegal, and doing so is discouraged. All information provided here is purely educational. <br />
* This guide was written for IDA 7.5. It should work on 7.3 and above. If you're using a cracked version, Scroll down to the "Pre 7.3" section. The rest doesn't apply to you at all.<br />
<br />
== Crucial Performance Tips ==<br />
<br />
* Close the function window while analyzing to speed up processing about 10 times, typically.<br />
** An active filter in the functions window will hurt speed much worse.<br />
* When analyzing ''massive'' files, close all of the windows inside IDA (IDA View-A, functions, output, etc). Processing will speed up anywhere from 5x to 100x.<br />
* Disable Lumina. Find a way to delete it from IDA if you can. If enabled, it will irreversibly "fix" names by setting them to completely incorrect values. This will waste your time and hurt your analysis.<br />
* IDA seems to operate on one thread. This means when doing anything remotely intensive, it will appear to freeze. This is normal. Don't Force Quit.<br />
* ''Heavily'' consider maxing out your RAM if you work with IDA very often. You won't regret it, and it will avoid system crashes when working with multiple shared caches.<br />
* If you're on an OS with the ability to create "desktops", we highly suggest you give IDA it's own. It will block your UI while loading otherwise.<br />
<br />
General tips regarding IDA usage for iOS RE: * If you are not patient, do not use IDA on the dyld_shared_cache because the processing will be very slow. * Modern versions of IDA come with an built-in dark mode. Use "IDASkins" if you are on an older version to enable dark mode. ''Your eyes will thank you if you work at night.''<br />
<br />
A majority of the information in this article details the process of reverse engineering using the dyld_shared_cache, as doing such is poorly documented in official documents.<br />
<br />
== Terms used ==<br />
<br />
* "Module" represents a Framework or library located in the dyld_shared_cache.<br />
* "Segment" or "Module Segment" refers to a specific segment of a framework.<br />
** The text segment contains code.<br />
** IDA 7.3 and greater include the ability to '''load only data segments on-demand''' without processing the text segment.<br />
<br />
== Analyzing the dyld_shared_cache in IDA Pro 7.3 and later. ==<br />
<br />
Helpful link: https://www.hex-rays.com/products/ida/support/idadoc/1705.shtml<br />
<br />
IDA 7.3 and later includes a powerful, improved shared cache toolkit. It eliminates the need for simulator binaries, and makes analysis possible when you cannot get access to simulator binaries (InternalUI builds, no macOS, no x64 decompiler, etc.)<br />
<br />
Everything described here was performed on a licensed copy of IDA Pro 7.5. Older, especially unlicensed versions, may not be able to handle all of these features.<br />
<br />
-----<br />
<br />
=== Analyzing a specific framework from the dyld_shared_cache. ===<br />
<br />
'''Do not "Load module and dependencies" option on "high level" frameworks.''' In iOS 13, with <code>SpringBoardHome</code> this results in loading 720 modules. This takes upwards of 2 to 3 days on an 8-core 4GHz 32GB-of-ram PC. In newer versions, due to consolidation, that number is down to ~400. You'll still be unable to use your PC for a few days at best. kritanta (@arm64e on Twitter) has loaded an entire shared cache a total of 3 times. There could even be a separate article on the unfixable issues that happen. Utilize the tools described below for the greater good.<br />
<br />
IDA 7.3 introduced powerful new tools for dealing with the cache. You can now load a single module and selectively load only segments you need from other locations in the shared cache. It can be a pain, but the alternative is much, much worse.<br />
<br />
==== Load the framework you're interested in ====<br />
<br />
# Select the "Load single module" option. Ensure you do not select "with dependencies".<br />
# Wait for the module you selected to load. It shouldn't take long.<br />
<br />
For this example we'll be using FrontBoard.framework.<br />
<br />
Loading is the easy part. Now we get to go through the process of correcting IDA's failures, as certain functions tend to fall apart in the dyld_shared_cache subsystem.<br />
<br />
==== Troubleshooting missing data (red addresses, garbage variable names, etc) ====<br />
<br />
The first thing you'll notice is that the assembly or pseudocode generated is absolute gibberish. ''If regular assembly is gibberish to you, this is ''advanced'' gibberish.''<br />
<br />
Swap to the IDA view for this. You may not be able to read assembly, but the pseudocode view doesn't properly handle the new features.<br />
<br />
===== Red addresses =====<br />
<br />
Swap to the "IDA View", as it doesn't work properly in the pseudocode view, and right-click a red address. We are going to assume that the one you clicked was a reference to <code>libobjc.dylib</code>, although it could be any library or framework in the cache.<br />
<br />
You'll see an option to load "libobjc.A:__OBJC_RO" or something similar, or an option to load the entirety of "libobjc.A". If you don't need to reverse the contents of "libobjc.A" (you don't), you should simply load only the segment IDA suggests. This allows you to avoid absolutely destroying your RAM and CPU when working in the cache, while also allowing you to make sense of the code within it.<br />
<br />
===== If the address is still red: =====<br />
<br />
IDA likely failed to recognize any information in the segment. This can be caused by a damaged database, if IDA crashed while processing data.<br />
<br />
Click the address and you'll be taken to the memory location, and if that assumption is correct and you can see vertical strings of letters:<br />
<br />
* In the Menu, click Edit -> Other -> Objective C -> Reload Objective C Info, then navigate to the function you're disassembling.<br />
* Right-click the red address and re-load the segment. Check "Do not show again for this session" unless you like repetition.<br />
* In the Menu, click Edit -> Other -> Objective C -> Reload Objective C Info (yes, again).<br />
* Right-click the far left string on the IDA View that holds the name of your target framework.<br />
* Load the entire framework (2nd option), not a specific section.<br />
* Right-click the red address and load the segment again.<br />
<br />
Your address is probably still red. If so, you've damaged your database. We'd advise deleting the database and starting from scratch. This is the fastest option.<br />
<br />
===== off_xxxxxxxxx (random hex address prefixed by "off_") in your assembly =====<br />
<br />
'''What causes this?'''<br />
<br />
These represent "refs". You're most likely looking at a class ref that failed to load.<br />
<br />
'''Fix'''<br />
<br />
# In the IDA View, double-click the <code>off_x</code> variable to be taken to the classrefs segment<br />
# Right-click the red memory address and load the suggested module segment.<br />
<br />
A name will appear. Good. Go back to your function.<br />
<br />
<ol start="3" style="list-style-type: decimal;"><br />
<li>Edit -> Other -> Objective C -> Reload Objective C Info</li></ol><br />
<br />
If it changes from <code>off_x</code> to <code>selRef</code>, <code>classRef</code>, or something similar, you can move on.<br />
<br />
If it does not change, see below<br />
<br />
'''What causes this?'''<br />
<br />
IDA improperly guessed the type of a struct it loaded due to a missing segment.<br />
<br />
'''Fix'''<br />
<br />
# Double click the pink text if you haven't yet to be taken to the class definition in __objc_data<br />
# Click the <code>_OBJC_CLASS...</code> item to select that line<br />
# Open Edit -> Struct Var<br />
# Select objc_class and hit OK<br />
# A red memory address will appear. Load that segment.<br />
# Make your way back to your function that you're disassembling.<br />
# Edit -> Other -> Objective C -> Reload Objective C Info<br />
# Cry, because it's finally fixed.<br />
<br />
Repeat this for any variables you feel are worth spending the time correcting.<br />
<br />
===== Other issues =====<br />
<br />
kritanta: ''I'm likely forgetting some. I loaded a shared cache fresh and walked myself through fixing issues for the sake of this guide. I'll continue to add solutions as I encounter them.''<br />
<br />
-----<br />
<br />
Interesting Note: Sometimes, you'll see an address and click to load it in. "What on earth is 'GeoServices' doing in this function?" You might think. Upon loading, you'll see it was something like <code>j__objc_retainAutoreleasedReturnValue_0</code>. This is a byproduct of the shared_cache's optimizations, and as a result, you'll end up with several duplicate functions like this. A script to fix these needs to be written, eventually.<br />
<br />
<br />
-----<br />
<br />
Typically loaded frameworks:<br /><br />
libobjc<br /><br />
Foundation<br /><br />
CoreFoundation<br /><br />
GeoServices ("trampoline")<br />
<br />
kritanta: ''I'm very interested in the concept of creating a "template database" that has data segments for these and others pre-loaded. If someone tries that, do update here with how that's done best.''<br />
<br />
-----<br />
<br />
=== Working with pseudocode from the dyld_shared_cache ===<br />
<br />
Something you'll likely become familiar with is the statement <code>(self + 10)</code>, where 10 is any 2 digit number. In objc source, you would see this as an ivar. If you've loaded in the relevant class information, you can help IDA display these ivars properly in the pseudocode view like so:<br />
<br />
* Right-click the <code>a1</code> or <code>self</code> variable on line one<br />
* Click Y or "Set ivar type"<br />
* Change the class of <code>self</code>/<code>a1</code> to the class shown next to it.<br />
* Change a1 to self if need be<br />
<br />
Ivars should now be properly generated and shown in pseudocode.<br />
<br />
<br />
-----<br />
<br />
=== InternalUI .development cache ===<br />
<br />
While someone more experienced could speak to the exact purpose of this build of the cache, given that a dump was leaked to the general public, there is no need not to discuss this.<br />
<br />
The .development cache (which cannot be loaded in cracked IDA versions) appears to be a build of the shared cache that properly holds symbols for the libobjc, libsystem, and other libraries, instead of raw addresses.<br />
<br />
If you're using Hopper or IDA 7.5, give the .development cache a shot.<br />
<br />
kritanta: ''Do note, I've had some issues with certain functions in it. I'm excited to see more information or research on the functionality of this object.''<br />
<br />
<br />
-----<br />
<br />
== Pre-7.3 dyld_shared_cache analysis by kritanta ==<br />
<br />
I do not intend to pick a fight with illegitimate IDA users. The software is insanely expensive, I cannot fault anyone in that regard. If you are using an illegitimate copy, don't tell me, I don't want to know. Best of luck.<br />
<br />
It's from a year of experience with it that I'm telling you: * Illegitimate versions of IDA cannot properly handle arm64e code very well. * Illegitimate versions of IDA cannot properly handle .development versions of shared caches available in InternalUI dumps whatsoever. It's completely incapable, and fails to process modules it loads. * Users of illegitimate versions of IDA should primarily stick to Simulator runtime binaries as detailed below. * Consider Hopper. It is capable of a few of IDA >7.3's features (arm64e, .development caches) and carries a much smaller price tag * Get comfortable with assembly if you intend to use Hopper. The pseudocode it generates is among the "least desirable" in the industry, and the assembly is easier to read. * Additionally, consider Ghidra. I'm not familiar with it, but others are, and can help you work with it. * Ghidra pseudocode I have heard is on par with IDA 7.0's pseudocode.<br />
<br />
I've decided to leave the below sections in this guide for educational purposes, but using a cracked IDA here is more than likely a waste of your time compared to the myriad of options available. Additionally, I obviously cannot condone the usage of such.<br />
<br />
=== If you are dead-set on using the arm64 shared cache ===<br />
<br />
'''Before you start analyzing the entire thing, I've already done that!''' I've publicly shared the fully processed cache here: https://developer.openpack.io/dyld_shared_cache_arm64.i64. Do not let my sacrifice of 4 days be in vain. Use this, don't waste your time.<br />
<br />
It includes SpringBoardHome and 740 other frameworks SpringBoardHome depends on. It's a 13 GB file. Have fun.<br />
<br />
This is not worth it, you have been warned. ''Please'' consider using simulator binaries instead.<br />
<br />
'''Trying to search for a function name will crash IDA entirely'''. Close the Functions view and open the "Program Segmentation" window. Browse frameworks like this, and carefully scroll through to find the function you want.<br />
<br />
Although you can work around the Function name search crash by using a full filter instead of the quick filter, this will cause decompilation to take several minutes while the filter is active. Additionally applying and removing the filter will take several minutes (but typically doesn't crash).<br />
<br />
=== Simulator Binaries: the recommended solution on older IDA versions ===<br />
<br />
The iOS simulator runtime is for you. x64 binaries that don't have the "Red Address" issue are available.<br />
<br />
Find them here: <code>/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 12.4.simruntime/Contents/Resources/RuntimeRoot/System/Library/PrivateFrameworks</code><br />
<br />
You may need to change the name of the folder for the simulator versions you have downloaded and installed.<br />
<br />
== Types and Functions Definitions ==<br />
<br />
IDA Pro does provide you a limited amount of types and functions definitions from Objective-C (although you will get many more on IDA Pro 7.5, but still there are wild functions and whatnot). The binaries however may import more functions or pack more types that IDA Pro does not have knowledge about. For example, the parameters of <code>dispatch_async</code> function may not be detected correctly. It may have only one parameter or not at all, making your binary analysis more difficult, not to mention when you work on different binaries and you face many other incorrectly typed functions. Use https://github.com/PoomSmart/IDAObjcTypes to import the types and definitions to fix this once and for all.<br />
<br />
== dsc_fix.py Plugin ==<br />
<br />
This plugin no longer functions, as the IDA SDK no longer provides the needed interfaces. Additionally, it needs to be updated for Python 3.</div>PoomSmarthttps://iphonedev.wiki/index.php?title=Dyld_shared_cache&diff=5702Dyld shared cache2021-06-05T13:57:33Z<p>PoomSmart: /* Simulator Runtime Frameworks */</p>
<hr />
<div>{{DISPLAYTITLE:dyld_shared_cache}}<br />
<br />
Since iPhone OS 3.1, all system (private and public) libraries have been combined into a big cache file to improve performance. The original files are redundant and thus eliminated from the system.<br />
<br />
If you're looking for binaries or libraries inside of <tt>[http://theiphonewiki.com/wiki//System/Library/Frameworks /System/Library/Frameworks]</tt> or <tt>/System/Library/PrivateFrameworks</tt> (or other directories) and can't, this is why.<br />
<br />
As of iOS 13.5 application code is now in frameworks in the shared cache. The binaries you see in <tt>/Applications</tt> or <tt>/private/var/staged_system_apps</tt> are now just shims, so if you attempt to class-dump them it will error out as no ObjC section will be found.<br />
<br />
OS X, along with any other *OS released by apple also uses a shared cache. Unlike iOS, OS X ships with the source binaries still on-disk, particularly so it can be updated with [https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/update_dyld_shared_cache.1.html update_dyld_shared_cache]. The cache is only vaguely documented in dyld man pages.<br />
<br />
== Obtaining a shared cache ==<br />
<br />
The easiest method for getting a dyld_shared_cache is as such:<br />
<br />
# Download or locate an ipsw for the target version and device <br />
# Rename it to a .zip, extract, and locate the largest .dmg <br />
# Mount the dmg and navigate to /System/Library/Caches/com.apple.dyld/ <br />
# Copy the dyld_shared_cache to your machine. <br />
<br />
<br />
== Extracting Frameworks and Libraries. ==<br />
<br />
Since iOS 8, the SDK no longer includes extracted frameworks. The only way to obtain the libraries running on your device is via extraction.<br />
<br />
Extracting the shared cache is useful in a few situations:<br />
<br />
* Linking against a framework or library not available in the public SDK<br />
* Using class-dump or similar tools to analyze Private Frameworks.<br />
* Reverse engineering the code in private or public frameworks within iOS.<br />
<br />
[https://github.com/arandomdev/DyldExtractor DyldExtractor] is currently (as of iOS 14) capable of extracting nearly perfect frameworks from the shared cache. However, these cannot yet be loaded by dyld, as more work needs done.<br />
<br />
== Shared cache static analysis == <br />
<br />
=== Simulator Runtime Frameworks ===<br />
<br />
''Can someone with an M1 mac comment on this?''<br />
<br />
The simulator runtime generated by Xcode includes fully symbolicated, perfect x64 binaries for Private and Public frameworks. For most shared_cache analysis, unless you own IDA 7.5 or the frameworks you are looking for are not available in simulators, you are fine with these. They're located under <code>/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot</code> (Xcode 11 and higher) or <code>/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot</code> (Xcode 10 and lower).<br />
<br />
=== Disassemblers capable of extraction ===<br />
<br />
Using [https://github.com/arandomdev/DyldExtractor DyldExtractor] is recommended for extraction. The only tool capable of extracting on its own is IDA Pro 7.5, and using an extractor can still be easier.<br />
<br />
==== IDA Pro ====<br />
<br />
IDA 7.5 includes a plethora of tools that make working with the dsc much more tolerable. It entirely eliminates the need for extraction or third-party scripts to fix output.<br />
<br />
Details and instructions on using the integrated tools can be found on the [[IDA Pro]] page. If you own a copy, check the IDA page on this wiki for a guide on using it.<br />
<br />
==== Hopper ====<br />
<br />
Hopper is capable of loading singular modules from the shared cache. It does not fix references and as such produces mostly useless output.<br />
<br />
It also allows loading the entire shared cache, but tends to crash when loading it. It's not worth your time.<br />
<br />
==== Ghidra ====<br />
<br />
Ghidra is capable of loading the shared cache<br />
<br />
''More information is needed here''<br />
<br />
There are [https://github.com/NationalSecurityAgency/ghidra/issues/682 known issues] with loading a shared cache. <br />
<br />
=== Standalone tools ===<br />
<br />
Working on current iOS versions:<br />
<br />
* [https://github.com/arandomdev/DyldExtractor DyldExtractor]. Python project capable of extracting and heavily fixing up frameworks from the shared cache. This tool produces nearly perfect output on current iOS versions. <br />
<br />
"Working":<br />
<br />
* [http://opensource.apple.com/source/dyld/ dsc_extractor (source code)]. More info [https://gist.github.com/NSExceptional/85527151eeec4b0640187a0a165da1cd here]. It produces the best results among all tools, but without branch islands workaround. Do note this is the exact same output provided by XCode automatically.<br />
<br />
Tools for previous iOS versions:<br />
<br />
* [https://github.com/kennytm/Miscellaneous/downloads dyld_decache] by KennyTM~ to extract these dylibs.<br />
* [https://gist.github.com/455086/ DySlim] by comex to mount the whole cache file on Mac OS X.<br />
* [https://github.com/phoenix3200/decache decache] by phoenixdev to nearly perfectly extract dylibs from iOS <= 6 cache file.<br />
* [http://www.newosxbook.com/index.php?page=downloads jtool] is another option starting from iOS 8. <br />
* [https://github.com/comex/imaon2 yasce] by comex is/was the best option for iOS 8 (and above), but you will need a nightly build version of rust; something like "rustc 1.9.0-nightly (339a409bf 2016-03-01)".<br />
* [https://github.com/macmade/dyld_cache_extract dyld_cache_extract] by macmade that works on macOS and provides a complete GUI. Clone repo and do 'git submodule update --remote' before buidling. It was reported to be not working on iOS 10.2's dyld_shared_cache_armv7s; gave a 561.1MB executable file.<br />
<br />
== Cache location ==<br />
<br />
The cache is located in <tt>/System/Library/Caches/com.apple.dyld/dyld_shared_cache_armX</tt>, where X can be:<br />
<br />
{| class="wikitable"<br />
|-<br />
! X<br />
! Device ARM Architecture<br />
|-<br />
| v6<br />
| ARMv6<br />
|-<br />
| v7<br />
| rowspan="3" | ARMv7<br />
|-<br />
| v7s<br />
|-<br />
| v7k<br />
|-<br />
| 64<br />
| ARMv8<br />
|-<br />
| 64e<br />
| ARMv8.3<br />
|}<br />
<br />
== "Development" vs "Release" caches ==<br />
<br />
=== Creation/background ===<br />
<br />
The source code for the tool used at apple is here:<br />
<br />
https://opensource.apple.com/source/dyld/dyld-733.6/dyld3/shared-cache/CacheBuilder.cpp.auto.html<br />
<br />
Specifically linked is the file responsible for determining if a development build is being created, and if so to avoid removing stubs. This is likely done to make debugging issues in frameworks much less painful.<br />
<br />
Evidence of these builds is present in dyld source (''link to a github mirror here please''), and they're likely used in internal iOS builds.<br />
<br />
<br />
=== Other Disassemblers ===<br />
<br />
''Information on how other disassemblers interact with these caches is needed.''<br />
<br />
<br />
=== Example usage for jtool ===<br />
<br />
To extract a specific binary from the cache ("UIKit" can be replaced with a different framework or library):<br />
<br />
<source lang=bash>jtool -extract UIKit path/to/dyld_shared_cache</source><br />
<br />
An example of one way to dump all the binaries at once (be careful with this, it creates huge files):<br />
<br />
<source lang=bash><br />
cache=dyld_shared_cache_arm64<br />
mkdir -p extracted && jtool -lv $cache | cut -c 24- | tail +5 | while read line; do mkdir -p extracted/"$(dirname "$line")"; jtool -extract $line $cache; mv $cache."$(basename "$line")" extracted/$line; done<br />
</source><br />
<br />
==== Problems with jtool ====<br />
<br />
Please be aware that decache produces currently (16.04.15) better and more usable results then jtool, as jtool fails to resolve and fix the "uniqued" objectiv c selectors correctly.<br />
<br />
Apple "uniques" objectiv c selectors, such as "alloc" (alloc is used almost everywhere), which are used in more then one place, into a single one. When extracting an image from the cache, the address of such a shared selector will most likely not be in the extracted image anymore, so this needs to fixed, which jtool apparently fails to do. (For more information: http://opensource.apple.com/source/dyld/dyld-132.13/launch-cache/update_dyld_shared_cache.cpp, look at the class ObjCSelectorUniquer)<br />
<br />
==== Not working since iOS 11 ====<br />
<br />
jtool2 is the newer version this user reports it not working on the iOS 11 shared cache - shows a warning "File is likely truncated (or header corrupt?)" and then doesn't get past "LC_DYLD_INFO..." http://newosxbook.com/forum/viewtopic.php?f=3&t=19577&start=50#p24183 Still same error exists on the cache from iOS 13.<br />
<br />
<source lang=bash><br />
$ ./jtool2 -e Stocks ./dyld_shared_cache_arm64 <br />
Warning: File is likely truncated (or header corrupt?) Binding opcodes falls outside file<br />
Warning: File is likely truncated (or header corrupt?) Binding opcodes falls outside file<br />
Warning: File is likely truncated (or header corrupt?) LC_FUNCTION_STARTS falls outside file<br />
0x176d9000-0x17731000 __TEXT (360448 bytes)<br />
0x2ccc2070-0x2ccd54a8 __DATA_CONST (78904 bytes)<br />
0x30571f60-0x30575f60 __DATA (16384 bytes)<br />
0x314c9a28-0x314ca000 __DATA_DIRTY (1496 bytes)<br />
0x316b3000-0x37064000 __LINKEDIT (94048256 bytes)<br />
0x31e3c4d0-0x31e3eaf8 Exports (9768 bytes)<br />
0x34689f18-0x346912f8 Symbol Table (29664 bytes)<br />
0x35a46500-0x35a46b90 Function Starts (1680 bytes)<br />
0x35bb1930-0x35bb1960 Data In Code (48 bytes)<br />
0x35d66710-0x37029aba String Table (19674026 bytes)<br />
LC_DYLD_INFO...<br />
</source><br />
<br />
== Class dumping ==<br />
<br />
See [[Reverse_Engineering_Tools#class-dump.2C_class_dump_z.2C_classdump-dyld|this section of Reverse Engineering Tools]].<br />
<br />
== External Links ==<br />
<br />
* [http://blog.howett.net/?p=75 Cache or Check?] — an analysis of the dyld_shared_cache system by D. Howett.<br />
* [https://github.com/deepinstinct/dsc_fix dsc_fix] — an IDA script that aids in reverse engineering dyld_shared_cache libraries</div>PoomSmarthttps://iphonedev.wiki/index.php?title=SBApplication&diff=5701SBApplication2021-06-05T05:15:41Z<p>PoomSmart: SBApplicationClassicMode enums</p>
<hr />
<div>[[SBApplication]] is a class that represents individual applications. It contains anything you could possibly want to know about the application it represents. <br />
<br />
== Fetching SBApplications ==<br />
[[SBApplicationController]] holds all known instances of SBApplication. There will usually just be a single instance per currently-running application. An instance can be retrieved using the wanted-application's bundle identifier.<br />
<source lang="objc"><br />
//iOS 7-<br />
SBApplication* app = [[SBApplicationController sharedInstance] applicationWithDisplayIdentifier:@"com.yourcompany.appname"];<br />
<br />
// iOS 8+<br />
SBApplication* app = [[SBApplicationController sharedInstance] applicationWithBundleIdentifier:@"com.yourcompany.appname"];<br />
</source><br />
<br />
== Fetching Frontmost App's SBApplication Instance ==<br />
This method will return the frontmost application's SBApplication instance. If no app is currently running <code>nil</code> will be returned. Internally it queries [[SBSceneManagerCoordinator]] to retrieve the application (if any) that is fulfilling the primary layout role.<br />
<source lang="objc"><br />
[[SpringBoard sharedApplication] _accessibilityFrontMostApplication];<br />
</source><br />
<br />
== Fetching All Instances ==<br />
[[SBApplicationController]] can provide an array containing all known instances of SBApplication. <br />
<source lang="objc"><br />
[[SBApplicationController sharedInstanceIfExists] runningApplications];<br />
</source><br />
<br />
== Fetch "Now Playing" App ==<br />
<source lang="objc"><br />
SBApplication *nowPlayingApp = [[SBMediaController sharedInstance] nowPlayingApplication];<br />
</source><br />
<br />
== Launching an SBApplication ==<br />
[[SBUIController]] can be used to launch an SBApplication.<br />
<source lang="objc"><br />
SBApplication *appToLaunch = [[SBApplicationController sharedInstanceIfExists] runningApplications][0];<br />
[[SBUIController sharedInstanceIfExists] activateApplication:appToLaunch];<br />
</source><br />
<br />
== Classic Mode ==<br />
<br />
Here are the constants that represent application classic mode depending on the screen type, retrieved from reversing <code>SBApplicationClassicModeDescription(NSInteger)</code> or <code>SBApplicationClassicModeForString(NSString *)</code> from [[SpringBoard.framework]].<br />
<br />
<source lang="objc"><br />
<br />
// The number suffix, if present, represents the diagonal size of the screen, in inches<br />
typedef NS_EMUM(NSInteger, SBApplicationClassicMode) {<br />
SBApplicationClassicModeNone = 0,<br />
SBApplicationClassicModePhone = 1,<br />
SBApplicationClassicModePhone4 = 2,<br />
SBApplicationClassicModePhone4_7 = 3,<br />
SBApplicationClassicModePhone5_5 = 4,<br />
SBApplicationClassicModePhone5_8_Zoomed = 5, // rounded<br />
SBApplicationClassicModePhone5_8 = 6, // rounded<br />
SBApplicationClassicModePhone6_1 = 7, // rounded<br />
SBApplicationClassicModePhone6_5 = 8, // rounded<br />
SBApplicationClassicModePhone6_7 = 9, // rounded<br />
SBApplicationClassicModePad = 10,<br />
SBApplicationClassicModePad_10_5 = 11,<br />
SBApplicationClassicModePad_12_9 = 12,<br />
SBApplicationClassicModePad_11 = 13 // rounded<br />
};<br />
<br />
</source><br />
<br />
To disable launch animations simply apply the correct activation setting before calling <code>-activateApplication:</code>.<br />
<source lang="objc"><br />
[appToLaunch setFlag:1 forActivationSetting:1]; // flag 1 = ON, Activation Setting 1 = @"noAnimate"<br />
</source><br />
<br />
'''Notes:'''<br />
* This method will not respect parental control. However, you can determine if an SBApplication is restricted (parental locked) by using [[SBApplicationRestrictionController]], which [[SBApplicationController]] holds an instance of. <br />
<source lang="objc"><br />
SBApplication *appToCheck = [[SBApplicationController sharedInstanceIfExists] runningApplications][0];<br />
BOOL appIsRestricted = [[[SBApplicationController sharedInstanceIfExists] restrictionController] isApplicationIdentifierRestricted:[appToCheck bundleIdentifier]];<br />
</source><br />
<br />
'''Other Known Activation Flags'''<br />
<br />
{| class="activationflags"<br />
|-<br />
! Flag || Setting<br />
|-<br />
| 1 || Launch without animations. <br />
|-<br />
| 8 || Force launch animation to use app's context view instead of a snapshot. <br />
|-<br />
| 11 || Delay launch animation.<br />
|-<br />
| 43 || Set the app as the "Now Playing" application. <br />
|}<br />
<br />
== Useful Methods == <br />
These are a few of the useful items in SBApplication. <br />
<source lang="objc"><br />
<br />
//the apps bundle id<br />
- (NSString *)bundleIdentifier; <br />
<br />
//is it SpringBoard's instance<br />
- (BOOL)isSpringBoard; <br />
<br />
//app location info<br />
- (NSString *)path;<br />
- (NSString *)dataContainerPath;<br />
- (NSString *)bundleContainerPath;<br />
- (NSString *)bundleVersion;<br />
- (NSString *)sandboxPath; <br />
<br />
//general info<br />
- (BOOL)isSetup;<br />
- (BOOL)isMobilePhone;<br />
- (BOOL)isFaceTime;<br />
- (BOOL)behavesLikePhone;<br />
- (BOOL)isWebApplication;<br />
- (BOOL)isWatchApplication;<br />
- (BOOL)isNowPlayingApplication;<br />
- (BOOL)isNowRecordingApplication;<br />
- (BOOL)showsProgress;<br />
- (BOOL)isRecordingAudio;<br />
- (BOOL)isRunning;<br />
- (BOOL)hasStartedLaunching;<br />
<br />
//the string displayed under the icon<br />
- (NSString *)displayName;<br />
<br />
//has it been launched at some point in SpringBoard's life<br />
- (BOOL)hasBeenFrontmost;<br />
<br />
//badge number<br />
- (id)badgeNumberOrString;<br />
<br />
//returns the app's FBScene instance, useful for doing context host view stuff<br />
- (FBScene *)mainScene;<br />
<br />
</source><br />
<br />
== Application Info.plist ==<br />
<br />
SpringBoard will recognize the following Info.plist keys:<br />
<br />
* UISystemProvisioning<br />
* SBDemoRole<ref name="hunt">http://blogs.oreilly.com/iphone/2008/11/hunting-down-infoplist-prefere.html</ref><br />
* SBIsRevealable<ref name="hunt"/><ref>http://www.tuaw.com/2007/11/29/enable-app-hiding-on-your-iphone/</ref><br />
* SBUsesNetwork<ref>http://stackoverflow.com/questions/596589/iphone-sdk-internet-connection-detection</ref><br />
* UIJetsamPriority<br />
* SBIconClass<br />
* SBSpotlightIcons<br />
* UIRoles<br />
* SBMachServices<br />
* disabled<br />
* CFBundleIconFile<br />
* SPSearchDomainLaunchInfo<br />
* SBAppTags<ref>http://www.ifans.com/forums/threads/what-keeps-these-hidden.331215/#post-2552445</ref><ref>http://www.ifans.com/forums/threads/hide-applications.76176/#post-717439</ref><br />
* Other UIKit keys described in http://developer.apple.com/IPhone/library/documentation/General/Reference/InfoPlistKeyReference/Articles/iPhoneOSKeys.html<br />
<br />
Starting from 3.2 these ''documented'' keys are also recognized:<br />
<br />
* ProductType, UIDeviceFamily, DeviceFamily<ref>The keys ProductType and DeviceFamily are private but equivalent to UIDeviceFamily.</ref><br />
* UIAppFonts<br />
* UIFileSharingEnabled<br />
* UISupportedInterfaceOrientations<br />
<br />
As of iOS 8, the following undocumented key is also recognized:<br />
<br />
* _UILaunchAlwaysFullScreen<ref>http://pastebin.com/XmRqevnD</ref><br />
<br />
== References ==<br />
<references /><br />
* Header: https://github.com/theos/headers/blob/master/SpringBoard/SBApplication.h<br />
<br />
{{occlass|library=SpringBoard.app|navbox=1}}</div>PoomSmarthttps://iphonedev.wiki/index.php?title=Best_Practices&diff=5692Best Practices2021-05-28T15:38:45Z<p>PoomSmart: /* Applications and Tweaks */</p>
<hr />
<div>Use the following guidelines to avoid your package or app being fragile and to increase the chances of it being accepted by a community host.<br />
<br />
== Applications and Tweaks ==<br />
* <code>NSHomeDirectory()</code> doesn't guarantee that it will return <code>/var/mobile</code>, especially from within sandboxed processes.<br />
** If your code is running as root, use extra caution when writing files that mobile can access - you might break the file's access permissions.<br />
** App Store apps will return their sandbox data path from <code>NSHomeDirectory()</code>.<br />
* See [[MobileSubstrate Pitfalls]] for additional guidelines regarding tweaks.<br />
* You should consider the UDID deprecated like Apple has for some time, but if you need the device's UDID, use [[libMobileGestalt.dylib]].<br />
* If you need to use singletons, see [[singleton pattern]] for advice.<br />
* If you need to respring from a tweak and you are targeting iOS 6 - 7, kill backboardd instead of SpringBoard. Killing SpringBoard has been known to cause some issues regarding the backlight. For iOS 8 and newer, if possible, use <code>-[HBRespringController respring]</code> from [https://github.com/hbang/libcephei/blob/master/HBRespringController.x libcephei] for a more appropriate way to respring. Simply killing the processes can destroy battery usage data (the feature since iOS 8).</div>PoomSmarthttps://iphonedev.wiki/index.php?title=Cydia_Substrate_Pitfalls&diff=5691Cydia Substrate Pitfalls2021-05-28T15:35:45Z<p>PoomSmart: /* MobileSubstrate APIs and states */</p>
<hr />
<div>Follow the following guidelines to avoid common [[MobileSubstrate]] mistakes. See also: [[Best Practices]].<br />
<br />
== Coding practices ==<br />
<br />
* Never use <code>[[UIDevice]]</code> in your constructor if you are hooking SpringBoard!<br />
* Access ivars through their associated properties, where practical.<br />
* Always call the old implementation of a method unless you require suppressing the default behavior. Similarly, only call the old implementation of a method from within the method hook.<br />
* Use documented/public SDK features wherever practical. Apple usually tests private APIs internally before making them public; often the public version is the same or similar to the private version that was in previous OS releases.<br />
* Avoid <code>[[UIAlertView]]</code> in SpringBoard--it doesn't participate in the SpringBoard-wide alert system; use a custom <code>SBAlertItem</code> subclass instead (not necessary for cases where you don't care if the system destroys your alert.)<br />
* Use <code>-autoresizingMask</code> and <code>-layoutSubviews</code> to make your extension resolution-independent and rotation-aware. However, if there are any modern APIs from Apple doing the same, consider using that. <code>-layoutSubviews</code> can be invoked too many times and the performance may be reduced.<br />
* Avoid doing extra work--the methods your extension hooks may be called from inside a tight loop; disk access is considered a LOT of extra work (related: properties are actually method calls, they can be slow.)<br />
* <code>UI*</code> methods must be performed on the main thread (this includes <code>[[UIImage]]</code>! use <code>CGImageSource</code> and company if you need to load images from a background thread.)<br />
* Never block the main thread! Performing any operation that can take significant time on the main thread is evil (that includes '''any''' operation that hits the network.)<br />
* Access resources through <code>NSBundle</code> so that they may be themed via WinterBoard.<br />
* Don't make assumptions about the ivar layout of a class; these can and will change across firmware versions.<br />
* If accessing low-level graphics hardware, beware that first-generation devices do _not_ have a unified memory model (VRAM and regular RAM are separate regions.)<br />
* Participate in the memory warning system if your extension has a significant memory footprint; release everything you can.<br />
* Use <code>mmap()</code> when working with large datasets--the kernel will swap it in and out of memory as necessary (but avoid heavy writes, as that's no better than virtual memory.)<br />
* Compile against the earliest possible firmware you can (compile against 3.0, not 3.0.1, 3.1 or 3.1.2); use feature detection if necessary.<br />
* Strip symbols if you have something to hide; use standard C (or C++) for the hidden parts--Objective-C will spill your details.<br />
* Many private frameworks have public headers available for Mac OS X; use them (also, there are header packs floating around--kennytm's is one of the best and is legal to distribute.)<br />
* Only link to the frameworks you actually need--importing unnecessary frameworks will increase app launch time (use dlopen/dlsym to load libraries and access symbols at runtime after the app has launched)<br />
** This is less of a concern on 3.1+, due to the [[dyld_shared_cache|dyld shared object cache]]. You still incur the overhead of library initializers, however.<br />
* Use a private prefix on classes and category methods: Objective-C has NO namespacing capabilities. (examples: two classes called Preferences that behave differently; two extensions define a <code>-[NSData base64String]</code> that behave slightly differently.)<br />
* Avoid waking the device or keeping the device from sleeping. If your extension needs to do something periodically, hook the Mail application's sync and integrate the action within that (scheduler/alarm extensions need not heed this warning.)<br />
* Avoid CPU-/GPU-/disk-intensive activity where the user would not expect it (battery life!)<br />
* Don't overuse <code>NSLog(), CFLog(), fprintf(stderr, …);</code> they're slow and synchronous.<br />
* If your extension exposes an icon, include both the 29x29, 59x60, and 90x90 icon sizes. 60x and 90x files can be suffixed with <code>@2x</code> or <code>@3x</code> (e.g. <code>image@2x.png</code>), and iOS will handle loading images for higher pixel ratios. Devices newer than the 3GS typically have a ratio of at least 2x, so these should typically be included. <br />
* Avoid changing the class of objects returned by public APIs--some App Store applications perform unnecessary checks against the class of an object and will fail.<br />
* Prefer binary plists over XML--they're much quicker (OpenSTEP-style text plists are also quick, but seem to be deprecated)<br />
* Manage memory correctly as per the Cocoa memory management guidelines; ensure all hooks comply as well.<br />
* Be aware that <code>-[NSBundle bundleIdentifier]</code> may return <code>nil</code> if it's invoked within an arbitrary process that does not belong to any specific bundle. When it's used with certain other methods that expect the non-null value, it can indefinitely crash the process. In some cases, it will drain the battery because the process will keep restarting. This is some [https://github.com/pr0crustes/SmoothTable/issues/2 bad example].<br />
* Respect the user's privacy.<br />
** The IMEI, telephone number, contacts list and email inbox are definitely private information.<br />
** The MAC address, Bluetooth address and UDID may be considered private information, depending on the jurisdiction.<br />
<br />
== Data management ==<br />
<br />
* Store preferences in /var/mobile/Library/Preferences to have iTunes back it up.<br />
* Store data in /var/mobile/Library/AddressBook or /var/mobile/Library/Keyboard to avoid the sandbox restrictions, if necessary.<br />
<br />
== MobileSubstrate APIs and states ==<br />
<br />
* Always include a [[MobileSubstrate#MobileLoader|MobileLoader]] filter plist.<br />
** If you require access to only SpringBoard, use "com.apple.springboard"; if you require access to all UIKit apps, use "com.apple.UIKit". However, read the next bullet.<br />
** If you hook a framework like "com.apple.UIKit", test your tweak in non-UIKit processes anyway (e.g. by temporarily changing the filter to "com.apple.Security" or "com.apple.CoreFoundation"). Broken tweaks with incorrect/missing filters will pull your tweak into processes you don't expect. Even the recent versions of Cydia Substrate reject the tweaks without the filter file, tweaks targeting UIKit can still run in such processes you don't expect. However, there is a way to prevent unwanted code injection to non-UIKit processes. For more filtering options (for example, injection into keyboard extensions), see [https://github.com/PoomSmart/EmojiPort-PE/blob/master/Tweak.x here]. The full macros are available [https://github.com/PoomSmart/PSHeader/blob/master/PS.h here].<br />
* Don't modify OS or Cydia files; use runtime-replacement instead.<br />
* [[Preferences.framework]] changed drastically between 3.1 and 3.2. Use [[PreferenceLoader]] and standard preferences plists for simple panes, [[PSViewController]] + [[UITableView]] for more complex panes ([[PSListController]] is okay for simple preferences, but is less subject to OS changes; PSViewController is more powerful, but many implementations were broken between 3.1 and 3.2). However, PSViewController + UITableView combination results in lost of side margins on iPad settings page on recent iOS versions.<br />
* If your extension exposes an API, document it!<br />
** Include headers '''inside''' your package so they're easy to find.<br />
* Use an established hooking framework such as substrate.h, CaptainHook.h or [[Logos]]; there is little benefit in rolling your own, and too many details have to be just right.<br />
* Never inhibit MobileSubstrate's [[MobileSubstrate#Safe_mode|safe mode]].<br />
* If your extension manipulates icon layouts, use [[IconSupport]] so you don't stomp all over other extensions' modifications or the stock/safe-mode layout.<br />
* Expect others to hook the same methods you do; expect them not to have read this list and to have done crazy things.<br />
* Prefer hooking methods over hooking functions--new jailbreaks don't always have kernel patches (although this is not as much of a concern, as jailbreakers understand the need for W^X) and MobileSubstrate may not support newer ARM instructions.<br />
* Use [http://www.cydiasubstrate.com/api/c/MSHookMessageEx/ MSHookMessageEx] instead of [http://www.cydiasubstrate.com/api/c/MSHookMessage/ MSHookMessage].<br />
** MSHookMessage allows you to specify an optional prefix which gets added to the original method, polluting the class.<br />
<br />
== Packaging ==<br />
<br />
* Include the proper Depends: line in your Debian control file (that way Cydia will automatically install dependencies and will alert users when they are missing required components like firmware version.)<br />
* Ensure your extension is localizable; use the standard .lproj system where possible. Avoid having images that include text.</div>PoomSmarthttps://iphonedev.wiki/index.php?title=RocketBootstrap&diff=5690RocketBootstrap2021-05-28T15:24:27Z<p>PoomSmart: </p>
<hr />
<div>{{Infobox Package<br />
|developer=[[User:Rpetrich|Ryan Petrich]]<br />
|version=1.0.10~beta1<br />
|package=com.rpetrich.rocketbootstrap<br />
}}<br />
<br />
'''RocketBootstrap''' is a library that solves a denied lookup error of [[IPC]] services on iOS 7 and above<ref>[http://iphonedevwiki.net/index.php/Updating_extensions_for_iOS_7#Inter-process_communication Updating extensions for iOS 7 - Inter-process communication]</ref>.<br />
<br />
''"One common way processes communicate with each other on iOS and OS X is through a messaging system called mach ports. Each port is a channel that can either receive or send messages. There is a central registration system for these ports called bootstrap, where ports can be registered and accessed by a service name assigned to them. Recent versions of iOS restrict which names a process can access—MobileMail, MobileSafari and App Store apps are only allowed to access a very specific set of services that come with iOS. RocketBootstrap adds a secondary lookup service that doesn't restrict which processes can access which services."'' <ref>[https://www.reddit.com/r/jailbreak/comments/1tv0qw/activator_182_rc1_released_with_rocketbootstrap/cebqh9p rpetrich's reddit post for RocketBootstrap's release]</ref><br />
<br />
== How to use this library ==<br />
<br />
Headers are available from [https://github.com/rpetrich/RocketBootstrap/tree/master RocketBootstrap's GitHub project] and the library can be found at <code>/usr/lib/librocketbootstrap.dylib</code> on a device where RocketBootstrap is installed. If using Theos, place the headers in <code>$THEOS/include/RocketBootstrap</code>, the library in <code>$THEOS/lib/</code>.<br />
<br />
=== Include directive ===<br />
<br />
<source lang="objc"><br />
#import <rocketbootstrap/rocketbootstrap.h><br />
</source><br />
<br />
=== Makefile ===<br />
<br />
Add to your Makefile:<br />
<br />
* <code>rocketbootstrap</code> to the <code>XXX_LIBRARIES</code> variable.<br />
* <code>AppSupport</code> to the <code>XXX_PRIVATE_FRAMEWORKS</code> variable.<br />
<br />
=== Packaging ===<br />
<br />
Add to your package's control file:<br />
<br />
* <code>, com.rpetrich.rocketbootstrap (>= 1.0.2) | firmware (<< 7.0)</code> to the <code>Depends</code> field.<br />
<br />
== LightMessaging example ==<br />
<br />
See [[LightMessaging]].<br />
<br />
== CPDistributedMessagingCenter Example ==<br />
<br />
Make sure you have the <tt>CPDistributedMessagingCenter</tt> interface declared.<br />
<br />
=== Server inside a SpringBoard tweak ===<br />
<br />
<source lang="objc"><br />
@interface MYMessagingCenter : NSObject {<br />
CPDistributedMessagingCenter * _messagingCenter;<br />
}<br />
@end<br />
<br />
@implementation MYMessagingCenter<br />
<br />
+ (void)load {<br />
[self sharedInstance];<br />
}<br />
<br />
+ (instancetype)sharedInstance {<br />
static dispatch_once_t once = 0;<br />
__strong static id sharedInstance = nil;<br />
dispatch_once(&once, ^{<br />
sharedInstance = [self new];<br />
});<br />
return sharedInstance;<br />
}<br />
<br />
- (instancetype)init {<br />
if ((self = [super init])) {<br />
_messagingCenter = [CPDistributedMessagingCenter centerNamed:@"com.mycompany.myCenter"];<br />
// apply rocketbootstrap regardless of iOS version (via rpetrich)<br />
rocketbootstrap_distributedmessagingcenter_apply(_messagingCenter);<br />
<br />
[_messagingCenter runServerOnCurrentThread];<br />
[_messagingCenter registerForMessageName:@"myMessageName" target:self selector:@selector(handleMessageNamed:withUserInfo:)];<br />
}<br />
<br />
return self;<br />
}<br />
<br />
- (NSDictionary *)handleMessageNamed:(NSString *)name withUserInfo:(NSDictionary *)userInfo {<br />
return [NSDictionary dictionaryWithObjectsAndKeys:@"key", @"object", nil];<br />
}<br />
<br />
@end<br />
</source><br />
<br />
=== Client from sandboxed app ===<br />
<br />
<source lang="objc"><br />
static CPDistributedMessagingCenter *c = nil;<br />
<br />
%ctor {<br />
c = [CPDistributedMessagingCenter centerNamed:@"com.mycompany.myCenter"];<br />
rocketbootstrap_distributedmessagingcenter_apply(c);<br />
<br />
// Send a message with no dictionary<br />
[c sendMessageName:@"myMessageName" userInfo:nil];<br />
<br />
// Send a message with a dictionary<br />
NSDictionary * message = [NSDictionary dictionaryWithObjectsAndKeys: @"key", @"object", nil];<br />
[c sendMessageName:@"myMessageName" userInfo:message];<br />
<br />
// Send a message with no dictionary and receive a reply dictionary<br />
NSDictionary * reply = [c sendMessageAndReceiveReplyName:@"myMessageName" userInfo:nil];<br />
<br />
// Send a message with a dictionary and receive a reply dictionary<br />
NSDictionary * replyWithMessage = [c sendMessageAndReceiveReplyName:@"myMessageName" userInfo:message];<br />
}<br />
</source><br />
<br />
== CFMessagePort Example ==<br />
<br />
(Pilfered from [http://nshipster.com/inter-process-communication/ the NSHipster article on IPC])<br />
<br />
=== Server ===<br />
<br />
<source lang="objc"><br />
static CFDataRef Callback(CFMessagePortRef port,<br />
SInt32 messageID,<br />
CFDataRef data,<br />
void *info)<br />
{<br />
// ...<br />
}<br />
<br />
%ctor {<br />
static CFMessagePortRef localPort =<br />
CFMessagePortCreateLocal(nil,<br />
CFSTR("com.example.app.port.server"),<br />
Callback,<br />
nil,<br />
nil);<br />
<br />
CFRunLoopSourceRef runLoopSource =<br />
CFMessagePortCreateRunLoopSource(nil, localPort, 0);<br />
<br />
CFRunLoopAddSource(CFRunLoopGetCurrent(),<br />
runLoopSource,<br />
kCFRunLoopCommonModes);<br />
<br />
rocketbootstrap_cfmessageportexposelocal(localPort);<br />
}<br />
</source><br />
<br />
=== Client ===<br />
<br />
<source lang="objc"><br />
void doStuff() {<br />
CFDataRef data;<br />
SInt32 messageID = 0x1111; // Arbitrary<br />
CFTimeInterval timeout = 10.0;<br />
<br />
CFMessagePortRef remotePort =<br />
rocketbootstrap_cfmessageportcreateremote(nil,<br />
CFSTR("com.example.app.port.client"));<br />
<br />
SInt32 status =<br />
CFMessagePortSendRequest(remotePort,<br />
messageID,<br />
data,<br />
timeout,<br />
timeout,<br />
NULL,<br />
NULL);<br />
<br />
if (status == kCFMessagePortSuccess) {<br />
// ...<br />
}<br />
}<br />
</source><br />
<br />
== Usage notes ==<br />
<br />
If you want to run a server inside a daemon, then you still need a simple SpringBoard tweak, that just has to call <code>rocketbootstrap_unlock</code> with the service name. Then you can run a server with the same name inside your daemon.<br />
<br />
You shouldn't be registering Mach services in sandboxed apps; RocketBootstrap allows exposing services ''to'' sandboxed apps, but can't allow exposing services ''from'' sandboxed apps without exposing a very large security flaw.<br />
<br />
Assuming there aren't any security problems, actually calling a service that's running inside of an app from SpringBoard (which is usually what people want to do) is problematic. Backgrounding apps causes them to enter a frozen "SIGSTOP" state, which means any calls to the service running inside of the app will block indefinitely.<br />
<br />
Even if that is suppressed, it could happen that the SpringBoard part attempts to call the service running in the app at the same time as the app is trying to call any of the usual SpringBoard services. When that happens, they deadlock. This might happen infrequently, but it's a really bad failure case in that the system just hangs. Real users will encounter it, if it's present.<br />
<br />
You can call from a background thread (not good, it could stay alive for a long time), or use timeouts (not good, now you have to tune it and you get UI hitches) or use asynchronous code (not bad, but it's more work than you may be willing to go through).<br />
<br />
== See also ==<br />
<br />
* [[IPC]]<br />
* [[libobjcipc]]<br />
<br />
== References ==<br />
<references /><br />
<br />
== External links ==<br />
<br />
* [https://github.com/rpetrich/RocketBootstrap RocketBootstrap on GitHub]<br />
<br />
{{Navbox Library}}<br />
<br />
[[Category:Cydia packages]]<br />
<br />
[[Category:Directories in /Library]]</div>PoomSmarthttps://iphonedev.wiki/index.php?title=Template:CoreFoundation_Version_Table&diff=5689Template:CoreFoundation Version Table2021-05-28T15:22:59Z<p>PoomSmart: </p>
<hr />
<div>{| class="wikitable sortable"<br />
|-<br />
! Firmware !! CoreFoundation version<br />
|-<br />
| 2.0 || 478.23<br />
|-<br />
| 2.1 || 478.26.1<br />
|-<br />
| 2.2 || 478.29<br />
|-<br />
| 3.0 || 478.47.7<br />
|-<br />
| 3.1 || 478.52<br />
|-<br />
| 3.2 || 478.61<br />
|-<br />
| 4.0 || 550.32<br />
|-<br />
| 4.1 || 550.38.1<br />
|-<br />
| 4.2 || 550.52 <br />
|-<br />
| 4.3 || 550.58.1<br />
|-<br />
| 5.0 || 675.00 <br />
|-<br />
| 5.1 || 690.10<br />
|-<br />
| 6.0 || 793.00<br />
|-<br />
| 6.1 || 793.00<br />
|-<br />
| 7.0 || 847.20<br />
|-<br />
| 7.1 || 847.24<br />
|-<br />
| 8.0 || 1140.10<br />
|-<br />
| 8.1 || 1141.14<br />
|-<br />
| 8.2 || 1142.16<br />
|-<br />
| 8.3 || 1144.17<br />
|-<br />
| 8.4 || 1145.15<br />
|-<br />
| 9.0 || 1240.10<br />
|-<br />
| 9.1 || 1241.11<br />
|-<br />
| 9.2 || 1242.13<br />
|-<br />
| 9.3 || 1280.38<br />
|-<br />
| 10.0 || 1348.00<br />
|-<br />
| 10.1 || 1348.00<br />
|-<br />
| 10.2 || 1348.22<br />
|-<br />
| 10.3 || 1349.56 <br />
|-<br />
| 11.0 || 1443.00 <br />
|-<br />
| 11.1 || 1445.32 <br />
|-<br />
| 11.2 || 1450.14<br />
|-<br />
| 11.3 || 1452.23<br />
|-<br />
| 11.4 || 1452.23<br />
|-<br />
| 12.0 || 1556.00<br />
|-<br />
| 12.1 || 1560.10<br />
|-<br />
| 12.2 || 1570.15<br />
|-<br />
| 12.3 || 1575.13<br />
|-<br />
| 12.4 || 1575.17<br />
|-<br />
| 12.5 || 1575.23<br />
|-<br />
| 13.0 || 1665.15<br />
|-<br />
| 13.1 || 1671.101<br />
|-<br />
| 13.2 || 1673.126<br />
|-<br />
| 13.3 || 1674.102<br />
|-<br />
| 13.4 || 1675.129<br />
|-<br />
| 13.5 || 1676.104<br />
|-<br />
| 13.6 || 1677.104<br />
|-<br />
| 13.7 || 1677.104<br />
|-<br />
| 14.0 || 1751.108<br />
|-<br />
| 14.1 || 1751.108<br />
|-<br />
| 14.2 || 1770.106<br />
|-<br />
| 14.3 || 1770.300<br />
|-<br />
| 14.4 || 1774.101<br />
|-<br />
| 14.5 || 1775.118<br />
|-<br />
|}</div>PoomSmarthttps://iphonedev.wiki/index.php?title=PreferenceLoader&diff=5688PreferenceLoader2021-05-28T15:20:30Z<p>PoomSmart: </p>
<hr />
<div>{{Infobox Package<br />
|screenshot=PrefLoaderScreenshot.png<br />
|developer=[[User:Dustin Howett|Dustin Howett]]<br />
|version=2.2.6<br />
|package=preferenceloader<br />
}}<br />
<br />
'''PreferenceLoader''' is an open-source<ref>[http://github.com/DHowett/preferenceloader PreferenceLoader Source]</ref> [[MobileSubstrate]] based utility that allows developers to add entries to the [[Preferences.app|Settings]] application, similar to the Settings bundles that AppStore apps use.<br />
<br />
The approach PreferenceLoader takes is different from other approaches in that the Settings-iPhone.plist and Settings-iPod.plist files are not modified on disk. When the [[Preferences.app|Settings]] application is loaded, entries are read from plists in <tt>/Library/PreferenceLoader/Preferences/</tt> and are dynamically added to the list before the AppStore applications' preferences group.<br />
<br />
PreferenceLoader also allows [[PreferenceBundles]] to be loaded from <tt>/Library/PreferenceBundles/</tt><ref name="1.2">PreferenceLoader version 1.2 and later</ref><ref>Bundles can also be loaded from /System/Library/PreferenceBundles/, but this is no longer the preferred method as of PreferenceLoader 1.2</ref>.<br />
<br />
== Entry file ==<br />
<br />
{{main|Preferences specifier plist}}<br />
<br />
Each entry is defined in its own plist. There are at least three ways to approach preferences support for your tweaks.<br />
<br />
=== Reduced approach ===<br />
<br />
Provides a switch on the root section of the preferences (like Airplane Mode). Recommended for configuration-less tweaks.<br />
<br />
<source lang="xml"><br />
<?xml version="1.0" encoding="UTF-8"?><br />
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><br />
<plist version="1.0"><br />
<dict><br />
<key>entry</key><br />
<dict><br />
<key>cell</key><br />
<string>PSSwitchCell</string><br />
<key>defaults</key><br />
<string>com.test.TestSettings</string><br />
<key>label</key><br />
<string>Test</string><br />
<key>key</key><br />
<string>enabled</string><br />
<key>default</key><br />
<true/><br />
<key>icon</key><br />
<string>TestIcon.png</string><br />
<key>PostNotification</key><br />
<string>com.test.TestSettings/preferences.changed</string><br />
</dict><br />
</dict><br />
</plist><br />
</source><br />
<br />
This sets up an entry called <code>Test</code> with an icon loaded from <code>TestIcon.png</code> to the left and a UISwitch on the right, starting in the ON position, saving the value in <code>[NSHomeDirectory() stringByAppendingFormat:@"/Library/Preferences/%s.plist", "com.test.TestSettings"]</code> for the key <tt>enabled</tt> and posting a Darwin notification named <code>com.test.TestSettings/preferences.changed</code>.<br />
<br />
=== Simple Approach ===<br />
<br />
Provides a pane where other cells can appear (like Wi-Fi). Recommended for configuration-friendly tweaks. Here's an example:<br />
<br />
<source lang="xml"><br />
<?xml version="1.0" encoding="UTF-8"?><br />
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><br />
<plist version="1.0"><br />
<dict><br />
<key>entry</key><br />
<dict><br />
<key>cell</key><br />
<string>PSLinkCell</string><br />
<key>icon</key><br />
<string>TestIcon.png</string><br />
<key>label</key><br />
<string>Test</string><br />
</dict><br />
<key>title</key><br />
<string>Test Settings</string><br />
<key>items</key><br />
<array><br />
<dict><br />
<key>cell</key><br />
<string>PSSwitchCell</string><br />
<key>defaults</key><br />
<string>com.test.TestSettings</string><br />
<key>key</key><br />
<string>enabled</string><br />
<key>label</key><br />
<string>Enabled</string><br />
<key>default</key><br />
<true/><br />
<key>PostNotification</key><br />
<string>com.test.TestSettings/preferences.changed</string><br />
</dict><br />
</array><br />
</dict><br />
</plist><br />
</source><br />
<br />
This sets up an entry called <code>Test</code> with an icon loaded from <code>TestIcon.png</code> to the left. The pushed page has the title set to <tt>Test Settings</tt>. The page will only contain a cell with the label <tt>Enabled</tt> UISwitch on the right, starting in the ON position, saving the value in <code>[NSHomeDirectory() stringByAppendingFormat:@"/Library/Preferences/%s.plist", "com.test.TestSettings"]</code> for the key <tt>enabled</tt> and posting a Darwin notification named <code>com.test.TestSettings/preferences.changed</code>.<br />
<br />
For more preferences values you can add [[Preferences_specifier_plist|specifier]] dictionaries to the <tt>items</tt> array.<br />
<br />
There is a good tutorial on [http://modmyi.com/forums/file-mods/22453-how-make-custom-menus-preferences-app-custom-preferences.html how to create settings plists on MMi].<br />
<br />
=== PreferenceBundle Approach ===<br />
<br />
You can create custom settings pages that are able to execute code. This only requires a plist that loads a [[PreferenceBundles|PreferenceBundle]]. Here's an example:<br />
<br />
<source lang="xml"><br />
<?xml version="1.0" encoding="UTF-8"?><br />
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><br />
<plist version="1.0"><br />
<dict><br />
<key>entry</key><br />
<dict><br />
<key>cell</key><br />
<string>PSLinkCell</string><br />
<key>label</key><br />
<string>Test</string><br />
<key>icon</key><br />
<string>TestIcon.png</string><br />
<key>isController</key><br />
<true/><br />
<key>bundle</key><br />
<string>TestSettings</string><br />
</dict><br />
</dict><br />
</plist><br />
</source><br />
<br />
This sets up an entry called <code>Test</code> with an icon loaded from <code>TestIcon.png</code> to the left. The rest of the details are up to the bundle named <tt>TestSettings</tt>.<br />
<br />
== Filtering<ref name="2.2.0-1">PreferenceLoader version 2.2.0-1 and later</ref> ==<br />
<br />
In a way similar to that of [[MobileSubstrate#MobileLoader|MobileSubstrate]], PreferenceLoader supports filters for entry plists and specifiers. The filter should be a dictionary for the key <tt>pl_filter</tt> which can contain these keys:<br />
<br />
* '''CoreFoundationVersion''' (array): The entry or specifier is loaded or displayed only if the version of [[CoreFoundation.framework]] is above the specified value or within the specified range. Currently, only the first 2 values are checked.<br />
{{CoreFoundation Version Table|center=1}}<br />
<br />
Below sample specifier will filter for iOS 6.0 or later.<br />
{|<br />
|- valign="top"<br />
|<br />
{{Collapse|1=<source lang="javascript">{<br />
cell = PSSwitchCell;<br />
defaults = "com.your.tweak";<br />
label = "Your Tweak";<br />
key = enabled;<br />
default = 1;<br />
icon = "/Applications/Preferences.app/icon-table@2x.png";<br />
PostNotification = "com.your.tweak/preferences.changed";<br />
pl_filter = {<br />
CoreFoundationVersion = (<br />
"793.00"<br />
);<br />
};<br />
}<br />
</source>|2=NeXTSTEP style}}<br />
||<br />
{{Collapse|1=<source lang="xml"><br />
<?xml version="1.0" encoding="UTF-8"?><br />
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><br />
<plist version="1.0"><br />
<dict><br />
<key>cell</key><br />
<string>PSSwitchCell</string><br />
<key>defaults</key><br />
<string>com.test.TestSettings</string><br />
<key>label</key><br />
<string>Test Setting</string><br />
<key>key</key><br />
<string>testKey</string><br />
<key>default</key><br />
<true/><br />
<key>pl_filter</key><br />
<dict><br />
<key>CoreFoundationVersion</key><br />
<array><br />
<string>793.00</string><br />
</array><br />
</dict><br />
</plist><br />
</source>|2=XML style}}<br />
|}<br />
<br />
To provide a range specify the lower bound first (checked as "greater or equal than") and the upper bound second (checked as "less than").<br />
The filter below will filter for iOS 4.X. <br />
{|<br />
|- valign="top"<br />
| NeXTSTEP style || XML style<br />
|-<br />
|<br />
<source lang="javascript">{<br />
pl_filter = {<br />
CoreFoundationVersion = (<br />
"550.32",<br />
"675.00"<br />
);<br />
};<br />
}<br />
</source><br />
||<br />
<source lang="xml"><br />
<key>pl_filter</key><br />
<dict><br />
<key>CoreFoundationVersion</key><br />
<array><br />
<string>550.32</string><br />
<string>675.00</string><br />
</array><br />
</dict><br />
</source><br />
|}<br />
<br />
== Localization<ref name="1.2">PreferenceLoader version 1.2 and later</ref> ==<br />
<br />
Preferences.framework can localize strings in specifier properties, such as titles and labels.<br />
<br />
Place your specifier plists and icons in a folder within <tt>/Library/PreferenceLoader/Preferences/</tt>. For each <tt>file</tt>.plist file and for each language you have translations for, create a <tt>file</tt>.strings.<br />
<br />
Here's an example:<br />
<br />
{|<br />
|+ style="text-align: left;" | /Library/PreferenceLoader/Preferences/Example/a.plist<br />
|- valign="top"<br />
|<br />
{{Collapse|1=<source lang="javascript">{<br />
entry = {<br />
cell = PSLinkCell;<br />
icon = "/Applications/Preferences.app/icon-table@2x.png";<br />
label = A;<br />
};<br />
items = (<br />
{<br />
cell = PSLinkCell;<br />
label = b;<br />
},<br />
{<br />
cell = PSEditTextCell;<br />
footerAlignment = 1;<br />
keyboard = dvorak;<br />
label = FOOD;<br />
placeholder = BREAD;<br />
}<br />
);<br />
title = "PSSpecifier Localization";<br />
}<br />
</source>|2=NeXTSTEP style}}<br />
||<br />
{{Collapse|1=<source lang="xml"><br />
<?xml version="1.0" encoding="UTF-8"?><br />
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><br />
<plist version="1.0"><br />
<key>entry</key><br />
<dict><br />
<key>cell</key><br />
<string>PSLinkCell</string><br />
<key>icon</key><br />
<string>/Applications/Preferences.app/icon-table@2x.png</string><br />
<key>label</key><br />
<string>A</string><br />
</dict><br />
<key>items</key><br />
<array><br />
<dict><br />
<key>cell</key><br />
<string>PSLinkCell</string><br />
<key>label</key><br />
<string>b</string><br />
</dict><br />
<dict><br />
<key>cell</key><br />
<string>PSEditTextCell</string><br />
<key>footerAlignment</key><br />
<string>1</string><br />
<key>keyboard</key><br />
<string>dvorak</string><br />
<key>label</key><br />
<string>FOOD</string><br />
<key>placeholder</key><br />
<string>BREAD</string><br />
</dict><br />
</array><br />
<key>title</key><br />
<string>PSSpecifier Localization</string><br />
</plist><br />
</source>|2=XML style}}<br />
|}<br />
<br />
<br />
{|<br />
|+ style="text-align: left;" | /Library/PreferenceLoader/Preferences/Example/en.lproj/a.strings<br />
|- valign="top"<br />
|<br />
{{Collapse|1=<source lang="javascript">{<br />
BREAD = "Bread and cheese";<br />
FOOD = Food;<br />
}<br />
</source>|2=NeXTSTEP style}}<br />
||<br />
{{Collapse|1=<source lang="xml"><br />
<?xml version="1.0" encoding="UTF-8"?><br />
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><br />
<plist version="1.0"><br />
<key>BREAD</key><br />
<string>Bread and cheese</string><br />
<key>FOOD</key><br />
<string>Food</string><br />
</plist><br />
</source>|2=XML style}}<br />
|}<br />
<br />
<br />
{|<br />
|+ style="text-align: left;" | /Library/PreferenceLoader/Preferences/Example/es.lproj/a.strings<br />
|- valign="top"<br />
|<br />
{{Collapse|1=<source lang="javascript">{<br />
BREAD = "Pan y queso";<br />
FOOD = Comida;<br />
}<br />
</source>|2=NeXTSTEP style}}<br />
||<br />
{{Collapse|1=<source lang="xml"><br />
<?xml version="1.0" encoding="UTF-8"?><br />
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><br />
<plist version="1.0"><br />
<key>BREAD</key><br />
<string>Pan y queso</string><br />
<key>FOOD</key><br />
<string>Comida</string><br />
</plist><br />
</source>|2=XML style}}<br />
|}<br />
<br />
<br />
{|<br />
|+ style="text-align: left;" | /Library/PreferenceLoader/Preferences/Example/b.plist<br />
|- valign="top"<br />
|<br />
{{Collapse|1=<source lang="javascript">{<br />
items = (<br />
{<br />
cell = PSTitleValueCell;<br />
label = VEHICLE;<br />
value = CAR;<br />
}<br />
);<br />
title = "PSSpecifier Localization";<br />
}<br />
</source>|2=NeXTSTEP style}}<br />
||<br />
{{Collapse|1=<source lang="xml"><br />
<?xml version="1.0" encoding="UTF-8"?><br />
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><br />
<plist version="1.0"><br />
<key>items</key><br />
<array><br />
<dict><br />
<key>cell</key><br />
<string>PSTitleValueCell</string><br />
<key>label</key><br />
<string>VEHICLE</string><br />
<key>value</key><br />
<string>CAR</string><br />
</dict><br />
</array><br />
<key>title</key><br />
<string>PSSpecifier Localization</string><br />
</plist><br />
</source>|2=XML style}}<br />
|}<br />
<br />
<br />
{|<br />
|+ style="text-align: left;" | /Library/PreferenceLoader/Preferences/Example/en.lproj/b.strings<br />
|- valign="top"<br />
|<br />
{{Collapse|1=<source lang="javascript">{<br />
CAR = Car;<br />
VEHICLE = Vehicle;<br />
}<br />
</source>|2=NeXTSTEP style}}<br />
||<br />
{{Collapse|1=<source lang="xml"><br />
<?xml version="1.0" encoding="UTF-8"?><br />
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><br />
<plist version="1.0"><br />
<key>CAR</key><br />
<string>Car</string><br />
<key>VEHICLE</key><br />
<string>Vehicle</string><br />
</plist><br />
</source>|2=XML style}}<br />
|}<br />
<br />
<br />
{|<br />
|+ style="text-align: left;" | /Library/PreferenceLoader/Preferences/Example/es.lproj/b.strings<br />
|- valign="top"<br />
|<br />
{{Collapse|1=<source lang="javascript">{<br />
CAR = Auto;<br />
VEHICLE = Vehiculo;<br />
}<br />
</source>|2=NeXTSTEP style}}<br />
||<br />
{{Collapse|1=<source lang="xml"><br />
<?xml version="1.0" encoding="UTF-8"?><br />
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><br />
<plist version="1.0"><br />
<key>CAR</key><br />
<string>Auto</string><br />
<key>VEHICLE</key><br />
<string>Vehiculo</string><br />
</plist><br />
</source>|2=XML style}}<br />
|}<br />
<br />
== Example code ==<br />
<br />
https://github.com/NoahSaso/theos-examples/tree/master/preferenceloader<br />
<br />
== References ==<br />
<references /><br />
<br />
== See also ==<br />
<br />
* [[PreferenceBundles]]<br />
* [[Preferences specifier plist]]<br />
<br />
== External links ==<br />
<br />
* [http://jontelang.com/guide/chapter3/the-settings.html Settings how to]<br />
<br />
{{Navbox Library}}<br />
[[Category:Directories in /Library]]<br />
[[Category:Preferences]]</div>PoomSmarthttps://iphonedev.wiki/index.php?title=Logos&diff=5687Logos2021-05-28T15:13:06Z<p>PoomSmart: </p>
<hr />
<div>Logos is a component of the [[Theos]] development suite that allows method hooking code to be written easily and clearly, using a set of special preprocessor directives.<br />
<br />
= Overview =<br />
<br />
The syntax provided by Logos greatly simplifies the development of MobileSubstrate extensions ("tweaks") which can hook other methods throughout the OS.<br />
In this context, "method hooking" refers to a technique used to replace or modify methods of classes found in other applications on the OS.<br />
<br />
= Getting Logos =<br />
<br />
Logos is distributed with [[Theos]], and you can use Logos' syntax in any Theos-built project without any extra setup. For more information about Theos, visit [[Theos|its page]].<br />
<br />
= List of Logos Directives =<br />
<br />
== Block level ==<br />
<br />
The directives in this category open a block of code which must be closed by an <tt>[[Logos#.25end|%end]]</tt> directive (shown below). These should not exist within functions or methods.<br />
<br />
=== %group ===<br />
<br />
<source lang="logos"><br />
%group Groupname<br />
</source><br />
<br />
Groups are for conditional initialization or code organization. Grouping can be useful for managing backwards compatibility with older code.<br />
<br />
Begin a hook group with the name ''Groupname''. Groups cannot be inside another <code>[[Logos#.25group|%group]]</code> block. All ungrouped hooks are in the implicit "_ungrouped" group. The _ungrouped group is initialized for you if there are no other groups. You can use the <code>%init</code> directive to initialize it manually. Other groups must be initialized with the <code>%init(Groupname)</code> directive.<br />
<br />
<source lang="logos"><br />
%group iOS8<br />
%hook IOS8_SPECIFIC_CLASS<br />
// your code here<br />
%end // end hook<br />
%end // end group ios8<br />
<br />
%group iOS9<br />
%hook IOS9_SPECIFIC_CLASS<br />
// your code here<br />
%end // end hook<br />
%end // end group ios9<br />
<br />
%ctor {<br />
if (kCFCoreFoundationVersionNumber > 1200) {<br />
%init(iOS9);<br />
} else {<br />
%init(iOS8);<br />
}<br />
}<br />
</source><br />
<br />
=== %hook ===<br />
<br />
<source lang="logos"><br />
%hook Classname<br />
</source><br />
<br />
Open a hook block for the class named ''Classname''.<br />
<br />
Can be inside a <tt>[[Logos#.25group|%group]]</tt> block.<br />
<br />
Here's a trivial example:<br />
<br />
<source lang="logos"><br />
%hook SBApplicationController<br />
-(void)uninstallApplication:(SBApplication *)application {<br />
NSLog(@"Hey, we're hooking uninstallApplication:!");<br />
%orig; // Call the original implementation of this method<br />
return;<br />
}<br />
%end<br />
</source><br />
<br />
==== %new ====<br />
<br />
<source lang="logos"><br />
%new<br />
%new(signature)<br />
</source><br />
<br />
Add a new method to a hooked class or subclass by adding this directive above the method definition. ''signature'' is the Objective-C type encoding for the new method; if it is omitted, one will be generated.<br />
<br />
Must be inside a <tt>[[Logos#.25hook|%hook]]</tt> block.<br />
<br />
=== %subclass ===<br />
<br />
<source lang="logos"><br />
%subclass Classname: Superclass <Protocol list><br />
</source><br />
<br />
Subclass block - the class is created at runtime and populated with methods. ivars are not yet supported (use associated objects).<br />
The <tt>[[Logos#.25new|%new]]</tt> specifier is needed for a method that doesn't exist in the superclass. <br />
To instantiate an object of the new class, you can use the <tt>[[Logos#.25c|%c]]</tt> operator.<br />
<br />
Can be inside a <tt>[[Logos#.25group|%group]]</tt> block.<br />
<br />
Here's an example:<br />
<br />
<source lang="logos"><br />
%subclass MyObject : NSObject<br />
<br />
- (id)init {<br />
self = %orig;<br />
[self setSomeValue:@"value"];<br />
return self;<br />
}<br />
<br />
//the following two new methods act as `@property (nonatomic, retain) id someValue;`<br />
%new<br />
- (id)someValue {<br />
return objc_getAssociatedObject(self, @selector(someValue));<br />
}<br />
<br />
%new<br />
- (void)setSomeValue:(id)value {<br />
objc_setAssociatedObject(self, @selector(someValue), value, OBJC_ASSOCIATION_RETAIN_NONATOMIC);<br />
}<br />
<br />
%end<br />
<br />
%ctor {<br />
MyObject *myObject = [[%c(MyObject) alloc] init];<br />
NSLog(@"myObject: %@", [myObject someValue]);<br />
}<br />
</source><br />
<br />
==== %property ====<br />
<br />
<source lang="logos"><br />
%property (nonatomic|assign|retain|copy|weak|strong|getter|setter) Type name;<br />
</source><br />
<br />
Add a property to a <tt>[[Logos#.25subclass|%subclass]]</tt> just like you would with <tt>@property</tt> to a normal Objective-C subclass as well as adding new properties to existing classes within <tt>[[Logos#.25hook|%hook]]</tt>.<br />
<br />
Must be inside a <tt>[[Logos#.25subclass|%subclass]]</tt> or <tt>[[Logos#.25hook|%hook]]</tt> block.<br />
<br />
=== %end ===<br />
<br />
<source lang="logos"><br />
%end<br />
</source><br />
<br />
Close a group/hook/subclass block.<br />
<br />
== Top level ==<br />
<br />
The directives in this category should not exist within a group/hook/subclass block.<br />
<br />
=== %config ===<br />
<br />
<source lang="logos"><br />
%config(Key=Value);<br />
</source><br />
<br />
Set a logos configuration flag.<br />
<br />
==== Configuration Flags ====<br />
<br />
{| class="wikitable"<br />
|-<br />
! Key<br />
! Values<br />
! Notes<br />
|-<br />
| rowspan="2" | generator<br />
| MobileSubstrate<br />
| generate code that uses [[MobileSubstrate]] for hooking.<br />
|-<br />
| internal<br />
| generate code that uses only internal Objective-C runtime methods for hooking.<br />
|-<br />
| rowspan="3" | warnings<br />
| none<br />
| suppress all warnings<br />
|-<br />
| default<br />
| non-fatal warnings<br />
|-<br />
| error<br />
| make all warnings fatal<br />
|-<br />
| rowspan="2" | dump<br />
| yaml<br />
| dump the internal parse tree in YAML format<br />
|-<br />
| <strike>perl</strike><br />
| <strike>dump the internal parse tree in a format suitable for evaluation as perl source.</strike><br /> dump to the perl source feature is removed since [https://github.com/DHowett/theos/commit/a05354a7b9839a5dce48f7c07114f30dd195b537 this commit].<br />
|}<br />
<br />
=== %hookf ===<br />
<br />
<source lang="logos"><br />
%hookf(rtype, symbolName, args...) { … }<br />
</source><br />
<br />
Generate a function hook for the function named ''symbolName''. If the name is passed as a literal string then the function will be dynamically looked up.<br />
<br />
<source lang="logos"><br />
// Given the function prototype<br />
FILE *fopen(const char *path, const char *mode);<br />
// The hook is thus made<br />
%hookf(FILE *, fopen, const char *path, const char *mode) {<br />
NSLog(@"Hey, we're hooking fopen to deny relative paths!");<br />
if (path[0] != '/') {<br />
return NULL;<br />
}<br />
return %orig; // Call the original implementation of this function<br />
}<br />
</source><br />
<br />
It is common for people to hook the function that its address is resolved at run-time like, <tt>MGGetBoolAnswer</tt>, for example:<br />
<br />
<source lang="logos"><br />
bool (*orig_MGGetBoolAnswer)(CFStringRef);<br />
bool fixed_MGGetBoolAnswer(CFStringRef string)<br />
{<br />
if (CFEqual(string, CFSTR("StarkCapability"))) {<br />
return kCFBooleanTrue;<br />
}<br />
return orig_MGGetBoolAnswer(string);<br />
}<br />
<br />
%ctor {<br />
MSHookFunction(((void *)MSFindSymbol(NULL, "_MGGetBoolAnswer")), (void *)fixed_MGGetBoolAnswer, (void **)&orig_MGGetBoolAnswer);<br />
...<br />
}<br />
</source><br />
<br />
You can also do:<br />
<br />
<source lang="logos"><br />
%hookf(bool, "_MGGetBoolAnswer", CFStringRef string)<br />
{<br />
if (CFEqual(string, CFSTR("StarkCapability"))) {<br />
return true;<br />
}<br />
return %orig;<br />
}<br />
</source><br />
<br />
=== %ctor ===<br />
<br />
<source lang="logos"><br />
%ctor { … }<br />
</source><br />
<br />
Generate an anonymous constructor (of default priority).<br />
<br />
=== %dtor ===<br />
<br />
<source lang="logos"><br />
%dtor { … }<br />
</source><br />
<br />
Generate an anonymous deconstructor (of default priority).<br />
<br />
== Function level ==<br />
<br />
The directives in this category should only exist within a function block.<br />
<br />
=== %init ===<br />
<br />
<source lang="logos"><br />
%init;<br />
%init([<class>=<expr>, …]);<br />
%init(Group[, [+|-]<class>=<expr>, …]);<br />
</source><br />
<br />
Initialize a group (or the default group). Passing no group name will initialize "_ungrouped", and passing class=expr arguments will substitute the given expressions for those classes at initialization time. The + sigil (as in class methods in Objective-C) can be prepended to the classname to substitute an expression for the metaclass. If not specified, the sigil defaults to -, to substitute the class itself. If not specified, the metaclass is derived from the class. The class name replacement is specially useful for classes that contain characters that can't be used as the class name token for the <tt>[[Logos#.25hook|%hook]]</tt> directive, such as spaces and dots.<br />
<br />
Usage:<br />
<source lang="logos"><br />
<br />
%hook SomeClass<br />
-(id)init {<br />
return %orig;<br />
}<br />
%end<br />
<br />
%ctor {<br />
%init(SomeClass=objc_getClass("class with spaces or dots in the name"));<br />
}<br />
</source><br />
<br />
=== %class ===<br />
<br />
<source lang="logos"><br />
%class Class;<br />
</source><br />
<br />
{{warning|<tt>%class</tt> is deprecated. Do not use it in new code.}}<br />
<br />
Forward-declare a class. Outmoded by <tt>[[Logos#.25c|%c]]</tt>, but still exists. Creates a $Class variable, and initializes it with the "_ungrouped" group.<br />
<br />
=== %c ===<br />
<br />
<source lang="logos"><br />
%c([+|-]Class)<br />
</source><br />
<br />
Evaluates to <tt>Class</tt> at runtime. If the + sigil is specified, it evaluates to MetaClass instead of Class. If not specified, the sigil defaults to -, evaluating to Class.<br />
<br />
=== %orig ===<br />
<br />
<source lang="logos"><br />
%orig<br />
%orig(arg1, …)<br />
</source><br />
<br />
Call the original hooked method. It doesn't function in a <tt>[[Logos#.25new|%new]]</tt>'d method. It works in subclasses, strangely enough, because MobileSubstrate will generate a supercall closure at hook time. (If the hooked method doesn't exist in the class we're hooking, it creates a stub that just calls the superclass implementation.) args is passed to the original function - don't include <tt>self</tt> and <tt>_cmd</tt>, Logos does this for you.<br />
<br />
=== %log ===<br />
<br />
<source lang="logos"><br />
%log;<br />
%log([(<type>)<expr>, …]);<br />
</source><br />
<br />
Dump the method arguments to syslog. Typed arguments included in <tt>%log</tt> will be logged as well.<br />
<br />
= File Extensions for Logos =<br />
<br />
{| class="wikitable"<br />
|-<br />
! Extension<br />
! Process order<br />
|-<br />
| .x<br />
| will be processed by Logos, then preprocessed and compiled as objective-c.<br />
|-<br />
| .xm<br />
| will be processed by Logos, then preprocessed and compiled as objective-c++.<br />
|-<br />
| .xi<br />
| will be preprocessed as objective-c first, then Logos will process the result, and then it will be compiled.<br />
|-<br />
| .xmi<br />
| will be preprocessed as objective-c++ first, then Logos will process the result, and then it will be compiled.<br />
|}<br />
<br />
xi or xmi files can use Logos directives in #define macros.<br />
<br />
= Splitting Logos Hooking Code Across Multiple Files =<br />
<br />
By default, the Logos pre-processor will only process one .xm file at build time. However, it is possible to split the Logos hooking code into multiple files.<br><br />
First, the main file has to be renamed to an .xmi file. Then, other .xm files can be included in it using the #include directive. The Logos pre-processor will add those files to the main file before processing it.<br />
<br />
== Groups ==<br />
<br />
Normally, it isn't possible to initialize hooking groups across multiple Logos files, but there is a workaround that can be used to unlock this functionality. This is done by wrapping group initializations inside of static methods that can then be called from other files.<br><br />
<br />
Take a look at the following code. All it does is log a message when the SpringBoard application has finished launching. It is inside of a group called '''TweakGroup''', which is initialized in a static function called '''InitGroup()'''.<br />
<source lang="logos"><br />
// Group.xm<br />
#import "Shared.h"<br />
<br />
%group TweakGroup<br />
%hook SpringBoard<br />
<br />
- (void)applicationDidFinishLaunching:(id)arg1 {<br />
%orig;<br />
NSLog(@"[Group Test] SpringBoard has finished launching");<br />
}<br />
<br />
%end<br />
%end<br />
<br />
extern "C" void InitGroup() {<br />
%init(TweakGroup);<br />
}<br />
</source><br />
<br />
As you may have noticed, there is an import for ''Shared.h'' at the top of ''Group.xm''. That is simply a header file that will be imported into our main Logos file so that we may call the function there:<br />
<source lang="logos"><br />
// Shared.h<br />
extern "C" void InitGroup();<br />
</source><br />
<br />
Finally, ''Shared.h'' can be imported into the Logos file that contains your constructor. Calling the static function will initialize the group from ''Group.xm'' and run its hooks:<br />
<source lang="logos"><br />
// Tweak.xm<br />
#import "Shared.h"<br />
<br />
%ctor {<br />
NSLog(@"[Group Test] Our hook for SpringBoard should show up below this");<br />
InitGroup();<br />
}<br />
</source><br />
<br />
If done correctly and compiled without errors, this could should log two messages: one from the constructor and the other one from the method inside the group. Keep in mind that this doesn't apply to hooks that aren't inside of a group.<br />
<br />
'''A few things to note''':<br />
* This doesn't work in normal C, so you must use ''.xm'' files for your groups and constructor.<br />
* You have to pay attention to how many times you call the initialization as Logos will no longer tell you if it is called more than once.<br />
<br />
= logify.pl =<br />
<br />
You can use logify.pl to create a Logos source file from a header file that will log all of the functions of that header file. Here is an example of a very simple Logos tweak generated by logify.pl<br />
<br />
Given a header file:<br />
<br />
<source lang="logos"><br />
@interface SSDownloadAsset : NSObject<br />
- (NSString *)finalizedPath;<br />
- (NSString *)downloadPath;<br />
- (NSString *)downloadFileName;<br />
+ (id)assetWithURL:(id)url type:(int)type;<br />
- (id)initWithURLRequest:(id)urlrequest type:(int)type;<br />
- (id)initWithURLRequest:(id)urlrequest;<br />
- (id)_initWithDownloadMetadata:(id)downloadMetadata type:(id)type;<br />
@end<br />
</source><br />
<br />
You can find logify.pl at $THEOS/bin/logify.pl and you would use it as so:<br />
<br />
<source lang="bash"><br />
$THEOS/bin/logify.pl ./SSDownloadAsset.h<br />
</source><br />
<br />
The resulting output should be:<br />
<br />
<source lang="logos"><br />
%hook SSDownloadAsset<br />
- (NSString *)finalizedPath { %log; NSString * r = %orig; NSLog(@" = %@", r); return r; }<br />
- (NSString *)downloadPath { %log; NSString * r = %orig; NSLog(@" = %@", r); return r; }<br />
- (NSString *)downloadFileName { %log; NSString * r = %orig; NSLog(@" = %@", r); return r; }<br />
+ (id)assetWithURL:(id)url type:(int)type { %log; id r = %orig; NSLog(@" = %@", r); return r; }<br />
- (id)initWithURLRequest:(id)urlrequest type:(int)type { %log; id r = %orig; NSLog(@" = %@", r); return r; }<br />
- (id)initWithURLRequest:(id)urlrequest { %log; id r = %orig; NSLog(@" = %@", r); return r; }<br />
- (id)_initWithDownloadMetadata:(id)downloadMetadata type:(id)type { %log; id r = %orig; NSLog(@" = %@", r); return r; }<br />
%end<br />
</source><br />
<br />
= External links =<br />
<br />
* [https://github.com/theos/logos/blob/master/bin/logos.pl Main ''logos.pl'' file]<br />
* [https://github.com/theos/logos/blob/master/bin/logify.pl ''logify.pl'' file]<br />
<br />
[[Category:Development Tools]]</div>PoomSmarthttps://iphonedev.wiki/index.php?title=Preferences_specifier_plist&diff=5682Preferences specifier plist2021-05-23T12:18:23Z<p>PoomSmart: /* Custom Settings Libraries */</p>
<hr />
<div>This document provides the specification of the dictionaries that specify the layout of an iOS preference pane. These can be supplied statically via .plist files or dynamically via the <code>_specifiers</code> ivar in a subclass of [[PSViewController]].<br />
<br />
== Root level ==<br />
<br />
The root level of the plist may contain these keys:<br />
<br />
{| class="wikitable"<br />
|-<br />
! key !! colspan="2" | type !! meaning !! depends<br />
|-<br />
| entry || colspan="2" | dictionary || Specifier-like dictionary. || -<br />
|-<br />
| title || string || localizable string || Title of the preference pane. || ''entry'' ≠ nil<br />
|-<br />
| items || array || ... of specifiers || Array of specifier dictionaries. || -<br />
|}<br />
<br />
The ''title'' key is used only for the root plist, otherwise, the ''label'' value from the specifier that pushed the new pane is used.<br />
<br />
== Specifier Keys and Values ==<br />
<br />
You can use any keys that your controller recognizes in the plist for further customization.<br />
<br />
''General to-do: Add explanations of each specifier and potentially a screenshot of it (gif for the spinner?).''<br />
<br />
=== Cell types ===<br />
<br />
Must be one of the following:<br />
* [[Preferences_specifier_plist#PSButtonCell|PSButtonCell]]<br />
* [[Preferences_specifier_plist#PSEditTextCell_.26_PSSecureEditTextCell|PSEditTextCell]]<br />
* [[Preferences_specifier_plist#PSEditTextViewCell|PSEditTextViewCell]]<br />
* [[Preferences_specifier_plist#PSGiantCell|PSGiantCell]]<br />
* [[Preferences_specifier_plist#PSGiantIconCell|PSGiantIconCell]]<br />
* [[Preferences_specifier_plist#PSGroupCell|PSGroupCell]]<br />
* [[Preferences_specifier_plist#PSLinkCell|PSLinkCell]]<br />
* [[Preferences_specifier_plist#PSLinkListCell_.26_PSSegmentCell|PSLinkListCell]]<br />
* [[Preferences_specifier_plist#PSListItemCell|PSListItemCell]]<br />
* [[Preferences_specifier_plist#PSEditTextCell_.26_PSSecureEditTextCell|PSSecureEditTextCell]]<br />
* [[Preferences_specifier_plist#PSLinkListCell_.26_PSSegmentCell|PSSegmentCell]]<br />
* [[Preferences_specifier_plist#PSSliderCell|PSSliderCell]]<br />
* [[Preferences_specifier_plist#PSSpinnerCell|PSSpinnerCell]]<br />
* [[Preferences_specifier_plist#PSStaticTextCell|PSStaticTextCell]]<br />
* [[Preferences_specifier_plist#PSSwitchCell|PSSwitchCell]]<br />
* [[Preferences_specifier_plist#PSTitleValueCell|PSTitleValueCell]]<br />
<br />
The cell type is determined from the class method {{ObjcCall|PSTableCell|ClassMethod=1|cellTypeFromString:}}.<br />
<br />
=== General keys ===<br />
<br />
{| class="wikitable"<br />
|-<br />
! key !! colspan="2" | type !! meaning !! depends<br />
|-<br />
| cell || string || <tt>&lt;cell type&gt;</tt> || Specifier cell type. || -<br />
|-<br />
| label || string || localizable string || Label of specifier. || -<br />
|-<br />
| defaults || string || bundle ID || User defaults associated with this specifier. || -<br />
|-<br />
| key || colspan="2" | string || Key of the user defaults. || ''defaults'' ≠ nil<br />
|-<br />
| default || colspan="2" | any || Default value of control. || -<br />
|-<br />
| id || colspan="2" | string || Specifier ID. || -<br />
|-<br />
| hasIcon || colspan="2" | boolean || Whether the specifier will have an icon. || ''bundle'' ≠ nil<br />
|-<br />
| icon || string || filename || File name of the icon to use. Default value is <tt>icon.png</tt>. The height of the icon should be 29px. || ''hasIcon'' = true<br />
|-<br />
| get || string || selector || Getter. || -<br />
|-<br />
| set || string || selector || Setter. || -<br />
|-<br />
| enabled || colspan="2" | boolean || Whether the control is enabled by default. || -<br />
|-<br />
| height || colspan="2" | real || Height of the cell. || -<br />
|-<br />
| PostNotification || colspan="2" | string || Darwin notification string to be posted when a change happens. || -<br />
|-<br />
| detail || string || class name || [[PSDetailController|Detail controller class]]. || -<br />
|-<br />
| cellClass || string || class name || Customized cell class || -<br />
|-<br />
| requiredCapabilities || array || ... of <tt>&lt;[[GSCapability|capability]]&gt;</tt>s || Required capabilities of the device such that this specifier can be shown. || -<br />
|-<br />
| dontIndentOnRemove || colspan="2" | boolean || Prevents the cell from being indented when the table view is in editing mode. || -<br />
|}<br />
<br />
''Investigate hasIcon key dependency since all but PSGroupCell display an icon if supplied.''<br />
<br />
Keys apply to all cells unless otherwise stated in their respective subsection.<br />
<br />
Signature and default methods for the set and get selectors:<br />
* <code>-(void)setPreferenceValue:(id)value forSpecifier:(PSSpecifier*)specifier;</code><br />
* <code>-(id)readPreferenceValue:(PSSpecifier*)specifier;</code><br />
<br />
=== PSButtonCell ===<br />
<br />
{| class="wikitable"<br />
|-<br />
! key !! colspan="2" | type !! meaning !! depends<br />
|-<br />
| action || string || selector || Action.<br/>Signature: <code>-(void)speciferPerformedAction:(PSSpecifier*)specifier;</code><br/> or <code>-(void)speciferPerformedAction;</code>|| -<br />
|-<br />
| confirmation || dictionary || <tt>&lt;confirmation&gt;</tt> || Definitions of the confirmation sheet before action is performed. || -<br />
|-<br />
| isDestructive || colspan="2" | boolean || Whether the action to be performed is destructive. The OK button will be in red if true if less than iOS7. || ''confirmation'' ≠ nil<br />
|}<br />
<br />
The ''confirmation'' value is a dictionary containing the following fields:<br />
<br />
{| class="wikitable"<br />
|-<br />
! key !! colspan="2" | type !! meaning<br />
|-<br />
| prompt || string || localizable string || Content of confirmation sheet.<br />
|-<br />
| title || string || localizable string || Title of confirmation sheet.<br />
|-<br />
| okTitle || string || localizable string || Title of the OK button.<br />
|-<br />
| cancelTitle || string || localizable string || Title of the cancel button.<br />
|}<br />
<br />
''To do: confirm this last table. Tests suggest "prompt" is the title, "title" is the okTitle, "okTitle" is MIA, cancelTitle works as stated. Investigate history of "isDestructive" key.''<br />
<br />
=== PSEditTextCell & PSSecureEditTextCell ===<br />
<br />
{| class="wikitable"<br />
|-<br />
! key !! colspan="2" | type !! meaning !! depends<br />
|-<br />
| keyboard || string || {"<tt>numbers</tt>", "<tt>phone</tt>"} || Type of keyboard. nil or invalid values uses a normal keyboard. || -<br />
|-<br />
| autoCaps || string || {"<tt>sentences</tt>", "<tt>words</tt>", "<tt>all</tt>"} || Autocapitalization type for cells that requires a keyboard. || ''keyboard'' = nil<br />
|-<br />
| placeholder || string || localizable string || Placeholder. || -<br />
|-<br />
| suffix || string || localizable string || Suffix. || -<br />
|-<br />
| bestGuess || string || selector || Initial value of text field. || -<br />
|-<br />
| noAutoCorrect || colspan="2" | boolean || Disable auto-correction. || -<br />
|-<br />
| isIP || colspan="2" | boolean || Input field intended for entering IP address (Use Numbers keyboard). || -<br />
|-<br />
| isURL || colspan="2" | boolean || Input field intended for entering URL (Use URL keyboard). || -<br />
|-<br />
| isNumeric || colspan="2" | boolean || Input field intended for entering numbers (Use NumberPad keyboard). || -<br />
|-<br />
| isDecimalPad || colspan="2" | boolean || Input field intended for entering decimal numbers (Use DecimalPad keyboard). || -<br />
|-<br />
| isEmail || colspan="2" | boolean || Input field intended for entering e-mail (Use EmailAddress keyboard). || -<br />
|-<br />
| isEmailAddressing || colspan="2" | boolean || ? || -<br />
|-<br />
| prompt || string || localizable string || Setup prompt. || -<br />
|-<br />
| okTitle || string || localizable string || Title for OK button in setup prompt. || ''prompt'' ≠ nil<br />
|-<br />
| cancelTitle || string || localizable string || Title for cancel button in setup prompt. || ''prompt'' ≠ nil<br />
|}<br />
<br />
''To do: Check "prompt", "okTitle" and "cancelTitle" as they appear to not work on iOS 6. Are these in the correct place?<br>Check what "suffix" does. Find "bestGuess" selector signature. Solve the mystery of "isEmailAddressing".''<br />
<br />
=== PSEditTextViewCell ===<br />
<br />
This specifier doesn't show a label so it is recommended to use a previous specifier to indicate what this specifier represents.<br />
<br />
The text area expands to fit the whole cell, so setting a height key will provide more space to write.<br />
<br />
Saved value is HTML text, <tt>&lt;div&gt;</tt> being the root tag block.<br />
<br />
=== PSGiantCell ===<br />
<br />
This specifier doesn't show a label so it is recommended to use a specifier before this one to indicate what this specifier represents.<br />
<br />
=== PSGiantIconCell ===<br />
<br />
This specifier uses the ''label'' key as text content.<br />
<br />
The font in this cell is bigger than normal.<br />
<br />
''To do: Find out the actual font and icon sizes.''<br />
<br />
=== PSGroupCell ===<br />
<br />
{| class="wikitable"<br />
|-<br />
! key !! type !! meaning !! depends<br />
|-<br />
| footerText || string || Text displayed in a small font after this specifier. || -<br />
|-<br />
| footerAlignment || integer || 0:left; 1:center; 2:right; defaults to 1. || -<br />
|-<br />
| headerCellClass || string || The class name to use for the header. || -<br />
|-<br />
| footerCellClass || string || The class name to use for the footer. || -<br />
|-<br />
| isStaticText || boolean || Whether the cells in this group have static text. || -<br />
|}<br />
<br />
If you want to make a Image Header read [http://cpdigitaldarkroom.com/2014/03/adding-a-image-header-to-your-tweaks-settings-pane this]. Hides the group title (<code>label</code> key).<br />
<br />
<code>isStaticText</code> is used in conjunction with PSStaticTextCell.<br />
<br />
''To do: Research "isStaticText" interaction with "PSStaticTextCell".''<br />
<br />
=== PSLinkCell ===<br />
<br />
{| class="wikitable"<br />
|-<br />
! key !! colspan="2" | type !! meaning !! depends<br />
|-<br />
| bundle || string || filename || Bundle file name. This bundle will be loaded for additional resources. || -<br />
|-<br />
| internal || colspan="2" | boolean || Directory to search for the bundle.<br/>If true, search in <tt>/AppleInternal/Library/PreferenceBundles/</tt>.<br/>If false, search in <tt>/System/Library/PreferenceBundles/.</tt> || ''bundle'' ≠ nil<br />
|-<br />
| isController || colspan="2" | boolean || Whether the bundle contains a controller class. || ''bundle'' ≠ nil<br />
|-<br />
| overridePrincipalClass || colspan="2" | boolean || Overrides the principal class by the detail controller when bundle has a controller. || ''isController'' = true<br />
|-<br />
| pane || string || class name || Edit pane class.<br />If ''bundle'' is absent, the edit pane class is obtained from the current bundle.<br />Default value is [[PSEditingPane]]. || ''detail'' ≠ nil<br />
|-<br />
| customControllerClass || string || class name || Custom controller class to use when the view become visible || -<br />
|-<br />
| lazy-bundle || colspan="2" | NSBundle || A bundle. This bundle will be loaded for additional resources. || -<br />
|}<br />
<br />
This specifier is useful for loading extra resources and custom code.<br />
<br />
If none of these keys are specified, the framework will try to load a plist using the label text as name.<br />
<br />
=== PSListItemCell ===<br />
<br />
This specifier makes use of the <tt>get</tt> key to get the value in the runtime.<br />
<br />
=== PSLinkListCell & PSSegmentCell ===<br />
<br />
{| class="wikitable"<br />
|-<br />
! key !! colspan="2" | type !! meaning !! depends<br />
|-<br />
| validValues || array || ...of strings || List of values to choose from. || -<br />
|-<br />
| validTitles || array || ...of localizable strings || Titles corresponding to the list of values. || -<br />
|-<br />
| shortTitles || array || ...of localizable strings || Short titles corresponding to the list of values, displayed in the link cell. || -<br />
|-<br />
| valuesDataSource || string || selector || Selector to call to get the list of values dynamically. || ''validValues'' = nil<br />
|-<br />
| titlesDataSource || string || selector || Selector to call to get the list of titles dynamically. || ''validTitles'' = nil<br />
|-<br />
| staticTextMessage || string || localizable string || The message to be added below the cells list of PSListItemsController. || ''cell'' = "<tt>PSLinkListCell</tt>"<br />
|}<br />
<br />
''valuesDataSource'' and ''titlesDataSource'' are performed on the target sent from {{ObjcCall|PSListController|loadSpecifiersFromPlistName:target:}}. They must return an NSArray containing the values and (localized) titles respectively. Their signatures should be<br />
<source lang="objc"><br />
-(NSArray*)dataFromTarget:(id)target;<br />
</source><br />
<br />
In order to make a PSLinkListCell actually work like a list, you must supply the key-value pair<br />
detail = PSListItemsController;<br />
<br />
=== PSSliderCell ===<br />
<br />
{| class="wikitable"<br />
|-<br />
! key !! colspan="2" | type !! meaning !! depends<br />
|-<br />
| min || colspan="2" | real || Minimum value of slider. || -<br />
|-<br />
| max || colspan="2" | real || Maximum value of slider. || -<br />
|-<br />
| showValue || colspan="2" | boolean || Show the value. || -<br />
|-<br />
| isContinuous || colspan="2" | boolean || Change the value by steps. Possibly deprecated. || -<br />
|-<br />
| isSegmented || colspan="2" | boolean || Change the value by steps. || -<br />
|-<br />
| segmentCount || colspan="2" | integer || Steps count. || -<br />
|-<br />
| leftImage || string || filename || Image displayed next to the slider on the left. || -<br />
|-<br />
| rightImage || string || filename || Image displayed next to the slider on the right. || -<br />
|}<br />
<br />
This specifier doesn't show a label so it is recommended to use a previous specifier to indicate what this specifier represents.<br />
<br />
Image files must reside in the same directory. They can be symlinks to files elsewhere though. If <code>showValue</code> is set to true it might overlap with the right image.<br />
<br />
''To Do: figure out if the step is a constant or a proportion (1/10? 1/16?) of the slider range.''<br />
<br />
=== PSSpinnerCell ===<br />
<br />
PSSpinnerCell is a simple cell with an animating spinner (UIActivityIndicatorView) inside it. Available only in iOS 7 (or higher)<sup>[citation needed]</sup>. There is no way to start or stop the animation manually, it is always running. Therefore, this cell is meant to be dynamically inserted and deleted from a PSListController subclass.<br />
<br />
=== PSStaticTextCell ===<br />
<br />
This specifier uses the ''label'' key as text content.<br />
<br />
=== PSSwitchCell ===<br />
<br />
{| class="wikitable"<br />
|-<br />
! key !! type !! meaning !! depends<br />
|-<br />
| alternateColors || boolean || Use an orange switch instead of blue. || iOS < 7<br />
|-<br />
| control-loading || boolean || Show an activity indicator view instead of switch (e.g. VPN cell) || -<br />
|-<br />
| negate || boolean || Invert the value displayed. || -<br />
|}<br />
<br />
You can dynamically set the UISwitch's state by returning YES or NO in the get method. When the switch's state changes, the set method is called.<br />
<br />
See [[Preferences_specifier_plist#PSSwitchCell_2|PSSwitchCell]] in the Recipes section for solving an issue on iOS 7.<br />
<br />
=== PSTitleValueCell ===<br />
<br />
This specifier makes use of the <tt>get</tt> key to get the value in the runtime.<br />
<br />
=== Miscellaneous ===<br />
<br />
{| class="wikitable"<br />
|-<br />
! key !! colspan="2" | type !! meaning !! depends<br />
|-<br />
| alignment || colspan="2" | integer || Text alignment. 0:left; 1:center; 2:right; defaults to 1. || ''cell'' ∈ {"<tt>PSGroupCell</tt>", "<tt>PSStaticTextCell</tt>"}<br />
|}<br />
<br />
''To do: check which specifiers support this key.''<br />
<br />
== <tt>PSSpecifier</tt> runtime properties of plist keys ==<br />
<br />
The table below only shows the keys recognized by <tt>SpecifiersForPlist</tt> when translating the plist into an array of <tt>PSSpecifier</tt>s. They may correspond to the actual properties of the specifier. If you would like to generate a <tt>PSSpecifier</tt> in runtime, some actions may differ:<br />
<br />
{| class="wikitable"<br />
|-<br />
! keys !! corresponding action<br />
|-<br />
| cell || Use the constructor, or change the <tt>cellType</tt> ivar.<br />
|-<br />
| label || Use the <tt>name</tt> declared property.<br />
|-<br />
| get || Use the constructor, or change the <tt>getter</tt> ivar.<br />
|-<br />
| set || Use the constructor, or change the <tt>setter</tt> ivar.<br />
|-<br />
| action || Change the <tt>action</tt> ivar.<br />
|-<br />
| default || Use the ''value'' property.<br />
|-<br />
| icon || {{ObjcCall|PSSpecifier|setProperty:forKey:}} Use the ''iconImage'' and UIImage as a key and property, or {{ObjcCall|PSSpecifier|setupIconImageWithPath:}}<br />
|-<br />
| autoCaps, keyboard, noAutoCorrect || {{ObjcCall|PSSpecifier|setKeyboardType:autoCaps:autoCorrection:}}<br />
|-<br />
| isIP, isURL, isNumeric, isEmail, isEmailAddressing || Change the <tt>textFieldType</tt> ivar.<br />
|-<br />
| bestGuess || Change the <tt>bestGuess</tt> ivar of the [[PSTextFieldSpecifier]] class.<br />
|-<br />
| validValues, validTitles, shortTitles || {{ObjcCall|PSSpecifier|setValues:titles:shortTitles:}}<br />
|-<br />
| confirmation || Create an instance of [[PSConfirmationSpecifier]].<br />
|-<br />
| enabled || Must be set to YES (as NSNumber) to make the specifier interactive. <br />
|}<br />
<br />
== Recipes ==<br />
<br />
{{main|PreferenceBundles}}<br />
<br />
Use the following snippet to create a PSSpecifier in the runtime:<br />
<source lang="objc"><br />
PSSpecifier* specifier = [PSSpecifier preferenceSpecifierNamed:@"title"<br />
target:self<br />
set:@selector(setPreferenceValue:specifier:)<br />
get:@selector(readPreferenceValue:)<br />
detail:Nil<br />
cell:<cell type><br />
edit:Nil];<br />
[specifier setProperty:@YES forKey:@"enabled"];<br />
</source><br />
<br />
Using <tt>@selector(setPreferenceValue:specifier:)</tt> as setter and <tt>@selector(readPreferenceValue:)</tt> as getter will ease the load on the work as the specifier will use its properties to make itself work, namely "defaults", "key", "default", "PostNotification".<br />
<br />
=== PSButtonCell ===<br />
<br />
The red delete button in VPN is in fact very easy to implement. All you need to do is add the following code:<br />
<br />
<source lang="objc"><br />
<br />
@interface UITableCell : UIView<br />
@end<br />
<br />
@interface UIImageAndTextTableCell : UITableCell<br />
-(id)titleTextLabel;<br />
@end<br />
<br />
@interface UIPreferencesTableCell : UIImageAndTextTableCell<br />
-(void)setTarget:(id)target;<br />
-(void)setAction:(SEL)action;<br />
@end<br />
<br />
@interface UIPreferencesControlTableCell : UIPreferencesTableCell<br />
@end<br />
<br />
@interface UIPreferencesDeleteTableCell : UIPreferencesControlTableCell<br />
@end<br />
<br />
@interface PSDeleteTableCell : UIPreferencesDeleteTableCell<br />
@end<br />
<br />
@implementation PSDeleteTableCell<br />
-(void)setValueChangedTarget:(id)target action:(SEL)action userInfo:(NSDictionary*)info {<br />
[self setTarget:target];<br />
[self setAction:action];<br />
}<br />
-(UILabel*)titleTextLabel {<br />
UILabel* res = [super titleTextLabel];<br />
res.textColor = [UIColor whiteColor];<br />
return res;<br />
}<br />
@end<br />
</source><br />
<br />
And add the following key-value pair to the button specifier:<br />
cellClass = PSDeleteTableCell;<br />
<br />
Note that <code>UIPreferencesDeleteTableCell</code> no longer exists as of iOS 6.0. It appears to be replaced by a boolean on PSButtonCell, <code>isDestructive</code>.<br />
<br />
=== PSEditTextCell & PSSecureEditTextCell ===<br />
<br />
To make the <tt>Return</tt> key close the keyboard add the following method to your PSListController subclass:<br />
<br />
<source lang="objc"><br />
- (void)_returnKeyPressed:(NSConcreteNotification *)notification {<br />
[self.view endEditing:YES];<br />
[super _returnKeyPressed:notification];<br />
}<br />
</source><br />
<br />
=== PSLinkCell ===<br />
<br />
PSLinkCell is useful for linking to sub-preference-panes. The simplest example just needs 2 keys:<br />
<br />
{<br />
cell = PSLinkCell;<br />
label = "Settings-iPhone";<br />
}<br />
<br />
The ''label'' is the important part. When user clicked on the link cell, iPhoneOS will use the '''unlocalized''' ''label'' as the file name of the plist for the next pane. In the example above, the main settings screen will appear.<br />
<br />
If you use just 2 keys, only plists inside {{applink|Preferences}} can be loaded. In order to load your own plist, you must use a custom subclass of [[PSListController]] in ''detail'':<br />
{<br />
cell = PSLinkCell;<br />
label = "My Awesome Pane";<br />
detail = MyListController;<br />
}<br />
<br />
MyListController can simply be an empty subclass of PSListController:<br />
<br />
<source lang="objc"><br />
@interface MyListController : PSListController {}<br />
@end<br />
@implementation MyListController<br />
@end<br />
</source><br />
<br />
The key thing is when you place MyListController inside your bundle, its bundle property will return your bundle which <tt>My Awesome Pane.plist</tt> can be found.<br />
<br />
=== PSSwitchCell ===<br />
<br />
Since iOS 7.0 and above the "alternateColors" key does not work. To be able to change the color of a switch, you must subclass PSSwitchTableCell in a [[PreferenceBundles|PreferenceBundle]] as follows: <br />
<br />
<source lang="objc"><br />
<br />
@interface PSTableCell : UITableViewCell<br />
@end<br />
@interface PSControlTableCell : PSTableCell<br />
- (UIControl *)control;<br />
@end<br />
@interface PSSwitchTableCell : PSControlTableCell<br />
- (id)initWithStyle:(int)style reuseIdentifier:(id)identifier specifier:(id)specifier;<br />
@end<br />
<br />
@interface SRSwitchTableCell : PSSwitchTableCell<br />
@end<br />
<br />
@implementation SRSwitchTableCell<br />
<br />
-(id)initWithStyle:(int)style reuseIdentifier:(id)identifier specifier:(id)specifier { //init method<br />
self = [super initWithStyle:style reuseIdentifier:identifier specifier:specifier]; //call the super init method<br />
if (self) {<br />
[((UISwitch *)[self control]) setOnTintColor:[UIColor redColor]]; //change the switch color<br />
}<br />
return self;<br />
}<br />
<br />
@end<br />
</source><br />
<br />
Then set this key-value pair for the specifier:<br />
cellClass = SRSwitchTableCell;<br />
<br />
A detailed tutorial about this has been written on [http://sharedroutine.com/?p=143 sharedroutine.com].<br />
<br />
=== PSTitleValueCell ===<br />
<br />
To display a value like <code>Preferences -> General -> About</code>, add the cell to your plist:<br />
<br />
{<br />
cell = PSTitleValueCell;<br />
label = Version;<br />
get = "valueForSpecifier:";<br />
}<br />
<br />
And add the getter method to your controller:<br />
<br />
<source lang="objc"><br />
- (NSString *)valueForSpecifier:(PSSpecifier *)specifier {<br />
return @"1.0";<br />
}<br />
</source><br />
<br />
=== Custom cells ===<br />
<br />
Making a custom cell, header or footer is useful because it allows you to customize the style, add an image, etc.<br />
<br />
All you need to do is make a class that looks like:<br />
<br />
<source lang="objc"><br />
@interface PSTableCell : UITableViewCell<br />
@end<br />
<br />
@protocol PreferencesTableCustomView<br />
- (id)initWithSpecifier:(PSSpecifier *)specifier;<br />
- (CGFloat)preferredHeightForWidth:(CGFloat)width;<br />
@end<br />
<br />
@interface CustomCell : PSTableCell <PreferencesTableCustomView> {<br />
UILabel *_label;<br />
}<br />
@end<br />
<br />
@implementation CustomCell<br />
- (id)initWithSpecifier:(PSSpecifier *)specifier {<br />
self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Cell" specifier:specifier];<br />
if (self) {<br />
_label = [[UILabel alloc] initWithFrame:[self frame]];<br />
[_label setLineBreakMode:UILineBreakModeWordWrap];<br />
[_label setNumberOfLines:0];<br />
[_label setText:@"You can use attributed text to make this prettier."];<br />
[_label setBackgroundColor:[UIColor clearColor]];<br />
[_label setShadowColor:[UIColor whiteColor]];<br />
[_label setShadowOffset:CGSizeMake(0,1)];<br />
[_label setTextAlignment:UITextAlignmentCenter];<br />
<br />
[self addSubview:_label];<br />
[_label release];<br />
}<br />
return self;<br />
}<br />
<br />
- (CGFloat)preferredHeightForWidth:(CGFloat)width {<br />
// Return a custom cell height.<br />
return 60.f;<br />
}<br />
@end<br />
</source><br />
<br />
Then, set the <code>cellClass</code>, <code>headerCellClass</code> or <code>footerCellClass</code> in your specifier. For example:<br />
...<br />
{ <br />
cell = PSGroupCell;<br />
'''footerCellClass = CustomCell;'''<br />
},<br />
...<br />
A <code>cell</code> doesn't have to be specified for custom cells.<br />
<br />
=== Constructing a PSLinkCell at runtime ===<br />
<br />
If you want to dynamically add a specifier for a PSLinkCell that lazy-loads a bundle, you can do it like this:<br />
<br />
<source lang="objc"><br />
PSSpecifier* specifier = [PSSpecifier preferenceSpecifierNamed:@"title"<br />
target:self<br />
set:NULL<br />
get:NULL<br />
detail:Nil<br />
cell:PSLinkCell<br />
edit:Nil];<br />
<br />
[specifier setProperty:@"/System/Library/PreferenceBundles/prefs.bundle" forKey:@"lazy-bundle"];<br />
[specifier setAction:@selector(lazyLoadBundle:)];<br />
<br />
// Now add the specifier to your controller.<br />
</source><br />
<br />
=== Constructing a PSLinkListCell at runtime ===<br />
<br />
If you want to dynamically add a specifier for a PSLinkListCell you can do it like this:<br />
<br />
<source lang="objc"><br />
PSSpecifier* specifier = [PSSpecifier preferenceSpecifierNamed:@"title"<br />
target:self<br />
set:NULL<br />
get:NULL<br />
detail:NSClassFromString(@"PSListItemsController")<br />
cell:PSLinkListCell<br />
edit:Nil];<br />
<br />
[specifier setProperty:@YES forKey:@"enabled"];<br />
[specifier setProperty:@"0" forKey:@"default"]; <br />
specifier.values = [NSArray arrayWithObjects:@"0",@"1",@"2",nil];<br />
specifier.titleDictionary = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:@"Title 1",@"Title 2",@"Title 3",nil] forKeys:specifier.values];<br />
specifier.shortTitleDictionary = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:@"T1",@"T@",@"T3",nil] forKeys:specifier.values];<br />
[specifier setProperty:@"kListValue" forKey:@"key"];<br />
<br />
// Now add the specifier to your controller.<br />
</source><br />
<br />
=== Making an editable PSListController ===<br />
<br />
With this you can perform a "swipe-to-delete" on the rows. <br />
<br />
You just have to use a subclass of <code>PSEditableListController</code> (which is a subclass of <code>PSListController</code>) for your List Controller. For example:<br />
<br />
<source lang="objc"><br />
@interface PSViewController : UIViewController<br />
@end<br />
@interface PSListController : PSViewController<br />
@end<br />
@interface PSEditableListController : PSListController<br />
@end<br />
@interface MyListController : PSEditableListController<br />
@end<br />
<br />
@implementation MyListController<br />
- (id)specifiers {<br />
if (!_specifiers) {<br />
//add a sample specifier to the list<br />
PSSpecifier* testSpecifier = [PSSpecifier preferenceSpecifierNamed:@"test"<br />
target:self<br />
set:NULL<br />
get:NULL<br />
detail:Nil<br />
cell:PSTitleValueCell<br />
edit:Nil];<br />
_specifiers = [[NSArray arrayWithObjects:testSpecifier, nil] retain];<br />
}<br />
return _specifiers;<br />
}<br />
@end<br />
</source><br />
<br />
Please note, you will only be able to delete a specifier, if its class is either <code>PSLinkListCell</code>, <code>PSListItemCell</code> or <code>PSTitleValueCell</code><br />
<br />
However, you can make all specifier's deletable by adding the function<br />
<source lang="objc"><br />
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {<br />
return UITableViewCellEditingStyleDelete;<br />
}<br />
</source><br />
<br />
To perform a custom action when the specifier gets deleted, you have to implement a method in your PSEditableListController subclass like this:<br />
<br />
<source lang="objc"><br />
-(void)removedSpecifier:(PSSpecifier*)specifier{<br />
UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"Removing specifier: "<br />
message:[specifier name]<br />
delegate:self<br />
cancelButtonTitle:@"OK"<br />
otherButtonTitles:nil];<br />
[alert show];<br />
}<br />
</source><br />
<br />
and set the deletionAction Key of the specifier:<br />
<br />
<source lang="objc"><br />
extern NSString* PSDeletionActionKey;<br />
<br />
/*<br />
construct the PSSpecifier* testSpecifier<br />
*/<br />
<br />
[testSpecifier setProperty:NSStringFromSelector(@selector(removedSpecifier:)) forKey:PSDeletionActionKey];<br />
</source><br />
<br />
=== Custom Settings Libraries ===<br />
<br />
* https://github.com/mlnlover11/SettingsKit/wiki<br />
* https://hbang.github.io/libcephei/<br />
<br />
== Plist Only ==<br />
<br />
''To do: add more difficult recipes, such as using the PSGroupCell properly, and making sub-preferences using the PSLinkCell''<br />
<br />
These will work as an independent plist, when put into "/Library/PreferenceLoader/Preferences". You need no Objective C or anything for these, just the plist file. This can be useful for adding preferences to things like [[Cydget]]s. Other examples from tweaks that use just the plist can be found in that same location.<br />
<br />
=== Required Structure ===<br />
<br />
This is the required outline to add a custom plist to the Preferences app.<br />
<source lang="xml"><br />
<?xml version="1.0" encoding="UTF-8"?><br />
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><br />
<plist version="1.0"><br />
<dict><br />
<key>entry</key><br />
<dict><br />
<key>cell</key><br />
<string>PSLinkCell</string><br />
<key>icon</key><br />
<string>TweakIcon@2x.png</string><br />
<key>label</key><br />
<string>Tweak Name</string><br />
</dict><br />
<br />
<key>items</key><br />
<array><br />
<br />
</array><br />
<key>title</key><br />
<string>Demo</string><br />
</dict><br />
</plist><br />
</source><br />
<br />
The various cells and items are put between the array tags.<br />
<br />
=== Example with PSEditTextCell ===<br />
<br />
Though there is nothing all that special about this cell, it is a good example of how to make other cells.<br />
<br />
<source lang="xml"><br />
<dict><br />
<key>cell</key><br />
<string>PSEditTextCell</string><br />
<key>placeholder</key><br />
<string>0.2</string><br />
<key>bestGuess</key><br />
<string>0.2</string><br />
<key>defaults</key><br />
<string>com.yourname.yourtweak</string><br />
<key>isDecimalPad</key><br />
<true/><br />
<key>key</key><br />
<string>savedName</string><br />
<key>label</key><br />
<string>Visible Name:</string><br />
</dict><br />
</source><br />
This would make an input text cell for numbers. Use the keys specified above to change its properties and appearance. This goes for any cell.<br />
<br />
== External links ==<br />
<br />
* https://code.google.com/p/networkpx/wiki/PreferencesSpecifierPlistFormat<br />
<br />
[[Category:Preferences]]</div>PoomSmarthttps://iphonedev.wiki/index.php?title=LibMobileGestalt.dylib&diff=5681LibMobileGestalt.dylib2021-05-22T10:56:45Z<p>PoomSmart: /* References */</p>
<hr />
<div>{{DISPLAYTITLE:libMobileGestalt.dylib}}<br />
<br />
'''libMobileGestalt''' is a library that can be used to get various system values such as the UDID, disk usage, device version and much more. It is comparable to [[liblockdown.dylib]]. See also [[lockdownd]].<br />
<br />
== MGCopyAnswer ==<br />
<source lang=c><br />
// Common form: MGCopyAnswer(CFStringRef string);<br />
CFStringRef value = MGCopyAnswer(kMGDeviceColor);<br />
NSLog(@"Value: %@", value);<br />
CFRelease(value);<br />
</source><br />
<br />
== MGGetBoolAnswer (iOS 7+) ==<br />
<source lang=c><br />
// bool MGGetBoolAnswer(CFStringRef key);<br />
bool value = MGGetBoolAnswer(CFSTR("UIProceduralWallpaperCapability"));<br />
NSLog(@"Value: %d", value);<br />
</source><br />
<br />
== References ==<br />
* Header: https://github.com/theos/headers/blob/master/MobileGestalt/MobileGestalt.h<br />
<br />
== External links ==<br />
* [https://blog.timac.org/2017/0124-deobfuscating-libmobilegestalt-keys/ Deobfuscating libMobileGestalt keys]<br />
* [https://github.com/PoomSmart/MGKeys List of all decrypted keys]<br />
<br />
{{Navbox Frameworks}}<br />
[[Category:Dynamic Libraries]]</div>PoomSmarthttps://iphonedev.wiki/index.php?title=SpringBoardHome.framework&diff=5678SpringBoardHome.framework2021-05-16T06:53:15Z<p>PoomSmart: Added screen types</p>
<hr />
<div>{{infobox Framework<br />
| vis = Private<br />
| since = 13.0<br />
| classID = SB / SBH<br />
}}<br />
<br />
'''SpringBoardHome''' is a framework that provides classes to deal with Homescreen Icon List elements in SpringBoard.<br />
<br />
Many of the classes dealing with icons that were previously contained in SpringBoard itself were moved here. It appears that the majority of classes dealing with the "Home Screen," a la Icons, the sidebar, etc. are being moved to this framework.<br />
<br />
More classes were moved to this framework with iOS 14, and it appears to have "taken the reins" in regards to icon placement and movement.<br />
<br />
== Screen Type ==<br />
<br />
Apple represents types of screens of all iOS/iPadOS devices as an integer. By reversing the function <code>SBHStringForScreenType</code>, we can derive all the values:<br />
<br />
<source lang="objc"><br />
<br />
typedef NS_ENUM(NSInteger, SBHScreenType) {<br />
SBHScreenTypeiPhone5 = 0,<br />
SBHScreenTypeiPhone6 = 1,<br />
SBHScreenTypeiPhone6Plus = 2,<br />
SBHScreenTypeiPhoneX = 3,<br />
SBHScreenTypeiPhoneXZoomed = 4,<br />
SBHScreenTypeiPhoneXsMax = 5,<br />
SBHScreenTypeiPhoneXsMaxZoomed = 6,<br />
SBHScreenTypeiPhoneXr = 7,<br />
SBHScreenTypeiPhoneXrZoomed = 8,<br />
SBHScreenTypeiPhone12Mini = 9,<br />
SBHScreenTypeiPhone12MiniZoomed = 10,<br />
SBHScreenTypeiPhone12 = 11,<br />
SBHScreenTypeiPhone12Zoomed = 12,<br />
SBHScreenTypeiPhone12ProMax = 13,<br />
SBHScreenTypeiPhone12ProMaxZoomed = 14,<br />
SBHScreenTypeiPad3 = 15,<br />
SBHScreenTypeiPadMini2 = 16,<br />
SBHScreenTypeiPad7 = 17,<br />
SBHScreenTypeiPadPro1 = 18,<br />
SBHScreenTypeiPadPro2 = 19,<br />
SBHScreenTypeiPadAir4 = 20,<br />
SBHScreenTypeiPadPro3 = 21,<br />
SBHScreenTypeiPadPro3Large = 22,<br />
SBHScreenTypeiPadPro3LargeZoomed = 23<br />
};<br />
<br />
</source><br />
<br />
* [https://developer.limneos.net/?ios=13.1.3&framework=SpringBoardHome.framework iOS 13 Headers]<br />
<br />
{{Navbox Frameworks}}</div>PoomSmarthttps://iphonedev.wiki/index.php?title=Libundirect&diff=5675Libundirect2021-05-09T13:58:23Z<p>PoomSmart: </p>
<hr />
<div>{{DISPLAYTITLE:libundirect}}<br />
{{Infobox Package<br />
|developer=[https://twitter.com/opa334dev Lars Fröder (opa334)]<br />
|version=1.1.1<br />
|package=com.opa334.libundirect<br />
}}<br />
<br />
'''libundirect''' is a patchfinding and rebinding 64-bit library that provides directives to hook Objective-C direct methods. With the feature called <code>objc_direct</code> introduced in Xcode 12 and iOS 14.0, these direct methods are stripped when compiled - being unexported C functions and thus their signature and name are missing.<br />
<br />
As a patchfinder, <code>libundirect_find()</code> can find the address of the function to hook by providing unique bytes within the function and the name of the binary or library that the function resides. You need to perform reverse engineering on the binary that you are working with in order to determine the bytes to use. See [https://github.com/opa334/libundirect/blob/main/README.md#patchfinder libundirect's note on patchfinding] or [https://gist.github.com/johnzaro/fdffd93c2ee0bc7db56d7959a67b4235 johnzaro's guide to using libundirect] for more details.<br />
<br />
As a rebinder, <code>libundirect_rebind()</code> can re-add Objective-C method signature to the function that you hook. This provides backward compatibility for earlier iOS versions that the signature is still intact - and that you have to import <code><libundirect/libundirect_hookoverwrite.h></code> to make <code>MSHookMessageEx()</code> aware of direct methods and turn itself into <code>MSHookFunction</code> (because it is just a C-like function now).<br />
<br />
== How to use this library ==<br />
<br />
Headers are available from [https://github.com/opa334/libundirect libundirect's GitHub project] or from [https://github.com/theos/headers Theos' headers project]. The library can be installed to <code>$THEOS/vendor/lib</code> by running <code>install_to_theos.sh</code> script inside libundirect repository.<br />
<br />
=== Include directive(s) ===<br />
<br />
<source lang="objc"><br />
#import <libundirect/libundirect.h><br />
#import <libundirect/libundirect_dynamic.h> // if you don't want to link directly against libundirect, import this one instead<br />
#import <libundirect/libundirect_hookoverwrite.h> // if you want backward compatibility<br />
</source><br />
<br />
=== Makefile ===<br />
<br />
Add to your Makefile:<br />
<br />
* <code>XXX_LIBRARIES = undirect</code><br />
<br />
=== Packaging ===<br />
<br />
Add to your package's control file:<br />
<br />
* <code>com.opa334.libundirect (>= 1.1.1)</code> to the <code>Depends</code> field.<br />
<br />
== Examples ==<br />
<br />
=== Hooking (and rebinding) a direct Objective-C method (MobileSafari) ===<br />
<br />
We will use the code in SafariPlus by opa334 as an example.<br />
<br />
<source lang="objc"><br />
#import <libundirect/libundirect.h><br />
#import <libundirect/libundirect_hookoverwrite.h><br />
#import <version.h><br />
<br />
%hook BrowserController<br />
<br />
- (void)tabControllerDocumentCountDidChange:(TabController *)tabController {<br />
%orig;<br />
...<br />
}<br />
<br />
%end<br />
<br />
...<br />
<br />
// In your constructor:<br />
<br />
if (IS_IOS_OR_NEWER(iOS_14_0)) {<br />
Class class_browserController = NSClassFromString(@"BrowserController");<br />
<br />
// -[BrowserController tabControllerDocumentCountDidChange:]<br />
// arm64 memory of function: [600100B4 F44FBEA9]<br />
// arm64e memory of function: [A00100B4 7F2303D5 F44FBEA9]<br />
// criteria: called by -[BrowserController _updateSceneTitle] (14.2: sub_100041e5c, references string @"Private Browsing")<br />
// 14.2: sub_10005bef8, arm64e: sub_10005E824<br />
<br />
#if __arm64e__<br />
void* tabControllerDocumentCountDidChange = libundirect_find(@"MobileSafari", (unsigned char[]){0xA0, 0x01, 0x00, 0xB4, 0x7F, 0x23, 0x03, 0xD5, 0xF4, 0x4F, 0xBE, 0xA9}, 12, 0);<br />
#else<br />
void* tabControllerDocumentCountDidChange = libundirect_find(@"MobileSafari", (unsigned char[]){0x60, 0x01, 0x00, 0xB4, 0xF4, 0x4F, 0xBE, 0xA9}, 8, 0);<br />
#endif<br />
<br />
libundirect_rebind(tabControllerDocumentCountDidChange, class_browserController, @selector(tabControllerDocumentCountDidChange:), "v@:@");<br />
}<br />
<br />
%init;<br />
</source><br />
<br />
=== Hooking an unnamed C function (libicucore) ===<br />
<br />
We will use the code in EmojiAttributes by PoomSmart as an example.<br />
<br />
<source lang="objc"><br />
#import <libundirect/libundirect.h><br />
<br />
...<br />
<br />
%group getUnicodeProperties<br />
<br />
%hookf(uint32_t, u_getUnicodeProperties, UChar32 c, int32_t column) {<br />
if (column >= propsVectorsColumns)<br />
return 0;<br />
uint16_t vecIndex = UTRIE2_GET16(&propsVectorsTrie, c);<br />
return propsVectors[vecIndex + column];<br />
}<br />
<br />
%end<br />
<br />
// In your constructor:<br />
<br />
#if TARGET_OS_SIMULATOR<br />
// Memory of function (iOS 13.5): 31C083FE 020F8F8D 00000055 4889E581 FFFFD700 00770789 F8C1E805 EB4A81FF FFFF0000 771731C0 81FF00DC 0000B940 0100000F 4DC889F8 C1E805EB 29B8D813 000081FF FFFF1000 773289F8 C1E80B48 8D0D30CC 1B000FB7 8C414010 000089F8 C1E80583 E03F01C8 89C0488D 0D15CC1B 000FB704 4183E71F 488D0487 488D0D03 CC1B000F B7044148 63CE4801 C1488D05 D2B11A00 8B04885D C3<br />
// Memory of function (iOS 12.4): 554889E5 31C083FE 020F8F8A 00000081 FFFFD700 00770789 F8C1E805 EB4C81FF FFFF0000 771731C0 81FF00DC 0000B940 0100000F 4DC889F8 C1E805EB 2B81FFFF FF100076 07B8D413 0000EB32 89F8C1E8 0B488D0D CFE61B00 0FB78C41 40100000 89F8C1E8 0583E03F 01C889C0 488D0DB4 E61B000F B7044183 E71F488D 0487488D 0DA2E61B 000FB704 414863CE 4801C148 8D0571D3 1A008B04 885DC3<br />
// Unique bytes (iOS 13.5): E03F01C8 89C0488D 0D15CC1B (offset: 100)<br />
// Unique bytes (iOS 12.4): 0583E03F 01C889C0 488D0DB4 (offset: 100)<br />
// Starting byte (iOS 13.5): 0x31<br />
// Starting byte (iOS 12.4): 0x55<br />
void *rp = libundirect_find(@"libicucore.A.dylib", (unsigned char[]){0xE0, 0x3F, 0x01, 0xC8, 0x89, 0xC0, 0x48, 0x8D, 0x0D, 0x15, 0xCC, 0x1B}, 12, 0x31);<br />
if (rp == NULL)<br />
rp = libundirect_find(@"libicucore.A.dylib", (unsigned char[]){0x05, 0x83, 0xE0, 0x3F, 0x01, 0xC8, 0x89, 0xC0, 0x48, 0x8D, 0x0D, 0xB4}, 12, 0x55);<br />
#else<br />
// Memory of function: 3F080071 6D000054 00008052 C0035FD6 087C0B53 1F690071 68000054 087C0513 08000014 087C1053 68020035 08809B52 1F00086B 08288052 08B19F1A 0815800B 090D00B0 29110F91 28D96878 09100012 2809080B 090D00B0 29110F91 28D96878 0801010B 890C00B0 29A12791 20D968B8 C0035FD6 1F410071 69000054 08548252 F5FFFF17 087C0B13 090D00B0 29110F91 28C5288B 08816079 0A280553 08412A8B 28796878 EAFFFF17<br />
// Unique bytes: 3F080071 6D000054 00008052 C0035FD6 (offset: 0)<br />
// Starting byte: 0x3F<br />
void *rp = libundirect_find(@"libicucore.A.dylib", (unsigned char[]){0x3F, 0x08, 0x00, 0x71, 0x6D, 0x00, 0x00, 0x54, 0x00, 0x00, 0x80, 0x52, 0xC0, 0x03, 0x5F, 0xD6}, 16, 0x3F);<br />
#endif<br />
<br />
%init(getUnicodeProperties, u_getUnicodeProperties = (void *)rp);<br />
</source><br />
<br />
== Project Examples ==<br />
<br />
{| class="wikitable"<br />
|-<br />
! Project<br />
! Author<br />
|-<br />
| [https://github.com/opa334/SafariPlus SafariPlus]<br />
| [https://github.com/opa334 opa334]<br />
|-<br />
| [https://github.com/udevsharold/safaritabs14 SafariTabs14]<br />
| [https://github.com/udevsharold udevsharold]<br />
|-<br />
| [https://github.com/p2kdev/SafariBlocker SafariBlocker]<br />
| [https://github.com/p2kdev p2kdev]<br />
|-<br />
| [https://github.com/PoomSmart/EmojiAttributes EmojiAttributes]<br />
| [https://github.com/PoomSmart PoomSmart]<br />
|}<br />
<br />
== External Links ==<br />
<br />
* [https://github.com/opa334/libundirect/blob/main/README.md libundirect's detailed usages]<br />
* [https://gist.github.com/johnzaro/fdffd93c2ee0bc7db56d7959a67b4235 Using disassembler to find unique bytes for libundirect]<br />
* [https://nshipster.com/direct/ Objective-C Direct Methods]<br />
<br />
{{Navbox Library}}<br />
<br />
[[Category:Cydia packages]]<br />
<br />
[[Category:Directories in /Library]]</div>PoomSmarthttps://iphonedev.wiki/index.php?title=Libundirect&diff=5674Libundirect2021-05-09T09:44:39Z<p>PoomSmart: /* Makefile */</p>
<hr />
<div>{{DISPLAYTITLE:libundirect}}<br />
{{Infobox Package<br />
|developer=[https://twitter.com/opa334dev Lars Fröder (opa334)]<br />
|version=1.1.1<br />
|package=com.opa334.libundirect<br />
}}<br />
<br />
'''libundirect''' is a patchfinding and rebinding 64-bit library that provides directives to hook Objective-C direct methods. With the feature called objc_direct introduced in Xcode 12 and iOS 14.0, these direct methods are stripped when compiled - being unexported C functions and thus their signature and name are missing.<br />
<br />
As a patchfinder, <code>libundirect_find()</code> can find the address of the function to hook by providing unique bytes within the function and the name of the binary that the function resides. You need to perform reverse engineering on the binary that you are working with in order to determine the bytes to use. See [https://github.com/opa334/libundirect/blob/main/README.md#patchfinder here] or [https://gist.github.com/johnzaro/fdffd93c2ee0bc7db56d7959a67b4235 here] for more details.<br />
<br />
As a rebinder, <code>libundirect_rebind()</code> can re-add Objective-C method signature to the function that you hook. This provides backward compatibility for earlier iOS versions that the signature is still intact - and that you have to import <code><libundirect/libundirect_hookoverwrite.h></code> to make <code>MSHookMessageEx()</code> aware of direct methods.<br />
<br />
== How to use this library ==<br />
<br />
Headers are available from [https://github.com/opa334/libundirect libundirect's GitHub project] or from [https://github.com/theos/headers Theos' headers project]. The library can be installed to <code>$THEOS/vendor/lib</code> by running <code>install_to_theos.sh</code> script inside libundirect repository.<br />
<br />
=== Include directive(s) ===<br />
<br />
<source lang="objc"><br />
#import <libundirect/libundirect.h><br />
#import <libundirect/libundirect_dynamic.h> // if you don't want to link directly against libundirect, import this one instead<br />
#import <libundirect/libundirect_hookoverwrite.h> // if you want backward compatibility<br />
</source><br />
<br />
=== Makefile ===<br />
<br />
Add to your Makefile:<br />
<br />
* <code>XXX_LIBRARIES = undirect</code><br />
<br />
=== Packaging ===<br />
<br />
Add to your package's control file:<br />
<br />
* <code>com.opa334.libundirect (>= 1.1.1)</code> to the <code>Depends</code> field.<br />
<br />
== Examples ==<br />
<br />
=== Hooking (and rebinding) a direct Objective-C method (MobileSafari) ===<br />
<br />
We will use the code in SafariPlus by opa334 as an example.<br />
<br />
<source lang="objc"><br />
#import <libundirect/libundirect.h><br />
#import <libundirect/libundirect_hookoverwrite.h><br />
#import <version.h><br />
<br />
%hook BrowserController<br />
<br />
- (void)tabControllerDocumentCountDidChange:(TabController *)tabController {<br />
%orig;<br />
...<br />
}<br />
<br />
%end<br />
<br />
...<br />
<br />
// In your constructor:<br />
<br />
if (IS_IOS_OR_NEWER(iOS_14_0)) {<br />
Class class_browserController = NSClassFromString(@"BrowserController");<br />
<br />
// -[BrowserController tabControllerDocumentCountDidChange:]<br />
// arm64 memory of function: [600100B4 F44FBEA9]<br />
// arm64e memory of function: [A00100B4 7F2303D5 F44FBEA9]<br />
// criteria: called by -[BrowserController _updateSceneTitle] (14.2: sub_100041e5c, references string @"Private Browsing")<br />
// 14.2: sub_10005bef8, arm64e: sub_10005E824<br />
<br />
#if __arm64e__<br />
void* tabControllerDocumentCountDidChange = libundirect_find(@"MobileSafari", (unsigned char[]){0xA0, 0x01, 0x00, 0xB4, 0x7F, 0x23, 0x03, 0xD5, 0xF4, 0x4F, 0xBE, 0xA9}, 12, 0);<br />
#else<br />
void* tabControllerDocumentCountDidChange = libundirect_find(@"MobileSafari", (unsigned char[]){0x60, 0x01, 0x00, 0xB4, 0xF4, 0x4F, 0xBE, 0xA9}, 8, 0);<br />
#endif<br />
<br />
libundirect_rebind(tabControllerDocumentCountDidChange, class_browserController, @selector(tabControllerDocumentCountDidChange:), "v@:@");<br />
}<br />
<br />
%init;<br />
</source><br />
<br />
=== Hooking an unnamed C function (libicucore) ===<br />
<br />
We will use the code in EmojiAttributes by PoomSmart as an example.<br />
<br />
<source lang="objc"><br />
#import <libundirect/libundirect.h><br />
<br />
...<br />
<br />
%group getUnicodeProperties<br />
<br />
%hookf(uint32_t, u_getUnicodeProperties, UChar32 c, int32_t column) {<br />
if (column >= propsVectorsColumns)<br />
return 0;<br />
uint16_t vecIndex = UTRIE2_GET16(&propsVectorsTrie, c);<br />
return propsVectors[vecIndex + column];<br />
}<br />
<br />
%end<br />
<br />
// In your constructor:<br />
<br />
#if TARGET_OS_SIMULATOR<br />
// Memory of function (iOS 13.5): 31C083FE 020F8F8D 00000055 4889E581 FFFFD700 00770789 F8C1E805 EB4A81FF FFFF0000 771731C0 81FF00DC 0000B940 0100000F 4DC889F8 C1E805EB 29B8D813 000081FF FFFF1000 773289F8 C1E80B48 8D0D30CC 1B000FB7 8C414010 000089F8 C1E80583 E03F01C8 89C0488D 0D15CC1B 000FB704 4183E71F 488D0487 488D0D03 CC1B000F B7044148 63CE4801 C1488D05 D2B11A00 8B04885D C3<br />
// Memory of function (iOS 12.4): 554889E5 31C083FE 020F8F8A 00000081 FFFFD700 00770789 F8C1E805 EB4C81FF FFFF0000 771731C0 81FF00DC 0000B940 0100000F 4DC889F8 C1E805EB 2B81FFFF FF100076 07B8D413 0000EB32 89F8C1E8 0B488D0D CFE61B00 0FB78C41 40100000 89F8C1E8 0583E03F 01C889C0 488D0DB4 E61B000F B7044183 E71F488D 0487488D 0DA2E61B 000FB704 414863CE 4801C148 8D0571D3 1A008B04 885DC3<br />
// Unique bytes (iOS 13.5): E03F01C8 89C0488D 0D15CC1B (offset: 100)<br />
// Unique bytes (iOS 12.4): 0583E03F 01C889C0 488D0DB4 (offset: 100)<br />
// Starting byte (iOS 13.5): 0x31<br />
// Starting byte (iOS 12.4): 0x55<br />
void *rp = libundirect_find(@"libicucore.A.dylib", (unsigned char[]){0xE0, 0x3F, 0x01, 0xC8, 0x89, 0xC0, 0x48, 0x8D, 0x0D, 0x15, 0xCC, 0x1B}, 12, 0x31);<br />
if (rp == NULL)<br />
rp = libundirect_find(@"libicucore.A.dylib", (unsigned char[]){0x05, 0x83, 0xE0, 0x3F, 0x01, 0xC8, 0x89, 0xC0, 0x48, 0x8D, 0x0D, 0xB4}, 12, 0x55);<br />
#else<br />
// Memory of function: 3F080071 6D000054 00008052 C0035FD6 087C0B53 1F690071 68000054 087C0513 08000014 087C1053 68020035 08809B52 1F00086B 08288052 08B19F1A 0815800B 090D00B0 29110F91 28D96878 09100012 2809080B 090D00B0 29110F91 28D96878 0801010B 890C00B0 29A12791 20D968B8 C0035FD6 1F410071 69000054 08548252 F5FFFF17 087C0B13 090D00B0 29110F91 28C5288B 08816079 0A280553 08412A8B 28796878 EAFFFF17<br />
// Unique bytes: 3F080071 6D000054 00008052 C0035FD6 (offset: 0)<br />
// Starting byte: 0x3F<br />
void *rp = libundirect_find(@"libicucore.A.dylib", (unsigned char[]){0x3F, 0x08, 0x00, 0x71, 0x6D, 0x00, 0x00, 0x54, 0x00, 0x00, 0x80, 0x52, 0xC0, 0x03, 0x5F, 0xD6}, 16, 0x3F);<br />
#endif<br />
<br />
%init(getUnicodeProperties, u_getUnicodeProperties = (void *)rp);<br />
</source><br />
<br />
== Project Examples ==<br />
<br />
{| class="wikitable"<br />
|-<br />
! Project<br />
! Author<br />
|-<br />
| [https://github.com/opa334/SafariPlus SafariPlus]<br />
| [https://github.com/opa334 opa334]<br />
|-<br />
| [https://github.com/udevsharold/safaritabs14 SafariTabs14]<br />
| [https://github.com/udevsharold udevsharold]<br />
|-<br />
| [https://github.com/p2kdev/SafariBlocker SafariBlocker]<br />
| [https://github.com/p2kdev p2kdev]<br />
|-<br />
| [https://github.com/PoomSmart/EmojiAttributes EmojiAttributes]<br />
| [https://github.com/PoomSmart PoomSmart]<br />
|}<br />
<br />
== External Links ==<br />
<br />
* [https://github.com/opa334/libundirect/blob/main/README.md libundirect's detailed usages]<br />
* [https://gist.github.com/johnzaro/fdffd93c2ee0bc7db56d7959a67b4235 Using disassembler to find unique bytes for libundirect]<br />
* [https://nshipster.com/direct/ Objective-C Direct Methods]<br />
<br />
{{Navbox Library}}<br />
<br />
[[Category:Cydia packages]]<br />
<br />
[[Category:Directories in /Library]]</div>PoomSmarthttps://iphonedev.wiki/index.php?title=Libundirect&diff=5673Libundirect2021-05-09T09:18:28Z<p>PoomSmart: /* Project Examples */</p>
<hr />
<div>{{DISPLAYTITLE:libundirect}}<br />
{{Infobox Package<br />
|developer=[https://twitter.com/opa334dev Lars Fröder (opa334)]<br />
|version=1.1.1<br />
|package=com.opa334.libundirect<br />
}}<br />
<br />
'''libundirect''' is a patchfinding and rebinding 64-bit library that provides directives to hook Objective-C direct methods. With the feature called objc_direct introduced in Xcode 12 and iOS 14.0, these direct methods are stripped when compiled - being unexported C functions and thus their signature and name are missing.<br />
<br />
As a patchfinder, <code>libundirect_find()</code> can find the address of the function to hook by providing unique bytes within the function and the name of the binary that the function resides. You need to perform reverse engineering on the binary that you are working with in order to determine the bytes to use. See [https://github.com/opa334/libundirect/blob/main/README.md#patchfinder here] or [https://gist.github.com/johnzaro/fdffd93c2ee0bc7db56d7959a67b4235 here] for more details.<br />
<br />
As a rebinder, <code>libundirect_rebind()</code> can re-add Objective-C method signature to the function that you hook. This provides backward compatibility for earlier iOS versions that the signature is still intact - and that you have to import <code><libundirect/libundirect_hookoverwrite.h></code> to make <code>MSHookMessageEx()</code> aware of direct methods.<br />
<br />
== How to use this library ==<br />
<br />
Headers are available from [https://github.com/opa334/libundirect libundirect's GitHub project] or from [https://github.com/theos/headers Theos' headers project]. The library can be installed to <code>$THEOS/vendor/lib</code> by running <code>install_to_theos.sh</code> script inside libundirect repository.<br />
<br />
=== Include directive(s) ===<br />
<br />
<source lang="objc"><br />
#import <libundirect/libundirect.h><br />
#import <libundirect/libundirect_dynamic.h> // if you don't want to link directly against libundirect, import this one instead<br />
#import <libundirect/libundirect_hookoverwrite.h> // if you want backward compatibility<br />
</source><br />
<br />
=== Makefile ===<br />
<br />
Add to your Makefile:<br />
<br />
* <code>libundirect</code> to the <code>XXX_LIBRARIES</code> variable.<br />
<br />
=== Packaging ===<br />
<br />
Add to your package's control file:<br />
<br />
* <code>com.opa334.libundirect (>= 1.1.1)</code> to the <code>Depends</code> field.<br />
<br />
== Examples ==<br />
<br />
=== Hooking (and rebinding) a direct Objective-C method (MobileSafari) ===<br />
<br />
We will use the code in SafariPlus by opa334 as an example.<br />
<br />
<source lang="objc"><br />
#import <libundirect/libundirect.h><br />
#import <libundirect/libundirect_hookoverwrite.h><br />
#import <version.h><br />
<br />
%hook BrowserController<br />
<br />
- (void)tabControllerDocumentCountDidChange:(TabController *)tabController {<br />
%orig;<br />
...<br />
}<br />
<br />
%end<br />
<br />
...<br />
<br />
// In your constructor:<br />
<br />
if (IS_IOS_OR_NEWER(iOS_14_0)) {<br />
Class class_browserController = NSClassFromString(@"BrowserController");<br />
<br />
// -[BrowserController tabControllerDocumentCountDidChange:]<br />
// arm64 memory of function: [600100B4 F44FBEA9]<br />
// arm64e memory of function: [A00100B4 7F2303D5 F44FBEA9]<br />
// criteria: called by -[BrowserController _updateSceneTitle] (14.2: sub_100041e5c, references string @"Private Browsing")<br />
// 14.2: sub_10005bef8, arm64e: sub_10005E824<br />
<br />
#if __arm64e__<br />
void* tabControllerDocumentCountDidChange = libundirect_find(@"MobileSafari", (unsigned char[]){0xA0, 0x01, 0x00, 0xB4, 0x7F, 0x23, 0x03, 0xD5, 0xF4, 0x4F, 0xBE, 0xA9}, 12, 0);<br />
#else<br />
void* tabControllerDocumentCountDidChange = libundirect_find(@"MobileSafari", (unsigned char[]){0x60, 0x01, 0x00, 0xB4, 0xF4, 0x4F, 0xBE, 0xA9}, 8, 0);<br />
#endif<br />
<br />
libundirect_rebind(tabControllerDocumentCountDidChange, class_browserController, @selector(tabControllerDocumentCountDidChange:), "v@:@");<br />
}<br />
<br />
%init;<br />
</source><br />
<br />
=== Hooking an unnamed C function (libicucore) ===<br />
<br />
We will use the code in EmojiAttributes by PoomSmart as an example.<br />
<br />
<source lang="objc"><br />
#import <libundirect/libundirect.h><br />
<br />
...<br />
<br />
%group getUnicodeProperties<br />
<br />
%hookf(uint32_t, u_getUnicodeProperties, UChar32 c, int32_t column) {<br />
if (column >= propsVectorsColumns)<br />
return 0;<br />
uint16_t vecIndex = UTRIE2_GET16(&propsVectorsTrie, c);<br />
return propsVectors[vecIndex + column];<br />
}<br />
<br />
%end<br />
<br />
// In your constructor:<br />
<br />
#if TARGET_OS_SIMULATOR<br />
// Memory of function (iOS 13.5): 31C083FE 020F8F8D 00000055 4889E581 FFFFD700 00770789 F8C1E805 EB4A81FF FFFF0000 771731C0 81FF00DC 0000B940 0100000F 4DC889F8 C1E805EB 29B8D813 000081FF FFFF1000 773289F8 C1E80B48 8D0D30CC 1B000FB7 8C414010 000089F8 C1E80583 E03F01C8 89C0488D 0D15CC1B 000FB704 4183E71F 488D0487 488D0D03 CC1B000F B7044148 63CE4801 C1488D05 D2B11A00 8B04885D C3<br />
// Memory of function (iOS 12.4): 554889E5 31C083FE 020F8F8A 00000081 FFFFD700 00770789 F8C1E805 EB4C81FF FFFF0000 771731C0 81FF00DC 0000B940 0100000F 4DC889F8 C1E805EB 2B81FFFF FF100076 07B8D413 0000EB32 89F8C1E8 0B488D0D CFE61B00 0FB78C41 40100000 89F8C1E8 0583E03F 01C889C0 488D0DB4 E61B000F B7044183 E71F488D 0487488D 0DA2E61B 000FB704 414863CE 4801C148 8D0571D3 1A008B04 885DC3<br />
// Unique bytes (iOS 13.5): E03F01C8 89C0488D 0D15CC1B (offset: 100)<br />
// Unique bytes (iOS 12.4): 0583E03F 01C889C0 488D0DB4 (offset: 100)<br />
// Starting byte (iOS 13.5): 0x31<br />
// Starting byte (iOS 12.4): 0x55<br />
void *rp = libundirect_find(@"libicucore.A.dylib", (unsigned char[]){0xE0, 0x3F, 0x01, 0xC8, 0x89, 0xC0, 0x48, 0x8D, 0x0D, 0x15, 0xCC, 0x1B}, 12, 0x31);<br />
if (rp == NULL)<br />
rp = libundirect_find(@"libicucore.A.dylib", (unsigned char[]){0x05, 0x83, 0xE0, 0x3F, 0x01, 0xC8, 0x89, 0xC0, 0x48, 0x8D, 0x0D, 0xB4}, 12, 0x55);<br />
#else<br />
// Memory of function: 3F080071 6D000054 00008052 C0035FD6 087C0B53 1F690071 68000054 087C0513 08000014 087C1053 68020035 08809B52 1F00086B 08288052 08B19F1A 0815800B 090D00B0 29110F91 28D96878 09100012 2809080B 090D00B0 29110F91 28D96878 0801010B 890C00B0 29A12791 20D968B8 C0035FD6 1F410071 69000054 08548252 F5FFFF17 087C0B13 090D00B0 29110F91 28C5288B 08816079 0A280553 08412A8B 28796878 EAFFFF17<br />
// Unique bytes: 3F080071 6D000054 00008052 C0035FD6 (offset: 0)<br />
// Starting byte: 0x3F<br />
void *rp = libundirect_find(@"libicucore.A.dylib", (unsigned char[]){0x3F, 0x08, 0x00, 0x71, 0x6D, 0x00, 0x00, 0x54, 0x00, 0x00, 0x80, 0x52, 0xC0, 0x03, 0x5F, 0xD6}, 16, 0x3F);<br />
#endif<br />
<br />
%init(getUnicodeProperties, u_getUnicodeProperties = (void *)rp);<br />
</source><br />
<br />
== Project Examples ==<br />
<br />
{| class="wikitable"<br />
|-<br />
! Project<br />
! Author<br />
|-<br />
| [https://github.com/opa334/SafariPlus SafariPlus]<br />
| [https://github.com/opa334 opa334]<br />
|-<br />
| [https://github.com/udevsharold/safaritabs14 SafariTabs14]<br />
| [https://github.com/udevsharold udevsharold]<br />
|-<br />
| [https://github.com/p2kdev/SafariBlocker SafariBlocker]<br />
| [https://github.com/p2kdev p2kdev]<br />
|-<br />
| [https://github.com/PoomSmart/EmojiAttributes EmojiAttributes]<br />
| [https://github.com/PoomSmart PoomSmart]<br />
|}<br />
<br />
== External Links ==<br />
<br />
* [https://github.com/opa334/libundirect/blob/main/README.md libundirect's detailed usages]<br />
* [https://gist.github.com/johnzaro/fdffd93c2ee0bc7db56d7959a67b4235 Using disassembler to find unique bytes for libundirect]<br />
* [https://nshipster.com/direct/ Objective-C Direct Methods]<br />
<br />
{{Navbox Library}}<br />
<br />
[[Category:Cydia packages]]<br />
<br />
[[Category:Directories in /Library]]</div>PoomSmarthttps://iphonedev.wiki/index.php?title=Libundirect&diff=5672Libundirect2021-05-09T03:50:39Z<p>PoomSmart: </p>
<hr />
<div>{{DISPLAYTITLE:libundirect}}<br />
{{Infobox Package<br />
|developer=[https://twitter.com/opa334dev Lars Fröder (opa334)]<br />
|version=1.1.1<br />
|package=com.opa334.libundirect<br />
}}<br />
<br />
'''libundirect''' is a patchfinding and rebinding 64-bit library that provides directives to hook Objective-C direct methods. With the feature called objc_direct introduced in Xcode 12 and iOS 14.0, these direct methods are stripped when compiled - being unexported C functions and thus their signature and name are missing.<br />
<br />
As a patchfinder, <code>libundirect_find()</code> can find the address of the function to hook by providing unique bytes within the function and the name of the binary that the function resides. You need to perform reverse engineering on the binary that you are working with in order to determine the bytes to use. See [https://github.com/opa334/libundirect/blob/main/README.md#patchfinder here] or [https://gist.github.com/johnzaro/fdffd93c2ee0bc7db56d7959a67b4235 here] for more details.<br />
<br />
As a rebinder, <code>libundirect_rebind()</code> can re-add Objective-C method signature to the function that you hook. This provides backward compatibility for earlier iOS versions that the signature is still intact - and that you have to import <code><libundirect/libundirect_hookoverwrite.h></code> to make <code>MSHookMessageEx()</code> aware of direct methods.<br />
<br />
== How to use this library ==<br />
<br />
Headers are available from [https://github.com/opa334/libundirect libundirect's GitHub project] or from [https://github.com/theos/headers Theos' headers project]. The library can be installed to <code>$THEOS/vendor/lib</code> by running <code>install_to_theos.sh</code> script inside libundirect repository.<br />
<br />
=== Include directive(s) ===<br />
<br />
<source lang="objc"><br />
#import <libundirect/libundirect.h><br />
#import <libundirect/libundirect_dynamic.h> // if you don't want to link directly against libundirect, import this one instead<br />
#import <libundirect/libundirect_hookoverwrite.h> // if you want backward compatibility<br />
</source><br />
<br />
=== Makefile ===<br />
<br />
Add to your Makefile:<br />
<br />
* <code>libundirect</code> to the <code>XXX_LIBRARIES</code> variable.<br />
<br />
=== Packaging ===<br />
<br />
Add to your package's control file:<br />
<br />
* <code>com.opa334.libundirect (>= 1.1.1)</code> to the <code>Depends</code> field.<br />
<br />
== Examples ==<br />
<br />
=== Hooking (and rebinding) a direct Objective-C method (MobileSafari) ===<br />
<br />
We will use the code in SafariPlus by opa334 as an example.<br />
<br />
<source lang="objc"><br />
#import <libundirect/libundirect.h><br />
#import <libundirect/libundirect_hookoverwrite.h><br />
#import <version.h><br />
<br />
%hook BrowserController<br />
<br />
- (void)tabControllerDocumentCountDidChange:(TabController *)tabController {<br />
%orig;<br />
...<br />
}<br />
<br />
%end<br />
<br />
...<br />
<br />
// In your constructor:<br />
<br />
if (IS_IOS_OR_NEWER(iOS_14_0)) {<br />
Class class_browserController = NSClassFromString(@"BrowserController");<br />
<br />
// -[BrowserController tabControllerDocumentCountDidChange:]<br />
// arm64 memory of function: [600100B4 F44FBEA9]<br />
// arm64e memory of function: [A00100B4 7F2303D5 F44FBEA9]<br />
// criteria: called by -[BrowserController _updateSceneTitle] (14.2: sub_100041e5c, references string @"Private Browsing")<br />
// 14.2: sub_10005bef8, arm64e: sub_10005E824<br />
<br />
#if __arm64e__<br />
void* tabControllerDocumentCountDidChange = libundirect_find(@"MobileSafari", (unsigned char[]){0xA0, 0x01, 0x00, 0xB4, 0x7F, 0x23, 0x03, 0xD5, 0xF4, 0x4F, 0xBE, 0xA9}, 12, 0);<br />
#else<br />
void* tabControllerDocumentCountDidChange = libundirect_find(@"MobileSafari", (unsigned char[]){0x60, 0x01, 0x00, 0xB4, 0xF4, 0x4F, 0xBE, 0xA9}, 8, 0);<br />
#endif<br />
<br />
libundirect_rebind(tabControllerDocumentCountDidChange, class_browserController, @selector(tabControllerDocumentCountDidChange:), "v@:@");<br />
}<br />
<br />
%init;<br />
</source><br />
<br />
=== Hooking an unnamed C function (libicucore) ===<br />
<br />
We will use the code in EmojiAttributes by PoomSmart as an example.<br />
<br />
<source lang="objc"><br />
#import <libundirect/libundirect.h><br />
<br />
...<br />
<br />
%group getUnicodeProperties<br />
<br />
%hookf(uint32_t, u_getUnicodeProperties, UChar32 c, int32_t column) {<br />
if (column >= propsVectorsColumns)<br />
return 0;<br />
uint16_t vecIndex = UTRIE2_GET16(&propsVectorsTrie, c);<br />
return propsVectors[vecIndex + column];<br />
}<br />
<br />
%end<br />
<br />
// In your constructor:<br />
<br />
#if TARGET_OS_SIMULATOR<br />
// Memory of function (iOS 13.5): 31C083FE 020F8F8D 00000055 4889E581 FFFFD700 00770789 F8C1E805 EB4A81FF FFFF0000 771731C0 81FF00DC 0000B940 0100000F 4DC889F8 C1E805EB 29B8D813 000081FF FFFF1000 773289F8 C1E80B48 8D0D30CC 1B000FB7 8C414010 000089F8 C1E80583 E03F01C8 89C0488D 0D15CC1B 000FB704 4183E71F 488D0487 488D0D03 CC1B000F B7044148 63CE4801 C1488D05 D2B11A00 8B04885D C3<br />
// Memory of function (iOS 12.4): 554889E5 31C083FE 020F8F8A 00000081 FFFFD700 00770789 F8C1E805 EB4C81FF FFFF0000 771731C0 81FF00DC 0000B940 0100000F 4DC889F8 C1E805EB 2B81FFFF FF100076 07B8D413 0000EB32 89F8C1E8 0B488D0D CFE61B00 0FB78C41 40100000 89F8C1E8 0583E03F 01C889C0 488D0DB4 E61B000F B7044183 E71F488D 0487488D 0DA2E61B 000FB704 414863CE 4801C148 8D0571D3 1A008B04 885DC3<br />
// Unique bytes (iOS 13.5): E03F01C8 89C0488D 0D15CC1B (offset: 100)<br />
// Unique bytes (iOS 12.4): 0583E03F 01C889C0 488D0DB4 (offset: 100)<br />
// Starting byte (iOS 13.5): 0x31<br />
// Starting byte (iOS 12.4): 0x55<br />
void *rp = libundirect_find(@"libicucore.A.dylib", (unsigned char[]){0xE0, 0x3F, 0x01, 0xC8, 0x89, 0xC0, 0x48, 0x8D, 0x0D, 0x15, 0xCC, 0x1B}, 12, 0x31);<br />
if (rp == NULL)<br />
rp = libundirect_find(@"libicucore.A.dylib", (unsigned char[]){0x05, 0x83, 0xE0, 0x3F, 0x01, 0xC8, 0x89, 0xC0, 0x48, 0x8D, 0x0D, 0xB4}, 12, 0x55);<br />
#else<br />
// Memory of function: 3F080071 6D000054 00008052 C0035FD6 087C0B53 1F690071 68000054 087C0513 08000014 087C1053 68020035 08809B52 1F00086B 08288052 08B19F1A 0815800B 090D00B0 29110F91 28D96878 09100012 2809080B 090D00B0 29110F91 28D96878 0801010B 890C00B0 29A12791 20D968B8 C0035FD6 1F410071 69000054 08548252 F5FFFF17 087C0B13 090D00B0 29110F91 28C5288B 08816079 0A280553 08412A8B 28796878 EAFFFF17<br />
// Unique bytes: 3F080071 6D000054 00008052 C0035FD6 (offset: 0)<br />
// Starting byte: 0x3F<br />
void *rp = libundirect_find(@"libicucore.A.dylib", (unsigned char[]){0x3F, 0x08, 0x00, 0x71, 0x6D, 0x00, 0x00, 0x54, 0x00, 0x00, 0x80, 0x52, 0xC0, 0x03, 0x5F, 0xD6}, 16, 0x3F);<br />
#endif<br />
<br />
%init(getUnicodeProperties, u_getUnicodeProperties = (void *)rp);<br />
</source><br />
<br />
== Project Examples ==<br />
<br />
{| class="wikitable"<br />
|-<br />
! Project<br />
! Author<br />
|-<br />
| [https://github.com/opa334/SafariPlus SafariPlus]<br />
| [https://github.com/opa334 opa334]<br />
|-<br />
| [https://github.com/udevsharold/safaritabs14 SafariTabs14]<br />
| [https://github.com/udevsharold udevsharold]<br />
|-<br />
| [https://github.com/PoomSmart/EmojiAttributes EmojiAttributes]<br />
| [https://github.com/PoomSmart PoomSmart]<br />
|}<br />
<br />
== External Links ==<br />
<br />
* [https://github.com/opa334/libundirect/blob/main/README.md libundirect's detailed usages]<br />
* [https://gist.github.com/johnzaro/fdffd93c2ee0bc7db56d7959a67b4235 Using disassembler to find unique bytes for libundirect]<br />
* [https://nshipster.com/direct/ Objective-C Direct Methods]<br />
<br />
{{Navbox Library}}<br />
<br />
[[Category:Cydia packages]]<br />
<br />
[[Category:Directories in /Library]]</div>PoomSmarthttps://iphonedev.wiki/index.php?title=Libundirect&diff=5671Libundirect2021-05-09T00:22:28Z<p>PoomSmart: /* External Links */</p>
<hr />
<div>{{DISPLAYTITLE:libundirect}}<br />
{{Infobox Package<br />
|developer=[https://twitter.com/opa334dev Lars Fröder (opa334)]<br />
|version=1.1.1<br />
|package=com.opa334.libundirect<br />
}}<br />
<br />
'''libundirect''' is a patchfinding and rebinding library that provides directives to hook Objective-C direct methods. With the feature called objc_direct introduced in Xcode 12 and iOS 14.0, these direct methods are stripped when compiled - being unexported C functions and thus their signature and name are missing.<br />
<br />
As a patchfinder, <code>libundirect_find()</code> can find the address of the function to hook by providing unique bytes within the function and the name of the binary that the function resides. You need to perform reverse engineering on the binary that you are working with in order to determine the bytes to use. See [https://github.com/opa334/libundirect/blob/main/README.md#patchfinder here] or [https://gist.github.com/johnzaro/fdffd93c2ee0bc7db56d7959a67b4235 here] for more details.<br />
<br />
As a rebinder, <code>libundirect_rebind()</code> can re-add Objective-C method signature to the function that you hook. This provides backward compatibility for earlier iOS versions that the signature is still intact - and that you have to import <code><libundirect/libundirect_hookoverwrite.h></code> to make <code>MSHookMessageEx()</code> aware of direct methods.<br />
<br />
== How to use this library ==<br />
<br />
Headers are available from [https://github.com/opa334/libundirect libundirect's GitHub project] or from [https://github.com/theos/headers Theos' headers project]. The library can be installed to <code>$THEOS/vendor/lib</code> by running <code>install_to_theos.sh</code> script inside libundirect repository.<br />
<br />
=== Include directive(s) ===<br />
<br />
<source lang="objc"><br />
#import <libundirect/libundirect.h><br />
#import <libundirect/libundirect_dynamic.h> // if you don't want to link directly against libundirect, import this one instead<br />
#import <libundirect/libundirect_hookoverwrite.h> // if you want backward compatibility<br />
</source><br />
<br />
=== Makefile ===<br />
<br />
Add to your Makefile:<br />
<br />
* <code>libundirect</code> to the <code>XXX_LIBRARIES</code> variable.<br />
<br />
=== Packaging ===<br />
<br />
Add to your package's control file:<br />
<br />
* <code>com.opa334.libundirect (>= 1.1.1)</code> to the <code>Depends</code> field.<br />
<br />
== Examples ==<br />
<br />
=== Hooking (and rebinding) a direct Objective-C method (MobileSafari) ===<br />
<br />
We will use the code in SafariPlus by opa334 as an example.<br />
<br />
<source lang="objc"><br />
#import <libundirect/libundirect.h><br />
#import <libundirect/libundirect_hookoverwrite.h><br />
#import <version.h><br />
<br />
%hook BrowserController<br />
<br />
- (void)tabControllerDocumentCountDidChange:(TabController *)tabController {<br />
%orig;<br />
...<br />
}<br />
<br />
%end<br />
<br />
...<br />
<br />
// In your constructor:<br />
<br />
if (IS_IOS_OR_NEWER(iOS_14_0)) {<br />
Class class_browserController = NSClassFromString(@"BrowserController");<br />
<br />
// -[BrowserController tabControllerDocumentCountDidChange:]<br />
// arm64 memory of function: [600100B4 F44FBEA9]<br />
// arm64e memory of function: [A00100B4 7F2303D5 F44FBEA9]<br />
// criteria: called by -[BrowserController _updateSceneTitle] (14.2: sub_100041e5c, references string @"Private Browsing")<br />
// 14.2: sub_10005bef8, arm64e: sub_10005E824<br />
<br />
#if __arm64e__<br />
void* tabControllerDocumentCountDidChange = libundirect_find(@"MobileSafari", (unsigned char[]){0xA0, 0x01, 0x00, 0xB4, 0x7F, 0x23, 0x03, 0xD5, 0xF4, 0x4F, 0xBE, 0xA9}, 12, 0);<br />
#else<br />
void* tabControllerDocumentCountDidChange = libundirect_find(@"MobileSafari", (unsigned char[]){0x60, 0x01, 0x00, 0xB4, 0xF4, 0x4F, 0xBE, 0xA9}, 8, 0);<br />
#endif<br />
<br />
libundirect_rebind(tabControllerDocumentCountDidChange, class_browserController, @selector(tabControllerDocumentCountDidChange:), "v@:@");<br />
}<br />
<br />
%init;<br />
</source><br />
<br />
=== Hooking an unnamed C function (libicucore) ===<br />
<br />
We will use the code in EmojiAttributes by PoomSmart as an example.<br />
<br />
<source lang="objc"><br />
#import <libundirect/libundirect.h><br />
<br />
...<br />
<br />
%group getUnicodeProperties<br />
<br />
%hookf(uint32_t, u_getUnicodeProperties, UChar32 c, int32_t column) {<br />
if (column >= propsVectorsColumns)<br />
return 0;<br />
uint16_t vecIndex = UTRIE2_GET16(&propsVectorsTrie, c);<br />
return propsVectors[vecIndex + column];<br />
}<br />
<br />
%end<br />
<br />
// In your constructor:<br />
<br />
#if TARGET_OS_SIMULATOR<br />
// Memory of function (iOS 13.5): 31C083FE 020F8F8D 00000055 4889E581 FFFFD700 00770789 F8C1E805 EB4A81FF FFFF0000 771731C0 81FF00DC 0000B940 0100000F 4DC889F8 C1E805EB 29B8D813 000081FF FFFF1000 773289F8 C1E80B48 8D0D30CC 1B000FB7 8C414010 000089F8 C1E80583 E03F01C8 89C0488D 0D15CC1B 000FB704 4183E71F 488D0487 488D0D03 CC1B000F B7044148 63CE4801 C1488D05 D2B11A00 8B04885D C3<br />
// Memory of function (iOS 12.4): 554889E5 31C083FE 020F8F8A 00000081 FFFFD700 00770789 F8C1E805 EB4C81FF FFFF0000 771731C0 81FF00DC 0000B940 0100000F 4DC889F8 C1E805EB 2B81FFFF FF100076 07B8D413 0000EB32 89F8C1E8 0B488D0D CFE61B00 0FB78C41 40100000 89F8C1E8 0583E03F 01C889C0 488D0DB4 E61B000F B7044183 E71F488D 0487488D 0DA2E61B 000FB704 414863CE 4801C148 8D0571D3 1A008B04 885DC3<br />
// Unique bytes (iOS 13.5): E03F01C8 89C0488D 0D15CC1B (offset: 100)<br />
// Unique bytes (iOS 12.4): 0583E03F 01C889C0 488D0DB4 (offset: 100)<br />
// Starting byte (iOS 13.5): 0x31<br />
// Starting byte (iOS 12.4): 0x55<br />
void *rp = libundirect_find(@"libicucore.A.dylib", (unsigned char[]){0xE0, 0x3F, 0x01, 0xC8, 0x89, 0xC0, 0x48, 0x8D, 0x0D, 0x15, 0xCC, 0x1B}, 12, 0x31);<br />
if (rp == NULL)<br />
rp = libundirect_find(@"libicucore.A.dylib", (unsigned char[]){0x05, 0x83, 0xE0, 0x3F, 0x01, 0xC8, 0x89, 0xC0, 0x48, 0x8D, 0x0D, 0xB4}, 12, 0x55);<br />
#else<br />
// Memory of function: 3F080071 6D000054 00008052 C0035FD6 087C0B53 1F690071 68000054 087C0513 08000014 087C1053 68020035 08809B52 1F00086B 08288052 08B19F1A 0815800B 090D00B0 29110F91 28D96878 09100012 2809080B 090D00B0 29110F91 28D96878 0801010B 890C00B0 29A12791 20D968B8 C0035FD6 1F410071 69000054 08548252 F5FFFF17 087C0B13 090D00B0 29110F91 28C5288B 08816079 0A280553 08412A8B 28796878 EAFFFF17<br />
// Unique bytes: 3F080071 6D000054 00008052 C0035FD6 (offset: 0)<br />
// Starting byte: 0x3F<br />
void *rp = libundirect_find(@"libicucore.A.dylib", (unsigned char[]){0x3F, 0x08, 0x00, 0x71, 0x6D, 0x00, 0x00, 0x54, 0x00, 0x00, 0x80, 0x52, 0xC0, 0x03, 0x5F, 0xD6}, 16, 0x3F);<br />
#endif<br />
<br />
%init(getUnicodeProperties, u_getUnicodeProperties = (void *)rp);<br />
</source><br />
<br />
== Project Examples ==<br />
<br />
{| class="wikitable"<br />
|-<br />
! Project<br />
! Author<br />
|-<br />
| [https://github.com/opa334/SafariPlus SafariPlus]<br />
| [https://github.com/opa334 opa334]<br />
|-<br />
| [https://github.com/udevsharold/safaritabs14 SafariTabs14]<br />
| [https://github.com/udevsharold udevsharold]<br />
|-<br />
| [https://github.com/PoomSmart/EmojiAttributes EmojiAttributes]<br />
| [https://github.com/PoomSmart PoomSmart]<br />
|}<br />
<br />
== External Links ==<br />
<br />
* [https://github.com/opa334/libundirect/blob/main/README.md libundirect's detailed usages]<br />
* [https://gist.github.com/johnzaro/fdffd93c2ee0bc7db56d7959a67b4235 Using disassembler to find unique bytes for libundirect]<br />
* [https://nshipster.com/direct/ Objective-C Direct Methods]<br />
<br />
{{Navbox Library}}<br />
<br />
[[Category:Cydia packages]]<br />
<br />
[[Category:Directories in /Library]]</div>PoomSmarthttps://iphonedev.wiki/index.php?title=Libundirect&diff=5670Libundirect2021-05-09T00:21:38Z<p>PoomSmart: </p>
<hr />
<div>{{DISPLAYTITLE:libundirect}}<br />
{{Infobox Package<br />
|developer=[https://twitter.com/opa334dev Lars Fröder (opa334)]<br />
|version=1.1.1<br />
|package=com.opa334.libundirect<br />
}}<br />
<br />
'''libundirect''' is a patchfinding and rebinding library that provides directives to hook Objective-C direct methods. With the feature called objc_direct introduced in Xcode 12 and iOS 14.0, these direct methods are stripped when compiled - being unexported C functions and thus their signature and name are missing.<br />
<br />
As a patchfinder, <code>libundirect_find()</code> can find the address of the function to hook by providing unique bytes within the function and the name of the binary that the function resides. You need to perform reverse engineering on the binary that you are working with in order to determine the bytes to use. See [https://github.com/opa334/libundirect/blob/main/README.md#patchfinder here] or [https://gist.github.com/johnzaro/fdffd93c2ee0bc7db56d7959a67b4235 here] for more details.<br />
<br />
As a rebinder, <code>libundirect_rebind()</code> can re-add Objective-C method signature to the function that you hook. This provides backward compatibility for earlier iOS versions that the signature is still intact - and that you have to import <code><libundirect/libundirect_hookoverwrite.h></code> to make <code>MSHookMessageEx()</code> aware of direct methods.<br />
<br />
== How to use this library ==<br />
<br />
Headers are available from [https://github.com/opa334/libundirect libundirect's GitHub project] or from [https://github.com/theos/headers Theos' headers project]. The library can be installed to <code>$THEOS/vendor/lib</code> by running <code>install_to_theos.sh</code> script inside libundirect repository.<br />
<br />
=== Include directive(s) ===<br />
<br />
<source lang="objc"><br />
#import <libundirect/libundirect.h><br />
#import <libundirect/libundirect_dynamic.h> // if you don't want to link directly against libundirect, import this one instead<br />
#import <libundirect/libundirect_hookoverwrite.h> // if you want backward compatibility<br />
</source><br />
<br />
=== Makefile ===<br />
<br />
Add to your Makefile:<br />
<br />
* <code>libundirect</code> to the <code>XXX_LIBRARIES</code> variable.<br />
<br />
=== Packaging ===<br />
<br />
Add to your package's control file:<br />
<br />
* <code>com.opa334.libundirect (>= 1.1.1)</code> to the <code>Depends</code> field.<br />
<br />
== Examples ==<br />
<br />
=== Hooking (and rebinding) a direct Objective-C method (MobileSafari) ===<br />
<br />
We will use the code in SafariPlus by opa334 as an example.<br />
<br />
<source lang="objc"><br />
#import <libundirect/libundirect.h><br />
#import <libundirect/libundirect_hookoverwrite.h><br />
#import <version.h><br />
<br />
%hook BrowserController<br />
<br />
- (void)tabControllerDocumentCountDidChange:(TabController *)tabController {<br />
%orig;<br />
...<br />
}<br />
<br />
%end<br />
<br />
...<br />
<br />
// In your constructor:<br />
<br />
if (IS_IOS_OR_NEWER(iOS_14_0)) {<br />
Class class_browserController = NSClassFromString(@"BrowserController");<br />
<br />
// -[BrowserController tabControllerDocumentCountDidChange:]<br />
// arm64 memory of function: [600100B4 F44FBEA9]<br />
// arm64e memory of function: [A00100B4 7F2303D5 F44FBEA9]<br />
// criteria: called by -[BrowserController _updateSceneTitle] (14.2: sub_100041e5c, references string @"Private Browsing")<br />
// 14.2: sub_10005bef8, arm64e: sub_10005E824<br />
<br />
#if __arm64e__<br />
void* tabControllerDocumentCountDidChange = libundirect_find(@"MobileSafari", (unsigned char[]){0xA0, 0x01, 0x00, 0xB4, 0x7F, 0x23, 0x03, 0xD5, 0xF4, 0x4F, 0xBE, 0xA9}, 12, 0);<br />
#else<br />
void* tabControllerDocumentCountDidChange = libundirect_find(@"MobileSafari", (unsigned char[]){0x60, 0x01, 0x00, 0xB4, 0xF4, 0x4F, 0xBE, 0xA9}, 8, 0);<br />
#endif<br />
<br />
libundirect_rebind(tabControllerDocumentCountDidChange, class_browserController, @selector(tabControllerDocumentCountDidChange:), "v@:@");<br />
}<br />
<br />
%init;<br />
</source><br />
<br />
=== Hooking an unnamed C function (libicucore) ===<br />
<br />
We will use the code in EmojiAttributes by PoomSmart as an example.<br />
<br />
<source lang="objc"><br />
#import <libundirect/libundirect.h><br />
<br />
...<br />
<br />
%group getUnicodeProperties<br />
<br />
%hookf(uint32_t, u_getUnicodeProperties, UChar32 c, int32_t column) {<br />
if (column >= propsVectorsColumns)<br />
return 0;<br />
uint16_t vecIndex = UTRIE2_GET16(&propsVectorsTrie, c);<br />
return propsVectors[vecIndex + column];<br />
}<br />
<br />
%end<br />
<br />
// In your constructor:<br />
<br />
#if TARGET_OS_SIMULATOR<br />
// Memory of function (iOS 13.5): 31C083FE 020F8F8D 00000055 4889E581 FFFFD700 00770789 F8C1E805 EB4A81FF FFFF0000 771731C0 81FF00DC 0000B940 0100000F 4DC889F8 C1E805EB 29B8D813 000081FF FFFF1000 773289F8 C1E80B48 8D0D30CC 1B000FB7 8C414010 000089F8 C1E80583 E03F01C8 89C0488D 0D15CC1B 000FB704 4183E71F 488D0487 488D0D03 CC1B000F B7044148 63CE4801 C1488D05 D2B11A00 8B04885D C3<br />
// Memory of function (iOS 12.4): 554889E5 31C083FE 020F8F8A 00000081 FFFFD700 00770789 F8C1E805 EB4C81FF FFFF0000 771731C0 81FF00DC 0000B940 0100000F 4DC889F8 C1E805EB 2B81FFFF FF100076 07B8D413 0000EB32 89F8C1E8 0B488D0D CFE61B00 0FB78C41 40100000 89F8C1E8 0583E03F 01C889C0 488D0DB4 E61B000F B7044183 E71F488D 0487488D 0DA2E61B 000FB704 414863CE 4801C148 8D0571D3 1A008B04 885DC3<br />
// Unique bytes (iOS 13.5): E03F01C8 89C0488D 0D15CC1B (offset: 100)<br />
// Unique bytes (iOS 12.4): 0583E03F 01C889C0 488D0DB4 (offset: 100)<br />
// Starting byte (iOS 13.5): 0x31<br />
// Starting byte (iOS 12.4): 0x55<br />
void *rp = libundirect_find(@"libicucore.A.dylib", (unsigned char[]){0xE0, 0x3F, 0x01, 0xC8, 0x89, 0xC0, 0x48, 0x8D, 0x0D, 0x15, 0xCC, 0x1B}, 12, 0x31);<br />
if (rp == NULL)<br />
rp = libundirect_find(@"libicucore.A.dylib", (unsigned char[]){0x05, 0x83, 0xE0, 0x3F, 0x01, 0xC8, 0x89, 0xC0, 0x48, 0x8D, 0x0D, 0xB4}, 12, 0x55);<br />
#else<br />
// Memory of function: 3F080071 6D000054 00008052 C0035FD6 087C0B53 1F690071 68000054 087C0513 08000014 087C1053 68020035 08809B52 1F00086B 08288052 08B19F1A 0815800B 090D00B0 29110F91 28D96878 09100012 2809080B 090D00B0 29110F91 28D96878 0801010B 890C00B0 29A12791 20D968B8 C0035FD6 1F410071 69000054 08548252 F5FFFF17 087C0B13 090D00B0 29110F91 28C5288B 08816079 0A280553 08412A8B 28796878 EAFFFF17<br />
// Unique bytes: 3F080071 6D000054 00008052 C0035FD6 (offset: 0)<br />
// Starting byte: 0x3F<br />
void *rp = libundirect_find(@"libicucore.A.dylib", (unsigned char[]){0x3F, 0x08, 0x00, 0x71, 0x6D, 0x00, 0x00, 0x54, 0x00, 0x00, 0x80, 0x52, 0xC0, 0x03, 0x5F, 0xD6}, 16, 0x3F);<br />
#endif<br />
<br />
%init(getUnicodeProperties, u_getUnicodeProperties = (void *)rp);<br />
</source><br />
<br />
== Project Examples ==<br />
<br />
{| class="wikitable"<br />
|-<br />
! Project<br />
! Author<br />
|-<br />
| [https://github.com/opa334/SafariPlus SafariPlus]<br />
| [https://github.com/opa334 opa334]<br />
|-<br />
| [https://github.com/udevsharold/safaritabs14 SafariTabs14]<br />
| [https://github.com/udevsharold udevsharold]<br />
|-<br />
| [https://github.com/PoomSmart/EmojiAttributes EmojiAttributes]<br />
| [https://github.com/PoomSmart PoomSmart]<br />
|}<br />
<br />
== External Links ==<br />
<br />
* [https://github.com/opa334/libundirect/blob/main/README.md libundirect's detailed usages]<br />
* [https://gist.github.com/johnzaro/fdffd93c2ee0bc7db56d7959a67b4235 Using disassembler to find unique bytes for libundirect]<br />
* [https://nshipster.com/direct/ Objective-C Direct Methods]<br />
GitHub]<br />
<br />
{{Navbox Library}}<br />
<br />
[[Category:Cydia packages]]<br />
<br />
[[Category:Directories in /Library]]</div>PoomSmarthttps://iphonedev.wiki/index.php?title=Libundirect&diff=5669Libundirect2021-05-09T00:19:03Z<p>PoomSmart: </p>
<hr />
<div>{{DISPLAYTITLE:libundirect}}<br />
{{Infobox Package<br />
|developer=[https://twitter.com/opa334dev Lars Fröder (opa334)]<br />
|version=1.1.1<br />
|package=com.opa334.libundirect<br />
}}<br />
<br />
'''libundirect''' is a patchfinding and rebinding library that provides directives to hook Objective-C direct methods. With the feature called objc_direct introduced in Xcode 12 and iOS 14.0, these direct methods are stripped when compiled - being unexported C functions and thus their signature and name are missing.<br />
<br />
As a patchfinder, <code>libundirect_find()</code> can find the address of the function to hook by providing unique bytes within the function and the name of the binary that the function resides. You need to perform reverse engineering on the binary that you are working with in order to determine the bytes to use. See [https://github.com/opa334/libundirect/blob/main/README.md#patchfinder here] or [https://gist.github.com/johnzaro/fdffd93c2ee0bc7db56d7959a67b4235 here] for more details.<br />
<br />
As a rebinder, <code>libundirect_rebind()</code> can re-add Objective-C method signature to the function that you hook. This provides backward compatibility for earlier iOS versions that the signature is still intact - and that you have to import <code><libundirect/libundirect_hookoverwrite.h></code> to make <code>MSHookMessageEx()</code> aware of direct methods.<br />
<br />
== How to use this library ==<br />
<br />
Headers are available from [https://github.com/opa334/libundirect libundirect's GitHub project] or from [https://github.com/theos/headers Theos' headers project]. The library can be installed to <code>$THEOS/vendor/lib</code> by running <code>install_to_theos.sh</code> script inside libundirect repository.<br />
<br />
=== Include directive(s) ===<br />
<br />
<source lang="objc"><br />
#import <libundirect/libundirect.h><br />
#import <libundirect/libundirect_dynamic.h> // if you don't want to link directly against libundirect, import this one instead<br />
#import <libundirect/libundirect_hookoverwrite.h> // if you want backward compatibility<br />
</source><br />
<br />
=== Makefile ===<br />
<br />
Add to your Makefile:<br />
<br />
* <code>libundirect</code> to the <code>XXX_LIBRARIES</code> variable.<br />
<br />
=== Packaging ===<br />
<br />
Add to your package's control file:<br />
<br />
* <code>com.opa334.libundirect (>= 1.1.1)</code> to the <code>Depends</code> field.<br />
<br />
== Examples ==<br />
<br />
=== Hooking (and rebinding) a direct Objective-C method (MobileSafari) ===<br />
<br />
We will use the code in SafariPlus by opa334 as an example.<br />
<br />
<source lang="objc"><br />
#import <libundirect/libundirect.h><br />
#import <libundirect/libundirect_hookoverwrite.h><br />
#import <version.h><br />
<br />
%hook BrowserController<br />
<br />
- (void)tabControllerDocumentCountDidChange:(TabController *)tabController {<br />
%orig;<br />
...<br />
}<br />
<br />
%end<br />
<br />
...<br />
<br />
// In your constructor:<br />
<br />
if (IS_IOS_OR_NEWER(iOS_14_0)) {<br />
Class class_browserController = NSClassFromString(@"BrowserController");<br />
<br />
// -[BrowserController tabControllerDocumentCountDidChange:]<br />
// arm64 memory of function: [600100B4 F44FBEA9]<br />
// arm64e memory of function: [A00100B4 7F2303D5 F44FBEA9]<br />
// criteria: called by -[BrowserController _updateSceneTitle] (14.2: sub_100041e5c, references string @"Private Browsing")<br />
// 14.2: sub_10005bef8, arm64e: sub_10005E824<br />
<br />
#if __arm64e__<br />
void* tabControllerDocumentCountDidChange = libundirect_find(@"MobileSafari", (unsigned char[]){0xA0, 0x01, 0x00, 0xB4, 0x7F, 0x23, 0x03, 0xD5, 0xF4, 0x4F, 0xBE, 0xA9}, 12, 0);<br />
#else<br />
void* tabControllerDocumentCountDidChange = libundirect_find(@"MobileSafari", (unsigned char[]){0x60, 0x01, 0x00, 0xB4, 0xF4, 0x4F, 0xBE, 0xA9}, 8, 0);<br />
#endif<br />
<br />
libundirect_rebind(tabControllerDocumentCountDidChange, class_browserController, @selector(tabControllerDocumentCountDidChange:), "v@:@");<br />
}<br />
<br />
%init;<br />
</source><br />
<br />
=== Hooking an unnamed C function (libicucore) ===<br />
<br />
We will use the code in EmojiAttributes by PoomSmart as an example.<br />
<br />
<source lang="objc"><br />
#import <libundirect/libundirect.h><br />
<br />
...<br />
<br />
%group getUnicodeProperties<br />
<br />
%hookf(uint32_t, u_getUnicodeProperties, UChar32 c, int32_t column) {<br />
if (column >= propsVectorsColumns)<br />
return 0;<br />
uint16_t vecIndex = UTRIE2_GET16(&propsVectorsTrie, c);<br />
return propsVectors[vecIndex + column];<br />
}<br />
<br />
%end<br />
<br />
// In your constructor:<br />
<br />
#if TARGET_OS_SIMULATOR<br />
// Memory of function (iOS 13.5): 31C083FE 020F8F8D 00000055 4889E581 FFFFD700 00770789 F8C1E805 EB4A81FF FFFF0000 771731C0 81FF00DC 0000B940 0100000F 4DC889F8 C1E805EB 29B8D813 000081FF FFFF1000 773289F8 C1E80B48 8D0D30CC 1B000FB7 8C414010 000089F8 C1E80583 E03F01C8 89C0488D 0D15CC1B 000FB704 4183E71F 488D0487 488D0D03 CC1B000F B7044148 63CE4801 C1488D05 D2B11A00 8B04885D C3<br />
// Memory of function (iOS 12.4): 554889E5 31C083FE 020F8F8A 00000081 FFFFD700 00770789 F8C1E805 EB4C81FF FFFF0000 771731C0 81FF00DC 0000B940 0100000F 4DC889F8 C1E805EB 2B81FFFF FF100076 07B8D413 0000EB32 89F8C1E8 0B488D0D CFE61B00 0FB78C41 40100000 89F8C1E8 0583E03F 01C889C0 488D0DB4 E61B000F B7044183 E71F488D 0487488D 0DA2E61B 000FB704 414863CE 4801C148 8D0571D3 1A008B04 885DC3<br />
// Unique bytes (iOS 13.5): E03F01C8 89C0488D 0D15CC1B (offset: 100)<br />
// Unique bytes (iOS 12.4): 0583E03F 01C889C0 488D0DB4 (offset: 100)<br />
// Starting byte (iOS 13.5): 0x31<br />
// Starting byte (iOS 12.4): 0x55<br />
void *rp = libundirect_find(@"libicucore.A.dylib", (unsigned char[]){0xE0, 0x3F, 0x01, 0xC8, 0x89, 0xC0, 0x48, 0x8D, 0x0D, 0x15, 0xCC, 0x1B}, 12, 0x31);<br />
if (rp == NULL)<br />
rp = libundirect_find(@"libicucore.A.dylib", (unsigned char[]){0x05, 0x83, 0xE0, 0x3F, 0x01, 0xC8, 0x89, 0xC0, 0x48, 0x8D, 0x0D, 0xB4}, 12, 0x55);<br />
#else<br />
// Memory of function: 3F080071 6D000054 00008052 C0035FD6 087C0B53 1F690071 68000054 087C0513 08000014 087C1053 68020035 08809B52 1F00086B 08288052 08B19F1A 0815800B 090D00B0 29110F91 28D96878 09100012 2809080B 090D00B0 29110F91 28D96878 0801010B 890C00B0 29A12791 20D968B8 C0035FD6 1F410071 69000054 08548252 F5FFFF17 087C0B13 090D00B0 29110F91 28C5288B 08816079 0A280553 08412A8B 28796878 EAFFFF17<br />
// Unique bytes: 3F080071 6D000054 00008052 C0035FD6 (offset: 0)<br />
// Starting byte: 0x3F<br />
void *rp = libundirect_find(@"libicucore.A.dylib", (unsigned char[]){0x3F, 0x08, 0x00, 0x71, 0x6D, 0x00, 0x00, 0x54, 0x00, 0x00, 0x80, 0x52, 0xC0, 0x03, 0x5F, 0xD6}, 16, 0x3F);<br />
#endif<br />
<br />
%init(getUnicodeProperties, u_getUnicodeProperties = (void *)rp);<br />
</source><br />
<br />
== Project Examples ==<br />
<br />
{| class="wikitable"<br />
|-<br />
! Project<br />
! Author<br />
|-<br />
| [https://github.com/opa334/SafariPlus SafariPlus]<br />
| [https://github.com/opa334 opa334]<br />
|-<br />
| [https://github.com/udevsharold/safaritabs14 SafariTabs14]<br />
| [https://github.com/udevsharold udevsharold]<br />
|-<br />
| [https://github.com/PoomSmart/EmojiAttributes EmojiAttributes]<br />
| [https://github.com/PoomSmart PoomSmart]<br />
|}<br />
<br />
== External Links ==<br />
<br />
* [https://github.com/opa334/libundirect/blob/main/README.md libundirect's detailed usages]<br />
* [https://gist.github.com/johnzaro/fdffd93c2ee0bc7db56d7959a67b4235 Using disassembler to find unique bytes for libundirect]<br />
* [https://nshipster.com/direct/ Objective-C Direct Methods]</div>PoomSmarthttps://iphonedev.wiki/index.php?title=Libundirect&diff=5667Libundirect2021-05-08T14:23:17Z<p>PoomSmart: /* Include directive(s) */</p>
<hr />
<div>{{DISPLAYTITLE:libundirect}}<br />
{{Infobox Package<br />
|developer=[https://twitter.com/opa334dev Lars Fröder (opa334)]<br />
|version=1.1.1<br />
|package=com.opa334.libundirect<br />
}}<br />
<br />
'''libundirect''' is a patchfinding and rebinding library that provides directives to hook Objective-C direct methods. With the feature called objc_direct introduced in Xcode 12 and iOS 14.0, these direct methods are stripped when compiled - being unexported C functions and thus their signature and name are missing.<br />
<br />
As a patchfinder, <code>libundirect_find()</code> can find the address of the function to hook by providing unique bytes within the function and the name of the binary that the function resides. You need to perform reverse engineering on the binary that you are working with in order to determine the bytes to use. See [https://github.com/opa334/libundirect/blob/main/README.md#patchfinder here] for more details.<br />
<br />
As a rebinder, <code>libundirect_rebind()</code> can re-add Objective-C method signature to the function that you hook. This provides backward compatibility for earlier iOS versions that the signature is still intact - and that you have to import <code><libundirect/libundirect_hookoverwrite.h></code> to make <code>MSHookMessageEx()</code> aware of direct methods.<br />
<br />
== How to use this library ==<br />
<br />
Headers are available from [https://github.com/opa334/libundirect libundirect's GitHub project] or from [https://github.com/theos/headers Theos' headers project]. The library can be installed to <code>$THEOS/vendor/lib</code> by running <code>install_to_theos.sh</code> script inside libundirect repository.<br />
<br />
=== Include directive(s) ===<br />
<br />
<source lang="objc"><br />
#import <libundirect/libundirect.h><br />
#import <libundirect/libundirect_dynamic.h> // if you don't want to link directly against libundirect, import this one instead<br />
#import <libundirect/libundirect_hookoverwrite.h> // if you want backward compatibility<br />
</source><br />
<br />
=== Makefile ===<br />
<br />
Add to your Makefile:<br />
<br />
* <code>libundirect</code> to the <code>XXX_LIBRARIES</code> variable.<br />
<br />
=== Packaging ===<br />
<br />
Add to your package's control file:<br />
<br />
* <code>com.opa334.libundirect (>= 1.1.1)</code> to the <code>Depends</code> field.<br />
<br />
== Examples ==<br />
<br />
=== Hooking (and rebinding) a direct Objective-C method (MobileSafari) ===<br />
<br />
We will use the code in SafariPlus by opa334 as an example.<br />
<br />
<source lang="objc"><br />
#import <libundirect/libundirect.h><br />
#import <libundirect/libundirect_hookoverwrite.h><br />
#import <version.h><br />
<br />
%hook BrowserController<br />
<br />
- (void)tabControllerDocumentCountDidChange:(TabController *)tabController {<br />
%orig;<br />
...<br />
}<br />
<br />
%end<br />
<br />
...<br />
<br />
// In your constructor:<br />
<br />
if (IS_IOS_OR_NEWER(iOS_14_0)) {<br />
Class class_browserController = NSClassFromString(@"BrowserController");<br />
<br />
// -[BrowserController tabControllerDocumentCountDidChange:]<br />
// arm64 memory of function: [600100B4 F44FBEA9]<br />
// arm64e memory of function: [A00100B4 7F2303D5 F44FBEA9]<br />
// criteria: called by -[BrowserController _updateSceneTitle] (14.2: sub_100041e5c, references string @"Private Browsing")<br />
// 14.2: sub_10005bef8, arm64e: sub_10005E824<br />
<br />
#if __arm64e__<br />
void* tabControllerDocumentCountDidChange = libundirect_find(@"MobileSafari", (unsigned char[]){0xA0, 0x01, 0x00, 0xB4, 0x7F, 0x23, 0x03, 0xD5, 0xF4, 0x4F, 0xBE, 0xA9}, 12, 0);<br />
#else<br />
void* tabControllerDocumentCountDidChange = libundirect_find(@"MobileSafari", (unsigned char[]){0x60, 0x01, 0x00, 0xB4, 0xF4, 0x4F, 0xBE, 0xA9}, 8, 0);<br />
#endif<br />
<br />
libundirect_rebind(tabControllerDocumentCountDidChange, class_browserController, @selector(tabControllerDocumentCountDidChange:), "v@:@");<br />
}<br />
<br />
%init;<br />
</source><br />
<br />
=== Hooking an unnamed C function (libicucore) ===<br />
<br />
We will use the code in EmojiAttributes by PoomSmart as an example.<br />
<br />
<source lang="objc"><br />
#import <libundirect/libundirect.h><br />
<br />
...<br />
<br />
%group getUnicodeProperties<br />
<br />
%hookf(uint32_t, u_getUnicodeProperties, UChar32 c, int32_t column) {<br />
if (column >= propsVectorsColumns)<br />
return 0;<br />
uint16_t vecIndex = UTRIE2_GET16(&propsVectorsTrie, c);<br />
return propsVectors[vecIndex + column];<br />
}<br />
<br />
%end<br />
<br />
// In your constructor:<br />
<br />
#if TARGET_OS_SIMULATOR<br />
// Memory of function (iOS 13.5): 31C083FE 020F8F8D 00000055 4889E581 FFFFD700 00770789 F8C1E805 EB4A81FF FFFF0000 771731C0 81FF00DC 0000B940 0100000F 4DC889F8 C1E805EB 29B8D813 000081FF FFFF1000 773289F8 C1E80B48 8D0D30CC 1B000FB7 8C414010 000089F8 C1E80583 E03F01C8 89C0488D 0D15CC1B 000FB704 4183E71F 488D0487 488D0D03 CC1B000F B7044148 63CE4801 C1488D05 D2B11A00 8B04885D C3<br />
// Memory of function (iOS 12.4): 554889E5 31C083FE 020F8F8A 00000081 FFFFD700 00770789 F8C1E805 EB4C81FF FFFF0000 771731C0 81FF00DC 0000B940 0100000F 4DC889F8 C1E805EB 2B81FFFF FF100076 07B8D413 0000EB32 89F8C1E8 0B488D0D CFE61B00 0FB78C41 40100000 89F8C1E8 0583E03F 01C889C0 488D0DB4 E61B000F B7044183 E71F488D 0487488D 0DA2E61B 000FB704 414863CE 4801C148 8D0571D3 1A008B04 885DC3<br />
// Unique bytes (iOS 13.5): E03F01C8 89C0488D 0D15CC1B (offset: 100)<br />
// Unique bytes (iOS 12.4): 0583E03F 01C889C0 488D0DB4 (offset: 100)<br />
// Starting byte (iOS 13.5): 0x31<br />
// Starting byte (iOS 12.4): 0x55<br />
void *rp = libundirect_find(@"libicucore.A.dylib", (unsigned char[]){0xE0, 0x3F, 0x01, 0xC8, 0x89, 0xC0, 0x48, 0x8D, 0x0D, 0x15, 0xCC, 0x1B}, 12, 0x31);<br />
if (rp == NULL)<br />
rp = libundirect_find(@"libicucore.A.dylib", (unsigned char[]){0x05, 0x83, 0xE0, 0x3F, 0x01, 0xC8, 0x89, 0xC0, 0x48, 0x8D, 0x0D, 0xB4}, 12, 0x55);<br />
#else<br />
// Memory of function: 3F080071 6D000054 00008052 C0035FD6 087C0B53 1F690071 68000054 087C0513 08000014 087C1053 68020035 08809B52 1F00086B 08288052 08B19F1A 0815800B 090D00B0 29110F91 28D96878 09100012 2809080B 090D00B0 29110F91 28D96878 0801010B 890C00B0 29A12791 20D968B8 C0035FD6 1F410071 69000054 08548252 F5FFFF17 087C0B13 090D00B0 29110F91 28C5288B 08816079 0A280553 08412A8B 28796878 EAFFFF17<br />
// Unique bytes: 3F080071 6D000054 00008052 C0035FD6 (offset: 0)<br />
// Starting byte: 0x3F<br />
void *rp = libundirect_find(@"libicucore.A.dylib", (unsigned char[]){0x3F, 0x08, 0x00, 0x71, 0x6D, 0x00, 0x00, 0x54, 0x00, 0x00, 0x80, 0x52, 0xC0, 0x03, 0x5F, 0xD6}, 16, 0x3F);<br />
#endif<br />
<br />
%init(getUnicodeProperties, u_getUnicodeProperties = (void *)rp);<br />
</source><br />
<br />
== Project Examples ==<br />
<br />
{| class="wikitable"<br />
|-<br />
! Project<br />
! Author<br />
|-<br />
| [https://github.com/opa334/SafariPlus SafariPlus]<br />
| [https://github.com/opa334 opa334]<br />
|-<br />
| [https://github.com/udevsharold/safaritabs14 SafariTabs14]<br />
| [https://github.com/udevsharold udevsharold]<br />
|-<br />
| [https://github.com/PoomSmart/EmojiAttributes EmojiAttributes]<br />
| [https://github.com/PoomSmart PoomSmart]<br />
|}<br />
<br />
== External Links ==<br />
<br />
* [https://github.com/opa334/libundirect/blob/main/README.md libundirect's detailed usages]<br />
* [https://nshipster.com/direct/ Objective-C Direct Methods]</div>PoomSmarthttps://iphonedev.wiki/index.php?title=Libundirect&diff=5666Libundirect2021-05-08T11:34:57Z<p>PoomSmart: /* Hooking (and rebinding) a direct Objective-C method (MobileSafari) */</p>
<hr />
<div>{{DISPLAYTITLE:libundirect}}<br />
{{Infobox Package<br />
|developer=[https://twitter.com/opa334dev Lars Fröder (opa334)]<br />
|version=1.1.1<br />
|package=com.opa334.libundirect<br />
}}<br />
<br />
'''libundirect''' is a patchfinding and rebinding library that provides directives to hook Objective-C direct methods. With the feature called objc_direct introduced in Xcode 12 and iOS 14.0, these direct methods are stripped when compiled - being unexported C functions and thus their signature and name are missing.<br />
<br />
As a patchfinder, <code>libundirect_find()</code> can find the address of the function to hook by providing unique bytes within the function and the name of the binary that the function resides. You need to perform reverse engineering on the binary that you are working with in order to determine the bytes to use. See [https://github.com/opa334/libundirect/blob/main/README.md#patchfinder here] for more details.<br />
<br />
As a rebinder, <code>libundirect_rebind()</code> can re-add Objective-C method signature to the function that you hook. This provides backward compatibility for earlier iOS versions that the signature is still intact - and that you have to import <code><libundirect/libundirect_hookoverwrite.h></code> to make <code>MSHookMessageEx()</code> aware of direct methods.<br />
<br />
== How to use this library ==<br />
<br />
Headers are available from [https://github.com/opa334/libundirect libundirect's GitHub project] or from [https://github.com/theos/headers Theos' headers project]. The library can be installed to <code>$THEOS/vendor/lib</code> by running <code>install_to_theos.sh</code> script inside libundirect repository.<br />
<br />
=== Include directive(s) ===<br />
<br />
<source lang="objc"><br />
#import <libundirect/libundirect.h><br />
#import <libundirect/libundirect_dynamic.h> // if you don't want to link directly against libundirect<br />
#import <libundirect/libundirect_hookoverwrite.h> // if you want backward compatibility<br />
</source><br />
<br />
=== Makefile ===<br />
<br />
Add to your Makefile:<br />
<br />
* <code>libundirect</code> to the <code>XXX_LIBRARIES</code> variable.<br />
<br />
=== Packaging ===<br />
<br />
Add to your package's control file:<br />
<br />
* <code>com.opa334.libundirect (>= 1.1.1)</code> to the <code>Depends</code> field.<br />
<br />
== Examples ==<br />
<br />
=== Hooking (and rebinding) a direct Objective-C method (MobileSafari) ===<br />
<br />
We will use the code in SafariPlus by opa334 as an example.<br />
<br />
<source lang="objc"><br />
#import <libundirect/libundirect.h><br />
#import <libundirect/libundirect_hookoverwrite.h><br />
#import <version.h><br />
<br />
%hook BrowserController<br />
<br />
- (void)tabControllerDocumentCountDidChange:(TabController *)tabController {<br />
%orig;<br />
...<br />
}<br />
<br />
%end<br />
<br />
...<br />
<br />
// In your constructor:<br />
<br />
if (IS_IOS_OR_NEWER(iOS_14_0)) {<br />
Class class_browserController = NSClassFromString(@"BrowserController");<br />
<br />
// -[BrowserController tabControllerDocumentCountDidChange:]<br />
// arm64 memory of function: [600100B4 F44FBEA9]<br />
// arm64e memory of function: [A00100B4 7F2303D5 F44FBEA9]<br />
// criteria: called by -[BrowserController _updateSceneTitle] (14.2: sub_100041e5c, references string @"Private Browsing")<br />
// 14.2: sub_10005bef8, arm64e: sub_10005E824<br />
<br />
#if __arm64e__<br />
void* tabControllerDocumentCountDidChange = libundirect_find(@"MobileSafari", (unsigned char[]){0xA0, 0x01, 0x00, 0xB4, 0x7F, 0x23, 0x03, 0xD5, 0xF4, 0x4F, 0xBE, 0xA9}, 12, 0);<br />
#else<br />
void* tabControllerDocumentCountDidChange = libundirect_find(@"MobileSafari", (unsigned char[]){0x60, 0x01, 0x00, 0xB4, 0xF4, 0x4F, 0xBE, 0xA9}, 8, 0);<br />
#endif<br />
<br />
libundirect_rebind(tabControllerDocumentCountDidChange, class_browserController, @selector(tabControllerDocumentCountDidChange:), "v@:@");<br />
}<br />
<br />
%init;<br />
</source><br />
<br />
=== Hooking an unnamed C function (libicucore) ===<br />
<br />
We will use the code in EmojiAttributes by PoomSmart as an example.<br />
<br />
<source lang="objc"><br />
#import <libundirect/libundirect.h><br />
<br />
...<br />
<br />
%group getUnicodeProperties<br />
<br />
%hookf(uint32_t, u_getUnicodeProperties, UChar32 c, int32_t column) {<br />
if (column >= propsVectorsColumns)<br />
return 0;<br />
uint16_t vecIndex = UTRIE2_GET16(&propsVectorsTrie, c);<br />
return propsVectors[vecIndex + column];<br />
}<br />
<br />
%end<br />
<br />
// In your constructor:<br />
<br />
#if TARGET_OS_SIMULATOR<br />
// Memory of function (iOS 13.5): 31C083FE 020F8F8D 00000055 4889E581 FFFFD700 00770789 F8C1E805 EB4A81FF FFFF0000 771731C0 81FF00DC 0000B940 0100000F 4DC889F8 C1E805EB 29B8D813 000081FF FFFF1000 773289F8 C1E80B48 8D0D30CC 1B000FB7 8C414010 000089F8 C1E80583 E03F01C8 89C0488D 0D15CC1B 000FB704 4183E71F 488D0487 488D0D03 CC1B000F B7044148 63CE4801 C1488D05 D2B11A00 8B04885D C3<br />
// Memory of function (iOS 12.4): 554889E5 31C083FE 020F8F8A 00000081 FFFFD700 00770789 F8C1E805 EB4C81FF FFFF0000 771731C0 81FF00DC 0000B940 0100000F 4DC889F8 C1E805EB 2B81FFFF FF100076 07B8D413 0000EB32 89F8C1E8 0B488D0D CFE61B00 0FB78C41 40100000 89F8C1E8 0583E03F 01C889C0 488D0DB4 E61B000F B7044183 E71F488D 0487488D 0DA2E61B 000FB704 414863CE 4801C148 8D0571D3 1A008B04 885DC3<br />
// Unique bytes (iOS 13.5): E03F01C8 89C0488D 0D15CC1B (offset: 100)<br />
// Unique bytes (iOS 12.4): 0583E03F 01C889C0 488D0DB4 (offset: 100)<br />
// Starting byte (iOS 13.5): 0x31<br />
// Starting byte (iOS 12.4): 0x55<br />
void *rp = libundirect_find(@"libicucore.A.dylib", (unsigned char[]){0xE0, 0x3F, 0x01, 0xC8, 0x89, 0xC0, 0x48, 0x8D, 0x0D, 0x15, 0xCC, 0x1B}, 12, 0x31);<br />
if (rp == NULL)<br />
rp = libundirect_find(@"libicucore.A.dylib", (unsigned char[]){0x05, 0x83, 0xE0, 0x3F, 0x01, 0xC8, 0x89, 0xC0, 0x48, 0x8D, 0x0D, 0xB4}, 12, 0x55);<br />
#else<br />
// Memory of function: 3F080071 6D000054 00008052 C0035FD6 087C0B53 1F690071 68000054 087C0513 08000014 087C1053 68020035 08809B52 1F00086B 08288052 08B19F1A 0815800B 090D00B0 29110F91 28D96878 09100012 2809080B 090D00B0 29110F91 28D96878 0801010B 890C00B0 29A12791 20D968B8 C0035FD6 1F410071 69000054 08548252 F5FFFF17 087C0B13 090D00B0 29110F91 28C5288B 08816079 0A280553 08412A8B 28796878 EAFFFF17<br />
// Unique bytes: 3F080071 6D000054 00008052 C0035FD6 (offset: 0)<br />
// Starting byte: 0x3F<br />
void *rp = libundirect_find(@"libicucore.A.dylib", (unsigned char[]){0x3F, 0x08, 0x00, 0x71, 0x6D, 0x00, 0x00, 0x54, 0x00, 0x00, 0x80, 0x52, 0xC0, 0x03, 0x5F, 0xD6}, 16, 0x3F);<br />
#endif<br />
<br />
%init(getUnicodeProperties, u_getUnicodeProperties = (void *)rp);<br />
</source><br />
<br />
== Project Examples ==<br />
<br />
{| class="wikitable"<br />
|-<br />
! Project<br />
! Author<br />
|-<br />
| [https://github.com/opa334/SafariPlus SafariPlus]<br />
| [https://github.com/opa334 opa334]<br />
|-<br />
| [https://github.com/udevsharold/safaritabs14 SafariTabs14]<br />
| [https://github.com/udevsharold udevsharold]<br />
|-<br />
| [https://github.com/PoomSmart/EmojiAttributes EmojiAttributes]<br />
| [https://github.com/PoomSmart PoomSmart]<br />
|}<br />
<br />
== External Links ==<br />
<br />
* [https://github.com/opa334/libundirect/blob/main/README.md libundirect's detailed usages]<br />
* [https://nshipster.com/direct/ Objective-C Direct Methods]</div>PoomSmarthttps://iphonedev.wiki/index.php?title=Libundirect&diff=5665Libundirect2021-05-08T11:00:54Z<p>PoomSmart: /* Hooking (and rebinding) a direct Objective-C method (MobileSafari) */</p>
<hr />
<div>{{DISPLAYTITLE:libundirect}}<br />
{{Infobox Package<br />
|developer=[https://twitter.com/opa334dev Lars Fröder (opa334)]<br />
|version=1.1.1<br />
|package=com.opa334.libundirect<br />
}}<br />
<br />
'''libundirect''' is a patchfinding and rebinding library that provides directives to hook Objective-C direct methods. With the feature called objc_direct introduced in Xcode 12 and iOS 14.0, these direct methods are stripped when compiled - being unexported C functions and thus their signature and name are missing.<br />
<br />
As a patchfinder, <code>libundirect_find()</code> can find the address of the function to hook by providing unique bytes within the function and the name of the binary that the function resides. You need to perform reverse engineering on the binary that you are working with in order to determine the bytes to use. See [https://github.com/opa334/libundirect/blob/main/README.md#patchfinder here] for more details.<br />
<br />
As a rebinder, <code>libundirect_rebind()</code> can re-add Objective-C method signature to the function that you hook. This provides backward compatibility for earlier iOS versions that the signature is still intact - and that you have to import <code><libundirect/libundirect_hookoverwrite.h></code> to make <code>MSHookMessageEx()</code> aware of direct methods.<br />
<br />
== How to use this library ==<br />
<br />
Headers are available from [https://github.com/opa334/libundirect libundirect's GitHub project] or from [https://github.com/theos/headers Theos' headers project]. The library can be installed to <code>$THEOS/vendor/lib</code> by running <code>install_to_theos.sh</code> script inside libundirect repository.<br />
<br />
=== Include directive(s) ===<br />
<br />
<source lang="objc"><br />
#import <libundirect/libundirect.h><br />
#import <libundirect/libundirect_dynamic.h> // if you don't want to link directly against libundirect<br />
#import <libundirect/libundirect_hookoverwrite.h> // if you want backward compatibility<br />
</source><br />
<br />
=== Makefile ===<br />
<br />
Add to your Makefile:<br />
<br />
* <code>libundirect</code> to the <code>XXX_LIBRARIES</code> variable.<br />
<br />
=== Packaging ===<br />
<br />
Add to your package's control file:<br />
<br />
* <code>com.opa334.libundirect (>= 1.1.1)</code> to the <code>Depends</code> field.<br />
<br />
== Examples ==<br />
<br />
=== Hooking (and rebinding) a direct Objective-C method (MobileSafari) ===<br />
<br />
We will use the code in SafariPlus by opa334 as an example.<br />
<br />
<source lang="objc"><br />
#import <libundirect/libundirect.h><br />
#import <libundirect/libundirect_hookoverwrite.h><br />
#import <version.h><br />
<br />
%hook BrowserController<br />
<br />
- (void)tabControllerDocumentCountDidChange:(TabController *)tabController {<br />
%orig;<br />
...<br />
}<br />
<br />
%end<br />
<br />
...<br />
<br />
// In your constructor:<br />
<br />
if (!IS_IOS_OR_NEWER(iOS_14_0)) return;<br />
<br />
Class class_browserController = NSClassFromString(@"BrowserController");<br />
<br />
// -[BrowserController tabControllerDocumentCountDidChange:]<br />
// arm64 memory of function: [600100B4 F44FBEA9]<br />
// arm64e memory of function: [A00100B4 7F2303D5 F44FBEA9]<br />
// criteria: called by -[BrowserController _updateSceneTitle] (14.2: sub_100041e5c, references string @"Private Browsing")<br />
// 14.2: sub_10005bef8, arm64e: sub_10005E824<br />
<br />
#if __arm64e__<br />
void* tabControllerDocumentCountDidChange = libundirect_find(@"MobileSafari", (unsigned char[]){0xA0, 0x01, 0x00, 0xB4, 0x7F, 0x23, 0x03, 0xD5, 0xF4, 0x4F, 0xBE, 0xA9}, 12, 0);<br />
#else<br />
void* tabControllerDocumentCountDidChange = libundirect_find(@"MobileSafari", (unsigned char[]){0x60, 0x01, 0x00, 0xB4, 0xF4, 0x4F, 0xBE, 0xA9}, 8, 0);<br />
#endif<br />
<br />
libundirect_rebind(tabControllerDocumentCountDidChange, class_browserController, @selector(tabControllerDocumentCountDidChange:), "v@:@");<br />
</source><br />
<br />
=== Hooking an unnamed C function (libicucore) ===<br />
<br />
We will use the code in EmojiAttributes by PoomSmart as an example.<br />
<br />
<source lang="objc"><br />
#import <libundirect/libundirect.h><br />
<br />
...<br />
<br />
%group getUnicodeProperties<br />
<br />
%hookf(uint32_t, u_getUnicodeProperties, UChar32 c, int32_t column) {<br />
if (column >= propsVectorsColumns)<br />
return 0;<br />
uint16_t vecIndex = UTRIE2_GET16(&propsVectorsTrie, c);<br />
return propsVectors[vecIndex + column];<br />
}<br />
<br />
%end<br />
<br />
// In your constructor:<br />
<br />
#if TARGET_OS_SIMULATOR<br />
// Memory of function (iOS 13.5): 31C083FE 020F8F8D 00000055 4889E581 FFFFD700 00770789 F8C1E805 EB4A81FF FFFF0000 771731C0 81FF00DC 0000B940 0100000F 4DC889F8 C1E805EB 29B8D813 000081FF FFFF1000 773289F8 C1E80B48 8D0D30CC 1B000FB7 8C414010 000089F8 C1E80583 E03F01C8 89C0488D 0D15CC1B 000FB704 4183E71F 488D0487 488D0D03 CC1B000F B7044148 63CE4801 C1488D05 D2B11A00 8B04885D C3<br />
// Memory of function (iOS 12.4): 554889E5 31C083FE 020F8F8A 00000081 FFFFD700 00770789 F8C1E805 EB4C81FF FFFF0000 771731C0 81FF00DC 0000B940 0100000F 4DC889F8 C1E805EB 2B81FFFF FF100076 07B8D413 0000EB32 89F8C1E8 0B488D0D CFE61B00 0FB78C41 40100000 89F8C1E8 0583E03F 01C889C0 488D0DB4 E61B000F B7044183 E71F488D 0487488D 0DA2E61B 000FB704 414863CE 4801C148 8D0571D3 1A008B04 885DC3<br />
// Unique bytes (iOS 13.5): E03F01C8 89C0488D 0D15CC1B (offset: 100)<br />
// Unique bytes (iOS 12.4): 0583E03F 01C889C0 488D0DB4 (offset: 100)<br />
// Starting byte (iOS 13.5): 0x31<br />
// Starting byte (iOS 12.4): 0x55<br />
void *rp = libundirect_find(@"libicucore.A.dylib", (unsigned char[]){0xE0, 0x3F, 0x01, 0xC8, 0x89, 0xC0, 0x48, 0x8D, 0x0D, 0x15, 0xCC, 0x1B}, 12, 0x31);<br />
if (rp == NULL)<br />
rp = libundirect_find(@"libicucore.A.dylib", (unsigned char[]){0x05, 0x83, 0xE0, 0x3F, 0x01, 0xC8, 0x89, 0xC0, 0x48, 0x8D, 0x0D, 0xB4}, 12, 0x55);<br />
#else<br />
// Memory of function: 3F080071 6D000054 00008052 C0035FD6 087C0B53 1F690071 68000054 087C0513 08000014 087C1053 68020035 08809B52 1F00086B 08288052 08B19F1A 0815800B 090D00B0 29110F91 28D96878 09100012 2809080B 090D00B0 29110F91 28D96878 0801010B 890C00B0 29A12791 20D968B8 C0035FD6 1F410071 69000054 08548252 F5FFFF17 087C0B13 090D00B0 29110F91 28C5288B 08816079 0A280553 08412A8B 28796878 EAFFFF17<br />
// Unique bytes: 3F080071 6D000054 00008052 C0035FD6 (offset: 0)<br />
// Starting byte: 0x3F<br />
void *rp = libundirect_find(@"libicucore.A.dylib", (unsigned char[]){0x3F, 0x08, 0x00, 0x71, 0x6D, 0x00, 0x00, 0x54, 0x00, 0x00, 0x80, 0x52, 0xC0, 0x03, 0x5F, 0xD6}, 16, 0x3F);<br />
#endif<br />
<br />
%init(getUnicodeProperties, u_getUnicodeProperties = (void *)rp);<br />
</source><br />
<br />
== Project Examples ==<br />
<br />
{| class="wikitable"<br />
|-<br />
! Project<br />
! Author<br />
|-<br />
| [https://github.com/opa334/SafariPlus SafariPlus]<br />
| [https://github.com/opa334 opa334]<br />
|-<br />
| [https://github.com/udevsharold/safaritabs14 SafariTabs14]<br />
| [https://github.com/udevsharold udevsharold]<br />
|-<br />
| [https://github.com/PoomSmart/EmojiAttributes EmojiAttributes]<br />
| [https://github.com/PoomSmart PoomSmart]<br />
|}<br />
<br />
== External Links ==<br />
<br />
* [https://github.com/opa334/libundirect/blob/main/README.md libundirect's detailed usages]<br />
* [https://nshipster.com/direct/ Objective-C Direct Methods]</div>PoomSmarthttps://iphonedev.wiki/index.php?title=Libundirect&diff=5664Libundirect2021-05-08T10:59:41Z<p>PoomSmart: /* Hooking an Objective-C method (MobileSafari) */</p>
<hr />
<div>{{DISPLAYTITLE:libundirect}}<br />
{{Infobox Package<br />
|developer=[https://twitter.com/opa334dev Lars Fröder (opa334)]<br />
|version=1.1.1<br />
|package=com.opa334.libundirect<br />
}}<br />
<br />
'''libundirect''' is a patchfinding and rebinding library that provides directives to hook Objective-C direct methods. With the feature called objc_direct introduced in Xcode 12 and iOS 14.0, these direct methods are stripped when compiled - being unexported C functions and thus their signature and name are missing.<br />
<br />
As a patchfinder, <code>libundirect_find()</code> can find the address of the function to hook by providing unique bytes within the function and the name of the binary that the function resides. You need to perform reverse engineering on the binary that you are working with in order to determine the bytes to use. See [https://github.com/opa334/libundirect/blob/main/README.md#patchfinder here] for more details.<br />
<br />
As a rebinder, <code>libundirect_rebind()</code> can re-add Objective-C method signature to the function that you hook. This provides backward compatibility for earlier iOS versions that the signature is still intact - and that you have to import <code><libundirect/libundirect_hookoverwrite.h></code> to make <code>MSHookMessageEx()</code> aware of direct methods.<br />
<br />
== How to use this library ==<br />
<br />
Headers are available from [https://github.com/opa334/libundirect libundirect's GitHub project] or from [https://github.com/theos/headers Theos' headers project]. The library can be installed to <code>$THEOS/vendor/lib</code> by running <code>install_to_theos.sh</code> script inside libundirect repository.<br />
<br />
=== Include directive(s) ===<br />
<br />
<source lang="objc"><br />
#import <libundirect/libundirect.h><br />
#import <libundirect/libundirect_dynamic.h> // if you don't want to link directly against libundirect<br />
#import <libundirect/libundirect_hookoverwrite.h> // if you want backward compatibility<br />
</source><br />
<br />
=== Makefile ===<br />
<br />
Add to your Makefile:<br />
<br />
* <code>libundirect</code> to the <code>XXX_LIBRARIES</code> variable.<br />
<br />
=== Packaging ===<br />
<br />
Add to your package's control file:<br />
<br />
* <code>com.opa334.libundirect (>= 1.1.1)</code> to the <code>Depends</code> field.<br />
<br />
== Examples ==<br />
<br />
=== Hooking (and rebinding) a direct Objective-C method (MobileSafari) ===<br />
<br />
We will use the code in SafariPlus by opa334 as an example.<br />
<br />
<source lang="objc"><br />
#import <libundirect/libundirect.h><br />
#import <libundirect/libundirect_hookoverwrite.h><br />
<br />
%hook BrowserController<br />
<br />
- (void)tabControllerDocumentCountDidChange:(TabController *)tabController {<br />
%orig;<br />
...<br />
}<br />
<br />
%end<br />
<br />
...<br />
<br />
// In your constructor:<br />
<br />
Class class_browserController = NSClassFromString(@"BrowserController");<br />
<br />
// -[BrowserController tabControllerDocumentCountDidChange:]<br />
// arm64 memory of function: [600100B4 F44FBEA9]<br />
// arm64e memory of function: [A00100B4 7F2303D5 F44FBEA9]<br />
// criteria: called by -[BrowserController _updateSceneTitle] (14.2: sub_100041e5c, references string @"Private Browsing")<br />
// 14.2: sub_10005bef8, arm64e: sub_10005E824<br />
<br />
#if __arm64e__<br />
void* tabControllerDocumentCountDidChange = libundirect_find(@"MobileSafari", (unsigned char[]){0xA0, 0x01, 0x00, 0xB4, 0x7F, 0x23, 0x03, 0xD5, 0xF4, 0x4F, 0xBE, 0xA9}, 12, 0);<br />
#else<br />
void* tabControllerDocumentCountDidChange = libundirect_find(@"MobileSafari", (unsigned char[]){0x60, 0x01, 0x00, 0xB4, 0xF4, 0x4F, 0xBE, 0xA9}, 8, 0);<br />
#endif<br />
<br />
libundirect_rebind(tabControllerDocumentCountDidChange, class_browserController, @selector(tabControllerDocumentCountDidChange:), "v@:@");<br />
</source><br />
<br />
=== Hooking an unnamed C function (libicucore) ===<br />
<br />
We will use the code in EmojiAttributes by PoomSmart as an example.<br />
<br />
<source lang="objc"><br />
#import <libundirect/libundirect.h><br />
<br />
...<br />
<br />
%group getUnicodeProperties<br />
<br />
%hookf(uint32_t, u_getUnicodeProperties, UChar32 c, int32_t column) {<br />
if (column >= propsVectorsColumns)<br />
return 0;<br />
uint16_t vecIndex = UTRIE2_GET16(&propsVectorsTrie, c);<br />
return propsVectors[vecIndex + column];<br />
}<br />
<br />
%end<br />
<br />
// In your constructor:<br />
<br />
#if TARGET_OS_SIMULATOR<br />
// Memory of function (iOS 13.5): 31C083FE 020F8F8D 00000055 4889E581 FFFFD700 00770789 F8C1E805 EB4A81FF FFFF0000 771731C0 81FF00DC 0000B940 0100000F 4DC889F8 C1E805EB 29B8D813 000081FF FFFF1000 773289F8 C1E80B48 8D0D30CC 1B000FB7 8C414010 000089F8 C1E80583 E03F01C8 89C0488D 0D15CC1B 000FB704 4183E71F 488D0487 488D0D03 CC1B000F B7044148 63CE4801 C1488D05 D2B11A00 8B04885D C3<br />
// Memory of function (iOS 12.4): 554889E5 31C083FE 020F8F8A 00000081 FFFFD700 00770789 F8C1E805 EB4C81FF FFFF0000 771731C0 81FF00DC 0000B940 0100000F 4DC889F8 C1E805EB 2B81FFFF FF100076 07B8D413 0000EB32 89F8C1E8 0B488D0D CFE61B00 0FB78C41 40100000 89F8C1E8 0583E03F 01C889C0 488D0DB4 E61B000F B7044183 E71F488D 0487488D 0DA2E61B 000FB704 414863CE 4801C148 8D0571D3 1A008B04 885DC3<br />
// Unique bytes (iOS 13.5): E03F01C8 89C0488D 0D15CC1B (offset: 100)<br />
// Unique bytes (iOS 12.4): 0583E03F 01C889C0 488D0DB4 (offset: 100)<br />
// Starting byte (iOS 13.5): 0x31<br />
// Starting byte (iOS 12.4): 0x55<br />
void *rp = libundirect_find(@"libicucore.A.dylib", (unsigned char[]){0xE0, 0x3F, 0x01, 0xC8, 0x89, 0xC0, 0x48, 0x8D, 0x0D, 0x15, 0xCC, 0x1B}, 12, 0x31);<br />
if (rp == NULL)<br />
rp = libundirect_find(@"libicucore.A.dylib", (unsigned char[]){0x05, 0x83, 0xE0, 0x3F, 0x01, 0xC8, 0x89, 0xC0, 0x48, 0x8D, 0x0D, 0xB4}, 12, 0x55);<br />
#else<br />
// Memory of function: 3F080071 6D000054 00008052 C0035FD6 087C0B53 1F690071 68000054 087C0513 08000014 087C1053 68020035 08809B52 1F00086B 08288052 08B19F1A 0815800B 090D00B0 29110F91 28D96878 09100012 2809080B 090D00B0 29110F91 28D96878 0801010B 890C00B0 29A12791 20D968B8 C0035FD6 1F410071 69000054 08548252 F5FFFF17 087C0B13 090D00B0 29110F91 28C5288B 08816079 0A280553 08412A8B 28796878 EAFFFF17<br />
// Unique bytes: 3F080071 6D000054 00008052 C0035FD6 (offset: 0)<br />
// Starting byte: 0x3F<br />
void *rp = libundirect_find(@"libicucore.A.dylib", (unsigned char[]){0x3F, 0x08, 0x00, 0x71, 0x6D, 0x00, 0x00, 0x54, 0x00, 0x00, 0x80, 0x52, 0xC0, 0x03, 0x5F, 0xD6}, 16, 0x3F);<br />
#endif<br />
<br />
%init(getUnicodeProperties, u_getUnicodeProperties = (void *)rp);<br />
</source><br />
<br />
== Project Examples ==<br />
<br />
{| class="wikitable"<br />
|-<br />
! Project<br />
! Author<br />
|-<br />
| [https://github.com/opa334/SafariPlus SafariPlus]<br />
| [https://github.com/opa334 opa334]<br />
|-<br />
| [https://github.com/udevsharold/safaritabs14 SafariTabs14]<br />
| [https://github.com/udevsharold udevsharold]<br />
|-<br />
| [https://github.com/PoomSmart/EmojiAttributes EmojiAttributes]<br />
| [https://github.com/PoomSmart PoomSmart]<br />
|}<br />
<br />
== External Links ==<br />
<br />
* [https://github.com/opa334/libundirect/blob/main/README.md libundirect's detailed usages]<br />
* [https://nshipster.com/direct/ Objective-C Direct Methods]</div>PoomSmarthttps://iphonedev.wiki/index.php?title=Updating_extensions_for_iOS_14&diff=5663Updating extensions for iOS 142021-05-08T10:54:18Z<p>PoomSmart: /* Hooking unexported Objective-C functions (objc_direct) */</p>
<hr />
<div>Let's collect knowledge like we did with [[Updating extensions for iOS 13|iOS 13]], [[Updating extensions for iOS 12|iOS 12]], [[Updating extensions for iOS 11|iOS 11]], [[Updating extensions for iOS 10|iOS 10]], [[Updating extensions for iOS 9|iOS 9]], [[Updating extensions for iOS 8|iOS 8]] and [[Updating extensions for iOS 7|iOS 7]] – paste in your notes and share what you've learned, and somebody else will organize it later. :) If you want to ask questions and share tips over chat with other developers, see [[How to use IRC]] for how to connect to #theos and #iphonedev.<br />
<br />
'''Hey developer, you can add your knowledge here! Yes, you! [http://iphonedevwiki.net/index.php?title=Special:UserLogin&returnto=Updating+extensions+for+iOS+14&type=signup Make an account and edit this page!]'''<br />
<br />
If you want to see what's been recently updated on this page, you can use the wiki's [http://iphonedevwiki.net/index.php?title=Updating_extensions_for_iOS_14&action=history history feature] to compare the revisions (to look at the diff) since the last time you visited this page.<br />
<br />
[[Category:Updating extensions]]<br />
<br />
== IMMessage instantMessageWithText ==<br />
<br />
All functions in the IMMessage class that start with "instantMessageWithText" now take an extra parameter, "threadIdentifier". For a message that's not replying to a specific thread, you can just pass in nil for this parameter.<br />
<br />
== Toolchain ==<br />
<br />
=== Xcode 10-11 and 12 are necessary to support iOS 14 and 13- for arm64e by single package ===<br />
<br />
arm64e ABI version is changed in iOS 14.<br />
<br />
We must compile both arm64e ABI version slice to support iOS 14 and 13- using Xcode 10-11 and 12.<br />
<br />
This topic for theos is under development [https://github.com/theos/theos/issues/563 thoes/issue#563]<br />
<br />
If you don't want to have multiple arm64e slices or go to greater length at the moment, use Xcode 11 or lower to compile your tweaks, or use Xcode's Toolchain from Xcode 11 and lower, as done [https://github.com/opa334/Choicy/blob/master/Makefile#L1 in Choicy here].<br />
<br />
== Hooking unexported Objective-C functions (objc_direct) ==<br />
<br />
Starting from Xcode 12 and iOS 14.0, Apple introduced objc_direct feature to shrink the compiled binary size and in hope to improve performance. As a result, Objective-C methods are not visible to any runtime browsers, any class-dump utilities and any disassemblers, raising a challenge for Objective-C direct methods hooking. Safari application is one of those that Apple transitioned to using objc_direct, making Safari tweaks more difficult to be created.<br />
<br />
[https://github.com/opa334/libundirect libundirect] by opa334dev thus is developed to act as a patchfinder (to find an address to the direct method that you want to hook) and as a rebinder (to add back the Objective-C signature to the direct method, providing backward compatibility). Visit [[libundirect]] for how to use it.</div>PoomSmarthttps://iphonedev.wiki/index.php?title=Welcome&diff=5662Welcome2021-05-08T10:53:33Z<p>PoomSmart: Added libundirect to the featured libraries</p>
<hr />
<div>__NOTOC__<br />
== Welcome to the iPhoneDevWiki ==<br />
[[File:Drill bits.jpg|right]]<br />
Our goal is to share the sum of all human<ref> We'll make an exception for lawyers; they may submit too. Cf. http://wiki.creativecommons.org/Frequently_Asked_Questions#How_does_a_Creative_Commons_license_operate.3F: "Creative Commons licenses are expressed in three different formats: the Commons Deed (human-readable code), the Legal Code (lawyer-readable code); and the metadata (machine readable code)."</ref> knowledge about jailbroken iOS development. In other words, this is a collection of documentation written by developers to help each other write extensions (tweaks) for jailbroken iOS, and you're invited to learn from it and contribute to it too.<br />
<br />
What is this wiki for?<br />
<br />
* Information about using iOS [[frameworks]] (both public and [[PrivateFrameworks|private]]), [[SpringBoard.app|SpringBoard]], system [[daemons]] (for hooking and hacking), and classes in applications included with the system.<br />
* Information about third-party libraries and extensions for developers ([[ActionMenu]], [[AppList]], [[Flipswitch]], [[IconSupport]], [[libactivator]], [[libundirect]], [[libhide]], [[libobjcipc]], [[libstatusbar]], [[PreferenceLoader]], [[RocketBootstrap]], etc.).<br />
* Lists of [[Open Source Projects]], [[Reverse Engineering Tools]], [[advice for new developers]], [[List of development blogs|development blogs]], and other useful information for developers.<br />
* Documentation about making [http://iphonedevwiki.net/index.php/Category:Preferences preferences] for extensions: [[PreferenceLoader]], [[PreferenceBundles]], [[Preferences specifier plist]], [[Preferences.framework]].<br />
* Anything else about development for jailbroken iOS devices. (For other technical information about iOS, see [http://theiphonewiki.com The iPhone Wiki], which covers topics including jailbreak exploits, internal iOS systems, and iOS hardware details. [http://theiphonewiki.com/wiki/Up_to_Speed "Up to Speed"] is its getting-started page about learning about security research on iOS.)<br />
<br />
Current featured article: '''[[Updating extensions for iOS 14]]'''<br />
<br />
New articles: [[Kik]], [[Active Developers]], [[IPC|Inter Process Communication (IPC)]], [[Using ARC in tweaks]], [[Career advice]], [[IOMobileFramebuffer]], [[IOAudio2Device]], [[IOAudio2Transformer]], [[RocketBootstrap]], [[Breadcrumbs]].<br />
<br />
If you'd like to make a new article or improve an existing article, see [[Help:Editing]] for advice (and see [[#Editing this wiki]] for ideas). '''Articles that need work''': [[Packaging]] (tools, control file tips, troubleshooting dpkg-deb errors), [[Next Steps After Getting Started]] (a set of ideas for tutorials you could write), ''edit this page and add your idea here''.<br />
<br />
Documentation over classes, especially regarding version-specific changes, hasn't been updated recently. If you see an article for a class you use and notice inaccuracies, something as simple as adding a "This information is outdated" or making a correction/note on code is incredibly helpful.<br />
<br />
== Getting started ==<br />
<br />
New to developing for jailbroken devices? Welcome, it's fun and challenging! Hopefully you already have some experience with Objective-C. You will want to get familiar with [[MobileSubstrate|Cydia Substrate (formerly called MobileSubstrate)]] and [[Theos]], and you can study some [[Open Source Projects]] to see how existing tweaks work. See '''[[Getting Started]]''' and also take a look at [[Best Practices]] and [[MobileSubstrate Pitfalls]]. If you're looking for a more thorough and sequential tutorial, take a look at the book ''[http://iosre.com/t/ios-app-reverse-engineering-the-worlds-1st-book-of-very-detailed-ios-app-reverse-engineering-skills/1117 iOS App Reverse Engineering]'' and its forum [http://bbs.iosre.com iOSRE].<br />
<br />
'''[[Getting Help | How to ask for help]]:''' There are tags for [http://stackoverflow.com/questions/tagged/jailbreak "jailbreak"], [http://stackoverflow.com/questions/tagged/cydia "Cydia"], and [http://stackoverflow.com/questions/tagged/theos "Theos"] on Stack Overflow, a site for programming questions in general; feel free to ask there as well. On reddit, there's [http://www.reddit.com/r/jailbreakdevelopers/ /r/jailbreakdevelopers]. For non-development-related troubleshooting questions, try [http://www.reddit.com/r/jailbreak/ /r/jailbreak].<br />
<br />
== Overview of contents ==<br />
<br />
By topic:<br />
<br />
* '''Frameworks''':<br />
** {{fwlink|UIKit}} &bull; {{fwlink|GraphicsServices}} &bull; {{fwlink|AppSupport}} &bull; {{fwlink|BiometricKit}} &bull; {{fwlink|ChatKit}} &bull; {{fwlink|MobileWiFi}} &bull; '''''[[Template:Navbox Frameworks|more »]]'''''<br />
* '''Applications''':<br />
** {{applink|SpringBoard}} &bull; {{applink|Preferences}} &bull; {{applink|MobileSafari}} &bull; '''''[[Template:Navbox Applications|more »]]'''''<br />
* '''Extensions''':<br />
** [[ActionMenu]] &bull; [[AppList]] &bull; [[Cydget]] &bull; [[Flipswitch]] &bull; [[IconSupport]] &bull; [[LayerSnapshotter]] &bull; [[libactivator]] &bull; [[libhide]] &bull; [[libobjcipc]] &bull; [[libstatusbar]] &bull; [[PreferenceLoader]] &bull; [[RocketBootstrap]] &bull; [[WinterBoard]] &bull; [[libPassword]] &bull; '''''[[:Category:Cydia_packages|more »]]'''''<br />
* '''System directories''':<br />
** [[Frameworks]] &bull; [[Internet Plug-Ins]] &bull; [[PreferenceBundles]] &bull; [[PrivateFrameworks]] &bull; '''''[[Template:Navbox_Library|more »]]'''''<br />
* '''Other parts of iOS''':<br />
** [[Bluetooth]] &bull; [[CgBI file format]] &bull; [[Coprocessors]] &bull; [[Daemons]] &bull; [[dyld_shared_cache]] &bull; [[Entitlements]] &bull; [[iOS Keyboard]] &bull; [[launchd]] &bull; [[NFC]] &bull; [[Notifications]] &bull; [[Seatbelt]]<br />
* '''Development tools''':<br />
** [[Cycript]] &bull; [[MobileSubstrate|Cydia Substrate (MobileSubstrate)]] &bull; [[debugserver|debugserver (remote debugging)]] &bull; [[Jailbreak Development Tools]] &bull; [[ldid]] &bull; [[On-device toolchains]] &bull; [[Reverse Engineering Tools]] &bull; [[Theos]], [[Logos]], [[NIC]], [[Logify]] &bull; [[Retrieving SDKs]] &bull; [[Xcode|Xcode &ndash; Bypass Provisioning Profile]] &bull; [[SSH Over USB]]<br />
* '''Other articles about development''':<br />
** [[Getting Started]] &bull; [[Best Practices]] &bull; [[MobileSubstrate Pitfalls]] &bull; [[Open Source Projects]] &bull; [[Advice for new developers]] &bull; [[Cydia Store Integration]] &bull; [[Tweak DRM]] &bull; [[Code Signing]] &bull; [[Repository Management]] &bull; [[Packaging]] &bull; [[Crack prevention]] &bull; [[List of development blogs]] &bull; [[Using ARC in tweaks]] &bull; [[Career advice]]<br />
<br />
By iOS version:<br />
<br />
* '''New in iOS 14:''' [[Updating extensions for iOS 14]]<br />
* '''New in iOS 13:''' [[Updating extensions for iOS 13]]<br />
* '''New in iOS 12:''' [[Updating extensions for iOS 12]]<br />
* '''New in iOS 11:''' [[Updating extensions for iOS 11]]<br />
* '''New in iOS 10:''' [[Updating extensions for iOS 10]], [[ControlCenterUI.framework]], [[UserNotificationsUIKit.framework]].<br />
* '''New in iOS 9:''' [[Updating extensions for iOS 9]], [[Updating extensions for iOS 9.3.3]], [[Breadcrumbs]].<br />
* '''New in iOS 8:''' [[Updating extensions for iOS 8]], [[AssertionServices.framework]], [[SBSRestartRenderServerAction]], [[FBSSystemService]], [[UIAlertController]].<br />
* '''New in iOS 7:''' [[Updating extensions for iOS 7]], [[Debugging on iOS 7]], [[Downgrading iPhone 4 from iOS 7]], [[BiometricKit.framework]], [[TouchID]], [[UIBackdropView]], [[AVFlashlight]], [[SBAppSliderController]].<br />
* '''New in iOS 6:''' [[BackBoardServices.framework]], [[backboardd]], [[ChatKit.framework]], [[BKSProcessAssertion]].<br />
* '''New in iOS 5:''' [[SBIconView]], [[CKMadridService]], [[SBAppContextHostManager]].<br />
* '''New in iOS 4:''' [[SBAppSwitcherModel]].<br />
<br />
Translated articles: <br />
<br />
* '''Français''': [[Main page/fr]] &bull; [[MobileSubstrate/fr]] &bull; [[SSH Over USB/fr]] &bull; [[UIFont/fr]] &bull; [[UIColor/fr]] &bull; [[ActorKit.framework/fr]] &bull; [[IOSOpenDev/fr]]<br />
* '''ไทย''': [[MobileSubstrate/th]] &bull; [[SSH Over USB/th]] &bull; [[SpringBoard.app/th]] &bull; [[UIColor/th]]<br />
* '''Deutsch''': [[Theos/de]]<br />
<br />
<!-- {{Navbox Frameworks}}<br />
{{Navbox Applications}} --><br />
<br />
== Editing this wiki ==<br />
<br />
* If you have anything at all to contribute, feel free to do so!<br />
* An account is required to edit pages, but everyone is welcome to make an account. <br />
<br />
Some ideas for information to contribute:<br />
<br />
* Add more projects to the list of [[Open Source Projects]], or fill out details on that page.<br />
* Expand [[Getting Started]] for new developers - what do they need to know before beginning? How do they set up a development environment on OS X, Windows, and Linux? What are common beginner's mistakes that they should watch out for? How to reverse-engineer parts of iOS for writing tweaks? How to debug with GDB and learn about memory management?<br />
* Update articles that haven't been significantly edited in a few years, such as [[Seatbelt]] and [[Crack prevention]]. See [[Special:AncientPages]] for a list of articles that haven't been updated recently.<br />
* Help [[Cycript]] explain why Cycript is fun - syntax highlighting, injection, auto-completion, generally exploring around.<br />
* Make a page that documents a class or framework you're familiar with.<br />
* If you've developed a library that other developers can use or write addons/plugins/extensions for, make a page that documents your project.<br />
* Update [[Xcode]] with better information about how to build apps for jailbroken devices.<br />
* Make the homepage more useful! For example, add links to good pages that are hidden/buried deep within the wiki.<br />
* The following articles are linked from nowhere in the wiki: [[Special:LonelyPages]] - you can fix that by linking them somewhere.<br />
* Check out the most popular pages and see if they need updating: [[Special:PopularPages]].<br />
* Write an article that is in demand: [[Special:WantedPages]].<br />
* Translate an existing article into a non-English language. Check out the list at [[Special:PopularPages]] for ideas about high-priority articles to translate, and then make a new page with this name format: <code>Article name/[language code]</code>. [http://svn.wikimedia.org/svnroot/mediawiki/trunk/phase3/languages/Names.php Here's the list of language codes.] For example: [[PreferenceLoader/de]] or [[Libactivator/sv]].<br />
<br />
----<br />
<br />
<references /></div>PoomSmarthttps://iphonedev.wiki/index.php?title=Libundirect&diff=5661Libundirect2021-05-08T10:52:31Z<p>PoomSmart: Added libundirect documentation</p>
<hr />
<div>{{DISPLAYTITLE:libundirect}}<br />
{{Infobox Package<br />
|developer=[https://twitter.com/opa334dev Lars Fröder (opa334)]<br />
|version=1.1.1<br />
|package=com.opa334.libundirect<br />
}}<br />
<br />
'''libundirect''' is a patchfinding and rebinding library that provides directives to hook Objective-C direct methods. With the feature called objc_direct introduced in Xcode 12 and iOS 14.0, these direct methods are stripped when compiled - being unexported C functions and thus their signature and name are missing.<br />
<br />
As a patchfinder, <code>libundirect_find()</code> can find the address of the function to hook by providing unique bytes within the function and the name of the binary that the function resides. You need to perform reverse engineering on the binary that you are working with in order to determine the bytes to use. See [https://github.com/opa334/libundirect/blob/main/README.md#patchfinder here] for more details.<br />
<br />
As a rebinder, <code>libundirect_rebind()</code> can re-add Objective-C method signature to the function that you hook. This provides backward compatibility for earlier iOS versions that the signature is still intact - and that you have to import <code><libundirect/libundirect_hookoverwrite.h></code> to make <code>MSHookMessageEx()</code> aware of direct methods.<br />
<br />
== How to use this library ==<br />
<br />
Headers are available from [https://github.com/opa334/libundirect libundirect's GitHub project] or from [https://github.com/theos/headers Theos' headers project]. The library can be installed to <code>$THEOS/vendor/lib</code> by running <code>install_to_theos.sh</code> script inside libundirect repository.<br />
<br />
=== Include directive(s) ===<br />
<br />
<source lang="objc"><br />
#import <libundirect/libundirect.h><br />
#import <libundirect/libundirect_dynamic.h> // if you don't want to link directly against libundirect<br />
#import <libundirect/libundirect_hookoverwrite.h> // if you want backward compatibility<br />
</source><br />
<br />
=== Makefile ===<br />
<br />
Add to your Makefile:<br />
<br />
* <code>libundirect</code> to the <code>XXX_LIBRARIES</code> variable.<br />
<br />
=== Packaging ===<br />
<br />
Add to your package's control file:<br />
<br />
* <code>com.opa334.libundirect (>= 1.1.1)</code> to the <code>Depends</code> field.<br />
<br />
== Examples ==<br />
<br />
=== Hooking an Objective-C method (MobileSafari) ===<br />
<br />
We will use the code in SafariPlus by opa334 as an example.<br />
<br />
<source lang="objc"><br />
#import <libundirect/libundirect.h><br />
#import <libundirect/libundirect_hookoverwrite.h><br />
<br />
%hook BrowserController<br />
<br />
- (void)tabControllerDocumentCountDidChange:(TabController *)tabController {<br />
%orig;<br />
...<br />
}<br />
<br />
%end<br />
<br />
...<br />
<br />
// In your constructor:<br />
<br />
Class class_browserController = NSClassFromString(@"BrowserController");<br />
<br />
// -[BrowserController tabControllerDocumentCountDidChange:]<br />
// arm64 memory of function: [600100B4 F44FBEA9]<br />
// arm64e memory of function: [A00100B4 7F2303D5 F44FBEA9]<br />
// criteria: called by -[BrowserController _updateSceneTitle] (14.2: sub_100041e5c, references string @"Private Browsing")<br />
// 14.2: sub_10005bef8, arm64e: sub_10005E824<br />
<br />
#if __arm64e__<br />
void* tabControllerDocumentCountDidChange = libundirect_find(@"MobileSafari", (unsigned char[]){0xA0, 0x01, 0x00, 0xB4, 0x7F, 0x23, 0x03, 0xD5, 0xF4, 0x4F, 0xBE, 0xA9}, 12, 0);<br />
#else<br />
void* tabControllerDocumentCountDidChange = libundirect_find(@"MobileSafari", (unsigned char[]){0x60, 0x01, 0x00, 0xB4, 0xF4, 0x4F, 0xBE, 0xA9}, 8, 0);<br />
#endif<br />
<br />
libundirect_rebind(tabControllerDocumentCountDidChange, class_browserController, @selector(tabControllerDocumentCountDidChange:), "v@:@");<br />
</source><br />
<br />
=== Hooking an unnamed C function (libicucore) ===<br />
<br />
We will use the code in EmojiAttributes by PoomSmart as an example.<br />
<br />
<source lang="objc"><br />
#import <libundirect/libundirect.h><br />
<br />
...<br />
<br />
%group getUnicodeProperties<br />
<br />
%hookf(uint32_t, u_getUnicodeProperties, UChar32 c, int32_t column) {<br />
if (column >= propsVectorsColumns)<br />
return 0;<br />
uint16_t vecIndex = UTRIE2_GET16(&propsVectorsTrie, c);<br />
return propsVectors[vecIndex + column];<br />
}<br />
<br />
%end<br />
<br />
// In your constructor:<br />
<br />
#if TARGET_OS_SIMULATOR<br />
// Memory of function (iOS 13.5): 31C083FE 020F8F8D 00000055 4889E581 FFFFD700 00770789 F8C1E805 EB4A81FF FFFF0000 771731C0 81FF00DC 0000B940 0100000F 4DC889F8 C1E805EB 29B8D813 000081FF FFFF1000 773289F8 C1E80B48 8D0D30CC 1B000FB7 8C414010 000089F8 C1E80583 E03F01C8 89C0488D 0D15CC1B 000FB704 4183E71F 488D0487 488D0D03 CC1B000F B7044148 63CE4801 C1488D05 D2B11A00 8B04885D C3<br />
// Memory of function (iOS 12.4): 554889E5 31C083FE 020F8F8A 00000081 FFFFD700 00770789 F8C1E805 EB4C81FF FFFF0000 771731C0 81FF00DC 0000B940 0100000F 4DC889F8 C1E805EB 2B81FFFF FF100076 07B8D413 0000EB32 89F8C1E8 0B488D0D CFE61B00 0FB78C41 40100000 89F8C1E8 0583E03F 01C889C0 488D0DB4 E61B000F B7044183 E71F488D 0487488D 0DA2E61B 000FB704 414863CE 4801C148 8D0571D3 1A008B04 885DC3<br />
// Unique bytes (iOS 13.5): E03F01C8 89C0488D 0D15CC1B (offset: 100)<br />
// Unique bytes (iOS 12.4): 0583E03F 01C889C0 488D0DB4 (offset: 100)<br />
// Starting byte (iOS 13.5): 0x31<br />
// Starting byte (iOS 12.4): 0x55<br />
void *rp = libundirect_find(@"libicucore.A.dylib", (unsigned char[]){0xE0, 0x3F, 0x01, 0xC8, 0x89, 0xC0, 0x48, 0x8D, 0x0D, 0x15, 0xCC, 0x1B}, 12, 0x31);<br />
if (rp == NULL)<br />
rp = libundirect_find(@"libicucore.A.dylib", (unsigned char[]){0x05, 0x83, 0xE0, 0x3F, 0x01, 0xC8, 0x89, 0xC0, 0x48, 0x8D, 0x0D, 0xB4}, 12, 0x55);<br />
#else<br />
// Memory of function: 3F080071 6D000054 00008052 C0035FD6 087C0B53 1F690071 68000054 087C0513 08000014 087C1053 68020035 08809B52 1F00086B 08288052 08B19F1A 0815800B 090D00B0 29110F91 28D96878 09100012 2809080B 090D00B0 29110F91 28D96878 0801010B 890C00B0 29A12791 20D968B8 C0035FD6 1F410071 69000054 08548252 F5FFFF17 087C0B13 090D00B0 29110F91 28C5288B 08816079 0A280553 08412A8B 28796878 EAFFFF17<br />
// Unique bytes: 3F080071 6D000054 00008052 C0035FD6 (offset: 0)<br />
// Starting byte: 0x3F<br />
void *rp = libundirect_find(@"libicucore.A.dylib", (unsigned char[]){0x3F, 0x08, 0x00, 0x71, 0x6D, 0x00, 0x00, 0x54, 0x00, 0x00, 0x80, 0x52, 0xC0, 0x03, 0x5F, 0xD6}, 16, 0x3F);<br />
#endif<br />
<br />
%init(getUnicodeProperties, u_getUnicodeProperties = (void *)rp);<br />
</source><br />
<br />
== Project Examples ==<br />
<br />
{| class="wikitable"<br />
|-<br />
! Project<br />
! Author<br />
|-<br />
| [https://github.com/opa334/SafariPlus SafariPlus]<br />
| [https://github.com/opa334 opa334]<br />
|-<br />
| [https://github.com/udevsharold/safaritabs14 SafariTabs14]<br />
| [https://github.com/udevsharold udevsharold]<br />
|-<br />
| [https://github.com/PoomSmart/EmojiAttributes EmojiAttributes]<br />
| [https://github.com/PoomSmart PoomSmart]<br />
|}<br />
<br />
== External Links ==<br />
<br />
* [https://github.com/opa334/libundirect/blob/main/README.md libundirect's detailed usages]<br />
* [https://nshipster.com/direct/ Objective-C Direct Methods]</div>PoomSmarthttps://iphonedev.wiki/index.php?title=Updating_extensions_for_iOS_13&diff=5660Updating extensions for iOS 132021-05-08T04:43:36Z<p>PoomSmart: /* Home Screen Layout */ Demonstrate how to adjust icon grid size</p>
<hr />
<div>Let's collect knowledge like we did with [[Updating extensions for iOS 12|iOS 12]], [[Updating extensions for iOS 11|iOS 11]], [[Updating extensions for iOS 10|iOS 10]], [[Updating extensions for iOS 9|iOS 9]], [[Updating extensions for iOS 8|iOS 8]] and [[Updating extensions for iOS 7|iOS 7]] – paste in your notes and share what you've learned, and somebody else will organize it later. :) If you want to ask questions and share tips over chat with other developers, see [[How to use IRC]] for how to connect to #theos and #iphonedev.<br />
<br />
'''Hey developer, you can add your knowledge here! Yes, you! [http://iphonedevwiki.net/index.php?title=Special:UserLogin&returnto=Updating+extensions+for+iOS+13&type=signup Make an account and edit this page!]'''<br />
<br />
If you want to see what's been recently updated on this page, you can use the wiki's [http://iphonedevwiki.net/index.php?title=Updating_extensions_for_iOS_13&action=history history feature] to compare the revisions (to look at the diff) since the last time you visited this page.<br />
<br />
[[Category:Updating extensions]]<br />
<br />
== SBApplication -(FBScene*)mainScene removed ==<br />
<br />
<code>-[SBApplication mainScene]</code> was removed in iOS 13. It can be accessed from a SBApplication by replacing <code>[myApp mainScene]</code> with the following:<br />
<br />
<code>[[FBSceneManager sharedInstance] sceneWithIdentifier:[myApp _baseSceneIdentifier]]</code><br />
<br />
<code>myApp</code> being the name of your SBApplication instance.<br />
<br />
== SBRootIconListView ==<br />
<br />
This class was removed entirely with iOS 13. Root Icon Lists are now instances of <code>SBIconListView</code>.<br />
<br />
== Home Screen Layout ==<br />
<br />
=== Classes ===<br />
<br />
==== SBIconListFlowLayout ==== <br />
<br />
Layout handling in iOS 13 now uses <code>SBIconListFlowLayouts</code>. These are provided by an instance of <code>SBHDefaultIconListLayoutProvider</code>.<br />
<br />
This alone handles row/column count. It also contains a <code>SBIconListGridLayoutConfiguration</code>, which controls the spacing and location of icons.<br />
<br />
==== SBIconListGridLayoutConfiguration ====<br />
<br />
This class contains several properties that can be modified to alter the layout. <br />
<br />
Selectors of interest include <code>portraitLayoutInsets</code> and <code>landscapeLayoutInsets</code>. These return an instance of <code>UIEdgeInsets</code> that can be used to manipulate layout.<br />
<br />
=== Modifying number of rows and columns ===<br />
<br />
It now depends on "where" you want to change the number of rows and columns. If you want to adjust the values for the icons in Home Screen (and Home Screen with Today widgets in iPad), you can conditionally apply that for the icon location <code>SBIconLocationRoot*</code>, like so:<br />
<br />
%hook SBHDefaultIconListLayoutProvider<br />
<br />
- (SBIconListGridLayout *)makeLayoutForIconLocation:(NSString *)iconLocation {<br />
SBIconListGridLayout *layout = %orig;<br />
if ([iconLocation hasPrefix:@"SBIconLocationRoot"]) {<br />
SBIconListGridLayoutConfiguration *config = [layout valueForKey:@"_layoutConfiguration"];<br />
config.numberOfLandscapeRows += 1;<br />
config.numberOfLandscapeColumns += 2;<br />
config.numberOfPortraitRows += 1;<br />
config.numberOfPortraitColumns += 2;<br />
}<br />
return layout;<br />
}<br />
<br />
%end<br />
<br />
== Generating an apps icon image ==<br />
<br />
Previously an icon image could be generated from an icon object like so<br />
<br />
<source lang="objc"><br />
SBIcon *icon = someIcon;<br />
UIImage *iconImage = [icon generateIconImage:2];<br />
</source><br />
<br />
In iOS 13 this method was changed to <code>-generateIconImageWithInfo:(struct SBIconImageInfo)info</code><br />
<br />
<source lang="objc"><br />
struct SBIconImageInfo {<br />
CGSize size;<br />
CGFloat scale;<br />
CGFloat continuousCornerRadius;<br />
};<br />
</source><br />
<br />
<source lang="objc"><br />
SBIconController *iconController = [NSClassFromString(@"SBIconController") sharedInstance];<br />
SBIcon *icon = [iconController.model expectedIconForDisplayIdentifier:@"com.apple.Music"];<br />
<br />
CGSize imageSize = CGSizeMake(60, 60);<br />
<br />
struct SBIconImageInfo imageInfo;<br />
imageInfo.size = imageSize;<br />
imageInfo.scale = [UIScreen mainScreen].scale;<br />
imageInfo.continuousCornerRadius = 12;<br />
<br />
UIImage *iconImage = [icon generateIconImageWithInfo:imageInfo];<br />
</source></div>PoomSmarthttps://iphonedev.wiki/index.php?title=Updating_extensions_for_iOS_14&diff=5659Updating extensions for iOS 142021-05-08T04:34:18Z<p>PoomSmart: Added information about libundirect</p>
<hr />
<div>Let's collect knowledge like we did with [[Updating extensions for iOS 13|iOS 13]], [[Updating extensions for iOS 12|iOS 12]], [[Updating extensions for iOS 11|iOS 11]], [[Updating extensions for iOS 10|iOS 10]], [[Updating extensions for iOS 9|iOS 9]], [[Updating extensions for iOS 8|iOS 8]] and [[Updating extensions for iOS 7|iOS 7]] – paste in your notes and share what you've learned, and somebody else will organize it later. :) If you want to ask questions and share tips over chat with other developers, see [[How to use IRC]] for how to connect to #theos and #iphonedev.<br />
<br />
'''Hey developer, you can add your knowledge here! Yes, you! [http://iphonedevwiki.net/index.php?title=Special:UserLogin&returnto=Updating+extensions+for+iOS+14&type=signup Make an account and edit this page!]'''<br />
<br />
If you want to see what's been recently updated on this page, you can use the wiki's [http://iphonedevwiki.net/index.php?title=Updating_extensions_for_iOS_14&action=history history feature] to compare the revisions (to look at the diff) since the last time you visited this page.<br />
<br />
[[Category:Updating extensions]]<br />
<br />
== IMMessage instantMessageWithText ==<br />
<br />
All functions in the IMMessage class that start with "instantMessageWithText" now take an extra parameter, "threadIdentifier". For a message that's not replying to a specific thread, you can just pass in nil for this parameter.<br />
<br />
== Toolchain ==<br />
<br />
=== Xcode 10-11 and 12 are necessary to support iOS 14 and 13- for arm64e by single package ===<br />
<br />
arm64e ABI version is changed in iOS 14.<br />
<br />
We must compile both arm64e ABI version slice to support iOS 14 and 13- using Xcode 10-11 and 12.<br />
<br />
This topic for theos is under development [https://github.com/theos/theos/issues/563 thoes/issue#563]<br />
<br />
If you don't want to have multiple arm64e slices or go to greater length at the moment, use Xcode 11 or lower to compile your tweaks, or use Xcode's Toolchain from Xcode 11 and lower, as done [https://github.com/opa334/Choicy/blob/master/Makefile#L1 in Choicy here].<br />
<br />
== Hooking unexported Objective-C functions (objc_direct) ==<br />
<br />
Starting from Xcode 12 and iOS 14.0, Apple introduced objc_direct feature to shrink the compiled binary size and in hope to improve performance. As a result, Objective-C methods are not visible to any runtime browsers, any class-dump utilities and any disassemblers, raising a challenge for Objective-C direct methods hooking. Safari application is one of those that Apple transitioned to using objc_direct, making Safari tweaks more difficult to be created.<br />
<br />
[https://github.com/opa334/libundirect libundirect] by opa334dev thus is developed to act as a patchfinder (to find an address to the direct method that you want to hook) and as a rebinder (to add back the Objective-C signature to the direct method, providing backward compatibility). You can consult its README for how to use it.</div>PoomSmarthttps://iphonedev.wiki/index.php?title=Updating_extensions_for_iOS_14&diff=5658Updating extensions for iOS 142021-05-08T04:24:29Z<p>PoomSmart: Use Xcode 11- Toolchain as an alternative to compile for arm64e cross-compatible</p>
<hr />
<div>Let's collect knowledge like we did with [[Updating extensions for iOS 13|iOS 13]], [[Updating extensions for iOS 12|iOS 12]], [[Updating extensions for iOS 11|iOS 11]], [[Updating extensions for iOS 10|iOS 10]], [[Updating extensions for iOS 9|iOS 9]], [[Updating extensions for iOS 8|iOS 8]] and [[Updating extensions for iOS 7|iOS 7]] – paste in your notes and share what you've learned, and somebody else will organize it later. :) If you want to ask questions and share tips over chat with other developers, see [[How to use IRC]] for how to connect to #theos and #iphonedev.<br />
<br />
'''Hey developer, you can add your knowledge here! Yes, you! [http://iphonedevwiki.net/index.php?title=Special:UserLogin&returnto=Updating+extensions+for+iOS+14&type=signup Make an account and edit this page!]'''<br />
<br />
If you want to see what's been recently updated on this page, you can use the wiki's [http://iphonedevwiki.net/index.php?title=Updating_extensions_for_iOS_14&action=history history feature] to compare the revisions (to look at the diff) since the last time you visited this page.<br />
<br />
[[Category:Updating extensions]]<br />
<br />
== IMMessage instantMessageWithText ==<br />
<br />
All functions in the IMMessage class that start with "instantMessageWithText" now take an extra parameter, "threadIdentifier". For a message that's not replying to a specific thread, you can just pass in nil for this parameter.<br />
<br />
== Toolchain ==<br />
<br />
=== Xcode 10-11 and 12 are necessary to support iOS 14 and 13- for arm64e by single package ===<br />
<br />
arm64e ABI version is changed in iOS 14.<br />
<br />
We must compile both arm64e ABI version slice to support iOS 14 and 13- using Xcode 10-11 and 12.<br />
<br />
This topic for theos is under development [https://github.com/theos/theos/issues/563 thoes/issue#563]<br />
<br />
If you don't want to have multiple arm64e slices or go to greater length at the moment, use Xcode 11 or lower to compile your tweaks, or use Xcode's Toolchain from Xcode 11 and lower, as done [https://github.com/opa334/Choicy/blob/master/Makefile#L1 in Choicy here].</div>PoomSmarthttps://iphonedev.wiki/index.php?title=AppList&diff=5657AppList2021-05-08T04:20:42Z<p>PoomSmart: Fixed/removed dead link and minor updates</p>
<hr />
<div>{{Infobox Package<br />
|developer=[[User:Rpetrich|Ryan Petrich]]<br />
|version=1.5.9<br />
|package=applist<br />
}}<br />
<br />
'''AppList''' is a library for fetching app information. As described on its package page: "Allows developers to query the list of installed apps and provide a preferences pane based on that information. Exports displayIdentifier, displayName, icon and smallIcon via a remote messaging center so that it's easy to write a prefs pane that presents a list of apps."<br />
<br />
== How to use this library ==<br />
<br />
Headers are available from [https://github.com/rpetrich/AppList/tree/master/public Applist's GitHub project] and the library can be found at <code>/usr/lib/libapplist.dylib</code> on a device where AppList is installed. If using Theos, place the headers in <code>$THEOS/include/AppList</code>, the library in <code>$THEOS/lib/</code>.<br />
<br />
=== Include directive ===<br />
<br />
<source lang="objc"><br />
#import <AppList/AppList.h><br />
</source><br />
<br />
=== Makefile ===<br />
<br />
Add to your Makefile:<br />
<br />
* <code>applist</code> to the <code>XXX_LIBRARIES</code> variable.<br />
<br />
=== Packaging ===<br />
<br />
Add to your package's control file:<br />
<br />
* <code>, mobilesubstrate (>= 0.9.5000), firmware (>= 3.0), com.rpetrich.rocketbootstrap (>= 1.0.3) | firmware (<< 7.0)</code> to the <code>Depends</code> field.<br />
<br />
== PreferenceLoader ==<br />
<br />
=== Simple Approach ===<br />
<br />
The common way to use AppList is via its [[PreferenceLoader]] (preferences) integration, by putting entries in a PreferenceLoader plist: [https://github.com/rpetrich/AppList/blob/master/sample/layout/Library/PreferenceLoader/Preferences/AppListSample.plist AppListSample.plist].<br />
<br />
{| class="wikitable"<br />
! Key !! Type !! Description !! Default value<br />
|-<br />
| ALNavigationTitle || string || Navigation title. || The specifier name<br />
|-<br />
| ALSingleEnabledMode || bool || Switch between single and multiple row selection. || NO<br />
|-<br />
| ALSectionDescriptors || array || Array of PSSpecifier-style dictionaries. || -<br />
|-<br />
| ALLocalizationBundle || string || Absolute path to a localization bundle. || nil<br />
|-<br />
| ALSettingsDefaultValue || object || Default value. || -<br />
|-<br />
| ALSettingsPath || string || Absolute file path to a settings file. || -<br />
|-<br />
| ALSettingsKey || string || Key for the data to be saved when <tt>ALSingleEnabledMode</tt> is true. || -<br />
|-<br />
| ALSettingsKeyPrefix || string || Key prefix for the key for the data to be saved when <tt>ALSingleEnabledMode</tt> is false. || "ALValue-"<br />
|-<br />
| ALChangeNotification || string || Darwin notification string to be posted when a change happens. || -<br />
|-<br />
| ALAllowsSelection || bool || Enable row selection. || ALSingleEnabledMode value<br />
|}<br />
<br />
''To do: Add missing keys "listed" in the [https://github.com/rpetrich/AppList/blob/master/ALApplicationTableDataSource.m source code]. Expand ALSectionDescriptors' usage like in [https://github.com/rpetrich/Emphasize/blob/master/layout/Library/PreferenceLoader/Preferences/Emphasize/Emphasize.plist Emphasize].''<br />
<br />
The following specifier presents a <code>PSLinkCell</code> for Cydia and iFile, which present a <code>PSLinkListCell</code> for a selection of options.<br />
<source lang="xml"><br />
{<br />
bundle = AppList;<br />
cell = PSLinkCell;<br />
icon = "/Applications/Preferences.app/icon.png";<br />
isController = 1;<br />
label = "AppList Sample";<br />
ALAllowsSelection = 1;<br />
ALSectionDescriptors = (<br />
{<br />
title = "Supported Applications";<br />
predicate = "(displayIdentifier IN {'com.saurik.Cydia','eu.heinelt.ifile'})";<br />
"cell-class-name" = "ALDisclosureIndicatedCell";<br />
"icon-size" = 29;<br />
"suppress-hidden-apps" = 1;<br />
action = "showPreferences";<br />
"display-identifier-macro" = "@@DISPLAYIDENTIFIER@@";<br />
entry = {<br />
PostNotification = "com.rpetrich.applist.example.plist";<br />
cell = PSLinkListCell;<br />
default = 0;<br />
defaults = "com.rpetrich.applist.example";<br />
detail = PSListItemsController;<br />
key = "AppColor-@@DISPLAYIDENTIFIER@@";<br />
validTitles = ("Default", "iOS Standard");<br />
validValues = (0, 1);<br />
bundle = "AppList";<br />
isController = 1;<br />
overridePrincipalClass = 1;<br />
};<br />
}<br />
);<br />
}<br />
</source><br />
<br />
== Retrieving Lists and Icons ==<br />
<br />
To get an array of applications' bundle identifiers and their display names sorted in alphabetical order by their display name:<br />
<source lang=objc><br />
// sort the apps by display name. displayIdentifiers is an autoreleased object.<br />
NSArray *sortedDisplayIdentifiers;<br />
NSDictionary *applications = [[ALApplicationList sharedApplicationList] applicationsFilteredUsingPredicate:[NSPredicate predicateWithFormat:@"isSystemApplication = TRUE"]<br />
onlyVisible:YES titleSortedIdentifiers:&sortedDisplayIdentifiers];<br />
</source><br />
<br />
To get the display identifier and icon for a specific app at index <code>idx</code>, choose a size from this enum:<br />
<br />
<source lang=objc><br />
enum {<br />
ALApplicationIconSizeSmall = 29,<br />
ALApplicationIconSizeLarge = 59<br />
};<br />
</source><br />
<br />
And use the following snippet:<br />
<br />
<source lang=objc><br />
NSString *displayIdentifier = [displayIdentifiers objectAtIndex:idx];<br />
UIImage *icon = [apps iconOfSize:ALApplicationIconSizeSmall forDisplayIdentifier:displayIdentifier];<br />
</source><br />
<br />
As seen in [https://github.com/twodayslate/ListLauncher7 ListLauncher7].<br />
<br />
== Retrieving Settings ==<br />
<br />
As a filter, when using the simple selections (as single or switch options):<br />
<br />
<source lang=logos><br />
%ctor {<br />
NSString *identifier = [NSBundle mainBundle].bundleIdentifier;<br />
NSMutableDictionary *plistDict = [[NSMutableDictionary alloc] initWithContentsOfFile:plistpath]; <br />
if ([[plistDict objectForKey:[ALSettingsKeyPrefix stringByAppendingString:identifier]] boolValue]) {<br />
%init(someGroup);<br />
}<br />
}<br />
</source><br />
<br />
== Usages in opensource projects ==<br />
<br />
* https://github.com/iceNuts/DisableNC-Switch<br />
* https://github.com/PoomSmart/AppPad<br />
<br />
== External links ==<br />
<br />
* [https://github.com/rpetrich/AppList AppList on GitHub]<br />
<br />
{{Navbox Library}}<br />
<br />
[[Category:Cydia packages]]<br />
<br />
[[Category:Directories in /Library]]</div>PoomSmarthttps://iphonedev.wiki/index.php?title=IDA_Pro&diff=5602IDA Pro2021-01-09T07:47:35Z<p>PoomSmart: Third-person rephrasing</p>
<hr />
<div>Notes: <br />
* All discussion of resources that can be obtained from InternalUI builds should be regarded as hypothetical and purely educational. Obtaining these builds without the express permission of Apple is illegal, and doing so is discouraged. All information provided here is purely educational. <br />
* This guide was written for IDA 7.5. It should work on 7.3 and above. If you're using a cracked version, Scroll down to the "Pre 7.3" section. The rest doesn't apply to you at all.<br />
<br />
== Crucial Performance Tips ==<br />
<br />
* Close the function window while analyzing to speed up processing about 10 times, typically.<br />
** An active filter in the functions window will hurt speed much worse.<br />
* When analyzing ''massive'' files, close all of the windows inside IDA (IDA View-A, functions, output, etc). Processing will speed up anywhere from 5x to 100x.<br />
* Disable Lumina. Find a way to delete it from IDA if you can. If enabled, it will irreversibly "fix" names by setting them to completely incorrect values. This will waste your time and hurt your analysis.<br />
* IDA seems to operate on one thread. This means when doing anything remotely intensive, it will appear to freeze. This is normal. Don't Force Quit.<br />
* ''Heavily'' consider maxing out your RAM if you work with IDA very often. You won't regret it, and it will avoid system crashes when working with multiple shared caches.<br />
* If you're on an OS with the ability to create "desktops", we highly suggest you give IDA it's own. It will block your UI while loading otherwise.<br />
<br />
General tips regarding IDA usage for iOS RE: * If you are not patient, do not use IDA on the dyld_shared_cache because the processing will be very slow. * Modern versions of IDA come with an built-in dark mode. Use "IDASkins" if you are on an older version to enable dark mode. ''Your eyes will thank you if you work at night.''<br />
<br />
A majority of the information in this article details the process of reverse engineering using the dyld_shared_cache, as doing such is poorly documented in official documents.<br />
<br />
== Terms used ==<br />
<br />
* "Module" represents a Framework or library located in the dyld_shared_cache.<br />
* "Segment" or "Module Segment" refers to a specific segment of a framework.<br />
** The text segment contains code.<br />
** IDA 7.3 and greater include the ability to '''load only data segments on-demand''' without processing the text segment.<br />
<br />
== Analyzing the dyld_shared_cache in IDA Pro 7.3 and later. ==<br />
<br />
Helpful link: https://www.hex-rays.com/products/ida/support/idadoc/1705.shtml<br />
<br />
IDA 7.3 and later includes a powerful, improved shared cache toolkit. It eliminates the need for simulator binaries, and makes analysis possible when you cannot get access to simulator binaries (InternalUI builds, no macOS, no x64 decompiler, etc.)<br />
<br />
Everything described here was performed on a licensed copy of IDA Pro 7.5. Older, especially unlicensed versions, may not be able to handle all of these features.<br />
<br />
-----<br />
<br />
=== Analyzing a specific framework from the dyld_shared_cache. ===<br />
<br />
'''Do not "Load module and dependencies" option on "high level" frameworks.''' In iOS 13, with <code>SpringBoardHome</code> this results in loading 720 modules. This takes upwards of 2 to 3 days on an 8-core 4GHz 32GB-of-ram PC. In newer versions, due to consolidation, that number is down to ~400. You'll still be unable to use your PC for a few days at best. kritanta (@arm64e on Twitter) has loaded an entire shared cache a total of 3 times. There could even be a separate article on the unfixable issues that happen. Utilize the tools described below for the greater good.<br />
<br />
IDA 7.3 introduced powerful new tools for dealing with the cache. You can now load a single module and selectively load only segments you need from other locations in the shared cache. It can be a pain, but the alternative is much, much worse.<br />
<br />
==== Load the framework you're interested in ====<br />
<br />
# Select the "Load single module" option. Ensure you do not select "with dependencies".<br />
# Wait for the module you selected to load. It shouldn't take long.<br />
<br />
For this example we'll be using FrontBoard.framework.<br />
<br />
Loading is the easy part. Now we get to go through the process of correcting IDA's failures, as certain functions tend to fall apart in the dyld_shared_cache subsystem.<br />
<br />
==== Troubleshooting missing data (red addresses, garbage variable names, etc) ====<br />
<br />
The first thing you'll notice is that the assembly or pseudocode generated is absolute gibberish. ''If regular assembly is gibberish to you, this is ''advanced'' gibberish.''<br />
<br />
Swap to the IDA view for this. You may not be able to read assembly, but the pseudocode view doesn't properly handle the new features.<br />
<br />
===== Red addresses =====<br />
<br />
Swap to the "IDA View", as it doesn't work properly in the pseudocode view, and right-click a red address. We are going to assume that the one you clicked was a reference to <code>libobjc.dylib</code>, although it could be any library or framework in the cache.<br />
<br />
You'll see an option to load "libobjc.A:__OBJC_RO" or something similar, or an option to load the entirety of "libobjc.A". If you don't need to reverse the contents of "libobjc.A" (you don't), you should simply load only the segment IDA suggests. This allows you to avoid absolutely destroying your RAM and CPU when working in the cache, while also allowing you to make sense of the code within it.<br />
<br />
===== If the address is still red: =====<br />
<br />
IDA likely failed to recognize any information in the segment. This can be caused by a damaged database, if IDA crashed while processing data.<br />
<br />
Click the address and you'll be taken to the memory location, and if that assumption is correct and you can see vertical strings of letters:<br />
<br />
* In the Menu, click Edit -> Other -> Objective C -> Reload Objective C Info, then navigate to the function you're disassembling.<br />
* Right-click the red address and re-load the segment. Check "Do not show again for this session" unless you like repetition.<br />
* In the Menu, click Edit -> Other -> Objective C -> Reload Objective C Info (yes, again).<br />
* Right-click the far left string on the IDA View that holds the name of your target framework.<br />
* Load the entire framework (2nd option), not a specific section.<br />
* Right-click the red address and load the segment again.<br />
<br />
Your address is probably still red. If so, you've damaged your database. We'd advise deleting the database and starting from scratch. This is the fastest option.<br />
<br />
===== off_xxxxxxxxx (random hex address prefixed by "off_") in your assembly =====<br />
<br />
'''What causes this?'''<br />
<br />
These represent "refs". You're most likely looking at a class ref that failed to load.<br />
<br />
'''Fix'''<br />
<br />
# In the IDA View, double-click the <code>off_x</code> variable to be taken to the classrefs segment<br />
# Right-click the red memory address and load the suggested module segment.<br />
<br />
A name will appear. Good. Go back to your function.<br />
<br />
<ol start="3" style="list-style-type: decimal;"><br />
<li>Edit -> Other -> Objective C -> Reload Objective C Info</li></ol><br />
<br />
If it changes from <code>off_x</code> to <code>selRef</code>, <code>classRef</code>, or something similar, you can move on.<br />
<br />
If it does not change, see below<br />
<br />
'''What causes this?'''<br />
<br />
IDA improperly guessed the type of a struct it loaded due to a missing segment.<br />
<br />
'''Fix'''<br />
<br />
# Double click the pink text if you haven't yet to be taken to the class definition in __objc_data<br />
# Click the <code>_OBJC_CLASS...</code> item to select that line<br />
# Open Edit -> Struct Var<br />
# Select objc_class and hit OK<br />
# A red memory address will appear. Load that segment.<br />
# Make your way back to your function that you're disassembling.<br />
# Edit -> Other -> Objective C -> Reload Objective C Info<br />
# Cry, because it's finally fixed.<br />
<br />
Repeat this for any variables you feel are worth spending the time correcting.<br />
<br />
===== Other issues =====<br />
<br />
kritanta: ''I'm likely forgetting some. I loaded a shared cache fresh and walked myself through fixing issues for the sake of this guide. I'll continue to add solutions as I encounter them.''<br />
<br />
-----<br />
<br />
Interesting Note: Sometimes, you'll see an address and click to load it in. "What on earth is 'GeoServices' doing in this function?" You might think. Upon loading, you'll see it was something like <code>j__objc_retainAutoreleasedReturnValue_0</code>. This is a byproduct of the shared_cache's optimizations, and as a result, you'll end up with several duplicate functions like this. A script to fix these needs to be written, eventually.<br />
<br />
<br />
-----<br />
<br />
Typically loaded frameworks:<br /><br />
libobjc<br /><br />
Foundation<br /><br />
CoreFoundation<br /><br />
GeoServices ("trampoline")<br />
<br />
kritanta: ''I'm very interested in the concept of creating a "template database" that has data segments for these and others pre-loaded. If someone tries that, do update here with how that's done best.''<br />
<br />
-----<br />
<br />
=== Working with pseudocode from the dyld_shared_cache ===<br />
<br />
Something you'll likely become familiar with is the statement <code>(self + 10)</code>, where 10 is any 2 digit number. In objc source, you would see this as an ivar. If you've loaded in the relevant class information, you can help IDA display these ivars properly in the pseudocode view like so:<br />
<br />
* Right-click the <code>a1</code> or <code>self</code> variable on line one<br />
* Click Y or "Set ivar type"<br />
* Change the class of <code>self</code>/<code>a1</code> to the class shown next to it.<br />
* Change a1 to self if need be<br />
<br />
Ivars should now be properly generated and shown in pseudocode.<br />
<br />
<br />
-----<br />
<br />
=== InternalUI .development cache ===<br />
<br />
While someone more experienced could speak to the exact purpose of this build of the cache, given that a dump was leaked to the general public, there is no need not to discuss this.<br />
<br />
The .development cache (which cannot be loaded in cracked IDA versions) appears to be a build of the shared cache that properly holds symbols for the libobjc, libsystem, and other libraries, instead of raw addresses.<br />
<br />
If you're using Hopper or IDA 7.5, give the .development cache a shot.<br />
<br />
kritanta: ''Do note, I've had some issues with certain functions in it. I'm excited to see more information or research on the functionality of this object.''<br />
<br />
<br />
-----<br />
<br />
== Pre-7.3 dyld_shared_cache analysis by kritanta ==<br />
<br />
I do not intend to pick a fight with illegitimate IDA users. The software is insanely expensive, I cannot fault anyone in that regard. If you are using an illegitimate copy, don't tell me, I don't want to know. Best of luck.<br />
<br />
It's from a year of experience with it that I'm telling you: * Illegitimate versions of IDA cannot properly handle arm64e code very well. * Illegitimate versions of IDA cannot properly handle .development versions of shared caches available in InternalUI dumps whatsoever. It's completely incapable, and fails to process modules it loads. * Users of illegitimate versions of IDA should primarily stick to Simulator runtime binaries as detailed below. * Consider Hopper. It is capable of a few of IDA >7.3's features (arm64e, .development caches) and carries a much smaller price tag * Get comfortable with assembly if you intend to use Hopper. The pseudocode it generates is among the "least desirable" in the industry, and the assembly is easier to read. * Additionally, consider Ghidra. I'm not familiar with it, but others are, and can help you work with it. * Ghidra pseudocode I have heard is on par with IDA 7.0's pseudocode.<br />
<br />
I've decided to leave the below sections in this guide for educational purposes, but using a cracked IDA here is more than likely a waste of your time compared to the myriad of options available. Additionally, I obviously cannot condone the usage of such.<br />
<br />
=== If you are dead-set on using the arm64 shared cache ===<br />
<br />
'''Before you start analyzing the entire thing, I've already done that!''' I've publicly shared the fully processed cache here: https://developer.openpack.io/dyld_shared_cache_arm64.i64. Do not let my sacrifice of 4 days be in vain. Use this, don't waste your time.<br />
<br />
It includes SpringBoardHome and 740 other frameworks SpringBoardHome depends on. It's a 13 GB file. Have fun.<br />
<br />
This is not worth it, you have been warned. ''Please'' consider using simulator binaries instead.<br />
<br />
'''Trying to search for a function name will crash IDA entirely'''. Close the Functions view and open the "Program Segmentation" window. Browse frameworks like this, and carefully scroll through to find the function you want.<br />
<br />
Although you can work around the Function name search crash by using a full filter instead of the quick filter, this will cause decompilation to take several minutes while the filter is active. Additionally applying and removing the filter will take several minutes (but typically doesn't crash).<br />
<br />
=== Simulator Binaries: the recommended solution on older IDA versions ===<br />
<br />
The iOS simulator runtime is for you. x64 binaries that don't have the "Red Address" issue are available.<br />
<br />
Find them here: <code>/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 12.4.simruntime/Contents/Resources/RuntimeRoot/System/Library/PrivateFrameworks</code><br />
<br />
You may need to change the name of the folder for the simulator versions you have downloaded and installed.<br />
<br />
== Types and Functions Definitions ==<br />
<br />
IDA Pro does provide you a limited amount of types and functions definitions from Objective-C. The binaries however may import more functions or pack more types that IDA Pro does not have knowledge about. For example, the parameters of <code>dispatch_async</code> function may not be detected correctly. It may have only one parameter or not at all, making your binary analysis more difficult, not to mention when you work on different binaries and you face many other incorrectly typed functions. Use https://github.com/PoomSmart/IDAObjcTypes to import the types and definitions to fix this once and for all.<br />
<br />
== dsc_fix.py Plugin ==<br />
<br />
This plugin no longer functions, as the IDA SDK no longer provides the needed interfaces. Additionally, it needs to be updated for Python 3.</div>PoomSmart