1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
| typedef struct { GetModuleHandleFunc _GetModuleHandle; GetProcAddressFunc _GetProcAddress; char jvmLib[MAX_LIBNAME_LENGTH]; char func1[MAX_FUNC_LENGTH]; char func2[MAX_FUNC_LENGTH]; char cmd[MAX_CMD_LENGTH]; char arg[MAX_ARGS][MAX_ARG_LENGTH]; char pipename[MAX_PIPE_NAME_LENGTH]; } DataBlock;
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;
data._GetModuleHandle = _GetModuleHandle; data._GetProcAddress = _GetProcAddress;
strcpy(data.jvmLib, "jvm"); strcpy(data.func1, "JVM_EnqueueOperation"); strcpy(data.func2, "_JVM_EnqueueOperation@20");
jstring_to_cstring(env, cmd, data.cmd, MAX_CMD_LENGTH); argsLen = (*env)->GetArrayLength(env, args); if (argsLen > 0) { if (argsLen > MAX_ARGS) { JNU_ThrowInternalError(env, "Too many arguments"); } for (i=0; i<argsLen; i++) { jobject obj = (*env)->GetObjectArrayElement(env, args, i); if (obj == NULL) { data.arg[i][0] = '\0'; } else { jstring_to_cstring(env, obj, data.arg[i], MAX_ARG_LENGTH); } if ((*env)->ExceptionOccurred(env)) return; } } for (i=argsLen; i<MAX_ARGS; i++) { data.arg[i][0] = '\0'; }
jstring_to_cstring(env, pipename, data.pipename, MAX_PIPE_NAME_LENGTH);
hProcess = (HANDLE)handle;
pData = (DataBlock*) VirtualAllocEx( hProcess, 0, sizeof(DataBlock), MEM_COMMIT, PAGE_READWRITE ); if (pData == NULL) { JNU_ThrowIOExceptionWithLastError(env, "VirtualAllocEx failed"); return; } WriteProcessMemory( hProcess, (LPVOID)pData, (LPCVOID)&data, (SIZE_T)sizeof(DataBlock), NULL );
stubLen = (DWORD)(*env)->GetArrayLength(env, stub); stubCode = (*env)->GetByteArrayElements(env, stub, &isCopy); pCode = (PDWORD) VirtualAllocEx( hProcess, 0, stubLen, MEM_COMMIT, PAGE_EXECUTE_READWRITE ); if (pCode == NULL) { JNU_ThrowIOExceptionWithLastError(env, "VirtualAllocEx failed"); VirtualFreeEx(hProcess, pData, 0, MEM_RELEASE); return; } WriteProcessMemory( hProcess, (LPVOID)pCode, (LPCVOID)stubCode, (SIZE_T)stubLen, NULL ); if (isCopy) { (*env)->ReleaseByteArrayElements(env, stub, stubCode, JNI_ABORT); }
hThread = CreateRemoteThread( hProcess, NULL, 0, (LPTHREAD_START_ROUTINE) pCode, pData, 0, NULL ); if (hThread != NULL) { if (WaitForSingleObject(hThread, INFINITE) != WAIT_OBJECT_0) { JNU_ThrowIOExceptionWithLastError(env, "WaitForSingleObject failed"); } else { DWORD exitCode; GetExitCodeThread(hThread, &exitCode); if (exitCode) { switch (exitCode) { case ERR_OPEN_JVM_FAIL : JNU_ThrowIOException(env, "jvm.dll not loaded by target process"); break; case ERR_GET_ENQUEUE_FUNC_FAIL : JNU_ThrowIOException(env, "Unable to enqueue operation: the target VM does not support attach mechanism"); break; default : JNU_ThrowInternalError(env, "Remote thread failed for unknown reason"); } } } CloseHandle(hThread); } else { if (GetLastError() == ERROR_NOT_ENOUGH_MEMORY) {
JNU_ThrowIOException(env, "Insufficient memory or insufficient privileges to attach"); } else { JNU_ThrowIOExceptionWithLastError(env, "CreateRemoteThread failed"); } } VirtualFreeEx(hProcess, pCode, 0, MEM_RELEASE); VirtualFreeEx(hProcess, pData, 0, MEM_RELEASE); }
|