evelyneee / ellekit

yet another tweak injector / tweak hooking library for darwin systems
BSD 3-Clause "New" or "Revised" License
433 stars 55 forks source link

[Enhancement] ellekit should block obj-c swizzle methods from running to early #24

Open Cryptiiiic opened 1 year ago

Cryptiiiic commented 1 year ago

Not really a bug but apps like paypal are terribly made and swizzle NSData initilize to call their debug logger class. Who tf knows why their debug logger is enabled in a release build. When ellekit's libinjector is loaded into the app, corefoundation is called which in turn calls nsdata, nsdata initilize. But since the app swizzled that function, their version is called instead. This in turn jumps to apps code to early before anything is setup and goes into an inifinite recursion loop.

This can be resolved by just blocking swizzling until tweaks are done loading.

hryan49 commented 1 year ago

Had an similar issue. Resolved it by replacing swizzles with %hook nested in a %group. Call the %init(group) inside your ctor after some type of validation/loop (I used dyld to make sure my framework was loaded first before advancing to the %init)

Cryptiiiic commented 1 year ago

Its not a tweak issue though, because the app swizzles nsdata initialize, when libinjector does anything ns related it calls the app's method which in turn calls other app stuff too early. Libinjector loads the tweaks so its not related to specific tweaks stuff. @hryan49

roothide commented 10 months ago

@Cryptiiiic May I ask which call in libinjector you are talking about triggers this case?

Cryptiiiic commented 10 months ago

@RootHide libinjector is part of ellekit. But anything down the injection chain will cause the issue. If a single dependency library or tweak loads core foundation it will break the app from swizzling.

roothide commented 10 months ago

@Cryptiiiic yes its the TweakLoader, and it does use CF functions. the internal implementation of CoreFoundation uses objc, and almost all tweaks use objc. are you saying that any call to a CF function in libinjector triggers the problem, or does it trigger the problem only after it calls a specific CF* function?

roothide commented 10 months ago

@Cryptiiiic could you show an example code for paypal(latest version?) that can reproduce this issue?

Cryptiiiic commented 10 months ago

@RootHide What do you mean example code? Any tweak/tweak dependency that links CoreFoundation will trigger the issue. The cf init code calls NSData initialize but paypal swizzles that. And since tweaks load very early, its ending up in the paypal code too early before anything is setup for paypal to run correctly leading to undefined behavior. In this case recursion happens.

No example code is needed because 99% of the time a tweak will be using corefoundtion. I already explained this in the prior messages.

roothide commented 10 months ago

@Cryptiiiic I use dopamine jailbreak with ellekit, and installed some tweaks which injected into paypal and linked CoreFoundation, but I didn't observe any abnormalities with paypal, it still runs normally. so how to reproduce the issue you said?

Cryptiiiic commented 10 months ago

@RootHide lol it seems they finally removed the debug code, it works fine now so we will have to find another example app. 5B60C9D9-D4C7-4FB4-A52D-3D9483B1C2E6

roothide commented 10 months ago

@Cryptiiiic alright.

I can understand the problem you said. usually objc+initialize will not be triggered prematurely, but because TweakLoader or tweaks use CoreFoundation, and the internal implementation of CoreFoundation uses objc extensively, this will cause the app code to get the opportunity to execute before the tweaks and cause abnormal behavior in the app, and even be used to detect jailbreaks and tweaks.

and almost all TweakLoaders use CoreFoundation or objc, so this is difficult to avoid, and almost all jailbreak payload-dylib will use xpc to connect to jbd before loading TweakLoader, and xpc also uses objc internally, which will also cause objc+initialize to be triggered.

I think we should be able to find a way to deal with this eventually, but there is nothing we can do at the moment.

yakuv0 commented 9 months ago

helloo

this seems related to what happens with Termius app on launch. crash report { "report": { "version": "3.2.0", "id": "1D91DF7E-D249-4D65-B1C5-71B391CA9BBD", "process_name": "Termius", "timestamp": 1697088010, "type": "standard" }, "binary_images": [ { "image_addr": 4386848768, "image_vmaddr": 0, "image_size": 32768, "name": "path/to/procursus/usr/lib/ellekit/libinjector.dylib", "uuid": "E36B82C6-B463-30AA-A94A-39E341F0437D", "cpu_type": 16777228, "cpu_subtype": 0, "major_version": 1, "minor_version": 0, "revision_version": 0 }, { "image_addr": 4311187456, "image_vmaddr": 4294967296, "image_size": 23855104, "name": "/path/to/Termius.app/Termius", "uuid": "2F7A73DD-5E70-3717-940C-94EC6939C7F9", "cpu_type": 16777228, "cpu_subtype": 0, "major_version": 0, "minor_version": 0, "revision_version": 0 },

above ellekit/libinjector.dylib is loaded before app which results in crash on launch.

app installed from App Store and equipped with jb and decryption detector which result in crash if the app is sideloaded but in this case where its on a rootless jb with disabling tweak injection via Choicy still result in crash and detects binary as decrypted when ellekit is loaded.

{"event_id":"da67487f617e458fb68147f7c5be611b","sdk":{"name":"sentry.cocoa","version":"7.4.7"}} {"type":"event","length":126317} {"extra":{"JailbreakCheckInfo":"sileo:\/\/ URL scheme detected, Suspicious file exists: \/var\/log\/apt, Suspicious file can be opened: \/var\/log\/apt","IsJailbroken":true,"Plan":"Not Registered","IsLoggedIn":false,"HasUsername":false},"message":{"formatted":"The application integrity has been compromised.\nMessage: App bundle not encrypted"},

for the jb detector in app shouldn't result in crash (just a warning massage in app), currently enabling shadow tweak on app doesn't result in crash on launch even with ellekit installed.

evelyneee commented 9 months ago

@yakuv0 Thats not related, remove your Xina files before making issues

yakuv0 commented 9 months ago

@evelyneee got no xina, jb is on palera1n

may you explain? report shows ellekit loading before app that why I though its related to the same issue.

evelyneee commented 9 months ago

It's detecting jailbreak files

roothide commented 9 months ago

obviously this app detects jailbreak, once you use choice to disable injection, it has nothing to do with ellekit.

yakuv0 commented 9 months ago

@RootHide @evelyneee indeed it is detecting jailbreak but that doesn't cause the crash on launch, disabling tweak injection with Choicy makes no change on crash state on launch, and in report shows ellekit (libinjector.dylib) loaded first which cause the crash.

Jailbreak detection in this app doesn't seem to have anything to do with crash, app launch when disabling tweak injection with shadow (and only by disabling shared libraries which seems effective to disable ellekit trigged before app)

JB detector in app notification after launch with no ellekit or tweaks installed on device (trigged by sileo url schema and apt path)

roothide commented 9 months ago

Can I ask what jailbreak you are using? at least in my ios15/dopamine jailbreak, when enabling choice to prohibit injection, ellekit and TweakLoader will not be loaded, so I think it has nothing to do with ellekit.

yakuv0 commented 9 months ago

@RootHide indeed you may get any info required.

device: ipad mini4 iOS:15.7.4 JB: palera1n rootless

seems all settings tweaks for rootless requires ellekit to be loaded, which introduced the crash bug on launch with ellekit installed for this app.

this wt been experiencing on rootless recently, not sure how that works on dopamine though and wt jb bypass are there.

Report includes info on the sequence of binaries launched and ellekit is on top Report detects binary as decrypted or injected with a message application integrity has been compromised

disable injection: -Choicy: app crash -Shadow (fishhook): app launch -Shado (ellekithook): app crash

roothide commented 9 months ago

then I may know the reason. On dopamine, choice can prevent any jailbreak module injection, even TweakLoader itself, but on palera1n it may need to rely on TweakLoader and substrate(ellekit) to work. so choice itself cannot prevent ellekit from being loaded on palera1n, and can you share your app crash log?

yakuv0 commented 9 months ago

@RootHide this result with no system crash log. logs from app's data. should an issue be created on Choicy's ?!

thought Choicy doesn't bypass shared libs as shadow does, actually this occurred with an app called roothide earlier when were looking for away around it on rootless.

roothide commented 9 months ago

okay, this is why:

image

Choicy hooks some system internal functions through ellekit when it starts, these functions may be very short in some iOS versions, so ellekit will use breakpoints to hook them, and at the same time set the exception port of the process to capture these breakpoint signals.

However, some apps will also set the exception port of the current process after startup, in order to capture their own crash information when the app itself has a BUG crash and collect this information to improve the app. when those functions that choicy hooked being called again, the app's exception capture module will report that this is an app crash and actively exit.

ellekit is the first substrate to adopt this hook method, which allows tweaks to hook short functions that they previously couldn't hook, but it is better to use it as a separate interface rather than the default behavior of MSHookFunction. tweak require clarity on their intentions and behaviors.

yakuv0 commented 9 months ago

@RootHide will keep an eye on ellekit's updates. glad that your able to figure out whats being triggered, you may lemme know if anything required to be tested.

yakuv0 commented 8 months ago

@RootHide vnodebypass from https://alias20.gitlab.io/apt/ is the current work around however this allows app launch and prevent ssh login on localhost