Bryce Bostwick does super cool & inspiring work on debugging and reverse-engineering apps. I found him on YouTube; His video on modding TikTok to only show cat videos (https://youtu.be/YW3jL2gI9IE) inspired me to mod Instagram to remove everything except the message feature, which is the only part I use. I've been meaning to get more into modding & reverse engineering–specifically modding Windows in the style of Windhawk (https://windhawk.net/). Bryce gives a great intro to doing that sort of thing on iOS with live, step-by-step videos.
If anyone knows someone similar for Android, I'd be interested in learning more. I've seen some of the impressive things that can be done using Revanced but there don't seem to be good guides for how to get started with something like that.
I'd also like to fond one such youtuber. If you want to get started though your best bet is probably combining jadx-gui (an amazing decompiler targetting Android) alongside with apktool to disassemble / patch / reassemble your apk and uber-apk-signer to sign it back afterward with mitmproxy to snoop on the API calls. That's my setup whenever i poke around old apps and try to make server emulators for them. A really cool tool is also Frida and xposed which lets you quickly hook into the apps.
I'm pretty new to RE though this kind of videos are super interesting for me
I used to do a decent bit of android reverse engineering.
It's pretty easy to grab an app, decompile and disassembly it, find what you need to change and then patch the smali and recompile.
It's been a long time since I looked at that stuff, but I think I used to use apktool and smali / baksmali from memory.
I remember something like dex2jar also, which gave you a jar you could use in any java decompiler, like jdgui, procyon etc. Easier to find what you are looking for in the decompiled java and then patch the smali.
Lots of android apps are obfuscated, but you can do stuff like add logs to the smali etc, probably remote debugging etc.
It has been a while, so that info might be woefully out of date now.
> I remember something like dex2jar also, which gave you a jar you could use in any java decompiler, like jdgui, procyon etc.
https://github.com/skylot/jadx is very handy for that nowadays. It also supports interactive variable/method/class name renaming to make the decomplied code easier to read. The decompiler isn't perfect, but I guess all available Java decompilers have their limitations with more complex bytecode…
Im going to try do what you described. But if you happen to write down the steps I'm interested. I hate that to post photos or chat with friends I have to be exposed to reels.
Anti-debugging (and even anti-anti-anti-debugging) tricks have been commonplace on the DOS/Windows side of things for a long time. Any old cracking/unpacking information will discuss those in varying amounts of detail.
How easy it is for the user to have control over what apps do is inversely related to how user-hostile the platform is. PT_DENY_ATTACH seems like a feature specifically invented for the purpose of serving the latter. Of course on the Windows side, which I believe doesn't have such a feature, the trick is to make the app attach to itself instead:
I'm kind of surprised Apple's App Store checks don't reject any app that makes direct syscalls. Syscalls on Apple platforms are not a stable ABI, so all syscalls must go through libSystem, which means any app that makes a syscall directly instead of going through libSystem is doing something that it shouldn't.
Similarly I'm wondering why the author here searched through the code for `mov w16, #26` instead of searching for `svc 0x80`.
`svc 0x80` is the command to execute any syscall, which syscall exactly is executed is based on the register x16, presumably the app make a very large amount of unrelated syscalls, so it wouldn't be useful to break on that, that's what he said in the video at least.
The whole point is the app is supposed to make zero syscalls directly, any syscalls that it makes are done by libSystem instead, and therefore the svc instruction should never occur in the app binary itself.
Compiler can sometimes inline syscall wrappers, so not that easy to check statically. For the same reason searching for SVC instructions would yield tons of results. If you search for the exact syscall ID moved into X16 you’d find it immediately.
The stable interface to syscalls on Apple platforms is libSystem, which is a dynamic library. Compilers cannot inline syscalls on Apple platforms as that would defeat the whole point of making libSystem the stable ABI. In fact, compilers don't even see libSystem itself when linking, they just see a .tbd file that lists all of libSystem's symbols.
Very interesting article, I always wanted a low-level phone reverse-engineering read like that to understand it better.
Few questions for the author: do you think the most popular commercial tool (guardsquare if im not wrong) brings anything new to the table which prevents an easy disassembly like this? Was TopWidgets protected by something similar or was it rather a local effort?
I find your videos fascinating and I'm surprised that more people haven't checked them out or read your articles. I personally use Android so the videos are technically not applicable for me but I still get a lot of value out of learning how some of the low level debugging in iOS works.
No, but you can use Frida (which replaces an inline syscall with a JMP to a handler) but it quickly becomes complicated if the app verifies its own integrity at unpredictable points during runtime. When this happens hardware breakpoints are your friend, however the developer can still make your life hard by inlining all over the app, and then you quickly run out of hardware breakpoints.
I mostly use an old phone on 16.6. iOS 17/18 is harder; you can jailbreak that if you have an iPad 7th Gen (technically iPadOS, but whatever). I have a couple but prefer the iPhone since it's less clunky to lug around!
I've seen some rumors of that device not supporting iPadOS 19, so I'm not really sure what the plan is if that's true. Maybe everyone starts forking money over to Corellium.
I certainly like them by default, but I get that others don't - one thing I could do is have them paused by default if `prefers-reduced-motion` is on. Though I'm curious if you (or any other folks here) have this enabled.
(would have added this ages ago if I knew this existed; not a CSS expert, just seeing it now by checking if web has an equivalent of iOS' `UIAccessibility.isReduceMotionEnabled`. neat!)
Setting doesn't exist on my os, and I certainly would not approve of a setting that gives people license to do (imo) shitty things to the user experience just because there's an obscure setting somewhere.
It's your site, you can do what you want; it's my browser, I will close tabs that annoy me with extreme prejudice.
The video at the top is one of the best programming videos I've ever watched. It's fast-paced, assumes just the right amount of knowledge, and has excellent demos that don't kill the flow of the video.
Great write up. I'm very curious whether this was a legitimate app which was unreasonably paranoid, or if it turns out he was debugging it in the first place because it was accused of being malware.
As best as I can tell, it’s just unreasonably paranoid — they do some very cool things with widgets that it seems like they were trying to protect (though those strategies are starting to leak out anyways)
There were some interesting things in the binary still. At one point I was trying to figure out why I was looking at code that looked like it was downloading a Windows .iso; turns out it was, and it was used for a network speed test widget!
If I ran the App Store : this would be enough evidence that I would heavily investigate all of their other apps for signs of illegal and immoral activity, also adding in static infinite loop detection on all app submissions
There's also the harderer mode, which I did on macOS a while back - patch the kernel to make PT_DENY_ATTACH do nothing. Macs actually make it fairly easy to run a patched kernel, but I guess on iOS it'd be a lot more trouble (KTRR etc.)
Although XNU is technically open-source, I found it easier to apply my patch with a hexeditor rather than recompiling.
You can also use the kernel task port to flip the bit on the proc struct. You can also do the same to allow unsigned code pages and RWX to enable JIT-ing.
I'm really curious about the "com.apple.tw.twrr" notification. Why does it start with com.apple? The app in question here (which looks like it's called Top Widgets) is not an Apple app.
Notification names are arbitrary strings. It's convention to use "fully-qualified" names like that to avoid collisions. In this case, I imagine that just happens to be what the developer chose as a prefix.
The whole point of reverse DNS notation is to have a conflict free namespace though. Using somebody else's namespace is asking for trouble in the future.
In this case it's probably additional subterfuge in case somebody examines all notifications posted and sees apple and thus ignores it.
It probably didn't crash the phone during review. App Store review is a human tapping through your app's common flows, looking for specific things. You don't provide them with the source code, and they don't really look at the binary, so it's not difficult to use private APIs or hide things from reviewers.
> Crashes your whole phone if you run it with a jailbreak on
Report it to the store as malware? Crashing the phone is obviously the behavior of malware, but you also have to wonder what other malicious behavior they're trying to hide.
I thought preventing this kind of crap was the supposed reason for apple's walled garden?
The crash can also reboot "normal" phones as explained in the article. This malware developer simply decided not to trigger it in that case.
But that's besides the point, isn't it? The fact that your phone happens to be jailbroken doesn't say anything about the rest of apple's store, and they clearly allow malware to be distributed.
Bryce Bostwick does super cool & inspiring work on debugging and reverse-engineering apps. I found him on YouTube; His video on modding TikTok to only show cat videos (https://youtu.be/YW3jL2gI9IE) inspired me to mod Instagram to remove everything except the message feature, which is the only part I use. I've been meaning to get more into modding & reverse engineering–specifically modding Windows in the style of Windhawk (https://windhawk.net/). Bryce gives a great intro to doing that sort of thing on iOS with live, step-by-step videos.
If anyone knows someone similar for Android, I'd be interested in learning more. I've seen some of the impressive things that can be done using Revanced but there don't seem to be good guides for how to get started with something like that.
I'd also like to fond one such youtuber. If you want to get started though your best bet is probably combining jadx-gui (an amazing decompiler targetting Android) alongside with apktool to disassemble / patch / reassemble your apk and uber-apk-signer to sign it back afterward with mitmproxy to snoop on the API calls. That's my setup whenever i poke around old apps and try to make server emulators for them. A really cool tool is also Frida and xposed which lets you quickly hook into the apps.
I'm pretty new to RE though this kind of videos are super interesting for me
I used to do a decent bit of android reverse engineering.
It's pretty easy to grab an app, decompile and disassembly it, find what you need to change and then patch the smali and recompile.
It's been a long time since I looked at that stuff, but I think I used to use apktool and smali / baksmali from memory.
I remember something like dex2jar also, which gave you a jar you could use in any java decompiler, like jdgui, procyon etc. Easier to find what you are looking for in the decompiled java and then patch the smali. Lots of android apps are obfuscated, but you can do stuff like add logs to the smali etc, probably remote debugging etc.
It has been a while, so that info might be woefully out of date now.
> I remember something like dex2jar also, which gave you a jar you could use in any java decompiler, like jdgui, procyon etc.
https://github.com/skylot/jadx is very handy for that nowadays. It also supports interactive variable/method/class name renaming to make the decomplied code easier to read. The decompiler isn't perfect, but I guess all available Java decompilers have their limitations with more complex bytecode…
Im going to try do what you described. But if you happen to write down the steps I'm interested. I hate that to post photos or chat with friends I have to be exposed to reels.
Anti-debugging (and even anti-anti-anti-debugging) tricks have been commonplace on the DOS/Windows side of things for a long time. Any old cracking/unpacking information will discuss those in varying amounts of detail.
How easy it is for the user to have control over what apps do is inversely related to how user-hostile the platform is. PT_DENY_ATTACH seems like a feature specifically invented for the purpose of serving the latter. Of course on the Windows side, which I believe doesn't have such a feature, the trick is to make the app attach to itself instead:
https://www.x86matthew.com/view_post?id=selfdebug
https://anti-debug.checkpoint.com/techniques/interactive.htm...
> PT_DENY_ATTACH seems like a feature specifically invented for the purpose of serving the latter
You're exactly right. It was literally invented by Apple for iTunes as part of its DRM solution back in the day.
I'm kind of surprised Apple's App Store checks don't reject any app that makes direct syscalls. Syscalls on Apple platforms are not a stable ABI, so all syscalls must go through libSystem, which means any app that makes a syscall directly instead of going through libSystem is doing something that it shouldn't.
Similarly I'm wondering why the author here searched through the code for `mov w16, #26` instead of searching for `svc 0x80`.
`svc 0x80` is the command to execute any syscall, which syscall exactly is executed is based on the register x16, presumably the app make a very large amount of unrelated syscalls, so it wouldn't be useful to break on that, that's what he said in the video at least.
The whole point is the app is supposed to make zero syscalls directly, any syscalls that it makes are done by libSystem instead, and therefore the svc instruction should never occur in the app binary itself.
Compiler can sometimes inline syscall wrappers, so not that easy to check statically. For the same reason searching for SVC instructions would yield tons of results. If you search for the exact syscall ID moved into X16 you’d find it immediately.
The stable interface to syscalls on Apple platforms is libSystem, which is a dynamic library. Compilers cannot inline syscalls on Apple platforms as that would defeat the whole point of making libSystem the stable ABI. In fact, compilers don't even see libSystem itself when linking, they just see a .tbd file that lists all of libSystem's symbols.
But how can you safely inline a non-stable ABI?
Hey all! Author here, happy to answer any questions. Thanks xmprt for sharing!
I watched your video on Youtube - it was interesting!
But also thanks for providing a written version too, it's very nice ;)
Very interesting article, I always wanted a low-level phone reverse-engineering read like that to understand it better.
Few questions for the author: do you think the most popular commercial tool (guardsquare if im not wrong) brings anything new to the table which prevents an easy disassembly like this? Was TopWidgets protected by something similar or was it rather a local effort?
(also, these comments are way too kind. thanks all!)
I find your videos fascinating and I'm surprised that more people haven't checked them out or read your articles. I personally use Android so the videos are technically not applicable for me but I still get a lot of value out of learning how some of the low level debugging in iOS works.
Does iOS have something like PTRACE_SYSCALL to hook up on syscalls entry and maybe change the return value? (Or detect where the SVC is being made)
No, but you can use Frida (which replaces an inline syscall with a JMP to a handler) but it quickly becomes complicated if the app verifies its own integrity at unpredictable points during runtime. When this happens hardware breakpoints are your friend, however the developer can still make your life hard by inlining all over the app, and then you quickly run out of hardware breakpoints.
Apple seems to have come so far from the iPhone4's misaligned Thumb 2 page crossing core fault.
Do you use a very old phone for jailbreaking, or are there more recent jailbreaks?
I mostly use an old phone on 16.6. iOS 17/18 is harder; you can jailbreak that if you have an iPad 7th Gen (technically iPadOS, but whatever). I have a couple but prefer the iPhone since it's less clunky to lug around!
I've seen some rumors of that device not supporting iPadOS 19, so I'm not really sure what the plan is if that's true. Maybe everyone starts forking money over to Corellium.
Autoplaying gif mixed into text, closed the page.
I certainly like them by default, but I get that others don't - one thing I could do is have them paused by default if `prefers-reduced-motion` is on. Though I'm curious if you (or any other folks here) have this enabled.
(would have added this ages ago if I knew this existed; not a CSS expert, just seeing it now by checking if web has an equivalent of iOS' `UIAccessibility.isReduceMotionEnabled`. neat!)
Setting doesn't exist on my os, and I certainly would not approve of a setting that gives people license to do (imo) shitty things to the user experience just because there's an obscure setting somewhere.
It's your site, you can do what you want; it's my browser, I will close tabs that annoy me with extreme prejudice.
You also removed the giant pole stuck up your ass?
You mean the disability that makes motion incredibly distracting while trying to read?
The video at the top is one of the best programming videos I've ever watched. It's fast-paced, assumes just the right amount of knowledge, and has excellent demos that don't kill the flow of the video.
Great write up. I'm very curious whether this was a legitimate app which was unreasonably paranoid, or if it turns out he was debugging it in the first place because it was accused of being malware.
Seems like a lot of effort to go to otherwise
As best as I can tell, it’s just unreasonably paranoid — they do some very cool things with widgets that it seems like they were trying to protect (though those strategies are starting to leak out anyways)
There were some interesting things in the binary still. At one point I was trying to figure out why I was looking at code that looked like it was downloading a Windows .iso; turns out it was, and it was used for a network speed test widget!
If I ran the App Store : this would be enough evidence that I would heavily investigate all of their other apps for signs of illegal and immoral activity, also adding in static infinite loop detection on all app submissions
There's lots of algorithms and patterns that use "while (1) {"
And of course, you can't really know if a loop is infinite because of the halting problem.
BillGates.iso: What is my purpose?
CoolWidgets.app: Your heft tests the network speed.
BillGates.iso: Oh my god.
Or maybe trying to prove copyright theft, if the app itself was recompiled with different logos etc
> Bypassing PT_DENY_ATTACH (Hard Mode)
There's also the harderer mode, which I did on macOS a while back - patch the kernel to make PT_DENY_ATTACH do nothing. Macs actually make it fairly easy to run a patched kernel, but I guess on iOS it'd be a lot more trouble (KTRR etc.)
Although XNU is technically open-source, I found it easier to apply my patch with a hexeditor rather than recompiling.
You can also use the kernel task port to flip the bit on the proc struct. You can also do the same to allow unsigned code pages and RWX to enable JIT-ing.
I'm really curious about the "com.apple.tw.twrr" notification. Why does it start with com.apple? The app in question here (which looks like it's called Top Widgets) is not an Apple app.
Notification names are arbitrary strings. It's convention to use "fully-qualified" names like that to avoid collisions. In this case, I imagine that just happens to be what the developer chose as a prefix.
The whole point of reverse DNS notation is to have a conflict free namespace though. Using somebody else's namespace is asking for trouble in the future.
In this case it's probably additional subterfuge in case somebody examines all notifications posted and sees apple and thus ignores it.
The tools are different, but this feels exactly like cracking Apple II copy protection in the 1980s using boot tracing. Some things don't change.
Does anyone know about people doing similar reverse engineering but for javascript code in websites?
The same author just put this out: https://youtu.be/F5m2JxplnXk
amazing!
a few of my writeups discuss ways of doing this:
appleid https://zemnmez.medium.com/how-to-hack-apple-id-f3cc9b483a41 steam https://hackerone.com/reports/409850
I wonder how Apple allowed an app that was purposely crashing the phone under specific conditions.
It probably didn't crash the phone during review. App Store review is a human tapping through your app's common flows, looking for specific things. You don't provide them with the source code, and they don't really look at the binary, so it's not difficult to use private APIs or hide things from reviewers.
For example, after being kicked off the App Store by sanctions, Russian banks have used "trojan apps" that show different apps inside Russia: https://appleinsider.com/articles/24/02/12/how-russian-banks...
The specific condition being the phone OS being modified with third-party code by exploiting iOS vulnerabilities. Yeah, I think Apple missed that one.
App reviews take on average less than a minute. The reviewer just signs in, taps randomly, and that's it.
I don't think Apple tests those conditions, they're not common.
Can you run custom kexts on a jailbroken iPhone? The cooler way to bypass it is just to modify the kernel itself.
Been really enjoying the author's YouTube content lately, even though I'm not too experienced in reverse engineering.
> Crashes your whole phone if you run it with a jailbreak on
Report it to the store as malware? Crashing the phone is obviously the behavior of malware, but you also have to wonder what other malicious behavior they're trying to hide.
I thought preventing this kind of crap was the supposed reason for apple's walled garden?
“With jailbreak on” means it’s not in the walled garden. I think Apple is fine with apps that crash jailbroken phones.
The crash can also reboot "normal" phones as explained in the article. This malware developer simply decided not to trigger it in that case.
But that's besides the point, isn't it? The fact that your phone happens to be jailbroken doesn't say anything about the rest of apple's store, and they clearly allow malware to be distributed.
> Crashes your whole phone if you run it with a jailbreak on (!)
Draconian anti-hacking laws for device owners, but not for corporate malware makers.