Re: [請益] 要如何繞過Keypro的驗證?
※ 引述《iman00b (I'm a n00b)》之銘言:
: 標題: Re: [請益] 要如何繞過Keypro的驗證?
: 於是後來又出現了 keypro 這種保護方式,這東西一開始不太好搞,
: 因為你在 debug 裡讀出來的數據,會跟實際上讀出來的數據有落差,
: 也因此才有人想出用模擬的方式,直接把軟體想要的數據給它。
: (我記得是軟蛀第一個這樣弄的)
....
: : 基本步驟
: : 1.利用SOFT-ICE找出負責驗證的程式片段 (已經編譯過的二位元程式)
: : 2.利用反組譯/編輯工具修改驗證程式片段(用組合語言改)、讓驗證無條件通過
: : 3.利用工具存檔、或是把修改好的程式貼到二位元檔案中
: : 剩下的know-how可以上網爬文、或是買書之類的,
.....
好奇請教.用DEBUG讀出來的數據會不太一樣?debug通常只看 register跟memory,
除非選址線或資料線可被程式先更動, 不然如何讀出不同?
: → iman00b:我是說進 debug 後從 keypro 讀進來的資料會不同. 03/04 04:19
: → iman00b:我跟軟蛀跟一些同好有數面之緣,我們私下會交流一些東西。 03/04 04:20
DDT 或 debug 使用int3 取回控制權, 除非keypro的查驗程式也同樣用到 int3
能察覺執行了 debug , 在控制權回到 debug 時, 預先更改了 keypro 的狀態,
否則除了時間 或 共用i/o 相互干擾外, debug是寫成獨立無關的, 可否說明
keypro程式 在有debug執行或不執行的情況下, 如何讓 cpu 讀出的值不同?
推
03/05 15:54, , 1F
03/05 15:54, 1F
推
03/05 16:02, , 2F
03/05 16:02, 2F
→
03/05 16:42, , 3F
03/05 16:42, 3F
→
03/05 16:42, , 4F
03/05 16:42, 4F
→
03/05 16:43, , 5F
03/05 16:43, 5F
→
03/05 16:44, , 6F
03/05 16:44, 6F
推
03/05 17:34, , 7F
03/05 17:34, 7F
→
03/05 17:58, , 8F
03/05 17:58, 8F
有道是: 世界上沒有攻不破的城牆!
keypro 除了共用 int3 偵測使用者使用了 debug break-point 之外, 還有那招
能讓 cpu 讀出的值不同?
在 vm86 mode 下, 其 memory space 是在 virtual memory 386 的 mapper
控制下, 會跟實體(real mode)的記憶體空間位址不同, 尤其是 0-400h 的
int vector table 部份. 但用 real mode 來跑 os 與 debug ap 就行了.
這跟如何啟動 debug 與 keypro ap 有關, 但跟 debug 跑或不跑是無關的.
X86 從一開始設計就有 pipleline pre fetch 設計, 此設計是會影響到 bus
snooping 設計的 comparator 用硬體造成的 interrupt 得到中斷點. 但不影
響使用軟體方法以 int 3 替代指令 強制產生斷點的方法, debug 返回被中斷
點程式接下去執行時, 一定是重新換位址重做, 會使 prefetch 重新再做. 所
以 pre fetch 不影響 debug 的執行結果.
→
03/05 19:27, , 9F
03/05 19:27, 9F
不用懷疑. debug int3 single step trace 跟 set breakpoint 是同樣方法.
→
03/05 19:35, , 10F
03/05 19:35, 10F
→
03/05 19:35, , 11F
03/05 19:35, 11F
→
03/05 19:36, , 12F
03/05 19:36, 12F
keypro 曾經被攻破是不用爭辯的. 至於用甚麼方法? 當然是會有各種方法!
DEBUG 是個程式, 要讓軟體程式每次執行時, 到某 memory 或 i/o port 所拿
到的資訊不同, 但其他某個程式(如 keypro)執行時, 到同一個 memory 或 i/o
port 都能取得不同且是特定的值, 如果兩者不共用某段程式, 也沒有相互干擾
之處, 那 不管是軟體或硬體 這就是偉大的發明了.
無論如何, 這種發明 還是得好好請教阿!
用 debug 去讀, 當然是有方法使之讀出不同值, 實況可能也是如此, 但這是有
共用到 int3 入口程式去干擾才有可能, 避開此招的方法也就很明顯.
除此之外, 還有甚麼方法?
偵測執行速度是可以知道執行次序被打斷, 這是 debug 不會去暫存 time 後再
顯示斷點的缺陷, 但 keypro 若這樣寫會受限於 cpu 與 RAM 種類速度, 是自尋
麻煩.
→
03/05 20:15, , 13F
03/05 20:15, 13F
你只要弄來一段程式讓 debug 在 x86 (必有prefetch功能)下跑出不同結果就行了,
如果要用 swap 指令, 標準正確用法是要用 lock prefix. 但這是在兩個程式共用
同一變數下才會使 swap 指令出錯, 這錯在 multi-bus processor 8080 cpu 就有.
debug 只會監測 keypro 程式如何執行, 不會去跟 keypro 共用與更改其變數.
→
03/05 20:19, , 14F
03/05 20:19, 14F
→
03/05 20:20, , 15F
03/05 20:20, 15F
→
03/05 20:20, , 16F
03/05 20:20, 16F
anti-debug 是有 debug 時代就同時存在的技術. 這跟底下的問題答案全然無關:
1. x86 pre fetch architecture 不會影響到 software 的 debug 執行.
2. 不相互干擾的軟體不會影響到另一個軟體的執行結果. debug 跟 os 在
提供消除相互干擾的原則上是相同的.
→
03/05 21:52, , 17F
03/05 21:52, 17F
→
03/05 21:53, , 18F
03/05 21:53, 18F
推
03/05 23:54, , 19F
03/05 23:54, 19F
→
03/05 23:58, , 20F
03/05 23:58, 20F
→
03/06 00:00, , 21F
03/06 00:00, 21F
→
03/06 00:02, , 22F
03/06 00:02, 22F
→
03/06 00:02, , 23F
03/06 00:02, 23F
→
03/06 00:21, , 24F
03/06 00:21, 24F
→
03/06 00:22, , 25F
03/06 00:22, 25F
→
03/06 00:22, , 26F
03/06 00:22, 26F
→
03/06 00:23, , 27F
03/06 00:23, 27F
p大, 這豈不有講跟沒講一樣?
L大, 用 debug 來 trace 或 追查 keypro 執行程式, 不必去自行 copy 執行檔才來
執行吧? debug 可以自行 load exe/com file, 設好各段 segment 及開始點.
single step 不能對 OS system call 進一步 trace 是因為執行次序被使用類似
self-modified code 的手法把下一個執行點給覆蓋掉或強制設定. 這是此 keypro
或 os 干擾 debug 的替換動作所致, 也就是被監測程式與 debug 相互干擾. 使
debug 不能自動替被監測執行的程式在下一個指令位址替換為 int3 指令, 以致
於不能達到自動 single step trace 目的. 但不容易 trace, 不是代表讀出的
memory 或 i/o port 會隨不同程式而有不同變動. 她只是不讓你爽快的用 single
step 自動 trace 到底. single step auto-trace 要依賴 inverse assembler 推
斷下一個指令碼的位址. 完整的 inverse assembler 與正確開頭點是其 trace 要
件.
推
03/06 00:33, , 28F
03/06 00:33, 28F
→
03/06 00:35, , 29F
03/06 00:35, 29F
→
03/06 00:35, , 30F
03/06 00:35, 30F
推
03/06 00:41, , 31F
03/06 00:41, 31F
→
03/06 08:34, , 32F
03/06 08:34, 32F
→
03/06 08:35, , 33F
03/06 08:35, 33F
→
03/06 08:35, , 34F
03/06 08:35, 34F
→
03/06 08:36, , 35F
03/06 08:36, 35F
這種回應不太就事論事. 說不出何以 debug 程式跟其他程式讀出同一個 memory 與 i/o
port 何以會有不同? debug 是監測待查的程式, 仍然是待查程式去執行, debug 用替
換法強制待查程式 int3 trap 中斷, 再觀察其執行的結果, 這裡面當 software trap
發生時, 除非待測程式也共用int3 入口插入片段程式, 否則被 debug 暫存的 register
或其他非 debug 使用的記憶體內容 沒有受到影響的機會.
中斷發生時頂多影響 stack 頂端的幾個位置受到覆蓋, 如果用那幾個位置傳送資料才有
被 debug 插入int3 中斷造成危害, 但一般的其他中斷事件(如 timer)發生時也會有同
樣狀況, 如果是這樣傳資料就會有與之相對應的特殊寫法, 她必須讓其他中斷不會干擾
到傳送資料在被取走之前發生. 也就是某區段的執行是無法被中斷的, 這種片斷有特殊
的 pattern.
推
03/06 11:48, , 36F
03/06 11:48, 36F
→
03/06 11:50, , 37F
03/06 11:50, 37F
推
03/06 11:55, , 38F
03/06 11:55, 38F
這個 cpu 是照規範設計的, 她有一定的規則遵行, pre fetch 也是種 cache, cache
也是做在 processor chip 上, 她遵行 write thru 規則.
Example:
CS:0100 B97502 MOV CX,0275
CS:0103 BE9001 MOV SI,0190
CS:0106 89F7 MOV DI,SI
CS:0108 AC LODSB
----------------------------------------------
CS:0109 C7060F012406 MOV Word Ptr [010F],0624
CS:010F 3473 XOR AL,73
----------------------------------------------
這個程式的徵結根本就在 本身是個 self-modified code 的程式,
xor al,73 不會被執行而是代以 and al,06 這個指令
不管是 single step multiple trace 或是只設斷點在 011a , 快跑完loop,
搬移的資料區事先全設ff, 事後都是同樣結果 06 .
CS:0111 AA STOSB
CS:0112 C7060F012406 MOV Word Ptr [010F],0624
-----------------------------------------7334--使之還原原指令,便於各種跑法.
CS:0118 E2EE LOOP 0108
Watch this:
CS:010F 2406 AND AL,06
===========================
很不幸, 在 vm86 mode 下執行 debug , 都沒有因 prefetch 而不發生 無法code
self modified 的效果. 我的老爺 cpu 是 P4 2.4GHz.
→
03/06 15:55, , 39F
03/06 15:55, 39F
single step 跟 loop 外才break 其結果都相同. 下一個指令照改不誤, 這是真正結果.
→
03/06 17:55, , 40F
03/06 17:55, 40F
L大 不是強調要動手 step trace 嗎? 怎不做做看? 這 prefetch 顯然是做成 cache
可不是 local memory. invalid/dirty byte 又不是無法被檢測出來!
→
03/06 18:32, , 41F
03/06 18:32, 41F
→
03/06 18:32, , 42F
03/06 18:32, 42F
→
03/06 18:32, , 43F
03/06 18:32, 43F
盡信書不如無書. 某人用 DDT/DEBUG 時, L大 可能還沒出世, 但這不是求問的重點.
可確定目前的 X86 cpu(P4), prefetch 不會影響 self modified code 的
single step trace 或 快速 loop 執行. 如果在 code 被修改處預先設斷點
不管 single step 或 快速執行 還是會讓指令覆蓋發生. 但 single step
trace 則照樣在指令覆蓋後, 仍然能 single step trace, 而不是無法 trace.
80386 之後的 cpu 是有硬體支援的 single step trap INT 1
還多了一個 single byte single step exception 指令碼 F1.
debug 要做 sigle step 可以不用只靠軟體做事先的指令替代.
→
03/06 21:02, , 44F
03/06 21:02, 44F
→
03/06 21:02, , 45F
03/06 21:02, 45F
→
03/06 21:03, , 46F
03/06 21:03, 46F
z80 的前身 8085/8080/8008 , 6502 KIM-1 還可以比嗎? 還麵包板咧?
英雄出少年, 比這就變成賣老啦. 不要老是說別人不懂沒用過, 就事論事比較平等.
PC/AT 之後, DOS prompt 之下的 debug 從來就不是完整的, 她沒有 286/386 的
inverse assembler, 除了 VM86 mode 下提供相容性使用外, 一直就是個 VM 下
的配合程式, 並不是個全功能 kernel debugger.
→
03/06 22:32, , 47F
03/06 22:32, 47F
→
03/06 22:32, , 48F
03/06 22:32, 48F
→
03/06 22:33, , 49F
03/06 22:33, 49F
→
03/06 22:34, , 50F
03/06 22:34, 50F
→
03/06 22:34, , 51F
03/06 22:34, 51F
只是告訴你 prefetch 那個例子在 x86/P4 沒那 link 所說的作用, 跟宣稱的不同 !
自 386 之後就有 single step exception 硬體支援.
Z80 是 intel 8085 的指令相容品在 intel 8080 之後才做的.
→
03/07 01:08, , 52F
03/07 01:08, 52F
→
03/07 01:10, , 53F
03/07 01:10, 53F
8085, z80 指令碼全相同, 只有2個指令碼 z80 多出來.
→
03/07 13:41, , 54F
03/07 13:41, 54F
Zilog 的創辦人之一原來是 intel 的工程師, 參與 8080 cpu 的設計.
8080 合併三晶片的8008 為單片, 增了指令, 但使用 +5 -5 +12V 三電源, 8085/Z80
用不同 CMOS 技術與製程, 使用單電源.
當年, Intel 還不准 Zilog 用他的指命碼易記名, 所以一個用 MOV, zilog 只好用 LD.
實況是 1974 8080上市時, 8085, Z80 都已經做出來(指令都大致相同), 但 Intel
有老式三電源 DRAM 的包袱, 當時還沒下定決心專做 CPU.
不會有人說 intel 抄 zilog. 為了區別, 除指令多兩個, 接腳方式不同,
Z80 還會在execution cycle 做DRAM refresh. clock rate 也可較快.
→
03/07 16:11, , 55F
03/07 16:11, 55F
→
03/07 16:11, , 56F
03/07 16:11, 56F
那是聽來的故事. 那款 8bit processor 好像都是同批人做的, 指令集都幾乎相同.
試用的先期試製品常常很早就做出來給客戶先試用.
→
03/08 08:31, , 57F
03/08 08:31, 57F
→
03/08 08:31, , 58F
03/08 08:31, 58F
→
03/08 08:33, , 59F
03/08 08:33, 59F
→
03/08 08:35, , 60F
03/08 08:35, 60F
→
03/08 08:36, , 61F
03/08 08:36, 61F
→
03/08 08:36, , 62F
03/08 08:36, 62F
→
03/08 08:37, , 63F
03/08 08:37, 63F
→
03/08 08:38, , 64F
03/08 08:38, 64F
"後來又出現了 keypro 這種保護方式,這東西一開始不太好搞,
因為你在 debug 裡讀出來的數據,會跟實際上讀出來的數據有落差."
======================================================================
這只是一個很簡單的疑問:
像 Autocad 這種程式最早就有裝在 Line Printer port 的 keypro.
Autocad 是個軟體程式會到那個 keypro 去查驗是否他家的 key.
不管是否自己寫個程式還是用 debug 去讀那個 keypro, 都是跟 autocad 同樣的
讀或寫, 理論上跟 autocad 應該沒兩樣.
唯一的麻煩是: 除了 autocad 才知道正確的讀寫次序.
所以, debug 就會被拿來監測 autocad 的讀寫次序與結果.
做 keypro 的當然會用 anti-debug 這類手段來迷惑或防止追蹤.
但干擾 debug 的也就那幾招. self-modified code 是最常用的防追縱老招.
像 autocad 使用 keypro 與 DOS 的時代, 那個 CPU 硬體並沒有像現在的
新處理機 已經能支援硬體虛擬化的完整設計, 才可能發生某個指令(如 I/O
或 disable interrupt)做了卻沒有預想的結果. 但 386 之後是有 VM86 這
個虛擬機, 但這需要 os kernel 的支援, 做keypro的也不會想洩密給 MS.
Autocad keypro 顯然有被破解過, 所以不可能是用 VM86 的 kernel 程式
來判別是否有自家的 keypro. 因為如果是這種方法, user mode 的程式才
會發生讀不到或讀出不一樣, 但 DOS 時代並沒有使用這方法. 如果是 kernel
內部程式, 那只有可能寫在 driver routine 內部, 在 window 時代, user
mode 的 debug 是不能進入這模式的. 這是用錯道具的問題.
這根本不是很行或不行的問題, 而是對電腦行為的認識與疑問的問題.
※ 編輯: ggg12345 來自: 140.115.4.90 (03/08 12:14)
討論串 (同標題文章)
完整討論串 (本文為第 4 之 6 篇):