JVM

原理

  • RASP 将会尝试启动 JVM 的 attach 功能,并将探针 jar 植入到 JVM 中。
  • 植入的探针将会利用 Java 提供的 instrument 能力(文档:https://docs.oracle.com/javase/8/docs/api/java/lang/instrument/Instrumentation.html),对部分函数的字节码进行修改,在函数入口插入拦截函数参数的字节码。
  • 此时如果目标函数被执行,拦截的函数参数将会拷贝到跨线程的队列中,并由另一线程完成数据上报。

测试用例

每个线程无限循环进程创建,文件操作以及网络请求,覆盖大多数 hook 点。由于大多数是 IO 行为,整体 CPU 不会太高,但是产生的消息量巨大。

调用耗时

使用 StopWatch 在每次字节码插入时开始计时,并在执行原始函数时暂停,能够较为精确地记录 RASP 额外指令带来的性能消耗。

测试结果

单线程低并发:

classmethodtp50(ns)tp90tp95tp99tp99.99max
java.lang.ProcessImplstart968232955123960596129991274815828223783
java.lang.ProcessImplgetOutputStream573388581133931768547852824476
java.lang.ProcessImplgetInputStream980127723417371725477668284967599
java.lang.ProcessImplgetErrorStream49617252918723882467276849348
java.io.FileInputStreamconstructor1053036148517582417869068532968732
java.io.FileOutputStreamconstructor887215839246911357786730146687335
java.io.FilerenameTo83232470052743220718150363090326511
java.io.Filelist619321637062752404839881510407834878852
java.io.Filedelete675901621362717584573591825808433088801
java.io.FilecreateNewFile1433334837543002431908470798309822
java.net.Socketconnect740971817282845424400721063736820627876
sun.nio.ch.Netconnect866511670333168204668271177179124649484
java.lang.ClassLoaderloadLibrary182276221165221165221165221165347072
java.net.URLClassLoaderconstructor141503515191930345147107954926564824
java.net.InetAddressgetAllByName666811530182596724514482650792837809513
java.net.DatagramSocketconnectInternal20964304863808824824470287414941886
sun.nio.fs.UnixNativeDispatcheropen156334656169982292513356703643932892
sun.nio.fs.UnixNativeDispatcherlink117743059549532271219336428325559608
sun.nio.fs.UnixNativeDispatcherunlink928816216207055564166742132426994
sun.nio.fs.UnixNativeDispatcherrename124222956642380239380624541823419290
sun.nio.fs.UnixNativeDispatchermkdir112873133659343307890280922923986627
sun.nio.fs.UnixNativeDispatcherrmdir9021245553796222677489813038024814
java.io.RandomAccessFileconstructor75161124814803437884930345449350
java.nio.file.Filescopy3858632983462049856008126756424
java.nio.file.Filesmove46047905120643217361360611647599

20个线程高并发:

classmethodtp50(ns)tp90tp95tp99tp99.99max
java.lang.ProcessImplstart53475102106261396607824291228806203956373
java.lang.ProcessImplgetOutputStream648410071126443444593296365154309431
java.lang.ProcessImplgetInputStream812316245251619087693247332148152728
java.lang.ProcessImplgetErrorStream5960908011226268721256922972210908
java.io.FileInputStreamconstructor92092282631551872513449882493044092
java.io.FileOutputStreamconstructor87331525322246664151152897914134987
java.io.FilerenameTo84241711724971687991146063072566531
java.io.Filelist378026986888489472440170624194253013256
java.io.Filedelete3253177660973767057471702970567466264
java.io.FilecreateNewFile12448336025433022667320769639302325311
java.net.Socketconnect7717910678814439678127821663317104182533
sun.nio.ch.Netconnect7641314273417039273109697617089298959759
java.lang.ClassLoaderloadLibrary90301156902156902156902156902163938
java.net.URLClassLoaderconstructor1389028133365702310891357669069458301
java.net.InetAddressgetAllByName39220152231184362474723209761405373643653
java.net.DatagramSocketconnectInternal202093388250706288568986391244518561
sun.nio.fs.UnixNativeDispatcheropen1282432555422851051301142289387704860
sun.nio.fs.UnixNativeDispatcherlink1135626203360371096811295155264969375
sun.nio.fs.UnixNativeDispatcherunlink87141678821150534781038511119177374
sun.nio.fs.UnixNativeDispatcherrename128162461532909866841224598645848260
sun.nio.fs.UnixNativeDispatchermkdir111122185129271913609351289124326385
sun.nio.fs.UnixNativeDispatcherrmdir899918185246867234116610711125197066
java.io.RandomAccessFileconstructor73271065413097399182687054492967952
java.nio.file.Filescopy527495091481440133841152841764104
java.nio.file.Filesmove47287327848920678787570736816949

内存占用

内存占用:50M 注入后内存立刻增长 30M,包括 JVM 开启的 AttachListener 线程,加载 SmithAgent 以及初始化 RASP 守护线程等带来的消耗。netty 开始通过 unix socket 与 server 通信后,缓存队列以及 socket 通信再次占用 20M。

CPU 消耗

单线程低并发情况下,注入时 CPU 飙升,随后 Agent 初始再次导致一波尖刺,然后逐步稳定,对 CPU 负载影响微乎其微。

20个线程高并发情况下,状况类似。