树莓派2B做个 ios虚拟定位器

@vrqq  January 9, 2020

思路

  • 借用libimobiledevice 和手机通信
  • iphone开热点,通过上述工具usb线组局域网
  • 写一个小网页做树莓派control-interface,用avahi-daemon广播自己域名给iphone,可以直接浏览器控制
  • Pi上用调ideviceimagemounter向手机写入开发者镜像
  • Pi上借助libimobiledevice库,以及"com.apple.dt.simulatelocation"协议发送虚拟定位给手机

准备环境

配置自动启动

新建/home/ubuntu/iosanywhere.service如下

[Unit]
Description=iOS Locate Simulator by vrqq
After=network.target

[Service]
ExecStart=/home/ubuntu/pi
ExecReload=/bin/kill -HUP $MAINPID
WorkingDirectory=/home/ubuntu
StandardOutput=inherit
StandardError=inherit
Restart=on-failure
User=root

[Install]
WantedBy=multi-user.target
Alias=iosanywhered.service

然后

cd /lib/systemd/system
sudo ln -s /home/ubuntu/iosanywhere.service
sudo systemctl enable iosanywhere

接下来开机就自动运行啦!当然我们也可以service iosanywhere start

注入开发者镜像

ideviceimagemounter 13.2/DeveloperDiskImage.dmg 13.2/DeveloperDiskImage.dmg.signature

用com.apple.dt.simulatelocation写位置

这部分是从各个开源版本抄来的
还原定位:我尝试发一个不正确的经纬度数字,然后等一小会就自动还原了,但是很不稳定。稳定办法还是重启。。

bool setLocation(const char* udid, std::string lat1, std::string lng2) {
    std::cout << "[DEBUG] latitude=" << latitude << " longitude=" << longitude << std::endl;
    idevice_t device = nullptr;
    lockdownd_client_t lckd = nullptr;
    lockdownd_service_descriptor_t service = nullptr;
    service_client_t client = nullptr;
    if (IDEVICE_E_SUCCESS != idevice_new(&device, udid)) {
        if (udid)
            std::cout << "No device found with udid " << udid << ", is it plugged in?" << std::endl;
        else
            std::cout << "No device found, is it plugged in?" << std::endl;
        return false;
    }
    int ldret;
    if (LOCKDOWN_E_SUCCESS != (ldret = lockdownd_client_new_with_handshake(device, &lckd, NULL))) {
        idevice_free(device);
        std::cout << "ERROR: Could not connect to lockdownd, error code "<< ldret << std::endl;
        return false;
    }
    lockdownd_start_service(lckd, "com.apple.dt.simulatelocation", &service);
    lockdownd_client_free(lckd);
    service_client_new(device, service, &client);

    // start sending lng/lat
    char datasize[4] = {0, 0, 0, 0};
    auto mksize = [&](size_t sz) {
        union {
            uint32_t uintval;
            char charval[4];
        }test, cnv;
        cnv.uintval = sz;
        test.uintval = 0x1;
        if (test.charval[0] == 0x1) {
            datasize[0] = cnv.charval[3]; datasize[1] = cnv.charval[2];
            datasize[2] = cnv.charval[1]; datasize[3] = cnv.charval[0];
        }
        else {
            datasize[0] = cnv.charval[0]; datasize[1] = cnv.charval[1];
            datasize[2] = cnv.charval[2]; datasize[3] = cnv.charval[3];
        }
    };
    size_t sent;
    service_send(client, datasize, sizeof(datasize), &sent);

    mksize(lat1.size());
    service_send(client, datasize, sizeof(datasize), &sent);
    service_send(client, lat1.c_str(), lat1.size(), &sent);
    mksize(lng2.size());
    service_send(client, datasize, sizeof(datasize), &sent);
    service_send(client, lng2.c_str(), lng2.size(), &sent);

    service_client_free(client);
    if (service)
        lockdownd_service_descriptor_free(service);
    idevice_free(device);
    return true;
}

网页版console

  • 用popen开进程执行外部程序
  • 配合fgetc或者fread读程序输出

开箱即用代码!

iosAnywhere_20200112.zip (LGPL-3.0 License)
下面几个来自/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/
10.3.zip (iPhone5 最高)
12.4.zip (iPhone6 最高)
13.2.zip (兼容iOS 13.3)
13.3.zip
13.4.zip
13.5.zip


仅有一条评论

  1. 胡子嫂嫂 胡子嫂嫂

    老公!想给你生猴子!

添加新评论