iosobjective-ciphonebackgroundkif

Programmatically sending tap event to coordinates in background in iOS using KIF


The idea is to make an app that can send a 'tap the screen at coordinates (x,y)' event continuously in the background of another app in iOS. Think of a 'Cookie Clicker' cheat. I am currently assisting my friends in his app, and my job is to attempt to bug it out as much as possible. I have a slight feeling that tapping one of his buttons as much as possible will bug out his app, thus why I'm here.

The method is using KIF along with the background execution in iOS to achieve this.

  1. In one of the classes, the file KIFUITestActor.m has the code:

    - (void)tapScreenAtPoint:(CGPoint)screenPoint
    {
    
    [self runBlock:^KIFTestStepResult(NSError **error) {
    
    // Try all the windows until we get one back that actually has something in it at the given point
    UIView *view = nil;
    for (UIWindow *window in [[[UIApplication sharedApplication] windowsWithKeyWindow] reverseObjectEnumerator]) {
        CGPoint windowPoint = [window convertPoint:screenPoint fromView:nil];
        view = [window hitTest:windowPoint withEvent:nil];
    
        // If we hit the window itself, then skip it.
        if (view != window && view != nil) {
            break;
        }
    }
    
    KIFTestWaitCondition(view, error, @"No view was found at the point %@", NSStringFromCGPoint(screenPoint));
    
    // This is mostly redundant of the test in _accessibilityElementWithLabel:
    CGPoint viewPoint = [view convertPoint:screenPoint fromView:nil];
    [view tapAtPoint:viewPoint];
    
    return KIFTestStepResultSuccess;
        }];
    }
    

    Would this be the code I'm looking for, and how would I implement it in Swift? (Or Objective-C if it makes things easier?)

  2. Would running the class as a background service achieve the background execution?

Many thanks if you can answer this question.


Solution

  • A couple options, depending on what you have access to. If you have the actual IPA of the other app that you want to 'bug out', and you can attach a test target to it, then KIF is a great option.

    This is a little guide on UI testing with KIF (easily googlable, link here). A quick summary though is:

      [tester tapViewWithAccessibilityLabel:@"Clear"];
    

    That kind of code should have an equivalent named tapViewAtPoint or something along those lines (I last used KIF over a year ago, but it should be well documented as it was then).

    However, if you DO NOT have access to the app you are trying to attack, which seems more likely for this type of question, then you can use a different approach altogether.

    Automator can help you script this up if you can at least download the app in the iPhone simulator. Since Xcode 9 I believe allows you to do this, this part should not be hard, as long as the target app IS on the app store.

    If it's not, and you don't have the code, I'd be curious to hear how you are being distributed the app, as there might still be a way to use one or the other option I suggested. Good luck!

    Edit: update based on re-reading the question + bounty request one more time

    Would running the class as a background service achieve the background execution?

    This again depends on if you CAN run it as a background service. If you have access to the code itself, then it could be done, although I'm not sure what the goal of background execution is in your described question.

    KIF won't be able to work on anything that isn't in the foreground. In general, iOS devices never funnel taps to an app in the background, so if the attack vector being tested is to repeatedly tap an app, background execution is likely not the answer.

    From your question this looks more like a use case for parallelizing a tap loop, and your problem seems like it could benefit from Xcode 9's parallel simulator feature addition.

    Although I have not personally tried this yet, you could do parallel KIF runs in multiple simulators on a machine running Xcode 9. This is likely the best way to get as many data points as possible about what caused issues, as with UI tests you can take a screenshot of the app at any point. In Xcode 9, I believe there is also a new feature to record a video straight from the Simulator (and no longer need Quicktime).