Advanced PDF Password Recovery Pro 2.12的不完美破解 (12千字)

看雪資料發表於2003-05-20

Advanced PDF Password Recovery Pro 2.12的不完美破解

當時破解這個東西完全是出於自己的需要,為了把一篇只讀的PDF文件另存為RTF文件進行編輯,
這篇破文感覺很不好寫,我怎麼安排都覺得亂糟糟,來回修改了幾次,我只能做到這個效果了,
有些地方純屬猜測,有興趣的慢慢看吧,看得頭暈了我不負責,我寫得自己都頭暈了。
*************************************************************************************
target    : Advanced PDF Password Recovery Pro 2.12
homepage  : http://www.elcomsoft.com/apdfpr.html
exefile  : apdfprp.exe 267,264 bytes
Protecter : ASProtect v1.2?

Unregistered version limitations:(引用官方原文)
?1.with a brute-force attack, passwords longer than 4 characters cannot be recovered
?2.some dictionary attack options are disabled
?3.the program decrypts only first 10% pages (but at least one page) of the documents, and replaces all other pages with blank (empty) ones

第一步當然要脫殼了,我用的是AsprStripperXP_v123
脫完後不能執行,原因是OEP不正確,如何恢復OEP,就本例而言,我採用的是比較簡單的方法:
先檢視一下脫殼後的檔案可以發現它是用Watcom32 C/C++編譯的,
用16進位制編輯器QIVEW開啟,搜尋'WATCOM',只找到一處在RVA=41B41Dh
然後稍往前看幾個位元組RVA=41B414h處是:
0041B414:E9 57 0C 00 00 =======> JMP 41C070
0041B419:?? ?? ?? ??
0041B41D:'WATCOM C/C++32'
我斷定這裡就是OEP=41B414,把脫殼後的檔案的OEP恢復後果然可以執行了
不知用Watcom32 C/C++編譯的可執行檔案是否都是這樣的,有待考證

================================================================================
下面是註冊驗證子過程,程式中多次呼叫這個子程式進行檢驗:
00409747                enter  40h, 0
0040974B                lea    eax, [ebp+var_40]
0040974E                call    sub_409687        ;讀取註冊碼
00409753                lea    eax, [ebp+var_40]
00409756                call    sub_4095C6        ;註冊碼驗證演算法
0040975B                leave
0040975C                retn
================================================================================
註冊碼驗證演算法:
004095C6 sub_4095C6      proc near
004095C6 var_6C          = byte ptr -6Ch
004095C6 var_10          = byte ptr -10h
004095C6                push    ebx
004095C7                push    ecx
004095C8                push    edx
004095C9                push    esi
004095CA                push    edi
004095CB                enter  6Ch, 0
004095CF                mov    esi, eax            ;註冊碼指標
004095D1                call    sub_41B260        ;取長度LEN
004095D6                mov    ecx, eax
004095D8                cmp    eax, 6            ;LEN>=6?
004095DB                jge    short loc_4095E4
004095DD loc_4095DD:    xor    eax, eax            ;註冊碼錯誤
004095DF                jmp    locret_409680
004095E4 loc_4095E4:    mov    ebx, 2
004095E9                cdq
004095EA                idiv    ebx
004095EC                test    edx, edx            ;註冊碼長度是偶數位嗎?
004095EE                jnz    short loc_4095DD
004095F0                mov    eax, ecx
004095F2                cdq
004095F3                idiv    ebx
004095F5                lea    ebx, [eax-2]        ;LEN/2-2
004095F8                lea    eax, [ebp+var_6C]
004095FB                call    sub_40F9BC        ;初始化四個32位連結變數
00409600                lea    edi, [esi+4]        ;從註冊碼的第5位開始
00409603                mov    edx, edi
00409605                lea    eax, [ebp+var_6C]
00409608                call    sub_40FA0D        ;填充,使訊息長度恰好是512位的整數倍
0040960D                lea    edx, [ebp+var_6C]    ;
00409610                lea    eax, [ebp+var_10]    ;
00409613                call    sub_40FE18        ;MD5演算法的主迴圈,從第5位開始,長度為LEN/2-2
00409618                mov    ebx, 10h
0040961D                mov    edx, offset unk_44FD00    ;16位元組常數
00409622                lea    eax, [ebp+var_10]    ;
00409625                call    sub_41B4E0        ;比較相等?
0040962A                test    eax, eax
0040962C                jnz    short loc_4095DD
0040962E                lea    eax, [ebp+var_6C]
00409631                call    sub_40F9BC        ;初始化四個32位連結變數
00409636                mov    ebx, ecx            ;LEN
00409638                mov    edx, esi            ;從註冊碼第1位開始
0040963A                lea    eax, [ebp+var_6C]
0040963D                call    sub_40FA0D        ;填充,使訊息長度恰好是512位的整數倍
00409642                lea    edx, [ebp+var_6C]    ;
00409645                lea    eax, [ebp+var_10]    ;
00409648                call    sub_40FE18        ;MD5演算法的主迴圈,對整個註冊碼運算
0040964D                lea    eax, [ebp+var_10]    ;
00409650                call    sub_409575        ;檢查註冊會員列表,你是否是其中的一位會員?
00409655                test    eax, eax            ;如果你是已註冊會員,返回EAX!=0
00409657                jz      short locret_409680
00409659                cmp    ds:dword_45A8F0, 0    ;是此次執行後第一次透過驗證嗎
00409660                jnz    short loc_40967B
00409662                push    10h            ;是第一次透過驗證
00409664                push    edi
00409665                call    ds:off_44FD18        ;重新整理登錄檔
0040966B                call    ds:off_44FD10        ;注意這行,有後話!!!
00409671                mov    ds:dword_45A8F0, 1    ;置已驗證過標誌
0040967B loc_40967B:    mov    eax, 1            ;是註冊使用者
00409680 locret_409680:  leave
00409681                pop    edi
00409682                pop    esi
00409683                pop    edx
00409684                pop    ecx
00409685                pop    ebx
00409686                retn
00409686 sub_4095C6      endp
================================================================================

整個註冊演算法很明瞭,合法的註冊碼只需滿足下述3個條件:
1.註冊碼長度LEN為不小於6的偶數
2.從註冊碼的第5位開始,取(LEN-4)/2位進行MD5運算,結果為16位元組固定數
3.對整個註冊碼進行MD5運算,結果在已註冊名單列表中

對於MD5從演算法上我們就別花心思逆運算了,如果你想逆算它沒人反對,成功了你可就大名鼎鼎了
我是懶人一個,我也不想出名,因此我選擇爆破。
哦,這麼簡單,隨便怎麼改吧,保證每次呼叫驗證過程返回EAX=1就行了唄,我為了搞的象模象樣的,
先下2個斷點,BPX 0040961D,BPX 0040964D,輸入一個合法長度的註冊碼,跟蹤進去,記錄下
我輸入的註冊碼對應的2個MD5結果,然後把這兩個結果PATCH進檔案裡,我剛輸入的註冊碼不就是合
法註冊碼了嗎?

可惜高興的太早了,這樣改完後限制依然存在。
奇怪了,註冊碼是整個串取MD5運算才比較的,感覺不應該漏掉哪位在其它地方設有暗樁的,
重新把反彙編結果中所有對註冊驗證子過程的參考呼叫處仔細檢視一下,發現下面2個可疑位置:

====下面程式碼與直接解密恢復%10頁碼限制有關==============================================
0040AA63  > E8 DFECFFFF    CALL _APDFPRP.00409747        ;註冊驗證子過程,成功則返回EAX=1
0040AA68  . 85C0          TEST EAX,EAX
0040AA6A  . 74 3D          JE SHORT _APDFPRP.0040AAA9
0040AA6C  . E9 33000000    JMP _APDFPRP.0040AAA4        ;可疑跳轉
0040AA71    7C 16 8F 1E A9 2B 82 8D                ;可疑資料
0040AA79    CF FA 48 8F 8B 98 05 FA
0040AA81    75 7E E2 6A A0 0F 53 32
0040AA89    BC DE 0F 83 94 5C 37 56
0040AA91    33 48 D5 27 73 74 A3 56
0040AA99    7B 36 F0 BF CF 26 70 3B
0040AAA1    6D B2 AD
0040AAA4  > E9 78000000    JMP _APDFPRP.0040AB21
0040AAA9  > 833D 90AC4500 >CMP DWORD PTR DS:[45AC90],0
0040AAB0  . 74 0E          JE SHORT _APDFPRP.0040AAC0

====下面程式碼與暴力攻擊密碼長度限制有關======================================================
00411F05  . E8 3D78FFFF    CALL _APDFPRP.00409747        ;註冊驗證子過程,成功則返回EAX=1
00411F0A  . 85C0          TEST EAX,EAX
00411F0C  . 75 28          JNZ SHORT _APDFPRP.00411F36
00411F0E  . 833D 34B24500 >CMP DWORD PTR DS:[45B234],4        ;最大密碼長度
00411F15  . 7E 0A          JLE SHORT _APDFPRP.00411F21
00411F17  . C705 34B24500 >MOV DWORD PTR DS:[45B234],4
00411F21  > 833D 30B24500 >CMP DWORD PTR DS:[45B230],4        ;最小密碼長度
00411F28  . 7E 22          JLE SHORT _APDFPRP.00411F4C
00411F2A  . C705 30B24500 >MOV DWORD PTR DS:[45B230],4
00411F34  . EB 16          JMP SHORT _APDFPRP.00411F4C
00411F36  > E9 11000000    JMP _APDFPRP.00411F4C        ;可疑跳轉
00411F3B    A4 52 B7 56 BF 2B 82 0D                ;可疑資料
00411F43    BB F0 C3 29 73 5D 81 E1
00411F4B    6A
00411F4C  > A1 30B24500    MOV EAX,DWORD PTR DS:[45B230]    
00411F51  . 3B05 34B24500  CMP EAX,DWORD PTR DS:[45B234]
00411F57  . 7E 04          JLE SHORT _APDFPRP.00411F5D
00411F59  > 31C0          XOR EAX,EAX
00411F5B  . EB 12          JMP SHORT _APDFPRP.00411F6F
00411F5D  > 85C0          TEST EAX,EAX
00411F5F  .^74 F8          JE SHORT _APDFPRP.00411F59
00411F61  . 833D 34B24500 >CMP DWORD PTR DS:[45B234],0
00411F68  .^74 EF          JE SHORT _APDFPRP.00411F59
00411F6A  . B8 01000000    MOV EAX,1
00411F6F  > 5F            POP EDI
00411F70  . 5E            POP ESI
00411F71  . 5A            POP EDX
00411F72  . 59            POP ECX
00411F73  . 5B            POP EBX
00411F74  . C3            RETN
================================================================================

可以看出上面2處在註冊驗證呼叫後都有一個可疑的跳轉和一段可疑的資料,我不信編譯器正常會編譯出這樣的程式碼,
這些地方應該是被加密處理過的,可是怎麼也找不到相應的解密過程。
忽然覺察到自己一直跟蹤的是脫殼後的程式,如果解碼是做在ASProtect殼裡的,當然找不到了
重新對未脫殼的程式進行跟蹤,還記得註冊碼驗證演算法中的下面這行嗎:
.text:0040966B                call    ds:off_44FD10        ;注意這行,有後話!!!
後話終於來了,跟蹤脫殼後的程式時這行呼叫過程直接RET返回,什麼也沒做
而跟蹤原來的沒脫殼的程式時這個呼叫程式碼是指向ASProtect殼裡分配的地址空間的,有一段比較複雜的解密程式碼,
每次程式啟動後第一次驗證透過會執行一次這段程式碼,對前面2處可疑跳轉及資料解密,(實際跟蹤發現,需解密的
程式碼還不止這2處,其它幾處我還不清楚有什麼用,因此就沒有把他們都貼出來)我猜測這些資料解密後就成
一段SMC程式碼,用來解除各自的限制。而解密的金鑰是由註冊碼算來的,在沒有正確註冊碼的情況下,想恢復這些代
碼的難度不可想象,我對ASProtect殼的研究不多,可能這就是所謂的帶KEY的ASProtect保護。

感覺自己象是走上了絕路,要不是自己需要用這個軟體,真是要放棄了,再試試看吧,既然它能恢復%10,說明解碼
功能都在程式裡面,解除限制應該是能實現的,後面的過程就比較苦惱了,沒有什麼特別的技巧的,慢慢跟蹤,瞪大
眼睛,找那%10限制的相關可疑點,印象中好象還碰到一個遞迴,幾經周折終於眼前一亮,來到這裡了:
================================================================================
0040D148  |. 8B45 10        MOV EAX,DWORD PTR SS:[EBP+10]    ;PDF文件總頁碼
0040D14B  |. 83C0 09        ADD EAX,9
0040D14E  |. BB 0A000000    MOV EBX,0A                ;10進位制的10呀,等你多時了
0040D153  |. 99            CDQ                    ;
0040D154  |. F7FB          IDIV EBX                ;PDF文件總頁碼的%10
0040D156  |. 3B01          CMP EAX,DWORD PTR DS:[ECX]        ;已經恢復的頁數
0040D158  |. 7E 04          JLE SHORT _APDFPRP.0040D15E        ;
0040D15A  |. FF01          INC DWORD PTR DS:[ECX]        ;還沒到%10呢,接著幹
0040D15C  |. EB 14          JMP SHORT _APDFPRP.0040D172        ;繼續下一頁
0040D15E  |> 6A 01          PUSH 1                ;已經到%10了,不玩活了
================================================================================
還不快把0AH改為01H,1/10=%10,1/1=100%,我算的對不?
解決掉了一個限制,可以喘口氣了,我需要的就是這項功能,還有2個限制沒去掉,我還真用不到。

這會兒心情不錯,再努努力,繼續跟蹤,找到下面2段程式碼:
================================================================================
00411EC1  . C705 D8BA4500 >MOV DWORD PTR DS:[45BAD8],5        ;初試化的密碼長度模常數
00411ECB  . 6A 00          PUSH 0                             
00411ECD  . 6A 00          PUSH 0                             
00411ECF  . 68 2E010000    PUSH 12E                           
00411ED4  . A1 70994500    MOV EAX,DWORD PTR DS:[459970]     
00411ED9  . FF70 38        PUSH DWORD PTR DS:[EAX+38]         
00411EDC  . 2E:FF15 F4B544>CALL DWORD PTR CS:[<&USER32.GetDlgItemInt>]
================================================================================
00414055  |> 8B0D D8BA4500  MOV ECX,DWORD PTR DS:[45BAD8]    ;密碼長度模常數=5
0041405B  |. A1 30B24500    MOV EAX,DWORD PTR DS:[45B230]    ;最小密碼長度
00414060  |. 99            CDQ                    ;
00414061  |. F7F9          IDIV ECX                ;
00414063  |. 8915 30B24500  MOV DWORD PTR DS:[45B230],EDX    ;最小密碼長度 MOD 5
00414069  |. A1 34B24500    MOV EAX,DWORD PTR DS:[45B234]    ;最大密碼長度
0041406E  |. 99            CDQ
0041406F  |. F7F9          IDIV ECX
00414071  |. 8915 34B24500  MOV DWORD PTR DS:[45B234],EDX    ;最大密碼長度 MOD 5
================================================================================
MOD 5的最大值當然是4了,你要暴力破解多長的密碼?隨你改了,太長我的機器可受不了哦。

剩下最後一項限制了,詞典攻擊限制,再鼓其勇氣,奮鬥了一陣子,沒能找到關鍵程式碼,非X時期,保重
身體要緊,我還是知難而退吧,留下一處遺憾,實在不想和它較勁了。

... ...期待有人繼續下去... ...
*************************************************************************************

-====heXer/iPB====-
-====2003.5.20====-

相關文章