3

ジェイルブレイクされたiPhoneのホーム画面でアプリのアイコンをクリックすることをシミュレートしたい。以下のコードを使用しましたが、有効になりませんでした。私は何か間違ったことをしましたか?

方法はgetFrontMostAppPort()正しいですか?イベント を使用しようとしてGSSendSystemEvent()も効果がありませんでした。

ところで、私はジェイルブレイクされたデバイスを意味します。誰か助けてくれませんか?とても感謝しています。

// Framework Paths
#define SBSERVPATH  "/System/Library/PrivateFrameworks/SpringBoardServices.framework/SpringBoardServices"

static mach_port_t getFrontMostAppPort() {
    bool locked;
    bool passcode;
    mach_port_t *port;
    void *lib = dlopen(SBSERVPATH, RTLD_LAZY);
    int (*SBSSpringBoardServerPort)() = dlsym(lib, "SBSSpringBoardServerPort");
    void* (*SBGetScreenLockStatus)(mach_port_t* port, bool *lockStatus, bool *passcodeEnabled) = dlsym(lib, "SBGetScreenLockStatus");
    port = (mach_port_t *)SBSSpringBoardServerPort();
    dlclose(lib);
    SBGetScreenLockStatus(port, &locked, &passcode);
    void *(*SBFrontmostApplicationDisplayIdentifier)(mach_port_t *port, char *result) = dlsym(lib, "SBFrontmostApplicationDisplayIdentifier");
    char appId[256];
    memset(appId, 0, sizeof(appId));
    SBFrontmostApplicationDisplayIdentifier(port, appId);
    NSString * frontmostApp=[NSString stringWithFormat:@"%s",appId];
    if([frontmostApp length] == 0 || locked)
        return GSGetPurpleSystemEventPort();
    else
        return GSCopyPurpleNamedPort(appId);
}

static void sendTouchEvent(GSHandInfoType handInfoType, CGPoint point) {

    uint8_t touchEvent[sizeof(GSEventRecord) + sizeof(GSHandInfo) + sizeof(GSPathInfo)];

    // structure of touch GSEvent
    struct GSTouchEvent {
        GSEventRecord record;
        GSHandInfo    handInfo;
    } * event = (struct GSTouchEvent*) &touchEvent;
    bzero(touchEvent, sizeof(touchEvent));

    // set up GSEvent
    event->record.type = kGSEventHand;
    event->record.subtype = kGSEventSubTypeUnknown;
    event->record.windowLocation = point;
    event->record.timestamp = GSCurrentEventTimestamp();
    event->record.infoSize = sizeof(GSHandInfo) + sizeof(GSPathInfo);
    event->handInfo.type = handInfoType;
    event->handInfo.x52 = 1;

    bzero(&event->handInfo.pathInfos[0], sizeof(GSPathInfo));
    event->handInfo.pathInfos[0].pathIndex     = 1;
    event->handInfo.pathInfos[0].pathIdentity  = 2;
    event->handInfo.pathInfos[0].pathProximity = (handInfoType == kGSHandInfoTypeTouchDown || handInfoType == kGSHandInfoTypeTouchDragged || handInfoType == kGSHandInfoTypeTouchMoved) ? 0x03 : 0x00;;
    event->handInfo.pathInfos[0].pathLocation  = point;


    mach_port_t port = (mach_port_t)getFrontMostAppPort();
    GSSendEvent((GSEventRecord *)event, port);
}

// why nothing happened?
static clickOnHome() {
    sendTouchEvent(kGSHandInfoTypeTouchDown, CGPointMake(100, 200));
    sleep(1);
    sendTouchEvent(kGSHandInfoTypeTouchUp, CGPointMake(100, 200));
}
4

1 に答える 1

3

はい、ここから取得した場合getFrontMostAppPort()、あなたの方法は問題ないと思います。

私はあなたが何を望んでいるのか理解しようとしています:

  1. 特定のアプリを (bundleId で) 開くだけの場合は、openCydia で利用できるコマンドライン ユーティリティを使用することをお勧めします。system()、または呼び出しを使用して、プログラムでこれを呼び出すことができますexec。または、この「オープン」機能を独自のアプリに組み込みたい場合は、こちらの回答を参照してください。

  2. さて、フォアグラウンドappではなく、バックグラウンドにあるアプリまたは微調整のコードを作成している可能性があります。そして、 bundleId でアプリを開くのではなく、特定の {x,y}座標に触れる必要があるかもしれません。あなたが本当にそれを望むなら、このコードは私のために働きます(この答えに基づいて...修正を加えて):

static void sendTouchEvent(GSHandInfoType handInfoType, CGPoint point) {

   uint8_t gsTouchEvent[sizeof(GSEventRecord) + sizeof(GSHandInfo) + sizeof(GSPathInfo)];

   // structure of touch GSEvent
   struct GSTouchEvent {
      GSEventRecord record;
      GSHandInfo    handInfo;
   } * touchEvent = (struct GSTouchEvent*) &gsTouchEvent;
   bzero(touchEvent, sizeof(touchEvent));

   touchEvent->record.type = kGSEventHand;
   touchEvent->record.subtype = kGSEventSubTypeUnknown;
   touchEvent->record.location = point;
   touchEvent->record.windowLocation = point;
   touchEvent->record.infoSize = sizeof(GSHandInfo) + sizeof(GSPathInfo);
   touchEvent->record.timestamp = GSCurrentEventTimestamp();
   //touchEvent->record.window = winRef;
   //touchEvent->record.senderPID = 919;  
   bzero(&touchEvent->handInfo, sizeof(GSHandInfo));
   bzero(&touchEvent->handInfo.pathInfos[0], sizeof(GSPathInfo));
   GSHandInfo touchEventHandInfo;
   touchEventHandInfo._0x5C = 0;
   touchEventHandInfo.deltaX = 0;
   touchEventHandInfo.deltaY = 0;
   touchEventHandInfo.height = 0;
   touchEventHandInfo.width = 0;
   touchEvent->handInfo = touchEventHandInfo;
   touchEvent->handInfo.type = (handInfoType == kGSHandInfoTypeTouchDown) ? 2 : 1;
   touchEvent->handInfo.deltaX = 1;
   touchEvent->handInfo.deltaY = 1;
   touchEvent->handInfo.pathInfosCount = 0;
   touchEvent->handInfo.pathInfos[0].pathIndex = 1;
   touchEvent->handInfo.pathInfos[0].pathIdentity = 2;
   touchEvent->handInfo.pathInfos[0].pathProximity = (handInfoType == kGSHandInfoTypeTouchDown || handInfoType == kGSHandInfoTypeTouchDragged || handInfoType == kGSHandInfoTypeTouchMoved) ? 0x03: 0x00;
   touchEvent->handInfo.x52 = 1;  // iOS 5+, I believe
   touchEvent->handInfo.pathInfos[0].pathLocation = point;
   //touchEvent->handInfo.pathInfos[0].pathWindow = winRef;

   GSEventRecord* record = (GSEventRecord*) touchEvent;
   record->timestamp = GSCurrentEventTimestamp();

   GSSendEvent(record, getFrontMostAppPort());
}

- (void) simulateHomeScreenTouch {
   CGPoint location = CGPointMake(50, 50);
   sendTouchEvent(kGSHandInfoTypeTouchDown, location);

   double delayInSeconds = 0.1;
   dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
   dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
      sendTouchEvent(kGSHandInfoTypeTouchUp, location);
   });
}

これにより、SpringBoard が最前面のアプリである (他のアプリが開いていない) 限り、タッチダウン/アップ イベントのペアが SpringBoard に送信されます。handInfoTypeまた、値がどこにマッピングされているか、2または1タッチ ダウン イベントとアップ イベントにマッピングされているかを確認できます。上記のコードは、生成するイベントが 2 種類だけであることを前提としています。


注:最初に x=100、y=200 の座標で試しましたが、何も起こりませんでした。座標は2つのホーム画面アイコンの間だと思います。他の座標 (x=50、y=50 など) を使用しても問題ありません。


注 II : このソリューションで実際に脱獄が必要になるとは思いません。プライベート APIを使用しているため、App Store に提出することはできませんが、これは、企業内の投獄された電話や愛好家向けの展開では機能するはずです。

于 2013-07-31T09:09:31.787 に答える