V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
iOS 开发实用技术导航
NSHipster 中文版
http://nshipster.cn/
cocos2d 开源 2D 游戏引擎
http://www.cocos2d-iphone.org/
CocoaPods
http://cocoapods.org/
Google Analytics for Mobile 统计解决方案
http://code.google.com/mobile/analytics/
WWDC
https://developer.apple.com/wwdc/
Design Guides and Resources
https://developer.apple.com/design/
Transcripts of WWDC sessions
http://asciiwwdc.com
Cocoa with Love
http://cocoawithlove.com/
Cocoa Dev Central
http://cocoadevcentral.com/
NSHipster
http://nshipster.com/
Style Guides
Google Objective-C Style Guide
NYTimes Objective-C Style Guide
Useful Tools and Services
Charles Web Debugging Proxy
Smore
scienhub
V2EX  ›  iDev

逆向解析苹果 bplist 的问题

  •  1
     
  •   scienhub ·
    batchfy · 1 天前 · 2168 次点击

    目的

    解析 bplist 文件

    背景

    本人研究医学图像 AI 的,现在有个需求,就是把医生在 Osirix (一个医生看影像的软件)上圈出来的 ROI ( region of interest ,就是一个闭合的多边形,将目标区域,比如肿瘤,围起来)转出来存成 json/xml 等 readable 的格式。

    由于 Osirix 批量导出的时候导出的是它自己的一个格式,里面存的是一堆 bytes ,类似于这种

    b'bplist00\xd4 后面很长
    

    说白了这东西里面存的就是 ROI 上的每个点的坐标,以及医生标注的 ROI 的名字(比如恶性肿瘤,良性肿瘤)。

    大概问了下 chatGPT ,说这是 bplist 的格式(我的理解大概是 Google protobuf 类似的东西,不过是 apple 的)。

    目前我们尝试了两种方案去解析 Osirix 导出的文件:

    1. 逆向工程。我们尝试了逆向工程,通过标注一些特定坐标的标注,然后观察 Osirix 导出的文件格式,大概写了个解析的代码。问题是这个逆向并不完美,总有些 case 会出现无法解析的问题。这个成功率大概有个 92%。

    2. 直接用 python 的 bplist 解析库。这个错误率更高,成功率大概只有 20%。很多 case 都无法解析。

    然后我今天突然发现 Osirix 居然有个开源版本Horos,并且有 ROI 导出的相关功能。

    如果有了怎么编码 ROI 的源码,按理说就能开发一个完美的工具来逆向了。问题是这个开源项目比较大,难以定位相关代码。我大概用 bplist/roi/NSKeyedArchiver 等关键词搜了下,没找到。

    我的问题

    有没有大哥比较熟悉 bplist 的,或者比较懂 MacOS 开发的,可以指点下如何快速定位源代码里相关代码的?

    第 1 条附言  ·  1 天前
    我创建了个 GitHub repo 把我的 bplist 数据和 python 脚本传上来了: https://github.com/batchfy/parse-osirix-bplist

    无法解析的 bplist 在这儿: https://github.com/batchfy/parse-osirix-bplist/tree/main/bplist/OsiriX_ROI_SR
    26 条回复    2025-03-22 01:51:59 +08:00
    scienhub
        3
    scienhub  
    OP
       1 天前
    @levelworm Thanks for checking the source! I’ll look into the two spots you mentioned, but might be tricky without a proper debug.
    levelworm
        4
    levelworm  
       1 天前
    @scienhub #3
    Sorry I know very little about MacOS programming, and not a good programmer :)
    92% doesn't look bad though, what are the rest of 8%? Just curious.
    levelworm
        5
    levelworm  
       1 天前
    Also, try out this tool: ImHex, a hex editor for reverse engineering. It has a bplist pattern parser:
    https://github.com/WerWolv/ImHex-Patterns/blob/master/patterns/bplist.hexpat
    scienhub
        6
    scienhub  
    OP
       1 天前
    @levelworm
    No clear pattern in the failed cases. All were exported from the same OsiriX version on the same Mac Studio server, and the patients are from the same hospital cohort.
    ETiV
        7
    ETiV  
       1 天前 via iPhone
    macOS 自带一个 PlistBuddy 没在默认的 PATH 下,
    /usr/libexec/PlistBuddy 。可以 dump 成 xml 再进行解析。
    shuax
        8
    shuax  
       1 天前
    你把 python 的 bplist 代码改改就行了吧,那个比较简单的。
    ratazzi
        9
    ratazzi  
       1 天前
    man plutil 可以转成 xml ,也可以从 xml 转回去
    ratazzi
        10
    ratazzi  
       1 天前
    python plistlib 这个是标准库,也支持二进制的
    scienhub
        11
    scienhub  
    OP
       1 天前
    @ETiV @shuax @ratazzi

    python bplist 这个我试过的,很多 case 会报错。

    /usr/libexec/PlistBuddy 这个我没有试过,但是我记得我试过另外一个 macOS 自带的命令行工具,也是无法转出,报错。

    我猜是 Osirix 在存 bplist 的时候做了什么特殊的处理,导致标准库无法读,所以比较想到源代码里看看啥情况。
    elgae
        12
    elgae  
       1 天前
    发个 ROI 文件,我试试看
    MozzieW
        13
    MozzieW  
       1 天前
    按照开发改代码的思路,假设你已经把 Horos 运行起来了,可以找到页面按钮的文案,搜索文案找到对应页面,也就能找到对应的逻辑。
    另外代码里面有个 ROIWindow 里面有 export xml 功能,不知道是不是你要找的
    icyalala
        14
    icyalala  
       1 天前
    直接把文件改名为 plist ,然后就能用 Xcode 直接打开。或者直接下个 plistedit pro 来导出其他格式
    rozbo
        15
    rozbo  
       1 天前
    这种有两个格式 plist ,其实就是 xml
    bplist ,其实就是二进制的 plist ,b 代表 binary
    是一种标准的格式,如果你只是想打开看一下,用 xcode 双击就可以
    如果你想用编程的方式解析, 各个语言基本都有 libplist 可以支持到

    针对你的情况,如果连 xcode 都无法打开,那有可能魔改了部分行为,就要具体去分析目标 app 的实现了。通过 ida 结合 lldb 调试去定位到。
    shuax
        16
    shuax  
       1 天前
    plist 文件发来
    nenseso
        17
    nenseso  
       1 天前
    先确认一下是不是 6270 开头的,如果是应该是标准的 bplist,随便整个 libplist 库可解
    ihwbunny
        18
    ihwbunny  
       1 天前
    @scienhub
    Plist 文件是 macOS 的属性列表 ( Property List ),用于保存系统和应用的配置和数据,被广泛应用于 macOS 系统中。

    macOS 自带的命令行工具有
    * defaults - 主要用来读写系统配置 Plist 文件
    * plutil - 用于转换格式对 Plist 有限的操作
    * PlistBuddy - 与 defaults 差不多, 不过语法上有时更灵活
    Xcode 自带的功能
    第三方的图形界面,PlistEdit pro 虽然是收费的当时可以免费使用。还有它的插件,比如 VS Code 等。
    scienhub
        19
    scienhub  
    OP
       1 天前
    @nenseso 最长公共前缀是 “bplist00\xd4”。
    我把我的数据上传到 GitHub 了: https://github.com/batchfy/parse-osirix-bplist/tree/main/bplist/OsiriX_ROI_SR
    shuax
        21
    shuax  
       1 天前
    @scienhub 你的不能解析的 bplist 末尾都多一个 0 ,然后 python 库 unsupported type: <class 'plistlib.UID'> 你自己补充一下应该就好吧。
    ETiV
        22
    ETiV  
       1 天前
    看了这 4 个文件,要是只需要坐标的话,直接正则匹配就行了:XY 坐标对儿都是 {a.b, m.n} 这样的字面量格式

    strings {文件名} 先转一下,然后从 XNSObject 的下一行开始读,读到含有 NSMutableArray 的行截止

    至于 [医生标注的 ROI 的名字(比如恶性肿瘤,良性肿瘤)] ,不知道是不是个枚举值,没有字面量的表示形式。
    icyalala
        23
    icyalala  
       1 天前   ❤️ 1
    这就是 NSKeyedArchiver 生成的 plist 文件,我逆向了一下 osirix lite ,丢给 copliot 让它写个转 json 的工具:
    https://pastebin.com/JMDB5h0m

    这个 plist 可能会在结尾多一个或者两个 0 ,所以解析的时候要多尝试两次。
    icyalala
        24
    icyalala  
       1 天前
    scienhub
        25
    scienhub  
    OP
       1 天前
    @icyalala 感谢大哥!你这个代码我编译了一下能解析我这边所有的文件!

    太感激了,大哥方便加个联系方式不,我主页有绿色软件联系方式,我这边给大哥发个红包,以示感谢。
    icyalala
        26
    icyalala  
       4 小时 21 分钟前
    @scienhub 不用不用。。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   928 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 34ms · UTC 22:13 · PVG 06:13 · LAX 15:13 · JFK 18:13
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.