*[标題]:Skin++通用界面換膚系統V2.0.1破解探讨
*[作者]:gz1X <gz1x(at)tom(dot)com>
*[來自]:中國黑客聯盟
*[前言]:
skin技術,大家都不會陌生,比如winamp,可以靈活的更換界面風格。早期的實作定制的外觀方法都需要程式本身做許多處理,編碼太麻煩。
後來出現了專門的Skin插件,ActiveSkin什麼的。再後來dll調用的skin軟體出現,需要Skin支援的程式調用幾個方法,就可以使自己的程式外觀完全改變,不需要程式設計者對skin技術有任何的了解。Skin++通用界面換膚系統V2.0.1就是其中比較出名的一款。
但是讓很多“貧民”使用者來說,要收費還是比較讓人煩的。恰好我前幾天做了個小項目,順便用了下朋友推薦的這款軟體。
*[軟體原理分析]:
逆向了下這款軟體,因為這款軟體是商業軟體,沒方法得到源代碼,是以我也是主觀的猜測。
原理上基本上是這樣:
通過消息鈎子來改變已有控件的外觀,函數原型是SetWindowsHookEx(WH_CALLWNDPROC, HookProc, 0, lThreadID);
這個函數就不多做解釋了,查閱MSDN。設定類型為WH_CALLWNDPROC的HOOK。
然後是截獲消息,當然不同控件發出的相同消息也是要分開處理的,簡單的方法是得到視窗句柄,而通過視窗句柄得到視窗類,一般在HOOK的CALLBACK 函數中可以獲得。接下來就是消息處理,一般都是從截獲WM_CREATE消息開始,再就是WM_PAINT,其他諸如滑鼠消息之類的也是要處理的,就不再多說。但是這裡的細節部分,比如鈎子的記錄,會出現很多煩瑣的東西,解決方案是為視窗類型建立類,然後由執行個體去解決視窗消息的處理和視窗狀态資料的記錄。獲得了視窗句柄以後,使用SetWindowLong技術将視窗句柄關聯到視窗類上。并且可以根據視窗的風格讓同一個類做出不同風格的顯示效果。
具體的代碼實作限于我的水準和時間問題,就不多做糾纏。
*[軟體用法說明]:
在VC平台下設定include和lib,tools/options/directory。也可以把SkinPPDemoSystem(VC)/ VCcases下的include和lib檔案的檔案拷貝到VC的對應目錄。在project/settings/link裡添上 SkinPPWTL.lib 。
然後将DLL目錄裡的SkinPPWTL.dll拷貝到windows目錄的system32目錄下(注意這個是沒破解的)。
生成project的時候,将Skins目錄裡的某張皮膚拷貝到項目目錄下,然後在源代碼裡加上#include "SkinPPWTL.h",int CMainFrame::OnCreate或者CMFC_SkinApp::InitInstance下加上skinppLoadSkin(_T ("xxx.ssk"));即可。
詳細的代碼可以參考附帶的demo。
如果不是正版使用者,在生成可執行檔案後運作會彈出對話框要求注冊。下面我們就破解掉它。關鍵是對SkinPPWTL.dll的破解。
*[軟體破解分析]:
那我們破除它。
[code]
10033097 |. 68 7C120710 PUSH skinppwt.1007127C ; ASCII "UIPower : ...?"
1003309C |. E8 F7E9FCFF CALL skinppwt.10001A98
100330A1 |. 8365 FC 00 AND DWORD PTR SS:[EBP-4],0
100330A5 |. 51 PUSH ECX
100330A6 |. 8BCC MOV ECX,ESP
100330A8 |. 8965 EC MOV DWORD PTR SS:[EBP-14],ESP
100330AB |. 68 10030710 PUSH skinppwt.10070310 ; ASCII "UIPOWER"
100330B0 |. E8 E3E9FCFF CALL skinppwt.10001A98
100330B5 |. FF35 A8270710 PUSH DWORD PTR DS:[100727A8]
100330BB |. 834D FC FF OR DWORD PTR SS:[EBP-4],FFFFFFFF
100330BF |. E8 B7F10000 CALL skinppwt.1004227B
100330C4 |. 83C4 14 ADD ESP,14
100330C7 |. 83F8 06 CMP EAX,6
100330CA |. 75 18 JNZ SHORT skinppwt.100330E4
100330CC |. 6A 05 PUSH 5 ; /IsShown = 5
100330CE |. 6A 00 PUSH 0 ; |DefDir = NULL
100330D0 |. 6A 00 PUSH 0 ; |Parameters = NULL
100330D7 |. 68 5C120710 PUSH skinppwt.1007125C ; |Operation = "open"
100330DC |. 6A 00 PUSH 0 ; |hWnd = NULL
100330DE |. FF15 3C840510 CALL DWORD PTR DS:[<&SHELL32.ShellExecut>; /ShellExecuteA
100330E4 |> 8B4D F4 MOV ECX,DWORD PTR SS:[EBP-C]
100330E7 |. 64:890D 000000>MOV DWORD PTR FS:[0],ECX
100330EE |. C9 LEAVE
100330EF /. C3 RETN
最讓人讨厭的是這句:
100330BF |. E8 B7F10000 CALL SkinPPWT.1004227B
跟進去就能看到是一個函數MessageBoxIndirect調用.
直接NOP掉。
接着看下面這個:
jump掉:
100330CA . EB 18 JMP SHORT SkinPPWT.100330E4
這裡查找75 18的時候可以把上下文加上,這樣:83 F8 06 75 18 6A 05然後替換為83 F8 06 EB 18 6A 05即可。
儲存SkinPPWTL.dll。拷貝到兩個地方:skin++安裝目錄的VCcases/Bin目錄下和windows目錄的system32目錄下。
*[軟體服務破解]:
有了這個skin++,當然是需要更多皮膚了,而軟體本身隻提供了不到10張。而正版的使用者才能下載下傳官方網站上的皮膚。不管那麼多,我到官方網站轉了一圈,分析了下網站下載下傳連結,發現了一個好玩的東西。可以通過下面的方法下載下傳到更多的皮膚:
用迅雷建立批量下載下傳任務,這樣:
(*) 範圍115-160。
下載下傳...正常應該能拿到50多張皮膚...Enjoy!
上面是網友gz1X寫的部分,我試驗了,破解很成功,達到了去掉每次啟動程式都彈出的詢問注冊的CMessageDialog,但是我想加點個人認為有必要的東西:
1、使用的調試軟體:
軟體:OllyICE
2、軟體的使用:
選擇打開要破解的SkinPPWTL.dll檔案之後按上述步驟完成修改之後,就有一個儲存修改的問題,我在使用的時候找遍了整個菜單欄,硬是沒有發現有儲存修改這個項的存在,後來發現操作方法如下:
a.被修改處右擊,選擇“複制到可執行檔案”,選擇“所有修改”
b.出現提示框“把選中的内容複制到可執行檔案”,選擇“全部複制”
c.彈出一個新的視窗,直接點X,關閉該子視窗,提示“檔案已更改”,選擇“是”,再彈“另存為”框,此時不要做任何修改,切記不可改檔案名,接着提示“檔案已存在”,問是否覆寫,點“是”,覆寫原檔案,關閉OllyICE,打完收功。
到此,對于達到最終目的來說,軟體的這些操作已經足夠,但程式使用後依然存在一個嚴重問題:程式所有視窗的标題欄右邊都有“SKIN++ UNREGISTERED!!!”字樣,這樣對于一個程式員來說,無異于沒做,然而網友gz1X沒有将此問題完善。經過調試,終于成功破解,操作步驟如下:
a.在反彙編視窗中右擊,出來一個菜單,我們在 查找->所有參考文本字串 上左鍵點選
b.現在出來另一個對話框,我們在這個對話框裡右擊,選擇“查找文本”菜單項,輸入“SKIN++ UNREGISTERED!!!”(注意這裡查找内容要區分大小寫)來查找,找到一處,位置在 008DACE2.
c.在此行,彙編指令為:push 00920784,這條指令用于将“SKIN++ UNREGISTERED!!!”所在的記憶體位址傳遞給子程式,我們隻需要将這個位址修改一下就可以改變顯示的字元了,這個字元串一共22個字元,壓棧的位址最後兩位84+22=A6,于是我們将這條指令改為:push 009297A6,儲存,退出。
再試試,問題是不是已經解決?