鐵人賽 Day 13 JSVMP 混淆: JavaScript 虛擬機的原理

鐵人賽 Day 13 JSVMP 混淆: JavaScript 虛擬機的原理
鐵人賽 Day 13 JSVMP 混淆: JavaScript 虛擬機的原理

本系列文章所討論的 JavaScript 資安與逆向工程技術,旨在分享知識、探討防禦之道,並促進技術交流。

所有內容僅供學術研究與學習,請勿用於任何非法或不道德的行為。

讀者應對自己的行為負完全責任。尊重法律與道德規範是所有技術人員應共同遵守的準則。

 

當基本的混淆技術不足以保護核心邏輯時,還可以採用更高階的防禦手段,虛擬機混淆(VM-Based Obfuscation, JSVMP)。

這種方法將JavaScript程式碼轉換成自定義的虛擬機指令,再由虛擬機在執行階段解譯,這讓逆向變得極度困難。

在 JSVMP 混淆的架構中,原本的人類可讀 JavaScript 並不會直接保留在程式碼裡,而是被轉換成一組特製的「虛擬機指令集」。這些指令就像是一種密碼化的腳本,必須透過內建的解譯器(虛擬機)來逐步翻譯與執行,才能讓原始邏輯真正運作。

由於原始邏輯被拆解並重新封裝,程式碼體積會成倍成長而且閱讀起來十分困難。

更重要的是因為核心行為是在執行階段才被逐步還原,前面介紹的各種分析方法幾乎派不上用場,這也是它能有效對抗逆向工程的原因之一。

  • 大量switch/case結構或查表操作: 解譯器通常透過 switch 判斷執行哪個虛擬指令。
  • 程式碼體積膨脹:原始邏輯被拆解成大量虛擬指令,檔案可能從幾 KB 變成數百 KB。
  • 動態解譯:真實邏輯只會在執行時透過解譯器還原,靜態分析工具幾乎無法直接讀懂。
  • 逆向成本高:必須同時研究「指令集規則」與「解譯流程」導致分析時間大幅增加。

下圖是經過JSVMP混淆過的程式碼,基本的執行邏輯已經無法直覺的閱讀理解。

1.jpg

當嘗試對其進行逆向工程時,你面對不是原始的程式邏輯,而是一個完全陌生的 「機器語言」

  • 指令未知: 無法理解每個指令的具體作用。(如: PUSH、ADD)
  • 控制流隱藏: 程式的執行路徑被位元碼所取代,原有的 if/else 或 for 迴圈結構被徹底抹平。
  • 資料分離: 程式邏輯和資料是分離的。很難單純透過靜態分析來理解整個程式的行為。

若要理解程式必須先逆向出這個虛擬機解釋器,搞懂它的指令集,才能將位元碼還原回有意義的程式邏輯。

這通常需要耗費大量的時間和精力,甚至需要編寫專門的腳本來自動化這個過程。

像是授權驗證、演算法、反作弊程式等,都不希望被輕易還原。比起單純的程式碼混淆,JSVMP幾乎讓逆向門檻瞬間提升數倍,如搭配其他防逆向技術夠能讓攻擊者難以下手。

 

 

JSVMP門檻高但也不是無敵的,無法否認確實讓逆向分析變得極為困難。

在資安的角度我們必須理解它的基本原理,才能設計對應的分析流程。

作者頭像
Nick

擅長從前端的互動設計到後端的資料處理,都能親自規劃與實作。對我來說開發網站不只是完成功能,而是打造一個能被真正使用、體驗順暢的平台。我喜歡把複雜的技術轉化成簡單好懂的成果,並在這個過程中持續學習與挑戰自己。