# 映客 iOS 客户端 v3.3 登录接口破解

By [specer](https://paragraph.com/@specer) · 2021-12-29

---

本来原则是找最旧的，然后找 android 的。但是当时手上暂时没有 android 机，就只能搞 iOS，但是老版本的映客客户端又没有手机登录的功能，于是只能硬着头皮用当前的最新版本。 由于手上没有越狱设备，于是直接从 PP 助手那里下载了一个现成的已经脱过壳的映客版本。以下是破解步骤的流水账记录

*   unzip inke.ipa
    
*   打开 Hopper Disassembler v3，把解压后的 Payload/inke.app/inke 二进制文件拖进 Hopper 里。
    
*   手机配代理连 Charles，走一遍手机号登录流程，抓取请求短信验证码和登录的请求。 请求短信验证码：
    

![请求短信验证码的参数](https://storage.googleapis.com/papyrus_images/b6844c2c0c3cc14027ee635d3b0c665900a6d399b94a7813e4f93d0e294d9548.png)

请求短信验证码的参数

登录的请求：

![请求登录的请求参数](https://storage.googleapis.com/papyrus_images/b54eb2c671050a1205ebbab09a51d71766dfe3c0296ea7e87530124e3be106ed.png)

请求登录的请求参数

*   根据这些请求里的一些字段，在 Hopper 的 Labels 框里猜测一些关键字。几番尝试后，发现输入 loginphone 后找到了想要找的函数：**\[UserLoginModel loginPhone:requestId:code:completion:\]** 然后再顺藤摸瓜，以 UserLoginModel 为关键字继续搜，发现了这个函数：
    
    **\[UserLoginModel requestVoiceCodeWithPhone:region:completion:\]**
    

![](https://storage.googleapis.com/papyrus_images/bca5b6186a46ee8b43615ba4415ca1cd02759cb570126143125eb1a7dc006151.png)

*   那就先从发送验证码的函数开始分析吧，反编译该函数后：
    

![](https://storage.googleapis.com/papyrus_images/fe2dca63454593bb5ccd16b9e0cba49d6f25c5c601ab63ad95c418e35d5c1e1c.png)

可以发现 **arg2** 就是手机号，然后分别被 **\[SecurityTool rsaEncrypt1:r5\]** 和 **\[SecurityTool md5Encrypt:r4\]** 加过密。后者看名字就能知道是 md5 加密，所以先自己给手机号 md5 一下看看：

![](https://storage.googleapis.com/papyrus_images/7d1a571a2410614914bd994034f0dfcaf9637c0baba62730ee412ee0c77656d5.png)

发现结果和请求里的字段貌似并没有什么关联，以为猜错了，后来想起自己登录映客的时候还选过区的，所以手机号可能需要加个 86：

![](https://storage.googleapis.com/papyrus_images/7d55d9fdd7d24ac26d8a636854fac14b70a99df5fbb24e9c2b3291f3eaadd3e5.png)

这下果然就对了，结果正好对应着请求里的 secret 字段。那猜测那个 rsa 加密函数的结果应该就是对应着请求里的 phone 字段了。

*   接着继续搜 SecurityTool 关键字，找到 rsaEncrypt1 函数，反汇编后：
    

![](https://storage.googleapis.com/papyrus_images/d5a6305f4b744f18db926f83cd5c06d65719fb9089c9c0ec9e0fd93d80c15fba.png)

可以发现里面多次出现了带 `MIH` 前缀的函数，猜测多半是用了什么开源库之类的东东，于是上 github 上搜下其中的 `MIHRSAPublicKey` 类，果然找到了相关资料，然后各种搜发现了一个叫 [MIHCrypto](https://github.com/hohl/MIHCrypto) 的开源库，按照教程新建的测试工程后，就开始仿照反汇编后的结果模拟加密逻辑：

![](https://storage.googleapis.com/papyrus_images/ad5ae30a2c1bcb6cf0f397f4c5c2939744304d0eecd7548fbde200948d30baf2.png)

这里有个小插曲，反汇编后的那个常量字符串由于太长了，显示不全，直接就显示三个点了…我模拟的加密逻辑始终会 crash 就是因为那个字串不全导致格式不对。又不会怎么用带 UI 版本的 gdb，后来想了很久，发现还有另一款反编译神器 IDA，抱着试一试的态度下载免费版的 IDA 后，果然能看到完整的常量字符串了：

![](https://storage.googleapis.com/papyrus_images/261000297d69fab17cda6ddd311fa3af6182378a331ae615727560a24129b782.png)

然后运行 demo，结果出来的加密结果跟抓包的 phone 字段不一样，没办法只能再重头再梳理一遍逻辑，看看哪里出问题了。不过研究了很久，真心确定过程并没有什么错误，于是抱着试一试的心理，用 paw 组包发送，居然成功了：

![](https://storage.googleapis.com/papyrus_images/1faa334454c14132c406fad3bdcbf0547e0d985fb1ba6519695fb3e7187a38e9.png)

*   解决了请求验证码的接口后，登录的接口也就很轻松了。登录接口的 code 就是验证码，phone 是和请求验证码一样的加密逻辑，secret 通过看反汇编的代码是 `手机号#短信验证码` 的 md5 的结果，request\_id 就是请求短信的返回包里的字段，组包发送，成功：
    

![](https://storage.googleapis.com/papyrus_images/715a2f52b8e75ed7a3951a89fe1432dfcf84cc235ac52d4f6d863d8853b1dc1d.png)

*   解决了手机登录后，再尝试下看看第三方联合登录有没有搞头。先拿微信举例，只要获取到映客的 WX\_App\_ID 和 WX\_App\_Secret 就可以了。WX\_App\_ID 是写死在客户端的，这个可以通过反编译拿到。但是 WX\_App\_Secret 通常都是存在服务器的，感觉没什么出路。正在纠结的时候发现映客是用的友盟集成的第三方登录组件，这个组件好处就是用起来很便利，当然坏处就是不安全，得提供给他们 WX\_App\_Secret，意味着这个字段或许我们可以在客户端反编译搜出来。果然以 ThirdPlatform 为关键字，搜出了相关方法：
    

![](https://storage.googleapis.com/papyrus_images/02ccfcf94c794e66a7625b57497207a90cfef931c2504c83c3490925b75c08fb.png)

![](https://storage.googleapis.com/papyrus_images/08599341ddc0e3139c37119e7a777d4da537aca448f4b33f5e3da7b49a0f099d.png)

于是在第三方的 app 里用这两个字段模拟微信登录的体验就是：在第三方的 app 里唤起微信的授权页，但是授权页是显示的是映客的 icon 和名称，用户点击允许后返回第三方的 app，然后第三方拿到 openid 和登录态等，用这些再去微信获取用户的基本信息，同理其他联合登录也是一样的方法。

---

*Originally published on [specer](https://paragraph.com/@specer/ios-v3-3)*
