這篇文章和OICQ本身沒有什麼聯絡,我只是想講一下程式破解的原理和方法,我在
這裡會儘量用易懂的語言來描述,如果你是一個初學者,那麼,此文就是為你而寫的。
我以OICQ99C 0820版為例,其它版本如OICQ2000
的破解方法基本上和此版本沒有區
別。
首先,在OICQ目錄下,每個使用者號碼下有一個叫matrix.cnt的檔案,此檔案的長
度是20位元組,它的內容就是此號碼的原密碼經過加密後對應的密文。要證明這一點非常
容易,只要稍有一點電腦能力的人都可以證明,所以這裡我就不費口舌了。在正式開始
前,請用二進位制編輯器開啟此檔案,熟悉一下內容。
啟動OICQ,出現OICQ使用者登入畫面,選擇你自己的號碼,然後輸入一個錯誤的密碼
,此時按CTRL+D進入SOFTICE畫面,設定斷點。我們事先應該都知道OICQ檢查密碼是否正
確的工作原理,即:先用GetWindowText()來取得密碼框中的密碼字串,將此字串用
其內定的演算法進行加密,得出加密後的密文,然後從磁碟中讀取matrix.cnt,與使用者輸
入的密碼的加密結果進行比較,如果相同,則使用者輸入的密碼為正確密碼。(或者先讀
檔案,後讀取密碼框中的值)跟據這個原理,這們應該把斷點設在readfile上,即輸入
:bpx
readfile。返回程式介面,點選“登入”,出現SOFTICE的畫面,指標停在KERNE
L32!READFILE上。按一下F12跳過此函式,將進入OICQ的領空。
我們現在要做的就是特別注意轉折語句,就是JZ,JNZ,JMP等第一個字元是J的語句
。因為這們己經假設,程式中必定存在一行轉折語句,當使用者輸入的是正解密碼時,它
跳轉(或不跳轉),而當使用者輸入錯誤密碼時,它不跳轉(或跳轉)。小心地按F10單步
執行程式碼,在出現轉折語句處設下一斷點(只是做一個記號),並且記錄它們的跳轉情
況(經驗豐富者知道哪裡有必要下斷點而哪裡沒有必要),直到程式出現密碼錯誤的對
話框為止。
這時候你可能己經花去了1分鐘的時間。好的,現在輸入正確的密碼作為比較。同樣
單步地執行程式碼,你將看到上次你在跳轉語句上作的記號。比較兩次的跳轉是否相同。
你將看到,當程式執行到這裡時,前後兩次的跳轉方向不同:
...
00441C1B call 0046c256
00441C20 cmp eax, ebx
00441C22 jz 00441C28----->就是這裡!
00441C24 mov esi, edi
...
分析一下這幾個程式碼,它首先呼叫函式0046C256,然後比較EAX與EBX的值,如果EAX與E
BX的值相同,就跳轉。我們重新執行程式,發現當輸入正確密碼時,EAX=1,當輸入錯誤
密碼時,EAX=0,而EBX總是0。所以,函式0046C256是一個可疑的函式!
按F8進入函式0046C256,我們要看看它做了什麼工作。
:0046C256 mov eax, 004CD33C
:0046C25B call 00486B88
:0046C260 sub esp, 00000010
:0046C263 push esi
:0046C264 push edi
:0046C265 mov esi, ecx
:0046C267 mov eax, dword ptr [ebp+08]
:0046C26A and dword ptr [ebp-04], 00000000
:0046C26E push [eax-08]
:0046C271 push eax
:0046C272 lea eax, dword ptr [ebp-1C]
:0046C275 push eax
:0046C276 call 00456718
:0046C27B add esp, 0000000C
:0046C27E push 00000001
:0046C280 pop edi
:0046C281 cmp dword ptr [esi+04], edi
:0046C284 jbe 0046C29E
:0046C286 lea eax, dword ptr [ebp-1C]
:0046C289 push 00000010
:0046C28B push eax
:0046C28C lea eax, dword ptr [ebp-1C]
:0046C28F push eax
:0046C290 call 00456718
:0046C295 add esp, 0000000C
:0046C298 inc edi
:0046C299 cmp edi, dword ptr [esi+04]
:0046C29C jb 0046C286
:0046C29E int 03
:0046C29F mov byte ptr [eax], 6A
:0046C2A2 adc byte ptr [ebp+5056E445], cl
:0046C2A8 call 00487900
:0046C2AD mov esi, eax
:0046C2AF add esp, 0000000C
:0046C2B2 neg esi
:0046C2B4 sbb esi, esi
:0046C2B6 or dword ptr [ebp-04], FFFFFFFF
:0046C2BA lea ecx, dword ptr [ebp+08]
:0046C2BD inc esi
:0046C2BE call 004A0665
:0046C2C3 int 03
:0046C2C4 dec ebp
:0046C2C5 hlt
:0046C2C6 mov eax, esi
:0046C2C8 pop edi
:0046C2C9 pop esi
:0046C2CA mov dword ptr fs:[00000000], ecx
:0046C2D1 leave
:0046C2D2 ret 0004
...
按F10單步執行。我們發現在這個函式中有一個非常有意思的地方:
:0046C286 lea eax, dword ptr [ebp-1C]
:0046C289 push 00000010
:0046C28B push eax
:0046C28C lea eax, dword ptr [ebp-1C]
:0046C28F push eax
:0046C290 call 00456718
:0046C295 add esp, 0000000C
:0046C298 inc edi
:0046C299 cmp edi, dword ptr [esi+04]
:0046C29C jb 0046C286
程式反覆地執行這些程式碼!!
為了能看的更清楚些,我用C++語言來簡述這幾個語句:
for( long i=0 ; i< *(esi+04) ; i++)
{
eax=*(ebp-1c);
呼叫函式 00456718;
}
就是說,函式00456718要被呼叫很多次,這個次數就是ESI+04的值,用D
ESI+04命令來
檢視其值,天哪!這不是matrix.cnt的內容嗎?(你原先在二進位制編輯器中己經開啟過
此檔案並且看到過它的內容)而ESI+04正是matrix.cnt的前4個位元組!我們現在有足夠的
理由相信,密碼被加密成了128位(即16個位元組),且加密函式存在於函式00456718中!
抬起眼睛看一下,在函式0046C256中,一開始也呼叫了一次00456718函式!為了再
進一步地證實我們的設想,讓我們再重新執行OICQ,輸入一個錯誤的密碼,但這次你輸
入的密碼長度最好和正確密碼的長度相同,在第一次呼叫00456718前設下一個斷點:
:0046C265 mov esi, ecx
:0046C267 mov eax, dword ptr [ebp+08]
:0046C26A and dword ptr [ebp-04], 00000000----->在這裡設一個斷點
:0046C26E push [eax-08]
:0046C271 push eax
:0046C272 lea eax, dword ptr [ebp-1C]
:0046C275 push eax
:0046C276 call 00456718
當程式執行至斷點處時,檢視各個暫存器的值,你在EAX裡看到了什麼?是的,EAX
裡面是你輸入的密碼,你用這個密碼進行登入,程式將出現密碼錯誤的資訊,但是,如
果你此時修改一下EAX的值,把它改為正確的密碼,你又驚喜地發現:OICQ己經成功地登
錄了!注意:只要你稍微留意一下,EAX-8的值正是密碼的長度。以上的事實己經證明了
:函式00456718就是OICQ的加密函式。
跟據種種跡象,這個函式具體是什麼演算法,學過密碼學的朋友己經不用往下看了。
但我們還必須深入證實。
按F8,將看到此函式:
:00456718 push ebp
:00456719 mov ebp, esp
:0045671B sub esp, 0000005C
:0045671E lea eax, dword ptr [ebp-5C]
:00456721 push eax
:00456722 call 00455A6E
:00456727 push [ebp+10]
:0045672A lea eax, dword ptr [ebp-5C]
:0045672D push [ebp+0C]
:00456730 push eax
:00456731 call 00455AA9
:00456736 lea eax, dword ptr [ebp-5C]
:00456739 push eax
:0045673A push [ebp+08]
:0045673D call 004565FD
:00456742 add esp, 00000018
:00456745 leave
:00456746 ret
函式看上去很短小,但它又呼叫了三個函式。檢視第一個函式:
:00455A6E push esi
:00455A6F mov esi, dword ptr [esp+08]
:00455A73 push 0000005C
:00455A75 push 00000000
:00455A77 push esi
:00455A78 call 00486FD0
:00455A7D and dword ptr [esi+10], 00000000
:00455A81 and dword ptr [esi+14], 00000000
:00455A85 and dword ptr [esi+58], 00000000
:00455A89 add esp, 0000000C
:00455A8C mov dword ptr [esi], 67452301
:00455A92 mov [esi+04], EFCDAB89
:00455A99 mov [esi+08], 98BADCFE
:00455AA0 mov [esi+0C], 10325476
:00455AA7 pop esi
:00455AA8 ret
看到標有紅色的四個語句了嗎?加密函式在一開始設定了4個32位的常數!!接下來
,在函式00455D5A中連續出現了64次諸如:
00455D60 mov edi, dword ptr [ebp+08]
00455D63 xor ebx, edx
00455D65 add ebx, dword ptr [eax]
00455D67 lea edi, dword ptr [edi+ebx-28955B88] ;注意,這是個常數!
00455D6E mov ebx, edi
形式的語句。至此為止,OICQ用的是什麼加密演算法,己經是不言而明瞭