iOS 上的 adb 工具 - libimobiledevice

一、简介 libimobiledevice 是一个与iOS设备通信的工具集,类似于安卓上的 adb 工具,像爱思助手、PP助手等底层都是用的这个工具。 A library to communicate with services on iOS devices using native protocols. ideviceinstaller 依赖于 libimobiledevice,主要用于操作 App,如获取应用列表、安装卸载应用等。 A command-line application to manage apps and app archives on iOS devices. 二、安装 Mac 上可以直接利用 Homebrew 安装: // 安装 libimobiledevice brew install libimobiledevice // 安装 ideviceinstaller brew install ideviceinstaller 三、使用 下面介绍常用的命令: 1. idevice_id 打印连接的设备的 UUID ➜ ~ idevice_id -l 0e68ed5333802b17d5ac62bfa708619de597eef2 2. idevicecrashreport 把设备上的崩溃报告移到指定文件夹。 ➜ ~ idevicecrashreport -u 0e68ed5333802b17d5ac62bfa708619de597eef2 crash Move: /com.apple.appstored/appstored.log Move: /Retired/rtcreportingd_2021-09-02-17-17-59_messageLog.ips Move: /Retired/liveshow-2021-08-31-165309.ips Move: /Retired/log-aggregated-2021-08-31-080228.ips ... 3. idevicedate 获取或者设置设备时间。 ...

2021年9月6日 · Darren Ou

iOS 沙盒挂载工具 - ifuse

一、ifuse ifuse 是一个文件系统工具,在未越狱的设备上可以挂载 App 的文件夹,在已越狱的设备上可以挂载根文件夹 This project allows mounting various directories of an iOS device locally using the FUSE file system interface. 二、安装 利用 Homebrew 进行安装: // 期间可能需要输入电脑密码 brew install macfuse brew install ifuse 安装时可能出现错误: // 编辑 ifuse 的安装配置 vim `brew formula ifuse` // 注释或删除以下几行 # on_macos do # disable! date: "2021-04-08", because: "requires closed-source macFUSE" # end // 重新安装 brew install ifuse 三、使用 1. 挂载 // 新建挂载点文件夹 mkdir ~/Sandbox // 设置挂载点 ifuse --container ifuse.test ~/Sandbox 此时 ifuse.test 的沙盒被成功挂载到 Sandbox 文件夹: ...

2021年9月5日 · Darren Ou

iOS 逆向入门 - TikTok 调试

一、MonkeyDev 1、简介 MonkeyDev 是一个工具集合,基于 iOSOpenDev 进行升级并集成到 Xcode 里面,可以用来开发越狱机器的插件,可以很方便地注入动态库并重签名安装到非越狱机器,堪称神器。 2、安装 参考官方文档进行安装:https://github.com/AloneMonkey/MonkeyDev/wiki 3、开始使用 新建 MonkeyApp 项目。 拖入 已砸壳 的 ipa 包到指定文件夹 配置开发证书。 如无意外即可运行到手机上。 4、其它运行问题 1. 链接错误 ld: file not found: /usr/lib/libstdc++.dylib 这是由于 Xcode 10 开始就不再集成 libstdc++ 库,需要把相关的库文件重新添加到对应的路径。 使用 GitHub 上的这个库 https://github.com/devdawei/libstdc- 可以比较方便地添加 libstdc++ 库。 2. Bundle ID TikTok 对 Bundle ID 应该有校验,用其它 Bundle ID 会导致无法联网,这时候可以在 Build Settings 里面,找到 MONKEYDEV_DEFAULT_BUNDLEID 设为 YES,这时候重新编辑安装到手机即可。 3. 需要国外手机卡 TikTok 对地区有限制,手机需要插上国外手机卡才能进行开播,这样对调试不太友好。 CTCarrier 是iOS上获取运营商信息的系统框架,我们可以对其进行 Hook,使其返回指定运营商信息。 得益于 MonkeyDev 维护了非越狱插件 CocoaPods 私有仓库(https://github.com/AloneMonkey/MonkeyDevSpecs),我们可以直接使用别人提供的插件,使用方法跟我们平时使用 CocoaPods 完全一致,添加对应的源地址即可: ...

2021年9月3日 · Darren Ou

C 语言中利用单引号表示整数

背景 在进行与竟品的性能对比中,需要知道竟品的部分参数,与竟品对齐参数后再进行性能测试。 在 hook TikTok 的摄像头输出参数时发现,PixelFormatType 的值是整数 875704422,这样的一串整数很难知道其含义。 分析 从 key PixelFormatType 可以猜出是 kCVPixelFormatType 枚举中的一个,kCVPixelFormatType 枚举中大部分的值是以 '420f' 这样的单引号形式来表示,通过逐一对比知道,原来 875704422 对应的就是 kCVPixelFormatType_420YpCbCr8BiPlanarFullRange 的值,也就是 '420f'。 那么,为什么 875704422 == '420f' ? 原来,可以通过 ascii 编码进行转换,以 '420f' 为例: 4/2/0/f 的 ascii 编码分别为 52/50/48/102 ,转换为二进制分别为 00110100/00110010/00110000/01100110,合并起来 00110100001100100011000001100110 转换为十进制,刚好就是 875704422。 为方便看出对应的字符串,写了以下转换算法: 转换算法 NSString * changeToTypeStr(int value) { char *str = malloc(10); int count = 0; while (value > 0) { char ch = (char)(value & 0xFF); str[count] = ch; value = value >> 8; count ++; } if (count > 1) { int left = 0, right = count - 1; while (left < right) { char tmp = str[left]; str[left] = str[right]; str[right] = tmp; left ++; right --; } } str[count] = '\0'; NSString *res = [[NSString alloc] initWithUTF8String:str]; free(str); return res; }

2021年9月1日 · Darren Ou

iOS 逆向入门 - 砸壳

一、背景 iOS 手机通过 App Store 安装的应用都经过加密,无法直接进行逆向分析。我们需要对应用进行解密,称为“砸壳”。 我手上的设备是 iPhone 6s,系统是 iOS 13.5.1 二、手机越狱 安装爱思助手,一键越狱的工具里面有很多个工具(不一定需要安装爱思助手,可以直接从官网下载越狱工具)。 这里主要推荐两个:一个是通过硬件漏洞进行越狱的 checkra1n;一个是通过软件漏洞进行越狱的 Unc0ver。 相对来说通过硬件漏洞进行越狱的 checkra1n 会比较稳定,我使用的是 checkra1n。 按照提示进行操作,手机重启后会出现 checkra1n 应用,打开应用安装 Cydia (这个过程手机需要连接代理)。 注意:不同的越狱工具,对手机跟系统都有要求,太新的设备或者太新的系统都有可能不支持,需要仔细阅读官网的文档。另外,保证手机的重要资料都已经备份。 三、通过 SSH 连接手机 1. Wi-Fi 手机安装 Cydia 后,默认安装了 OpenSSH,可以直接通过 Wi-Fi 或者 USB 连接手机。 ssh root@your_device_ip_address // 密码默认为 alpine 2. USB // 安装 usbmuxd brew install usbmuxd // 建立端口映射(把 2222 映射到 22) iproxy 2222 22 // 建立 ssh 连接 ssh -p 2222 root@localhost 建立端口映射时,终端会一直显示 “waiting for connection”,这是正常的,新建一个终端窗口进行其它操作即可。 ...

2021年8月30日 · Darren Ou

iOS 逆向入门 - 工具

iOS 越狱 https://checkra.in/ (基于硬件漏洞,较稳定) https://unc0ver.dev/ (基于软件漏洞,每次重启手机后都要再越狱) App文件系统结构 https://www.i-funbox.com/zh-cn/index.html https://macroplant.com/iexplorer App UI调试工具 https://revealapp.com/ https://lookin.work/ (免费) 反编译工具 https://hex-rays.com/ida-pro/ https://www.hopperapp.com/ MachO https://github.com/gdbinit/MachOView 越狱开发框架 https://github.com/theos/theos ipa砸壳工具 https://github.com/stefanesser/dumpdecrypted https://github.com/KJCracks/Clutch https://github.com/AloneMonkey/frida-ios-dump class-dump http://stevenygard.com/projects/class-dump/ 动态库注入 https://github.com/alexzielenski/optool 获取keychain信息 https://github.com/ptoomey3/Keychain-Dumper 工具集 https://github.com/kokoabim/iOSOpenDev https://github.com/AloneMonkey/MonkeyDev (基于iOSOpenDev开发,可开发非越狱插件) 持续更新。。。

2021年8月29日 · Darren Ou

iOS UI 自动化测试简介

前言 发布内测版的时候,每次在提交代码前、上传ipa包前、发布前都需要手动地跑一下主流程,比如在视频详情页划几页,在直播页划几个直播间等。都是比较重复且有规律的操作,可以利用自动化测试来代替手工操作。 我们在Jenkins上面打包时,会有一个UI自动化测试的选项,是架构组自己弄的一套自动化测试环境,想要自己搭建估计不太方便。所以需要有一套轻量级切足够易用的UI自动化测试框架。 XCUITest 简介 XCUITest是苹果在iOS9.3提供的自动化测试框架(iOS9.3之前提供的是UI Automation),Xcode自带的框架,不需要搭建其它环境,由于是苹果提供的框架,运行稳定。使用Swift或者OC编写测试用例(可能对于测试不是很友好)。 使用 func testExample() throws { // UI tests must launch the application that they test. let app = XCUIApplication(bundleIdentifier: "appium.test") app.launch() // 启动应用 for _ in 1 ..< 5 { app.swipeUp() // 上划 } for _ in 1 ... 3 { app.swipeRight() // 右划 } app.swipeDown() // 下划刷新 sleep(5) // 等待5s再执行下一步 app.cells.firstMatch.tap() // 点击当前的第一个cell for _ in 1 ... 5 { app.swipeUp() // 上划 sleep(2) // 等待2s再执行下一步 } app.buttons["live_room_quit_btn"].tap() // 点击标志btn } 通过id获取UI元素,需要先在代码设置accessibilityIdentifier: _quitButton.accessibilityIdentifier = @"live_room_quit_btn"; ...

2020年11月28日 · Darren Ou

【利用基于 Lint 的启动代码监控 Android 进房间流程】iOS 平台的可行性调研

一、目的 通过标识关键代码,利用Lint定期检测关键代码,当关键代码发生变更时,可以在报告中体现,避免引入意外的修改。 二、Lint Lint介绍 Lint 作为一种工具程序,主要负责静态源码分析,负责代码规范、代码缺陷等检测。(https://zh.wikipedia.org/wiki/Lint) Android 原生已经提供了 Lint 静态分析工具,而 iOS 则有对应的 OCLint 和 SwiftLint。 三、android实现代码监控的原理 Android Lint可以对Java/Kotlin源码使用uast进行语法分析,最后生成一棵AST抽象语法树,这棵树的每个节点都是一个方法,包含方法签名和方法体。 通过自定义的Lint规则,找到应用启动的入口方法。从入口方法开始遍历整棵调用树,即可对每个方法节点的代码段进行分析。 1. 获取关键代码段 open fun shouldMonitor(node: UMethod): Boolean { return node.getAnnotations().find { it.qualifiedName == LINT_MONITOR_ANNOTATION } != null } android通过注解的方式,标识需要检测的方法实现。通过Android Lint的自定义规则判断注解标识的方法,找到入口方法,然后对代码段进行分析。 iOS对应的OCLint也可以通过自定义规则进行静态分析,但是iOS没有注解,iOS如果需要标识关键代码段,目前想到的只能hardcode检测列表(包括类和方法名)来实现标识关键代码段的效果。但是这样的维护成本比较大。 iOS可以利用类似以下的代码片段进行类和方法的判断: for(auto it = parent->meth_begin(), end = parent->meth_end(); it != end; ++it) { const auto method = *it; if(declHasEnforceAttribute(method, *this)) { const auto selector = method->getSelector(); if(!implementation->getMethod(selector, method->isInstanceMethod())) { const string className = parent->getNameAsString(); const string methodName = selector.getAsString(); addViolation(implementation, this, "subclasses of " + className + " must implement " + methodName); } } } 注:在生成OCLint自定义规则工程时,Xcode 12会因架构问题出错,暂未找到解决方案,可暂时先切换Xcode 11生成OCLint自定义规则工程 ...

2020年8月20日 · Darren Ou

直播间横屏技术方案

一、背景 目前直播间已支持PC推流直播,但只支持竖屏播放,导致观看体验不佳,故需要把横屏模式加上。 二、面临的问题 1、只有两天开发时间,时间紧迫; 2、屏幕切换时存在UI异常风险; 3、横屏模式需要应用全局支持横屏方向,存在影响其他业务风险; 三、方案 1、切换横屏入口的显示(加开关) joinChannel/joinGroup成功 -> roomType == BSRoomType_PCRoom -> 判断开关 -> 显示入口 2、横竖屏切换初步方案 1.项目配置: 在AppDelegate里重写方法: - (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window { UIViewController *topViewController = [BaseViewController bl_findTopMostViewController]; if (topViewController && [topViewController isKindOfClass:NSClassFromString(@"DSLandscapeViewController")]) { return topViewController.supportedInterfaceOrientations; } return UIInterfaceOrientationMaskPortrait; } 2.竖屏转横屏: 新建一个支持横屏的DSLandscapeViewController并重写UIViewController的方法: - (UIInterfaceOrientationMask)supportedInterfaceOrientations { return UIInterfaceOrientationMaskLandscapeRight | UIInterfaceOrientationMaskPortrait; // 这里加上竖屏,是因为横屏转竖屏时,需要把当前vc先转过来,后面会讲到 } - (BOOL)shouldAutorotate { return YES; } 从竖屏vc(DSLiveShowViewController)旋转时,初始化横屏vc(DSLandscapeViewController),并把竖屏vc当前持有的BLLiveRoomAudienceSession传递给横屏vc。然后在当前navigationController的子vc中,把竖屏vc替换成横屏vc(原竖屏vc会销毁)。 - (void)switchToLandscapeView { DSLandscapeViewController *viewController = [[DSLandscapeViewController alloc] initWithAudienceSession:self.audienceSession]; NSMutableArray *viewControllers = [[NSMutableArray alloc] initWithArray:self.navigationController.viewControllers]; [viewControllers removeObject:self]; [viewControllers addObject:viewController]; [self.navigationController setViewControllers:viewControllers animated:YES]; self.audienceSession = nil; } 横屏vc初始化videoView,并调用session的方法传递给mediasdk([self.audienceSession changeRemoteViewForGroup:self.videoView];) ...

2020年1月4日 · Darren Ou

iOS 项目接入 CallKit 框架

CallKit是什么 苹果在WWDC 2016发布了iOS 10的新框架CallKit,它允许开发者在VoIP类型APP整合系统原生语音界面,以获得更好的用户体验。 接入CallKit后,APP里面的通话会被写入系统通话记录,而且APP通话时的优先级比一般VoIP的APP优先级要高。 CallKit主要类 我们可以把系统提供的CallKit框架理解成一个通话的界面UI,我们做的只是把这个通话界面跟我们的应用联系起来, 比如有一个语音电话过来了,那么我们就呼起这个界面,用户在这个界面上点击了静音按钮,我们相应地做静音的处理。 同样地,如果用户在应用里面点击了静音按钮,也要把状态同步到系统的界面。 呼起CallKit & CallKit回调 CXProviderConfiguration 描述系统通话界面的标题、logo、来电铃声等 CXCallUpdate 描述来电信息,如来电用户名、是否视频聊天等 CXProvider 同步连接状态到CallKit CXProviderDelegate 用户在系统通话界面上动作的回调 应用把状态同步到系统: CXCallAction 用户不同动作的描述,如:呼出电话、接听、挂断、静音等(分别对应CXStartCallAction、CXAnswerCallAction、CXEndCallAction、CXSetMutedCallAction) CXTransaction 把用户的不同动作打包成CXTransaction再传递给系统 CXCallController 把CXTransaction传递给系统 原理 1、呼入 来电 1.CallKitTestApp接收到服务器的来电信息(后台时VoIP Push) 2.创建CXCallUpdate对象记录来电信息,并记录该通话唯一标识 3.通过CXProvider对象把来电信息通知系统 4.系统接收到来电信息后显示原生来电UI 响应来电 1.用户在原生来电UI上点击接听按钮(或挂断按钮) 2.系统把动作封装成CXAnswerCallAction,通过CXProvider的Delegate回调到CallKitTestApp 3.CallKitTestApp收到回调后会开始配置mediasdk,调整UI等操作,最后开始通话 结束来电 1.CallKitTestApp在前台时,用户点击挂断按钮 2.创建CXTransaction对象,用于包装挂断动作CXEndCallAction(包含该通话唯一标识) 3.通过CXCallController对象把挂断动作通知系统 4.系统成功挂断该通话后,通过CXProvider的Delegate回调到CallKitTestApp 5.CallKitTestApp收到回调后会开始释放mediasdk(这里要注意释放顺序,不能在系统回调前把sdk释放掉),调整UI等操作 2、呼出 1.用户在CallKitTestApp呼出电话 2.创建CXTransaction对象,用于包装呼出动作CXStartCallAction(包含该通话唯一标识、呼出号码等信息) 3.通过CXCallController对象把呼出动作通知系统 4.系统成功呼出该通话后,通过CXProvider的Delegate回调到CallKitTestApp 5.CallKitTestApp收到回调后会开始配置mediasdk,调整UI等操作,最后开始通话 以上呼出逻辑是CallKitTestApp中IP-IP电话的处理逻辑,因为CallKitTestApp里面还有自动转换IP-PSTN逻辑,涉及到mediasdk资源释放问题,导致应用不稳定,内测版中暂时把呼出部分屏蔽。 CallKitTestApp如何接入 1、mediasdk做兼容 1.系统资源申请成功后再配置mediasdk 2.等系统资源释放后再释放mediasdk 为满足以上两点,mediasdk开放了下面几个接口,在CallKit模式下,等系统回调后再做mediasdk配置、激活、释放等操作 // In CallKit, it should be called by `perform Answer/start CallAction` bool callKit_test_configAudio(MEDIA_HANDLE handle); // In CallKit, it should be Called by `didActivateAudioSession` bool callKit_test_startAudio(MEDIA_HANDLE handle); // In CallKit, it should be Called by `didDeactivateAudioSession` void callKit_test_stopAudio(MEDIA_HANDLE handle); // In CallKit, it should be Called by `performEndCallAction` void callKit_test_releaseAudio(MEDIA_HANDLE handle); 2、CallKitTestApp在前台状态 1.在CallKitTestApp项目中添加BOProviderDelegate对象,作为与CallKit通信的桥梁。 ...

2019年5月10日 · Darren Ou