製作自己的記憶體序號產生器--------檔案隱藏精靈註冊碼獲取 (4千字)

看雪資料發表於2015-11-15


檔案隱藏精靈是我的一個網友寫的軟體,很方便很實用。
這次那她開刀主要是目的是學習記憶體補丁技術。用動態
記憶體補丁取得軟體真正的註冊碼。並且對破解軟體的
思路經驗進行總結,以饗讀者。

下載地址:http://www.megspace.com/computers/bluenightsky/
保護方式:aspack2.12+自刪除
使用工具:OllyDbg1.09C漢化版,DeDe,pe-scan,W32Dasm,VC++6.0
作業系統:win2000
破解難度:初級

      破解過程

一、解除軟體保護。
檔案隱藏精靈用的是ASPACK2.12的殼,手工和使用工具很容易就能脫掉。
但是脫殼後的程式會刪除自己,使得DeDe不能正常對它進行反彙編。
用ollydbg跟蹤發現 00477D19 > E8 A2CBF8FF CALL FILEMAGI.004048C0
如果進入這個CALL,程式就會生成一個名稱為delme.bat的批處理檔案,
然後呼叫winexec()函式,用SW_HIDE引數隱藏執行這個批處理檔案達到刪除自己的目的。
透過跟蹤未脫殼的檔案和脫殼後的檔案比較發現
004573A1 . 80B8 9C000000 00  CMP BYTE PTR DS:[EAX+9C],0
004573A8  ^74 BF             JE SHORT FileMagi.00457369
未脫殼的檔案這裡的跳轉條件一直為真,而脫殼以後第二次經過這裡跳轉條件就為假了。
在004573A1處看反彙編程式碼視窗下面的視窗:
EAX+9C指向的01101464被置為1,則CMP後Z標誌被置1,JE跳轉實現。
讓我們看看是那裡改變了01101464的值的。因為程式要初始化記憶體才能看到01101464
所以我們先在004573A1 CMP BYTE PTR DS:[EAX+9C],0處下斷點。因為第一次迴圈時
01101464得值不會改變。斷下後開啟“記憶體映象”視窗(檢視-記憶體)找到01101464
(圖片1)
滑鼠右鍵-〉斷點-〉記憶體寫入
然後執行。程式斷在了00457142
我們可以看到ESI+9C指向的地址正是01101464
00457140 |. EB 07 JMP SHORT FILEMAGI.00457149
00457142 C686 9C000000 01 MOV BYTE PTR DS:[ESI+9C],1//這裡改變了01101464的值
00457149 |> 8BC3 MOV EAX,EBX
0045714B |. 5A POP EDX
關閉程式(工具欄上的X號),檢視選單-〉檔案,選擇脫殼後的程式檔案查詢
C686 9C000000 01,把01改為00,也就是改為MOV BYTE PTR DS:[ESI+9C],0就OK了。
然後DeDe就可以正常的對他進行反彙編。但是程式不能正常退出。
把004573A8   ^74 BF JE SHORT FileMagi.00457369改為
004573A8  .^EB BF JMP SHORT FileMagi.00457369
也可以效果一樣。

二、對軟體註冊方式的分析。
這個軟體是一組密碼、使用者名稱對應一個序列號的方式進行註冊的。
可以一臺機器上有多個使用者。使用者也可以在任意機器使用複製。
用DeDe對程式進行反彙編。
在過程-〉事件裡面,找到註冊按鈕的事件對應的入口地址
00475DFC /. 55 PUSH EBP
然後回到OllyDbg。點工具欄上面的“前往反彙編地址”按鈕,輸入入口地址00475DFC。
在反彙編指令處按F2設斷點。執行。幫助裡面註冊。
輸入使用者名稱、密碼、序列號(數字)-〉確定。在OllyDbg中被斷下。
按F8但步跟蹤來到
00475F78 |. 8B45 C8 MOV EAX,DWORD PTR SS:[EBP-38]
00475F7B |. E8 4443F9FF CALL FILEMAGI.0040A2C4
00475F80 |. DC5D F8 FCOMP QWORD PTR SS:[EBP-8]//註冊碼在這裡!!!!
00475F83 |. DFE0 FSTSW AX
00475F85 |. 9E SAHF
00475F86 |. 0F85 EA000000 JNZ FILEMAGI.00476076
00475F8C |. 8BC3 MOV EAX,EBX
00475F8E |. E8 5DDEFDFF CALL FILEMAGI.00453DF0
在00475F80指令處EBP-8裡面就可以看到註冊碼了。浮點數!!!小數點前面的就是真正的註冊碼了。
分析演算法做序號產生器太麻煩了用到了浮點指令,因為是明碼比較。所以可以利用程式裡面的演算法程式碼。
但是也不能每次為了得到註冊碼就對程式跟蹤一次太麻煩了。製作一個記憶體序號產生器是個很好的辦法。
不受軟體加殼的影響、不修改硬碟上的程式檔案……

三、製作記憶體補丁
記憶體補丁我是用VC做的。由於用的是WINDOWS的API函式。所以,明白原理後用其他語言(比如:Delphi,VB)
也能做出同樣的效果。
首先要在資料段找一個空隙方我們的補丁程式碼。用OllyDbg向下拉找到一個空白處(16進位制全部為00,反彙編
程式碼為DB 00)我找到的是00477D53處(很大的一個房間);
首先先修改00475F80處指令,讓指令跳轉到我們的補丁程式碼處
00475F80 E9 CE1D0000 JMP FileMagi.00477D53
這個指令佔用5個位元組正好覆蓋了
00475F80 |. DC5D F8 FCOMP QWORD PTR SS:[EBP-8]
00475F83 DFE0 FSTSW AX
為了程式能正常執行,我們要在我們的補丁程式碼處恢復這兩條指令。
這是補丁程式碼處的程式碼
00477D53 DC5D F8 FCOMP QWORD PTR SS:[EBP-8] //比較(恢復原來的指令)
00477D56 DD45 F8 FLD QWORD PTR SS:[EBP-8] //把正確的傳遞到暫存器(浮點指令)
00477D59 36:DD15 6D7D4700 FST QWORD PTR SS:[477D6D] //把暫存器數值寫入一個可寫入地址(浮點指令)
00477D60 DFE0 FSTSW AX //(恢復原來的指令)
00477D62 ^E9 1EE2FFFF JMP FileMagi.00475F85 //跳回原來指令的下一條指令
這樣執行註冊以後。正確的註冊碼就儲存在了00477D6D。我們只要讀取00477D6D處的數值就可以了。

現在我們說一下注冊機編寫的步驟:
首先用FindWindow函式得到視窗控制程式碼,然後用GetWindowThreadID函式從視窗控制程式碼得到這個程式的ID
HWND hWnd=::FindWindow("tapplication","file-magic");//第一個引數是類,第二個引數是視窗標題。
GetWindowThreadProcessId(hWnd,&hProcId);//第一個引數是視窗控制程式碼,第二個引數是程式ID為DWORD型。
接著用OpenProcess得到程式的讀寫許可權
HANDLE nOK =OpenProcess(PROCESS_ALL_ACCESS|PROCESS_TERMINATE|PROCESS_VM_OPERATION|PROCESS_VM_READ| 
                            PROCESS_VM_WRITE,FALSE,hProcId);  //開啟程式並得到讀與許可權
最後用WriteProcessMemory和ReadProcessMemory讀寫記憶體,然後你的記憶體序號產生器就做成啦:-) 
除錯發現註冊碼讀取需要用雙精度浮點數(double)儲存。
程式下載:http://202.102.229.61/zhima

相關文章