欢迎来到我的个人博客。
- 我是一名 iOS / macOS 开发者,base 广州,喜欢捣鼓电子产品,擅长打羽毛球。
- 我将在这里记录技术,记录生活。
- Just for fun ~
欢迎来到我的个人博客。
frp 是一个专注于内网穿透的高性能的反向代理应用,支持 TCP、UDP、HTTP、HTTPS 等多种协议。可以将内网服务以安全、便捷的方式通过具有公网 IP 节点的中转暴露到公网。 一、服务端配置 1、安装及配置 这里以群晖 NAS 为例: 在 Docker 注册表里搜索 frps,安装 latest 版本(也可以安装指定版本); 在映像里创建容器,并进入高级设置; 在高级设置里启用自动重新启动; 在存储空间添加文件,装载路径为 /etc/frp/frps.ini; 网络里勾选使用与 Docker Host 相同的网络; 启动容器。 2、frps.ini 配置文件 [common] bind_port = 7000 token = your_token dashboard_port = 7500 dashboard_user = your_dashboard_user dashboard_pwd = your_dashboard_pwd vhost_http_port = 8000 vhost_https_port = 8001 二、客户端配置 1、安装及配置 同样以群晖 NAS 为例,安装及配置基本跟服务端相同,配置文件改为 frpc.ini 即可。 2、frpc.ini 配置文件 [common] server_addr = your_server_addr server_port = 7000 tls_enable = true token = your_token [ssh] type = tcp local_ip = 192....
一、前言 阿里云盘即使不是会员也不会限速,获得广大好评。如果能把阿里云盘挂载到 NAS 上,相当于扩充了 NAS 的磁盘容量,也可以利用这一点实现在线播放视频、数据同步等功能。 aliyundrive-webdav 这个工具可以让阿里云盘成为支持 WebDAV 协议的文件服务器,下面简单介绍其安装及使用。 二、安装配置 1、aliyundrive-webdav 安装 在 Docker 注册表里搜索 aliyundrive-webdav,安装 latest 版本(也可以安装指定版本); 在映像里创建容器,并进入高级设置; 在高级设置里启用自动重新启动; 在存储空间添加文件夹,装载路径为 /etc/aliyundrive-webdav/; 添加 8080 端口; 添加 REFRESH_TOKEN、WEBDAV_AUTH_USER、WEBDAV_AUTH_PASSWORD 三个环境变量(REFRESH_TOKEN 在后面介绍如何获取); 启动容器。 2、refresh_token 获取 登录阿里云盘网页版,F12 进入开发者模式,然后在对应位置获取 refresh_token。 三、挂载 四、数据同步
一、前言 距离去年入坑 NAS 已经一年多了(群晖 NAS - 购置篇),这一年多里学习了很多 NAS 的玩法,感觉能够发挥了 NAS 应有的作用。 这里简单介绍一下我利用 NAS 做了什么事情,但不会介绍详细的实现方法,因为网上已经有大量的参考文章。 二、外网访问 能在外网访问家里的 NAS,会多很多玩法,所以怎么实现外网访问是我入坑 NAS 的第一课。 1、QuickConnect QuickConnect 是群晖官方提供的远程访问服务,使用起来最简单门槛最低,但存在几个缺点: 限速比较严重,只有 500k/s 左右下载速度; 数据会经过群晖服务器进行中转,且账号必须绑定手机号,让我觉得会有隐私问题; 只有白群晖能用,黑群晖无法激活。 基于这几个缺点,我需要找其它的替代方案。 2、公网 IP 最方便的公网访问方式就是家里的宽带有公网 IP,无需转发直接访问,但不是所有宽带都能开通公网 IP。 这里的公网 IP 特指 IPv4 的公网 IP,因为 IPv4 的公网 IP 的兼容性最好,所有运营商都支持访问;IPv6 的公网 IP 甚至每个网口都能分配一个 IP,但目前来说应用还不是很广泛,有些运营商有些路由器都还不支持访问。 不同运营商情况大概如下: 如果家里宽带用的是电信,那么可以打电话给客服免费开通公网 IP,很大概率可以开通,如果开通不了就多打几次电话。电信宽带还不支持分配和访问 IPv6 公网 IP。 移动宽带则是完全不向个人开放 IPv4 的公网 IP,但是默认支持 IPv6 IP。 联通的话据说申请难度比电信要高,但我还没用过没有发言权。 我在广州家里用的是移动宽带,默认分配了 IPv6 的公网 IP,所以是可以直接 IPv6 IP 来访问我家里的 NAS。...
本博客使用 Hugo 搭建,这里记录一下搭建过程。 Hugo is one of the most popular open-source static site generators. With its amazing speed and flexibility, Hugo makes building websites fun again. 一、Hugo 基本使用 i. 命令使用 # Hugo 安装 brew install hugo # 新建博客 hugo new site hugo-blog # 添加主题(修改 config.yml 配置文件中 `theme: PaperMod`) git submodule add https://github.com/oudushu/hugo-PaperMod.git themes/PaperMod # 新建博文 hugo new posts/web-hugo-blog.md # 网站预览(http://localhost:1313/) hugo server # 生成静态文件(public 文件夹) hugo ii. 图片 图片资源存放在 static 文件夹中,我习惯每篇文章都新建一个文件夹存放图片,如:hugo-blog/static/image/web-hugo-blog/image-20220316160415439....
一、工具 在逆向的过程中,我们经常需要往目标执行文件中注入自己的逻辑,从而实现 hook 的目的。 我们常用 optool 工具实现动态库注入。 Command Line Tool for interacting with MachO binaries on OSX/iOS 了解这个工具的原理,有助于我们对 MachO 文件有更深入的了解。 二、源码解析 关键代码如下: BOOL insertLoadEntryIntoBinary(NSString *dylibPath, NSMutableData *binary, struct thin_header macho, uint32_t type) { // 判断 Load Command 类型 if (type != LC_REEXPORT_DYLIB && type != LC_LOAD_WEAK_DYLIB && type != LC_LOAD_UPWARD_DYLIB && type != LC_LOAD_DYLIB) { LOG("Invalid load command type"); return NO; } // 判断动态库是否已经注入 // parse load commands to see if our load command is already there uint32_t lastOffset = 0; if (binaryHasLoadCommandForDylib(binary, dylibPath, &lastOffset, macho)) { // there already exists a load command for this payload so change the command type uint32_t originalType = *(uint32_t *)(binary....
在通过逆向分析竞品过程中,经常需要分析其实现逻辑。但由于没有符号,我们会遇到一些阻碍。 一、符号恢复 我们经常 hook 一个方法并加断点可快速获得参数值,但是使用 bt 命令打印堆栈信息时,只能看到 ___lldb_unnamed_symbol279180$$TikTok 的信息,原因是 Objective-C 在打包时会被 stripped out,导致无法看到具体符号。 1. restore-symbol 使用 可以利用 restore-symbol 工具恢复符号(只能恢复 Objective-C 符号,无法恢复 C/C++ 符号),具体使用如下: # git clone --recursive https://github.com/tobefuturer/restore-symbol.git # cd restore-symbol # make # ./restore-symbol TikTok -o TikTok_symbol 2. 错误处理 在运行时会报错:2022-01-06 18:07:15.103 restore-symbol[17534:7647405] *** Assertion failure in -[CDObjectiveC2Processor loadClassAtAddress:], CDObjectiveC2Processor.m:258,原因是使用了 Swift 语言,而解析 Swift 的方法已过期。我们可以简单粗暴地把抛出异常的代码注释掉,重新 make 即可成功恢复符号。 3. 验证 把 ipa 包里的 MachO 文件替换为恢复符号后的 MachO 文件,重签名后运行到手机上(MonkeyDev 工具已经集成重签名的功能,这里只需要替换 TargetApp 里面的 MachO 文件,clean 后 rebuild 即可)。...
今年总体来说过得挺顺利,阿 B 顺利出生,工作上加入了新团队,技术上有了更多的积累,只是投资上稍亏损,无伤大雅。 个人 今年最大的事情当属 BB 的出生,老婆从三月怀孕,到十一月顺利生下牛宝宝。无论是怀孕过程中老婆身体上的不适还是出生后对 BB 无微不至的照顾,都相当不容易,不由感叹母亲的伟大及生命的奇妙。 今年形成了两个比较好的习惯,一个是写博客,虽说不上高产,但今年的文章写得比往年都多,无论是记录生活还是记录技术,对自己来说都是一个积累;一个是刷算法,下半年开始,基本上能坚持每天至少刷一道题,感觉对思维灵活度上有一定帮助,以前提到算法都有恐惧感,现在已经好多了。 今年在兴趣上的投入比往年都多一些,打球的频率基本能保证每周一到两次,双十二时还买了一双羽毛球鞋,但是还舍不得穿。年初开始入坑 NAS,积累了一定的服务器运维能力,还折腾了下路由器。兴趣上的投入对自己还比较满意。 今年二月开始还房贷,原来还有车贷,阿 B 出生后有较多支出,公司取消大小周后没了加班工资,钱包有一定的压力。不过好消息是今年涨薪了两次,今年十月份已经还完了车贷,总体上来说压力不算太大,还有一些盈余。 购物上还是放不开手脚,今年新出的 MBP 还有 iPhone 13 都很吸引,但考虑到家庭较大的支出,还是忍下来了,希望明年有更多的收入满足自己的购物欲。 今年投资算是比较失败,基金、A 股、美股都有不同程度的亏损,估计明年我的投资会更加偏向保守。 工作 今年在公司职业发展上有个比较大的转变,四月份时从客户端开发转岗到 ToB 的业务,到八月份时 ToB 业务停止维护,加入到音视频 SDK 开发团队,负责跟 iOS 平台相关的开发维护工作。对自己的学习能力是一个考验,好在团队同事还有 leader 都会在工作上引导我,目前已经逐渐上手。加入到音视频 SDK 开发团队,自己在音视频上有了更多的了解,也开始 C ++ 的学习,技术上有了更多的积累。 今年年中时升了职级,薪资也稍上涨了一些,这也是比较值得开心的好消息。 2022 展望 希望阿 B 能健健康康茁壮成长,家里人都能身体健康。 希望能力上能有更多的长进,技术上有更多的积累,好好复习 iOS 技术栈,说不定能进入更好的公司。 坚持写博客、刷算法、打球。目标是养成读书的习惯。
开发工具 iTerm2 iTerm2 is a terminal emulator for macOS that does amazing things. Tabby Tabby is an infinitely customizable cross-platform terminal app for local shells, serial, SSH and Telnet connections. Fig Fig adds VSCode-style autocomplete to your existing terminal. 终端自动补全工具,能在终端里有 VSCode 的自动补全体验,支持 iTerm2。如果你使用的是 zsh,也可以安装 zsh-autosuggestions 作为补充使用。 Homebrew The Missing Package Manager for macOS. Oh My Zsh Oh My Zsh is an open source, community-driven framework for managing your ### zsh configuration....
在「iOS 逆向入门 - 绕过抖音反调试」中提到常用反调试手段,这里写下具体实现。 一、常用反逆向手段 1、反调试:ptrace ptrace 被常用于防止 lldb 依附,原理是一个进程只能被 ptrace 只能被一次,先于别人调用 ptrace 则可以防止别人依附。 ptrace 有几种方式进行调用: 1)直接调用 #import <sys/ptrace.h> ptrace(PT_DENY_ATTACH,0,0,0); iOS SDK 中不包含 ptrace.h 头文件,无法使用此方法调用,可使用以下方法。 2)通过 dlopen + dlsym 调用 #import <dlfcn.h> #import <sys/types.h> typedef int (*ptrace_ptr_t)(int _request, pid_t _pid, caddr_t _addr, int _data); #if !defined(PT_DENY_ATTACH) #define PT_DENY_ATTACH 31 #endif void disable_attach() { void* handle = dlopen(0, RTLD_GLOBAL | RTLD_NOW); ptrace_ptr_t ptrace_ptr = dlsym(handle, "ptrace"); ptrace_ptr(PT_DENY_ATTACH, 0, 0, 0); dlclose(handle); } 3)通过 syscall 调用 #import <sys/syscall....
一、dSYM 文件生成 1、Xcode 自动生成,配置: Xcode -> Build Settings -> Code Generation -> Generate Debug Symbols -> Yes Xcode -> Build Settings -> Build Option -> Debug Information Format -> DWARF with dSYM File 2、手动生成: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/dsymutil /Users/oudushu/Library/Developer/Xcode/DerivedData/YourApp-cqvijavqbptjyhbwewgpdmzbmwzk/Build/Products/Debug-iphonesimulator/YourApp.app/YourApp -o YourApp.dSYM 二、如何找到对应的 dSYM 文件: 从发布的归档包里面找: Xcode -> Window -> Organizer -> 找到打包好的文件(Show in Finder)-> 选中文件(右键显示包内容)-> dSYMs文件夹下就是了 从iTunes Connect里面找 mdfind工具:mdfind “com_apple_xcode_dsym_uuids == E30FC309-DF7B-3C9F-8AC5-7F0F6047D65F” 三、symbolicatecrash 1、查找 find /Applications/Xcode.app -name symbolicatecrash -type f /Applications/Xcode.app/Contents/SharedFrameworks/DVTFoundation.framework/Versions/A/Resources/symbolicatecrash 2、使用 export DEVELOPER_DIR=/Applications/Xcode....
这是一篇流水账,记录老婆怀胎十月到阿B出生的历程。 怀孕 2021年3月,有一天试纸出现两条杠,去到医院再次确认,确实是怀孕了。 把医生的化验单给老爸老妈看,他们也非常开心,老妈说道:明年过年我们家可就热闹了。 老婆说小孩子很小气,过了3个月才跟身边的朋友说这件事。 怀孕期间 多亏了外企的“福利”,老婆大部分时间都是在家办公,这就避免了上下班的麻烦,缺点是独自在家少人交流。 这里感慨一下外企对于孕妇的政策确实要比国内企业人性化,比如产假更多、补贴更多、还能在家办公。 得知怀孕前,老婆已经拿到SHEIN、小鹏等公司的offer,得知怀孕后,把offer都拒了。 冲刺 11月7日,把丈母娘接到广州,有丈母娘照顾老婆,我放心得多。 期间丈母娘煮饭做家务陪老婆散步陪老婆产检,真是辛苦。 计划 基于我老婆的情况,一家人讨论了一个星期,决定了剖腹产。计划阿B跟我老婆同一天生日,这该是多么美好的场景。 于是11月20日去医院让医生开了住院单,21日办理了入院手续,22日经过医生的确认,确定了23日早上七点的剖腹产手术 一切都按照计划去推进。 出生 2021年11月23日星期二,距离阿B的预产期只剩下两天,这天是我老婆的生日。 前一天医生安排了早上七点第一床手术。 3:36 老婆给我打电话,跟我说破羊水了,医生正在给她做检查。心里一惊,难道阿B想提前出生? 4:08 老婆宫口开得比较快,我赶紧起床。 4:16 跟丈母娘一起出发去医院。 5:03 到了医院,老婆已被推进分娩中心。 6:13 老婆已开5指,经医生讨论,决定尝试顺产,取消了手术。 8:55 阿B出生! 9:16 老婆给我打电话阿B顺利出生。我给家人朋友报喜。 阿B顺产出生,真是计划外的惊喜。 新生儿科 阿B出生后在分娩中心观察了两个小时,护士采取了各种措施,阿B体温还未恢复正常水平,医生决定让阿B在新生儿科住院观察几天。 护士推着阿B出来,我见了一面,拍了几张照片,就被送到新生儿科了。 第一次见到阿B,第一次听到听到阿B的声音,简直心都化了。 老婆出院 11月25日下午,去到医院给老婆办理出院手续。 看到老婆的状态挺好,心里不由感慨阿B醒目,真会挑时间出生,晚一个小时发动,可能就按照计划进行剖腹产了。 阿B回家 11月26日下午,医生给我打电话,阿B的各项指标都正常,符合出院的条件了。 11月27日上午,去到医院办理阿B的出院手续。 接到阿B的时候,让老婆去抱他下楼,老婆不会抱,折腾了几分钟。 月嫂说阿B身体素质好,哭声响亮,眼仔碌碌,压根不需要住新生儿科。 阿B美照
一、背景 经过之前对 iOS 逆向的初步了解,想了个实现 TikTok 自动播放下一个视频的小需求实践一下。 二、实现过程 1、使用 class-dump 工具获取类信息 class-dump 工具通过解析 MachO 文件生成类信息,包括 OC 方法、属性、成员变量等。 有几个点需要留意: C 语言函数无法 dump; OC 方法的参数如果是对象类型,则只会显示 id; dump 出来的 OC 方法包含了 .h .m 文件里面的。 2、通过视图堆栈找出对应文件 从视图堆栈里面可以很方便找出播放器相关的文件,从 class-dump 出来的文件中找到相关文件,在文件中找出相关方法。 比如我需要实现自动播放下一个视频的话,分为两个步骤:1.监听播放完一个视频的事件;2.播放下一个视频。 找到“播放下一个视频”的方法: 我从视图堆栈里定位到 AWEFeedTableViewController 类; 从 class-dump 出来的文件中打开 AWEFeedTableViewController.h; 在文件中搜索 NextVideo,很容易可以找到 - (void)scrollToNextVideo; 方法。 类似的方法找出“播放完一个视频的事件”。 3、快速验证 从上一步找到的类还有对应方法是否真的可以实现“播放下一个视频”呢?我们可以在代码中 Hook 对应方法验证,但是这样验证的方法比较低效。 使用 Cycript 可以动态调试 App,这里简单介绍如何通过 Cycript 快速验证: 越狱手机上通过 Cydia 安装 Cycript; 通过 SSH 连接手机; 找到进程:root# ps -e | grep 'TikTok'; 依附到进程:cycript -p 进程号; 打印视图堆栈,输入命令:UIApp....
一、背景 在「iOS 逆向入门 - TikTok 调试」文章中介绍了使用 MonkeyDev 工具对 TikTok 进行调试。使用同样的方法对抖音进行调试的过程中遇到了几个问题,在这里记录一下。 二、动态库注入失败 按照 TikTok 的方式运行后,发现控制台没有打印 insert dylib success 的信息,猜测动态库注入失败了,果然在编译信息的输出中找到相关错误打印: 在 MonkeyDev 的 change.log 中找到信息,尝试恢复使用 optool 工具注入动态库。 下载 optool 的二进制文件并复制到相应位置,然后修改以下代码: # 注释原来的 MONKEYPARSER # "$MONKEYPARSER" install -c load -p "@executable_path/Frameworks/lib""${TARGET_NAME}""Dylib.dylib" -t "${BUILD_APP_PATH}/${APP_BINARY}" # 修改为 optool OPTOOL="${MONKEYDEV_PATH}/bin/optool" "$OPTOOL" install -c load -p "@executable_path/Frameworks/lib""${TARGET_NAME}""Dylib.dylib" -t "${BUILD_APP_PATH}/${APP_BINARY}" 重新编译运行后可发现控制台中出现 insert dylib success 信息,证明动态库已经注入成功。 三、绕过反调试 动态库注入成功后,发现控制台没有了任何输出,且 lldb 已经断开,证明抖音使用了某种反调试手段。 1、反调试常规手段 1)ptrace ptrace 被常用于防止 lldb 依附,原理是一个进程只能被 ptrace 只能被一次,先于别人调用 ptrace 则可以防止别人依附。...
一、简介 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....
一、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....