tft每日頭條

 > 科技

 > 軟件破解與防破解的那些事

軟件破解與防破解的那些事

科技 更新时间:2024-07-06 00:51:45

首先我們要明确一點:

理論上不存在無法破解的軟件,但也并不是說破解軟件比開發容易一萬倍,

防破解的目的不是要做一個無法破解的軟件,而是讓破解軟件的成本遠大于購買軟件的成本

現在筆者簡略表演幾個有代表性的軟件破解,當然,要看懂下面的内容,需要一點點C語言的編程基礎.

我們先來一個最最簡單的軟件破解,假設我們寫了一個軟件,它的注冊手段代碼如下

#include "stdio.h" #include "string.h" int main() { char Key[32]; printf("請輸入注冊碼:"); gets(Key); if (strcmp(Key,"abc123456")==0) printf("注冊成功"); else printf("注冊失敗"); }

把他編譯成exe,運行一下

軟件破解與防破解的那些事(軟件破解與防破解的那些事)1

要破解怎麼辦呢?超簡單的,你把這個程序後綴改成txt然後打開,搜索注冊碼.然後翻一翻key就找到了

軟件破解與防破解的那些事(軟件破解與防破解的那些事)2

别笑,就算是今天,仍然有一大堆軟件采用這種軟件保護機制,不過這類軟件要不大多不怎麼值錢比如xx管理系統,計算器之類的,要不就是軟件作者别有用心防君子不防小人.你可能會問了,問題出在那了呢,這類保護機制的問題是,目前大部分的編譯器都會将字符串常量直接存儲在可執行文件結構中,所以你要是硬編碼key,那麼上面這種破解方法幾乎是屢試不爽甚至不需要什麼逆向破解知識就能搞定.

那麼,讓我們進入防破解V2.0時代,為了與時俱進,我們稍微把上面的代碼改一下

#include "stdio.h" #include "string.h" #include "windows.h" #include "math.h" int main() { char iKey[32]; char Key[32]; char ID[32]; int iID=0xabc1d3f; sprintf(Key,"%x",iID*8 123456); printf("你的機器碼是%x\n",iID); printf("請輸入注冊碼:"); gets(iKey); if (strcmp(Key,iKey)==0) MessageBoxA(0,"注冊成功","",MB_OK); else MessageBoxA(0,"注冊失敗","",MB_OK); }

軟件破解與防破解的那些事(軟件破解與防破解的那些事)3

現在"TXT"破解法已經不頂用了,你看,key找不到了

軟件破解與防破解的那些事(軟件破解與防破解的那些事)4

怎麼樣,這種保護手段是不是熟悉的味道熟悉的配方,這個機器碼可以從網卡MAC,CPU型号,内存大小等等等等去生成,當然,key的算法也可以拉上MD5,SHA等等等等手段來弄而不是簡簡單單的乘一個8再加上123456,總之從機器碼到注冊碼的算法你能玩出花.

但,這又有什麼卵用呢,打開ollydbg,對MessageBoxA下斷點(也就是彈窗的函數)

軟件破解與防破解的那些事(軟件破解與防破解的那些事)5

然後輸入一個錯誤的注冊碼,命中斷點,很快,我們來到了判斷注冊碼是否正确的邏輯處理代碼

軟件破解與防破解的那些事(軟件破解與防破解的那些事)6

你猜猜,要是我們把這個判斷注冊碼是否正确的代碼給它删了)(nop指令填充)會怎麼樣

軟件破解與防破解的那些事(軟件破解與防破解的那些事)7

你會發現,握草,不管我輸入什麼,都是注冊成功

軟件破解與防破解的那些事(軟件破解與防破解的那些事)8

那麼問題出在哪了呢,你發現,萬惡之源都始于那個MessageBox函數,正是這個函數,讓我們順藤摸瓜找到了注冊碼判斷代碼,時至今日,仍然有非常非常大的一部分軟件使用着這個二三十年前就在用的保護手段,每年死于MessageBox被破解的軟件,圍起來可以繞地球三圈.也就是這個保護機制,成就了所謂軟件發布後十分鐘就被破解的悲慘結局.

軟件破解與防破解的那些事(軟件破解與防破解的那些事)9

這個時候,你痛定思痛,mmp,有内鬼,既然MessageBox不好用,那我不用就是了,于是你把代碼改成下面這樣

#include "stdio.h" #include "string.h" #include "windows.h" #include "math.h" int main() { char iKey[32]; char Key[32]; char ID[32]; int iID=0xabc1d3f; sprintf(Key,"%x",iID*8 123456); printf("你的機器碼是%x\n",iID); printf("請輸入注冊碼:"); gets(iKey); if (strcmp(Key,iKey)==0) printf("注冊成功"); else exit(0); }

你看,啧.隻要你注冊碼沒輸對,我直接把軟件退出(或者跳到别的地方),看你怎麼辦

可惜,内鬼年年有,"注冊成功"幾個字還是出賣了你,打開ollydbg,查找字符串參考,然後雙擊

軟件破解與防破解的那些事(軟件破解與防破解的那些事)10

軟件破解與防破解的那些事(軟件破解與防破解的那些事)11

軟件破解與防破解的那些事(軟件破解與防破解的那些事)12

哦豁,完蛋,換湯不換藥,還是給逮住了.

你察覺到這樣一個地方判斷注冊碼實在不靠譜,所以,你改變了策略,把檢查注冊碼的代碼複制了n遍,或者逐字符檢查注冊碼的準确性,還有人将注冊成功等字樣進行加密或混淆,等到要用的時候再取出來

#include "stdio.h" #include "string.h" #include "windows.h" #include "math.h" int main() { char iKey[32]; char Key[32]; char ID[32]; int iID=0xabc1d3f; sprintf(Key,"%x",iID*8 123456); printf("你的機器碼是%x\n",iID); printf("請輸入注冊碼:"); gets(iKey); if (strcmp(Key,iKey)==0) printf("注冊成功"); else exit(0); if (strcmp(Key,iKey)==0) printf("注冊成功"); else exit(0); if (strcmp(Key,iKey)==0) printf("注冊成功"); else exit(0); if (strcmp(Key,iKey)==0) printf("注冊成功"); else exit(0); if (strcmp(Key,iKey)==0) printf("注冊成功"); else exit(0); if (strcmp(Key,iKey)==0) printf("注冊成功"); else exit(0); if (strcmp(Key,iKey)==0) printf("注冊成功"); else exit(0); if (strcmp(Key,iKey)==0) printf("注冊成功"); else exit(0); }

軟件破解與防破解的那些事(軟件破解與防破解的那些事)13

你放心,不管你複制多少次,要找出來都是時間問題,吃棗是會被破解的.同時隻要你要用到明文字符串你遲早還是要解密的,這種手段類似于加upx壓縮殼,隻需要等待數據解壓完成,所有的東西又都是明文的了。因此比較聰明的做法是,要用時解密,用完後馬上把明文抹掉,這樣說不定能拖延更長的時間。但這仍然也是時間問題。

你開始發現,與其揪出内鬼,不如主動出擊,也就是我們著名的與其解決問題不如解決提出問題的人,終于,你開始對調試器下手了,然後你成功進化到防破解V2.5時代.

這個時候,不得不介紹一個老掉牙的但非常有名的函數

IsDebugPresent

你可能有點懵,這個函數是幹啥子用的?,簡單來說,當我們破解一個程序的時候,大部分情況下我們會打開一個叫調試器的東西來對軟件進行反編譯分析,诶,重點就在這,IsDebugPresent這個函數,就能檢測我們的程序有沒有被一個調試器附加,你想啊,正常情況我們用軟件誰會吃飽撐着附加一個調試器來用,你要是用調試器附加我,你肯定就是想幹壞事.

于是,你開始把代碼寫成這樣:

#include "stdio.h" #include "string.h" #include "windows.h" #include "math.h" int main() { char iKey[32]; char Key[32]; char ID[32]; int iID=0xabc1d3f; if (IsDebuggerPresent()) { MessageBoxA(NULL,"小樣,就你還破解我的程序,回家喝奶去吧","",MB_OK); return 0; } sprintf(Key,"%x",iID*8 123456); printf("你的機器碼是%x\n",iID); printf("請輸入注冊碼:"); gets(iKey); if (strcmp(Key,iKey)==0) printf("注冊成功"); else exit(0); }

于是,當下次再ollydbg加載調試你的程序的時候,就會出現下面的情景

軟件破解與防破解的那些事(軟件破解與防破解的那些事)14

曾經很長一段時間(包括現在),很多軟件或加密殼都會檢查是否有調試器正在調試自己,比如tls段會在加載時被執行,如果檢查到自己正在被人調試破解,就會設置一個tag讓程序跑到沒啥用的地方去或者直接退出重新,也有利用變形的PE頭讓調試器無法加載,總之手段很多.

可惜這還是沒什麼卵用,比如IsDebugPresent可以通過修改FS寄存器的标志位來讓它徹底啞火,同樣的手段包括但不限于檢查int 3軟中斷,Raw Call,Query PEB,檢查Debug Privilege和父進程等等等等,都有繞過的方式.

軟件破解與防破解的那些事(軟件破解與防破解的那些事)15

暗樁嘛,隻要你插,一個一個拔總是拔的完的

好了,還有啥法子不,放心道高一尺魔高一丈,現在我們來到了現在最流行的,防破解V3.0 VMP時代,

先澄清一下,這裡的VMP并不是VMP殼,它全程叫Virtual Machine Protection,簡單來說,為啥我們破解軟件那麼輕車熟路,還不是因為x86 x64 arm的那堆彙編指令集我們太熟悉了呗.要是我們自己發明一套指令集,然後用這個指令集寫程序并運行在我們自己的虛拟機上,那麼,破解者一進來,看到的不就是一臉懵逼了麼

可惜的是,VM的運行機制決定了它可能造成幾十倍乃至幾百倍的性能損失,所以,VMP必須用于保護那種關鍵且不是性能瓶頸的代碼,否者你的軟件跑起來就會像

軟件破解與防破解的那些事(軟件破解與防破解的那些事)16

那麼,VMP保護機制是完美的麼,當然不是,VMP說白了,也隻能做到延長分析時間,你要是把VMP做的足夠複雜,足夠讓一個Cracker醉生夢死了,但是如果這個時間足夠久,你的軟件足夠的值錢讓人有欲望來破解, 他們仍然可以充分地分析你VM機的運行機制,當你的VM機運行機制被摸清了,軟件就離淪陷不遠了.

不過你可以放心,分析VM機執行機理,可比自己寫VM機要頭疼多了,畢竟一個是你需要通過代碼來揣測别人的思路,而另一個本身是自己的思路轉為代碼,因此基于這點可以說:

破解軟件比制作軟件簡單,在很多情況下,不存在的!

軟件破解與防破解的那些事(軟件破解與防破解的那些事)17

你可能會問了,為什麼現在市面上那麼多軟件,那麼多遊戲,購買了那麼多聽起來那麼牛逼的保護軟件,結果還是被破解了.而且剛發出來一天就被破解了.

其實很大的問題就出在這個商業保護軟件(比如保護殼)上,因為這類保護殼大多都會被賣給一大票的軟件開發商,有一句話叫樹大招風,就像現在流行的VMP保護機制,之所以能保護,是因為其運行機理破解者不明确,如果你這個軟件就給自己用,而且你這軟件還不怎麼值錢,除非大佬空虛寂寞冷,不然誰會有那閑工夫去分析你的虛拟機是怎麼跑的,但商業保護殼不同,不論其采用什麼樣的保護機制,隻要分析過一遍搞清楚了,幾乎所有使用這類保護機制的軟件都會淪陷,而且在灰色産業上.這種破解甚至還頗有利可圖,隻要這個保護機制不更新,一次投入,長期回報.于是隻有說在第一次分析時會花上很長的時間,之後就都隻是玩套路了.

因此,購買商業保護殼,其實其保護效果并沒有想象中的那麼強,很可能在灰色産業中形同虛設,甚至一個具有反逆向基礎的碼農自己寫的說不定還更有效果.當然一個軟件是被破解概率高不高,仍然是我之前提到的那句話:防破解不是讓軟件無法破解,而是讓破解軟件的成本遠大于購買軟件的成本

軟件破解與防破解的那些事(軟件破解與防破解的那些事)18

畢竟你說你一個軟件拿來開源都沒人愛用,你還整天琢磨着怎麼才不會被破解,寒摻不老鐵.

那麼你會開始問了,有沒有更給力點的防破解技術?好像之前說的說來說去,無非就是拖延時間,诶,這個我們要擺正心态,不論是加密還是破解,其實說白了最終就是拖延時間,你看那些加密算法,依據其數學理論,如果要破解,它的計算量就算你把全世界的計算機加起來一塊算,也夠你算三個世界末日了.

不過别擔心,更給力的方法還是有的,你想啊,為什麼我們之前說了那麼多軟件都被破解了,最最關鍵的一個原因,是我們能搞到代碼,即使這個代碼已經是經過編譯後的一堆彙編指令,但隻要我們有這堆代碼,遲早我們還是能搞懂這個程序是怎麼回事的,然後我們就可以對症下藥幹壞事.

這就像給你有一包面粉,而程序就是一個面包機,你把面粉塞進面包機做出了面包,有天你好奇啊,這面包機咋整咋整就出來一塊面包了呢,你就動手把面包機拆了,然後你就知道面包機是怎麼回事了.

所以有沒有辦法不讓用戶知道我們的代碼是什麼樣的呢,就像你把面粉交給了面包師傅做面包,這個面包是怎麼做的,你就隻能指望看面包師傅有沒有這個心情告訴你了.

為此,有請早期一個相當流行且普遍的遊戲防破解工具(物理)

軟件破解與防破解的那些事(軟件破解與防破解的那些事)19

你現在可能表情是一臉問号,但我沒和你開玩笑,在2000年時代,大部分的遊戲運行在光盤CD中,但盜版也容易啊,把光盤裡的數據一複制下來,然後就可以複制出一萬張盜版光碟,所以遊戲廠商們就想辦法,想來想去就想到了榔頭

其操作方法很簡單,拿榔頭和釘子,在光盤上釘幾條刮痕出來,造成人工的壞道,然後再将數據燒錄到正确的扇區中,這樣下來雖然程序還是可以正确運行,但是當光頭讀盤讀到這個壞道的時候,就會讀不過去,于是你會發現打開光盤後,沒有關鍵的文件,這樣你就沒辦法将遊戲或者說程序拷貝出來了,同時還會對壞道的位置做一個标記,遊戲運行時也會檢查這個标記,那麼想要盜版你就也得拿起榔頭在光盤同樣的位置上砸出同樣的刮痕出來,當然,這幾乎是不可能的.

軟件破解與防破解的那些事(軟件破解與防破解的那些事)20

當年這個技術當年又叫防盜環技術,但不管它的名字叫的多高大上,本質上就和榔頭釘釘子如出一轍是同樣的東西,可惜虛拟光驅出現後,同樣有辦法複刻光盤的一切數據(包括壞道),所以,這個技術拿到今天來看并沒有什麼卵用.不過這仍然給了我們足夠的啟發.

現在讓我們進入防破解V3.x時代,之所以不叫V4.0是因為這類技術很早就有并且比VMP保護流行的時間還早的多,而且它可能是最近接理論上不可破解的防破解手段.

我們先聊的是加密狗或者又叫Ukey保護,就是運行軟件你需要插入一個U盤一樣的東西到電腦上,實際上這個Ukey是一個微型電腦,軟件的一些關鍵的算法和代碼,都在這個UKey的芯片裡,當我們PC上的軟件運行後,當我們需要執行這類關鍵算法時,我們會向這個Ukey傳遞數據,然後UKey将結果計算出來,返回給PC的軟件上,這樣就避免了用戶直接能夠逆向取得關鍵的算法代碼,破解也就無從談起了.這也就是為什麼到了今天,Ukey保護仍然非常的流行.

可惜,UKey保護仍然有諸多的限制,首先就是帶着一個Ukey賊麻煩,萬一UKey丢了補辦是一個麻煩事,運行軟件插Ukey也是個神煩的事情,同時,UKey的性能決定了它可能不能執行一些過于消耗性能和内存空間的代碼,數據交互也因帶寬和通訊延遲會造成性能損失,所以它和VMP保護機制一樣,同樣不是一個省油的燈,同時開發人員的水平不到位,該保護的代碼沒保護,保護來沒啥用的代碼塞了一堆,也會給Cracker帶來機會,而且隻要你的軟件夠值錢,你是不是太瞧不起我華強北了

軟件破解與防破解的那些事(軟件破解與防破解的那些事)21

把Ukey拆開來,使用某種"藥水"剝開外層找到内部的芯片并接上已經熔斷的"讀引腳"(有些芯片連這步都省了,直接熱風槍一吹接闆讀ROM) 然後再把芯片的代碼給讀出來

軟件破解與防破解的那些事(軟件破解與防破解的那些事)22

于是,UKey保護也宣布淪陷.

你發現,隻要是把實體的東西交到用戶的手上,遲早會出問題,所以,這個Ukey保護現在大部分情況下變成了帶數字證書的網絡驗證模式,這類的關鍵代碼從Ukey轉移到了服務器上,數據交互通過網絡來做.其實這種保護機制和Ukey保護原理是一樣的并沒有什麼本質的區别,但同樣處于網絡帶寬也延遲的考慮,同樣具有一定的性能損失和設計缺陷.

需要重點提及的是,這類網絡保護的手段必須專門設計以保護程序中的一系列關鍵"功能"代碼而不是"防破解"代碼(比如代碼解密,注冊驗證),因為後者幾乎沒啥卵用仍然能夠将"防破解"的代碼清除或Dump解密代碼或僞造本地服務器實現破解.

所以你指望一堆什麼x盾,x寶一鍵能一勞永逸一鍵保護程序,程序必須經過專業碼農而不是彩筆專門的設計才能起到其應有的保護效果

但現實情況是,處于用戶離線運行和性能延遲瓶頸的考慮,這種網絡保護設計的往往都有很大的缺陷,因此,并不是說這東西不好,而是理想很豐滿現實很骨幹,實在無能為力啊.

當然,代碼保護的手段很多且花樣玩法也很多,本文隻是初略介紹幾個比較有代表性的破解和反破解手段.如有興趣想要學:

軟件破解與防破解的那些事(軟件破解與防破解的那些事)23

,

更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!

查看全部

相关科技资讯推荐

热门科技资讯推荐

网友关注

Copyright 2023-2024 - www.tftnews.com All Rights Reserved