再談powerbuilder程式防止破解的辦法

pb8發表於2009-09-16

鑑於任何程式都執行cpu指令並可被反編譯成彙編碼,也就是說,理論上,程式都是在裸奔,所以天下無不可破之程式。所以這裡討論的防止,只是一定程度上的,比如提高破解難度,拖延時間,讓破解者挫折感增加等等。

一. pb的現狀

pb從5-12,其pbd檔案,和dll檔案格式的版本都為0600(pb5尚不知曉,還沒找到pb5的程式),結構大致一樣。所以pbkiller的作者只要還有時間,他可以在一到三個月就做出最新的版本。這個軟體比起shudepb來說更滅絕人性,因為作者將其免費(最初好像也是要賣錢的,無奈,沒有采用shudepb那樣的網路計算,使得其被破解了。從這一點看也蠻有意思。),從而使得無數的好事者參與到破解的學習中。因為我們寫的程式眾多,高手只對商業價值高的軟體感興趣,而且以它為職業餬口,而初學者只是隨便找個軟體練手。我朋友有個軟體被初學者拿來在裡面放了一些新檔案,其實根本沒破解到,但是宣稱為“破解版”。破解方法寫到:輸入隨便的註冊碼,提示出錯,然後就得到真正的註冊碼了。。。如果不出錯,多試幾次即可。結果呢?程式根本就不在輸入註冊碼的地方判斷正確以否,你說搞笑不搞笑。pbkiller目前最高版2.5.8只支援6-9,我看過,程式碼反編譯比較漂亮。錯誤肯定存在,但已經很完美了。

“錯誤”只有對自己的專案反向時才會頭痛,對破解者而言,他們只想看註冊部分的演算法。

shudepb是商業版,而且幾千塊一套。這一定程度對pb有利,畢竟初學者是不會去買一套沒用的工具來學習破解的。而且demo版它限制程式碼的長度,非註冊版看不全程式碼。還真是厚道。所以如果你不打算應對反編譯軟體的話,那請把程式碼寫在100行之後(具體是不是100行限制,自己測試看看)。這是最簡單辦法(pb10以上)。

至於"pbd"還原器,原理是用pb本身的方法得到dw的反編譯程式碼。這個不叫做破解。pbd中的dw本來就可以直接用,而pb又有函式可以得到語法。這就沒什麼新鮮的了。pb的本身函式是不會提供功能給你能反編譯得到原始碼的。是絕對不可能的。

在網上搜尋破解pb程式的帖子,通用的說法是:程式沒法用OD來調,而且pbvm裡也不好跟,都是要用到pbkiller這個利器,這在一定程度上說明,對付菜鳥,使得其反編譯成功的機率小一些,就能更好的保護自己辛苦勞動的軟體。

目前幾種破解的方法:

      a. 看程式演算法和思路,直接破解演算法,公佈演算法或者寫序號產生器。(如果程式碼一覽無遺,這個方法其實最簡單,但是也有很多菜鳥看不懂pb程式碼,還在網上到處問。可笑)

      b. 有人嘗試搜尋pbd中的關鍵程式碼,用ue修改pbd中的位元組。(這個有難度,做的人不多,而且多數菜鳥只限於pbkiller會用而已,對pbd檔案不瞭解。據我自己觀察:對pbd有了解的話,很多地方可以用ue直接改。),比如修改一個位元組可以把+變成-,把=變成<>,有點恐怖。

      c. 對於外部dll的呼叫,有破解者提議寫假的dll來爆破之。讓其返回一個已經註冊過的序號的依據,如磁碟號。有所謂的免狗程式應該遮蔽了對狗的呼叫或者搞了假的dll。所以有必要多處驗證檔案的md5值。只要他沒法修改pbd檔案。

以下是我猜想的一些做法,是否切實可行,待大家提意見,一個軟體總是新出時容易被破解,如果一年都沒被破解,以後版本升級,變來變去的,破解也就更少了。
我曉得一個朋友的軟體,他一年連出十多個版本,新版一出,兩三天之內就被破。他用的是delphi寫的,他真可憐。二進位制編譯的軟體及asm之後也許更容易破解吧,只要除錯就搞定了。就像pb一樣,破解得非常快。
pb程式其實也佔幾個優勢:多是商業軟體,商業使用者還是有購買的習俗。練手者不太容易找pb程式來破解,因為共享軟體很多。一般是你的使用者用得還可以,又不想給錢,就會有破解的念頭。pb做的都是管理軟體,破解高手對商業價值不高的軟體不感興趣。再者pb程式難以除錯,知道的人都不想弄。加之sql之類的,顯得異常繁雜,遠沒有破解一個二進位制編譯的,通用的,使用量大的軟體有意思。
代理商破解的可能性更大。


二.我的幾個構想的方法(都只針對增加難度,讓靜態pbd反編譯難度加大,讓pj者知難而退)
1.能採用machinecode方式的儘量用機器編譯,單一exe檔案,用pbkiller和shudepb都無法看到程式碼,只能看到變數。pj知難而退。
2.我有幾個專案,程式碼超級大,在當初用pb10的時候就沒法編譯成機器碼。現在的pb11因為有string和blob的bug沒法編譯成機器碼,而pb12剛出來,還沒測試。不過程式碼太多似乎沒法編譯成單一machinecode的exe。那就只能用p-code。
所以第二點就是欺騙,在程式下放跟exe同名的假的pbd檔案。比如程式為main.exe,放一個假的main.pbd給pj者去除錯。當然不一定是假的pbd,你隨便找一個pbd,用ue刪除一些二進位制數字即可,做的跟真的一樣。
pbd可以放在在window系統目錄下,或者path定義的任何地方。或者之前文章也提到,寫他幾十個註冊函式,放在不同的pbd裡,到底是哪一個,只有你曉得,搞死他。librarylist也可以做做文章。因為同名物件,都依照lib順序來查詢。

3.程式啟動時抓一個時間,啟動結束後,抓一個時間,如果中途有停頓,是否可以判定在被除錯,我想你可以刪除他電腦上任何東西。反正都是破壞,別讓他悠閒的除錯程式。我作為一個寫程式碼的人,我認為有必要這麼做。他要QJ你,自然也允許你反抗。某個防毒軟體當年就這樣把破解版搞得吐血。
4.註冊碼輸入時,不做任何提示和判斷。只是寫一個標誌,程式啟動時在title那裡顯示為“正式版”或者註冊版,但是實際上,我可以延期驗證或者隨機驗證。呵呵,這樣也許把破解者都搞得沒辦法。因為他只要輸入一次註冊碼,不管是什麼字元,都成了正式版。而至於什麼時間驗證,除非他有那個耐心,否則也覺得破解麻煩。對破解者而言,抓個特徵值是個小case,而要一行一行地看程式碼,估計吐血而死。
5.ini中的註冊碼調入記憶體和真實註冊碼對比時,我認為將其複雜化後放入一個陣列或者blob中,註冊碼不是在程式啟動時,而是在多時,多點,多處,重複的校驗。我的想法,在100個地方校驗,其程式破解的難度就可能讓pj者早退卻了。
而且,把註冊碼和系列號都跟程式的變數或者功能,或者資料返回條數等掛鉤,做的非常隱蔽,不再是體現在一個if比較的地方。那就能大大減少破解的可能。因為我們知道,破解者無法修改pbd,而且不熟悉pb程式碼。如果搞得太複雜,可能他早就不幹了。
6.我以後發行程式準備放100個或者1000個pbd在程式下,破解者要反編譯就去反吧。看到100個pbd,就算我搞pb幾年我也知難而退了。看到1000個pbd,立即倒地吐血而死。
7.如果主程式不能編譯成單一machinecode的exe,則某些關鍵功能可以用run外部程式方式來執行,而外部程式用pb單獨編寫一個小的程式,小的程式是完全能編譯成功的。
8.費解演算法和寫法。比如把一個數放入陣列,然後在其他地方,其他時候有意無意去改變,或者複製,移動,再到某些時間去執行某些操作。或者引發一些限制。破解變成去看你的程式碼,我想沒人願意繼續下去。
9.如果代理商破解你的軟體,你就讓客戶對他產生不信任即可。買他的破解版就會被騙錢!做到這個足矣。而且你得一棍子把他敲死。
10.發若干個自己做的“破解版”,其實都是測試版,這樣使用者找遍網上也下載不到真正的破解版。很多國內網站轉載時都是煞有介事地稱其為“破解版,綠色版,完全版”,其實都是測試版,搞笑!

11.暗樁:檢測使用者越過註冊部分,不動聲色地做限制。或者在多處多時深層次的地方,或者細節的地方做限制。比如資料彙總等於0.或者是其他單據隱蔽的錯誤等。

12.攻擊:生成病毒特徵體,致使防毒軟體介入。或者刪除自己,或者重啟,因為重啟不可阻止,而且破壞除錯過程。

13.程式執行完,呼叫一個外部exe刪除所有檔案,包括main.exe和所有pbd和dll(如果他做一個假的dll,就會被刪除,而程式啟動時釋放一個新的檔案出來,永遠只使用自己的檔案。這樣他修改dll和pbd都沒用。)

14.必須研究和使用pbkiller和shudepb這兩個工具,研究它們的bug,利用bug寫關鍵程式碼,至少在它bug沒解決之前是可以保護的。比如pbkiller對dec{4}的解析不出來(*提示:如對不同精度的數做賦值,則丟失精度,或者做數學運算等等,丟失精度後轉為字串或者blob),對longlong也解析不出來。。。都可以利用之。這兩個工具還有很多很多的bug。

*20090730今天分析發現一個pb的bug可以使得pbkiller無法得到任何程式碼:

-------------------------

//global function integer lf_count ()

int  li_i0001

.....一直到

int  li_i3260
int  li_i3261

int  li_i3262

int  li_i3263

int  li_i3264

return 1024

--------------------------

本想測試一下pbkiller對程式碼行數有沒有限制,發現pb9在變數數超過3264行後,儲存就會出錯,但是重啟IDE又能插入一個,可以儲存,但是插入第二個變數就不行了,我用這種方法最大可以插入到:int  li_i3270。現在我們先寫3264個,編譯和呼叫這個函式都沒錯。然後多申明一個:比如int  li_i3265,採用增量編譯後,主呼叫程式中返回1024(注意:不能進行全編譯,否則報記憶體只讀錯誤),這倒沒什麼價值,價值在於這樣編譯後的pbd,pbkiller無法反編譯出任何程式碼。大家可以測試一下。如果用作關鍵點計算或者返回幾個關鍵引數,倒是蠻好的!不過,工程project也只能用增量編譯,否則IDE報錯退出。

15.pbNI的運用。使得關鍵程式碼可以融入pbd,但是pbkiller又反不到,其他調式工具也單獨除錯不到。具體未測試過。見黃國疇的blog有例項。

16.編譯後的檔案假設包括一個main.exe和main.pbd,second.pbd,用ue開啟main.exe,在最後部分RTL標誌以上有一個dat*標誌,找到其中的pbd列表,修改一下,如:mypic.jpg,然後把相應的pbd檔案改改名字。效果也挺搞笑的。

17.做3-10個exe(不是主程式),其作用只是依次呼叫,比如1.exe呼叫2.exe,2.exe又去調3.exe.最後呼叫main.exe,各步驟的呼叫都帶引數,並且這3-10個exe還執行部分檔案操作和資料處理,或者部分認證和檔案校驗等,然後最後呼叫main.exe,而且帶引數。這些引數隱蔽地作為一些地方的資料。也可以在3-10.exe執行過程中將一些資料寫入sql中或者檔案中。如此使用倍增難度的方式來為難pj者。

還是那句話,不要讓pbkiller直接看到你的原始碼(給破解者一個假的pbd是個好辦法),保護自己的軟體一年以上。給客戶一個必須要掏錢的理由!
只要能防止靜態下反編譯到你的pbd(一般破解者就是直接找跟主檔案同名的pbd來編譯看看是否能找到註冊演算法,根本不會在意你的pbd到底是不是正確的!!!也不會在意你對他的欺騙),你就有99.99%的希望保護到自己的軟體,如果你的軟體受眾很少的話。

有興趣可以參考《加密與解密》P197頁的幾個對軟體保護的建議。(*見網上有,就摘抄過來):

本節將給出關於軟體保護的一般性建議,這些都是無數人經驗的總結。程式設計師在設計自己的保護方式時最好能夠遵守這裡給出的準則,這樣會提高軟體的保護強度。
(1)軟體最終發行之前一定要將可執行程式進行加殼/壓縮,使得解密者無法直接修改程式。如果時間允許並且有相應的技術能力,最好是設計自己的加殼/壓縮方法。如果採用現成的加殼工具,最好不要選擇流行的工具,因為這些工具已被廣泛深入地加以研究,有了通用的脫殼/解壓辦法。另外,最好採用兩種以上的不同的工具來對程式進行加殼/壓縮,並儘可能地利用這些工具提供的反跟蹤特性。
(2)增加對軟體自身的完整性檢查。這包括對磁碟檔案和記憶體映像的檢查,以防止有人未經允許修改程式以達到破解的目的。DLL和EXE之間可以互相檢查完整性。
(3)不要採用一目瞭然的名字來命名函式和檔案,如IsLicensedVersion()、key.dat等。所有與軟體保護相關的字串都不能以明文形式直接存放在可執行檔案中,這些字串最好是動態生成。
(4)儘可能少地給使用者提示資訊,因為這些蛛絲馬跡都可能導致解密者直接深入到保護的核心。比如,當檢測到破解企圖之後,不要立即給使用者提示資訊,而是在系統的某個地方做一個記號,隨機地過一段時間後使軟體停止工作,或者裝作正常工作但實際上卻在所處理的資料中加入了一些垃圾。
(5)將註冊碼、安裝時間記錄在多個不同的地方。
(7)檢查註冊資訊和時間的程式碼越分散越好。不要呼叫同一個函式或判斷同一個全域性標誌,因為這樣做的話只要修改了一個地方則全部都被破解了。
(8)不要依賴於GetLocalTime( )、GetSystemTime(
)這樣眾所周知的函式來獲取系統時間,可以通過讀取關鍵的系統檔案的修改時間來得到系統時間的資訊。
(9)如果有可能的話,可以採用聯網檢查註冊碼的方法,且資料在網上傳輸時要加密。
(10)除了加殼/壓縮之外,還需要自己程式設計在軟體中嵌入反跟蹤的程式碼,以增加安全性。
(11)在檢查註冊資訊的時候插入大量無用的運算以誤導解密者,並在檢查出錯誤的註冊資訊之後加入延時。
(12)給軟體保護加入一定的隨機性,比如除了啟動時檢查註冊碼之外,還可以在軟體執行的某個時刻隨機地檢查註冊碼。隨機值還可以很好地防止那些模擬工具,如軟體狗模擬程式。
(13)如果採用註冊碼的保護方式,最好是一機一碼,即註冊碼與機器特徵相關,這樣一臺機器上的註冊碼就無法在另外一臺機器上使用,可以防止有人散播註冊碼,並且機器號的演算法不要太迷信硬碟序列號,因用相關工具可以修改其值。
(14)如果試用版與正式版是分開的兩個版本,且試用版的軟體沒有某項功能,則不要僅僅使相關的選單變灰,而是徹底刪除相關的程式碼,使得編譯後的程式中根本沒有相關的功能程式碼。
(15)如果軟體中包含驅動程式,則最好將保護判斷加在驅動程式中。因為驅動程式在訪問系統資源時受到的限制比普通應用程式少得多,這也給了軟體設計者發揮的餘地。
(16)如果採用keyfile的保護方式,則keyfile的尺寸不能太小,可將其結構設計得比較複雜,在程式中不同的地方對keyfile的不同部分進行復雜的運算和檢查。
(17)自己設計的檢查註冊資訊的演算法不能過於簡單,最好是採用比較成熟的密碼學演算法。可以在網上找到大量的原始碼。

相關文章