VMProtect 是一種很可靠的工具,能夠保護應用程序代碼免受分析和破解,但只有在應用程序內保護機制正確構建且沒有可能破壞整個保護的嚴重錯誤的狀況下,才能實現最好的效果。 讓咱們一塊兒來看看爲應用程序提供良好保護的關鍵要素。算法
【VMProtect最新試用版下載】bash
許多開發人員在設計本身的應用程序註冊過程時經常犯的一個錯誤是將整個註冊密鑰檢查包含在一個單獨的函數中,該函數還返回一個易於理解的值:函數
function CheckRegistration(const RegNumber: String): Boolean;
begin
if RegNumber='123' then
Result:=True
else
Result:=False;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
...
if not CheckRegistration(RegNumber) then
exit;
Application.CreateForm(TForm2, Form2);
Form2.ShowModal;
...
end;複製代碼
使用這種方法,入侵者甚至不須要理解密鑰檢查算法。他可能只是在檢查過程的開頭修改代碼,就可以使其始終返回正確的註冊密鑰值:工具
function CheckRegistration(const RegNumber: String): Boolean;
begin
Result:=True;
exit;
...
end;複製代碼
檢查密鑰的一種更有效的方法是將檢查的正確性嵌入到程序的主要操做邏輯中,使得註冊密鑰檢查的算法不能與調用過程的算法分離。咱們還建議將操做邏輯與註冊密鑰檢查過程「混合」,以便在繞過檢查時使程序失敗。 對於上面的示例,能夠按以下方式完成:ui
function CheckRegistration(const RegNumber: String): Boolean;
begin
if RegNumber='123' then
begin
Application.CreateForm(TForm2, Form2);
Result:=True
end
else
Result:=False;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
...
Form2:=nil;
if not CheckRegistration(RegNumber) then
exit;
Form2.ShowModal;
...
end;複製代碼
若是這樣來實現CheckRegistration的功能,入侵者想要繞過它的話,就必須分析全部細節中的註冊密鑰檢查代碼。若是此應用程序受VMProtect保護,則建議同時虛擬化CheckRegistration函數和TForm1.Button1Click過程。 爲了使黑客更難破解程序,你能夠打開「Ultra」保護模式,將代碼突變和虛擬化結合起來。spa
開發人員常犯的另外一個錯誤是註冊密鑰檢查的錯誤實現。輸入的密鑰一般只是與正確的值進行比較。經過跟蹤字符串比較函數的參數,cracker能夠輕鬆匹配密鑰的正確值:設計
var ValidRegNumber: String;
...
function CheckRegistration(const RegNumber: String): Boolean;
begin
if RegNumber=ValidRegNumber then
Result:=True
else
Result:=False;
end;複製代碼
爲避免這種狀況,咱們建議比較密鑰的哈希值,而不是實際值。哈希函數是不可逆的,所以破解者沒法從哈希中檢索真正的密鑰值,而且必須花費更多的時間來研究程序,由於如今須要分析更多的代碼片斷,而不單單是註冊密鑰檢查過程:code
var
HashOfValidRegNumber: Longint;
...
// Peter Weinberger's PJW hashing algorithm example of use function HashPJW(const Value: String): Longint; var I:Integer; G:Longint; begin Result:=0; for I:=1 to Length(Value) do begin Result:=(Result shl 4)+Ord(Value[I]); G:=Result and $F0000000; if G<>0 then Result:=(Result xor (G shr 24)) xor G; end; end; function CheckRegistration(const RegNumber: String): Boolean; begin if HashPJW(RegNumber)=HashOfValidRegNumber then Result:=True else Result:=False; end; ... initialization HashOfValidRegNumber:=HashPJW(ValidRegNumber); end.複製代碼
使用VMProtect保護應用程序時,應使用 HashPJW 和 CheckRegistration 功能,讓黑客更難入侵。orm
一般,即便在註冊程序上花費大量時間的開發人員也不多注意保護註冊程序的結果。下面的示例在調用序列號檢查過程以前使用全局變量來存儲和控制應用程序的註冊狀態。 對於入侵者來講,找到一個全局變量是件小事 - 他只須要在註冊以前和以後比較數據段。順便說一下,流行的ArtMoney程序使用相同的原理。內存
var IsRegistered: Boolean;
...
procedure TForm1.Button1Click(Sender: TObject);
begin
...
if not IsRegistered then
IsRegistered:=CheckRegistration(RegNumber);
if not IsRegistered then
exit;
...
end;複製代碼
爲避免這種狀況,咱們建議將與程序註冊相關的全部檢查結果存儲在動態內存中。在這種狀況下,在註冊以前和以後掃描修改的存儲塊的數據段是無用的。這是一個很是簡單的示例,演示如何將結果存儲在動態分配的內存中:
type PBoolean = ^Boolean;
var IsRegistered: PBoolean;
...
procedure TForm1.Button1Click(Sender: TObject);
begin
...
if not IsRegistered^ then
IsRegistered^:=CheckRegistration(RegNumber);
if not IsRegistered^ then
exit;
...
end;
...
initialization
New(IsRegistered);複製代碼
這些是利用內置保護機制的最簡單方法。註冊程序,註冊密鑰檢查和存儲結果的實際實現僅限於開發人員的創造性。不管如何,你應該知道這些常見錯誤,避免在開發本身的保護機制時出現這種錯誤。