erlang 的原始碼保護機制(經典)

來源:互聯網
上載者:User

稍微深入研究過一點 java 的同學,恐怕都知道什麼叫做 “反編譯” 。也就是說,隨便拿一個 class 檔案,找一個 jad 來,所有的 “智慧結晶” 就全都 “真相大白” 了,跟原先的 source code 相比,區別只是沒有注釋而已。

對於開源軟體開發人員來說,這本是無所謂的事,但對於商業開發人員而言,這簡直就是噩夢。在 java 的世界,道高一尺魔高一丈(及其反覆迭代)的結果是,這件事最終演變得比較詭異,以至於專門誕生了一個名叫 “代碼混淆” 的產業。在我上一次關注的時候,這個領域的最新進展是可以 “混淆” 程式執行的流程,以至於正常的人類閱讀反編譯出來的源碼,將會導致嚴重的腦殘。不過,傳說又出了個叫做 “流程最佳化器” 的東東……(這個故事未完待續)。

其實,這件事困擾的不僅只是 java ,幾乎所有 “有原始碼” 的程式都有這個煩惱。比如,飽受折磨的還有 php, asp 以及 .net。不知道有沒有高人能從 “機器碼” 反編譯出 C 和 C++ 的來源程式呢,反正我挺好奇的。不過,話說回來, “沒有原始碼” 的程式,恐怕還真的沒有。保護原始碼,在我們現如今 “處處是山寨,遍地是豺狼” 的產業現狀之下,似乎仍然是個不得不認真對待的事情。

在原始碼保護的問題上,Erlang 的表現又會如何?今天體驗了一把,應該說,設計得很細緻,至於說這樣的設計是否能夠完全杜絕原始碼的泄露,這個問題恐怕仍然需要留給 “專家” 們去研究。好吧,口水就噴到這裡,下面上乾貨。

目前這個階段,對 Erlang 原始碼的保護,主要是在 debug_info 上做手腳,因為,在 debug_info 裡面有完整的原始碼,可以極其輕鬆的從中 “找回” 源碼(兩個語句而已,在官方文檔之中都有例子)。

先看如何從 Erlang 的 beam 檔案擷取原始碼。象這樣的一個簡單程式:

-module(a).
 
-export([test/0]).
 
test() ->
  io:format("source code.~n", []).

帶 debug_info 編譯,並運行之。

$ erlc +debug_info a.erl
$ erl -s a test -s c q -noshell
source code.
$

我們可以這樣還原它的源碼:

$ erl
1>  {ok,{_,[{abstract_code,{_,AC}}]}} = beam_lib:chunks(code:which(a), abstract_code]).
{ok,{a,[{abstract_code,
            {raw_abstract_v1,
                [{attribute,1,file,{"./a.erl",1}},
                 {attribute,1,module,a},
                 {attribute,3,export,[{test,0}]},
                 {function,5,test,0,
                     [{clause,5,[],[],[{call,6,{remote,...},[...]}]}]},
                 {eof,7}]}}]}}
2> io:fwrite("~s~n", [erl_prettypr:format(erl_syntax:form_list(AC))]).
-file("./a.erl", 1).

-module(a).

-export([test/0]).

test() -> io:format("source code.~n", []).

ok
3>

看,和源碼幾乎完全一致。

那麼,如果我們編譯的時候不帶 debug_info 呢?是的,完全可以。不過,如果你想要在這樣的 beam 上執行 debugger 或者 xref 之類的動作,那麼,沒有 debug_info 就做不了。天知道我們會不會有需要做 “現場調試” 的時候呢。有沒有既保留 debug_info 又阻止其他人通過 debug_info 來得到源碼的辦法呢?有,那就是——加密 debug_info 。

首先建立一個 ~/.erlang.crypt 檔案,內容如下:

$ cat ~/.erlang.crypt
[{debug_info, des3_cbc, [], "my_source_code_secret_key"}].

這裡的 “my_source_code_secret_key” 就被用來產生對 debug_info 加密的密鑰。用 encrypt_debug_info 參數編譯,並運行之。

$ erlc +encrypt_debug_info a.erl
$ erl -s a test -s c q -noshell
source code.

現在拿掉 ~/.erlang.crypt (類比生產機環境),看看能否正常運行。

$ mv ~/.erlang.crypt ~/.erlang.old.crypt
$ erl -s a test -s c q -noshell
source code.

運行沒問題。此時,是否還能還原源碼呢。

$ erl
1>  beam_lib:chunks(code:which(a), [abstract_code]).
{error,beam_lib,
       {key_missing_or_invalid,"./a.beam",abstract_code}}

這正是我們想要的。

比如說,假如某日我們需要在這台生產機上做 “現場調試”,那就再加上 ~/.erlang.crypt 檔案。作為驗證,我們再執行一次還原源碼的操作。

$ mv ~/.erlang.old.crypt ~/.erlang.crypt
$ erl
1>  {ok,{_,[{abstract_code,{_,AC}}]}} = beam_lib:chunks(code:which(a), abstract_code]).
{ok,{a,[{abstract_code,
            {raw_abstract_v1,
                [{attribute,1,file,{"./a.erl",1}},
                 {attribute,1,module,a},
                 {attribute,3,export,[{test,0}]},
                 {function,5,test,0,
                     [{clause,5,[],[],[{call,6,{remote,...},[...]}]}]},
                 {eof,7}]}}]}}
2> io:fwrite("~s~n", [erl_prettypr:format(erl_syntax:form_list(AC))]).
-file("./a.erl", 1).

-module(a).

-export([test/0]).

test() -> io:format("source code.~n", []).

ok
3>

看 debug_info 還原出來了。

我們藏在 debug_info 中的源碼是被 des3_cbc 演算法保護起來的,有興趣的童鞋可以去 wiki 百科瞭解它的加密強度,解開它的關鍵是 ~/.erlang.crypt 檔案,只要它不泄露,那麼在生產環境下,我們的代碼就仍然是安全的,也就是說,就算這台機器被黑掉了,也還原不出源碼(如果我說錯了,請糾正我),而且只要你持有 .erlang.crypt 檔案,(在需要的時候)仍然可以進行調試。

實驗之前,確實沒想到 Erlang 還設計了這麼一個機制,挺細緻的。需要說明的是,上述方案是對 beam 中的 debug_info 進行了加密,從而阻止其他人從中擷取源碼,至於是否還有其他的還原源碼的可能,目前還不是很清楚。比如,理論上,是否有可能通過 beam 之中的 op code 反編譯出原始的 source code 呢?對於這個話題,如果有童鞋知道,請不吝賜教。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.