iOS动态库注入实践-伪造微信定位

原理:创建一个动态库利用oc的runtime特性替换定位相关回调方法伪造GPS坐标,然后将动态库注入微信。

伪造GPS坐标

原理图:

fake

替换CLLocationManager的setDelegate:方法,将CLLocationManager的delegate替换为我们自定义的WMLocationProxy代理类,WMLocationProxy持有真正的CLLocationManager的delegate。

1
2
3
4
5
6
- (void)wm_setDelegate:(id)delegate {
    WMLocationProxy *proxy = [[WMLocationProxy alloc] init];
    proxy.oLMDelegate = delegate;
    self.proxy = proxy;
    [self wm_setDelegate:proxy];
}

在WMLocationProxy中转发CLLocationManagerDelegate的方法时先替换位置坐标,然后再转发给CLLocationManagerDelegate。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
- (void)forwardInvocation:(NSInvocation *)anInvocation {
    if (self.oLMDelegate && [self.oLMDelegate respondsToSelector:anInvocation.selector]) {
        if (anInvocation.selector == @selector(locationManager:didUpdateToLocation:fromLocation:)) {

            CLLocation *originLocation;
            [anInvocation getArgument:&originLocation atIndex:3];

            CLLocation *newLocation = [self makeFakeLocationWithOriginLocation:originLocation];
            [anInvocation setArgument:&newLocation atIndex:3];
        }

        if (anInvocation.selector == @selector(locationManager:didUpdateLocations:)) {
            __unsafe_unretained NSArray *locations;
            [anInvocation getArgument:&locations atIndex:3];
            if (locations.count > 0) {
                CLLocation *originLocation = locations[0];
                CLLocation *fakeLocation = [self makeFakeLocationWithOriginLocation:originLocation];
                NSArray *fakeLocations = @[fakeLocation];
                self.orginLocations = fakeLocations;
                [anInvocation setArgument:&fakeLocations atIndex:3];
            }
        }
        [anInvocation invokeWithTarget:self.oLMDelegate];
    }
}

动态库(Dynamic library)注入

iOS8发布之后Xcode允许创建动态库,我们可以创建一个动态库和原ipa文件合并重新打包ipa。具体参考iOSDylibInjectionDemo

stackoverflow关于动态库的问题可以看看