您現在的位置是:首頁 > 綜藝首頁綜藝
安全狗技術研究|JavaAgent技術在記憶體馬中的應用
安全狗怎麼使用
JavaAgent技術簡介
JDK1。5開始引入了Agent機制(即啟動java程式時新增“-javaagen
t
”引數,Java Agent機制允許使用者在JVM載入class檔案的時候先載入自己編寫的Agent檔案,透過修改JVM傳入的位元組碼來實現注入
自定義的程式碼
。
採用
這種方式
時,
必須在容器啟動時新增jvm引數,所以需要重啟Web容器。
JDK1。6新增了attach方式,可以對執行中的jav
a
程序附加agent
,提供了動態修改執行中已經被載入的類的途徑。一般透過
VirtualMachine的attach(pid)方法獲得VirtualMachine例項,隨後
可
呼叫loadagent方法將JavaAgent的jar包載入到目標JVM中。
下面一個章節筆者將透過兩個demo案例說明
J
ava
A
gent技術的兩種方式,讓讀者明白premain和agentmain的具體原理。
JavaAgent兩種方式
1
Premain
建立一個
sayHello
類,寫一個say
()
方法。
建立一個People類,執行say
()
方法,輸出結果為:
hello,world!
建立
Transformer
重寫t
ransformer
方法,實現修改傳入J
VM
的位元組碼。筆者這裡透過javassist對類位元組碼進行處理。
定義
Premain
類的p
remain
方法
使用Maven打包成
TestPremain-1。0-SNAPSHOT。jar
檔案,需要如下修改p
om。xml
檔案。
把
設定為p
remain
方法所在類。
在執行配置中新增vm選項
圖1
執行結果如圖2所示,修改了say方法。
圖2
2
Agentmain
同premain也建立一個People類迴圈列印字串,程式碼如下所示。
重寫
transform
方法,注入程序後列印輸出代理的類,程式碼如下所示。
新建Agent類實現agentmain方法,程式碼如下所示
將
A
gent設定為
並打包成為jar檔案。
Pom。xml
檔案如下所示,值得注意的是如果需要修改已經被JVM載入過的類的位元組碼,那麼還需要在MANIFEST。MF中新增Can-Retransform-Classes:true或Can-Redefine-Classes:true。
建立
Attach
類注入目標類的程序,程式碼如下所示。
A
ttach捕獲到類程序號如圖
3
所示。
圖
3
先執行people類在執行attach,執行結果如圖
4
所示。
圖
4
分析JavaAgent型記憶體馬
由上文可知Agentmain
可
實現最重要的三個類Agent
A
ttach
T
ransform,來分析冰蠍作者之前寫的memshell實現原理,專案地址:
https://github。com/rebeyond/memShell。git
M
emshell中
T
ransform類程式碼如圖5所示。
圖
5
不同於前面章節的demo,這裡除了使用
ClassPool。getDefault()
還使用
ClassClassPath
搜尋class路徑其
原理
是
:
ClassPool。getDefault()獲取的ClassPool使用JVM的classpath
。
在Tomcat等Web伺服器執行時,伺服器會使用多個類載入器作為系統類載入器,這可能導致ClassPool可能無法找到使用者的類
。
這時,ClassPool須新增額外的classpath才能搜尋到使用者的類
。
如上程式碼:作者
H
ook了
ApplicationFilterChain
中的
internalDoFilter
方法,然後定義一個long型別的屬性,elapsedTime
,
並透過insertBefore
方法將
source。txt
中內容
插入到方法內容的開始處
。
source。txt
是url引數和agent互動的邏輯,如圖6所示。
圖
6
筆者之前用此記憶體馬時發現兩個特點
:
第一是
該記憶體馬會
自己刪除jar包,實現程式碼如下。
圖
7
第二
點是
重啟tomcat服務之後記憶體馬還是存在,只有透過jps-
l
kill掉程序後啟動服務才能刪除記憶體馬
,
其
原理
是使用了
ShutdownHook
機制。
圖
8
透過使用
Runtime。addShutdownHook(Thread hook)
方法註冊
JVM
關閉的勾子,呼叫
writeFiles
方法把jar包落地磁碟
,
再透過
Runtime。exec
啟動
java-jar inject。jar
。
由於Hook的關鍵函式,即,
ApplicationFilterChai
n
。interna
l
DoFilter
是tomcat的方法
,
導致其他中介軟體不適用,在冰蠍3
。0
中的記憶體馬作者更改了Hook點(原始碼版本為
V3。0Beta11_t00ls
)
。
在
agentmain
中做了一個判斷,如果是Tomcat選hook
javax。servlet。http。HttpServlet
中的
service
方法,如果是weblogic選擇
hook
weblogic。servlet。
internal。
Servlet
Stub
I
mpl
中的
execute
方法。
程式碼如圖9所示。
圖
9
在jdk
9及以後的版本不允許SelfAttach(即無法attach自身的程序)
。修改前面章節Attach
demo,將jdk換成9之後的,attach自身的P
ID
會報錯提示
Can not attach to current VM
。程式碼如下,報錯截圖如圖1
0
所示。
圖
10
看到
Rebeyond
師傅在《
Java記憶體攻擊技術漫談
》中提出一種方法,繞過
allowAttachSelf
。首先
D
ebug
attch執行流程,如圖1
1
所示。
可以
發現
attach的時候會建立一個HotSpotVirtualMachine的父類
物件,取鍵值對
jdk。attach。allowAttachSelf
的值計算後儲存到
ALLOW_ATTACH_SELF
中
,
可透過反射修改該屬性值。
圖1
1
ALLOW_ATTACH_SELF欄位有final修飾符
,需要設定
setAccessible(true)
;
具體程式碼如下所示。
修改後會彈出警告資訊如圖1
2
所示,成功注入結果如圖1
3
所示。
圖1
2
圖1
3
回到冰蠍3
。0
原始碼中,透過
setProperty
將
jdk。attach。allowAttachSelf
設定為
true
,實現繞過
SelfAttach。
總結
文
從permain和agentmain兩種實現Java
A
gent的原理方法引入到java
agent在記憶體馬中的應用,透過分析memshell到冰蠍3
。0
記憶體馬原始碼,
加深了對
agent型記憶體馬Hook的關鍵函式
、
持久化方法
以及
繞過
SelfAttach
方法等記憶體馬技術點
的理解與學習,希望對讀者有幫助
。