shichg123 发表于 2019-10-19 19:55:58

iOS逆向实践 — 逆向微信,伪装定位(二)

承接上一篇

## 1. 创建工程

还是跟之前的步骤一致,创建工程,然后配置 Makefile。注意创建工程时名字只能包含数字跟字母。



Makefile

上面引入的 `FakeWeChatLocationManager.m` 文件是主要代码实现的地方,分离出来好模块化。

## 2. Reveal 注入

为了更好地定位代码,需要分析一下“附近的人”这个界面对应的类名是什么,然后进一步分析其实现。这时候需要用到 Reveal。

Reaveal 是一个超级强啊的 UI 分析工具。但是正常情况下,我们只能使用 Reveal 来检测调试自己的 APP,第三方的 APP 无法检测。不过,方法总比问题多。注入 Reveal 的手段就是通过编写 tweak 来链接 reveal 提供的动态库。

### 2.1 获取 libReveal.dylib

在 Reveal 菜单中找到 .dylib 文件:



### 2.2 将 libReveal.dylib 导入目标的 Documents 目录

这是按照代码来确定的。导入的方式很多,可以使用PP助手也可以使用 ssh。但是毕竟PP助手,不用查找来查找去,比较直观:



将库文件拖进去:



如果你的PP助手点开之后进入的是 APP 的安装目录而不是沙盒路径,那么就需要到 Cydia 安装一个叫 afc2add 的补丁了,解决越狱后用 usb 访问文件系统的问题。

### 2.3 创建 RevealUtil

代码来源于 Reveal 官网中关于[安装的文档](http://support.revealapp.com/kb/getting-started/revealrevealxcode),这里将实际工作代码跟 xm 划分出来,是为了便于模块化我们的工程,让 tweak 只完成一个 hook 的功能:

```
//
//RevealUtil.h
//temp
//
//Created by Pandara on 16/8/14.
//Copyright © 2016年 Pandara. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface RevealUtil : NSObject {   
    void *_revealLib;
}

- (void)startReveal;
- (void)stopReveal;

@end
```

```
//
//RevealUtil.m
//temp
//
//Created by Pandara on 16/8/14.
//Copyright © 2016年 Pandara. All rights reserved.
//

#import "RevealUtil.h"
#import <dlfcn.h>

@implementation RevealUtil
- (void)startReveal {   
    if (NSClassFromString(@"IBARevealLoader") != nil) {      
      return;   
    }      
   
    NSString *revealLibName = @"libReveal.dylib";   
    NSString *documentDirectory = ;   
    NSString *dylibPath = ;      
   
    _revealLib = NULL;   
    _revealLib = dlopen(, RTLD_NOW);   
    if (_revealLib == NULL) {      
      char *error = dlerror();      
      NSLog(@"dlopen error: %s", error);   
    } else {      
      //Post a notification to signal Reveal to start the service
      [ postNotificationName:@"IBARevealRequestStart" object:nil];   
    }
}

- (void)stopReveal {   
    if (_revealLib == NULL) {      
      return;   
    }      
   
    [ postNotificationName:@"IBARevealRequestStop" object:nil];   
    if (dlclose(_revealLib) == 0) {      
      _revealLib = NULL;   
    } else {      
      char *error = dlerror();      
      NSLog(@"Reveal library could not be unloaded: %s", error);
    }
}

@end
```

### 2.4 创建 Theos 工程

编写好加载 dylib 的源码之后,需要继续构建我们的 Theos 工程来 hook 住微信,好调用我们加载 Reveal 的代码。xm 文件代码如下:

```
#import "RevealUtil.h"

%hook MicroMessengerAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {      
      %orig;      
      
      RevealUtil *ru = [ init];      
      ;      
      
      return YES;
}
%end
```

修改 Makefile 文件,将新增的文件添加到路径指定中,链接必要的 framework 以及 libz.dylib:

```
THEOS_DEVICE_IP = 192.168.31.222
ARCHS = arm64
TARGET = iphone:9.3

include $(THEOS)/makefiles/common.mk

TWEAK_NAME = RevealUtil
RevealUtil_FILES = Tweak.xm RevealUtil.m
RevealUtil_FRAMEWORKS = UIKit CFNetwork
RevealUtil_LDFLAGS = -lz

include $(THEOS_MAKE_PATH)/tweak.mk

after-install::      
      install.exec "killall -9 WeChat"
```

最后 make package install 一条龙将包安装到机器,成功之后,只要与 iOS 设备在同一局域网下,就可以对界面进行调试了:



### 2.5 寻找需要 hook 住的类名以及方法名称

打开 Reveal, 查看“附近的人”对应的类名是什么:



并不能直接查找到 ViewController 对应的类名,但是可以看到这个 tableView 里面的 cell 名称有 PeopleNearBy 这样的关键词。于是猜测 ViewController 也具备这样的关键词。在之前 class-dump 出的头文件中,果然找到这样一个类 `PeopleNearByListViewController`,但是从头文件中没有找到什么蛛丝马迹。

思考来思考去,还是应该从 hook 住 `CLLocationManager` 的 `startUpdatingLocation` 方法入手。

## 3 实现 FakeLocation

代码没什么难处,源码放在了 (https://github.com/PandaraWen/FakeWeChatLocation) 上,下面解剖一下实现思路:

### 3.1 设置定位

这里用了最简陋的方法,就是弹出对话框输入经纬度(因为喜欢日本,所以顺手设置了东京的经纬度为默认值),点击确定后将数据保存到 `NSUserDefault` 。代码就不贴了,无非就是生成一个 `UIAlertController` 然后显示出来。需要 hook 住 `MicroMessengerAppDelegate` 中的 `didFinishLaunchingWithOptions` 方法来实现。

### 3.2 Fake 定位信息

Fake 定位信息实际上就如同上面所说, hook 住 `CLLocationManager` 的 `startUpdatingLocation` 方法,然后直接读取存在 `NSUserDefault` 中的经纬度,直接返回给 delegate:

```
%hook CLLocationManager
- (void)startUpdatingLocation {   
    CGFloat lat = [[ objectForKey:@"PD_FAKE_LOCATION_LAT"] doubleValue];   
    CGFloat lng = [[ objectForKey:@"PD_FAKE_LOCATION_LNG"] doubleValue];   
    if (lat < 0.1 || lng < 0.1) {      
      lat = 35.707013;      
      lng = 139.730562;   
    }      
   
    CLLocation *tokyoLocation = [ initWithLatitude:lat longitude:lng];   
   
    CLLocation *cantonLocation = [ initWithLatitude:23.127444 longitude:113.257217];

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"   
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{      
      ;   
    });
#pragma clang diagnostic pop
}
%end
```

上面我用了 GCD 来延时,是因为之前直接使用 `responseToSelector` 来做 delegate 判断的时候发现没有不能通过条件,难道原代码中是 `startUpdateingLocation` 之后再 `setDelegate` 的吗?

### 3.3 打包安装

make package install 之后,搞定,因为 hook 住的是 CLLocationManager,所以作用范围比较大,效果如下:



*设置定位*



*附近的人*



*朋友圈定位*

## 4. 小结

现在提到的 APP 逆向,大多都是以编写功能 tweak 为目的的。而 tweak 的核心就是 hook,为了实现 hook,我们需要知道 APP 内部的一些实现,所以需要 class-dump,还有反编译。而这两个操作的前提,就是砸壳,先把能够分析的文件弄出来再说,要不都是扯淡。砸壳可以自己砸,也可以上第三方分发渠道下载,一般都是已经砸过壳的了,能省一些功夫。






页: [1]
查看完整版本: iOS逆向实践 — 逆向微信,伪装定位(二)