/* * Class: sun_tools_attach_WindowsVirtualMachine * Method: createPipe * Signature: (Ljava/lang/String;)J */ JNIEXPORT jlong JNICALL Java_sun_tools_attach_WindowsVirtualMachine_createPipe (JNIEnv *env, jclass cls, jstring pipename) { HANDLE hPipe; char name[MAX_PIPE_NAME_LENGTH]; jstring_to_cstring(env, pipename, name, MAX_PIPE_NAME_LENGTH); hPipe = CreateNamedPipe( name, // pipe name PIPE_ACCESS_INBOUND, // read access PIPE_TYPE_BYTE | // byte mode PIPE_READMODE_BYTE | PIPE_WAIT, // blocking mode 1, // max. instances 128, // output buffer size 8192, // input buffer size NMPWAIT_USE_DEFAULT_WAIT, // client time-out NULL); // default security attribute if (hPipe == INVALID_HANDLE_VALUE) { JNU_ThrowIOExceptionWithLastError(env, "CreateNamedPipe failed"); } return (jlong)hPipe; }
/* * Class: sun_tools_attach_VirtualMachineImpl * Method: createPipe * Signature: (Ljava/lang/String;)J */ JNIEXPORT jlong JNICALL Java_sun_tools_attach_VirtualMachineImpl_createPipe (JNIEnv *env, jclass cls, jstring pipename) { HANDLE hPipe; char name[MAX_PIPE_NAME_LENGTH]; SECURITY_ATTRIBUTES sa; LPSECURITY_ATTRIBUTES lpSA = NULL; // Custom Security Descriptor is required here to "get" Medium Integrity Level. // In order to allow Medium Integrity Level clients to open // and use a NamedPipe created by an High Integrity Level process. TCHAR *szSD = TEXT("D:") // Discretionary ACL TEXT("(A;OICI;GRGW;;;WD)") // Allow read/write to Everybody TEXT("(A;OICI;GA;;;SY)") // Allow full control to System TEXT("(A;OICI;GA;;;BA)"); // Allow full control to Administrators sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.bInheritHandle = FALSE; sa.lpSecurityDescriptor = NULL; if (ConvertStringSecurityDescriptorToSecurityDescriptor (szSD, SDDL_REVISION_1, &(sa.lpSecurityDescriptor), NULL)) { lpSA = &sa; } jstring_to_cstring(env, pipename, name, MAX_PIPE_NAME_LENGTH); hPipe = CreateNamedPipe( name, // pipe name PIPE_ACCESS_INBOUND, // read access PIPE_TYPE_BYTE | // byte mode PIPE_READMODE_BYTE | PIPE_WAIT, // blocking mode 1, // max. instances 128, // output buffer size 8192, // input buffer size NMPWAIT_USE_DEFAULT_WAIT, // client time-out lpSA); // security attributes LocalFree(sa.lpSecurityDescriptor); if (hPipe == INVALID_HANDLE_VALUE) { char msg[256]; _snprintf(msg, sizeof(msg), "CreateNamedPipe failed: %d", GetLastError()); JNU_ThrowIOExceptionWithLastError(env, msg); } return (jlong)hPipe; }
/* * 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 numBytes; DWORD stubLen; HANDLE hProcess, hThread; jint argsLen, i; jbyte* stubCode; jboolean isCopy; /* * Setup data to copy to target process */ data._LoadLibrary = _LoadLibrary; data._GetProcAddress = _GetProcAddress; strcpy(data.jvmLib, "jvm"); strcpy(data.func1, "JVM_EnqueueOperation"); strcpy(data.func2, "_JVM_EnqueueOperation@20"); /* * Command and arguments */ 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'; } /* pipe name */ jstring_to_cstring(env, pipename, data.pipename, MAX_PIPE_NAME_LENGTH); /* * Allocate memory in target process for data and code stub * (assumed aligned and matches architecture of target process) */ 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, (LPVOID)&data, (DWORD)sizeof(DataBlock), &numBytes ); 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, (LPVOID)stubCode, (DWORD)stubLen, &numBytes ); if (isCopy) { (*env)->ReleaseByteArrayElements(env, stub, stubCode, JNI_ABORT); } /* * Create thread in target process to execute code */ 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 { JNU_ThrowIOExceptionWithLastError(env, "CreateRemoteThread failed"); } VirtualFreeEx(hProcess, pCode, 0, MEM_RELEASE); VirtualFreeEx(hProcess, pData, 0, MEM_RELEASE); }