钉钉打卡修改定位
分析
常规方案:
- Xcode debug模式下的模拟定位,可直接修改手机定位;
- 爱思助手等工具修改虚拟定位
- 根据打卡页面的定位服务功能类去hook定位结果数据;
- 拦截系统的定位回调API方法,修改定位信息,抛回给应用业务。
上述方案分析:
方案1 肯定不在本次的实践里,因为实在太简单了~;
方案2 最新实践了下,钉钉已经能识别了,打不了卡衰;
方案3 需要了解钉钉的业务场景,去查看钉钉dump后的部分代码,会相对耗时;
方案4 这里是在系统和应用之间,做一次拦截,这个方案不需要考虑业务实现,具有普适性,后续其他应用也能使用该方案,价值更高。
逆向步骤:
1. 第一步 越狱机上安装钉钉应用。 砸包导出DingTalk.ipa,获取bundleId等信息
-
手机越狱和砸包,这里就不细说了哈, 教程实在太多了
对DingTalk可执行文件dump,获取到对应的.h文件
class-dump -H Payload/DingTalk.app/DingTalk -o DingTalk
2. 获取应用进程名 DingTalk
,作为tweak注入的应用
这个方法比较多,ipa里的info.plist文件可以查看,手机通过USB线 连接Mac,控制台中可以看到进程日志打印
3. 书写定位信息hook的核心代码
我们知道系统的单点定位API,是如下接口,我们只需要拦截,修改定位信息,然后修改后的定位信息抛回去,那是不是OK了?
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
是的,我们就是拦截这个方法。
在钉钉的dump文件夹中搜了一下didUpdateLocations, 有好多类使用到了。
在这里,不针对具体业务场景处理了,我们还是使用最简单有效的方式来hook。对系统类CLLocationManager
的setDelegate 和delegate做一次hook,然后拦截方法- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray
的代理实现。
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Method orignalMethod = class_getInstanceMethod(self, @selector(setDelegate:));
Method swizzledMethod = class_getInstanceMethod(self, @selector(wesk_setDelegate:));
method_exchangeImplementations(orignalMethod, swizzledMethod);
Method orignalMethod2 = class_getInstanceMethod(self, @selector(delegate));
Method swizzledMethod2 = class_getInstanceMethod(self, @selector(wesk_delegate));
method_exchangeImplementations(orignalMethod2, swizzledMethod2);
});
}
- (void)wesk_setDelegate:(id)delegate {
if (delegate) {
WLocationProxy *proxy = [[WLocationProxy alloc] initWithTarget:delegate];
self.weskProxy = proxy;
[self wesk_setDelegate:proxy];
} else {
self.weskProxy = nil;
[self wesk_setDelegate:delegate];
}
}
- (id)wesk_delegate {
id delegate = [self wesk_delegate];
if (delegate == self.weskProxy) {
return self.weskProxy.target;
}
return delegate;
}
这里用了NSProxy中间代理对象,进行消息处理,WLocationProxy 重要代码:
@implementation WLocationProxy
- (instancetype)initWithTarget:(id)target {
_target = target;
return self;
}
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
// 使用mock 定位.
CLLocation *mockLocation = [[CLLocation alloc] initWithLatitude:[WLocationInstance sharedInstance].mockLatitude longitude:[WLocationInstance sharedInstance].mockLongitude];
locations = @[mockLocation];
[self.target locationManager:manager didUpdateLocations:locations];
}
@end
4. 工程创建及编译修改
创建Tweak 工程 ddhook。
钉钉app的bundleId: com.laiwang.DingTalk
![工程创建](https://upload-images.jianshu.io/upload_images/2906485-46cf07ed7d025b9b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/940)
创建好工程之后,修改Makefile 编译文件如下:
TARGET := iphone:clang:latest:7.0
INSTALL_TARGET_PROCESSES = DingTalk
THEOS_DEVICE_IP = 10.1.50.123
THEOS_DEVICE_PORT = 22
ARCHS = armv7 arm64
iOSRE_FRAMEWORKS=UIKit Foundation
include $(THEOS)/makefiles/common.mk
SRC = $(wildcard src/WLocation/*.m)
TWEAK_NAME = DDHook
DDHook_FILES = $(wildcard src/WLocation/*.m) src/Tweak.x
DDHook_CFLAGS = -fobjc-arc
include $(THEOS_MAKE_PATH)/tweak.mk
after-install::
install.exec "killall -9 DingTalk"
PS: 这里将Twea.x的文件层级 进行了拖动,同时创建了文件夹WLocation
, 这个在Tweak.x文件里 访问WLocation目录下的类时,需要加上路径,如
#import "WLocation/WLocationInstance.h"
Tweak.x 文件中选一个启动必调用的类,地图上随便拾取了一个北京的定位坐标(116.433598,39.911103),然后进行定位数据mock赋值,如下:
%hook UIViewController
- (void)viewDidLoad {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[WLocationInstance sharedInstance].customLocation = YES;
[WLocationInstance sharedInstance].mockLatitude = 39.911103;
[WLocationInstance sharedInstance].mockLongitude = 116.433598;
});
%orig;//调用原始方法
}
%end
最终打卡页效果如下:
总结:
钉钉打卡定位的修改,在越狱机上实现,总体来说,技术不是很难。 主要是思路,怎么去做是最简单有效。
怎么在我们其他应用上拦截?
如果是在非越狱机上修改,我们有没有什么更好的方案?