米米的博客

做了一点微小的工作

背景

Enigma 机是二战时德军使用的加密装置。它拥有三个可以转动的转子,一个固定的反射器,插线板,键盘,灯板等组件。插线板能够交换两个字母,转子可以将一个字母映射为另一个字母。这都是通过电路实现的。使用者点击键盘上的按键输入明文字母后,机器中电池产生的电流将通过插线板、三个转子、反射器,然后折返,再次通过三个转子和插线板,将灯板上的密文字母对应的灯泡点亮。每次按下按键时,转子会产生旋转,并且在到达特定位置时会产生进位。因此,每次加密时导通的电路会发生变化,使得 Enigma 机的加密过程难以被破解。Enigma 的实现和软件模拟器可以参考前面的文章自己打造一台恩尼格玛密码机

在二战后期,德军使用的 Enigma 机允许操作者从多个转子中选择 3 个,每个转子有 26 种初始位置,并且插线板上可以交换 10 组字母。这产生了一个巨大的密钥空间,看上去使 Enigma 机坚不可摧。然而,波兰数学家 Rejewski 在 30 年代就发现了 Enigma 机操作流程上存在的弱点,并针对其设计了破解方法。在二战爆发后,相关的技术被共享给了盟军的情报机构,但德军也加强了 Enigma 密码的安全性。英国数学家和计算机科学家 Turing 进一步地设计了已知明文攻击的方法,成功破解了 Enigma 机,为世界反法西斯战争的胜利做出了重要的贡献。笔者复现了 Rejewski 和 Turing 破解 Enigma 机使用的方法,并将在本文中详细介绍。

算法原理

Rejewski 的破解方法

在上世纪三十年代,Enigma 机的操作流程是:每天所有人都会使用相同的日密钥,但日密钥不用于加密信息;在发送一条信息时,操作者需要先随机生成三个字母的信息密钥。操作者会首先使用日密钥,将信息密钥输入两次,产生的 6 个字母的密文作为开头。随后,操作者将机器的转子调整为信息密钥所对应的转子位置,并开始加密信息。信息密钥输入两次的原因是为了避免信息传输中因为干扰出现错误,收信方如果发现通过日密钥解码出的前 6 个字母明文不是重复两次的格式,则可以发现问题。但是,重复是加密的敌人,Rejewski 敏锐地观察到了这一点。第一个字母和第四个字母是同一个明文加密出来的,并且输入第一个字母时,转子的设置都是日密钥,是完全相同的。于是,在某一天中收到的所有由 Enigma 机加密的密文,都会满足类似这样的规则:

  • 如果第 1 个字母为 A,那么第 4 个字母为 E;
  • 如果第 1 个字母为 B,那么第 4 个字母为 L;
  • 如果第 1 个字母为 C,那么第 4 个字母为 C;
ABCDEFGHIJKLMN
ELCONWDIAPKSZH

表:密文的第一个字母和第四个字母的对应表格(部分)

将结果列出,如上表所示。Rejewski 发现,表中的字母存在一些 “链”,例如,上一行的字母 A 对应下一行的字母 E,上一行的字母 E 对应下一行的字母 N,以此类推,最后又回到字母 A。这样就产生了字母链 AENHI。同时,也可以找到其它的字母链:BLSJP,C,DOFWVG,K,MZURTY,Q,X。如果机器的初始状态相同,那么得到的字母链自然也是相同的。更重要的是,Rejewski 发现,插线板的存在只会改变字母链中的字母,但不会影响各个字母链的长度。
例如,在上面的场景中,额外将 A 和 C 之间加入一条接线,那么,原先的 AENHI 链会变为 CENHI,C 链会变为 A 链;但两条链的长度是不变的。因此,字母链的长度特征是插线板作用下的不变量,它只和转子的初始位置有关,由此可以将插线板的作用和转子的初始位置解耦合。波兰的破译团队用了一年的时间进行预计算,得到了所有转子初始位置与字母链的长度的对应关系。此后,在收到新的密文后,破译者可以查表,将字母链的长度与预计算的结果进行比较,得到可能的转子的初始位置。在成功恢复出转子初始位置后,破译者可以对密文进行解密,之后进一步地分析插线板的状态。具体的算法原理如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
输入:前6个密文字母的对应表格 T
输出:解集 Solutions

预计算阶段:
----------------------------------------
# 由波兰 Bomba 机模拟的 Enigma 机
E ← Enigma()

# 存储的数据库,用于之后查表
Database ← Map()

for each S in PossibleSettings:
E.setPosition(S)
C ← FindChainsByEnigma(E)
Database.store(S, C)

破解过程:
----------------------------------------
Solutions ← Set()

for each S in PossibleSettings:
Matched ← true

for i ← 1 to 3:
Chain ← FindChainsInTableRow(T[i], T[i+3])
Expected ← Database.get(S + i)

if Chain ≠ Expected:
# 字母链没有通过检验
Matched ← false

if Matched = true:
# 当前初始状态对应的字母链通过了检验
# 将可能的解加入解集
Solutions.add(S)
阅读全文 »

SDRPlay RSP1 是一款性价比较高的 SDR 接收机,支持频率范围从 1kHz 到 2GHz,适用于无线电接收、频谱分析、信号侦查等应用场景。笔者最近购买了一台进行研究,虽然是国产的改进版本,但主要芯片型号与原版的 RSP1 相同,因此可以使用同款的驱动和软件。然而,许多好用的上位机软件只支持 Windows 系统,在 Mac 上配置一个合适的环境还需要一番功夫。本文将介绍在 Mac 上使用 SDRPlay RSP1 的具体方法。

使用 SDRuno

SDRPlay 官方提供了丰富的软件支持,其中功能最完善的是 SDRuno,可惜只有 Windows 版本,而且由于驱动问题,需要使用虚拟机才能在 Mac 上运行。如果要使用 SDRuno,需要先通过 VMWare Fusion 或者 Parallels Desktop 等软件安装 Windows 系统,然后在 Windows 系统中安装 SDRuno。之后,将 SDRPlay RSP1 设备连接到 Mac 上,并通过 USB 透传到虚拟机中,即可识别到设备。

使用 SDR++

SDR++ 是一款开源的 SDR 软件,支持多种设备,包括 SDRPlay RSP1。它的界面简洁,功能强大,支持多种操作系统,包括 Windows、Linux 和 macOS。在 macOS 上使用 SDR++ 非常方便,只需要从 GitHub 仓库中下载对应的安装包,安装后即可使用。SDR++ 支持多种设备,可以在侧栏中的 Source 下拉菜单中选择。然而,在 macOS 上,默认安装好的 SDR++ 并不能识别到 SDRPlay RSP1。查看文档可以发现,支持 SDRPlay RSP1 需要安装 sdrplay_source 插件,这个插件在 Release 版本中是包含的,但它依赖于 SDRplay API,需要手动进行安装。

SDRplay API 是 SDRPlay 官方提供的一套 API,用于支持 SDRPlay 设备在第三方软件中的使用。它可以从 SDRPlay 官网上下载。下载好后,完成安装,相关资源会存放在 /usr/local/sdrplay//usr/local/lib/ 目录下。然而,此时再次启动 SDR++,发现仍然无法识别到 SDRPlay RSP1。这是因为 SDR++ 写死了加载动态库文件的地址,需要手动拷贝才可以:

1
cp /usr/local/lib/libsdrplay_api.so.3 /Applications/SDR++.app/Contents/Frameworks/

完成之后,再次启动 SDR++,即可在 Source 下拉菜单中看到 SDRPlay RSP1 设备。

SDR++中使用SDRPlay RSP1

需要注意,如果其它应用程序占用了设备,侧栏中会出现 No device available 的提示。此时需要关闭占用设备的应用程序,然后重新插拔设备,再重启 SDR++ 然后重新选择设备。

其它软件

除了重点介绍的 SDRuno 和 SDR++,还有一些其它软件也支持在 Mac 上使用 SDRPlay RSP1,例如 SDRconnectCubicSDR 等。SDRconnect 也是由 SDRPlay 官方提供的,相比 SDRuno 支持更多系统,可以方便的在 macOS 上使用。然而,它的功能相对较弱,缺少一些高级功能,并且界面存在一些 bug,本文撰写时最新的 1.0.4 版本在拖动部分子框体时会出现错位的问题,使用体验一般。CubicSDR 是一个开源软件,支持多种 SDR 设备,但是代码已经很久没有更新了。总的来说,SDR++ 是在 macOS 上使用 SDRPlay RSP1 的最佳选择。如果不介意使用虚拟机的话,SDRuno 也是一个不错的选择。

Proxmark3 是一款 RFID 工具,支持多种协议和频段,常用于 IC、ID 卡的研究、破解、仿制和安全测试等场景。Proxmark3 的硬件包括主控板和天线,主控板上有 ARM 架构的处理器和用于调制解调的 FPGA。软件则包含运行在 ARM 处理器上的固件和运行在计算机的客户端软件,两者需要版本匹配才能工作。在淘宝上有许多商家售卖 Proxmark3,且会附送软件。然而,笔者注意到,原版的 Proxmark3 软件是以 GPL 协议开源的,但卖家提供的软件通常只有二进制形式,而没有包含源代码,存在违反开源协议的嫌疑。为了支持开源事业,笔者直接从闲鱼上以较低的价格购买了 Proxmark3 硬件,并尝试自行刷写固件。

现在社区中较为活跃的 Proxmark3 软件是由 RfidResearchGroup 团队维护的,其仓库地址为 https://github.com/RfidResearchGroup/proxmark3。由于 Chris "Iceman" Herrmann 是主要的开发者,因此这一版本通常被称为 Iceman(冰人)版本。

Iceman 软件支持多种不同的 Proxmark3 硬件,包括 RDV4、Easy 等。在编译使用 Proxmark3 之前,需要先确认 Proxmark3 的硬件版本。如果硬件和软件版本不匹配,可能在烧录固件或者在使用时报错,此时重新编译软件并烧录正确的固件即可解决。不同版本的 Proxmark3 外观可参考下图,截取自 Proxmark3 网站。市面上比较常见的是 Proxmark3 Easy 版本。RDV4 版本功能更加强大,但是价格也更高,售价通常超过 1000 元。

不同的Proxmark3硬件

编译 Iceman 版本的 Proxmark3 软件

Iceman 软件可以在 Linux、Windows、macOS 等系统上编译和运行,本文以 Linux 为例。

首先,将仓库克隆到本地:

1
git clone https://github.com/RfidResearchGroup/proxmark3

然后进入目录,执行编译命令:

1
2
3
cd proxmark3
make clean
make all PLATFORM=PM3GENERIC

make all 默认的配置是编译兼容 RDV4 硬件版本的软件,然而现在市面上常见的 Proxmark3 都并不是这一硬件版本。因此,需要指定 PLATFORM 参数,将编译目标设置为 PM3GENERIC,也就是 Generic Proxmark3 platforms。

编译完成后,待烧录的固件将会生成在 recovery 目录下。client 目录下则会出现 proxmark3 可执行文件,这就是客户端软件,是一个命令行工具。仓库根目录下的 pm3 脚本会执行 proxmark3,本文后续的操作也都是基于这个工具进行的。如果要使用图形界面,需要单独下载额外的 GUI 程序。

阅读全文 »

在 macOS 上的「照片」App 中,通过智能相簿功能可以方便地管理照片。在创建智能相簿时,可以设定一系列规则,根据相机型号、拍摄日期等条件筛选照片,然后将这些照片添加到相册中。当相册中有新照片加入时,符合条件的照片也会自动添加到智能相簿中。

智能相簿

但是,目前智能相簿所支持的条件仍然有一定的局限性。例如,笔者想要筛选出来自 iPhone 6S 的照片,即使设置了相机型号规则,也还有大量的手机截屏没有被包含进来。造成问题的原因是手机截屏照片的 EXIF 中并不包含相机型号信息。如果需要筛选这些截屏,使用分辨率作为判断依据是更好的,可惜智能相簿目前还不支持对分辨率进行筛选。类似这样的需求还有很多,有没有办法通过自动化的方式进行处理呢?答案是肯定的,使用 Applescript 编程即可实现。

Applescript 是 macOS 系统自带的脚本语言,可以用于控制系统内置应用程序,实现自动化操作。对于「照片」App,Applescript 可以用于获取照片信息、创建相册、添加照片等操作。下面是一个简单的例子,用于筛选 iPhone 6S 的截屏照片,并将其添加到一个名为「iPhone 6S Screenshot」的相册中。

运行这段脚本的方法是,打开「脚本编辑器」App,将脚本粘贴到编辑器中,然后点击运行按钮。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
tell application "Photos"
log "Start..."

-- 创建一个新相册,如果相册已存在则使用现有相册
if not (exists album "iPhone 6S Screenshot") then
make new album named "iPhone 6S Screenshot"
end if
set targetAlbum to album "iPhone 6S Screenshot"

-- 定义目标分辨率
set targetWidth to 750
set targetHeight to 1334

-- 初始化图片列表
set imageList to {}

-- 获取所有照片
set allPhotos to every media item

-- 循环检查每张照片的分辨率
repeat with aPhoto in allPhotos
if width of aPhoto is targetWidth and height of aPhoto is targetHeight then
-- 打印照片的信息,例如文件名
log "Matching photo: " & filename of aPhoto & ", Date: " & date of aPhoto
-- 将符合分辨率的照片添加到列表
set end of imageList to aPhoto
end if
end repeat

-- 如果列表不为空,将照片添加到相册
if (count of imageList) > 0 then
-- 打印符合条件的照片数量
log "Number of matching photos: " & (count of imageList)
add imageList to targetAlbum
else
log "No matching photos found."
end if
end tell

如果一切顺利,脚本编辑器的输出窗口中会显示符合条件的照片信息。运行完成后,「照片」App 也会弹出提示,让用户确认操作。

这个例子只是一个简单的示例,实际应用中可以根据需求进行扩展,例如添加更多的筛选条件、自动化处理照片等。现有的大模型也可以帮助编写 Applescript 的代码。不过,在通过 Applescript 自动化操作其它 App 时,错误的代码逻辑可能会导致数据丢失,因此需要仔细检查代码并做好备份。

近期,笔者接到了维修一台屏幕完全碎裂的 iPad 的请求。根据机主描述,这台 iPad 在多年前由于从高处跌落,外屏完全损坏,无法开机,因此长期没有使用。但是里面有一些重要的照片,希望能够取出来。

经过检查,这台 iPad 型号为 iPad Mini 1(A1432 版本)。机器状况确实非常不理想,不仅屏幕碎裂,后壳也有明显的变形。只能祈祷主板没有受损,不然就超出笔者的维修能力了。

变形的机身和内屏,外屏由于完全碎裂爆出了很多玻璃渣,已经丢弃

这一代 iPad 的外屏是通过胶水粘合的,正常的拆卸方法是加热后将屏幕揭开,但由于外屏已经完全脱落,这一步骤甚至可以省略。进一步拆卸可以参考 iFixit 发布的指南,并不麻烦,主要就是拧螺丝和拆排线,谨慎操作即可,避免损坏一些脆弱的部件。经过拆卸,这台机器的主板外观还比较完好,变形也比较轻微,看上去还能抢救一下。但是,除了主板外,其它很多硬件都存在不同程度的受损。

拆卸出的主板很完整,但电池已经变形了

相比于单独购买屏幕、电池等配件进行替换,更方便的方法是直接买一台好的 iPad,来一手借尸还魂,把坏机器的主板挪过去。在闲鱼上,同款的 iPad Mini 1 已经是白菜价格,外观成色完美的也就大几十块钱,因此这个方案是经济可行的。

硬件维修的部分还算顺利,经过拆机和更换硬件,这台 iPad Mini 1 终于能够正常开机了。

拆机过程

点亮设备

接下来才是真正有趣的部分:这台 iPad 设置了锁屏密码,但是由于多年没有开机,机主已经忘记了密码。如果要将其中的数据备份出来,就得想办法访问到 iPad 的文件系统了。如果设备在越狱后开启了 SSH 服务,我们可以通过 libimobiledevice 提供的 usbmuxd 转发端口,使用 SSH 连接来访问文件系统。但遗憾的是,经过简单的实验,这台 iPad 似乎并没有越狱,SSH 服务也没有启动,这条路行不通。

由于 iPad Mini 1 是非常古早的设备,想必是有很多现成的 n-day 漏洞可以利用。其中,最著名的就是 2019 年由 iOS 安全研究员 axi0mX 披露的 checkm8 漏洞(这个缩写类似 DotA2 中的 str8,8=eight 是读音的缩写,原意即为 checkmate)。checkm8 漏洞存在于 iOS 设备的 ROM 中,通过 USB 发送恶意的 Payload,可以实现任意代码执行,绕过设备的安全启动限制。这个漏洞影响了搭载 A5 到 A11 芯片的苹果设备,并且苹果无法通过软件更新来修复这个漏洞,非常适合我们的场景。不过,由于 checkm8 漏洞利用需要通过 USB 进行,目前针对 A5 芯片最成熟的方案是使用 Arduino USB Host Shield,这需要我们准备特殊的硬件。

阅读全文 »
0%