Cycript script to run app in background - ios

I have a cycript backboardd script that works great on iOS 7 for modifying an app to continue running in the background.
app = [BKProcess processForPid:$PID];
alive = [[BKProcessAssertion alloc] initWithReason:7 identifier:"AppKeepAlive"];
[alive setFlags:0xF];
[sc addAssertion:alive];
This is all that's needed. However on iOS 8 this does't work as BKProcess is now BKSProcess and BKProcessAssertion is now BKSProcessAssertion and they have different methods.
There doesn't seem to be a way to attach the assertion to the app like on iOS 7.
Can some please help me get this working under iOS 8.

There is, however when I used this I simply used the initializer with the required PID.
- (id)initWithPID:flags:reason:name:withHandler:
Check out the BKSProcessAssertion header for reference.
If you want to see an implementation for reference, check out MessageBox (now deprecated, but for reference):

Related

Check whether Running the app or Testing UI

I need a set of code to run only when testing the app(UITesting) not when running the app. I have been trying to find whether running the app or it's a UITesting?.
This is new on xcode 8 and above.
Can some help me with this please.
Now we can simply check this with one line of code for "UITesting".
[[[NSProcessInfo processInfo] arguments]
containsObject:#"-ui_testing"]
-ui_testing would appear only when testing the app.

What happens if I use LAPolicyDeviceOwnerAuthentication on iOS 8?

In my app, I would like to know if the user has setup a passcode or fingerprint (touchID). There's a pretty easy method just for that: [LAContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthentication error:error].
However, Apple's docs say LAPolicyDeviceOwnerAuthentication is only available on iOS9 and above. I would rather not crash iOS 8 users without explanation, even if it is getting older. The thing is, I've tried it on an iOS8.4 simulator, and it seems to compile and just work.
What ill effects can happen if I use LAPolicyDeviceOwnerAuthentication on iOS 8?
I use code similar to this:
LAPolicy localAuthPolicy = LAPolicyDeviceOwnerAuthenticationWithBiometrics;
if (![[UIDevice currentDevice].systemVersion hasPrefix:#"8."]) {
localAuthPolicy = LAPolicyDeviceOwnerAuthentication;
}
This ensures I only use LAPolicyDeviceOwnerAuthentication on iOS 9 and later.
It's undocumented what actually happens on an iOS 8 device when you attempt to use LAPolicyDeviceOwnerAuthentication. It's very unlikely anything will crash but the authentication may return NO due to an unknown value or it may succeed because iOS 8 only had one valid value and it may not do any checking.
Unfortunately Objective-C doesn't provide any runtime checks for valid enum values like you can do with constants, methods, and classes.
If you use LAPolicyDeviceOwnerAuthentication on anything below iOS 9, the app will crash. That is what happened to my app when I didn't realize that this was not available on anything below iOS 9, but my app supported iOS 8.x as its minimum supported OS version.

CKQueryOperation iOS 9 only work plugged in

I am using CloudKit in my iOS 9 app and I have a CKQueryOperation that work fine and performs as expected when plugged into the Mac. As soon as the query is run when it is not plugged in to the Mac, it does not finish. There is no error message, the activity indicator I added never stops and the results are never displayed.
If I start the operation when unplugged, then plug it in it completes too.
The code was copied and adapted from an app built in Xcode 6.4 and works as expected in that app.
Any ideas why this could be happening? Could it be anything to do with app thinning in iOS 9?
Thank you
ANSWER
Adding this fixed the issue:
queryOperation.qualityOfService = NSQualityOfService.UserInitiated
The default QoS changed in iOS 9. If the query operation is user initiated, then it needs to be marked as such.
See CKOperation.h and the QualityOfService property.

IOMobileFramebufferGetLayerDefaultSurface not working on iOS 9

My main question is, how can I reverse engineer a private API function that already exists, but has been modified in a new version of iOS?
I have created an iOS application to record the screen content using IOSurface and IOMobileFramebuffer. The main functions the framebuffer use to open it are IOMobileFramebufferGetMainDisplay(connect) and IOMobileFramebufferGetLayerDefaultSurface.
These functions have been used since the very first version of the app, and they have worked on all versions of iOS 7 and 8. However, on the latest iOS 9 beta, which is beta 5, the function IOMobileFramebufferGetLayerDefaultSurface does not work. The function does not return 0, as it should when it successfully opens the framebuffer.
This other user on StackOverflow seems to also be experiencing the same issue: IOMobileFramebufferGetLayerDefaultSurface function failed on iOS 9. We have a reference to IOMobileFramebufferConnection named “_framebufferConnection” and an IOSurfaceRef named “_screenSurface” Here is the current code:
IOMobileFramebufferGetMainDisplay(&_framebufferConnection);
IOMobileFramebufferGetLayerDefaultSurface(_framebufferConnection, 0, &_screenSurface;
As stated before, these work perfectly on iOS 7-8, but on iOS 9, the second function crashes. I have also looked at the binaries with the symbols for both versions and compared them. The second parameter of the LDR is slightly different in iOS 9, when compared to the iOS 8.4.1 binary. So, back to the main question, how can I reverse engineer IOMobileFramebufferGetLayerDefaultSurface, or see how in what way it’s actually been modified on iOS 9?
To answer the question of "how in what way it’s actually been modified on iOS 9", I did some digging into IOMobileFramebufferGetLayerDefaultSurface on iOS8 vs iOS9 (GM). Here are the results of what I found:
Setup:
IOMobileFramebufferRef fb;
IOMobileFramebufferGetMainDisplay(&fb);
iOS8 Implementation:
Calls through to kern_GetLayerDefaultSurface
Which accesses underlying IOConnection
io_connect_t fbConnect = *(io_connect_t *)((char *)fb + 20)
To retrieve the IOSurfaceID via
IOSurfaceID surfaceID;
uint32_t outCount = 1;
IOConnectCallScalarMethod(fbConnect, 3, {0, 0}, 2, &surfaceID, &outCount)
Returns IOSurfaceLookup(surfaceID)
iOS9 Implementation:
Same steps as above aside from the return
Then tries to retrieve a mach port to access the surface via
io_service_t fbService = *(io_service_t *)((char *)fb + 16)
mach_port_t surfacePort;
IOServiceOpen(fbService, mach_task_self(), 3, &surfacePort)
On success, return IOSurfaceLookupFromMachPort(surfacePort)
It is on the last step that IOServiceOpen returns error 0x2c7 (unsupported function). Notice that the 3rd argument specifying the type of connection is 3 instead of the usual 0 when opening the framebuffer service. It is almost certain that this new connection type has permissions restrictions that prevent anyone but Apple from retrieving a mach port to access the IOMFB surface.
What's somewhat interesting is that the call to IOConnectCallScalarMethod still works to retrieve the ID of the IOMFB surface. However, it can no longer be accessed using IOSurfaceLookup because the surface is no longer global. It's a little surprising that it was global in the first place!
Hope this helps demystify why IOMFB can no longer be used to record the screen.
Source: My own use of LLDB with an iPhone6 running iOS 8.4 and an iPhone6+ running iOS9 GM
I believe #nevyn is correct. However, I would like to elaborate a bit more. I have looked into this exact issue extensively, and the IOMobileFramebufferGetLayerDefaultSurface function does return -536870201, while it should return 0 if it runs the function without any problems. This error is on the internet, but it only appears when users encounter generic problems with QuickTime. It could be that Apple has indeed locked up the framework completely, and needs an Apple-only entitlement to access the framebuffer. We cannot add these entitlements, since it also has to be on the provisioning profile. I currently am trying to read and interpret the disassembly and doing some reverse engineering work on the IOMobileFramebuffer binary to see if any of the parameters have changed since the last iOS version. I will surely update this answer if I discover anything. But if this is the case, I would suggest trying to find another method of trying to capture/record the screen content.
-UPDATE-
It seems as if there is evidence that this would be the case, if you read this, it shows the exact same error code, and it means that the function is "unsupported", and returns an IOKit error. At least we know what this means now. However, I am still unsure of how to fix it, or to make the function work. I will continue looking into this.
UPDATE 2
I have actually discovered a brand new class in iOS 9, "FigScreenCaptureController", and it is part of the MediaToolbox framework! What the strange thing is though, is why would Apple include this only in iOS 9? So, maybe there will be a way to record the display through this...I will be looking into this class more in depth very soon.
Not entirely correct - it's just a matter of an entitlement, as you can see if you dump the kext:
$ jtool -d __TEXT.__cstring 97.IOMobileGraphicsFamily.kext | grep com.apple
0xffffff80220c91a2: com.apple.private.allow-explicit-graphics-priority
If you self sign (jtool --sign --ent) with this , everything works well.
This does mean that on non-JB devices you can't use it. But with a jailbreak the immense power is in your hands once more.
IOMobileFramebuffer is completely locked down on iOS 9 and cannot be used from non-Apple apps anymore. AFAICT, this closes the last private API to capture the screen efficiently. ReplayKit is the only replacement, but does not allow programmatic access to the actual video data.

Xcode+watchkit simulation: does not support a debuggable architecture:

I am trying to run in Xcode both the main App (which is active in background) and the WatchkitApp (which sends requests to main App through the watchkit extension). Everything works fine in standalone, but no way to make it work simultaneously.
My main concern is to understand this message when trying to attach a process: what does this mean ?
Xcode couldn't attach to "myApp"
"myApp" does not support a debuggable architecture
Thank you.
Edit:
I just read that main app in ObjectiveC and watch app in swift is a problem: https://mkswap.net/m/blog/How+to+debug+an+iOS+app+while+the+WatchKit+app+is+currently+running+in+the+simulator
It happened to me when an extension process was hanging around refusing to terminate. Find and kill it in the Activity Monitor.
Actually, I had that same error message, and I fixed it by resolving a bug that crashed my phone app on launch.
I didn't think to run just the phone in debug so I got confused too.
I'm running ObjC on the phone and Swift on the Watch App.

Resources