allowAttachSelf绕过
在Java9及以后的版本不允许SelfAttach(即无法attach自身的进程),如图
调试一下,发现这里ALLOW_ATTACH_SELF字段设置为false
步入getSavedProperty,最终到ImmitableCollections中的table中去查找allowAttachSelf,找不到,返回空
之后,这里进行了ALLOW_ATTACH_SELF字段的检测,若不为true则抛出异常
这样看来有两种方法对这个检验进行绕过一种是使用反射直接更改HotSpotVirtualMachine中的ALLOW_ATTACH_SELF字段,另一种是想办法在ImmitableCollections中的table中添加jdk.attach.allowAttachSelf。
rebeyond师傅使用的是第一种方法。
Field field=cls.getDeclaredField("ALLOW_ATTACH_SELF"); |
|
field.setAccessible(true); |
|
Field modifiersField=Field.class.getDeclaredField("modifiers"); |
|
modifiersField.setAccessible(true); |
|
modifiersField.setInt(field,field.getModifiers()&~Modifier.FINAL); |
|
field.setBoolean(null,true); |
这样便完成了allowAttachSelf机制的绕过。
内存马防检测
instrument机制实现类agent内存马的注入,但是也可以实现对内存马进行检测。
这里给出的方法就是注入内存马后将instrument机制破坏的,使其无法检测进程的类字节码等。
以下为instrument的工作流程
1.检测工具作为Client,根据指定的PID,向目标JVM发起attach请求;
2.JVM收到请求后,做一些校验(比如上文提到的jdk.attach.allowAttachSelf的校验),校验通过后,会打开一个IPC通道。
3.接下来Client会封装一个名为AttachOperation的C++对象,发送给Server端;
4.Server端会把Client发过来的AttachOperation对象放入一个队列;
5.Server端另外一个线程会从队列中取出AttachOperation对象并解析,然后执行对应的操作,并把执行结果通过IPC通道返回Client。
windows端
现在loadAgent处下断点,步入调试。
步入,执行execute方法
看一下execute方法
InputStream execute(String cmd, Object ... args) |
|
throws AgentLoadException, IOException |
|
{
|
|
assert args.length <= 3; // includes null |
|
// create a pipe using a random name |
|
Random rnd = new Random(); |
|
int r = rnd.nextInt(); |
|
String pipeprefix = "\\\\.\\pipe\\javatool"; |
|
String pipename = pipeprefix + r; |
|
long hPipe; |
|
try {
|
|
hPipe = createPipe(pipename);//创建pipe管道 |
|
} catch (IOException ce) {
|
|
// Retry with another random pipe name. |
|
r = rnd.nextInt(); |
|
pipename = pipeprefix + r; |
|
hPipe = createPipe(pipename); |
|
} |
|
// check if we are detached - in theory it's possible that detach is invoked |
|
// after this check but before we enqueue the command. |
|
if (hProcess == -1) {
|
|
closePipe(hPipe); |
|
throw new IOException("Detached from target VM"); |
|
} |
|
try {
|
|
// enqueue the command to the process |
|
enqueue(hProcess, stub, cmd, pipename, args);//调用enqueue方法 |
|
.... |
这个enqueue是native方法。
看一下这个方法的源码
/* |
|
* Class: sun_tools_attach_WindowsVirtualMachine |
|
* Method: enqueue |
|
* Signature: (JZLjava/lang/String;[Ljava/lang/Object;)V |
|
*/ |
|
JNIEXPORT void JNICALL Java_sun_tools_attach_WindowsVirtualMachine_enqueue |
|
(JNIEnv *env, jclass cls, jlong handle, jbyteArray stub, jstring cmd, |
|
jstring pipename, jobjectArray args) |
|
{
|
|
DataBlock data; |
|
DataBlock* pData; |
|
DWORD* pCode; |
|
DWORD stubLen; |
|
HANDLE hProcess, hThread; |
|
jint argsLen, i; |
|
jbyte* stubCode; |
|
jboolean isCopy; |
|
</ |