前言
整個逆向的過程花了我快十二個小時,其中可能有很多地方有講錯或是描述不完全的,請各位見諒,這是我第一次嘗試逆向,整個過程都參考了很多前輩的教學,希望這篇文章可以幫助到跟我一樣入門的新手 XD
聲明:本文的內容僅做學習用途,不會提供任何破解檔案
這篇文章要破解的軟體是 Things 3,版本為 3.14.2
尋找破解的切入點
打開 Things,可以看到關於授權的部分只有右上角的剩餘試用天數,那我們就從這邊出發吧!
切換 App 語系
我們先把 App 換成英文的,好讓我們等等可以直接在 Hopper 找字串 這部分可以參考 jkg 大大的文章 如何單獨修改某個 iOS / iPadOS / macOS App 預設的語言?
完成啦🎉
那我們等等就從 days left
下手吧!
利用 Hopper 來找到關鍵 Function
從上圖我們可以看到剩餘天數已經變成 days left
,這時我們就可以打開 Hopper 來找出關鍵的驗證授權 Function
定位到特定的 Function
我們打開 Hopper 並且加載 Things 後,因為我們要找字串,所以先點左邊的 str
後輸入 days left
從圖片中我們可以感覺到 %ld days left [DATEFORMATTER]
最可疑,所以我們雙擊它後,再按下鍵盤上的 x
,會跳出下圖的視窗,我們點兩下或是選中後按 Go就可以跳過去了
進入後我們點上面的按鈕,看看能不能從偽代碼中看出驗證的Function
看來很快就找到我們要的東西了 XD
Frida Hook Function
接下來用 Frida 來 Hook 相關的 Function,我們的思路是找到這個驗證授權的 Function 後,將它 return True,是不是就等於有授權呢,接下來我們用 Frida 來實測看看
frida-trace -m "-[* *isProductLicensed*]" "Things"
我們可以看到 Frida 幫我們找到了 Function,並且產生了一隻 isProductLicensed.js
用編輯器打開 isProductLicensed.js
,並將下方的 return 改為 1 後存檔
Frida hook function
接下來就是要 Hook function 啦,我們把剛剛的 js 存檔,再把 Things 重新打開,但這次重開的瞬間,我們要趕快再執行一次 frida-trace
的指令,因為他的驗證是做在剛執行的時候,如果我們錯過了那個時機,就算已經成功 Hook 也會顯示試用
成功啦 🎉🎉🎉
Frida 注入成功了…. 然後呢?
對耶,看起來是破解成功了,但我總不能每次打開,每次都要開一次 frida 吧?
dylib 代碼注入
找了很多文章,看起來可以用 dylib 來做到 Hook Function,那我們就來做一個 dylib 吧!
利用 Xcode 來建立 dylib
點擊 Create a new Xcode project
點下 macOS
分頁,選擇 Library
把該填的填一填後就可以建立專案啦~
接下來我們寫上 Hook 的程式碼
按下左上的三角形來 Build 如果沒問題,那就是注入 dylib 的時候啦!
insert_dylib
接著我們要用的是 insert_dylib ,利用它來注入我們的 Patch
Build 好 insert_dylib 後,我們把剛剛建好的 libThingsPatch.dylib
也移過來
執行 insert_dylib <dylib_path> <binary_path>
這邊要注意一下第二個參數是 Binary的路徑 哦
完成後我們進到 Binary 的所在處,可以看到多了 Things3_patched
,這個就是 insert_dylib 幫我們 Patch 好的檔案,我們把原本的移除,替換成剛剛打包好的檔案
再次執行一次打完 Patch 的 Things
成功啦 🎉🎉🎉
9/2 更新
有天使用 CleanMyMac X 之後,突然 Things 就打不開了
因為找不到問題,所以陷入了思考,後來想到可以打開「系統監視程式」來看 log,我們就來看看能不能找出問題吧
看起來是缺少了什麼東西吧?!
一開始以為是 CleanMyMac X 清掉一些 dependency 導致 dylib 無法正常開啟
將 Build 模式從 debug 改為 Release 後,用 CleanMyMac X 清掃完也還是一樣會掛掉
後來才發現是 CleanMyMac X 把 dylib 砍掉了
赫然發現,insert_dylib 是幫你把要注入的 dylib 路徑寫死在裡面,
然後應用程式啟動的時候從那個路徑去注入 dylib,如果那個路徑沒有東西,那當然沒東西注入啊!
所以我們要改一下寫法,為了避免 dylib 的位置會變動,我們要把 dylib 放在 binary 旁邊,這樣可以跟 App 一起帶著走
接下來是重點!!!
這次將 dylib_path
設定成 @executable_path/libThingPatch.dylib
然後再跑一次 insert_dylib
的流程
~/insert_dylib @executable_path/libThingsPatch.dylib Things3
剩下的就跟之前一樣,把 Things3_patched 換成 Things3
然後就完成啦~
Reference
一行代码走天下,Frida+Hopper v4.5.19 Demo,调试Ummy Video Downloader的注册验证算法